@camstack/addon-provider-rademacher 0.2.55 → 0.2.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/addon.js CHANGED
@@ -20168,7 +20168,20 @@ var RecentTracksQueryInput = object({
20168
20168
  projection: TrackProjectionSchema.optional(),
20169
20169
  /** Include stationary-promoted rows (parked objects). Default false: the
20170
20170
  * feed lists passages; parking records live on the stationary registry. */
20171
- includeStationary: boolean().optional()
20171
+ includeStationary: boolean().optional(),
20172
+ /**
20173
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
20174
+ *
20175
+ * The same filter `listTracks` takes, because the timeline's class chips must
20176
+ * mean the same thing whether the scope is one camera or twelve. Until this
20177
+ * existed the scoped feed downloaded a page and narrowed it on the phone
20178
+ * while the single-camera path narrowed the read — one filter, two costs.
20179
+ *
20180
+ * A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
20181
+ * whose class list is unreadable are kept, and the client's rule stays the
20182
+ * exact one.
20183
+ */
20184
+ classes: array(string()).optional()
20172
20185
  });
20173
20186
  var RecentTracksPageSchema = object({
20174
20187
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -20555,7 +20568,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20555
20568
  /** Include stationary-promoted rows (parked objects handed to the
20556
20569
  * stationary registry). Default false: the timeline lists passages,
20557
20570
  * not parking records (operator decision, 2026-08-15). */
20558
- includeStationary: boolean().optional()
20571
+ includeStationary: boolean().optional(),
20572
+ /**
20573
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
20574
+ *
20575
+ * Added 2026-09-03: the timeline's class chips filtered in the CLIENT,
20576
+ * on a day of rows already downloaded. The zone filter had been moved
20577
+ * here for exactly that reason — and it is also what lets the rows come
20578
+ * back `slim` — but the class filter was left behind, so a narrow
20579
+ * selection was still a wide read followed by a wide discard.
20580
+ *
20581
+ * Empty is "show all", not "nothing matches": a chip row with nothing
20582
+ * selected is an operator who has not narrowed anything, and an empty
20583
+ * timeline would read as a camera that saw nothing.
20584
+ */
20585
+ classes: array(string()).optional()
20559
20586
  }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
20560
20587
  kind: "mutation",
20561
20588
  auth: "admin"
@@ -24324,8 +24351,22 @@ var automationControlCapability = {
24324
24351
  * threshold.
24325
24352
  */
24326
24353
  var BatteryStatusSchema = object({
24327
- /** 0..100 inclusive. Firmware-reported. */
24328
- percentage: number().min(0).max(100),
24354
+ /**
24355
+ * 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
24356
+ * provider has registered the capability but no reading has landed.
24357
+ *
24358
+ * It is nullable because it was not, and the only value a provider could
24359
+ * seed with was `0`. A battery camera behind an NVR therefore announced
24360
+ * itself at 0% on every start and corrected itself a moment later, which is
24361
+ * indistinguishable from a real flat battery: it fires the low-battery alert
24362
+ * every time the hub restarts. Unknown is not empty (D315), and on a battery
24363
+ * reading the difference is an alarm.
24364
+ *
24365
+ * `vacuum-control` and `lawn-mower-control` already model it this way.
24366
+ * Consumers must SKIP a null rather than coerce it — `battery-band` already
24367
+ * declines to band a non-finite reading, which is the correct shape.
24368
+ */
24369
+ percentage: number().min(0).max(100).nullable(),
24329
24370
  /**
24330
24371
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
24331
24372
  * Reolink-specific for the Solar Panel 2 accessory (will become
package/dist/addon.mjs CHANGED
@@ -20167,7 +20167,20 @@ var RecentTracksQueryInput = object({
20167
20167
  projection: TrackProjectionSchema.optional(),
20168
20168
  /** Include stationary-promoted rows (parked objects). Default false: the
20169
20169
  * feed lists passages; parking records live on the stationary registry. */
20170
- includeStationary: boolean().optional()
20170
+ includeStationary: boolean().optional(),
20171
+ /**
20172
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
20173
+ *
20174
+ * The same filter `listTracks` takes, because the timeline's class chips must
20175
+ * mean the same thing whether the scope is one camera or twelve. Until this
20176
+ * existed the scoped feed downloaded a page and narrowed it on the phone
20177
+ * while the single-camera path narrowed the read — one filter, two costs.
20178
+ *
20179
+ * A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
20180
+ * whose class list is unreadable are kept, and the client's rule stays the
20181
+ * exact one.
20182
+ */
20183
+ classes: array(string()).optional()
20171
20184
  });
20172
20185
  var RecentTracksPageSchema = object({
20173
20186
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -20554,7 +20567,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20554
20567
  /** Include stationary-promoted rows (parked objects handed to the
20555
20568
  * stationary registry). Default false: the timeline lists passages,
20556
20569
  * not parking records (operator decision, 2026-08-15). */
20557
- includeStationary: boolean().optional()
20570
+ includeStationary: boolean().optional(),
20571
+ /**
20572
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
20573
+ *
20574
+ * Added 2026-09-03: the timeline's class chips filtered in the CLIENT,
20575
+ * on a day of rows already downloaded. The zone filter had been moved
20576
+ * here for exactly that reason — and it is also what lets the rows come
20577
+ * back `slim` — but the class filter was left behind, so a narrow
20578
+ * selection was still a wide read followed by a wide discard.
20579
+ *
20580
+ * Empty is "show all", not "nothing matches": a chip row with nothing
20581
+ * selected is an operator who has not narrowed anything, and an empty
20582
+ * timeline would read as a camera that saw nothing.
20583
+ */
20584
+ classes: array(string()).optional()
20558
20585
  }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
20559
20586
  kind: "mutation",
20560
20587
  auth: "admin"
@@ -24323,8 +24350,22 @@ var automationControlCapability = {
24323
24350
  * threshold.
24324
24351
  */
24325
24352
  var BatteryStatusSchema = object({
24326
- /** 0..100 inclusive. Firmware-reported. */
24327
- percentage: number().min(0).max(100),
24353
+ /**
24354
+ * 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
24355
+ * provider has registered the capability but no reading has landed.
24356
+ *
24357
+ * It is nullable because it was not, and the only value a provider could
24358
+ * seed with was `0`. A battery camera behind an NVR therefore announced
24359
+ * itself at 0% on every start and corrected itself a moment later, which is
24360
+ * indistinguishable from a real flat battery: it fires the low-battery alert
24361
+ * every time the hub restarts. Unknown is not empty (D315), and on a battery
24362
+ * reading the difference is an alarm.
24363
+ *
24364
+ * `vacuum-control` and `lawn-mower-control` already model it this way.
24365
+ * Consumers must SKIP a null rather than coerce it — `battery-band` already
24366
+ * declines to band a non-finite reading, which is the correct shape.
24367
+ */
24368
+ percentage: number().min(0).max(100).nullable(),
24328
24369
  /**
24329
24370
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
24330
24371
  * Reolink-specific for the Solar Panel 2 accessory (will become
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-rademacher",
3
- "version": "0.2.55",
3
+ "version": "0.2.57",
4
4
  "description": "Rademacher HomePilot device-provider addon for CamStack — wraps the @apocaliss92/noderademacher local-hub client (roller shutters over the cover cap)",
5
5
  "keywords": [
6
6
  "camstack",