[ipcamera] Instar API updates for new 2k+ range (#13805)

* Instar updates
* Detect which API to use from reply.
* Add handling of REFRESH to instar.

Signed-off-by: Matthew Skinner <matt@pcmus.com>
This commit is contained in:
Matthew Skinner 2022-12-03 20:20:11 +11:00 committed by GitHub
parent 75b639e9b3
commit 2a78b306d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 215 additions and 77 deletions

View File

@ -14,6 +14,7 @@ package org.openhab.binding.ipcamera.internal;
import static org.openhab.binding.ipcamera.internal.IpCameraBindingConstants.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import org.eclipse.jdt.annotation.NonNullByDefault;
@ -62,43 +63,61 @@ public class InstarHandler extends ChannelDuplexHandler {
ipCameraHandler.logger.trace("HTTP Result back from camera is \t:{}:", content);
switch (requestUrl) {
case "/param.cgi?cmd=getinfrared":
if (content.contains("var infraredstat=\"auto")) {
if (content.contains("var infraredstat=\"auto") || content.contains("infraredstat=\"2\"")) {
ipCameraHandler.setChannelState(CHANNEL_AUTO_LED, OnOffType.ON);
} else {
ipCameraHandler.setChannelState(CHANNEL_AUTO_LED, OnOffType.OFF);
}
break;
case "/param.cgi?cmd=getoverlayattr&-region=1":// Text Overlays
if (content.contains("var show_1=\"0\"")) {
if (content.contains("var show_1=\"0\"") || content.contains("show=\"0\"")) {
ipCameraHandler.setChannelState(CHANNEL_TEXT_OVERLAY, StringType.EMPTY);
} else {
value1 = Helper.searchString(content, "var name_1=\"");
if (!value1.isEmpty()) {
ipCameraHandler.setChannelState(CHANNEL_TEXT_OVERLAY, StringType.valueOf(value1));
} else {
value1 = Helper.searchString(content, "name=\"");
if (!value1.isEmpty()) {
ipCameraHandler.setChannelState(CHANNEL_TEXT_OVERLAY, StringType.valueOf(value1));
}
}
}
break;
case "/cgi-bin/hi3510/param.cgi?cmd=getmdattr":// Motion Alarm
// Motion Alarm
case "/cgi-bin/hi3510/param.cgi?cmd=getmdattr":// Motion Alarm old
if (content.contains("var m1_enable=\"1\"")) {
ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.ON);
} else {
ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.OFF);
}
break;
case "/cgi-bin/hi3510/param.cgi?cmd=getaudioalarmattr":// Audio Alarm
if (content.contains("var aa_enable=\"1\"")) {
case "/param.cgi?cmd=getalarmattr":// Motion Alarm new
if (content.contains("armed=\"1\"")) {
ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.ON);
} else {
ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.OFF);
}
break;
case "/param.cgi?cmd=getaudioalarmattr":// Audio Alarm
if (content.contains("enable=\"1\"")) {
ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.ON);
value1 = Helper.searchString(content, "var aa_value=\"");
if (!value1.isEmpty()) {
value1 = Helper.searchString(content, "aa_value=\"");
if (!value1.isEmpty()) {// old cameras have threshold in percentage
ipCameraHandler.setChannelState(CHANNEL_THRESHOLD_AUDIO_ALARM, PercentType.valueOf(value1));
} else {
value1 = Helper.searchString(content, "threshold=\"");
if (!value1.isEmpty()) {// newer cameras have values up to 10
ipCameraHandler.setChannelState(CHANNEL_THRESHOLD_AUDIO_ALARM,
PercentType.valueOf(value1 + "0"));
}
}
} else {
ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.OFF);
ipCameraHandler.setChannelState(CHANNEL_THRESHOLD_AUDIO_ALARM, OnOffType.OFF);
}
break;
case "param.cgi?cmd=getpirattr":// PIR Alarm
if (content.contains("var pir_enable=\"1\"")) {
case "/param.cgi?cmd=getpirattr":// PIR Alarm
if (content.contains("enable=\"1\"")) {
ipCameraHandler.setChannelState(CHANNEL_ENABLE_PIR_ALARM, OnOffType.ON);
} else {
ipCameraHandler.setChannelState(CHANNEL_ENABLE_PIR_ALARM, OnOffType.OFF);
@ -107,80 +126,175 @@ public class InstarHandler extends ChannelDuplexHandler {
ipCameraHandler.noMotionDetected(CHANNEL_PIR_ALARM);
break;
case "/param.cgi?cmd=getioattr":// External Alarm Input
if (content.contains("var io_enable=\"1\"")) {
if (content.contains("enable=\"1\"")) {
ipCameraHandler.setChannelState(CHANNEL_ENABLE_EXTERNAL_ALARM_INPUT, OnOffType.ON);
} else {
ipCameraHandler.setChannelState(CHANNEL_ENABLE_EXTERNAL_ALARM_INPUT, OnOffType.OFF);
}
break;
default:
if (requestUrl.startsWith("/param.cgi?cmd=setasaction&-server=1&enable=1")
&& content.contains("response=\"200\";")) {// new
ipCameraHandler.newInstarApi = true;
ipCameraHandler.logger.debug("Alarm server sucessfully setup for a 2k+ Instar camera");
} else if (requestUrl.startsWith("/param.cgi?cmd=setmdalarm&-aname=server2&-switch=on&-interval=1")
&& content.startsWith("[Succeed]set ok")) {
ipCameraHandler.newInstarApi = false;
ipCameraHandler.logger.debug("Alarm server sucessfully setup for a 1080p Instar camera");
} else {
ipCameraHandler.logger.debug("Unknown reply from URI:{}", requestUrl);
}
}
} finally {
ReferenceCountUtil.release(msg);
}
}
// This handles the commands that come from the Openhab event bus.
// This handles the commands that come from the openHAB event bus.
public void handleCommand(ChannelUID channelUID, Command command) {
if (command instanceof RefreshType) {
switch (channelUID.getId()) {
case CHANNEL_THRESHOLD_AUDIO_ALARM:
case CHANNEL_ENABLE_AUDIO_ALARM:
ipCameraHandler.sendHttpGET("/param.cgi?cmd=getaudioalarmattr");
break;
case CHANNEL_ENABLE_EXTERNAL_ALARM_INPUT:
ipCameraHandler.sendHttpGET("/param.cgi?cmd=getioattr");
break;
case CHANNEL_ENABLE_MOTION_ALARM:
if (ipCameraHandler.newInstarApi) {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=getalarmattr");
} else {
ipCameraHandler.sendHttpGET("/cgi-bin/hi3510/param.cgi?cmd=getmdattr");
}
break;
case CHANNEL_ENABLE_PIR_ALARM:
ipCameraHandler.sendHttpGET("/param.cgi?cmd=getpirattr");
break;
case CHANNEL_AUTO_LED:
ipCameraHandler.sendHttpGET("/param.cgi?cmd=getinfrared");
break;
case CHANNEL_TEXT_OVERLAY:
ipCameraHandler.sendHttpGET("/param.cgi?cmd=getoverlayattr&-region=1");
break;
}
return;
} // end of "REFRESH"
switch (channelUID.getId()) {
case CHANNEL_THRESHOLD_AUDIO_ALARM:
int value = Math.round(Float.valueOf(command.toString()));
if (value == 0) {
ipCameraHandler.sendHttpGET("/cgi-bin/hi3510/param.cgi?cmd=setaudioalarmattr&-aa_enable=0");
} else {
ipCameraHandler.sendHttpGET("/cgi-bin/hi3510/param.cgi?cmd=setaudioalarmattr&-aa_enable=1");
ipCameraHandler
.sendHttpGET("/cgi-bin/hi3510/param.cgi?cmd=setaudioalarmattr&-aa_enable=1&-aa_value="
+ command.toString());
}
return;
case CHANNEL_ENABLE_AUDIO_ALARM:
if (OnOffType.ON.equals(command)) {
ipCameraHandler.sendHttpGET("/cgi-bin/hi3510/param.cgi?cmd=setaudioalarmattr&-aa_enable=1");
} else {
ipCameraHandler.sendHttpGET("/cgi-bin/hi3510/param.cgi?cmd=setaudioalarmattr&-aa_enable=0");
}
return;
case CHANNEL_ENABLE_MOTION_ALARM:
if (OnOffType.ON.equals(command)) {
ipCameraHandler.sendHttpGET(
"/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");
} else {
ipCameraHandler.sendHttpGET(
"/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");
}
return;
case CHANNEL_TEXT_OVERLAY:
String text = Helper.encodeSpecialChars(command.toString());
if (text.isEmpty()) {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setoverlayattr&-region=1&-show=0");
} else {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=" + text);
}
return;
case CHANNEL_AUTO_LED:
if (OnOffType.ON.equals(command)) {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setinfrared&-infraredstat=auto");
} else {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setinfrared&-infraredstat=close");
}
return;
case CHANNEL_ENABLE_PIR_ALARM:
if (OnOffType.ON.equals(command)) {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setpirattr&-pir_enable=1");
} else {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setpirattr&-pir_enable=0");
}
return;
case CHANNEL_ENABLE_EXTERNAL_ALARM_INPUT:
if (OnOffType.ON.equals(command)) {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setioattr&-io_enable=1");
} else {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setioattr&-io_enable=0");
}
return;
if (ipCameraHandler.newInstarApi) {
switch (channelUID.getId()) {
case CHANNEL_THRESHOLD_AUDIO_ALARM:
if (OnOffType.OFF.equals(command) || PercentType.ZERO.equals(command)) {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setaudioalarmattr&enable=0");
} else if (OnOffType.ON.equals(command)) {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setaudioalarmattr&enable=1");
} else if (command instanceof PercentType) {
int value = ((PercentType) command).toBigDecimal().divide(BigDecimal.TEN).intValue();
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setaudioalarmattr&enable=1&threshold=" + value);
}
return;
case CHANNEL_ENABLE_AUDIO_ALARM:
if (OnOffType.ON.equals(command)) {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setaudioalarmattr&enable=1");
} else {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setaudioalarmattr&enable=0");
}
return;
case CHANNEL_ENABLE_MOTION_ALARM:
if (OnOffType.ON.equals(command)) {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setalarmattr&armed=1");
} else {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setalarmattr&armed=0");
}
return;
case CHANNEL_TEXT_OVERLAY:
String text = Helper.encodeSpecialChars(command.toString());
if (text.isEmpty()) {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setoverlayattr&-region=1&-show=0");
} else {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=" + text);
}
return;
case CHANNEL_AUTO_LED:
if (OnOffType.ON.equals(command)) {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setinfrared&-infraredstat=2");
} else {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setinfrared&-infraredstat=0");
}
return;
case CHANNEL_ENABLE_PIR_ALARM:
if (OnOffType.ON.equals(command)) {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setpirattr&enable=1");
} else {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setpirattr&enable=0");
}
return;
case CHANNEL_ENABLE_EXTERNAL_ALARM_INPUT:
if (OnOffType.ON.equals(command)) {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setioattr&enable=1");
} else {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setioattr&enable=0");
}
return;
}
} else {
switch (channelUID.getId()) {
case CHANNEL_THRESHOLD_AUDIO_ALARM:
if (OnOffType.OFF.equals(command) || PercentType.ZERO.equals(command)) {
ipCameraHandler.sendHttpGET("/cgi-bin/hi3510/param.cgi?cmd=setaudioalarmattr&-aa_enable=0");
} else if (OnOffType.ON.equals(command)) {
ipCameraHandler.sendHttpGET("/cgi-bin/hi3510/param.cgi?cmd=setaudioalarmattr&-aa_enable=1");
} else if (command instanceof PercentType) {
int value = ((PercentType) command).toBigDecimal().divide(BigDecimal.TEN).intValue();
ipCameraHandler.sendHttpGET(
"/cgi-bin/hi3510/param.cgi?cmd=setaudioalarmattr&-aa_enable=1&-aa_value=" + value * 10);
}
return;
case CHANNEL_ENABLE_AUDIO_ALARM:
if (OnOffType.ON.equals(command)) {
ipCameraHandler.sendHttpGET("/cgi-bin/hi3510/param.cgi?cmd=setaudioalarmattr&-aa_enable=1");
} else {
ipCameraHandler.sendHttpGET("/cgi-bin/hi3510/param.cgi?cmd=setaudioalarmattr&-aa_enable=0");
}
return;
case CHANNEL_ENABLE_MOTION_ALARM:
if (OnOffType.ON.equals(command)) {
ipCameraHandler.sendHttpGET(
"/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");
} else {
ipCameraHandler.sendHttpGET(
"/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");
}
return;
case CHANNEL_TEXT_OVERLAY:
String text = Helper.encodeSpecialChars(command.toString());
if (text.isEmpty()) {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setoverlayattr&-region=1&-show=0");
} else {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=" + text);
}
return;
case CHANNEL_AUTO_LED:
if (OnOffType.ON.equals(command)) {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setinfrared&-infraredstat=auto");
} else {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setinfrared&-infraredstat=close");
}
return;
case CHANNEL_ENABLE_PIR_ALARM:
if (OnOffType.ON.equals(command)) {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setpirattr&-pir_enable=1");
} else {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setpirattr&-pir_enable=0");
}
return;
case CHANNEL_ENABLE_EXTERNAL_ALARM_INPUT:
if (OnOffType.ON.equals(command)) {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setioattr&-io_enable=1");
} else {
ipCameraHandler.sendHttpGET("/param.cgi?cmd=setioattr&-io_enable=0");
}
return;
}
}
}
@ -216,20 +330,39 @@ public class InstarHandler extends ChannelDuplexHandler {
}
if (!objectCode.isEmpty()) {
switch (objectCode) {
// person=1, car=2, animal=4 so 1+2+4=7 means one of each.
case "0":// no object
break;
case "1":// person/human
case "1":
ipCameraHandler.motionDetected(CHANNEL_HUMAN_ALARM);
break;
case "2":// car/vehicles
case "2":
ipCameraHandler.motionDetected(CHANNEL_CAR_ALARM);
break;
case "3":
ipCameraHandler.motionDetected(CHANNEL_HUMAN_ALARM);
ipCameraHandler.motionDetected(CHANNEL_CAR_ALARM);
break;
case "3":// animals
case "4":
ipCameraHandler.motionDetected(CHANNEL_ANIMAL_ALARM);
break;
case "5":
ipCameraHandler.motionDetected(CHANNEL_HUMAN_ALARM);
ipCameraHandler.motionDetected(CHANNEL_ANIMAL_ALARM);
break;
case "6":
ipCameraHandler.motionDetected(CHANNEL_CAR_ALARM);
ipCameraHandler.motionDetected(CHANNEL_ANIMAL_ALARM);
break;
case "7":
ipCameraHandler.motionDetected(CHANNEL_HUMAN_ALARM);
ipCameraHandler.motionDetected(CHANNEL_CAR_ALARM);
ipCameraHandler.motionDetected(CHANNEL_ANIMAL_ALARM);
break;
default:
if (objectCode.startsWith("/instar?")) {
return;// has no object due to older Instar camera model
}
ipCameraHandler.logger.debug("Unknown object detection code:{}", objectCode);
}
}
@ -238,14 +371,14 @@ public class InstarHandler extends ChannelDuplexHandler {
// If a camera does not need to poll a request as often as snapshots, it can be
// added here. Binding steps through the list.
public ArrayList<String> getLowPriorityRequests() {
ArrayList<String> lowPriorityRequests = new ArrayList<String>(2);
lowPriorityRequests.add("/cgi-bin/hi3510/param.cgi?cmd=getaudioalarmattr");
ArrayList<String> lowPriorityRequests = new ArrayList<String>(7);
lowPriorityRequests.add("/param.cgi?cmd=getaudioalarmattr");
lowPriorityRequests.add("/cgi-bin/hi3510/param.cgi?cmd=getmdattr");
lowPriorityRequests.add("/param.cgi?cmd=getalarmattr");
lowPriorityRequests.add("/param.cgi?cmd=getinfrared");
lowPriorityRequests.add("/param.cgi?cmd=getoverlayattr&-region=1");
lowPriorityRequests.add("/param.cgi?cmd=getpirattr");
lowPriorityRequests.add("/param.cgi?cmd=getioattr"); // ext alarm input on/off
// lowPriorityRequests.add("/param.cgi?cmd=getserverinfo");
return lowPriorityRequests;
}
}

View File

@ -170,6 +170,7 @@ public class IpCameraHandler extends BaseThingHandler {
private String basicAuth = "";
public boolean useBasicAuth = false;
public boolean useDigestAuth = false;
public boolean newInstarApi = false;
public String snapshotUri = "";
public String mjpegUri = "";
private byte[] currentSnapshot = new byte[] { (byte) 0x00 };
@ -1642,7 +1643,8 @@ public class IpCameraHandler extends BaseThingHandler {
if (mjpegUri.isEmpty()) {
mjpegUri = "/mjpegstream.cgi?-chn=12";
}
// Newer Instar cameras use this to setup the Alarm Server
// Newer Instar cameras use this to setup the Alarm Server, plus it is used to work out which API is
// implemented based on the response to these two requests.
sendHttpGET(
"/param.cgi?cmd=setasaction&-server=1&enable=1&-interval=1&cmd=setasattr&-as_index=1&-as_server="
+ hostIp + "&-as_port=" + SERVLET_PORT + "&-as_path=/ipcamera/"

View File

@ -409,7 +409,7 @@ public class OnvifConnection {
request.headers().add("Content-Type",
"application/soap+xml; charset=utf-8; action=\"" + actionString + "/" + requestType + "\"");
request.headers().add("Charset", "utf-8");
request.headers().set("Host", extractIPportFromUrl(xAddr));
request.headers().set("Host", ipAddress + ":" + onvifPort);
request.headers().set("Connection", HttpHeaderValues.CLOSE);
request.headers().set("Accept-Encoding", "gzip, deflate");
String fullXml = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\"" + extraEnvelope + ">"
@ -578,8 +578,11 @@ public class OnvifConnection {
onvifPort = Integer.parseInt(url.substring(beginIndex + 1, endIndex));
} else {// 192.168.1.1
ipAddress = url;
deviceXAddr = "http://" + ipAddress + "/onvif/device_service";
logger.debug("No Onvif Port found when parsing:{}", url);
return;
}
deviceXAddr = "http://" + ipAddress + ":" + onvifPort + "/onvif/device_service";
}
public void gotoPreset(int index) {