├── .gitattributes
├── .github
└── ISSUE_TEMPLATE
│ └── bug_report.md
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── img
├── ANPR.png
├── CIDEvents
│ ├── 1.png
│ ├── 2.png
│ ├── 3.png
│ ├── 4.png
│ └── 5.png
├── Doorbell.png
├── GenericAlarm.png
├── NotifyCenter.png
├── PTZ.png
├── Radar.png
├── RawAlarm.png
├── Text.png
├── XML.png
├── accesscontrol.png
├── accesscontrolterminal.jpg
├── axpro.png
├── axproPicture.jpg
├── hikanprcamera.jpg
├── hikcamera.jpg
├── hikcamerasettings.png
├── hikptzcamera.png
├── info.png
├── loading.gif
├── logo.png
├── madeinitaly.png
├── picture.png
├── pictureproperties.png
└── speaker.jpg
├── nodes
├── ANPR-config.html
├── ANPR-config.js
├── AXPro-config.html
├── AXPro-config.js
├── AccessControl-config.html
├── AccessControl-config.js
├── Doorbell-config.html
├── Doorbell-config.js
├── Hikvision-config copy.js
├── Hikvision-config.html
├── Hikvision-config.js
├── Speaker-config.html
├── Speaker-config.js
├── hikvisionUltimateANPR.html
├── hikvisionUltimateANPR.js
├── hikvisionUltimateAccessControlTerminal.html
├── hikvisionUltimateAccessControlTerminal.js
├── hikvisionUltimateAlarm.html
├── hikvisionUltimateAlarm.js
├── hikvisionUltimateAlarmRaw.html
├── hikvisionUltimateAlarmRaw.js
├── hikvisionUltimateAxPro.html
├── hikvisionUltimateAxPro.js
├── hikvisionUltimateDoorbell.html
├── hikvisionUltimateDoorbell.js
├── hikvisionUltimatePTZ.html
├── hikvisionUltimatePTZ.js
├── hikvisionUltimatePicture.html
├── hikvisionUltimatePicture.js
├── hikvisionUltimateSpeaker.html
├── hikvisionUltimateSpeaker.js
├── hikvisionUltimateText.html
├── hikvisionUltimateText.js
├── hikvisionUltimateXML.html
├── hikvisionUltimateXML.js
├── icons
│ ├── camera-icon.png
│ ├── camera-icon.svg
│ ├── node-alarm.png
│ ├── node-alarm.svg
│ ├── node-anpr-icon.png
│ ├── node-anpr-icon.svg
│ ├── node-radar-icon.png
│ ├── node-radar-icon.svg
│ ├── node-raw-icon.png
│ ├── node-raw-icon.svg
│ ├── ptz-icon.png
│ └── ptz-icon.svg
└── utils
│ ├── AccessControlEvents
│ ├── MAJOR_ALARM-0x1.json
│ ├── MAJOR_EVENT-0x5.json
│ ├── MAJOR_EXCEPTION-0x2.json
│ └── MAJOR_OPERATION-0x3.json
│ ├── Sha256.js
│ ├── classDoorbellCapabilities.js
│ ├── dateManagement.js
│ ├── escape-json.js
│ ├── hikDiscovery.js
│ └── ipAddressHelper.js
├── package-lock.json
└── package.json
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: Supergiovane
7 |
8 | ---
9 |
10 | **Salutation (i'll not respond to users that doesn’t wrote at least "Hello")**
11 |
12 | **Describe the bug**
13 | A clear and concise description of what the bug is.
14 |
15 | **To Reproduce**
16 | Steps to reproduce the behavior:
17 | 1. Go to '...'
18 | 2. Click on '....'
19 | 3. Scroll down to '....'
20 | 4. See error
21 |
22 | **Expected behavior**
23 | A clear and concise description of what you expected to happen.
24 |
25 | **Screenshots**
26 | If applicable, add screenshots to help explain your problem.
27 |
28 | **Hikvision-Ultimate Version**
29 | - Eg. 1.1.95
30 |
31 | **Are you running node-red behind homematic, docker or anything similar?**
32 | - Eg. Node-Red running alone in RaspberryPi
33 |
34 | **Additional context**
35 | Add any other context about the problem here.
36 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Massimo
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/img/ANPR.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/ANPR.png
--------------------------------------------------------------------------------
/img/CIDEvents/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/CIDEvents/1.png
--------------------------------------------------------------------------------
/img/CIDEvents/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/CIDEvents/2.png
--------------------------------------------------------------------------------
/img/CIDEvents/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/CIDEvents/3.png
--------------------------------------------------------------------------------
/img/CIDEvents/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/CIDEvents/4.png
--------------------------------------------------------------------------------
/img/CIDEvents/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/CIDEvents/5.png
--------------------------------------------------------------------------------
/img/Doorbell.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/Doorbell.png
--------------------------------------------------------------------------------
/img/GenericAlarm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/GenericAlarm.png
--------------------------------------------------------------------------------
/img/NotifyCenter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/NotifyCenter.png
--------------------------------------------------------------------------------
/img/PTZ.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/PTZ.png
--------------------------------------------------------------------------------
/img/Radar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/Radar.png
--------------------------------------------------------------------------------
/img/RawAlarm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/RawAlarm.png
--------------------------------------------------------------------------------
/img/Text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/Text.png
--------------------------------------------------------------------------------
/img/XML.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/XML.png
--------------------------------------------------------------------------------
/img/accesscontrol.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/accesscontrol.png
--------------------------------------------------------------------------------
/img/accesscontrolterminal.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/accesscontrolterminal.jpg
--------------------------------------------------------------------------------
/img/axpro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/axpro.png
--------------------------------------------------------------------------------
/img/axproPicture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/axproPicture.jpg
--------------------------------------------------------------------------------
/img/hikanprcamera.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/hikanprcamera.jpg
--------------------------------------------------------------------------------
/img/hikcamera.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/hikcamera.jpg
--------------------------------------------------------------------------------
/img/hikcamerasettings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/hikcamerasettings.png
--------------------------------------------------------------------------------
/img/hikptzcamera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/hikptzcamera.png
--------------------------------------------------------------------------------
/img/info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/info.png
--------------------------------------------------------------------------------
/img/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/loading.gif
--------------------------------------------------------------------------------
/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/logo.png
--------------------------------------------------------------------------------
/img/madeinitaly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/madeinitaly.png
--------------------------------------------------------------------------------
/img/picture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/picture.png
--------------------------------------------------------------------------------
/img/pictureproperties.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/pictureproperties.png
--------------------------------------------------------------------------------
/img/speaker.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/img/speaker.jpg
--------------------------------------------------------------------------------
/nodes/ANPR-config.html:
--------------------------------------------------------------------------------
1 |
97 |
98 |
--------------------------------------------------------------------------------
/nodes/AXPro-config.html:
--------------------------------------------------------------------------------
1 |
31 |
32 |
--------------------------------------------------------------------------------
/nodes/AccessControl-config.html:
--------------------------------------------------------------------------------
1 |
97 |
98 |
--------------------------------------------------------------------------------
/nodes/Doorbell-config.html:
--------------------------------------------------------------------------------
1 |
102 |
103 |
--------------------------------------------------------------------------------
/nodes/Hikvision-config.html:
--------------------------------------------------------------------------------
1 |
103 |
104 |
185 |
186 |
--------------------------------------------------------------------------------
/nodes/Speaker-config.html:
--------------------------------------------------------------------------------
1 |
102 |
103 |
159 |
160 |
--------------------------------------------------------------------------------
/nodes/hikvisionUltimateANPR.html:
--------------------------------------------------------------------------------
1 |
53 |
54 |
82 |
83 |
--------------------------------------------------------------------------------
/nodes/hikvisionUltimateANPR.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | module.exports = function (RED) {
4 | function hikvisionUltimateANPR(config) {
5 | RED.nodes.createNode(this, config);
6 | var node = this;
7 | node.topic = config.topic || config.name;
8 | node.server = RED.nodes.getNode(config.server)
9 | node.avoidsameplatetime = config.avoidsameplatetime || 20; // Doesn't send the same plate in this timeframe, in seconds.
10 | node.currentPlate = ""; // Stores the current plate (for the avoidsameplatetime function)
11 | node.timerAvoidSamePlate = null; // Timer for avoiding repeating plate
12 | node.bAvoidSamePlate = false;
13 |
14 | node.setNodeStatus = ({ fill, shape, text }) => {
15 | var dDate = new Date();
16 | node.status({ fill: fill, shape: shape, text: text + " (" + dDate.getDate() + ", " + dDate.toLocaleTimeString() + ")" })
17 | }
18 |
19 | // Called from config node, to send output to the flow
20 | node.sendPayload = (_msg) => {
21 | if (_msg === null || _msg === undefined) return;
22 | _msg.topic = node.topic;
23 | if (_msg.hasOwnProperty("errorDescription")) { node.send([null, _msg]); return; }; // It's a connection error/restore comunication.
24 | if (!_msg.hasOwnProperty("payload") || (_msg.hasOwnProperty("payload") && (_msg.payload === undefined || _msg.payload === null))) return;
25 |
26 | if (node.currentPlate === _msg.payload) {
27 | if (node.bAvoidSamePlate) {
28 | try { node.setNodeStatus({ fill: "grey", shape: "ring", text: "Temporary block same plate " + _msg.payload }); } catch (error) { };
29 | return;
30 | }
31 | }
32 |
33 | // Timer for avoiding same plate
34 | // ##########################
35 | if (node.timerAvoidSamePlate !== null) clearTimeout(node.timerAvoidSamePlate);
36 | node.bAvoidSamePlate = true;
37 | node.timerAvoidSamePlate = setTimeout(() => {
38 | node.bAvoidSamePlate = false;
39 | }, node.avoidsameplatetime * 1000);
40 | // ##########################
41 |
42 | node.currentPlate = _msg.payload;
43 | node.send([_msg, null]);
44 | try {
45 | node.setNodeStatus({ fill: "green", shape: "dot", text: "Plate " + _msg.payload });
46 | } catch (error) { }
47 | }
48 |
49 | // On each deploy, unsubscribe+resubscribe
50 | if (node.server) {
51 | node.server.removeClient(node);
52 | node.server.addClient(node);
53 | }
54 |
55 | this.on('input', function (msg) {
56 |
57 | });
58 |
59 | node.on("close", function (done) {
60 | if (node.server) {
61 | node.server.removeClient(node);
62 | }
63 | done();
64 | });
65 |
66 | }
67 |
68 | RED.nodes.registerType("hikvisionUltimateANPR", hikvisionUltimateANPR);
69 | }
--------------------------------------------------------------------------------
/nodes/hikvisionUltimateAccessControlTerminal.html:
--------------------------------------------------------------------------------
1 |
104 |
105 |
142 |
143 |
--------------------------------------------------------------------------------
/nodes/hikvisionUltimateAccessControlTerminal.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | module.exports = function (RED) {
4 | function hikvisionUltimateAccessControlTerminal(config) {
5 | RED.nodes.createNode(this, config);
6 | var node = this;
7 | node.topic = config.topic || config.name;
8 | node.server = RED.nodes.getNode(config.server)
9 | node.filtermajorevent = Number(config.filtermajorevent) || 0;
10 | node.filterminorevent = parseInt(config.filterminorevent || 0, 16); // Hex to decimal
11 |
12 |
13 | node.setNodeStatus = ({ fill, shape, text }) => {
14 | var dDate = new Date();
15 | node.status({ fill: fill, shape: shape, text: text + " (" + dDate.getDate() + ", " + dDate.toLocaleTimeString() + ")" })
16 | }
17 |
18 | // Called from config node, to send output to the flow
19 | node.sendPayload = (_msg) => {
20 | if (_msg === null || _msg === undefined) return;
21 | _msg.topic = node.topic;
22 | if (_msg.hasOwnProperty("errorDescription")) { node.send([null, _msg]); return; }; // It's a connection error/restore comunication.
23 | if (!_msg.hasOwnProperty("payload") || (_msg.hasOwnProperty("payload") && (_msg.payload === undefined || _msg.payload === null))) return;
24 |
25 | // Apply filter
26 | if (node.filtermajorevent > 0) {
27 | if (Number(_msg.payload.major) === node.filtermajorevent) {
28 | if (node.filterminorevent > 0) {
29 | if (Number(_msg.payload.minor) === node.filterminorevent) {
30 | node.send([_msg, null]);
31 | setTimeout(() => {
32 | node.setNodeStatus({ fill: "green", shape: "dot", text: "Event " + _msg.payload.eventDescription });
33 | }, 1000);
34 | } else {
35 | try {
36 | setTimeout(() => {
37 | node.setNodeStatus({ fill: "grey", shape: "dot", text: "Filtered " + _msg.payload.eventDescription });
38 | }, 500);
39 | } catch (error) { }
40 | return;
41 | }
42 | } else {
43 | node.send([_msg, null]);
44 | setTimeout(() => {
45 | node.setNodeStatus({ fill: "green", shape: "dot", text: "Event " + _msg.payload.eventDescription });
46 | }, 1000);
47 | }
48 | }
49 | } else {
50 | node.send([_msg, null]);
51 | try {
52 | setTimeout(() => {
53 | node.setNodeStatus({ fill: "green", shape: "dot", text: "Event " + _msg.payload.eventDescription });
54 | }, 1000);
55 | } catch (error) { }
56 | }
57 |
58 |
59 | }
60 |
61 | // On each deploy, unsubscribe+resubscribe
62 | if (node.server) {
63 | node.server.removeClient(node);
64 | node.server.addClient(node);
65 | }
66 |
67 | this.on('input', function (msg) {
68 |
69 | });
70 |
71 | node.on("close", function (done) {
72 | if (node.server) {
73 | node.server.removeClient(node);
74 | }
75 | done();
76 | });
77 |
78 | }
79 |
80 | RED.nodes.registerType("hikvisionUltimateAccessControlTerminal", hikvisionUltimateAccessControlTerminal);
81 | }
--------------------------------------------------------------------------------
/nodes/hikvisionUltimateAlarmRaw.html:
--------------------------------------------------------------------------------
1 |
51 |
52 |
74 |
75 |
--------------------------------------------------------------------------------
/nodes/hikvisionUltimateAlarmRaw.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | module.exports = function (RED) {
4 | function hikvisionUltimateAlarmRaw(config) {
5 | RED.nodes.createNode(this, config);
6 | var node = this;
7 | node.topic = config.topic || config.name;
8 | node.server = RED.nodes.getNode(config.server)
9 |
10 | node.setNodeStatus = ({ fill, shape, text }) => {
11 | var dDate = new Date();
12 | node.status({ fill: fill, shape: shape, text: text + " (" + dDate.getDate() + ", " + dDate.toLocaleTimeString() + ")" })
13 | }
14 |
15 | // Called from config node, to send output to the flow
16 | node.sendPayload = (_msg, extension = '') => {
17 | if (_msg === null || _msg === undefined) return;
18 | _msg.topic = node.topic;
19 | if (_msg.hasOwnProperty("errorDescription")) { node.send([null, _msg, null]); return; }; // It's a connection error/restore comunication.
20 | if (!_msg.hasOwnProperty("payload") || (_msg.hasOwnProperty("payload") && _msg.payload === undefined)) return;
21 |
22 | if (_msg.type !== undefined && _msg.type === 'img') {
23 | _msg.extension = extension;
24 | node.send([null, null, _msg]);
25 | return;
26 | }
27 |
28 |
29 | // Heartbeat discard
30 | // 0
31 | // videoloss
32 | // inactive
33 | if (_msg.hasOwnProperty("payload")
34 | && _msg.payload.hasOwnProperty("eventType")
35 | && _msg.payload.eventType.toString().toLowerCase() === "videoloss"
36 | && _msg.payload.eventState.toString().toLowerCase() === "inactive"
37 | && _msg.payload.hasOwnProperty("activePostCount") && (Number(_msg.payload.activePostCount) === 0 || Number(_msg.payload.activePostCount) === 1)) {
38 | // It's a HertBeat, exit.
39 | node.setNodeStatus({ fill: "green", shape: "ring", text: "Waiting for alert..." });
40 | return;
41 | };
42 |
43 | node.setNodeStatus({ fill: "green", shape: "dot", text: "Alert received" });
44 | node.send([_msg, null, null]);
45 | }
46 |
47 | // On each deploy, unsubscribe+resubscribe
48 | if (node.server) {
49 | node.server.removeClient(node);
50 | node.server.addClient(node);
51 | }
52 |
53 | this.on('input', function (msg) {
54 |
55 | });
56 |
57 | node.on("close", function (done) {
58 | if (node.server) {
59 | node.server.removeClient(node);
60 | }
61 | done();
62 | });
63 |
64 | }
65 |
66 | RED.nodes.registerType("hikvisionUltimateAlarmRaw", hikvisionUltimateAlarmRaw);
67 | }
--------------------------------------------------------------------------------
/nodes/hikvisionUltimateAxPro.html:
--------------------------------------------------------------------------------
1 |
53 |
54 |
77 |
78 |
--------------------------------------------------------------------------------
/nodes/hikvisionUltimateAxPro.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash')
2 |
3 | module.exports = function (RED) {
4 | function hikvisionUltimateAxPro(config) {
5 | RED.nodes.createNode(this, config);
6 | var node = this;
7 | node.topic = config.topic || config.name;
8 | node.server = RED.nodes.getNode(config.server)
9 | node.zonesStatus = [] // Contains the status of all zones
10 | node.outputtype = Number(config.outputtype || 0)
11 |
12 | node.setNodeStatus = ({ fill, shape, text }) => {
13 | var dDate = new Date();
14 | node.status({ fill: fill, shape: shape, text: text + " (" + dDate.getDate() + ", " + dDate.toLocaleTimeString() + ")" })
15 | }
16 |
17 | // Called from config node, to send output to the flow
18 | node.sendPayload = (_msg) => {
19 | if (_msg === null || _msg === undefined) return;
20 | _msg.topic = node.topic;
21 | if (_msg.hasOwnProperty("errorDescription")) { node.send([null, _msg]); return; }; // It's a connection error/restore comunication.
22 | // If heartbeat, return
23 | if (_msg.payload.hasOwnProperty("eventType") && _msg.payload.hasOwnProperty("eventState") && _msg.payload.eventType === "cidEvent" && _msg.payload.eventState === "inactive") return
24 | if ((node.outputtype === 0 || node.outputtype === 1) && _msg.payload.hasOwnProperty('CIDEvent')) {
25 | // ALARM EVENT
26 | node.send([{ payload: { CIDEvent: RED.util.cloneMessage(_msg.payload.CIDEvent) } }, null]); // Clone message to avoid adding _msgid
27 | }
28 | if ((node.outputtype === 0 || node.outputtype === 2) && _msg.payload.hasOwnProperty('ZoneList')) {
29 | // CHECK ONLY THE CHANGED ZONE STATUS
30 | for (let index = 0; index < _msg.payload.ZoneList.length; index++) {
31 | try {
32 | const receivedZone = _msg.payload.ZoneList[index].Zone;
33 | let foundInZoneStatus = node.zonesStatus.find((element) => element.id === receivedZone.id)
34 | if (!_.isEqual(foundInZoneStatus, receivedZone)) {
35 | if (foundInZoneStatus === undefined) {
36 | node.zonesStatus.push(receivedZone) // Add updated
37 | } else {
38 | node.zonesStatus[node.zonesStatus.findIndex((element) => element.id === receivedZone.id)] = receivedZone
39 | //node.zonesStatus.splice(foundInZoneStatus)
40 | //node.zonesStatus.push(receivedZone) // Add updated
41 | }
42 | node.setNodeStatus({ fill: "green", shape: "dot", text: "Zone changed " + receivedZone.name });
43 | node.send([{ payload: { zoneUpdate: RED.util.cloneMessage(receivedZone) } }, null]); // Clone message to avoid adding _msgid
44 | }
45 | } catch (error) { }
46 | }
47 | } else {
48 | //node.send([_msg, null])
49 | node.setNodeStatus({ fill: "green", shape: "ring", text: "Waiting for zone change" });
50 | }
51 |
52 | }
53 |
54 | // On each deploy, unsubscribe+resubscribe
55 | if (node.server) {
56 | node.server.removeClient(node);
57 | node.server.addClient(node);
58 | }
59 |
60 | this.on('input', function (msg) {
61 | try {
62 | // Disarm Area
63 | if (msg.hasOwnProperty("disarmArea")) {
64 | node.server.disarmArea(msg.disarmArea)
65 | }
66 | // Arm Away Area
67 | if (msg.hasOwnProperty("armAwayArea")) {
68 | node.server.armAwayArea(msg.armAwayArea)
69 | }
70 | // Arm Stay Area
71 | if (msg.hasOwnProperty("armStayArea")) {
72 | node.server.armStayArea(msg.armStayArea)
73 | }
74 | // Clear Alarm Area
75 | if (msg.hasOwnProperty("clearAlarmArea")) {
76 | node.server.clearAlarmArea(msg.clearAlarmArea)
77 | }
78 |
79 | // Disarm All Area in a batch
80 | if (msg.hasOwnProperty("disarmAllAreas")) {
81 | node.server.disarmAllAreas()
82 | }
83 | // Clear All Alarm Areas
84 | if (msg.hasOwnProperty("clearAllAlarmAreas")) {
85 | node.server.clearAllAlarmAreas()
86 | }
87 |
88 | } catch (error) { }
89 |
90 |
91 | });
92 |
93 | node.on("close", function (done) {
94 | if (node.server) {
95 | node.server.removeClient(node);
96 | }
97 | done();
98 | });
99 |
100 | }
101 |
102 | RED.nodes.registerType("hikvisionUltimateAxPro", hikvisionUltimateAxPro);
103 | }
--------------------------------------------------------------------------------
/nodes/hikvisionUltimateDoorbell.html:
--------------------------------------------------------------------------------
1 |
55 |
56 |
151 |
152 |
--------------------------------------------------------------------------------
/nodes/hikvisionUltimateDoorbell.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | module.exports = function (RED) {
4 | function hikvisionUltimateDoorbell(config) {
5 | RED.nodes.createNode(this, config);
6 | var node = this;
7 | node.topic = config.topic || config.name;
8 | node.server = RED.nodes.getNode(config.server)
9 | node.ringStatus = (config.ringStatus === null || config.ringStatus === undefined) ? "all" : config.ringStatus.toLowerCase();
10 | node.floorNo = (config.floorNo === null || config.floorNo === undefined) ? "all" : config.floorNo;
11 | node.unitNo = (config.unitNo === null || config.unitNo === undefined) ? "all" : config.unitNo;
12 | node.zoneNo = (config.zoneNo === null || config.zoneNo === undefined) ? "all" : config.zoneNo;
13 | node.buildingNo = (config.buildingNo === null || config.buildingNo === undefined) ? "all" : config.buildingNo;
14 | node.currentEmittedMSG = {}; // To keep the current status and avoid emitting msg if already emitted.
15 |
16 | node.setNodeStatus = ({ fill, shape, text }) => {
17 | var dDate = new Date();
18 | node.status({ fill: fill, shape: shape, text: text + " (" + dDate.getDate() + ", " + dDate.toLocaleTimeString() + ")" })
19 | }
20 |
21 |
22 | // Called from config node, to send output to the flow
23 | // Expected return JSON from ISAPI/VideoIntercom/callerInfo
24 | // {
25 | // "CallerInfo": {
26 | // "buildingNo": 1,
27 | // "floorNo": 1,
28 | // "zoneNo": 1,
29 | // "unitNo": 1,
30 | // "devNo": 88,
31 | // "devType": 1,
32 | // "lockNum": 1,
33 | // "status": "idle" ("idle,ring,onCall")
34 | // }
35 | // }
36 | // "devType":{ 1-door station, 2-master station,
37 | // 3-indoor station, 4-outer door station, 5-villa door station, 6-doorphone,
38 | // 7-Infosight Client Software, 8-iVMS-4200 Client Software, 9-APP,
39 | // 10-doorbell, 11-VOIP Client Software, 12-network camera, 13-access control device*/
40 | node.sendPayload = (_msg) => {
41 | if (_msg === null || _msg === undefined) return;
42 |
43 | if (_msg.type !== undefined && _msg.type === 'img') {
44 | _msg.extension = extension;
45 | node.send([null, null, _msg]);
46 | return;
47 | }
48 |
49 |
50 | _msg.topic = node.topic;
51 | _msg.payload = true;
52 | if (_msg.hasOwnProperty("errorDescription")) { node.send([null, _msg]); return; }; // It's a connection error/restore comunication.
53 | //node.send([_msg, null]);
54 | if (_msg.hasOwnProperty("CallerInfo") && _msg.CallerInfo.hasOwnProperty("status")) {
55 |
56 | if (
57 | ((node.ringStatus === "all" || node.ringStatus === _msg.CallerInfo.status.toString()))
58 | && (node.floorNo === "all" || node.floorNo === _msg.CallerInfo.floorNo.toString())
59 | && (node.unitNo === "all" || node.unitNo === _msg.CallerInfo.unitNo.toString())
60 | && (node.zoneNo === "all" || node.zoneNo === _msg.CallerInfo.zoneNo.toString())
61 | && (node.buildingNo === "all" || node.buildingNo === _msg.CallerInfo.buildingNo.toString())
62 | ) {
63 | delete _msg._msgid; // To allow objects compare
64 | delete node.currentEmittedMSG._msgid; // To allow objects compare
65 |
66 | if (RED.util.compareObjects(node.currentEmittedMSG, _msg)) return; // Omit sending the same notification more than once
67 | node.currentEmittedMSG = _msg;
68 | // Oputputs only msg that are no "idle"
69 | if (_msg.CallerInfo.status.toString() !== "idle") node.send([_msg, null]);
70 | }
71 |
72 | }
73 | }
74 |
75 | // On each deploy, unsubscribe+resubscribe
76 | if (node.server) {
77 | node.server.removeClient(node);
78 | node.server.addClient(node);
79 | }
80 |
81 |
82 | this.on('input', function (msg) {
83 | // node.request = async function (_callerNode, _method, _URL, _body) {
84 |
85 | if (msg.hasOwnProperty("openDoor")) {
86 | // Open the door latch
87 | let iDoor = msg.openDoor || 1;
88 | //
89 | //
90 | //
91 | //
92 | //
93 | //
94 | //
95 | //
96 | //
97 | //
98 | //
99 | let sBody = `
100 | `+ iDoor + `
101 | unlock
102 | HikvisionUltimate
103 |
104 | `;
105 |
106 | // Try with API 2.0
107 | node.server.request(node, "PUT", "/ISAPI/VideoIntercom/remoteOpenDoor", sBody).then(success => {
108 | node.setNodeStatus({ fill: "green", shape: "ring", text: "Door unlocked" });
109 | msg.payload = true;
110 | node.send([msg, null]);
111 | }).catch(error => {
112 | // Try with API 1.0
113 | node.server.request(node, "PUT", "/ISAPI/AccessControl/RemoteControl/door/" + iDoor, "open").then(success => {
114 | node.setNodeStatus({ fill: "green", shape: "ring", text: "Door unlocked" });
115 | msg.payload = true;
116 | node.send([msg, null]);
117 | }).catch(error => {
118 | node.setNodeStatus({ fill: "red", shape: "ring", text: "Error unlocking door " + error.message });
119 | msg.payload = false;
120 | node.send([msg, null]);
121 | });
122 |
123 | });
124 |
125 | }
126 |
127 | if (msg.hasOwnProperty("hangUp")) {
128 | try {
129 | // Both calls are needed to stop current ring and call
130 |
131 | // Stop ringing. This stops the APP ringing.
132 | // Try with API 2.0, but with some firmware it doesn't work
133 | node.server.request(node, "DELETE", "/ISAPI/VideoIntercom/ring", "").then(success => {
134 | node.setNodeStatus({ fill: "green", shape: "ring", text: "Stop ringing" });
135 | }).catch(error => {
136 | node.setNodeStatus({ fill: "red", shape: "ring", text: "Error stop ringing " + error.message });
137 | RED.log.error("hikvisionUltimateDoorbell: Error stopping ring " + error.message);
138 | });
139 |
140 | // Stop current call initiated by the intercom. This stops the intercom call.
141 | // Try with API 2.0
142 | setTimeout(() => {
143 | //const jHangUp = JSON.stringify(JSON.parse(`{"CallSignal": { "cmdType": "hangUp" } }`));
144 | try {
145 | const jHangUp = JSON.parse(JSON.stringify(JSON.parse(`{"CallSignal": {"cmdType": "hangUp"}}`)))
146 | node.server.request(node, "PUT", "/ISAPI/VideoIntercom/callSignal?format=json", jHangUp).then(success => {
147 | node.setNodeStatus({ fill: "green", shape: "ring", text: "Hang Up" });
148 | }).catch(error => {
149 | RED.log.error("hikvisionUltimateDoorbell: Error hangUp " + error.message);
150 | });
151 | } catch (error) {
152 | }
153 |
154 | setTimeout(() => {
155 | try {
156 | const jReject = JSON.parse(JSON.stringify(JSON.parse(`{"CallSignal": {"cmdType": "reject"}}`)))
157 | node.server.request(node, "PUT", "/ISAPI/VideoIntercom/callSignal?format=json", jReject).then(success => {
158 | node.setNodeStatus({ fill: "green", shape: "ring", text: "reject" });
159 | }).catch(error => {
160 | RED.log.error("hikvisionUltimateDoorbell: Error reject " + error.message);
161 | });
162 | } catch (error) {
163 | }
164 |
165 | }, 1000);
166 | }, 1000);
167 | } catch (error) {
168 |
169 | }
170 |
171 | }
172 |
173 |
174 |
175 | });
176 |
177 | node.on("close", function (done) {
178 | if (node.server) {
179 | node.server.removeClient(node);
180 | }
181 | if (node.server) {
182 | node.server.removeClient(node);
183 | }
184 | done();
185 | });
186 |
187 | }
188 |
189 | RED.nodes.registerType("hikvisionUltimateDoorbell", hikvisionUltimateDoorbell);
190 | }
--------------------------------------------------------------------------------
/nodes/hikvisionUltimatePTZ.html:
--------------------------------------------------------------------------------
1 |
53 |
54 |
132 |
133 |
--------------------------------------------------------------------------------
/nodes/hikvisionUltimatePTZ.js:
--------------------------------------------------------------------------------
1 | module.exports = function (RED) {
2 | function hikvisionUltimatePTZ(config) {
3 | RED.nodes.createNode(this, config);
4 | var node = this;
5 | node.topic = config.topic || node.name;
6 | node.server = RED.nodes.getNode(config.server)
7 | node.PTZPreset = (config.PTZPreset === null || config.PTZPreset === undefined) ? "1" : config.PTZPreset;
8 | node.channelID = (config.channelID === null || config.channelID === undefined) ? "1" : config.channelID;
9 |
10 | node.setNodeStatus = ({ fill, shape, text }) => {
11 | var dDate = new Date();
12 | node.status({ fill: fill, shape: shape, text: text + " (" + dDate.getDate() + ", " + dDate.toLocaleTimeString() + ")" })
13 | }
14 |
15 | // Called from config node, to send output to the flow
16 | node.sendPayload = (_msg) => {
17 | if (_msg === null || _msg === undefined) return;
18 |
19 | if (_msg.type !== undefined && _msg.type === 'img') {
20 | // The payload is an image, exit.
21 | return;
22 | }
23 |
24 | _msg.topic = node.topic;
25 | if (_msg.hasOwnProperty("errorDescription")) { node.send([null, _msg]); return; }; // It's a connection error/restore comunication.
26 | if (!_msg.hasOwnProperty("payload") || (_msg.hasOwnProperty("payload") && _msg.payload === undefined)) return;
27 |
28 | if (_msg.hasOwnProperty("payload")) {
29 | if (_msg.payload.hasOwnProperty("eventType")) {
30 | // Chech if it's only a hearbeat alarm
31 | try {
32 | var sAlarmType = _msg.payload.eventType.toString().toLowerCase();
33 | if (sAlarmType === "videoloss" && _msg.payload.hasOwnProperty("activePostCount") && _msg.payload.activePostCount == "0") {
34 | node.setNodeStatus({ fill: "green", shape: "ring", text: "Received HeartBeat (the device is online)" });
35 | return; // It's a Heartbeat
36 | }
37 | } catch (error) { }
38 | }
39 | }
40 | node.send([_msg, null]);
41 | node.setNodeStatus({ fill: "green", shape: "dot", text: "PTZ Pteset recalled." });
42 | }
43 |
44 | // On each deploy, unsubscribe+resubscribe
45 | if (node.server) {
46 | node.server.removeClient(node);
47 | node.server.addClient(node);
48 | }
49 |
50 | this.on('input', function (msg) {
51 | if (msg === null || msg === undefined) return;
52 | if (msg.hasOwnProperty("payload") && msg.hasOwnProperty("payload") !== null && msg.hasOwnProperty("payload") !== undefined) {
53 | if (typeof msg.payload === "boolean" && msg.payload === true) {
54 | recallPTZ();
55 | } else if (typeof msg.payload === "object") {
56 | // Set the preset via input msg
57 | if (msg.payload.hasOwnProperty("channelID")) node.channelID = msg.payload.channelID;
58 | if (msg.payload.hasOwnProperty("PTZPreset")) node.PTZPreset = msg.payload.PTZPreset;
59 | node.setNodeStatus({ fill: "green", shape: "dot", text: "Preset passed by msg input." });
60 | recallPTZ();
61 | }
62 | }
63 |
64 | });
65 |
66 | // Recalls the PTZ
67 | function recallPTZ() {
68 | // Recall PTZ Preset
69 | // Params: _callerNode, _method, _URL, _body
70 | try {
71 | node.server.request(node, "PUT", "/ISAPI/PTZCtrl/channels/" + node.channelID + "/presets/" + node.PTZPreset + "/goto", "");
72 | } catch (error) {
73 |
74 | }
75 | }
76 |
77 | node.on("close", function (done) {
78 | if (node.server) {
79 | node.server.removeClient(node);
80 | }
81 | done();
82 | });
83 |
84 | }
85 |
86 | RED.nodes.registerType("hikvisionUltimatePTZ", hikvisionUltimatePTZ);
87 | }
--------------------------------------------------------------------------------
/nodes/hikvisionUltimatePicture.html:
--------------------------------------------------------------------------------
1 |
174 |
175 |
322 |
323 |
--------------------------------------------------------------------------------
/nodes/hikvisionUltimatePicture.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = function (RED) {
3 |
4 | const jimp = require("jimp"); // Resize
5 |
6 |
7 | function hikvisionUltimatePicture(config) {
8 | RED.nodes.createNode(this, config);
9 | var node = this;
10 | node.topic = config.topic || config.name;
11 | node.server = RED.nodes.getNode(config.server)
12 | node.picture; // Stores the cam image
13 | node.pictureLarghezza = 0;
14 | node.pictureAltezza = 0;
15 | node.urlImageCurrentIndex = config.urlImageCurrentIndex === undefined ? 0 : config.urlImageCurrentIndex; // Stores the valid URL
16 | node.previousInputMessage = {}; // 01/09/2022 previous msg input to be passet to the output
17 |
18 | node.setNodeStatus = ({ fill, shape, text }) => {
19 | var dDate = new Date();
20 | node.status({ fill: fill, shape: shape, text: text + " (" + dDate.getDate() + ", " + dDate.toLocaleTimeString() + ")" })
21 | }
22 |
23 | // 15/12/2020 apply the manipulation to the node's variable
24 | node.variabilizeManipulation = (_config) => {
25 | node.channelID = (_config.channelID === null || _config.channelID === undefined) ? "1" : _config.channelID;
26 | node.qualityimage = (_config.qualityimage === null || _config.qualityimage === undefined || _config.qualityimage.trim() === "") ? "80" : _config.qualityimage;
27 | node.rotateimage = (_config.rotateimage === null || _config.rotateimage === undefined) ? "0" : _config.rotateimage;
28 | node.widthimage = (_config.widthimage === null || _config.widthimage === undefined || _config.widthimage.trim() === "") ? "0" : _config.widthimage;
29 | node.heightimage = (_config.heightimage === null || _config.heightimage === undefined || _config.heightimage.trim() === "") ? "0" : _config.heightimage;
30 | node.cropimage = (_config.cropimage === null || _config.cropimage === undefined || _config.cropimage.trim() === "") ? "" : _config.cropimage;
31 | // 27/01/2021 Fonts
32 | node.textoverlay = (_config.textoverlay === null || _config.textoverlay === undefined || _config.textoverlay.trim() === "") ? "" : _config.textoverlay;
33 | node.textoverlayXY = (_config.textoverlayXY === null || _config.textoverlayXY === undefined || _config.textoverlayXY.trim() === "") ? "0,0" : _config.textoverlayXY;
34 | node.textoverlayWH = (_config.textoverlayWH === null || _config.textoverlayWH === undefined || _config.textoverlayWH.trim() === "") ? "" : _config.textoverlayWH;
35 | node.textoverlayFont = (_config.textoverlayFont === null || _config.textoverlayFont === undefined || _config.textoverlayFont.trim() === "") ? "FONT_SANS_32_WHITE" : _config.textoverlayFont;
36 |
37 | node.urlImage = ["/ISAPI/Streaming/channels/" + node.channelID + "01/picture", "/ISAPI/ContentMgmt/StreamingProxy/channels/" + node.channelID + "01/picture"]; // Stores all URLS the node will try to get images from
38 | //node.urlImage = ["/ISAPI/ContentMgmt/StreamingProxy/channels/" + node.channelID + "01/picture", "/ISAPI/Streaming/channels/" + node.channelID + "01/picture"]; // Stores all URLS the node will try to get images from
39 | if (node.urlImageCurrentIndex > node.urlImage.length - 1) node.urlImageCurrentIndex = 0;
40 |
41 | if (node.cropimage !== "" && node.cropimage.split(",").length === 4) {
42 | node.cropimage = {
43 | x: Number(node.cropimage.split(",")[0].trim()),
44 | y: Number(node.cropimage.split(",")[1].trim()),
45 | w: Number(node.cropimage.split(",")[2].trim()),
46 | h: Number(node.cropimage.split(",")[3].trim())
47 | }
48 | } else {
49 | node.cropimage = "";
50 | }
51 |
52 | if (node.textoverlayXY !== "" && node.textoverlayXY.split(",").length === 2) {
53 | node.textoverlayXY = {
54 | x: Number(node.textoverlayXY.split(",")[0].trim()),
55 | y: Number(node.textoverlayXY.split(",")[1].trim())
56 | }
57 | } else {
58 | node.textoverlayXY = "";
59 | }
60 |
61 | if (node.textoverlayWH !== "" && node.textoverlayWH.split(",").length === 2) {
62 | node.textoverlayWH = {
63 | w: Number(node.textoverlayWH.split(",")[0].trim()),
64 | h: Number(node.textoverlayWH.split(",")[1].trim())
65 | }
66 | } else {
67 | node.textoverlayWH = "";
68 | }
69 | }
70 | node.variabilizeManipulation(config);
71 |
72 |
73 |
74 | // 14/12/2020 Get the picture image from camera
75 | RED.httpAdmin.get("/hikvisionUltimateGetPicture", RED.auth.needsPermission('hikvisionUltimatePicture.read'), function (req, res) {
76 | if (typeof req.query.serverID !== "undefined" && req.query.serverID !== null && req.query.serverID !== "") {
77 | var _nodeServer = RED.nodes.getNode(req.query.serverID);// Retrieve node.id of the config node.
78 | // Create the config object
79 | //#region CREATING CONFIG
80 | var sManipulate = req.query.manipulate;
81 | var oConfig = { channelID: sManipulate.split("-SEP-")[0].toString().trim() };
82 | oConfig.qualityimage = sManipulate.split("-SEP-")[1].toString().trim();
83 | oConfig.rotateimage = sManipulate.split("-SEP-")[2].toString().trim();
84 | oConfig.widthimage = sManipulate.split("-SEP-")[3].toString().trim();
85 | oConfig.heightimage = sManipulate.split("-SEP-")[4].toString().trim();
86 | oConfig.cropimage = sManipulate.split("-SEP-")[5].toString().trim().replace(/-/g, ",");
87 | oConfig.textoverlay = sManipulate.split("-SEP-")[6].toString().trim();
88 | oConfig.textoverlayXY = sManipulate.split("-SEP-")[7].toString().trim().replace(/-/g, ",");
89 | oConfig.textoverlayWH = sManipulate.split("-SEP-")[8].toString().trim().replace(/-/g, ",");
90 | oConfig.textoverlayFont = sManipulate.split("-SEP-")[9].toString().trim();
91 | node.urlImageCurrentIndex = (sManipulate.split("-SEP-")[10].toString().trim() === "YES" ? 0 : node.urlImageCurrentIndex); // Retry from beginning, to find the right image url
92 |
93 | node.variabilizeManipulation(oConfig);
94 | //#endregion
95 |
96 | //console.log("MAN " + JSON.stringify(oConfig))
97 | if (_nodeServer === null) {
98 | res.json({ picture: "", width: 0, height: 0 });
99 | } else {
100 | node.picture = null;
101 | node.server = _nodeServer;
102 | // Call the request, that then sends the result via node.sendPayload function
103 | node.server.request(node, "GET", node.urlImage[node.urlImageCurrentIndex], null).then(success => {
104 | // Wait until the server has called node.sendPayload and node.sendPayload has populated the node.picture variable
105 | var iTimeout = 0;
106 | var CB = () => {
107 | iTimeout += 1;
108 | if (iTimeout >= 15) {
109 | // Set the URL to the next in the list, so it can retry with that url in SendPayload
110 | node.urlImageCurrentIndex += 1;
111 | if (node.urlImageCurrentIndex > node.urlImage.length - 1) {
112 | // No more URLs to try
113 | node.urlImageCurrentIndex = 0;
114 | res.json({ picture: "", width: " !Error getting picture Timeout! ", height: 0 });
115 | } else {
116 | // Cycled through all URLS
117 | res.json({ picture: "", width: " !Retry new URL... ", height: 0 });
118 | }
119 | return;
120 | } else {
121 | if (node.picture !== null) {
122 | res.json({ picture: node.picture, width: node.pictureLarghezza, height: node.pictureAltezza, urlImageCurrentIndex: node.urlImageCurrentIndex });
123 | return;
124 | }
125 | setTimeout(CB, 500);
126 | }
127 | }
128 | setTimeout(CB, 500);
129 |
130 | }).catch(error => {
131 | // No more URLs to try
132 | node.urlImageCurrentIndex = 0;
133 | res.json({ picture: "", width: " !Error getting picture! ", height: " !" + error.message + "! " });
134 | });
135 | }
136 | } else { res.json({ picture: "", width: 0, height: 0 }); }
137 | });
138 |
139 | // Get picture
140 | // node.getPicture = (_picBase64) => new Promise(function (resolve, reject) {
141 | // try {
142 | // jimp.read(_picBase64)
143 | // .then(image => {
144 | // if (node.rotateimage !== 0) image = image.rotate(Number(node.rotateimage));
145 | // if (node.cropimage !== "") image = image.crop(node.cropimage.x, node.cropimage.y, node.cropimage.w, node.cropimage.h);
146 | // if (node.heightimage !== "0" && node.widthimage !== "0") image = image.resize(Number(node.widthimage), Number(node.heightimage));
147 | // if (node.qualityimage !== 100) image = image.quality(Number(node.qualityimage));
148 | // node.pictureLarghezza = image.bitmap.width;
149 | // node.pictureAltezza = image.bitmap.height;
150 |
151 | // jimp.loadFont(jimp.FONT_SANS_32_WHITE).then(font => {
152 | // image = image.print(font, 10, 10, 'Hello World!');
153 | // }).catch(err => { });
154 |
155 | // image.getBufferAsync(jimp.MIME_JPEG).then(picture => {
156 | // node.picture = "data:image/jpg;base64," + picture.toString("base64");
157 | // resolve(node.picture);
158 | // }).catch(error => {
159 | // reject(error);
160 | // });
161 | // });
162 | // } catch (error) {
163 | // reject(error);
164 | // }
165 | // });
166 |
167 | // Get picture
168 | async function getPicture(_picBase64) {
169 | try {
170 | image = await jimp.read(_picBase64);
171 | if (node.rotateimage !== 0) image = await image.rotate(Number(node.rotateimage));
172 | if (node.cropimage !== "") image = await image.crop(node.cropimage.x, node.cropimage.y, node.cropimage.w, node.cropimage.h);
173 | if (node.heightimage !== "0" && node.widthimage !== "0") image = await image.resize(Number(node.widthimage), Number(node.heightimage));
174 | if (node.qualityimage !== 100) image = await image.quality(Number(node.qualityimage));
175 | node.pictureLarghezza = image.bitmap.width;
176 | node.pictureAltezza = image.bitmap.height;
177 |
178 | // 27/01/2021 FONTS
179 | if (node.textoverlay !== "") {
180 | const oFont = jimp[node.textoverlayFont];
181 | try {
182 | const font = await jimp.loadFont(oFont);
183 | if (node.textoverlayWH === "") {
184 | image = await image.print(font, node.textoverlayXY.x, node.textoverlayXY.y, {
185 | text: node.textoverlay,
186 | alignmentX: jimp.HORIZONTAL_ALIGN_LEFT,
187 | alignmentY: jimp.VERTICAL_ALIGN_TOP
188 | });
189 | } else {
190 | image = await image.print(font, node.textoverlayXY.x, node.textoverlayXY.y, {
191 | text: node.textoverlay,
192 | alignmentX: jimp.HORIZONTAL_ALIGN_LEFT,
193 | alignmentY: jimp.VERTICAL_ALIGN_TOP
194 | }, node.textoverlayWH.w, node.textoverlayWH.h);
195 | }
196 | } catch (error) {
197 |
198 | }
199 |
200 | }
201 |
202 | let picture = await image.getBufferAsync(jimp.MIME_JPEG);
203 | let b64 = picture.toString("base64");
204 | node.picture = "data:image/jpg;base64," + b64;
205 | // Return various type of picture formats
206 | return ({
207 | forUI: node.picture, forEmail: picture, base64: b64
208 | });
209 |
210 | } catch (error) {
211 | return (error);
212 | }
213 | };
214 |
215 |
216 | // Called from config node, to send output to the flow
217 | node.sendPayload = (_msg) => {
218 | if (_msg === null || _msg === undefined) return;
219 |
220 | if (_msg.type !== undefined && _msg.type === 'img') {
221 | // Coming from an event containing an image
222 | return;
223 | }
224 | // 01/09/2022 Add the previous input message
225 | _msg.previousInputMessage = node.previousInputMessage;
226 | _msg.topic = node.topic;
227 | if (_msg.hasOwnProperty("errorDescription")) { node.send([null, _msg]); return; }; // It's a connection error/restore comunication.
228 | if (!_msg.hasOwnProperty("payload") || (_msg.hasOwnProperty("payload") && _msg.payload === undefined)) return;
229 |
230 | // 07/04/2021 The server has got a wrong response from camera/NVR
231 | if (_msg.hasOwnProperty("wrongResponse")) {
232 | // Maybe the URL was not working because the NVR is old or requires another URL
233 | // Try with another URL
234 | node.setNodeStatus({ fill: "yellow", shape: "ring", text: "Got wrong response. Trying wit another URL." });
235 | // Call the request, that then sends the result via node.sendPayload function
236 | //console.log("BANANA FIGA NON VA CON", node.urlImage[node.urlImageCurrentIndex]);
237 | if (node.server.debug) RED.log.info("BANANA TRYING GETTING IMAGE WITH", node.urlImage[node.urlImageCurrentIndex]);
238 | //console.log("BANANA PROVA CON", node.urlImage[node.urlImageCurrentIndex]);
239 | node.server.request(node, "GET", node.urlImage[node.urlImageCurrentIndex], null); // Hybrid NVR get image from an IP camera
240 |
241 | return;
242 | }
243 |
244 | if (_msg.payload.hasOwnProperty("eventType")) {
245 | // Chech if it's only a hearbeat alarm
246 | try {
247 | var sAlarmType = _msg.payload.eventType.toString().toLowerCase();
248 | if (sAlarmType === "videoloss" && _msg.payload.hasOwnProperty("activePostCount") && _msg.payload.activePostCount == "0") {
249 | node.setNodeStatus({ fill: "green", shape: "ring", text: "Received HeartBeat (the device is online)" });
250 | return; // It's a Heartbeat
251 | }
252 | } catch (error) { }
253 | return;
254 | }
255 |
256 |
257 | getPicture(_msg.payload).then(data => {
258 | _msg.payload = data.forUI;
259 | _msg.forEmail = data.forEmail;
260 | _msg.base64 = data.base64;
261 | node.send(_msg, null);
262 | node.setNodeStatus({ fill: "green", shape: "dot", text: "Picture received" });
263 | }).catch(error => {
264 | node.setNodeStatus({ fill: "red", shape: "dot", text: "GetBuffer error: " + error.message });
265 | })
266 |
267 |
268 | }
269 |
270 | // On each deploy, unsubscribe+resubscribe
271 | if (node.server) {
272 | node.server.removeClient(node);
273 | node.server.addClient(node);
274 | }
275 |
276 | this.on('input', function (msg) {
277 | if (msg === null || msg === undefined) return;
278 | // 01/09/2022 Save the original message to be passed through and sent out
279 | node.previousInputMessage = msg;
280 | if (msg.hasOwnProperty("textoverlay")) node.textoverlay = msg.textoverlay;
281 |
282 | if (msg.hasOwnProperty("payload") && msg.payload !== null && msg.payload !== undefined) {
283 | if (msg.payload === true) {
284 | try {
285 | // Call the request, that then sends the result via node.sendPayload function
286 | node.server.request(node, "GET", node.urlImage[node.urlImageCurrentIndex], null);
287 | } catch (error) {
288 |
289 | }
290 | }
291 | }
292 |
293 | });
294 |
295 | node.on("close", function (done) {
296 | if (node.server) {
297 | node.server.removeClient(node);
298 | }
299 | done();
300 | });
301 |
302 | }
303 |
304 | RED.nodes.registerType("hikvisionUltimatePicture", hikvisionUltimatePicture);
305 | }
--------------------------------------------------------------------------------
/nodes/hikvisionUltimateSpeaker.html:
--------------------------------------------------------------------------------
1 |
109 |
110 |
138 |
139 |
--------------------------------------------------------------------------------
/nodes/hikvisionUltimateSpeaker.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | module.exports = function (RED) {
4 | function hikvisionUltimateSpeaker(config) {
5 | RED.nodes.createNode(this, config);
6 | var node = this;
7 | node.topic = config.topic || config.name;
8 | node.server = RED.nodes.getNode(config.server)
9 |
10 |
11 | node.setNodeStatus = ({ fill, shape, text }) => {
12 | var dDate = new Date();
13 | node.status({ fill: fill, shape: shape, text: text + " (" + dDate.getDate() + ", " + dDate.toLocaleTimeString() + ")" })
14 | }
15 |
16 | // Called from config node, to send output to the flow
17 | node.sendPayload = (_msg) => {
18 | if (_msg === null || _msg === undefined) return;
19 | _msg.topic = node.topic;
20 | if (_msg.hasOwnProperty("errorDescription")) { node.send([null, _msg]); return; }; // It's a connection error/restore comunication.
21 | if (!_msg.hasOwnProperty("payload") || (_msg.hasOwnProperty("payload") && (_msg.payload === undefined || _msg.payload === null))) return;
22 |
23 |
24 | node.send([_msg, null]);
25 | try {
26 | //node.setNodeStatus({ fill: "green", shape: "dot", text: "Plate " + _msg.payload });
27 | } catch (error) { }
28 | }
29 |
30 | // On each deploy, unsubscribe+resubscribe
31 | if (node.server) {
32 | node.server.removeClient(node);
33 | node.server.addClient(node);
34 | }
35 |
36 | this.on('input', function (msg) {
37 | if (msg.payload === true) {
38 | (async () => {
39 | msg.payload = await node.server.playAloud(config.customAudioID, config.volume);
40 | node.send([msg, null]);
41 | node.setNodeStatus({ fill: "green", shape: "dot", text: "Play" });
42 | })();
43 | }
44 | if (msg.payload === false) {
45 | (async () => {
46 | msg.payload = await node.server.stopFile(config.customAudioID);
47 | node.send([msg, null]);
48 | node.setNodeStatus({ fill: "grey", shape: "dot", text: "Stop" });
49 | })();
50 | }
51 | });
52 |
53 | node.on("close", function (done) {
54 | if (node.server) {
55 | node.server.removeClient(node);
56 | }
57 | done();
58 | });
59 |
60 | }
61 |
62 | RED.nodes.registerType("hikvisionUltimateSpeaker", hikvisionUltimateSpeaker);
63 | }
--------------------------------------------------------------------------------
/nodes/hikvisionUltimateText.html:
--------------------------------------------------------------------------------
1 |
57 |
58 |
134 |
135 |
--------------------------------------------------------------------------------
/nodes/hikvisionUltimateText.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | module.exports = function (RED) {
4 | function hikvisionUltimateText(config) {
5 | RED.nodes.createNode(this, config);
6 | var node = this;
7 | node.server = RED.nodes.getNode(config.server)
8 | node.row1 = config.row1 === undefined ? "" : config.row1;
9 | node.row1XY = config.row1XY === undefined ? "" : config.row1XY;
10 | node.row2 = config.row2 === undefined ? "" : config.row2;
11 | node.row2XY = config.row2XY === undefined ? "" : config.row2XY;
12 | node.row3 = config.row3 === undefined ? "" : config.row3;
13 | node.row3XY = config.row3XY === undefined ? "" : config.row3XY;
14 | node.row4 = config.row4 === undefined ? "" : config.row4;
15 | node.row4XY = config.row4XY === undefined ? "" : config.row4XY;
16 | node.channelID = config.channelID === undefined ? "1" : config.channelID;
17 |
18 |
19 | node.setNodeStatus = ({ fill, shape, text }) => {
20 | var dDate = new Date();
21 | node.status({ fill: fill, shape: shape, text: text + " (" + dDate.getDate() + ", " + dDate.toLocaleTimeString() + ")" })
22 | }
23 |
24 |
25 |
26 | this.on('input', function (msg) {
27 |
28 | // Overrides
29 | if (msg.hasOwnProperty("row1")) node.row1 = msg.row1;
30 | if (msg.hasOwnProperty("row1XY")) node.row1XY = msg.row1XY;
31 | if (msg.hasOwnProperty("row2")) node.row2 = msg.row2;
32 | if (msg.hasOwnProperty("row2XY")) node.row2XY = msg.row2XY;
33 | if (msg.hasOwnProperty("row3")) node.row3 = msg.row3;
34 | if (msg.hasOwnProperty("row3XY")) node.row3XY = msg.row3XY;
35 | if (msg.hasOwnProperty("row4")) node.row4 = msg.row4;
36 | if (msg.hasOwnProperty("row4XY")) node.row4XY = msg.row4XY;
37 | if (msg.hasOwnProperty("channelid")) node.channelID = msg.channelid;
38 |
39 | let sRows = `
40 |
41 |
42 |
43 | 1
44 | ` + (node.row1.trim() === "" ? "false" : "true") + `
45 | ` + (node.row1XY.trim() === "" ? "" : node.row1XY.split(",")[0]) + `
46 | ` + (node.row1XY.trim() === "" ? "" : node.row1XY.split(",")[1]) + `
47 | ` + node.row1 + `
48 |
49 |
50 |
51 | 2
52 | ` + (node.row2.trim() === "" ? "false" : "true") + `
53 | ` + (node.row2XY.trim() === "" ? "" : node.row2XY.split(",")[0]) + `
54 | ` + (node.row2XY.trim() === "" ? "" : node.row2XY.split(",")[1]) + `
55 | ` + node.row2 + `
56 |
57 |
58 |
59 | 3
60 | ` + (node.row3.trim() === "" ? "false" : "true") + `
61 | ` + (node.row3XY.trim() === "" ? "" : node.row3XY.split(",")[0]) + `
62 | ` + (node.row3XY.trim() === "" ? "" : node.row3XY.split(",")[1]) + `
63 | ` + node.row3 + `
64 |
65 |
66 |
67 | 4
68 | ` + (node.row4.trim() === "" ? "false" : "true") + `
69 | ` + (node.row4XY.trim() === "" ? "" : node.row4XY.split(",")[0]) + `
70 | ` + (node.row4XY.trim() === "" ? "" : node.row4XY.split(",")[1]) + `
71 | ` + node.row4 + `
72 |
73 |
74 | `;
75 |
76 |
77 | node.setNodeStatus({ fill: "green", shape: "ring", text: "OK" });
78 | try {
79 | // Params: _callerNode, _method, _URL, _body
80 | node.server.request(node, "PUT", "/ISAPI/System/Video/inputs/channels/" + node.channelID + "/overlays/text", sRows);
81 | } catch (error) {
82 | // Try this, maybe the device is an old Turbo DVR
83 | try {
84 | node.server.request(node, "PUT", "/ISAPI/System/Video/inputs/channels/" + node.channelID + "/overlays", sRows);
85 | } catch (error) { }
86 | }
87 |
88 | });
89 |
90 | // Called from config node, to send output to the flow
91 | node.sendPayload = (_msg) => {
92 |
93 | };
94 |
95 |
96 | node.on("close", function (done) {
97 | done();
98 | });
99 |
100 | }
101 |
102 | RED.nodes.registerType("hikvisionUltimateText", hikvisionUltimateText);
103 | }
--------------------------------------------------------------------------------
/nodes/hikvisionUltimateXML.html:
--------------------------------------------------------------------------------
1 |
62 |
63 |
98 |
99 |
--------------------------------------------------------------------------------
/nodes/hikvisionUltimateXML.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | module.exports = function (RED) {
4 | function hikvisionUltimateXML(config) {
5 | RED.nodes.createNode(this, config);
6 | var node = this;
7 | node.server = RED.nodes.getNode(config.server)
8 | node.xmlText = config.xmlText === undefined ? "" : config.xmlText;
9 | node.path = config.path === undefined ? "" : config.path;
10 | node.method = config.method === undefined ? "PUT" : config.method;
11 |
12 |
13 | node.setNodeStatus = ({ fill, shape, text }) => {
14 | var dDate = new Date();
15 | node.status({ fill: fill, shape: shape, text: text + " (" + dDate.getDate() + ", " + dDate.toLocaleTimeString() + ")" })
16 | }
17 |
18 | // Called from config node, to send output to the flow
19 | node.sendPayload = (_msg) => {
20 | if (_msg.type !== undefined && _msg.type === 'img') {
21 | // The payload is an image, exit.
22 | return;
23 | }
24 | node.setNodeStatus({ fill: "green", shape: "ring", text: "Received response" });
25 | if (_msg === null || _msg === undefined) return;
26 | node.send(_msg);
27 |
28 | }
29 |
30 | this.on('input', function (msg) {
31 |
32 | // Overrides
33 | if (msg.hasOwnProperty("XML")) node.xmlText = msg.XML;
34 | if (msg.hasOwnProperty("path")) node.path = msg.path;
35 | if (msg.hasOwnProperty("method")) node.method = msg.method;
36 |
37 | node.setNodeStatus({ fill: "green", shape: "ring", text: "Send request..." });
38 | try {
39 | // Params: _callerNode, _method, _URL, _body, _fromXMLNode
40 | node.server.request(node, node.method, node.path, node.xmlText, true);
41 | } catch (error) {
42 |
43 | }
44 |
45 | });
46 |
47 |
48 | node.on("close", function (done) {
49 | done();
50 | });
51 |
52 | }
53 |
54 | RED.nodes.registerType("hikvisionUltimateXML", hikvisionUltimateXML);
55 | }
--------------------------------------------------------------------------------
/nodes/icons/camera-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/nodes/icons/camera-icon.png
--------------------------------------------------------------------------------
/nodes/icons/camera-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/nodes/icons/node-alarm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/nodes/icons/node-alarm.png
--------------------------------------------------------------------------------
/nodes/icons/node-alarm.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/nodes/icons/node-anpr-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/nodes/icons/node-anpr-icon.png
--------------------------------------------------------------------------------
/nodes/icons/node-anpr-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/nodes/icons/node-radar-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/nodes/icons/node-radar-icon.png
--------------------------------------------------------------------------------
/nodes/icons/node-radar-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/nodes/icons/node-raw-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/nodes/icons/node-raw-icon.png
--------------------------------------------------------------------------------
/nodes/icons/node-raw-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/nodes/icons/ptz-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supergiovane/node-red-contrib-hikvision-ultimate/26609177ef5ea918e3ae839151351174121f3098/nodes/icons/ptz-icon.png
--------------------------------------------------------------------------------
/nodes/icons/ptz-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/nodes/utils/AccessControlEvents/MAJOR_ALARM-0x1.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "ShortDescription": "MINOR_ALARMIN_SHORT_CIRCUIT",
4 | "Value": "0x400",
5 | "Description": "Zone Short Circuit Attempts Alarm"
6 | },
7 | {
8 | "ShortDescription": "MINOR_ALARMIN_BROKEN_CIRCUIT",
9 | "Value": "0x401",
10 | "Description": "Zone Disconnected Alarm"
11 | },
12 | {
13 | "ShortDescription": "MINOR_ALARMIN_EXCEPTION",
14 | "Value": "0x402",
15 | "Description": "Zone Exception Alarm"
16 | },
17 | {
18 | "ShortDescription": "MINOR_ALARMIN_RESUME",
19 | "Value": "0x403",
20 | "Description": "Zone Restored"
21 | },
22 | {
23 | "ShortDescription": "MINOR_HOST_DESMANTLE_ALARM",
24 | "Value": "0x404",
25 | "Description": "Zone Tampering Alarm"
26 | },
27 | {
28 | "ShortDescription": "MINOR_HOST_DESMANTLE_RESUME",
29 | "Value": "0x405",
30 | "Description": "Zone Tampering Restored"
31 | },
32 | {
33 | "ShortDescription": "MINOR_CARD_READER_DESMANTLE_ALARM",
34 | "Value": "0x406",
35 | "Description": "Card Reader Tampering Alarm"
36 | },
37 | {
38 | "ShortDescription": "MINOR_CARD_READER_DESMANTLE_RESUME",
39 | "Value": "0x407",
40 | "Description": "Card Reader Tampering Restored"
41 | },
42 | {
43 | "ShortDescription": "MINOR_CASE_SENSOR_ALARM",
44 | "Value": "0x408",
45 | "Description": "Alarm Input Alarm Triggered"
46 | },
47 | {
48 | "ShortDescription": "MINOR_CASE_SENSOR_RESUME",
49 | "Value": "0x409",
50 | "Description": "Alarm Input Restored"
51 | },
52 | {
53 | "ShortDescription": "MINOR_STRESS_ALARM",
54 | "Value": "0x40a",
55 | "Description": "Duress Alarm"
56 | },
57 | {
58 | "ShortDescription": "MINOR_OFFLINE_ECENT_NEARLY_FULL",
59 | "Value": "0x40b",
60 | "Description": "No Memory for Offline Event Storage Alarm"
61 | },
62 | {
63 | "ShortDescription": "MINOR_CARD_MAX_AUTHENTICATE_FAIL",
64 | "Value": "0x40c",
65 | "Description": "Maximum Failed Card Authentications Alarm"
66 | },
67 | {
68 | "ShortDescription": "MINOR_SD_CARD_FULL",
69 | "Value": "0x40d",
70 | "Description": "SD Card Full Alarm"
71 | },
72 | {
73 | "ShortDescription": "MINOR_LINKAGE_CAPTURE_PIC",
74 | "Value": "0x40e",
75 | "Description": "Capture Linkage Alarm"
76 | },
77 | {
78 | "ShortDescription": "MINOR_SECURITY_MODULE_DESMANTLE_ALARM",
79 | "Value": "0x40f",
80 | "Description": "Secure Door Control Unit Tampering Alarm"
81 | },
82 | {
83 | "ShortDescription": "MINOR_SECURITY_MODULE_DESMANTLE_RESUME",
84 | "Value": "0x410",
85 | "Description": "Secure Door Control Unit Tampering Restored"
86 | },
87 | {
88 | "ShortDescription": "MINOR_FIRE_IMPORT_SHORT_CIRCUIT",
89 | "Value": "0x415",
90 | "Description": "Fire Input Short Circuit Attempts Alarm"
91 | },
92 | {
93 | "ShortDescription": "MINOR_FIRE_IMPORT_BROKEN_CIRCUIT",
94 | "Value": "0x416",
95 | "Description": "Fire Input Open Circuit Attempts Alarm"
96 | },
97 | {
98 | "ShortDescription": "MINOR_FIRE_IMPORT_RESUME",
99 | "Value": "0x417",
100 | "Description": "Fire Input Restored"
101 | },
102 | {
103 | "ShortDescription": "MINOR_FIRE_BUTTON_TRIGGER",
104 | "Value": "0x418",
105 | "Description": "Fire Button Triggered"
106 | },
107 | {
108 | "ShortDescription": "MINOR_FIRE_BUTTON_RESUME",
109 | "Value": "0x419",
110 | "Description": "Fire Button Resumed"
111 | },
112 | {
113 | "ShortDescription": "MINOR_MAINTENANCE_BUTTON_TRIGGER",
114 | "Value": "0x41a",
115 | "Description": "Maintenance Button Triggered"
116 | },
117 | {
118 | "ShortDescription": "MINOR_MAINTENANCE_BUTTON_RESUME",
119 | "Value": "0x41b",
120 | "Description": "Maintenance Button Resumed"
121 | },
122 | {
123 | "ShortDescription": "MINOR_EMERGENCY_BUTTON_TRIGGER",
124 | "Value": "0x41c",
125 | "Description": "Panic Button Triggered"
126 | },
127 | {
128 | "ShortDescription": "MINOR_EMERGENCY_BUTTON_RESUME",
129 | "Value": "0x41d",
130 | "Description": "Panic Button Resumed"
131 | },
132 | {
133 | "ShortDescription": "MINOR_DISTRACT_CONTROLLER_ALARM",
134 | "Value": "0x41e",
135 | "Description": "Distributed Elevator Controller Tampering Alarm"
136 | },
137 | {
138 | "ShortDescription": "MINOR_DISTRACT_CONTROLLER_RESUME",
139 | "Value": "0x41f",
140 | "Description": "Distributed Elevator Controller Tampering Restored"
141 | },
142 | {
143 | "ShortDescription": "MINOR_CHANNEL_CONTROLLER_DESMANTLE_ALARM",
144 | "Value": "0x422",
145 | "Description": "Lane Controller Tampering Alarm"
146 | },
147 | {
148 | "ShortDescription": "MINOR_CHANNEL_CONTROLLER_DESMANTLE_RESUME",
149 | "Value": "0x423",
150 | "Description": "Lane Controller Tampering Alarm Restored"
151 | },
152 | {
153 | "ShortDescription": "MINOR_CHANNEL_CONTROLLER_FIRE_IMPORT_ALARM",
154 | "Value": "0x424",
155 | "Description": "Lane Controller Fire Input Alarm"
156 | },
157 | {
158 | "ShortDescription": "MINOR_CHANNEL_CONTROLLER_FIRE_IMPORT_RESUME",
159 | "Value": "0x425",
160 | "Description": "Lane Controller Fire Input Alarm Restored"
161 | },
162 | {
163 | "ShortDescription": "MINOR_PRINTER_OUT_OF_PAPER",
164 | "Value": "0x440",
165 | "Description": "No Paper in Printer Alarm"
166 | },
167 | {
168 | "ShortDescription": "MINOR_LEGAL_EVENT_NEARLY_FULL",
169 | "Value": "0x442",
170 | "Description": "No Memory Alarm for Valid Offline Event Storage"
171 | },
172 | {
173 | "ShortDescription": "MINOR_ALARM_CUSTOM1 to MINOR_ALARM_CUSTOM64",
174 | "Value": "0x900 to 0x93f",
175 | "Description": "Access Control: Custom Alarm Event 1 to Custom Alarm Event 64"
176 | }
177 | ]
--------------------------------------------------------------------------------
/nodes/utils/AccessControlEvents/MAJOR_EXCEPTION-0x2.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "ShortDescription": "MINOR_NET_BROKEN",
4 | "Value": "0x27",
5 | "Description": "Network Disconnected"
6 | },
7 | {
8 | "ShortDescription": "MINOR_RS485_DEVICE_ABNORMAL",
9 | "Value": "0x3a",
10 | "Description": "RS485 Connection Exception"
11 | },
12 | {
13 | "ShortDescription": "MINOR_RS485_DEVICE_REVERT",
14 | "Value": "0x3b",
15 | "Description": "RS485 Connection Restored"
16 | },
17 | {
18 | "ShortDescription": "MINOR_DEV_POWER_ON",
19 | "Value": "0x400",
20 | "Description": "Power on"
21 | },
22 | {
23 | "ShortDescription": "MINOR_DEV_POWER_OFF",
24 | "Value": "0x401",
25 | "Description": "Power off"
26 | },
27 | {
28 | "ShortDescription": "MINOR_WATCH_DOG_RESET",
29 | "Value": "0x402",
30 | "Description": "Watchdog Reset"
31 | },
32 | {
33 | "ShortDescription": "MINOR_LOW_BATTERY",
34 | "Value": "0x403",
35 | "Description": "Low Battery Voltage"
36 | },
37 | {
38 | "ShortDescription": "MINOR_BATTERY_RESUME",
39 | "Value": "0x404",
40 | "Description": "Battery Voltage Restored"
41 | },
42 | {
43 | "ShortDescription": "MINOR_AC_OFF",
44 | "Value": "0x405",
45 | "Description": "AC Power Disconnected"
46 | },
47 | {
48 | "ShortDescription": "MINOR_AC_RESUME",
49 | "Value": "0x406",
50 | "Description": "AC Power Restored"
51 | },
52 | {
53 | "ShortDescription": "MINOR_NET_RESUME",
54 | "Value": "0x407",
55 | "Description": "Network Restored"
56 | },
57 | {
58 | "ShortDescription": "MINOR_FLASH_ABNORMAL",
59 | "Value": "0x408",
60 | "Description": "Flash Reading and Writing Exception"
61 | },
62 | {
63 | "ShortDescription": "MINOR_CARD_READER_OFFLINE",
64 | "Value": "0x409",
65 | "Description": "Card Reader Offline"
66 | },
67 | {
68 | "ShortDescription": "MINOR_CAED_READER_RESUME",
69 | "Value": "0x40a",
70 | "Description": "Card Reader Online"
71 | },
72 | {
73 | "ShortDescription": "MINOR_INDICATOR_LIGHT_OFF",
74 | "Value": "0x40b",
75 | "Description": "Indicator Turns off"
76 | },
77 | {
78 | "ShortDescription": "MINOR_INDICATOR_LIGHT_RESUME",
79 | "Value": "0x40c",
80 | "Description": "Indicator Resumed"
81 | },
82 | {
83 | "ShortDescription": "MINOR_CHANNEL_CONTROLLER_OFF",
84 | "Value": "0x40d",
85 | "Description": "Lane Controller Offline"
86 | },
87 | {
88 | "ShortDescription": "MINOR_CHANNEL_CONTROLLER_RESUME",
89 | "Value": "0x40e",
90 | "Description": "Lane Controller Online"
91 | },
92 | {
93 | "ShortDescription": "MINOR_SECURITY_MODULE_OFF",
94 | "Value": "0x40f",
95 | "Description": "Secure Door Control Unit Offline"
96 | },
97 | {
98 | "ShortDescription": "MINOR_SECURITY_MODULE_RESUME",
99 | "Value": "0x410",
100 | "Description": "Secure Door Control Unit Online"
101 | },
102 | {
103 | "ShortDescription": "MINOR_BATTERY_ELECTRIC_LOW",
104 | "Value": "0x411",
105 | "Description": "Low Battery Voltage (Only for Face Recognition Terminal)"
106 | },
107 | {
108 | "ShortDescription": "MINOR_BATTERY_ELECTRIC_RESUME",
109 | "Value": "0x412",
110 | "Description": "Battery Voltage Recovered (Only for Face Recognition Terminal)"
111 | },
112 | {
113 | "ShortDescription": "MINOR_LOCAL_CONTROL_NET_BROKEN",
114 | "Value": "0x413",
115 | "Description": "Network of Distributed Access Controller Disconnected"
116 | },
117 | {
118 | "ShortDescription": "MINOR_LOCAL_CONTROL_NET_RSUME",
119 | "Value": "0x414",
120 | "Description": "Network of Distributed Access Controller Restored"
121 | },
122 | {
123 | "ShortDescription": "MINOR_MASTER_RS485_LOOPNODE_BROKEN",
124 | "Value": "0x415",
125 | "Description": "RS485 Loop of Master Access Controller Disconnected"
126 | },
127 | {
128 | "ShortDescription": "MINOR_MASTER_RS485_LOOPNODE_RESUME",
129 | "Value": "0x416",
130 | "Description": "RS485 Loop of Master Access Controller Connected"
131 | },
132 | {
133 | "ShortDescription": "MINOR_LOCAL_CONTROL_OFFLINE",
134 | "Value": "0x417",
135 | "Description": "Distributed Access Controller Offline"
136 | },
137 | {
138 | "ShortDescription": "MINOR_LOCAL_CONTROL_RESUME",
139 | "Value": "0x418",
140 | "Description": "Distributed Access Controller Online"
141 | },
142 | {
143 | "ShortDescription": "MINOR_LOCAL_DOWNSIDE_RS485_LOOPNODE_BROKEN",
144 | "Value": "0x419",
145 | "Description": "Downstream RS485 Loop of Distributed Access Control Disconnected"
146 | },
147 | {
148 | "ShortDescription": "MINOR_LOCAL_DOWNSIDE_RS485_LOOPNODE_RESUME",
149 | "Value": "0x41a",
150 | "Description": "Downstream RS485 Loop of Distributed Access Control Connected"
151 | },
152 | {
153 | "ShortDescription": "MINOR_DISTRACT_CONTROLLER_ONLINE",
154 | "Value": "0x41b",
155 | "Description": "Distributed Elevator Controller Online"
156 | },
157 | {
158 | "ShortDescription": "MINOR_DISTRACT_CONTROLLER_OFFLINE",
159 | "Value": "0x41c",
160 | "Description": "Distributed Elevator Controller Offline"
161 | },
162 | {
163 | "ShortDescription": "MINOR_ID_CARD_READER_NOT_CONNECT",
164 | "Value": "0x41d",
165 | "Description": "ID Card Reader Disconnected"
166 | },
167 | {
168 | "ShortDescription": "MINOR_ID_CARD_READER_RESUME",
169 | "Value": "0x41e",
170 | "Description": "ID Card Reader Connected"
171 | },
172 | {
173 | "ShortDescription": "MINOR_FINGER_PRINT_MODULE_NOT_CONNECT",
174 | "Value": "0x41f",
175 | "Description": "Fingerprint Module Disconnected"
176 | },
177 | {
178 | "ShortDescription": "MINOR_FINGER_PRINT_MODULE_RESUME",
179 | "Value": "0x420",
180 | "Description": "Fingerprint Module Connected"
181 | },
182 | {
183 | "ShortDescription": "MINOR_CAMERA_NOT_CONNECT",
184 | "Value": "0x421",
185 | "Description": "Camera Disconnected"
186 | },
187 | {
188 | "ShortDescription": "MINOR_CAMERA_RESUME",
189 | "Value": "0x422",
190 | "Description": "Camera Connected"
191 | },
192 | {
193 | "ShortDescription": "MINOR_COM_NOT_CONNECT",
194 | "Value": "0x423",
195 | "Description": "COM Port Disconnected"
196 | },
197 | {
198 | "ShortDescription": "MINOR_COM_RESUME",
199 | "Value": "0x424",
200 | "Description": "COM Port Connected"
201 | },
202 | {
203 | "ShortDescription": "MINOR_DEVICE_NOT_AUTHORIZE",
204 | "Value": "0x425",
205 | "Description": "Device Unauthorized"
206 | },
207 | {
208 | "ShortDescription": "MINOR_PEOPLE_AND_ID_CARD_DEVICE_ONLINE",
209 | "Value": "0x426",
210 | "Description": "Face Recognition Terminal Online"
211 | },
212 | {
213 | "ShortDescription": "MINOR_PEOPLE_AND_ID_CARD_DEVICE_OFFLINE",
214 | "Value": "0x427",
215 | "Description": "Face Recognition Terminal Offline"
216 | },
217 | {
218 | "ShortDescription": "MINOR_LOCAL_LOGIN_LOCK",
219 | "Value": "0x428",
220 | "Description": "Local Login Lock"
221 | },
222 | {
223 | "ShortDescription": "MINOR_LOCAL_LOGIN_UNLOCK",
224 | "Value": "0x429",
225 | "Description": "Local Login Unlock"
226 | },
227 | {
228 | "ShortDescription": "MINOR_SUBMARINEBACK_COMM_BREAK",
229 | "Value": "0x42a",
230 | "Description": "Communication with Anti-passing Back Server Failed"
231 | },
232 | {
233 | "ShortDescription": "MINOR_SUBMARINEBACK_COMM_RESUME",
234 | "Value": "0x42b",
235 | "Description": "Communication with Anti-passing Back Server Restored"
236 | },
237 | {
238 | "ShortDescription": "MINOR_MOTOR_SENSOR_EXCEPTION",
239 | "Value": "0x42c",
240 | "Description": "Motor or Sensor Exception"
241 | },
242 | {
243 | "ShortDescription": "MINOR_CAN_BUS_EXCEPTION",
244 | "Value": "0x42d",
245 | "Description": "CAN Bus Exception"
246 | },
247 | {
248 | "ShortDescription": "MINOR_CAN_BUS_RESUME",
249 | "Value": "0x42e",
250 | "Description": "CAN Bus Exception Restored"
251 | },
252 | {
253 | "ShortDescription": "MINOR_GATE_TEMPERATURE_OVERRUN",
254 | "Value": "0x42f",
255 | "Description": "Too High Pedestal Temperature"
256 | },
257 | {
258 | "ShortDescription": "MINOR_IR_EMITTER_EXCEPTION",
259 | "Value": "0x430",
260 | "Description": "Active Infrared Intrusion Detector Exception"
261 | },
262 | {
263 | "ShortDescription": "MINOR_IR_EMITTER_RESUME",
264 | "Value": "0x431",
265 | "Description": "Active Infrared Intrusion Detector Restored"
266 | },
267 | {
268 | "ShortDescription": "MINOR_LAMP_BOARD_COMM_EXCEPTION",
269 | "Value": "0x432",
270 | "Description": "Communication with Light Board Failed"
271 | },
272 | {
273 | "ShortDescription": "MINOR_LAMP_BOARD_COMM_RESUME",
274 | "Value": "0x433",
275 | "Description": "Communication with Light Board Restored"
276 | },
277 | {
278 | "ShortDescription": "MINOR_IR_ADAPTOR_COMM_EXCEPTION",
279 | "Value": "0x434",
280 | "Description": "Communication with IR Adaptor Failed"
281 | },
282 | {
283 | "ShortDescription": "MINOR_IR_ADAPTOR_COMM_RESUME",
284 | "Value": "0x435",
285 | "Description": "Communication with IR Adaptor Restored"
286 | },
287 | {
288 | "ShortDescription": "MINOR_PRINTER_ONLINE",
289 | "Value": "0x436",
290 | "Description": "Printer Online"
291 | },
292 | {
293 | "ShortDescription": "MINOR_PRINTER_OFFLINE",
294 | "Value": "0x437",
295 | "Description": "Printer Offline"
296 | },
297 | {
298 | "ShortDescription": "MINOR_4G_MOUDLE_ONLINE",
299 | "Value": "0x438",
300 | "Description": "4G Module Online"
301 | },
302 | {
303 | "ShortDescription": "MINOR_4G_MOUDLE_OFFLINE",
304 | "Value": "0x439",
305 | "Description": "4G Module Offline"
306 | },
307 | {
308 | "ShortDescription": "MINOR_AUXILIARY_BOARD_OFFLINE",
309 | "Value": "0x43c",
310 | "Description": "Auxiliary Board Disconnected"
311 | },
312 | {
313 | "ShortDescription": "MINOR_AUXILIARY_BOARD_RESUME",
314 | "Value": "0x43d",
315 | "Description": "Auxiliary Board Connected"
316 | },
317 | {
318 | "ShortDescription": "MINOR_IDCARD_SECURITY_MOUDLE_EXCEPTION",
319 | "Value": "0x43e",
320 | "Description": "Secure ID Card Unit Exception"
321 | },
322 | {
323 | "ShortDescription": "MINOR_IDCARD_SECURITY_MOUDLE_RESUME",
324 | "Value": "0x43f",
325 | "Description": "Secure ID Card Unit Restored"
326 | },
327 | {
328 | "ShortDescription": "MINOR_FP_PERIPHERAL_EXCEPTION",
329 | "Value": "0x440",
330 | "Description": "Fingerprint Collection Peripheral Exception"
331 | },
332 | {
333 | "ShortDescription": "MINOR_FP_PERIPHERAL_RESUME",
334 | "Value": "0x441",
335 | "Description": "Fingerprint Collection Peripheral Restored"
336 | },
337 | {
338 | "ShortDescription": "MINOR_EXCEPTION_CUSTOM1 to MINOR_EXCEPTION_CUSTOM64",
339 | "Value": "0x900 to 0x93f",
340 | "Description": "Access Control: Custom Exception Event 1 to Custom Exception Event 64"
341 | }
342 | ]
--------------------------------------------------------------------------------
/nodes/utils/AccessControlEvents/MAJOR_OPERATION-0x3.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "ShortDescription": "MINOR_LOCAL_LOGIN",
4 | "Value": "0x50",
5 | "Description": "Local Login"
6 | },
7 | {
8 | "ShortDescription": "MINOR_LOCAL_LOGOUT",
9 | "Value": "0x51",
10 | "Description": "Local Logout"
11 | },
12 | {
13 | "ShortDescription": "MINOR_LOCAL_UPGRADE",
14 | "Value": "0x5a",
15 | "Description": "Local Upgrade"
16 | },
17 | {
18 | "ShortDescription": "MINOR_REMOTE_LOGIN",
19 | "Value": "0x70",
20 | "Description": "Remote Login"
21 | },
22 | {
23 | "ShortDescription": "MINOR_REMOTE_LOGOUT",
24 | "Value": "0x71",
25 | "Description": "Remote Logout"
26 | },
27 | {
28 | "ShortDescription": "MINOR_REMOTE_ARM",
29 | "Value": "0x79",
30 | "Description": "Remote Arming"
31 | },
32 | {
33 | "ShortDescription": "MINOR_REMOTE_DISARM",
34 | "Value": "0x7a",
35 | "Description": "Remote Disarming"
36 | },
37 | {
38 | "ShortDescription": "MINOR_REMOTE_REBOOT",
39 | "Value": "0x7b",
40 | "Description": "Remote Reboot"
41 | },
42 | {
43 | "ShortDescription": "MINOR_REMOTE_UPGRADE",
44 | "Value": "0x7e",
45 | "Description": "Remote Upgrade"
46 | },
47 | {
48 | "ShortDescription": "MINOR_REMOTE_CFGFILE_OUTPUT",
49 | "Value": "0x86",
50 | "Description": "Remote Operation: Export Configuration File"
51 | },
52 | {
53 | "ShortDescription": "MINOR_REMOTE_CFGFILE_INTPUT",
54 | "Value": "0x87",
55 | "Description": "Remote Operation: Import Configuration File"
56 | },
57 | {
58 | "ShortDescription": "MINOR_REMOTE_ALARMOUT_OPEN_MAN",
59 | "Value": "0xd6",
60 | "Description": "Remote Operation: Enable Alarm Output Manually"
61 | },
62 | {
63 | "ShortDescription": "MINOR_REMOTE_ALARMOUT_CLOSE_MAN",
64 | "Value": "0xd7",
65 | "Description": "Remote Operation: Disable Alarm Output Manually"
66 | },
67 | {
68 | "ShortDescription": "MINOR_REMOTE_OPEN_DOOR",
69 | "Value": "0x400",
70 | "Description": "Door Remotely Open"
71 | },
72 | {
73 | "ShortDescription": "MINOR_REMOTE_CLOSE_DOOR",
74 | "Value": "0x401",
75 | "Description": "Door Remotely Closed"
76 | },
77 | {
78 | "ShortDescription": "MINOR_REMOTE_ALWAYS_OPEN",
79 | "Value": "0x402",
80 | "Description": "Remain Open Remotely"
81 | },
82 | {
83 | "ShortDescription": "MINOR_REMOTE_ALWAYS_CLOSE",
84 | "Value": "0x403",
85 | "Description": "Remain Closed Remotely"
86 | },
87 | {
88 | "ShortDescription": "MINOR_REMOTE_CHECK_TIME",
89 | "Value": "0x404",
90 | "Description": "Remote: Manual Time Sync"
91 | },
92 | {
93 | "ShortDescription": "MINOR_NTP_CHECK_TIME",
94 | "Value": "0x405",
95 | "Description": "Network Time Protocol Synchronization"
96 | },
97 | {
98 | "ShortDescription": "MINOR_REMOTE_CLEAR_CARD",
99 | "Value": "0x406",
100 | "Description": "Remote Operation: Clear All Card No."
101 | },
102 | {
103 | "ShortDescription": "MINOR_REMOTE_RESTORE_CFG",
104 | "Value": "0x407",
105 | "Description": "Remote Operation: Restore Defaults"
106 | },
107 | {
108 | "ShortDescription": "MINOR_ALARMIN_ARM",
109 | "Value": "0x408",
110 | "Description": "Zone Arming"
111 | },
112 | {
113 | "ShortDescription": "MINOR_ALARMIN_DISARM",
114 | "Value": "0x409",
115 | "Description": "Zone Disarming"
116 | },
117 | {
118 | "ShortDescription": "MINOR_LOCAL_RESTORE_CFG",
119 | "Value": "0x40a",
120 | "Description": "Local Operation: Restore Defaults"
121 | },
122 | {
123 | "ShortDescription": "MINOR_REMOTE_CAPTURE_PIC",
124 | "Value": "0x40b",
125 | "Description": "Remote Operation: Capture"
126 | },
127 | {
128 | "ShortDescription": "MINOR_MOD_NET_REPORT_CFG",
129 | "Value": "0x40c",
130 | "Description": "Edit Network Parameters"
131 | },
132 | {
133 | "ShortDescription": "MINOR_MOD_GPRS_REPORT_PARAM",
134 | "Value": "0x40d",
135 | "Description": "Edit GPRS Parameters"
136 | },
137 | {
138 | "ShortDescription": "MINOR_MOD_REPORT_GROUP_PARAM",
139 | "Value": "0x40e",
140 | "Description": "Edit Control Center Parameters"
141 | },
142 | {
143 | "ShortDescription": "MINOR_UNLOCK_PASSWORD_OPEN_DOOR",
144 | "Value": "0x40f",
145 | "Description": "Enter Dismiss Code"
146 | },
147 | {
148 | "ShortDescription": "MINOR_AUTO_RENUMBER",
149 | "Value": "0x410",
150 | "Description": "Auto Renumber"
151 | },
152 | {
153 | "ShortDescription": "MINOR_AUTO_COMPLEMENT_NUMBER",
154 | "Value": "0x411",
155 | "Description": "Auto Supplement Number"
156 | },
157 | {
158 | "ShortDescription": "MINOR_NORMAL_CFGFILE_INPUT",
159 | "Value": "0x412",
160 | "Description": "Import Configuration File"
161 | },
162 | {
163 | "ShortDescription": "MINOR_NORMAL_CFGFILE_OUTTPUT",
164 | "Value": "0x413",
165 | "Description": "Export Configuration File"
166 | },
167 | {
168 | "ShortDescription": "MINOR_CARD_RIGHT_INPUT",
169 | "Value": "0x414",
170 | "Description": "Import Card Permission Parameters"
171 | },
172 | {
173 | "ShortDescription": "MINOR_CARD_RIGHT_OUTTPUT",
174 | "Value": "0x415",
175 | "Description": "Export Card Permission Parameters"
176 | },
177 | {
178 | "ShortDescription": "MINOR_LOCAL_USB_UPGRADE",
179 | "Value": "0x416",
180 | "Description": "Upgrade Device via USB flash Drive"
181 | },
182 | {
183 | "ShortDescription": "MINOR_REMOTE_VISITOR_CALL_LADDER",
184 | "Value": "0x417",
185 | "Description": "Visitor Calling Elevator"
186 | },
187 | {
188 | "ShortDescription": "MINOR_REMOTE_HOUSEHOLD_CALL_LADDER",
189 | "Value": "0x418",
190 | "Description": "Resident Calling Elevator"
191 | },
192 | {
193 | "ShortDescription": "MINOR_REMOTE_ACTUAL_GUARD",
194 | "Value": "0x419",
195 | "Description": "Remotely Arming"
196 | },
197 | {
198 | "ShortDescription": "MINOR_REMOTE_ACTUAL_UNGUARD",
199 | "Value": "0x41a",
200 | "Description": "Remotely Disarming"
201 | },
202 | {
203 | "ShortDescription": "MINOR_REMOTE_CONTROL_NOT_CODE_OPER_FAILED",
204 | "Value": "0x41b",
205 | "Description": "Operation Failed: Keyfob Not Pairing"
206 | },
207 | {
208 | "ShortDescription": "MINOR_REMOTE_CONTROL_CLOSE_DOOR",
209 | "Value": "0x41c",
210 | "Description": "Keyfob Operation: Close Door"
211 | },
212 | {
213 | "ShortDescription": "MINOR_REMOTE_CONTROL_OPEN_DOOR",
214 | "Value": "0x41d",
215 | "Description": "Keyfob Operation: Open Door"
216 | },
217 | {
218 | "ShortDescription": "MINOR_REMOTE_CONTROL_ALWAYS_OPEN_DOOR",
219 | "Value": "0x41e",
220 | "Description": "Keyfob Operation: Remain Door Open"
221 | },
222 | {
223 | "ShortDescription": "MINOR_M1_CARD_ENCRYPT_VERIFY_OPEN",
224 | "Value": "0x41f",
225 | "Description": "M1 Card Encryption Verification Enabled"
226 | },
227 | {
228 | "ShortDescription": "MINOR_M1_CARD_ENCRYPT_VERIFY_CLOSE",
229 | "Value": "0x420",
230 | "Description": "M1 Card Encryption Verification Disabled"
231 | },
232 | {
233 | "ShortDescription": "MINOR_NFC_FUNCTION_OPEN",
234 | "Value": "0X421",
235 | "Description": "Opening Door with NFC Card Enabled"
236 | },
237 | {
238 | "ShortDescription": "MINOR_NFC_FUNCTION_CLOSE",
239 | "Value": "0X422",
240 | "Description": "Opening Door with NFC Card Disabled"
241 | },
242 | {
243 | "ShortDescription": "MINOR_OFFLINE_DATA_OUTPUT",
244 | "Value": "0x423",
245 | "Description": "Export Offline Collected Data"
246 | },
247 | {
248 | "ShortDescription": "MINOR_CREATE_SSH_LINK",
249 | "Value": "0x42d",
250 | "Description": "Establish SSH Connection"
251 | },
252 | {
253 | "ShortDescription": "MINOR_CLOSE_SSH_LINK",
254 | "Value": "0x42e",
255 | "Description": "Disconnect SSH Connection"
256 | },
257 | {
258 | "ShortDescription": "MINOR_OPERATION_CUSTOM1 to MINOR_OPERATION_CUSTOM64",
259 | "Value": "0x900-0x93f",
260 | "Description": "Access Control: Custom Operation Event 1 to Custom Operation Event 64"
261 | }
262 | ]
--------------------------------------------------------------------------------
/nodes/utils/Sha256.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | exports.__esModule = true;
3 | exports.sha256 = void 0;
4 | function m(e, t) {
5 | var n = (65535 & e) + (65535 & t);
6 | return (e >> 16) + (t >> 16) + (n >> 16) << 16 | 65535 & n;
7 | }
8 | function C(e, t) {
9 | return e >>> t | e << 32 - t;
10 | }
11 | function fun0(e) {
12 | var t = '';
13 | for (var n = 0; n < 4 * e.length; n++) {
14 | t += '0123456789abcdef'.charAt(e[n >> 2] >> 8 * (3 - n % 4) + 4 & 15) +
15 | '0123456789abcdef'.charAt(e[n >> 2] >> 8 * (3 - n % 4) & 15);
16 | }
17 | return t;
18 | }
19 | function fun1(e, t) {
20 | var n;
21 | var r;
22 | var s;
23 | var o;
24 | var i;
25 | var a;
26 | var u;
27 | var c;
28 | var l;
29 | var d;
30 | var p;
31 | var P;
32 | var h = [1116352408, 1899447441, 3049323471, 3921009573, 961987163, 1508970993, 2453635748, 2870763221, 3624381080,
33 | 310598401, 607225278, 1426881987, 1925078388, 2162078206, 2614888103, 3248222580, 3835390401, 4022224774,
34 | 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, 2554220882, 2821834349, 2952996808,
35 | 3210313671, 3336571891, 3584528711, 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291,
36 | 1695183700, 1986661051, 2177026350, 2456956037, 2730485921, 2820302411, 3259730800, 3345764771, 3516065817,
37 | 3600352804, 4094571909, 275423344, 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, 1537002063,
38 | 1747873779, 1955562222, 2024104815, 2227730452, 2361852424, 2428436474, 2756734187, 3204031479, 3329325298];
39 | var f = [1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225];
40 | var I = Array(64);
41 | for (e[t >> 5] |= 128 << 24 - t % 32, e[15 + (t + 64 >> 9 << 4)] = t, l = 0; l < e.length; l += 16) {
42 | for (n = f[0], r = f[1], s = f[2], o = f[3], i = f[4], a = f[5], u = f[6], c = f[7], d = 0; d < 64; d++) {
43 | I[d] = d < 16 ? e[d + l] : m(m(m(C(I[d - 2], 17) ^ C(I[d - 2], 19) ^ I[d - 2] >>> 10, I[d - 7]), C(I[d - 15], 7) ^ C(I[d - 15], 18) ^ I[d - 15] >>> 3), I[d - 16]);
44 | p = m(m(m(m(c, C(i, 6) ^ C(i, 11) ^ C(i, 25)), i & a ^ ~i & u), h[d]), I[d]);
45 | P = m(C(n, 2) ^ C(n, 13) ^ C(n, 22), n & r ^ n & s ^ r & s);
46 | c = u;
47 | u = a;
48 | a = i;
49 | i = m(o, p);
50 | o = s;
51 | s = r;
52 | r = n;
53 | n = m(p, P);
54 | }
55 | f[0] = m(n, f[0]);
56 | f[1] = m(r, f[1]);
57 | f[2] = m(s, f[2]);
58 | f[3] = m(o, f[3]);
59 | f[4] = m(i, f[4]);
60 | f[5] = m(a, f[5]);
61 | f[6] = m(u, f[6]);
62 | f[7] = m(c, f[7]);
63 | }
64 | return f;
65 | }
66 | function fun2(e) {
67 | var t = [];
68 | for (var n = 0; n < 8 * e.length; n += 8) {
69 | t[n >> 5] |= (255 & e.charCodeAt(n / 8)) << 24 - n % 32;
70 | }
71 | return t;
72 | }
73 | function fun3(e) {
74 | e = e.replace(/\r\n/g, '\n');
75 | var t = '';
76 | for (var n = 0; n < e.length; n++) {
77 | var r = e.charCodeAt(n);
78 | if (r < 128) {
79 | t += String.fromCharCode(r);
80 | }
81 | else {
82 | if (r > 127 && r < 2048) {
83 | t += String.fromCharCode(r >> 6 | 192);
84 | }
85 | else {
86 | t += String.fromCharCode(r >> 12 | 224);
87 | t += String.fromCharCode(r >> 6 & 63 | 128);
88 | }
89 | t += String.fromCharCode(63 & r | 128);
90 | }
91 | }
92 | return t;
93 | }
94 | function sha256(e) {
95 | var a0 = fun1(fun2(e = (fun3(e))), 8 * e.length);
96 | return fun0(a0);
97 | }
98 | exports.sha256 = sha256;
99 |
--------------------------------------------------------------------------------
/nodes/utils/classDoorbellCapabilities.js:
--------------------------------------------------------------------------------
1 | // Declaration
2 | module.exports = class classDoorbellCapabilities {
3 | /**
4 | * @param {string} [_model]
5 | * @param {string} [_firmwareVersion]
6 | * @param {number} [_port]
7 | */
8 | constructor(_model, _firmwareVersion, _port) {
9 | this.model = _model;
10 | this.firmwareVersion = _firmwareVersion;
11 | this.port = _port;
12 | }
13 | }
14 | // 13/01/2023 Gather infos
15 | RED.httpAdmin.get("/hikvisionUltimateGetInfoDoorBell", RED.auth.needsPermission('Doorbellconfig.read'), async function (req, res) {
16 | let _nodeServer = RED.nodes.getNode(req.query.nodeID);// Retrieve node.id of the config node.
17 | if (_nodeServer === null) _nodeServer = { server: RED.nodes.getNode(node.id) };
18 | // Setting default params
19 | let jParams = {
20 | protocol: _nodeServer.server.protocol,
21 | host: _nodeServer.server.host.includes(":") ? _nodeServer.server.host.split(":")[0] : _nodeServer.server.host,
22 | port: _nodeServer.server.port,
23 | user: _nodeServer.server.credentials.user,
24 | password: _nodeServer.server.credentials.password,
25 | authentication: _nodeServer.server.authentication
26 | };
27 | var clientInfo;
28 | if (req.query.hasOwnProperty("params")) {
29 | jParams = JSON.parse(decodeURIComponent(req.query.params));// Retrieve node.id of the config node.
30 | if (jParams.password === "__PWRD__") {
31 | jParams.password = _nodeServer.server.credentials.password;
32 | }
33 | }
34 |
35 | if (jParams.authentication === "digest") clientInfo = new DigestFetch(jParams.user, jParams.password); // Instantiate the fetch client.
36 | if (jParams.authentication === "basic") clientInfo = new DigestFetch(jParams.user, jParams.password, { basic: true }); // Instantiate the fetch client.
37 | var opt = {
38 | // These properties are part of the Fetch Standard
39 | method: "GET",
40 | headers: {}, // request headers. format is the identical to that accepted by the Headers constructor (see below)
41 | body: null, // request body. can be null, a string, a Buffer, a Blob, or a Node.js Readable stream
42 | redirect: 'follow', // set to `manual` to extract redirect headers, `error` to reject redirect
43 | signal: null, // pass an instance of AbortSignal to optionally abort requests
44 |
45 | // The following properties are node-fetch extensions
46 | follow: 20, // maximum redirect count. 0 to not follow redirect
47 | timeout: 5000, // req/res timeout in ms, it resets on redirect. 0 to disable (OS limit applies). Signal is recommended instead.
48 | compress: false, // support gzip/deflate content encoding. false to disable
49 | size: 0, // maximum response body size in bytes. 0 to disable
50 | agent: jParams.protocol === "https" ? customHttpsAgent : null // http(s).Agent instance or function that returns an instance (see below)
51 | };
52 | try {
53 | let result = {}; // Result to be returned
54 | async function deviceInfo() {
55 | try {
56 | const resInfo = await clientInfo.fetch(jParams.protocol + "://" + jParams.host + ":" + jParams.port + "/ISAPI/System/deviceInfo", opt);
57 | const body = await resInfo.text();
58 | const parser = new XMLParser();
59 | return parser.parse(body).DeviceInfo;
60 |
61 | } catch (error) {
62 | throw error;
63 | }
64 | }
65 | async function callSignal() {
66 | try {
67 | const resInfo = await clientInfo.fetch(jParams.protocol + "://" + jParams.host + ":" + jParams.port + "/ISAPI/VideoIntercom/callSignal/capabilities?format=json", opt);
68 | const body = await resInfo.text();
69 | return JSON.parse(body).CallSignal.cmdType["@opt"];
70 |
71 | } catch (error) {
72 | throw error;
73 | }
74 | }
75 | result.deviceInfo = await deviceInfo();
76 | result.callSignal = await callSignal();
77 |
78 | res.json(result);
79 |
80 |
81 | } catch (err) {
82 | res.json({ error: err.message });
83 | }
84 |
85 |
86 |
87 | });
--------------------------------------------------------------------------------
/nodes/utils/dateManagement.js:
--------------------------------------------------------------------------------
1 | exports.toHikvisionISODateString = function (date) {
2 | var tzo = -date.getTimezoneOffset(),
3 | dif = tzo >= 0 ? '+' : '-',
4 | pad = function (num) {
5 | return (num < 10 ? '0' : '') + num;
6 | };
7 |
8 | return date.getFullYear() +
9 | '-' + pad(date.getMonth() + 1) +
10 | '-' + pad(date.getDate()) +
11 | 'T' + pad(date.getHours()) +
12 | ':' + pad(date.getMinutes()) +
13 | ':' + pad(date.getSeconds()) +
14 | dif + pad(Math.floor(Math.abs(tzo) / 60)) +
15 | ':' + pad(Math.abs(tzo) % 60);
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/nodes/utils/escape-json.js:
--------------------------------------------------------------------------------
1 | /*
2 | Escape JSON
3 | */
4 | var escapeJSON = exports.escapeJSON = function(json) {
5 | var escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
6 | var meta = { // table of character substitutions
7 | '\b': '\\b',
8 | '\t': '\\t',
9 | '\n': '\\n',
10 | '\f': '\\f',
11 | '\r': '\\r',
12 | '"' : '\\"',
13 | '\\': '\\\\'
14 | };
15 |
16 | escapable.lastIndex = 0;
17 | return escapable.test(json) ? '"' + json.replace(escapable, function (a) {
18 | var c = meta[a];
19 | return (typeof c === 'string') ? c
20 | : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
21 | }) + '"' : '"' + json + '"';
22 |
23 | };
--------------------------------------------------------------------------------
/nodes/utils/hikDiscovery.js:
--------------------------------------------------------------------------------
1 | // Search all devicees on the lan
2 | // inquiry
3 | // 239.255.255.250
4 | // Port 37020
5 | // Protocol: UDP
6 | const ipAddress = require('./ipAddressHelper')
7 | const { XMLParser } = require("fast-xml-parser");
8 | const parser = new XMLParser();
9 | var aDevices = new Array(); // Devices to return
10 |
11 |
12 | //Multicast Client receiving sent messages
13 | exports.Discover = async function getAllHikvisionDevicesDescriptors() {
14 | return new Promise(function (resolve, reject) {
15 | const MCAST_PORT = 37020;
16 | const MCAST_ADDR = "239.255.255.250"; //same mcast address as Server
17 | let HOST = ''; //this is your own IP
18 | const discoMSG = 'inquiry';
19 | try {
20 | HOST = ipAddress.getLocalAddress();
21 | } catch (error) {
22 |
23 | }
24 | try {
25 | const dgram = require('dgram');
26 | const client = dgram.createSocket({ type: 'udp4', reuseAddr: true });
27 |
28 | client.on('listening', function () {
29 | let currentAddress = client.address();
30 | //console.log('UDP Client listening on ' + currentAddress.address + ":" + currentAddress.port);
31 | client.setBroadcast(true)
32 | client.setMulticastTTL(128);
33 | client.addMembership(MCAST_ADDR);
34 | });
35 |
36 | client.on('message', function (message, remote) {
37 |
38 | try {
39 |
40 | let jObj = parser.parse(message.toString());
41 | if (jObj.hasOwnProperty("ProbeMatch")) {
42 | if (aDevices.find(a => a.IPv4Address === jObj.ProbeMatch.IPv4Address) === undefined) {
43 | aDevices.push(jObj.ProbeMatch);
44 | }
45 | }
46 |
47 | } catch (error) {
48 | reject([]);
49 | console.log('getAllHikvisionDevicesDescriptors: From: ' + remote.address + ':' + remote.port + ' - ' + error.message);
50 | }
51 |
52 | });
53 |
54 | client.bind(MCAST_PORT);
55 |
56 | // Send query message
57 | setTimeout(() => {
58 | let b = Buffer.from(discoMSG);
59 | client.send(b, 0, b.length, MCAST_PORT, MCAST_ADDR, function () {
60 | //console.log("Sent " + b);
61 | });
62 | }, 10);
63 |
64 | // Set timeout timer
65 | setTimeout(() => {
66 | try {
67 | client.dropMembership(MCAST_ADDR);
68 | client.close();
69 | client.disconnect();
70 | } catch (error) {
71 | }
72 | resolve(aDevices);
73 | }, 2000);
74 | } catch (error) {
75 |
76 | }
77 |
78 | })
79 |
80 | }
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/nodes/utils/ipAddressHelper.js:
--------------------------------------------------------------------------------
1 | // Helper for ipaddresses
2 | const os = require('os')
3 |
4 | // #region "GET LOCAL INTERFACE PROPERTIES"
5 | function getIPv4Interfaces () {
6 | // get the local address of the IPv4 interface we're going to use
7 | const candidateInterfaces = {}
8 | const interfaces = os.networkInterfaces()
9 | for (const iface in interfaces) {
10 | for (const key in interfaces[iface]) {
11 | const intf = interfaces[iface][key]
12 | // 11/05/2022 Fixed a breaking change introduced by node 18 (https://nodejs.org/api/os.html#osnetworkinterfaces)
13 | // In Node < 18, intf.family is a string "IPv4" or "IPv6", from node 18, is an integer, for example 4.
14 | try {
15 | //// knxLog.get().debug('ipAddressHelper.js: parsing interface: %s (%j)', iface, intf)
16 | if (intf.family !== undefined && intf.family.toString().includes('4') && !intf.internal) {
17 | //// knxLog.get().trace('ipAddressHelper.js: Found suitable interface: %s (%j)', iface, intf)
18 | candidateInterfaces[iface] = intf
19 | } else {
20 | //// knxLog.get().trace('ipAddressHelper.js: Found NOT suitable interface: %s (%j)', iface, intf)
21 | }
22 | } catch (error) {
23 | //// knxLog.get().error('ipAddressHelper.js: getIPv4Interfaces: error parsing the interface %s (%j)', iface, intf)
24 | }
25 | }
26 | }
27 |
28 | return candidateInterfaces
29 | }
30 |
31 | exports.getLocalAddress = function (_interface = '') {
32 | // knxLog.get().trace('ipAddressHelper.js: getLocalAddress: getting interfaces')
33 | const candidateInterfaces = getIPv4Interfaces()
34 | // if user has declared a desired interface then use it
35 | if (_interface !== '') {
36 | if (!candidateInterfaces.hasOwnProperty(_interface)) {
37 | // knxLog.get().error('ipAddressHelper.js: exports.getLocalAddress: Interface ' + _interface + ' not found or has no useful IPv4 address!')
38 | throw Error('Interface ' + _interface + ' not found or has no useful IPv4 address!')
39 | } else {
40 | return candidateInterfaces[_interface].address
41 | }
42 | }
43 |
44 | // just return the first available IPv4 non-loopback interface
45 | if (Object.keys(candidateInterfaces).length > 0) {
46 | return candidateInterfaces[Object.keys(candidateInterfaces)[0]].address
47 | }
48 | // no local IpV4 interfaces?
49 | throw Error('No valid IPv4 interfaces detected')
50 | }
51 | // #endregion
52 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "node-red-contrib-hikvision-ultimate",
3 | "version": "1.2.10",
4 | "description": "A native set of nodes for Hikvision (and compatible) Cameras, Alarms, Radars, NVR, Doorbells, etc.",
5 | "author": "Supergiovane (https://github.com/Supergiovane)",
6 | "dependencies": {
7 | "node-fetch": "2.6.7",
8 | "digest-fetch": "2.0.1",
9 | "jimp": "0.22.10",
10 | "lodash": "4.17.21",
11 | "fast-xml-parser": "4.0.13",
12 | "dicer": "0.3.1"
13 | },
14 | "keywords": [
15 | "node-red",
16 | "hikvision",
17 | "alarm",
18 | "camera",
19 | "radar",
20 | "ANPR",
21 | "license plate",
22 | "doorbell",
23 | "door intercom",
24 | "access control terminal",
25 | "Ax Pro"
26 | ],
27 | "engines": {
28 | "node": ">=16.0.0"
29 | },
30 | "license": "MIT",
31 | "repository": {
32 | "type": "git",
33 | "url": "https://github.com/Supergiovane/node-red-contrib-hikvision-ultimate"
34 | },
35 | "node-red": {
36 | "nodes": {
37 | "Hikvision-config": "nodes/Hikvision-config.js",
38 | "AXPro-config": "nodes/AXPro-config.js",
39 | "Doorbell-config": "nodes/Doorbell-config.js",
40 | "ANPR-config": "nodes/ANPR-config.js",
41 | "Speaker-config": "nodes/Speaker-config.js",
42 | "AccessControl-config": "nodes/AccessControl-config.js",
43 | "hikvisionUltimateText": "nodes/hikvisionUltimateText.js",
44 | "hikvisionUltimateAlarm": "nodes/hikvisionUltimateAlarm.js",
45 | "hikvisionUltimateAlarmRaw": "nodes/hikvisionUltimateAlarmRaw.js",
46 | "hikvisionUltimateANPR": "nodes/hikvisionUltimateANPR.js",
47 | "hikvisionUltimatePTZ": "nodes/hikvisionUltimatePTZ.js",
48 | "hikvisionUltimatePicture": "nodes/hikvisionUltimatePicture.js",
49 | "hikvisionUltimateXML": "nodes/hikvisionUltimateXML.js",
50 | "hikvisionUltimateDoorbell": "nodes/hikvisionUltimateDoorbell.js",
51 | "hikvisionUltimateAxPro": "nodes/hikvisionUltimateAxPro.js",
52 | "hikvisionUltimateAccessControlTerminal": "nodes/hikvisionUltimateAccessControlTerminal.js",
53 | "hikvisionUltimateSpeaker": "nodes/hikvisionUltimateSpeaker.js"
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------