node-red-contrib-hik-media-buffer 1.1.46 → 1.1.48

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 +27 -18
  2. package/package.json +1 -1
@@ -22,9 +22,7 @@ module.exports = function(RED) {
22
22
  let isClosing = false;
23
23
  let lastTriggerTime = {};
24
24
  let nvrOnline = true;
25
-
26
25
  let statoCanale = {};
27
- let ultimoAllarmeTempo = {};
28
26
 
29
27
  const httpsAgent = new https.Agent({ rejectUnauthorized: false });
30
28
 
@@ -80,7 +78,7 @@ module.exports = function(RED) {
80
78
  while ((matchBlocco = bloccoRegex.exec(xmlData)) !== null) {
81
79
  const bloccoContenuto = matchBlocco[1];
82
80
 
83
- const idMatch = bloccoContenuto.match(/<id>(\d+)<\/id>/i);
81
+ const idMatch = bloccoContenited.match(/<id>(\d+)<\/id>/i);
84
82
  const statusMatch = bloccoContenuto.match(/<status>([^<]+)</i);
85
83
 
86
84
  if (idMatch && statusMatch) {
@@ -120,20 +118,21 @@ module.exports = function(RED) {
120
118
 
121
119
  const heartbeatInterval = setInterval(checkCameras, 30000);
122
120
 
123
- // --- DOWNLOAD MULTIMEDIALE DA NVR CON LOGICA STRUTTURALE ORIGINALE ---
121
+ // --- DOWNLOAD MULTIMEDIALE BASATO SULL'ISPEZIONA REALE DELL'NVR ---
124
122
  async function downloadMedia(evento, channelID) {
125
123
  const nowTime = Date.now();
126
124
  if (!lastTriggerTime[channelID]) lastTriggerTime[channelID] = 0;
127
125
  if (nowTime - lastTriggerTime[channelID] < 5000) return;
128
126
  lastTriggerTime[channelID] = nowTime;
129
127
 
130
- // ISTANZIAMO camAuth SULL'NVR: Risolve il problema delle credenziali vuote nel vecchio blocco
131
128
  const camAuth = new AxiosDigestAuth({ username: node.user, password: node.pass });
132
129
 
133
130
  const referenceTime = new Date();
134
131
  const timestamp = Math.floor(referenceTime.getTime() / 1000);
135
- const startTime = toHikDate(new Date(referenceTime.getTime() - (10 * 1000)));
136
- const endTime = toHikDate(new Date(referenceTime.getTime() + (10 * 1000)));
132
+
133
+ // Finestra temporale basata sulle date ISO
134
+ const startTime = toHikDate(new Date(referenceTime.getTime() - (20 * 1000)));
135
+ const endTime = toHikDate(new Date(referenceTime.getTime() + (20 * 1000)));
137
136
 
138
137
  node.status({fill:"yellow", shape:"dot", text:`Download Cam ${channelID}...`});
139
138
  const nomeCamera = await getCameraName(channelID);
@@ -141,12 +140,21 @@ module.exports = function(RED) {
141
140
  await new Promise(resolve => setTimeout(resolve, 6000));
142
141
  const baseUrl = `${node.protocol}://${node.host}:${node.port}/ISAPI/ContentMgmt`;
143
142
 
143
+ // Ricostruiamo l'evento con il case-sensitive corretto per l'NVR (FieldDetection / LineDetection)
144
+ let eventoNVR = "FieldDetection";
145
+ for (let e of EventList) {
146
+ if (evento.toLowerCase() === e.toLowerCase()) {
147
+ eventoNVR = e;
148
+ break;
149
+ }
150
+ }
151
+
144
152
  let output = {
145
153
  tipo_messaggio: "evento",
146
154
  nome_cliente: node.name,
147
155
  nome_telecamera: nomeCamera,
148
156
  ip_telecamera: node.host,
149
- tipo_evento: evento,
157
+ tipo_evento: eventoNVR,
150
158
  timestamp_epoch: timestamp,
151
159
  stato_telecamera: "ONLINE",
152
160
  channel: channelID.toString(),
@@ -155,16 +163,19 @@ module.exports = function(RED) {
155
163
  };
156
164
 
157
165
  const parsedChannel = parseInt(channelID, 10);
158
- const trackVideo = (parsedChannel * 100) + 1; // Formula NVR (*100+1)
159
- const trackFoto = (parsedChannel * 100) + 3; // Formula NVR (*100+3)
166
+ const trackVideo = (parsedChannel * 100) + 1; // Canale 2 -> 201
167
+ const trackFoto = (parsedChannel * 100) + 3; // Canale 2 -> 203
160
168
 
161
- const tracks = [{ id: trackVideo.toString() }, { id: trackFoto.toString() }];
169
+ const tracks = [
170
+ { id: trackVideo.toString(), isFoto: false },
171
+ { id: trackFoto.toString(), isFoto: true }
172
+ ];
162
173
  let fileDaCancellare = [];
163
174
 
164
175
  try {
165
176
  for (let t of tracks) {
166
- // RIPRISTINATO: Il tuo XML originale esatto con <trackIDList> e ${evento} dinamico
167
- 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>`;
177
+ // COPIATO DALL'ISPEZIONA: Inserito <contentTypeList> e corretto metadataDescriptor proprietario hikvision
178
+ 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><contentTypeList><contentType>metadata</contentType></contentTypeList><maxResults>30</maxResults><metadataList><metadataDescriptor>recordType.meta.hikvision.com/${eventoNVR}</metadataDescriptor></metadataList></CMSearchDescription>`;
168
179
 
169
180
  const resSearch = await camAuth.request({
170
181
  method: 'POST', url: `${baseUrl}/search`, data: searchXml, headers: { "Content-Type": "application/xml" }
@@ -183,8 +194,8 @@ module.exports = function(RED) {
183
194
  });
184
195
 
185
196
  let buffer = Buffer.from(resDown.data);
186
- if (t.id === trackFoto.toString()) {
187
- // SALVA FOTO IN LOCALE
197
+ if (t.isFoto) {
198
+ // SALVA FOTO TERMICA NATIVA IN LOCALE
188
199
  const fullImgPath = path.join(baseStorage, `img_${timestamp}.jpg`);
189
200
  fs.writeFileSync(fullImgPath, buffer);
190
201
  output.foto_base64 = fs.readFileSync(fullImgPath, { encoding: 'base64' });
@@ -245,9 +256,7 @@ module.exports = function(RED) {
245
256
  if (chMatch) {
246
257
  let ev = "Unknown";
247
258
  for (let e of EventList) { if (data.includes(e.toLowerCase())) { ev = e; break; } }
248
-
249
- if (ev === "Unknown") return; // Ignora heartbeat o altri eventi non mappati
250
-
259
+ if (ev === "Unknown") return;
251
260
  downloadMedia(ev, chMatch[1]);
252
261
  }
253
262
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-hik-media-buffer",
3
- "version": "1.1.46",
3
+ "version": "1.1.48",
4
4
  "description": "Ottiene buffer video e immagine da camere Hikvision via ISAPI",
5
5
  "keywords": [
6
6
  "node-red",