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.IpCameraBindingConstants.FFmpegFormat;
23 import org.openhab.binding.ipcamera.internal.handler.IpCameraHandler;
24 import org.openhab.core.library.types.DecimalType;
25 import org.openhab.core.library.types.OnOffType;
26 import org.openhab.core.library.types.PercentType;
27 import org.openhab.core.thing.ChannelUID;
28 import org.openhab.core.types.Command;
29 import org.openhab.core.types.RefreshType;
30 import org.openhab.core.types.UnDefType;
32 import io.netty.channel.ChannelDuplexHandler;
33 import io.netty.channel.ChannelHandlerContext;
34 import io.netty.util.ReferenceCountUtil;
37 * The {@link DahuaHandler} is responsible for handling commands, which are
38 * sent to one of the channels.
40 * @author Matthew Skinner - Initial contribution
44 public class DahuaHandler extends ChannelDuplexHandler {
45 private IpCameraHandler ipCameraHandler;
46 private int nvrChannel;
48 public DahuaHandler(IpCameraHandler handler, int nvrChannel) {
49 ipCameraHandler = handler;
50 this.nvrChannel = nvrChannel;
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) {
59 String content = msg.toString();
61 if (!content.isEmpty()) {
62 ipCameraHandler.logger.trace("HTTP Result back from camera is \t:{}:", content);
64 // determine if the motion detection is turned on or off.
65 if (content.contains("table.MotionDetect[0].Enable=true")) {
66 ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.ON);
67 } else if (content.contains("table.MotionDetect[" + nvrChannel + "].Enable=false")) {
68 ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.OFF);
70 // Handle motion alarm
71 if (content.contains("Code=VideoMotion;action=Start;index=0")) {
72 ipCameraHandler.motionDetected(CHANNEL_MOTION_ALARM);
73 } else if (content.contains("Code=VideoMotion;action=Stop;index=0")) {
74 ipCameraHandler.noMotionDetected(CHANNEL_MOTION_ALARM);
76 // Handle item taken alarm
77 if (content.contains("Code=TakenAwayDetection;action=Start;index=0")) {
78 ipCameraHandler.motionDetected(CHANNEL_ITEM_TAKEN);
79 } else if (content.contains("Code=TakenAwayDetection;action=Stop;index=0")) {
80 ipCameraHandler.noMotionDetected(CHANNEL_ITEM_TAKEN);
82 // Handle item left alarm
83 if (content.contains("Code=LeftDetection;action=Start;index=0")) {
84 ipCameraHandler.motionDetected(CHANNEL_ITEM_LEFT);
85 } else if (content.contains("Code=LeftDetection;action=Stop;index=0")) {
86 ipCameraHandler.noMotionDetected(CHANNEL_ITEM_LEFT);
88 // Handle CrossLineDetection alarm
89 if (content.contains("Code=CrossLineDetection;action=Start;index=0")) {
90 ipCameraHandler.motionDetected(CHANNEL_LINE_CROSSING_ALARM);
91 } else if (content.contains("Code=CrossLineDetection;action=Stop;index=0")) {
92 ipCameraHandler.noMotionDetected(CHANNEL_LINE_CROSSING_ALARM);
94 // determine if the audio alarm is turned on or off.
95 if (content.contains("table.AudioDetect[0].MutationDetect=true")) {
96 ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.ON);
97 } else if (content.contains("table.AudioDetect[0].MutationDetect=false")) {
98 ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.OFF);
100 // Handle AudioMutation alarm
101 if (content.contains("Code=AudioMutation;action=Start;index=0")) {
102 ipCameraHandler.audioDetected();
103 } else if (content.contains("Code=AudioMutation;action=Stop;index=0")) {
104 ipCameraHandler.noAudioDetected();
106 // Handle AudioMutationThreshold alarm
107 if (content.contains("table.AudioDetect[0].MutationThreold=")) {
108 String value = ipCameraHandler.returnValueFromString(content, "table.AudioDetect[0].MutationThreold=");
109 ipCameraHandler.setChannelState(CHANNEL_THRESHOLD_AUDIO_ALARM, PercentType.valueOf(value));
111 // Handle FaceDetection alarm
112 if (content.contains("Code=FaceDetection;action=Start;index=0")) {
113 ipCameraHandler.motionDetected(CHANNEL_FACE_DETECTED);
114 } else if (content.contains("Code=FaceDetection;action=Stop;index=0")) {
115 ipCameraHandler.noMotionDetected(CHANNEL_FACE_DETECTED);
117 // Handle ParkingDetection alarm
118 if (content.contains("Code=ParkingDetection;action=Start;index=0")) {
119 ipCameraHandler.motionDetected(CHANNEL_PARKING_ALARM);
120 } else if (content.contains("Code=ParkingDetection;action=Stop;index=0")) {
121 ipCameraHandler.noMotionDetected(CHANNEL_PARKING_ALARM);
123 // Handle CrossRegionDetection alarm
124 if (content.contains("Code=CrossRegionDetection;action=Start;index=0")) {
125 ipCameraHandler.motionDetected(CHANNEL_FIELD_DETECTION_ALARM);
126 } else if (content.contains("Code=CrossRegionDetection;action=Stop;index=0")) {
127 ipCameraHandler.noMotionDetected(CHANNEL_FIELD_DETECTION_ALARM);
129 // Handle External Input alarm
130 if (content.contains("Code=AlarmLocal;action=Start;index=0")) {
131 ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT, OnOffType.ON);
132 } else if (content.contains("Code=AlarmLocal;action=Stop;index=0")) {
133 ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT, OnOffType.OFF);
135 // Handle External Input alarm2
136 if (content.contains("Code=AlarmLocal;action=Start;index=1")) {
137 ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT2, OnOffType.ON);
138 } else if (content.contains("Code=AlarmLocal;action=Stop;index=1")) {
139 ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT2, OnOffType.OFF);
141 // CrossLineDetection alarm on/off
142 if (content.contains("table.VideoAnalyseRule[0][1].Enable=true")) {
143 ipCameraHandler.setChannelState(CHANNEL_ENABLE_LINE_CROSSING_ALARM, OnOffType.ON);
144 } else if (content.contains("table.VideoAnalyseRule[0][1].Enable=false")) {
145 ipCameraHandler.setChannelState(CHANNEL_ENABLE_LINE_CROSSING_ALARM, OnOffType.OFF);
148 ReferenceCountUtil.release(msg);
152 // This handles the commands that come from the Openhab event bus.
153 public void handleCommand(ChannelUID channelUID, Command command) {
154 if (command instanceof RefreshType) {
155 switch (channelUID.getId()) {
156 case CHANNEL_THRESHOLD_AUDIO_ALARM:
157 // ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=AudioDetect[0]");
159 case CHANNEL_ENABLE_AUDIO_ALARM:
160 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=AudioDetect[0]");
162 case CHANNEL_ENABLE_LINE_CROSSING_ALARM:
163 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=VideoAnalyseRule");
165 case CHANNEL_ENABLE_MOTION_ALARM:
166 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=MotionDetect[0]");
169 return; // Return as we have handled the refresh command above and don't need to
171 } // end of "REFRESH"
172 switch (channelUID.getId()) {
173 case CHANNEL_TEXT_OVERLAY:
174 String text = Helper.encodeSpecialChars(command.toString());
175 if (text.isEmpty()) {
176 ipCameraHandler.sendHttpGET(
177 "/cgi-bin/configManager.cgi?action=setConfig&VideoWidget[0].CustomTitle[1].EncodeBlend=false");
179 ipCameraHandler.sendHttpGET(
180 "/cgi-bin/configManager.cgi?action=setConfig&VideoWidget[0].CustomTitle[1].EncodeBlend=true&VideoWidget[0].CustomTitle[1].Text="
184 case CHANNEL_ENABLE_LED:
185 ipCameraHandler.setChannelState(CHANNEL_AUTO_LED, OnOffType.OFF);
186 if (DecimalType.ZERO.equals(command) || OnOffType.OFF.equals(command)) {
187 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Off");
188 } else if (OnOffType.ON.equals(command)) {
190 .sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Manual");
192 ipCameraHandler.sendHttpGET(
193 "/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Manual&Lighting[0][0].MiddleLight[0].Light="
194 + command.toString());
197 case CHANNEL_AUTO_LED:
198 if (OnOffType.ON.equals(command)) {
199 ipCameraHandler.setChannelState(CHANNEL_ENABLE_LED, UnDefType.UNDEF);
200 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Auto");
203 case CHANNEL_THRESHOLD_AUDIO_ALARM:
204 int threshold = Math.round(Float.valueOf(command.toString()));
206 if (threshold == 0) {
207 ipCameraHandler.sendHttpGET(
208 "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationThreold=1");
210 ipCameraHandler.sendHttpGET(
211 "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationThreold=" + threshold);
214 case CHANNEL_ENABLE_AUDIO_ALARM:
215 if (OnOffType.ON.equals(command)) {
216 ipCameraHandler.sendHttpGET(
217 "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationDetect=true&AudioDetect[0].EventHandler.Dejitter=1");
219 ipCameraHandler.sendHttpGET(
220 "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationDetect=false");
223 case CHANNEL_ENABLE_LINE_CROSSING_ALARM:
224 if (OnOffType.ON.equals(command)) {
225 ipCameraHandler.sendHttpGET(
226 "/cgi-bin/configManager.cgi?action=setConfig&VideoAnalyseRule[0][1].Enable=true");
228 ipCameraHandler.sendHttpGET(
229 "/cgi-bin/configManager.cgi?action=setConfig&VideoAnalyseRule[0][1].Enable=false");
232 case CHANNEL_ENABLE_MOTION_ALARM:
233 if (OnOffType.ON.equals(command)) {
234 ipCameraHandler.sendHttpGET(
235 "/cgi-bin/configManager.cgi?action=setConfig&MotionDetect[0].Enable=true&MotionDetect[0].EventHandler.Dejitter=1");
238 .sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&MotionDetect[0].Enable=false");
241 case CHANNEL_ACTIVATE_ALARM_OUTPUT:
242 if (OnOffType.ON.equals(command)) {
243 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[0].Mode=1");
245 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[0].Mode=0");
248 case CHANNEL_ACTIVATE_ALARM_OUTPUT2:
249 if (OnOffType.ON.equals(command)) {
250 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[1].Mode=1");
252 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[1].Mode=0");
255 case CHANNEL_FFMPEG_MOTION_CONTROL:
256 if (OnOffType.ON.equals(command)) {
257 ipCameraHandler.motionAlarmEnabled = true;
258 } else if (OnOffType.OFF.equals(command) || DecimalType.ZERO.equals(command)) {
259 ipCameraHandler.motionAlarmEnabled = false;
260 ipCameraHandler.noMotionDetected(CHANNEL_MOTION_ALARM);
262 ipCameraHandler.motionAlarmEnabled = true;
263 ipCameraHandler.motionThreshold = Double.valueOf(command.toString()) / 10000;
265 ipCameraHandler.setupFfmpegFormat(FFmpegFormat.RTSP_ALARMS);
270 // If a camera does not need to poll a request as often as snapshots, it can be
271 // added here. Binding steps through the list.
272 public ArrayList<String> getLowPriorityRequests() {
273 ArrayList<String> lowPriorityRequests = new ArrayList<String>(1);
274 return lowPriorityRequests;