node-red-contrib-hik-media-buffer 1.1.116 → 1.1.117

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 +22 -22
  2. package/package.json +1 -1
@@ -112,7 +112,12 @@ module.exports = function(RED) {
112
112
 
113
113
  const heartbeatInterval = setInterval(checkCameras, 30000);
114
114
 
115
- // --- DOWNLOAD CON URL E BODY SECONDO SPECIFICHE ---
115
+ // --- FORMATTATORE PER IL BODY DI RICERCA (Con i trattini: 2026-07-07T17:24:00Z) ---
116
+ function toHikSearchDate(d) {
117
+ return d.toISOString().split('.')[0] + "Z";
118
+ }
119
+
120
+ // --- DOWNLOAD CON ORARIO DINAMICO STRETTO SULL'ULTIMO EVENTO ---
116
121
  async function downloadMedia(evento, channelID) {
117
122
  const nowTime = Date.now();
118
123
  if (!lastTriggerTime[channelID]) lastTriggerTime[channelID] = 0;
@@ -124,13 +129,15 @@ module.exports = function(RED) {
124
129
  const timestamp = Math.floor(referenceTime.getTime() / 1000);
125
130
 
126
131
  const videoTrackID = (parseInt(channelID) * 100) + 1;
127
-
128
- // Recupera il nome reale prima di inviare l'allarme
129
132
  const nomeCamera = await getCameraNameFromNVR(channelID);
130
133
  node.status({fill:"yellow", shape:"dot", text:`Download Cam ${channelID}...`});
131
134
 
132
- const startSearchStr = referenceTime.toISOString().split('T')[0] + "T00:00:00 01:00";
133
- const endSearchStr = referenceTime.toISOString().split('T')[0] + "T23:59:59 01:00";
135
+ // FINESTRA TEMPORALE REALE: Cerchiamo l'evento da 2 minuti fa a 1 minuto nel futuro
136
+ const inizioFinestra = new Date(referenceTime.getTime() - (2 * 60 * 1000));
137
+ const fineFinestra = new Date(referenceTime.getTime() + (1 * 60 * 1000));
138
+
139
+ const startSearchStr = toHikSearchDate(inizioFinestra);
140
+ const endSearchStr = toHikSearchDate(fineFinestra);
134
141
 
135
142
  let output = {
136
143
  tipo_messaggio: "evento",
@@ -148,16 +155,13 @@ module.exports = function(RED) {
148
155
  let fileDaCancellare = [];
149
156
 
150
157
  try {
151
- // 1. SCARICAMENTO IMMAGINE
158
+ // 1. 📸 RICERCA E SCARICAMENTO IMMAGINE (Formato con i trattini nel body)
152
159
  const payloadFoto = {
153
160
  "EventSearchDescription": {
154
161
  "searchID": "C5AFEE35-B1E0-4C01-83F8-47FD77892E4A",
155
162
  "searchResultPosition": 0,
156
- "maxResults": 30,
157
- "timeSpanList": [{
158
- "startTime": startSearchStr,
159
- "endTime": endSearchStr
160
- }],
163
+ "maxResults": 1, // Prendiamo solo il più vicino all'evento attuale
164
+ "timeSpanList": [{ "startTime": startSearchStr, "endTime": endSearchStr }],
161
165
  "type": "all",
162
166
  "channels": [parseInt(channelID)],
163
167
  "eventType": "behavior",
@@ -189,21 +193,18 @@ module.exports = function(RED) {
189
193
  fileDaCancellare.push(fullImgPath);
190
194
  }
191
195
 
192
- // 2. SCARICAMENTO VIDEO
193
- const startVideoSearch = referenceTime.toISOString().split('T')[0] + "T00:00:00Z";
194
- const endVideoSearch = referenceTime.toISOString().split('T')[0] + "T23:59:59Z";
195
-
196
+ // 2. 🎥 RICERCA E SCARICAMENTO VIDEO (Formato con i trattini nel body)
196
197
  const payloadVideoSearch = `<?xml version="1.0" encoding="utf-8"?>
197
198
  <CMSearchDescription>
198
199
  <searchID>CEC13F0F-1AEA-4474-A2DA-CFFF332C7C5B</searchID>
199
200
  <trackList><trackID>${videoTrackID}</trackID></trackList>
200
201
  <timeSpanList>
201
202
  <timeSpan>
202
- <startTime>${startVideoSearch}</startTime>
203
- <endTime>${endVideoSearch}</endTime>
203
+ <startTime>${startSearchStr}</startTime>
204
+ <endTime>${endSearchStr}</endTime>
204
205
  </timeSpan>
205
206
  </timeSpanList>
206
- <maxResults>100</maxResults>
207
+ <maxResults>1</maxResults>
207
208
  <searchResultPostion>0</searchResultPostion>
208
209
  <metadataList><metadataDescriptor>//recordType.meta.std-cgi.com</metadataDescriptor></metadataList>
209
210
  </CMSearchDescription>`;
@@ -220,8 +221,10 @@ module.exports = function(RED) {
220
221
  const uriMatch = xmlString.match(/<playbackURI>([\s\S]*?)<\/playbackURI>/i);
221
222
 
222
223
  if (uriMatch && uriMatch[1]) {
224
+ // Estrae il playbackURI grezzo che contiene GIÀ la data compressa senza trattini generata dall'NVR
223
225
  const playbackURIGrezzo = uriMatch[1].trim();
224
226
 
227
+ // Inviamo il downloadRequest passando l'URI nativo fornito dall'NVR (che rispetta il formato compresso)
225
228
  const payloadDownload = `<?xml version="1.0" encoding="UTF-8"?>
226
229
  <downloadRequest>
227
230
  <playbackURI>${playbackURIGrezzo}</playbackURI>
@@ -259,12 +262,9 @@ module.exports = function(RED) {
259
262
 
260
263
  if (output.foto_base64 || output.video_base64) {
261
264
  node.send({ payload: output });
262
-
263
265
  setTimeout(() => {
264
266
  for (let file of fileDaCancellare) {
265
- try {
266
- if (fs.existsSync(file)) fs.unlinkSync(file);
267
- } catch (err) {}
267
+ try { if (fs.existsSync(file)) fs.unlinkSync(file); } catch (err) {}
268
268
  }
269
269
  }, 120000);
270
270
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-hik-media-buffer",
3
- "version": "1.1.116",
3
+ "version": "1.1.117",
4
4
  "description": "Ottiene buffer video e immagine da camere Hikvision via ISAPI",
5
5
  "keywords": [
6
6
  "node-red",