2 * Copyright (c) 2010-2023 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.thing.binding.ThingHandler;
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 AmcrestHandler} is responsible for handling commands, which are
37 * sent to one of the channels.
39 * @author Matthew Skinner - Initial contribution
43 public class AmcrestHandler extends ChannelDuplexHandler {
44 private String requestUrl = "Empty";
45 private IpCameraHandler ipCameraHandler;
47 public AmcrestHandler(ThingHandler handler) {
48 ipCameraHandler = (IpCameraHandler) handler;
51 public void setURL(String url) {
55 // This handles the incoming http replies back from the camera.
57 public void channelRead(@Nullable ChannelHandlerContext ctx, @Nullable Object msg) throws Exception {
58 if (msg == null || ctx == null) {
62 String content = msg.toString();
63 ipCameraHandler.logger.trace("HTTP Result back from camera is \t:{}:", content);
64 if (content.contains("Error: No Events")) {
65 if ("/cgi-bin/eventManager.cgi?action=getEventIndexes&code=VideoMotion".equals(requestUrl)) {
66 ipCameraHandler.noMotionDetected(CHANNEL_MOTION_ALARM);
67 } else if ("/cgi-bin/eventManager.cgi?action=getEventIndexes&code=AudioMutation".equals(requestUrl)) {
68 ipCameraHandler.noAudioDetected();
70 } else if (content.contains("channels[0]=0")) {
71 if ("/cgi-bin/eventManager.cgi?action=getEventIndexes&code=VideoMotion".equals(requestUrl)) {
72 ipCameraHandler.motionDetected(CHANNEL_MOTION_ALARM);
73 } else if ("/cgi-bin/eventManager.cgi?action=getEventIndexes&code=AudioMutation".equals(requestUrl)) {
74 ipCameraHandler.audioDetected();
78 if (content.contains("table.MotionDetect[0].Enable=false")) {
79 ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.OFF);
80 } else if (content.contains("table.MotionDetect[0].Enable=true")) {
81 ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.ON);
83 // determine if the audio alarm is turned on or off.
84 if (content.contains("table.AudioDetect[0].MutationDetect=true")) {
85 ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.ON);
86 } else if (content.contains("table.AudioDetect[0].MutationDetect=false")) {
87 ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.OFF);
89 // Handle AudioMutationThreshold alarm
90 if (content.contains("table.AudioDetect[0].MutationThreold=")) {
91 String value = ipCameraHandler.returnValueFromString(content, "table.AudioDetect[0].MutationThreold=");
92 ipCameraHandler.setChannelState(CHANNEL_THRESHOLD_AUDIO_ALARM, PercentType.valueOf(value));
94 // Privacy Mode on/off
95 if (content.contains("Code=LensMaskOpen;") || content.contains("table.LeLensMask[0].Enable=true")) {
96 ipCameraHandler.setChannelState(CHANNEL_ENABLE_PRIVACY_MODE, OnOffType.ON);
97 } else if (content.contains("Code=LensMaskClose;")
98 || content.contains("table.LeLensMask[0].Enable=false")) {
99 ipCameraHandler.setChannelState(CHANNEL_ENABLE_PRIVACY_MODE, OnOffType.OFF);
102 ReferenceCountUtil.release(msg);
107 // This handles the commands that come from the Openhab event bus.
108 public void handleCommand(ChannelUID channelUID, Command command) {
109 if (command instanceof RefreshType) {
110 switch (channelUID.getId()) {
111 case CHANNEL_THRESHOLD_AUDIO_ALARM:
112 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=AudioDetect[0]");
114 case CHANNEL_ENABLE_AUDIO_ALARM:
115 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=AudioDetect[0]");
117 case CHANNEL_ENABLE_LINE_CROSSING_ALARM:
119 .sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=CrossLineDetection[0]");
121 case CHANNEL_ENABLE_MOTION_ALARM:
122 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=MotionDetect[0]");
124 case CHANNEL_ENABLE_PRIVACY_MODE:
125 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=LeLensMask[0]");
128 return; // Return as we have handled the refresh command above and don't need to
130 } // end of "REFRESH"
131 switch (channelUID.getId()) {
132 case CHANNEL_TEXT_OVERLAY:
133 String text = Helper.encodeSpecialChars(command.toString());
134 if (text.isEmpty()) {
135 ipCameraHandler.sendHttpGET(
136 "/cgi-bin/configManager.cgi?action=setConfig&VideoWidget[0].CustomTitle[1].EncodeBlend=false");
138 ipCameraHandler.sendHttpGET(
139 "/cgi-bin/configManager.cgi?action=setConfig&VideoWidget[0].CustomTitle[1].EncodeBlend=true&VideoWidget[0].CustomTitle[1].Text="
143 case CHANNEL_ENABLE_LED:
144 ipCameraHandler.setChannelState(CHANNEL_AUTO_LED, OnOffType.OFF);
145 if (DecimalType.ZERO.equals(command) || OnOffType.OFF.equals(command)) {
146 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Off");
147 } else if (OnOffType.ON.equals(command)) {
149 .sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Manual");
151 ipCameraHandler.sendHttpGET(
152 "/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Manual&Lighting[0][0].MiddleLight[0].Light="
153 + command.toString());
156 case CHANNEL_AUTO_LED:
157 if (OnOffType.ON.equals(command)) {
158 ipCameraHandler.setChannelState(CHANNEL_ENABLE_LED, UnDefType.UNDEF);
159 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Auto");
162 case CHANNEL_THRESHOLD_AUDIO_ALARM:
163 int threshold = Math.round(Float.valueOf(command.toString()));
165 if (threshold == 0) {
166 ipCameraHandler.sendHttpGET(
167 "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationThreold=1");
169 ipCameraHandler.sendHttpGET(
170 "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationThreold=" + threshold);
173 case CHANNEL_ENABLE_AUDIO_ALARM:
174 if (OnOffType.ON.equals(command)) {
175 ipCameraHandler.sendHttpGET(
176 "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationDetect=true&AudioDetect[0].EventHandler.Dejitter=1");
178 ipCameraHandler.sendHttpGET(
179 "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationDetect=false");
182 case CHANNEL_ENABLE_LINE_CROSSING_ALARM:
183 if (OnOffType.ON.equals(command)) {
184 ipCameraHandler.sendHttpGET(
185 "/cgi-bin/configManager.cgi?action=setConfig&VideoAnalyseRule[0][1].Enable=true");
187 ipCameraHandler.sendHttpGET(
188 "/cgi-bin/configManager.cgi?action=setConfig&VideoAnalyseRule[0][1].Enable=false");
191 case CHANNEL_ENABLE_MOTION_ALARM:
192 if (OnOffType.ON.equals(command)) {
193 ipCameraHandler.sendHttpGET(
194 "/cgi-bin/configManager.cgi?action=setConfig&MotionDetect[0].Enable=true&MotionDetect[0].EventHandler.Dejitter=1");
197 .sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&MotionDetect[0].Enable=false");
200 case CHANNEL_ACTIVATE_ALARM_OUTPUT:
201 if (OnOffType.ON.equals(command)) {
202 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[0].Mode=1");
204 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[0].Mode=0");
207 case CHANNEL_ACTIVATE_ALARM_OUTPUT2:
208 if (OnOffType.ON.equals(command)) {
209 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[1].Mode=1");
211 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[1].Mode=0");
214 case CHANNEL_ENABLE_PRIVACY_MODE:
215 if (OnOffType.OFF.equals(command)) {
217 .sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&LeLensMask[0].Enable=false");
218 } else if (OnOffType.ON.equals(command)) {
220 .sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&LeLensMask[0].Enable=true");
226 // If a camera does not need to poll a request as often as snapshots, it can be
227 // added here. Binding steps through the list.
228 public ArrayList<String> getLowPriorityRequests() {
229 ArrayList<String> lowPriorityRequests = new ArrayList<String>(1);
230 return lowPriorityRequests;