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.digiplex.internal.handler;
15 import static org.openhab.binding.digiplex.internal.DigiplexBindingConstants.*;
16 import static org.openhab.binding.digiplex.internal.handler.TypeUtils.openClosedFromBoolean;
18 import java.time.ZonedDateTime;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.binding.digiplex.internal.DigiplexBindingConstants;
23 import org.openhab.binding.digiplex.internal.communication.DigiplexMessageHandler;
24 import org.openhab.binding.digiplex.internal.communication.DigiplexRequest;
25 import org.openhab.binding.digiplex.internal.communication.ZoneStatusRequest;
26 import org.openhab.binding.digiplex.internal.communication.ZoneStatusResponse;
27 import org.openhab.binding.digiplex.internal.communication.events.ZoneEvent;
28 import org.openhab.binding.digiplex.internal.communication.events.ZoneEventType;
29 import org.openhab.binding.digiplex.internal.communication.events.ZoneStatusEvent;
30 import org.openhab.core.library.types.DateTimeType;
31 import org.openhab.core.library.types.OpenClosedType;
32 import org.openhab.core.library.types.StringType;
33 import org.openhab.core.thing.Bridge;
34 import org.openhab.core.thing.ChannelUID;
35 import org.openhab.core.thing.Thing;
36 import org.openhab.core.thing.ThingStatus;
37 import org.openhab.core.thing.ThingStatusDetail;
38 import org.openhab.core.thing.ThingStatusInfo;
39 import org.openhab.core.thing.binding.BaseThingHandler;
40 import org.openhab.core.types.Command;
41 import org.openhab.core.types.RefreshType;
42 import org.openhab.core.types.State;
43 import org.openhab.core.types.UnDefType;
46 * The {@link DigiplexZoneHandler} is responsible for handling commands, which are
47 * sent to one of the channels.
49 * @author Robert Michalak - Initial contribution
52 public class DigiplexZoneHandler extends BaseThingHandler {
54 private @Nullable DigiplexBridgeHandler bridgeHandler;
55 private DigiplexZoneMessageHandler messageHandler = new DigiplexZoneMessageHandler();
57 private int areaNo = 0; // not known at the beginning (protocol limitation)
58 private OpenClosedType status = OpenClosedType.CLOSED;
59 private StringType extendedStatus = new StringType("CLOSED");
60 private OpenClosedType alarm = OpenClosedType.CLOSED;
61 private OpenClosedType fireAlarm = OpenClosedType.CLOSED;
62 private OpenClosedType supervisionLost = OpenClosedType.CLOSED;
63 private OpenClosedType lowBattery = OpenClosedType.CLOSED;
64 private State lastTriggered = UnDefType.NULL;
66 public DigiplexZoneHandler(Thing thing) {
71 public void handleCommand(ChannelUID channelUID, Command command) {
72 switch (channelUID.getId()) {
74 if (command == RefreshType.REFRESH) {
75 updateState(ZONE_STATUS, status);
78 case ZONE_EXTENDED_STATUS:
79 if (command == RefreshType.REFRESH) {
80 updateState(ZONE_EXTENDED_STATUS, extendedStatus);
84 if (command == RefreshType.REFRESH) {
85 updateState(ZONE_ALARM, alarm);
89 if (command == RefreshType.REFRESH) {
90 updateState(ZONE_FIRE_ALARM, fireAlarm);
93 case ZONE_SUPERVISION_LOST:
94 if (command == RefreshType.REFRESH) {
95 updateState(ZONE_SUPERVISION_LOST, supervisionLost);
98 case ZONE_LOW_BATTERY:
99 if (command == RefreshType.REFRESH) {
100 updateState(ZONE_LOW_BATTERY, lowBattery);
103 case ZONE_LAST_TRIGGERED:
104 if (command == RefreshType.REFRESH) {
105 if (lastTriggered != UnDefType.NULL) {
106 updateState(ZONE_LAST_TRIGGERED, lastTriggered);
113 @SuppressWarnings("null")
115 public void initialize() {
116 Bridge bridge = getBridge();
117 if (bridge == null) {
118 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
121 this.bridgeHandler = (DigiplexBridgeHandler) bridge.getHandler();
123 String nodeParm = getThing().getProperties().get(DigiplexBindingConstants.PROPERTY_ZONE_NO);
124 zoneNo = Integer.parseInt(nodeParm);
125 String areaParm = getThing().getProperties().get(DigiplexBindingConstants.PROPERTY_AREA_NO);
126 if (areaParm != null) {
127 areaNo = Integer.parseInt(areaParm);
130 bridgeHandler.registerMessageHandler(messageHandler);
132 DigiplexRequest request = new ZoneStatusRequest(zoneNo);
133 bridgeHandler.sendRequest(request);
135 updateStatus(ThingStatus.ONLINE);
138 private void updateChannels(boolean allChannels) {
139 updateState(ZONE_STATUS, status);
140 updateState(ZONE_EXTENDED_STATUS, extendedStatus);
141 if (lastTriggered != UnDefType.NULL) {
142 updateState(ZONE_LAST_TRIGGERED, lastTriggered);
145 updateState(ZONE_ALARM, alarm);
146 updateState(ZONE_FIRE_ALARM, fireAlarm);
147 updateState(ZONE_SUPERVISION_LOST, supervisionLost);
148 updateState(ZONE_LOW_BATTERY, lowBattery);
152 @SuppressWarnings("null")
154 public void handleRemoval() {
155 if (messageHandler != null) {
156 bridgeHandler.unregisterMessageHandler(messageHandler);
158 super.handleRemoval();
161 @SuppressWarnings("null")
163 public void bridgeStatusChanged(ThingStatusInfo thingStatusInfo) {
164 if (thingStatusInfo.getStatus() == ThingStatus.OFFLINE) {
165 updateStatus(ThingStatus.OFFLINE, thingStatusInfo.getStatusDetail());
166 } else if (thingStatusInfo.getStatus() == ThingStatus.ONLINE) {
167 updateStatus(ThingStatus.ONLINE);
168 DigiplexRequest request = new ZoneStatusRequest(zoneNo);
169 bridgeHandler.sendRequest(request);
173 private void updateAreaNo(int areaNo) {
174 if (this.areaNo == 0) {
175 this.areaNo = areaNo;
176 getThing().setProperty(DigiplexBindingConstants.PROPERTY_AREA_NO, Integer.toString(areaNo));
180 private class DigiplexZoneMessageHandler implements DigiplexMessageHandler {
183 public void handleZoneStatusResponse(ZoneStatusResponse response) {
184 if (response.zoneNo == DigiplexZoneHandler.this.zoneNo) {
185 status = response.status.toOpenClosedType();
186 extendedStatus = new StringType(response.status.toString());
187 alarm = openClosedFromBoolean(response.alarm);
188 fireAlarm = openClosedFromBoolean(response.fireAlarm);
189 supervisionLost = openClosedFromBoolean(response.supervisionLost);
190 lowBattery = openClosedFromBoolean(response.lowBattery);
191 updateChannels(true);
196 public void handleZoneStatusEvent(ZoneStatusEvent event) {
197 if (event.getZoneNo() == DigiplexZoneHandler.this.zoneNo) {
198 status = event.getStatus().toOpenClosedType();
199 extendedStatus = new StringType(event.getStatus().toString());
200 lastTriggered = new DateTimeType(ZonedDateTime.now());
201 updateChannels(false);
202 updateAreaNo(event.getAreaNo());
207 public void handleZoneEvent(ZoneEvent event) {
208 if (event.getZoneNo() == DigiplexZoneHandler.this.zoneNo) {
209 switch (event.getType()) {
212 alarm = openClosedFromBoolean(event.getType() == ZoneEventType.ALARM);
213 updateState(ZONE_ALARM, alarm);
216 case FIRE_ALARM_RESTORE:
217 fireAlarm = openClosedFromBoolean(event.getType() == ZoneEventType.FIRE_ALARM);
218 updateState(ZONE_FIRE_ALARM, fireAlarm);
221 case LOW_BATTERY_RESTORE:
222 lowBattery = openClosedFromBoolean(event.getType() == ZoneEventType.LOW_BATTERY);
223 updateState(ZONE_LOW_BATTERY, lowBattery);
225 case SUPERVISION_TROUBLE:
226 case SUPERVISION_TROUBLE_RESTORE:
227 supervisionLost = openClosedFromBoolean(event.getType() == ZoneEventType.SUPERVISION_TROUBLE);
228 updateState(ZONE_SUPERVISION_LOST, supervisionLost);
234 updateAreaNo(event.getAreaNo());