node-red-contrib-hik-media-buffer 1.1.43 → 1.1.45
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 +17 -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,15 +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
171
|
const searchXml = `<?xml version="1.0" encoding="utf-8"?><CMSearchDescription><searchID>LAST_EVENT</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/${evento}</metadataDescriptor></metadataList></CMSearchDescription>`;
|
|
172
|
-
|
|
173
172
|
const resSearch = await nvrAuth.request({
|
|
174
173
|
method: 'POST', url: `${baseUrl}/search`, data: searchXml, headers: { "Content-Type": "application/xml" }
|
|
175
174
|
});
|
|
@@ -179,7 +178,7 @@ module.exports = function(RED) {
|
|
|
179
178
|
|
|
180
179
|
if (uriMatch) {
|
|
181
180
|
const rawUri = uriMatch[1].replace(/&/g, '&');
|
|
182
|
-
const resDown = await
|
|
181
|
+
const resDown = await nvrAuth.request({
|
|
183
182
|
method: 'GET',
|
|
184
183
|
url: `${baseUrl}/download`,
|
|
185
184
|
data: `<?xml version="1.0" encoding="UTF-8"?><downloadRequest><playbackURI>${rawUri.replace(/&/g, '&')}</playbackURI></downloadRequest>`,
|
|
@@ -225,7 +224,7 @@ module.exports = function(RED) {
|
|
|
225
224
|
}
|
|
226
225
|
|
|
227
226
|
} catch (e) {
|
|
228
|
-
node.error(`Errore Download
|
|
227
|
+
node.error(`Errore Download NVR per Canale ${channelID}: ${e.message}`);
|
|
229
228
|
}
|
|
230
229
|
node.status({fill:"green", shape:"ring", text:"In ascolto"});
|
|
231
230
|
}
|
|
@@ -248,14 +247,20 @@ module.exports = function(RED) {
|
|
|
248
247
|
if (data.includes("active")) {
|
|
249
248
|
const chMatch = data.match(/<channelid>(\d+)<\/channelid>/i);
|
|
250
249
|
if (chMatch) {
|
|
250
|
+
let channelID = chMatch[1];
|
|
251
251
|
let ev = "Unknown";
|
|
252
|
+
|
|
252
253
|
for (let e of EventList) {
|
|
253
254
|
if (data.includes(e.toLowerCase())) {
|
|
254
255
|
ev = e;
|
|
255
256
|
break;
|
|
256
257
|
}
|
|
257
258
|
}
|
|
258
|
-
|
|
259
|
+
|
|
260
|
+
// Se non è un allarme presente in lista o è un heartbeat, fermati qui
|
|
261
|
+
if (ev === "Unknown") return;
|
|
262
|
+
|
|
263
|
+
downloadMedia(ev, channelID);
|
|
259
264
|
}
|
|
260
265
|
}
|
|
261
266
|
});
|