]> git.basschouten.com Git - openhab-addons.git/blob
127bee61af863dd00a0774685efe9e5a007cfe80
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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 import java.util.Objects;
24
25 import org.openhab.binding.jeelink.internal.JeeLinkSensorHandler;
26 import org.openhab.binding.jeelink.internal.ReadingPublisher;
27 import org.openhab.binding.jeelink.internal.RollingAveragePublisher;
28 import org.openhab.binding.jeelink.internal.RollingReadingAverage;
29 import org.openhab.binding.jeelink.internal.config.LaCrosseTemperatureSensorConfig;
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.openhab.core.util.StringUtils;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 /**
46  * Handler for a LaCrosse Temperature Sensor thing.
47  *
48  * @author Volker Bier - Initial contribution
49  */
50 public class LaCrosseTemperatureSensorHandler extends JeeLinkSensorHandler<LaCrosseTemperatureReading> {
51     private final Logger logger = LoggerFactory.getLogger(LaCrosseTemperatureSensorHandler.class);
52
53     public LaCrosseTemperatureSensorHandler(Thing thing, String sensorType) {
54         super(thing, sensorType);
55     }
56
57     @Override
58     public Class<LaCrosseTemperatureReading> getReadingClass() {
59         return LaCrosseTemperatureReading.class;
60     }
61
62     @Override
63     public ReadingPublisher<LaCrosseTemperatureReading> createPublisher() {
64         return new ReadingPublisher<LaCrosseTemperatureReading>() {
65             private final Map<Integer, ReadingPublisher<LaCrosseTemperatureReading>> channelPublishers = new HashMap<>();
66
67             @Override
68             public void publish(LaCrosseTemperatureReading reading) {
69                 if (reading != null) {
70                     int channelNo = reading.getChannel();
71
72                     ReadingPublisher<LaCrosseTemperatureReading> publisher;
73                     synchronized (channelPublishers) {
74                         publisher = channelPublishers.get(channelNo);
75                         if (publisher == null) {
76                             publisher = createPublisherForChannel(channelNo);
77                             channelPublishers.put(channelNo, publisher);
78
79                             createMissingChannels(reading.getChannel());
80                         }
81                     }
82
83                     publisher.publish(reading);
84                 }
85             }
86
87             private void createMissingChannels(int channelNo) {
88                 List<Channel> missingChannels = new ArrayList<>();
89
90                 String idSuffix = channelNo > 1 ? String.valueOf(channelNo) : "";
91                 String labelSuffix = channelNo > 1 ? " " + channelNo : "";
92                 for (String channelName : new String[] { TEMPERATURE_CHANNEL, HUMIDITY_CHANNEL }) {
93                     if (getThing().getChannel(channelName + idSuffix) == null) {
94                         missingChannels.add(ChannelBuilder
95                                 .create(new ChannelUID(getThing().getUID(), channelName + idSuffix), "Number")
96                                 .withType(new ChannelTypeUID(getThing().getThingTypeUID().getBindingId(), channelName))
97                                 .withLabel(Objects.requireNonNull(StringUtils.capitalize(channelName + labelSuffix)))
98                                 .build());
99                     }
100                 }
101                 missingChannels.addAll(getThing().getChannels());
102
103                 if (!missingChannels.isEmpty()) {
104                     ThingBuilder thingBuilder = editThing();
105                     thingBuilder.withChannels(missingChannels);
106                     updateThing(thingBuilder.build());
107                 }
108             }
109
110             @Override
111             public void dispose() {
112                 synchronized (channelPublishers) {
113                     for (ReadingPublisher<LaCrosseTemperatureReading> p : channelPublishers.values()) {
114                         p.dispose();
115                     }
116                     channelPublishers.clear();
117                 }
118             }
119         };
120     }
121
122     public ReadingPublisher<LaCrosseTemperatureReading> createPublisherForChannel(int channelNo) {
123         ReadingPublisher<LaCrosseTemperatureReading> publisher = new ReadingPublisher<LaCrosseTemperatureReading>() {
124             @Override
125             public void publish(LaCrosseTemperatureReading reading) {
126                 if (reading != null && getThing().getStatus() == ThingStatus.ONLINE) {
127                     BigDecimal temp = new BigDecimal(reading.getTemperature()).setScale(1, RoundingMode.HALF_UP);
128
129                     if (channelNo == 1) {
130                         logger.debug(
131                                 "updating states for thing {} ({}): temp={} ({}), humidity={}, batteryNew={}, batteryLow={}",
132                                 getThing().getLabel(), getThing().getUID().getId(), temp, reading.getTemperature(),
133                                 reading.getHumidity(), reading.isBatteryNew(), reading.isBatteryLow());
134                         updateState(TEMPERATURE_CHANNEL, new QuantityType<>(temp, SIUnits.CELSIUS));
135                         updateState(HUMIDITY_CHANNEL, new QuantityType<>(reading.getHumidity(), Units.PERCENT));
136                         updateState(BATTERY_NEW_CHANNEL, OnOffType.from(reading.isBatteryNew()));
137                         updateState(BATTERY_LOW_CHANNEL, OnOffType.from(reading.isBatteryLow()));
138                     } else {
139                         logger.debug("updating states for channel {} of thing {} ({}): temp={} ({}), humidity={}",
140                                 reading.getChannel(), getThing().getLabel(), getThing().getUID().getId(), temp,
141                                 reading.getTemperature(), reading.getHumidity());
142                         updateState(TEMPERATURE_CHANNEL + reading.getChannel(),
143                                 new QuantityType<>(temp, SIUnits.CELSIUS));
144                         updateState(HUMIDITY_CHANNEL + reading.getChannel(),
145                                 new QuantityType<>(reading.getHumidity(), Units.PERCENT));
146                     }
147                 }
148             }
149
150             @Override
151             public void dispose() {
152             }
153         };
154
155         LaCrosseTemperatureSensorConfig cfg = getConfigAs(LaCrosseTemperatureSensorConfig.class);
156         if (cfg.bufferSize > 1 && cfg.updateInterval > 0) {
157             publisher = new RollingAveragePublisher<LaCrosseTemperatureReading>(cfg.bufferSize, cfg.updateInterval,
158                     publisher, scheduler) {
159                 @Override
160                 public RollingReadingAverage<LaCrosseTemperatureReading> createRollingReadingAverage(int bufferSize) {
161                     return new LaCrosseRollingReadingAverage(bufferSize);
162                 }
163             };
164         }
165
166         if (cfg.maxDiff > 0) {
167             publisher = new DifferenceCheckingPublisher(cfg.maxDiff, publisher);
168         }
169
170         publisher = new BoundsCheckingPublisher(cfg.minTemp, cfg.maxTemp, publisher);
171
172         return publisher;
173     }
174 }