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