@camstack/addon-provider-ecowitt 0.2.118 → 0.2.120

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 +130 -84
  2. package/dist/addon.mjs +130 -84
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -10537,11 +10537,11 @@ var ModelVariantGroupSchema = object({
10537
10537
  /** Quantization axis. Omit ⇒ the fp32 base build. */
10538
10538
  precision: _enum(["fp32", "int8"]).optional(),
10539
10539
  /**
10540
- * Speed-optimization axis. Omit ⇒ the standard build. `fast` marks a
10541
- * latency-optimized export (e.g. ReLU-activation variant) — the slot the
10542
- * future performance variants plug into.
10540
+ * Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
10541
+ * an alternate training of the same family (Scrypted `relu_test`); chip
10542
+ * label is "Test".
10543
10543
  */
10544
- optimization: _enum(["standard", "fast"]).optional(),
10544
+ optimization: _enum(["standard", "test"]).optional(),
10545
10545
  /**
10546
10546
  * Input-resolution axis (square input side, px). Omit ⇒ the family's native
10547
10547
  * resolution (640 for yolo26). Reduced-input builds (320 / 256) are a big,
@@ -10564,9 +10564,10 @@ var ModelProviderIdSchema = _enum([
10564
10564
  * are per upstream. A persisted custom-model row written when this field was a
10565
10565
  * string still parses — the string is lifted into `{ weights }`.
10566
10566
  *
10567
- * Every licence surface (the admin "Models and licenses" page,
10568
- * `THIRD_PARTY_MODELS.md`, the Hugging Face model table) is GENERATED from
10569
- * these records by `scripts/gen-model-licenses.ts` (D661).
10567
+ * Every machine licence surface (`THIRD_PARTY_MODELS.md`, the Hugging Face
10568
+ * model table) is GENERATED from these records by
10569
+ * `scripts/gen-model-licenses.ts` (D661). Operator-facing docs live in
10570
+ * `camstack/docs` → `/docs/detection/models`.
10570
10571
  */
10571
10572
  var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { weights: value } : value, object({
10572
10573
  /** SPDX id of the WEIGHTS' terms, a `LicenseRef-*` for non-SPDX terms, or `UNKNOWN`. */
@@ -14197,7 +14198,7 @@ DeviceType.Camera;
14197
14198
  * This matters here more than anywhere else in the repo, because every provider
14198
14199
  * that knows a device's host knows its PASSWORD too: `{ host, port, username,
14199
14200
  * password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
14200
- * and `http://admin:hunter2@192.168.x.x/` is a URL a browser accepts. The
14201
+ * and `http://admin:hunter2@192.168.60.139/` is a URL a browser accepts. The
14201
14202
  * camera's own page will ask for its own login. That is correct, and pre-
14202
14203
  * filling it is the operator's business, not ours.
14203
14204
  *
@@ -17482,7 +17483,7 @@ method(object({
17482
17483
  timeoutMs: 6e5
17483
17484
  });
17484
17485
  method(object({
17485
- nodeId: string(),
17486
+ targetNodeId: string(),
17486
17487
  modelId: string(),
17487
17488
  format: _enum(MODEL_FORMATS),
17488
17489
  entry: ModelCatalogEntrySchema
@@ -19986,8 +19987,9 @@ var NcRuleSchema = NcRuleInputSchema.extend({
19986
19987
  disabledTargetIds: array(string()).default([])
19987
19988
  });
19988
19989
  /**
19989
- * The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
19990
- * still-true state. `backups-exports` and `alarm` are not sections — a completed
19990
+ * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
19991
+ * report a still-true state. `addons` is the crash-looped addons only and
19992
+ * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
19991
19993
  * job is not an open state, and the alarm stays instant.
19992
19994
  */
19993
19995
  var NcStateSummarySectionIdSchema = _enum([
@@ -19999,6 +20001,7 @@ var NcStateSummarySectionIdSchema = _enum([
19999
20001
  "detection-blind",
20000
20002
  "nodes",
20001
20003
  "addons",
20004
+ "addon-updates",
20002
20005
  "updates"
20003
20006
  ]);
20004
20007
  /** One section of a previewed state summary. `unavailable` = its state could not be read. */
@@ -20479,7 +20482,19 @@ var NcAlarmModeDelaysListSchema = array(object({
20479
20482
  * When this mode may be armed. Absent / null = always allowed (same as a
20480
20483
  * rule with no `schedule`). Evaluated with {@link isScheduleActive}.
20481
20484
  */
20482
- schedule: NcScheduleSchema.optional()
20485
+ schedule: NcScheduleSchema.optional(),
20486
+ /**
20487
+ * D706: while this mode's ENTRY DELAY runs, do the alarm rules' own pushes go out (as an
20488
+ * intrusion naming the locations)? Absent = false — the entry-delay notification is the
20489
+ * only one, and the matches ride the triggered notification's mosaic (D705).
20490
+ */
20491
+ notifyDuringEntryDelay: boolean().optional(),
20492
+ /**
20493
+ * D706: notify "watched again" when a sensor this arm bypassed closes and opens again.
20494
+ * Absent = false (logged, not sent). Even when true it is not sent when that same sensor
20495
+ * is the one that starts the entry delay — the entry-delay notification already names it.
20496
+ */
20497
+ notifySensorRewatched: boolean().optional()
20483
20498
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
20484
20499
  var NcAlarmModeDelaysEditListSchema = array(object({
20485
20500
  mode: AlarmArmModeSchema,
@@ -20488,7 +20503,11 @@ var NcAlarmModeDelaysEditListSchema = array(object({
20488
20503
  triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
20489
20504
  postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
20490
20505
  /** Set a schedule, or `null` to clear (mode always allowed again). */
20491
- schedule: NcScheduleSchema.nullable().optional()
20506
+ schedule: NcScheduleSchema.nullable().optional(),
20507
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
20508
+ notifyDuringEntryDelay: boolean().nullable().optional(),
20509
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
20510
+ notifySensorRewatched: boolean().nullable().optional()
20492
20511
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
20493
20512
  /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
20494
20513
  var NcAlarmNonBlockingEditSchema = object({
@@ -21449,39 +21468,19 @@ Object.freeze(Object.fromEntries([{
21449
21468
  label: "Face recognition model",
21450
21469
  defaultModelId: "auraface-r100",
21451
21470
  indexName: "the enrolled face gallery",
21452
- options: [
21453
- {
21454
- id: "auraface-r100",
21455
- label: "AuraFace R100"
21456
- },
21457
- {
21458
- id: "arcface-r100",
21459
- label: "ArcFace (ResNet34)"
21460
- },
21461
- {
21462
- id: "inception-resnet-v1",
21463
- label: "Inception ResNet V1"
21464
- }
21465
- ]
21471
+ options: [{
21472
+ id: "auraface-r100",
21473
+ label: "AuraFace R100"
21474
+ }]
21466
21475
  }, {
21467
21476
  stepId: "clip-embedding",
21468
21477
  label: "Semantic search model",
21469
- defaultModelId: "mobileclip-s1",
21478
+ defaultModelId: "siglip2-b16-224",
21470
21479
  indexName: "the object semantic-search index",
21471
- options: [
21472
- {
21473
- id: "mobileclip-s1",
21474
- label: "MobileCLIP S1"
21475
- },
21476
- {
21477
- id: "mobileclip-s2",
21478
- label: "MobileCLIP S2"
21479
- },
21480
- {
21481
- id: "siglip2-b16-224",
21482
- label: "SigLIP2 B/16 (Apache-2.0)"
21483
- }
21484
- ]
21480
+ options: [{
21481
+ id: "siglip2-b16-224",
21482
+ label: "SigLIP2 B/16 (Apache-2.0)"
21483
+ }]
21485
21484
  }].map((s) => [s.stepId, s.defaultModelId])));
21486
21485
  var CLUSTER_STEP_SETTING_FIELDS = [{
21487
21486
  stepId: "face-embedding",
@@ -24369,6 +24368,22 @@ var MotionSourceEnum = _enum([
24369
24368
  "device-activity"
24370
24369
  ]);
24371
24370
  /**
24371
+ * What opened an on-motion detection SESSION: the motion source that passed the
24372
+ * camera's `motionSources` gate, and what raised it (the camera itself, or a
24373
+ * sensor the operator attached — D672). `sensorName` is the attached sensor's
24374
+ * device name as the orchestrator's camera-sensors resolution last read it;
24375
+ * absent when unknown or when the camera itself triggered.
24376
+ *
24377
+ * Carried on the session attach ONLY so the runner's `DetectionPhaseTransition`
24378
+ * can say what started the session (D672 rule 11, amended 2026-10-06). The
24379
+ * runner never decides anything on it.
24380
+ */
24381
+ var SessionTriggerSchema = object({
24382
+ source: MotionSourceEnum,
24383
+ triggeredBy: MotionTriggeredBySchema,
24384
+ sensorName: string().optional()
24385
+ });
24386
+ /**
24372
24387
  * List of motion sources active on a camera. Empty array is valid:
24373
24388
  * "no source" — happens for battery cams without firmware motion when
24374
24389
  * the operator hasn't opted into the SW analyzer (would hold the
@@ -24620,6 +24635,14 @@ var RunnerCameraConfigSchema = object({
24620
24635
  */
24621
24636
  motionSources: MotionSourcesSchema.default(["analyzer"]),
24622
24637
  /**
24638
+ * What opened this attach, on a SESSION attach only (see
24639
+ * {@link SessionTriggerSchema}). OPTIONAL with no default: absent on a
24640
+ * standing attach, an occupancy burst, a re-dispatch with no motion event
24641
+ * behind it, and every attach from an orchestrator older than the field — the
24642
+ * runner then names no source on the phase event.
24643
+ */
24644
+ sessionTrigger: SessionTriggerSchema.optional(),
24645
+ /**
24623
24646
  * WHICH root detector runs for this camera. The detection counterpart of
24624
24647
  * {@link motionSources}, same shape and same discipline: a per-camera list
24625
24648
  * of sources the system understands, vendor-agnostic, owned here.
@@ -32008,7 +32031,7 @@ var LocalInterfaceSchema = object({
32008
32031
  name: string(),
32009
32032
  family: _enum(["IPv4", "IPv6"]),
32010
32033
  address: string(),
32011
- /** CIDR shorthand (e.g. `192.168.x.x/24`). Empty when OS doesn't expose. */
32034
+ /** CIDR shorthand (e.g. `192.168.10.10/24`). Empty when OS doesn't expose. */
32012
32035
  cidr: string(),
32013
32036
  /** OS netmask. Stable across calls so the SDK can hash on it. */
32014
32037
  netmask: string(),
@@ -32062,7 +32085,8 @@ var ConnectionEndpointSchema = object({
32062
32085
  "lan-ipv4",
32063
32086
  "lan-ipv6",
32064
32087
  "public",
32065
- "loopback"
32088
+ "loopback",
32089
+ "app-link"
32066
32090
  ]),
32067
32091
  /**
32068
32092
  * Originating-interface kind — `lan`/`wifi`/`docker`/`vpn`/`other`/
@@ -32131,15 +32155,27 @@ var GetConnectionEndpointsResultSchema = object({
32131
32155
  localPort: AdvertisedLocalPortSchema
32132
32156
  });
32133
32157
  /**
32134
- * The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
32135
- * AUTO (resolved from the candidate ranking at send time); `resolved` reports
32136
- * what AUTO currently picks, so the UI can show the effective value either way.
32158
+ * The address flagged for notification links. `baseUrl: null` = AUTO, which
32159
+ * since D709 is the CamStack app link; `resolved` reports the effective value,
32160
+ * so the UI can show it either way.
32137
32161
  */
32138
32162
  var NotificationEndpointSchema = object({
32139
32163
  /** The operator's explicit choice, or null for AUTO. */
32140
32164
  baseUrl: string().nullable(),
32141
- /** What the ranking currently resolves to (null when nothing is reachable). */
32142
- resolved: string().nullable()
32165
+ /**
32166
+ * The effective flagged address: the explicit choice, else (AUTO) the
32167
+ * CamStack app link `https://camstack.zentik.app` (D709). A pre-D709 hub
32168
+ * answered the public tunnel / mesh here, or null.
32169
+ */
32170
+ resolved: string().nullable(),
32171
+ /**
32172
+ * The hub origin an app link carries as `hub=` (D709): the hub's best
32173
+ * public HTTPS address — the tunnel, then the mesh (Tailscale MagicDNS) —
32174
+ * picked from this cap's own palette by `pickAppLinkHub`. `null` when the
32175
+ * hub advertises neither; the app link is then minted without `hub=`.
32176
+ * Absent on a pre-D709 hub.
32177
+ */
32178
+ appLinkHub: string().nullable()
32143
32179
  });
32144
32180
  /**
32145
32181
  * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
@@ -32193,7 +32229,11 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
32193
32229
  * Pass `'https'` when the caller is itself loaded over HTTPS
32194
32230
  * to avoid mixed-content blocks in the browser. The public
32195
32231
  * tunnel always emits `https://` regardless. */
32196
- scheme: _enum(["http", "https"]).optional()
32232
+ scheme: _enum(["http", "https"]).optional(),
32233
+ /** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
32234
+ * an address notification links can be flagged with, not a hub
32235
+ * route. Default `false`: racers and rankers never see it. */
32236
+ includeAppLink: boolean().optional()
32197
32237
  }), 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, {
32198
32238
  kind: "mutation",
32199
32239
  auth: "admin"
@@ -32522,7 +32562,7 @@ var MeshPeerSchema = object({
32522
32562
  tags: array(string()).readonly(),
32523
32563
  /** True when the peer advertises itself as an exit-node candidate. */
32524
32564
  exitNodeOption: boolean(),
32525
- /** Subnet routes the peer advertises (e.g. `["192.168.x.x/24"]`). */
32565
+ /** Subnet routes the peer advertises (e.g. `["192.168.10.0/24"]`). */
32526
32566
  advertisedRoutes: array(string()).readonly(),
32527
32567
  /** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
32528
32568
  userLogin: string().nullable(),
@@ -33850,7 +33890,13 @@ var OsdStatusSchema = object({ overlays: array(object({
33850
33890
  */
33851
33891
  availablePositions: array(OsdPositionEnum).readonly(),
33852
33892
  /** Firmware does not allow editing the `text` field (e.g. timestamp). */
33853
- readOnly: boolean().optional()
33893
+ readOnly: boolean().optional(),
33894
+ /**
33895
+ * Firmware text ceiling for this overlay. Absent = no known limit.
33896
+ * The OSD manager truncates here on every write — never stores its own
33897
+ * copy on the binding.
33898
+ */
33899
+ maxCharacters: number().int().positive().optional()
33854
33900
  })).readonly() });
33855
33901
  var OsdOverlayPatchSchema = object({
33856
33902
  enabled: boolean().optional(),
@@ -33901,7 +33947,9 @@ var OsdTemplateBindingSchema = object({
33901
33947
  valuePath: string().min(1).max(64),
33902
33948
  /** Convert TO this unit at render (`tryConvertUnit`). Absent = source unit. */
33903
33949
  displayUnit: string().max(16).optional(),
33904
- maxDecimals: number().int().min(0).max(4).default(1)
33950
+ maxDecimals: number().int().min(0).max(4).default(1),
33951
+ /** Raw value → display text (same shape as slot binding). Empty string hides. */
33952
+ valueMap: record(string(), string()).optional()
33905
33953
  });
33906
33954
  /**
33907
33955
  * A named template: bindings (alias → leaf field) + a parser that
@@ -33951,18 +33999,11 @@ var OsdSlotBindingSchema = object({
33951
33999
  source: OsdSourceSchema,
33952
34000
  /** `${value}` and `${unit}` are substituted; every occurrence. */
33953
34001
  template: string().max(96).default("${value}"),
33954
- /** Truncate with an ellipsis past this length. Absent = no limit. */
33955
- maxCharacters: number().int().min(4).max(64).optional(),
33956
34002
  /**
33957
34003
  * Decimal places for a numeric value. `0` yields an integer — the
33958
34004
  * documented workaround for firmwares that reject `.` in overlay text.
33959
34005
  */
33960
34006
  maxDecimals: number().int().min(0).max(4).default(1),
33961
- /**
33962
- * Appended via `${unit}` when no unit conversion produces a label.
33963
- * Prefer `source.displayUnit` for converted device-state values.
33964
- */
33965
- unitLabel: string().max(8).optional(),
33966
34007
  /** Raw value → display text, e.g. `{"true":"MOTION","false":""}`. */
33967
34008
  valueMap: record(string(), string()).optional(),
33968
34009
  /** Time windows in which the slot is shown. Absent = always. */
@@ -33971,9 +34012,7 @@ var OsdSlotBindingSchema = object({
33971
34012
  * Display gate, in the notification centre's condition vocabulary.
33972
34013
  * Only the keys reported by `getConditionSupport` are accepted.
33973
34014
  */
33974
- conditions: NcConditionsSchema.optional(),
33975
- /** Rendered when the gate is closed or the value unreadable. Empty = hide. */
33976
- fallbackText: string().max(64).default("")
34015
+ conditions: NcConditionsSchema.optional()
33977
34016
  });
33978
34017
  /** One camera slot, as the operator sees it: firmware truth + our binding. */
33979
34018
  var OsdSlotViewSchema = object({
@@ -52206,12 +52245,14 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
52206
52245
  {
52207
52246
  id: "addons",
52208
52247
  family: "system",
52209
- label: "Addons",
52210
- kinds: [
52211
- "addon-crash-loop",
52212
- "addon-update-available",
52213
- "addon-updated"
52214
- ]
52248
+ label: "Addons stopped",
52249
+ kinds: ["addon-crash-loop"]
52250
+ },
52251
+ {
52252
+ id: "addon-updates",
52253
+ family: "system",
52254
+ label: "Addon updates",
52255
+ kinds: ["addon-update-available", "addon-updated"]
52215
52256
  },
52216
52257
  {
52217
52258
  id: "updates",
@@ -52371,13 +52412,15 @@ var STATE_SUMMARY_SECTION_VARS = [
52371
52412
  },
52372
52413
  {
52373
52414
  name: "summaryAddons",
52374
- label: "Summary: addons",
52375
- example: "@camstack/addon-recorder 1.2.3 → 1.2.4",
52376
- kinds: [
52377
- "addon-crash-loop",
52378
- "addon-update-available",
52379
- "addon-updated"
52380
- ]
52415
+ label: "Summary: addons stopped",
52416
+ example: "hub — recorder stopped after repeated crashes",
52417
+ kinds: ["addon-crash-loop"]
52418
+ },
52419
+ {
52420
+ name: "summaryAddonUpdates",
52421
+ label: "Summary: addon updates",
52422
+ example: "hub:\n• @camstack/addon-recorder 1.2.3 → 1.2.4",
52423
+ kinds: ["addon-update-available", "addon-updated"]
52381
52424
  },
52382
52425
  {
52383
52426
  name: "summaryUpdates",
@@ -52461,6 +52504,7 @@ var STATE_SUMMARY_VARS = [
52461
52504
  [...RULE_BODY_ONLY],
52462
52505
  [...RULE_TEXT],
52463
52506
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
52507
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
52464
52508
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
52465
52509
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
52466
52510
  ([...RULE_TEXT], [...CONSUMABLE]),
@@ -52501,6 +52545,8 @@ var STATE_SUMMARY_VARS = [
52501
52545
  [...RULE_TEXT],
52502
52546
  [...RULE_TEXT],
52503
52547
  [...RULE_TEXT],
52548
+ [...RULE_TEXT],
52549
+ [...RULE_TEXT],
52504
52550
  ...STATE_SUMMARY_VARS
52505
52551
  ];
52506
52552
  new Set([
@@ -58928,7 +58974,7 @@ function buildConnectionFormSchema() {
58928
58974
  type: "text",
58929
58975
  key: "host",
58930
58976
  label: "Gateway host / IP",
58931
- placeholder: "192.168.x.x",
58977
+ placeholder: "192.168.10.50",
58932
58978
  showWhen: {
58933
58979
  field: "transport",
58934
58980
  equals: "local"
@@ -59010,21 +59056,21 @@ function slugifyHost(value) {
59010
59056
  * Extra per-scan inputs for Ecowitt network discovery. Mirrors Gree's scan form. On a flat network,
59011
59057
  * leave blank to sweep the addon node's local subnet. To reach gateways on OTHER subnets, list one or
59012
59058
  * more directed broadcast addresses, gateway IPs, or CIDRs (comma / newline separated) — each is
59013
- * swept independently and the responders are merged. A directed broadcast (e.g. 192.168.x.x) or a
59059
+ * swept independently and the responders are merged. A directed broadcast (e.g. 192.168.20.255) or a
59014
59060
  * unicast gateway IP both work because the `CMD_BROADCAST` probe answers a unicast just as well.
59015
59061
  */
59016
59062
  function buildDiscoveryParamsFormSchema() {
59017
59063
  return { sections: [{
59018
59064
  id: "scan",
59019
59065
  title: "Scan options",
59020
- description: "Leave empty to scan the local subnet. To scan other subnets, list their broadcast addresses (e.g. 192.168.x.x), gateway IPs (e.g. 192.168.x.x), or CIDRs (e.g. 192.168.x.x/24) — comma or newline separated. Each subnet is swept independently and unreachable ones are skipped.",
59066
+ description: "Leave empty to scan the local subnet. To scan other subnets, list their broadcast addresses (e.g. 192.168.20.255), gateway IPs (e.g. 192.168.20.181), or CIDRs (e.g. 192.168.20.0/24) — comma or newline separated. Each subnet is swept independently and unreachable ones are skipped.",
59021
59067
  columns: 1,
59022
59068
  fields: [{
59023
59069
  type: "text",
59024
59070
  key: "broadcastAddress",
59025
59071
  label: "Broadcast addresses / gateway IPs / CIDRs",
59026
59072
  required: false,
59027
- placeholder: "192.168.x.x, 192.168.x.x/24"
59073
+ placeholder: "192.168.20.255, 192.168.30.0/24"
59028
59074
  }, {
59029
59075
  type: "number",
59030
59076
  key: "timeoutMs",
@@ -59198,8 +59244,8 @@ function parseIpv4(value) {
59198
59244
  ];
59199
59245
  }
59200
59246
  /**
59201
- * Convert an IPv4 CIDR (e.g. `192.168.x.x/24`) into its directed broadcast address
59202
- * (`192.168.x.x`) — the address `Ecowitt.discover` sweeps to reach a foreign subnet. Returns
59247
+ * Convert an IPv4 CIDR (e.g. `192.0.2.0/24`) into its directed broadcast address
59248
+ * (`192.0.2.255`) — the address `Ecowitt.discover` sweeps to reach a foreign subnet. Returns
59203
59249
  * `null` for anything that is not a well-formed IPv4 CIDR (a bare IP, garbage, or an out-of-range
59204
59250
  * prefix), so the caller can treat the input as a literal broadcast/gateway address instead.
59205
59251
  */
@@ -59223,8 +59269,8 @@ function cidrToBroadcast(value) {
59223
59269
  * Parse the operator scan input into a de-duplicated, ordered list of directed broadcast targets.
59224
59270
  *
59225
59271
  * Accepts a free-form string of comma / newline / whitespace separated tokens where each token is
59226
- * either a broadcast address (`192.168.x.x`), a bare gateway IP (`192.168.x.x` — the
59227
- * `CMD_BROADCAST` probe answers a unicast too), or a CIDR (`192.168.x.x/24`, expanded to its
59272
+ * either a broadcast address (`192.0.2.255`), a bare gateway IP (`192.0.2.10` — the
59273
+ * `CMD_BROADCAST` probe answers a unicast too), or a CIDR (`192.0.2.0/24`, expanded to its
59228
59274
  * directed broadcast). Blank input yields an empty list, meaning "sweep the local subnet only".
59229
59275
  * Invalid tokens are dropped rather than throwing — discovery input is best-effort.
59230
59276
  */
package/dist/addon.mjs CHANGED
@@ -10536,11 +10536,11 @@ var ModelVariantGroupSchema = object({
10536
10536
  /** Quantization axis. Omit ⇒ the fp32 base build. */
10537
10537
  precision: _enum(["fp32", "int8"]).optional(),
10538
10538
  /**
10539
- * Speed-optimization axis. Omit ⇒ the standard build. `fast` marks a
10540
- * latency-optimized export (e.g. ReLU-activation variant) — the slot the
10541
- * future performance variants plug into.
10539
+ * Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
10540
+ * an alternate training of the same family (Scrypted `relu_test`); chip
10541
+ * label is "Test".
10542
10542
  */
10543
- optimization: _enum(["standard", "fast"]).optional(),
10543
+ optimization: _enum(["standard", "test"]).optional(),
10544
10544
  /**
10545
10545
  * Input-resolution axis (square input side, px). Omit ⇒ the family's native
10546
10546
  * resolution (640 for yolo26). Reduced-input builds (320 / 256) are a big,
@@ -10563,9 +10563,10 @@ var ModelProviderIdSchema = _enum([
10563
10563
  * are per upstream. A persisted custom-model row written when this field was a
10564
10564
  * string still parses — the string is lifted into `{ weights }`.
10565
10565
  *
10566
- * Every licence surface (the admin "Models and licenses" page,
10567
- * `THIRD_PARTY_MODELS.md`, the Hugging Face model table) is GENERATED from
10568
- * these records by `scripts/gen-model-licenses.ts` (D661).
10566
+ * Every machine licence surface (`THIRD_PARTY_MODELS.md`, the Hugging Face
10567
+ * model table) is GENERATED from these records by
10568
+ * `scripts/gen-model-licenses.ts` (D661). Operator-facing docs live in
10569
+ * `camstack/docs` → `/docs/detection/models`.
10569
10570
  */
10570
10571
  var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { weights: value } : value, object({
10571
10572
  /** SPDX id of the WEIGHTS' terms, a `LicenseRef-*` for non-SPDX terms, or `UNKNOWN`. */
@@ -14196,7 +14197,7 @@ DeviceType.Camera;
14196
14197
  * This matters here more than anywhere else in the repo, because every provider
14197
14198
  * that knows a device's host knows its PASSWORD too: `{ host, port, username,
14198
14199
  * password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
14199
- * and `http://admin:hunter2@192.168.x.x/` is a URL a browser accepts. The
14200
+ * and `http://admin:hunter2@192.168.60.139/` is a URL a browser accepts. The
14200
14201
  * camera's own page will ask for its own login. That is correct, and pre-
14201
14202
  * filling it is the operator's business, not ours.
14202
14203
  *
@@ -17481,7 +17482,7 @@ method(object({
17481
17482
  timeoutMs: 6e5
17482
17483
  });
17483
17484
  method(object({
17484
- nodeId: string(),
17485
+ targetNodeId: string(),
17485
17486
  modelId: string(),
17486
17487
  format: _enum(MODEL_FORMATS),
17487
17488
  entry: ModelCatalogEntrySchema
@@ -19985,8 +19986,9 @@ var NcRuleSchema = NcRuleInputSchema.extend({
19985
19986
  disabledTargetIds: array(string()).default([])
19986
19987
  });
19987
19988
  /**
19988
- * The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
19989
- * still-true state. `backups-exports` and `alarm` are not sections — a completed
19989
+ * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
19990
+ * report a still-true state. `addons` is the crash-looped addons only and
19991
+ * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
19990
19992
  * job is not an open state, and the alarm stays instant.
19991
19993
  */
19992
19994
  var NcStateSummarySectionIdSchema = _enum([
@@ -19998,6 +20000,7 @@ var NcStateSummarySectionIdSchema = _enum([
19998
20000
  "detection-blind",
19999
20001
  "nodes",
20000
20002
  "addons",
20003
+ "addon-updates",
20001
20004
  "updates"
20002
20005
  ]);
20003
20006
  /** One section of a previewed state summary. `unavailable` = its state could not be read. */
@@ -20478,7 +20481,19 @@ var NcAlarmModeDelaysListSchema = array(object({
20478
20481
  * When this mode may be armed. Absent / null = always allowed (same as a
20479
20482
  * rule with no `schedule`). Evaluated with {@link isScheduleActive}.
20480
20483
  */
20481
- schedule: NcScheduleSchema.optional()
20484
+ schedule: NcScheduleSchema.optional(),
20485
+ /**
20486
+ * D706: while this mode's ENTRY DELAY runs, do the alarm rules' own pushes go out (as an
20487
+ * intrusion naming the locations)? Absent = false — the entry-delay notification is the
20488
+ * only one, and the matches ride the triggered notification's mosaic (D705).
20489
+ */
20490
+ notifyDuringEntryDelay: boolean().optional(),
20491
+ /**
20492
+ * D706: notify "watched again" when a sensor this arm bypassed closes and opens again.
20493
+ * Absent = false (logged, not sent). Even when true it is not sent when that same sensor
20494
+ * is the one that starts the entry delay — the entry-delay notification already names it.
20495
+ */
20496
+ notifySensorRewatched: boolean().optional()
20482
20497
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
20483
20498
  var NcAlarmModeDelaysEditListSchema = array(object({
20484
20499
  mode: AlarmArmModeSchema,
@@ -20487,7 +20502,11 @@ var NcAlarmModeDelaysEditListSchema = array(object({
20487
20502
  triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
20488
20503
  postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
20489
20504
  /** Set a schedule, or `null` to clear (mode always allowed again). */
20490
- schedule: NcScheduleSchema.nullable().optional()
20505
+ schedule: NcScheduleSchema.nullable().optional(),
20506
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
20507
+ notifyDuringEntryDelay: boolean().nullable().optional(),
20508
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
20509
+ notifySensorRewatched: boolean().nullable().optional()
20491
20510
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
20492
20511
  /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
20493
20512
  var NcAlarmNonBlockingEditSchema = object({
@@ -21448,39 +21467,19 @@ Object.freeze(Object.fromEntries([{
21448
21467
  label: "Face recognition model",
21449
21468
  defaultModelId: "auraface-r100",
21450
21469
  indexName: "the enrolled face gallery",
21451
- options: [
21452
- {
21453
- id: "auraface-r100",
21454
- label: "AuraFace R100"
21455
- },
21456
- {
21457
- id: "arcface-r100",
21458
- label: "ArcFace (ResNet34)"
21459
- },
21460
- {
21461
- id: "inception-resnet-v1",
21462
- label: "Inception ResNet V1"
21463
- }
21464
- ]
21470
+ options: [{
21471
+ id: "auraface-r100",
21472
+ label: "AuraFace R100"
21473
+ }]
21465
21474
  }, {
21466
21475
  stepId: "clip-embedding",
21467
21476
  label: "Semantic search model",
21468
- defaultModelId: "mobileclip-s1",
21477
+ defaultModelId: "siglip2-b16-224",
21469
21478
  indexName: "the object semantic-search index",
21470
- options: [
21471
- {
21472
- id: "mobileclip-s1",
21473
- label: "MobileCLIP S1"
21474
- },
21475
- {
21476
- id: "mobileclip-s2",
21477
- label: "MobileCLIP S2"
21478
- },
21479
- {
21480
- id: "siglip2-b16-224",
21481
- label: "SigLIP2 B/16 (Apache-2.0)"
21482
- }
21483
- ]
21479
+ options: [{
21480
+ id: "siglip2-b16-224",
21481
+ label: "SigLIP2 B/16 (Apache-2.0)"
21482
+ }]
21484
21483
  }].map((s) => [s.stepId, s.defaultModelId])));
21485
21484
  var CLUSTER_STEP_SETTING_FIELDS = [{
21486
21485
  stepId: "face-embedding",
@@ -24368,6 +24367,22 @@ var MotionSourceEnum = _enum([
24368
24367
  "device-activity"
24369
24368
  ]);
24370
24369
  /**
24370
+ * What opened an on-motion detection SESSION: the motion source that passed the
24371
+ * camera's `motionSources` gate, and what raised it (the camera itself, or a
24372
+ * sensor the operator attached — D672). `sensorName` is the attached sensor's
24373
+ * device name as the orchestrator's camera-sensors resolution last read it;
24374
+ * absent when unknown or when the camera itself triggered.
24375
+ *
24376
+ * Carried on the session attach ONLY so the runner's `DetectionPhaseTransition`
24377
+ * can say what started the session (D672 rule 11, amended 2026-10-06). The
24378
+ * runner never decides anything on it.
24379
+ */
24380
+ var SessionTriggerSchema = object({
24381
+ source: MotionSourceEnum,
24382
+ triggeredBy: MotionTriggeredBySchema,
24383
+ sensorName: string().optional()
24384
+ });
24385
+ /**
24371
24386
  * List of motion sources active on a camera. Empty array is valid:
24372
24387
  * "no source" — happens for battery cams without firmware motion when
24373
24388
  * the operator hasn't opted into the SW analyzer (would hold the
@@ -24619,6 +24634,14 @@ var RunnerCameraConfigSchema = object({
24619
24634
  */
24620
24635
  motionSources: MotionSourcesSchema.default(["analyzer"]),
24621
24636
  /**
24637
+ * What opened this attach, on a SESSION attach only (see
24638
+ * {@link SessionTriggerSchema}). OPTIONAL with no default: absent on a
24639
+ * standing attach, an occupancy burst, a re-dispatch with no motion event
24640
+ * behind it, and every attach from an orchestrator older than the field — the
24641
+ * runner then names no source on the phase event.
24642
+ */
24643
+ sessionTrigger: SessionTriggerSchema.optional(),
24644
+ /**
24622
24645
  * WHICH root detector runs for this camera. The detection counterpart of
24623
24646
  * {@link motionSources}, same shape and same discipline: a per-camera list
24624
24647
  * of sources the system understands, vendor-agnostic, owned here.
@@ -32007,7 +32030,7 @@ var LocalInterfaceSchema = object({
32007
32030
  name: string(),
32008
32031
  family: _enum(["IPv4", "IPv6"]),
32009
32032
  address: string(),
32010
- /** CIDR shorthand (e.g. `192.168.x.x/24`). Empty when OS doesn't expose. */
32033
+ /** CIDR shorthand (e.g. `192.168.10.10/24`). Empty when OS doesn't expose. */
32011
32034
  cidr: string(),
32012
32035
  /** OS netmask. Stable across calls so the SDK can hash on it. */
32013
32036
  netmask: string(),
@@ -32061,7 +32084,8 @@ var ConnectionEndpointSchema = object({
32061
32084
  "lan-ipv4",
32062
32085
  "lan-ipv6",
32063
32086
  "public",
32064
- "loopback"
32087
+ "loopback",
32088
+ "app-link"
32065
32089
  ]),
32066
32090
  /**
32067
32091
  * Originating-interface kind — `lan`/`wifi`/`docker`/`vpn`/`other`/
@@ -32130,15 +32154,27 @@ var GetConnectionEndpointsResultSchema = object({
32130
32154
  localPort: AdvertisedLocalPortSchema
32131
32155
  });
32132
32156
  /**
32133
- * The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
32134
- * AUTO (resolved from the candidate ranking at send time); `resolved` reports
32135
- * what AUTO currently picks, so the UI can show the effective value either way.
32157
+ * The address flagged for notification links. `baseUrl: null` = AUTO, which
32158
+ * since D709 is the CamStack app link; `resolved` reports the effective value,
32159
+ * so the UI can show it either way.
32136
32160
  */
32137
32161
  var NotificationEndpointSchema = object({
32138
32162
  /** The operator's explicit choice, or null for AUTO. */
32139
32163
  baseUrl: string().nullable(),
32140
- /** What the ranking currently resolves to (null when nothing is reachable). */
32141
- resolved: string().nullable()
32164
+ /**
32165
+ * The effective flagged address: the explicit choice, else (AUTO) the
32166
+ * CamStack app link `https://camstack.zentik.app` (D709). A pre-D709 hub
32167
+ * answered the public tunnel / mesh here, or null.
32168
+ */
32169
+ resolved: string().nullable(),
32170
+ /**
32171
+ * The hub origin an app link carries as `hub=` (D709): the hub's best
32172
+ * public HTTPS address — the tunnel, then the mesh (Tailscale MagicDNS) —
32173
+ * picked from this cap's own palette by `pickAppLinkHub`. `null` when the
32174
+ * hub advertises neither; the app link is then minted without `hub=`.
32175
+ * Absent on a pre-D709 hub.
32176
+ */
32177
+ appLinkHub: string().nullable()
32142
32178
  });
32143
32179
  /**
32144
32180
  * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
@@ -32192,7 +32228,11 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
32192
32228
  * Pass `'https'` when the caller is itself loaded over HTTPS
32193
32229
  * to avoid mixed-content blocks in the browser. The public
32194
32230
  * tunnel always emits `https://` regardless. */
32195
- scheme: _enum(["http", "https"]).optional()
32231
+ scheme: _enum(["http", "https"]).optional(),
32232
+ /** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
32233
+ * an address notification links can be flagged with, not a hub
32234
+ * route. Default `false`: racers and rankers never see it. */
32235
+ includeAppLink: boolean().optional()
32196
32236
  }), 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, {
32197
32237
  kind: "mutation",
32198
32238
  auth: "admin"
@@ -32521,7 +32561,7 @@ var MeshPeerSchema = object({
32521
32561
  tags: array(string()).readonly(),
32522
32562
  /** True when the peer advertises itself as an exit-node candidate. */
32523
32563
  exitNodeOption: boolean(),
32524
- /** Subnet routes the peer advertises (e.g. `["192.168.x.x/24"]`). */
32564
+ /** Subnet routes the peer advertises (e.g. `["192.168.10.0/24"]`). */
32525
32565
  advertisedRoutes: array(string()).readonly(),
32526
32566
  /** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
32527
32567
  userLogin: string().nullable(),
@@ -33849,7 +33889,13 @@ var OsdStatusSchema = object({ overlays: array(object({
33849
33889
  */
33850
33890
  availablePositions: array(OsdPositionEnum).readonly(),
33851
33891
  /** Firmware does not allow editing the `text` field (e.g. timestamp). */
33852
- readOnly: boolean().optional()
33892
+ readOnly: boolean().optional(),
33893
+ /**
33894
+ * Firmware text ceiling for this overlay. Absent = no known limit.
33895
+ * The OSD manager truncates here on every write — never stores its own
33896
+ * copy on the binding.
33897
+ */
33898
+ maxCharacters: number().int().positive().optional()
33853
33899
  })).readonly() });
33854
33900
  var OsdOverlayPatchSchema = object({
33855
33901
  enabled: boolean().optional(),
@@ -33900,7 +33946,9 @@ var OsdTemplateBindingSchema = object({
33900
33946
  valuePath: string().min(1).max(64),
33901
33947
  /** Convert TO this unit at render (`tryConvertUnit`). Absent = source unit. */
33902
33948
  displayUnit: string().max(16).optional(),
33903
- maxDecimals: number().int().min(0).max(4).default(1)
33949
+ maxDecimals: number().int().min(0).max(4).default(1),
33950
+ /** Raw value → display text (same shape as slot binding). Empty string hides. */
33951
+ valueMap: record(string(), string()).optional()
33904
33952
  });
33905
33953
  /**
33906
33954
  * A named template: bindings (alias → leaf field) + a parser that
@@ -33950,18 +33998,11 @@ var OsdSlotBindingSchema = object({
33950
33998
  source: OsdSourceSchema,
33951
33999
  /** `${value}` and `${unit}` are substituted; every occurrence. */
33952
34000
  template: string().max(96).default("${value}"),
33953
- /** Truncate with an ellipsis past this length. Absent = no limit. */
33954
- maxCharacters: number().int().min(4).max(64).optional(),
33955
34001
  /**
33956
34002
  * Decimal places for a numeric value. `0` yields an integer — the
33957
34003
  * documented workaround for firmwares that reject `.` in overlay text.
33958
34004
  */
33959
34005
  maxDecimals: number().int().min(0).max(4).default(1),
33960
- /**
33961
- * Appended via `${unit}` when no unit conversion produces a label.
33962
- * Prefer `source.displayUnit` for converted device-state values.
33963
- */
33964
- unitLabel: string().max(8).optional(),
33965
34006
  /** Raw value → display text, e.g. `{"true":"MOTION","false":""}`. */
33966
34007
  valueMap: record(string(), string()).optional(),
33967
34008
  /** Time windows in which the slot is shown. Absent = always. */
@@ -33970,9 +34011,7 @@ var OsdSlotBindingSchema = object({
33970
34011
  * Display gate, in the notification centre's condition vocabulary.
33971
34012
  * Only the keys reported by `getConditionSupport` are accepted.
33972
34013
  */
33973
- conditions: NcConditionsSchema.optional(),
33974
- /** Rendered when the gate is closed or the value unreadable. Empty = hide. */
33975
- fallbackText: string().max(64).default("")
34014
+ conditions: NcConditionsSchema.optional()
33976
34015
  });
33977
34016
  /** One camera slot, as the operator sees it: firmware truth + our binding. */
33978
34017
  var OsdSlotViewSchema = object({
@@ -52205,12 +52244,14 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
52205
52244
  {
52206
52245
  id: "addons",
52207
52246
  family: "system",
52208
- label: "Addons",
52209
- kinds: [
52210
- "addon-crash-loop",
52211
- "addon-update-available",
52212
- "addon-updated"
52213
- ]
52247
+ label: "Addons stopped",
52248
+ kinds: ["addon-crash-loop"]
52249
+ },
52250
+ {
52251
+ id: "addon-updates",
52252
+ family: "system",
52253
+ label: "Addon updates",
52254
+ kinds: ["addon-update-available", "addon-updated"]
52214
52255
  },
52215
52256
  {
52216
52257
  id: "updates",
@@ -52370,13 +52411,15 @@ var STATE_SUMMARY_SECTION_VARS = [
52370
52411
  },
52371
52412
  {
52372
52413
  name: "summaryAddons",
52373
- label: "Summary: addons",
52374
- example: "@camstack/addon-recorder 1.2.3 → 1.2.4",
52375
- kinds: [
52376
- "addon-crash-loop",
52377
- "addon-update-available",
52378
- "addon-updated"
52379
- ]
52414
+ label: "Summary: addons stopped",
52415
+ example: "hub — recorder stopped after repeated crashes",
52416
+ kinds: ["addon-crash-loop"]
52417
+ },
52418
+ {
52419
+ name: "summaryAddonUpdates",
52420
+ label: "Summary: addon updates",
52421
+ example: "hub:\n• @camstack/addon-recorder 1.2.3 → 1.2.4",
52422
+ kinds: ["addon-update-available", "addon-updated"]
52380
52423
  },
52381
52424
  {
52382
52425
  name: "summaryUpdates",
@@ -52460,6 +52503,7 @@ var STATE_SUMMARY_VARS = [
52460
52503
  [...RULE_BODY_ONLY],
52461
52504
  [...RULE_TEXT],
52462
52505
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
52506
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
52463
52507
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
52464
52508
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
52465
52509
  ([...RULE_TEXT], [...CONSUMABLE]),
@@ -52500,6 +52544,8 @@ var STATE_SUMMARY_VARS = [
52500
52544
  [...RULE_TEXT],
52501
52545
  [...RULE_TEXT],
52502
52546
  [...RULE_TEXT],
52547
+ [...RULE_TEXT],
52548
+ [...RULE_TEXT],
52503
52549
  ...STATE_SUMMARY_VARS
52504
52550
  ];
52505
52551
  new Set([
@@ -58927,7 +58973,7 @@ function buildConnectionFormSchema() {
58927
58973
  type: "text",
58928
58974
  key: "host",
58929
58975
  label: "Gateway host / IP",
58930
- placeholder: "192.168.x.x",
58976
+ placeholder: "192.168.10.50",
58931
58977
  showWhen: {
58932
58978
  field: "transport",
58933
58979
  equals: "local"
@@ -59009,21 +59055,21 @@ function slugifyHost(value) {
59009
59055
  * Extra per-scan inputs for Ecowitt network discovery. Mirrors Gree's scan form. On a flat network,
59010
59056
  * leave blank to sweep the addon node's local subnet. To reach gateways on OTHER subnets, list one or
59011
59057
  * more directed broadcast addresses, gateway IPs, or CIDRs (comma / newline separated) — each is
59012
- * swept independently and the responders are merged. A directed broadcast (e.g. 192.168.x.x) or a
59058
+ * swept independently and the responders are merged. A directed broadcast (e.g. 192.168.20.255) or a
59013
59059
  * unicast gateway IP both work because the `CMD_BROADCAST` probe answers a unicast just as well.
59014
59060
  */
59015
59061
  function buildDiscoveryParamsFormSchema() {
59016
59062
  return { sections: [{
59017
59063
  id: "scan",
59018
59064
  title: "Scan options",
59019
- description: "Leave empty to scan the local subnet. To scan other subnets, list their broadcast addresses (e.g. 192.168.x.x), gateway IPs (e.g. 192.168.x.x), or CIDRs (e.g. 192.168.x.x/24) — comma or newline separated. Each subnet is swept independently and unreachable ones are skipped.",
59065
+ description: "Leave empty to scan the local subnet. To scan other subnets, list their broadcast addresses (e.g. 192.168.20.255), gateway IPs (e.g. 192.168.20.181), or CIDRs (e.g. 192.168.20.0/24) — comma or newline separated. Each subnet is swept independently and unreachable ones are skipped.",
59020
59066
  columns: 1,
59021
59067
  fields: [{
59022
59068
  type: "text",
59023
59069
  key: "broadcastAddress",
59024
59070
  label: "Broadcast addresses / gateway IPs / CIDRs",
59025
59071
  required: false,
59026
- placeholder: "192.168.x.x, 192.168.x.x/24"
59072
+ placeholder: "192.168.20.255, 192.168.30.0/24"
59027
59073
  }, {
59028
59074
  type: "number",
59029
59075
  key: "timeoutMs",
@@ -59197,8 +59243,8 @@ function parseIpv4(value) {
59197
59243
  ];
59198
59244
  }
59199
59245
  /**
59200
- * Convert an IPv4 CIDR (e.g. `192.168.x.x/24`) into its directed broadcast address
59201
- * (`192.168.x.x`) — the address `Ecowitt.discover` sweeps to reach a foreign subnet. Returns
59246
+ * Convert an IPv4 CIDR (e.g. `192.0.2.0/24`) into its directed broadcast address
59247
+ * (`192.0.2.255`) — the address `Ecowitt.discover` sweeps to reach a foreign subnet. Returns
59202
59248
  * `null` for anything that is not a well-formed IPv4 CIDR (a bare IP, garbage, or an out-of-range
59203
59249
  * prefix), so the caller can treat the input as a literal broadcast/gateway address instead.
59204
59250
  */
@@ -59222,8 +59268,8 @@ function cidrToBroadcast(value) {
59222
59268
  * Parse the operator scan input into a de-duplicated, ordered list of directed broadcast targets.
59223
59269
  *
59224
59270
  * Accepts a free-form string of comma / newline / whitespace separated tokens where each token is
59225
- * either a broadcast address (`192.168.x.x`), a bare gateway IP (`192.168.x.x` — the
59226
- * `CMD_BROADCAST` probe answers a unicast too), or a CIDR (`192.168.x.x/24`, expanded to its
59271
+ * either a broadcast address (`192.0.2.255`), a bare gateway IP (`192.0.2.10` — the
59272
+ * `CMD_BROADCAST` probe answers a unicast too), or a CIDR (`192.0.2.0/24`, expanded to its
59227
59273
  * directed broadcast). Blank input yields an empty list, meaning "sweep the local subnet only".
59228
59274
  * Invalid tokens are dropped rather than throwing — discovery input is best-effort.
59229
59275
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-ecowitt",
3
- "version": "0.2.118",
3
+ "version": "0.2.120",
4
4
  "description": "Ecowitt weather-station device-provider addon for CamStack — wraps the @apocaliss92/nodewitt local-poll / push client",
5
5
  "keywords": [
6
6
  "camstack",