2 * Copyright (c) 2010-2021 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.ArrayList;
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.types.Command;
27 import org.openhab.core.types.RefreshType;
28 import org.openhab.core.types.UnDefType;
30 import io.netty.channel.ChannelDuplexHandler;
31 import io.netty.channel.ChannelHandlerContext;
32 import io.netty.util.ReferenceCountUtil;
35 * The {@link DahuaHandler} is responsible for handling commands, which are
36 * sent to one of the channels.
38 * @author Matthew Skinner - Initial contribution
42 public class DahuaHandler extends ChannelDuplexHandler {
43 private IpCameraHandler ipCameraHandler;
44 private int nvrChannel;
46 public DahuaHandler(IpCameraHandler handler, int nvrChannel) {
47 ipCameraHandler = handler;
48 this.nvrChannel = nvrChannel;
51 // This handles the incoming http replies back from the camera.
53 public void channelRead(@Nullable ChannelHandlerContext ctx, @Nullable Object msg) throws Exception {
54 if (msg == null || ctx == null) {
58 String content = msg.toString();
59 ipCameraHandler.logger.trace("HTTP Result back from camera is \t:{}:", content);
60 // determine if the motion detection is turned on or off.
61 if (content.contains("table.MotionDetect[0].Enable=true")) {
62 ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.ON);
63 } else if (content.contains("table.MotionDetect[" + nvrChannel + "].Enable=false")) {
64 ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.OFF);
66 // Handle motion alarm
67 if (content.contains("Code=VideoMotion;action=Start;index=0")) {
68 ipCameraHandler.motionDetected(CHANNEL_MOTION_ALARM);
69 } else if (content.contains("Code=VideoMotion;action=Stop;index=0")) {
70 ipCameraHandler.noMotionDetected(CHANNEL_MOTION_ALARM);
72 // Handle item taken alarm
73 if (content.contains("Code=TakenAwayDetection;action=Start;index=0")) {
74 ipCameraHandler.motionDetected(CHANNEL_ITEM_TAKEN);
75 } else if (content.contains("Code=TakenAwayDetection;action=Stop;index=0")) {
76 ipCameraHandler.noMotionDetected(CHANNEL_ITEM_TAKEN);
78 // Handle item left alarm
79 if (content.contains("Code=LeftDetection;action=Start;index=0")) {
80 ipCameraHandler.motionDetected(CHANNEL_ITEM_LEFT);
81 } else if (content.contains("Code=LeftDetection;action=Stop;index=0")) {
82 ipCameraHandler.noMotionDetected(CHANNEL_ITEM_LEFT);
84 // Handle CrossLineDetection alarm
85 if (content.contains("Code=CrossLineDetection;action=Start;index=0")) {
86 ipCameraHandler.motionDetected(CHANNEL_LINE_CROSSING_ALARM);
87 } else if (content.contains("Code=CrossLineDetection;action=Stop;index=0")) {
88 ipCameraHandler.noMotionDetected(CHANNEL_LINE_CROSSING_ALARM);
90 // determine if the audio alarm is turned on or off.
91 if (content.contains("table.AudioDetect[0].MutationDetect=true")) {
92 ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.ON);
93 } else if (content.contains("table.AudioDetect[0].MutationDetect=false")) {
94 ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.OFF);
96 // Handle AudioMutation alarm
97 if (content.contains("Code=AudioMutation;action=Start;index=0")) {
98 ipCameraHandler.audioDetected();
99 } else if (content.contains("Code=AudioMutation;action=Stop;index=0")) {
100 ipCameraHandler.noAudioDetected();
102 // Handle AudioMutationThreshold alarm
103 if (content.contains("table.AudioDetect[0].MutationThreold=")) {
104 String value = ipCameraHandler.returnValueFromString(content, "table.AudioDetect[0].MutationThreold=");
105 ipCameraHandler.setChannelState(CHANNEL_THRESHOLD_AUDIO_ALARM, PercentType.valueOf(value));
107 // Handle FaceDetection alarm
108 if (content.contains("Code=FaceDetection;action=Start;index=0")) {
109 ipCameraHandler.motionDetected(CHANNEL_FACE_DETECTED);
110 } else if (content.contains("Code=FaceDetection;action=Stop;index=0")) {
111 ipCameraHandler.noMotionDetected(CHANNEL_FACE_DETECTED);
113 // Handle ParkingDetection alarm
114 if (content.contains("Code=ParkingDetection;action=Start;index=0")) {
115 ipCameraHandler.motionDetected(CHANNEL_PARKING_ALARM);
116 } else if (content.contains("Code=ParkingDetection;action=Stop;index=0")) {
117 ipCameraHandler.noMotionDetected(CHANNEL_PARKING_ALARM);
119 // Handle CrossRegionDetection alarm
120 if (content.contains("Code=CrossRegionDetection;action=Start;index=0")) {
121 ipCameraHandler.motionDetected(CHANNEL_FIELD_DETECTION_ALARM);
122 } else if (content.contains("Code=CrossRegionDetection;action=Stop;index=0")) {
123 ipCameraHandler.noMotionDetected(CHANNEL_FIELD_DETECTION_ALARM);
125 // Handle External Input alarm
126 if (content.contains("Code=AlarmLocal;action=Start;index=0")) {
127 ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT, OnOffType.ON);
128 } else if (content.contains("Code=AlarmLocal;action=Stop;index=0")) {
129 ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT, OnOffType.OFF);
131 // Handle External Input alarm2
132 if (content.contains("Code=AlarmLocal;action=Start;index=1")) {
133 ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT2, OnOffType.ON);
134 } else if (content.contains("Code=AlarmLocal;action=Stop;index=1")) {
135 ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT2, OnOffType.OFF);
137 // CrossLineDetection alarm on/off
138 if (content.contains("table.VideoAnalyseRule[0][1].Enable=true")) {
139 ipCameraHandler.setChannelState(CHANNEL_ENABLE_LINE_CROSSING_ALARM, OnOffType.ON);
140 } else if (content.contains("table.VideoAnalyseRule[0][1].Enable=false")) {
141 ipCameraHandler.setChannelState(CHANNEL_ENABLE_LINE_CROSSING_ALARM, OnOffType.OFF);
143 // Privacy Mode on/off
144 if (content.contains("Code=LensMaskOpen;") || content.contains("table.LeLensMask[0].Enable=true")) {
145 ipCameraHandler.setChannelState(CHANNEL_ENABLE_PRIVACY_MODE, OnOffType.ON);
146 } else if (content.contains("Code=LensMaskClose;")
147 || content.contains("table.LeLensMask[0].Enable=false")) {
148 ipCameraHandler.setChannelState(CHANNEL_ENABLE_PRIVACY_MODE, OnOffType.OFF);
151 ReferenceCountUtil.release(msg);
155 // This handles the commands that come from the Openhab event bus.
156 public void handleCommand(ChannelUID channelUID, Command command) {
157 if (command instanceof RefreshType) {
158 switch (channelUID.getId()) {
159 case CHANNEL_THRESHOLD_AUDIO_ALARM:
160 // ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=AudioDetect[0]");
162 case CHANNEL_ENABLE_AUDIO_ALARM:
163 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=AudioDetect[0]");
165 case CHANNEL_ENABLE_LINE_CROSSING_ALARM:
166 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=VideoAnalyseRule");
168 case CHANNEL_ENABLE_MOTION_ALARM:
169 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=MotionDetect[0]");
171 case CHANNEL_ENABLE_PRIVACY_MODE:
172 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=LeLensMask[0]");
175 return; // Return as we have handled the refresh command above and don't need to
177 } // end of "REFRESH"
178 switch (channelUID.getId()) {
179 case CHANNEL_TEXT_OVERLAY:
180 String text = Helper.encodeSpecialChars(command.toString());
181 if (text.isEmpty()) {
182 ipCameraHandler.sendHttpGET(
183 "/cgi-bin/configManager.cgi?action=setConfig&VideoWidget[0].CustomTitle[1].EncodeBlend=false");
185 ipCameraHandler.sendHttpGET(
186 "/cgi-bin/configManager.cgi?action=setConfig&VideoWidget[0].CustomTitle[1].EncodeBlend=true&VideoWidget[0].CustomTitle[1].Text="
190 case CHANNEL_ENABLE_LED:
191 ipCameraHandler.setChannelState(CHANNEL_AUTO_LED, OnOffType.OFF);
192 if (DecimalType.ZERO.equals(command) || OnOffType.OFF.equals(command)) {
193 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Off");
194 } else if (OnOffType.ON.equals(command)) {
196 .sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Manual");
198 ipCameraHandler.sendHttpGET(
199 "/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Manual&Lighting[0][0].MiddleLight[0].Light="
200 + command.toString());
203 case CHANNEL_AUTO_LED:
204 if (OnOffType.ON.equals(command)) {
205 ipCameraHandler.setChannelState(CHANNEL_ENABLE_LED, UnDefType.UNDEF);
206 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Auto");
209 case CHANNEL_THRESHOLD_AUDIO_ALARM:
210 int threshold = Math.round(Float.valueOf(command.toString()));
212 if (threshold == 0) {
213 ipCameraHandler.sendHttpGET(
214 "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationThreold=1");
216 ipCameraHandler.sendHttpGET(
217 "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationThreold=" + threshold);
220 case CHANNEL_ENABLE_AUDIO_ALARM:
221 if (OnOffType.ON.equals(command)) {
222 ipCameraHandler.sendHttpGET(
223 "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationDetect=true&AudioDetect[0].EventHandler.Dejitter=1");
225 ipCameraHandler.sendHttpGET(
226 "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationDetect=false");
229 case CHANNEL_ENABLE_LINE_CROSSING_ALARM:
230 if (OnOffType.ON.equals(command)) {
231 ipCameraHandler.sendHttpGET(
232 "/cgi-bin/configManager.cgi?action=setConfig&VideoAnalyseRule[0][1].Enable=true");
234 ipCameraHandler.sendHttpGET(
235 "/cgi-bin/configManager.cgi?action=setConfig&VideoAnalyseRule[0][1].Enable=false");
238 case CHANNEL_ENABLE_MOTION_ALARM:
239 if (OnOffType.ON.equals(command)) {
240 ipCameraHandler.sendHttpGET(
241 "/cgi-bin/configManager.cgi?action=setConfig&MotionDetect[0].Enable=true&MotionDetect[0].EventHandler.Dejitter=1");
244 .sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&MotionDetect[0].Enable=false");
247 case CHANNEL_ACTIVATE_ALARM_OUTPUT:
248 if (OnOffType.ON.equals(command)) {
249 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[0].Mode=1");
251 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[0].Mode=0");
254 case CHANNEL_ACTIVATE_ALARM_OUTPUT2:
255 if (OnOffType.ON.equals(command)) {
256 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[1].Mode=1");
258 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[1].Mode=0");
261 case CHANNEL_ENABLE_PRIVACY_MODE:
262 if (OnOffType.OFF.equals(command)) {
264 .sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&LeLensMask[0].Enable=false");
265 } else if (OnOffType.ON.equals(command)) {
267 .sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&LeLensMask[0].Enable=true");
273 // If a camera does not need to poll a request as often as snapshots, it can be
274 // added here. Binding steps through the list.
275 public ArrayList<String> getLowPriorityRequests() {
276 ArrayList<String> lowPriorityRequests = new ArrayList<String>(1);
277 return lowPriorityRequests;