]> git.basschouten.com Git - openhab-addons.git/blob
91d54179f4b6e5fa4c3c6e1d5e448ee39edbea6b
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.jeelink.internal.lacrosse;
14
15 import static org.openhab.binding.jeelink.internal.JeeLinkBindingConstants.*;
16
17 import java.math.BigDecimal;
18 import java.math.RoundingMode;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23
24 import org.openhab.binding.jeelink.internal.JeeLinkSensorHandler;
25 import org.openhab.binding.jeelink.internal.ReadingPublisher;
26 import org.openhab.binding.jeelink.internal.RollingAveragePublisher;
27 import org.openhab.binding.jeelink.internal.RollingReadingAverage;
28 import org.openhab.binding.jeelink.internal.config.LaCrosseTemperatureSensorConfig;
29 import org.openhab.binding.jeelink.internal.util.StringUtils;
30 import org.openhab.core.library.types.OnOffType;
31 import org.openhab.core.library.types.QuantityType;
32 import org.openhab.core.library.unit.SIUnits;
33 import org.openhab.core.library.unit.Units;
34 import org.openhab.core.thing.Channel;
35 import org.openhab.core.thing.ChannelUID;
36 import org.openhab.core.thing.Thing;
37 import org.openhab.core.thing.ThingStatus;
38 import org.openhab.core.thing.binding.builder.ChannelBuilder;
39 import org.openhab.core.thing.binding.builder.ThingBuilder;
40 import org.openhab.core.thing.type.ChannelTypeUID;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 /**
45  * Handler for a LaCrosse Temperature Sensor thing.
46  *
47  * @author Volker Bier - Initial contribution
48  */
49 public class LaCrosseTemperatureSensorHandler extends JeeLinkSensorHandler<LaCrosseTemperatureReading> {
50     private final Logger logger = LoggerFactory.getLogger(LaCrosseTemperatureSensorHandler.class);
51
52     public LaCrosseTemperatureSensorHandler(Thing thing, String sensorType) {
53         super(thing, sensorType);
54     }
55
56     @Override
57     public Class<LaCrosseTemperatureReading> getReadingClass() {
58         return LaCrosseTemperatureReading.class;
59     }
60
61     @Override
62     public ReadingPublisher<LaCrosseTemperatureReading> createPublisher() {
63         return new ReadingPublisher<LaCrosseTemperatureReading>() {
64             private final Map<Integer, ReadingPublisher<LaCrosseTemperatureReading>> channelPublishers = new HashMap<>();
65
66             @Override
67             public void publish(LaCrosseTemperatureReading reading) {
68                 if (reading != null) {
69                     int channelNo = reading.getChannel();
70
71                     ReadingPublisher<LaCrosseTemperatureReading> publisher;
72                     synchronized (channelPublishers) {
73                         publisher = channelPublishers.get(channelNo);
74                         if (publisher == null) {
75                             publisher = createPublisherForChannel(channelNo);
76                             channelPublishers.put(channelNo, publisher);
77
78                             createMissingChannels(reading.getChannel());
79                         }
80                     }
81
82                     publisher.publish(reading);
83                 }
84             }
85
86             private void createMissingChannels(int channelNo) {
87                 List<Channel> missingChannels = new ArrayList<>();
88
89                 String idSuffix = channelNo > 1 ? String.valueOf(channelNo) : "";
90                 String labelSuffix = channelNo > 1 ? " " + channelNo : "";
91                 for (String channelName : new String[] { TEMPERATURE_CHANNEL, HUMIDITY_CHANNEL }) {
92                     if (getThing().getChannel(channelName + idSuffix) == null) {
93                         missingChannels.add(ChannelBuilder
94                                 .create(new ChannelUID(getThing().getUID(), channelName + idSuffix), "Number")
95                                 .withType(new ChannelTypeUID(getThing().getThingTypeUID().getBindingId(), channelName))
96                                 .withLabel(StringUtils.capitalize(channelName + labelSuffix)).build());
97                     }
98                 }
99                 missingChannels.addAll(getThing().getChannels());
100
101                 if (!missingChannels.isEmpty()) {
102                     ThingBuilder thingBuilder = editThing();
103                     thingBuilder.withChannels(missingChannels);
104                     updateThing(thingBuilder.build());
105                 }
106             }
107
108             @Override
109             public void dispose() {
110                 synchronized (channelPublishers) {
111                     for (ReadingPublisher<LaCrosseTemperatureReading> p : channelPublishers.values()) {
112                         p.dispose();
113                     }
114                     channelPublishers.clear();
115                 }
116             }
117         };
118     }
119
120     public ReadingPublisher<LaCrosseTemperatureReading> createPublisherForChannel(int channelNo) {
121         ReadingPublisher<LaCrosseTemperatureReading> publisher = new ReadingPublisher<LaCrosseTemperatureReading>() {
122             @Override
123             public void publish(LaCrosseTemperatureReading reading) {
124                 if (reading != null && getThing().getStatus() == ThingStatus.ONLINE) {
125                     BigDecimal temp = new BigDecimal(reading.getTemperature()).setScale(1, RoundingMode.HALF_UP);
126
127                     if (channelNo == 1) {
128                         logger.debug(
129                                 "updating states for thing {} ({}): temp={} ({}), humidity={}, batteryNew={}, batteryLow={}",
130                                 getThing().getLabel(), getThing().getUID().getId(), temp, reading.getTemperature(),
131                                 reading.getHumidity(), reading.isBatteryNew(), reading.isBatteryLow());
132                         updateState(TEMPERATURE_CHANNEL, new QuantityType<>(temp, SIUnits.CELSIUS));
133                         updateState(HUMIDITY_CHANNEL, new QuantityType<>(reading.getHumidity(), Units.PERCENT));
134                         updateState(BATTERY_NEW_CHANNEL, reading.isBatteryNew() ? OnOffType.ON : OnOffType.OFF);
135                         updateState(BATTERY_LOW_CHANNEL, reading.isBatteryLow() ? OnOffType.ON : OnOffType.OFF);
136                     } else {
137                         logger.debug("updating states for channel {} of thing {} ({}): temp={} ({}), humidity={}",
138                                 reading.getChannel(), getThing().getLabel(), getThing().getUID().getId(), temp,
139                                 reading.getTemperature(), reading.getHumidity());
140                         updateState(TEMPERATURE_CHANNEL + reading.getChannel(),
141                                 new QuantityType<>(temp, SIUnits.CELSIUS));
142                         updateState(HUMIDITY_CHANNEL + reading.getChannel(),
143                                 new QuantityType<>(reading.getHumidity(), Units.PERCENT));
144                     }
145                 }
146             }
147
148             @Override
149             public void dispose() {
150             }
151         };
152
153         LaCrosseTemperatureSensorConfig cfg = getConfigAs(LaCrosseTemperatureSensorConfig.class);
154         if (cfg.bufferSize > 1 && cfg.updateInterval > 0) {
155             publisher = new RollingAveragePublisher<LaCrosseTemperatureReading>(cfg.bufferSize, cfg.updateInterval,
156                     publisher, scheduler) {
157                 @Override
158                 public RollingReadingAverage<LaCrosseTemperatureReading> createRollingReadingAverage(int bufferSize) {
159                     return new LaCrosseRollingReadingAverage(bufferSize);
160                 }
161             };
162         }
163
164         if (cfg.maxDiff > 0) {
165             publisher = new DifferenceCheckingPublisher(cfg.maxDiff, publisher);
166         }
167
168         publisher = new BoundsCheckingPublisher(cfg.minTemp, cfg.maxTemp, publisher);
169
170         return publisher;
171     }
172 }