node-red-contrib-hik-media-buffer 1.2.6 → 1.2.7
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-download.js +52 -25
- package/package.json +1 -1
package/hik-download.js
CHANGED
|
@@ -62,23 +62,43 @@ module.exports = function(RED) {
|
|
|
62
62
|
return;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
//
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
d
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
65
|
+
// 🌟 1. FORMATTAZIONE DELLE DATE IN BASE ALLA PORTA (Bivio Logico)
|
|
66
|
+
let startTimeNVR, endTimeNVR, playbackURIGrezzo, payloadDownload;
|
|
67
|
+
|
|
68
|
+
const isPort85 = (port.toString() === "85");
|
|
69
|
+
|
|
70
|
+
if (isPort85) {
|
|
71
|
+
// Formato specifico DVR Porta 85: AAAA-MM-GGTHH:MM:SS (Senza Z, con trattini e due punti)
|
|
72
|
+
const formattaDataDVR = (dataStr) => {
|
|
73
|
+
let d = dataStr.replace(' ', 'T').split('.')[0].replace('Z', '');
|
|
74
|
+
if (d.includes('T') && d.split('T')[1].length === 5) {
|
|
75
|
+
d += ':00';
|
|
76
|
+
}
|
|
77
|
+
return d;
|
|
78
|
+
};
|
|
79
|
+
startTimeNVR = formattaDataDVR(startTimeRaw);
|
|
80
|
+
endTimeNVR = formattaDataDVR(endTimeRaw);
|
|
81
|
+
|
|
82
|
+
// RTSP con porta e XML senza namespace
|
|
83
|
+
const trackId = targetChannels[0] + "01"; // Default temporaneo per comporre l'URI prima del ciclo
|
|
84
|
+
playbackURIGrezzo = `rtsp://${host}:${port}/Streaming/tracks/TRACK_PLACEHOLDER/?starttime=${startTimeNVR}&endtime=${endTimeNVR}`;
|
|
85
|
+
} else {
|
|
86
|
+
// Formato classico NVR (Senza trattini e senza due punti)
|
|
87
|
+
const pulisciDataNVR = (dataStr) => {
|
|
88
|
+
let d = dataStr.replace(' ', 'T').replace(/[-:]/g, '').split('.')[0].replace('Z', '');
|
|
89
|
+
if (d.includes('T') && d.split('T')[1].length === 4) {
|
|
90
|
+
d += '00';
|
|
91
|
+
}
|
|
92
|
+
return d;
|
|
93
|
+
};
|
|
94
|
+
startTimeNVR = pulisciDataNVR(startTimeRaw);
|
|
95
|
+
endTimeNVR = pulisciDataNVR(endTimeRaw);
|
|
77
96
|
|
|
78
|
-
|
|
79
|
-
|
|
97
|
+
// RTSP senza porta
|
|
98
|
+
playbackURIGrezzo = `rtsp://${host}/Streaming/tracks/TRACK_PLACEHOLDER/?starttime=${startTimeNVR}&endtime=${endTimeNVR}`;
|
|
99
|
+
}
|
|
80
100
|
|
|
81
|
-
// Creazione cartella C:\download\YYYY-MM-DD
|
|
101
|
+
// Creazione cartella di salvataggio C:\download\YYYY-MM-DD
|
|
82
102
|
const dataGiorno = startTimeRaw.substring(0, 10).replace(/\//g, '-');
|
|
83
103
|
const baseDir = "C:\\download";
|
|
84
104
|
const targetDir = path.join(baseDir, dataGiorno);
|
|
@@ -95,6 +115,7 @@ module.exports = function(RED) {
|
|
|
95
115
|
|
|
96
116
|
const digest = new DigestAuthClass({ username: user, password: pass });
|
|
97
117
|
|
|
118
|
+
// 🌟 2. CICLO DI DOWNLOAD
|
|
98
119
|
for (let index = 0; index < targetChannels.length; index++) {
|
|
99
120
|
const ch = targetChannels[index];
|
|
100
121
|
const trackId = ch + "01";
|
|
@@ -105,17 +126,24 @@ module.exports = function(RED) {
|
|
|
105
126
|
text: `Download Ch ${ch} (${index + 1}/${targetChannels.length})...`
|
|
106
127
|
});
|
|
107
128
|
|
|
108
|
-
//
|
|
109
|
-
const
|
|
110
|
-
const playbackURIXml =
|
|
129
|
+
// Sostituiamo il placeholder con la traccia corrente del ciclo
|
|
130
|
+
const uriCorrente = playbackURIGrezzo.replace('TRACK_PLACEHOLDER', trackId);
|
|
131
|
+
const playbackURIXml = uriCorrente.replace(/&/g, '&');
|
|
111
132
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
133
|
+
// Costruiamo l'XML a seconda del tipo di macchina
|
|
134
|
+
if (isPort85) {
|
|
135
|
+
payloadDownload = `<?xml version="1.0" encoding="UTF-8"?>
|
|
136
|
+
<downloadRequest>
|
|
137
|
+
<playbackURI>${playbackURIXml}</playbackURI>
|
|
138
|
+
</downloadRequest>`;
|
|
139
|
+
} else {
|
|
140
|
+
payloadDownload = `<?xml version="1.0" encoding="UTF-8"?>
|
|
141
|
+
<downloadRequest version="1.0" xmlns="http://www.isapi.org/ver20/XMLSchema">
|
|
142
|
+
<playbackURI>${playbackURIXml}</playbackURI>
|
|
143
|
+
</downloadRequest>`;
|
|
144
|
+
}
|
|
116
145
|
|
|
117
146
|
try {
|
|
118
|
-
// 🌟 2. GET DI DOWNLOAD CON PAYLOAD XML E RESPONSE 'STREAM'
|
|
119
147
|
const response = await digest.request({
|
|
120
148
|
method: 'GET',
|
|
121
149
|
url: `${protocol}://${host}:${port}/ISAPI/ContentMgmt/download`,
|
|
@@ -130,10 +158,9 @@ module.exports = function(RED) {
|
|
|
130
158
|
if (response.status === 200 || response.status === 206) {
|
|
131
159
|
const nomeCondominio = (msg.nvr_name || node.name || 'NVR').replace(/[^a-zA-Z0-9]/g, '_');
|
|
132
160
|
const oraInizio = startTimeNVR.split('T')[1] || startTimeNVR;
|
|
133
|
-
const finalFileName = `${nomeCondominio}_Cam${ch}_${oraInizio}.mp4`;
|
|
161
|
+
const finalFileName = `${nomeCondominio}_Cam${ch}_${oraInizio.replace(/:/g, '')}.mp4`;
|
|
134
162
|
const finalFilePath = path.join(targetDir, finalFileName);
|
|
135
163
|
|
|
136
|
-
// 🌟 3. SALVATAGGIO TRAMITE STREAM (Ottimizzato per file grandi)
|
|
137
164
|
const writer = fs.createWriteStream(finalFilePath);
|
|
138
165
|
response.data.pipe(writer);
|
|
139
166
|
|