]> git.basschouten.com Git - openhab-addons.git/blob
62520edead0e80dec7c6f84ce9e2546874569135
[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.jablotron.internal.handler;
14
15 import static org.openhab.binding.jablotron.JablotronBindingConstants.*;
16
17 import java.util.List;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.openhab.binding.jablotron.internal.model.JablotronControlResponse;
21 import org.openhab.binding.jablotron.internal.model.JablotronDataUpdateResponse;
22 import org.openhab.binding.jablotron.internal.model.JablotronServiceDetailSegment;
23 import org.openhab.binding.jablotron.internal.model.JablotronServiceDetailSegmentInfo;
24 import org.openhab.core.cache.ExpiringCache;
25 import org.openhab.core.library.types.OnOffType;
26 import org.openhab.core.library.types.QuantityType;
27 import org.openhab.core.library.types.StringType;
28 import org.openhab.core.library.unit.SIUnits;
29 import org.openhab.core.thing.Channel;
30 import org.openhab.core.thing.ChannelUID;
31 import org.openhab.core.thing.Thing;
32 import org.openhab.core.thing.binding.builder.ChannelBuilder;
33 import org.openhab.core.thing.binding.builder.ThingBuilder;
34 import org.openhab.core.thing.type.ChannelTypeUID;
35 import org.openhab.core.types.Command;
36 import org.openhab.core.types.RefreshType;
37 import org.openhab.core.types.State;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 /**
42  * The {@link JablotronJa100Handler} is responsible for handling commands, which are
43  * sent to one of the channels.
44  *
45  * @author Ondrej Pecta - Initial contribution
46  */
47 @NonNullByDefault
48 public class JablotronJa100Handler extends JablotronAlarmHandler {
49
50     private final Logger logger = LoggerFactory.getLogger(JablotronJa100Handler.class);
51
52     public JablotronJa100Handler(Thing thing, String alarmName) {
53         super(thing, alarmName);
54         dataCache = new ExpiringCache<>(CACHE_TIMEOUT_MS, this::sendGetStatusRequest);
55     }
56
57     @Override
58     public void handleCommand(ChannelUID channelUID, Command command) {
59         if (RefreshType.REFRESH.equals(command)) {
60             logger.debug("refreshing channel: {}", channelUID.getId());
61             updateChannel(channelUID.getId());
62         } else {
63             if (channelUID.getId().startsWith("state_") && command instanceof StringType) {
64                 scheduler.execute(() -> {
65                     controlSTATESection(channelUID.getId().toUpperCase(), command.toString());
66                 });
67             }
68
69             if (channelUID.getId().startsWith("pgm_") && command instanceof OnOffType) {
70                 scheduler.execute(() -> {
71                     controlPGMSection(channelUID.getId().toUpperCase(), command.equals(OnOffType.ON) ? "set" : "unset");
72                 });
73             }
74         }
75     }
76
77     private void updateChannel(String channel) {
78         ExpiringCache<JablotronDataUpdateResponse> localDataCache = dataCache;
79         if (localDataCache != null) {
80             if (channel.startsWith("state_") || channel.startsWith("pgm_") || channel.startsWith("thermometer_")
81                     || channel.startsWith("thermostat_")) {
82                 updateSegmentStatus(channel, localDataCache.getValue());
83             } else if (CHANNEL_LAST_CHECK_TIME.equals(channel)) {
84                 // not updating
85             } else {
86                 updateEventChannel(channel);
87             }
88         }
89     }
90
91     private void createChannel(JablotronServiceDetailSegment section) {
92         if (section.getSegmentId().startsWith("PGM_")) {
93             createPGMChannel(section.getSegmentId().toLowerCase(), section.getSegmentName());
94         } else {
95             createStateChannel(section.getSegmentId().toLowerCase(), section.getSegmentName());
96         }
97     }
98
99     private void createTempChannel(String name, String label) {
100         ChannelTypeUID temperature = new ChannelTypeUID(BINDING_ID, "temperature");
101         ThingBuilder thingBuilder = editThing();
102         Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), name), "Number:Temperature")
103                 .withLabel(label).withType(temperature).build();
104         thingBuilder.withChannel(channel);
105         updateThing(thingBuilder.build());
106     }
107
108     private void createThermostatChannel(String name, String label) {
109         ChannelTypeUID temperature = new ChannelTypeUID(BINDING_ID, "thermostat");
110         ThingBuilder thingBuilder = editThing();
111         Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), name), "Number:Temperature")
112                 .withLabel(label).withType(temperature).build();
113         thingBuilder.withChannel(channel);
114         updateThing(thingBuilder.build());
115     }
116
117     private void createPGMChannel(String name, String label) {
118         ChannelTypeUID pgmStatus = new ChannelTypeUID(BINDING_ID, "pgm_state");
119         ThingBuilder thingBuilder = editThing();
120         Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), name), "Switch").withLabel(label)
121                 .withType(pgmStatus).build();
122         thingBuilder.withChannel(channel);
123         updateThing(thingBuilder.build());
124     }
125
126     private void createStateChannel(String name, String label) {
127         ChannelTypeUID alarmStatus = new ChannelTypeUID(BINDING_ID, "alarm_state");
128         ThingBuilder thingBuilder = editThing();
129         Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), name), "String").withLabel(label)
130                 .withType(alarmStatus).build();
131         thingBuilder.withChannel(channel);
132         updateThing(thingBuilder.build());
133     }
134
135     @Override
136     protected void updateSegmentStatus(JablotronServiceDetailSegment segment) {
137         logger.debug("Segment id: {} and status: {}", segment.getSegmentId(), segment.getSegmentState());
138         String segmentId = segment.getSegmentId();
139
140         if (segmentId.startsWith("STATE_") || segmentId.startsWith("PGM_")) {
141             processSection(segment);
142         } else if (segmentId.startsWith("THERMOMETER_")) {
143             processThermometer(segment);
144         } else if (segmentId.startsWith("THERMOSTAT_")) {
145             processThermostat(segment);
146         } else {
147             logger.debug("Unknown segment received: {} with state: {}", segment.getSegmentId(),
148                     segment.getSegmentState());
149         }
150     }
151
152     private void processSection(JablotronServiceDetailSegment segment) {
153         String segmentId = segment.getSegmentId().toLowerCase();
154         Channel channel = getThing().getChannel(segmentId);
155         if (channel == null) {
156             logger.debug("Creating a new channel: {}", segmentId);
157             createChannel(segment);
158         }
159         channel = getThing().getChannel(segmentId);
160         if (channel != null) {
161             logger.debug("Updating channel: {} to value: {}", channel.getUID(), segment.getSegmentState());
162             State newState;
163             if (segmentId.startsWith("pgm_")) {
164                 newState = OnOffType.from(!"unset".equals(segment.getSegmentState()));
165             } else {
166                 newState = new StringType(segment.getSegmentState());
167             }
168             updateState(channel.getUID(), newState);
169         } else {
170             logger.debug("The channel: {} still doesn't exist!", segmentId);
171         }
172     }
173
174     private void processThermometer(JablotronServiceDetailSegment segment) {
175         String segmentId = segment.getSegmentId().toLowerCase();
176         Channel channel = getThing().getChannel(segmentId);
177         if (channel == null) {
178             logger.debug("Creating a new temperature channel: {}", segmentId);
179             createTempChannel(segmentId, segment.getSegmentName());
180             processThermometer(segment);
181             return;
182         }
183         updateTemperatureChannel(channel, segment);
184     }
185
186     private void processThermostat(JablotronServiceDetailSegment segment) {
187         String segmentId = segment.getSegmentId().toLowerCase();
188         Channel channel = getThing().getChannel(segmentId);
189         if (channel == null) {
190             logger.debug("Creating a new thermostat channel: {}", segmentId);
191             createThermostatChannel(segmentId, segment.getSegmentName());
192             processThermostat(segment);
193             return;
194         }
195         updateTemperatureChannel(channel, segment);
196     }
197
198     private void updateTemperatureChannel(Channel channel, JablotronServiceDetailSegment segment) {
199         List<JablotronServiceDetailSegmentInfo> infos = segment.getSegmentInfos();
200         if (!infos.isEmpty()) {
201             logger.debug("Found value: {} and type: {}", infos.get(0).getValue(), infos.get(0).getType());
202             updateState(channel.getUID(), QuantityType.valueOf(infos.get(0).getValue(), SIUnits.CELSIUS));
203         } else {
204             logger.debug("No segment information received");
205         }
206     }
207
208     public synchronized void controlPGMSection(String section, String status) {
209         logger.debug("Controlling section: {} with status: {}", section, status);
210         JablotronControlResponse response = sendUserCode(section, section.toLowerCase(), status, thingConfig.getCode());
211
212         updateAlarmStatus();
213         if (response == null) {
214             logger.debug("null response/status received during the control of PGM section: {}", section);
215         }
216     }
217
218     public synchronized void controlSTATESection(String section, String status) {
219         logger.debug("Controlling section: {} with status: {}", section, status);
220         JablotronControlResponse response = sendUserCode(section, section.toLowerCase().replace("state", "section"),
221                 status, thingConfig.getCode());
222
223         updateAlarmStatus();
224         if (response == null) {
225             logger.debug("null response/status received during the control of STATE section: {}", section);
226         }
227     }
228 }