2 * Copyright (c) 2010-2023 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 if (nodeParm != null) {
125 zoneNo = Integer.parseInt(nodeParm);
127 String areaParm = getThing().getProperties().get(DigiplexBindingConstants.PROPERTY_AREA_NO);
128 if (areaParm != null) {
129 areaNo = Integer.parseInt(areaParm);
132 bridgeHandler.registerMessageHandler(messageHandler);
134 DigiplexRequest request = new ZoneStatusRequest(zoneNo);
135 bridgeHandler.sendRequest(request);
137 updateStatus(ThingStatus.ONLINE);
140 private void updateChannels(boolean allChannels) {
141 updateState(ZONE_STATUS, status);
142 updateState(ZONE_EXTENDED_STATUS, extendedStatus);
143 if (lastTriggered != UnDefType.NULL) {
144 updateState(ZONE_LAST_TRIGGERED, lastTriggered);
147 updateState(ZONE_ALARM, alarm);
148 updateState(ZONE_FIRE_ALARM, fireAlarm);
149 updateState(ZONE_SUPERVISION_LOST, supervisionLost);
150 updateState(ZONE_LOW_BATTERY, lowBattery);
154 @SuppressWarnings("null")
156 public void handleRemoval() {
157 if (messageHandler != null) {
158 bridgeHandler.unregisterMessageHandler(messageHandler);
160 super.handleRemoval();
163 @SuppressWarnings("null")
165 public void bridgeStatusChanged(ThingStatusInfo thingStatusInfo) {
166 if (thingStatusInfo.getStatus() == ThingStatus.OFFLINE) {
167 updateStatus(ThingStatus.OFFLINE, thingStatusInfo.getStatusDetail());
168 } else if (thingStatusInfo.getStatus() == ThingStatus.ONLINE) {
169 updateStatus(ThingStatus.ONLINE);
170 DigiplexRequest request = new ZoneStatusRequest(zoneNo);
171 bridgeHandler.sendRequest(request);
175 private void updateAreaNo(int areaNo) {
176 if (this.areaNo == 0) {
177 this.areaNo = areaNo;
178 getThing().setProperty(DigiplexBindingConstants.PROPERTY_AREA_NO, Integer.toString(areaNo));
182 private class DigiplexZoneMessageHandler implements DigiplexMessageHandler {
185 public void handleZoneStatusResponse(ZoneStatusResponse response) {
186 if (response.zoneNo == DigiplexZoneHandler.this.zoneNo) {
187 status = response.status.toOpenClosedType();
188 extendedStatus = new StringType(response.status.toString());
189 alarm = openClosedFromBoolean(response.alarm);
190 fireAlarm = openClosedFromBoolean(response.fireAlarm);
191 supervisionLost = openClosedFromBoolean(response.supervisionLost);
192 lowBattery = openClosedFromBoolean(response.lowBattery);
193 updateChannels(true);
198 public void handleZoneStatusEvent(ZoneStatusEvent event) {
199 if (event.getZoneNo() == DigiplexZoneHandler.this.zoneNo) {
200 status = event.getStatus().toOpenClosedType();
201 extendedStatus = new StringType(event.getStatus().toString());
202 lastTriggered = new DateTimeType(ZonedDateTime.now());
203 updateChannels(false);
204 updateAreaNo(event.getAreaNo());
209 public void handleZoneEvent(ZoneEvent event) {
210 if (event.getZoneNo() == DigiplexZoneHandler.this.zoneNo) {
211 switch (event.getType()) {
214 alarm = openClosedFromBoolean(event.getType() == ZoneEventType.ALARM);
215 updateState(ZONE_ALARM, alarm);
218 case FIRE_ALARM_RESTORE:
219 fireAlarm = openClosedFromBoolean(event.getType() == ZoneEventType.FIRE_ALARM);
220 updateState(ZONE_FIRE_ALARM, fireAlarm);
223 case LOW_BATTERY_RESTORE:
224 lowBattery = openClosedFromBoolean(event.getType() == ZoneEventType.LOW_BATTERY);
225 updateState(ZONE_LOW_BATTERY, lowBattery);
227 case SUPERVISION_TROUBLE:
228 case SUPERVISION_TROUBLE_RESTORE:
229 supervisionLost = openClosedFromBoolean(event.getType() == ZoneEventType.SUPERVISION_TROUBLE);
230 updateState(ZONE_SUPERVISION_LOST, supervisionLost);
236 updateAreaNo(event.getAreaNo());