@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.js
CHANGED
|
@@ -5373,7 +5373,7 @@ var ZodIssueCode = {
|
|
|
5373
5373
|
var ZodFirstPartyTypeKind;
|
|
5374
5374
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5375
5375
|
//#endregion
|
|
5376
|
-
//#region ../types/dist/sleep-
|
|
5376
|
+
//#region ../types/dist/sleep-C-v96WpE.mjs
|
|
5377
5377
|
/**
|
|
5378
5378
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5379
5379
|
* window to float samples (D455).
|
|
@@ -6929,6 +6929,10 @@ var ProfileRtspEntrySchema = object({
|
|
|
6929
6929
|
codec: string().optional(),
|
|
6930
6930
|
resolution: CamStreamResolutionSchema.optional()
|
|
6931
6931
|
});
|
|
6932
|
+
object({
|
|
6933
|
+
field: string().min(1),
|
|
6934
|
+
on: literal("advance")
|
|
6935
|
+
});
|
|
6932
6936
|
/**
|
|
6933
6937
|
* Output schema shared by the contribution + live methods.
|
|
6934
6938
|
*
|
|
@@ -7510,7 +7514,45 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
7510
7514
|
return DeviceRole;
|
|
7511
7515
|
}({});
|
|
7512
7516
|
//#endregion
|
|
7513
|
-
//#region ../types/dist/composition-
|
|
7517
|
+
//#region ../types/dist/composition-BK-GTFYb.mjs
|
|
7518
|
+
/**
|
|
7519
|
+
* LA tabella "quale booleano di questo tipo di device conta come ALTO", e il
|
|
7520
|
+
* valutatore puro del suo FRONTE.
|
|
7521
|
+
*
|
|
7522
|
+
* Viveva dentro il builtin virtual-doorbell
|
|
7523
|
+
* (`@camstack/system` — `builtins/doorbell/trigger-engine.ts`) e i suoi
|
|
7524
|
+
* predicati erano privati al modulo. Il recorder ne ha bisogno per il trigger
|
|
7525
|
+
* `RecordingTriggers.sensorDeviceIds`: copiarla avrebbe creato la SECONDA
|
|
7526
|
+
* tabella, che diverge alla prima cap aggiunta e il cui sintomo — "il sensore
|
|
7527
|
+
* fa suonare il campanello ma non registra" — è esattamente D62. Quindi si
|
|
7528
|
+
* SPOSTA qui e il doorbell la ri-esporta.
|
|
7529
|
+
*
|
|
7530
|
+
* ⚠ NON è `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), e le
|
|
7531
|
+
* due non vanno unificate: quella risponde a "qual è la PAROLA di stato per una
|
|
7532
|
+
* regola" (e include `presence`, `cover`, `alarm-panel`), questa a "qual è il
|
|
7533
|
+
* booleano il cui FRONTE conta". Vocabolari deliberatamente diversi.
|
|
7534
|
+
*/
|
|
7535
|
+
/**
|
|
7536
|
+
* Known binary / switch source caps → the boolean slice field whose
|
|
7537
|
+
* false→true rise counts as ACTIVE. Every entry is "fire on active".
|
|
7538
|
+
* Sensors whose "active" reading is not a plain boolean (presence's string
|
|
7539
|
+
* state, connectivity's connected flag) are deliberately excluded — a
|
|
7540
|
+
* reconnect is not a doorbell press, and it is not a recording either.
|
|
7541
|
+
*/
|
|
7542
|
+
var SOURCE_CAP_ACTIVE_FIELD = {
|
|
7543
|
+
contact: "entryOpen",
|
|
7544
|
+
binary: "on",
|
|
7545
|
+
switch: "on",
|
|
7546
|
+
motion: "detected",
|
|
7547
|
+
flood: "flooded",
|
|
7548
|
+
gas: "detected",
|
|
7549
|
+
smoke: "detected",
|
|
7550
|
+
"carbon-monoxide": "detected",
|
|
7551
|
+
vibration: "detected",
|
|
7552
|
+
tamper: "tampered"
|
|
7553
|
+
};
|
|
7554
|
+
/** Cap names whose presence in a device's bindings qualify it as a source. */
|
|
7555
|
+
var SOURCE_CAPS = Object.keys(SOURCE_CAP_ACTIVE_FIELD);
|
|
7514
7556
|
/**
|
|
7515
7557
|
* Error types for the safe expression engine. Two distinct classes so callers
|
|
7516
7558
|
* can tell a compile-time (grammar) failure from a runtime (evaluation)
|
|
@@ -7708,6 +7750,20 @@ var table = {
|
|
|
7708
7750
|
const present = args.flatMap((a, i) => a === null ? [] : [asFiniteNumber(a, "latest", i)]);
|
|
7709
7751
|
return present.length === 0 ? null : finiteResult(Math.max(...present), "latest");
|
|
7710
7752
|
}
|
|
7753
|
+
},
|
|
7754
|
+
rose: {
|
|
7755
|
+
minArgs: 2,
|
|
7756
|
+
maxArgs: 3,
|
|
7757
|
+
apply: () => {
|
|
7758
|
+
throw new ExpressionEvalError("rose: stateful evaluation context is required");
|
|
7759
|
+
}
|
|
7760
|
+
},
|
|
7761
|
+
count: {
|
|
7762
|
+
minArgs: 1,
|
|
7763
|
+
maxArgs: 1,
|
|
7764
|
+
apply: () => {
|
|
7765
|
+
throw new ExpressionEvalError("count: stateful evaluation context is required");
|
|
7766
|
+
}
|
|
7711
7767
|
}
|
|
7712
7768
|
};
|
|
7713
7769
|
Object.freeze(Object.assign(Object.create(null), table));
|
|
@@ -8222,6 +8278,7 @@ var CompositionItemEntrySchema = object({
|
|
|
8222
8278
|
var CompositionFeatureSchema = discriminatedUnion("kind", [object({
|
|
8223
8279
|
kind: literal("fields"),
|
|
8224
8280
|
cap: string().min(1),
|
|
8281
|
+
enabled: boolean().optional(),
|
|
8225
8282
|
fields: record(string().min(1), CompositionFieldSourceSchema).refine((fields) => Object.keys(fields).length <= 32, { message: `at most 32 fields per capability` }),
|
|
8226
8283
|
/**
|
|
8227
8284
|
* Items of the cap's item array, keyed by item key (D663). Naming `items`
|
|
@@ -8233,6 +8290,7 @@ var CompositionFeatureSchema = discriminatedUnion("kind", [object({
|
|
|
8233
8290
|
}), object({
|
|
8234
8291
|
kind: literal("passthrough"),
|
|
8235
8292
|
cap: string().min(1),
|
|
8293
|
+
enabled: boolean().optional(),
|
|
8236
8294
|
source: CompositionSourceRefSchema
|
|
8237
8295
|
})]);
|
|
8238
8296
|
var CompositionSchema = object({
|
|
@@ -8262,7 +8320,6 @@ var CompositionSchema = object({
|
|
|
8262
8320
|
});
|
|
8263
8321
|
new Set([
|
|
8264
8322
|
"track",
|
|
8265
|
-
"summary",
|
|
8266
8323
|
"face",
|
|
8267
8324
|
"identity",
|
|
8268
8325
|
"plate",
|
|
@@ -13642,6 +13699,15 @@ var cameraStreamsCapability = {
|
|
|
13642
13699
|
*/
|
|
13643
13700
|
durability: "session"
|
|
13644
13701
|
};
|
|
13702
|
+
EventCategory.DoorbellOnPressed;
|
|
13703
|
+
var CompositionEventPlanSchema = object({
|
|
13704
|
+
featureIndex: number().int().nonnegative(),
|
|
13705
|
+
cap: string(),
|
|
13706
|
+
eventName: string(),
|
|
13707
|
+
category: _enum(EventCategory),
|
|
13708
|
+
stateField: string(),
|
|
13709
|
+
fieldKey: string()
|
|
13710
|
+
});
|
|
13645
13711
|
/** One refusal, named (D391). `path` points into the composition, e.g. `features[0].fields.celsius`. */
|
|
13646
13712
|
var CompositionProblemSchema = object({
|
|
13647
13713
|
code: _enum([
|
|
@@ -13691,12 +13757,14 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
13691
13757
|
]);
|
|
13692
13758
|
/**
|
|
13693
13759
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
13694
|
-
* field of its cap changes value · `constant` reads nothing, computed once
|
|
13760
|
+
* field of its cap changes value · `constant` reads nothing, computed once ·
|
|
13761
|
+
* `accumulator` advances from the target's seed/current output.
|
|
13695
13762
|
*/
|
|
13696
13763
|
var CompositionFieldRoleSchema = _enum([
|
|
13697
13764
|
"derived",
|
|
13698
13765
|
"clock",
|
|
13699
|
-
"constant"
|
|
13766
|
+
"constant",
|
|
13767
|
+
"accumulator"
|
|
13700
13768
|
]);
|
|
13701
13769
|
/** The item a planned field belongs to; its `path` is then the dotted path INSIDE the item. */
|
|
13702
13770
|
var CompositionFieldItemSchema = object({
|
|
@@ -13732,6 +13800,7 @@ var CompositionFeatureModeSchema = _enum([
|
|
|
13732
13800
|
"replace"
|
|
13733
13801
|
]);
|
|
13734
13802
|
var CompositionFeaturePlanSchema = object({
|
|
13803
|
+
/** Index in the stored feature array; disabled features are omitted rather than re-indexed. */
|
|
13735
13804
|
featureIndex: number().int().nonnegative(),
|
|
13736
13805
|
cap: string(),
|
|
13737
13806
|
mode: CompositionFeatureModeSchema
|
|
@@ -13740,7 +13809,8 @@ var CompositionValidationSchema = object({
|
|
|
13740
13809
|
ok: boolean(),
|
|
13741
13810
|
problems: array(CompositionProblemSchema),
|
|
13742
13811
|
fields: array(CompositionFieldPlanSchema),
|
|
13743
|
-
features: array(CompositionFeaturePlanSchema)
|
|
13812
|
+
features: array(CompositionFeaturePlanSchema),
|
|
13813
|
+
events: array(CompositionEventPlanSchema)
|
|
13744
13814
|
});
|
|
13745
13815
|
/**
|
|
13746
13816
|
* Mirrors `CoreBlockStatus`, pinned by `core-blocks-source.spec.ts`. `degraded`:
|
|
@@ -15996,6 +16066,34 @@ var DeviceBindingsForDeviceSchema = object({
|
|
|
15996
16066
|
nativeAddonId: string()
|
|
15997
16067
|
}))
|
|
15998
16068
|
});
|
|
16069
|
+
/**
|
|
16070
|
+
* The STORED wrapper activation for one `(device, capability)` pair — the row
|
|
16071
|
+
* `setWrapperActive` writes, read back three-way (D675):
|
|
16072
|
+
*
|
|
16073
|
+
* - `value` — the store answered and holds an activation: the bound wrapper's
|
|
16074
|
+
* addon id, or `null`, the operator's explicit "off" marker (D62);
|
|
16075
|
+
* - `missing` — the store answered, its activation map exists, and it holds
|
|
16076
|
+
* nothing for this pair: the operator never activated or deactivated a
|
|
16077
|
+
* wrapper here;
|
|
16078
|
+
* - `failed` — the store could not be read, holds no activation map at all
|
|
16079
|
+
* (an empty or unready snapshot, D44), or holds something that is not an
|
|
16080
|
+
* activation. It carries NO information: a consumer must never read it as
|
|
16081
|
+
* `missing` (D315, D393).
|
|
16082
|
+
*
|
|
16083
|
+
* This is the persisted INPUT, not the derived `getBindings` view — no registry
|
|
16084
|
+
* resolution, no `defaultActive` auto-binding, no cluster native-cap folding.
|
|
16085
|
+
*/
|
|
16086
|
+
var WrapperActivationReadSchema = discriminatedUnion("kind", [
|
|
16087
|
+
object({
|
|
16088
|
+
kind: literal("value"),
|
|
16089
|
+
wrapperAddonId: string().nullable()
|
|
16090
|
+
}),
|
|
16091
|
+
object({ kind: literal("missing") }),
|
|
16092
|
+
object({
|
|
16093
|
+
kind: literal("failed"),
|
|
16094
|
+
error: string()
|
|
16095
|
+
})
|
|
16096
|
+
]);
|
|
15999
16097
|
var SavedDeviceRowSchema = object({
|
|
16000
16098
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
16001
16099
|
id: number(),
|
|
@@ -16794,6 +16892,21 @@ var deviceManagerCapability = {
|
|
|
16794
16892
|
auth: "admin"
|
|
16795
16893
|
}),
|
|
16796
16894
|
/**
|
|
16895
|
+
* The STORED wrapper activation for one `(device, capName)` pair, three-way
|
|
16896
|
+
* (`value` / `missing` / `failed`, see {@link WrapperActivationReadSchema}).
|
|
16897
|
+
*
|
|
16898
|
+
* The narrow read of the durable authority behind `getBindings`: a
|
|
16899
|
+
* consumer that must know what the operator PERSISTED (virtual-doorbell,
|
|
16900
|
+
* before it drops a press) asks this instead of pulling device-manager's
|
|
16901
|
+
* whole addon store through `addonSettingsRaw.getGlobal` — which answered
|
|
16902
|
+
* `{}` on every isolated-engine hub and so never worked (D675). It reads
|
|
16903
|
+
* ONE row (the activation map, ~1.6 KB), never the ~625 KB store.
|
|
16904
|
+
*/
|
|
16905
|
+
getWrapperActivation: method(object({
|
|
16906
|
+
deviceId: number(),
|
|
16907
|
+
capName: string().min(1)
|
|
16908
|
+
}), WrapperActivationReadSchema),
|
|
16909
|
+
/**
|
|
16797
16910
|
* Return the addon ids that declared a wrapper provider for `capName`.
|
|
16798
16911
|
* Backs the device-bindings UI's wrapper-picker dropdown. Entries are
|
|
16799
16912
|
* sourced from `CapabilityRegistry.wrapperProviders`, populated when
|
|
@@ -23290,6 +23403,102 @@ var oauthIntegrationCapability = {
|
|
|
23290
23403
|
getDescriptor: method(_void(), OauthIntegrationDescriptorSchema, { auth: "admin" }) }
|
|
23291
23404
|
};
|
|
23292
23405
|
/**
|
|
23406
|
+
* What started a camera's onboard motion (D672). `camera` is the camera's own
|
|
23407
|
+
* firmware; `sensor` is a device the operator ATTACHED to it. Absent on the
|
|
23408
|
+
* wire means the camera: only the camera-sensors bridge ever says `sensor`.
|
|
23409
|
+
*/
|
|
23410
|
+
var MotionTriggeredBySchema = discriminatedUnion("kind", [object({ kind: literal("camera") }), object({
|
|
23411
|
+
kind: literal("sensor"),
|
|
23412
|
+
deviceId: number().int().positive()
|
|
23413
|
+
})]);
|
|
23414
|
+
Object.freeze({ kind: "camera" });
|
|
23415
|
+
var CameraSensorRefSchema = object({
|
|
23416
|
+
addonId: string().min(1),
|
|
23417
|
+
stableId: string().min(1)
|
|
23418
|
+
});
|
|
23419
|
+
function cameraSensorRefKey(ref) {
|
|
23420
|
+
return `${ref.addonId}/${ref.stableId}`;
|
|
23421
|
+
}
|
|
23422
|
+
/** CS-1 accepts exactly one mode; CS-2 (D673) widens it to confirm / replace. */
|
|
23423
|
+
var CameraSensorsModeSchema = _enum(["in-addition"]);
|
|
23424
|
+
object({
|
|
23425
|
+
mode: CameraSensorsModeSchema,
|
|
23426
|
+
sensors: array(CameraSensorRefSchema).min(1).max(8)
|
|
23427
|
+
}).superRefine((value, ctx) => {
|
|
23428
|
+
const seen = /* @__PURE__ */ new Set();
|
|
23429
|
+
value.sensors.forEach((ref, index) => {
|
|
23430
|
+
const key = cameraSensorRefKey(ref);
|
|
23431
|
+
if (seen.has(key)) ctx.addIssue({
|
|
23432
|
+
code: "custom",
|
|
23433
|
+
path: ["sensors", index],
|
|
23434
|
+
message: `duplicate camera sensor ${key}`
|
|
23435
|
+
});
|
|
23436
|
+
seen.add(key);
|
|
23437
|
+
});
|
|
23438
|
+
});
|
|
23439
|
+
var RefFields = {
|
|
23440
|
+
addonId: string(),
|
|
23441
|
+
stableId: string()
|
|
23442
|
+
};
|
|
23443
|
+
var CameraSensorAttachmentSchema = discriminatedUnion("state", [
|
|
23444
|
+
object({
|
|
23445
|
+
...RefFields,
|
|
23446
|
+
state: literal("ready"),
|
|
23447
|
+
deviceId: number(),
|
|
23448
|
+
name: string(),
|
|
23449
|
+
caps: array(string()).readonly()
|
|
23450
|
+
}),
|
|
23451
|
+
object({
|
|
23452
|
+
...RefFields,
|
|
23453
|
+
state: literal("offline"),
|
|
23454
|
+
deviceId: number(),
|
|
23455
|
+
name: string(),
|
|
23456
|
+
reason: _enum(["offline", "disabled"])
|
|
23457
|
+
}),
|
|
23458
|
+
object({
|
|
23459
|
+
...RefFields,
|
|
23460
|
+
state: literal("missing"),
|
|
23461
|
+
reason: string()
|
|
23462
|
+
}),
|
|
23463
|
+
object({
|
|
23464
|
+
...RefFields,
|
|
23465
|
+
state: literal("unsupported"),
|
|
23466
|
+
deviceId: number(),
|
|
23467
|
+
name: string(),
|
|
23468
|
+
reason: string()
|
|
23469
|
+
}),
|
|
23470
|
+
object({
|
|
23471
|
+
...RefFields,
|
|
23472
|
+
state: literal("unreadable"),
|
|
23473
|
+
reason: string()
|
|
23474
|
+
})
|
|
23475
|
+
]);
|
|
23476
|
+
/**
|
|
23477
|
+
* Why a configured camera forwards NOTHING from its sensors, however ready they
|
|
23478
|
+
* are (D672): it does not list `onboard` in `motionSources` (attaching a sensor
|
|
23479
|
+
* does not add it), or it has no active detection config at all (the bridge
|
|
23480
|
+
* reads the active config). Absent = forwarded, or an older node that does not
|
|
23481
|
+
* say.
|
|
23482
|
+
*/
|
|
23483
|
+
var CameraSensorsNotForwardedSchema = _enum(["onboard-not-listed", "no-active-detection"]);
|
|
23484
|
+
var CameraSensorsStatusSchema = discriminatedUnion("state", [
|
|
23485
|
+
object({ state: literal("not-configured") }),
|
|
23486
|
+
object({
|
|
23487
|
+
state: literal("unreadable"),
|
|
23488
|
+
reason: string()
|
|
23489
|
+
}),
|
|
23490
|
+
object({
|
|
23491
|
+
state: literal("configured"),
|
|
23492
|
+
mode: CameraSensorsModeSchema,
|
|
23493
|
+
sensors: array(CameraSensorAttachmentSchema).readonly(),
|
|
23494
|
+
notForwarded: CameraSensorsNotForwardedSchema.optional()
|
|
23495
|
+
})
|
|
23496
|
+
]);
|
|
23497
|
+
Object.freeze({
|
|
23498
|
+
state: "unreadable",
|
|
23499
|
+
reason: "camera sensor mappings not loaded"
|
|
23500
|
+
});
|
|
23501
|
+
/**
|
|
23293
23502
|
* A model choice has a SCOPE, and a scope change has a workflow.
|
|
23294
23503
|
*
|
|
23295
23504
|
* ## The two scopes
|
|
@@ -24038,6 +24247,12 @@ var MotionEventSchema = object({
|
|
|
24038
24247
|
/** Populated by B5 (recording playback URL for this event). */
|
|
24039
24248
|
mediaUrl: string().optional(),
|
|
24040
24249
|
/**
|
|
24250
|
+
* The FIRST trigger of an `onboard` episode, written once at open (D672).
|
|
24251
|
+
* Absent = not recorded (a row written before D672, or an analyzer /
|
|
24252
|
+
* device-activity episode) — never read as "the camera" (D393).
|
|
24253
|
+
*/
|
|
24254
|
+
triggeredBy: MotionTriggeredBySchema.optional(),
|
|
24255
|
+
/**
|
|
24041
24256
|
* One row per motion EPISODE, not one per push (D475). `null` while the
|
|
24042
24257
|
* episode is still open — a further rising edge extends it in place rather
|
|
24043
24258
|
* than inserting a new row. Set once, at close, to `lastOnAt - startedAt`
|
|
@@ -24531,131 +24746,6 @@ var RecentTracksQueryInput = object({
|
|
|
24531
24746
|
/** See {@link ExcludeSourcesDoc}. */
|
|
24532
24747
|
excludeSources: array(TrackSourceSchema).optional()
|
|
24533
24748
|
});
|
|
24534
|
-
/**
|
|
24535
|
-
* A Summary (D359): the per-camera session envelope that references tracks.
|
|
24536
|
-
* `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
|
|
24537
|
-
* 'summary'`, served by the event-media plane at `/m/<id>`), null until the
|
|
24538
|
-
* first frame with a member visible has been materialised (D482 — it was the
|
|
24539
|
-
* row's composite key, which embedded the owner and could name another table's
|
|
24540
|
-
* row once event ids became per-table rowids).
|
|
24541
|
-
*/
|
|
24542
|
-
var SummarySchema = object({
|
|
24543
|
-
id: string(),
|
|
24544
|
-
deviceId: number(),
|
|
24545
|
-
openedAt: number(),
|
|
24546
|
-
lastActiveAt: number(),
|
|
24547
|
-
sealedAt: number().nullable(),
|
|
24548
|
-
memberCount: number().int().nonnegative(),
|
|
24549
|
-
groupShotMediaId: number().int().nullable()
|
|
24550
|
-
});
|
|
24551
|
-
var SummariesQueryInput = object({
|
|
24552
|
-
deviceIds: array(number()).min(1),
|
|
24553
|
-
since: number().optional(),
|
|
24554
|
-
until: number().optional(),
|
|
24555
|
-
limit: number().int().min(1).max(200).default(50),
|
|
24556
|
-
/** The same member-wise filter {@link listRecentSummaries} takes — one
|
|
24557
|
-
* meaning of "dog" on every summary surface. */
|
|
24558
|
-
classes: array(string().min(1).max(60)).max(40).optional()
|
|
24559
|
-
});
|
|
24560
|
-
var SummaryDetailSchema = object({
|
|
24561
|
-
summary: SummarySchema,
|
|
24562
|
-
/** Members in absorption order, oldest join first. */
|
|
24563
|
-
members: array(object({
|
|
24564
|
-
trackId: string(),
|
|
24565
|
-
/**
|
|
24566
|
-
* The track's class at the time it JOINED, or `null` when it was unresolved
|
|
24567
|
-
* and the track no longer exists to fill it.
|
|
24568
|
-
*
|
|
24569
|
-
* The join, not the latest opinion: class voting can re-decide a track's
|
|
24570
|
-
* class afterwards, and a group's composition is the history of who came
|
|
24571
|
-
* together. A consumer counts these to badge a thumbnail — "two people and a
|
|
24572
|
-
* dog" — rather than being handed a second, denormalised tally that would
|
|
24573
|
-
* drift from the members it claims to describe.
|
|
24574
|
-
*/
|
|
24575
|
-
className: string().nullable(),
|
|
24576
|
-
/** `primary` is the one member that carries the group's identity. */
|
|
24577
|
-
role: _enum([
|
|
24578
|
-
"primary",
|
|
24579
|
-
"sibling",
|
|
24580
|
-
"child"
|
|
24581
|
-
]).nullable(),
|
|
24582
|
-
joinedAt: number(),
|
|
24583
|
-
/** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
|
|
24584
|
-
* at read time. Absent when nothing resolved, never an empty string. */
|
|
24585
|
-
label: string().optional(),
|
|
24586
|
-
/** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
|
|
24587
|
-
* recognised nobody, and absent for a member whose track has been pruned —
|
|
24588
|
-
* a thumbnail that names the wrong person is worse than one naming nobody. */
|
|
24589
|
-
subLabel: string().optional()
|
|
24590
|
-
})).readonly()
|
|
24591
|
-
});
|
|
24592
|
-
/**
|
|
24593
|
-
* What a LIST of groups carries: the envelope plus what it is MADE OF.
|
|
24594
|
-
*
|
|
24595
|
-
* Coarse on purpose — the operator's rule is "only the rough data on the list,
|
|
24596
|
-
* we extend when we notice we need more". Enough to draw the card ("two people
|
|
24597
|
-
* and a dog") and no more. The MEMBERS, their names and the per-member links
|
|
24598
|
-
* are on {@link getSummary}: shipping every member of every group so a client
|
|
24599
|
-
* can count them turns a page of two hundred groups into a thousand records to
|
|
24600
|
-
* draw two hundred badges.
|
|
24601
|
-
*/
|
|
24602
|
-
var SummaryListItemSchema = object({
|
|
24603
|
-
summary: SummarySchema,
|
|
24604
|
-
/** Class counts, most numerous first; `className: null` is a member whose
|
|
24605
|
-
* class never resolved, counted so the counts add up to `memberCount`. */
|
|
24606
|
-
classes: array(object({
|
|
24607
|
-
className: string().nullable(),
|
|
24608
|
-
count: number().int().positive()
|
|
24609
|
-
})).readonly()
|
|
24610
|
-
});
|
|
24611
|
-
var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
|
|
24612
|
-
/**
|
|
24613
|
-
* The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
|
|
24614
|
-
*
|
|
24615
|
-
* The reel on the cameras page and the Events gallery both ride a cursor, so a
|
|
24616
|
-
* summaries feed that could only answer "the last N for these cameras"
|
|
24617
|
-
* (`listSummaries`) would make groups available in the timeline and nowhere
|
|
24618
|
-
* else. Two feeds with different ordering contracts would be two ideas of what
|
|
24619
|
-
* "newest" means, on one screen.
|
|
24620
|
-
*/
|
|
24621
|
-
var RecentSummariesQueryInput = object({
|
|
24622
|
-
/** Devices to merge. An empty array yields an empty page. */
|
|
24623
|
-
deviceIds: array(number()),
|
|
24624
|
-
/** Window lower bound on `lastActiveAt` (inclusive). */
|
|
24625
|
-
since: number().optional(),
|
|
24626
|
-
/** Window upper bound on `lastActiveAt` (inclusive). */
|
|
24627
|
-
until: number().optional(),
|
|
24628
|
-
limit: number().int().min(1).max(500).default(100),
|
|
24629
|
-
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
24630
|
-
cursor: string().optional(),
|
|
24631
|
-
/**
|
|
24632
|
-
* Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
|
|
24633
|
-
* deliberately the same name: the events filter tree emits one list of ticked
|
|
24634
|
-
* taxonomy nodes, and a summaries feed that called it something else would
|
|
24635
|
-
* make the operator's one filter component produce two shapes.
|
|
24636
|
-
*
|
|
24637
|
-
* A question about the MEMBERS: a group matches when ANY of them does. "Show
|
|
24638
|
-
* me the arrivals with a dog" has to return the group of four people who had
|
|
24639
|
-
* one with them; a filter on the group's own fields could only ever answer
|
|
24640
|
-
* about its primary.
|
|
24641
|
-
*
|
|
24642
|
-
* Matched against all THREE tiers of a member — the class (`animal`), the
|
|
24643
|
-
* sub-class (`dog`) and the instance (a name, a plate) — because which tier a
|
|
24644
|
-
* ticked node lives on is the taxonomy's business, not the caller's. `dog` is
|
|
24645
|
-
* an event kind in the tree and a tier-1 label on an `animal` track; a filter
|
|
24646
|
-
* that read only the class would answer "animal" and never "dog".
|
|
24647
|
-
*
|
|
24648
|
-
* ABSENT or EMPTY means no filter — absent is not a selection of none.
|
|
24649
|
-
*/
|
|
24650
|
-
classes: array(string().min(1).max(60)).max(40).optional()
|
|
24651
|
-
});
|
|
24652
|
-
var RecentSummariesPageSchema = object({
|
|
24653
|
-
/** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
|
|
24654
|
-
* {@link listSummaries} — one list shape, so a card renders the same
|
|
24655
|
-
* whichever feed drew it. */
|
|
24656
|
-
summaries: array(SummaryListItemSchema).readonly(),
|
|
24657
|
-
nextCursor: string().nullable()
|
|
24658
|
-
});
|
|
24659
24749
|
var RecentTracksPageSchema = object({
|
|
24660
24750
|
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
24661
24751
|
tracks: array(TrackSchema).readonly(),
|
|
@@ -25193,15 +25283,6 @@ var pipelineAnalyticsCapability = {
|
|
|
25193
25283
|
* are not included (same contract as `listTracks`).
|
|
25194
25284
|
*/
|
|
25195
25285
|
listRecentTracks: method(RecentTracksQueryInput, RecentTracksPageSchema),
|
|
25196
|
-
/** Newest first by `openedAt`, for a camera set, inside an optional window. */
|
|
25197
|
-
listSummaries: method(SummariesQueryInput, SummariesPageSchema),
|
|
25198
|
-
/**
|
|
25199
|
-
* The PAGED feed — the reel and the Events gallery. Same cursor contract as
|
|
25200
|
-
* {@link listRecentTracks}, so one screen cannot hold two ideas of newest.
|
|
25201
|
-
*/
|
|
25202
|
-
listRecentSummaries: method(RecentSummariesQueryInput, RecentSummariesPageSchema),
|
|
25203
|
-
/** One summary with its member track ids; `null` for an id nobody wrote. */
|
|
25204
|
-
getSummary: method(object({ id: string() }), SummaryDetailSchema.nullable()),
|
|
25205
25286
|
clearTracks: method(object({ deviceId: number() }), _void(), {
|
|
25206
25287
|
kind: "mutation",
|
|
25207
25288
|
auth: "admin"
|
|
@@ -27228,6 +27309,23 @@ var MotionSourceEnum = _enum([
|
|
|
27228
27309
|
*/
|
|
27229
27310
|
var MotionSourcesSchema = array(MotionSourceEnum);
|
|
27230
27311
|
/**
|
|
27312
|
+
* The operator-facing name of each MOTION source (D672: `onboard` = the
|
|
27313
|
+
* camera's sensors — its own motion plus any sensor attached to it). The wire
|
|
27314
|
+
* value stays `onboard`; only the label changed. `detectionSources: 'onboard'`
|
|
27315
|
+
* ("Camera onboard AI") and the notification source filter keep their labels.
|
|
27316
|
+
*/
|
|
27317
|
+
var MOTION_SOURCE_LABELS = {
|
|
27318
|
+
analyzer: "Frame-diff Analyzer (motion addon)",
|
|
27319
|
+
onboard: "Camera sensors",
|
|
27320
|
+
"device-activity": "Device activity (the device says it is working)"
|
|
27321
|
+
};
|
|
27322
|
+
/** The order the motion-source picker offers them in (not the enum's order). */
|
|
27323
|
+
var MOTION_SOURCE_PICKER_ORDER = [
|
|
27324
|
+
"analyzer",
|
|
27325
|
+
"onboard",
|
|
27326
|
+
"device-activity"
|
|
27327
|
+
];
|
|
27328
|
+
/**
|
|
27231
27329
|
* Which root detector a camera runs — EXACTLY ONE.
|
|
27232
27330
|
*
|
|
27233
27331
|
* Deliberately the SAME vocabulary post-analysis already tags every detection
|
|
@@ -27574,7 +27672,14 @@ var RunnerCameraConfigSchema = object({
|
|
|
27574
27672
|
*/
|
|
27575
27673
|
inferenceDevices: array(RunnerInferenceDeviceSchema).readonly().optional()
|
|
27576
27674
|
});
|
|
27577
|
-
|
|
27675
|
+
MOTION_SOURCE_PICKER_ORDER.map((value) => value === "onboard" ? {
|
|
27676
|
+
value,
|
|
27677
|
+
label: MOTION_SOURCE_LABELS[value],
|
|
27678
|
+
description: "The camera's own motion, plus any sensor attached to it"
|
|
27679
|
+
} : {
|
|
27680
|
+
value,
|
|
27681
|
+
label: MOTION_SOURCE_LABELS[value]
|
|
27682
|
+
}), 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;
|
|
27578
27683
|
/**
|
|
27579
27684
|
* Runtime load summary returned by `getLocalLoad`. Used by the orchestrator's
|
|
27580
27685
|
* load-balancing levels (L2 capacity-based, L3 hardware-aware) to decide
|
|
@@ -28340,6 +28445,11 @@ var CameraStatusSchema = object({
|
|
|
28340
28445
|
*/
|
|
28341
28446
|
switchedOff: array(CameraSwitchIdSchema).readonly(),
|
|
28342
28447
|
/**
|
|
28448
|
+
* The camera's attached sensors (D672). Optional only for a status composed
|
|
28449
|
+
* by an orchestrator older than D672; this orchestrator always sets it.
|
|
28450
|
+
*/
|
|
28451
|
+
cameraSensors: CameraSensorsStatusSchema.optional(),
|
|
28452
|
+
/**
|
|
28343
28453
|
* Stages of the bounded fan-out that were CUT SHORT — a timeout or a
|
|
28344
28454
|
* rejection — and whose block is therefore `null` because we could not
|
|
28345
28455
|
* READ it, not because there is nothing there.
|
|
@@ -31811,44 +31921,6 @@ var videoclipsCapability = {
|
|
|
31811
31921
|
}
|
|
31812
31922
|
};
|
|
31813
31923
|
/**
|
|
31814
|
-
* LA tabella "quale booleano di questo tipo di device conta come ALTO", e il
|
|
31815
|
-
* valutatore puro del suo FRONTE.
|
|
31816
|
-
*
|
|
31817
|
-
* Viveva dentro il builtin virtual-doorbell
|
|
31818
|
-
* (`@camstack/system` — `builtins/doorbell/trigger-engine.ts`) e i suoi
|
|
31819
|
-
* predicati erano privati al modulo. Il recorder ne ha bisogno per il trigger
|
|
31820
|
-
* `RecordingTriggers.sensorDeviceIds`: copiarla avrebbe creato la SECONDA
|
|
31821
|
-
* tabella, che diverge alla prima cap aggiunta e il cui sintomo — "il sensore
|
|
31822
|
-
* fa suonare il campanello ma non registra" — è esattamente D62. Quindi si
|
|
31823
|
-
* SPOSTA qui e il doorbell la ri-esporta.
|
|
31824
|
-
*
|
|
31825
|
-
* ⚠ NON è `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), e le
|
|
31826
|
-
* due non vanno unificate: quella risponde a "qual è la PAROLA di stato per una
|
|
31827
|
-
* regola" (e include `presence`, `cover`, `alarm-panel`), questa a "qual è il
|
|
31828
|
-
* booleano il cui FRONTE conta". Vocabolari deliberatamente diversi.
|
|
31829
|
-
*/
|
|
31830
|
-
/**
|
|
31831
|
-
* Known binary / switch source caps → the boolean slice field whose
|
|
31832
|
-
* false→true rise counts as ACTIVE. Every entry is "fire on active".
|
|
31833
|
-
* Sensors whose "active" reading is not a plain boolean (presence's string
|
|
31834
|
-
* state, connectivity's connected flag) are deliberately excluded — a
|
|
31835
|
-
* reconnect is not a doorbell press, and it is not a recording either.
|
|
31836
|
-
*/
|
|
31837
|
-
var SOURCE_CAP_ACTIVE_FIELD = {
|
|
31838
|
-
contact: "entryOpen",
|
|
31839
|
-
binary: "on",
|
|
31840
|
-
switch: "on",
|
|
31841
|
-
motion: "detected",
|
|
31842
|
-
flood: "flooded",
|
|
31843
|
-
gas: "detected",
|
|
31844
|
-
smoke: "detected",
|
|
31845
|
-
"carbon-monoxide": "detected",
|
|
31846
|
-
vibration: "detected",
|
|
31847
|
-
tamper: "tampered"
|
|
31848
|
-
};
|
|
31849
|
-
/** Cap names whose presence in a device's bindings qualify it as a source. */
|
|
31850
|
-
var SOURCE_CAPS = Object.keys(SOURCE_CAP_ACTIVE_FIELD);
|
|
31851
|
-
/**
|
|
31852
31924
|
* Doorbell button cap. Two kinds of providers coexist behind this cap
|
|
31853
31925
|
* name (same pattern as `snapshot`):
|
|
31854
31926
|
*
|
|
@@ -31921,7 +31993,13 @@ var doorbellCapability = {
|
|
|
31921
31993
|
* push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no
|
|
31922
31994
|
* release/duration — it's a pulse.
|
|
31923
31995
|
*/
|
|
31924
|
-
onPressed: {
|
|
31996
|
+
onPressed: {
|
|
31997
|
+
data: DoorbellPressEventSchema,
|
|
31998
|
+
fromState: {
|
|
31999
|
+
field: "lastPressedAt",
|
|
32000
|
+
on: "advance"
|
|
32001
|
+
}
|
|
32002
|
+
} },
|
|
31925
32003
|
status: {
|
|
31926
32004
|
schema: DoorbellStatusSchema,
|
|
31927
32005
|
kind: "push"
|
|
@@ -37414,7 +37492,9 @@ var MotionOnMotionChangedDataSchema = object({
|
|
|
37414
37492
|
detected: boolean(),
|
|
37415
37493
|
timestamp: number(),
|
|
37416
37494
|
source: MotionSourceEnum,
|
|
37417
|
-
regions: array(MotionRegionSchema).readonly().optional()
|
|
37495
|
+
regions: array(MotionRegionSchema).readonly().optional(),
|
|
37496
|
+
/** Who started it (D672). Absent = the camera itself. Only `onboard` carries `sensor`. */
|
|
37497
|
+
triggeredBy: MotionTriggeredBySchema.optional()
|
|
37418
37498
|
});
|
|
37419
37499
|
var motionCapability = {
|
|
37420
37500
|
name: "motion",
|
|
@@ -40776,12 +40856,21 @@ var RecordingStorageUsageSchema = object({
|
|
|
40776
40856
|
*/
|
|
40777
40857
|
devicesRead: _enum(["archive", "unavailable"]).optional(),
|
|
40778
40858
|
/**
|
|
40859
|
+
* Is the `archive` answer WHOLE (D674): the hour ledger loaded without
|
|
40860
|
+
* hitting its row cap, and at least one location resolved? Only then may a
|
|
40861
|
+
* camera ABSENT from `devices[]` be read as "no footage" — and only then is a
|
|
40862
|
+
* row's `oldestMs` the archive's oldest rather than the oldest of a fraction.
|
|
40863
|
+
* OPTIONAL: a recorder predating D674 omits it, and a consumer must read the
|
|
40864
|
+
* absence as `false`. A retention floor is a delete; it never guesses.
|
|
40865
|
+
*/
|
|
40866
|
+
complete: boolean().optional(),
|
|
40867
|
+
/**
|
|
40779
40868
|
* Per-physical-volume capacity. OPTIONAL, and consumers must render the rest
|
|
40780
|
-
* of the payload without it:
|
|
40781
|
-
*
|
|
40782
|
-
*
|
|
40783
|
-
*
|
|
40784
|
-
*
|
|
40869
|
+
* of the payload without it: a recorder that could not build it omits it. A
|
|
40870
|
+
* UI that dereferences it unconditionally crashes the whole Storage page over
|
|
40871
|
+
* a missing disk bar. (The hub's cap routers pass output through unvalidated
|
|
40872
|
+
* since 2026-07-11 — `cap-router-builder.ts` — so a newer recorder's fields
|
|
40873
|
+
* are not stripped by an older hub.)
|
|
40785
40874
|
*/
|
|
40786
40875
|
locations: array(RecordingLocationUsageSchema).optional()
|
|
40787
40876
|
});
|
|
@@ -44705,7 +44794,12 @@ Object.freeze({
|
|
|
44705
44794
|
number: {
|
|
44706
44795
|
kind: "fixed",
|
|
44707
44796
|
result: ["number", "null"]
|
|
44708
|
-
}
|
|
44797
|
+
},
|
|
44798
|
+
rose: {
|
|
44799
|
+
kind: "fixed",
|
|
44800
|
+
result: ["number", "null"]
|
|
44801
|
+
},
|
|
44802
|
+
count: NUMBER
|
|
44709
44803
|
});
|
|
44710
44804
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
44711
44805
|
/**
|
|
@@ -48046,6 +48140,12 @@ Object.freeze({
|
|
|
48046
48140
|
addonId: null,
|
|
48047
48141
|
access: "view"
|
|
48048
48142
|
},
|
|
48143
|
+
"deviceManager.getWrapperActivation": {
|
|
48144
|
+
capName: "device-manager",
|
|
48145
|
+
capScope: "system",
|
|
48146
|
+
addonId: null,
|
|
48147
|
+
access: "view"
|
|
48148
|
+
},
|
|
48049
48149
|
"deviceManager.listAll": {
|
|
48050
48150
|
capName: "device-manager",
|
|
48051
48151
|
capScope: "system",
|
|
@@ -50320,12 +50420,6 @@ Object.freeze({
|
|
|
50320
50420
|
addonId: null,
|
|
50321
50421
|
access: "view"
|
|
50322
50422
|
},
|
|
50323
|
-
"pipelineAnalytics.getSummary": {
|
|
50324
|
-
capName: "pipeline-analytics",
|
|
50325
|
-
capScope: "device",
|
|
50326
|
-
addonId: null,
|
|
50327
|
-
access: "view"
|
|
50328
|
-
},
|
|
50329
50423
|
"pipelineAnalytics.getTrack": {
|
|
50330
50424
|
capName: "pipeline-analytics",
|
|
50331
50425
|
capScope: "device",
|
|
@@ -50386,12 +50480,6 @@ Object.freeze({
|
|
|
50386
50480
|
addonId: null,
|
|
50387
50481
|
access: "view"
|
|
50388
50482
|
},
|
|
50389
|
-
"pipelineAnalytics.listRecentSummaries": {
|
|
50390
|
-
capName: "pipeline-analytics",
|
|
50391
|
-
capScope: "device",
|
|
50392
|
-
addonId: null,
|
|
50393
|
-
access: "view"
|
|
50394
|
-
},
|
|
50395
50483
|
"pipelineAnalytics.listRecentTracks": {
|
|
50396
50484
|
capName: "pipeline-analytics",
|
|
50397
50485
|
capScope: "device",
|
|
@@ -50422,12 +50510,6 @@ Object.freeze({
|
|
|
50422
50510
|
addonId: null,
|
|
50423
50511
|
access: "view"
|
|
50424
50512
|
},
|
|
50425
|
-
"pipelineAnalytics.listSummaries": {
|
|
50426
|
-
capName: "pipeline-analytics",
|
|
50427
|
-
capScope: "device",
|
|
50428
|
-
addonId: null,
|
|
50429
|
-
access: "view"
|
|
50430
|
-
},
|
|
50431
50513
|
"pipelineAnalytics.listTrackMedia": {
|
|
50432
50514
|
capName: "pipeline-analytics",
|
|
50433
50515
|
capScope: "device",
|
|
@@ -53855,6 +53937,11 @@ Object.freeze({
|
|
|
53855
53937
|
form: "single",
|
|
53856
53938
|
optional: false
|
|
53857
53939
|
}],
|
|
53940
|
+
"deviceManager.getWrapperActivation": [{
|
|
53941
|
+
name: "deviceId",
|
|
53942
|
+
form: "single",
|
|
53943
|
+
optional: false
|
|
53944
|
+
}],
|
|
53858
53945
|
"deviceManager.listAll": [{
|
|
53859
53946
|
name: "deviceIds",
|
|
53860
53947
|
form: "array",
|
|
@@ -54592,11 +54679,6 @@ Object.freeze({
|
|
|
54592
54679
|
form: "single",
|
|
54593
54680
|
optional: true
|
|
54594
54681
|
}],
|
|
54595
|
-
"pipelineAnalytics.listRecentSummaries": [{
|
|
54596
|
-
name: "deviceIds",
|
|
54597
|
-
form: "array",
|
|
54598
|
-
optional: false
|
|
54599
|
-
}],
|
|
54600
54682
|
"pipelineAnalytics.listRecentTracks": [{
|
|
54601
54683
|
name: "deviceIds",
|
|
54602
54684
|
form: "array",
|
|
@@ -54607,11 +54689,6 @@ Object.freeze({
|
|
|
54607
54689
|
form: "array",
|
|
54608
54690
|
optional: true
|
|
54609
54691
|
}],
|
|
54610
|
-
"pipelineAnalytics.listSummaries": [{
|
|
54611
|
-
name: "deviceIds",
|
|
54612
|
-
form: "array",
|
|
54613
|
-
optional: false
|
|
54614
|
-
}],
|
|
54615
54692
|
"pipelineAnalytics.listTrackMedia": [{
|
|
54616
54693
|
name: "deviceId",
|
|
54617
54694
|
form: "single",
|