@camstack/addon-provider-tuya 0.2.27 → 0.2.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addon.js +184 -34
- package/dist/addon.mjs +184 -34
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -6621,6 +6621,13 @@ var BaseAddon = class {
|
|
|
6621
6621
|
_readinessGeneration = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2, 14);
|
|
6622
6622
|
/** Capability names this addon registered at init — used to emit matching `down` events on shutdown. */
|
|
6623
6623
|
_registeredCapNames = [];
|
|
6624
|
+
/**
|
|
6625
|
+
* True only after `readAddonStore` actually answered. Constructor
|
|
6626
|
+
* defaults look like stored config when the store is down — a forked
|
|
6627
|
+
* addon that auto-starts from those defaults (cloudflare-tunnel quick
|
|
6628
|
+
* mode, 2026-08-25) is not "the operator chose this".
|
|
6629
|
+
*/
|
|
6630
|
+
settingsStoreReady = false;
|
|
6624
6631
|
/** Default config values. Provided via constructor. */
|
|
6625
6632
|
defaults;
|
|
6626
6633
|
constructor(defaults) {
|
|
@@ -7021,7 +7028,9 @@ var BaseAddon = class {
|
|
|
7021
7028
|
];
|
|
7022
7029
|
let lastErr;
|
|
7023
7030
|
for (let attempt = 0; attempt <= delaysMs.length; attempt++) try {
|
|
7024
|
-
|
|
7031
|
+
const stored = await settings.readAddonStore() ?? {};
|
|
7032
|
+
this.settingsStoreReady = true;
|
|
7033
|
+
return stored;
|
|
7025
7034
|
} catch (err) {
|
|
7026
7035
|
lastErr = err;
|
|
7027
7036
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -7029,6 +7038,7 @@ var BaseAddon = class {
|
|
|
7029
7038
|
if (attempt === delaysMs.length) break;
|
|
7030
7039
|
await new Promise((r) => setTimeout(r, delaysMs[attempt]));
|
|
7031
7040
|
}
|
|
7041
|
+
this.settingsStoreReady = false;
|
|
7032
7042
|
this._ctx?.logger?.warn?.("readAddonStore: settings-store unavailable after retries — using defaults", { meta: { error: lastErr instanceof Error ? lastErr.message : String(lastErr) } });
|
|
7033
7043
|
return {};
|
|
7034
7044
|
}
|
|
@@ -8932,6 +8942,12 @@ var ModelVariantGroupSchema = object({
|
|
|
8932
8942
|
*/
|
|
8933
8943
|
resolution: number().int().positive().optional()
|
|
8934
8944
|
});
|
|
8945
|
+
var ModelProviderIdSchema = _enum([
|
|
8946
|
+
"camstack",
|
|
8947
|
+
"frigate",
|
|
8948
|
+
"scrypted",
|
|
8949
|
+
"custom"
|
|
8950
|
+
]);
|
|
8935
8951
|
var ModelCatalogEntrySchema = object({
|
|
8936
8952
|
id: string(),
|
|
8937
8953
|
name: string(),
|
|
@@ -9029,6 +9045,12 @@ var ModelCatalogEntrySchema = object({
|
|
|
9029
9045
|
*/
|
|
9030
9046
|
group: ModelVariantGroupSchema.optional(),
|
|
9031
9047
|
/**
|
|
9048
|
+
* Catalog source for the pipeline stepper's provider-first picker. Absent on
|
|
9049
|
+
* built-in CamStack entries (treated as `camstack`) and on registry rows
|
|
9050
|
+
* persisted before this field existed (`inferModelProvider` fills those).
|
|
9051
|
+
*/
|
|
9052
|
+
provider: ModelProviderIdSchema.optional(),
|
|
9053
|
+
/**
|
|
9032
9054
|
* Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
|
|
9033
9055
|
* applies (Frigate / COCO public catalog). Set on a custom model whose raw
|
|
9034
9056
|
* labels already ARE the CamStack macros (Scrypted identity map).
|
|
@@ -12837,6 +12859,27 @@ var LinkedDeviceSchema = object({
|
|
|
12837
12859
|
features: array(string()),
|
|
12838
12860
|
producesTrackedEvents: boolean().optional()
|
|
12839
12861
|
});
|
|
12862
|
+
/** One camera's resolved linked set, tagged with the camera it belongs to.
|
|
12863
|
+
* The batch answer needs the tag; the single-device answer already has it
|
|
12864
|
+
* from the input, which is why `getLinkedDevices` keeps the untagged shape. */
|
|
12865
|
+
var LinkedDevicesForDeviceSchema = object({
|
|
12866
|
+
deviceId: number(),
|
|
12867
|
+
mode: LinkedDevicesModeSchema,
|
|
12868
|
+
devices: array(LinkedDeviceSchema)
|
|
12869
|
+
});
|
|
12870
|
+
/** One device's binding map — the shape `getBindings`, `getBindingsBatch` and
|
|
12871
|
+
* `getAllBindings` all answer in. Declared once: three copies of the same
|
|
12872
|
+
* object literal is exactly how the three drift apart. */
|
|
12873
|
+
var DeviceBindingsForDeviceSchema = object({
|
|
12874
|
+
deviceId: number(),
|
|
12875
|
+
entries: array(object({
|
|
12876
|
+
capName: string(),
|
|
12877
|
+
kind: _enum(["native", "wrapped"]),
|
|
12878
|
+
providerAddonId: string(),
|
|
12879
|
+
providerNodeId: string(),
|
|
12880
|
+
nativeAddonId: string()
|
|
12881
|
+
}))
|
|
12882
|
+
});
|
|
12840
12883
|
var SavedDeviceRowSchema = object({
|
|
12841
12884
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
12842
12885
|
id: number(),
|
|
@@ -13062,11 +13105,25 @@ method(object({
|
|
|
13062
13105
|
projection: _enum(["full", "slim"]).optional(),
|
|
13063
13106
|
/** Return only camera devices. Filtering server-side instead of
|
|
13064
13107
|
* shipping 293 rows to find 12. */
|
|
13065
|
-
isCamera: boolean().optional()
|
|
13108
|
+
isCamera: boolean().optional(),
|
|
13109
|
+
/**
|
|
13110
|
+
* Return only these device ids. For the caller that already KNOWS the
|
|
13111
|
+
* handful it wants and needs a field the id-bearing answer does not
|
|
13112
|
+
* carry — the viewer's linked-devices panel joins `type` and `online`
|
|
13113
|
+
* onto ~8 linked ids and, unfiltered, dragged the fleet across to do
|
|
13114
|
+
* it: 433 KB slim / 958 KB full for 967 devices, on a query that
|
|
13115
|
+
* refetches on the reconcile interval, on a phone.
|
|
13116
|
+
*
|
|
13117
|
+
* Safe to send at a hub that predates it: Zod STRIPS unknown input
|
|
13118
|
+
* keys rather than rejecting them (verified against the live hub
|
|
13119
|
+
* 2026-08-25 — 967 rows came back), so an old hub answers exactly what
|
|
13120
|
+
* it answers today and the caller filters as it already does.
|
|
13121
|
+
*/
|
|
13122
|
+
deviceIds: array(number()).optional()
|
|
13066
13123
|
}), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
|
|
13067
13124
|
mode: LinkedDevicesModeSchema,
|
|
13068
13125
|
devices: array(LinkedDeviceSchema)
|
|
13069
|
-
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
13126
|
+
})), method(object({ deviceIds: array(number()) }), array(LinkedDevicesForDeviceSchema)), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
13070
13127
|
deviceId: number(),
|
|
13071
13128
|
values: record(string(), unknown())
|
|
13072
13129
|
}), object({ success: literal(true) }), {
|
|
@@ -13093,25 +13150,7 @@ method(object({
|
|
|
13093
13150
|
}), method(object({ deviceId: number() }), array(StreamProbeResultSchema), {
|
|
13094
13151
|
kind: "mutation",
|
|
13095
13152
|
auth: "admin"
|
|
13096
|
-
}), method(object({ deviceId: number() }), object({
|
|
13097
|
-
deviceId: number(),
|
|
13098
|
-
entries: array(object({
|
|
13099
|
-
capName: string(),
|
|
13100
|
-
kind: _enum(["native", "wrapped"]),
|
|
13101
|
-
providerAddonId: string(),
|
|
13102
|
-
providerNodeId: string(),
|
|
13103
|
-
nativeAddonId: string()
|
|
13104
|
-
}))
|
|
13105
|
-
})), method(object({}), array(object({
|
|
13106
|
-
deviceId: number(),
|
|
13107
|
-
entries: array(object({
|
|
13108
|
-
capName: string(),
|
|
13109
|
-
kind: _enum(["native", "wrapped"]),
|
|
13110
|
-
providerAddonId: string(),
|
|
13111
|
-
providerNodeId: string(),
|
|
13112
|
-
nativeAddonId: string()
|
|
13113
|
-
}))
|
|
13114
|
-
}))), method(object({
|
|
13153
|
+
}), method(object({ deviceId: number() }), DeviceBindingsForDeviceSchema), method(object({ deviceIds: array(number()) }), array(DeviceBindingsForDeviceSchema)), method(object({}), array(DeviceBindingsForDeviceSchema)), method(object({
|
|
13115
13154
|
deviceId: number(),
|
|
13116
13155
|
capName: string(),
|
|
13117
13156
|
wrapperAddonId: string(),
|
|
@@ -15521,12 +15560,15 @@ var NcOccupancyConditionSchema = object({
|
|
|
15521
15560
|
* there is no second switch that can disagree with the first and every rule
|
|
15522
15561
|
* authored before the decision migrates for free (`audioModeOf`):
|
|
15523
15562
|
*
|
|
15524
|
-
* - **LABEL mode — `labels` present.** The rule fires
|
|
15525
|
-
*
|
|
15526
|
-
* `hitPercent` and `samplingSeconds` are ignored
|
|
15527
|
-
*
|
|
15528
|
-
*
|
|
15529
|
-
*
|
|
15563
|
+
* - **LABEL mode — `labels` present.** The rule fires when `confirmHits`
|
|
15564
|
+
* labelled frames land inside `confirmWindowSec` (default 2 in 5 s).
|
|
15565
|
+
* `hitPercent` and `samplingSeconds` are still ignored — a percentage of
|
|
15566
|
+
* frames is the wrong question for a classifier that labels 1–3 frames
|
|
15567
|
+
* per episode. The count window is the brake that drops a single-frame
|
|
15568
|
+
* false positive; the rule's own `throttle` cooldown is the other. The
|
|
15569
|
+
* per-label confidence floor is the analyzer's (`classificationMinScore`,
|
|
15570
|
+
* per device) — a label only reaches this condition if the classifier was
|
|
15571
|
+
* already confident enough. `confirmHits: 1` restores first-frame fire.
|
|
15530
15572
|
* - **LEVEL mode — `dbThreshold` present, no labels.** The sampling window IS
|
|
15531
15573
|
* the condition: at least `hitPercent`% of the samples over
|
|
15532
15574
|
* `samplingSeconds` must be at or above `dbThreshold` dBFS (see
|
|
@@ -15553,14 +15595,22 @@ var NcOccupancyConditionSchema = object({
|
|
|
15553
15595
|
* an operator who typed `dog` mean the same thing.
|
|
15554
15596
|
*/
|
|
15555
15597
|
var NcAudioConditionSchema = object({
|
|
15556
|
-
/** LABEL MODE: audio macro labels. Present ⇒
|
|
15598
|
+
/** LABEL MODE: audio macro labels. Present ⇒ count-in-window confirm. */
|
|
15557
15599
|
labels: array(string().min(1)).min(1).optional(),
|
|
15558
15600
|
/** LEVEL MODE: floor in dBFS (negative-going, `0` = full scale). */
|
|
15559
15601
|
dbThreshold: number().min(-96).max(0).optional(),
|
|
15560
15602
|
/** LEVEL MODE ONLY: percentage of the window's samples that must be hits (1–100). */
|
|
15561
15603
|
hitPercent: number().int().min(1).max(100).default(60),
|
|
15562
15604
|
/** LEVEL MODE ONLY: length of the sampling window in seconds. */
|
|
15563
|
-
samplingSeconds: number().int().min(1).max(300).default(10)
|
|
15605
|
+
samplingSeconds: number().int().min(1).max(300).default(10),
|
|
15606
|
+
/**
|
|
15607
|
+
* LABEL MODE: how many labelled frames must land inside
|
|
15608
|
+
* {@link NcAudioConditionSchema.shape.confirmWindowSec} before dispatch.
|
|
15609
|
+
* Absent ⇒ 2 (the matcher default). `1` is first-frame fire.
|
|
15610
|
+
*/
|
|
15611
|
+
confirmHits: number().int().min(1).max(20).optional(),
|
|
15612
|
+
/** LABEL MODE: the window those frames must share, in seconds. Absent ⇒ 5. */
|
|
15613
|
+
confirmWindowSec: number().int().min(1).max(60).optional()
|
|
15564
15614
|
});
|
|
15565
15615
|
/**
|
|
15566
15616
|
* Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
|
|
@@ -17934,6 +17984,46 @@ var RecentTracksPageSchema = object({
|
|
|
17934
17984
|
/** Cursor for the next page, or null when this page is the last. */
|
|
17935
17985
|
nextCursor: string().nullable()
|
|
17936
17986
|
});
|
|
17987
|
+
var LIST_GROUPS_DEFAULT_LIMIT = 40;
|
|
17988
|
+
var LIST_GROUPS_MAX_LIMIT = 100;
|
|
17989
|
+
var AnalyticsGroupRecordSchema = object({
|
|
17990
|
+
id: string(),
|
|
17991
|
+
deviceId: number().int(),
|
|
17992
|
+
openedAt: number().int(),
|
|
17993
|
+
closedAt: number().int(),
|
|
17994
|
+
timestamp: number().int(),
|
|
17995
|
+
memberCount: number().int(),
|
|
17996
|
+
memberTrackIds: array(string()).readonly(),
|
|
17997
|
+
className: string(),
|
|
17998
|
+
classes: array(string()).readonly(),
|
|
17999
|
+
/** Relative event-media path, or null when the group has no picture yet. */
|
|
18000
|
+
mediaUrl: string().nullable(),
|
|
18001
|
+
singleton: boolean()
|
|
18002
|
+
});
|
|
18003
|
+
var AnalyticsGroupMemberSchema = object({
|
|
18004
|
+
trackId: string(),
|
|
18005
|
+
deviceId: number().int(),
|
|
18006
|
+
className: string(),
|
|
18007
|
+
firstSeen: number().int(),
|
|
18008
|
+
lastSeen: number().int(),
|
|
18009
|
+
mediaUrl: string().nullable()
|
|
18010
|
+
});
|
|
18011
|
+
var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
|
|
18012
|
+
var ListGroupsQueryInput = object({
|
|
18013
|
+
/** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
|
|
18014
|
+
deviceIds: array(number()),
|
|
18015
|
+
/** Window lower bound on `closedAt` (inclusive). */
|
|
18016
|
+
since: number().optional(),
|
|
18017
|
+
/** Window upper bound on `openedAt` (inclusive). */
|
|
18018
|
+
until: number().optional(),
|
|
18019
|
+
limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
|
|
18020
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
18021
|
+
cursor: string().optional()
|
|
18022
|
+
});
|
|
18023
|
+
var ListGroupsPageSchema = object({
|
|
18024
|
+
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
18025
|
+
nextCursor: string().nullable()
|
|
18026
|
+
});
|
|
17937
18027
|
var KeyEventQueryInput = object({
|
|
17938
18028
|
deviceId: number(),
|
|
17939
18029
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -18009,7 +18099,9 @@ var TrackCascadeCountsSchema = object({
|
|
|
18009
18099
|
/** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
|
|
18010
18100
|
plates: number().int(),
|
|
18011
18101
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
18012
|
-
embeddings: number().int()
|
|
18102
|
+
embeddings: number().int(),
|
|
18103
|
+
/** Group membership + group rows removed with their last member (best-effort). */
|
|
18104
|
+
groups: number().int()
|
|
18013
18105
|
});
|
|
18014
18106
|
/** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
|
|
18015
18107
|
var DiskReconcileCountsSchema = object({
|
|
@@ -18155,7 +18247,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
18155
18247
|
* stationary registry). Default false: the timeline lists passages,
|
|
18156
18248
|
* not parking records (operator decision, 2026-08-15). */
|
|
18157
18249
|
includeStationary: boolean().optional()
|
|
18158
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(
|
|
18250
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
|
|
18251
|
+
deviceId: number(),
|
|
18252
|
+
groupId: string().min(1)
|
|
18253
|
+
}), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
18159
18254
|
kind: "mutation",
|
|
18160
18255
|
auth: "admin"
|
|
18161
18256
|
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
|
|
@@ -18465,7 +18560,8 @@ var PipelineModelOptionSchema = object({
|
|
|
18465
18560
|
sizeMB: number()
|
|
18466
18561
|
})),
|
|
18467
18562
|
group: ModelVariantGroupSchema.optional(),
|
|
18468
|
-
legacy: boolean().optional()
|
|
18563
|
+
legacy: boolean().optional(),
|
|
18564
|
+
provider: ModelProviderIdSchema.optional()
|
|
18469
18565
|
});
|
|
18470
18566
|
var ConfigFieldBridge = custom();
|
|
18471
18567
|
var PipelineAddonSchemaSchema = object({
|
|
@@ -26570,7 +26666,12 @@ var PlateInfoSchema = object({
|
|
|
26570
26666
|
plateBbox: BoundingBoxSchema.optional(),
|
|
26571
26667
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
26572
26668
|
keyFrameMediaKey: string().optional(),
|
|
26573
|
-
base64: string().optional()
|
|
26669
|
+
base64: string().optional(),
|
|
26670
|
+
/**
|
|
26671
|
+
* Same crop as a data-plane URL. `getPlateByTrack` returns this and
|
|
26672
|
+
* never inlines JPEG; `listPlates` still inlines for the admin-ui.
|
|
26673
|
+
*/
|
|
26674
|
+
cropUrl: string().optional()
|
|
26574
26675
|
});
|
|
26575
26676
|
var MediaFileLiteSchema = object({
|
|
26576
26677
|
key: string(),
|
|
@@ -32094,6 +32195,12 @@ Object.freeze({
|
|
|
32094
32195
|
addonId: null,
|
|
32095
32196
|
access: "view"
|
|
32096
32197
|
},
|
|
32198
|
+
"deviceManager.getBindingsBatch": {
|
|
32199
|
+
capName: "device-manager",
|
|
32200
|
+
capScope: "system",
|
|
32201
|
+
addonId: null,
|
|
32202
|
+
access: "view"
|
|
32203
|
+
},
|
|
32097
32204
|
"deviceManager.getChildren": {
|
|
32098
32205
|
capName: "device-manager",
|
|
32099
32206
|
capScope: "system",
|
|
@@ -32154,6 +32261,12 @@ Object.freeze({
|
|
|
32154
32261
|
addonId: null,
|
|
32155
32262
|
access: "view"
|
|
32156
32263
|
},
|
|
32264
|
+
"deviceManager.getLinkedDevicesBatch": {
|
|
32265
|
+
capName: "device-manager",
|
|
32266
|
+
capScope: "system",
|
|
32267
|
+
addonId: null,
|
|
32268
|
+
access: "view"
|
|
32269
|
+
},
|
|
32157
32270
|
"deviceManager.getRoleDisplayDefaults": {
|
|
32158
32271
|
capName: "device-manager",
|
|
32159
32272
|
capScope: "system",
|
|
@@ -33924,6 +34037,12 @@ Object.freeze({
|
|
|
33924
34037
|
addonId: null,
|
|
33925
34038
|
access: "view"
|
|
33926
34039
|
},
|
|
34040
|
+
"pipelineAnalytics.getGroup": {
|
|
34041
|
+
capName: "pipeline-analytics",
|
|
34042
|
+
capScope: "device",
|
|
34043
|
+
addonId: null,
|
|
34044
|
+
access: "view"
|
|
34045
|
+
},
|
|
33927
34046
|
"pipelineAnalytics.getKeyEvents": {
|
|
33928
34047
|
capName: "pipeline-analytics",
|
|
33929
34048
|
capScope: "device",
|
|
@@ -34008,6 +34127,12 @@ Object.freeze({
|
|
|
34008
34127
|
addonId: null,
|
|
34009
34128
|
access: "view"
|
|
34010
34129
|
},
|
|
34130
|
+
"pipelineAnalytics.listGroups": {
|
|
34131
|
+
capName: "pipeline-analytics",
|
|
34132
|
+
capScope: "device",
|
|
34133
|
+
addonId: null,
|
|
34134
|
+
access: "view"
|
|
34135
|
+
},
|
|
34011
34136
|
"pipelineAnalytics.listOpsLog": {
|
|
34012
34137
|
capName: "pipeline-analytics",
|
|
34013
34138
|
capScope: "device",
|
|
@@ -36789,6 +36914,11 @@ Object.freeze({
|
|
|
36789
36914
|
form: "single",
|
|
36790
36915
|
optional: false
|
|
36791
36916
|
}],
|
|
36917
|
+
"deviceManager.getBindingsBatch": [{
|
|
36918
|
+
name: "deviceIds",
|
|
36919
|
+
form: "array",
|
|
36920
|
+
optional: false
|
|
36921
|
+
}],
|
|
36792
36922
|
"deviceManager.getChildren": [{
|
|
36793
36923
|
name: "parentDeviceId",
|
|
36794
36924
|
form: "single",
|
|
@@ -36834,6 +36964,11 @@ Object.freeze({
|
|
|
36834
36964
|
form: "single",
|
|
36835
36965
|
optional: false
|
|
36836
36966
|
}],
|
|
36967
|
+
"deviceManager.getLinkedDevicesBatch": [{
|
|
36968
|
+
name: "deviceIds",
|
|
36969
|
+
form: "array",
|
|
36970
|
+
optional: false
|
|
36971
|
+
}],
|
|
36837
36972
|
"deviceManager.getSettingsSchema": [{
|
|
36838
36973
|
name: "deviceId",
|
|
36839
36974
|
form: "single",
|
|
@@ -36854,6 +36989,11 @@ Object.freeze({
|
|
|
36854
36989
|
form: "single",
|
|
36855
36990
|
optional: false
|
|
36856
36991
|
}],
|
|
36992
|
+
"deviceManager.listAll": [{
|
|
36993
|
+
name: "deviceIds",
|
|
36994
|
+
form: "array",
|
|
36995
|
+
optional: true
|
|
36996
|
+
}],
|
|
36857
36997
|
"deviceManager.loadConfig": [{
|
|
36858
36998
|
name: "deviceId",
|
|
36859
36999
|
form: "single",
|
|
@@ -37427,6 +37567,11 @@ Object.freeze({
|
|
|
37427
37567
|
form: "single",
|
|
37428
37568
|
optional: false
|
|
37429
37569
|
}],
|
|
37570
|
+
"pipelineAnalytics.getGroup": [{
|
|
37571
|
+
name: "deviceId",
|
|
37572
|
+
form: "single",
|
|
37573
|
+
optional: false
|
|
37574
|
+
}],
|
|
37430
37575
|
"pipelineAnalytics.getKeyEvents": [{
|
|
37431
37576
|
name: "deviceId",
|
|
37432
37577
|
form: "single",
|
|
@@ -37482,6 +37627,11 @@ Object.freeze({
|
|
|
37482
37627
|
form: "array",
|
|
37483
37628
|
optional: false
|
|
37484
37629
|
}],
|
|
37630
|
+
"pipelineAnalytics.listGroups": [{
|
|
37631
|
+
name: "deviceIds",
|
|
37632
|
+
form: "array",
|
|
37633
|
+
optional: false
|
|
37634
|
+
}],
|
|
37485
37635
|
"pipelineAnalytics.listOpsLog": [{
|
|
37486
37636
|
name: "deviceId",
|
|
37487
37637
|
form: "single",
|
package/dist/addon.mjs
CHANGED
|
@@ -6620,6 +6620,13 @@ var BaseAddon = class {
|
|
|
6620
6620
|
_readinessGeneration = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2, 14);
|
|
6621
6621
|
/** Capability names this addon registered at init — used to emit matching `down` events on shutdown. */
|
|
6622
6622
|
_registeredCapNames = [];
|
|
6623
|
+
/**
|
|
6624
|
+
* True only after `readAddonStore` actually answered. Constructor
|
|
6625
|
+
* defaults look like stored config when the store is down — a forked
|
|
6626
|
+
* addon that auto-starts from those defaults (cloudflare-tunnel quick
|
|
6627
|
+
* mode, 2026-08-25) is not "the operator chose this".
|
|
6628
|
+
*/
|
|
6629
|
+
settingsStoreReady = false;
|
|
6623
6630
|
/** Default config values. Provided via constructor. */
|
|
6624
6631
|
defaults;
|
|
6625
6632
|
constructor(defaults) {
|
|
@@ -7020,7 +7027,9 @@ var BaseAddon = class {
|
|
|
7020
7027
|
];
|
|
7021
7028
|
let lastErr;
|
|
7022
7029
|
for (let attempt = 0; attempt <= delaysMs.length; attempt++) try {
|
|
7023
|
-
|
|
7030
|
+
const stored = await settings.readAddonStore() ?? {};
|
|
7031
|
+
this.settingsStoreReady = true;
|
|
7032
|
+
return stored;
|
|
7024
7033
|
} catch (err) {
|
|
7025
7034
|
lastErr = err;
|
|
7026
7035
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -7028,6 +7037,7 @@ var BaseAddon = class {
|
|
|
7028
7037
|
if (attempt === delaysMs.length) break;
|
|
7029
7038
|
await new Promise((r) => setTimeout(r, delaysMs[attempt]));
|
|
7030
7039
|
}
|
|
7040
|
+
this.settingsStoreReady = false;
|
|
7031
7041
|
this._ctx?.logger?.warn?.("readAddonStore: settings-store unavailable after retries — using defaults", { meta: { error: lastErr instanceof Error ? lastErr.message : String(lastErr) } });
|
|
7032
7042
|
return {};
|
|
7033
7043
|
}
|
|
@@ -8931,6 +8941,12 @@ var ModelVariantGroupSchema = object({
|
|
|
8931
8941
|
*/
|
|
8932
8942
|
resolution: number().int().positive().optional()
|
|
8933
8943
|
});
|
|
8944
|
+
var ModelProviderIdSchema = _enum([
|
|
8945
|
+
"camstack",
|
|
8946
|
+
"frigate",
|
|
8947
|
+
"scrypted",
|
|
8948
|
+
"custom"
|
|
8949
|
+
]);
|
|
8934
8950
|
var ModelCatalogEntrySchema = object({
|
|
8935
8951
|
id: string(),
|
|
8936
8952
|
name: string(),
|
|
@@ -9028,6 +9044,12 @@ var ModelCatalogEntrySchema = object({
|
|
|
9028
9044
|
*/
|
|
9029
9045
|
group: ModelVariantGroupSchema.optional(),
|
|
9030
9046
|
/**
|
|
9047
|
+
* Catalog source for the pipeline stepper's provider-first picker. Absent on
|
|
9048
|
+
* built-in CamStack entries (treated as `camstack`) and on registry rows
|
|
9049
|
+
* persisted before this field existed (`inferModelProvider` fills those).
|
|
9050
|
+
*/
|
|
9051
|
+
provider: ModelProviderIdSchema.optional(),
|
|
9052
|
+
/**
|
|
9031
9053
|
* Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
|
|
9032
9054
|
* applies (Frigate / COCO public catalog). Set on a custom model whose raw
|
|
9033
9055
|
* labels already ARE the CamStack macros (Scrypted identity map).
|
|
@@ -12836,6 +12858,27 @@ var LinkedDeviceSchema = object({
|
|
|
12836
12858
|
features: array(string()),
|
|
12837
12859
|
producesTrackedEvents: boolean().optional()
|
|
12838
12860
|
});
|
|
12861
|
+
/** One camera's resolved linked set, tagged with the camera it belongs to.
|
|
12862
|
+
* The batch answer needs the tag; the single-device answer already has it
|
|
12863
|
+
* from the input, which is why `getLinkedDevices` keeps the untagged shape. */
|
|
12864
|
+
var LinkedDevicesForDeviceSchema = object({
|
|
12865
|
+
deviceId: number(),
|
|
12866
|
+
mode: LinkedDevicesModeSchema,
|
|
12867
|
+
devices: array(LinkedDeviceSchema)
|
|
12868
|
+
});
|
|
12869
|
+
/** One device's binding map — the shape `getBindings`, `getBindingsBatch` and
|
|
12870
|
+
* `getAllBindings` all answer in. Declared once: three copies of the same
|
|
12871
|
+
* object literal is exactly how the three drift apart. */
|
|
12872
|
+
var DeviceBindingsForDeviceSchema = object({
|
|
12873
|
+
deviceId: number(),
|
|
12874
|
+
entries: array(object({
|
|
12875
|
+
capName: string(),
|
|
12876
|
+
kind: _enum(["native", "wrapped"]),
|
|
12877
|
+
providerAddonId: string(),
|
|
12878
|
+
providerNodeId: string(),
|
|
12879
|
+
nativeAddonId: string()
|
|
12880
|
+
}))
|
|
12881
|
+
});
|
|
12839
12882
|
var SavedDeviceRowSchema = object({
|
|
12840
12883
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
12841
12884
|
id: number(),
|
|
@@ -13061,11 +13104,25 @@ method(object({
|
|
|
13061
13104
|
projection: _enum(["full", "slim"]).optional(),
|
|
13062
13105
|
/** Return only camera devices. Filtering server-side instead of
|
|
13063
13106
|
* shipping 293 rows to find 12. */
|
|
13064
|
-
isCamera: boolean().optional()
|
|
13107
|
+
isCamera: boolean().optional(),
|
|
13108
|
+
/**
|
|
13109
|
+
* Return only these device ids. For the caller that already KNOWS the
|
|
13110
|
+
* handful it wants and needs a field the id-bearing answer does not
|
|
13111
|
+
* carry — the viewer's linked-devices panel joins `type` and `online`
|
|
13112
|
+
* onto ~8 linked ids and, unfiltered, dragged the fleet across to do
|
|
13113
|
+
* it: 433 KB slim / 958 KB full for 967 devices, on a query that
|
|
13114
|
+
* refetches on the reconcile interval, on a phone.
|
|
13115
|
+
*
|
|
13116
|
+
* Safe to send at a hub that predates it: Zod STRIPS unknown input
|
|
13117
|
+
* keys rather than rejecting them (verified against the live hub
|
|
13118
|
+
* 2026-08-25 — 967 rows came back), so an old hub answers exactly what
|
|
13119
|
+
* it answers today and the caller filters as it already does.
|
|
13120
|
+
*/
|
|
13121
|
+
deviceIds: array(number()).optional()
|
|
13065
13122
|
}), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
|
|
13066
13123
|
mode: LinkedDevicesModeSchema,
|
|
13067
13124
|
devices: array(LinkedDeviceSchema)
|
|
13068
|
-
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
13125
|
+
})), method(object({ deviceIds: array(number()) }), array(LinkedDevicesForDeviceSchema)), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
13069
13126
|
deviceId: number(),
|
|
13070
13127
|
values: record(string(), unknown())
|
|
13071
13128
|
}), object({ success: literal(true) }), {
|
|
@@ -13092,25 +13149,7 @@ method(object({
|
|
|
13092
13149
|
}), method(object({ deviceId: number() }), array(StreamProbeResultSchema), {
|
|
13093
13150
|
kind: "mutation",
|
|
13094
13151
|
auth: "admin"
|
|
13095
|
-
}), method(object({ deviceId: number() }), object({
|
|
13096
|
-
deviceId: number(),
|
|
13097
|
-
entries: array(object({
|
|
13098
|
-
capName: string(),
|
|
13099
|
-
kind: _enum(["native", "wrapped"]),
|
|
13100
|
-
providerAddonId: string(),
|
|
13101
|
-
providerNodeId: string(),
|
|
13102
|
-
nativeAddonId: string()
|
|
13103
|
-
}))
|
|
13104
|
-
})), method(object({}), array(object({
|
|
13105
|
-
deviceId: number(),
|
|
13106
|
-
entries: array(object({
|
|
13107
|
-
capName: string(),
|
|
13108
|
-
kind: _enum(["native", "wrapped"]),
|
|
13109
|
-
providerAddonId: string(),
|
|
13110
|
-
providerNodeId: string(),
|
|
13111
|
-
nativeAddonId: string()
|
|
13112
|
-
}))
|
|
13113
|
-
}))), method(object({
|
|
13152
|
+
}), method(object({ deviceId: number() }), DeviceBindingsForDeviceSchema), method(object({ deviceIds: array(number()) }), array(DeviceBindingsForDeviceSchema)), method(object({}), array(DeviceBindingsForDeviceSchema)), method(object({
|
|
13114
13153
|
deviceId: number(),
|
|
13115
13154
|
capName: string(),
|
|
13116
13155
|
wrapperAddonId: string(),
|
|
@@ -15520,12 +15559,15 @@ var NcOccupancyConditionSchema = object({
|
|
|
15520
15559
|
* there is no second switch that can disagree with the first and every rule
|
|
15521
15560
|
* authored before the decision migrates for free (`audioModeOf`):
|
|
15522
15561
|
*
|
|
15523
|
-
* - **LABEL mode — `labels` present.** The rule fires
|
|
15524
|
-
*
|
|
15525
|
-
* `hitPercent` and `samplingSeconds` are ignored
|
|
15526
|
-
*
|
|
15527
|
-
*
|
|
15528
|
-
*
|
|
15562
|
+
* - **LABEL mode — `labels` present.** The rule fires when `confirmHits`
|
|
15563
|
+
* labelled frames land inside `confirmWindowSec` (default 2 in 5 s).
|
|
15564
|
+
* `hitPercent` and `samplingSeconds` are still ignored — a percentage of
|
|
15565
|
+
* frames is the wrong question for a classifier that labels 1–3 frames
|
|
15566
|
+
* per episode. The count window is the brake that drops a single-frame
|
|
15567
|
+
* false positive; the rule's own `throttle` cooldown is the other. The
|
|
15568
|
+
* per-label confidence floor is the analyzer's (`classificationMinScore`,
|
|
15569
|
+
* per device) — a label only reaches this condition if the classifier was
|
|
15570
|
+
* already confident enough. `confirmHits: 1` restores first-frame fire.
|
|
15529
15571
|
* - **LEVEL mode — `dbThreshold` present, no labels.** The sampling window IS
|
|
15530
15572
|
* the condition: at least `hitPercent`% of the samples over
|
|
15531
15573
|
* `samplingSeconds` must be at or above `dbThreshold` dBFS (see
|
|
@@ -15552,14 +15594,22 @@ var NcOccupancyConditionSchema = object({
|
|
|
15552
15594
|
* an operator who typed `dog` mean the same thing.
|
|
15553
15595
|
*/
|
|
15554
15596
|
var NcAudioConditionSchema = object({
|
|
15555
|
-
/** LABEL MODE: audio macro labels. Present ⇒
|
|
15597
|
+
/** LABEL MODE: audio macro labels. Present ⇒ count-in-window confirm. */
|
|
15556
15598
|
labels: array(string().min(1)).min(1).optional(),
|
|
15557
15599
|
/** LEVEL MODE: floor in dBFS (negative-going, `0` = full scale). */
|
|
15558
15600
|
dbThreshold: number().min(-96).max(0).optional(),
|
|
15559
15601
|
/** LEVEL MODE ONLY: percentage of the window's samples that must be hits (1–100). */
|
|
15560
15602
|
hitPercent: number().int().min(1).max(100).default(60),
|
|
15561
15603
|
/** LEVEL MODE ONLY: length of the sampling window in seconds. */
|
|
15562
|
-
samplingSeconds: number().int().min(1).max(300).default(10)
|
|
15604
|
+
samplingSeconds: number().int().min(1).max(300).default(10),
|
|
15605
|
+
/**
|
|
15606
|
+
* LABEL MODE: how many labelled frames must land inside
|
|
15607
|
+
* {@link NcAudioConditionSchema.shape.confirmWindowSec} before dispatch.
|
|
15608
|
+
* Absent ⇒ 2 (the matcher default). `1` is first-frame fire.
|
|
15609
|
+
*/
|
|
15610
|
+
confirmHits: number().int().min(1).max(20).optional(),
|
|
15611
|
+
/** LABEL MODE: the window those frames must share, in seconds. Absent ⇒ 5. */
|
|
15612
|
+
confirmWindowSec: number().int().min(1).max(60).optional()
|
|
15563
15613
|
});
|
|
15564
15614
|
/**
|
|
15565
15615
|
* Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
|
|
@@ -17933,6 +17983,46 @@ var RecentTracksPageSchema = object({
|
|
|
17933
17983
|
/** Cursor for the next page, or null when this page is the last. */
|
|
17934
17984
|
nextCursor: string().nullable()
|
|
17935
17985
|
});
|
|
17986
|
+
var LIST_GROUPS_DEFAULT_LIMIT = 40;
|
|
17987
|
+
var LIST_GROUPS_MAX_LIMIT = 100;
|
|
17988
|
+
var AnalyticsGroupRecordSchema = object({
|
|
17989
|
+
id: string(),
|
|
17990
|
+
deviceId: number().int(),
|
|
17991
|
+
openedAt: number().int(),
|
|
17992
|
+
closedAt: number().int(),
|
|
17993
|
+
timestamp: number().int(),
|
|
17994
|
+
memberCount: number().int(),
|
|
17995
|
+
memberTrackIds: array(string()).readonly(),
|
|
17996
|
+
className: string(),
|
|
17997
|
+
classes: array(string()).readonly(),
|
|
17998
|
+
/** Relative event-media path, or null when the group has no picture yet. */
|
|
17999
|
+
mediaUrl: string().nullable(),
|
|
18000
|
+
singleton: boolean()
|
|
18001
|
+
});
|
|
18002
|
+
var AnalyticsGroupMemberSchema = object({
|
|
18003
|
+
trackId: string(),
|
|
18004
|
+
deviceId: number().int(),
|
|
18005
|
+
className: string(),
|
|
18006
|
+
firstSeen: number().int(),
|
|
18007
|
+
lastSeen: number().int(),
|
|
18008
|
+
mediaUrl: string().nullable()
|
|
18009
|
+
});
|
|
18010
|
+
var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
|
|
18011
|
+
var ListGroupsQueryInput = object({
|
|
18012
|
+
/** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
|
|
18013
|
+
deviceIds: array(number()),
|
|
18014
|
+
/** Window lower bound on `closedAt` (inclusive). */
|
|
18015
|
+
since: number().optional(),
|
|
18016
|
+
/** Window upper bound on `openedAt` (inclusive). */
|
|
18017
|
+
until: number().optional(),
|
|
18018
|
+
limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
|
|
18019
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
18020
|
+
cursor: string().optional()
|
|
18021
|
+
});
|
|
18022
|
+
var ListGroupsPageSchema = object({
|
|
18023
|
+
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
18024
|
+
nextCursor: string().nullable()
|
|
18025
|
+
});
|
|
17936
18026
|
var KeyEventQueryInput = object({
|
|
17937
18027
|
deviceId: number(),
|
|
17938
18028
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -18008,7 +18098,9 @@ var TrackCascadeCountsSchema = object({
|
|
|
18008
18098
|
/** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
|
|
18009
18099
|
plates: number().int(),
|
|
18010
18100
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
18011
|
-
embeddings: number().int()
|
|
18101
|
+
embeddings: number().int(),
|
|
18102
|
+
/** Group membership + group rows removed with their last member (best-effort). */
|
|
18103
|
+
groups: number().int()
|
|
18012
18104
|
});
|
|
18013
18105
|
/** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
|
|
18014
18106
|
var DiskReconcileCountsSchema = object({
|
|
@@ -18154,7 +18246,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
18154
18246
|
* stationary registry). Default false: the timeline lists passages,
|
|
18155
18247
|
* not parking records (operator decision, 2026-08-15). */
|
|
18156
18248
|
includeStationary: boolean().optional()
|
|
18157
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(
|
|
18249
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
|
|
18250
|
+
deviceId: number(),
|
|
18251
|
+
groupId: string().min(1)
|
|
18252
|
+
}), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
18158
18253
|
kind: "mutation",
|
|
18159
18254
|
auth: "admin"
|
|
18160
18255
|
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
|
|
@@ -18464,7 +18559,8 @@ var PipelineModelOptionSchema = object({
|
|
|
18464
18559
|
sizeMB: number()
|
|
18465
18560
|
})),
|
|
18466
18561
|
group: ModelVariantGroupSchema.optional(),
|
|
18467
|
-
legacy: boolean().optional()
|
|
18562
|
+
legacy: boolean().optional(),
|
|
18563
|
+
provider: ModelProviderIdSchema.optional()
|
|
18468
18564
|
});
|
|
18469
18565
|
var ConfigFieldBridge = custom();
|
|
18470
18566
|
var PipelineAddonSchemaSchema = object({
|
|
@@ -26569,7 +26665,12 @@ var PlateInfoSchema = object({
|
|
|
26569
26665
|
plateBbox: BoundingBoxSchema.optional(),
|
|
26570
26666
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
26571
26667
|
keyFrameMediaKey: string().optional(),
|
|
26572
|
-
base64: string().optional()
|
|
26668
|
+
base64: string().optional(),
|
|
26669
|
+
/**
|
|
26670
|
+
* Same crop as a data-plane URL. `getPlateByTrack` returns this and
|
|
26671
|
+
* never inlines JPEG; `listPlates` still inlines for the admin-ui.
|
|
26672
|
+
*/
|
|
26673
|
+
cropUrl: string().optional()
|
|
26573
26674
|
});
|
|
26574
26675
|
var MediaFileLiteSchema = object({
|
|
26575
26676
|
key: string(),
|
|
@@ -32093,6 +32194,12 @@ Object.freeze({
|
|
|
32093
32194
|
addonId: null,
|
|
32094
32195
|
access: "view"
|
|
32095
32196
|
},
|
|
32197
|
+
"deviceManager.getBindingsBatch": {
|
|
32198
|
+
capName: "device-manager",
|
|
32199
|
+
capScope: "system",
|
|
32200
|
+
addonId: null,
|
|
32201
|
+
access: "view"
|
|
32202
|
+
},
|
|
32096
32203
|
"deviceManager.getChildren": {
|
|
32097
32204
|
capName: "device-manager",
|
|
32098
32205
|
capScope: "system",
|
|
@@ -32153,6 +32260,12 @@ Object.freeze({
|
|
|
32153
32260
|
addonId: null,
|
|
32154
32261
|
access: "view"
|
|
32155
32262
|
},
|
|
32263
|
+
"deviceManager.getLinkedDevicesBatch": {
|
|
32264
|
+
capName: "device-manager",
|
|
32265
|
+
capScope: "system",
|
|
32266
|
+
addonId: null,
|
|
32267
|
+
access: "view"
|
|
32268
|
+
},
|
|
32156
32269
|
"deviceManager.getRoleDisplayDefaults": {
|
|
32157
32270
|
capName: "device-manager",
|
|
32158
32271
|
capScope: "system",
|
|
@@ -33923,6 +34036,12 @@ Object.freeze({
|
|
|
33923
34036
|
addonId: null,
|
|
33924
34037
|
access: "view"
|
|
33925
34038
|
},
|
|
34039
|
+
"pipelineAnalytics.getGroup": {
|
|
34040
|
+
capName: "pipeline-analytics",
|
|
34041
|
+
capScope: "device",
|
|
34042
|
+
addonId: null,
|
|
34043
|
+
access: "view"
|
|
34044
|
+
},
|
|
33926
34045
|
"pipelineAnalytics.getKeyEvents": {
|
|
33927
34046
|
capName: "pipeline-analytics",
|
|
33928
34047
|
capScope: "device",
|
|
@@ -34007,6 +34126,12 @@ Object.freeze({
|
|
|
34007
34126
|
addonId: null,
|
|
34008
34127
|
access: "view"
|
|
34009
34128
|
},
|
|
34129
|
+
"pipelineAnalytics.listGroups": {
|
|
34130
|
+
capName: "pipeline-analytics",
|
|
34131
|
+
capScope: "device",
|
|
34132
|
+
addonId: null,
|
|
34133
|
+
access: "view"
|
|
34134
|
+
},
|
|
34010
34135
|
"pipelineAnalytics.listOpsLog": {
|
|
34011
34136
|
capName: "pipeline-analytics",
|
|
34012
34137
|
capScope: "device",
|
|
@@ -36788,6 +36913,11 @@ Object.freeze({
|
|
|
36788
36913
|
form: "single",
|
|
36789
36914
|
optional: false
|
|
36790
36915
|
}],
|
|
36916
|
+
"deviceManager.getBindingsBatch": [{
|
|
36917
|
+
name: "deviceIds",
|
|
36918
|
+
form: "array",
|
|
36919
|
+
optional: false
|
|
36920
|
+
}],
|
|
36791
36921
|
"deviceManager.getChildren": [{
|
|
36792
36922
|
name: "parentDeviceId",
|
|
36793
36923
|
form: "single",
|
|
@@ -36833,6 +36963,11 @@ Object.freeze({
|
|
|
36833
36963
|
form: "single",
|
|
36834
36964
|
optional: false
|
|
36835
36965
|
}],
|
|
36966
|
+
"deviceManager.getLinkedDevicesBatch": [{
|
|
36967
|
+
name: "deviceIds",
|
|
36968
|
+
form: "array",
|
|
36969
|
+
optional: false
|
|
36970
|
+
}],
|
|
36836
36971
|
"deviceManager.getSettingsSchema": [{
|
|
36837
36972
|
name: "deviceId",
|
|
36838
36973
|
form: "single",
|
|
@@ -36853,6 +36988,11 @@ Object.freeze({
|
|
|
36853
36988
|
form: "single",
|
|
36854
36989
|
optional: false
|
|
36855
36990
|
}],
|
|
36991
|
+
"deviceManager.listAll": [{
|
|
36992
|
+
name: "deviceIds",
|
|
36993
|
+
form: "array",
|
|
36994
|
+
optional: true
|
|
36995
|
+
}],
|
|
36856
36996
|
"deviceManager.loadConfig": [{
|
|
36857
36997
|
name: "deviceId",
|
|
36858
36998
|
form: "single",
|
|
@@ -37426,6 +37566,11 @@ Object.freeze({
|
|
|
37426
37566
|
form: "single",
|
|
37427
37567
|
optional: false
|
|
37428
37568
|
}],
|
|
37569
|
+
"pipelineAnalytics.getGroup": [{
|
|
37570
|
+
name: "deviceId",
|
|
37571
|
+
form: "single",
|
|
37572
|
+
optional: false
|
|
37573
|
+
}],
|
|
37429
37574
|
"pipelineAnalytics.getKeyEvents": [{
|
|
37430
37575
|
name: "deviceId",
|
|
37431
37576
|
form: "single",
|
|
@@ -37481,6 +37626,11 @@ Object.freeze({
|
|
|
37481
37626
|
form: "array",
|
|
37482
37627
|
optional: false
|
|
37483
37628
|
}],
|
|
37629
|
+
"pipelineAnalytics.listGroups": [{
|
|
37630
|
+
name: "deviceIds",
|
|
37631
|
+
form: "array",
|
|
37632
|
+
optional: false
|
|
37633
|
+
}],
|
|
37484
37634
|
"pipelineAnalytics.listOpsLog": [{
|
|
37485
37635
|
name: "deviceId",
|
|
37486
37636
|
form: "single",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-provider-tuya",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.28",
|
|
4
4
|
"description": "Tuya / Smart Life device-provider addon for CamStack — account-onboarded (Tuya IoT cloud fetch of device localKeys) + LOCAL DP control via the @apocaliss92/nodetuya encrypted-LAN client, exposing switch / water-heater-family kettle entities",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|