@camstack/addon-provider-homematic 1.2.103 → 1.2.104

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 +314 -12
  2. package/dist/addon.mjs +314 -12
  3. package/package.json +2 -2
package/dist/addon.js CHANGED
@@ -5369,7 +5369,7 @@ var ZodIssueCode = {
5369
5369
  var ZodFirstPartyTypeKind;
5370
5370
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5371
5371
  //#endregion
5372
- //#region ../types/dist/sleep-DEuj7E3j.mjs
5372
+ //#region ../types/dist/sleep-BDR76Ykr.mjs
5373
5373
  /**
5374
5374
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5375
5375
  * window to float samples (D455).
@@ -11620,6 +11620,21 @@ var streamSignalsCapability = {
11620
11620
  mode: "singleton",
11621
11621
  deviceTypes: Object.values(DeviceType),
11622
11622
  runtimeState: StreamSignalsStatusSchema,
11623
+ /**
11624
+ * Runtime-state durability: **session** — mirrored in RAM, never written.
11625
+ *
11626
+ * The slice holds what the DEVICE says it can emit. That is a probed fact,
11627
+ * not an operator choice: the provider re-declares it on every registration,
11628
+ * so losing it loses nothing and persisting it would freeze an answer the
11629
+ * camera is entitled to change. Measured the same day on the sibling case —
11630
+ * `native-object-detection.supportedClasses` was persisted, and a firmware
11631
+ * class the camera really detected stayed missing for the life of the row
11632
+ * because the fix could not reach it.
11633
+ *
11634
+ * See `RuntimeStateDurability`. Enforced by
11635
+ * `scripts/check-runtime-state-durability.ts`.
11636
+ */
11637
+ durability: "session",
11623
11638
  methods: {
11624
11639
  /**
11625
11640
  * What this device can emit. Empty is a valid and common answer — most
@@ -18251,6 +18266,48 @@ var NcAlarmConfigSchema = object({
18251
18266
  settings: NcAlarmSettingsSchema,
18252
18267
  coverage: array(NcAlarmModeCoverageSchema)
18253
18268
  });
18269
+ /**
18270
+ * ONE rule's demand on ONE camera's clip ring.
18271
+ *
18272
+ * A rule, not a camera: the broker takes the MAX over the asks that reach a
18273
+ * camera, so the answer stays a faithful description of the rules and the
18274
+ * bounding (the byte budget, the broker's own ceiling) stays where the cost
18275
+ * lives. A camera that appears in no ask is being told **nothing** — which is
18276
+ * a different thing from never having been told, and only the envelope
18277
+ * (`rulesLoaded`) can tell those apart.
18278
+ */
18279
+ var NcClipRetentionAskSchema = object({
18280
+ /**
18281
+ * The camera this ask is about. **Absent = every camera**, which is what a
18282
+ * rule with no `conditions.devices` means: it can fire anywhere, so it is
18283
+ * asking everywhere.
18284
+ */
18285
+ deviceId: number().int().nonnegative().optional(),
18286
+ /** Seconds of history the rule needs held for it. Never zero — a rule that
18287
+ * needs nothing produces no ask at all. */
18288
+ seconds: number().min(0).max(60),
18289
+ /** The profile the rule cuts from, when it named one. Absent = the cheapest
18290
+ * assigned, which is what the cut defaults to. */
18291
+ profile: CamProfileSchema.optional(),
18292
+ /** Who is asking — so a retention the operator did not expect names a rule. */
18293
+ ruleId: string(),
18294
+ ruleName: string(),
18295
+ /** Why this many seconds: the rule's own window, or the occupancy ceiling. */
18296
+ reason: _enum(["window", "occupancy"])
18297
+ });
18298
+ /**
18299
+ * The whole answer, with the one bit that keeps absence from reading as zero.
18300
+ *
18301
+ * `rulesLoaded` is false until the rule ledger has completed a load at least
18302
+ * once. A centre that is up but has not read its rules yet answers with an
18303
+ * empty ask list that means nothing at all — applying it would drop every
18304
+ * camera's ring to zero for the first events after a restart, which is the
18305
+ * footage this mechanism exists to keep.
18306
+ */
18307
+ var NcClipRetentionPlanSchema = object({
18308
+ rulesLoaded: boolean(),
18309
+ asks: array(NcClipRetentionAskSchema).readonly()
18310
+ });
18254
18311
  method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), method(object({ ruleId: string() }), object({ rule: NcRuleSchema.nullable() }), { auth: "admin" }), method(object({ rule: NcRuleInputSchema }), object({ rule: NcRuleSchema }), {
18255
18312
  kind: "mutation",
18256
18313
  auth: "admin",
@@ -18271,7 +18328,7 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
18271
18328
  }), object({ success: literal(true) }), {
18272
18329
  kind: "mutation",
18273
18330
  auth: "admin"
18274
- }), method(object({}), object({ mutedDeviceIds: array(number().int()).readonly() }), { auth: "admin" }), method(object({
18331
+ }), method(object({}), NcClipRetentionPlanSchema, { auth: "admin" }), method(object({}), object({ mutedDeviceIds: array(number().int()).readonly() }), { auth: "admin" }), method(object({
18275
18332
  deviceId: number().int(),
18276
18333
  muted: boolean()
18277
18334
  }), object({ success: literal(true) }), {
@@ -20845,6 +20902,33 @@ var RunReplayFrameProcessorResultSchema = object({ tracks: array(object({
20845
20902
  * solid is this track", cheaper than re-deriving it from a trajectory. */
20846
20903
  framesMatched: number().int()
20847
20904
  })).readonly() });
20905
+ /**
20906
+ * The long-term series a camera produces. A closed union so a typo cannot
20907
+ * invent one, and the ONE declaration of it — the addon's `AnalyticsLtsSeries`
20908
+ * is an alias of this, not a second list.
20909
+ */
20910
+ var AnalyticsLtsSeriesSchema = _enum([
20911
+ "motion",
20912
+ "audio-dbfs",
20913
+ "battery",
20914
+ "occupancy"
20915
+ ]);
20916
+ /**
20917
+ * One closed 5-minute bucket of a long-term series.
20918
+ *
20919
+ * `samples` is how many readings the bucket folded — it is the ACTIVITY for a
20920
+ * series like `motion`, and the confidence for one like `occupancy`. A bucket
20921
+ * that exists at all was measured; a bucket that is absent was not, which is a
20922
+ * different claim from zero and the reason this is a sparse series.
20923
+ */
20924
+ var LtsBucketSchema = object({
20925
+ scope: string(),
20926
+ bucketStart: number().int(),
20927
+ samples: number().int().nonnegative(),
20928
+ sum: number(),
20929
+ min: number(),
20930
+ max: number()
20931
+ });
20848
20932
  DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
20849
20933
  deviceId: number(),
20850
20934
  trackId: string()
@@ -20891,6 +20975,14 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20891
20975
  kinds: array(string()).optional(),
20892
20976
  limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
20893
20977
  }), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(KeyEventBatchQueryInput, array(KeyEventsForDeviceSchema).readonly()), method(object({
20978
+ deviceId: number(),
20979
+ series: AnalyticsLtsSeriesSchema,
20980
+ /** Omit for EVERY scope of this series in the range. */
20981
+ scope: string().optional(),
20982
+ from: number(),
20983
+ to: number(),
20984
+ limit: number().int().positive().optional()
20985
+ }), array(LtsBucketSchema).readonly()), method(object({
20894
20986
  deviceId: number(),
20895
20987
  since: number(),
20896
20988
  until: number(),
@@ -21509,6 +21601,14 @@ var MotionSourceEnum = _enum([
21509
21601
  */
21510
21602
  var MotionSourcesSchema = array(MotionSourceEnum);
21511
21603
  /**
21604
+ * Which root detectors a camera runs. Deliberately the SAME vocabulary
21605
+ * post-analysis already tags every detection with (`DetectionSource`) rather
21606
+ * than a second spelling of the same two ideas — the value an operator picks
21607
+ * here is the value that comes back on the track, the overlay and the debug
21608
+ * row.
21609
+ */
21610
+ var DetectionSourcesSchema = array(DetectionSourceSchema);
21611
+ /**
21512
21612
  * Input shape for `pipeline-runner.reportMotion` cap method. Exported
21513
21613
  * so cap-side consumers (the orchestrator forward, the runner addon's
21514
21614
  * cap implementation, tests) can reuse the type instead of redeclaring
@@ -21659,6 +21759,35 @@ var RunnerCameraConfigSchema = object({
21659
21759
  * events; the orchestrator forwards to `reportMotion`.
21660
21760
  */
21661
21761
  motionSources: MotionSourcesSchema.default(["analyzer"]),
21762
+ /**
21763
+ * WHICH root detector runs for this camera. The detection counterpart of
21764
+ * {@link motionSources}, same shape and same discipline: a per-camera list
21765
+ * of sources the system understands, vendor-agnostic, owned here.
21766
+ *
21767
+ * - `pipeline` — this runner's own root step on decoded pixels (`steps`).
21768
+ * - `onboard` — the CAMERA's own detector, admitted only when it is named
21769
+ * here. Its boxes reach post-analysis on the same
21770
+ * `PipelineInferenceResult` payload as the pipeline's, so an onboard-born
21771
+ * track gets the same tracker, the same overlay and the same detail
21772
+ * subtree (face / plate / embedding).
21773
+ *
21774
+ * `['onboard']` alone is the REPLACEMENT: this runner's root step does not
21775
+ * run, and that is where a camera with a usable onboard detector buys back
21776
+ * its share of the accelerator. It saves the root inference, not the decode
21777
+ * — the detail subtree still needs pixels to cut crops from.
21778
+ *
21779
+ * A camera whose onboard detections carry no geometry cannot serve as a root
21780
+ * step at all (there is nothing to track), and the cap that knows this says
21781
+ * so on `native-object-detection.getOptions().geometry`. On Reolink that is
21782
+ * every battery camera: the boxes ride a sub-stream a battery camera never
21783
+ * attaches, so such a camera stays on `['pipeline']` and its onboard AI is
21784
+ * worth exactly what it already is — a wake signal with a class.
21785
+ *
21786
+ * Defaults to `['pipeline']`, which is byte-for-byte today's behaviour: a
21787
+ * vendor never turns a detector on for the operator, and neither does a
21788
+ * default.
21789
+ */
21790
+ detectionSources: DetectionSourcesSchema.default(["pipeline"]),
21662
21791
  pipelineEnabled: boolean().default(true),
21663
21792
  /** Ordered tree of video steps. Absent → runner skips video detection. */
21664
21793
  steps: array(PipelineStepInputSchema).readonly().optional(),
@@ -21840,7 +21969,47 @@ var RunnerLocalMetricsSchema = object({
21840
21969
  queueDepth: number(),
21841
21970
  frameLazy: FrameLazyMetricsSchema.optional()
21842
21971
  });
21972
+ /**
21973
+ * Pipeline Runner capability — runtime detection workhorse.
21974
+ *
21975
+ * One instance per node. Receives camera assignments from
21976
+ * `addon-pipeline-orchestrator`, subscribes to the local stream-broker for
21977
+ * decoded frames, drains motion + detection queues, calls the local
21978
+ * `motion-detection` and `pipeline-executor` capabilities, and emits typed
21979
+ * `pipeline.inference-result` and `detection.motion-analysis` events on
21980
+ * the bus.
21981
+ *
21982
+ * Distinct from `pipeline-orchestrator` (the hub-side load balancer) — the
21983
+ * runner has zero knowledge of other agents, no global state, and never
21984
+ * makes assignment decisions itself.
21985
+ */
21986
+ /**
21987
+ * Why a runner declined to look at a camera out of band. Named rather than a
21988
+ * bare `false`: a camera asleep on battery (D173), one attached elsewhere, one
21989
+ * already mid-session and one already bursting are four different facts, and a
21990
+ * caller told only "no" cannot tell a protection from a bug.
21991
+ */
21992
+ var OccupancyBurstRefusalSchema = _enum([
21993
+ "not-attached",
21994
+ "battery-asleep",
21995
+ "not-watching",
21996
+ "already-bursting"
21997
+ ]);
21843
21998
  method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mutation" }), method(object({ deviceId: number() }), object({ success: literal(true) }), { kind: "mutation" }), method(ReportMotionInputSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), RunnerLocalLoadSchema), method(_void(), RunnerLocalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(_void(), array(CameraMetricsWithDeviceIdSchema).readonly()), method(_void(), array(number()).readonly()), method(object({
21999
+ deviceId: number(),
22000
+ /** How many frames to collect. The caller sizes this against what its
22001
+ * own confirmation needs; the runner clamps it to the field's range. */
22002
+ frames: number().int().positive().optional(),
22003
+ /** Why, for the log. A burst nobody can attribute is a cost nobody can
22004
+ * defend — the periodic one at least has a timer to point at. */
22005
+ reason: string()
22006
+ }), object({
22007
+ started: boolean(),
22008
+ refusedBecause: OccupancyBurstRefusalSchema.optional()
22009
+ }), {
22010
+ auth: "admin",
22011
+ kind: "mutation"
22012
+ }), method(object({
21844
22013
  handle: FrameHandleSchema,
21845
22014
  bbox: NativeCropBboxSchema,
21846
22015
  maxWidth: number().int().positive().optional(),
@@ -28670,11 +28839,46 @@ var NativeObjectDetectionStatusSchema = object({
28670
28839
  supportedClasses: array(NativeObjectClassEnum).readonly(),
28671
28840
  /**
28672
28841
  * Whether forwarding of onboard AI detections is enabled for this device.
28673
- * Default FALSE (opt-in, cold-start) — onboard AI pushes are noisy/sparse and
28674
- * churn the tracker, so forwarding stays off until the operator enables it.
28842
+ *
28843
+ * Cold-start OFF on every camera. A vendor does not decide which detector a
28844
+ * camera runs — that is the operator's choice, and it is made where every
28845
+ * other detection choice is made. `geometry` on
28846
+ * {@link NativeObjectDetectionOptionsSchema} is how the form says what the
28847
+ * choice would buy this particular camera.
28675
28848
  */
28676
28849
  enabled: boolean()
28677
28850
  });
28851
+ /**
28852
+ * WHEN a camera's onboard detections carry geometry.
28853
+ *
28854
+ * - `boxed` — always. The provider holds a standing channel for the boxes, so
28855
+ * a detection is a trackable subject whenever the camera sees one.
28856
+ * - `while-streaming` — only while some stream of this camera is already open.
28857
+ * The boxes ride the video's own side-channel rather than a feed of their
28858
+ * own, so they cost nothing and they exist only when something is pulling.
28859
+ * On Reolink this is every BATTERY camera: a persistent second feed is real
28860
+ * radio drain, but a camera that is awake is awake precisely because
28861
+ * something is in front of it, and its stream is already being pulled.
28862
+ * - `flag-only` — never. The firmware ships the class and nothing else; the
28863
+ * pipeline needs geometry to make a subject, so such a push reaches the
28864
+ * tracker as motion and no further.
28865
+ *
28866
+ * Reported and not inferred, because the operator's question in front of the
28867
+ * picker is "what do I get", and these are three different answers (D14: the
28868
+ * derived form is only as honest as `getOptions`).
28869
+ */
28870
+ var NativeObjectGeometryEnum = _enum([
28871
+ "boxed",
28872
+ "while-streaming",
28873
+ "flag-only"
28874
+ ]);
28875
+ var NativeObjectDetectionOptionsSchema = object({
28876
+ /** Classes this firmware can detect — the same list the status reports. */
28877
+ supportedClasses: array(NativeObjectClassEnum).readonly(),
28878
+ /** What a detection from this camera carries. */
28879
+ geometry: NativeObjectGeometryEnum
28880
+ });
28881
+ var NativeObjectDetectionSettingsPatchSchema = object({ enabled: boolean().optional() });
28678
28882
  var NativeObjectDetectionRuntimeStateSchema = NativeObjectDetectionStatusSchema.extend({
28679
28883
  /** Required by createRuntimeStateBridge — epoch ms of last refresh. */
28680
28884
  lastFetchedAt: number() });
@@ -28684,13 +28888,23 @@ var nativeObjectDetectionCapability = {
28684
28888
  deviceNative: true,
28685
28889
  mode: "singleton",
28686
28890
  deviceTypes: [DeviceType.Camera],
28687
- methods: { setEnabled: method(object({
28688
- deviceId: number(),
28689
- enabled: boolean()
28690
- }), _void(), {
28691
- kind: "mutation",
28692
- auth: "admin"
28693
- }) },
28891
+ methods: {
28892
+ getOptions: method(object({ deviceId: number() }), NativeObjectDetectionOptionsSchema),
28893
+ setSettings: method(object({
28894
+ deviceId: number(),
28895
+ settings: NativeObjectDetectionSettingsPatchSchema
28896
+ }), _void(), {
28897
+ kind: "mutation",
28898
+ auth: "admin"
28899
+ }),
28900
+ setEnabled: method(object({
28901
+ deviceId: number(),
28902
+ enabled: boolean()
28903
+ }), _void(), {
28904
+ kind: "mutation",
28905
+ auth: "admin"
28906
+ })
28907
+ },
28694
28908
  events: { onDetected: { data: object({
28695
28909
  deviceId: number(),
28696
28910
  detection: NativeDetectionSchema
@@ -33538,7 +33752,28 @@ var PerScopeBreakdownSchema = object({
33538
33752
  /** Total tracked objects in this scope (frame / zone / unzoned). */
33539
33753
  totalObjects: number().int().nonnegative(),
33540
33754
  /** Per-class count. Keys are macro class names (e.g. `person`, `car`). */
33541
- byClass: record(string(), number().int().nonnegative())
33755
+ byClass: record(string(), number().int().nonnegative()),
33756
+ /**
33757
+ * Of `totalObjects`, how many are STANDING — objects the census holds,
33758
+ * present but not going anywhere (a parked car, a bin, a statue).
33759
+ *
33760
+ * The operator's question about a scene has two halves and they answer
33761
+ * different things: "what is parked here" is stable for hours and must not
33762
+ * flap, while "who is walking through" is the thing an alert is about. One
33763
+ * number could only serve one of them, and `totalObjects` served the first
33764
+ * badly — a passer-by moved it and every occupancy rule saw a change.
33765
+ *
33766
+ * `standing + transient === totalObjects`, always. The total keeps its old
33767
+ * meaning exactly, so no rule written against it changes behaviour.
33768
+ *
33769
+ * ABSENT means UNKNOWN, never zero (D393): a snapshot from a node older than
33770
+ * this field cannot say, and a reader that folds absence in as 0 reports "no
33771
+ * parked objects here" about a camera whose lot is full.
33772
+ */
33773
+ standingObjects: number().int().nonnegative().optional(),
33774
+ /** Of `totalObjects`, how many are passing through. See `standingObjects` —
33775
+ * same absence rule. */
33776
+ transientObjects: number().int().nonnegative().optional()
33542
33777
  });
33543
33778
  var ZoneScopeBreakdownSchema = PerScopeBreakdownSchema.extend({
33544
33779
  zoneId: string(),
@@ -33661,6 +33896,23 @@ var HistoryPointSchema = object({
33661
33896
  * triple covers the three spatial scopes (per-zone, frame-wide,
33662
33897
  * outside-any-zone). Crossing them with `className?` gives the full
33663
33898
  * combinatorial coverage the operator UI requested.
33899
+ *
33900
+ * ## ⚠️ The three history methods are DEPRECATED
33901
+ *
33902
+ * They are served from a 60-MINUTE in-memory ring. It dies with the process,
33903
+ * so after a restart they report nothing about a night that did happen, and any
33904
+ * window past an hour is silently clamped — a caller cannot tell a clamp from
33905
+ * an empty scene. The presets in the occupancy chart existed to hide that
33906
+ * horizon rather than to answer a question.
33907
+ *
33908
+ * Use `pipelineAnalytics.readLongTermSeries({ series: 'occupancy', scope })`
33909
+ * instead. Those rows are already written for every camera, ~60 bytes per
33910
+ * (camera, scope, 5-minute bucket), kept for a year, and survive a restart.
33911
+ * Spell the scope with `occupancyScope(zoneId?, className?)` — the same
33912
+ * function the writer uses, so the two cannot drift.
33913
+ *
33914
+ * The ring stays until these three go, and it is the only thing left reading
33915
+ * it. Do not add a fourth caller.
33664
33916
  */
33665
33917
  var zoneAnalyticsCapability = {
33666
33918
  name: "zone-analytics",
@@ -38060,12 +38312,24 @@ Object.freeze({
38060
38312
  addonId: null,
38061
38313
  access: "create"
38062
38314
  },
38315
+ "nativeObjectDetection.getOptions": {
38316
+ capName: "native-object-detection",
38317
+ capScope: "device",
38318
+ addonId: null,
38319
+ access: "view"
38320
+ },
38063
38321
  "nativeObjectDetection.setEnabled": {
38064
38322
  capName: "native-object-detection",
38065
38323
  capScope: "device",
38066
38324
  addonId: null,
38067
38325
  access: "create"
38068
38326
  },
38327
+ "nativeObjectDetection.setSettings": {
38328
+ capName: "native-object-detection",
38329
+ capScope: "device",
38330
+ addonId: null,
38331
+ access: "create"
38332
+ },
38069
38333
  "navigation.getFeatures": {
38070
38334
  capName: "navigation",
38071
38335
  capScope: "device",
@@ -38330,6 +38594,12 @@ Object.freeze({
38330
38594
  addonId: null,
38331
38595
  access: "view"
38332
38596
  },
38597
+ "notificationRules.getClipRetentionAsks": {
38598
+ capName: "notification-rules",
38599
+ capScope: "system",
38600
+ addonId: null,
38601
+ access: "view"
38602
+ },
38333
38603
  "notificationRules.getConditionCatalog": {
38334
38604
  capName: "notification-rules",
38335
38605
  capScope: "system",
@@ -38840,6 +39110,12 @@ Object.freeze({
38840
39110
  addonId: null,
38841
39111
  access: "create"
38842
39112
  },
39113
+ "pipelineAnalytics.readLongTermSeries": {
39114
+ capName: "pipeline-analytics",
39115
+ capScope: "device",
39116
+ addonId: null,
39117
+ access: "view"
39118
+ },
38843
39119
  "pipelineAnalytics.rebuildObjectEmbeddings": {
38844
39120
  capName: "pipeline-analytics",
38845
39121
  capScope: "device",
@@ -39512,6 +39788,12 @@ Object.freeze({
39512
39788
  addonId: null,
39513
39789
  access: "create"
39514
39790
  },
39791
+ "pipelineRunner.requestOccupancyBurst": {
39792
+ capName: "pipeline-runner",
39793
+ capScope: "system",
39794
+ addonId: null,
39795
+ access: "create"
39796
+ },
39515
39797
  "pipelineRunner.runDetailSubtree": {
39516
39798
  capName: "pipeline-runner",
39517
39799
  capScope: "system",
@@ -42292,11 +42574,21 @@ Object.freeze({
42292
42574
  form: "single",
42293
42575
  optional: false
42294
42576
  }],
42577
+ "nativeObjectDetection.getOptions": [{
42578
+ name: "deviceId",
42579
+ form: "single",
42580
+ optional: false
42581
+ }],
42295
42582
  "nativeObjectDetection.setEnabled": [{
42296
42583
  name: "deviceId",
42297
42584
  form: "single",
42298
42585
  optional: false
42299
42586
  }],
42587
+ "nativeObjectDetection.setSettings": [{
42588
+ name: "deviceId",
42589
+ form: "single",
42590
+ optional: false
42591
+ }],
42300
42592
  "navigation.getFeatures": [{
42301
42593
  name: "deviceId",
42302
42594
  form: "single",
@@ -42646,6 +42938,11 @@ Object.freeze({
42646
42938
  form: "single",
42647
42939
  optional: false
42648
42940
  }],
42941
+ "pipelineAnalytics.readLongTermSeries": [{
42942
+ name: "deviceId",
42943
+ form: "single",
42944
+ optional: false
42945
+ }],
42649
42946
  "pipelineAnalytics.rebuildObjectEmbeddings": [{
42650
42947
  name: "deviceId",
42651
42948
  form: "single",
@@ -42836,6 +43133,11 @@ Object.freeze({
42836
43133
  form: "single",
42837
43134
  optional: false
42838
43135
  }],
43136
+ "pipelineRunner.requestOccupancyBurst": [{
43137
+ name: "deviceId",
43138
+ form: "single",
43139
+ optional: false
43140
+ }],
42839
43141
  "pipelineRunner.runDetailSubtree": [{
42840
43142
  name: "deviceId",
42841
43143
  form: "single",
package/dist/addon.mjs CHANGED
@@ -5370,7 +5370,7 @@ var ZodIssueCode = {
5370
5370
  var ZodFirstPartyTypeKind;
5371
5371
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5372
5372
  //#endregion
5373
- //#region ../types/dist/sleep-DEuj7E3j.mjs
5373
+ //#region ../types/dist/sleep-BDR76Ykr.mjs
5374
5374
  /**
5375
5375
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5376
5376
  * window to float samples (D455).
@@ -11621,6 +11621,21 @@ var streamSignalsCapability = {
11621
11621
  mode: "singleton",
11622
11622
  deviceTypes: Object.values(DeviceType),
11623
11623
  runtimeState: StreamSignalsStatusSchema,
11624
+ /**
11625
+ * Runtime-state durability: **session** — mirrored in RAM, never written.
11626
+ *
11627
+ * The slice holds what the DEVICE says it can emit. That is a probed fact,
11628
+ * not an operator choice: the provider re-declares it on every registration,
11629
+ * so losing it loses nothing and persisting it would freeze an answer the
11630
+ * camera is entitled to change. Measured the same day on the sibling case —
11631
+ * `native-object-detection.supportedClasses` was persisted, and a firmware
11632
+ * class the camera really detected stayed missing for the life of the row
11633
+ * because the fix could not reach it.
11634
+ *
11635
+ * See `RuntimeStateDurability`. Enforced by
11636
+ * `scripts/check-runtime-state-durability.ts`.
11637
+ */
11638
+ durability: "session",
11624
11639
  methods: {
11625
11640
  /**
11626
11641
  * What this device can emit. Empty is a valid and common answer — most
@@ -18252,6 +18267,48 @@ var NcAlarmConfigSchema = object({
18252
18267
  settings: NcAlarmSettingsSchema,
18253
18268
  coverage: array(NcAlarmModeCoverageSchema)
18254
18269
  });
18270
+ /**
18271
+ * ONE rule's demand on ONE camera's clip ring.
18272
+ *
18273
+ * A rule, not a camera: the broker takes the MAX over the asks that reach a
18274
+ * camera, so the answer stays a faithful description of the rules and the
18275
+ * bounding (the byte budget, the broker's own ceiling) stays where the cost
18276
+ * lives. A camera that appears in no ask is being told **nothing** — which is
18277
+ * a different thing from never having been told, and only the envelope
18278
+ * (`rulesLoaded`) can tell those apart.
18279
+ */
18280
+ var NcClipRetentionAskSchema = object({
18281
+ /**
18282
+ * The camera this ask is about. **Absent = every camera**, which is what a
18283
+ * rule with no `conditions.devices` means: it can fire anywhere, so it is
18284
+ * asking everywhere.
18285
+ */
18286
+ deviceId: number().int().nonnegative().optional(),
18287
+ /** Seconds of history the rule needs held for it. Never zero — a rule that
18288
+ * needs nothing produces no ask at all. */
18289
+ seconds: number().min(0).max(60),
18290
+ /** The profile the rule cuts from, when it named one. Absent = the cheapest
18291
+ * assigned, which is what the cut defaults to. */
18292
+ profile: CamProfileSchema.optional(),
18293
+ /** Who is asking — so a retention the operator did not expect names a rule. */
18294
+ ruleId: string(),
18295
+ ruleName: string(),
18296
+ /** Why this many seconds: the rule's own window, or the occupancy ceiling. */
18297
+ reason: _enum(["window", "occupancy"])
18298
+ });
18299
+ /**
18300
+ * The whole answer, with the one bit that keeps absence from reading as zero.
18301
+ *
18302
+ * `rulesLoaded` is false until the rule ledger has completed a load at least
18303
+ * once. A centre that is up but has not read its rules yet answers with an
18304
+ * empty ask list that means nothing at all — applying it would drop every
18305
+ * camera's ring to zero for the first events after a restart, which is the
18306
+ * footage this mechanism exists to keep.
18307
+ */
18308
+ var NcClipRetentionPlanSchema = object({
18309
+ rulesLoaded: boolean(),
18310
+ asks: array(NcClipRetentionAskSchema).readonly()
18311
+ });
18255
18312
  method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), method(object({ ruleId: string() }), object({ rule: NcRuleSchema.nullable() }), { auth: "admin" }), method(object({ rule: NcRuleInputSchema }), object({ rule: NcRuleSchema }), {
18256
18313
  kind: "mutation",
18257
18314
  auth: "admin",
@@ -18272,7 +18329,7 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
18272
18329
  }), object({ success: literal(true) }), {
18273
18330
  kind: "mutation",
18274
18331
  auth: "admin"
18275
- }), method(object({}), object({ mutedDeviceIds: array(number().int()).readonly() }), { auth: "admin" }), method(object({
18332
+ }), method(object({}), NcClipRetentionPlanSchema, { auth: "admin" }), method(object({}), object({ mutedDeviceIds: array(number().int()).readonly() }), { auth: "admin" }), method(object({
18276
18333
  deviceId: number().int(),
18277
18334
  muted: boolean()
18278
18335
  }), object({ success: literal(true) }), {
@@ -20846,6 +20903,33 @@ var RunReplayFrameProcessorResultSchema = object({ tracks: array(object({
20846
20903
  * solid is this track", cheaper than re-deriving it from a trajectory. */
20847
20904
  framesMatched: number().int()
20848
20905
  })).readonly() });
20906
+ /**
20907
+ * The long-term series a camera produces. A closed union so a typo cannot
20908
+ * invent one, and the ONE declaration of it — the addon's `AnalyticsLtsSeries`
20909
+ * is an alias of this, not a second list.
20910
+ */
20911
+ var AnalyticsLtsSeriesSchema = _enum([
20912
+ "motion",
20913
+ "audio-dbfs",
20914
+ "battery",
20915
+ "occupancy"
20916
+ ]);
20917
+ /**
20918
+ * One closed 5-minute bucket of a long-term series.
20919
+ *
20920
+ * `samples` is how many readings the bucket folded — it is the ACTIVITY for a
20921
+ * series like `motion`, and the confidence for one like `occupancy`. A bucket
20922
+ * that exists at all was measured; a bucket that is absent was not, which is a
20923
+ * different claim from zero and the reason this is a sparse series.
20924
+ */
20925
+ var LtsBucketSchema = object({
20926
+ scope: string(),
20927
+ bucketStart: number().int(),
20928
+ samples: number().int().nonnegative(),
20929
+ sum: number(),
20930
+ min: number(),
20931
+ max: number()
20932
+ });
20849
20933
  DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
20850
20934
  deviceId: number(),
20851
20935
  trackId: string()
@@ -20892,6 +20976,14 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20892
20976
  kinds: array(string()).optional(),
20893
20977
  limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
20894
20978
  }), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(KeyEventBatchQueryInput, array(KeyEventsForDeviceSchema).readonly()), method(object({
20979
+ deviceId: number(),
20980
+ series: AnalyticsLtsSeriesSchema,
20981
+ /** Omit for EVERY scope of this series in the range. */
20982
+ scope: string().optional(),
20983
+ from: number(),
20984
+ to: number(),
20985
+ limit: number().int().positive().optional()
20986
+ }), array(LtsBucketSchema).readonly()), method(object({
20895
20987
  deviceId: number(),
20896
20988
  since: number(),
20897
20989
  until: number(),
@@ -21510,6 +21602,14 @@ var MotionSourceEnum = _enum([
21510
21602
  */
21511
21603
  var MotionSourcesSchema = array(MotionSourceEnum);
21512
21604
  /**
21605
+ * Which root detectors a camera runs. Deliberately the SAME vocabulary
21606
+ * post-analysis already tags every detection with (`DetectionSource`) rather
21607
+ * than a second spelling of the same two ideas — the value an operator picks
21608
+ * here is the value that comes back on the track, the overlay and the debug
21609
+ * row.
21610
+ */
21611
+ var DetectionSourcesSchema = array(DetectionSourceSchema);
21612
+ /**
21513
21613
  * Input shape for `pipeline-runner.reportMotion` cap method. Exported
21514
21614
  * so cap-side consumers (the orchestrator forward, the runner addon's
21515
21615
  * cap implementation, tests) can reuse the type instead of redeclaring
@@ -21660,6 +21760,35 @@ var RunnerCameraConfigSchema = object({
21660
21760
  * events; the orchestrator forwards to `reportMotion`.
21661
21761
  */
21662
21762
  motionSources: MotionSourcesSchema.default(["analyzer"]),
21763
+ /**
21764
+ * WHICH root detector runs for this camera. The detection counterpart of
21765
+ * {@link motionSources}, same shape and same discipline: a per-camera list
21766
+ * of sources the system understands, vendor-agnostic, owned here.
21767
+ *
21768
+ * - `pipeline` — this runner's own root step on decoded pixels (`steps`).
21769
+ * - `onboard` — the CAMERA's own detector, admitted only when it is named
21770
+ * here. Its boxes reach post-analysis on the same
21771
+ * `PipelineInferenceResult` payload as the pipeline's, so an onboard-born
21772
+ * track gets the same tracker, the same overlay and the same detail
21773
+ * subtree (face / plate / embedding).
21774
+ *
21775
+ * `['onboard']` alone is the REPLACEMENT: this runner's root step does not
21776
+ * run, and that is where a camera with a usable onboard detector buys back
21777
+ * its share of the accelerator. It saves the root inference, not the decode
21778
+ * — the detail subtree still needs pixels to cut crops from.
21779
+ *
21780
+ * A camera whose onboard detections carry no geometry cannot serve as a root
21781
+ * step at all (there is nothing to track), and the cap that knows this says
21782
+ * so on `native-object-detection.getOptions().geometry`. On Reolink that is
21783
+ * every battery camera: the boxes ride a sub-stream a battery camera never
21784
+ * attaches, so such a camera stays on `['pipeline']` and its onboard AI is
21785
+ * worth exactly what it already is — a wake signal with a class.
21786
+ *
21787
+ * Defaults to `['pipeline']`, which is byte-for-byte today's behaviour: a
21788
+ * vendor never turns a detector on for the operator, and neither does a
21789
+ * default.
21790
+ */
21791
+ detectionSources: DetectionSourcesSchema.default(["pipeline"]),
21663
21792
  pipelineEnabled: boolean().default(true),
21664
21793
  /** Ordered tree of video steps. Absent → runner skips video detection. */
21665
21794
  steps: array(PipelineStepInputSchema).readonly().optional(),
@@ -21841,7 +21970,47 @@ var RunnerLocalMetricsSchema = object({
21841
21970
  queueDepth: number(),
21842
21971
  frameLazy: FrameLazyMetricsSchema.optional()
21843
21972
  });
21973
+ /**
21974
+ * Pipeline Runner capability — runtime detection workhorse.
21975
+ *
21976
+ * One instance per node. Receives camera assignments from
21977
+ * `addon-pipeline-orchestrator`, subscribes to the local stream-broker for
21978
+ * decoded frames, drains motion + detection queues, calls the local
21979
+ * `motion-detection` and `pipeline-executor` capabilities, and emits typed
21980
+ * `pipeline.inference-result` and `detection.motion-analysis` events on
21981
+ * the bus.
21982
+ *
21983
+ * Distinct from `pipeline-orchestrator` (the hub-side load balancer) — the
21984
+ * runner has zero knowledge of other agents, no global state, and never
21985
+ * makes assignment decisions itself.
21986
+ */
21987
+ /**
21988
+ * Why a runner declined to look at a camera out of band. Named rather than a
21989
+ * bare `false`: a camera asleep on battery (D173), one attached elsewhere, one
21990
+ * already mid-session and one already bursting are four different facts, and a
21991
+ * caller told only "no" cannot tell a protection from a bug.
21992
+ */
21993
+ var OccupancyBurstRefusalSchema = _enum([
21994
+ "not-attached",
21995
+ "battery-asleep",
21996
+ "not-watching",
21997
+ "already-bursting"
21998
+ ]);
21844
21999
  method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mutation" }), method(object({ deviceId: number() }), object({ success: literal(true) }), { kind: "mutation" }), method(ReportMotionInputSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), RunnerLocalLoadSchema), method(_void(), RunnerLocalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(_void(), array(CameraMetricsWithDeviceIdSchema).readonly()), method(_void(), array(number()).readonly()), method(object({
22000
+ deviceId: number(),
22001
+ /** How many frames to collect. The caller sizes this against what its
22002
+ * own confirmation needs; the runner clamps it to the field's range. */
22003
+ frames: number().int().positive().optional(),
22004
+ /** Why, for the log. A burst nobody can attribute is a cost nobody can
22005
+ * defend — the periodic one at least has a timer to point at. */
22006
+ reason: string()
22007
+ }), object({
22008
+ started: boolean(),
22009
+ refusedBecause: OccupancyBurstRefusalSchema.optional()
22010
+ }), {
22011
+ auth: "admin",
22012
+ kind: "mutation"
22013
+ }), method(object({
21845
22014
  handle: FrameHandleSchema,
21846
22015
  bbox: NativeCropBboxSchema,
21847
22016
  maxWidth: number().int().positive().optional(),
@@ -28671,11 +28840,46 @@ var NativeObjectDetectionStatusSchema = object({
28671
28840
  supportedClasses: array(NativeObjectClassEnum).readonly(),
28672
28841
  /**
28673
28842
  * Whether forwarding of onboard AI detections is enabled for this device.
28674
- * Default FALSE (opt-in, cold-start) — onboard AI pushes are noisy/sparse and
28675
- * churn the tracker, so forwarding stays off until the operator enables it.
28843
+ *
28844
+ * Cold-start OFF on every camera. A vendor does not decide which detector a
28845
+ * camera runs — that is the operator's choice, and it is made where every
28846
+ * other detection choice is made. `geometry` on
28847
+ * {@link NativeObjectDetectionOptionsSchema} is how the form says what the
28848
+ * choice would buy this particular camera.
28676
28849
  */
28677
28850
  enabled: boolean()
28678
28851
  });
28852
+ /**
28853
+ * WHEN a camera's onboard detections carry geometry.
28854
+ *
28855
+ * - `boxed` — always. The provider holds a standing channel for the boxes, so
28856
+ * a detection is a trackable subject whenever the camera sees one.
28857
+ * - `while-streaming` — only while some stream of this camera is already open.
28858
+ * The boxes ride the video's own side-channel rather than a feed of their
28859
+ * own, so they cost nothing and they exist only when something is pulling.
28860
+ * On Reolink this is every BATTERY camera: a persistent second feed is real
28861
+ * radio drain, but a camera that is awake is awake precisely because
28862
+ * something is in front of it, and its stream is already being pulled.
28863
+ * - `flag-only` — never. The firmware ships the class and nothing else; the
28864
+ * pipeline needs geometry to make a subject, so such a push reaches the
28865
+ * tracker as motion and no further.
28866
+ *
28867
+ * Reported and not inferred, because the operator's question in front of the
28868
+ * picker is "what do I get", and these are three different answers (D14: the
28869
+ * derived form is only as honest as `getOptions`).
28870
+ */
28871
+ var NativeObjectGeometryEnum = _enum([
28872
+ "boxed",
28873
+ "while-streaming",
28874
+ "flag-only"
28875
+ ]);
28876
+ var NativeObjectDetectionOptionsSchema = object({
28877
+ /** Classes this firmware can detect — the same list the status reports. */
28878
+ supportedClasses: array(NativeObjectClassEnum).readonly(),
28879
+ /** What a detection from this camera carries. */
28880
+ geometry: NativeObjectGeometryEnum
28881
+ });
28882
+ var NativeObjectDetectionSettingsPatchSchema = object({ enabled: boolean().optional() });
28679
28883
  var NativeObjectDetectionRuntimeStateSchema = NativeObjectDetectionStatusSchema.extend({
28680
28884
  /** Required by createRuntimeStateBridge — epoch ms of last refresh. */
28681
28885
  lastFetchedAt: number() });
@@ -28685,13 +28889,23 @@ var nativeObjectDetectionCapability = {
28685
28889
  deviceNative: true,
28686
28890
  mode: "singleton",
28687
28891
  deviceTypes: [DeviceType.Camera],
28688
- methods: { setEnabled: method(object({
28689
- deviceId: number(),
28690
- enabled: boolean()
28691
- }), _void(), {
28692
- kind: "mutation",
28693
- auth: "admin"
28694
- }) },
28892
+ methods: {
28893
+ getOptions: method(object({ deviceId: number() }), NativeObjectDetectionOptionsSchema),
28894
+ setSettings: method(object({
28895
+ deviceId: number(),
28896
+ settings: NativeObjectDetectionSettingsPatchSchema
28897
+ }), _void(), {
28898
+ kind: "mutation",
28899
+ auth: "admin"
28900
+ }),
28901
+ setEnabled: method(object({
28902
+ deviceId: number(),
28903
+ enabled: boolean()
28904
+ }), _void(), {
28905
+ kind: "mutation",
28906
+ auth: "admin"
28907
+ })
28908
+ },
28695
28909
  events: { onDetected: { data: object({
28696
28910
  deviceId: number(),
28697
28911
  detection: NativeDetectionSchema
@@ -33539,7 +33753,28 @@ var PerScopeBreakdownSchema = object({
33539
33753
  /** Total tracked objects in this scope (frame / zone / unzoned). */
33540
33754
  totalObjects: number().int().nonnegative(),
33541
33755
  /** Per-class count. Keys are macro class names (e.g. `person`, `car`). */
33542
- byClass: record(string(), number().int().nonnegative())
33756
+ byClass: record(string(), number().int().nonnegative()),
33757
+ /**
33758
+ * Of `totalObjects`, how many are STANDING — objects the census holds,
33759
+ * present but not going anywhere (a parked car, a bin, a statue).
33760
+ *
33761
+ * The operator's question about a scene has two halves and they answer
33762
+ * different things: "what is parked here" is stable for hours and must not
33763
+ * flap, while "who is walking through" is the thing an alert is about. One
33764
+ * number could only serve one of them, and `totalObjects` served the first
33765
+ * badly — a passer-by moved it and every occupancy rule saw a change.
33766
+ *
33767
+ * `standing + transient === totalObjects`, always. The total keeps its old
33768
+ * meaning exactly, so no rule written against it changes behaviour.
33769
+ *
33770
+ * ABSENT means UNKNOWN, never zero (D393): a snapshot from a node older than
33771
+ * this field cannot say, and a reader that folds absence in as 0 reports "no
33772
+ * parked objects here" about a camera whose lot is full.
33773
+ */
33774
+ standingObjects: number().int().nonnegative().optional(),
33775
+ /** Of `totalObjects`, how many are passing through. See `standingObjects` —
33776
+ * same absence rule. */
33777
+ transientObjects: number().int().nonnegative().optional()
33543
33778
  });
33544
33779
  var ZoneScopeBreakdownSchema = PerScopeBreakdownSchema.extend({
33545
33780
  zoneId: string(),
@@ -33662,6 +33897,23 @@ var HistoryPointSchema = object({
33662
33897
  * triple covers the three spatial scopes (per-zone, frame-wide,
33663
33898
  * outside-any-zone). Crossing them with `className?` gives the full
33664
33899
  * combinatorial coverage the operator UI requested.
33900
+ *
33901
+ * ## ⚠️ The three history methods are DEPRECATED
33902
+ *
33903
+ * They are served from a 60-MINUTE in-memory ring. It dies with the process,
33904
+ * so after a restart they report nothing about a night that did happen, and any
33905
+ * window past an hour is silently clamped — a caller cannot tell a clamp from
33906
+ * an empty scene. The presets in the occupancy chart existed to hide that
33907
+ * horizon rather than to answer a question.
33908
+ *
33909
+ * Use `pipelineAnalytics.readLongTermSeries({ series: 'occupancy', scope })`
33910
+ * instead. Those rows are already written for every camera, ~60 bytes per
33911
+ * (camera, scope, 5-minute bucket), kept for a year, and survive a restart.
33912
+ * Spell the scope with `occupancyScope(zoneId?, className?)` — the same
33913
+ * function the writer uses, so the two cannot drift.
33914
+ *
33915
+ * The ring stays until these three go, and it is the only thing left reading
33916
+ * it. Do not add a fourth caller.
33665
33917
  */
33666
33918
  var zoneAnalyticsCapability = {
33667
33919
  name: "zone-analytics",
@@ -38061,12 +38313,24 @@ Object.freeze({
38061
38313
  addonId: null,
38062
38314
  access: "create"
38063
38315
  },
38316
+ "nativeObjectDetection.getOptions": {
38317
+ capName: "native-object-detection",
38318
+ capScope: "device",
38319
+ addonId: null,
38320
+ access: "view"
38321
+ },
38064
38322
  "nativeObjectDetection.setEnabled": {
38065
38323
  capName: "native-object-detection",
38066
38324
  capScope: "device",
38067
38325
  addonId: null,
38068
38326
  access: "create"
38069
38327
  },
38328
+ "nativeObjectDetection.setSettings": {
38329
+ capName: "native-object-detection",
38330
+ capScope: "device",
38331
+ addonId: null,
38332
+ access: "create"
38333
+ },
38070
38334
  "navigation.getFeatures": {
38071
38335
  capName: "navigation",
38072
38336
  capScope: "device",
@@ -38331,6 +38595,12 @@ Object.freeze({
38331
38595
  addonId: null,
38332
38596
  access: "view"
38333
38597
  },
38598
+ "notificationRules.getClipRetentionAsks": {
38599
+ capName: "notification-rules",
38600
+ capScope: "system",
38601
+ addonId: null,
38602
+ access: "view"
38603
+ },
38334
38604
  "notificationRules.getConditionCatalog": {
38335
38605
  capName: "notification-rules",
38336
38606
  capScope: "system",
@@ -38841,6 +39111,12 @@ Object.freeze({
38841
39111
  addonId: null,
38842
39112
  access: "create"
38843
39113
  },
39114
+ "pipelineAnalytics.readLongTermSeries": {
39115
+ capName: "pipeline-analytics",
39116
+ capScope: "device",
39117
+ addonId: null,
39118
+ access: "view"
39119
+ },
38844
39120
  "pipelineAnalytics.rebuildObjectEmbeddings": {
38845
39121
  capName: "pipeline-analytics",
38846
39122
  capScope: "device",
@@ -39513,6 +39789,12 @@ Object.freeze({
39513
39789
  addonId: null,
39514
39790
  access: "create"
39515
39791
  },
39792
+ "pipelineRunner.requestOccupancyBurst": {
39793
+ capName: "pipeline-runner",
39794
+ capScope: "system",
39795
+ addonId: null,
39796
+ access: "create"
39797
+ },
39516
39798
  "pipelineRunner.runDetailSubtree": {
39517
39799
  capName: "pipeline-runner",
39518
39800
  capScope: "system",
@@ -42293,11 +42575,21 @@ Object.freeze({
42293
42575
  form: "single",
42294
42576
  optional: false
42295
42577
  }],
42578
+ "nativeObjectDetection.getOptions": [{
42579
+ name: "deviceId",
42580
+ form: "single",
42581
+ optional: false
42582
+ }],
42296
42583
  "nativeObjectDetection.setEnabled": [{
42297
42584
  name: "deviceId",
42298
42585
  form: "single",
42299
42586
  optional: false
42300
42587
  }],
42588
+ "nativeObjectDetection.setSettings": [{
42589
+ name: "deviceId",
42590
+ form: "single",
42591
+ optional: false
42592
+ }],
42301
42593
  "navigation.getFeatures": [{
42302
42594
  name: "deviceId",
42303
42595
  form: "single",
@@ -42647,6 +42939,11 @@ Object.freeze({
42647
42939
  form: "single",
42648
42940
  optional: false
42649
42941
  }],
42942
+ "pipelineAnalytics.readLongTermSeries": [{
42943
+ name: "deviceId",
42944
+ form: "single",
42945
+ optional: false
42946
+ }],
42650
42947
  "pipelineAnalytics.rebuildObjectEmbeddings": [{
42651
42948
  name: "deviceId",
42652
42949
  form: "single",
@@ -42837,6 +43134,11 @@ Object.freeze({
42837
43134
  form: "single",
42838
43135
  optional: false
42839
43136
  }],
43137
+ "pipelineRunner.requestOccupancyBurst": [{
43138
+ name: "deviceId",
43139
+ form: "single",
43140
+ optional: false
43141
+ }],
42840
43142
  "pipelineRunner.runDetailSubtree": [{
42841
43143
  name: "deviceId",
42842
43144
  form: "single",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-homematic",
3
- "version": "1.2.103",
3
+ "version": "1.2.104",
4
4
  "description": "Homematic / HomematicIP (CCU3 / RaspberryMatic) device-provider addon for CamStack — wraps the nodehomematic library",
5
5
  "keywords": [
6
6
  "camstack",
@@ -68,7 +68,7 @@
68
68
  "dev": "vite build --watch",
69
69
  "typecheck": "tsc --noEmit",
70
70
  "test": "vitest run",
71
- "publish": "npm publish --access public"
71
+ "publish:npm": "npm publish --access public"
72
72
  },
73
73
  "dependencies": {
74
74
  "nodehomematic": "^0.4.1"