@apocaliss92/nodelink-js 0.4.22 → 0.4.23
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/dist/BaichuanVideoStream-NTIGPHYJ.js +7 -0
- package/dist/{DiagnosticsTools-HO3VI6D5.js → DiagnosticsTools-ILDDJZL7.js} +3 -3
- package/dist/{chunk-S2UTGNFN.js → chunk-AHY4L7JI.js} +2 -2
- package/dist/{chunk-C57QV7IL.js → chunk-GVWJGQPT.js} +5 -1
- package/dist/chunk-GVWJGQPT.js.map +1 -0
- package/dist/{chunk-EZ7WNPLB.js → chunk-P4X5OU25.js} +521 -19
- package/dist/chunk-P4X5OU25.js.map +1 -0
- package/dist/cli/rtsp-server.cjs +506 -14
- package/dist/cli/rtsp-server.cjs.map +1 -1
- package/dist/cli/rtsp-server.js +3 -3
- package/dist/index.cjs +534 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +327 -1
- package/dist/index.d.ts +343 -0
- package/dist/index.js +31 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/BaichuanVideoStream-HGPU2MZ3.js +0 -7
- package/dist/chunk-C57QV7IL.js.map +0 -1
- package/dist/chunk-EZ7WNPLB.js.map +0 -1
- /package/dist/{BaichuanVideoStream-HGPU2MZ3.js.map → BaichuanVideoStream-NTIGPHYJ.js.map} +0 -0
- /package/dist/{DiagnosticsTools-HO3VI6D5.js.map → DiagnosticsTools-ILDDJZL7.js.map} +0 -0
- /package/dist/{chunk-S2UTGNFN.js.map → chunk-AHY4L7JI.js.map} +0 -0
package/dist/cli/rtsp-server.cjs
CHANGED
|
@@ -60,7 +60,7 @@ var init_urls = __esm({
|
|
|
60
60
|
function bcHeaderHasPayloadOffset(messageClass) {
|
|
61
61
|
return messageClass === BC_CLASS_MODERN_24 || messageClass === BC_CLASS_MODERN_24_ALT || messageClass === BC_CLASS_FILE_DOWNLOAD;
|
|
62
62
|
}
|
|
63
|
-
var BC_TCP_DEFAULT_PORT, BC_MAGIC, BC_MAGIC_REV, BC_XML_KEY, BC_AES_IV, BC_CLASS_LEGACY, BC_CLASS_MODERN_20, BC_CLASS_MODERN_24, BC_CLASS_MODERN_24_ALT, BC_CLASS_FILE_DOWNLOAD, BC_CMD_ID_LOGOUT, BC_CMD_ID_VIDEO, BC_CMD_ID_VIDEO_STOP, BC_CMD_ID_FILE_INFO_LIST_REPLAY, BC_CMD_ID_FILE_INFO_LIST_STOP, BC_CMD_ID_FILE_INFO_LIST_DL_VIDEO, BC_CMD_ID_FILE_INFO_LIST_DOWNLOAD, BC_CMD_ID_FILE_INFO_LIST_OPEN, BC_CMD_ID_FILE_INFO_LIST_GET, BC_CMD_ID_FILE_INFO_LIST_CLOSE, BC_CMD_ID_FIND_REC_VIDEO_OPEN, BC_CMD_ID_FIND_REC_VIDEO_GET, BC_CMD_ID_FIND_REC_VIDEO_CLOSE, BC_CMD_ID_TALK_ABILITY, BC_CMD_ID_TALK_RESET, BC_CMD_ID_TALK_CONFIG, BC_CMD_ID_TALK, BC_CMD_ID_PTZ_CONTROL, BC_CMD_ID_PTZ_CONTROL_PRESET, BC_CMD_ID_GET_PTZ_PRESET, BC_CMD_ID_GET_PTZ_POSITION, BC_CMD_ID_GET_ZOOM_FOCUS, BC_CMD_ID_SET_ZOOM_FOCUS, BC_CMD_ID_GET_BATTERY_INFO_LIST, BC_CMD_ID_GET_BATTERY_INFO, BC_CMD_ID_UDP_KEEP_ALIVE, BC_CMD_ID_GET_PIR_INFO, BC_CMD_ID_SET_PIR_INFO, BC_CMD_ID_GET_MOTION_ALARM, BC_CMD_ID_SET_MOTION_ALARM, BC_CMD_ID_GET_AI_ALARM, BC_CMD_ID_SET_AI_ALARM, BC_CMD_ID_GET_AUDIO_ALARM, BC_CMD_ID_AUDIO_ALARM_PLAY, BC_CMD_ID_GET_WHITE_LED, BC_CMD_ID_SET_WHITE_LED_STATE, BC_CMD_ID_SET_WHITE_LED_TASK, BC_CMD_ID_FLOODLIGHT_STATUS_LIST, BC_CMD_ID_ABILITY_INFO, BC_CMD_ID_SUPPORT, BC_CMD_ID_PING, BC_CMD_ID_CHANNEL_INFO_ALL, BC_CMD_ID_GET_OSD_DATETIME, BC_CMD_ID_SET_OSD_DATETIME, BC_CMD_ID_GET_RECORD_CFG, BC_CMD_ID_GET_ABILITY_SUPPORT, BC_CMD_ID_GET_FTP_TASK, BC_CMD_ID_GET_VERSION_INFO, BC_CMD_ID_GET_RECORD, BC_CMD_ID_GET_HDD_INFO_LIST, BC_CMD_ID_GET_WIFI_SIGNAL, BC_CMD_ID_GET_WIFI, BC_CMD_ID_GET_ONLINE_USER_LIST, BC_CMD_ID_GET_DAY_RECORDS, BC_CMD_ID_GET_STREAM_INFO_LIST, BC_CMD_ID_GET_LED_STATE, BC_CMD_ID_GET_EMAIL_TASK, BC_CMD_ID_GET_AUDIO_TASK, BC_CMD_ID_GET_AUDIO_CFG, BC_CMD_ID_GET_DAY_NIGHT_THRESHOLD, BC_CMD_ID_GET_TIMELAPSE_CFG, BC_CMD_ID_GET_AI_DENOISE, BC_CMD_ID_GET_KIT_AP_CFG, BC_CMD_ID_GET_REC_ENC_CFG, BC_CMD_ID_GET_ACCESS_USER_LIST, BC_CMD_ID_GET_SLEEP_STATE, BC_CMD_ID_GET_VIDEO_INPUT, BC_CMD_ID_GET_SYSTEM_GENERAL, BC_CMD_ID_GET_SUPPORT, BC_CMD_ID_GET_AI_CFG, BC_CMD_ID_SET_AI_CFG, BC_CMD_ID_GET_SIREN_STATUS, BC_CMD_ID_SET_AUDIO_TASK, BC_CMD_ID_SET_VIDEO_INPUT, BC_CMD_ID_SET_DAY_NIGHT_THRESHOLD, BC_CMD_ID_GET_ENC, BC_CMD_ID_SET_ENC, BC_CMD_ID_GET_PRIVACY_MASK, BC_CMD_ID_SET_PRIVACY_MASK, BC_CMD_ID_SET_AI_DENOISE, BC_CMD_ID_SET_LED_STATE, BC_CMD_ID_SET_AUDIO_CFG, BC_CMD_ID_SET_EMAIL_TASK, BC_CMD_ID_GET_AUTO_FOCUS, BC_CMD_ID_SET_AUTO_FOCUS, BC_CMD_ID_GET_EMAIL, BC_CMD_ID_SET_EMAIL, BC_CMD_ID_TEST_EMAIL, BC_CMD_ID_GET_NTP, BC_CMD_ID_SET_NTP, BC_CMD_ID_SET_SYSTEM_GENERAL, BC_CMD_ID_GET_DST, BC_CMD_ID_SET_DST, BC_CMD_ID_GET_AUTO_REBOOT, BC_CMD_ID_SET_AUTO_REBOOT, BC_CMD_ID_CMD_123, BC_CMD_ID_CMD_209, BC_CMD_ID_CMD_265, BC_CMD_ID_CMD_440, BC_CMD_ID_PUSH_VIDEO_INPUT, BC_CMD_ID_PUSH_SERIAL, BC_CMD_ID_PUSH_NET_INFO, BC_CMD_ID_PUSH_DINGDONG_LIST, BC_CMD_ID_PUSH_SLEEP_STATUS, BC_CMD_ID_PUSH_COORDINATE_POINT_LIST, BC_CMD_ID_DING_DONG_CTRL, BC_CMD_ID_GET_DING_DONG_LIST, BC_CMD_ID_DING_DONG_OPT, BC_CMD_ID_GET_DING_DONG_CFG, BC_CMD_ID_SET_DING_DONG_CFG, BC_CMD_ID_QUICK_REPLY_PLAY, BC_CMD_ID_GET_DING_DONG_SILENT, BC_CMD_ID_SET_DING_DONG_SILENT;
|
|
63
|
+
var BC_TCP_DEFAULT_PORT, BC_MAGIC, BC_MAGIC_REV, BC_XML_KEY, BC_AES_IV, BC_CLASS_LEGACY, BC_CLASS_MODERN_20, BC_CLASS_MODERN_24, BC_CLASS_MODERN_24_ALT, BC_CLASS_FILE_DOWNLOAD, BC_CMD_ID_LOGOUT, BC_CMD_ID_VIDEO, BC_CMD_ID_VIDEO_STOP, BC_CMD_ID_FILE_INFO_LIST_REPLAY, BC_CMD_ID_FILE_INFO_LIST_STOP, BC_CMD_ID_FILE_INFO_LIST_DL_VIDEO, BC_CMD_ID_FILE_INFO_LIST_DOWNLOAD, BC_CMD_ID_FILE_INFO_LIST_OPEN, BC_CMD_ID_FILE_INFO_LIST_GET, BC_CMD_ID_FILE_INFO_LIST_CLOSE, BC_CMD_ID_FIND_REC_VIDEO_OPEN, BC_CMD_ID_FIND_REC_VIDEO_GET, BC_CMD_ID_FIND_REC_VIDEO_CLOSE, BC_CMD_ID_TALK_ABILITY, BC_CMD_ID_TALK_RESET, BC_CMD_ID_TALK_CONFIG, BC_CMD_ID_TALK, BC_CMD_ID_PTZ_CONTROL, BC_CMD_ID_PTZ_CONTROL_PRESET, BC_CMD_ID_GET_PTZ_PRESET, BC_CMD_ID_GET_PTZ_POSITION, BC_CMD_ID_GET_ZOOM_FOCUS, BC_CMD_ID_SET_ZOOM_FOCUS, BC_CMD_ID_GET_BATTERY_INFO_LIST, BC_CMD_ID_GET_BATTERY_INFO, BC_CMD_ID_UDP_KEEP_ALIVE, BC_CMD_ID_GET_PIR_INFO, BC_CMD_ID_SET_PIR_INFO, BC_CMD_ID_GET_MOTION_ALARM, BC_CMD_ID_SET_MOTION_ALARM, BC_CMD_ID_GET_AI_ALARM, BC_CMD_ID_SET_AI_ALARM, BC_CMD_ID_GET_AUDIO_ALARM, BC_CMD_ID_AUDIO_ALARM_PLAY, BC_CMD_ID_GET_WHITE_LED, BC_CMD_ID_SET_WHITE_LED_STATE, BC_CMD_ID_SET_WHITE_LED_TASK, BC_CMD_ID_FLOODLIGHT_STATUS_LIST, BC_CMD_ID_ABILITY_INFO, BC_CMD_ID_SUPPORT, BC_CMD_ID_PING, BC_CMD_ID_GET_SNAPSHOT, BC_CMD_ID_GET_UID, BC_CMD_ID_CHANNEL_INFO_ALL, BC_CMD_ID_GET_OSD_DATETIME, BC_CMD_ID_SET_OSD_DATETIME, BC_CMD_ID_GET_RECORD_CFG, BC_CMD_ID_GET_ABILITY_SUPPORT, BC_CMD_ID_GET_FTP_TASK, BC_CMD_ID_GET_VERSION_INFO, BC_CMD_ID_GET_RECORD, BC_CMD_ID_GET_HDD_INFO_LIST, BC_CMD_ID_GET_WIFI_SIGNAL, BC_CMD_ID_GET_WIFI, BC_CMD_ID_GET_ONLINE_USER_LIST, BC_CMD_ID_GET_DAY_RECORDS, BC_CMD_ID_GET_STREAM_INFO_LIST, BC_CMD_ID_GET_LED_STATE, BC_CMD_ID_GET_EMAIL_TASK, BC_CMD_ID_GET_AUDIO_TASK, BC_CMD_ID_GET_AUDIO_CFG, BC_CMD_ID_GET_DAY_NIGHT_THRESHOLD, BC_CMD_ID_GET_TIMELAPSE_CFG, BC_CMD_ID_GET_AI_DENOISE, BC_CMD_ID_GET_KIT_AP_CFG, BC_CMD_ID_GET_REC_ENC_CFG, BC_CMD_ID_GET_ACCESS_USER_LIST, BC_CMD_ID_GET_SLEEP_STATE, BC_CMD_ID_GET_VIDEO_INPUT, BC_CMD_ID_GET_SYSTEM_GENERAL, BC_CMD_ID_GET_SUPPORT, BC_CMD_ID_GET_AI_CFG, BC_CMD_ID_SET_AI_CFG, BC_CMD_ID_GET_SIREN_STATUS, BC_CMD_ID_SET_AUDIO_TASK, BC_CMD_ID_SET_VIDEO_INPUT, BC_CMD_ID_SET_DAY_NIGHT_THRESHOLD, BC_CMD_ID_GET_ENC, BC_CMD_ID_SET_ENC, BC_CMD_ID_GET_PRIVACY_MASK, BC_CMD_ID_SET_PRIVACY_MASK, BC_CMD_ID_SET_AI_DENOISE, BC_CMD_ID_SET_LED_STATE, BC_CMD_ID_SET_AUDIO_CFG, BC_CMD_ID_SET_EMAIL_TASK, BC_CMD_ID_GET_AUTO_FOCUS, BC_CMD_ID_SET_AUTO_FOCUS, BC_CMD_ID_GET_EMAIL, BC_CMD_ID_SET_EMAIL, BC_CMD_ID_TEST_EMAIL, BC_CMD_ID_GET_NTP, BC_CMD_ID_SET_NTP, BC_CMD_ID_SET_SYSTEM_GENERAL, BC_CMD_ID_GET_DST, BC_CMD_ID_SET_DST, BC_CMD_ID_GET_AUTO_REBOOT, BC_CMD_ID_SET_AUTO_REBOOT, BC_CMD_ID_CMD_123, BC_CMD_ID_CMD_209, BC_CMD_ID_CMD_265, BC_CMD_ID_CMD_440, BC_CMD_ID_PUSH_VIDEO_INPUT, BC_CMD_ID_PUSH_SERIAL, BC_CMD_ID_PUSH_NET_INFO, BC_CMD_ID_PUSH_DINGDONG_LIST, BC_CMD_ID_PUSH_SLEEP_STATUS, BC_CMD_ID_PUSH_COORDINATE_POINT_LIST, BC_CMD_ID_DING_DONG_CTRL, BC_CMD_ID_GET_DING_DONG_LIST, BC_CMD_ID_DING_DONG_OPT, BC_CMD_ID_GET_DING_DONG_CFG, BC_CMD_ID_SET_DING_DONG_CFG, BC_CMD_ID_QUICK_REPLY_PLAY, BC_CMD_ID_GET_DING_DONG_SILENT, BC_CMD_ID_SET_DING_DONG_SILENT;
|
|
64
64
|
var init_constants = __esm({
|
|
65
65
|
"src/protocol/constants.ts"() {
|
|
66
66
|
"use strict";
|
|
@@ -124,6 +124,8 @@ var init_constants = __esm({
|
|
|
124
124
|
BC_CMD_ID_ABILITY_INFO = 151;
|
|
125
125
|
BC_CMD_ID_SUPPORT = 199;
|
|
126
126
|
BC_CMD_ID_PING = 93;
|
|
127
|
+
BC_CMD_ID_GET_SNAPSHOT = 109;
|
|
128
|
+
BC_CMD_ID_GET_UID = 114;
|
|
127
129
|
BC_CMD_ID_CHANNEL_INFO_ALL = 145;
|
|
128
130
|
BC_CMD_ID_GET_OSD_DATETIME = 44;
|
|
129
131
|
BC_CMD_ID_SET_OSD_DATETIME = 45;
|
|
@@ -16480,15 +16482,14 @@ var getAiStateViaGetAiAlarm = async (params) => {
|
|
|
16480
16482
|
0
|
|
16481
16483
|
);
|
|
16482
16484
|
};
|
|
16485
|
+
const isSupportedResponse = (xml) => {
|
|
16486
|
+
return /<AiDetectCfg[\s>]/i.test(xml) && getXmlText(xml, "type") != null;
|
|
16487
|
+
};
|
|
16483
16488
|
for (const type of candidateTypes) {
|
|
16484
16489
|
try {
|
|
16485
16490
|
const xml = await tryOnce(type, ch);
|
|
16486
|
-
if (xml) {
|
|
16487
|
-
return {
|
|
16488
|
-
channel: ch,
|
|
16489
|
-
alarm_state: Number(getXmlText(xml, "alarm_state") ?? "0"),
|
|
16490
|
-
support: Number(getXmlText(xml, "support") ?? "0")
|
|
16491
|
-
};
|
|
16491
|
+
if (xml && isSupportedResponse(xml)) {
|
|
16492
|
+
return { channel: ch, alarm_state: 0, support: 1 };
|
|
16492
16493
|
}
|
|
16493
16494
|
} catch (e) {
|
|
16494
16495
|
if (looksLikeConnectionDrop(e)) throw e;
|
|
@@ -16498,12 +16499,8 @@ var getAiStateViaGetAiAlarm = async (params) => {
|
|
|
16498
16499
|
for (const type of candidateTypes) {
|
|
16499
16500
|
try {
|
|
16500
16501
|
const xml = await tryOnce(type, void 0);
|
|
16501
|
-
if (xml) {
|
|
16502
|
-
return {
|
|
16503
|
-
channel: ch,
|
|
16504
|
-
alarm_state: Number(getXmlText(xml, "alarm_state") ?? "0"),
|
|
16505
|
-
support: Number(getXmlText(xml, "support") ?? "0")
|
|
16506
|
-
};
|
|
16502
|
+
if (xml && isSupportedResponse(xml)) {
|
|
16503
|
+
return { channel: ch, alarm_state: 0, support: 1 };
|
|
16507
16504
|
}
|
|
16508
16505
|
} catch (e) {
|
|
16509
16506
|
if (looksLikeConnectionDrop(e)) throw e;
|
|
@@ -17003,6 +17000,354 @@ var calculatePipOverlayPosition = (params) => {
|
|
|
17003
17000
|
};
|
|
17004
17001
|
};
|
|
17005
17002
|
|
|
17003
|
+
// src/reolink/baichuan/utils/privacyMask.ts
|
|
17004
|
+
init_xml();
|
|
17005
|
+
var DEFAULT_SHELTER_CANVAS = {
|
|
17006
|
+
width: 540,
|
|
17007
|
+
height: 304
|
|
17008
|
+
};
|
|
17009
|
+
function decodeShelterCoord(value) {
|
|
17010
|
+
const v = (value | 0) >>> 0;
|
|
17011
|
+
return { pixel: v >>> 16, canvas: v & 65535 };
|
|
17012
|
+
}
|
|
17013
|
+
function encodeShelterCoord(pixel, canvas) {
|
|
17014
|
+
const p = Math.min(65535, Math.max(0, Math.floor(pixel)));
|
|
17015
|
+
const c = Math.min(65535, Math.max(0, Math.floor(canvas)));
|
|
17016
|
+
return p * 65536 + c;
|
|
17017
|
+
}
|
|
17018
|
+
function clamp01(value) {
|
|
17019
|
+
if (!Number.isFinite(value)) return 0;
|
|
17020
|
+
if (value < 0) return 0;
|
|
17021
|
+
if (value > 1) return 1;
|
|
17022
|
+
return value;
|
|
17023
|
+
}
|
|
17024
|
+
function decodeRect(raw, canvas, idKey) {
|
|
17025
|
+
const xRaw = Number(raw["topLeftX"] ?? 0) | 0;
|
|
17026
|
+
const yRaw = Number(raw["topLeftY"] ?? 0) | 0;
|
|
17027
|
+
const wRaw = Number(raw["width"] ?? 0) | 0;
|
|
17028
|
+
const hRaw = Number(raw["height"] ?? 0) | 0;
|
|
17029
|
+
const xPixel = decodeShelterCoord(xRaw).pixel;
|
|
17030
|
+
const yPixel = decodeShelterCoord(yRaw).pixel;
|
|
17031
|
+
const wPixel = decodeShelterCoord(wRaw).pixel;
|
|
17032
|
+
const hPixel = decodeShelterCoord(hRaw).pixel;
|
|
17033
|
+
return {
|
|
17034
|
+
id: Number(raw[idKey] ?? 0) | 0,
|
|
17035
|
+
enable: Number(raw["enable"] ?? 0) === 1,
|
|
17036
|
+
layer: Number(raw["layer"] ?? 0) | 0,
|
|
17037
|
+
color: Number(raw["color"] ?? 0) | 0,
|
|
17038
|
+
x: canvas.width > 0 ? xPixel / canvas.width : 0,
|
|
17039
|
+
y: canvas.height > 0 ? yPixel / canvas.height : 0,
|
|
17040
|
+
width: canvas.width > 0 ? wPixel / canvas.width : 0,
|
|
17041
|
+
height: canvas.height > 0 ? hPixel / canvas.height : 0
|
|
17042
|
+
};
|
|
17043
|
+
}
|
|
17044
|
+
function extractCanvasFromShelterXml(xml) {
|
|
17045
|
+
const xMatch = xml.match(/<topLeftX>(\d+)<\/topLeftX>/g) ?? [];
|
|
17046
|
+
const yMatch = xml.match(/<topLeftY>(\d+)<\/topLeftY>/g) ?? [];
|
|
17047
|
+
let canvasX = 0;
|
|
17048
|
+
let canvasY = 0;
|
|
17049
|
+
for (const tag of xMatch) {
|
|
17050
|
+
const v = Number(tag.replace(/<\/?topLeftX>/g, "")) | 0;
|
|
17051
|
+
if (v > 0) {
|
|
17052
|
+
canvasX = v & 65535;
|
|
17053
|
+
break;
|
|
17054
|
+
}
|
|
17055
|
+
}
|
|
17056
|
+
for (const tag of yMatch) {
|
|
17057
|
+
const v = Number(tag.replace(/<\/?topLeftY>/g, "")) | 0;
|
|
17058
|
+
if (v > 0) {
|
|
17059
|
+
canvasY = v & 65535;
|
|
17060
|
+
break;
|
|
17061
|
+
}
|
|
17062
|
+
}
|
|
17063
|
+
return {
|
|
17064
|
+
width: canvasX > 0 ? canvasX : DEFAULT_SHELTER_CANVAS.width,
|
|
17065
|
+
height: canvasY > 0 ? canvasY : DEFAULT_SHELTER_CANVAS.height
|
|
17066
|
+
};
|
|
17067
|
+
}
|
|
17068
|
+
function parseRectTags(block) {
|
|
17069
|
+
const out = {};
|
|
17070
|
+
const grab = (tag) => {
|
|
17071
|
+
const m = block.match(new RegExp(`<${tag}>([^<]*)<\\/${tag}>`));
|
|
17072
|
+
if (m && m[1] !== void 0) out[tag] = m[1];
|
|
17073
|
+
};
|
|
17074
|
+
grab("id");
|
|
17075
|
+
grab("name");
|
|
17076
|
+
grab("enable");
|
|
17077
|
+
grab("layer");
|
|
17078
|
+
grab("color");
|
|
17079
|
+
grab("topLeftX");
|
|
17080
|
+
grab("topLeftY");
|
|
17081
|
+
grab("width");
|
|
17082
|
+
grab("height");
|
|
17083
|
+
grab("pPos");
|
|
17084
|
+
grab("tPos");
|
|
17085
|
+
grab("zPos");
|
|
17086
|
+
return out;
|
|
17087
|
+
}
|
|
17088
|
+
function decodePrivacyMaskZones(xml) {
|
|
17089
|
+
const canvas = extractCanvasFromShelterXml(xml);
|
|
17090
|
+
const enable = Number(getXmlText(xml, "enable") ?? "0") === 1;
|
|
17091
|
+
const maxNum = Number(getXmlText(xml, "maxNum") ?? "0") | 0;
|
|
17092
|
+
const trackEnable = Number(getXmlText(xml, "trackEnable") ?? "0") === 1;
|
|
17093
|
+
const maxTrackShelterNum = Number(getXmlText(xml, "maxTrackShelterNum") ?? "0") | 0;
|
|
17094
|
+
const shelterList = [];
|
|
17095
|
+
const shelterListBlock = xml.match(
|
|
17096
|
+
/<shelterList>([\s\S]*?)<\/shelterList>/
|
|
17097
|
+
)?.[1];
|
|
17098
|
+
if (shelterListBlock) {
|
|
17099
|
+
const blocks = shelterListBlock.matchAll(
|
|
17100
|
+
/<Shelter>([\s\S]*?)<\/Shelter>/g
|
|
17101
|
+
);
|
|
17102
|
+
for (const m of blocks) {
|
|
17103
|
+
const tags = parseRectTags(m[1] ?? "");
|
|
17104
|
+
const decoded = decodeRect(tags, canvas, "id");
|
|
17105
|
+
shelterList.push(decoded);
|
|
17106
|
+
}
|
|
17107
|
+
}
|
|
17108
|
+
const trackShelterList = [];
|
|
17109
|
+
const trackBlock = xml.match(
|
|
17110
|
+
/<trackShelterList>([\s\S]*?)<\/trackShelterList>/
|
|
17111
|
+
)?.[1];
|
|
17112
|
+
if (trackBlock) {
|
|
17113
|
+
const blocks = trackBlock.matchAll(
|
|
17114
|
+
/<trackShelter>([\s\S]*?)<\/trackShelter>/g
|
|
17115
|
+
);
|
|
17116
|
+
for (const m of blocks) {
|
|
17117
|
+
const tags = parseRectTags(m[1] ?? "");
|
|
17118
|
+
const base = decodeRect(
|
|
17119
|
+
tags,
|
|
17120
|
+
canvas,
|
|
17121
|
+
"name"
|
|
17122
|
+
);
|
|
17123
|
+
trackShelterList.push({
|
|
17124
|
+
...base,
|
|
17125
|
+
pPos: Number(tags.pPos ?? -1) | 0,
|
|
17126
|
+
tPos: Number(tags.tPos ?? -1) | 0,
|
|
17127
|
+
zPos: Number(tags.zPos ?? -1) | 0
|
|
17128
|
+
});
|
|
17129
|
+
}
|
|
17130
|
+
}
|
|
17131
|
+
return {
|
|
17132
|
+
enable,
|
|
17133
|
+
maxNum,
|
|
17134
|
+
shelterList,
|
|
17135
|
+
trackEnable,
|
|
17136
|
+
maxTrackShelterNum,
|
|
17137
|
+
trackShelterList,
|
|
17138
|
+
canvas
|
|
17139
|
+
};
|
|
17140
|
+
}
|
|
17141
|
+
function denormalizeRect(rect, canvas) {
|
|
17142
|
+
const xPx = Math.min(canvas.width, Math.round(clamp01(rect.x) * canvas.width));
|
|
17143
|
+
const yPx = Math.min(canvas.height, Math.round(clamp01(rect.y) * canvas.height));
|
|
17144
|
+
const wPx = Math.min(
|
|
17145
|
+
canvas.width - xPx,
|
|
17146
|
+
Math.round(clamp01(rect.width) * canvas.width)
|
|
17147
|
+
);
|
|
17148
|
+
const hPx = Math.min(
|
|
17149
|
+
canvas.height - yPx,
|
|
17150
|
+
Math.round(clamp01(rect.height) * canvas.height)
|
|
17151
|
+
);
|
|
17152
|
+
return {
|
|
17153
|
+
topLeftX: encodeShelterCoord(xPx, canvas.width),
|
|
17154
|
+
topLeftY: encodeShelterCoord(yPx, canvas.height),
|
|
17155
|
+
width: encodeShelterCoord(wPx, canvas.width),
|
|
17156
|
+
height: encodeShelterCoord(hPx, canvas.height)
|
|
17157
|
+
};
|
|
17158
|
+
}
|
|
17159
|
+
function encodeShelterListXml(rects, canvas, maxNum) {
|
|
17160
|
+
if (maxNum <= 0) return "<shelterList />";
|
|
17161
|
+
const sorted = [...rects].sort((a, b) => a.id - b.id).slice(0, maxNum);
|
|
17162
|
+
const byId = new Map(sorted.map((r) => [r.id, r]));
|
|
17163
|
+
const parts = [];
|
|
17164
|
+
parts.push("<shelterList>");
|
|
17165
|
+
for (let id = 0; id < maxNum; id++) {
|
|
17166
|
+
const r = byId.get(id);
|
|
17167
|
+
if (r && r.enable) {
|
|
17168
|
+
const { topLeftX, topLeftY, width, height } = denormalizeRect(r, canvas);
|
|
17169
|
+
parts.push(
|
|
17170
|
+
`<Shelter><id>${id}</id><enable>1</enable><layer>${r.layer | 0}</layer><color>${r.color | 0}</color><topLeftX>${topLeftX}</topLeftX><topLeftY>${topLeftY}</topLeftY><width>${width}</width><height>${height}</height></Shelter>`
|
|
17171
|
+
);
|
|
17172
|
+
} else if (r) {
|
|
17173
|
+
const { topLeftX, topLeftY, width, height } = denormalizeRect(r, canvas);
|
|
17174
|
+
parts.push(
|
|
17175
|
+
`<Shelter><id>${id}</id><enable>0</enable><layer>${r.layer | 0}</layer><color>${r.color | 0}</color><topLeftX>${topLeftX}</topLeftX><topLeftY>${topLeftY}</topLeftY><width>${width}</width><height>${height}</height></Shelter>`
|
|
17176
|
+
);
|
|
17177
|
+
} else {
|
|
17178
|
+
parts.push(
|
|
17179
|
+
`<Shelter><id>${id}</id><enable>0</enable><layer>0</layer><color>0</color><topLeftX>0</topLeftX><topLeftY>0</topLeftY><width>0</width><height>0</height></Shelter>`
|
|
17180
|
+
);
|
|
17181
|
+
}
|
|
17182
|
+
}
|
|
17183
|
+
parts.push("</shelterList>");
|
|
17184
|
+
return parts.join("");
|
|
17185
|
+
}
|
|
17186
|
+
function encodeTrackShelterListXml(rects, canvas, maxNum) {
|
|
17187
|
+
if (maxNum <= 0) return "<trackShelterList />";
|
|
17188
|
+
const sorted = [...rects].sort((a, b) => a.id - b.id).slice(0, maxNum);
|
|
17189
|
+
const byId = new Map(sorted.map((r) => [r.id, r]));
|
|
17190
|
+
const parts = [];
|
|
17191
|
+
parts.push("<trackShelterList>");
|
|
17192
|
+
for (let id = 0; id < maxNum; id++) {
|
|
17193
|
+
const r = byId.get(id);
|
|
17194
|
+
if (r) {
|
|
17195
|
+
const { topLeftX, topLeftY, width, height } = denormalizeRect(r, canvas);
|
|
17196
|
+
parts.push(
|
|
17197
|
+
`<trackShelter><name>${id}</name><enable>${r.enable ? 1 : 0}</enable><layer>${r.layer | 0}</layer><color>${r.color | 0}</color><topLeftX>${topLeftX}</topLeftX><topLeftY>${topLeftY}</topLeftY><width>${width}</width><height>${height}</height><pPos>${r.pPos | 0}</pPos><tPos>${r.tPos | 0}</tPos><zPos>${r.zPos | 0}</zPos></trackShelter>`
|
|
17198
|
+
);
|
|
17199
|
+
} else {
|
|
17200
|
+
parts.push(
|
|
17201
|
+
`<trackShelter><name>${id}</name><enable>0</enable><layer>0</layer><color>0</color><topLeftX>0</topLeftX><topLeftY>0</topLeftY><width>0</width><height>0</height><pPos>-1</pPos><tPos>-1</tPos><zPos>-1</zPos></trackShelter>`
|
|
17202
|
+
);
|
|
17203
|
+
}
|
|
17204
|
+
}
|
|
17205
|
+
parts.push("</trackShelterList>");
|
|
17206
|
+
return parts.join("");
|
|
17207
|
+
}
|
|
17208
|
+
function patchShelterXml(shelterXml, patch, canvas, maxNum, maxTrackShelterNum) {
|
|
17209
|
+
let out = shelterXml;
|
|
17210
|
+
if (patch.enable !== void 0) {
|
|
17211
|
+
out = out.replace(
|
|
17212
|
+
/<enable>[^<]*<\/enable>/,
|
|
17213
|
+
`<enable>${patch.enable ? 1 : 0}</enable>`
|
|
17214
|
+
);
|
|
17215
|
+
}
|
|
17216
|
+
if (patch.shelterList !== void 0) {
|
|
17217
|
+
const fragment = encodeShelterListXml(patch.shelterList, canvas, maxNum);
|
|
17218
|
+
out = out.replace(/<shelterList[\s\S]*?(?:\/>|<\/shelterList>)/, fragment);
|
|
17219
|
+
}
|
|
17220
|
+
if (patch.trackEnable !== void 0) {
|
|
17221
|
+
out = out.replace(
|
|
17222
|
+
/<trackEnable>[^<]*<\/trackEnable>/,
|
|
17223
|
+
`<trackEnable>${patch.trackEnable ? 1 : 0}</trackEnable>`
|
|
17224
|
+
);
|
|
17225
|
+
}
|
|
17226
|
+
if (patch.trackShelterList !== void 0) {
|
|
17227
|
+
const fragment = encodeTrackShelterListXml(
|
|
17228
|
+
patch.trackShelterList,
|
|
17229
|
+
canvas,
|
|
17230
|
+
maxTrackShelterNum
|
|
17231
|
+
);
|
|
17232
|
+
out = out.replace(
|
|
17233
|
+
/<trackShelterList[\s\S]*?(?:\/>|<\/trackShelterList>)/,
|
|
17234
|
+
fragment
|
|
17235
|
+
);
|
|
17236
|
+
}
|
|
17237
|
+
return out;
|
|
17238
|
+
}
|
|
17239
|
+
|
|
17240
|
+
// src/reolink/baichuan/utils/aiDetectCfg.ts
|
|
17241
|
+
init_xml();
|
|
17242
|
+
function decodeAiDetectCfg(xml) {
|
|
17243
|
+
const type = getXmlText(xml, "type");
|
|
17244
|
+
if (type == null) throw new Error("AiDetectCfg: missing <type>");
|
|
17245
|
+
return {
|
|
17246
|
+
chn: Number(getXmlText(xml, "chn") ?? "0") | 0,
|
|
17247
|
+
type,
|
|
17248
|
+
sensitivity: Number(getXmlText(xml, "sensitivity") ?? "0") | 0,
|
|
17249
|
+
stayTime: Number(getXmlText(xml, "stayTime") ?? "0") | 0,
|
|
17250
|
+
minTargetWidth: Number(getXmlText(xml, "minTargetWidth") ?? "0"),
|
|
17251
|
+
minTargetHeight: Number(getXmlText(xml, "minTargetHeight") ?? "0"),
|
|
17252
|
+
maxTargetWidth: Number(getXmlText(xml, "maxTargetWidth") ?? "0"),
|
|
17253
|
+
maxTargetHeight: Number(getXmlText(xml, "maxTargetHeight") ?? "0"),
|
|
17254
|
+
width: Number(getXmlText(xml, "width") ?? "0") | 0,
|
|
17255
|
+
height: Number(getXmlText(xml, "height") ?? "0") | 0,
|
|
17256
|
+
area: getXmlText(xml, "area") ?? ""
|
|
17257
|
+
};
|
|
17258
|
+
}
|
|
17259
|
+
function clamp012(value) {
|
|
17260
|
+
if (!Number.isFinite(value)) return 0;
|
|
17261
|
+
if (value < 0) return 0;
|
|
17262
|
+
if (value > 1) return 1;
|
|
17263
|
+
return value;
|
|
17264
|
+
}
|
|
17265
|
+
function fmtFraction(value) {
|
|
17266
|
+
const v = clamp012(value);
|
|
17267
|
+
const e = v.toExponential(6);
|
|
17268
|
+
return e.replace(/e([+-])(\d)$/, "e$10$2");
|
|
17269
|
+
}
|
|
17270
|
+
function patchAiDetectCfgXml(currentXml, patch) {
|
|
17271
|
+
let out = currentXml;
|
|
17272
|
+
if (patch.sensitivity !== void 0) {
|
|
17273
|
+
out = out.replace(
|
|
17274
|
+
/<sensitivity>[^<]*<\/sensitivity>/,
|
|
17275
|
+
`<sensitivity>${patch.sensitivity | 0}</sensitivity>`
|
|
17276
|
+
);
|
|
17277
|
+
}
|
|
17278
|
+
if (patch.stayTime !== void 0) {
|
|
17279
|
+
out = out.replace(
|
|
17280
|
+
/<stayTime>[^<]*<\/stayTime>/,
|
|
17281
|
+
`<stayTime>${patch.stayTime | 0}</stayTime>`
|
|
17282
|
+
);
|
|
17283
|
+
}
|
|
17284
|
+
if (patch.minTargetWidth !== void 0) {
|
|
17285
|
+
out = out.replace(
|
|
17286
|
+
/<minTargetWidth>[^<]*<\/minTargetWidth>/,
|
|
17287
|
+
`<minTargetWidth>${fmtFraction(patch.minTargetWidth)}</minTargetWidth>`
|
|
17288
|
+
);
|
|
17289
|
+
}
|
|
17290
|
+
if (patch.minTargetHeight !== void 0) {
|
|
17291
|
+
out = out.replace(
|
|
17292
|
+
/<minTargetHeight>[^<]*<\/minTargetHeight>/,
|
|
17293
|
+
`<minTargetHeight>${fmtFraction(patch.minTargetHeight)}</minTargetHeight>`
|
|
17294
|
+
);
|
|
17295
|
+
}
|
|
17296
|
+
if (patch.maxTargetWidth !== void 0) {
|
|
17297
|
+
out = out.replace(
|
|
17298
|
+
/<maxTargetWidth>[^<]*<\/maxTargetWidth>/,
|
|
17299
|
+
`<maxTargetWidth>${fmtFraction(patch.maxTargetWidth)}</maxTargetWidth>`
|
|
17300
|
+
);
|
|
17301
|
+
}
|
|
17302
|
+
if (patch.maxTargetHeight !== void 0) {
|
|
17303
|
+
out = out.replace(
|
|
17304
|
+
/<maxTargetHeight>[^<]*<\/maxTargetHeight>/,
|
|
17305
|
+
`<maxTargetHeight>${fmtFraction(patch.maxTargetHeight)}</maxTargetHeight>`
|
|
17306
|
+
);
|
|
17307
|
+
}
|
|
17308
|
+
if (patch.area !== void 0) {
|
|
17309
|
+
out = out.replace(
|
|
17310
|
+
/<area>[^<]*<\/area>/,
|
|
17311
|
+
`<area>${patch.area}</area>`
|
|
17312
|
+
);
|
|
17313
|
+
}
|
|
17314
|
+
return out;
|
|
17315
|
+
}
|
|
17316
|
+
|
|
17317
|
+
// src/reolink/baichuan/utils/motionSensitivity.ts
|
|
17318
|
+
function clampInt(value, min, max) {
|
|
17319
|
+
if (!Number.isFinite(value)) return min;
|
|
17320
|
+
return Math.min(max, Math.max(min, Math.floor(value)));
|
|
17321
|
+
}
|
|
17322
|
+
function clampSensitivity(value) {
|
|
17323
|
+
return clampInt(value, 0, 50);
|
|
17324
|
+
}
|
|
17325
|
+
function clampHour(value) {
|
|
17326
|
+
return clampInt(value, 0, 23);
|
|
17327
|
+
}
|
|
17328
|
+
function clampMinute(value) {
|
|
17329
|
+
return clampInt(value, 0, 59);
|
|
17330
|
+
}
|
|
17331
|
+
function encodeMotionSensitivityListXml(bands) {
|
|
17332
|
+
if (bands.length === 0) return "<sensitivityInfoList />";
|
|
17333
|
+
const sorted = [...bands].sort((a, b) => a.id - b.id);
|
|
17334
|
+
const parts = ["<sensitivityInfoList>"];
|
|
17335
|
+
for (const b of sorted) {
|
|
17336
|
+
parts.push(
|
|
17337
|
+
`<sensitivityInfo><id>${b.id | 0}</id><sensitivity>${clampSensitivity(b.sensitivity)}</sensitivity><beginHour>${clampHour(b.beginHour)}</beginHour><beginMinute>${clampMinute(b.beginMinute)}</beginMinute><endHour>${clampHour(b.endHour)}</endHour><endMinute>${clampMinute(b.endMinute)}</endMinute></sensitivityInfo>`
|
|
17338
|
+
);
|
|
17339
|
+
}
|
|
17340
|
+
parts.push("</sensitivityInfoList>");
|
|
17341
|
+
return parts.join("");
|
|
17342
|
+
}
|
|
17343
|
+
function patchMotionSensitivityListXml(currentXml, bands) {
|
|
17344
|
+
const fragment = encodeMotionSensitivityListXml(bands);
|
|
17345
|
+
return currentXml.replace(
|
|
17346
|
+
/<sensitivityInfoList[\s\S]*?(?:\/>|<\/sensitivityInfoList>)/,
|
|
17347
|
+
fragment
|
|
17348
|
+
);
|
|
17349
|
+
}
|
|
17350
|
+
|
|
17006
17351
|
// src/reolink/baichuan/utils/ptz.ts
|
|
17007
17352
|
init_xml();
|
|
17008
17353
|
var resolvePtzDirection = (command) => {
|
|
@@ -22358,7 +22703,7 @@ var ReolinkBaichuanApi = class _ReolinkBaichuanApi {
|
|
|
22358
22703
|
* Note: Snapshot uses a special message ID system for binary responses
|
|
22359
22704
|
*/
|
|
22360
22705
|
async getSnapshot(channel, options) {
|
|
22361
|
-
const cmdId =
|
|
22706
|
+
const cmdId = BC_CMD_ID_GET_SNAPSHOT;
|
|
22362
22707
|
if (channel === void 0) {
|
|
22363
22708
|
const composite = options?.compositeOptions;
|
|
22364
22709
|
const widerChannel = composite?.widerChannel ?? 0;
|
|
@@ -25961,6 +26306,12 @@ ${stderr}`)
|
|
|
25961
26306
|
`<valueTable>${opts.valueTable}</valueTable>`
|
|
25962
26307
|
);
|
|
25963
26308
|
}
|
|
26309
|
+
if (opts.sensitivitySchedule !== void 0) {
|
|
26310
|
+
modifiedXml = patchMotionSensitivityListXml(
|
|
26311
|
+
modifiedXml,
|
|
26312
|
+
opts.sensitivitySchedule
|
|
26313
|
+
);
|
|
26314
|
+
}
|
|
25964
26315
|
await this.sendXml({
|
|
25965
26316
|
cmdId: BC_CMD_ID_SET_MOTION_ALARM,
|
|
25966
26317
|
channel: ch,
|
|
@@ -26008,6 +26359,72 @@ ${stderr}`)
|
|
|
26008
26359
|
payloadXml: modifiedXml
|
|
26009
26360
|
});
|
|
26010
26361
|
}
|
|
26362
|
+
/**
|
|
26363
|
+
* SetAiDetectionFull (cmd_id=343 — same as `setAiDetection`).
|
|
26364
|
+
*
|
|
26365
|
+
* Pcap-confirmed (May 2026, E1 Zoom): the Reolink app sends the full
|
|
26366
|
+
* `<AiDetectCfg>` block via cmd_id=343 for ALL fields — area mask,
|
|
26367
|
+
* min/maxTarget* thresholds, sensitivity, stayTime — in one round-trip.
|
|
26368
|
+
* There's no separate "full setter" command (we previously suspected
|
|
26369
|
+
* cmd_id=345 but that's used for something else not yet identified).
|
|
26370
|
+
*
|
|
26371
|
+
* Wire format note: min/maxTarget* fractions are serialized in
|
|
26372
|
+
* scientific notation with 6 decimal places (e.g. "5.000000e-01" for
|
|
26373
|
+
* 0.5). The helper {@link patchAiDetectCfgXml} handles the formatting.
|
|
26374
|
+
*
|
|
26375
|
+
* @param channel 0-based channel
|
|
26376
|
+
* @param aiType one of "people" / "vehicle" / "dog_cat" / "face" / "package"
|
|
26377
|
+
* @param patch partial edit; any omitted field is preserved as-is
|
|
26378
|
+
*/
|
|
26379
|
+
async setAiDetectionFull(channel, aiType, patch) {
|
|
26380
|
+
const ch = this.normalizeChannel(channel);
|
|
26381
|
+
const resolvedAiType = await this.resolveAiTypeForSetAiDetection(
|
|
26382
|
+
ch,
|
|
26383
|
+
aiType
|
|
26384
|
+
);
|
|
26385
|
+
const getXml = `<?xml version="1.0" encoding="UTF-8" ?>
|
|
26386
|
+
<body>
|
|
26387
|
+
<AiDetectCfg version="1.1">
|
|
26388
|
+
<chn>${ch}</chn>
|
|
26389
|
+
<type>${xmlEscape(resolvedAiType)}</type>
|
|
26390
|
+
</AiDetectCfg>
|
|
26391
|
+
</body>`;
|
|
26392
|
+
const currentXml = await this.sendXml({
|
|
26393
|
+
cmdId: BC_CMD_ID_GET_AI_ALARM,
|
|
26394
|
+
channel: ch,
|
|
26395
|
+
payloadXml: getXml
|
|
26396
|
+
});
|
|
26397
|
+
const patchedXml = patchAiDetectCfgXml(currentXml, patch);
|
|
26398
|
+
await this.sendXml({
|
|
26399
|
+
cmdId: BC_CMD_ID_SET_AI_ALARM,
|
|
26400
|
+
channel: ch,
|
|
26401
|
+
payloadXml: patchedXml
|
|
26402
|
+
});
|
|
26403
|
+
}
|
|
26404
|
+
/**
|
|
26405
|
+
* GetAiDetectionFull (cmd_id=342). Typed version of `getAiAlarmRaw`
|
|
26406
|
+
* returning the full {@link AiDetectCfgZone} for a single AI type.
|
|
26407
|
+
*/
|
|
26408
|
+
async getAiDetectionFull(channel, aiType) {
|
|
26409
|
+
const ch = this.normalizeChannel(channel);
|
|
26410
|
+
const resolvedAiType = await this.resolveAiTypeForSetAiDetection(
|
|
26411
|
+
ch,
|
|
26412
|
+
aiType
|
|
26413
|
+
);
|
|
26414
|
+
const getXml = `<?xml version="1.0" encoding="UTF-8" ?>
|
|
26415
|
+
<body>
|
|
26416
|
+
<AiDetectCfg version="1.1">
|
|
26417
|
+
<chn>${ch}</chn>
|
|
26418
|
+
<type>${xmlEscape(resolvedAiType)}</type>
|
|
26419
|
+
</AiDetectCfg>
|
|
26420
|
+
</body>`;
|
|
26421
|
+
const xml = await this.sendXml({
|
|
26422
|
+
cmdId: BC_CMD_ID_GET_AI_ALARM,
|
|
26423
|
+
channel: ch,
|
|
26424
|
+
payloadXml: getXml
|
|
26425
|
+
});
|
|
26426
|
+
return decodeAiDetectCfg(xml);
|
|
26427
|
+
}
|
|
26011
26428
|
// --------------------
|
|
26012
26429
|
// Siren/Audio Alarm APIs
|
|
26013
26430
|
// --------------------
|
|
@@ -27588,6 +28005,69 @@ ${xml}`
|
|
|
27588
28005
|
...timeoutOpts
|
|
27589
28006
|
});
|
|
27590
28007
|
}
|
|
28008
|
+
/**
|
|
28009
|
+
* GetMaskZones (cmdId=52) returning a typed structure with normalized
|
|
28010
|
+
* 0..1 rectangles instead of the raw camera fixed-point integers.
|
|
28011
|
+
*
|
|
28012
|
+
* The camera-side coord system is `(pixel << 16) | canvas_dim` where
|
|
28013
|
+
* `canvas_dim` is the firmware-specific mask canvas (E1 Zoom = 540×304).
|
|
28014
|
+
* The returned `canvas` block remembers those dims so callers can
|
|
28015
|
+
* round-trip without re-fetching.
|
|
28016
|
+
*
|
|
28017
|
+
* @see decodePrivacyMaskZones — pure helper exported for UI consumers.
|
|
28018
|
+
*/
|
|
28019
|
+
async getMaskZones(channel, options) {
|
|
28020
|
+
const xml = await this.sendPcapDerivedSettingsGetXml({
|
|
28021
|
+
cmdId: BC_CMD_ID_GET_PRIVACY_MASK,
|
|
28022
|
+
...channel != null ? { channel } : {},
|
|
28023
|
+
...options?.timeoutMs != null ? { timeoutMs: options.timeoutMs } : {}
|
|
28024
|
+
});
|
|
28025
|
+
return decodePrivacyMaskZones(xml);
|
|
28026
|
+
}
|
|
28027
|
+
/**
|
|
28028
|
+
* SetMaskZones (cmdId=53, read-modify-write of cmdId=52).
|
|
28029
|
+
*
|
|
28030
|
+
* Edits the rectangular shelter list and/or PTZ-tracking shelter list
|
|
28031
|
+
* in one call. Coordinates are normalized 0..1 of the camera mask
|
|
28032
|
+
* canvas — the lib re-fetches the current Shelter block, extracts the
|
|
28033
|
+
* canvas dims from the wire (low-16 of any non-zero coord), and
|
|
28034
|
+
* denormalizes back to the camera's pixel × canvas encoding.
|
|
28035
|
+
*
|
|
28036
|
+
* Pass `enable`/`trackEnable` to toggle the master enable flags without
|
|
28037
|
+
* touching the rectangle data. Pass `shelterList`/`trackShelterList` to
|
|
28038
|
+
* replace the corresponding list — missing slots are padded with
|
|
28039
|
+
* disabled zero-rects matching the camera's idle pattern.
|
|
28040
|
+
*
|
|
28041
|
+
* @param channel 0-based channel
|
|
28042
|
+
* @param patch partial edit; any omitted field is preserved as-is
|
|
28043
|
+
* @param options.canvas override the auto-detected mask canvas (only
|
|
28044
|
+
* needed when the GET response has no non-zero coords to extract from)
|
|
28045
|
+
* @param options.timeoutMs custom request timeout
|
|
28046
|
+
*/
|
|
28047
|
+
async setMaskZones(channel, patch, options) {
|
|
28048
|
+
const ch = this.normalizeChannel(channel);
|
|
28049
|
+
const timeoutOpts = options?.timeoutMs != null ? { timeoutMs: options.timeoutMs } : {};
|
|
28050
|
+
const currentXml = await this.sendXml({
|
|
28051
|
+
cmdId: BC_CMD_ID_GET_PRIVACY_MASK,
|
|
28052
|
+
channel: ch,
|
|
28053
|
+
...timeoutOpts
|
|
28054
|
+
});
|
|
28055
|
+
const current = decodePrivacyMaskZones(currentXml);
|
|
28056
|
+
const canvas = options?.canvas ?? current.canvas;
|
|
28057
|
+
const patchedXml = patchShelterXml(
|
|
28058
|
+
currentXml,
|
|
28059
|
+
patch,
|
|
28060
|
+
canvas,
|
|
28061
|
+
current.maxNum,
|
|
28062
|
+
current.maxTrackShelterNum
|
|
28063
|
+
);
|
|
28064
|
+
await this.sendXml({
|
|
28065
|
+
cmdId: BC_CMD_ID_SET_PRIVACY_MASK,
|
|
28066
|
+
channel: ch,
|
|
28067
|
+
payloadXml: ensureXmlHeader(patchedXml),
|
|
28068
|
+
...timeoutOpts
|
|
28069
|
+
});
|
|
28070
|
+
}
|
|
27591
28071
|
/**
|
|
27592
28072
|
* GetAudioNoise via Baichuan (cmdId=439). Reads `enable` + `level`
|
|
27593
28073
|
* from the aiDenoise block. Mirrors reolink_aio's `GetAudioNoise`.
|
|
@@ -28274,6 +28754,18 @@ ${xml}`
|
|
|
28274
28754
|
});
|
|
28275
28755
|
return parseVersionInfo(xml);
|
|
28276
28756
|
}
|
|
28757
|
+
/**
|
|
28758
|
+
* GetUid (cmd_id=114). Returns the device UID / serial visible in the
|
|
28759
|
+
* Reolink app. Response shape: `<Uid><uid>9527000XXXXX</uid></Uid>`.
|
|
28760
|
+
* Device-global — no channel parameter.
|
|
28761
|
+
*/
|
|
28762
|
+
async getUid(options) {
|
|
28763
|
+
const xml = await this.sendXml({
|
|
28764
|
+
cmdId: BC_CMD_ID_GET_UID,
|
|
28765
|
+
...options?.timeoutMs != null ? { timeoutMs: options.timeoutMs } : {}
|
|
28766
|
+
});
|
|
28767
|
+
return (getXmlText(xml, "uid") ?? "").trim();
|
|
28768
|
+
}
|
|
28277
28769
|
async getLedState(channel, options) {
|
|
28278
28770
|
const rawXml = await this.sendPcapDerivedSettingsGetXml({
|
|
28279
28771
|
cmdId: BC_CMD_ID_GET_LED_STATE,
|