@apocaliss92/nodelink-js 0.4.24 → 0.4.26

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.
@@ -19000,6 +19000,39 @@ var applyFloodlightSettingsToXml = (xml, settings) => {
19000
19000
  return modifiedXml;
19001
19001
  };
19002
19002
 
19003
+ // src/reolink/baichuan/utils/whiteLedStatusPush.ts
19004
+ var parseFloodlightStatusListPushXml = (xml) => {
19005
+ const out = [];
19006
+ const re = /<channel>\s*(\d+)\s*<\/channel>[\s\S]*?<status>\s*(\d+)\s*<\/status>/gi;
19007
+ let m;
19008
+ while ((m = re.exec(xml)) !== null) {
19009
+ const channel = Number.parseInt(m[1] ?? "", 10);
19010
+ const status = Number.parseInt(m[2] ?? "", 10);
19011
+ if (!Number.isFinite(channel) || !Number.isFinite(status)) continue;
19012
+ out.push({ channel, status });
19013
+ }
19014
+ return out;
19015
+ };
19016
+
19017
+ // src/reolink/baichuan/utils/sirenStatusPush.ts
19018
+ var parseSirenStatusListPushXml = (xml) => {
19019
+ const out = [];
19020
+ const re = /<(?:channelId|channel)>\s*(\d+)\s*<\/(?:channelId|channel)>[\s\S]*?<status>\s*(\d+)\s*<\/status>(?:[\s\S]*?<playing>\s*(\d+)\s*<\/playing>)?/gi;
19021
+ let m;
19022
+ while ((m = re.exec(xml)) !== null) {
19023
+ const channel = Number.parseInt(m[1] ?? "", 10);
19024
+ const status = Number.parseInt(m[2] ?? "", 10);
19025
+ if (!Number.isFinite(channel) || !Number.isFinite(status)) continue;
19026
+ const entry = { channel, status };
19027
+ if (m[3] !== void 0) {
19028
+ const playing = Number.parseInt(m[3], 10);
19029
+ if (Number.isFinite(playing)) entry.playing = playing;
19030
+ }
19031
+ out.push(entry);
19032
+ }
19033
+ return out;
19034
+ };
19035
+
19003
19036
  // src/reolink/baichuan/ReolinkBaichuanApi.ts
19004
19037
  var DUAL_LENS_DUAL_MOTION_MODELS = /* @__PURE__ */ new Set([
19005
19038
  "Reolink Duo PoE",
@@ -19278,7 +19311,7 @@ var ReolinkBaichuanApi = class _ReolinkBaichuanApi {
19278
19311
  });
19279
19312
  client.on("push", (frame) => {
19280
19313
  const cmdId = frame.header.cmdId;
19281
- if (cmdId !== BC_CMD_ID_PUSH_VIDEO_INPUT && cmdId !== BC_CMD_ID_PUSH_SERIAL && cmdId !== BC_CMD_ID_PUSH_NET_INFO && cmdId !== BC_CMD_ID_PUSH_DINGDONG_LIST && cmdId !== BC_CMD_ID_PUSH_SLEEP_STATUS && cmdId !== BC_CMD_ID_PUSH_COORDINATE_POINT_LIST) {
19314
+ if (cmdId !== BC_CMD_ID_PUSH_VIDEO_INPUT && cmdId !== BC_CMD_ID_PUSH_SERIAL && cmdId !== BC_CMD_ID_PUSH_NET_INFO && cmdId !== BC_CMD_ID_PUSH_DINGDONG_LIST && cmdId !== BC_CMD_ID_PUSH_SLEEP_STATUS && cmdId !== BC_CMD_ID_PUSH_COORDINATE_POINT_LIST && cmdId !== BC_CMD_ID_FLOODLIGHT_STATUS_LIST && cmdId !== BC_CMD_ID_GET_AUDIO_ALARM) {
19282
19315
  return;
19283
19316
  }
19284
19317
  try {
@@ -28319,6 +28352,33 @@ ${xml}`
28319
28352
  };
28320
28353
  return;
28321
28354
  }
28355
+ if (cmdId === BC_CMD_ID_FLOODLIGHT_STATUS_LIST) {
28356
+ const entries = parseFloodlightStatusListPushXml(xml);
28357
+ if (entries.length === 0) return;
28358
+ for (const entry of entries) {
28359
+ const channel = normalizePushChannel(entry.channel) ?? channelFromHeader;
28360
+ getEntry(channel).floodlightStatus = {
28361
+ updatedAtMs: now,
28362
+ value: { status: entry.status === 1 }
28363
+ };
28364
+ }
28365
+ return;
28366
+ }
28367
+ if (cmdId === BC_CMD_ID_GET_AUDIO_ALARM) {
28368
+ const entries = parseSirenStatusListPushXml(xml);
28369
+ if (entries.length === 0) return;
28370
+ for (const entry of entries) {
28371
+ const channel = normalizePushChannel(entry.channel) ?? channelFromHeader;
28372
+ getEntry(channel).sirenStatus = {
28373
+ updatedAtMs: now,
28374
+ value: {
28375
+ status: entry.status === 1,
28376
+ ...entry.playing !== void 0 ? { playing: entry.playing === 1 } : {}
28377
+ }
28378
+ };
28379
+ }
28380
+ return;
28381
+ }
28322
28382
  }
28323
28383
  /** Read-only snapshot of cached settings pushes (cmd_id 78/79/464/484/623/723). */
28324
28384
  getSettingsPushCacheSnapshot() {
@@ -28351,6 +28411,18 @@ ${xml}`
28351
28411
  ...entry.coordinatePointList,
28352
28412
  value: { ...entry.coordinatePointList.value }
28353
28413
  }
28414
+ } : {},
28415
+ ...entry.floodlightStatus ? {
28416
+ floodlightStatus: {
28417
+ ...entry.floodlightStatus,
28418
+ value: { ...entry.floodlightStatus.value }
28419
+ }
28420
+ } : {},
28421
+ ...entry.sirenStatus ? {
28422
+ sirenStatus: {
28423
+ ...entry.sirenStatus,
28424
+ value: { ...entry.sirenStatus.value }
28425
+ }
28354
28426
  } : {}
28355
28427
  });
28356
28428
  }
@@ -28374,6 +28446,29 @@ ${xml}`
28374
28446
  getCoordinatePointListFromPushCache(channel = 0) {
28375
28447
  return this.settingsPushCache.get(channel)?.coordinatePointList;
28376
28448
  }
28449
+ /**
28450
+ * Last cmd_id 291 (FloodlightStatusList) push observed for the channel.
28451
+ * The camera emits this whenever the floodlight transitions on/off,
28452
+ * including the auto-off after the FloodlightManual duration. This is
28453
+ * the only reliable source for the current manual state because cmd 289
28454
+ * only returns the FloodlightTask config.
28455
+ *
28456
+ * Returns undefined when no push has been received yet.
28457
+ */
28458
+ getCachedFloodlightStatus(channel = 0) {
28459
+ return this.settingsPushCache.get(channel)?.floodlightStatus;
28460
+ }
28461
+ /**
28462
+ * Last cmd_id 547 (SirenStatusList) push observed for the channel.
28463
+ * Captures the actual on/off transitions including the firmware's
28464
+ * built-in auto-off after the siren playback duration expires —
28465
+ * polling cmd 547 alone can race that auto-off.
28466
+ *
28467
+ * Returns undefined when no push has been received yet.
28468
+ */
28469
+ getCachedSirenStatus(channel = 0) {
28470
+ return this.settingsPushCache.get(channel)?.sirenStatus;
28471
+ }
28377
28472
  // --------------------
28378
28473
  // PCAP-derived settings getters (typed wrappers)
28379
28474
  // --------------------