@camstack/addon-export-hap 1.2.68 → 1.2.70
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/hap-export.addon.js +152 -4
- package/dist/hap-export.addon.mjs +152 -4
- package/package.json +1 -1
package/dist/hap-export.addon.js
CHANGED
|
@@ -11247,6 +11247,89 @@ var LocationStatSchema = object({
|
|
|
11247
11247
|
fileCount: number(),
|
|
11248
11248
|
present: boolean()
|
|
11249
11249
|
});
|
|
11250
|
+
/** Lifecycle of a backup run. Terminal states: succeeded / failed / cancelled. */
|
|
11251
|
+
var BackupRunStateSchema = _enum([
|
|
11252
|
+
"queued",
|
|
11253
|
+
"running",
|
|
11254
|
+
"succeeded",
|
|
11255
|
+
"failed",
|
|
11256
|
+
"cancelled"
|
|
11257
|
+
]);
|
|
11258
|
+
/**
|
|
11259
|
+
* Where a running backup currently is. `queued` before it starts,
|
|
11260
|
+
* `building` while the tar.gz is being staged, `uploading` during the
|
|
11261
|
+
* per-destination fan-out, `done` once terminal.
|
|
11262
|
+
*/
|
|
11263
|
+
var BackupRunPhaseSchema = _enum([
|
|
11264
|
+
"queued",
|
|
11265
|
+
"building",
|
|
11266
|
+
"uploading",
|
|
11267
|
+
"done"
|
|
11268
|
+
]);
|
|
11269
|
+
/**
|
|
11270
|
+
* Observable state of one backup run — readable WHILE it runs via
|
|
11271
|
+
* `backup.listRuns`. This is what makes the execution queue and
|
|
11272
|
+
* `backup.cancel` usable: the 2026-09-04 incident (two concurrent
|
|
11273
|
+
* multi-GB builds, staging 5.1 GB → 18 GB, load 62) was only
|
|
11274
|
+
* diagnosable with `du` because nothing reported that runs existed or
|
|
11275
|
+
* how large the staged archive had grown.
|
|
11276
|
+
*/
|
|
11277
|
+
var BackupRunSchema = object({
|
|
11278
|
+
/** Stable run id — the handle `backup.cancel` takes. */
|
|
11279
|
+
id: string(),
|
|
11280
|
+
state: BackupRunStateSchema,
|
|
11281
|
+
phase: BackupRunPhaseSchema,
|
|
11282
|
+
/**
|
|
11283
|
+
* Resolved destination location ids. Empty while queued (targets are
|
|
11284
|
+
* resolved when the run starts, against the then-current policies).
|
|
11285
|
+
*/
|
|
11286
|
+
destinationIds: array(string()).readonly(),
|
|
11287
|
+
label: string().optional(),
|
|
11288
|
+
/** ms-epoch when the run was submitted (trigger call / schedule fire). */
|
|
11289
|
+
requestedAt: number(),
|
|
11290
|
+
/** ms-epoch when the run left the queue and started building. */
|
|
11291
|
+
startedAt: number().optional(),
|
|
11292
|
+
/** ms-epoch when the run reached a terminal state. */
|
|
11293
|
+
finishedAt: number().optional(),
|
|
11294
|
+
/** Compressed bytes of the staging archive written so far. */
|
|
11295
|
+
stagedBytes: number(),
|
|
11296
|
+
/** Final staged archive size, once the build phase completes. */
|
|
11297
|
+
archiveSizeBytes: number().optional(),
|
|
11298
|
+
/** Bytes pushed to the destination currently uploading. */
|
|
11299
|
+
uploadedBytes: number(),
|
|
11300
|
+
/** Destinations where the archive fully landed (uploaded + indexed). */
|
|
11301
|
+
completedDestinationIds: array(string()).readonly(),
|
|
11302
|
+
/** Destinations that failed during the fan-out. */
|
|
11303
|
+
failedDestinationIds: array(string()).readonly(),
|
|
11304
|
+
/** Failure message when `state === 'failed'`. */
|
|
11305
|
+
error: string().optional(),
|
|
11306
|
+
/**
|
|
11307
|
+
* 1-based place in the execution queue — 1 = runs next. Present only
|
|
11308
|
+
* while `state === 'queued'`. Stamped by the orchestrator from the
|
|
11309
|
+
* queue's OWN pending order, never derived from timestamps, so the
|
|
11310
|
+
* UI cannot show an order the executor will not honour.
|
|
11311
|
+
*/
|
|
11312
|
+
queuePosition: number().int().min(1).optional()
|
|
11313
|
+
});
|
|
11314
|
+
/**
|
|
11315
|
+
* Result of `backup.trigger`. The call still resolves when the run
|
|
11316
|
+
* terminates (compat with schedule-driven runs and the admin UI), but
|
|
11317
|
+
* it now names the run and says whether it had to WAIT: a trigger that
|
|
11318
|
+
* arrives while another run is in flight is enqueued (or joined onto
|
|
11319
|
+
* an identical already-queued run), never started concurrently.
|
|
11320
|
+
*/
|
|
11321
|
+
var BackupTriggerResultSchema = object({
|
|
11322
|
+
/** The run this trigger mapped to — poll it via `listRuns`, stop it via `cancel`. */
|
|
11323
|
+
runId: string(),
|
|
11324
|
+
/** True when the run waited behind an in-flight run instead of starting immediately. */
|
|
11325
|
+
queued: boolean(),
|
|
11326
|
+
/** True when this trigger was coalesced onto an identical already-queued run. */
|
|
11327
|
+
joined: boolean(),
|
|
11328
|
+
/** True when the run was cancelled before completing every destination. */
|
|
11329
|
+
cancelled: boolean(),
|
|
11330
|
+
/** One entry per destination the archive landed at (partial on cancel). */
|
|
11331
|
+
entries: array(BackupEntrySchema).readonly()
|
|
11332
|
+
});
|
|
11250
11333
|
/**
|
|
11251
11334
|
* A backup schedule — the N:M "entry" that binds one cron cadence to a
|
|
11252
11335
|
* SET of destination locations. Supersedes the per-location cron on
|
|
@@ -11294,7 +11377,10 @@ method(_void(), array(BackupDestinationInfoSchema).readonly(), { auth: "admin" }
|
|
|
11294
11377
|
* retention (manual runs).
|
|
11295
11378
|
*/
|
|
11296
11379
|
retentionCount: number().int().min(1).max(1e3).optional()
|
|
11297
|
-
}).optional(),
|
|
11380
|
+
}).optional(), BackupTriggerResultSchema, {
|
|
11381
|
+
kind: "mutation",
|
|
11382
|
+
auth: "admin"
|
|
11383
|
+
}), method(_void(), array(BackupRunSchema).readonly(), { auth: "admin" }), method(object({ runId: string() }), object({ cancelled: boolean() }), {
|
|
11298
11384
|
kind: "mutation",
|
|
11299
11385
|
auth: "admin"
|
|
11300
11386
|
}), method(_void(), array(BackupEntrySchema).readonly(), { auth: "admin" }), method(_void(), array(LocationStatSchema).readonly(), { auth: "admin" }), method(object({
|
|
@@ -12011,6 +12097,14 @@ method(object({
|
|
|
12011
12097
|
}), object({ success: literal(true) }), {
|
|
12012
12098
|
kind: "mutation",
|
|
12013
12099
|
auth: "admin"
|
|
12100
|
+
}), method(object({ deviceId: number().int().nonnegative() }), object({
|
|
12101
|
+
derivedStreamsDeleted: array(string()).readonly(),
|
|
12102
|
+
assignmentsPurged: boolean(),
|
|
12103
|
+
probeSnapshotsDropped: number().int().nonnegative(),
|
|
12104
|
+
rtspTokenRowsDeleted: number().int().nonnegative()
|
|
12105
|
+
}), {
|
|
12106
|
+
kind: "mutation",
|
|
12107
|
+
auth: "admin"
|
|
12014
12108
|
}), method(object({
|
|
12015
12109
|
deviceId: number(),
|
|
12016
12110
|
/** Absent = the LOWEST assigned profile — a notification attachment is
|
|
@@ -19642,7 +19736,20 @@ var RecentTracksQueryInput = object({
|
|
|
19642
19736
|
projection: TrackProjectionSchema.optional(),
|
|
19643
19737
|
/** Include stationary-promoted rows (parked objects). Default false: the
|
|
19644
19738
|
* feed lists passages; parking records live on the stationary registry. */
|
|
19645
|
-
includeStationary: boolean().optional()
|
|
19739
|
+
includeStationary: boolean().optional(),
|
|
19740
|
+
/**
|
|
19741
|
+
* Restrict to these track classes. ABSENT or EMPTY means no filter.
|
|
19742
|
+
*
|
|
19743
|
+
* The same filter `listTracks` takes, because the timeline's class chips must
|
|
19744
|
+
* mean the same thing whether the scope is one camera or twelve. Until this
|
|
19745
|
+
* existed the scoped feed downloaded a page and narrowed it on the phone
|
|
19746
|
+
* while the single-camera path narrowed the read — one filter, two costs.
|
|
19747
|
+
*
|
|
19748
|
+
* A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
|
|
19749
|
+
* whose class list is unreadable are kept, and the client's rule stays the
|
|
19750
|
+
* exact one.
|
|
19751
|
+
*/
|
|
19752
|
+
classes: array(string()).optional()
|
|
19646
19753
|
});
|
|
19647
19754
|
var RecentTracksPageSchema = object({
|
|
19648
19755
|
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
@@ -23684,8 +23791,22 @@ DeviceType.Automation, method(object({ deviceId: number().int().nonnegative() })
|
|
|
23684
23791
|
* threshold.
|
|
23685
23792
|
*/
|
|
23686
23793
|
var BatteryStatusSchema = object({
|
|
23687
|
-
/**
|
|
23688
|
-
|
|
23794
|
+
/**
|
|
23795
|
+
* 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
|
|
23796
|
+
* provider has registered the capability but no reading has landed.
|
|
23797
|
+
*
|
|
23798
|
+
* It is nullable because it was not, and the only value a provider could
|
|
23799
|
+
* seed with was `0`. A battery camera behind an NVR therefore announced
|
|
23800
|
+
* itself at 0% on every start and corrected itself a moment later, which is
|
|
23801
|
+
* indistinguishable from a real flat battery: it fires the low-battery alert
|
|
23802
|
+
* every time the hub restarts. Unknown is not empty (D315), and on a battery
|
|
23803
|
+
* reading the difference is an alarm.
|
|
23804
|
+
*
|
|
23805
|
+
* `vacuum-control` and `lawn-mower-control` already model it this way.
|
|
23806
|
+
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
23807
|
+
* declines to band a non-finite reading, which is the correct shape.
|
|
23808
|
+
*/
|
|
23809
|
+
percentage: number().min(0).max(100).nullable(),
|
|
23689
23810
|
/**
|
|
23690
23811
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
23691
23812
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -30233,6 +30354,12 @@ Object.freeze({
|
|
|
30233
30354
|
addonId: null,
|
|
30234
30355
|
access: "create"
|
|
30235
30356
|
},
|
|
30357
|
+
"backup.cancel": {
|
|
30358
|
+
capName: "backup",
|
|
30359
|
+
capScope: "system",
|
|
30360
|
+
addonId: null,
|
|
30361
|
+
access: "create"
|
|
30362
|
+
},
|
|
30236
30363
|
"backup.delete": {
|
|
30237
30364
|
capName: "backup",
|
|
30238
30365
|
capScope: "system",
|
|
@@ -30275,6 +30402,12 @@ Object.freeze({
|
|
|
30275
30402
|
addonId: null,
|
|
30276
30403
|
access: "view"
|
|
30277
30404
|
},
|
|
30405
|
+
"backup.listRuns": {
|
|
30406
|
+
capName: "backup",
|
|
30407
|
+
capScope: "system",
|
|
30408
|
+
addonId: null,
|
|
30409
|
+
access: "view"
|
|
30410
|
+
},
|
|
30278
30411
|
"backup.listSchedules": {
|
|
30279
30412
|
capName: "backup",
|
|
30280
30413
|
capScope: "system",
|
|
@@ -34841,6 +34974,12 @@ Object.freeze({
|
|
|
34841
34974
|
addonId: null,
|
|
34842
34975
|
access: "create"
|
|
34843
34976
|
},
|
|
34977
|
+
"streamBroker.forgetDeviceHardware": {
|
|
34978
|
+
capName: "stream-broker",
|
|
34979
|
+
capScope: "system",
|
|
34980
|
+
addonId: null,
|
|
34981
|
+
access: "delete"
|
|
34982
|
+
},
|
|
34844
34983
|
"streamBroker.getAllRtspEntries": {
|
|
34845
34984
|
capName: "stream-broker",
|
|
34846
34985
|
capScope: "system",
|
|
@@ -37299,6 +37438,11 @@ Object.freeze({
|
|
|
37299
37438
|
form: "single",
|
|
37300
37439
|
optional: false
|
|
37301
37440
|
}],
|
|
37441
|
+
"streamBroker.forgetDeviceHardware": [{
|
|
37442
|
+
name: "deviceId",
|
|
37443
|
+
form: "single",
|
|
37444
|
+
optional: false
|
|
37445
|
+
}],
|
|
37302
37446
|
"streamBroker.getDeviceAudioMute": [{
|
|
37303
37447
|
name: "deviceId",
|
|
37304
37448
|
form: "single",
|
|
@@ -85249,6 +85393,10 @@ var LOW_BATTERY_THRESHOLD_PCT = 20;
|
|
|
85249
85393
|
* - `percentage <= LOW_BATTERY_THRESHOLD_PCT` → `StatusLowBattery.LOW`
|
|
85250
85394
|
*/
|
|
85251
85395
|
var batteryCharacteristicUpdates = reader(BatteryStatusSchema.pick({ percentage: true }).extend({ charging: BatteryStatusSchema.shape.charging.optional() }), (status) => {
|
|
85396
|
+
if (status.percentage === null) return status.charging === void 0 ? [] : [{
|
|
85397
|
+
characteristic: import_dist.Characteristic.ChargingState,
|
|
85398
|
+
value: status.charging === "none" ? import_dist.Characteristic.ChargingState.NOT_CHARGING : import_dist.Characteristic.ChargingState.CHARGING
|
|
85399
|
+
}];
|
|
85252
85400
|
const pct = Math.max(0, Math.min(100, Math.round(status.percentage)));
|
|
85253
85401
|
return [
|
|
85254
85402
|
{
|
|
@@ -11235,6 +11235,89 @@ var LocationStatSchema = object({
|
|
|
11235
11235
|
fileCount: number(),
|
|
11236
11236
|
present: boolean()
|
|
11237
11237
|
});
|
|
11238
|
+
/** Lifecycle of a backup run. Terminal states: succeeded / failed / cancelled. */
|
|
11239
|
+
var BackupRunStateSchema = _enum([
|
|
11240
|
+
"queued",
|
|
11241
|
+
"running",
|
|
11242
|
+
"succeeded",
|
|
11243
|
+
"failed",
|
|
11244
|
+
"cancelled"
|
|
11245
|
+
]);
|
|
11246
|
+
/**
|
|
11247
|
+
* Where a running backup currently is. `queued` before it starts,
|
|
11248
|
+
* `building` while the tar.gz is being staged, `uploading` during the
|
|
11249
|
+
* per-destination fan-out, `done` once terminal.
|
|
11250
|
+
*/
|
|
11251
|
+
var BackupRunPhaseSchema = _enum([
|
|
11252
|
+
"queued",
|
|
11253
|
+
"building",
|
|
11254
|
+
"uploading",
|
|
11255
|
+
"done"
|
|
11256
|
+
]);
|
|
11257
|
+
/**
|
|
11258
|
+
* Observable state of one backup run — readable WHILE it runs via
|
|
11259
|
+
* `backup.listRuns`. This is what makes the execution queue and
|
|
11260
|
+
* `backup.cancel` usable: the 2026-09-04 incident (two concurrent
|
|
11261
|
+
* multi-GB builds, staging 5.1 GB → 18 GB, load 62) was only
|
|
11262
|
+
* diagnosable with `du` because nothing reported that runs existed or
|
|
11263
|
+
* how large the staged archive had grown.
|
|
11264
|
+
*/
|
|
11265
|
+
var BackupRunSchema = object({
|
|
11266
|
+
/** Stable run id — the handle `backup.cancel` takes. */
|
|
11267
|
+
id: string(),
|
|
11268
|
+
state: BackupRunStateSchema,
|
|
11269
|
+
phase: BackupRunPhaseSchema,
|
|
11270
|
+
/**
|
|
11271
|
+
* Resolved destination location ids. Empty while queued (targets are
|
|
11272
|
+
* resolved when the run starts, against the then-current policies).
|
|
11273
|
+
*/
|
|
11274
|
+
destinationIds: array(string()).readonly(),
|
|
11275
|
+
label: string().optional(),
|
|
11276
|
+
/** ms-epoch when the run was submitted (trigger call / schedule fire). */
|
|
11277
|
+
requestedAt: number(),
|
|
11278
|
+
/** ms-epoch when the run left the queue and started building. */
|
|
11279
|
+
startedAt: number().optional(),
|
|
11280
|
+
/** ms-epoch when the run reached a terminal state. */
|
|
11281
|
+
finishedAt: number().optional(),
|
|
11282
|
+
/** Compressed bytes of the staging archive written so far. */
|
|
11283
|
+
stagedBytes: number(),
|
|
11284
|
+
/** Final staged archive size, once the build phase completes. */
|
|
11285
|
+
archiveSizeBytes: number().optional(),
|
|
11286
|
+
/** Bytes pushed to the destination currently uploading. */
|
|
11287
|
+
uploadedBytes: number(),
|
|
11288
|
+
/** Destinations where the archive fully landed (uploaded + indexed). */
|
|
11289
|
+
completedDestinationIds: array(string()).readonly(),
|
|
11290
|
+
/** Destinations that failed during the fan-out. */
|
|
11291
|
+
failedDestinationIds: array(string()).readonly(),
|
|
11292
|
+
/** Failure message when `state === 'failed'`. */
|
|
11293
|
+
error: string().optional(),
|
|
11294
|
+
/**
|
|
11295
|
+
* 1-based place in the execution queue — 1 = runs next. Present only
|
|
11296
|
+
* while `state === 'queued'`. Stamped by the orchestrator from the
|
|
11297
|
+
* queue's OWN pending order, never derived from timestamps, so the
|
|
11298
|
+
* UI cannot show an order the executor will not honour.
|
|
11299
|
+
*/
|
|
11300
|
+
queuePosition: number().int().min(1).optional()
|
|
11301
|
+
});
|
|
11302
|
+
/**
|
|
11303
|
+
* Result of `backup.trigger`. The call still resolves when the run
|
|
11304
|
+
* terminates (compat with schedule-driven runs and the admin UI), but
|
|
11305
|
+
* it now names the run and says whether it had to WAIT: a trigger that
|
|
11306
|
+
* arrives while another run is in flight is enqueued (or joined onto
|
|
11307
|
+
* an identical already-queued run), never started concurrently.
|
|
11308
|
+
*/
|
|
11309
|
+
var BackupTriggerResultSchema = object({
|
|
11310
|
+
/** The run this trigger mapped to — poll it via `listRuns`, stop it via `cancel`. */
|
|
11311
|
+
runId: string(),
|
|
11312
|
+
/** True when the run waited behind an in-flight run instead of starting immediately. */
|
|
11313
|
+
queued: boolean(),
|
|
11314
|
+
/** True when this trigger was coalesced onto an identical already-queued run. */
|
|
11315
|
+
joined: boolean(),
|
|
11316
|
+
/** True when the run was cancelled before completing every destination. */
|
|
11317
|
+
cancelled: boolean(),
|
|
11318
|
+
/** One entry per destination the archive landed at (partial on cancel). */
|
|
11319
|
+
entries: array(BackupEntrySchema).readonly()
|
|
11320
|
+
});
|
|
11238
11321
|
/**
|
|
11239
11322
|
* A backup schedule — the N:M "entry" that binds one cron cadence to a
|
|
11240
11323
|
* SET of destination locations. Supersedes the per-location cron on
|
|
@@ -11282,7 +11365,10 @@ method(_void(), array(BackupDestinationInfoSchema).readonly(), { auth: "admin" }
|
|
|
11282
11365
|
* retention (manual runs).
|
|
11283
11366
|
*/
|
|
11284
11367
|
retentionCount: number().int().min(1).max(1e3).optional()
|
|
11285
|
-
}).optional(),
|
|
11368
|
+
}).optional(), BackupTriggerResultSchema, {
|
|
11369
|
+
kind: "mutation",
|
|
11370
|
+
auth: "admin"
|
|
11371
|
+
}), method(_void(), array(BackupRunSchema).readonly(), { auth: "admin" }), method(object({ runId: string() }), object({ cancelled: boolean() }), {
|
|
11286
11372
|
kind: "mutation",
|
|
11287
11373
|
auth: "admin"
|
|
11288
11374
|
}), method(_void(), array(BackupEntrySchema).readonly(), { auth: "admin" }), method(_void(), array(LocationStatSchema).readonly(), { auth: "admin" }), method(object({
|
|
@@ -11999,6 +12085,14 @@ method(object({
|
|
|
11999
12085
|
}), object({ success: literal(true) }), {
|
|
12000
12086
|
kind: "mutation",
|
|
12001
12087
|
auth: "admin"
|
|
12088
|
+
}), method(object({ deviceId: number().int().nonnegative() }), object({
|
|
12089
|
+
derivedStreamsDeleted: array(string()).readonly(),
|
|
12090
|
+
assignmentsPurged: boolean(),
|
|
12091
|
+
probeSnapshotsDropped: number().int().nonnegative(),
|
|
12092
|
+
rtspTokenRowsDeleted: number().int().nonnegative()
|
|
12093
|
+
}), {
|
|
12094
|
+
kind: "mutation",
|
|
12095
|
+
auth: "admin"
|
|
12002
12096
|
}), method(object({
|
|
12003
12097
|
deviceId: number(),
|
|
12004
12098
|
/** Absent = the LOWEST assigned profile — a notification attachment is
|
|
@@ -19630,7 +19724,20 @@ var RecentTracksQueryInput = object({
|
|
|
19630
19724
|
projection: TrackProjectionSchema.optional(),
|
|
19631
19725
|
/** Include stationary-promoted rows (parked objects). Default false: the
|
|
19632
19726
|
* feed lists passages; parking records live on the stationary registry. */
|
|
19633
|
-
includeStationary: boolean().optional()
|
|
19727
|
+
includeStationary: boolean().optional(),
|
|
19728
|
+
/**
|
|
19729
|
+
* Restrict to these track classes. ABSENT or EMPTY means no filter.
|
|
19730
|
+
*
|
|
19731
|
+
* The same filter `listTracks` takes, because the timeline's class chips must
|
|
19732
|
+
* mean the same thing whether the scope is one camera or twelve. Until this
|
|
19733
|
+
* existed the scoped feed downloaded a page and narrowed it on the phone
|
|
19734
|
+
* while the single-camera path narrowed the read — one filter, two costs.
|
|
19735
|
+
*
|
|
19736
|
+
* A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
|
|
19737
|
+
* whose class list is unreadable are kept, and the client's rule stays the
|
|
19738
|
+
* exact one.
|
|
19739
|
+
*/
|
|
19740
|
+
classes: array(string()).optional()
|
|
19634
19741
|
});
|
|
19635
19742
|
var RecentTracksPageSchema = object({
|
|
19636
19743
|
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
@@ -23672,8 +23779,22 @@ DeviceType.Automation, method(object({ deviceId: number().int().nonnegative() })
|
|
|
23672
23779
|
* threshold.
|
|
23673
23780
|
*/
|
|
23674
23781
|
var BatteryStatusSchema = object({
|
|
23675
|
-
/**
|
|
23676
|
-
|
|
23782
|
+
/**
|
|
23783
|
+
* 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
|
|
23784
|
+
* provider has registered the capability but no reading has landed.
|
|
23785
|
+
*
|
|
23786
|
+
* It is nullable because it was not, and the only value a provider could
|
|
23787
|
+
* seed with was `0`. A battery camera behind an NVR therefore announced
|
|
23788
|
+
* itself at 0% on every start and corrected itself a moment later, which is
|
|
23789
|
+
* indistinguishable from a real flat battery: it fires the low-battery alert
|
|
23790
|
+
* every time the hub restarts. Unknown is not empty (D315), and on a battery
|
|
23791
|
+
* reading the difference is an alarm.
|
|
23792
|
+
*
|
|
23793
|
+
* `vacuum-control` and `lawn-mower-control` already model it this way.
|
|
23794
|
+
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
23795
|
+
* declines to band a non-finite reading, which is the correct shape.
|
|
23796
|
+
*/
|
|
23797
|
+
percentage: number().min(0).max(100).nullable(),
|
|
23677
23798
|
/**
|
|
23678
23799
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
23679
23800
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -30221,6 +30342,12 @@ Object.freeze({
|
|
|
30221
30342
|
addonId: null,
|
|
30222
30343
|
access: "create"
|
|
30223
30344
|
},
|
|
30345
|
+
"backup.cancel": {
|
|
30346
|
+
capName: "backup",
|
|
30347
|
+
capScope: "system",
|
|
30348
|
+
addonId: null,
|
|
30349
|
+
access: "create"
|
|
30350
|
+
},
|
|
30224
30351
|
"backup.delete": {
|
|
30225
30352
|
capName: "backup",
|
|
30226
30353
|
capScope: "system",
|
|
@@ -30263,6 +30390,12 @@ Object.freeze({
|
|
|
30263
30390
|
addonId: null,
|
|
30264
30391
|
access: "view"
|
|
30265
30392
|
},
|
|
30393
|
+
"backup.listRuns": {
|
|
30394
|
+
capName: "backup",
|
|
30395
|
+
capScope: "system",
|
|
30396
|
+
addonId: null,
|
|
30397
|
+
access: "view"
|
|
30398
|
+
},
|
|
30266
30399
|
"backup.listSchedules": {
|
|
30267
30400
|
capName: "backup",
|
|
30268
30401
|
capScope: "system",
|
|
@@ -34829,6 +34962,12 @@ Object.freeze({
|
|
|
34829
34962
|
addonId: null,
|
|
34830
34963
|
access: "create"
|
|
34831
34964
|
},
|
|
34965
|
+
"streamBroker.forgetDeviceHardware": {
|
|
34966
|
+
capName: "stream-broker",
|
|
34967
|
+
capScope: "system",
|
|
34968
|
+
addonId: null,
|
|
34969
|
+
access: "delete"
|
|
34970
|
+
},
|
|
34832
34971
|
"streamBroker.getAllRtspEntries": {
|
|
34833
34972
|
capName: "stream-broker",
|
|
34834
34973
|
capScope: "system",
|
|
@@ -37287,6 +37426,11 @@ Object.freeze({
|
|
|
37287
37426
|
form: "single",
|
|
37288
37427
|
optional: false
|
|
37289
37428
|
}],
|
|
37429
|
+
"streamBroker.forgetDeviceHardware": [{
|
|
37430
|
+
name: "deviceId",
|
|
37431
|
+
form: "single",
|
|
37432
|
+
optional: false
|
|
37433
|
+
}],
|
|
37290
37434
|
"streamBroker.getDeviceAudioMute": [{
|
|
37291
37435
|
name: "deviceId",
|
|
37292
37436
|
form: "single",
|
|
@@ -85237,6 +85381,10 @@ var LOW_BATTERY_THRESHOLD_PCT = 20;
|
|
|
85237
85381
|
* - `percentage <= LOW_BATTERY_THRESHOLD_PCT` → `StatusLowBattery.LOW`
|
|
85238
85382
|
*/
|
|
85239
85383
|
var batteryCharacteristicUpdates = reader(BatteryStatusSchema.pick({ percentage: true }).extend({ charging: BatteryStatusSchema.shape.charging.optional() }), (status) => {
|
|
85384
|
+
if (status.percentage === null) return status.charging === void 0 ? [] : [{
|
|
85385
|
+
characteristic: import_dist.Characteristic.ChargingState,
|
|
85386
|
+
value: status.charging === "none" ? import_dist.Characteristic.ChargingState.NOT_CHARGING : import_dist.Characteristic.ChargingState.CHARGING
|
|
85387
|
+
}];
|
|
85240
85388
|
const pct = Math.max(0, Math.min(100, Math.round(status.percentage)));
|
|
85241
85389
|
return [
|
|
85242
85390
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-export-hap",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.70",
|
|
4
4
|
"description": "HomeKit (HAP) exporter for CamStack devices. Publishes each exposed device as its own HomeKit accessory: cameras and doorbells with SRTP streaming, HomeKit Secure Video, motion, two-way audio, PTZ and battery; switches, lights, locks and sensors through a capability→service table.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|