node-red-contrib-hikvision-ultimate
Advanced tools
Comparing version 0.0.3 to 0.0.4
@@ -5,3 +5,7 @@ # node-red-contrib-hikvision-ultimate | ||
<p> | ||
<b>Version 0.0.2 BETA</b> November 2020<br/> | ||
<b>Version 0.0.4 BETA</b> November 2020<br/> | ||
- Added ANPR License Plate Node. | ||
</p> | ||
<p> | ||
<b>Version 0.0.3 BETA</b> November 2020<br/> | ||
- Added connection checks and reconnection. | ||
@@ -8,0 +12,0 @@ </p> |
@@ -5,120 +5,90 @@ | ||
var urllib = require('urllib'); | ||
var urllibCheckConnection = require('urllib'); | ||
var xml2js = require('xml2js').parseString; | ||
const urllib = require('urllib'); | ||
var Agent = require('agentkeepalive'); | ||
const xml2js = require('xml2js').parseString; | ||
function Hikvisionconfig(config) { | ||
RED.nodes.createNode(this, config) | ||
var node = this | ||
node.host = config.host | ||
node.port = config.port | ||
node.nodeClients = [] // Stores the registered clients | ||
node.timertimerConnectionCheck = setTimeout(function () { node.CheckConnection(); }, 2000); | ||
node.alarmStreamConnected = false; | ||
node.host = config.host; | ||
node.port = config.port; | ||
node.nodeClients = []; // Stores the registered clients | ||
node.isConnected = false; | ||
// 25/11/2020 | ||
//#region "Check Connection" | ||
node.CheckConnection = () => { | ||
// Try to find out, if the server responds. | ||
var optionsCheck = { | ||
"digestAuth": node.credentials.user + ":" + node.credentials.password, | ||
"timeout": 8000 | ||
}; | ||
urllibCheckConnection.request("http://" + node.host + "/ISAPI/Event/notification/alertStream", optionsCheck, function (err, data, res) { | ||
if (err) { | ||
// console.log("ERROR: " + err); | ||
// // Error connecting to the server | ||
// node.nodeClients.forEach(oClient => { | ||
// try { | ||
// oClient.setNodeStatus({ fill: "red", shape: "shape", text: "Disconnected: " + errr }); | ||
// } catch (error) { } | ||
// }) | ||
// node.alarmStreamConnected = false; | ||
} | ||
try { | ||
//console.log("CHECK STATUS: " + res.statusCode); | ||
if (res.statusCode !== 200) { | ||
node.nodeClients.forEach(oClient => { | ||
try { | ||
oClient.setNodeStatus({ fill: "red", shape: "shape", text: "Disconnected. Status " + res.statusCode }); | ||
// Inform clients about disconnections. | ||
if (node.alarmStreamConnected === true) { | ||
oClient.send({ topic: oClient.topic || "", payload: "Disconnected" }); | ||
} | ||
} catch (error) { } | ||
}) | ||
node.alarmStreamConnected = false; | ||
} else { | ||
if (node.alarmStreamConnected === false) { | ||
node.alarmStreamConnected = true; | ||
node.startAlarmStream(); | ||
node.nodeClients.forEach(oClient => { | ||
try { | ||
oClient.setNodeStatus({ fill: "green", shape: "ring", text: "Connected" }); | ||
} catch (error) { } | ||
}) | ||
} | ||
} | ||
} catch (error) { | ||
} | ||
node.timerConnectionCheck = setTimeout(function () { node.CheckConnection(); }, 5000); | ||
node.startAlarmStream = () => { | ||
var keepaliveAgent = new Agent({ | ||
keepAlive: true | ||
}); | ||
}; | ||
//#endregion | ||
// Starts alarm stream | ||
node.startAlarmStream = () => { | ||
//console.log("START MAIN STREAM"); | ||
var options = { | ||
"digestAuth": node.credentials.user + ":" + node.credentials.password, | ||
"streaming": true, | ||
"timeout": 5000 | ||
"agent": keepaliveAgent | ||
}; | ||
urllib.request("http://" + node.host + "/ISAPI/Event/notification/alertStream", options, function (err, data, res) { | ||
node.urllibRequest = urllib.request("http://" + node.host + "/ISAPI/Event/notification/alertStream", options, function (err, data, res) { | ||
if (err) { | ||
console.log("MAIN ERROR: " + err); | ||
node.setAllClientsStatus({ fill: "grey", shape: "ring", text: "Server unreachable. Retry..." }); | ||
if (node.isConnected) { | ||
node.nodeClients.forEach(oClient => { | ||
oClient.sendPayload({ topic: oClient.topic || "", payload: null, connected: false }); | ||
}) | ||
} | ||
node.isConnected = false; | ||
setTimeout(node.startAlarmStream, 10000); // Reconnect | ||
return; | ||
} | ||
try { | ||
//console.log("MAIN STATUS: " + res.statusCode); | ||
} catch (error) { | ||
} | ||
try { | ||
//console.log("HEADERS: " + res.headers); | ||
} catch (error) { | ||
} | ||
try { | ||
//console.log("DATA: " + data.toString()); | ||
} catch (error) { | ||
} | ||
res.on('data', function (chunk) { | ||
//console.log("chunk: " + chunk.toString()); | ||
var sRet = chunk.toString(); | ||
sRet = sRet.substring(sRet.indexOf("<?xml")); // Remove all before <?xml | ||
// By xml2js | ||
xml2js(sRet, function (err, result) { | ||
node.nodeClients.forEach(oClient => { | ||
oClient.send({ topic: oClient.topic || "", payload: result }); | ||
}) | ||
}); | ||
node.isConnected = true; | ||
try { | ||
var sRet = chunk.toString(); | ||
sRet = sRet.substring(sRet.indexOf("<")); // Get only the XML, starting with "<" | ||
// By xml2js | ||
xml2js(sRet, function (err, result) { | ||
node.nodeClients.forEach(oClient => { | ||
if (result !== undefined) oClient.sendPayload({ topic: oClient.topic || "", payload: result, connected: true }); | ||
}) | ||
}); | ||
} catch (error) { console.log("ERRORE CATCHATO " + error); } | ||
}); | ||
res.on('end', function () { | ||
//console.log("END"); | ||
console.log("END"); | ||
}); | ||
res.on('close', function () { | ||
console.log("CLOSE"); | ||
node.setAllClientsStatus({ fill: "grey", shape: "ring", text: "Disconnected. Retry..." }); | ||
if (node.isConnected) { | ||
node.nodeClients.forEach(oClient => { | ||
oClient.sendPayload({ topic: oClient.topic || "", payload: null, connected: false }); | ||
}); | ||
} | ||
node.isConnected = false; | ||
setTimeout(node.startAlarmStream, 10000); // Reconnect | ||
}); | ||
res.on('error', function (err) { | ||
console.log("ERROR: " + err); | ||
}); | ||
}); | ||
}; | ||
setTimeout(node.startAlarmStream, 5000); // First connection. | ||
//#region "FUNCTIONS" | ||
node.on('close', function (removed, done) { | ||
clearTimeout(node.timerConnectionCheck); | ||
done(); | ||
}); | ||
node.setAllClientsStatus = ({ fill, shape, text }) => { | ||
function nextStatus(oClient) { | ||
oClient.setNodeStatus({ fill: fill, shape: shape, text: text }) | ||
} | ||
node.nodeClients.map(nextStatus); | ||
} | ||
node.addClient = (_Node) => { | ||
@@ -131,8 +101,6 @@ // Check if node already exists | ||
try { | ||
_Node.setNodeStatus({ fill: "gray", shape: "shape", text: "Waiting for connection" }); | ||
} catch (error) { | ||
} | ||
_Node.setNodeStatus({ fill: "grey", shape: "ring", text: "Waiting for connection" }); | ||
} catch (error) { } | ||
}; | ||
} | ||
node.removeClient = (_Node) => { | ||
@@ -150,10 +118,7 @@ // Remove the client node from the clients array | ||
} | ||
} | ||
}; | ||
//#endregion | ||
} | ||
RED.nodes.registerType("Hikvision-config", Hikvisionconfig, { | ||
@@ -160,0 +125,0 @@ credentials: { |
@@ -8,3 +8,3 @@ | ||
node.server = RED.nodes.getNode(config.server) | ||
node.setNodeStatus = ({ fill, shape, text }) => { | ||
@@ -15,2 +15,9 @@ var dDate = new Date(); | ||
// Called from config node, to send output to the flow | ||
node.sendPayload = (_msg) => { | ||
if (_msg.payload === null) { node.send(_msg); return; }; // If null, then it's disconnected. Avoid processing the event | ||
node.setNodeStatus({ fill: "green", shape: "dot", text: "Alert received" }); | ||
node.send(_msg); | ||
} | ||
// On each deploy, unsubscribe+resubscribe | ||
@@ -23,3 +30,3 @@ if (node.server) { | ||
this.on('input', function (msg) { | ||
node.setNodeStatus({ fill: "green", shape: "ring", text: "banana" }); | ||
}); | ||
@@ -26,0 +33,0 @@ |
{ | ||
"name": "node-red-contrib-hikvision-ultimate", | ||
"version": "0.0.3", | ||
"version": "0.0.4", | ||
"description": "A native set of node for Hikvision Cameras, Alarms, Radars etc.", | ||
@@ -8,3 +8,4 @@ "author": "Supergiovane (https://github.com/Supergiovane)", | ||
"urllib": "2.36.1", | ||
"xml2js": "0.4.23" | ||
"xml2js": "0.4.23", | ||
"child_process": "1.0.2" | ||
}, | ||
@@ -25,5 +26,6 @@ "keywords": [ | ||
"Hikvision-config": "nodes/Hikvision-config.js", | ||
"hikvisionUltimateAlarmRaw": "nodes/hikvisionUltimateAlarmRaw.js" | ||
"hikvisionUltimateAlarmRaw": "nodes/hikvisionUltimateAlarmRaw.js", | ||
"hikvisionUltimateANPR": "nodes/hikvisionUltimateANPR.js" | ||
} | ||
} | ||
} |
# node-red-contrib-hikvision-ultimate | ||
A native set of node for Hikvision Cameras, Alarms, Radars, NVR etc. | ||
@@ -11,7 +12,4 @@ [![NPM version][npm-version-image]][npm-url] | ||
## A native set of node for Hikvision Cameras, Alarms, Radars, NVR etc. | ||
<img src='https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/master/img/RawAlarm.png' width="80%"> | ||
### THIS NODESET IS IN BETA. E' ancora brutto, ma funziona. | ||
@@ -21,3 +19,4 @@ ## DESCRIPTION | ||
Works with cameras, NVR and also with specialized devices, like Radar (for example DS-PR1-60 and 120).<br/> | ||
There is currently **only one node**, that traps the alarms, in RAW mode, and outputs a JSON.<br/> | ||
There are currently **only two node**, one that traps the alarms, in RAW mode, and outputs a JSON and the other that outputs the ANPR License Plate numbers.<br/> | ||
***THIS NODESET IS IN BETA. E' ancora brutto, ma funziona.*** | ||
@@ -33,4 +32,2 @@ ## RAW Alarm Node | ||
[![Donate via PayPal](https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square)](https://www.paypal.me/techtoday). | ||
## CHANGELOG | ||
@@ -37,0 +34,0 @@ * See <a href="https://github.com/Supergiovane/node-red-contrib-hikvision-ultimate/blob/master/CHANGELOG.md">here the changelog</a> |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
419364
16
173
3
39
+ Addedchild_process@1.0.2
+ Addedchild_process@1.0.2(transitive)