@camstack/addon-export-hap 1.2.59 → 1.2.60
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 +218 -4
- package/dist/hap-export.addon.mjs +218 -4
- package/package.json +1 -1
package/dist/hap-export.addon.js
CHANGED
|
@@ -8684,6 +8684,20 @@ var RelocateJobSchema = object({
|
|
|
8684
8684
|
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
8685
8685
|
*/
|
|
8686
8686
|
rowsReconciled: number().int().nonnegative().optional(),
|
|
8687
|
+
/**
|
|
8688
|
+
* Rows this run FORGOT because the file they name is not on disk.
|
|
8689
|
+
*
|
|
8690
|
+
* The mover derived the path from the row's own fields and `stat`ed it; an
|
|
8691
|
+
* ENOENT there is a per-path confirmation that the segment is gone (D296),
|
|
8692
|
+
* and the durable row is dropped through the same channel eviction uses. It
|
|
8693
|
+
* is reported for the same reason `rowsReconciled` is: this is a durable
|
|
8694
|
+
* mutation nobody asked for, and a migration that quietly erases hour rows is
|
|
8695
|
+
* the same failure as one that quietly skips them (D295).
|
|
8696
|
+
*
|
|
8697
|
+
* The production drain of 2026-08-30 would have reported 11 074 here — the
|
|
8698
|
+
* ledger claimed 5.65 GB of footage that no longer existed.
|
|
8699
|
+
*/
|
|
8700
|
+
rowsForgotten: number().int().nonnegative().optional(),
|
|
8687
8701
|
startedAt: number(),
|
|
8688
8702
|
finishedAt: number().nullable(),
|
|
8689
8703
|
error: string().nullable()
|
|
@@ -9047,6 +9061,91 @@ var RelocateResidueSchema = object({
|
|
|
9047
9061
|
segments: number().int().nonnegative(),
|
|
9048
9062
|
bytes: number().int().nonnegative()
|
|
9049
9063
|
}).nullable();
|
|
9064
|
+
/**
|
|
9065
|
+
* Ask one location whether its durable hour rows describe the disk — the walk
|
|
9066
|
+
* (D319).
|
|
9067
|
+
*
|
|
9068
|
+
* `apply` DEFAULTS TO FALSE and that default is the product: the operator's
|
|
9069
|
+
* missing tool is the question, and the dry run is how they sanity-check the
|
|
9070
|
+
* destructive run before authorising it.
|
|
9071
|
+
*/
|
|
9072
|
+
var LedgerWalkInputSchema = object({
|
|
9073
|
+
locationId: string().min(1),
|
|
9074
|
+
/** Forget the confirmed-absent rows, rather than only counting them. */
|
|
9075
|
+
apply: boolean().optional(),
|
|
9076
|
+
/** Narrow to one camera. */
|
|
9077
|
+
deviceId: number().int().positive().optional(),
|
|
9078
|
+
/** Narrow to these recording profiles; empty/absent = every profile. */
|
|
9079
|
+
profiles: array(string().min(1)).optional()
|
|
9080
|
+
});
|
|
9081
|
+
/** Why a whole walk did nothing. Every one leaves the ledger untouched. */
|
|
9082
|
+
var LedgerWalkRefusalSchema = _enum([
|
|
9083
|
+
"location-unknown",
|
|
9084
|
+
"source-writable",
|
|
9085
|
+
"no-ledger",
|
|
9086
|
+
"archive-unreadable",
|
|
9087
|
+
"anchor-absent",
|
|
9088
|
+
"anchor-unreadable",
|
|
9089
|
+
"anchor-moved"
|
|
9090
|
+
]);
|
|
9091
|
+
_enum([
|
|
9092
|
+
"live-tail",
|
|
9093
|
+
"listing-error",
|
|
9094
|
+
"path-mismatch",
|
|
9095
|
+
"durable-refused"
|
|
9096
|
+
]);
|
|
9097
|
+
/** Every skip reason, always present, always a number — so a reason that never
|
|
9098
|
+
* fired reports as zero rather than absent and the report shape is constant
|
|
9099
|
+
* between passes. Spelled out rather than `z.record` for exactly that. */
|
|
9100
|
+
var LedgerWalkSkipCountsSchema = object({
|
|
9101
|
+
"live-tail": number().int().nonnegative(),
|
|
9102
|
+
"listing-error": number().int().nonnegative(),
|
|
9103
|
+
"path-mismatch": number().int().nonnegative(),
|
|
9104
|
+
"durable-refused": number().int().nonnegative()
|
|
9105
|
+
});
|
|
9106
|
+
/** One camera's share of a walk, so a report names cameras and not rows. */
|
|
9107
|
+
var LedgerWalkDeviceReportSchema = object({
|
|
9108
|
+
deviceId: number().int(),
|
|
9109
|
+
hoursWalked: number().int().nonnegative(),
|
|
9110
|
+
hoursMissing: number().int().nonnegative(),
|
|
9111
|
+
ghostSegments: number().int().nonnegative(),
|
|
9112
|
+
ghostBytes: number().int().nonnegative(),
|
|
9113
|
+
forgottenSegments: number().int().nonnegative(),
|
|
9114
|
+
orphanFiles: number().int().nonnegative()
|
|
9115
|
+
});
|
|
9116
|
+
/**
|
|
9117
|
+
* What one walk claimed, listed, found and (only when armed) forgot.
|
|
9118
|
+
*
|
|
9119
|
+
* `archiveSegments` is the **M** and `segmentsClaimed` the **N** (D295), so a
|
|
9120
|
+
* walk that saw a fraction of the location is visible in its own report rather
|
|
9121
|
+
* than in the absence of one.
|
|
9122
|
+
*/
|
|
9123
|
+
var LedgerWalkReportSchema = object({
|
|
9124
|
+
locationId: string(),
|
|
9125
|
+
applied: boolean(),
|
|
9126
|
+
refused: LedgerWalkRefusalSchema.nullable(),
|
|
9127
|
+
archiveSegments: number().int().nonnegative().nullable(),
|
|
9128
|
+
archiveBytes: number().int().nonnegative().nullable(),
|
|
9129
|
+
hoursClaimed: number().int().nonnegative(),
|
|
9130
|
+
hoursWalked: number().int().nonnegative(),
|
|
9131
|
+
hoursMissing: number().int().nonnegative(),
|
|
9132
|
+
/** `readdir` calls issued — the cost, stated in the unit that is paid. */
|
|
9133
|
+
listings: number().int().nonnegative(),
|
|
9134
|
+
segmentsClaimed: number().int().nonnegative(),
|
|
9135
|
+
ghostSegments: number().int().nonnegative(),
|
|
9136
|
+
ghostBytes: number().int().nonnegative(),
|
|
9137
|
+
ghostHoursWhole: number().int().nonnegative(),
|
|
9138
|
+
forgottenSegments: number().int().nonnegative(),
|
|
9139
|
+
forgottenBytes: number().int().nonnegative(),
|
|
9140
|
+
/** Files under a claimed hour that no durable row names. Never deleted. */
|
|
9141
|
+
orphanFiles: number().int().nonnegative(),
|
|
9142
|
+
orphanSample: array(string()).readonly(),
|
|
9143
|
+
hoursSkipped: number().int().nonnegative(),
|
|
9144
|
+
skippedByReason: LedgerWalkSkipCountsSchema,
|
|
9145
|
+
/** The walk stopped at its per-pass hour bound with claims unwalked. */
|
|
9146
|
+
bounded: boolean(),
|
|
9147
|
+
byDevice: array(LedgerWalkDeviceReportSchema).readonly()
|
|
9148
|
+
});
|
|
9050
9149
|
/** How many rows a media pass would still act on against a given target — the
|
|
9051
9150
|
* media lane's denominator AND its residue, from ONE derivation so the two can
|
|
9052
9151
|
* never disagree. `null` = the count could not be taken. */
|
|
@@ -19455,13 +19554,15 @@ var ListGroupsPageSchema = object({
|
|
|
19455
19554
|
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
19456
19555
|
nextCursor: string().nullable()
|
|
19457
19556
|
});
|
|
19557
|
+
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
19558
|
+
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
19458
19559
|
var KeyEventQueryInput = object({
|
|
19459
19560
|
deviceId: number(),
|
|
19460
19561
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
19461
19562
|
since: number(),
|
|
19462
19563
|
/** Window upper bound (track firstSeen ≤ until). */
|
|
19463
19564
|
until: number(),
|
|
19464
|
-
limit: number().int().min(1).max(
|
|
19565
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
19465
19566
|
/** Drop tracks scoring below this importance. */
|
|
19466
19567
|
minImportance: number().min(0).max(1).optional(),
|
|
19467
19568
|
/** Restrict to a single class (e.g. 'person'). */
|
|
@@ -19483,6 +19584,32 @@ var KeyEventSchema = object({
|
|
|
19483
19584
|
...TrackFlagFields,
|
|
19484
19585
|
...TrackRetrainFields
|
|
19485
19586
|
});
|
|
19587
|
+
/** `getKeyEvents`' window and filters, asked of a SET of cameras at once. */
|
|
19588
|
+
var KeyEventBatchQueryInput = object({
|
|
19589
|
+
deviceIds: array(number()).min(1).max(200),
|
|
19590
|
+
since: number(),
|
|
19591
|
+
until: number(),
|
|
19592
|
+
/** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
|
|
19593
|
+
* across the set, which would let a busy camera starve a quiet one of its
|
|
19594
|
+
* rows and change what the merged feed contains. */
|
|
19595
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
19596
|
+
minImportance: number().min(0).max(1).optional(),
|
|
19597
|
+
classFilter: string().optional()
|
|
19598
|
+
});
|
|
19599
|
+
/**
|
|
19600
|
+
* One camera's key events in a batch answer.
|
|
19601
|
+
*
|
|
19602
|
+
* The row exists for every requested id. `getKeyEvents` degrades to `[]` on
|
|
19603
|
+
* error rather than throwing, so a camera whose store read failed and one with
|
|
19604
|
+
* no events in the window were ALREADY indistinguishable per camera — the
|
|
19605
|
+
* batch does not make that worse, and the row keeps the deviceId the single
|
|
19606
|
+
* method's output never carried (the caller used to stamp it from the fan-out
|
|
19607
|
+
* key, which only worked because there was one query per camera).
|
|
19608
|
+
*/
|
|
19609
|
+
var KeyEventsForDeviceSchema = object({
|
|
19610
|
+
deviceId: number(),
|
|
19611
|
+
events: array(KeyEventSchema).readonly()
|
|
19612
|
+
});
|
|
19486
19613
|
object({
|
|
19487
19614
|
trackId: string(),
|
|
19488
19615
|
className: string(),
|
|
@@ -19752,7 +19879,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19752
19879
|
until: number().optional(),
|
|
19753
19880
|
kinds: array(string()).optional(),
|
|
19754
19881
|
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19755
|
-
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19882
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(KeyEventBatchQueryInput, array(KeyEventsForDeviceSchema).readonly()), method(object({
|
|
19756
19883
|
deviceId: number(),
|
|
19757
19884
|
since: number(),
|
|
19758
19885
|
until: number(),
|
|
@@ -27452,6 +27579,9 @@ method(object({
|
|
|
27452
27579
|
}), method(RelocateResidueInputSchema, RelocateResidueSchema, {
|
|
27453
27580
|
kind: "query",
|
|
27454
27581
|
auth: "admin"
|
|
27582
|
+
}), method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
27583
|
+
kind: "mutation",
|
|
27584
|
+
auth: "admin"
|
|
27455
27585
|
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
27456
27586
|
kind: "mutation",
|
|
27457
27587
|
auth: "admin"
|
|
@@ -27843,7 +27973,26 @@ var SceneMonitorStatusSchema = object({
|
|
|
27843
27973
|
monitors: array(SceneMonitorSchema),
|
|
27844
27974
|
lastFetchedAt: number()
|
|
27845
27975
|
});
|
|
27846
|
-
|
|
27976
|
+
/**
|
|
27977
|
+
* One camera's row in a `listScenesBatch` answer.
|
|
27978
|
+
*
|
|
27979
|
+
* `status` is NULLABLE and the nullability is the whole point. `scene-monitor`
|
|
27980
|
+
* is a `defaultActive` wrapper, so every camera is asked; a camera whose
|
|
27981
|
+
* provider is absent (pipeline-analytics not deployed, the post-processing node
|
|
27982
|
+
* down) cannot answer, and that is not the same fact as a camera with no scenes
|
|
27983
|
+
* configured. Fanned out per camera the difference was visible — one query
|
|
27984
|
+
* errored while the others resolved — and a batch that returned only the rows
|
|
27985
|
+
* it managed would have destroyed it, silently, by making an unreachable camera
|
|
27986
|
+
* indistinguishable from one that answered `monitors: []`.
|
|
27987
|
+
*
|
|
27988
|
+
* So: EVERY requested deviceId gets a row. `status: null` means "this camera
|
|
27989
|
+
* could not be read"; `status.monitors: []` means "read, and it has none".
|
|
27990
|
+
*/
|
|
27991
|
+
var SceneMonitorStatusForDeviceSchema = object({
|
|
27992
|
+
deviceId: number(),
|
|
27993
|
+
status: SceneMonitorStatusSchema.nullable()
|
|
27994
|
+
});
|
|
27995
|
+
DeviceType.Camera, method(object({ deviceId: number() }), SceneMonitorStatusSchema), method(object({ deviceIds: array(number()).min(1).max(200) }), array(SceneMonitorStatusForDeviceSchema).readonly()), method(object({
|
|
27847
27996
|
deviceId: number(),
|
|
27848
27997
|
label: string(),
|
|
27849
27998
|
roi: MaskRectShapeSchema,
|
|
@@ -29192,6 +29341,27 @@ var CameraOccupancySnapshotSchema = object({
|
|
|
29192
29341
|
stationaryObjects: array(StationaryObjectSchema).readonly().optional()
|
|
29193
29342
|
});
|
|
29194
29343
|
/**
|
|
29344
|
+
* One camera's row in a `getCurrentSnapshotBatch` answer.
|
|
29345
|
+
*
|
|
29346
|
+
* THREE outcomes, and the single-camera method could only express two of them
|
|
29347
|
+
* because `snapshot: null` was already spoken for:
|
|
29348
|
+
*
|
|
29349
|
+
* - `read: 'read'`, `snapshot` present — the live occupancy reading.
|
|
29350
|
+
* - `read: 'read'`, `snapshot: null` — read, and this camera has no reading
|
|
29351
|
+
* yet: no frame since boot, and no parked-object registry to hydrate from.
|
|
29352
|
+
* - `read: 'unreadable'` — the owner could not answer for this
|
|
29353
|
+
* camera. `snapshot` is null, and it does NOT mean "nothing parked here".
|
|
29354
|
+
*
|
|
29355
|
+
* Collapsing the last two is the failure this field exists to prevent: a
|
|
29356
|
+
* hydration that threw would otherwise render as an empty Stationary section,
|
|
29357
|
+
* which is a definite claim about a camera nobody could read.
|
|
29358
|
+
*/
|
|
29359
|
+
var CameraOccupancySnapshotForDeviceSchema = object({
|
|
29360
|
+
deviceId: number(),
|
|
29361
|
+
read: _enum(["read", "unreadable"]),
|
|
29362
|
+
snapshot: CameraOccupancySnapshotSchema.nullable()
|
|
29363
|
+
});
|
|
29364
|
+
/**
|
|
29195
29365
|
* Time-series resolution. The history methods return one bucket per
|
|
29196
29366
|
* step over the requested range. Smaller resolutions cost more
|
|
29197
29367
|
* memory + bandwidth; bound to discrete steps so caller cannot ask
|
|
@@ -29215,7 +29385,7 @@ var HistoryPointSchema = object({
|
|
|
29215
29385
|
/** Object count averaged over the bucket (rounded to nearest integer). */
|
|
29216
29386
|
count: number().int().nonnegative()
|
|
29217
29387
|
});
|
|
29218
|
-
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({
|
|
29388
|
+
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(CameraOccupancySnapshotForDeviceSchema).readonly()), method(object({
|
|
29219
29389
|
deviceId: number(),
|
|
29220
29390
|
zoneId: string(),
|
|
29221
29391
|
className: string().optional()
|
|
@@ -32520,6 +32690,12 @@ Object.freeze({
|
|
|
32520
32690
|
addonId: null,
|
|
32521
32691
|
access: "view"
|
|
32522
32692
|
},
|
|
32693
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
32694
|
+
capName: "pipeline-analytics",
|
|
32695
|
+
capScope: "device",
|
|
32696
|
+
addonId: null,
|
|
32697
|
+
access: "view"
|
|
32698
|
+
},
|
|
32523
32699
|
"pipelineAnalytics.getMotionEvents": {
|
|
32524
32700
|
capName: "pipeline-analytics",
|
|
32525
32701
|
capScope: "device",
|
|
@@ -33696,6 +33872,12 @@ Object.freeze({
|
|
|
33696
33872
|
addonId: null,
|
|
33697
33873
|
access: "view"
|
|
33698
33874
|
},
|
|
33875
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
33876
|
+
capName: "recording",
|
|
33877
|
+
capScope: "system",
|
|
33878
|
+
addonId: null,
|
|
33879
|
+
access: "create"
|
|
33880
|
+
},
|
|
33699
33881
|
"recording.refreshStorageLocationsForMigration": {
|
|
33700
33882
|
capName: "recording",
|
|
33701
33883
|
capScope: "system",
|
|
@@ -33822,6 +34004,12 @@ Object.freeze({
|
|
|
33822
34004
|
addonId: null,
|
|
33823
34005
|
access: "view"
|
|
33824
34006
|
},
|
|
34007
|
+
"sceneMonitor.listScenesBatch": {
|
|
34008
|
+
capName: "scene-monitor",
|
|
34009
|
+
capScope: "device",
|
|
34010
|
+
addonId: null,
|
|
34011
|
+
access: "view"
|
|
34012
|
+
},
|
|
33825
34013
|
"sceneMonitor.recheckNow": {
|
|
33826
34014
|
capName: "scene-monitor",
|
|
33827
34015
|
capScope: "device",
|
|
@@ -35178,6 +35366,12 @@ Object.freeze({
|
|
|
35178
35366
|
addonId: null,
|
|
35179
35367
|
access: "view"
|
|
35180
35368
|
},
|
|
35369
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
35370
|
+
capName: "zone-analytics",
|
|
35371
|
+
capScope: "device",
|
|
35372
|
+
addonId: null,
|
|
35373
|
+
access: "view"
|
|
35374
|
+
},
|
|
35181
35375
|
"zoneAnalytics.getUnzonedHistory": {
|
|
35182
35376
|
capName: "zone-analytics",
|
|
35183
35377
|
capScope: "device",
|
|
@@ -36182,6 +36376,11 @@ Object.freeze({
|
|
|
36182
36376
|
form: "single",
|
|
36183
36377
|
optional: false
|
|
36184
36378
|
}],
|
|
36379
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
36380
|
+
name: "deviceIds",
|
|
36381
|
+
form: "array",
|
|
36382
|
+
optional: false
|
|
36383
|
+
}],
|
|
36185
36384
|
"pipelineAnalytics.getMotionEvents": [{
|
|
36186
36385
|
name: "deviceId",
|
|
36187
36386
|
form: "single",
|
|
@@ -36622,6 +36821,11 @@ Object.freeze({
|
|
|
36622
36821
|
form: "single",
|
|
36623
36822
|
optional: false
|
|
36624
36823
|
}],
|
|
36824
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
36825
|
+
name: "deviceId",
|
|
36826
|
+
form: "single",
|
|
36827
|
+
optional: true
|
|
36828
|
+
}],
|
|
36625
36829
|
"recording.relocateFootage": [{
|
|
36626
36830
|
name: "deviceId",
|
|
36627
36831
|
form: "single",
|
|
@@ -36687,6 +36891,11 @@ Object.freeze({
|
|
|
36687
36891
|
form: "single",
|
|
36688
36892
|
optional: false
|
|
36689
36893
|
}],
|
|
36894
|
+
"sceneMonitor.listScenesBatch": [{
|
|
36895
|
+
name: "deviceIds",
|
|
36896
|
+
form: "array",
|
|
36897
|
+
optional: false
|
|
36898
|
+
}],
|
|
36690
36899
|
"sceneMonitor.recheckNow": [{
|
|
36691
36900
|
name: "deviceId",
|
|
36692
36901
|
form: "single",
|
|
@@ -36948,6 +37157,11 @@ Object.freeze({
|
|
|
36948
37157
|
form: "single",
|
|
36949
37158
|
optional: false
|
|
36950
37159
|
}],
|
|
37160
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
37161
|
+
name: "deviceIds",
|
|
37162
|
+
form: "array",
|
|
37163
|
+
optional: false
|
|
37164
|
+
}],
|
|
36951
37165
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
36952
37166
|
name: "deviceId",
|
|
36953
37167
|
form: "single",
|
|
@@ -8672,6 +8672,20 @@ var RelocateJobSchema = object({
|
|
|
8672
8672
|
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
8673
8673
|
*/
|
|
8674
8674
|
rowsReconciled: number().int().nonnegative().optional(),
|
|
8675
|
+
/**
|
|
8676
|
+
* Rows this run FORGOT because the file they name is not on disk.
|
|
8677
|
+
*
|
|
8678
|
+
* The mover derived the path from the row's own fields and `stat`ed it; an
|
|
8679
|
+
* ENOENT there is a per-path confirmation that the segment is gone (D296),
|
|
8680
|
+
* and the durable row is dropped through the same channel eviction uses. It
|
|
8681
|
+
* is reported for the same reason `rowsReconciled` is: this is a durable
|
|
8682
|
+
* mutation nobody asked for, and a migration that quietly erases hour rows is
|
|
8683
|
+
* the same failure as one that quietly skips them (D295).
|
|
8684
|
+
*
|
|
8685
|
+
* The production drain of 2026-08-30 would have reported 11 074 here — the
|
|
8686
|
+
* ledger claimed 5.65 GB of footage that no longer existed.
|
|
8687
|
+
*/
|
|
8688
|
+
rowsForgotten: number().int().nonnegative().optional(),
|
|
8675
8689
|
startedAt: number(),
|
|
8676
8690
|
finishedAt: number().nullable(),
|
|
8677
8691
|
error: string().nullable()
|
|
@@ -9035,6 +9049,91 @@ var RelocateResidueSchema = object({
|
|
|
9035
9049
|
segments: number().int().nonnegative(),
|
|
9036
9050
|
bytes: number().int().nonnegative()
|
|
9037
9051
|
}).nullable();
|
|
9052
|
+
/**
|
|
9053
|
+
* Ask one location whether its durable hour rows describe the disk — the walk
|
|
9054
|
+
* (D319).
|
|
9055
|
+
*
|
|
9056
|
+
* `apply` DEFAULTS TO FALSE and that default is the product: the operator's
|
|
9057
|
+
* missing tool is the question, and the dry run is how they sanity-check the
|
|
9058
|
+
* destructive run before authorising it.
|
|
9059
|
+
*/
|
|
9060
|
+
var LedgerWalkInputSchema = object({
|
|
9061
|
+
locationId: string().min(1),
|
|
9062
|
+
/** Forget the confirmed-absent rows, rather than only counting them. */
|
|
9063
|
+
apply: boolean().optional(),
|
|
9064
|
+
/** Narrow to one camera. */
|
|
9065
|
+
deviceId: number().int().positive().optional(),
|
|
9066
|
+
/** Narrow to these recording profiles; empty/absent = every profile. */
|
|
9067
|
+
profiles: array(string().min(1)).optional()
|
|
9068
|
+
});
|
|
9069
|
+
/** Why a whole walk did nothing. Every one leaves the ledger untouched. */
|
|
9070
|
+
var LedgerWalkRefusalSchema = _enum([
|
|
9071
|
+
"location-unknown",
|
|
9072
|
+
"source-writable",
|
|
9073
|
+
"no-ledger",
|
|
9074
|
+
"archive-unreadable",
|
|
9075
|
+
"anchor-absent",
|
|
9076
|
+
"anchor-unreadable",
|
|
9077
|
+
"anchor-moved"
|
|
9078
|
+
]);
|
|
9079
|
+
_enum([
|
|
9080
|
+
"live-tail",
|
|
9081
|
+
"listing-error",
|
|
9082
|
+
"path-mismatch",
|
|
9083
|
+
"durable-refused"
|
|
9084
|
+
]);
|
|
9085
|
+
/** Every skip reason, always present, always a number — so a reason that never
|
|
9086
|
+
* fired reports as zero rather than absent and the report shape is constant
|
|
9087
|
+
* between passes. Spelled out rather than `z.record` for exactly that. */
|
|
9088
|
+
var LedgerWalkSkipCountsSchema = object({
|
|
9089
|
+
"live-tail": number().int().nonnegative(),
|
|
9090
|
+
"listing-error": number().int().nonnegative(),
|
|
9091
|
+
"path-mismatch": number().int().nonnegative(),
|
|
9092
|
+
"durable-refused": number().int().nonnegative()
|
|
9093
|
+
});
|
|
9094
|
+
/** One camera's share of a walk, so a report names cameras and not rows. */
|
|
9095
|
+
var LedgerWalkDeviceReportSchema = object({
|
|
9096
|
+
deviceId: number().int(),
|
|
9097
|
+
hoursWalked: number().int().nonnegative(),
|
|
9098
|
+
hoursMissing: number().int().nonnegative(),
|
|
9099
|
+
ghostSegments: number().int().nonnegative(),
|
|
9100
|
+
ghostBytes: number().int().nonnegative(),
|
|
9101
|
+
forgottenSegments: number().int().nonnegative(),
|
|
9102
|
+
orphanFiles: number().int().nonnegative()
|
|
9103
|
+
});
|
|
9104
|
+
/**
|
|
9105
|
+
* What one walk claimed, listed, found and (only when armed) forgot.
|
|
9106
|
+
*
|
|
9107
|
+
* `archiveSegments` is the **M** and `segmentsClaimed` the **N** (D295), so a
|
|
9108
|
+
* walk that saw a fraction of the location is visible in its own report rather
|
|
9109
|
+
* than in the absence of one.
|
|
9110
|
+
*/
|
|
9111
|
+
var LedgerWalkReportSchema = object({
|
|
9112
|
+
locationId: string(),
|
|
9113
|
+
applied: boolean(),
|
|
9114
|
+
refused: LedgerWalkRefusalSchema.nullable(),
|
|
9115
|
+
archiveSegments: number().int().nonnegative().nullable(),
|
|
9116
|
+
archiveBytes: number().int().nonnegative().nullable(),
|
|
9117
|
+
hoursClaimed: number().int().nonnegative(),
|
|
9118
|
+
hoursWalked: number().int().nonnegative(),
|
|
9119
|
+
hoursMissing: number().int().nonnegative(),
|
|
9120
|
+
/** `readdir` calls issued — the cost, stated in the unit that is paid. */
|
|
9121
|
+
listings: number().int().nonnegative(),
|
|
9122
|
+
segmentsClaimed: number().int().nonnegative(),
|
|
9123
|
+
ghostSegments: number().int().nonnegative(),
|
|
9124
|
+
ghostBytes: number().int().nonnegative(),
|
|
9125
|
+
ghostHoursWhole: number().int().nonnegative(),
|
|
9126
|
+
forgottenSegments: number().int().nonnegative(),
|
|
9127
|
+
forgottenBytes: number().int().nonnegative(),
|
|
9128
|
+
/** Files under a claimed hour that no durable row names. Never deleted. */
|
|
9129
|
+
orphanFiles: number().int().nonnegative(),
|
|
9130
|
+
orphanSample: array(string()).readonly(),
|
|
9131
|
+
hoursSkipped: number().int().nonnegative(),
|
|
9132
|
+
skippedByReason: LedgerWalkSkipCountsSchema,
|
|
9133
|
+
/** The walk stopped at its per-pass hour bound with claims unwalked. */
|
|
9134
|
+
bounded: boolean(),
|
|
9135
|
+
byDevice: array(LedgerWalkDeviceReportSchema).readonly()
|
|
9136
|
+
});
|
|
9038
9137
|
/** How many rows a media pass would still act on against a given target — the
|
|
9039
9138
|
* media lane's denominator AND its residue, from ONE derivation so the two can
|
|
9040
9139
|
* never disagree. `null` = the count could not be taken. */
|
|
@@ -19443,13 +19542,15 @@ var ListGroupsPageSchema = object({
|
|
|
19443
19542
|
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
19444
19543
|
nextCursor: string().nullable()
|
|
19445
19544
|
});
|
|
19545
|
+
var KEY_EVENTS_DEFAULT_LIMIT = 50;
|
|
19546
|
+
var KEY_EVENTS_MAX_LIMIT = 200;
|
|
19446
19547
|
var KeyEventQueryInput = object({
|
|
19447
19548
|
deviceId: number(),
|
|
19448
19549
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
19449
19550
|
since: number(),
|
|
19450
19551
|
/** Window upper bound (track firstSeen ≤ until). */
|
|
19451
19552
|
until: number(),
|
|
19452
|
-
limit: number().int().min(1).max(
|
|
19553
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
19453
19554
|
/** Drop tracks scoring below this importance. */
|
|
19454
19555
|
minImportance: number().min(0).max(1).optional(),
|
|
19455
19556
|
/** Restrict to a single class (e.g. 'person'). */
|
|
@@ -19471,6 +19572,32 @@ var KeyEventSchema = object({
|
|
|
19471
19572
|
...TrackFlagFields,
|
|
19472
19573
|
...TrackRetrainFields
|
|
19473
19574
|
});
|
|
19575
|
+
/** `getKeyEvents`' window and filters, asked of a SET of cameras at once. */
|
|
19576
|
+
var KeyEventBatchQueryInput = object({
|
|
19577
|
+
deviceIds: array(number()).min(1).max(200),
|
|
19578
|
+
since: number(),
|
|
19579
|
+
until: number(),
|
|
19580
|
+
/** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
|
|
19581
|
+
* across the set, which would let a busy camera starve a quiet one of its
|
|
19582
|
+
* rows and change what the merged feed contains. */
|
|
19583
|
+
limit: number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
|
|
19584
|
+
minImportance: number().min(0).max(1).optional(),
|
|
19585
|
+
classFilter: string().optional()
|
|
19586
|
+
});
|
|
19587
|
+
/**
|
|
19588
|
+
* One camera's key events in a batch answer.
|
|
19589
|
+
*
|
|
19590
|
+
* The row exists for every requested id. `getKeyEvents` degrades to `[]` on
|
|
19591
|
+
* error rather than throwing, so a camera whose store read failed and one with
|
|
19592
|
+
* no events in the window were ALREADY indistinguishable per camera — the
|
|
19593
|
+
* batch does not make that worse, and the row keeps the deviceId the single
|
|
19594
|
+
* method's output never carried (the caller used to stamp it from the fan-out
|
|
19595
|
+
* key, which only worked because there was one query per camera).
|
|
19596
|
+
*/
|
|
19597
|
+
var KeyEventsForDeviceSchema = object({
|
|
19598
|
+
deviceId: number(),
|
|
19599
|
+
events: array(KeyEventSchema).readonly()
|
|
19600
|
+
});
|
|
19474
19601
|
object({
|
|
19475
19602
|
trackId: string(),
|
|
19476
19603
|
className: string(),
|
|
@@ -19740,7 +19867,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
19740
19867
|
until: number().optional(),
|
|
19741
19868
|
kinds: array(string()).optional(),
|
|
19742
19869
|
limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
|
|
19743
|
-
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
|
|
19870
|
+
}), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(KeyEventBatchQueryInput, array(KeyEventsForDeviceSchema).readonly()), method(object({
|
|
19744
19871
|
deviceId: number(),
|
|
19745
19872
|
since: number(),
|
|
19746
19873
|
until: number(),
|
|
@@ -27440,6 +27567,9 @@ method(object({
|
|
|
27440
27567
|
}), method(RelocateResidueInputSchema, RelocateResidueSchema, {
|
|
27441
27568
|
kind: "query",
|
|
27442
27569
|
auth: "admin"
|
|
27570
|
+
}), method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
|
|
27571
|
+
kind: "mutation",
|
|
27572
|
+
auth: "admin"
|
|
27443
27573
|
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
27444
27574
|
kind: "mutation",
|
|
27445
27575
|
auth: "admin"
|
|
@@ -27831,7 +27961,26 @@ var SceneMonitorStatusSchema = object({
|
|
|
27831
27961
|
monitors: array(SceneMonitorSchema),
|
|
27832
27962
|
lastFetchedAt: number()
|
|
27833
27963
|
});
|
|
27834
|
-
|
|
27964
|
+
/**
|
|
27965
|
+
* One camera's row in a `listScenesBatch` answer.
|
|
27966
|
+
*
|
|
27967
|
+
* `status` is NULLABLE and the nullability is the whole point. `scene-monitor`
|
|
27968
|
+
* is a `defaultActive` wrapper, so every camera is asked; a camera whose
|
|
27969
|
+
* provider is absent (pipeline-analytics not deployed, the post-processing node
|
|
27970
|
+
* down) cannot answer, and that is not the same fact as a camera with no scenes
|
|
27971
|
+
* configured. Fanned out per camera the difference was visible — one query
|
|
27972
|
+
* errored while the others resolved — and a batch that returned only the rows
|
|
27973
|
+
* it managed would have destroyed it, silently, by making an unreachable camera
|
|
27974
|
+
* indistinguishable from one that answered `monitors: []`.
|
|
27975
|
+
*
|
|
27976
|
+
* So: EVERY requested deviceId gets a row. `status: null` means "this camera
|
|
27977
|
+
* could not be read"; `status.monitors: []` means "read, and it has none".
|
|
27978
|
+
*/
|
|
27979
|
+
var SceneMonitorStatusForDeviceSchema = object({
|
|
27980
|
+
deviceId: number(),
|
|
27981
|
+
status: SceneMonitorStatusSchema.nullable()
|
|
27982
|
+
});
|
|
27983
|
+
DeviceType.Camera, method(object({ deviceId: number() }), SceneMonitorStatusSchema), method(object({ deviceIds: array(number()).min(1).max(200) }), array(SceneMonitorStatusForDeviceSchema).readonly()), method(object({
|
|
27835
27984
|
deviceId: number(),
|
|
27836
27985
|
label: string(),
|
|
27837
27986
|
roi: MaskRectShapeSchema,
|
|
@@ -29180,6 +29329,27 @@ var CameraOccupancySnapshotSchema = object({
|
|
|
29180
29329
|
stationaryObjects: array(StationaryObjectSchema).readonly().optional()
|
|
29181
29330
|
});
|
|
29182
29331
|
/**
|
|
29332
|
+
* One camera's row in a `getCurrentSnapshotBatch` answer.
|
|
29333
|
+
*
|
|
29334
|
+
* THREE outcomes, and the single-camera method could only express two of them
|
|
29335
|
+
* because `snapshot: null` was already spoken for:
|
|
29336
|
+
*
|
|
29337
|
+
* - `read: 'read'`, `snapshot` present — the live occupancy reading.
|
|
29338
|
+
* - `read: 'read'`, `snapshot: null` — read, and this camera has no reading
|
|
29339
|
+
* yet: no frame since boot, and no parked-object registry to hydrate from.
|
|
29340
|
+
* - `read: 'unreadable'` — the owner could not answer for this
|
|
29341
|
+
* camera. `snapshot` is null, and it does NOT mean "nothing parked here".
|
|
29342
|
+
*
|
|
29343
|
+
* Collapsing the last two is the failure this field exists to prevent: a
|
|
29344
|
+
* hydration that threw would otherwise render as an empty Stationary section,
|
|
29345
|
+
* which is a definite claim about a camera nobody could read.
|
|
29346
|
+
*/
|
|
29347
|
+
var CameraOccupancySnapshotForDeviceSchema = object({
|
|
29348
|
+
deviceId: number(),
|
|
29349
|
+
read: _enum(["read", "unreadable"]),
|
|
29350
|
+
snapshot: CameraOccupancySnapshotSchema.nullable()
|
|
29351
|
+
});
|
|
29352
|
+
/**
|
|
29183
29353
|
* Time-series resolution. The history methods return one bucket per
|
|
29184
29354
|
* step over the requested range. Smaller resolutions cost more
|
|
29185
29355
|
* memory + bandwidth; bound to discrete steps so caller cannot ask
|
|
@@ -29203,7 +29373,7 @@ var HistoryPointSchema = object({
|
|
|
29203
29373
|
/** Object count averaged over the bucket (rounded to nearest integer). */
|
|
29204
29374
|
count: number().int().nonnegative()
|
|
29205
29375
|
});
|
|
29206
|
-
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({
|
|
29376
|
+
DeviceType.Camera, method(object({ deviceId: number() }), CameraOccupancySnapshotSchema.nullable()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(CameraOccupancySnapshotForDeviceSchema).readonly()), method(object({
|
|
29207
29377
|
deviceId: number(),
|
|
29208
29378
|
zoneId: string(),
|
|
29209
29379
|
className: string().optional()
|
|
@@ -32508,6 +32678,12 @@ Object.freeze({
|
|
|
32508
32678
|
addonId: null,
|
|
32509
32679
|
access: "view"
|
|
32510
32680
|
},
|
|
32681
|
+
"pipelineAnalytics.getKeyEventsBatch": {
|
|
32682
|
+
capName: "pipeline-analytics",
|
|
32683
|
+
capScope: "device",
|
|
32684
|
+
addonId: null,
|
|
32685
|
+
access: "view"
|
|
32686
|
+
},
|
|
32511
32687
|
"pipelineAnalytics.getMotionEvents": {
|
|
32512
32688
|
capName: "pipeline-analytics",
|
|
32513
32689
|
capScope: "device",
|
|
@@ -33684,6 +33860,12 @@ Object.freeze({
|
|
|
33684
33860
|
addonId: null,
|
|
33685
33861
|
access: "view"
|
|
33686
33862
|
},
|
|
33863
|
+
"recording.reconcileLedgerAgainstDisk": {
|
|
33864
|
+
capName: "recording",
|
|
33865
|
+
capScope: "system",
|
|
33866
|
+
addonId: null,
|
|
33867
|
+
access: "create"
|
|
33868
|
+
},
|
|
33687
33869
|
"recording.refreshStorageLocationsForMigration": {
|
|
33688
33870
|
capName: "recording",
|
|
33689
33871
|
capScope: "system",
|
|
@@ -33810,6 +33992,12 @@ Object.freeze({
|
|
|
33810
33992
|
addonId: null,
|
|
33811
33993
|
access: "view"
|
|
33812
33994
|
},
|
|
33995
|
+
"sceneMonitor.listScenesBatch": {
|
|
33996
|
+
capName: "scene-monitor",
|
|
33997
|
+
capScope: "device",
|
|
33998
|
+
addonId: null,
|
|
33999
|
+
access: "view"
|
|
34000
|
+
},
|
|
33813
34001
|
"sceneMonitor.recheckNow": {
|
|
33814
34002
|
capName: "scene-monitor",
|
|
33815
34003
|
capScope: "device",
|
|
@@ -35166,6 +35354,12 @@ Object.freeze({
|
|
|
35166
35354
|
addonId: null,
|
|
35167
35355
|
access: "view"
|
|
35168
35356
|
},
|
|
35357
|
+
"zoneAnalytics.getCurrentSnapshotBatch": {
|
|
35358
|
+
capName: "zone-analytics",
|
|
35359
|
+
capScope: "device",
|
|
35360
|
+
addonId: null,
|
|
35361
|
+
access: "view"
|
|
35362
|
+
},
|
|
35169
35363
|
"zoneAnalytics.getUnzonedHistory": {
|
|
35170
35364
|
capName: "zone-analytics",
|
|
35171
35365
|
capScope: "device",
|
|
@@ -36170,6 +36364,11 @@ Object.freeze({
|
|
|
36170
36364
|
form: "single",
|
|
36171
36365
|
optional: false
|
|
36172
36366
|
}],
|
|
36367
|
+
"pipelineAnalytics.getKeyEventsBatch": [{
|
|
36368
|
+
name: "deviceIds",
|
|
36369
|
+
form: "array",
|
|
36370
|
+
optional: false
|
|
36371
|
+
}],
|
|
36173
36372
|
"pipelineAnalytics.getMotionEvents": [{
|
|
36174
36373
|
name: "deviceId",
|
|
36175
36374
|
form: "single",
|
|
@@ -36610,6 +36809,11 @@ Object.freeze({
|
|
|
36610
36809
|
form: "single",
|
|
36611
36810
|
optional: false
|
|
36612
36811
|
}],
|
|
36812
|
+
"recording.reconcileLedgerAgainstDisk": [{
|
|
36813
|
+
name: "deviceId",
|
|
36814
|
+
form: "single",
|
|
36815
|
+
optional: true
|
|
36816
|
+
}],
|
|
36613
36817
|
"recording.relocateFootage": [{
|
|
36614
36818
|
name: "deviceId",
|
|
36615
36819
|
form: "single",
|
|
@@ -36675,6 +36879,11 @@ Object.freeze({
|
|
|
36675
36879
|
form: "single",
|
|
36676
36880
|
optional: false
|
|
36677
36881
|
}],
|
|
36882
|
+
"sceneMonitor.listScenesBatch": [{
|
|
36883
|
+
name: "deviceIds",
|
|
36884
|
+
form: "array",
|
|
36885
|
+
optional: false
|
|
36886
|
+
}],
|
|
36678
36887
|
"sceneMonitor.recheckNow": [{
|
|
36679
36888
|
name: "deviceId",
|
|
36680
36889
|
form: "single",
|
|
@@ -36936,6 +37145,11 @@ Object.freeze({
|
|
|
36936
37145
|
form: "single",
|
|
36937
37146
|
optional: false
|
|
36938
37147
|
}],
|
|
37148
|
+
"zoneAnalytics.getCurrentSnapshotBatch": [{
|
|
37149
|
+
name: "deviceIds",
|
|
37150
|
+
form: "array",
|
|
37151
|
+
optional: false
|
|
37152
|
+
}],
|
|
36939
37153
|
"zoneAnalytics.getUnzonedHistory": [{
|
|
36940
37154
|
name: "deviceId",
|
|
36941
37155
|
form: "single",
|
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.60",
|
|
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",
|