@camstack/addon-provider-amcrest 0.2.129 → 0.2.130

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 (3) hide show
  1. package/dist/addon.js +128 -82
  2. package/dist/addon.mjs +128 -82
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -10579,11 +10579,11 @@ var ModelVariantGroupSchema = object({
10579
10579
  /** Quantization axis. Omit ⇒ the fp32 base build. */
10580
10580
  precision: _enum(["fp32", "int8"]).optional(),
10581
10581
  /**
10582
- * Speed-optimization axis. Omit ⇒ the standard build. `fast` marks a
10583
- * latency-optimized export (e.g. ReLU-activation variant) — the slot the
10584
- * future performance variants plug into.
10582
+ * Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
10583
+ * an alternate training of the same family (Scrypted `relu_test`); chip
10584
+ * label is "Test".
10585
10585
  */
10586
- optimization: _enum(["standard", "fast"]).optional(),
10586
+ optimization: _enum(["standard", "test"]).optional(),
10587
10587
  /**
10588
10588
  * Input-resolution axis (square input side, px). Omit ⇒ the family's native
10589
10589
  * resolution (640 for yolo26). Reduced-input builds (320 / 256) are a big,
@@ -10606,9 +10606,10 @@ var ModelProviderIdSchema = _enum([
10606
10606
  * are per upstream. A persisted custom-model row written when this field was a
10607
10607
  * string still parses — the string is lifted into `{ weights }`.
10608
10608
  *
10609
- * Every licence surface (the admin "Models and licenses" page,
10610
- * `THIRD_PARTY_MODELS.md`, the Hugging Face model table) is GENERATED from
10611
- * these records by `scripts/gen-model-licenses.ts` (D661).
10609
+ * Every machine licence surface (`THIRD_PARTY_MODELS.md`, the Hugging Face
10610
+ * model table) is GENERATED from these records by
10611
+ * `scripts/gen-model-licenses.ts` (D661). Operator-facing docs live in
10612
+ * `camstack/docs` → `/docs/detection/models`.
10612
10613
  */
10613
10614
  var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { weights: value } : value, object({
10614
10615
  /** SPDX id of the WEIGHTS' terms, a `LicenseRef-*` for non-SPDX terms, or `UNKNOWN`. */
@@ -14239,7 +14240,7 @@ DeviceType.Camera;
14239
14240
  * This matters here more than anywhere else in the repo, because every provider
14240
14241
  * that knows a device's host knows its PASSWORD too: `{ host, port, username,
14241
14242
  * password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
14242
- * and `http://admin:hunter2@192.168.x.x/` is a URL a browser accepts. The
14243
+ * and `http://admin:hunter2@192.168.60.139/` is a URL a browser accepts. The
14243
14244
  * camera's own page will ask for its own login. That is correct, and pre-
14244
14245
  * filling it is the operator's business, not ours.
14245
14246
  *
@@ -17524,7 +17525,7 @@ method(object({
17524
17525
  timeoutMs: 6e5
17525
17526
  });
17526
17527
  method(object({
17527
- nodeId: string(),
17528
+ targetNodeId: string(),
17528
17529
  modelId: string(),
17529
17530
  format: _enum(MODEL_FORMATS),
17530
17531
  entry: ModelCatalogEntrySchema
@@ -20028,8 +20029,9 @@ var NcRuleSchema = NcRuleInputSchema.extend({
20028
20029
  disabledTargetIds: array(string()).default([])
20029
20030
  });
20030
20031
  /**
20031
- * The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
20032
- * still-true state. `backups-exports` and `alarm` are not sections — a completed
20032
+ * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
20033
+ * report a still-true state. `addons` is the crash-looped addons only and
20034
+ * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
20033
20035
  * job is not an open state, and the alarm stays instant.
20034
20036
  */
20035
20037
  var NcStateSummarySectionIdSchema = _enum([
@@ -20041,6 +20043,7 @@ var NcStateSummarySectionIdSchema = _enum([
20041
20043
  "detection-blind",
20042
20044
  "nodes",
20043
20045
  "addons",
20046
+ "addon-updates",
20044
20047
  "updates"
20045
20048
  ]);
20046
20049
  /** One section of a previewed state summary. `unavailable` = its state could not be read. */
@@ -20521,7 +20524,19 @@ var NcAlarmModeDelaysListSchema = array(object({
20521
20524
  * When this mode may be armed. Absent / null = always allowed (same as a
20522
20525
  * rule with no `schedule`). Evaluated with {@link isScheduleActive}.
20523
20526
  */
20524
- schedule: NcScheduleSchema.optional()
20527
+ schedule: NcScheduleSchema.optional(),
20528
+ /**
20529
+ * D706: while this mode's ENTRY DELAY runs, do the alarm rules' own pushes go out (as an
20530
+ * intrusion naming the locations)? Absent = false — the entry-delay notification is the
20531
+ * only one, and the matches ride the triggered notification's mosaic (D705).
20532
+ */
20533
+ notifyDuringEntryDelay: boolean().optional(),
20534
+ /**
20535
+ * D706: notify "watched again" when a sensor this arm bypassed closes and opens again.
20536
+ * Absent = false (logged, not sent). Even when true it is not sent when that same sensor
20537
+ * is the one that starts the entry delay — the entry-delay notification already names it.
20538
+ */
20539
+ notifySensorRewatched: boolean().optional()
20525
20540
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
20526
20541
  var NcAlarmModeDelaysEditListSchema = array(object({
20527
20542
  mode: AlarmArmModeSchema,
@@ -20530,7 +20545,11 @@ var NcAlarmModeDelaysEditListSchema = array(object({
20530
20545
  triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
20531
20546
  postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
20532
20547
  /** Set a schedule, or `null` to clear (mode always allowed again). */
20533
- schedule: NcScheduleSchema.nullable().optional()
20548
+ schedule: NcScheduleSchema.nullable().optional(),
20549
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
20550
+ notifyDuringEntryDelay: boolean().nullable().optional(),
20551
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
20552
+ notifySensorRewatched: boolean().nullable().optional()
20534
20553
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
20535
20554
  /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
20536
20555
  var NcAlarmNonBlockingEditSchema = object({
@@ -21491,39 +21510,19 @@ Object.freeze(Object.fromEntries([{
21491
21510
  label: "Face recognition model",
21492
21511
  defaultModelId: "auraface-r100",
21493
21512
  indexName: "the enrolled face gallery",
21494
- options: [
21495
- {
21496
- id: "auraface-r100",
21497
- label: "AuraFace R100"
21498
- },
21499
- {
21500
- id: "arcface-r100",
21501
- label: "ArcFace (ResNet34)"
21502
- },
21503
- {
21504
- id: "inception-resnet-v1",
21505
- label: "Inception ResNet V1"
21506
- }
21507
- ]
21513
+ options: [{
21514
+ id: "auraface-r100",
21515
+ label: "AuraFace R100"
21516
+ }]
21508
21517
  }, {
21509
21518
  stepId: "clip-embedding",
21510
21519
  label: "Semantic search model",
21511
- defaultModelId: "mobileclip-s1",
21520
+ defaultModelId: "siglip2-b16-224",
21512
21521
  indexName: "the object semantic-search index",
21513
- options: [
21514
- {
21515
- id: "mobileclip-s1",
21516
- label: "MobileCLIP S1"
21517
- },
21518
- {
21519
- id: "mobileclip-s2",
21520
- label: "MobileCLIP S2"
21521
- },
21522
- {
21523
- id: "siglip2-b16-224",
21524
- label: "SigLIP2 B/16 (Apache-2.0)"
21525
- }
21526
- ]
21522
+ options: [{
21523
+ id: "siglip2-b16-224",
21524
+ label: "SigLIP2 B/16 (Apache-2.0)"
21525
+ }]
21527
21526
  }].map((s) => [s.stepId, s.defaultModelId])));
21528
21527
  var CLUSTER_STEP_SETTING_FIELDS = [{
21529
21528
  stepId: "face-embedding",
@@ -24411,6 +24410,22 @@ var MotionSourceEnum = _enum([
24411
24410
  "device-activity"
24412
24411
  ]);
24413
24412
  /**
24413
+ * What opened an on-motion detection SESSION: the motion source that passed the
24414
+ * camera's `motionSources` gate, and what raised it (the camera itself, or a
24415
+ * sensor the operator attached — D672). `sensorName` is the attached sensor's
24416
+ * device name as the orchestrator's camera-sensors resolution last read it;
24417
+ * absent when unknown or when the camera itself triggered.
24418
+ *
24419
+ * Carried on the session attach ONLY so the runner's `DetectionPhaseTransition`
24420
+ * can say what started the session (D672 rule 11, amended 2026-10-06). The
24421
+ * runner never decides anything on it.
24422
+ */
24423
+ var SessionTriggerSchema = object({
24424
+ source: MotionSourceEnum,
24425
+ triggeredBy: MotionTriggeredBySchema,
24426
+ sensorName: string().optional()
24427
+ });
24428
+ /**
24414
24429
  * List of motion sources active on a camera. Empty array is valid:
24415
24430
  * "no source" — happens for battery cams without firmware motion when
24416
24431
  * the operator hasn't opted into the SW analyzer (would hold the
@@ -24662,6 +24677,14 @@ var RunnerCameraConfigSchema = object({
24662
24677
  */
24663
24678
  motionSources: MotionSourcesSchema.default(["analyzer"]),
24664
24679
  /**
24680
+ * What opened this attach, on a SESSION attach only (see
24681
+ * {@link SessionTriggerSchema}). OPTIONAL with no default: absent on a
24682
+ * standing attach, an occupancy burst, a re-dispatch with no motion event
24683
+ * behind it, and every attach from an orchestrator older than the field — the
24684
+ * runner then names no source on the phase event.
24685
+ */
24686
+ sessionTrigger: SessionTriggerSchema.optional(),
24687
+ /**
24665
24688
  * WHICH root detector runs for this camera. The detection counterpart of
24666
24689
  * {@link motionSources}, same shape and same discipline: a per-camera list
24667
24690
  * of sources the system understands, vendor-agnostic, owned here.
@@ -32563,7 +32586,7 @@ var LocalInterfaceSchema = object({
32563
32586
  name: string(),
32564
32587
  family: _enum(["IPv4", "IPv6"]),
32565
32588
  address: string(),
32566
- /** CIDR shorthand (e.g. `192.168.x.x/24`). Empty when OS doesn't expose. */
32589
+ /** CIDR shorthand (e.g. `192.168.10.10/24`). Empty when OS doesn't expose. */
32567
32590
  cidr: string(),
32568
32591
  /** OS netmask. Stable across calls so the SDK can hash on it. */
32569
32592
  netmask: string(),
@@ -32617,7 +32640,8 @@ var ConnectionEndpointSchema = object({
32617
32640
  "lan-ipv4",
32618
32641
  "lan-ipv6",
32619
32642
  "public",
32620
- "loopback"
32643
+ "loopback",
32644
+ "app-link"
32621
32645
  ]),
32622
32646
  /**
32623
32647
  * Originating-interface kind — `lan`/`wifi`/`docker`/`vpn`/`other`/
@@ -32686,15 +32710,27 @@ var GetConnectionEndpointsResultSchema = object({
32686
32710
  localPort: AdvertisedLocalPortSchema
32687
32711
  });
32688
32712
  /**
32689
- * The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
32690
- * AUTO (resolved from the candidate ranking at send time); `resolved` reports
32691
- * what AUTO currently picks, so the UI can show the effective value either way.
32713
+ * The address flagged for notification links. `baseUrl: null` = AUTO, which
32714
+ * since D709 is the CamStack app link; `resolved` reports the effective value,
32715
+ * so the UI can show it either way.
32692
32716
  */
32693
32717
  var NotificationEndpointSchema = object({
32694
32718
  /** The operator's explicit choice, or null for AUTO. */
32695
32719
  baseUrl: string().nullable(),
32696
- /** What the ranking currently resolves to (null when nothing is reachable). */
32697
- resolved: string().nullable()
32720
+ /**
32721
+ * The effective flagged address: the explicit choice, else (AUTO) the
32722
+ * CamStack app link `https://camstack.zentik.app` (D709). A pre-D709 hub
32723
+ * answered the public tunnel / mesh here, or null.
32724
+ */
32725
+ resolved: string().nullable(),
32726
+ /**
32727
+ * The hub origin an app link carries as `hub=` (D709): the hub's best
32728
+ * public HTTPS address — the tunnel, then the mesh (Tailscale MagicDNS) —
32729
+ * picked from this cap's own palette by `pickAppLinkHub`. `null` when the
32730
+ * hub advertises neither; the app link is then minted without `hub=`.
32731
+ * Absent on a pre-D709 hub.
32732
+ */
32733
+ appLinkHub: string().nullable()
32698
32734
  });
32699
32735
  /**
32700
32736
  * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
@@ -32748,7 +32784,11 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
32748
32784
  * Pass `'https'` when the caller is itself loaded over HTTPS
32749
32785
  * to avoid mixed-content blocks in the browser. The public
32750
32786
  * tunnel always emits `https://` regardless. */
32751
- scheme: _enum(["http", "https"]).optional()
32787
+ scheme: _enum(["http", "https"]).optional(),
32788
+ /** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
32789
+ * an address notification links can be flagged with, not a hub
32790
+ * route. Default `false`: racers and rankers never see it. */
32791
+ includeAppLink: boolean().optional()
32752
32792
  }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
32753
32793
  kind: "mutation",
32754
32794
  auth: "admin"
@@ -33077,7 +33117,7 @@ var MeshPeerSchema = object({
33077
33117
  tags: array(string()).readonly(),
33078
33118
  /** True when the peer advertises itself as an exit-node candidate. */
33079
33119
  exitNodeOption: boolean(),
33080
- /** Subnet routes the peer advertises (e.g. `["192.168.x.x/24"]`). */
33120
+ /** Subnet routes the peer advertises (e.g. `["192.168.10.0/24"]`). */
33081
33121
  advertisedRoutes: array(string()).readonly(),
33082
33122
  /** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
33083
33123
  userLogin: string().nullable(),
@@ -34405,7 +34445,13 @@ var OsdStatusSchema = object({ overlays: array(object({
34405
34445
  */
34406
34446
  availablePositions: array(OsdPositionEnum).readonly(),
34407
34447
  /** Firmware does not allow editing the `text` field (e.g. timestamp). */
34408
- readOnly: boolean().optional()
34448
+ readOnly: boolean().optional(),
34449
+ /**
34450
+ * Firmware text ceiling for this overlay. Absent = no known limit.
34451
+ * The OSD manager truncates here on every write — never stores its own
34452
+ * copy on the binding.
34453
+ */
34454
+ maxCharacters: number().int().positive().optional()
34409
34455
  })).readonly() });
34410
34456
  var OsdOverlayPatchSchema = object({
34411
34457
  enabled: boolean().optional(),
@@ -34502,7 +34548,9 @@ var OsdTemplateBindingSchema = object({
34502
34548
  valuePath: string().min(1).max(64),
34503
34549
  /** Convert TO this unit at render (`tryConvertUnit`). Absent = source unit. */
34504
34550
  displayUnit: string().max(16).optional(),
34505
- maxDecimals: number().int().min(0).max(4).default(1)
34551
+ maxDecimals: number().int().min(0).max(4).default(1),
34552
+ /** Raw value → display text (same shape as slot binding). Empty string hides. */
34553
+ valueMap: record(string(), string()).optional()
34506
34554
  });
34507
34555
  /**
34508
34556
  * A named template: bindings (alias → leaf field) + a parser that
@@ -34552,18 +34600,11 @@ var OsdSlotBindingSchema = object({
34552
34600
  source: OsdSourceSchema,
34553
34601
  /** `${value}` and `${unit}` are substituted; every occurrence. */
34554
34602
  template: string().max(96).default("${value}"),
34555
- /** Truncate with an ellipsis past this length. Absent = no limit. */
34556
- maxCharacters: number().int().min(4).max(64).optional(),
34557
34603
  /**
34558
34604
  * Decimal places for a numeric value. `0` yields an integer — the
34559
34605
  * documented workaround for firmwares that reject `.` in overlay text.
34560
34606
  */
34561
34607
  maxDecimals: number().int().min(0).max(4).default(1),
34562
- /**
34563
- * Appended via `${unit}` when no unit conversion produces a label.
34564
- * Prefer `source.displayUnit` for converted device-state values.
34565
- */
34566
- unitLabel: string().max(8).optional(),
34567
34608
  /** Raw value → display text, e.g. `{"true":"MOTION","false":""}`. */
34568
34609
  valueMap: record(string(), string()).optional(),
34569
34610
  /** Time windows in which the slot is shown. Absent = always. */
@@ -34572,9 +34613,7 @@ var OsdSlotBindingSchema = object({
34572
34613
  * Display gate, in the notification centre's condition vocabulary.
34573
34614
  * Only the keys reported by `getConditionSupport` are accepted.
34574
34615
  */
34575
- conditions: NcConditionsSchema.optional(),
34576
- /** Rendered when the gate is closed or the value unreadable. Empty = hide. */
34577
- fallbackText: string().max(64).default("")
34616
+ conditions: NcConditionsSchema.optional()
34578
34617
  });
34579
34618
  /** One camera slot, as the operator sees it: firmware truth + our binding. */
34580
34619
  var OsdSlotViewSchema = object({
@@ -53429,12 +53468,14 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
53429
53468
  {
53430
53469
  id: "addons",
53431
53470
  family: "system",
53432
- label: "Addons",
53433
- kinds: [
53434
- "addon-crash-loop",
53435
- "addon-update-available",
53436
- "addon-updated"
53437
- ]
53471
+ label: "Addons stopped",
53472
+ kinds: ["addon-crash-loop"]
53473
+ },
53474
+ {
53475
+ id: "addon-updates",
53476
+ family: "system",
53477
+ label: "Addon updates",
53478
+ kinds: ["addon-update-available", "addon-updated"]
53438
53479
  },
53439
53480
  {
53440
53481
  id: "updates",
@@ -53594,13 +53635,15 @@ var STATE_SUMMARY_SECTION_VARS = [
53594
53635
  },
53595
53636
  {
53596
53637
  name: "summaryAddons",
53597
- label: "Summary: addons",
53598
- example: "@camstack/addon-recorder 1.2.3 → 1.2.4",
53599
- kinds: [
53600
- "addon-crash-loop",
53601
- "addon-update-available",
53602
- "addon-updated"
53603
- ]
53638
+ label: "Summary: addons stopped",
53639
+ example: "hub — recorder stopped after repeated crashes",
53640
+ kinds: ["addon-crash-loop"]
53641
+ },
53642
+ {
53643
+ name: "summaryAddonUpdates",
53644
+ label: "Summary: addon updates",
53645
+ example: "hub:\n• @camstack/addon-recorder 1.2.3 → 1.2.4",
53646
+ kinds: ["addon-update-available", "addon-updated"]
53604
53647
  },
53605
53648
  {
53606
53649
  name: "summaryUpdates",
@@ -53684,6 +53727,7 @@ var STATE_SUMMARY_VARS = [
53684
53727
  [...RULE_BODY_ONLY],
53685
53728
  [...RULE_TEXT],
53686
53729
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
53730
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
53687
53731
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
53688
53732
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
53689
53733
  ([...RULE_TEXT], [...CONSUMABLE]),
@@ -53724,6 +53768,8 @@ var STATE_SUMMARY_VARS = [
53724
53768
  [...RULE_TEXT],
53725
53769
  [...RULE_TEXT],
53726
53770
  [...RULE_TEXT],
53771
+ [...RULE_TEXT],
53772
+ [...RULE_TEXT],
53727
53773
  ...STATE_SUMMARY_VARS
53728
53774
  ];
53729
53775
  new Set([
@@ -56666,7 +56712,7 @@ var AmcrestCamera = class AmcrestCamera extends BaseDevice {
56666
56712
  key: "host",
56667
56713
  label: "Camera IP",
56668
56714
  required: true,
56669
- placeholder: "192.168.x.x"
56715
+ placeholder: "192.168.10.100"
56670
56716
  },
56671
56717
  {
56672
56718
  type: "number",
@@ -70888,13 +70934,13 @@ function enumerateHosts(cidr) {
70888
70934
  for (let d = 1; d <= 254; d += 1) out.push(`${a}.${b}.${c}.${d}`);
70889
70935
  return out;
70890
70936
  }
70891
- /** Best-effort local /24 from the first non-internal IPv4 interface (e.g. `192.168.x.x/24`). */
70937
+ /** Best-effort local /24 from the first non-internal IPv4 interface (e.g. `192.168.10.0/24`). */
70892
70938
  function detectLocalCidr() {
70893
70939
  for (const addrs of Object.values((0, node_os.networkInterfaces)())) for (const addr of addrs ?? []) if (addr.family === "IPv4" && !addr.internal) {
70894
70940
  const [a, b, c] = addr.address.split(".");
70895
70941
  return `${a}.${b}.${c}.0/24`;
70896
70942
  }
70897
- return "192.168.x.x/24";
70943
+ return "192.168.10.0/24";
70898
70944
  }
70899
70945
  /** Flatten a host into a flat row-key slug — must match `generateStableId`'s host fallback so a
70900
70946
  * re-scan of a host-added camera is detected as already onboarded. */
@@ -70963,7 +71009,7 @@ function buildCreationFormSchema() {
70963
71009
  key: "host",
70964
71010
  label: "Camera IP",
70965
71011
  required: true,
70966
- placeholder: "192.168.x.x",
71012
+ placeholder: "192.168.10.100",
70967
71013
  inputType: "text"
70968
71014
  },
70969
71015
  {
@@ -71014,14 +71060,14 @@ function buildDiscoveryParamsFormSchema() {
71014
71060
  }, {
71015
71061
  id: "scan",
71016
71062
  title: "Scan options",
71017
- description: "The credentialed CGI subnet scan is the reliable path (multicast WS-Discovery is not received on a macvlan/br0 hub). IMPORTANT: leaving the network blank scans only the HUB’s own subnet — if your cameras are on a DIFFERENT subnet than the hub, you MUST enter their CIDR here (e.g. 192.168.x.x/24), otherwise the scan returns nothing.",
71063
+ description: "The credentialed CGI subnet scan is the reliable path (multicast WS-Discovery is not received on a macvlan/br0 hub). IMPORTANT: leaving the network blank scans only the HUB’s own subnet — if your cameras are on a DIFFERENT subnet than the hub, you MUST enter their CIDR here (e.g. 192.168.60.0/24), otherwise the scan returns nothing.",
71018
71064
  columns: 1,
71019
71065
  fields: [{
71020
71066
  type: "text",
71021
71067
  key: "networkCidr",
71022
71068
  label: "Network (CIDR) — required if cameras are on a different subnet than the hub",
71023
71069
  required: false,
71024
- placeholder: "192.168.x.x/24"
71070
+ placeholder: "192.168.60.0/24"
71025
71071
  }, {
71026
71072
  type: "number",
71027
71073
  key: "timeoutMs",
package/dist/addon.mjs CHANGED
@@ -10558,11 +10558,11 @@ var ModelVariantGroupSchema = object({
10558
10558
  /** Quantization axis. Omit ⇒ the fp32 base build. */
10559
10559
  precision: _enum(["fp32", "int8"]).optional(),
10560
10560
  /**
10561
- * Speed-optimization axis. Omit ⇒ the standard build. `fast` marks a
10562
- * latency-optimized export (e.g. ReLU-activation variant) — the slot the
10563
- * future performance variants plug into.
10561
+ * Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
10562
+ * an alternate training of the same family (Scrypted `relu_test`); chip
10563
+ * label is "Test".
10564
10564
  */
10565
- optimization: _enum(["standard", "fast"]).optional(),
10565
+ optimization: _enum(["standard", "test"]).optional(),
10566
10566
  /**
10567
10567
  * Input-resolution axis (square input side, px). Omit ⇒ the family's native
10568
10568
  * resolution (640 for yolo26). Reduced-input builds (320 / 256) are a big,
@@ -10585,9 +10585,10 @@ var ModelProviderIdSchema = _enum([
10585
10585
  * are per upstream. A persisted custom-model row written when this field was a
10586
10586
  * string still parses — the string is lifted into `{ weights }`.
10587
10587
  *
10588
- * Every licence surface (the admin "Models and licenses" page,
10589
- * `THIRD_PARTY_MODELS.md`, the Hugging Face model table) is GENERATED from
10590
- * these records by `scripts/gen-model-licenses.ts` (D661).
10588
+ * Every machine licence surface (`THIRD_PARTY_MODELS.md`, the Hugging Face
10589
+ * model table) is GENERATED from these records by
10590
+ * `scripts/gen-model-licenses.ts` (D661). Operator-facing docs live in
10591
+ * `camstack/docs` → `/docs/detection/models`.
10591
10592
  */
10592
10593
  var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { weights: value } : value, object({
10593
10594
  /** SPDX id of the WEIGHTS' terms, a `LicenseRef-*` for non-SPDX terms, or `UNKNOWN`. */
@@ -14218,7 +14219,7 @@ DeviceType.Camera;
14218
14219
  * This matters here more than anywhere else in the repo, because every provider
14219
14220
  * that knows a device's host knows its PASSWORD too: `{ host, port, username,
14220
14221
  * password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
14221
- * and `http://admin:hunter2@192.168.x.x/` is a URL a browser accepts. The
14222
+ * and `http://admin:hunter2@192.168.60.139/` is a URL a browser accepts. The
14222
14223
  * camera's own page will ask for its own login. That is correct, and pre-
14223
14224
  * filling it is the operator's business, not ours.
14224
14225
  *
@@ -17503,7 +17504,7 @@ method(object({
17503
17504
  timeoutMs: 6e5
17504
17505
  });
17505
17506
  method(object({
17506
- nodeId: string(),
17507
+ targetNodeId: string(),
17507
17508
  modelId: string(),
17508
17509
  format: _enum(MODEL_FORMATS),
17509
17510
  entry: ModelCatalogEntrySchema
@@ -20007,8 +20008,9 @@ var NcRuleSchema = NcRuleInputSchema.extend({
20007
20008
  disabledTargetIds: array(string()).default([])
20008
20009
  });
20009
20010
  /**
20010
- * The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
20011
- * still-true state. `backups-exports` and `alarm` are not sections — a completed
20011
+ * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
20012
+ * report a still-true state. `addons` is the crash-looped addons only and
20013
+ * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
20012
20014
  * job is not an open state, and the alarm stays instant.
20013
20015
  */
20014
20016
  var NcStateSummarySectionIdSchema = _enum([
@@ -20020,6 +20022,7 @@ var NcStateSummarySectionIdSchema = _enum([
20020
20022
  "detection-blind",
20021
20023
  "nodes",
20022
20024
  "addons",
20025
+ "addon-updates",
20023
20026
  "updates"
20024
20027
  ]);
20025
20028
  /** One section of a previewed state summary. `unavailable` = its state could not be read. */
@@ -20500,7 +20503,19 @@ var NcAlarmModeDelaysListSchema = array(object({
20500
20503
  * When this mode may be armed. Absent / null = always allowed (same as a
20501
20504
  * rule with no `schedule`). Evaluated with {@link isScheduleActive}.
20502
20505
  */
20503
- schedule: NcScheduleSchema.optional()
20506
+ schedule: NcScheduleSchema.optional(),
20507
+ /**
20508
+ * D706: while this mode's ENTRY DELAY runs, do the alarm rules' own pushes go out (as an
20509
+ * intrusion naming the locations)? Absent = false — the entry-delay notification is the
20510
+ * only one, and the matches ride the triggered notification's mosaic (D705).
20511
+ */
20512
+ notifyDuringEntryDelay: boolean().optional(),
20513
+ /**
20514
+ * D706: notify "watched again" when a sensor this arm bypassed closes and opens again.
20515
+ * Absent = false (logged, not sent). Even when true it is not sent when that same sensor
20516
+ * is the one that starts the entry delay — the entry-delay notification already names it.
20517
+ */
20518
+ notifySensorRewatched: boolean().optional()
20504
20519
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
20505
20520
  var NcAlarmModeDelaysEditListSchema = array(object({
20506
20521
  mode: AlarmArmModeSchema,
@@ -20509,7 +20524,11 @@ var NcAlarmModeDelaysEditListSchema = array(object({
20509
20524
  triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
20510
20525
  postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
20511
20526
  /** Set a schedule, or `null` to clear (mode always allowed again). */
20512
- schedule: NcScheduleSchema.nullable().optional()
20527
+ schedule: NcScheduleSchema.nullable().optional(),
20528
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
20529
+ notifyDuringEntryDelay: boolean().nullable().optional(),
20530
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
20531
+ notifySensorRewatched: boolean().nullable().optional()
20513
20532
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
20514
20533
  /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
20515
20534
  var NcAlarmNonBlockingEditSchema = object({
@@ -21470,39 +21489,19 @@ Object.freeze(Object.fromEntries([{
21470
21489
  label: "Face recognition model",
21471
21490
  defaultModelId: "auraface-r100",
21472
21491
  indexName: "the enrolled face gallery",
21473
- options: [
21474
- {
21475
- id: "auraface-r100",
21476
- label: "AuraFace R100"
21477
- },
21478
- {
21479
- id: "arcface-r100",
21480
- label: "ArcFace (ResNet34)"
21481
- },
21482
- {
21483
- id: "inception-resnet-v1",
21484
- label: "Inception ResNet V1"
21485
- }
21486
- ]
21492
+ options: [{
21493
+ id: "auraface-r100",
21494
+ label: "AuraFace R100"
21495
+ }]
21487
21496
  }, {
21488
21497
  stepId: "clip-embedding",
21489
21498
  label: "Semantic search model",
21490
- defaultModelId: "mobileclip-s1",
21499
+ defaultModelId: "siglip2-b16-224",
21491
21500
  indexName: "the object semantic-search index",
21492
- options: [
21493
- {
21494
- id: "mobileclip-s1",
21495
- label: "MobileCLIP S1"
21496
- },
21497
- {
21498
- id: "mobileclip-s2",
21499
- label: "MobileCLIP S2"
21500
- },
21501
- {
21502
- id: "siglip2-b16-224",
21503
- label: "SigLIP2 B/16 (Apache-2.0)"
21504
- }
21505
- ]
21501
+ options: [{
21502
+ id: "siglip2-b16-224",
21503
+ label: "SigLIP2 B/16 (Apache-2.0)"
21504
+ }]
21506
21505
  }].map((s) => [s.stepId, s.defaultModelId])));
21507
21506
  var CLUSTER_STEP_SETTING_FIELDS = [{
21508
21507
  stepId: "face-embedding",
@@ -24390,6 +24389,22 @@ var MotionSourceEnum = _enum([
24390
24389
  "device-activity"
24391
24390
  ]);
24392
24391
  /**
24392
+ * What opened an on-motion detection SESSION: the motion source that passed the
24393
+ * camera's `motionSources` gate, and what raised it (the camera itself, or a
24394
+ * sensor the operator attached — D672). `sensorName` is the attached sensor's
24395
+ * device name as the orchestrator's camera-sensors resolution last read it;
24396
+ * absent when unknown or when the camera itself triggered.
24397
+ *
24398
+ * Carried on the session attach ONLY so the runner's `DetectionPhaseTransition`
24399
+ * can say what started the session (D672 rule 11, amended 2026-10-06). The
24400
+ * runner never decides anything on it.
24401
+ */
24402
+ var SessionTriggerSchema = object({
24403
+ source: MotionSourceEnum,
24404
+ triggeredBy: MotionTriggeredBySchema,
24405
+ sensorName: string().optional()
24406
+ });
24407
+ /**
24393
24408
  * List of motion sources active on a camera. Empty array is valid:
24394
24409
  * "no source" — happens for battery cams without firmware motion when
24395
24410
  * the operator hasn't opted into the SW analyzer (would hold the
@@ -24641,6 +24656,14 @@ var RunnerCameraConfigSchema = object({
24641
24656
  */
24642
24657
  motionSources: MotionSourcesSchema.default(["analyzer"]),
24643
24658
  /**
24659
+ * What opened this attach, on a SESSION attach only (see
24660
+ * {@link SessionTriggerSchema}). OPTIONAL with no default: absent on a
24661
+ * standing attach, an occupancy burst, a re-dispatch with no motion event
24662
+ * behind it, and every attach from an orchestrator older than the field — the
24663
+ * runner then names no source on the phase event.
24664
+ */
24665
+ sessionTrigger: SessionTriggerSchema.optional(),
24666
+ /**
24644
24667
  * WHICH root detector runs for this camera. The detection counterpart of
24645
24668
  * {@link motionSources}, same shape and same discipline: a per-camera list
24646
24669
  * of sources the system understands, vendor-agnostic, owned here.
@@ -32542,7 +32565,7 @@ var LocalInterfaceSchema = object({
32542
32565
  name: string(),
32543
32566
  family: _enum(["IPv4", "IPv6"]),
32544
32567
  address: string(),
32545
- /** CIDR shorthand (e.g. `192.168.x.x/24`). Empty when OS doesn't expose. */
32568
+ /** CIDR shorthand (e.g. `192.168.10.10/24`). Empty when OS doesn't expose. */
32546
32569
  cidr: string(),
32547
32570
  /** OS netmask. Stable across calls so the SDK can hash on it. */
32548
32571
  netmask: string(),
@@ -32596,7 +32619,8 @@ var ConnectionEndpointSchema = object({
32596
32619
  "lan-ipv4",
32597
32620
  "lan-ipv6",
32598
32621
  "public",
32599
- "loopback"
32622
+ "loopback",
32623
+ "app-link"
32600
32624
  ]),
32601
32625
  /**
32602
32626
  * Originating-interface kind — `lan`/`wifi`/`docker`/`vpn`/`other`/
@@ -32665,15 +32689,27 @@ var GetConnectionEndpointsResultSchema = object({
32665
32689
  localPort: AdvertisedLocalPortSchema
32666
32690
  });
32667
32691
  /**
32668
- * The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
32669
- * AUTO (resolved from the candidate ranking at send time); `resolved` reports
32670
- * what AUTO currently picks, so the UI can show the effective value either way.
32692
+ * The address flagged for notification links. `baseUrl: null` = AUTO, which
32693
+ * since D709 is the CamStack app link; `resolved` reports the effective value,
32694
+ * so the UI can show it either way.
32671
32695
  */
32672
32696
  var NotificationEndpointSchema = object({
32673
32697
  /** The operator's explicit choice, or null for AUTO. */
32674
32698
  baseUrl: string().nullable(),
32675
- /** What the ranking currently resolves to (null when nothing is reachable). */
32676
- resolved: string().nullable()
32699
+ /**
32700
+ * The effective flagged address: the explicit choice, else (AUTO) the
32701
+ * CamStack app link `https://camstack.zentik.app` (D709). A pre-D709 hub
32702
+ * answered the public tunnel / mesh here, or null.
32703
+ */
32704
+ resolved: string().nullable(),
32705
+ /**
32706
+ * The hub origin an app link carries as `hub=` (D709): the hub's best
32707
+ * public HTTPS address — the tunnel, then the mesh (Tailscale MagicDNS) —
32708
+ * picked from this cap's own palette by `pickAppLinkHub`. `null` when the
32709
+ * hub advertises neither; the app link is then minted without `hub=`.
32710
+ * Absent on a pre-D709 hub.
32711
+ */
32712
+ appLinkHub: string().nullable()
32677
32713
  });
32678
32714
  /**
32679
32715
  * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
@@ -32727,7 +32763,11 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
32727
32763
  * Pass `'https'` when the caller is itself loaded over HTTPS
32728
32764
  * to avoid mixed-content blocks in the browser. The public
32729
32765
  * tunnel always emits `https://` regardless. */
32730
- scheme: _enum(["http", "https"]).optional()
32766
+ scheme: _enum(["http", "https"]).optional(),
32767
+ /** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
32768
+ * an address notification links can be flagged with, not a hub
32769
+ * route. Default `false`: racers and rankers never see it. */
32770
+ includeAppLink: boolean().optional()
32731
32771
  }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
32732
32772
  kind: "mutation",
32733
32773
  auth: "admin"
@@ -33056,7 +33096,7 @@ var MeshPeerSchema = object({
33056
33096
  tags: array(string()).readonly(),
33057
33097
  /** True when the peer advertises itself as an exit-node candidate. */
33058
33098
  exitNodeOption: boolean(),
33059
- /** Subnet routes the peer advertises (e.g. `["192.168.x.x/24"]`). */
33099
+ /** Subnet routes the peer advertises (e.g. `["192.168.10.0/24"]`). */
33060
33100
  advertisedRoutes: array(string()).readonly(),
33061
33101
  /** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
33062
33102
  userLogin: string().nullable(),
@@ -34384,7 +34424,13 @@ var OsdStatusSchema = object({ overlays: array(object({
34384
34424
  */
34385
34425
  availablePositions: array(OsdPositionEnum).readonly(),
34386
34426
  /** Firmware does not allow editing the `text` field (e.g. timestamp). */
34387
- readOnly: boolean().optional()
34427
+ readOnly: boolean().optional(),
34428
+ /**
34429
+ * Firmware text ceiling for this overlay. Absent = no known limit.
34430
+ * The OSD manager truncates here on every write — never stores its own
34431
+ * copy on the binding.
34432
+ */
34433
+ maxCharacters: number().int().positive().optional()
34388
34434
  })).readonly() });
34389
34435
  var OsdOverlayPatchSchema = object({
34390
34436
  enabled: boolean().optional(),
@@ -34481,7 +34527,9 @@ var OsdTemplateBindingSchema = object({
34481
34527
  valuePath: string().min(1).max(64),
34482
34528
  /** Convert TO this unit at render (`tryConvertUnit`). Absent = source unit. */
34483
34529
  displayUnit: string().max(16).optional(),
34484
- maxDecimals: number().int().min(0).max(4).default(1)
34530
+ maxDecimals: number().int().min(0).max(4).default(1),
34531
+ /** Raw value → display text (same shape as slot binding). Empty string hides. */
34532
+ valueMap: record(string(), string()).optional()
34485
34533
  });
34486
34534
  /**
34487
34535
  * A named template: bindings (alias → leaf field) + a parser that
@@ -34531,18 +34579,11 @@ var OsdSlotBindingSchema = object({
34531
34579
  source: OsdSourceSchema,
34532
34580
  /** `${value}` and `${unit}` are substituted; every occurrence. */
34533
34581
  template: string().max(96).default("${value}"),
34534
- /** Truncate with an ellipsis past this length. Absent = no limit. */
34535
- maxCharacters: number().int().min(4).max(64).optional(),
34536
34582
  /**
34537
34583
  * Decimal places for a numeric value. `0` yields an integer — the
34538
34584
  * documented workaround for firmwares that reject `.` in overlay text.
34539
34585
  */
34540
34586
  maxDecimals: number().int().min(0).max(4).default(1),
34541
- /**
34542
- * Appended via `${unit}` when no unit conversion produces a label.
34543
- * Prefer `source.displayUnit` for converted device-state values.
34544
- */
34545
- unitLabel: string().max(8).optional(),
34546
34587
  /** Raw value → display text, e.g. `{"true":"MOTION","false":""}`. */
34547
34588
  valueMap: record(string(), string()).optional(),
34548
34589
  /** Time windows in which the slot is shown. Absent = always. */
@@ -34551,9 +34592,7 @@ var OsdSlotBindingSchema = object({
34551
34592
  * Display gate, in the notification centre's condition vocabulary.
34552
34593
  * Only the keys reported by `getConditionSupport` are accepted.
34553
34594
  */
34554
- conditions: NcConditionsSchema.optional(),
34555
- /** Rendered when the gate is closed or the value unreadable. Empty = hide. */
34556
- fallbackText: string().max(64).default("")
34595
+ conditions: NcConditionsSchema.optional()
34557
34596
  });
34558
34597
  /** One camera slot, as the operator sees it: firmware truth + our binding. */
34559
34598
  var OsdSlotViewSchema = object({
@@ -53408,12 +53447,14 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
53408
53447
  {
53409
53448
  id: "addons",
53410
53449
  family: "system",
53411
- label: "Addons",
53412
- kinds: [
53413
- "addon-crash-loop",
53414
- "addon-update-available",
53415
- "addon-updated"
53416
- ]
53450
+ label: "Addons stopped",
53451
+ kinds: ["addon-crash-loop"]
53452
+ },
53453
+ {
53454
+ id: "addon-updates",
53455
+ family: "system",
53456
+ label: "Addon updates",
53457
+ kinds: ["addon-update-available", "addon-updated"]
53417
53458
  },
53418
53459
  {
53419
53460
  id: "updates",
@@ -53573,13 +53614,15 @@ var STATE_SUMMARY_SECTION_VARS = [
53573
53614
  },
53574
53615
  {
53575
53616
  name: "summaryAddons",
53576
- label: "Summary: addons",
53577
- example: "@camstack/addon-recorder 1.2.3 → 1.2.4",
53578
- kinds: [
53579
- "addon-crash-loop",
53580
- "addon-update-available",
53581
- "addon-updated"
53582
- ]
53617
+ label: "Summary: addons stopped",
53618
+ example: "hub — recorder stopped after repeated crashes",
53619
+ kinds: ["addon-crash-loop"]
53620
+ },
53621
+ {
53622
+ name: "summaryAddonUpdates",
53623
+ label: "Summary: addon updates",
53624
+ example: "hub:\n• @camstack/addon-recorder 1.2.3 → 1.2.4",
53625
+ kinds: ["addon-update-available", "addon-updated"]
53583
53626
  },
53584
53627
  {
53585
53628
  name: "summaryUpdates",
@@ -53663,6 +53706,7 @@ var STATE_SUMMARY_VARS = [
53663
53706
  [...RULE_BODY_ONLY],
53664
53707
  [...RULE_TEXT],
53665
53708
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
53709
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
53666
53710
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
53667
53711
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
53668
53712
  ([...RULE_TEXT], [...CONSUMABLE]),
@@ -53703,6 +53747,8 @@ var STATE_SUMMARY_VARS = [
53703
53747
  [...RULE_TEXT],
53704
53748
  [...RULE_TEXT],
53705
53749
  [...RULE_TEXT],
53750
+ [...RULE_TEXT],
53751
+ [...RULE_TEXT],
53706
53752
  ...STATE_SUMMARY_VARS
53707
53753
  ];
53708
53754
  new Set([
@@ -56645,7 +56691,7 @@ var AmcrestCamera = class AmcrestCamera extends BaseDevice {
56645
56691
  key: "host",
56646
56692
  label: "Camera IP",
56647
56693
  required: true,
56648
- placeholder: "192.168.x.x"
56694
+ placeholder: "192.168.10.100"
56649
56695
  },
56650
56696
  {
56651
56697
  type: "number",
@@ -70867,13 +70913,13 @@ function enumerateHosts(cidr) {
70867
70913
  for (let d = 1; d <= 254; d += 1) out.push(`${a}.${b}.${c}.${d}`);
70868
70914
  return out;
70869
70915
  }
70870
- /** Best-effort local /24 from the first non-internal IPv4 interface (e.g. `192.168.x.x/24`). */
70916
+ /** Best-effort local /24 from the first non-internal IPv4 interface (e.g. `192.168.10.0/24`). */
70871
70917
  function detectLocalCidr() {
70872
70918
  for (const addrs of Object.values(networkInterfaces())) for (const addr of addrs ?? []) if (addr.family === "IPv4" && !addr.internal) {
70873
70919
  const [a, b, c] = addr.address.split(".");
70874
70920
  return `${a}.${b}.${c}.0/24`;
70875
70921
  }
70876
- return "192.168.x.x/24";
70922
+ return "192.168.10.0/24";
70877
70923
  }
70878
70924
  /** Flatten a host into a flat row-key slug — must match `generateStableId`'s host fallback so a
70879
70925
  * re-scan of a host-added camera is detected as already onboarded. */
@@ -70942,7 +70988,7 @@ function buildCreationFormSchema() {
70942
70988
  key: "host",
70943
70989
  label: "Camera IP",
70944
70990
  required: true,
70945
- placeholder: "192.168.x.x",
70991
+ placeholder: "192.168.10.100",
70946
70992
  inputType: "text"
70947
70993
  },
70948
70994
  {
@@ -70993,14 +71039,14 @@ function buildDiscoveryParamsFormSchema() {
70993
71039
  }, {
70994
71040
  id: "scan",
70995
71041
  title: "Scan options",
70996
- description: "The credentialed CGI subnet scan is the reliable path (multicast WS-Discovery is not received on a macvlan/br0 hub). IMPORTANT: leaving the network blank scans only the HUB’s own subnet — if your cameras are on a DIFFERENT subnet than the hub, you MUST enter their CIDR here (e.g. 192.168.x.x/24), otherwise the scan returns nothing.",
71042
+ description: "The credentialed CGI subnet scan is the reliable path (multicast WS-Discovery is not received on a macvlan/br0 hub). IMPORTANT: leaving the network blank scans only the HUB’s own subnet — if your cameras are on a DIFFERENT subnet than the hub, you MUST enter their CIDR here (e.g. 192.168.60.0/24), otherwise the scan returns nothing.",
70997
71043
  columns: 1,
70998
71044
  fields: [{
70999
71045
  type: "text",
71000
71046
  key: "networkCidr",
71001
71047
  label: "Network (CIDR) — required if cameras are on a different subnet than the hub",
71002
71048
  required: false,
71003
- placeholder: "192.168.x.x/24"
71049
+ placeholder: "192.168.60.0/24"
71004
71050
  }, {
71005
71051
  type: "number",
71006
71052
  key: "timeoutMs",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-amcrest",
3
- "version": "0.2.129",
3
+ "version": "0.2.130",
4
4
  "description": "Amcrest/Dahua camera device provider addon for CamStack — Dahua CGI over HTTP(S) with digest auth (snapshot, RTSP catalog, PTZ, image/day-night config)",
5
5
  "keywords": [
6
6
  "camstack",