]> git.basschouten.com Git - openhab-addons.git/blob
60fbca5f4a2f042bb9ff779c44009629c6774ddb
[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.digiplex.internal.handler;
14
15 import static org.openhab.binding.digiplex.internal.DigiplexBindingConstants.*;
16 import static org.openhab.binding.digiplex.internal.handler.TypeUtils.openClosedFromBoolean;
17
18 import java.time.ZonedDateTime;
19
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;
44
45 /**
46  * The {@link DigiplexZoneHandler} is responsible for handling commands, which are
47  * sent to one of the channels.
48  *
49  * @author Robert Michalak - Initial contribution
50  */
51 @NonNullByDefault
52 public class DigiplexZoneHandler extends BaseThingHandler {
53
54     private @Nullable DigiplexBridgeHandler bridgeHandler;
55     private DigiplexZoneMessageHandler messageHandler = new DigiplexZoneMessageHandler();
56     private int zoneNo;
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;
65
66     public DigiplexZoneHandler(Thing thing) {
67         super(thing);
68     }
69
70     @Override
71     public void handleCommand(ChannelUID channelUID, Command command) {
72         switch (channelUID.getId()) {
73             case ZONE_STATUS:
74                 if (command == RefreshType.REFRESH) {
75                     updateState(ZONE_STATUS, status);
76                 }
77                 break;
78             case ZONE_EXTENDED_STATUS:
79                 if (command == RefreshType.REFRESH) {
80                     updateState(ZONE_EXTENDED_STATUS, extendedStatus);
81                 }
82                 break;
83             case ZONE_ALARM:
84                 if (command == RefreshType.REFRESH) {
85                     updateState(ZONE_ALARM, alarm);
86                 }
87                 break;
88             case ZONE_FIRE_ALARM:
89                 if (command == RefreshType.REFRESH) {
90                     updateState(ZONE_FIRE_ALARM, fireAlarm);
91                 }
92                 break;
93             case ZONE_SUPERVISION_LOST:
94                 if (command == RefreshType.REFRESH) {
95                     updateState(ZONE_SUPERVISION_LOST, supervisionLost);
96                 }
97                 break;
98             case ZONE_LOW_BATTERY:
99                 if (command == RefreshType.REFRESH) {
100                     updateState(ZONE_LOW_BATTERY, lowBattery);
101                 }
102                 break;
103             case ZONE_LAST_TRIGGERED:
104                 if (command == RefreshType.REFRESH) {
105                     if (lastTriggered != UnDefType.NULL) {
106                         updateState(ZONE_LAST_TRIGGERED, lastTriggered);
107                     }
108                 }
109                 break;
110         }
111     }
112
113     @SuppressWarnings("null")
114     @Override
115     public void initialize() {
116         Bridge bridge = getBridge();
117         if (bridge == null) {
118             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
119             return;
120         }
121         this.bridgeHandler = (DigiplexBridgeHandler) bridge.getHandler();
122
123         String nodeParm = getThing().getProperties().get(DigiplexBindingConstants.PROPERTY_ZONE_NO);
124         if (nodeParm != null) {
125             zoneNo = Integer.parseInt(nodeParm);
126         }
127         String areaParm = getThing().getProperties().get(DigiplexBindingConstants.PROPERTY_AREA_NO);
128         if (areaParm != null) {
129             areaNo = Integer.parseInt(areaParm);
130         }
131
132         bridgeHandler.registerMessageHandler(messageHandler);
133
134         DigiplexRequest request = new ZoneStatusRequest(zoneNo);
135         bridgeHandler.sendRequest(request);
136
137         updateStatus(ThingStatus.ONLINE);
138     }
139
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);
145         }
146         if (allChannels) {
147             updateState(ZONE_ALARM, alarm);
148             updateState(ZONE_FIRE_ALARM, fireAlarm);
149             updateState(ZONE_SUPERVISION_LOST, supervisionLost);
150             updateState(ZONE_LOW_BATTERY, lowBattery);
151         }
152     }
153
154     @SuppressWarnings("null")
155     @Override
156     public void handleRemoval() {
157         if (messageHandler != null) {
158             bridgeHandler.unregisterMessageHandler(messageHandler);
159         }
160         super.handleRemoval();
161     }
162
163     @SuppressWarnings("null")
164     @Override
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);
172         }
173     }
174
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));
179         }
180     }
181
182     private class DigiplexZoneMessageHandler implements DigiplexMessageHandler {
183
184         @Override
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);
194             }
195         }
196
197         @Override
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());
205             }
206         }
207
208         @Override
209         public void handleZoneEvent(ZoneEvent event) {
210             if (event.getZoneNo() == DigiplexZoneHandler.this.zoneNo) {
211                 switch (event.getType()) {
212                     case ALARM:
213                     case ALARM_RESTORE:
214                         alarm = openClosedFromBoolean(event.getType() == ZoneEventType.ALARM);
215                         updateState(ZONE_ALARM, alarm);
216                         break;
217                     case FIRE_ALARM:
218                     case FIRE_ALARM_RESTORE:
219                         fireAlarm = openClosedFromBoolean(event.getType() == ZoneEventType.FIRE_ALARM);
220                         updateState(ZONE_FIRE_ALARM, fireAlarm);
221                         break;
222                     case LOW_BATTERY:
223                     case LOW_BATTERY_RESTORE:
224                         lowBattery = openClosedFromBoolean(event.getType() == ZoneEventType.LOW_BATTERY);
225                         updateState(ZONE_LOW_BATTERY, lowBattery);
226                         break;
227                     case SUPERVISION_TROUBLE:
228                     case SUPERVISION_TROUBLE_RESTORE:
229                         supervisionLost = openClosedFromBoolean(event.getType() == ZoneEventType.SUPERVISION_TROUBLE);
230                         updateState(ZONE_SUPERVISION_LOST, supervisionLost);
231                         break;
232                     default:
233                         break;
234
235                 }
236                 updateAreaNo(event.getAreaNo());
237             }
238         }
239     }
240 }