Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

node-red-contrib-hikvision-ultimate

Package Overview
Dependencies
Maintainers
1
Versions
119
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-red-contrib-hikvision-ultimate - npm Package Compare versions

Comparing version 0.0.12 to 0.0.13

4

CHANGELOG.md

@@ -5,2 +5,6 @@ # node-red-contrib-hikvision-ultimate

<p>
<b>Version 0.0.13 BETA</b> December 2020<br/>
- Moved ANPR code into async functions, do help very slow PC's to correctly handle the data.<br/>
</p>
<p>
<b>Version 0.0.12 BETA</b> November 2020<br/>

@@ -7,0 +11,0 @@ - Added support for devices sending XML as well as for devices sending JSON.<br/>

303

nodes/ANPR-config.js

@@ -26,8 +26,7 @@

// At start, reads the last recognized plate and starts listening from the time last plate was recognized.
// This avoid output all the previoulsy plate list, stored by the camera.
node.initPlateReader = () => {
// Function to get the plate list from the camera
async function getPlates(_lastPicName) {
if (_lastPicName == undefined || _lastPicName == null || _lastPicName == "") return null;
node.setAllClientsStatus({ fill: "grey", shape: "ring", text: "Connecting..." });
var client = new DigestFetch(node.credentials.user, node.credentials.password); // Instantiate the fetch client.
const client = new DigestFetch(node.credentials.user, node.credentials.password); // Instantiate the fetch client.
controller = new AbortController(); // For aborting the stream request

@@ -38,3 +37,3 @@ var options = {

headers: { 'content-type': 'application/xml' }, // request headers. format is the identical to that accepted by the Headers constructor (see below)
body: "<AfterTime><picTime>202001010101010000</picTime></AfterTime>", // request body. can be null, a string, a Buffer, a Blob, or a Node.js Readable stream
body: "<AfterTime><picTime>" + _lastPicName + "</picTime></AfterTime>", // request body. can be null, a string, a Buffer, a Blob, or a Node.js Readable stream
redirect: 'follow', // set to `manual` to extract redirect headers, `error` to reject redirect

@@ -46,109 +45,111 @@ signal: controller.signal, // pass an instance of AbortSignal to optionally abort requests

timeout: 5000, // req/res timeout in ms, it resets on redirect. 0 to disable (OS limit applies). Signal is recommended instead.
compress: true, // support gzip/deflate content encoding. false to disable
compress: false, // support gzip/deflate content encoding. false to disable
size: 0, // maximum response body size in bytes. 0 to disable
agent: null // http(s).Agent instance or function that returns an instance (see below)
}
client.fetch("http://" + node.host + "/ISAPI/Traffic/channels/1/vehicleDetect/plates", options)
.then(response => {
//RED.log.error(response.status + " " + response.statusText);
if (response.statusText === "Unauthorized") {
node.setAllClientsStatus({ fill: "red", shape: "ring", text: response.statusText });
};
try {
const response = await client.fetch("http://" + node.host + "/ISAPI/Traffic/channels/1/vehicleDetect/plates", options);
if (response.status >= 200 && response.status <= 300) {
node.setAllClientsStatus({ fill: "green", shape: "ring", text: "Connected." });
} else {
node.setAllClientsStatus({ fill: "red", shape: "ring", text: response.statusText });
// console.log("BANANA Error response " + response.statusText);
throw ("Error response: " + response.statusText);
}
//#region "BODY"
const body = await response.text();
var sRet = "";
sRet = body.toString();
//// console.log("BANANA " + sRet);
var oPlates = null;
try {
var i = sRet.indexOf("<"); // Get only the XML, starting with "<"
if (i > -1) {
sRet = sRet.substring(i);
// By xml2js
xml2js(sRet, function (err, result) {
oPlates = result;
});
} else {
i = sRet.indexOf("{") // It's a Json
if (i > -1) {
sRet = sRet.substring(i);
oPlates = JSON.parse(result);
} else {
// Invalid body
RED.log.info("ANPR-config: DecodingBody: Invalid Json " + sRet);
// console.log("BANANA ANPR-config: DecodingBody: Invalid Json " + sRet);
throw ("Error Invalid Json: " + sRet);
}
}
if (response.statusText === "Ok") {
node.setAllClientsStatus({ fill: "green", shape: "ring", text: "Connected." });
// console.log("BANANA GIASONE " + JSON.stringify(oPlates));
// Working the plates. Must be sure, that no error occurs, before acknolwedging the plate last picName
if (oPlates.Plates !== null) {
node.setAllClientsStatus({ fill: "green", shape: "ring", text: "Waiting for vehicle..." });
if (!node.isConnected) {
node.nodeClients.forEach(oClient => {
oClient.sendPayload({ topic: oClient.topic || "", payload: null, connected: true });
})
}
node.isConnected = true;
return oPlates;
} else {
// Error in parsing XML
throw ("Error: oPlates.Plates is null");
}
return response.body;
}).then(body => {
body.on('readable', () => {
let chunk;
var sRet = "";
node.lastPicName = "";
while (null !== (chunk = body.read())) {
sRet = chunk.toString();
}
//console.log ("BANANA " + sRet)
var oPlates = null;
try {
var i = sRet.indexOf("<"); // Get only the XML, starting with "<"
if (i > -1) {
sRet = sRet.substring(i);
// By xml2js
xml2js(sRet, function (err, result) {
oPlates = result;
});
} else {
i = sRet.indexOf("{") // It's a Json
if (i > -1) {
sRet = sRet.substring(i);
oPlates = JSON.parse(result);
} else {
// Invalid body
RED.log.info("ANPR-config: DecodingBody: Invalid Json " + sRet);
node.lastPicName = ""; // This raises an error, below.
oPlates = null; // Set null
}
}
} catch (error) {
RED.log.error("ANPR-config: ERRORE CATCHATO initPlateReader:" + error);
node.lastPicName = ""; // This raises an error, below.
}
} catch (error) {
RED.log.error("ANPR-config: ERRORE CATCHATO initPlateReader:" + error);
// console.log("BANANA ANPR-config: ERRORE CATCHATO initPlateReader: " + error);
throw ("Error initPlateReader: " + error);
}
//#endregion
} catch (err) {
// Main Error
// console.log("BANANA MAIN ERROR: " + err);
// Abort request
try {
if (controller !== null) controller.abort();
} catch (error) { }
node.setAllClientsStatus({ fill: "grey", shape: "ring", text: "Server unreachable: " + err + " Retry..." });
if (node.isConnected) {
node.nodeClients.forEach(oClient => {
oClient.sendPayload({ topic: oClient.topic || "", payload: null, connected: false });
})
}
node.isConnected = false;
return null;
};
// Working the plates. Must be sure, that no error occurs, before acknolwedging the plate last picName
};
// At start, reads the last recognized plate and starts listening from the time last plate was recognized.
// This avoid output all the previoulsy plate list, stored by the camera.
node.initPlateReader = () => {
// console.log("BANANA INITPLATEREADER");
node.setAllClientsStatus({ fill: "grey", shape: "ring", text: "Getting prev list to be ignored..." });
(async () => {
var oPlates = await getPlates("202001010101010000");
if (oPlates === null) {
setTimeout(node.initPlateReader, 10000); // Restart initPlateReader
} else {
// console.log("BANANA STRIGONE " + JSON.stringify(oPlates))
if (oPlates.Plates.hasOwnProperty("Plate") && oPlates.Plates.Plate.length > 0) {
try {
if (oPlates !== null) {
if (oPlates.Plates !== null) {
if (oPlates.Plates.hasOwnProperty("Plate") && oPlates.Plates.Plate.length > 0) {
node.lastPicName = oPlates.Plates.Plate[oPlates.Plates.Plate.length - 1].picName;
//node.lastPicName = "202001010101010000"; // BANANA SIMULAZIONE CON LETTURA DI TUTTE LE TARGHE
node.setAllClientsStatus({ fill: "grey", shape: "ring", text: "Found " + oPlates.Plates.Plate.length + " ignored plates. Last was " + node.lastPicName });
} else {
// No previously plates found, set a default datetime
node.setAllClientsStatus({ fill: "grey", shape: "ring", text: "No previously plates found." });
node.lastPicName = "202001010101010000";
}
}
}
node.lastPicName = oPlates.Plates.Plate[oPlates.Plates.Plate.length - 1].picName;
node.setAllClientsStatus({ fill: "grey", shape: "ring", text: "Found " + oPlates.Plates.Plate.length + " ignored plates. Last was " + node.lastPicName });
} catch (error) {
node.setAllClientsStatus({ fill: "red", shape: "ring", text: "Ahi lasso Error: " + error });
node.lastPicName = ""; // This raises an error, below.
// console.log("BANANA Error oPlates.Plates.Plate[oPlates.Plates.Plate.length - 1]: " + error);
setTimeout(node.initPlateReader, 10000); // Restart initPlateReader
return;
}
if (node.lastPicName === "") {
// Some errors occurred
// Abort request
try {
if (controller !== null) controller.abort();
} catch (error) { }
node.setAllClientsStatus({ fill: "red", shape: "ring", text: "Error occurred in init plates list." });
node.isConnected = false;
setTimeout(node.initPlateReader, 5000); // Reconnect
} else {
node.setAllClientsStatus({ fill: "green", shape: "ring", text: "Waiting for vehicle..." });
if (!node.isConnected) {
node.nodeClients.forEach(oClient => {
oClient.sendPayload({ topic: oClient.topic || "", payload: null, connected: true });
})
}
node.isConnected = true;
setTimeout(node.queryForPlates, 2000); // Start main polling thread
}
});
})
.catch(err => {
// Abort request
try {
if (controller !== null) controller.abort();
} catch (error) { }
node.setAllClientsStatus({ fill: "grey", shape: "ring", text: "Server unreachable: " + err + " Retry..." });
if (node.isConnected) {
node.nodeClients.forEach(oClient => {
oClient.sendPayload({ topic: oClient.topic || "", payload: null, connected: false });
})
} else {
// No previously plates found, set a default datetime
node.setAllClientsStatus({ fill: "grey", shape: "ring", text: "No previously plates found." });
node.lastPicName = "202001010101010000";
}
node.isConnected = false;
setTimeout(node.initPlateReader, 5000); // Reconnect
return;
});
setTimeout(node.queryForPlates, 2000); // Start main polling thread
}
})();
};

@@ -159,2 +160,3 @@

node.queryForPlates = () => {
// console.log("BANANA queryForPlates");
if (node.lastPicName === "") {

@@ -170,65 +172,12 @@ // Should not be here!

setTimeout(node.initPlateReader, 10000); // Restart whole process.
return;
}
controller = new AbortController(); // For aborting the stream request
var client = new DigestFetch(node.credentials.user, node.credentials.password); // Instantiate the fetch client.
var options = {
// These properties are part of the Fetch Standard
method: 'POST',
headers: { 'content-type': 'application/xml' }, // request headers. format is the identical to that accepted by the Headers constructor (see below)
body: "<AfterTime><picTime>" + node.lastPicName + "</picTime></AfterTime>", // request body. can be null, a string, a Buffer, a Blob, or a Node.js Readable stream
redirect: 'follow', // set to `manual` to extract redirect headers, `error` to reject redirect
signal: controller.signal, // pass an instance of AbortSignal to optionally abort requests
// The following properties are node-fetch extensions
follow: 20, // maximum redirect count. 0 to not follow redirect
timeout: 5000, // req/res timeout in ms, it resets on redirect. 0 to disable (OS limit applies). Signal is recommended instead.
compress: true, // support gzip/deflate content encoding. false to disable
size: 0, // maximum response body size in bytes. 0 to disable
agent: null // http(s).Agent instance or function that returns an instance (see below)
}
client.fetch("http://" + node.host + "/ISAPI/Traffic/channels/1/vehicleDetect/plates", options)
.then(response => {
//RED.log.error(response.status + " " + response.statusText);
if (response.statusText === "Unauthorized") {
node.setAllClientsStatus({ fill: "red", shape: "ring", text: response.statusText });
}
if (response.statusText === "Ok") {
node.setAllClientsStatus({ fill: "green", shape: "ring", text: "Connected." });
}
return response.body;
}).then(body => {
let chunk;
var oRet = "";
while (null !== (chunk = body.read())) {
sRet = chunk.toString();
}
node.isConnected = true;
try {
var i = sRet.indexOf("<"); // Get only the XML, starting with "<"
if (i > -1) {
sRet = sRet.substring(i);
// By xml2js
xml2js(sRet, function (err, result) {
oRet = result;
});
} else {
i = sRet.indexOf("{") // It's a Json
if (i > -1) {
sRet = sRet.substring(i);
oRet = JSON.parse(sRet);
}else {
// Invalid body
RED.log.info("ANPR-config: DecodingBodyPlateReader: Invalid Json " + sRet);
oRet = null;
}
}
} catch (error) { RED.log.error("ANPR-config: ERRORE CATCHATO vehicleDetect/plates:" + error); }
// Send the message to the child nodes
if (oRet !== null && oRet.Plates !== null && oRet.Plates.hasOwnProperty("Plate")) {
if (oRet.Plates.Plate.length > 0) {
oRet.Plates.Plate.forEach(oPlate => {
} else {
(async () => {
var oPlates = await getPlates(node.lastPicName);
if (oPlates === null) {
// An error was occurred.
setTimeout(node.initPlateReader, 10000); // Restart initPlateReader from scratch
} else {
if (oPlates.Plates.hasOwnProperty("Plate") && oPlates.Plates.Plate.length > 0) {
// Send the message to the child nodes
oPlates.Plates.Plate.forEach(oPlate => {
node.nodeClients.forEach(oClient => {

@@ -238,22 +187,13 @@ oClient.sendPayload({ topic: oClient.topic || "", plate: oPlate, payload: oPlate.plateNumber, connected: true });

})
} else {
// No new plates found
}
setTimeout(node.queryForPlates, 1000); // Call the cunction again.
}
setTimeout(node.queryForPlates, 1000); // Call the cunction again.
})
.catch(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.initPlateReader, 10000); // Restart whole process.
return;
});
})();
}
};
// Start!
setTimeout(node.initPlateReader, 5000); // First connection.
setTimeout(node.initPlateReader, 10000); // First connection.

@@ -266,3 +206,2 @@

} catch (error) { }
if (node.initPlateReader !== null) clearTimeout(node.initPlateReader);
done();

@@ -269,0 +208,0 @@ });

{
"name": "node-red-contrib-hikvision-ultimate",
"version": "0.0.12",
"version": "0.0.13",
"description": "A native set of node for Hikvision Cameras, Alarms, Radars etc.",

@@ -5,0 +5,0 @@ "author": "Supergiovane (https://github.com/Supergiovane)",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc