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.thing.binding.ThingHandler;
29 import org.openhab.core.types.Command;
30 import org.openhab.core.types.RefreshType;
31 import org.openhab.core.types.UnDefType;
33 import io.netty.channel.ChannelDuplexHandler;
34 import io.netty.channel.ChannelHandlerContext;
35 import io.netty.util.ReferenceCountUtil;
38 * The {@link AmcrestHandler} is responsible for handling commands, which are
39 * sent to one of the channels.
41 * @author Matthew Skinner - Initial contribution
45 public class AmcrestHandler extends ChannelDuplexHandler {
46 private String requestUrl = "Empty";
47 private IpCameraHandler ipCameraHandler;
49 public AmcrestHandler(ThingHandler handler) {
50 ipCameraHandler = (IpCameraHandler) handler;
53 public void setURL(String url) {
57 // This handles the incoming http replies back from the camera.
59 public void channelRead(@Nullable ChannelHandlerContext ctx, @Nullable Object msg) throws Exception {
60 if (msg == null || ctx == null) {
64 String content = msg.toString();
66 if (!content.isEmpty()) {
67 ipCameraHandler.logger.trace("HTTP Result back from camera is \t:{}:", content);
69 if (content.contains("Error: No Events")) {
70 if ("/cgi-bin/eventManager.cgi?action=getEventIndexes&code=VideoMotion".equals(requestUrl)) {
71 ipCameraHandler.noMotionDetected(CHANNEL_MOTION_ALARM);
72 } else if ("/cgi-bin/eventManager.cgi?action=getEventIndexes&code=AudioMutation".equals(requestUrl)) {
73 ipCameraHandler.noAudioDetected();
75 } else if (content.contains("channels[0]=0")) {
76 if ("/cgi-bin/eventManager.cgi?action=getEventIndexes&code=VideoMotion".equals(requestUrl)) {
77 ipCameraHandler.motionDetected(CHANNEL_MOTION_ALARM);
78 } else if ("/cgi-bin/eventManager.cgi?action=getEventIndexes&code=AudioMutation".equals(requestUrl)) {
79 ipCameraHandler.audioDetected();
83 if (content.contains("table.MotionDetect[0].Enable=false")) {
84 ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.OFF);
85 } else if (content.contains("table.MotionDetect[0].Enable=true")) {
86 ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.ON);
88 // determine if the audio alarm is turned on or off.
89 if (content.contains("table.AudioDetect[0].MutationDetect=true")) {
90 ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.ON);
91 } else if (content.contains("table.AudioDetect[0].MutationDetect=false")) {
92 ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.OFF);
94 // Handle AudioMutationThreshold alarm
95 if (content.contains("table.AudioDetect[0].MutationThreold=")) {
96 String value = ipCameraHandler.returnValueFromString(content, "table.AudioDetect[0].MutationThreold=");
97 ipCameraHandler.setChannelState(CHANNEL_THRESHOLD_AUDIO_ALARM, PercentType.valueOf(value));
101 ReferenceCountUtil.release(msg);
106 // This handles the commands that come from the Openhab event bus.
107 public void handleCommand(ChannelUID channelUID, Command command) {
108 if (command instanceof RefreshType) {
109 switch (channelUID.getId()) {
110 case CHANNEL_THRESHOLD_AUDIO_ALARM:
111 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=AudioDetect[0]");
113 case CHANNEL_ENABLE_AUDIO_ALARM:
114 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=AudioDetect[0]");
116 case CHANNEL_ENABLE_LINE_CROSSING_ALARM:
118 .sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=CrossLineDetection[0]");
120 case CHANNEL_ENABLE_MOTION_ALARM:
121 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=MotionDetect[0]");
124 return; // Return as we have handled the refresh command above and don't need to
126 } // end of "REFRESH"
127 switch (channelUID.getId()) {
128 case CHANNEL_TEXT_OVERLAY:
129 String text = Helper.encodeSpecialChars(command.toString());
130 if (text.isEmpty()) {
131 ipCameraHandler.sendHttpGET(
132 "/cgi-bin/configManager.cgi?action=setConfig&VideoWidget[0].CustomTitle[1].EncodeBlend=false");
134 ipCameraHandler.sendHttpGET(
135 "/cgi-bin/configManager.cgi?action=setConfig&VideoWidget[0].CustomTitle[1].EncodeBlend=true&VideoWidget[0].CustomTitle[1].Text="
139 case CHANNEL_ENABLE_LED:
140 ipCameraHandler.setChannelState(CHANNEL_AUTO_LED, OnOffType.OFF);
141 if (DecimalType.ZERO.equals(command) || OnOffType.OFF.equals(command)) {
142 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Off");
143 } else if (OnOffType.ON.equals(command)) {
145 .sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Manual");
147 ipCameraHandler.sendHttpGET(
148 "/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Manual&Lighting[0][0].MiddleLight[0].Light="
149 + command.toString());
152 case CHANNEL_AUTO_LED:
153 if (OnOffType.ON.equals(command)) {
154 ipCameraHandler.setChannelState(CHANNEL_ENABLE_LED, UnDefType.UNDEF);
155 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&Lighting[0][0].Mode=Auto");
158 case CHANNEL_THRESHOLD_AUDIO_ALARM:
159 int threshold = Math.round(Float.valueOf(command.toString()));
161 if (threshold == 0) {
162 ipCameraHandler.sendHttpGET(
163 "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationThreold=1");
165 ipCameraHandler.sendHttpGET(
166 "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationThreold=" + threshold);
169 case CHANNEL_ENABLE_AUDIO_ALARM:
170 if (OnOffType.ON.equals(command)) {
171 ipCameraHandler.sendHttpGET(
172 "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationDetect=true&AudioDetect[0].EventHandler.Dejitter=1");
174 ipCameraHandler.sendHttpGET(
175 "/cgi-bin/configManager.cgi?action=setConfig&AudioDetect[0].MutationDetect=false");
178 case CHANNEL_ENABLE_LINE_CROSSING_ALARM:
179 if (OnOffType.ON.equals(command)) {
180 ipCameraHandler.sendHttpGET(
181 "/cgi-bin/configManager.cgi?action=setConfig&VideoAnalyseRule[0][1].Enable=true");
183 ipCameraHandler.sendHttpGET(
184 "/cgi-bin/configManager.cgi?action=setConfig&VideoAnalyseRule[0][1].Enable=false");
187 case CHANNEL_ENABLE_MOTION_ALARM:
188 if (OnOffType.ON.equals(command)) {
189 ipCameraHandler.sendHttpGET(
190 "/cgi-bin/configManager.cgi?action=setConfig&MotionDetect[0].Enable=true&MotionDetect[0].EventHandler.Dejitter=1");
193 .sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&MotionDetect[0].Enable=false");
196 case CHANNEL_ACTIVATE_ALARM_OUTPUT:
197 if (OnOffType.ON.equals(command)) {
198 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[0].Mode=1");
200 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[0].Mode=0");
203 case CHANNEL_ACTIVATE_ALARM_OUTPUT2:
204 if (OnOffType.ON.equals(command)) {
205 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[1].Mode=1");
207 ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=setConfig&AlarmOut[1].Mode=0");
210 case CHANNEL_FFMPEG_MOTION_CONTROL:
211 if (OnOffType.ON.equals(command)) {
212 ipCameraHandler.motionAlarmEnabled = true;
213 } else if (OnOffType.OFF.equals(command) || DecimalType.ZERO.equals(command)) {
214 ipCameraHandler.motionAlarmEnabled = false;
215 ipCameraHandler.noMotionDetected(CHANNEL_MOTION_ALARM);
217 ipCameraHandler.motionAlarmEnabled = true;
218 ipCameraHandler.motionThreshold = Double.valueOf(command.toString());
219 ipCameraHandler.motionThreshold = ipCameraHandler.motionThreshold / 10000;
221 ipCameraHandler.setupFfmpegFormat(FFmpegFormat.RTSP_ALARMS);
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;