node-red-contrib-hikvision-ultimate
Advanced tools
Comparing version 1.0.7 to 1.0.8
@@ -5,2 +5,7 @@ # node-red-contrib-hikvision-ultimate | ||
<p> | ||
<b>Version 1.0.8</b> December 2020<br/> | ||
- NEW: Picture node, you can now CROP the image, to obtain a zoomed portion, for example, of a door or things like this.<br/> | ||
- NEW: Picture node, the config window shows the actual picture you see, including all image manipulation you've done through settings.<br/> | ||
</p> | ||
<p> | ||
<b>Version 1.0.7</b> December 2020<br/> | ||
@@ -7,0 +12,0 @@ - NEW: Picture node, you can now set the output quality, from 10 to 100.<br/> |
@@ -218,3 +218,3 @@ | ||
follow: 20, // maximum redirect count. 0 to not follow redirect | ||
timeout: 15000, // req/res timeout in ms, it resets on redirect. 0 to disable (OS limit applies). Signal is recommended instead. | ||
timeout: 8000, // req/res timeout in ms, it resets on redirect. 0 to disable (OS limit applies). Signal is recommended instead. | ||
compress: false, // support gzip/deflate content encoding. false to disable | ||
@@ -221,0 +221,0 @@ size: 0, // maximum response body size in bytes. 0 to disable |
@@ -6,2 +6,3 @@ | ||
function hikvisionUltimatePicture(config) { | ||
@@ -11,8 +12,5 @@ RED.nodes.createNode(this, config); | ||
node.server = RED.nodes.getNode(config.server) | ||
node.PTZPreset = (config.PTZPreset === null || config.PTZPreset === undefined) ? "1" : config.PTZPreset; | ||
node.channelID = (config.channelID === null || config.channelID === undefined) ? "1" : config.channelID; | ||
node.rotateimage = (config.rotateimage === null || config.rotateimage === undefined) ? "0" : config.rotateimage; | ||
node.heightimage = (config.heightimage === null || config.heightimage === undefined || config.heightimage.trim() === "") ? "0" : config.heightimage; | ||
node.widthimage = (config.widthimage === null || config.widthimage === undefined || config.rotateimage.trim() === "") ? "0" : config.widthimage; | ||
node.qualityimage = (config.qualityimage === null || config.qualityimage === undefined || config.qualityimage.trim() === "") ? "80" : config.qualityimage; | ||
node.picture; // Stores the cam image | ||
node.pictureLarghezza = 0; | ||
node.pictureAltezza = 0; | ||
@@ -24,2 +22,101 @@ node.setNodeStatus = ({ fill, shape, text }) => { | ||
// 15/12/2020 apply the manipulation to the node's variable | ||
node.variabilizeManipulation = (_config) => { | ||
node.channelID = (_config.channelID === null || _config.channelID === undefined) ? "1" : _config.channelID; | ||
node.qualityimage = (_config.qualityimage === null || _config.qualityimage === undefined || _config.qualityimage.trim() === "") ? "80" : _config.qualityimage; | ||
node.rotateimage = (_config.rotateimage === null || _config.rotateimage === undefined) ? "0" : _config.rotateimage; | ||
node.widthimage = (_config.widthimage === null || _config.widthimage === undefined || _config.widthimage.trim() === "") ? "0" : _config.widthimage; | ||
node.heightimage = (_config.heightimage === null || _config.heightimage === undefined || _config.heightimage.trim() === "") ? "0" : _config.heightimage; | ||
node.cropimage = (_config.cropimage === null || _config.cropimage === undefined || _config.cropimage.trim() === "") ? "" : _config.cropimage; | ||
if (node.cropimage !== "" && node.cropimage.split(",").length === 4) { | ||
node.cropimage = { | ||
x: Number(node.cropimage.split(",")[0].trim()), | ||
y: Number(node.cropimage.split(",")[1].trim()), | ||
w: Number(node.cropimage.split(",")[2].trim()), | ||
h: Number(node.cropimage.split(",")[3].trim()) | ||
} | ||
} else { | ||
node.cropimage = ""; | ||
} | ||
} | ||
node.variabilizeManipulation(config); | ||
// 14/12/2020 Get the picture image from camera | ||
RED.httpAdmin.get("/hikvisionUltimateGetPicture", RED.auth.needsPermission('hikvisionUltimatePicture.read'), function (req, res) { | ||
if (typeof req.query.serverID !== "undefined" && req.query.serverID !== null && req.query.serverID !== "") { | ||
var _nodeServer = RED.nodes.getNode(req.query.serverID);// Retrieve node.id of the config node. | ||
// Create the config object | ||
//#region CREATING CONFIG | ||
// var sManipulate = $("#node-input-channelID").val(); | ||
// sManipulate += "SEP" + $("#node-input-qualityimage").val(); | ||
// sManipulate += "SEP" + $("#node-input-rotateimage").val(); | ||
// sManipulate += "SEP" + $("#node-input-widthimage").val(); | ||
// sManipulate += "SEP" + $("#node-input-heightimage").val(); | ||
// sManipulate += "SEP" + $("#node-input-cropimage").val().toString().trim().replace(/\s/g, '').replace(/,/g,"-"); | ||
var sManipulate = req.query.manipulate; | ||
var oConfig = { channelID: sManipulate.split("SEP")[0].toString().trim() }; | ||
oConfig.qualityimage = sManipulate.split("SEP")[1].toString().trim(); | ||
oConfig.rotateimage = sManipulate.split("SEP")[2].toString().trim(); | ||
oConfig.widthimage = sManipulate.split("SEP")[3].toString().trim(); | ||
oConfig.heightimage = sManipulate.split("SEP")[4].toString().trim(); | ||
oConfig.cropimage = sManipulate.split("SEP")[5].toString().trim().replace(/-/g, ","); | ||
node.variabilizeManipulation(oConfig); | ||
//#endregion | ||
//console.log("MAN " + JSON.stringify(oConfig)) | ||
if (_nodeServer === null) { | ||
res.json({ picture: "", width: 0, height: 0 }); | ||
} else { | ||
node.picture = null; | ||
node.server = _nodeServer; | ||
// Call the request, that then sends the result via node.sendPayload function | ||
node.server.request(node, "GET", "/ISAPI/Streaming/channels/" + node.channelID + "01/picture", null).then(success => { | ||
// Wait until the server has called node.sendPayload and node.sendPayload has populated the node.picture variable | ||
var iTimeout = 0; | ||
var CB = () => { | ||
iTimeout += 1; | ||
if (iTimeout >= 10) { | ||
res.json({ picture: "", width: 0, height: 0 }); | ||
return; | ||
} else { | ||
if (node.picture !== null) { | ||
res.json({ picture: node.picture, width: node.pictureLarghezza, height: node.pictureAltezza }); | ||
return; | ||
} | ||
setTimeout(CB, 500); | ||
} | ||
} | ||
setTimeout(CB, 500); | ||
}).catch(error => { | ||
res.json({ picture: "", width: 0, height: 0 }); | ||
}); | ||
} | ||
} else { res.json({ picture: "", width: 0, height: 0 }); } | ||
}); | ||
// Get picture | ||
node.getPicture = (_picBase64) => new Promise(function (resolve, reject) { | ||
try { | ||
jimp.read(_picBase64) | ||
.then(image => { | ||
if (node.rotateimage !== 0) image = image.rotate(Number(node.rotateimage)); | ||
if (node.cropimage !== "") image = image.crop(node.cropimage.x, node.cropimage.y, node.cropimage.w, node.cropimage.h); | ||
if (node.heightimage !== "0" && node.widthimage !== "0") image = image.resize(Number(node.widthimage), Number(node.heightimage)); | ||
//image = image.crop(x, y, w, h); | ||
image = image.quality(Number(node.qualityimage)); | ||
node.pictureLarghezza = image.bitmap.width; | ||
node.pictureAltezza = image.bitmap.height; | ||
image.getBufferAsync(jimp.MIME_JPEG).then(picture => { | ||
node.picture = "data:image/jpg;base64," + picture.toString("base64"); | ||
resolve(node.picture); | ||
}).catch(error => { | ||
reject(error); | ||
}); | ||
}); | ||
} catch (error) { | ||
reject(error); | ||
} | ||
}); | ||
// Called from config node, to send output to the flow | ||
@@ -42,22 +139,11 @@ node.sendPayload = (_msg) => { | ||
node.getPicture(_msg.payload).then(data => { | ||
_msg.payload = data; | ||
node.send(_msg, null); | ||
node.setNodeStatus({ fill: "green", shape: "dot", text: "Picture received" }); | ||
}).catch(error => { | ||
node.setNodeStatus({ fill: "red", shape: "dot", text: "GetBuffer error: " + error.message }); | ||
}) | ||
try { | ||
jimp.read(_msg.payload) | ||
.then(image => { | ||
if (node.rotateimage !== 0) image = image.rotate(Number(node.rotateimage)); | ||
if (node.heightimage !== "0" && node.widthimage !== "0") image = image.resize(Number(node.widthimage), Number(node.heightimage)); | ||
image = image.quality(Number(node.qualityimage)); | ||
image.getBufferAsync(jimp.MIME_JPEG).then(picture => { | ||
_msg.payload = "data:image/jpg;base64," + picture.toString("base64"); | ||
node.send(_msg, null); | ||
node.setNodeStatus({ fill: "green", shape: "dot", text: "Picture received" }); | ||
}).catch(error => { | ||
node.setNodeStatus({ fill: "red", shape: "dot", text: "GetBuffer error: " + error.message }); | ||
}); | ||
}); | ||
} catch (error) { | ||
node.setNodeStatus({ fill: "red", shape: "dot", text: "Image error: " + error.message }); | ||
} | ||
} | ||
@@ -78,3 +164,3 @@ | ||
try { | ||
// http://192.168.1.13/ISAPI/Streaming/Channels/101/picture | ||
// Call the request, that then sends the result via node.sendPayload function | ||
node.server.request(node, "GET", "/ISAPI/Streaming/channels/" + node.channelID + "01/picture", null); | ||
@@ -81,0 +167,0 @@ } catch (error) { |
{ | ||
"name": "node-red-contrib-hikvision-ultimate", | ||
"version": "1.0.7", | ||
"version": "1.0.8", | ||
"description": "A native set of node for Hikvision Cameras, Alarms, Radars etc.", | ||
@@ -5,0 +5,0 @@ "author": "Supergiovane (https://github.com/Supergiovane)", |
@@ -171,2 +171,4 @@ # node-red-contrib-hikvision-ultimate | ||
<img src='https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/master/img/pictureproperties.png' width="40%"> | ||
**Flow Messages** | ||
@@ -173,0 +175,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
883607
38
1014
338