@camstack/addon-osd-manager 0.1.146 → 0.1.148
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/{MotionZonesSettings-DAxqXklY.mjs → MotionZonesSettings-BE9WUdRt.mjs} +2 -2
- package/dist/{PrivacyMaskSettings-DxY1SExl.mjs → PrivacyMaskSettings-DS9QMvLQ.mjs} +4 -4
- package/dist/{SceneMonitorEditor-D2d47F_V.mjs → SceneMonitorEditor-Dp9VUno1.mjs} +3 -3
- package/dist/_stub.js +11 -11
- package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-CyeMVww2.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-BrVYU0wm.mjs} +3 -3
- package/dist/_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CCyGyV4m.mjs +26 -0
- package/dist/{hostInit-DEeDzJK5.mjs → hostInit-5x_5PqnW.mjs} +2 -2
- package/dist/index.js +292 -215
- package/dist/index.mjs +292 -215
- package/dist/{player-overlays-DeusjeOj.mjs → player-overlays-BF0CGxFK.mjs} +1 -1
- package/dist/remoteEntry.js +1 -1
- package/dist/{responsive-bl9DCRTN.mjs → responsive-COf1R73i.mjs} +1 -1
- package/dist/{scene-monitor-copy-BIDfr4E5.mjs → scene-monitor-copy-D_ksge64.mjs} +1 -1
- package/dist/{square-yZRmjMIg.mjs → square-D6ZZGuyC.mjs} +1 -1
- package/dist/{trash-2-IqfhyJQ1.mjs → trash-2-B-TzfoNr.mjs} +1 -1
- package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-AnF0MZSp.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-Cq_qaEBf.mjs} +1 -1
- package/package.json +1 -1
- package/dist/_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-H1dXnudd.mjs +0 -26
package/dist/index.mjs
CHANGED
|
@@ -5369,7 +5369,7 @@ var ZodIssueCode = {
|
|
|
5369
5369
|
var ZodFirstPartyTypeKind;
|
|
5370
5370
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5371
5371
|
//#endregion
|
|
5372
|
-
//#region ../types/dist/sleep-
|
|
5372
|
+
//#region ../types/dist/sleep-C-v96WpE.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).
|
|
@@ -6925,6 +6925,10 @@ var ProfileRtspEntrySchema = object({
|
|
|
6925
6925
|
codec: string().optional(),
|
|
6926
6926
|
resolution: CamStreamResolutionSchema.optional()
|
|
6927
6927
|
});
|
|
6928
|
+
object({
|
|
6929
|
+
field: string().min(1),
|
|
6930
|
+
on: literal("advance")
|
|
6931
|
+
});
|
|
6928
6932
|
/**
|
|
6929
6933
|
* Output schema shared by the contribution + live methods.
|
|
6930
6934
|
*
|
|
@@ -7506,7 +7510,45 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
7506
7510
|
return DeviceRole;
|
|
7507
7511
|
}({});
|
|
7508
7512
|
//#endregion
|
|
7509
|
-
//#region ../types/dist/composition-
|
|
7513
|
+
//#region ../types/dist/composition-BK-GTFYb.mjs
|
|
7514
|
+
/**
|
|
7515
|
+
* LA tabella "quale booleano di questo tipo di device conta come ALTO", e il
|
|
7516
|
+
* valutatore puro del suo FRONTE.
|
|
7517
|
+
*
|
|
7518
|
+
* Viveva dentro il builtin virtual-doorbell
|
|
7519
|
+
* (`@camstack/system` — `builtins/doorbell/trigger-engine.ts`) e i suoi
|
|
7520
|
+
* predicati erano privati al modulo. Il recorder ne ha bisogno per il trigger
|
|
7521
|
+
* `RecordingTriggers.sensorDeviceIds`: copiarla avrebbe creato la SECONDA
|
|
7522
|
+
* tabella, che diverge alla prima cap aggiunta e il cui sintomo — "il sensore
|
|
7523
|
+
* fa suonare il campanello ma non registra" — è esattamente D62. Quindi si
|
|
7524
|
+
* SPOSTA qui e il doorbell la ri-esporta.
|
|
7525
|
+
*
|
|
7526
|
+
* ⚠ NON è `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), e le
|
|
7527
|
+
* due non vanno unificate: quella risponde a "qual è la PAROLA di stato per una
|
|
7528
|
+
* regola" (e include `presence`, `cover`, `alarm-panel`), questa a "qual è il
|
|
7529
|
+
* booleano il cui FRONTE conta". Vocabolari deliberatamente diversi.
|
|
7530
|
+
*/
|
|
7531
|
+
/**
|
|
7532
|
+
* Known binary / switch source caps → the boolean slice field whose
|
|
7533
|
+
* false→true rise counts as ACTIVE. Every entry is "fire on active".
|
|
7534
|
+
* Sensors whose "active" reading is not a plain boolean (presence's string
|
|
7535
|
+
* state, connectivity's connected flag) are deliberately excluded — a
|
|
7536
|
+
* reconnect is not a doorbell press, and it is not a recording either.
|
|
7537
|
+
*/
|
|
7538
|
+
var SOURCE_CAP_ACTIVE_FIELD = {
|
|
7539
|
+
contact: "entryOpen",
|
|
7540
|
+
binary: "on",
|
|
7541
|
+
switch: "on",
|
|
7542
|
+
motion: "detected",
|
|
7543
|
+
flood: "flooded",
|
|
7544
|
+
gas: "detected",
|
|
7545
|
+
smoke: "detected",
|
|
7546
|
+
"carbon-monoxide": "detected",
|
|
7547
|
+
vibration: "detected",
|
|
7548
|
+
tamper: "tampered"
|
|
7549
|
+
};
|
|
7550
|
+
/** Cap names whose presence in a device's bindings qualify it as a source. */
|
|
7551
|
+
var SOURCE_CAPS = Object.keys(SOURCE_CAP_ACTIVE_FIELD);
|
|
7510
7552
|
/**
|
|
7511
7553
|
* Error types for the safe expression engine. Two distinct classes so callers
|
|
7512
7554
|
* can tell a compile-time (grammar) failure from a runtime (evaluation)
|
|
@@ -7704,6 +7746,20 @@ var table = {
|
|
|
7704
7746
|
const present = args.flatMap((a, i) => a === null ? [] : [asFiniteNumber(a, "latest", i)]);
|
|
7705
7747
|
return present.length === 0 ? null : finiteResult(Math.max(...present), "latest");
|
|
7706
7748
|
}
|
|
7749
|
+
},
|
|
7750
|
+
rose: {
|
|
7751
|
+
minArgs: 2,
|
|
7752
|
+
maxArgs: 3,
|
|
7753
|
+
apply: () => {
|
|
7754
|
+
throw new ExpressionEvalError("rose: stateful evaluation context is required");
|
|
7755
|
+
}
|
|
7756
|
+
},
|
|
7757
|
+
count: {
|
|
7758
|
+
minArgs: 1,
|
|
7759
|
+
maxArgs: 1,
|
|
7760
|
+
apply: () => {
|
|
7761
|
+
throw new ExpressionEvalError("count: stateful evaluation context is required");
|
|
7762
|
+
}
|
|
7707
7763
|
}
|
|
7708
7764
|
};
|
|
7709
7765
|
Object.freeze(Object.assign(Object.create(null), table));
|
|
@@ -8218,6 +8274,7 @@ var CompositionItemEntrySchema = object({
|
|
|
8218
8274
|
var CompositionFeatureSchema = discriminatedUnion("kind", [object({
|
|
8219
8275
|
kind: literal("fields"),
|
|
8220
8276
|
cap: string().min(1),
|
|
8277
|
+
enabled: boolean().optional(),
|
|
8221
8278
|
fields: record(string().min(1), CompositionFieldSourceSchema).refine((fields) => Object.keys(fields).length <= 32, { message: `at most 32 fields per capability` }),
|
|
8222
8279
|
/**
|
|
8223
8280
|
* Items of the cap's item array, keyed by item key (D663). Naming `items`
|
|
@@ -8229,6 +8286,7 @@ var CompositionFeatureSchema = discriminatedUnion("kind", [object({
|
|
|
8229
8286
|
}), object({
|
|
8230
8287
|
kind: literal("passthrough"),
|
|
8231
8288
|
cap: string().min(1),
|
|
8289
|
+
enabled: boolean().optional(),
|
|
8232
8290
|
source: CompositionSourceRefSchema
|
|
8233
8291
|
})]);
|
|
8234
8292
|
var CompositionSchema = object({
|
|
@@ -8258,7 +8316,6 @@ var CompositionSchema = object({
|
|
|
8258
8316
|
});
|
|
8259
8317
|
new Set([
|
|
8260
8318
|
"track",
|
|
8261
|
-
"summary",
|
|
8262
8319
|
"face",
|
|
8263
8320
|
"identity",
|
|
8264
8321
|
"plate",
|
|
@@ -13638,6 +13695,15 @@ var cameraStreamsCapability = {
|
|
|
13638
13695
|
*/
|
|
13639
13696
|
durability: "session"
|
|
13640
13697
|
};
|
|
13698
|
+
EventCategory.DoorbellOnPressed;
|
|
13699
|
+
var CompositionEventPlanSchema = object({
|
|
13700
|
+
featureIndex: number().int().nonnegative(),
|
|
13701
|
+
cap: string(),
|
|
13702
|
+
eventName: string(),
|
|
13703
|
+
category: _enum(EventCategory),
|
|
13704
|
+
stateField: string(),
|
|
13705
|
+
fieldKey: string()
|
|
13706
|
+
});
|
|
13641
13707
|
/** One refusal, named (D391). `path` points into the composition, e.g. `features[0].fields.celsius`. */
|
|
13642
13708
|
var CompositionProblemSchema = object({
|
|
13643
13709
|
code: _enum([
|
|
@@ -13687,12 +13753,14 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
13687
13753
|
]);
|
|
13688
13754
|
/**
|
|
13689
13755
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
13690
|
-
* field of its cap changes value · `constant` reads nothing, computed once
|
|
13756
|
+
* field of its cap changes value · `constant` reads nothing, computed once ·
|
|
13757
|
+
* `accumulator` advances from the target's seed/current output.
|
|
13691
13758
|
*/
|
|
13692
13759
|
var CompositionFieldRoleSchema = _enum([
|
|
13693
13760
|
"derived",
|
|
13694
13761
|
"clock",
|
|
13695
|
-
"constant"
|
|
13762
|
+
"constant",
|
|
13763
|
+
"accumulator"
|
|
13696
13764
|
]);
|
|
13697
13765
|
/** The item a planned field belongs to; its `path` is then the dotted path INSIDE the item. */
|
|
13698
13766
|
var CompositionFieldItemSchema = object({
|
|
@@ -13728,6 +13796,7 @@ var CompositionFeatureModeSchema = _enum([
|
|
|
13728
13796
|
"replace"
|
|
13729
13797
|
]);
|
|
13730
13798
|
var CompositionFeaturePlanSchema = object({
|
|
13799
|
+
/** Index in the stored feature array; disabled features are omitted rather than re-indexed. */
|
|
13731
13800
|
featureIndex: number().int().nonnegative(),
|
|
13732
13801
|
cap: string(),
|
|
13733
13802
|
mode: CompositionFeatureModeSchema
|
|
@@ -13736,7 +13805,8 @@ var CompositionValidationSchema = object({
|
|
|
13736
13805
|
ok: boolean(),
|
|
13737
13806
|
problems: array(CompositionProblemSchema),
|
|
13738
13807
|
fields: array(CompositionFieldPlanSchema),
|
|
13739
|
-
features: array(CompositionFeaturePlanSchema)
|
|
13808
|
+
features: array(CompositionFeaturePlanSchema),
|
|
13809
|
+
events: array(CompositionEventPlanSchema)
|
|
13740
13810
|
});
|
|
13741
13811
|
/**
|
|
13742
13812
|
* Mirrors `CoreBlockStatus`, pinned by `core-blocks-source.spec.ts`. `degraded`:
|
|
@@ -15992,6 +16062,34 @@ var DeviceBindingsForDeviceSchema = object({
|
|
|
15992
16062
|
nativeAddonId: string()
|
|
15993
16063
|
}))
|
|
15994
16064
|
});
|
|
16065
|
+
/**
|
|
16066
|
+
* The STORED wrapper activation for one `(device, capability)` pair — the row
|
|
16067
|
+
* `setWrapperActive` writes, read back three-way (D675):
|
|
16068
|
+
*
|
|
16069
|
+
* - `value` — the store answered and holds an activation: the bound wrapper's
|
|
16070
|
+
* addon id, or `null`, the operator's explicit "off" marker (D62);
|
|
16071
|
+
* - `missing` — the store answered, its activation map exists, and it holds
|
|
16072
|
+
* nothing for this pair: the operator never activated or deactivated a
|
|
16073
|
+
* wrapper here;
|
|
16074
|
+
* - `failed` — the store could not be read, holds no activation map at all
|
|
16075
|
+
* (an empty or unready snapshot, D44), or holds something that is not an
|
|
16076
|
+
* activation. It carries NO information: a consumer must never read it as
|
|
16077
|
+
* `missing` (D315, D393).
|
|
16078
|
+
*
|
|
16079
|
+
* This is the persisted INPUT, not the derived `getBindings` view — no registry
|
|
16080
|
+
* resolution, no `defaultActive` auto-binding, no cluster native-cap folding.
|
|
16081
|
+
*/
|
|
16082
|
+
var WrapperActivationReadSchema = discriminatedUnion("kind", [
|
|
16083
|
+
object({
|
|
16084
|
+
kind: literal("value"),
|
|
16085
|
+
wrapperAddonId: string().nullable()
|
|
16086
|
+
}),
|
|
16087
|
+
object({ kind: literal("missing") }),
|
|
16088
|
+
object({
|
|
16089
|
+
kind: literal("failed"),
|
|
16090
|
+
error: string()
|
|
16091
|
+
})
|
|
16092
|
+
]);
|
|
15995
16093
|
var SavedDeviceRowSchema = object({
|
|
15996
16094
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
15997
16095
|
id: number(),
|
|
@@ -16790,6 +16888,21 @@ var deviceManagerCapability = {
|
|
|
16790
16888
|
auth: "admin"
|
|
16791
16889
|
}),
|
|
16792
16890
|
/**
|
|
16891
|
+
* The STORED wrapper activation for one `(device, capName)` pair, three-way
|
|
16892
|
+
* (`value` / `missing` / `failed`, see {@link WrapperActivationReadSchema}).
|
|
16893
|
+
*
|
|
16894
|
+
* The narrow read of the durable authority behind `getBindings`: a
|
|
16895
|
+
* consumer that must know what the operator PERSISTED (virtual-doorbell,
|
|
16896
|
+
* before it drops a press) asks this instead of pulling device-manager's
|
|
16897
|
+
* whole addon store through `addonSettingsRaw.getGlobal` — which answered
|
|
16898
|
+
* `{}` on every isolated-engine hub and so never worked (D675). It reads
|
|
16899
|
+
* ONE row (the activation map, ~1.6 KB), never the ~625 KB store.
|
|
16900
|
+
*/
|
|
16901
|
+
getWrapperActivation: method(object({
|
|
16902
|
+
deviceId: number(),
|
|
16903
|
+
capName: string().min(1)
|
|
16904
|
+
}), WrapperActivationReadSchema),
|
|
16905
|
+
/**
|
|
16793
16906
|
* Return the addon ids that declared a wrapper provider for `capName`.
|
|
16794
16907
|
* Backs the device-bindings UI's wrapper-picker dropdown. Entries are
|
|
16795
16908
|
* sourced from `CapabilityRegistry.wrapperProviders`, populated when
|
|
@@ -23286,6 +23399,102 @@ var oauthIntegrationCapability = {
|
|
|
23286
23399
|
getDescriptor: method(_void(), OauthIntegrationDescriptorSchema, { auth: "admin" }) }
|
|
23287
23400
|
};
|
|
23288
23401
|
/**
|
|
23402
|
+
* What started a camera's onboard motion (D672). `camera` is the camera's own
|
|
23403
|
+
* firmware; `sensor` is a device the operator ATTACHED to it. Absent on the
|
|
23404
|
+
* wire means the camera: only the camera-sensors bridge ever says `sensor`.
|
|
23405
|
+
*/
|
|
23406
|
+
var MotionTriggeredBySchema = discriminatedUnion("kind", [object({ kind: literal("camera") }), object({
|
|
23407
|
+
kind: literal("sensor"),
|
|
23408
|
+
deviceId: number().int().positive()
|
|
23409
|
+
})]);
|
|
23410
|
+
Object.freeze({ kind: "camera" });
|
|
23411
|
+
var CameraSensorRefSchema = object({
|
|
23412
|
+
addonId: string().min(1),
|
|
23413
|
+
stableId: string().min(1)
|
|
23414
|
+
});
|
|
23415
|
+
function cameraSensorRefKey(ref) {
|
|
23416
|
+
return `${ref.addonId}/${ref.stableId}`;
|
|
23417
|
+
}
|
|
23418
|
+
/** CS-1 accepts exactly one mode; CS-2 (D673) widens it to confirm / replace. */
|
|
23419
|
+
var CameraSensorsModeSchema = _enum(["in-addition"]);
|
|
23420
|
+
object({
|
|
23421
|
+
mode: CameraSensorsModeSchema,
|
|
23422
|
+
sensors: array(CameraSensorRefSchema).min(1).max(8)
|
|
23423
|
+
}).superRefine((value, ctx) => {
|
|
23424
|
+
const seen = /* @__PURE__ */ new Set();
|
|
23425
|
+
value.sensors.forEach((ref, index) => {
|
|
23426
|
+
const key = cameraSensorRefKey(ref);
|
|
23427
|
+
if (seen.has(key)) ctx.addIssue({
|
|
23428
|
+
code: "custom",
|
|
23429
|
+
path: ["sensors", index],
|
|
23430
|
+
message: `duplicate camera sensor ${key}`
|
|
23431
|
+
});
|
|
23432
|
+
seen.add(key);
|
|
23433
|
+
});
|
|
23434
|
+
});
|
|
23435
|
+
var RefFields = {
|
|
23436
|
+
addonId: string(),
|
|
23437
|
+
stableId: string()
|
|
23438
|
+
};
|
|
23439
|
+
var CameraSensorAttachmentSchema = discriminatedUnion("state", [
|
|
23440
|
+
object({
|
|
23441
|
+
...RefFields,
|
|
23442
|
+
state: literal("ready"),
|
|
23443
|
+
deviceId: number(),
|
|
23444
|
+
name: string(),
|
|
23445
|
+
caps: array(string()).readonly()
|
|
23446
|
+
}),
|
|
23447
|
+
object({
|
|
23448
|
+
...RefFields,
|
|
23449
|
+
state: literal("offline"),
|
|
23450
|
+
deviceId: number(),
|
|
23451
|
+
name: string(),
|
|
23452
|
+
reason: _enum(["offline", "disabled"])
|
|
23453
|
+
}),
|
|
23454
|
+
object({
|
|
23455
|
+
...RefFields,
|
|
23456
|
+
state: literal("missing"),
|
|
23457
|
+
reason: string()
|
|
23458
|
+
}),
|
|
23459
|
+
object({
|
|
23460
|
+
...RefFields,
|
|
23461
|
+
state: literal("unsupported"),
|
|
23462
|
+
deviceId: number(),
|
|
23463
|
+
name: string(),
|
|
23464
|
+
reason: string()
|
|
23465
|
+
}),
|
|
23466
|
+
object({
|
|
23467
|
+
...RefFields,
|
|
23468
|
+
state: literal("unreadable"),
|
|
23469
|
+
reason: string()
|
|
23470
|
+
})
|
|
23471
|
+
]);
|
|
23472
|
+
/**
|
|
23473
|
+
* Why a configured camera forwards NOTHING from its sensors, however ready they
|
|
23474
|
+
* are (D672): it does not list `onboard` in `motionSources` (attaching a sensor
|
|
23475
|
+
* does not add it), or it has no active detection config at all (the bridge
|
|
23476
|
+
* reads the active config). Absent = forwarded, or an older node that does not
|
|
23477
|
+
* say.
|
|
23478
|
+
*/
|
|
23479
|
+
var CameraSensorsNotForwardedSchema = _enum(["onboard-not-listed", "no-active-detection"]);
|
|
23480
|
+
var CameraSensorsStatusSchema = discriminatedUnion("state", [
|
|
23481
|
+
object({ state: literal("not-configured") }),
|
|
23482
|
+
object({
|
|
23483
|
+
state: literal("unreadable"),
|
|
23484
|
+
reason: string()
|
|
23485
|
+
}),
|
|
23486
|
+
object({
|
|
23487
|
+
state: literal("configured"),
|
|
23488
|
+
mode: CameraSensorsModeSchema,
|
|
23489
|
+
sensors: array(CameraSensorAttachmentSchema).readonly(),
|
|
23490
|
+
notForwarded: CameraSensorsNotForwardedSchema.optional()
|
|
23491
|
+
})
|
|
23492
|
+
]);
|
|
23493
|
+
Object.freeze({
|
|
23494
|
+
state: "unreadable",
|
|
23495
|
+
reason: "camera sensor mappings not loaded"
|
|
23496
|
+
});
|
|
23497
|
+
/**
|
|
23289
23498
|
* A model choice has a SCOPE, and a scope change has a workflow.
|
|
23290
23499
|
*
|
|
23291
23500
|
* ## The two scopes
|
|
@@ -24034,6 +24243,12 @@ var MotionEventSchema = object({
|
|
|
24034
24243
|
/** Populated by B5 (recording playback URL for this event). */
|
|
24035
24244
|
mediaUrl: string().optional(),
|
|
24036
24245
|
/**
|
|
24246
|
+
* The FIRST trigger of an `onboard` episode, written once at open (D672).
|
|
24247
|
+
* Absent = not recorded (a row written before D672, or an analyzer /
|
|
24248
|
+
* device-activity episode) — never read as "the camera" (D393).
|
|
24249
|
+
*/
|
|
24250
|
+
triggeredBy: MotionTriggeredBySchema.optional(),
|
|
24251
|
+
/**
|
|
24037
24252
|
* One row per motion EPISODE, not one per push (D475). `null` while the
|
|
24038
24253
|
* episode is still open — a further rising edge extends it in place rather
|
|
24039
24254
|
* than inserting a new row. Set once, at close, to `lastOnAt - startedAt`
|
|
@@ -24527,131 +24742,6 @@ var RecentTracksQueryInput = object({
|
|
|
24527
24742
|
/** See {@link ExcludeSourcesDoc}. */
|
|
24528
24743
|
excludeSources: array(TrackSourceSchema).optional()
|
|
24529
24744
|
});
|
|
24530
|
-
/**
|
|
24531
|
-
* A Summary (D359): the per-camera session envelope that references tracks.
|
|
24532
|
-
* `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
|
|
24533
|
-
* 'summary'`, served by the event-media plane at `/m/<id>`), null until the
|
|
24534
|
-
* first frame with a member visible has been materialised (D482 — it was the
|
|
24535
|
-
* row's composite key, which embedded the owner and could name another table's
|
|
24536
|
-
* row once event ids became per-table rowids).
|
|
24537
|
-
*/
|
|
24538
|
-
var SummarySchema = object({
|
|
24539
|
-
id: string(),
|
|
24540
|
-
deviceId: number(),
|
|
24541
|
-
openedAt: number(),
|
|
24542
|
-
lastActiveAt: number(),
|
|
24543
|
-
sealedAt: number().nullable(),
|
|
24544
|
-
memberCount: number().int().nonnegative(),
|
|
24545
|
-
groupShotMediaId: number().int().nullable()
|
|
24546
|
-
});
|
|
24547
|
-
var SummariesQueryInput = object({
|
|
24548
|
-
deviceIds: array(number()).min(1),
|
|
24549
|
-
since: number().optional(),
|
|
24550
|
-
until: number().optional(),
|
|
24551
|
-
limit: number().int().min(1).max(200).default(50),
|
|
24552
|
-
/** The same member-wise filter {@link listRecentSummaries} takes — one
|
|
24553
|
-
* meaning of "dog" on every summary surface. */
|
|
24554
|
-
classes: array(string().min(1).max(60)).max(40).optional()
|
|
24555
|
-
});
|
|
24556
|
-
var SummaryDetailSchema = object({
|
|
24557
|
-
summary: SummarySchema,
|
|
24558
|
-
/** Members in absorption order, oldest join first. */
|
|
24559
|
-
members: array(object({
|
|
24560
|
-
trackId: string(),
|
|
24561
|
-
/**
|
|
24562
|
-
* The track's class at the time it JOINED, or `null` when it was unresolved
|
|
24563
|
-
* and the track no longer exists to fill it.
|
|
24564
|
-
*
|
|
24565
|
-
* The join, not the latest opinion: class voting can re-decide a track's
|
|
24566
|
-
* class afterwards, and a group's composition is the history of who came
|
|
24567
|
-
* together. A consumer counts these to badge a thumbnail — "two people and a
|
|
24568
|
-
* dog" — rather than being handed a second, denormalised tally that would
|
|
24569
|
-
* drift from the members it claims to describe.
|
|
24570
|
-
*/
|
|
24571
|
-
className: string().nullable(),
|
|
24572
|
-
/** `primary` is the one member that carries the group's identity. */
|
|
24573
|
-
role: _enum([
|
|
24574
|
-
"primary",
|
|
24575
|
-
"sibling",
|
|
24576
|
-
"child"
|
|
24577
|
-
]).nullable(),
|
|
24578
|
-
joinedAt: number(),
|
|
24579
|
-
/** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
|
|
24580
|
-
* at read time. Absent when nothing resolved, never an empty string. */
|
|
24581
|
-
label: string().optional(),
|
|
24582
|
-
/** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
|
|
24583
|
-
* recognised nobody, and absent for a member whose track has been pruned —
|
|
24584
|
-
* a thumbnail that names the wrong person is worse than one naming nobody. */
|
|
24585
|
-
subLabel: string().optional()
|
|
24586
|
-
})).readonly()
|
|
24587
|
-
});
|
|
24588
|
-
/**
|
|
24589
|
-
* What a LIST of groups carries: the envelope plus what it is MADE OF.
|
|
24590
|
-
*
|
|
24591
|
-
* Coarse on purpose — the operator's rule is "only the rough data on the list,
|
|
24592
|
-
* we extend when we notice we need more". Enough to draw the card ("two people
|
|
24593
|
-
* and a dog") and no more. The MEMBERS, their names and the per-member links
|
|
24594
|
-
* are on {@link getSummary}: shipping every member of every group so a client
|
|
24595
|
-
* can count them turns a page of two hundred groups into a thousand records to
|
|
24596
|
-
* draw two hundred badges.
|
|
24597
|
-
*/
|
|
24598
|
-
var SummaryListItemSchema = object({
|
|
24599
|
-
summary: SummarySchema,
|
|
24600
|
-
/** Class counts, most numerous first; `className: null` is a member whose
|
|
24601
|
-
* class never resolved, counted so the counts add up to `memberCount`. */
|
|
24602
|
-
classes: array(object({
|
|
24603
|
-
className: string().nullable(),
|
|
24604
|
-
count: number().int().positive()
|
|
24605
|
-
})).readonly()
|
|
24606
|
-
});
|
|
24607
|
-
var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
|
|
24608
|
-
/**
|
|
24609
|
-
* The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
|
|
24610
|
-
*
|
|
24611
|
-
* The reel on the cameras page and the Events gallery both ride a cursor, so a
|
|
24612
|
-
* summaries feed that could only answer "the last N for these cameras"
|
|
24613
|
-
* (`listSummaries`) would make groups available in the timeline and nowhere
|
|
24614
|
-
* else. Two feeds with different ordering contracts would be two ideas of what
|
|
24615
|
-
* "newest" means, on one screen.
|
|
24616
|
-
*/
|
|
24617
|
-
var RecentSummariesQueryInput = object({
|
|
24618
|
-
/** Devices to merge. An empty array yields an empty page. */
|
|
24619
|
-
deviceIds: array(number()),
|
|
24620
|
-
/** Window lower bound on `lastActiveAt` (inclusive). */
|
|
24621
|
-
since: number().optional(),
|
|
24622
|
-
/** Window upper bound on `lastActiveAt` (inclusive). */
|
|
24623
|
-
until: number().optional(),
|
|
24624
|
-
limit: number().int().min(1).max(500).default(100),
|
|
24625
|
-
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
24626
|
-
cursor: string().optional(),
|
|
24627
|
-
/**
|
|
24628
|
-
* Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
|
|
24629
|
-
* deliberately the same name: the events filter tree emits one list of ticked
|
|
24630
|
-
* taxonomy nodes, and a summaries feed that called it something else would
|
|
24631
|
-
* make the operator's one filter component produce two shapes.
|
|
24632
|
-
*
|
|
24633
|
-
* A question about the MEMBERS: a group matches when ANY of them does. "Show
|
|
24634
|
-
* me the arrivals with a dog" has to return the group of four people who had
|
|
24635
|
-
* one with them; a filter on the group's own fields could only ever answer
|
|
24636
|
-
* about its primary.
|
|
24637
|
-
*
|
|
24638
|
-
* Matched against all THREE tiers of a member — the class (`animal`), the
|
|
24639
|
-
* sub-class (`dog`) and the instance (a name, a plate) — because which tier a
|
|
24640
|
-
* ticked node lives on is the taxonomy's business, not the caller's. `dog` is
|
|
24641
|
-
* an event kind in the tree and a tier-1 label on an `animal` track; a filter
|
|
24642
|
-
* that read only the class would answer "animal" and never "dog".
|
|
24643
|
-
*
|
|
24644
|
-
* ABSENT or EMPTY means no filter — absent is not a selection of none.
|
|
24645
|
-
*/
|
|
24646
|
-
classes: array(string().min(1).max(60)).max(40).optional()
|
|
24647
|
-
});
|
|
24648
|
-
var RecentSummariesPageSchema = object({
|
|
24649
|
-
/** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
|
|
24650
|
-
* {@link listSummaries} — one list shape, so a card renders the same
|
|
24651
|
-
* whichever feed drew it. */
|
|
24652
|
-
summaries: array(SummaryListItemSchema).readonly(),
|
|
24653
|
-
nextCursor: string().nullable()
|
|
24654
|
-
});
|
|
24655
24745
|
var RecentTracksPageSchema = object({
|
|
24656
24746
|
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
24657
24747
|
tracks: array(TrackSchema).readonly(),
|
|
@@ -25189,15 +25279,6 @@ var pipelineAnalyticsCapability = {
|
|
|
25189
25279
|
* are not included (same contract as `listTracks`).
|
|
25190
25280
|
*/
|
|
25191
25281
|
listRecentTracks: method(RecentTracksQueryInput, RecentTracksPageSchema),
|
|
25192
|
-
/** Newest first by `openedAt`, for a camera set, inside an optional window. */
|
|
25193
|
-
listSummaries: method(SummariesQueryInput, SummariesPageSchema),
|
|
25194
|
-
/**
|
|
25195
|
-
* The PAGED feed — the reel and the Events gallery. Same cursor contract as
|
|
25196
|
-
* {@link listRecentTracks}, so one screen cannot hold two ideas of newest.
|
|
25197
|
-
*/
|
|
25198
|
-
listRecentSummaries: method(RecentSummariesQueryInput, RecentSummariesPageSchema),
|
|
25199
|
-
/** One summary with its member track ids; `null` for an id nobody wrote. */
|
|
25200
|
-
getSummary: method(object({ id: string() }), SummaryDetailSchema.nullable()),
|
|
25201
25282
|
clearTracks: method(object({ deviceId: number() }), _void(), {
|
|
25202
25283
|
kind: "mutation",
|
|
25203
25284
|
auth: "admin"
|
|
@@ -27224,6 +27305,23 @@ var MotionSourceEnum = _enum([
|
|
|
27224
27305
|
*/
|
|
27225
27306
|
var MotionSourcesSchema = array(MotionSourceEnum);
|
|
27226
27307
|
/**
|
|
27308
|
+
* The operator-facing name of each MOTION source (D672: `onboard` = the
|
|
27309
|
+
* camera's sensors — its own motion plus any sensor attached to it). The wire
|
|
27310
|
+
* value stays `onboard`; only the label changed. `detectionSources: 'onboard'`
|
|
27311
|
+
* ("Camera onboard AI") and the notification source filter keep their labels.
|
|
27312
|
+
*/
|
|
27313
|
+
var MOTION_SOURCE_LABELS = {
|
|
27314
|
+
analyzer: "Frame-diff Analyzer (motion addon)",
|
|
27315
|
+
onboard: "Camera sensors",
|
|
27316
|
+
"device-activity": "Device activity (the device says it is working)"
|
|
27317
|
+
};
|
|
27318
|
+
/** The order the motion-source picker offers them in (not the enum's order). */
|
|
27319
|
+
var MOTION_SOURCE_PICKER_ORDER = [
|
|
27320
|
+
"analyzer",
|
|
27321
|
+
"onboard",
|
|
27322
|
+
"device-activity"
|
|
27323
|
+
];
|
|
27324
|
+
/**
|
|
27227
27325
|
* Which root detector a camera runs — EXACTLY ONE.
|
|
27228
27326
|
*
|
|
27229
27327
|
* Deliberately the SAME vocabulary post-analysis already tags every detection
|
|
@@ -27570,7 +27668,14 @@ var RunnerCameraConfigSchema = object({
|
|
|
27570
27668
|
*/
|
|
27571
27669
|
inferenceDevices: array(RunnerInferenceDeviceSchema).readonly().optional()
|
|
27572
27670
|
});
|
|
27573
|
-
|
|
27671
|
+
MOTION_SOURCE_PICKER_ORDER.map((value) => value === "onboard" ? {
|
|
27672
|
+
value,
|
|
27673
|
+
label: MOTION_SOURCE_LABELS[value],
|
|
27674
|
+
description: "The camera's own motion, plus any sensor attached to it"
|
|
27675
|
+
} : {
|
|
27676
|
+
value,
|
|
27677
|
+
label: MOTION_SOURCE_LABELS[value]
|
|
27678
|
+
}), motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, maxSessionHoldMsField.min, maxSessionHoldMsField.max, maxSessionHoldMsField.step, maxSessionHoldMsField.default, audioMotionWindowMsField.min, audioMotionWindowMsField.max, audioMotionWindowMsField.step, audioMotionWindowMsField.default, preRollInferenceFramesField.min, preRollInferenceFramesField.max, preRollInferenceFramesField.step, preRollInferenceFramesField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
|
|
27574
27679
|
/**
|
|
27575
27680
|
* Runtime load summary returned by `getLocalLoad`. Used by the orchestrator's
|
|
27576
27681
|
* load-balancing levels (L2 capacity-based, L3 hardware-aware) to decide
|
|
@@ -28336,6 +28441,11 @@ var CameraStatusSchema = object({
|
|
|
28336
28441
|
*/
|
|
28337
28442
|
switchedOff: array(CameraSwitchIdSchema).readonly(),
|
|
28338
28443
|
/**
|
|
28444
|
+
* The camera's attached sensors (D672). Optional only for a status composed
|
|
28445
|
+
* by an orchestrator older than D672; this orchestrator always sets it.
|
|
28446
|
+
*/
|
|
28447
|
+
cameraSensors: CameraSensorsStatusSchema.optional(),
|
|
28448
|
+
/**
|
|
28339
28449
|
* Stages of the bounded fan-out that were CUT SHORT — a timeout or a
|
|
28340
28450
|
* rejection — and whose block is therefore `null` because we could not
|
|
28341
28451
|
* READ it, not because there is nothing there.
|
|
@@ -31807,44 +31917,6 @@ var videoclipsCapability = {
|
|
|
31807
31917
|
}
|
|
31808
31918
|
};
|
|
31809
31919
|
/**
|
|
31810
|
-
* LA tabella "quale booleano di questo tipo di device conta come ALTO", e il
|
|
31811
|
-
* valutatore puro del suo FRONTE.
|
|
31812
|
-
*
|
|
31813
|
-
* Viveva dentro il builtin virtual-doorbell
|
|
31814
|
-
* (`@camstack/system` — `builtins/doorbell/trigger-engine.ts`) e i suoi
|
|
31815
|
-
* predicati erano privati al modulo. Il recorder ne ha bisogno per il trigger
|
|
31816
|
-
* `RecordingTriggers.sensorDeviceIds`: copiarla avrebbe creato la SECONDA
|
|
31817
|
-
* tabella, che diverge alla prima cap aggiunta e il cui sintomo — "il sensore
|
|
31818
|
-
* fa suonare il campanello ma non registra" — è esattamente D62. Quindi si
|
|
31819
|
-
* SPOSTA qui e il doorbell la ri-esporta.
|
|
31820
|
-
*
|
|
31821
|
-
* ⚠ NON è `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), e le
|
|
31822
|
-
* due non vanno unificate: quella risponde a "qual è la PAROLA di stato per una
|
|
31823
|
-
* regola" (e include `presence`, `cover`, `alarm-panel`), questa a "qual è il
|
|
31824
|
-
* booleano il cui FRONTE conta". Vocabolari deliberatamente diversi.
|
|
31825
|
-
*/
|
|
31826
|
-
/**
|
|
31827
|
-
* Known binary / switch source caps → the boolean slice field whose
|
|
31828
|
-
* false→true rise counts as ACTIVE. Every entry is "fire on active".
|
|
31829
|
-
* Sensors whose "active" reading is not a plain boolean (presence's string
|
|
31830
|
-
* state, connectivity's connected flag) are deliberately excluded — a
|
|
31831
|
-
* reconnect is not a doorbell press, and it is not a recording either.
|
|
31832
|
-
*/
|
|
31833
|
-
var SOURCE_CAP_ACTIVE_FIELD = {
|
|
31834
|
-
contact: "entryOpen",
|
|
31835
|
-
binary: "on",
|
|
31836
|
-
switch: "on",
|
|
31837
|
-
motion: "detected",
|
|
31838
|
-
flood: "flooded",
|
|
31839
|
-
gas: "detected",
|
|
31840
|
-
smoke: "detected",
|
|
31841
|
-
"carbon-monoxide": "detected",
|
|
31842
|
-
vibration: "detected",
|
|
31843
|
-
tamper: "tampered"
|
|
31844
|
-
};
|
|
31845
|
-
/** Cap names whose presence in a device's bindings qualify it as a source. */
|
|
31846
|
-
var SOURCE_CAPS = Object.keys(SOURCE_CAP_ACTIVE_FIELD);
|
|
31847
|
-
/**
|
|
31848
31920
|
* Doorbell button cap. Two kinds of providers coexist behind this cap
|
|
31849
31921
|
* name (same pattern as `snapshot`):
|
|
31850
31922
|
*
|
|
@@ -31917,7 +31989,13 @@ var doorbellCapability = {
|
|
|
31917
31989
|
* push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no
|
|
31918
31990
|
* release/duration — it's a pulse.
|
|
31919
31991
|
*/
|
|
31920
|
-
onPressed: {
|
|
31992
|
+
onPressed: {
|
|
31993
|
+
data: DoorbellPressEventSchema,
|
|
31994
|
+
fromState: {
|
|
31995
|
+
field: "lastPressedAt",
|
|
31996
|
+
on: "advance"
|
|
31997
|
+
}
|
|
31998
|
+
} },
|
|
31921
31999
|
status: {
|
|
31922
32000
|
schema: DoorbellStatusSchema,
|
|
31923
32001
|
kind: "push"
|
|
@@ -37410,7 +37488,9 @@ var MotionOnMotionChangedDataSchema = object({
|
|
|
37410
37488
|
detected: boolean(),
|
|
37411
37489
|
timestamp: number(),
|
|
37412
37490
|
source: MotionSourceEnum,
|
|
37413
|
-
regions: array(MotionRegionSchema).readonly().optional()
|
|
37491
|
+
regions: array(MotionRegionSchema).readonly().optional(),
|
|
37492
|
+
/** Who started it (D672). Absent = the camera itself. Only `onboard` carries `sensor`. */
|
|
37493
|
+
triggeredBy: MotionTriggeredBySchema.optional()
|
|
37414
37494
|
});
|
|
37415
37495
|
var motionCapability = {
|
|
37416
37496
|
name: "motion",
|
|
@@ -40772,12 +40852,21 @@ var RecordingStorageUsageSchema = object({
|
|
|
40772
40852
|
*/
|
|
40773
40853
|
devicesRead: _enum(["archive", "unavailable"]).optional(),
|
|
40774
40854
|
/**
|
|
40855
|
+
* Is the `archive` answer WHOLE (D674): the hour ledger loaded without
|
|
40856
|
+
* hitting its row cap, and at least one location resolved? Only then may a
|
|
40857
|
+
* camera ABSENT from `devices[]` be read as "no footage" — and only then is a
|
|
40858
|
+
* row's `oldestMs` the archive's oldest rather than the oldest of a fraction.
|
|
40859
|
+
* OPTIONAL: a recorder predating D674 omits it, and a consumer must read the
|
|
40860
|
+
* absence as `false`. A retention floor is a delete; it never guesses.
|
|
40861
|
+
*/
|
|
40862
|
+
complete: boolean().optional(),
|
|
40863
|
+
/**
|
|
40775
40864
|
* Per-physical-volume capacity. OPTIONAL, and consumers must render the rest
|
|
40776
|
-
* of the payload without it:
|
|
40777
|
-
*
|
|
40778
|
-
*
|
|
40779
|
-
*
|
|
40780
|
-
*
|
|
40865
|
+
* of the payload without it: a recorder that could not build it omits it. A
|
|
40866
|
+
* UI that dereferences it unconditionally crashes the whole Storage page over
|
|
40867
|
+
* a missing disk bar. (The hub's cap routers pass output through unvalidated
|
|
40868
|
+
* since 2026-07-11 — `cap-router-builder.ts` — so a newer recorder's fields
|
|
40869
|
+
* are not stripped by an older hub.)
|
|
40781
40870
|
*/
|
|
40782
40871
|
locations: array(RecordingLocationUsageSchema).optional()
|
|
40783
40872
|
});
|
|
@@ -44701,7 +44790,12 @@ Object.freeze({
|
|
|
44701
44790
|
number: {
|
|
44702
44791
|
kind: "fixed",
|
|
44703
44792
|
result: ["number", "null"]
|
|
44704
|
-
}
|
|
44793
|
+
},
|
|
44794
|
+
rose: {
|
|
44795
|
+
kind: "fixed",
|
|
44796
|
+
result: ["number", "null"]
|
|
44797
|
+
},
|
|
44798
|
+
count: NUMBER
|
|
44705
44799
|
});
|
|
44706
44800
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
44707
44801
|
/**
|
|
@@ -48042,6 +48136,12 @@ Object.freeze({
|
|
|
48042
48136
|
addonId: null,
|
|
48043
48137
|
access: "view"
|
|
48044
48138
|
},
|
|
48139
|
+
"deviceManager.getWrapperActivation": {
|
|
48140
|
+
capName: "device-manager",
|
|
48141
|
+
capScope: "system",
|
|
48142
|
+
addonId: null,
|
|
48143
|
+
access: "view"
|
|
48144
|
+
},
|
|
48045
48145
|
"deviceManager.listAll": {
|
|
48046
48146
|
capName: "device-manager",
|
|
48047
48147
|
capScope: "system",
|
|
@@ -50316,12 +50416,6 @@ Object.freeze({
|
|
|
50316
50416
|
addonId: null,
|
|
50317
50417
|
access: "view"
|
|
50318
50418
|
},
|
|
50319
|
-
"pipelineAnalytics.getSummary": {
|
|
50320
|
-
capName: "pipeline-analytics",
|
|
50321
|
-
capScope: "device",
|
|
50322
|
-
addonId: null,
|
|
50323
|
-
access: "view"
|
|
50324
|
-
},
|
|
50325
50419
|
"pipelineAnalytics.getTrack": {
|
|
50326
50420
|
capName: "pipeline-analytics",
|
|
50327
50421
|
capScope: "device",
|
|
@@ -50382,12 +50476,6 @@ Object.freeze({
|
|
|
50382
50476
|
addonId: null,
|
|
50383
50477
|
access: "view"
|
|
50384
50478
|
},
|
|
50385
|
-
"pipelineAnalytics.listRecentSummaries": {
|
|
50386
|
-
capName: "pipeline-analytics",
|
|
50387
|
-
capScope: "device",
|
|
50388
|
-
addonId: null,
|
|
50389
|
-
access: "view"
|
|
50390
|
-
},
|
|
50391
50479
|
"pipelineAnalytics.listRecentTracks": {
|
|
50392
50480
|
capName: "pipeline-analytics",
|
|
50393
50481
|
capScope: "device",
|
|
@@ -50418,12 +50506,6 @@ Object.freeze({
|
|
|
50418
50506
|
addonId: null,
|
|
50419
50507
|
access: "view"
|
|
50420
50508
|
},
|
|
50421
|
-
"pipelineAnalytics.listSummaries": {
|
|
50422
|
-
capName: "pipeline-analytics",
|
|
50423
|
-
capScope: "device",
|
|
50424
|
-
addonId: null,
|
|
50425
|
-
access: "view"
|
|
50426
|
-
},
|
|
50427
50509
|
"pipelineAnalytics.listTrackMedia": {
|
|
50428
50510
|
capName: "pipeline-analytics",
|
|
50429
50511
|
capScope: "device",
|
|
@@ -53851,6 +53933,11 @@ Object.freeze({
|
|
|
53851
53933
|
form: "single",
|
|
53852
53934
|
optional: false
|
|
53853
53935
|
}],
|
|
53936
|
+
"deviceManager.getWrapperActivation": [{
|
|
53937
|
+
name: "deviceId",
|
|
53938
|
+
form: "single",
|
|
53939
|
+
optional: false
|
|
53940
|
+
}],
|
|
53854
53941
|
"deviceManager.listAll": [{
|
|
53855
53942
|
name: "deviceIds",
|
|
53856
53943
|
form: "array",
|
|
@@ -54588,11 +54675,6 @@ Object.freeze({
|
|
|
54588
54675
|
form: "single",
|
|
54589
54676
|
optional: true
|
|
54590
54677
|
}],
|
|
54591
|
-
"pipelineAnalytics.listRecentSummaries": [{
|
|
54592
|
-
name: "deviceIds",
|
|
54593
|
-
form: "array",
|
|
54594
|
-
optional: false
|
|
54595
|
-
}],
|
|
54596
54678
|
"pipelineAnalytics.listRecentTracks": [{
|
|
54597
54679
|
name: "deviceIds",
|
|
54598
54680
|
form: "array",
|
|
@@ -54603,11 +54685,6 @@ Object.freeze({
|
|
|
54603
54685
|
form: "array",
|
|
54604
54686
|
optional: true
|
|
54605
54687
|
}],
|
|
54606
|
-
"pipelineAnalytics.listSummaries": [{
|
|
54607
|
-
name: "deviceIds",
|
|
54608
|
-
form: "array",
|
|
54609
|
-
optional: false
|
|
54610
|
-
}],
|
|
54611
54688
|
"pipelineAnalytics.listTrackMedia": [{
|
|
54612
54689
|
name: "deviceId",
|
|
54613
54690
|
form: "single",
|