@camstack/addon-provider-dreame 0.2.147 → 0.2.149

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 CHANGED
@@ -44,7 +44,7 @@ let net = require("net");
44
44
  net = __toESM(net, 1);
45
45
  let zlib = require("zlib");
46
46
  zlib = __toESM(zlib, 1);
47
- //#region ../types/dist/event-category-DOl51-Ij.mjs
47
+ //#region ../types/dist/event-category-BfJwUd2S.mjs
48
48
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
49
49
  EventCategory["SystemBoot"] = "system.boot";
50
50
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -361,6 +361,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
361
361
  */
362
362
  EventCategory["PipelineDetectionBlind"] = "pipeline.detection-blind";
363
363
  /**
364
+ * A camera's motion source has fired constantly with no subject for an hour
365
+ * (motion duty or session count over the bar, zero detections) — it is not
366
+ * blind, its motion zones or sensitivity want tuning (D907). Paired with
367
+ * {@link PipelineMotionCalm}.
368
+ */
369
+ EventCategory["PipelineMotionNoisy"] = "pipeline.motion-noisy";
370
+ /** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
371
+ EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
372
+ /**
364
373
  * Per-camera pipeline config was mutated by the orchestrator
365
374
  * (3-level settings change via `setAgentAddonDefaults` /
366
375
  * `setCameraStepToggle` / `setCameraPipelineForAgent` or a
@@ -732,6 +741,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
732
741
  EventCategory["BackupRestored"] = "backup.restored";
733
742
  EventCategory["NotificationDispatched"] = "notification.dispatched";
734
743
  EventCategory["NotificationFailed"] = "notification.failed";
744
+ /**
745
+ * A notification rule that cannot work (D905): its stored row does not load,
746
+ * or it still names a device / delivery target the prune CONFIRMED deleted.
747
+ * One edge per rule per distinct set of reasons; never on an unanswered read.
748
+ */
749
+ EventCategory["NotificationRuleBroken"] = "notification.rule-broken";
750
+ /** The clear of {@link NotificationRuleBroken}: the rule loads and names nothing deleted. */
751
+ EventCategory["NotificationRuleRepaired"] = "notification.rule-repaired";
735
752
  EventCategory["DeviceUpdated"] = "device.updated";
736
753
  /**
737
754
  * Transport-level connectivity. Emitted by the device driver when
@@ -5459,7 +5476,7 @@ var ZodIssueCode$1 = {
5459
5476
  var ZodFirstPartyTypeKind$1;
5460
5477
  ZodFirstPartyTypeKind$1 || (ZodFirstPartyTypeKind$1 = {});
5461
5478
  //#endregion
5462
- //#region ../types/dist/sleep-_sV1BE2f.mjs
5479
+ //#region ../types/dist/sleep-DJFUfKvA.mjs
5463
5480
  /**
5464
5481
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5465
5482
  * window to float samples (D455).
@@ -7988,7 +8005,7 @@ var EntryDescriptorSchema = object({
7988
8005
  /** JSON Schema of the entry body; `secret: true` marks a password field. */
7989
8006
  fields: record(string(), unknown())
7990
8007
  }).strict();
7991
- /** What crosses the wire and sits in the engine's catalog: JSON only, no Zod. */
8008
+ /** What crosses the wire from an addon: JSON only, no Zod. An unknown key is refused. */
7992
8009
  var RecordKindDeclarationSchema = object({
7993
8010
  database: _enum(RECORD_DATABASES).default("settings"),
7994
8011
  class: _enum(RECORD_CLASSES),
@@ -8007,14 +8024,6 @@ var RecordKindDeclarationSchema = object({
8007
8024
  secretPaths: array(string().min(1)).default([]),
8008
8025
  /** The id key of each array that carries a secret (`{ headers: 'name' }`). */
8009
8026
  secretArrayKeys: record(string(), string()).default({}),
8010
- /**
8011
- * RETIRED (D900): the legacy table a kind adopted from during the records
8012
- * migration. Nothing declares it any more and nothing reads it; the schema
8013
- * still ACCEPTS it because the catalog rows the migration wrote carry it
8014
- * (an orphaned kind is never redeclared) and an addon built before the
8015
- * removal still sends it. Never set it.
8016
- */
8017
- adoptsFrom: string().min(1).optional(),
8018
8027
  /** Kinds that must agree through `transact` sit in one file under one family name. */
8019
8028
  transactFamily: string().min(1).optional(),
8020
8029
  entry: EntryDescriptorSchema.optional()
@@ -12706,17 +12715,6 @@ object({
12706
12715
  createdAt: number(),
12707
12716
  updatedAt: number()
12708
12717
  });
12709
- object({
12710
- id: string(),
12711
- label: string(),
12712
- isAdmin: boolean().default(false),
12713
- allowedProviders: AllowedProviderSchema,
12714
- allowedDevices: AllowedDevicesSchema,
12715
- tokenHash: string(),
12716
- tokenPrefix: string(),
12717
- createdAt: number(),
12718
- lastUsedAt: number().optional()
12719
- });
12720
12718
  object({
12721
12719
  id: string(),
12722
12720
  userId: string(),
@@ -16698,16 +16696,36 @@ var RecordKindStateSchema = _enum([
16698
16696
  var DeclareKindResultSchema = object({
16699
16697
  kindId: number().int(),
16700
16698
  state: RecordKindStateSchema,
16701
- createdIndexes: array(string()),
16702
- /**
16703
- * RETIRED (D900): always `null`. It carried the records-migration boot guard;
16704
- * it stays on the wire, null, because an addon built before the removal reads
16705
- * an ABSENT field as "adoption pending" and refuses to start.
16706
- */
16707
- adoptionPending: _null()
16699
+ createdIndexes: array(string())
16708
16700
  });
16709
16701
  /** Keychain refs a write released (the old marker is gone from the row): the owner deletes the values. */
16710
16702
  var SecretRefsList = array(string());
16703
+ /**
16704
+ * One op of a `transact`: the single-row writes, each on a kind of the caller.
16705
+ * All ops of one call share ONE database file and ONE `transactFamily`.
16706
+ */
16707
+ var RecordTransactOpSchema = discriminatedUnion("op", [
16708
+ object({
16709
+ op: literal("put"),
16710
+ kind: RecordKindNameSchema,
16711
+ record: RecordInputSchema,
16712
+ ifRev: number().int().min(0).optional()
16713
+ }),
16714
+ object({
16715
+ op: literal("patch"),
16716
+ kind: RecordKindNameSchema,
16717
+ id: RecordIdSchema,
16718
+ data: RecordBodySchema,
16719
+ at: number().int().nullable().optional(),
16720
+ expiresAt: number().int().nullable().optional(),
16721
+ ifRev: number().int().min(1).optional()
16722
+ }),
16723
+ object({
16724
+ op: literal("delete"),
16725
+ kind: RecordKindNameSchema,
16726
+ id: RecordIdSchema
16727
+ })
16728
+ ]);
16711
16729
  var RecordSecretRefsSchema = record(string(), record(string(), string()));
16712
16730
  method(object({ kinds: record(RecordKindNameSchema, RecordKindDeclarationSchema) }), object({ kinds: record(string(), DeclareKindResultSchema) }), {
16713
16731
  kind: "mutation",
@@ -16814,6 +16832,16 @@ method(object({ kinds: record(RecordKindNameSchema, RecordKindDeclarationSchema)
16814
16832
  }), {
16815
16833
  kind: "mutation",
16816
16834
  auth: "admin"
16835
+ }), method(object({ ops: array(RecordTransactOpSchema).min(1).max(RECORD_BATCH_MAX) }), object({
16836
+ results: array(object({
16837
+ rev: number().int().nullable(),
16838
+ deleted: boolean()
16839
+ })),
16840
+ releasedRefs: SecretRefsList,
16841
+ secretRefs: SecretRefsList
16842
+ }), {
16843
+ kind: "mutation",
16844
+ auth: "admin"
16817
16845
  }), method(object({
16818
16846
  deviceId: number().int(),
16819
16847
  kinds: array(RecordKindNameSchema).optional()
@@ -42437,9 +42465,13 @@ var NcSystemEventKindSchema = _enum([
42437
42465
  "node-updating",
42438
42466
  "node-inference-unavailable",
42439
42467
  "detection-blind",
42468
+ "motion-noisy",
42469
+ "motion-calm",
42440
42470
  "recording-stalled",
42441
42471
  "recording-healthy",
42442
42472
  "recording-degraded",
42473
+ "device-attention-required",
42474
+ "device-attention-resolved",
42443
42475
  "storage-location-low",
42444
42476
  "storage-location-critical",
42445
42477
  "storage-location-ok",
@@ -42463,6 +42495,8 @@ var NcSystemEventKindSchema = _enum([
42463
42495
  "alert-critical",
42464
42496
  "alert-error",
42465
42497
  "alert-critical-resolved",
42498
+ "rule-broken",
42499
+ "rule-repaired",
42466
42500
  "camera-online",
42467
42501
  "camera-offline",
42468
42502
  "camera-disabled",
@@ -55786,6 +55820,16 @@ var DishwasherStatusSchema = object({
55786
55820
  powerState: string().nullable(),
55787
55821
  saltLevel: DishwasherConsumableLevelSchema.nullable(),
55788
55822
  rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
55823
+ /**
55824
+ * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
55825
+ * combined care-and-filter reminder raised); false when every such reminder reads clear; null
55826
+ * when none is reported. A cleared reminder is not an unknown one.
55827
+ */
55828
+ filterCleaningDue: boolean().nullable(),
55829
+ /** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
55830
+ machineCareDue: boolean().nullable(),
55831
+ /** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
55832
+ machineCareRemainingRuns: number().int().nonnegative().nullable(),
55789
55833
  /** Option states: null when the appliance does not expose the option or has not said. */
55790
55834
  halfLoad: boolean().nullable(),
55791
55835
  hygienePlus: boolean().nullable(),
@@ -64584,16 +64628,6 @@ var UpdateUserInputSchema = object({
64584
64628
  allowedDevices: record(string(), union([array(string()), literal("*")])).optional(),
64585
64629
  scopes: array(TokenScopeSchema).optional()
64586
64630
  });
64587
- var ApiKeySummarySchema = object({
64588
- id: string(),
64589
- label: string(),
64590
- isAdmin: boolean().default(false),
64591
- allowedProviders: union([array(string()), literal("*")]).optional(),
64592
- allowedDevices: record(string(), union([array(string()), literal("*")])).optional(),
64593
- tokenPrefix: string(),
64594
- createdAt: number(),
64595
- lastUsedAt: number().optional()
64596
- });
64597
64631
  var OauthSessionSummarySchema = object({
64598
64632
  id: string(),
64599
64633
  userId: string(),
@@ -64615,8 +64649,7 @@ var TotpStatusSchema = object({
64615
64649
  confirmedAt: number().nullable()
64616
64650
  });
64617
64651
  /**
64618
- * user-management — singleton capability for user accounts and the
64619
- * legacy API-key rows.
64652
+ * user-management — singleton capability for user accounts.
64620
64653
  *
64621
64654
  * v2 model: every method gated by `auth: 'admin'`. Admin-only delegation
64622
64655
  * — the subset check on `setUserScopes` is moot
@@ -64672,10 +64705,6 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
64672
64705
  }), UserSummarySchema.extend({ passwordHash: string() }).nullable(), {
64673
64706
  kind: "mutation",
64674
64707
  access: "view"
64675
- }), method(_void(), array(ApiKeySummarySchema), { auth: "admin" }), method(object({ id: string() }), object({ success: literal(true) }), {
64676
- kind: "mutation",
64677
- auth: "admin",
64678
- access: "delete"
64679
64708
  }), method(object({ userId: string() }), TotpSetupResultSchema, {
64680
64709
  kind: "mutation",
64681
64710
  auth: "admin",
@@ -74147,6 +74176,12 @@ Object.freeze({
74147
74176
  addonId: null,
74148
74177
  access: "view"
74149
74178
  },
74179
+ "records.transact": {
74180
+ capName: "records",
74181
+ capScope: "system",
74182
+ addonId: null,
74183
+ access: "create"
74184
+ },
74150
74185
  "sceneMonitor.captureReference": {
74151
74186
  capName: "scene-monitor",
74152
74187
  capScope: "device",
@@ -75479,12 +75514,6 @@ Object.freeze({
75479
75514
  addonId: null,
75480
75515
  access: "view"
75481
75516
  },
75482
- "userManagement.listApiKeys": {
75483
- capName: "user-management",
75484
- capScope: "system",
75485
- addonId: null,
75486
- access: "view"
75487
- },
75488
75517
  "userManagement.listExternalIdentities": {
75489
75518
  capName: "user-management",
75490
75519
  capScope: "system",
@@ -75539,12 +75568,6 @@ Object.freeze({
75539
75568
  addonId: null,
75540
75569
  access: "create"
75541
75570
  },
75542
- "userManagement.revokeApiKey": {
75543
- capName: "user-management",
75544
- capScope: "system",
75545
- addonId: null,
75546
- access: "delete"
75547
- },
75548
75571
  "userManagement.revokeOauthSession": {
75549
75572
  capName: "user-management",
75550
75573
  capScope: "system",
@@ -78909,9 +78932,13 @@ new Map(Object.entries({
78909
78932
  "stream-online": "device-events",
78910
78933
  "stream-offline": "device-events",
78911
78934
  "detection-blind": "device-events",
78935
+ "motion-noisy": "device-events",
78936
+ "motion-calm": "device-events",
78912
78937
  "recording-stalled": "device-events",
78913
78938
  "recording-healthy": "device-events",
78914
78939
  "recording-degraded": "device-events",
78940
+ "device-attention-required": "device-events",
78941
+ "device-attention-resolved": "device-events",
78915
78942
  "node-online": "system",
78916
78943
  "node-offline": "system",
78917
78944
  "node-restarting": "system",
@@ -78928,6 +78955,8 @@ new Map(Object.entries({
78928
78955
  "alert-critical": "system",
78929
78956
  "alert-error": "system",
78930
78957
  "alert-critical-resolved": "system",
78958
+ "rule-broken": "system",
78959
+ "rule-repaired": "system",
78931
78960
  "storage-location-low": "system",
78932
78961
  "storage-location-critical": "system",
78933
78962
  "storage-location-ok": "system",
@@ -78992,6 +79021,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
78992
79021
  label: "Detecting nothing",
78993
79022
  kinds: ["detection-blind"]
78994
79023
  },
79024
+ {
79025
+ id: "motion-noise",
79026
+ family: "device-events",
79027
+ label: "Motion without a subject",
79028
+ kinds: ["motion-noisy", "motion-calm"]
79029
+ },
78995
79030
  {
78996
79031
  id: "recording",
78997
79032
  family: "device-events",
@@ -79002,6 +79037,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
79002
79037
  "recording-degraded"
79003
79038
  ]
79004
79039
  },
79040
+ {
79041
+ id: "device-attention",
79042
+ family: "device-events",
79043
+ label: "Needs attention",
79044
+ kinds: ["device-attention-required", "device-attention-resolved"]
79045
+ },
79005
79046
  {
79006
79047
  id: "nodes",
79007
79048
  family: "system",
@@ -79062,6 +79103,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
79062
79103
  "alert-critical-resolved"
79063
79104
  ]
79064
79105
  },
79106
+ {
79107
+ id: "rule-health",
79108
+ family: "system",
79109
+ label: "Notification rules",
79110
+ kinds: ["rule-broken", "rule-repaired"]
79111
+ },
79065
79112
  {
79066
79113
  id: "alarm",
79067
79114
  family: "alarm",
@@ -79135,6 +79182,7 @@ var ALERT_EPISODE = [
79135
79182
  "alert-error",
79136
79183
  "alert-critical-resolved"
79137
79184
  ];
79185
+ var DEVICE_ATTENTION = ["device-attention-required", "device-attention-resolved"];
79138
79186
  var UPDATES = [
79139
79187
  "addon-update-available",
79140
79188
  "server-update-available",
@@ -79164,9 +79212,12 @@ var DEVICE_EVENTS = [
79164
79212
  "stream-online",
79165
79213
  "stream-offline",
79166
79214
  "detection-blind",
79215
+ "motion-noisy",
79216
+ "motion-calm",
79167
79217
  "recording-stalled",
79168
79218
  "recording-healthy",
79169
79219
  "recording-degraded",
79220
+ ...DEVICE_ATTENTION,
79170
79221
  ...ALARM
79171
79222
  ];
79172
79223
  /** Every kind a summary may speak about — the two summarisable families. */
@@ -79334,7 +79385,13 @@ var STATE_SUMMARY_VARS = [
79334
79385
  [...RULE_TEXT],
79335
79386
  [...RULE_TEXT],
79336
79387
  [...RULE_TEXT],
79337
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79388
+ [...RULE_TEXT],
79389
+ [...RULE_TEXT],
79390
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79391
+ [...RULE_TEXT],
79392
+ [...RULE_TEXT],
79393
+ [...RULE_TEXT],
79394
+ [...RULE_TEXT],
79338
79395
  [...RULE_TEXT],
79339
79396
  [...RULE_TEXT],
79340
79397
  [...RULE_TEXT],
@@ -79352,11 +79409,11 @@ var STATE_SUMMARY_VARS = [
79352
79409
  [...RULE_TEXT],
79353
79410
  [...RULE_TEXT],
79354
79411
  [...RULE_TEXT],
79412
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79355
79413
  ([...RULE_TEXT], [...ALERT_EPISODE]),
79414
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79356
79415
  ([...RULE_TEXT], [...ALERT_EPISODE]),
79357
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79358
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79359
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79416
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79360
79417
  [...RULE_TEXT],
79361
79418
  [...RULE_TEXT],
79362
79419
  [...RULE_TEXT],
@@ -79377,6 +79434,125 @@ var STATE_SUMMARY_VARS = [
79377
79434
  [...RULE_TEXT],
79378
79435
  ...STATE_SUMMARY_VARS
79379
79436
  ];
79437
+ new Map([
79438
+ {
79439
+ id: "device-connectivity",
79440
+ family: "device-events",
79441
+ label: "Device connectivity (offline / back online)",
79442
+ bad: ["device-offline"],
79443
+ recovery: ["device-online"],
79444
+ snapshotLabel: "Devices offline now",
79445
+ snapshotSection: "device-state"
79446
+ },
79447
+ {
79448
+ id: "device-switch",
79449
+ family: "device-events",
79450
+ label: "Device switched off / back on",
79451
+ bad: ["device-disabled"],
79452
+ recovery: ["device-enabled"],
79453
+ snapshotLabel: "Devices switched off now",
79454
+ snapshotSection: "device-state"
79455
+ },
79456
+ {
79457
+ id: "stream-connectivity",
79458
+ family: "device-events",
79459
+ label: "Stream connectivity (offline / back online)",
79460
+ bad: ["stream-offline"],
79461
+ recovery: ["stream-online"],
79462
+ snapshotLabel: "Streams offline now",
79463
+ snapshotSection: "streams"
79464
+ },
79465
+ {
79466
+ id: "battery",
79467
+ family: "device-events",
79468
+ label: "Battery (low / back to normal)",
79469
+ bad: ["device-battery-low"],
79470
+ recovery: ["device-battery-normal"],
79471
+ snapshotLabel: "Batteries low now",
79472
+ snapshotSection: "battery"
79473
+ },
79474
+ {
79475
+ id: "consumables",
79476
+ family: "device-events",
79477
+ label: "Consumables (low / replaced)",
79478
+ bad: ["device-consumable-low"],
79479
+ recovery: ["device-consumable-normal"],
79480
+ snapshotLabel: "Consumables low now",
79481
+ snapshotSection: "consumables"
79482
+ },
79483
+ {
79484
+ id: "tanks",
79485
+ family: "device-events",
79486
+ label: "Tanks (low or full / back to normal)",
79487
+ bad: ["device-tank-low", "device-tank-full"],
79488
+ recovery: ["device-tank-normal"],
79489
+ snapshotLabel: "Tanks low or full now",
79490
+ snapshotSection: "tanks"
79491
+ },
79492
+ {
79493
+ id: "motion-noise",
79494
+ family: "device-events",
79495
+ label: "Motion without a subject (constant / calm again)",
79496
+ bad: ["motion-noisy"],
79497
+ recovery: ["motion-calm"],
79498
+ snapshotLabel: "Cameras with constant motion now",
79499
+ snapshotSection: null
79500
+ },
79501
+ {
79502
+ id: "recording-health",
79503
+ family: "device-events",
79504
+ label: "Recording health (stalled or degraded / recording again)",
79505
+ bad: ["recording-stalled", "recording-degraded"],
79506
+ recovery: ["recording-healthy"],
79507
+ snapshotLabel: "Recordings stalled now",
79508
+ snapshotSection: null
79509
+ },
79510
+ {
79511
+ id: "device-attention",
79512
+ family: "device-events",
79513
+ label: "Device needs attention (raised / resolved)",
79514
+ bad: ["device-attention-required"],
79515
+ recovery: ["device-attention-resolved"],
79516
+ snapshotLabel: "Devices needing attention now",
79517
+ snapshotSection: null
79518
+ },
79519
+ {
79520
+ id: "node-connectivity",
79521
+ family: "system",
79522
+ label: "Node connectivity (offline / back online)",
79523
+ bad: ["node-offline"],
79524
+ recovery: ["node-online"],
79525
+ snapshotLabel: "Nodes offline now",
79526
+ snapshotSection: "nodes"
79527
+ },
79528
+ {
79529
+ id: "storage-space",
79530
+ family: "system",
79531
+ label: "Storage space (low or critical / ok again)",
79532
+ bad: ["storage-location-low", "storage-location-critical"],
79533
+ recovery: ["storage-location-ok"],
79534
+ snapshotLabel: "Storage locations low now",
79535
+ snapshotSection: null
79536
+ },
79537
+ {
79538
+ id: "critical-alerts",
79539
+ family: "system",
79540
+ label: "Critical alerts (raised / resolved)",
79541
+ bad: ["alert-critical"],
79542
+ recovery: ["alert-critical-resolved"],
79543
+ snapshotLabel: "Critical alerts open now",
79544
+ snapshotSection: null
79545
+ },
79546
+ {
79547
+ id: "rule-health",
79548
+ family: "system",
79549
+ label: "Rule health (broken / repaired)",
79550
+ bad: ["rule-broken"],
79551
+ recovery: ["rule-repaired"],
79552
+ snapshotLabel: "Notification rules broken now",
79553
+ snapshotSection: null
79554
+ }
79555
+ ].flatMap((spec) => [...spec.bad, ...spec.recovery].map((kind) => [kind, spec])));
79380
79556
  new Set([
79381
79557
  "disarmed",
79382
79558
  "armed_home",
@@ -132826,8 +133002,6 @@ function buildConnectionFormSchema() {
132826
133002
  id: "credentials",
132827
133003
  title: "Dreamehome account",
132828
133004
  titleKey: "provider-dreame:connection.s_credentials.title",
132829
- description: "Sign in with your Dreamehome (Dreame app) account credentials.",
132830
- descriptionKey: "provider-dreame:connection.s_credentials.description",
132831
133005
  columns: 1,
132832
133006
  fields: [{
132833
133007
  type: "text",
@@ -132849,8 +133023,6 @@ function buildConnectionFormSchema() {
132849
133023
  id: "region",
132850
133024
  title: "Region",
132851
133025
  titleKey: "provider-dreame:connection.s_region.title",
132852
- description: "Select the Dreame cloud region your account is registered in.",
132853
- descriptionKey: "provider-dreame:connection.s_region.description",
132854
133026
  columns: 1,
132855
133027
  fields: [{
132856
133028
  type: "select",
@@ -135269,6 +135441,81 @@ function rfcUrl(host, port) {
135269
135441
  return `tcp://${host}:${String(port)}`;
135270
135442
  }
135271
135443
  //#endregion
135444
+ //#region src/devices/dreame-pin-attention.ts
135445
+ var REFUSED_CODE_MINUS_ONE = /startMonitor refused \(code -1\)/;
135446
+ /** The refusal an error carries, or `null` when it is some other failure. */
135447
+ function classifyPinRefusal(err, accessCodeSet) {
135448
+ const message = err instanceof Error ? err.message : String(err);
135449
+ if (!REFUSED_CODE_MINUS_ONE.test(message)) return null;
135450
+ return accessCodeSet ? "rejected" : "missing";
135451
+ }
135452
+ function pinAlertId(deviceId) {
135453
+ return `dreame.pin-required:${String(deviceId)}`;
135454
+ }
135455
+ function buildPinAlert(deviceId, deviceName, reason) {
135456
+ const now = Date.now();
135457
+ return {
135458
+ id: pinAlertId(deviceId),
135459
+ category: "device.credentials-required",
135460
+ severity: "critical",
135461
+ title: reason === "missing" ? "Camera PIN required" : "Camera PIN rejected",
135462
+ message: reason === "missing" ? `${deviceName} needs its camera PIN before its video can open. Enter it in the device settings.` : `${deviceName} refused the camera PIN that is set. Enter the correct PIN in the device settings.`,
135463
+ action: {
135464
+ label: "Enter PIN",
135465
+ href: `/devices/${String(deviceId)}`,
135466
+ navigation: "app"
135467
+ },
135468
+ status: "active",
135469
+ read: false,
135470
+ createdAt: now,
135471
+ updatedAt: now,
135472
+ source: {
135473
+ type: "device",
135474
+ id: String(deviceId)
135475
+ },
135476
+ metadata: { episodeKey: reason }
135477
+ };
135478
+ }
135479
+ /**
135480
+ * One device's PIN episode. It raises the alert ONCE per episode, and while the
135481
+ * episode is open it tells the wake path to stand down: a refusal that needs the
135482
+ * operator is terminal until the PIN setting changes, so the broker's 30 s
135483
+ * re-dial must not re-open the monitor and fail again.
135484
+ */
135485
+ var PinAttention = class {
135486
+ ports;
135487
+ open = null;
135488
+ constructor(ports) {
135489
+ this.ports = ports;
135490
+ }
135491
+ /** True while the PIN is known to be unusable — the wake must not try. */
135492
+ get blocked() {
135493
+ return this.open !== null;
135494
+ }
135495
+ /** A wake failed. Raises the alert on the first refusal of an episode. */
135496
+ async refused(reason) {
135497
+ if (this.open !== null) return "already-open";
135498
+ this.open = reason;
135499
+ await this.ports.emit(buildPinAlert(this.ports.deviceId, this.ports.deviceName(), reason));
135500
+ return "raised";
135501
+ }
135502
+ /** A monitor opened: the PIN works, the episode is over. */
135503
+ async succeeded() {
135504
+ return this.settingChanged();
135505
+ }
135506
+ /**
135507
+ * The PIN setting changed: the episode is no longer known to be terminal, so
135508
+ * the next wake tries again. The alert is resolved here — a still-wrong PIN
135509
+ * raises a fresh episode on that wake.
135510
+ */
135511
+ async settingChanged() {
135512
+ if (this.open === null) return false;
135513
+ this.open = null;
135514
+ await this.ports.resolve(pinAlertId(this.ports.deviceId));
135515
+ return true;
135516
+ }
135517
+ };
135518
+ //#endregion
135272
135519
  //#region src/devices/dreame-navigation-actions.ts
135273
135520
  /** Forward throttle magnitude for a full-forward nudge (device speed units). */
135274
135521
  var FORWARD_SPEED = 200;
@@ -181460,15 +181707,13 @@ var CAMERA_SETTINGS_SCHEMA = { sections: [{
181460
181707
  id: "camera-backend",
181461
181708
  title: "Video backend",
181462
181709
  titleKey: "provider-dreame:camera_settings.s_camera-backend.title",
181463
- description: "Which cloud video service this robot streams through. The two are not interchangeable: only the Aliyun path is implemented here — a robot on Tencent can be seen in the Dreame app but not by CamStack, because Tencent offers it a proprietary P2P plane we do not speak. Changing this asks the ROBOT to switch and waits until its SDK reports ready; the robot is the authority on where it actually is.",
181710
+ description: "Only the Aliyun path is implemented; a robot on Tencent cannot be viewed by CamStack. Changing this asks the robot to switch.",
181464
181711
  descriptionKey: "provider-dreame:camera_settings.s_camera-backend.description",
181465
181712
  fields: [{
181466
181713
  type: "select",
181467
181714
  key: "videoVendor",
181468
181715
  label: "Backend",
181469
181716
  labelKey: "provider-dreame:camera_settings.s_camera-backend.videoVendor.label",
181470
- description: "Aliyun streams through a plain relay and works today. Tencent is offered so the other path can be tested once it exists.",
181471
- descriptionKey: "provider-dreame:camera_settings.s_camera-backend.videoVendor.description",
181472
181717
  options: [{
181473
181718
  value: "ali",
181474
181719
  label: "Aliyun LinkVisual (supported)",
@@ -181654,6 +181899,10 @@ var DreameCameraDevice = class extends DreameChildDevice {
181654
181899
  const data = event.data;
181655
181900
  if ((typeof data === "object" && data !== null && "deviceId" in data ? data.deviceId : null) !== this.id) return;
181656
181901
  if (this.session === null) {
181902
+ if (this.pinAttention.blocked) {
181903
+ this.ctx.logger.debug("robot camera: wake skipped — the camera PIN needs the operator", { tags: { deviceId: this.id } });
181904
+ return;
181905
+ }
181657
181906
  this.openStream().catch(() => void 0);
181658
181907
  return;
181659
181908
  }
@@ -181740,8 +181989,65 @@ var DreameCameraDevice = class extends DreameChildDevice {
181740
181989
  durationMs: Date.now() - startedAt
181741
181990
  };
181742
181991
  }
181992
+ /**
181993
+ * The PIN episode (D911): a monitor refused for want of the camera PIN needs
181994
+ * the operator, so it raises ONE critical alert and the wake stands down
181995
+ * until the PIN setting changes.
181996
+ */
181997
+ pinAttention = new PinAttention({
181998
+ deviceId: this.id,
181999
+ deviceName: () => this.name,
182000
+ emit: async (alert) => {
182001
+ const emit = this.ctx.api.alerts?.emit;
182002
+ if (emit === void 0) {
182003
+ this.ctx.logger.warn("robot camera: PIN alert skipped — alerts capability missing", { tags: { deviceId: this.id } });
182004
+ return;
182005
+ }
182006
+ try {
182007
+ await emit.mutate(alert);
182008
+ this.ctx.logger.warn("robot camera: PIN alert raised — the wake stops until the PIN changes", {
182009
+ tags: { deviceId: this.id },
182010
+ meta: {
182011
+ alertId: alert.id,
182012
+ episodeKey: alert.metadata?.["episodeKey"]
182013
+ }
182014
+ });
182015
+ } catch (err) {
182016
+ this.ctx.logger.warn("robot camera: PIN alert emit failed", {
182017
+ tags: { deviceId: this.id },
182018
+ meta: { error: errMsg(err) }
182019
+ });
182020
+ }
182021
+ },
182022
+ resolve: async (alertId) => {
182023
+ const update = this.ctx.api.alerts?.update;
182024
+ if (update === void 0) return;
182025
+ try {
182026
+ await update.mutate({
182027
+ alertId,
182028
+ patch: {
182029
+ status: "completed",
182030
+ read: true
182031
+ }
182032
+ });
182033
+ this.ctx.logger.info("robot camera: PIN alert resolved", {
182034
+ tags: { deviceId: this.id },
182035
+ meta: { alertId }
182036
+ });
182037
+ } catch (err) {
182038
+ this.ctx.logger.warn("robot camera: PIN alert resolve failed", {
182039
+ tags: { deviceId: this.id },
182040
+ meta: {
182041
+ alertId,
182042
+ error: errMsg(err)
182043
+ }
182044
+ });
182045
+ }
182046
+ }
182047
+ });
181743
182048
  openStream() {
181744
182049
  if (this.opening !== null) return this.opening;
182050
+ if (this.pinAttention.blocked) return Promise.reject(/* @__PURE__ */ new Error("camera PIN unusable — waiting for the operator"));
181745
182051
  const run = (async () => {
181746
182052
  const startedAt = Date.now();
181747
182053
  try {
@@ -181773,6 +182079,7 @@ var DreameCameraDevice = class extends DreameChildDevice {
181773
182079
  this.publishBattery();
181774
182080
  this.publishCatalog();
181775
182081
  await this.publishRelay(this.session);
182082
+ this.pinAttention.succeeded();
181776
182083
  this.ctx.logger.info("robot camera: monitor open, RTP server published", {
181777
182084
  tags: { deviceId: this.id },
181778
182085
  meta: {
@@ -181789,6 +182096,9 @@ var DreameCameraDevice = class extends DreameChildDevice {
181789
182096
  error: errMsg(err)
181790
182097
  }
181791
182098
  });
182099
+ const code = this.config.get("navigationAccessCode");
182100
+ const refusal = classifyPinRefusal(err, code !== void 0 && code !== "");
182101
+ if (refusal !== null) await this.pinAttention.refused(refusal);
181792
182102
  throw err;
181793
182103
  }
181794
182104
  })();
@@ -182006,6 +182316,7 @@ var DreameCameraDevice = class extends DreameChildDevice {
182006
182316
  }
182007
182317
  }
182008
182318
  if (!("navigationAccessCode" in patch)) return;
182319
+ await this.pinAttention.settingChanged();
182009
182320
  await this.closeStream("removed");
182010
182321
  this.controller = null;
182011
182322
  this.controllerHandle = null;
@@ -183825,8 +184136,6 @@ var DreameVacuumMapDevice = class extends DreameChildDevice {
183825
184136
  id: "map-style",
183826
184137
  title: "Map Style",
183827
184138
  titleKey: "provider-dreame:schema.s_map-style.title",
183828
- description: "Colour scheme and overlays for the rendered cleaning map.",
183829
- descriptionKey: "provider-dreame:schema.s_map-style.description",
183830
184139
  columns: 2,
183831
184140
  fields: [
183832
184141
  {