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.ipcamera.internal;
15 import static org.openhab.binding.ipcamera.internal.IpCameraBindingConstants.*;
17 import java.util.List;
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.binding.ipcamera.internal.handler.IpCameraHandler;
22 import org.openhab.core.library.types.DecimalType;
23 import org.openhab.core.library.types.OnOffType;
24 import org.openhab.core.library.types.PercentType;
25 import org.openhab.core.thing.ChannelUID;
26 import org.openhab.core.thing.binding.ThingHandler;
27 import org.openhab.core.types.Command;
28 import org.openhab.core.types.RefreshType;
29 import org.openhab.core.types.UnDefType;
31 import io.netty.channel.ChannelDuplexHandler;
32 import io.netty.channel.ChannelHandlerContext;
33 import io.netty.util.ReferenceCountUtil;
36 * The {@link FoscamHandler} is responsible for handling commands, which are
37 * sent to one of the channels.
39 * @author Matthew Skinner - Initial contribution
43 public class FoscamHandler extends ChannelDuplexHandler {
44 private IpCameraHandler ipCameraHandler;
45 private String password, username;
47 public FoscamHandler(ThingHandler handler, String username, String password) {
48 ipCameraHandler = (IpCameraHandler) handler;
49 this.username = username;
50 this.password = password;
53 // This handles the incoming http replies back from the camera.
55 public void channelRead(@Nullable ChannelHandlerContext ctx, @Nullable Object msg) throws Exception {
56 if (msg == null || ctx == null) {
60 String content = msg.toString();
61 ipCameraHandler.logger.trace("HTTP Result back from camera is \t:{}:", content);
62 ////////////// Motion Alarm //////////////
63 if (content.contains("<motionDetectAlarm>")) {
64 if (content.contains("<motionDetectAlarm>0</motionDetectAlarm>")) {
65 ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.OFF);
66 } else if (content.contains("<motionDetectAlarm>1</motionDetectAlarm>")) { // Enabled but no alarm
67 ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.ON);
68 ipCameraHandler.noMotionDetected(CHANNEL_MOTION_ALARM);
69 } else if (content.contains("<motionDetectAlarm>2</motionDetectAlarm>")) {// Enabled, alarm on
70 ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.ON);
71 ipCameraHandler.motionDetected(CHANNEL_MOTION_ALARM);
75 ////////////// Sound Alarm //////////////
76 if (content.contains("<soundAlarm>0</soundAlarm>")) {
77 ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.OFF);
78 ipCameraHandler.setChannelState(CHANNEL_AUDIO_ALARM, OnOffType.OFF);
80 if (content.contains("<soundAlarm>1</soundAlarm>")) {
81 ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.ON);
82 ipCameraHandler.noAudioDetected();
84 if (content.contains("<soundAlarm>2</soundAlarm>")) {
85 ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.ON);
86 ipCameraHandler.audioDetected();
89 ////////////// Sound Threshold //////////////
90 if (content.contains("<sensitivity>0</sensitivity>")) {
91 ipCameraHandler.setChannelState(CHANNEL_THRESHOLD_AUDIO_ALARM, PercentType.ZERO);
93 if (content.contains("<sensitivity>1</sensitivity>")) {
94 ipCameraHandler.setChannelState(CHANNEL_THRESHOLD_AUDIO_ALARM, PercentType.valueOf("50"));
96 if (content.contains("<sensitivity>2</sensitivity>")) {
97 ipCameraHandler.setChannelState(CHANNEL_THRESHOLD_AUDIO_ALARM, PercentType.HUNDRED);
100 //////////////// Infrared LED /////////////////////
101 if (content.contains("<infraLedState>0</infraLedState>")) {
102 ipCameraHandler.setChannelState(CHANNEL_ENABLE_LED, OnOffType.OFF);
104 if (content.contains("<infraLedState>1</infraLedState>")) {
105 ipCameraHandler.setChannelState(CHANNEL_ENABLE_LED, OnOffType.ON);
108 if (content.contains("</CGI_Result>")) {
110 ipCameraHandler.logger.debug("End of FOSCAM handler reached, so closing the channel to the camera now");
113 ReferenceCountUtil.release(msg);
117 // This handles the commands that come from the Openhab event bus.
118 public void handleCommand(ChannelUID channelUID, Command command) {
119 if (command instanceof RefreshType) {
120 switch (channelUID.getId()) {
121 case CHANNEL_THRESHOLD_AUDIO_ALARM:
122 ipCameraHandler.sendHttpGET(
123 "/cgi-bin/CGIProxy.fcgi?cmd=getAudioAlarmConfig&usr=" + username + "&pwd=" + password);
125 case CHANNEL_ENABLE_AUDIO_ALARM:
126 ipCameraHandler.sendHttpGET(
127 "/cgi-bin/CGIProxy.fcgi?cmd=getAudioAlarmConfig&usr=" + username + "&pwd=" + password);
129 case CHANNEL_ENABLE_MOTION_ALARM:
131 .sendHttpGET("/cgi-bin/CGIProxy.fcgi?cmd=getDevState&usr=" + username + "&pwd=" + password);
134 return; // Return as we have handled the refresh command above and don't need to
136 } // end of "REFRESH"
137 switch (channelUID.getId()) {
138 case CHANNEL_ENABLE_LED:
139 // Disable the auto mode first
140 ipCameraHandler.sendHttpGET(
141 "/cgi-bin/CGIProxy.fcgi?cmd=setInfraLedConfig&mode=1&usr=" + username + "&pwd=" + password);
142 ipCameraHandler.setChannelState(CHANNEL_AUTO_LED, OnOffType.OFF);
143 if (DecimalType.ZERO.equals(command) || OnOffType.OFF.equals(command)) {
144 ipCameraHandler.sendHttpGET(
145 "/cgi-bin/CGIProxy.fcgi?cmd=closeInfraLed&usr=" + username + "&pwd=" + password);
147 ipCameraHandler.sendHttpGET(
148 "/cgi-bin/CGIProxy.fcgi?cmd=openInfraLed&usr=" + username + "&pwd=" + password);
151 case CHANNEL_AUTO_LED:
152 if (OnOffType.ON.equals(command)) {
153 ipCameraHandler.setChannelState(CHANNEL_ENABLE_LED, UnDefType.UNDEF);
154 ipCameraHandler.sendHttpGET(
155 "/cgi-bin/CGIProxy.fcgi?cmd=setInfraLedConfig&mode=0&usr=" + username + "&pwd=" + password);
157 ipCameraHandler.sendHttpGET(
158 "/cgi-bin/CGIProxy.fcgi?cmd=setInfraLedConfig&mode=1&usr=" + username + "&pwd=" + password);
161 case CHANNEL_THRESHOLD_AUDIO_ALARM:
162 int value = Math.round(Float.valueOf(command.toString()));
164 ipCameraHandler.sendHttpGET("/cgi-bin/CGIProxy.fcgi?cmd=setAudioAlarmConfig&isEnable=0&usr="
165 + username + "&pwd=" + password);
166 } else if (value <= 33) {
168 .sendHttpGET("/cgi-bin/CGIProxy.fcgi?cmd=setAudioAlarmConfig&isEnable=1&sensitivity=0&usr="
169 + username + "&pwd=" + password);
170 } else if (value <= 66) {
172 .sendHttpGET("/cgi-bin/CGIProxy.fcgi?cmd=setAudioAlarmConfig&isEnable=1&sensitivity=1&usr="
173 + username + "&pwd=" + password);
176 .sendHttpGET("/cgi-bin/CGIProxy.fcgi?cmd=setAudioAlarmConfig&isEnable=1&sensitivity=2&usr="
177 + username + "&pwd=" + password);
180 case CHANNEL_ENABLE_AUDIO_ALARM:
181 if (OnOffType.ON.equals(command)) {
182 if (ipCameraHandler.cameraConfig.getCustomAudioAlarmUrl().isEmpty()) {
183 ipCameraHandler.sendHttpGET("/cgi-bin/CGIProxy.fcgi?cmd=setAudioAlarmConfig&isEnable=1&usr="
184 + username + "&pwd=" + password);
186 ipCameraHandler.sendHttpGET(ipCameraHandler.cameraConfig.getCustomAudioAlarmUrl());
189 ipCameraHandler.sendHttpGET("/cgi-bin/CGIProxy.fcgi?cmd=setAudioAlarmConfig&isEnable=0&usr="
190 + username + "&pwd=" + password);
193 case CHANNEL_ENABLE_MOTION_ALARM:
194 if (OnOffType.ON.equals(command)) {
195 if (ipCameraHandler.cameraConfig.getCustomMotionAlarmUrl().isEmpty()) {
196 ipCameraHandler.sendHttpGET("/cgi-bin/CGIProxy.fcgi?cmd=setMotionDetectConfig&isEnable=1&usr="
197 + username + "&pwd=" + password);
198 ipCameraHandler.sendHttpGET("/cgi-bin/CGIProxy.fcgi?cmd=setMotionDetectConfig1&isEnable=1&usr="
199 + username + "&pwd=" + password);
201 ipCameraHandler.sendHttpGET(ipCameraHandler.cameraConfig.getCustomMotionAlarmUrl());
204 ipCameraHandler.sendHttpGET("/cgi-bin/CGIProxy.fcgi?cmd=setMotionDetectConfig&isEnable=0&usr="
205 + username + "&pwd=" + password);
206 ipCameraHandler.sendHttpGET("/cgi-bin/CGIProxy.fcgi?cmd=setMotionDetectConfig1&isEnable=0&usr="
207 + username + "&pwd=" + password);
213 // If a camera does not need to poll a request as often as snapshots, it can be
214 // added here. Binding steps through the list.
215 public List<String> getLowPriorityRequests() {