]> git.basschouten.com Git - openhab-addons.git/blob
5fab0345cc3a155f8779b2d41136039eed3e6288
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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.nikohomecontrol.internal.handler;
14
15 import static org.openhab.binding.nikohomecontrol.internal.NikoHomeControlBindingConstants.*;
16 import static org.openhab.core.types.RefreshType.REFRESH;
17
18 import java.util.HashMap;
19 import java.util.Map;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.binding.nikohomecontrol.internal.protocol.NhcAccess;
24 import org.openhab.binding.nikohomecontrol.internal.protocol.NhcAccessEvent;
25 import org.openhab.binding.nikohomecontrol.internal.protocol.NikoHomeControlCommunication;
26 import org.openhab.binding.nikohomecontrol.internal.protocol.NikoHomeControlConstants.AccessType;
27 import org.openhab.binding.nikohomecontrol.internal.protocol.nhc2.NhcAccess2;
28 import org.openhab.core.library.types.OnOffType;
29 import org.openhab.core.thing.Bridge;
30 import org.openhab.core.thing.ChannelUID;
31 import org.openhab.core.thing.Thing;
32 import org.openhab.core.thing.ThingStatus;
33 import org.openhab.core.thing.ThingStatusDetail;
34 import org.openhab.core.types.Command;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 /**
39  * The {@link NikoHomeControlAccessHandler} is responsible for handling commands, which are
40  * sent to one of the channels.
41  *
42  * @author Mark Herwege - Initial Contribution
43  */
44 @NonNullByDefault
45 public class NikoHomeControlAccessHandler extends NikoHomeControlBaseHandler implements NhcAccessEvent {
46
47     private final Logger logger = LoggerFactory.getLogger(NikoHomeControlAccessHandler.class);
48
49     private volatile @Nullable NhcAccess nhcAccess;
50
51     public NikoHomeControlAccessHandler(Thing thing) {
52         super(thing);
53     }
54
55     @Override
56     void handleCommandSelection(ChannelUID channelUID, Command command) {
57         NhcAccess nhcAccess = this.nhcAccess;
58         if (nhcAccess == null) {
59             logger.debug("access device with ID {} not initialized", deviceId);
60             return;
61         }
62
63         logger.debug("handle command {} for {}", command, channelUID);
64
65         switch (channelUID.getId()) {
66             case CHANNEL_BELL_BUTTON:
67                 if (REFRESH.equals(command)) {
68                     accessBellEvent(nhcAccess.getBellState());
69                 } else {
70                     handleBellButtonCommand(command);
71                 }
72                 break;
73             case CHANNEL_RING_AND_COME_IN:
74                 if (REFRESH.equals(command)) {
75                     accessRingAndComeInEvent(nhcAccess.getRingAndComeInState());
76                 } else {
77                     handleRingAndComeInCommand(command);
78                 }
79                 break;
80             case CHANNEL_LOCK:
81                 if (REFRESH.equals(command)) {
82                     accessDoorLockEvent(nhcAccess.getDoorLockState());
83                 } else {
84                     handleDoorLockCommand(command);
85                 }
86                 break;
87             default:
88                 logger.debug("unexpected command for channel {}", channelUID.getId());
89         }
90     }
91
92     private void handleBellButtonCommand(Command command) {
93         NhcAccess nhcAccess = this.nhcAccess;
94         if (nhcAccess == null) {
95             logger.debug("access device with ID {} not initialized", deviceId);
96             return;
97         }
98
99         if (command instanceof OnOffType) {
100             OnOffType s = (OnOffType) command;
101             if (OnOffType.ON.equals(s)) {
102                 nhcAccess.executeBell();
103             }
104         }
105     }
106
107     private void handleRingAndComeInCommand(Command command) {
108         NhcAccess nhcAccess = this.nhcAccess;
109         if (nhcAccess == null) {
110             logger.debug("access device with ID {} not initialized", deviceId);
111             return;
112         }
113
114         if (command instanceof OnOffType) {
115             OnOffType s = (OnOffType) command;
116             nhcAccess.executeRingAndComeIn(OnOffType.ON.equals(s));
117         }
118     }
119
120     private void handleDoorLockCommand(Command command) {
121         NhcAccess nhcAccess = this.nhcAccess;
122         if (nhcAccess == null) {
123             logger.debug("access device with ID {} not initialized", deviceId);
124             return;
125         }
126
127         if (command instanceof OnOffType) {
128             OnOffType s = (OnOffType) command;
129             if (OnOffType.OFF.equals(s)) {
130                 nhcAccess.executeUnlock();
131             }
132         }
133     }
134
135     @Override
136     public void initialize() {
137         initialized = false;
138
139         NikoHomeControlAccessConfig config = getConfig().as(NikoHomeControlAccessConfig.class);
140         deviceId = config.accessId;
141
142         NikoHomeControlBridgeHandler bridgeHandler = getBridgeHandler();
143         if (bridgeHandler == null) {
144             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
145                     "@text/offline.configuration-error.invalid-bridge-handler");
146             return;
147         }
148
149         updateStatus(ThingStatus.UNKNOWN);
150
151         Bridge bridge = getBridge();
152         if ((bridge != null) && ThingStatus.ONLINE.equals(bridge.getStatus())) {
153             // We need to do this in a separate thread because we may have to wait for the
154             // communication to become active
155             commStartThread = scheduler.submit(this::startCommunication);
156         }
157     }
158
159     @Override
160     synchronized void startCommunication() {
161         NikoHomeControlCommunication nhcComm = getCommunication(getBridgeHandler());
162
163         if (nhcComm == null) {
164             return;
165         }
166
167         if (!nhcComm.communicationActive()) {
168             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
169                     "@text/offline.communication-error");
170             return;
171         }
172
173         NhcAccess nhcAccess = nhcComm.getAccessDevices().get(deviceId);
174         if (nhcAccess == null) {
175             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
176                     "@text/offline.configuration-error.deviceId");
177             return;
178         }
179
180         nhcAccess.setEventHandler(this);
181
182         updateProperties(nhcAccess);
183
184         String location = nhcAccess.getLocation();
185         if (thing.getLocation() == null) {
186             thing.setLocation(location);
187         }
188
189         this.nhcAccess = nhcAccess;
190
191         initialized = true;
192         deviceInitialized();
193     }
194
195     @Override
196     void refresh() {
197         NhcAccess access = nhcAccess;
198         if (access != null) {
199             accessBellEvent(access.getBellState());
200             accessDoorLockEvent(access.getDoorLockState());
201             if (access.getType().equals(AccessType.RINGANDCOMEIN)) {
202                 accessRingAndComeInEvent(access.getRingAndComeInState());
203             }
204         }
205     }
206
207     @Override
208     public void dispose() {
209         NikoHomeControlCommunication nhcComm = getCommunication(getBridgeHandler());
210         if (nhcComm != null) {
211             NhcAccess access = nhcComm.getAccessDevices().get(deviceId);
212             if (access != null) {
213                 access.unsetEventHandler();
214             }
215         }
216         nhcAccess = null;
217         super.dispose();
218     }
219
220     private void updateProperties(NhcAccess nhcAccess) {
221         Map<String, String> properties = new HashMap<>();
222
223         if (nhcAccess instanceof NhcAccess2) {
224             NhcAccess2 access = (NhcAccess2) nhcAccess;
225             properties.put(PROPERTY_DEVICE_TYPE, access.getDeviceType());
226             properties.put(PROPERTY_DEVICE_TECHNOLOGY, access.getDeviceTechnology());
227             properties.put(PROPERTY_DEVICE_MODEL, access.getDeviceModel());
228         }
229
230         String buttonId = nhcAccess.getButtonId();
231         if (buttonId != null) {
232             properties.put("buttonId", buttonId);
233         }
234
235         if (nhcAccess.supportsVideoStream()) {
236             properties.put("username", "admin");
237             properties.put("password", "123qwe");
238             String ipAddress = nhcAccess.getIpAddress();
239             if (ipAddress != null) {
240                 properties.put("ipAddress", ipAddress);
241             }
242             String mjpegUri = nhcAccess.getMjpegUri();
243             if (mjpegUri != null) {
244                 properties.put("mjpegUri", mjpegUri);
245             }
246             String tnUri = nhcAccess.getTnUri();
247             if (tnUri != null) {
248                 properties.put("tnUri", tnUri);
249             }
250         }
251
252         thing.setProperties(properties);
253     }
254
255     @Override
256     public void accessBellEvent(boolean state) {
257         NhcAccess nhcAccess = this.nhcAccess;
258         if (nhcAccess == null) {
259             logger.debug("access device with ID {} not initialized", deviceId);
260             return;
261         }
262
263         updateState(CHANNEL_BELL_BUTTON, OnOffType.from(state));
264         updateStatus(ThingStatus.ONLINE);
265     }
266
267     @Override
268     public void accessRingAndComeInEvent(boolean state) {
269         NhcAccess nhcAccess = this.nhcAccess;
270         if (nhcAccess == null) {
271             logger.debug("access device with ID {} not initialized", deviceId);
272             return;
273         }
274
275         updateState(CHANNEL_RING_AND_COME_IN, OnOffType.from(state));
276         updateStatus(ThingStatus.ONLINE);
277     }
278
279     @Override
280     public void accessDoorLockEvent(boolean state) {
281         NhcAccess nhcAccess = this.nhcAccess;
282         if (nhcAccess == null) {
283             logger.debug("access device with ID {} not initialized", deviceId);
284             return;
285         }
286
287         updateState(CHANNEL_LOCK, OnOffType.from(state));
288         updateStatus(ThingStatus.ONLINE);
289     }
290
291     @Override
292     public void updateVideoDeviceProperties() {
293         NhcAccess access = nhcAccess;
294         if (access != null) {
295             updateProperties(access);
296         }
297     }
298 }