Java tutorial
/** * Copyright (c) 2010-2019 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0 * * SPDX-License-Identifier: EPL-2.0 */ package org.openhab.binding.jeelink.internal.lacrosse; import static org.openhab.binding.jeelink.internal.JeeLinkBindingConstants.*; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.types.QuantityType; import org.eclipse.smarthome.core.library.unit.SIUnits; import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; import org.eclipse.smarthome.core.thing.Channel; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.binding.builder.ChannelBuilder; import org.eclipse.smarthome.core.thing.binding.builder.ThingBuilder; import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; import org.openhab.binding.jeelink.internal.JeeLinkSensorHandler; import org.openhab.binding.jeelink.internal.ReadingPublisher; import org.openhab.binding.jeelink.internal.RollingAveragePublisher; import org.openhab.binding.jeelink.internal.RollingReadingAverage; import org.openhab.binding.jeelink.internal.config.LaCrosseTemperatureSensorConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Handler for a LaCrosse Temperature Sensor thing. * * @author Volker Bier - Initial contribution */ public class LaCrosseTemperatureSensorHandler extends JeeLinkSensorHandler<LaCrosseTemperatureReading> { private final Logger logger = LoggerFactory.getLogger(LaCrosseTemperatureSensorHandler.class); public LaCrosseTemperatureSensorHandler(Thing thing) { super(thing); } @Override public Class<LaCrosseTemperatureReading> getReadingClass() { return LaCrosseTemperatureReading.class; } @Override public ReadingPublisher<LaCrosseTemperatureReading> createPublisher() { return new ReadingPublisher<LaCrosseTemperatureReading>() { private final Map<Integer, ReadingPublisher<LaCrosseTemperatureReading>> channelPublishers = new HashMap<>(); @Override public void publish(LaCrosseTemperatureReading reading) { if (reading != null) { int channelNo = reading.getChannel(); ReadingPublisher<LaCrosseTemperatureReading> publisher; synchronized (channelPublishers) { publisher = channelPublishers.get(channelNo); if (publisher == null) { publisher = createPublisherForChannel(channelNo); channelPublishers.put(channelNo, publisher); createMissingChannels(reading.getChannel()); } } publisher.publish(reading); } } private void createMissingChannels(int channelNo) { List<Channel> missingChannels = new ArrayList<>(); String idSuffix = channelNo > 1 ? String.valueOf(channelNo) : ""; String labelSuffix = channelNo > 1 ? " " + channelNo : ""; for (String channelName : new String[] { TEMPERATURE_CHANNEL, HUMIDITY_CHANNEL }) { if (getThing().getChannel(channelName + idSuffix) == null) { missingChannels.add(ChannelBuilder .create(new ChannelUID(getThing().getUID(), channelName + idSuffix), "Number") .withType(new ChannelTypeUID(getThing().getThingTypeUID().getBindingId(), channelName)) .withLabel(StringUtils.capitalize(channelName + labelSuffix)).build()); } } missingChannels.addAll(getThing().getChannels()); if (!missingChannels.isEmpty()) { ThingBuilder thingBuilder = editThing(); thingBuilder.withChannels(missingChannels); updateThing(thingBuilder.build()); } } @Override public void dispose() { synchronized (channelPublishers) { for (ReadingPublisher<LaCrosseTemperatureReading> p : channelPublishers.values()) { p.dispose(); } channelPublishers.clear(); } } }; } public ReadingPublisher<LaCrosseTemperatureReading> createPublisherForChannel(int channelNo) { ReadingPublisher<LaCrosseTemperatureReading> publisher = new ReadingPublisher<LaCrosseTemperatureReading>() { @Override public void publish(LaCrosseTemperatureReading reading) { if (reading != null && getThing().getStatus() == ThingStatus.ONLINE) { BigDecimal temp = new BigDecimal(reading.getTemperature()).setScale(1, RoundingMode.HALF_UP); if (channelNo == 1) { logger.debug( "updating states for thing {} ({}): temp={} ({}), humidity={}, batteryNew={}, batteryLow={}", getThing().getLabel(), getThing().getUID().getId(), temp, reading.getTemperature(), reading.getHumidity(), reading.isBatteryNew(), reading.isBatteryLow()); updateState(TEMPERATURE_CHANNEL, new QuantityType<>(temp, SIUnits.CELSIUS)); updateState(HUMIDITY_CHANNEL, new QuantityType<>(reading.getHumidity(), SmartHomeUnits.PERCENT)); updateState(BATTERY_NEW_CHANNEL, reading.isBatteryNew() ? OnOffType.ON : OnOffType.OFF); updateState(BATTERY_LOW_CHANNEL, reading.isBatteryLow() ? OnOffType.ON : OnOffType.OFF); } else { logger.debug("updating states for channel {} of thing {} ({}): temp={} ({}), humidity={}", reading.getChannel(), getThing().getLabel(), getThing().getUID().getId(), temp, reading.getTemperature(), reading.getHumidity()); updateState(TEMPERATURE_CHANNEL + reading.getChannel(), new QuantityType<>(temp, SIUnits.CELSIUS)); updateState(HUMIDITY_CHANNEL + reading.getChannel(), new QuantityType<>(reading.getHumidity(), SmartHomeUnits.PERCENT)); } } } @Override public void dispose() { } }; LaCrosseTemperatureSensorConfig cfg = getConfigAs(LaCrosseTemperatureSensorConfig.class); if (cfg.bufferSize > 1 && cfg.updateInterval > 0) { publisher = new RollingAveragePublisher<LaCrosseTemperatureReading>(cfg.bufferSize, cfg.updateInterval, publisher, scheduler) { @Override public RollingReadingAverage<LaCrosseTemperatureReading> createRollingReadingAverage( int bufferSize) { return new LaCrosseRollingReadingAverage(bufferSize); } }; } if (cfg.maxDiff > 0) { publisher = new DifferenceCheckingPublisher(cfg.maxDiff, publisher); } publisher = new BoundsCheckingPublisher(cfg.minTemp, cfg.maxTemp, publisher); return publisher; } }