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.
Files changed (2) hide show
  1. package/hik-media-buffer.js +18 -12
  2. package/package.json +1 -1
@@ -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 [ps. 57-58 del manuale]
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>([^<]+)<\/status>/i);
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 senza inviare messaggi di stato a vuoto
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() - (10 * 1000)));
141
- const endTime = toHikDate(new Date(referenceTime.getTime() + (10 * 1000)));
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) [cite: 958]
165
- const trackFoto = (parsedChannel * 100) + 3; // Formula dinamica NVR (*100+3) [cite: 958]
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>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>`;
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(/&amp;/g, '&');
182
- const resDown = await camAuth.request({
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, '&amp;')}</playbackURI></downloadRequest>`,
@@ -225,7 +225,7 @@ module.exports = function(RED) {
225
225
  }
226
226
 
227
227
  } catch (e) {
228
- node.error(`Errore Download Cam ${channelID}: ${e.message}`);
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
- downloadMedia(ev, chMatch[1]);
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
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-hik-media-buffer",
3
- "version": "1.1.43",
3
+ "version": "1.1.44",
4
4
  "description": "Ottiene buffer video e immagine da camere Hikvision via ISAPI",
5
5
  "keywords": [
6
6
  "node-red",