diff --git a/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/HikvisionHandler.java b/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/HikvisionHandler.java index d99920f865c..a2e86da0677 100644 --- a/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/HikvisionHandler.java +++ b/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/HikvisionHandler.java @@ -60,6 +60,56 @@ public class HikvisionHandler extends ChannelDuplexHandler { this.nvrChannel = nvrChannel; } + private void processEvent(String content) { + // some cameras use or and NVRs use channel 0 to say all channels + if (content.contains("hannelID>" + nvrChannel) || content.contains("0")) { + final int debounce = 3; + String eventType = Helper.fetchXML(content, "", ""); + switch (eventType) { + case "videoloss": + if (content.contains("inactive")) { + if (vmdCount > 1) { + vmdCount = 1; + } + countDown(); + countDown(); + } + break; + case "PIR": + ipCameraHandler.motionDetected(CHANNEL_PIR_ALARM); + pirCount = debounce; + break; + case "attendedBaggage": + ipCameraHandler.setChannelState(CHANNEL_ITEM_TAKEN, OnOffType.ON); + takenCount = debounce; + break; + case "unattendedBaggage": + ipCameraHandler.setChannelState(CHANNEL_ITEM_LEFT, OnOffType.ON); + leftCount = debounce; + break; + case "facedetection": + ipCameraHandler.setChannelState(CHANNEL_FACE_DETECTED, OnOffType.ON); + faceCount = debounce; + break; + case "VMD": + ipCameraHandler.motionDetected(CHANNEL_MOTION_ALARM); + vmdCount = debounce; + break; + case "fielddetection": + ipCameraHandler.motionDetected(CHANNEL_FIELD_DETECTION_ALARM); + fieldCount = debounce; + break; + case "linedetection": + ipCameraHandler.motionDetected(CHANNEL_LINE_CROSSING_ALARM); + lineCount = debounce; + break; + default: + logger.debug("Unrecognised Hikvision eventType={}", eventType); + } + } + countDown(); + } + // This handles the incoming http replies back from the camera. @Override public void channelRead(@Nullable ChannelHandlerContext ctx, @Nullable Object msg) throws Exception { @@ -67,59 +117,10 @@ public class HikvisionHandler extends ChannelDuplexHandler { return; } try { - int debounce = 3; String content = msg.toString(); logger.trace("HTTP Result back from camera is \t:{}:", content); - if (content.contains("--boundary")) {// Alarm checking goes in here// - if (content.contains("" + nvrChannel + " - if (content.contains("linedetection")) { - ipCameraHandler.motionDetected(CHANNEL_LINE_CROSSING_ALARM); - lineCount = debounce; - } - if (content.contains("fielddetection")) { - ipCameraHandler.motionDetected(CHANNEL_FIELD_DETECTION_ALARM); - fieldCount = debounce; - } - if (content.contains("VMD")) { - ipCameraHandler.motionDetected(CHANNEL_MOTION_ALARM); - vmdCount = debounce; - } - if (content.contains("facedetection")) { - ipCameraHandler.setChannelState(CHANNEL_FACE_DETECTED, OnOffType.ON); - faceCount = debounce; - } - if (content.contains("unattendedBaggage")) { - ipCameraHandler.setChannelState(CHANNEL_ITEM_LEFT, OnOffType.ON); - leftCount = debounce; - } - if (content.contains("attendedBaggage")) { - ipCameraHandler.setChannelState(CHANNEL_ITEM_TAKEN, OnOffType.ON); - takenCount = debounce; - } - if (content.contains("PIR")) { - ipCameraHandler.motionDetected(CHANNEL_PIR_ALARM); - pirCount = debounce; - } - if (content.contains("videoloss\r\ninactive")) { - if (vmdCount > 1) { - vmdCount = 1; - } - countDown(); - countDown(); - } - } else if (content.contains("0")) {// NVR uses channel 0 to say all - // channels - if (content.contains("videoloss\r\ninactive")) { - if (vmdCount > 1) { - vmdCount = 1; - } - countDown(); - countDown(); - } - } - countDown(); - } + if (content.startsWith("--boundary")) {// Alarm checking goes in here// + processEvent(content); } else { String replyElement = Helper.fetchXML(content, "", "<"); switch (replyElement) { @@ -196,23 +197,7 @@ public class HikvisionHandler extends ChannelDuplexHandler { } break; default: - if (content.contains("" + nvrChannel + "0")) {// some camera use c or - // - if (content.contains( - "videoloss\r\ninactive")) { - if (vmdCount > 1) { - vmdCount = 1; - } - countDown(); - countDown(); - } - countDown(); - } - } else { - logger.debug("Unhandled reply-{}.", content); - } + logger.debug("Unhandled reply-{}.", content); break; } } diff --git a/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/handler/IpCameraHandler.java b/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/handler/IpCameraHandler.java index 09a59477f3d..9e0c93215cc 100644 --- a/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/handler/IpCameraHandler.java +++ b/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/handler/IpCameraHandler.java @@ -206,6 +206,7 @@ public class IpCameraHandler extends BaseThingHandler { private byte[] incomingJpeg = new byte[0]; private String incomingMessage = ""; private String contentType = "empty"; + private String boundary = ""; private Object reply = new Object(); private String requestUrl = ""; private boolean closeConnection = true; @@ -255,6 +256,8 @@ public class IpCameraHandler extends BaseThingHandler { firstStreamedMsg = msg; streamToGroup(firstStreamedMsg, mjpegChannelGroup, true); } + } else { + boundary = Helper.searchString(contentType, "boundary="); } } else if (contentType.contains("image/jp")) { if (bytesToRecieve == 0) { @@ -305,11 +308,32 @@ public class IpCameraHandler extends BaseThingHandler { } // Alarm Streams never have a LastHttpContent as they always stay open// else if (contentType.contains("multipart")) { - if (bytesAlreadyRecieved != 0) { - reply = incomingMessage; - incomingMessage = ""; - bytesToRecieve = 0; - bytesAlreadyRecieved = 0; + int beginIndex, endIndex; + if (bytesToRecieve == 0) { + beginIndex = incomingMessage.indexOf("Content-Length:"); + if (beginIndex != -1) { + endIndex = incomingMessage.indexOf("\r\n", beginIndex); + if (endIndex != -1) { + bytesToRecieve = Integer.parseInt( + incomingMessage.substring(beginIndex + 15, endIndex).strip()); + } + } + } + // --boundary and headers are not included in the Content-Length value + if (bytesAlreadyRecieved > bytesToRecieve) { + // Check if message has a second --boundary + endIndex = incomingMessage.indexOf("--" + boundary, bytesToRecieve); + if (endIndex == -1) { + reply = incomingMessage; + incomingMessage = ""; + bytesToRecieve = 0; + bytesAlreadyRecieved = 0; + } else { + reply = incomingMessage.substring(0, endIndex); + incomingMessage = incomingMessage.substring(endIndex, incomingMessage.length()); + bytesToRecieve = 0;// Triggers search next time for Content-Length: + bytesAlreadyRecieved = incomingMessage.length() - endIndex; + } super.channelRead(ctx, reply); } } @@ -1411,7 +1435,7 @@ public class IpCameraHandler extends BaseThingHandler { updateState(channelToUpdate, valueOf); } - void bringCameraOnline() { + private void bringCameraOnline() { isOnline = true; updateStatus(ThingStatus.ONLINE); groupTracker.listOfOnlineCameraHandlers.add(this); @@ -1421,19 +1445,6 @@ public class IpCameraHandler extends BaseThingHandler { localFuture.cancel(false); } - switch (thing.getThingTypeUID().getId()) { - case HIKVISION_THING: - sendHttpGET("/ISAPI/Smart/AudioDetection/channels/" + cameraConfig.getNvrChannel() + "01"); - sendHttpGET("/ISAPI/Smart/LineDetection/" + cameraConfig.getNvrChannel() + "01"); - sendHttpGET("/ISAPI/Smart/FieldDetection/" + cameraConfig.getNvrChannel() + "01"); - sendHttpGET( - "/ISAPI/System/Video/inputs/channels/" + cameraConfig.getNvrChannel() + "01/motionDetection"); - sendHttpGET("/ISAPI/System/Video/inputs/channels/" + cameraConfig.getNvrChannel() + "/overlays/text/1"); - sendHttpGET("/ISAPI/System/IO/inputs/" + cameraConfig.getNvrChannel()); - sendHttpGET("/ISAPI/System/IO/inputs/" + cameraConfig.getNvrChannel()); - break; - } - if (cameraConfig.getGifPreroll() > 0 || cameraConfig.getUpdateImageWhen().contains("1")) { snapshotPolling = true; snapshotJob = threadPool.scheduleWithFixedDelay(this::snapshotRunnable, 1000, cameraConfig.getPollTime(),