node-red-contrib-hik-media-buffer 1.1.43 → 1.1.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/hik-media-buffer.js +18 -12
- package/package.json +1 -1
package/hik-media-buffer.js
CHANGED
|
@@ -65,7 +65,7 @@ module.exports = function(RED) {
|
|
|
65
65
|
const nvrAuth = new AxiosDigestAuth({ username: node.user, password: node.pass });
|
|
66
66
|
|
|
67
67
|
try {
|
|
68
|
-
// Interroghiamo l'NVR sullo stato globale dei suoi canali proxy
|
|
68
|
+
// Interroghiamo l'NVR sullo stato globale dei suoi canali proxy
|
|
69
69
|
const res = await nvrAuth.request({
|
|
70
70
|
method: 'GET',
|
|
71
71
|
url: `${node.protocol}://${node.host}:${node.port}/ISAPI/ContentMgmt/InputProxy/channels/status`,
|
|
@@ -85,7 +85,7 @@ module.exports = function(RED) {
|
|
|
85
85
|
|
|
86
86
|
// Estraiamo l'ID del canale e il suo stato dal blocco attuale
|
|
87
87
|
const idMatch = bloccoContenuto.match(/<id>(\d+)<\/id>/i);
|
|
88
|
-
const statusMatch = bloccoContenuto.match(/<status>([^<]+)
|
|
88
|
+
const statusMatch = bloccoContenuto.match(/<status>([^<]+)</i); // Corretta regex di chiusura tag
|
|
89
89
|
|
|
90
90
|
if (idMatch && statusMatch) {
|
|
91
91
|
const ch = idMatch[1];
|
|
@@ -102,7 +102,7 @@ module.exports = function(RED) {
|
|
|
102
102
|
node.send({ payload: { tipo_messaggio: "status", stato_telecamera: "offline", nome_cliente: node.name, nome_telecamera: `Canale_${ch}`, ip_nvr: node.host, channel: ch.toString(), msg: "Camera scollegata o offline su NVR" } });
|
|
103
103
|
statoCanale[ch] = false;
|
|
104
104
|
} else if (statoCanale[ch] === undefined) {
|
|
105
|
-
// Primo avvio: memorizziamo lo stato iniziale
|
|
105
|
+
// Primo avvio: memorizziamo lo stato iniziale
|
|
106
106
|
statoCanale[ch] = isOnline;
|
|
107
107
|
}
|
|
108
108
|
}
|
|
@@ -124,7 +124,6 @@ module.exports = function(RED) {
|
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
// Il controllo camere gira in background ogni 30 secondi interrogando solo l'NVR
|
|
128
127
|
const heartbeatInterval = setInterval(checkCameras, 30000);
|
|
129
128
|
|
|
130
129
|
// --- DOWNLOAD, SALVATAGGIO, CONVERSIONE E RIMOZIONE DALL'NVR ---
|
|
@@ -137,12 +136,13 @@ module.exports = function(RED) {
|
|
|
137
136
|
const nvrAuth = new AxiosDigestAuth({ username: node.user, password: node.pass });
|
|
138
137
|
const referenceTime = new Date();
|
|
139
138
|
const timestamp = Math.floor(referenceTime.getTime() / 1000);
|
|
140
|
-
const startTime = toHikDate(new Date(referenceTime.getTime() - (
|
|
141
|
-
const endTime = toHikDate(new Date(referenceTime.getTime() + (
|
|
139
|
+
const startTime = toHikDate(new Date(referenceTime.getTime() - (15 * 1000))); // Allargato a 15s per sicurezza
|
|
140
|
+
const endTime = toHikDate(new Date(referenceTime.getTime() + (15 * 1000)));
|
|
142
141
|
|
|
143
142
|
node.status({fill:"yellow", shape:"dot", text:`Download Cam ${channelID}...`});
|
|
144
143
|
const nomeCamera = await getCameraName(channelID);
|
|
145
144
|
|
|
145
|
+
// Ritardo tecnico per dare tempo all'NVR di chiudere e indicizzare il file su HDD
|
|
146
146
|
await new Promise(resolve => setTimeout(resolve, 6000));
|
|
147
147
|
const baseUrl = `${node.protocol}://${node.host}:${node.port}/ISAPI/ContentMgmt`;
|
|
148
148
|
|
|
@@ -161,14 +161,14 @@ module.exports = function(RED) {
|
|
|
161
161
|
|
|
162
162
|
let fileDaCancellare = [];
|
|
163
163
|
const parsedChannel = parseInt(channelID, 10);
|
|
164
|
-
const trackVideo = (parsedChannel * 100) + 1; // Formula dinamica NVR (*100+1)
|
|
165
|
-
const trackFoto = (parsedChannel * 100) + 3; // Formula dinamica NVR (*100+3)
|
|
164
|
+
const trackVideo = (parsedChannel * 100) + 1; // Formula dinamica NVR (*100+1) e.g. 201
|
|
165
|
+
const trackFoto = (parsedChannel * 100) + 3; // Formula dinamica NVR (*100+3) e.g. 203
|
|
166
166
|
|
|
167
167
|
const tracks = [{ id: trackVideo.toString(), type: "video" }, { id: trackFoto.toString(), type: "foto" }];
|
|
168
168
|
|
|
169
169
|
try {
|
|
170
170
|
for (let t of tracks) {
|
|
171
|
-
const searchXml = `<?xml version="1.0" encoding="utf-8"?><CMSearchDescription><searchID>
|
|
171
|
+
const searchXml = `<?xml version="1.0" encoding="utf-8"?><CMSearchDescription><searchID>NVR_CATCH</searchID><trackIDList><trackID>${t.id}</trackID></trackIDList><timeSpanList><timeSpan><startTime>${startTime}</startTime><endTime>${endTime}</endTime></timeSpan></timeSpanList><maxResults>100</maxResults><metadataList><metadataDescriptor>//recordType.meta.std-cgi.com/${output.tipo_evento}</metadataDescriptor></metadataList></CMSearchDescription>`;
|
|
172
172
|
|
|
173
173
|
const resSearch = await nvrAuth.request({
|
|
174
174
|
method: 'POST', url: `${baseUrl}/search`, data: searchXml, headers: { "Content-Type": "application/xml" }
|
|
@@ -179,7 +179,7 @@ module.exports = function(RED) {
|
|
|
179
179
|
|
|
180
180
|
if (uriMatch) {
|
|
181
181
|
const rawUri = uriMatch[1].replace(/&/g, '&');
|
|
182
|
-
const resDown = await
|
|
182
|
+
const resDown = await nvrAuth.request({
|
|
183
183
|
method: 'GET',
|
|
184
184
|
url: `${baseUrl}/download`,
|
|
185
185
|
data: `<?xml version="1.0" encoding="UTF-8"?><downloadRequest><playbackURI>${rawUri.replace(/&/g, '&')}</playbackURI></downloadRequest>`,
|
|
@@ -225,7 +225,7 @@ module.exports = function(RED) {
|
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
} catch (e) {
|
|
228
|
-
node.error(`Errore Download
|
|
228
|
+
node.error(`Errore Download NVR per Canale ${channelID}: ${e.message}`);
|
|
229
229
|
}
|
|
230
230
|
node.status({fill:"green", shape:"ring", text:"In ascolto"});
|
|
231
231
|
}
|
|
@@ -248,14 +248,20 @@ module.exports = function(RED) {
|
|
|
248
248
|
if (data.includes("active")) {
|
|
249
249
|
const chMatch = data.match(/<channelid>(\d+)<\/channelid>/i);
|
|
250
250
|
if (chMatch) {
|
|
251
|
+
let channelID = chMatch[1];
|
|
251
252
|
let ev = "Unknown";
|
|
253
|
+
|
|
252
254
|
for (let e of EventList) {
|
|
253
255
|
if (data.includes(e.toLowerCase())) {
|
|
254
256
|
ev = e;
|
|
255
257
|
break;
|
|
256
258
|
}
|
|
257
259
|
}
|
|
258
|
-
|
|
260
|
+
|
|
261
|
+
// Se non è un allarme presente in lista o è un heartbeat, fermati qui
|
|
262
|
+
if (ev === "Unknown") return;
|
|
263
|
+
|
|
264
|
+
downloadMedia(ev, channelID);
|
|
259
265
|
}
|
|
260
266
|
}
|
|
261
267
|
});
|