2 * Copyright (c) 2010-2020 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.jablotron.internal.handler;
15 import static org.openhab.binding.jablotron.JablotronBindingConstants.CACHE_TIMEOUT_MS;
16 import static org.openhab.binding.jablotron.JablotronBindingConstants.CHANNEL_LAST_CHECK_TIME;
18 import java.util.List;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.openhab.binding.jablotron.internal.model.JablotronControlResponse;
22 import org.openhab.binding.jablotron.internal.model.JablotronDataUpdateResponse;
23 import org.openhab.binding.jablotron.internal.model.JablotronServiceDetailSegment;
24 import org.openhab.binding.jablotron.internal.model.JablotronServiceDetailSegmentInfo;
25 import org.openhab.core.cache.ExpiringCache;
26 import org.openhab.core.library.types.OnOffType;
27 import org.openhab.core.library.types.QuantityType;
28 import org.openhab.core.library.types.StringType;
29 import org.openhab.core.library.unit.SIUnits;
30 import org.openhab.core.thing.Channel;
31 import org.openhab.core.thing.ChannelUID;
32 import org.openhab.core.thing.Thing;
33 import org.openhab.core.thing.binding.builder.ChannelBuilder;
34 import org.openhab.core.thing.binding.builder.ThingBuilder;
35 import org.openhab.core.thing.type.ChannelTypeUID;
36 import org.openhab.core.types.Command;
37 import org.openhab.core.types.RefreshType;
38 import org.openhab.core.types.State;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
43 * The {@link JablotronJa100Handler} is responsible for handling commands, which are
44 * sent to one of the channels.
46 * @author Ondrej Pecta - Initial contribution
49 public class JablotronJa100Handler extends JablotronAlarmHandler {
51 private final Logger logger = LoggerFactory.getLogger(JablotronJa100Handler.class);
53 public JablotronJa100Handler(Thing thing, String alarmName) {
54 super(thing, alarmName);
55 dataCache = new ExpiringCache<>(CACHE_TIMEOUT_MS, this::sendGetStatusRequest);
59 public void handleCommand(ChannelUID channelUID, Command command) {
60 if (RefreshType.REFRESH.equals(command)) {
61 logger.debug("refreshing channel: {}", channelUID.getId());
62 updateChannel(channelUID.getId());
64 if (channelUID.getId().startsWith("state_") && command instanceof StringType) {
65 scheduler.execute(() -> {
66 controlSTATESection(channelUID.getId().toUpperCase(), command.toString());
70 if (channelUID.getId().startsWith("pgm_") && command instanceof OnOffType) {
71 scheduler.execute(() -> {
72 controlPGMSection(channelUID.getId().toUpperCase(), command.equals(OnOffType.ON) ? "set" : "unset");
78 private void updateChannel(String channel) {
79 ExpiringCache<JablotronDataUpdateResponse> localDataCache = dataCache;
80 if (localDataCache != null) {
81 if (channel.startsWith("state_") || channel.startsWith("pgm_") || channel.startsWith("thermometer_")
82 || channel.startsWith("thermostat_")) {
83 updateSegmentStatus(channel, localDataCache.getValue());
84 } else if (CHANNEL_LAST_CHECK_TIME.equals(channel)) {
87 updateEventChannel(channel);
92 private void createChannel(JablotronServiceDetailSegment section) {
93 if (section.getSegmentId().startsWith("PGM_")) {
94 createPGMChannel(section.getSegmentId().toLowerCase(), section.getSegmentName());
96 createStateChannel(section.getSegmentId().toLowerCase(), section.getSegmentName());
100 private void createTempChannel(String name, String label) {
101 ChannelTypeUID temperature = new ChannelTypeUID("jablotron", "temperature");
102 ThingBuilder thingBuilder = editThing();
103 Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), name), "Number:Temperature")
104 .withLabel(label).withType(temperature).build();
105 thingBuilder.withChannel(channel);
106 updateThing(thingBuilder.build());
109 private void createThermostatChannel(String name, String label) {
110 ChannelTypeUID temperature = new ChannelTypeUID("jablotron", "thermostat");
111 ThingBuilder thingBuilder = editThing();
112 Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), name), "Number:Temperature")
113 .withLabel(label).withType(temperature).build();
114 thingBuilder.withChannel(channel);
115 updateThing(thingBuilder.build());
118 private void createPGMChannel(String name, String label) {
119 ThingBuilder thingBuilder = editThing();
120 Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), name), "Switch").withLabel(label)
122 thingBuilder.withChannel(channel);
123 updateThing(thingBuilder.build());
126 private void createStateChannel(String name, String label) {
127 ChannelTypeUID alarmStatus = new ChannelTypeUID("jablotron", "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());
136 protected void updateSegmentStatus(JablotronServiceDetailSegment segment) {
137 logger.debug("Segment id: {} and status: {}", segment.getSegmentId(), segment.getSegmentState());
138 String segmentId = segment.getSegmentId();
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);
147 logger.debug("Unknown segment received: {} with state: {}", segment.getSegmentId(),
148 segment.getSegmentState());
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);
159 channel = getThing().getChannel(segmentId);
160 if (channel != null) {
161 logger.debug("Updating channel: {} to value: {}", channel.getUID(), segment.getSegmentState());
163 if (segmentId.startsWith("pgm_")) {
164 newState = "unset".equals(segment.getSegmentState()) ? OnOffType.OFF : OnOffType.ON;
166 newState = new StringType(segment.getSegmentState());
168 updateState(channel.getUID(), newState);
170 logger.debug("The channel: {} still doesn't exist!", segmentId);
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);
183 updateTemperatureChannel(channel, segment);
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);
195 updateTemperatureChannel(channel, segment);
198 private void updateTemperatureChannel(Channel channel, JablotronServiceDetailSegment segment) {
199 List<JablotronServiceDetailSegmentInfo> infos = segment.getSegmentInfos();
200 if (infos.size() > 0) {
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));
204 logger.debug("No segment information received");
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());
213 if (response == null) {
214 logger.debug("null response/status received during the control of PGM section: {}", section);
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());
224 if (response == null) {
225 logger.debug("null response/status received during the control of STATE section: {}", section);