@camstack/addon-provider-dreame 0.2.123 → 0.2.124
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 +203 -17
- package/dist/addon.mjs +203 -17
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -63368,6 +63368,15 @@ var ClipSearchStrictnessSchema = _enum([
|
|
|
63368
63368
|
"balanced",
|
|
63369
63369
|
"strict"
|
|
63370
63370
|
]);
|
|
63371
|
+
/** Steps whose effect a root label can BE. */
|
|
63372
|
+
var LABEL_SUPPLY_STEP_IDS = [
|
|
63373
|
+
"animal-classifier",
|
|
63374
|
+
"vehicle-classifier",
|
|
63375
|
+
"package-detection"
|
|
63376
|
+
];
|
|
63377
|
+
/** Steps whose box a root detection can BE. */
|
|
63378
|
+
var CROP_SUPPLY_STEP_IDS = ["plate-detection", "face-detection"];
|
|
63379
|
+
[...LABEL_SUPPLY_STEP_IDS, ...CROP_SUPPLY_STEP_IDS];
|
|
63371
63380
|
var MODEL_FORMATS = [
|
|
63372
63381
|
"onnx",
|
|
63373
63382
|
"coreml",
|
|
@@ -63500,6 +63509,35 @@ var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { wei
|
|
|
63500
63509
|
/** True when the weights or their data forbid commercial use. */
|
|
63501
63510
|
nonCommercial: boolean().optional()
|
|
63502
63511
|
}));
|
|
63512
|
+
/**
|
|
63513
|
+
* One step a ROOT detector can supply from its own output (D730) — see
|
|
63514
|
+
* `ModelCatalogEntry.suppliesSteps`.
|
|
63515
|
+
*
|
|
63516
|
+
* - `label`: the root's raw class IS the step's answer. `labelToEffect` maps
|
|
63517
|
+
* the root's label to the step's vocabulary; `uncovered` is the vocabulary
|
|
63518
|
+
* the root cannot produce (shown as unavailable, never a blocker).
|
|
63519
|
+
* - `crop`: the root draws the box the step would have found (`license_plate`
|
|
63520
|
+
* for plate-detection, `face` for face-detection). The box becomes a detail
|
|
63521
|
+
* child of the `parentMacro` detection that contains it — never a track.
|
|
63522
|
+
*/
|
|
63523
|
+
var RootStepSupplySchema = discriminatedUnion("kind", [object({
|
|
63524
|
+
kind: literal("label"),
|
|
63525
|
+
stepId: _enum(LABEL_SUPPLY_STEP_IDS),
|
|
63526
|
+
labelToEffect: record(string(), string()),
|
|
63527
|
+
uncovered: array(string()).readonly()
|
|
63528
|
+
}), object({
|
|
63529
|
+
kind: literal("crop"),
|
|
63530
|
+
stepId: _enum(CROP_SUPPLY_STEP_IDS),
|
|
63531
|
+
rootLabels: array(string()).readonly(),
|
|
63532
|
+
parentMacro: _enum(["vehicle", "person"]),
|
|
63533
|
+
childClass: _enum(["plate", "face"]),
|
|
63534
|
+
/**
|
|
63535
|
+
* The root's smaller input side, stamped on read by `rootSuppliesOf` from
|
|
63536
|
+
* the model entry — what a step's `minRootInputPx` gate judges. Never
|
|
63537
|
+
* stored by an import.
|
|
63538
|
+
*/
|
|
63539
|
+
rootInputPx: number().int().positive().optional()
|
|
63540
|
+
})]);
|
|
63503
63541
|
var ModelCatalogEntrySchema = object({
|
|
63504
63542
|
id: string(),
|
|
63505
63543
|
name: string(),
|
|
@@ -63626,6 +63664,16 @@ var ModelCatalogEntrySchema = object({
|
|
|
63626
63664
|
*/
|
|
63627
63665
|
classMap: DetectionCatalogClassMapSchema.optional(),
|
|
63628
63666
|
/**
|
|
63667
|
+
* The pipeline steps this ROOT detector can supply from its own output
|
|
63668
|
+
* (D730): its labels name a step's effect (`deer` for `animal-classifier`)
|
|
63669
|
+
* or draw a step's box (`license_plate` for `plate-detection`). Computed at
|
|
63670
|
+
* import from THIS model's labelmap by `deriveRootSupplies`, never written
|
|
63671
|
+
* by hand and never assumed per family; a row without it is derived on read
|
|
63672
|
+
* (`rootSuppliesOf`). Whether a camera uses it is the step's own
|
|
63673
|
+
* `useRootModel` flag (`resolveRootSupply`).
|
|
63674
|
+
*/
|
|
63675
|
+
suppliesSteps: array(RootStepSupplySchema).readonly().optional(),
|
|
63676
|
+
/**
|
|
63629
63677
|
* The model's CLIP feature-space contract (text encoder, dimension, vector
|
|
63630
63678
|
* index, token window, search floor) — see `clip-model.ts`. Present ONLY on a
|
|
63631
63679
|
* CLIP image encoder; its absence is what "not a CLIP model" means to the
|
|
@@ -69091,6 +69139,18 @@ method(_void(), array(string()).readonly(), { auth: "admin" }), method(object({
|
|
|
69091
69139
|
kind: "mutation",
|
|
69092
69140
|
auth: "admin"
|
|
69093
69141
|
});
|
|
69142
|
+
function hostnameOf(baseUrl) {
|
|
69143
|
+
try {
|
|
69144
|
+
const host = new URL(baseUrl).hostname;
|
|
69145
|
+
return host.length > 0 ? host : null;
|
|
69146
|
+
} catch {
|
|
69147
|
+
return null;
|
|
69148
|
+
}
|
|
69149
|
+
}
|
|
69150
|
+
/** The bare hostname of a base URL, or `null` when it does not parse. */
|
|
69151
|
+
function hubAddressHostname(baseUrl) {
|
|
69152
|
+
return baseUrl === null ? null : hostnameOf(baseUrl);
|
|
69153
|
+
}
|
|
69094
69154
|
/**
|
|
69095
69155
|
* Transport bounds for AI capability methods.
|
|
69096
69156
|
*
|
|
@@ -71693,6 +71753,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
71693
71753
|
"stream-offline",
|
|
71694
71754
|
"node-online",
|
|
71695
71755
|
"node-offline",
|
|
71756
|
+
"node-restarting",
|
|
71757
|
+
"node-updating",
|
|
71696
71758
|
"node-inference-unavailable",
|
|
71697
71759
|
"detection-blind",
|
|
71698
71760
|
"addon-crash-loop",
|
|
@@ -76210,6 +76272,34 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
76210
76272
|
timestamp: number()
|
|
76211
76273
|
});
|
|
76212
76274
|
/**
|
|
76275
|
+
* A root model's boxes standing in for one crop-kind step's own inference
|
|
76276
|
+
* (D730) — see `runPipeline.suppliedRoot`.
|
|
76277
|
+
*/
|
|
76278
|
+
var SuppliedRootOutputSchema = object({
|
|
76279
|
+
stepId: string(),
|
|
76280
|
+
/** The root model that drew the boxes — stamped on the result. */
|
|
76281
|
+
modelId: string(),
|
|
76282
|
+
detections: array(object({
|
|
76283
|
+
/** `[x1, y1, x2, y2]` in the pixels of the call's image. */
|
|
76284
|
+
bbox: tuple([
|
|
76285
|
+
number(),
|
|
76286
|
+
number(),
|
|
76287
|
+
number(),
|
|
76288
|
+
number()
|
|
76289
|
+
]),
|
|
76290
|
+
score: number(),
|
|
76291
|
+
/**
|
|
76292
|
+
* Five facial landmarks in the same pixels — a face the step's own
|
|
76293
|
+
* detector already re-found inside a root face box (D730), so its
|
|
76294
|
+
* embedder child aligns it exactly as it aligns any detected face.
|
|
76295
|
+
*/
|
|
76296
|
+
landmarks: array(object({
|
|
76297
|
+
x: number(),
|
|
76298
|
+
y: number()
|
|
76299
|
+
})).optional()
|
|
76300
|
+
})).min(1)
|
|
76301
|
+
});
|
|
76302
|
+
/**
|
|
76213
76303
|
* Reference to the frame's retained NATIVE surface + the parent crop's placement
|
|
76214
76304
|
* within the frame, so the executor can re-cut a leaf child ROI at native
|
|
76215
76305
|
* resolution on the detail plane. See the `runPipeline` `nativeCropRef` field.
|
|
@@ -76339,7 +76429,8 @@ var PipelineModelOptionSchema = object({
|
|
|
76339
76429
|
group: ModelVariantGroupSchema.optional(),
|
|
76340
76430
|
legacy: boolean().optional(),
|
|
76341
76431
|
provider: ModelProviderIdSchema.optional(),
|
|
76342
|
-
defaultConfidence: number().optional()
|
|
76432
|
+
defaultConfidence: number().optional(),
|
|
76433
|
+
suppliesSteps: array(RootStepSupplySchema).readonly().optional()
|
|
76343
76434
|
});
|
|
76344
76435
|
var ConfigFieldBridge = custom();
|
|
76345
76436
|
var PipelineAddonSchemaSchema = object({
|
|
@@ -76607,7 +76698,16 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
|
|
|
76607
76698
|
* `device-not-servable`), and nothing reaches the camera's live
|
|
76608
76699
|
* trace stream. Absent ⇒ unchanged behaviour.
|
|
76609
76700
|
*/
|
|
76610
|
-
replay: literal(true).optional()
|
|
76701
|
+
replay: literal(true).optional(),
|
|
76702
|
+
/**
|
|
76703
|
+
* Root-supplied detections for the tree's ROOT step (D730). Set by
|
|
76704
|
+
* `runDetailSubtree` when the camera's root model supplies a crop-kind
|
|
76705
|
+
* step (a Frigate+ `license_plate` for `plate-detection`): the step is
|
|
76706
|
+
* NOT inferred, these boxes are its output, and its children (the plate
|
|
76707
|
+
* reader) run on them through their own crop policy. Boxes are in the
|
|
76708
|
+
* PIXELS of the image this call carries. Absent ⇒ the root step runs.
|
|
76709
|
+
*/
|
|
76710
|
+
suppliedRoot: SuppliedRootOutputSchema.optional()
|
|
76611
76711
|
}), PipelineRunResultBridge, { kind: "mutation" }), method(object({
|
|
76612
76712
|
steps: array(PipelineStepInputSchema).min(1),
|
|
76613
76713
|
frames: array(FrameInputSchema).min(1).max(255),
|
|
@@ -77749,7 +77849,22 @@ method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mu
|
|
|
77749
77849
|
*/
|
|
77750
77850
|
cropJpeg: string().optional(),
|
|
77751
77851
|
parent: DetailParentSchema,
|
|
77752
|
-
steps: array(string()).optional()
|
|
77852
|
+
steps: array(string()).optional(),
|
|
77853
|
+
/**
|
|
77854
|
+
* The camera's root model already drew this step's boxes (D730): a
|
|
77855
|
+
* `license_plate` inside the parent vehicle. The named step is NOT
|
|
77856
|
+
* inferred — these FRAME-space boxes are its output — and its
|
|
77857
|
+
* requested children (the plate reader) run on them. Absent ⇒ every
|
|
77858
|
+
* requested step infers as before.
|
|
77859
|
+
*/
|
|
77860
|
+
supplied: object({
|
|
77861
|
+
stepId: string(),
|
|
77862
|
+
modelId: string(),
|
|
77863
|
+
boxes: array(object({
|
|
77864
|
+
bbox: NativeCropBboxSchema,
|
|
77865
|
+
score: number()
|
|
77866
|
+
})).min(1)
|
|
77867
|
+
}).optional()
|
|
77753
77868
|
}), object({ details: array(DetailResultSchema) }).nullable(), { kind: "mutation" }), method(object({
|
|
77754
77869
|
/** Catalog step id, e.g. `clip-embedding`. */
|
|
77755
77870
|
stepId: string(),
|
|
@@ -85017,6 +85132,27 @@ var ViewerEndpointsSchema = object({
|
|
|
85017
85132
|
/** What the ranking currently resolves to (may be empty if nothing is up). */
|
|
85018
85133
|
resolved: array(string()).readonly()
|
|
85019
85134
|
});
|
|
85135
|
+
/**
|
|
85136
|
+
* One audience's hub address (see `hub-address.ts`): the operator's stored
|
|
85137
|
+
* override, the address in use, and where it came from.
|
|
85138
|
+
*/
|
|
85139
|
+
var HubAddressSnapshotSchema = object({
|
|
85140
|
+
/** The operator's override, or null for automatic. */
|
|
85141
|
+
override: string().nullable(),
|
|
85142
|
+
/** The address in use, or null when nothing qualifies (never loopback). */
|
|
85143
|
+
resolved: string().nullable(),
|
|
85144
|
+
source: _enum([
|
|
85145
|
+
"override",
|
|
85146
|
+
"auto",
|
|
85147
|
+
"none"
|
|
85148
|
+
])
|
|
85149
|
+
});
|
|
85150
|
+
var HubAddressesSchema = object({
|
|
85151
|
+
/** "Hub address for agents" — agents' bundle/model pulls, LAN devices. */
|
|
85152
|
+
cluster: HubAddressSnapshotSchema,
|
|
85153
|
+
/** "Public address for sign-in links" — e-mail links, OIDC, WebAuthn, OAuth2. */
|
|
85154
|
+
browser: HubAddressSnapshotSchema
|
|
85155
|
+
});
|
|
85020
85156
|
var AllowedAddressesSchema = object({
|
|
85021
85157
|
/**
|
|
85022
85158
|
* Allowlist of interface addresses operators have explicitly opted
|
|
@@ -85063,7 +85199,13 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
|
|
|
85063
85199
|
* an address notification links can be flagged with, not a hub
|
|
85064
85200
|
* route. Default `false`: racers and rankers never see it. */
|
|
85065
85201
|
includeAppLink: boolean().optional()
|
|
85066
|
-
}), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(_void(),
|
|
85202
|
+
}), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(_void(), HubAddressesSchema), method(object({
|
|
85203
|
+
audience: _enum(["cluster", "browser"]),
|
|
85204
|
+
baseUrl: string().nullable()
|
|
85205
|
+
}), HubAddressesSchema, {
|
|
85206
|
+
kind: "mutation",
|
|
85207
|
+
auth: "admin"
|
|
85208
|
+
}), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
|
|
85067
85209
|
kind: "mutation",
|
|
85068
85210
|
auth: "admin"
|
|
85069
85211
|
}), method(object({
|
|
@@ -85521,7 +85663,8 @@ var MotionStatusSchema = object({
|
|
|
85521
85663
|
* writes this slice (not even a boot seed), and neither does the runner's
|
|
85522
85664
|
* phase machine: its phase is "a session is attached" for every on-motion
|
|
85523
85665
|
* session, not motion, and it now has its own `DetectionPhaseTransition`.
|
|
85524
|
-
* A provider's `isDetected`
|
|
85666
|
+
* A provider's `isDetected` and `getStatus` answer from the hub's slice
|
|
85667
|
+
* (`hubMotionNativeProvider`).
|
|
85525
85668
|
* - **Sensors** (Home Assistant binary sensors, Homematic, Matter, Alexa
|
|
85526
85669
|
* imports) — the provider pushes both edges itself, from the upstream
|
|
85527
85670
|
* system's own state change. That is the sensor's own fact.
|
|
@@ -96686,6 +96829,12 @@ Object.freeze({
|
|
|
96686
96829
|
addonId: null,
|
|
96687
96830
|
access: "view"
|
|
96688
96831
|
},
|
|
96832
|
+
"localNetwork.getHubAddresses": {
|
|
96833
|
+
capName: "local-network",
|
|
96834
|
+
capScope: "system",
|
|
96835
|
+
addonId: null,
|
|
96836
|
+
access: "view"
|
|
96837
|
+
},
|
|
96689
96838
|
"localNetwork.getNotificationEndpoint": {
|
|
96690
96839
|
capName: "local-network",
|
|
96691
96840
|
capScope: "system",
|
|
@@ -96740,6 +96889,12 @@ Object.freeze({
|
|
|
96740
96889
|
addonId: null,
|
|
96741
96890
|
access: "create"
|
|
96742
96891
|
},
|
|
96892
|
+
"localNetwork.setHubAddress": {
|
|
96893
|
+
capName: "local-network",
|
|
96894
|
+
capScope: "system",
|
|
96895
|
+
addonId: null,
|
|
96896
|
+
access: "create"
|
|
96897
|
+
},
|
|
96743
96898
|
"localNetwork.setNotificationEndpoint": {
|
|
96744
96899
|
capName: "local-network",
|
|
96745
96900
|
capScope: "system",
|
|
@@ -105139,6 +105294,8 @@ new Map(Object.entries({
|
|
|
105139
105294
|
"detection-blind": "device-events",
|
|
105140
105295
|
"node-online": "system",
|
|
105141
105296
|
"node-offline": "system",
|
|
105297
|
+
"node-restarting": "system",
|
|
105298
|
+
"node-updating": "system",
|
|
105142
105299
|
"node-inference-unavailable": "system",
|
|
105143
105300
|
"addon-crash-loop": "system",
|
|
105144
105301
|
"addon-update-available": "system",
|
|
@@ -105216,6 +105373,7 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
105216
105373
|
kinds: [
|
|
105217
105374
|
"node-offline",
|
|
105218
105375
|
"node-online",
|
|
105376
|
+
"node-restarting",
|
|
105219
105377
|
"node-inference-unavailable"
|
|
105220
105378
|
]
|
|
105221
105379
|
},
|
|
@@ -105237,6 +105395,7 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
105237
105395
|
label: "Server & container updates",
|
|
105238
105396
|
kinds: [
|
|
105239
105397
|
"server-update-available",
|
|
105398
|
+
"node-updating",
|
|
105240
105399
|
"server-updated",
|
|
105241
105400
|
"wrapper-update-available"
|
|
105242
105401
|
]
|
|
@@ -105384,6 +105543,7 @@ var STATE_SUMMARY_SECTION_VARS = [
|
|
|
105384
105543
|
kinds: [
|
|
105385
105544
|
"node-offline",
|
|
105386
105545
|
"node-online",
|
|
105546
|
+
"node-restarting",
|
|
105387
105547
|
"node-inference-unavailable"
|
|
105388
105548
|
]
|
|
105389
105549
|
},
|
|
@@ -105405,6 +105565,7 @@ var STATE_SUMMARY_SECTION_VARS = [
|
|
|
105405
105565
|
example: "server 1.2.377 → 1.2.378",
|
|
105406
105566
|
kinds: [
|
|
105407
105567
|
"server-update-available",
|
|
105568
|
+
"node-updating",
|
|
105408
105569
|
"server-updated",
|
|
105409
105570
|
"wrapper-update-available"
|
|
105410
105571
|
]
|
|
@@ -105437,7 +105598,7 @@ var STATE_SUMMARY_VARS = [
|
|
|
105437
105598
|
{
|
|
105438
105599
|
name: "summarySection",
|
|
105439
105600
|
label: "Summary: this section",
|
|
105440
|
-
description: "The section a per-section summary row is about
|
|
105601
|
+
description: "The section a per-section summary row is about; on a summary sent as one message, every section it reports, comma-separated.",
|
|
105441
105602
|
example: "Batterie scariche",
|
|
105442
105603
|
group: "system",
|
|
105443
105604
|
families: ["rule"],
|
|
@@ -108438,6 +108599,18 @@ function nextVacuumControlSlice(prev, next) {
|
|
|
108438
108599
|
}
|
|
108439
108600
|
//#endregion
|
|
108440
108601
|
//#region src/devices/dreame-camera-stream.ts
|
|
108602
|
+
/**
|
|
108603
|
+
* The robot camera as a stream the broker can pull — the pure facts.
|
|
108604
|
+
*
|
|
108605
|
+
* A Dreame relay carries video only between `open()` and `close()`, and the
|
|
108606
|
+
* robot runs on a battery, so the camera cannot sit in the catalog with a
|
|
108607
|
+
* URL the way a mains RTSP camera does. The seam is the broker's own battery
|
|
108608
|
+
* path: `battery.wakeForStream` opens the monitor, and the catalog then
|
|
108609
|
+
* names the local RFC 4571 server (`dreame-rfc4571-server.ts`) the broker
|
|
108610
|
+
* pulls. While the monitor is CLOSED the
|
|
108611
|
+
* catalog carries the broker's lazy sentinel (Reolink's shape): the stream is
|
|
108612
|
+
* listed, and the first dial asks the publisher to materialize it.
|
|
108613
|
+
*/
|
|
108441
108614
|
/** The one stream the robot camera offers. Half of the broker id (`<deviceId>/live`). */
|
|
108442
108615
|
var CAMERA_STREAM_ID = "live";
|
|
108443
108616
|
/** The plugin's cap: a monitor never outlives this, whoever is watching. */
|
|
@@ -108517,17 +108690,13 @@ function cameraStreamCatalog(session) {
|
|
|
108517
108690
|
/**
|
|
108518
108691
|
* The host the broker is told to dial. The provider and the ingest owner
|
|
108519
108692
|
* share the hub today, but a broker on another node reaches the hub only
|
|
108520
|
-
* through
|
|
108521
|
-
*
|
|
108693
|
+
* through the hub's address for agents — `local-network.getHubAddresses()
|
|
108694
|
+
* .cluster` (the Network page's override, else the detected LAN address).
|
|
108695
|
+
* Loopback when that names nothing: then the only broker that can dial at
|
|
108696
|
+
* all is this node's own.
|
|
108522
108697
|
*/
|
|
108523
|
-
function advertisedRfcHost(
|
|
108524
|
-
|
|
108525
|
-
try {
|
|
108526
|
-
const host = new URL(hubPublicUrl).hostname;
|
|
108527
|
-
return host.length > 0 ? host : "127.0.0.1";
|
|
108528
|
-
} catch {
|
|
108529
|
-
return "127.0.0.1";
|
|
108530
|
-
}
|
|
108698
|
+
function advertisedRfcHost(clusterBaseUrl) {
|
|
108699
|
+
return hubAddressHostname(clusterBaseUrl) ?? "127.0.0.1";
|
|
108531
108700
|
}
|
|
108532
108701
|
function rfcUrl(host, port) {
|
|
108533
108702
|
return `tcp://${host}:${String(port)}`;
|
|
@@ -154917,6 +155086,23 @@ var DreameCameraDevice = class extends DreameChildDevice {
|
|
|
154917
155086
|
}
|
|
154918
155087
|
unsubscribeRefresh = null;
|
|
154919
155088
|
/** Register the stream on the broker — the server, or the lazy sentinel (push semantics; the catalog is the durable copy). */
|
|
155089
|
+
/**
|
|
155090
|
+
* The hub's address for agents (`local-network.getHubAddresses().cluster`:
|
|
155091
|
+
* the Network page's override, else the detected LAN address). A failed
|
|
155092
|
+
* read is `null` — `advertisedRfcHost` then answers loopback, which this
|
|
155093
|
+
* node's own broker can still dial.
|
|
155094
|
+
*/
|
|
155095
|
+
async hubClusterAddress() {
|
|
155096
|
+
try {
|
|
155097
|
+
return (await this.ctx.api.localNetwork.getHubAddresses.query()).cluster.resolved;
|
|
155098
|
+
} catch (err) {
|
|
155099
|
+
this.ctx.logger.warn("robot camera: hub address unavailable — advertising loopback", {
|
|
155100
|
+
tags: { deviceId: this.id },
|
|
155101
|
+
meta: { error: err instanceof Error ? err.message : String(err) }
|
|
155102
|
+
});
|
|
155103
|
+
return null;
|
|
155104
|
+
}
|
|
155105
|
+
}
|
|
154920
155106
|
async publishRelay(session) {
|
|
154921
155107
|
const [descriptor] = cameraStreamCatalog(session);
|
|
154922
155108
|
if (descriptor === void 0) return;
|
|
@@ -155002,7 +155188,7 @@ var DreameCameraDevice = class extends DreameChildDevice {
|
|
|
155002
155188
|
rfc
|
|
155003
155189
|
};
|
|
155004
155190
|
this.session = {
|
|
155005
|
-
url: rfcUrl(advertisedRfcHost(
|
|
155191
|
+
url: rfcUrl(advertisedRfcHost(await this.hubClusterAddress()), rfc.port),
|
|
155006
155192
|
sdp: rfc.sdp
|
|
155007
155193
|
};
|
|
155008
155194
|
this.sessionOpenedAt = Date.now();
|
package/dist/addon.mjs
CHANGED
|
@@ -63365,6 +63365,15 @@ var ClipSearchStrictnessSchema = _enum([
|
|
|
63365
63365
|
"balanced",
|
|
63366
63366
|
"strict"
|
|
63367
63367
|
]);
|
|
63368
|
+
/** Steps whose effect a root label can BE. */
|
|
63369
|
+
var LABEL_SUPPLY_STEP_IDS = [
|
|
63370
|
+
"animal-classifier",
|
|
63371
|
+
"vehicle-classifier",
|
|
63372
|
+
"package-detection"
|
|
63373
|
+
];
|
|
63374
|
+
/** Steps whose box a root detection can BE. */
|
|
63375
|
+
var CROP_SUPPLY_STEP_IDS = ["plate-detection", "face-detection"];
|
|
63376
|
+
[...LABEL_SUPPLY_STEP_IDS, ...CROP_SUPPLY_STEP_IDS];
|
|
63368
63377
|
var MODEL_FORMATS = [
|
|
63369
63378
|
"onnx",
|
|
63370
63379
|
"coreml",
|
|
@@ -63497,6 +63506,35 @@ var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { wei
|
|
|
63497
63506
|
/** True when the weights or their data forbid commercial use. */
|
|
63498
63507
|
nonCommercial: boolean().optional()
|
|
63499
63508
|
}));
|
|
63509
|
+
/**
|
|
63510
|
+
* One step a ROOT detector can supply from its own output (D730) — see
|
|
63511
|
+
* `ModelCatalogEntry.suppliesSteps`.
|
|
63512
|
+
*
|
|
63513
|
+
* - `label`: the root's raw class IS the step's answer. `labelToEffect` maps
|
|
63514
|
+
* the root's label to the step's vocabulary; `uncovered` is the vocabulary
|
|
63515
|
+
* the root cannot produce (shown as unavailable, never a blocker).
|
|
63516
|
+
* - `crop`: the root draws the box the step would have found (`license_plate`
|
|
63517
|
+
* for plate-detection, `face` for face-detection). The box becomes a detail
|
|
63518
|
+
* child of the `parentMacro` detection that contains it — never a track.
|
|
63519
|
+
*/
|
|
63520
|
+
var RootStepSupplySchema = discriminatedUnion("kind", [object({
|
|
63521
|
+
kind: literal("label"),
|
|
63522
|
+
stepId: _enum(LABEL_SUPPLY_STEP_IDS),
|
|
63523
|
+
labelToEffect: record(string(), string()),
|
|
63524
|
+
uncovered: array(string()).readonly()
|
|
63525
|
+
}), object({
|
|
63526
|
+
kind: literal("crop"),
|
|
63527
|
+
stepId: _enum(CROP_SUPPLY_STEP_IDS),
|
|
63528
|
+
rootLabels: array(string()).readonly(),
|
|
63529
|
+
parentMacro: _enum(["vehicle", "person"]),
|
|
63530
|
+
childClass: _enum(["plate", "face"]),
|
|
63531
|
+
/**
|
|
63532
|
+
* The root's smaller input side, stamped on read by `rootSuppliesOf` from
|
|
63533
|
+
* the model entry — what a step's `minRootInputPx` gate judges. Never
|
|
63534
|
+
* stored by an import.
|
|
63535
|
+
*/
|
|
63536
|
+
rootInputPx: number().int().positive().optional()
|
|
63537
|
+
})]);
|
|
63500
63538
|
var ModelCatalogEntrySchema = object({
|
|
63501
63539
|
id: string(),
|
|
63502
63540
|
name: string(),
|
|
@@ -63623,6 +63661,16 @@ var ModelCatalogEntrySchema = object({
|
|
|
63623
63661
|
*/
|
|
63624
63662
|
classMap: DetectionCatalogClassMapSchema.optional(),
|
|
63625
63663
|
/**
|
|
63664
|
+
* The pipeline steps this ROOT detector can supply from its own output
|
|
63665
|
+
* (D730): its labels name a step's effect (`deer` for `animal-classifier`)
|
|
63666
|
+
* or draw a step's box (`license_plate` for `plate-detection`). Computed at
|
|
63667
|
+
* import from THIS model's labelmap by `deriveRootSupplies`, never written
|
|
63668
|
+
* by hand and never assumed per family; a row without it is derived on read
|
|
63669
|
+
* (`rootSuppliesOf`). Whether a camera uses it is the step's own
|
|
63670
|
+
* `useRootModel` flag (`resolveRootSupply`).
|
|
63671
|
+
*/
|
|
63672
|
+
suppliesSteps: array(RootStepSupplySchema).readonly().optional(),
|
|
63673
|
+
/**
|
|
63626
63674
|
* The model's CLIP feature-space contract (text encoder, dimension, vector
|
|
63627
63675
|
* index, token window, search floor) — see `clip-model.ts`. Present ONLY on a
|
|
63628
63676
|
* CLIP image encoder; its absence is what "not a CLIP model" means to the
|
|
@@ -69088,6 +69136,18 @@ method(_void(), array(string()).readonly(), { auth: "admin" }), method(object({
|
|
|
69088
69136
|
kind: "mutation",
|
|
69089
69137
|
auth: "admin"
|
|
69090
69138
|
});
|
|
69139
|
+
function hostnameOf(baseUrl) {
|
|
69140
|
+
try {
|
|
69141
|
+
const host = new URL(baseUrl).hostname;
|
|
69142
|
+
return host.length > 0 ? host : null;
|
|
69143
|
+
} catch {
|
|
69144
|
+
return null;
|
|
69145
|
+
}
|
|
69146
|
+
}
|
|
69147
|
+
/** The bare hostname of a base URL, or `null` when it does not parse. */
|
|
69148
|
+
function hubAddressHostname(baseUrl) {
|
|
69149
|
+
return baseUrl === null ? null : hostnameOf(baseUrl);
|
|
69150
|
+
}
|
|
69091
69151
|
/**
|
|
69092
69152
|
* Transport bounds for AI capability methods.
|
|
69093
69153
|
*
|
|
@@ -71690,6 +71750,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
71690
71750
|
"stream-offline",
|
|
71691
71751
|
"node-online",
|
|
71692
71752
|
"node-offline",
|
|
71753
|
+
"node-restarting",
|
|
71754
|
+
"node-updating",
|
|
71693
71755
|
"node-inference-unavailable",
|
|
71694
71756
|
"detection-blind",
|
|
71695
71757
|
"addon-crash-loop",
|
|
@@ -76207,6 +76269,34 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
76207
76269
|
timestamp: number()
|
|
76208
76270
|
});
|
|
76209
76271
|
/**
|
|
76272
|
+
* A root model's boxes standing in for one crop-kind step's own inference
|
|
76273
|
+
* (D730) — see `runPipeline.suppliedRoot`.
|
|
76274
|
+
*/
|
|
76275
|
+
var SuppliedRootOutputSchema = object({
|
|
76276
|
+
stepId: string(),
|
|
76277
|
+
/** The root model that drew the boxes — stamped on the result. */
|
|
76278
|
+
modelId: string(),
|
|
76279
|
+
detections: array(object({
|
|
76280
|
+
/** `[x1, y1, x2, y2]` in the pixels of the call's image. */
|
|
76281
|
+
bbox: tuple([
|
|
76282
|
+
number(),
|
|
76283
|
+
number(),
|
|
76284
|
+
number(),
|
|
76285
|
+
number()
|
|
76286
|
+
]),
|
|
76287
|
+
score: number(),
|
|
76288
|
+
/**
|
|
76289
|
+
* Five facial landmarks in the same pixels — a face the step's own
|
|
76290
|
+
* detector already re-found inside a root face box (D730), so its
|
|
76291
|
+
* embedder child aligns it exactly as it aligns any detected face.
|
|
76292
|
+
*/
|
|
76293
|
+
landmarks: array(object({
|
|
76294
|
+
x: number(),
|
|
76295
|
+
y: number()
|
|
76296
|
+
})).optional()
|
|
76297
|
+
})).min(1)
|
|
76298
|
+
});
|
|
76299
|
+
/**
|
|
76210
76300
|
* Reference to the frame's retained NATIVE surface + the parent crop's placement
|
|
76211
76301
|
* within the frame, so the executor can re-cut a leaf child ROI at native
|
|
76212
76302
|
* resolution on the detail plane. See the `runPipeline` `nativeCropRef` field.
|
|
@@ -76336,7 +76426,8 @@ var PipelineModelOptionSchema = object({
|
|
|
76336
76426
|
group: ModelVariantGroupSchema.optional(),
|
|
76337
76427
|
legacy: boolean().optional(),
|
|
76338
76428
|
provider: ModelProviderIdSchema.optional(),
|
|
76339
|
-
defaultConfidence: number().optional()
|
|
76429
|
+
defaultConfidence: number().optional(),
|
|
76430
|
+
suppliesSteps: array(RootStepSupplySchema).readonly().optional()
|
|
76340
76431
|
});
|
|
76341
76432
|
var ConfigFieldBridge = custom();
|
|
76342
76433
|
var PipelineAddonSchemaSchema = object({
|
|
@@ -76604,7 +76695,16 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
|
|
|
76604
76695
|
* `device-not-servable`), and nothing reaches the camera's live
|
|
76605
76696
|
* trace stream. Absent ⇒ unchanged behaviour.
|
|
76606
76697
|
*/
|
|
76607
|
-
replay: literal(true).optional()
|
|
76698
|
+
replay: literal(true).optional(),
|
|
76699
|
+
/**
|
|
76700
|
+
* Root-supplied detections for the tree's ROOT step (D730). Set by
|
|
76701
|
+
* `runDetailSubtree` when the camera's root model supplies a crop-kind
|
|
76702
|
+
* step (a Frigate+ `license_plate` for `plate-detection`): the step is
|
|
76703
|
+
* NOT inferred, these boxes are its output, and its children (the plate
|
|
76704
|
+
* reader) run on them through their own crop policy. Boxes are in the
|
|
76705
|
+
* PIXELS of the image this call carries. Absent ⇒ the root step runs.
|
|
76706
|
+
*/
|
|
76707
|
+
suppliedRoot: SuppliedRootOutputSchema.optional()
|
|
76608
76708
|
}), PipelineRunResultBridge, { kind: "mutation" }), method(object({
|
|
76609
76709
|
steps: array(PipelineStepInputSchema).min(1),
|
|
76610
76710
|
frames: array(FrameInputSchema).min(1).max(255),
|
|
@@ -77746,7 +77846,22 @@ method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mu
|
|
|
77746
77846
|
*/
|
|
77747
77847
|
cropJpeg: string().optional(),
|
|
77748
77848
|
parent: DetailParentSchema,
|
|
77749
|
-
steps: array(string()).optional()
|
|
77849
|
+
steps: array(string()).optional(),
|
|
77850
|
+
/**
|
|
77851
|
+
* The camera's root model already drew this step's boxes (D730): a
|
|
77852
|
+
* `license_plate` inside the parent vehicle. The named step is NOT
|
|
77853
|
+
* inferred — these FRAME-space boxes are its output — and its
|
|
77854
|
+
* requested children (the plate reader) run on them. Absent ⇒ every
|
|
77855
|
+
* requested step infers as before.
|
|
77856
|
+
*/
|
|
77857
|
+
supplied: object({
|
|
77858
|
+
stepId: string(),
|
|
77859
|
+
modelId: string(),
|
|
77860
|
+
boxes: array(object({
|
|
77861
|
+
bbox: NativeCropBboxSchema,
|
|
77862
|
+
score: number()
|
|
77863
|
+
})).min(1)
|
|
77864
|
+
}).optional()
|
|
77750
77865
|
}), object({ details: array(DetailResultSchema) }).nullable(), { kind: "mutation" }), method(object({
|
|
77751
77866
|
/** Catalog step id, e.g. `clip-embedding`. */
|
|
77752
77867
|
stepId: string(),
|
|
@@ -85014,6 +85129,27 @@ var ViewerEndpointsSchema = object({
|
|
|
85014
85129
|
/** What the ranking currently resolves to (may be empty if nothing is up). */
|
|
85015
85130
|
resolved: array(string()).readonly()
|
|
85016
85131
|
});
|
|
85132
|
+
/**
|
|
85133
|
+
* One audience's hub address (see `hub-address.ts`): the operator's stored
|
|
85134
|
+
* override, the address in use, and where it came from.
|
|
85135
|
+
*/
|
|
85136
|
+
var HubAddressSnapshotSchema = object({
|
|
85137
|
+
/** The operator's override, or null for automatic. */
|
|
85138
|
+
override: string().nullable(),
|
|
85139
|
+
/** The address in use, or null when nothing qualifies (never loopback). */
|
|
85140
|
+
resolved: string().nullable(),
|
|
85141
|
+
source: _enum([
|
|
85142
|
+
"override",
|
|
85143
|
+
"auto",
|
|
85144
|
+
"none"
|
|
85145
|
+
])
|
|
85146
|
+
});
|
|
85147
|
+
var HubAddressesSchema = object({
|
|
85148
|
+
/** "Hub address for agents" — agents' bundle/model pulls, LAN devices. */
|
|
85149
|
+
cluster: HubAddressSnapshotSchema,
|
|
85150
|
+
/** "Public address for sign-in links" — e-mail links, OIDC, WebAuthn, OAuth2. */
|
|
85151
|
+
browser: HubAddressSnapshotSchema
|
|
85152
|
+
});
|
|
85017
85153
|
var AllowedAddressesSchema = object({
|
|
85018
85154
|
/**
|
|
85019
85155
|
* Allowlist of interface addresses operators have explicitly opted
|
|
@@ -85060,7 +85196,13 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
|
|
|
85060
85196
|
* an address notification links can be flagged with, not a hub
|
|
85061
85197
|
* route. Default `false`: racers and rankers never see it. */
|
|
85062
85198
|
includeAppLink: boolean().optional()
|
|
85063
|
-
}), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(_void(),
|
|
85199
|
+
}), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(_void(), HubAddressesSchema), method(object({
|
|
85200
|
+
audience: _enum(["cluster", "browser"]),
|
|
85201
|
+
baseUrl: string().nullable()
|
|
85202
|
+
}), HubAddressesSchema, {
|
|
85203
|
+
kind: "mutation",
|
|
85204
|
+
auth: "admin"
|
|
85205
|
+
}), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
|
|
85064
85206
|
kind: "mutation",
|
|
85065
85207
|
auth: "admin"
|
|
85066
85208
|
}), method(object({
|
|
@@ -85518,7 +85660,8 @@ var MotionStatusSchema = object({
|
|
|
85518
85660
|
* writes this slice (not even a boot seed), and neither does the runner's
|
|
85519
85661
|
* phase machine: its phase is "a session is attached" for every on-motion
|
|
85520
85662
|
* session, not motion, and it now has its own `DetectionPhaseTransition`.
|
|
85521
|
-
* A provider's `isDetected`
|
|
85663
|
+
* A provider's `isDetected` and `getStatus` answer from the hub's slice
|
|
85664
|
+
* (`hubMotionNativeProvider`).
|
|
85522
85665
|
* - **Sensors** (Home Assistant binary sensors, Homematic, Matter, Alexa
|
|
85523
85666
|
* imports) — the provider pushes both edges itself, from the upstream
|
|
85524
85667
|
* system's own state change. That is the sensor's own fact.
|
|
@@ -96683,6 +96826,12 @@ Object.freeze({
|
|
|
96683
96826
|
addonId: null,
|
|
96684
96827
|
access: "view"
|
|
96685
96828
|
},
|
|
96829
|
+
"localNetwork.getHubAddresses": {
|
|
96830
|
+
capName: "local-network",
|
|
96831
|
+
capScope: "system",
|
|
96832
|
+
addonId: null,
|
|
96833
|
+
access: "view"
|
|
96834
|
+
},
|
|
96686
96835
|
"localNetwork.getNotificationEndpoint": {
|
|
96687
96836
|
capName: "local-network",
|
|
96688
96837
|
capScope: "system",
|
|
@@ -96737,6 +96886,12 @@ Object.freeze({
|
|
|
96737
96886
|
addonId: null,
|
|
96738
96887
|
access: "create"
|
|
96739
96888
|
},
|
|
96889
|
+
"localNetwork.setHubAddress": {
|
|
96890
|
+
capName: "local-network",
|
|
96891
|
+
capScope: "system",
|
|
96892
|
+
addonId: null,
|
|
96893
|
+
access: "create"
|
|
96894
|
+
},
|
|
96740
96895
|
"localNetwork.setNotificationEndpoint": {
|
|
96741
96896
|
capName: "local-network",
|
|
96742
96897
|
capScope: "system",
|
|
@@ -105136,6 +105291,8 @@ new Map(Object.entries({
|
|
|
105136
105291
|
"detection-blind": "device-events",
|
|
105137
105292
|
"node-online": "system",
|
|
105138
105293
|
"node-offline": "system",
|
|
105294
|
+
"node-restarting": "system",
|
|
105295
|
+
"node-updating": "system",
|
|
105139
105296
|
"node-inference-unavailable": "system",
|
|
105140
105297
|
"addon-crash-loop": "system",
|
|
105141
105298
|
"addon-update-available": "system",
|
|
@@ -105213,6 +105370,7 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
105213
105370
|
kinds: [
|
|
105214
105371
|
"node-offline",
|
|
105215
105372
|
"node-online",
|
|
105373
|
+
"node-restarting",
|
|
105216
105374
|
"node-inference-unavailable"
|
|
105217
105375
|
]
|
|
105218
105376
|
},
|
|
@@ -105234,6 +105392,7 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
105234
105392
|
label: "Server & container updates",
|
|
105235
105393
|
kinds: [
|
|
105236
105394
|
"server-update-available",
|
|
105395
|
+
"node-updating",
|
|
105237
105396
|
"server-updated",
|
|
105238
105397
|
"wrapper-update-available"
|
|
105239
105398
|
]
|
|
@@ -105381,6 +105540,7 @@ var STATE_SUMMARY_SECTION_VARS = [
|
|
|
105381
105540
|
kinds: [
|
|
105382
105541
|
"node-offline",
|
|
105383
105542
|
"node-online",
|
|
105543
|
+
"node-restarting",
|
|
105384
105544
|
"node-inference-unavailable"
|
|
105385
105545
|
]
|
|
105386
105546
|
},
|
|
@@ -105402,6 +105562,7 @@ var STATE_SUMMARY_SECTION_VARS = [
|
|
|
105402
105562
|
example: "server 1.2.377 → 1.2.378",
|
|
105403
105563
|
kinds: [
|
|
105404
105564
|
"server-update-available",
|
|
105565
|
+
"node-updating",
|
|
105405
105566
|
"server-updated",
|
|
105406
105567
|
"wrapper-update-available"
|
|
105407
105568
|
]
|
|
@@ -105434,7 +105595,7 @@ var STATE_SUMMARY_VARS = [
|
|
|
105434
105595
|
{
|
|
105435
105596
|
name: "summarySection",
|
|
105436
105597
|
label: "Summary: this section",
|
|
105437
|
-
description: "The section a per-section summary row is about
|
|
105598
|
+
description: "The section a per-section summary row is about; on a summary sent as one message, every section it reports, comma-separated.",
|
|
105438
105599
|
example: "Batterie scariche",
|
|
105439
105600
|
group: "system",
|
|
105440
105601
|
families: ["rule"],
|
|
@@ -108435,6 +108596,18 @@ function nextVacuumControlSlice(prev, next) {
|
|
|
108435
108596
|
}
|
|
108436
108597
|
//#endregion
|
|
108437
108598
|
//#region src/devices/dreame-camera-stream.ts
|
|
108599
|
+
/**
|
|
108600
|
+
* The robot camera as a stream the broker can pull — the pure facts.
|
|
108601
|
+
*
|
|
108602
|
+
* A Dreame relay carries video only between `open()` and `close()`, and the
|
|
108603
|
+
* robot runs on a battery, so the camera cannot sit in the catalog with a
|
|
108604
|
+
* URL the way a mains RTSP camera does. The seam is the broker's own battery
|
|
108605
|
+
* path: `battery.wakeForStream` opens the monitor, and the catalog then
|
|
108606
|
+
* names the local RFC 4571 server (`dreame-rfc4571-server.ts`) the broker
|
|
108607
|
+
* pulls. While the monitor is CLOSED the
|
|
108608
|
+
* catalog carries the broker's lazy sentinel (Reolink's shape): the stream is
|
|
108609
|
+
* listed, and the first dial asks the publisher to materialize it.
|
|
108610
|
+
*/
|
|
108438
108611
|
/** The one stream the robot camera offers. Half of the broker id (`<deviceId>/live`). */
|
|
108439
108612
|
var CAMERA_STREAM_ID = "live";
|
|
108440
108613
|
/** The plugin's cap: a monitor never outlives this, whoever is watching. */
|
|
@@ -108514,17 +108687,13 @@ function cameraStreamCatalog(session) {
|
|
|
108514
108687
|
/**
|
|
108515
108688
|
* The host the broker is told to dial. The provider and the ingest owner
|
|
108516
108689
|
* share the hub today, but a broker on another node reaches the hub only
|
|
108517
|
-
* through
|
|
108518
|
-
*
|
|
108690
|
+
* through the hub's address for agents — `local-network.getHubAddresses()
|
|
108691
|
+
* .cluster` (the Network page's override, else the detected LAN address).
|
|
108692
|
+
* Loopback when that names nothing: then the only broker that can dial at
|
|
108693
|
+
* all is this node's own.
|
|
108519
108694
|
*/
|
|
108520
|
-
function advertisedRfcHost(
|
|
108521
|
-
|
|
108522
|
-
try {
|
|
108523
|
-
const host = new URL(hubPublicUrl).hostname;
|
|
108524
|
-
return host.length > 0 ? host : "127.0.0.1";
|
|
108525
|
-
} catch {
|
|
108526
|
-
return "127.0.0.1";
|
|
108527
|
-
}
|
|
108695
|
+
function advertisedRfcHost(clusterBaseUrl) {
|
|
108696
|
+
return hubAddressHostname(clusterBaseUrl) ?? "127.0.0.1";
|
|
108528
108697
|
}
|
|
108529
108698
|
function rfcUrl(host, port) {
|
|
108530
108699
|
return `tcp://${host}:${String(port)}`;
|
|
@@ -154914,6 +155083,23 @@ var DreameCameraDevice = class extends DreameChildDevice {
|
|
|
154914
155083
|
}
|
|
154915
155084
|
unsubscribeRefresh = null;
|
|
154916
155085
|
/** Register the stream on the broker — the server, or the lazy sentinel (push semantics; the catalog is the durable copy). */
|
|
155086
|
+
/**
|
|
155087
|
+
* The hub's address for agents (`local-network.getHubAddresses().cluster`:
|
|
155088
|
+
* the Network page's override, else the detected LAN address). A failed
|
|
155089
|
+
* read is `null` — `advertisedRfcHost` then answers loopback, which this
|
|
155090
|
+
* node's own broker can still dial.
|
|
155091
|
+
*/
|
|
155092
|
+
async hubClusterAddress() {
|
|
155093
|
+
try {
|
|
155094
|
+
return (await this.ctx.api.localNetwork.getHubAddresses.query()).cluster.resolved;
|
|
155095
|
+
} catch (err) {
|
|
155096
|
+
this.ctx.logger.warn("robot camera: hub address unavailable — advertising loopback", {
|
|
155097
|
+
tags: { deviceId: this.id },
|
|
155098
|
+
meta: { error: err instanceof Error ? err.message : String(err) }
|
|
155099
|
+
});
|
|
155100
|
+
return null;
|
|
155101
|
+
}
|
|
155102
|
+
}
|
|
154917
155103
|
async publishRelay(session) {
|
|
154918
155104
|
const [descriptor] = cameraStreamCatalog(session);
|
|
154919
155105
|
if (descriptor === void 0) return;
|
|
@@ -154999,7 +155185,7 @@ var DreameCameraDevice = class extends DreameChildDevice {
|
|
|
154999
155185
|
rfc
|
|
155000
155186
|
};
|
|
155001
155187
|
this.session = {
|
|
155002
|
-
url: rfcUrl(advertisedRfcHost(
|
|
155188
|
+
url: rfcUrl(advertisedRfcHost(await this.hubClusterAddress()), rfc.port),
|
|
155003
155189
|
sdp: rfc.sdp
|
|
155004
155190
|
};
|
|
155005
155191
|
this.sessionOpenedAt = Date.now();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-provider-dreame",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.124",
|
|
4
4
|
"description": "Dreame robot-vacuum / lawn-mower device-provider addon for CamStack — wraps the @apocaliss92/nodedreame Dreamehome cloud client",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|