2 * Copyright (c) 2010-2020 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
14 package org.openhab.binding.ipcamera.internal;
16 import static org.openhab.binding.ipcamera.internal.IpCameraBindingConstants.*;
18 import java.util.ArrayList;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.binding.ipcamera.internal.handler.IpCameraHandler;
23 import org.openhab.core.library.types.DecimalType;
24 import org.openhab.core.library.types.OnOffType;
25 import org.openhab.core.library.types.PercentType;
26 import org.openhab.core.thing.ChannelUID;
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 DahuaHandler} is responsible for handling commands, which are
37 * sent to one of the channels.
39 * @author Matthew Skinner - Initial contribution
43 public class DahuaHandler extends ChannelDuplexHandler {
44 private IpCameraHandler ipCameraHandler;
45 private int nvrChannel;
47 public DahuaHandler(IpCameraHandler handler, int nvrChannel) {
48 ipCameraHandler = handler;
49 this.nvrChannel = nvrChannel;
52 // This handles the incoming http replies back from the camera.
54 public void channelRead(@Nullable ChannelHandlerContext ctx, @Nullable Object msg) throws Exception {
55 if (msg == null || ctx == null) {
59 String content = msg.toString();
60 ipCameraHandler.logger.trace("HTTP Result back from camera is \t:{}:", content);
61 // determine if the motion detection is turned on or off.
62 if (content.contains("table.MotionDetect[0].Enable=true")) {
63 ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.ON);
64 } else if (content.contains("table.MotionDetect[" + nvrChannel + "].Enable=false")) {
65 ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.OFF);
67 // Handle motion alarm
68 if (content.contains("Code=VideoMotion;action=Start;index=0")) {
69 ipCameraHandler.motionDetected(CHANNEL_MOTION_ALARM);
70 } else if (content.contains("Code=VideoMotion;action=Stop;index=0")) {
71 ipCameraHandler.noMotionDetected(CHANNEL_MOTION_ALARM);
73 // Handle item taken alarm
74 if (content.contains("Code=TakenAwayDetection;action=Start;index=0")) {
75 ipCameraHandler.motionDetected(CHANNEL_ITEM_TAKEN);
76 } else if (content.contains("Code=TakenAwayDetection;action=Stop;index=0")) {
77 ipCameraHandler.noMotionDetected(CHANNEL_ITEM_TAKEN);
79 // Handle item left alarm
80 if (content.contains("Code=LeftDetection;action=Start;index=0")) {
81 ipCameraHandler.motionDetected(CHANNEL_ITEM_LEFT);
82 } else if (content.contains("Code=LeftDetection;action=Stop;index=0")) {
83 ipCameraHandler.noMotionDetected(CHANNEL_ITEM_LEFT);
85 // Handle CrossLineDetection alarm
86 if (content.contains("Code=CrossLineDetection;action=Start;index=0")) {
87 ipCameraHandler.motionDetected(CHANNEL_LINE_CROSSING_ALARM);
88 } else if (content.contains("Code=CrossLineDetection;action=Stop;index=0")) {
89 ipCameraHandler.noMotionDetected(CHANNEL_LINE_CROSSING_ALARM);
91 // determine if the audio alarm is turned on or off.
92 if (content.contains("table.AudioDetect[0].MutationDetect=true")) {
93 ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.ON);
94 } else if (content.contains("table.AudioDetect[0].MutationDetect=false")) {
95 ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.OFF);
97 // Handle AudioMutation alarm
98 if (content.contains("Code=AudioMutation;action=Start;index=0")) {
99 ipCameraHandler.audioDetected();
100 } else if (content.contains("Code=AudioMutation;action=Stop;index=0")) {
101 ipCameraHandler.noAudioDetected();
103 // Handle AudioMutationThreshold alarm
104 if (content.contains("table.AudioDetect[0].MutationThreold=")) {
105 String value = ipCameraHandler.returnValueFromString(content, "table.AudioDetect[0].MutationThreold=");
106 ipCameraHandler.setChannelState(CHANNEL_THRESHOLD_AUDIO_ALARM, PercentType.valueOf(value));
108 // Handle FaceDetection alarm
109 if (content.contains("Code=FaceDetection;action=Start;index=0")) {
110 ipCameraHandler.motionDetected(CHANNEL_FACE_DETECTED);
111 } else if (content.contains("Code=FaceDetection;action=Stop;index=0")) {
112 ipCameraHandler.noMotionDetected(CHANNEL_FACE_DETECTED);
114 // Handle ParkingDetection alarm
115 if (content.contains("Code=ParkingDetection;action=Start;index=0")) {
116 ipCameraHandler.motionDetected(CHANNEL_PARKING_ALARM);
117 } else if (content.contains("Code=ParkingDetection;action=Stop;index=0")) {
118 ipCameraHandler.noMotionDetected(CHANNEL_PARKING_ALARM);
120 // Handle CrossRegionDetection alarm
121 if (content.contains("Code=CrossRegionDetection;action=Start;index=0")) {
122 ipCameraHandler.motionDetected(CHANNEL_FIELD_DETECTION_ALARM);
123 } else if (content.contains("Code=CrossRegionDetection;action=Stop;index=0")) {
124 ipCameraHandler.noMotionDetected(CHANNEL_FIELD_DETECTION_ALARM);
126 // Handle External Input alarm
127 if (content.contains("Code=AlarmLocal;action=Start;index=0")) {
128 ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT, OnOffType.ON);
129 } else if (content.contains("Code=AlarmLocal;action=Stop;index=0")) {
130 ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT, OnOffType.OFF);
132 // Handle External Input alarm2
133 if (content.contains("Code=AlarmLocal;action=Start;index=1")) {
134 ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT2, OnOffType.ON);
135 } else if (content.contains("Code=AlarmLocal;action=Stop;index=1")) {
136 ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT2, OnOffType.OFF);
138 // CrossLineDetection alarm on/off
139 if (content.contains("table.VideoAnalyseRule[0][1].Enable=true")) {
140 ipCameraHandler.setChannelState(CHANNEL_ENABLE_LINE_CROSSING_ALARM, OnOffType.ON);
141 } else if (content.contains("table.VideoAnalyseRule[0][1].Enable=false")) {
142 ipCameraHandler.setChannelState(CHANNEL_ENABLE_LINE_CROSSING_ALARM, OnOffType.OFF);
144 // Privacy Mode on/off
145 if (content.contains("Code=LensMaskOpen;") || content.contains("table.LeLensMask[0].Enable=true")) {
146 ipCameraHandler.setChannelState(CHANNEL_ENABLE_PRIVACY_MODE, OnOffType.ON);
147 } else if (content.contains("Code=LensMaskClose;")
148 || content.contains("table.LeLensMask[0].Enable=false")) {
149 ipCameraHandler.setChannelState(CHANNEL_ENABLE_PRIVACY_MODE, OnOffType.OFF);
152 ReferenceCountUtil.release(msg);
156 // This handles the commands that come from the Openhab event bus.
157 public void handleCommand(ChannelUID channelUID, Command command) {
158 if (command instanceof RefreshType) {
159 switch (channelUID.getId()) {
160 case CHANNEL_THRESHOLD_AUDIO_ALARM:
161 // ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=AudioDetect[0]");
163 case CHANNEL_ENABLE_AUDIO_ALARM:
164 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=AudioDetect[0]");
166 case CHANNEL_ENABLE_LINE_CROSSING_ALARM:
167 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=VideoAnalyseRule");
169 case CHANNEL_ENABLE_MOTION_ALARM:
170 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=MotionDetect[0]");
172 case CHANNEL_ENABLE_PRIVACY_MODE:
173 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=LeLensMask[0]");
176 return; // Return as we have handled the refresh command above and don't need to
178 } // end of "REFRESH"
179 switch (channelUID.getId()) {
180 case CHANNEL_TEXT_OVERLAY:
181 String text = Helper.encodeSpecialChars(command.toString());
182 if (text.isEmpty()) {
183 ipCameraHandler.sendHttpGET(
184 "/cgi-bin/configManager.cgi?action=setConfig&VideoWidget[0].CustomTitle[1].EncodeBlend=false");
186 ipCameraHandler.sendHttpGET(
187 "/cgi-bin/configManager.cgi?action=setConfig&VideoWidget[0].CustomTitle[1].EncodeBlend=true&VideoWidget[0].CustomTitle[1].Text="
191 case CHANNEL_ENABLE_LED:
192 ipCameraHandler.setChannelState(CHANNEL_AUTO_LED, OnOffType.OFF);
193 if (DecimalType.ZERO.equals(command) || OnOffType.OFF.equals(command)) {
194 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Off");
195 } else if (OnOffType.ON.equals(command)) {
197 .sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Manual");
199 ipCameraHandler.sendHttpGET(
200 "/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Manual&Lighting[0][0].MiddleLight[0].Light="
201 + command.toString());
204 case CHANNEL_AUTO_LED:
205 if (OnOffType.ON.equals(command)) {
206 ipCameraHandler.setChannelState(CHANNEL_ENABLE_LED, UnDefType.UNDEF);
207 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Auto");
210 case CHANNEL_THRESHOLD_AUDIO_ALARM:
211 int threshold = Math.round(Float.valueOf(command.toString()));
213 if (threshold == 0) {
214 ipCameraHandler.sendHttpGET(
215 "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationThreold=1");
217 ipCameraHandler.sendHttpGET(
218 "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationThreold=" + threshold);
221 case CHANNEL_ENABLE_AUDIO_ALARM:
222 if (OnOffType.ON.equals(command)) {
223 ipCameraHandler.sendHttpGET(
224 "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationDetect=true&AudioDetect[0].EventHandler.Dejitter=1");
226 ipCameraHandler.sendHttpGET(
227 "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationDetect=false");
230 case CHANNEL_ENABLE_LINE_CROSSING_ALARM:
231 if (OnOffType.ON.equals(command)) {
232 ipCameraHandler.sendHttpGET(
233 "/cgi-bin/configManager.cgi?action=setConfig&VideoAnalyseRule[0][1].Enable=true");
235 ipCameraHandler.sendHttpGET(
236 "/cgi-bin/configManager.cgi?action=setConfig&VideoAnalyseRule[0][1].Enable=false");
239 case CHANNEL_ENABLE_MOTION_ALARM:
240 if (OnOffType.ON.equals(command)) {
241 ipCameraHandler.sendHttpGET(
242 "/cgi-bin/configManager.cgi?action=setConfig&MotionDetect[0].Enable=true&MotionDetect[0].EventHandler.Dejitter=1");
245 .sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&MotionDetect[0].Enable=false");
248 case CHANNEL_ACTIVATE_ALARM_OUTPUT:
249 if (OnOffType.ON.equals(command)) {
250 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[0].Mode=1");
252 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[0].Mode=0");
255 case CHANNEL_ACTIVATE_ALARM_OUTPUT2:
256 if (OnOffType.ON.equals(command)) {
257 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[1].Mode=1");
259 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[1].Mode=0");
262 case CHANNEL_ENABLE_PRIVACY_MODE:
263 if (OnOffType.OFF.equals(command)) {
265 .sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&LeLensMask[0].Enable=false");
266 } else if (OnOffType.ON.equals(command)) {
268 .sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&LeLensMask[0].Enable=true");
274 // If a camera does not need to poll a request as often as snapshots, it can be
275 // added here. Binding steps through the list.
276 public ArrayList<String> getLowPriorityRequests() {
277 ArrayList<String> lowPriorityRequests = new ArrayList<String>(1);
278 return lowPriorityRequests;