]> git.basschouten.com Git - openhab-addons.git/blob
6f5746244ef4bf01bb9e12157701cb1498a6a3e5
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.ipcamera.internal;
14
15 import static org.openhab.binding.ipcamera.internal.IpCameraBindingConstants.*;
16
17 import java.util.List;
18
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.library.types.StringType;
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;
30
31 import io.netty.channel.ChannelDuplexHandler;
32 import io.netty.channel.ChannelHandlerContext;
33 import io.netty.util.ReferenceCountUtil;
34
35 /**
36  * The {@link DahuaHandler} is responsible for handling commands, which are
37  * sent to one of the channels.
38  *
39  * @author Matthew Skinner - Initial contribution
40  */
41
42 @NonNullByDefault
43 public class DahuaHandler extends ChannelDuplexHandler {
44     private IpCameraHandler ipCameraHandler;
45     private int nvrChannel;
46
47     public DahuaHandler(IpCameraHandler handler, int nvrChannel) {
48         ipCameraHandler = handler;
49         this.nvrChannel = nvrChannel;
50     }
51
52     private void processEvent(String content) {
53         int startIndex = content.indexOf("Code=", 12) + 5;// skip --myboundary and Code=
54         int endIndex = content.indexOf(";", startIndex + 1);
55         if (startIndex == -1 || endIndex == -1) {
56             ipCameraHandler.logger.debug("Code= not found in Dahua event. Content was:{}", content);
57             return;
58         }
59         String code = content.substring(startIndex, endIndex);
60         startIndex = endIndex + 8;// skip ;action=
61         endIndex = content.indexOf(";", startIndex);
62         if (startIndex == -1 || endIndex == -1) {
63             ipCameraHandler.logger.debug(";action= not found in Dahua event. Content was:{}", content);
64             return;
65         }
66         String action = content.substring(startIndex, endIndex);
67         startIndex = content.indexOf(";data=", startIndex);
68         if (startIndex > 0) {
69             endIndex = content.lastIndexOf("}");
70             if (endIndex > 0) {
71                 String data = content.substring(startIndex + 6, endIndex + 1);
72                 ipCameraHandler.setChannelState(CHANNEL_LAST_EVENT_DATA, new StringType(data));
73             }
74         }
75         switch (code) {
76             case "VideoMotion":
77                 if ("Start".equals(action)) {
78                     ipCameraHandler.motionDetected(CHANNEL_MOTION_ALARM);
79                 } else if ("Stop".equals(action)) {
80                     ipCameraHandler.noMotionDetected(CHANNEL_MOTION_ALARM);
81                 }
82                 break;
83             case "TakenAwayDetection":
84                 if ("Start".equals(action)) {
85                     ipCameraHandler.motionDetected(CHANNEL_ITEM_TAKEN);
86                 } else if ("Stop".equals(action)) {
87                     ipCameraHandler.noMotionDetected(CHANNEL_ITEM_TAKEN);
88                 }
89                 break;
90             case "LeftDetection":
91                 if ("Start".equals(action)) {
92                     ipCameraHandler.motionDetected(CHANNEL_ITEM_LEFT);
93                 } else if ("Stop".equals(action)) {
94                     ipCameraHandler.noMotionDetected(CHANNEL_ITEM_LEFT);
95                 }
96                 break;
97             case "SmartMotionVehicle":
98                 if ("Start".equals(action)) {
99                     ipCameraHandler.motionDetected(CHANNEL_CAR_ALARM);
100                 } else if ("Stop".equals(action)) {
101                     ipCameraHandler.noMotionDetected(CHANNEL_CAR_ALARM);
102                 }
103                 break;
104             case "SmartMotionHuman":
105                 if ("Start".equals(action)) {
106                     ipCameraHandler.motionDetected(CHANNEL_HUMAN_ALARM);
107                 } else if ("Stop".equals(action)) {
108                     ipCameraHandler.noMotionDetected(CHANNEL_HUMAN_ALARM);
109                 }
110                 break;
111             case "CrossLineDetection":
112                 if ("Start".equals(action)) {
113                     ipCameraHandler.motionDetected(CHANNEL_LINE_CROSSING_ALARM);
114                 } else if ("Stop".equals(action)) {
115                     ipCameraHandler.noMotionDetected(CHANNEL_LINE_CROSSING_ALARM);
116                 }
117                 break;
118             case "AudioAnomaly":
119             case "AudioMutation":
120                 if ("Start".equals(action)) {
121                     ipCameraHandler.audioDetected();
122                 } else if ("Stop".equals(action)) {
123                     ipCameraHandler.noAudioDetected();
124                 }
125                 break;
126             case "FaceDetection":
127                 if ("Start".equals(action)) {
128                     ipCameraHandler.motionDetected(CHANNEL_FACE_DETECTED);
129                 } else if ("Stop".equals(action)) {
130                     ipCameraHandler.noMotionDetected(CHANNEL_FACE_DETECTED);
131                 }
132                 break;
133             case "ParkingDetection":
134                 if ("Start".equals(action)) {
135                     ipCameraHandler.setChannelState(CHANNEL_PARKING_ALARM, OnOffType.ON);
136                 } else if ("Stop".equals(action)) {
137                     ipCameraHandler.setChannelState(CHANNEL_PARKING_ALARM, OnOffType.OFF);
138                 }
139                 break;
140             case "CrossRegionDetection":
141                 if ("Start".equals(action)) {
142                     ipCameraHandler.motionDetected(CHANNEL_FIELD_DETECTION_ALARM);
143                 } else if ("Stop".equals(action)) {
144                     ipCameraHandler.noMotionDetected(CHANNEL_FIELD_DETECTION_ALARM);
145                 }
146                 break;
147             case "VideoLoss":
148             case "VideoBlind":
149                 if ("Start".equals(action)) {
150                     ipCameraHandler.setChannelState(CHANNEL_TOO_DARK_ALARM, OnOffType.ON);
151                 } else if ("Stop".equals(action)) {
152                     ipCameraHandler.setChannelState(CHANNEL_TOO_DARK_ALARM, OnOffType.OFF);
153                 }
154                 break;
155             case "VideoAbnormalDetection":
156                 if ("Start".equals(action)) {
157                     ipCameraHandler.setChannelState(CHANNEL_SCENE_CHANGE_ALARM, OnOffType.ON);
158                 } else if ("Stop".equals(action)) {
159                     ipCameraHandler.setChannelState(CHANNEL_SCENE_CHANGE_ALARM, OnOffType.OFF);
160                 }
161                 break;
162             case "VideoUnFocus":
163                 if ("Start".equals(action)) {
164                     ipCameraHandler.setChannelState(CHANNEL_TOO_BLURRY_ALARM, OnOffType.ON);
165                 } else if ("Stop".equals(action)) {
166                     ipCameraHandler.setChannelState(CHANNEL_TOO_BLURRY_ALARM, OnOffType.OFF);
167                 }
168                 break;
169             case "AlarmLocal":
170                 if ("Start".equals(action)) {
171                     if (content.contains("index=0")) {
172                         ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT, OnOffType.ON);
173                     } else {
174                         ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT2, OnOffType.ON);
175                     }
176                 } else if ("Stop".equals(action)) {
177                     if (content.contains("index=0")) {
178                         ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT, OnOffType.OFF);
179                     } else {
180                         ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT2, OnOffType.OFF);
181                     }
182                 }
183                 break;
184             case "LensMaskOpen":
185                 ipCameraHandler.setChannelState(CHANNEL_ENABLE_PRIVACY_MODE, OnOffType.ON);
186                 break;
187             case "LensMaskClose":
188                 ipCameraHandler.setChannelState(CHANNEL_ENABLE_PRIVACY_MODE, OnOffType.OFF);
189                 break;
190             // Skip these so they are not logged.
191             case "TimeChange":
192             case "IntelliFrame":
193             case "NTPAdjustTime":
194             case "StorageChange":
195             case "Reboot":
196             case "NewFile":
197             case "VideoMotionInfo":
198             case "RtspSessionDisconnect":
199             case "LeFunctionStatusSync":
200             case "RecordDelete":
201                 break;
202             default:
203                 ipCameraHandler.logger.debug("Unrecognised Dahua event, Code={}, action={}", code, action);
204         }
205     }
206
207     // This handles the incoming http replies back from the camera.
208     @Override
209     public void channelRead(@Nullable ChannelHandlerContext ctx, @Nullable Object msg) throws Exception {
210         if (msg == null || ctx == null) {
211             return;
212         }
213         try {
214             String content = msg.toString();
215             if (content.startsWith("--myboundary")) {
216                 processEvent(content);
217                 return;
218             }
219             ipCameraHandler.logger.trace("HTTP Result back from camera is \t:{}:", content);
220             // determine if the motion detection is turned on or off.
221             if (content.contains("table.MotionDetect[0].Enable=true")) {
222                 ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.ON);
223             } else if (content.contains("table.MotionDetect[" + nvrChannel + "].Enable=false")) {
224                 ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.OFF);
225             }
226
227             // determine if the audio alarm is turned on or off.
228             if (content.contains("table.AudioDetect[0].MutationDetect=true")) {
229                 ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.ON);
230             } else if (content.contains("table.AudioDetect[0].MutationDetect=false")) {
231                 ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.OFF);
232             }
233
234             // Handle AudioMutationThreshold alarm
235             if (content.contains("table.AudioDetect[0].MutationThreold=")) {
236                 String value = ipCameraHandler.returnValueFromString(content, "table.AudioDetect[0].MutationThreold=");
237                 ipCameraHandler.setChannelState(CHANNEL_THRESHOLD_AUDIO_ALARM, PercentType.valueOf(value));
238             }
239
240             // CrossLineDetection alarm on/off
241             if (content.contains("table.VideoAnalyseRule[0][1].Enable=true")) {
242                 ipCameraHandler.setChannelState(CHANNEL_ENABLE_LINE_CROSSING_ALARM, OnOffType.ON);
243             } else if (content.contains("table.VideoAnalyseRule[0][1].Enable=false")) {
244                 ipCameraHandler.setChannelState(CHANNEL_ENABLE_LINE_CROSSING_ALARM, OnOffType.OFF);
245             }
246             // Privacy Mode on/off
247             if (content.contains("table.LeLensMask[0].Enable=true")) {
248                 ipCameraHandler.setChannelState(CHANNEL_ENABLE_PRIVACY_MODE, OnOffType.ON);
249             } else if (content.contains("table.LeLensMask[0].Enable=false")) {
250                 ipCameraHandler.setChannelState(CHANNEL_ENABLE_PRIVACY_MODE, OnOffType.OFF);
251             }
252         } finally {
253             ReferenceCountUtil.release(msg);
254         }
255     }
256
257     // This handles the commands that come from the openHAB event bus.
258     public void handleCommand(ChannelUID channelUID, Command command) {
259         if (command instanceof RefreshType) {
260             switch (channelUID.getId()) {
261                 case CHANNEL_ENABLE_AUDIO_ALARM:
262                     ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=AudioDetect[0]");
263                     return;
264                 case CHANNEL_ENABLE_LINE_CROSSING_ALARM:
265                     ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=VideoAnalyseRule");
266                     return;
267                 case CHANNEL_ENABLE_MOTION_ALARM:
268                     ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=MotionDetect[0]");
269                     return;
270                 case CHANNEL_ENABLE_PRIVACY_MODE:
271                     ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=LeLensMask[0]");
272                     return;
273             }
274             return;
275         } // end of "REFRESH"
276         switch (channelUID.getId()) {
277             case CHANNEL_TEXT_OVERLAY:
278                 String text = Helper.encodeSpecialChars(command.toString());
279                 if (text.isEmpty()) {
280                     ipCameraHandler.sendHttpGET(
281                             "/cgi-bin/configManager.cgi?action=setConfig&VideoWidget[0].CustomTitle[1].EncodeBlend=false");
282                 } else {
283                     ipCameraHandler.sendHttpGET(
284                             "/cgi-bin/configManager.cgi?action=setConfig&VideoWidget[0].CustomTitle[1].EncodeBlend=true&VideoWidget[0].CustomTitle[1].Text="
285                                     + text);
286                 }
287                 return;
288             case CHANNEL_ENABLE_LED:
289                 ipCameraHandler.setChannelState(CHANNEL_AUTO_LED, OnOffType.OFF);
290                 if (DecimalType.ZERO.equals(command) || OnOffType.OFF.equals(command)) {
291                     ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Off");
292                 } else if (OnOffType.ON.equals(command)) {
293                     ipCameraHandler
294                             .sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Manual");
295                 } else {
296                     ipCameraHandler.sendHttpGET(
297                             "/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Manual&Lighting[0][0].MiddleLight[0].Light="
298                                     + command.toString());
299                 }
300                 return;
301             case CHANNEL_AUTO_LED:
302                 if (OnOffType.ON.equals(command)) {
303                     ipCameraHandler.setChannelState(CHANNEL_ENABLE_LED, UnDefType.UNDEF);
304                     ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Auto");
305                 }
306                 return;
307             case CHANNEL_THRESHOLD_AUDIO_ALARM:
308                 int threshold = Math.round(Float.valueOf(command.toString()));
309
310                 if (threshold == 0) {
311                     ipCameraHandler.sendHttpGET(
312                             "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationThreold=1");
313                 } else {
314                     ipCameraHandler.sendHttpGET(
315                             "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationThreold=" + threshold);
316                 }
317                 return;
318             case CHANNEL_ENABLE_AUDIO_ALARM:
319                 if (OnOffType.ON.equals(command)) {
320                     ipCameraHandler.sendHttpGET(
321                             "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationDetect=true&AudioDetect[0].EventHandler.Dejitter=1");
322                 } else {
323                     ipCameraHandler.sendHttpGET(
324                             "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationDetect=false");
325                 }
326                 return;
327             case CHANNEL_ENABLE_LINE_CROSSING_ALARM:
328                 if (OnOffType.ON.equals(command)) {
329                     ipCameraHandler.sendHttpGET(
330                             "/cgi-bin/configManager.cgi?action=setConfig&VideoAnalyseRule[0][1].Enable=true");
331                 } else {
332                     ipCameraHandler.sendHttpGET(
333                             "/cgi-bin/configManager.cgi?action=setConfig&VideoAnalyseRule[0][1].Enable=false");
334                 }
335                 return;
336             case CHANNEL_ENABLE_MOTION_ALARM:
337                 if (OnOffType.ON.equals(command)) {
338                     ipCameraHandler.sendHttpGET(
339                             "/cgi-bin/configManager.cgi?action=setConfig&MotionDetect[0].Enable=true&MotionDetect[0].EventHandler.Dejitter=1");
340                 } else {
341                     ipCameraHandler
342                             .sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&MotionDetect[0].Enable=false");
343                 }
344                 return;
345             case CHANNEL_ACTIVATE_ALARM_OUTPUT:
346                 if (OnOffType.ON.equals(command)) {
347                     ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[0].Mode=1");
348                 } else {
349                     ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[0].Mode=0");
350                 }
351                 return;
352             case CHANNEL_ACTIVATE_ALARM_OUTPUT2:
353                 if (OnOffType.ON.equals(command)) {
354                     ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[1].Mode=1");
355                 } else {
356                     ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[1].Mode=0");
357                 }
358                 return;
359             case CHANNEL_ENABLE_PRIVACY_MODE:
360                 if (OnOffType.OFF.equals(command)) {
361                     ipCameraHandler
362                             .sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&LeLensMask[0].Enable=false");
363                 } else if (OnOffType.ON.equals(command)) {
364                     ipCameraHandler
365                             .sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&LeLensMask[0].Enable=true");
366                 }
367                 return;
368         }
369     }
370
371     // If a camera does not need to poll a request as often as snapshots, it can be
372     // added here. Binding steps through the list.
373     public List<String> getLowPriorityRequests() {
374         return List.of();
375     }
376 }