iobroker.agent-dvr 0.0.2 → 0.0.4

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/build/main.js CHANGED
@@ -278,6 +278,7 @@ class AgentDvr extends utils.Adapter {
278
278
  registry = /* @__PURE__ */ new Map();
279
279
  ptzActive = /* @__PURE__ */ new Map();
280
280
  widgetSig = {};
281
+ profileSig = "";
281
282
  lastEventFn = {};
282
283
  camAspect = {};
283
284
  devById = /* @__PURE__ */ new Map();
@@ -382,6 +383,43 @@ class AgentDvr extends utils.Adapter {
382
383
  }
383
384
  });
384
385
  }
386
+ apiGetBuffer(path) {
387
+ return new Promise((resolve) => {
388
+ const timeout = Math.max(1e3, Math.min(3e4, this.config.httpTimeoutMs || 8e3));
389
+ const opts = {
390
+ hostname: this.config.ip,
391
+ port: this.config.port || 8090,
392
+ path,
393
+ method: "GET",
394
+ timeout
395
+ };
396
+ if (this.authHeader) {
397
+ opts.headers = { Authorization: this.authHeader };
398
+ }
399
+ try {
400
+ const req = http.request(opts, (res) => {
401
+ const chunks = [];
402
+ res.on("data", (c) => chunks.push(c));
403
+ res.on("end", () => {
404
+ if (res.statusCode && res.statusCode >= 400) {
405
+ resolve({ ok: false, error: `HTTP ${res.statusCode}` });
406
+ } else {
407
+ resolve({ ok: true, data: Buffer.concat(chunks) });
408
+ }
409
+ });
410
+ res.on("error", (e) => resolve({ ok: false, error: e.message }));
411
+ });
412
+ req.on("error", (e) => resolve({ ok: false, error: e.message }));
413
+ req.on("timeout", () => {
414
+ req.destroy();
415
+ resolve({ ok: false, error: "timeout" });
416
+ });
417
+ req.end();
418
+ } catch (e) {
419
+ resolve({ ok: false, error: String(e.message || e) });
420
+ }
421
+ });
422
+ }
385
423
  async ensureFolder(id, name, type = "channel") {
386
424
  if (this.ensuredFolders.has(id)) {
387
425
  return;
@@ -471,6 +509,28 @@ class AgentDvr extends utils.Adapter {
471
509
  ensureButton(id, name, entry) {
472
510
  return this.ensureControl(id, name, entry, "button");
473
511
  }
512
+ async ensureSelector(id, name, entry, states) {
513
+ if (!this.ensuredFolders.has(id)) {
514
+ await this.ensurePath(id);
515
+ await this.setObjectNotExistsAsync(id, {
516
+ type: "state",
517
+ common: { name, type: "number", role: "level", read: true, write: true, states },
518
+ native: {}
519
+ });
520
+ await this.setStateAsync(id, { val: 0, ack: true });
521
+ this.ensuredFolders.add(id);
522
+ }
523
+ this.registry.set(id, entry);
524
+ }
525
+ async fetchSnapshotB64(oid, snapId) {
526
+ const imgRes = await this.apiGetBuffer(`/photo.jpg?oid=${oid}`);
527
+ if (imgRes.ok && imgRes.data) {
528
+ await this.setStateAsync(snapId, {
529
+ val: `data:image/jpeg;base64,${imgRes.data.toString("base64")}`,
530
+ ack: true
531
+ });
532
+ }
533
+ }
474
534
  async ensureFlag(id, name) {
475
535
  if (this.ensuredFolders.has(id)) {
476
536
  return;
@@ -501,6 +561,28 @@ class AgentDvr extends utils.Adapter {
501
561
  for (const c of SYS_COMMANDS) {
502
562
  await this.ensureButton(`system.control.${c.id}`, c.name, { kind: "sys", path: c.path });
503
563
  }
564
+ await this.ensureFolder("system.profile", "Profile", "channel");
565
+ await this.ensureSelector(
566
+ "system.profile.selector",
567
+ "Active profile",
568
+ { kind: "setProfile" },
569
+ { 0: "Home", 1: "Away", 2: "Night" }
570
+ );
571
+ if (!this.ensuredFolders.has("system.profile.list")) {
572
+ await this.setObjectNotExistsAsync("system.profile.list", {
573
+ type: "state",
574
+ common: {
575
+ name: "Available profiles (JSON)",
576
+ type: "string",
577
+ role: "json",
578
+ read: true,
579
+ write: false
580
+ },
581
+ native: {}
582
+ });
583
+ this.ensuredFolders.add("system.profile.list");
584
+ await this.setStateAsync("system.profile.list", { val: "[]", ack: true });
585
+ }
504
586
  }
505
587
  }
506
588
  // ---- camera aspect detection ----
@@ -570,6 +652,33 @@ class AgentDvr extends utils.Adapter {
570
652
  await this.writeLeaf(`${fid}.urls.mjpeg`, `${this.baseUrl}/video.mjpg?oids=${d.oid}`);
571
653
  await this.writeLeaf(`${fid}.urls.mp4`, `${this.baseUrl}/video.mp4?oids=${d.oid}`);
572
654
  }
655
+ if (d.ot === 2) {
656
+ const snapId = `${fid}.snapshot_b64`;
657
+ if (!this.ensuredFolders.has(snapId)) {
658
+ await this.ensurePath(snapId);
659
+ await this.setObjectNotExistsAsync(snapId, {
660
+ type: "state",
661
+ common: {
662
+ name: "Snapshot (Base64)",
663
+ type: "string",
664
+ role: "state",
665
+ read: true,
666
+ write: false
667
+ },
668
+ native: {}
669
+ });
670
+ await this.setStateAsync(snapId, { val: "", ack: true });
671
+ this.ensuredFolders.add(snapId);
672
+ }
673
+ await this.ensureButton(`${fid}.control.refreshSnapshotB64`, "Refresh snapshot (Base64)", {
674
+ kind: "snapshotB64",
675
+ oid: d.oid,
676
+ fid
677
+ });
678
+ if (this.config.enableSnapshotB64) {
679
+ await this.fetchSnapshotB64(d.oid, snapId);
680
+ }
681
+ }
573
682
  await this.updateCameraEvents(d, fid);
574
683
  }
575
684
  // ---- event formatting ----
@@ -829,6 +938,7 @@ class AgentDvr extends utils.Adapter {
829
938
  }
830
939
  // ---- main poll ----
831
940
  async poll() {
941
+ var _a, _b;
832
942
  const res = await this.apiGet("/command/getObjects");
833
943
  const json = asJson(res.data);
834
944
  if (!res.ok || !json) {
@@ -864,6 +974,34 @@ class AgentDvr extends utils.Adapter {
864
974
  if (status) {
865
975
  await this.flattenWrite(status, "system.status", 0);
866
976
  }
977
+ if (this.config.enableSystemControls && Array.isArray(json.profiles)) {
978
+ const states = {};
979
+ let activeInd = null;
980
+ for (const p of json.profiles) {
981
+ if (p && typeof p === "object") {
982
+ const po = p;
983
+ const ind = (_b = (_a = po.id) != null ? _a : po.ind) != null ? _b : po.index;
984
+ const pname = po.name;
985
+ if (typeof ind === "number" && (typeof pname === "string" || typeof pname === "number")) {
986
+ states[ind] = String(pname);
987
+ if (po.active === true) {
988
+ activeInd = ind;
989
+ }
990
+ }
991
+ }
992
+ }
993
+ if (Object.keys(states).length > 0) {
994
+ const sig = JSON.stringify(states);
995
+ if (sig !== this.profileSig) {
996
+ this.profileSig = sig;
997
+ await this.extendObjectAsync("system.profile.selector", { common: { states } });
998
+ await this.setStateAsync("system.profile.list", { val: sig, ack: true });
999
+ }
1000
+ if (activeInd !== null) {
1001
+ await this.setStateAsync("system.profile.selector", { val: activeInd, ack: true });
1002
+ }
1003
+ }
1004
+ }
867
1005
  if (this.config.enableOverview) {
868
1006
  const cams = devices.filter((d) => d.ot === 2);
869
1007
  const ovId = "overview";
@@ -931,6 +1069,27 @@ class AgentDvr extends utils.Adapter {
931
1069
  }
932
1070
  }
933
1071
  async runCommand(relId, entry, val) {
1072
+ if (entry.kind === "setProfile") {
1073
+ const ind = typeof val === "number" ? val : parseInt(String(val != null ? val : ""), 10);
1074
+ if (!isNaN(ind)) {
1075
+ const url2 = `/command/setProfile?ind=${ind}`;
1076
+ const cmdRes2 = await this.apiGet(url2);
1077
+ if (cmdRes2.ok) {
1078
+ this.log.debug(`OK: ${url2}`);
1079
+ await this.setStateAsync(relId, { val: ind, ack: true });
1080
+ } else {
1081
+ this.log.warn(`Command failed (${url2}): ${cmdRes2.error}`);
1082
+ }
1083
+ this.scheduleRefresh();
1084
+ }
1085
+ return;
1086
+ }
1087
+ if (entry.kind === "snapshotB64") {
1088
+ const snapId = `${entry.fid}.snapshot_b64`;
1089
+ await this.fetchSnapshotB64(entry.oid, snapId);
1090
+ await this.setStateAsync(relId, { val: false, ack: true });
1091
+ return;
1092
+ }
934
1093
  if (entry.kind === "push") {
935
1094
  this.log.info(`Push trigger cam ${entry.oid}`);
936
1095
  await this.setStateAsync(relId, { val: "", ack: true });