2 * Copyright (c) 2010-2024 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.nikohomecontrol.internal.handler;
15 import static org.openhab.binding.nikohomecontrol.internal.NikoHomeControlBindingConstants.*;
16 import static org.openhab.core.types.RefreshType.REFRESH;
18 import java.util.HashMap;
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;
39 * The {@link NikoHomeControlAccessHandler} is responsible for handling commands, which are
40 * sent to one of the channels.
42 * @author Mark Herwege - Initial Contribution
45 public class NikoHomeControlAccessHandler extends NikoHomeControlBaseHandler implements NhcAccessEvent {
47 private final Logger logger = LoggerFactory.getLogger(NikoHomeControlAccessHandler.class);
49 private volatile @Nullable NhcAccess nhcAccess;
51 public NikoHomeControlAccessHandler(Thing thing) {
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);
63 logger.debug("handle command {} for {}", command, channelUID);
65 switch (channelUID.getId()) {
66 case CHANNEL_BELL_BUTTON:
67 if (REFRESH.equals(command)) {
68 accessBellEvent(nhcAccess.getBellState());
70 handleBellButtonCommand(command);
73 case CHANNEL_RING_AND_COME_IN:
74 if (REFRESH.equals(command)) {
75 accessRingAndComeInEvent(nhcAccess.getRingAndComeInState());
77 handleRingAndComeInCommand(command);
81 if (REFRESH.equals(command)) {
82 accessDoorLockEvent(nhcAccess.getDoorLockState());
84 handleDoorLockCommand(command);
88 logger.debug("unexpected command for channel {}", channelUID.getId());
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);
99 if (command instanceof OnOffType) {
100 OnOffType s = (OnOffType) command;
101 if (OnOffType.ON.equals(s)) {
102 nhcAccess.executeBell();
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);
114 if (command instanceof OnOffType) {
115 OnOffType s = (OnOffType) command;
116 nhcAccess.executeRingAndComeIn(OnOffType.ON.equals(s));
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);
127 if (command instanceof OnOffType) {
128 OnOffType s = (OnOffType) command;
129 if (OnOffType.OFF.equals(s)) {
130 nhcAccess.executeUnlock();
136 public void initialize() {
139 NikoHomeControlAccessConfig config = getConfig().as(NikoHomeControlAccessConfig.class);
140 deviceId = config.accessId;
142 NikoHomeControlBridgeHandler bridgeHandler = getBridgeHandler();
143 if (bridgeHandler == null) {
144 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
145 "@text/offline.configuration-error.invalid-bridge-handler");
149 updateStatus(ThingStatus.UNKNOWN);
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);
160 synchronized void startCommunication() {
161 NikoHomeControlCommunication nhcComm = getCommunication(getBridgeHandler());
163 if (nhcComm == null) {
167 if (!nhcComm.communicationActive()) {
168 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
169 "@text/offline.communication-error");
173 NhcAccess nhcAccess = nhcComm.getAccessDevices().get(deviceId);
174 if (nhcAccess == null) {
175 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
176 "@text/offline.configuration-error.deviceId");
180 nhcAccess.setEventHandler(this);
182 updateProperties(nhcAccess);
184 String location = nhcAccess.getLocation();
185 if (thing.getLocation() == null) {
186 thing.setLocation(location);
189 this.nhcAccess = nhcAccess;
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());
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();
220 private void updateProperties(NhcAccess nhcAccess) {
221 Map<String, String> properties = new HashMap<>();
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());
230 String buttonId = nhcAccess.getButtonId();
231 if (buttonId != null) {
232 properties.put("buttonId", buttonId);
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);
242 String mjpegUri = nhcAccess.getMjpegUri();
243 if (mjpegUri != null) {
244 properties.put("mjpegUri", mjpegUri);
246 String tnUri = nhcAccess.getTnUri();
248 properties.put("tnUri", tnUri);
252 thing.setProperties(properties);
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);
263 updateState(CHANNEL_BELL_BUTTON, OnOffType.from(state));
264 updateStatus(ThingStatus.ONLINE);
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);
275 updateState(CHANNEL_RING_AND_COME_IN, OnOffType.from(state));
276 updateStatus(ThingStatus.ONLINE);
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);
287 updateState(CHANNEL_LOCK, OnOffType.from(state));
288 updateStatus(ThingStatus.ONLINE);
292 public void updateVideoDeviceProperties() {
293 NhcAccess access = nhcAccess;
294 if (access != null) {
295 updateProperties(access);