]> git.basschouten.com Git - openhab-addons.git/blob
bdacdc168bfdfc5517c86f3afbeb52c4af89c65e
[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.math.BigDecimal;
18 import java.util.ArrayList;
19
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.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
30 import io.netty.channel.ChannelDuplexHandler;
31 import io.netty.channel.ChannelHandlerContext;
32 import io.netty.util.ReferenceCountUtil;
33
34 /**
35  * The {@link InstarHandler} is responsible for handling commands, which are
36  * sent to one of the channels.
37  *
38  * @author Matthew Skinner - Initial contribution
39  */
40
41 @NonNullByDefault
42 public class InstarHandler extends ChannelDuplexHandler {
43     private IpCameraHandler ipCameraHandler;
44     private String requestUrl = "Empty";
45
46     public InstarHandler(IpCameraHandler thingHandler) {
47         ipCameraHandler = thingHandler;
48     }
49
50     public void setURL(String url) {
51         requestUrl = url;
52     }
53
54     // This handles the incoming http replies back from the camera.
55     @Override
56     public void channelRead(@Nullable ChannelHandlerContext ctx, @Nullable Object msg) throws Exception {
57         if (msg == null || ctx == null) {
58             return;
59         }
60         try {
61             String value1 = "";
62             String content = msg.toString();
63             ipCameraHandler.logger.trace("HTTP Result back from camera is \t:{}:", content);
64             switch (requestUrl) {
65                 case "/param.cgi?cmd=getinfrared":
66                     if (content.contains("var infraredstat=\"auto") || content.contains("infraredstat=\"2\"")) {
67                         ipCameraHandler.setChannelState(CHANNEL_AUTO_LED, OnOffType.ON);
68                     } else {
69                         ipCameraHandler.setChannelState(CHANNEL_AUTO_LED, OnOffType.OFF);
70                     }
71                     break;
72                 case "/param.cgi?cmd=getoverlayattr&-region=1":// Text Overlays
73                     if (content.contains("var show_1=\"0\"") || content.contains("show=\"0\"")) {
74                         ipCameraHandler.setChannelState(CHANNEL_TEXT_OVERLAY, StringType.EMPTY);
75                     } else {
76                         value1 = Helper.searchString(content, "var name_1=\"");
77                         if (!value1.isEmpty()) {
78                             ipCameraHandler.setChannelState(CHANNEL_TEXT_OVERLAY, StringType.valueOf(value1));
79                         } else {
80                             value1 = Helper.searchString(content, "name=\"");
81                             if (!value1.isEmpty()) {
82                                 ipCameraHandler.setChannelState(CHANNEL_TEXT_OVERLAY, StringType.valueOf(value1));
83                             }
84                         }
85                     }
86                     break;
87                 case "/cgi-bin/hi3510/param.cgi?cmd=getmdattr":// Motion Alarm old
88                     if (content.contains("var m1_enable=\"1\"")) {
89                         ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.ON);
90                     } else {
91                         ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.OFF);
92                     }
93                     break;
94                 case "/param.cgi?cmd=getalarmattr":// Motion Alarm new
95                     if (content.contains("armed=\"1\"")) {
96                         ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.ON);
97                     } else {
98                         ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.OFF);
99                     }
100                     break;
101                 case "/param.cgi?cmd=getaudioalarmattr":// Audio Alarm
102                     if (content.contains("enable=\"1\"")) {
103                         ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.ON);
104                         value1 = Helper.searchString(content, "aa_value=\"");
105                         if (!value1.isEmpty()) {// old cameras have threshold in percentage
106                             ipCameraHandler.setChannelState(CHANNEL_THRESHOLD_AUDIO_ALARM, PercentType.valueOf(value1));
107                         } else {
108                             value1 = Helper.searchString(content, "threshold=\"");
109                             if (!value1.isEmpty()) {// newer cameras have values up to 10
110                                 ipCameraHandler.setChannelState(CHANNEL_THRESHOLD_AUDIO_ALARM,
111                                         PercentType.valueOf(value1 + "0"));
112                             }
113                         }
114                     } else {
115                         ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.OFF);
116                         ipCameraHandler.setChannelState(CHANNEL_THRESHOLD_AUDIO_ALARM, OnOffType.OFF);
117                     }
118                     break;
119                 case "/param.cgi?cmd=getpirattr":// PIR Alarm
120                     if (content.contains("enable=\"1\"")) {
121                         ipCameraHandler.setChannelState(CHANNEL_ENABLE_PIR_ALARM, OnOffType.ON);
122                     } else {
123                         ipCameraHandler.setChannelState(CHANNEL_ENABLE_PIR_ALARM, OnOffType.OFF);
124                     }
125                     // Reset the Alarm, need to find better place to put this.
126                     ipCameraHandler.noMotionDetected(CHANNEL_PIR_ALARM);
127                     break;
128                 case "/param.cgi?cmd=getioattr":// External Alarm Input
129                     if (content.contains("enable=\"1\"")) {
130                         ipCameraHandler.setChannelState(CHANNEL_ENABLE_EXTERNAL_ALARM_INPUT, OnOffType.ON);
131                     } else {
132                         ipCameraHandler.setChannelState(CHANNEL_ENABLE_EXTERNAL_ALARM_INPUT, OnOffType.OFF);
133                     }
134                     break;
135                 default:
136                     if (requestUrl.startsWith("/param.cgi?cmd=setasaction&-server=1&enable=1")
137                             && content.contains("response=\"200\";")) {// new
138                         ipCameraHandler.newInstarApi = true;
139                         ipCameraHandler.logger.debug("Alarm server sucessfully setup for a 2k+ Instar camera");
140                     } else if (requestUrl.startsWith("/param.cgi?cmd=setmdalarm&-aname=server2&-switch=on&-interval=1")
141                             && content.startsWith("[Succeed]set ok")) {
142                         ipCameraHandler.newInstarApi = false;
143                         ipCameraHandler.logger.debug("Alarm server sucessfully setup for a 1080p Instar camera");
144                     } else {
145                         ipCameraHandler.logger.debug("Unknown reply from URI:{}", requestUrl);
146                     }
147             }
148         } finally {
149             ReferenceCountUtil.release(msg);
150         }
151     }
152
153     // This handles the commands that come from the openHAB event bus.
154     public void handleCommand(ChannelUID channelUID, Command command) {
155         if (command instanceof RefreshType) {
156             switch (channelUID.getId()) {
157                 case CHANNEL_THRESHOLD_AUDIO_ALARM:
158                 case CHANNEL_ENABLE_AUDIO_ALARM:
159                     ipCameraHandler.sendHttpGET("/param.cgi?cmd=getaudioalarmattr");
160                     break;
161                 case CHANNEL_ENABLE_EXTERNAL_ALARM_INPUT:
162                     ipCameraHandler.sendHttpGET("/param.cgi?cmd=getioattr");
163                     break;
164                 case CHANNEL_ENABLE_MOTION_ALARM:
165                     if (ipCameraHandler.newInstarApi) {
166                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=getalarmattr");
167                     } else {
168                         ipCameraHandler.sendHttpGET("/cgi-bin/hi3510/param.cgi?cmd=getmdattr");
169                     }
170                     break;
171                 case CHANNEL_ENABLE_PIR_ALARM:
172                     ipCameraHandler.sendHttpGET("/param.cgi?cmd=getpirattr");
173                     break;
174                 case CHANNEL_AUTO_LED:
175                     ipCameraHandler.sendHttpGET("/param.cgi?cmd=getinfrared");
176                     break;
177                 case CHANNEL_TEXT_OVERLAY:
178                     ipCameraHandler.sendHttpGET("/param.cgi?cmd=getoverlayattr&-region=1");
179                     break;
180             }
181             return;
182         } // end of "REFRESH"
183         if (ipCameraHandler.newInstarApi) {
184             switch (channelUID.getId()) {
185                 case CHANNEL_THRESHOLD_AUDIO_ALARM:
186                     if (OnOffType.OFF.equals(command) || PercentType.ZERO.equals(command)) {
187                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setaudioalarmattr&enable=0");
188                     } else if (OnOffType.ON.equals(command)) {
189                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setaudioalarmattr&enable=1");
190                     } else if (command instanceof PercentType) {
191                         int value = ((PercentType) command).toBigDecimal().divide(BigDecimal.TEN).intValue();
192                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setaudioalarmattr&enable=1&threshold=" + value);
193                     }
194                     return;
195                 case CHANNEL_ENABLE_AUDIO_ALARM:
196                     if (OnOffType.ON.equals(command)) {
197                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setaudioalarmattr&enable=1");
198                     } else {
199                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setaudioalarmattr&enable=0");
200                     }
201                     return;
202                 case CHANNEL_ENABLE_MOTION_ALARM:
203                     if (OnOffType.ON.equals(command)) {
204                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setalarmattr&armed=1");
205                     } else {
206                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setalarmattr&armed=0");
207                     }
208                     return;
209                 case CHANNEL_TEXT_OVERLAY:
210                     String text = Helper.encodeSpecialChars(command.toString());
211                     if (text.isEmpty()) {
212                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setoverlayattr&-region=1&-show=0");
213                     } else {
214                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=" + text);
215                     }
216                     return;
217                 case CHANNEL_AUTO_LED:
218                     if (OnOffType.ON.equals(command)) {
219                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setinfrared&-infraredstat=2");
220                     } else {
221                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setinfrared&-infraredstat=0");
222                     }
223                     return;
224                 case CHANNEL_ENABLE_PIR_ALARM:
225                     if (OnOffType.ON.equals(command)) {
226                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setpirattr&enable=1");
227                     } else {
228                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setpirattr&enable=0");
229                     }
230                     return;
231                 case CHANNEL_ENABLE_EXTERNAL_ALARM_INPUT:
232                     if (OnOffType.ON.equals(command)) {
233                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setioattr&enable=1");
234                     } else {
235                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setioattr&enable=0");
236                     }
237                     return;
238             }
239         } else {
240             switch (channelUID.getId()) {
241                 case CHANNEL_THRESHOLD_AUDIO_ALARM:
242                     if (OnOffType.OFF.equals(command) || PercentType.ZERO.equals(command)) {
243                         ipCameraHandler.sendHttpGET("/cgi-bin/hi3510/param.cgi?cmd=setaudioalarmattr&-aa_enable=0");
244                     } else if (OnOffType.ON.equals(command)) {
245                         ipCameraHandler.sendHttpGET("/cgi-bin/hi3510/param.cgi?cmd=setaudioalarmattr&-aa_enable=1");
246                     } else if (command instanceof PercentType) {
247                         int value = ((PercentType) command).toBigDecimal().divide(BigDecimal.TEN).intValue();
248                         ipCameraHandler.sendHttpGET(
249                                 "/cgi-bin/hi3510/param.cgi?cmd=setaudioalarmattr&-aa_enable=1&-aa_value=" + value * 10);
250                     }
251                     return;
252                 case CHANNEL_ENABLE_AUDIO_ALARM:
253                     if (OnOffType.ON.equals(command)) {
254                         ipCameraHandler.sendHttpGET("/cgi-bin/hi3510/param.cgi?cmd=setaudioalarmattr&-aa_enable=1");
255                     } else {
256                         ipCameraHandler.sendHttpGET("/cgi-bin/hi3510/param.cgi?cmd=setaudioalarmattr&-aa_enable=0");
257                     }
258                     return;
259                 case CHANNEL_ENABLE_MOTION_ALARM:
260                     if (OnOffType.ON.equals(command)) {
261                         ipCameraHandler.sendHttpGET(
262                                 "/cgi-bin/hi3510/param.cgi?cmd=setmdattr&-enable=1&-name=1&cmd=setmdattr&-enable=1&-name=2&cmd=setmdattr&-enable=1&-name=3&cmd=setmdattr&-enable=1&-name=4");
263                     } else {
264                         ipCameraHandler.sendHttpGET(
265                                 "/cgi-bin/hi3510/param.cgi?cmd=setmdattr&-enable=0&-name=1&cmd=setmdattr&-enable=0&-name=2&cmd=setmdattr&-enable=0&-name=3&cmd=setmdattr&-enable=0&-name=4");
266                     }
267                     return;
268                 case CHANNEL_TEXT_OVERLAY:
269                     String text = Helper.encodeSpecialChars(command.toString());
270                     if (text.isEmpty()) {
271                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setoverlayattr&-region=1&-show=0");
272                     } else {
273                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=" + text);
274                     }
275                     return;
276                 case CHANNEL_AUTO_LED:
277                     if (OnOffType.ON.equals(command)) {
278                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setinfrared&-infraredstat=auto");
279                     } else {
280                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setinfrared&-infraredstat=close");
281                     }
282                     return;
283                 case CHANNEL_ENABLE_PIR_ALARM:
284                     if (OnOffType.ON.equals(command)) {
285                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setpirattr&-pir_enable=1");
286                     } else {
287                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setpirattr&-pir_enable=0");
288                     }
289                     return;
290                 case CHANNEL_ENABLE_EXTERNAL_ALARM_INPUT:
291                     if (OnOffType.ON.equals(command)) {
292                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setioattr&-io_enable=1");
293                     } else {
294                         ipCameraHandler.sendHttpGET("/param.cgi?cmd=setioattr&-io_enable=0");
295                     }
296                     return;
297             }
298         }
299     }
300
301     public void alarmTriggered(String alarm) {
302         // older cameras placed the & for the first query, whilst newer cameras do not.
303         // examples are /instar?&active=6 vs /instar?active=6&object=0
304         ipCameraHandler.setChannelState(CHANNEL_LAST_EVENT_DATA, new StringType(alarm));
305         String alarmCode = alarm.replaceAll(".+active=", "");
306         alarmCode = alarmCode.replaceAll("&.+", "");
307         String objectCode = alarm.replaceAll(".+object=", "");
308         switch (alarmCode) {
309             case "1":// The motion area boxes 1-4
310             case "2":
311             case "3":
312             case "4":
313                 ipCameraHandler.motionDetected(CHANNEL_MOTION_ALARM);
314                 break;
315             case "5":// PIR
316                 ipCameraHandler.motionDetected(CHANNEL_PIR_ALARM);
317                 break;
318             case "6":// Audio Alarm
319                 ipCameraHandler.audioDetected();
320                 break;
321             case "7":// Motion area 1 + PIR
322             case "8":// Motion area 2 + PIR
323             case "9":// Motion area 3 + PIR
324             case "10":// Motion area 4 + PIR
325                 ipCameraHandler.motionDetected(CHANNEL_MOTION_ALARM);
326                 ipCameraHandler.motionDetected(CHANNEL_PIR_ALARM);
327                 break;
328             default:
329                 ipCameraHandler.logger.debug("Unknown alarm code:{}", alarmCode);
330         }
331         if (!objectCode.isEmpty()) {
332             switch (objectCode) {
333                 // person=1, car=2, animal=4 so 1+2+4=7 means one of each.
334                 case "0":// no object
335                     break;
336                 case "1":
337                     ipCameraHandler.motionDetected(CHANNEL_HUMAN_ALARM);
338                     break;
339                 case "2":
340                     ipCameraHandler.motionDetected(CHANNEL_CAR_ALARM);
341                     break;
342                 case "3":
343                     ipCameraHandler.motionDetected(CHANNEL_HUMAN_ALARM);
344                     ipCameraHandler.motionDetected(CHANNEL_CAR_ALARM);
345                     break;
346                 case "4":
347                     ipCameraHandler.motionDetected(CHANNEL_ANIMAL_ALARM);
348                     break;
349                 case "5":
350                     ipCameraHandler.motionDetected(CHANNEL_HUMAN_ALARM);
351                     ipCameraHandler.motionDetected(CHANNEL_ANIMAL_ALARM);
352                     break;
353                 case "6":
354                     ipCameraHandler.motionDetected(CHANNEL_CAR_ALARM);
355                     ipCameraHandler.motionDetected(CHANNEL_ANIMAL_ALARM);
356                     break;
357                 case "7":
358                     ipCameraHandler.motionDetected(CHANNEL_HUMAN_ALARM);
359                     ipCameraHandler.motionDetected(CHANNEL_CAR_ALARM);
360                     ipCameraHandler.motionDetected(CHANNEL_ANIMAL_ALARM);
361                     break;
362                 default:
363                     if (objectCode.startsWith("/instar?")) {
364                         return;// has no object due to older Instar camera model
365                     }
366                     ipCameraHandler.logger.debug("Unknown object detection code:{}", objectCode);
367             }
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 ArrayList<String> getLowPriorityRequests() {
374         ArrayList<String> lowPriorityRequests = new ArrayList<String>(7);
375         lowPriorityRequests.add("/param.cgi?cmd=getaudioalarmattr");
376         lowPriorityRequests.add("/cgi-bin/hi3510/param.cgi?cmd=getmdattr");
377         lowPriorityRequests.add("/param.cgi?cmd=getalarmattr");
378         lowPriorityRequests.add("/param.cgi?cmd=getinfrared");
379         lowPriorityRequests.add("/param.cgi?cmd=getoverlayattr&-region=1");
380         lowPriorityRequests.add("/param.cgi?cmd=getpirattr");
381         lowPriorityRequests.add("/param.cgi?cmd=getioattr"); // ext alarm input on/off
382         return lowPriorityRequests;
383     }
384 }