@camstack/addon-provider-dreame 0.2.134 → 0.2.136
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 +341 -37
- package/dist/addon.mjs +341 -37
- package/package.json +1 -1
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-
|
|
47
|
+
//#region ../types/dist/event-category-DOl51-Ij.mjs
|
|
48
48
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
49
49
|
EventCategory["SystemBoot"] = "system.boot";
|
|
50
50
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -123,9 +123,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
123
123
|
/**
|
|
124
124
|
* The node's one-shot runner boot check (D877): planned runners against the
|
|
125
125
|
* process service, `degraded` when any is failed, refused or missing. The
|
|
126
|
-
* alert centre turns it into one
|
|
126
|
+
* alert centre turns it into one critical alert.
|
|
127
127
|
*/
|
|
128
128
|
EventCategory["SystemRunnerCheck"] = "system.runner-check";
|
|
129
|
+
/**
|
|
130
|
+
* An alert EPISODE opened or closed, emitted by the alert centre for alerts
|
|
131
|
+
* of severity `critical` or `error` (`AlertEpisodePayload`). The alert
|
|
132
|
+
* centre sends no notification of its own: Notification Center turns this
|
|
133
|
+
* into the `alert-critical` / `alert-error` / `alert-critical-resolved`
|
|
134
|
+
* system-event kinds, and reconciles from the alerts store because a bus
|
|
135
|
+
* event may be dropped (D8, D11).
|
|
136
|
+
*/
|
|
137
|
+
EventCategory["AlertEpisode"] = "alert.episode";
|
|
129
138
|
EventCategory["AddonError"] = "addon.error";
|
|
130
139
|
EventCategory["AddonPageReady"] = "addon.page-ready";
|
|
131
140
|
EventCategory["AddonWidgetReady"] = "addon.widget-ready";
|
|
@@ -5450,7 +5459,7 @@ var ZodIssueCode$1 = {
|
|
|
5450
5459
|
var ZodFirstPartyTypeKind$1;
|
|
5451
5460
|
ZodFirstPartyTypeKind$1 || (ZodFirstPartyTypeKind$1 = {});
|
|
5452
5461
|
//#endregion
|
|
5453
|
-
//#region ../types/dist/sleep-
|
|
5462
|
+
//#region ../types/dist/sleep-BxjU_fJM.mjs
|
|
5454
5463
|
/**
|
|
5455
5464
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5456
5465
|
* window to float samples (D455).
|
|
@@ -13227,7 +13236,14 @@ var AlertSeveritySchema = _enum([
|
|
|
13227
13236
|
]);
|
|
13228
13237
|
var AlertActionSchema = object({
|
|
13229
13238
|
label: string(),
|
|
13230
|
-
href: string().optional()
|
|
13239
|
+
href: string().optional(),
|
|
13240
|
+
/**
|
|
13241
|
+
* How `href` is followed. Absent / `app`: an admin-ui route (client-side).
|
|
13242
|
+
* `server`: a route the HUB serves (an addon HTTP route such as an OAuth
|
|
13243
|
+
* start) — the browser must leave the SPA with a full navigation, because
|
|
13244
|
+
* the SPA has no such route and would bounce to the home page.
|
|
13245
|
+
*/
|
|
13246
|
+
navigation: _enum(["app", "server"]).optional()
|
|
13231
13247
|
});
|
|
13232
13248
|
var AlertStatusSchema = _enum([
|
|
13233
13249
|
"active",
|
|
@@ -17608,7 +17624,11 @@ var deviceDiscoveryCapability = {
|
|
|
17608
17624
|
};
|
|
17609
17625
|
/**
|
|
17610
17626
|
* `device-adoption` — generic discovery + adoption surface,
|
|
17611
|
-
* system-scoped
|
|
17627
|
+
* system-scoped collection (one provider per integration addon), routed
|
|
17628
|
+
* by explicit `{ addonId }` on direct `deviceAdoption.*` calls — the same
|
|
17629
|
+
* pin model as `connection-test`. The admin UI keeps using
|
|
17630
|
+
* `deviceManager.adoption*` (which already threads `addonId`). The de-HA-ified
|
|
17631
|
+
* successor to `ha-discovery`:
|
|
17612
17632
|
* keyed by `integrationId` (the addon resolves integrationId → broker
|
|
17613
17633
|
* internally) rather than a connection-specific `brokerId`, and it
|
|
17614
17634
|
* REUSES the shared `DiscoveredChildDevice` candidate type from
|
|
@@ -17773,7 +17793,7 @@ var ResyncResultSchema = object({
|
|
|
17773
17793
|
var deviceAdoptionCapability = {
|
|
17774
17794
|
name: "device-adoption",
|
|
17775
17795
|
scope: "system",
|
|
17776
|
-
mode: "
|
|
17796
|
+
mode: "collection",
|
|
17777
17797
|
status: {
|
|
17778
17798
|
schema: AdoptionStatusSchema,
|
|
17779
17799
|
kind: "poll"
|
|
@@ -41968,6 +41988,9 @@ var NcSystemEventKindSchema = _enum([
|
|
|
41968
41988
|
"server-updated",
|
|
41969
41989
|
"export-completed",
|
|
41970
41990
|
"backup-completed",
|
|
41991
|
+
"alert-critical",
|
|
41992
|
+
"alert-error",
|
|
41993
|
+
"alert-critical-resolved",
|
|
41971
41994
|
"camera-online",
|
|
41972
41995
|
"camera-offline",
|
|
41973
41996
|
"camera-disabled",
|
|
@@ -51044,7 +51067,10 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
|
|
|
51044
51067
|
}), method(object({ jobId: string().optional() }), StorageMigrationJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
51045
51068
|
kind: "mutation",
|
|
51046
51069
|
auth: "admin"
|
|
51047
|
-
}), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({
|
|
51070
|
+
}), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({ locationIds: array(string()).readonly() }), object({
|
|
51071
|
+
clear: boolean(),
|
|
51072
|
+
repointLocationId: string().optional()
|
|
51073
|
+
}), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
|
|
51048
51074
|
kind: "mutation",
|
|
51049
51075
|
auth: "admin"
|
|
51050
51076
|
}), method(StorageCleanupInputSchema, object({ jobId: string() }), {
|
|
@@ -55325,6 +55351,11 @@ onStatusChanged: { data: object({
|
|
|
55325
55351
|
*
|
|
55326
55352
|
* `kind: 'poll'` — cloud REST APIs typically have no push channel; the
|
|
55327
55353
|
* provider refreshes the slice on an interval and eagerly after commands.
|
|
55354
|
+
*
|
|
55355
|
+
* UNKNOWN IS NOT OFF. Every field the appliance reports separately is
|
|
55356
|
+
* nullable: `null` means "not known right now" (the appliance has not said,
|
|
55357
|
+
* the link is down, or the description does not carry it) and is never
|
|
55358
|
+
* rendered or exported as `false` / `0`. `availability` says why.
|
|
55328
55359
|
*/
|
|
55329
55360
|
var DishwasherStateSchema = _enum([
|
|
55330
55361
|
"idle",
|
|
@@ -55334,35 +55365,155 @@ var DishwasherStateSchema = _enum([
|
|
|
55334
55365
|
"error",
|
|
55335
55366
|
"unavailable"
|
|
55336
55367
|
]);
|
|
55368
|
+
/**
|
|
55369
|
+
* The appliance's own operation state, uncollapsed. `state` above is the coarse
|
|
55370
|
+
* view for compact surfaces; this is what the appliance said.
|
|
55371
|
+
*/
|
|
55372
|
+
var DishwasherOperationStateSchema = _enum([
|
|
55373
|
+
"Inactive",
|
|
55374
|
+
"Ready",
|
|
55375
|
+
"DelayedStart",
|
|
55376
|
+
"Run",
|
|
55377
|
+
"Pause",
|
|
55378
|
+
"ActionRequired",
|
|
55379
|
+
"Finished",
|
|
55380
|
+
"Error",
|
|
55381
|
+
"Aborting"
|
|
55382
|
+
]);
|
|
55383
|
+
/**
|
|
55384
|
+
* Why fields may be `null`:
|
|
55385
|
+
* - `available` — the link is up and the description is loaded;
|
|
55386
|
+
* - `offline` — the local link is down (values are unknown, not last-known);
|
|
55387
|
+
* - `description-missing` — the link is up but the appliance's description could not
|
|
55388
|
+
* be loaded, so its values cannot be decoded.
|
|
55389
|
+
*/
|
|
55390
|
+
var DishwasherAvailabilitySchema = _enum([
|
|
55391
|
+
"available",
|
|
55392
|
+
"offline",
|
|
55393
|
+
"description-missing"
|
|
55394
|
+
]);
|
|
55337
55395
|
var DishwasherConsumableLevelSchema = _enum([
|
|
55338
55396
|
"ok",
|
|
55339
55397
|
"low",
|
|
55340
55398
|
"empty"
|
|
55341
55399
|
]);
|
|
55342
55400
|
var DishwasherStatusSchema = object({
|
|
55401
|
+
availability: DishwasherAvailabilitySchema,
|
|
55402
|
+
/** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
|
|
55343
55403
|
state: DishwasherStateSchema,
|
|
55344
|
-
/**
|
|
55404
|
+
/** The appliance's operation state as reported; null when not known. */
|
|
55405
|
+
operationState: DishwasherOperationStateSchema.nullable(),
|
|
55406
|
+
/** Feature key of the ACTIVE (running) program, or null when none runs / not known. */
|
|
55345
55407
|
program: string().nullable(),
|
|
55346
|
-
/**
|
|
55408
|
+
/** Feature key of the SELECTED program (what Start would run), or null when none / not known. */
|
|
55409
|
+
selectedProgram: string().nullable(),
|
|
55410
|
+
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
55347
55411
|
availablePrograms: array(string()),
|
|
55348
|
-
/**
|
|
55349
|
-
|
|
55412
|
+
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
55413
|
+
remainingSeconds: number().int().nonnegative().nullable(),
|
|
55414
|
+
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
55415
|
+
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
55350
55416
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
55351
55417
|
progressPercent: number().min(0).max(100).nullable(),
|
|
55352
|
-
/** True when the door is reported open. */
|
|
55353
|
-
doorOpen: boolean(),
|
|
55354
|
-
/** True when
|
|
55355
|
-
|
|
55356
|
-
/**
|
|
55357
|
-
|
|
55418
|
+
/** True when the door is reported open; null when the door state is not known. */
|
|
55419
|
+
doorOpen: boolean().nullable(),
|
|
55420
|
+
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
55421
|
+
doorLocked: boolean().nullable(),
|
|
55422
|
+
/** True when remote start is allowed (door closed, power on, etc.); null when not known. */
|
|
55423
|
+
remoteStartAllowed: boolean().nullable(),
|
|
55424
|
+
/** True when the appliance accepts remote control now; null when not known. */
|
|
55425
|
+
remoteControlActive: boolean().nullable(),
|
|
55426
|
+
/** True while somebody operates the appliance at its panel; null when not reported. */
|
|
55427
|
+
localControlActive: boolean().nullable(),
|
|
55428
|
+
/** Main power / switched-on state; null when not known. */
|
|
55429
|
+
powerOn: boolean().nullable(),
|
|
55430
|
+
/** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
|
|
55431
|
+
powerState: string().nullable(),
|
|
55358
55432
|
saltLevel: DishwasherConsumableLevelSchema.nullable(),
|
|
55359
55433
|
rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
|
|
55360
|
-
|
|
55361
|
-
|
|
55434
|
+
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
55435
|
+
halfLoad: boolean().nullable(),
|
|
55436
|
+
hygienePlus: boolean().nullable(),
|
|
55437
|
+
/** Extra dry option when the appliance exposes it. */
|
|
55438
|
+
extraDry: boolean().nullable(),
|
|
55439
|
+
/** Intensive zone (lower basket) when the appliance exposes it. */
|
|
55440
|
+
intensiveZone: boolean().nullable(),
|
|
55441
|
+
/** VarioSpeed / VarioSpeed+ when the appliance exposes it. */
|
|
55442
|
+
varioSpeedPlus: boolean().nullable(),
|
|
55443
|
+
/** Child lock (controls disabled on the appliance); null when not known. */
|
|
55444
|
+
childLock: boolean().nullable(),
|
|
55445
|
+
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
55446
|
+
activeEvents: array(string()),
|
|
55447
|
+
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
55362
55448
|
errorCode: number().nullable(),
|
|
55449
|
+
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
55363
55450
|
errorLabel: string().nullable(),
|
|
55451
|
+
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
55364
55452
|
lastFetchedAt: number()
|
|
55365
55453
|
});
|
|
55454
|
+
var DeviceIdSchema = number().int().nonnegative();
|
|
55455
|
+
/** A value a program option or setting can take. */
|
|
55456
|
+
var DishwasherValueSchema = union([
|
|
55457
|
+
boolean(),
|
|
55458
|
+
string(),
|
|
55459
|
+
number()
|
|
55460
|
+
]);
|
|
55461
|
+
var DishwasherAccessSchema = _enum([
|
|
55462
|
+
"none",
|
|
55463
|
+
"read",
|
|
55464
|
+
"readWrite",
|
|
55465
|
+
"writeOnly",
|
|
55466
|
+
"readStatic"
|
|
55467
|
+
]);
|
|
55468
|
+
/**
|
|
55469
|
+
* One option or setting the appliance declares, with the constraints its description
|
|
55470
|
+
* gives. A `readWrite` descriptor that is `available` is what `setOption` accepts.
|
|
55471
|
+
*/
|
|
55472
|
+
var DishwasherOptionDescriptorSchema = object({
|
|
55473
|
+
/** Feature key (`Dishcare.Dishwasher.Option.ExtraDry`). */
|
|
55474
|
+
key: string(),
|
|
55475
|
+
/** Last segment of the key, for display. */
|
|
55476
|
+
name: string(),
|
|
55477
|
+
type: _enum([
|
|
55478
|
+
"boolean",
|
|
55479
|
+
"number",
|
|
55480
|
+
"enum",
|
|
55481
|
+
"string"
|
|
55482
|
+
]),
|
|
55483
|
+
access: DishwasherAccessSchema,
|
|
55484
|
+
/** The appliance reports this entity as currently available. */
|
|
55485
|
+
available: boolean(),
|
|
55486
|
+
/** Unit the description declares for a number; null when it declares none. */
|
|
55487
|
+
unit: string().nullable(),
|
|
55488
|
+
min: number().nullable(),
|
|
55489
|
+
max: number().nullable(),
|
|
55490
|
+
step: number().nullable(),
|
|
55491
|
+
/** Allowed members of an enum; null for other types. */
|
|
55492
|
+
enumValues: array(string()).nullable(),
|
|
55493
|
+
defaultValue: DishwasherValueSchema.nullable()
|
|
55494
|
+
});
|
|
55495
|
+
var DishwasherProgramSchema = object({
|
|
55496
|
+
/** Feature key (`Dishcare.Dishwasher.Program.Eco50`) — what `setProgram` / `start` take. */
|
|
55497
|
+
key: string(),
|
|
55498
|
+
name: string(),
|
|
55499
|
+
/** The appliance currently offers this program. */
|
|
55500
|
+
available: boolean(),
|
|
55501
|
+
/** The options this program lists, with the program-level access / availability / default. */
|
|
55502
|
+
options: array(DishwasherOptionDescriptorSchema)
|
|
55503
|
+
});
|
|
55504
|
+
var DishwasherOptionsSchema = object({
|
|
55505
|
+
availability: DishwasherAvailabilitySchema,
|
|
55506
|
+
/** What the appliance can be told to do, from the commands its description declares. */
|
|
55507
|
+
supportsStart: boolean(),
|
|
55508
|
+
supportsPause: boolean(),
|
|
55509
|
+
supportsResume: boolean(),
|
|
55510
|
+
supportsStop: boolean(),
|
|
55511
|
+
supportsPower: boolean(),
|
|
55512
|
+
/** Every program the description lists, with its options. */
|
|
55513
|
+
programs: array(DishwasherProgramSchema),
|
|
55514
|
+
/** Every option and setting entity the description lists (programs reference these by key). */
|
|
55515
|
+
options: array(DishwasherOptionDescriptorSchema)
|
|
55516
|
+
});
|
|
55366
55517
|
var dishwasherCapability = {
|
|
55367
55518
|
name: "dishwasher",
|
|
55368
55519
|
scope: "device",
|
|
@@ -55370,58 +55521,102 @@ var dishwasherCapability = {
|
|
|
55370
55521
|
mode: "singleton",
|
|
55371
55522
|
deviceTypes: [DeviceType.Dishwasher],
|
|
55372
55523
|
methods: {
|
|
55373
|
-
|
|
55524
|
+
/**
|
|
55525
|
+
* Start a program. Without `program` the selected one starts. `options` are
|
|
55526
|
+
* option feature keys; each is checked against the program's constraints.
|
|
55527
|
+
*/
|
|
55528
|
+
start: method(object({
|
|
55529
|
+
deviceId: DeviceIdSchema,
|
|
55530
|
+
program: string().min(1).optional(),
|
|
55531
|
+
options: record(string(), DishwasherValueSchema).optional()
|
|
55532
|
+
}), _void(), {
|
|
55374
55533
|
kind: "mutation",
|
|
55375
55534
|
auth: "protected"
|
|
55376
55535
|
}),
|
|
55377
|
-
pause: method(object({ deviceId:
|
|
55536
|
+
pause: method(object({ deviceId: DeviceIdSchema }), _void(), {
|
|
55378
55537
|
kind: "mutation",
|
|
55379
55538
|
auth: "protected"
|
|
55380
55539
|
}),
|
|
55381
|
-
|
|
55540
|
+
resume: method(object({ deviceId: DeviceIdSchema }), _void(), {
|
|
55382
55541
|
kind: "mutation",
|
|
55383
55542
|
auth: "protected"
|
|
55384
55543
|
}),
|
|
55544
|
+
stop: method(object({ deviceId: DeviceIdSchema }), _void(), {
|
|
55545
|
+
kind: "mutation",
|
|
55546
|
+
auth: "protected"
|
|
55547
|
+
}),
|
|
55548
|
+
/** Select (not start) a program; refused when the appliance does not offer it. */
|
|
55385
55549
|
setProgram: method(object({
|
|
55386
|
-
deviceId:
|
|
55550
|
+
deviceId: DeviceIdSchema,
|
|
55387
55551
|
program: string().min(1)
|
|
55388
55552
|
}), _void(), {
|
|
55389
55553
|
kind: "mutation",
|
|
55390
55554
|
auth: "protected"
|
|
55391
55555
|
}),
|
|
55392
55556
|
setPower: method(object({
|
|
55393
|
-
deviceId:
|
|
55557
|
+
deviceId: DeviceIdSchema,
|
|
55394
55558
|
on: boolean()
|
|
55395
55559
|
}), _void(), {
|
|
55396
55560
|
kind: "mutation",
|
|
55397
55561
|
auth: "protected"
|
|
55398
55562
|
}),
|
|
55399
55563
|
setHalfLoad: method(object({
|
|
55400
|
-
deviceId:
|
|
55564
|
+
deviceId: DeviceIdSchema,
|
|
55401
55565
|
on: boolean()
|
|
55402
55566
|
}), _void(), {
|
|
55403
55567
|
kind: "mutation",
|
|
55404
55568
|
auth: "protected"
|
|
55405
55569
|
}),
|
|
55406
55570
|
setHygienePlus: method(object({
|
|
55407
|
-
deviceId:
|
|
55571
|
+
deviceId: DeviceIdSchema,
|
|
55408
55572
|
on: boolean()
|
|
55409
55573
|
}), _void(), {
|
|
55410
55574
|
kind: "mutation",
|
|
55411
55575
|
auth: "protected"
|
|
55412
55576
|
}),
|
|
55577
|
+
setExtraDry: method(object({
|
|
55578
|
+
deviceId: DeviceIdSchema,
|
|
55579
|
+
on: boolean()
|
|
55580
|
+
}), _void(), {
|
|
55581
|
+
kind: "mutation",
|
|
55582
|
+
auth: "protected"
|
|
55583
|
+
}),
|
|
55584
|
+
setIntensiveZone: method(object({
|
|
55585
|
+
deviceId: DeviceIdSchema,
|
|
55586
|
+
on: boolean()
|
|
55587
|
+
}), _void(), {
|
|
55588
|
+
kind: "mutation",
|
|
55589
|
+
auth: "protected"
|
|
55590
|
+
}),
|
|
55591
|
+
setVarioSpeedPlus: method(object({
|
|
55592
|
+
deviceId: DeviceIdSchema,
|
|
55593
|
+
on: boolean()
|
|
55594
|
+
}), _void(), {
|
|
55595
|
+
kind: "mutation",
|
|
55596
|
+
auth: "protected"
|
|
55597
|
+
}),
|
|
55598
|
+
setChildLock: method(object({
|
|
55599
|
+
deviceId: DeviceIdSchema,
|
|
55600
|
+
on: boolean()
|
|
55601
|
+
}), _void(), {
|
|
55602
|
+
kind: "mutation",
|
|
55603
|
+
auth: "protected"
|
|
55604
|
+
}),
|
|
55605
|
+
/**
|
|
55606
|
+
* Write any option or setting by feature key. Refused when the description does
|
|
55607
|
+
* not list it, it is not writable or not available now, or the value is outside
|
|
55608
|
+
* its declared range / members.
|
|
55609
|
+
*/
|
|
55413
55610
|
setOption: method(object({
|
|
55414
|
-
deviceId:
|
|
55611
|
+
deviceId: DeviceIdSchema,
|
|
55415
55612
|
key: string().min(1),
|
|
55416
|
-
value:
|
|
55417
|
-
boolean(),
|
|
55418
|
-
string(),
|
|
55419
|
-
number()
|
|
55420
|
-
])
|
|
55613
|
+
value: DishwasherValueSchema
|
|
55421
55614
|
}), _void(), {
|
|
55422
55615
|
kind: "mutation",
|
|
55423
55616
|
auth: "protected"
|
|
55424
|
-
})
|
|
55617
|
+
}),
|
|
55618
|
+
/** What this appliance can do, from its own description — the UI is derived from it. */
|
|
55619
|
+
getOptions: method(object({ deviceId: DeviceIdSchema }), DishwasherOptionsSchema, { auth: "protected" })
|
|
55425
55620
|
},
|
|
55426
55621
|
status: {
|
|
55427
55622
|
schema: DishwasherStatusSchema,
|
|
@@ -69518,6 +69713,12 @@ Object.freeze({
|
|
|
69518
69713
|
addonId: null,
|
|
69519
69714
|
access: "view"
|
|
69520
69715
|
},
|
|
69716
|
+
"dishwasher.getOptions": {
|
|
69717
|
+
capName: "dishwasher",
|
|
69718
|
+
capScope: "device",
|
|
69719
|
+
addonId: null,
|
|
69720
|
+
access: "view"
|
|
69721
|
+
},
|
|
69521
69722
|
"dishwasher.getStatus": {
|
|
69522
69723
|
capName: "dishwasher",
|
|
69523
69724
|
capScope: "device",
|
|
@@ -69530,6 +69731,24 @@ Object.freeze({
|
|
|
69530
69731
|
addonId: null,
|
|
69531
69732
|
access: "create"
|
|
69532
69733
|
},
|
|
69734
|
+
"dishwasher.resume": {
|
|
69735
|
+
capName: "dishwasher",
|
|
69736
|
+
capScope: "device",
|
|
69737
|
+
addonId: null,
|
|
69738
|
+
access: "create"
|
|
69739
|
+
},
|
|
69740
|
+
"dishwasher.setChildLock": {
|
|
69741
|
+
capName: "dishwasher",
|
|
69742
|
+
capScope: "device",
|
|
69743
|
+
addonId: null,
|
|
69744
|
+
access: "create"
|
|
69745
|
+
},
|
|
69746
|
+
"dishwasher.setExtraDry": {
|
|
69747
|
+
capName: "dishwasher",
|
|
69748
|
+
capScope: "device",
|
|
69749
|
+
addonId: null,
|
|
69750
|
+
access: "create"
|
|
69751
|
+
},
|
|
69533
69752
|
"dishwasher.setHalfLoad": {
|
|
69534
69753
|
capName: "dishwasher",
|
|
69535
69754
|
capScope: "device",
|
|
@@ -69542,6 +69761,12 @@ Object.freeze({
|
|
|
69542
69761
|
addonId: null,
|
|
69543
69762
|
access: "create"
|
|
69544
69763
|
},
|
|
69764
|
+
"dishwasher.setIntensiveZone": {
|
|
69765
|
+
capName: "dishwasher",
|
|
69766
|
+
capScope: "device",
|
|
69767
|
+
addonId: null,
|
|
69768
|
+
access: "create"
|
|
69769
|
+
},
|
|
69545
69770
|
"dishwasher.setOption": {
|
|
69546
69771
|
capName: "dishwasher",
|
|
69547
69772
|
capScope: "device",
|
|
@@ -69560,6 +69785,12 @@ Object.freeze({
|
|
|
69560
69785
|
addonId: null,
|
|
69561
69786
|
access: "create"
|
|
69562
69787
|
},
|
|
69788
|
+
"dishwasher.setVarioSpeedPlus": {
|
|
69789
|
+
capName: "dishwasher",
|
|
69790
|
+
capScope: "device",
|
|
69791
|
+
addonId: null,
|
|
69792
|
+
access: "create"
|
|
69793
|
+
},
|
|
69563
69794
|
"dishwasher.start": {
|
|
69564
69795
|
capName: "dishwasher",
|
|
69565
69796
|
capScope: "device",
|
|
@@ -74006,6 +74237,12 @@ Object.freeze({
|
|
|
74006
74237
|
addonId: null,
|
|
74007
74238
|
access: "view"
|
|
74008
74239
|
},
|
|
74240
|
+
"storageMigration.moverClearance": {
|
|
74241
|
+
capName: "storage-migration",
|
|
74242
|
+
capScope: "system",
|
|
74243
|
+
addonId: null,
|
|
74244
|
+
access: "view"
|
|
74245
|
+
},
|
|
74009
74246
|
"storageMigration.movers": {
|
|
74010
74247
|
capName: "storage-migration",
|
|
74011
74248
|
capScope: "system",
|
|
@@ -76199,6 +76436,11 @@ Object.freeze({
|
|
|
76199
76436
|
form: "single",
|
|
76200
76437
|
optional: false
|
|
76201
76438
|
}],
|
|
76439
|
+
"dishwasher.getOptions": [{
|
|
76440
|
+
name: "deviceId",
|
|
76441
|
+
form: "single",
|
|
76442
|
+
optional: false
|
|
76443
|
+
}],
|
|
76202
76444
|
"dishwasher.getStatus": [{
|
|
76203
76445
|
name: "deviceId",
|
|
76204
76446
|
form: "single",
|
|
@@ -76209,6 +76451,21 @@ Object.freeze({
|
|
|
76209
76451
|
form: "single",
|
|
76210
76452
|
optional: false
|
|
76211
76453
|
}],
|
|
76454
|
+
"dishwasher.resume": [{
|
|
76455
|
+
name: "deviceId",
|
|
76456
|
+
form: "single",
|
|
76457
|
+
optional: false
|
|
76458
|
+
}],
|
|
76459
|
+
"dishwasher.setChildLock": [{
|
|
76460
|
+
name: "deviceId",
|
|
76461
|
+
form: "single",
|
|
76462
|
+
optional: false
|
|
76463
|
+
}],
|
|
76464
|
+
"dishwasher.setExtraDry": [{
|
|
76465
|
+
name: "deviceId",
|
|
76466
|
+
form: "single",
|
|
76467
|
+
optional: false
|
|
76468
|
+
}],
|
|
76212
76469
|
"dishwasher.setHalfLoad": [{
|
|
76213
76470
|
name: "deviceId",
|
|
76214
76471
|
form: "single",
|
|
@@ -76219,6 +76476,11 @@ Object.freeze({
|
|
|
76219
76476
|
form: "single",
|
|
76220
76477
|
optional: false
|
|
76221
76478
|
}],
|
|
76479
|
+
"dishwasher.setIntensiveZone": [{
|
|
76480
|
+
name: "deviceId",
|
|
76481
|
+
form: "single",
|
|
76482
|
+
optional: false
|
|
76483
|
+
}],
|
|
76222
76484
|
"dishwasher.setOption": [{
|
|
76223
76485
|
name: "deviceId",
|
|
76224
76486
|
form: "single",
|
|
@@ -76234,6 +76496,11 @@ Object.freeze({
|
|
|
76234
76496
|
form: "single",
|
|
76235
76497
|
optional: false
|
|
76236
76498
|
}],
|
|
76499
|
+
"dishwasher.setVarioSpeedPlus": [{
|
|
76500
|
+
name: "deviceId",
|
|
76501
|
+
form: "single",
|
|
76502
|
+
optional: false
|
|
76503
|
+
}],
|
|
76237
76504
|
"dishwasher.start": [{
|
|
76238
76505
|
name: "deviceId",
|
|
76239
76506
|
form: "single",
|
|
@@ -78275,6 +78542,9 @@ new Map(Object.entries({
|
|
|
78275
78542
|
"wrapper-update-available": "system",
|
|
78276
78543
|
"backup-completed": "system",
|
|
78277
78544
|
"export-completed": "system",
|
|
78545
|
+
"alert-critical": "system",
|
|
78546
|
+
"alert-error": "system",
|
|
78547
|
+
"alert-critical-resolved": "system",
|
|
78278
78548
|
"storage-location-low": "system",
|
|
78279
78549
|
"storage-location-critical": "system",
|
|
78280
78550
|
"storage-location-ok": "system",
|
|
@@ -78399,6 +78669,16 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
78399
78669
|
"storage-location-ok"
|
|
78400
78670
|
]
|
|
78401
78671
|
},
|
|
78672
|
+
{
|
|
78673
|
+
id: "alerts",
|
|
78674
|
+
family: "system",
|
|
78675
|
+
label: "Alerts",
|
|
78676
|
+
kinds: [
|
|
78677
|
+
"alert-critical",
|
|
78678
|
+
"alert-error",
|
|
78679
|
+
"alert-critical-resolved"
|
|
78680
|
+
]
|
|
78681
|
+
},
|
|
78402
78682
|
{
|
|
78403
78683
|
id: "alarm",
|
|
78404
78684
|
family: "alarm",
|
|
@@ -78443,6 +78723,21 @@ var NC_SENSOR_RAISED_FIELD_BY_KIND = Object.freeze(Object.fromEntries(Object.ent
|
|
|
78443
78723
|
return [[descriptor.kind, field]];
|
|
78444
78724
|
})));
|
|
78445
78725
|
Object.freeze(Object.keys(NC_SENSOR_RAISED_FIELD_BY_KIND));
|
|
78726
|
+
object({
|
|
78727
|
+
phase: _enum(["raised", "resolved"]),
|
|
78728
|
+
episodeId: string().min(1),
|
|
78729
|
+
alertId: string().min(1),
|
|
78730
|
+
severity: AlertSeveritySchema,
|
|
78731
|
+
category: string(),
|
|
78732
|
+
title: string(),
|
|
78733
|
+
message: string(),
|
|
78734
|
+
sourceType: string().optional(),
|
|
78735
|
+
sourceId: string().optional(),
|
|
78736
|
+
nodeId: string().optional(),
|
|
78737
|
+
/** The alert's own action link (where the operator acts on it), when it has one. */
|
|
78738
|
+
actionUrl: string().optional(),
|
|
78739
|
+
at: number()
|
|
78740
|
+
});
|
|
78446
78741
|
var RULE_BODY_ONLY = ["body"];
|
|
78447
78742
|
var RULE_TEXT = ["title", "body"];
|
|
78448
78743
|
var BATTERY = ["device-battery-low", "device-battery-normal"];
|
|
@@ -78452,6 +78747,11 @@ var TANK = [
|
|
|
78452
78747
|
"device-tank-full",
|
|
78453
78748
|
"device-tank-normal"
|
|
78454
78749
|
];
|
|
78750
|
+
var ALERT_EPISODE = [
|
|
78751
|
+
"alert-critical",
|
|
78752
|
+
"alert-error",
|
|
78753
|
+
"alert-critical-resolved"
|
|
78754
|
+
];
|
|
78455
78755
|
var UPDATES = [
|
|
78456
78756
|
"addon-update-available",
|
|
78457
78757
|
"server-update-available",
|
|
@@ -78644,14 +78944,14 @@ var STATE_SUMMARY_VARS = [
|
|
|
78644
78944
|
([...RULE_TEXT], [...CONSUMABLE]),
|
|
78645
78945
|
([...RULE_TEXT], [...TANK]),
|
|
78646
78946
|
[...RULE_TEXT],
|
|
78647
|
-
([...RULE_TEXT], [...UPDATES]),
|
|
78648
|
-
([...RULE_TEXT], [...UPDATES]),
|
|
78649
|
-
[...RULE_TEXT],
|
|
78947
|
+
([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
|
|
78948
|
+
([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
|
|
78650
78949
|
[...RULE_TEXT],
|
|
78651
78950
|
[...RULE_TEXT],
|
|
78652
78951
|
[...RULE_TEXT],
|
|
78653
78952
|
[...RULE_TEXT],
|
|
78654
78953
|
[...RULE_TEXT],
|
|
78954
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78655
78955
|
[...RULE_TEXT],
|
|
78656
78956
|
[...RULE_TEXT],
|
|
78657
78957
|
[...RULE_TEXT],
|
|
@@ -78669,7 +78969,11 @@ var STATE_SUMMARY_VARS = [
|
|
|
78669
78969
|
[...RULE_TEXT],
|
|
78670
78970
|
[...RULE_TEXT],
|
|
78671
78971
|
[...RULE_TEXT],
|
|
78672
|
-
[...RULE_TEXT],
|
|
78972
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78973
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78974
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78975
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78976
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78673
78977
|
[...RULE_TEXT],
|
|
78674
78978
|
[...RULE_TEXT],
|
|
78675
78979
|
[...RULE_TEXT],
|
package/dist/addon.mjs
CHANGED
|
@@ -41,7 +41,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
41
41
|
var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
42
42
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
43
43
|
//#endregion
|
|
44
|
-
//#region ../types/dist/event-category-
|
|
44
|
+
//#region ../types/dist/event-category-DOl51-Ij.mjs
|
|
45
45
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
46
46
|
EventCategory["SystemBoot"] = "system.boot";
|
|
47
47
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -120,9 +120,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
120
120
|
/**
|
|
121
121
|
* The node's one-shot runner boot check (D877): planned runners against the
|
|
122
122
|
* process service, `degraded` when any is failed, refused or missing. The
|
|
123
|
-
* alert centre turns it into one
|
|
123
|
+
* alert centre turns it into one critical alert.
|
|
124
124
|
*/
|
|
125
125
|
EventCategory["SystemRunnerCheck"] = "system.runner-check";
|
|
126
|
+
/**
|
|
127
|
+
* An alert EPISODE opened or closed, emitted by the alert centre for alerts
|
|
128
|
+
* of severity `critical` or `error` (`AlertEpisodePayload`). The alert
|
|
129
|
+
* centre sends no notification of its own: Notification Center turns this
|
|
130
|
+
* into the `alert-critical` / `alert-error` / `alert-critical-resolved`
|
|
131
|
+
* system-event kinds, and reconciles from the alerts store because a bus
|
|
132
|
+
* event may be dropped (D8, D11).
|
|
133
|
+
*/
|
|
134
|
+
EventCategory["AlertEpisode"] = "alert.episode";
|
|
126
135
|
EventCategory["AddonError"] = "addon.error";
|
|
127
136
|
EventCategory["AddonPageReady"] = "addon.page-ready";
|
|
128
137
|
EventCategory["AddonWidgetReady"] = "addon.widget-ready";
|
|
@@ -5447,7 +5456,7 @@ var ZodIssueCode$1 = {
|
|
|
5447
5456
|
var ZodFirstPartyTypeKind$1;
|
|
5448
5457
|
ZodFirstPartyTypeKind$1 || (ZodFirstPartyTypeKind$1 = {});
|
|
5449
5458
|
//#endregion
|
|
5450
|
-
//#region ../types/dist/sleep-
|
|
5459
|
+
//#region ../types/dist/sleep-BxjU_fJM.mjs
|
|
5451
5460
|
/**
|
|
5452
5461
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5453
5462
|
* window to float samples (D455).
|
|
@@ -13224,7 +13233,14 @@ var AlertSeveritySchema = _enum([
|
|
|
13224
13233
|
]);
|
|
13225
13234
|
var AlertActionSchema = object({
|
|
13226
13235
|
label: string(),
|
|
13227
|
-
href: string().optional()
|
|
13236
|
+
href: string().optional(),
|
|
13237
|
+
/**
|
|
13238
|
+
* How `href` is followed. Absent / `app`: an admin-ui route (client-side).
|
|
13239
|
+
* `server`: a route the HUB serves (an addon HTTP route such as an OAuth
|
|
13240
|
+
* start) — the browser must leave the SPA with a full navigation, because
|
|
13241
|
+
* the SPA has no such route and would bounce to the home page.
|
|
13242
|
+
*/
|
|
13243
|
+
navigation: _enum(["app", "server"]).optional()
|
|
13228
13244
|
});
|
|
13229
13245
|
var AlertStatusSchema = _enum([
|
|
13230
13246
|
"active",
|
|
@@ -17605,7 +17621,11 @@ var deviceDiscoveryCapability = {
|
|
|
17605
17621
|
};
|
|
17606
17622
|
/**
|
|
17607
17623
|
* `device-adoption` — generic discovery + adoption surface,
|
|
17608
|
-
* system-scoped
|
|
17624
|
+
* system-scoped collection (one provider per integration addon), routed
|
|
17625
|
+
* by explicit `{ addonId }` on direct `deviceAdoption.*` calls — the same
|
|
17626
|
+
* pin model as `connection-test`. The admin UI keeps using
|
|
17627
|
+
* `deviceManager.adoption*` (which already threads `addonId`). The de-HA-ified
|
|
17628
|
+
* successor to `ha-discovery`:
|
|
17609
17629
|
* keyed by `integrationId` (the addon resolves integrationId → broker
|
|
17610
17630
|
* internally) rather than a connection-specific `brokerId`, and it
|
|
17611
17631
|
* REUSES the shared `DiscoveredChildDevice` candidate type from
|
|
@@ -17770,7 +17790,7 @@ var ResyncResultSchema = object({
|
|
|
17770
17790
|
var deviceAdoptionCapability = {
|
|
17771
17791
|
name: "device-adoption",
|
|
17772
17792
|
scope: "system",
|
|
17773
|
-
mode: "
|
|
17793
|
+
mode: "collection",
|
|
17774
17794
|
status: {
|
|
17775
17795
|
schema: AdoptionStatusSchema,
|
|
17776
17796
|
kind: "poll"
|
|
@@ -41965,6 +41985,9 @@ var NcSystemEventKindSchema = _enum([
|
|
|
41965
41985
|
"server-updated",
|
|
41966
41986
|
"export-completed",
|
|
41967
41987
|
"backup-completed",
|
|
41988
|
+
"alert-critical",
|
|
41989
|
+
"alert-error",
|
|
41990
|
+
"alert-critical-resolved",
|
|
41968
41991
|
"camera-online",
|
|
41969
41992
|
"camera-offline",
|
|
41970
41993
|
"camera-disabled",
|
|
@@ -51041,7 +51064,10 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
|
|
|
51041
51064
|
}), method(object({ jobId: string().optional() }), StorageMigrationJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
51042
51065
|
kind: "mutation",
|
|
51043
51066
|
auth: "admin"
|
|
51044
|
-
}), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({
|
|
51067
|
+
}), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({ locationIds: array(string()).readonly() }), object({
|
|
51068
|
+
clear: boolean(),
|
|
51069
|
+
repointLocationId: string().optional()
|
|
51070
|
+
}), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
|
|
51045
51071
|
kind: "mutation",
|
|
51046
51072
|
auth: "admin"
|
|
51047
51073
|
}), method(StorageCleanupInputSchema, object({ jobId: string() }), {
|
|
@@ -55322,6 +55348,11 @@ onStatusChanged: { data: object({
|
|
|
55322
55348
|
*
|
|
55323
55349
|
* `kind: 'poll'` — cloud REST APIs typically have no push channel; the
|
|
55324
55350
|
* provider refreshes the slice on an interval and eagerly after commands.
|
|
55351
|
+
*
|
|
55352
|
+
* UNKNOWN IS NOT OFF. Every field the appliance reports separately is
|
|
55353
|
+
* nullable: `null` means "not known right now" (the appliance has not said,
|
|
55354
|
+
* the link is down, or the description does not carry it) and is never
|
|
55355
|
+
* rendered or exported as `false` / `0`. `availability` says why.
|
|
55325
55356
|
*/
|
|
55326
55357
|
var DishwasherStateSchema = _enum([
|
|
55327
55358
|
"idle",
|
|
@@ -55331,35 +55362,155 @@ var DishwasherStateSchema = _enum([
|
|
|
55331
55362
|
"error",
|
|
55332
55363
|
"unavailable"
|
|
55333
55364
|
]);
|
|
55365
|
+
/**
|
|
55366
|
+
* The appliance's own operation state, uncollapsed. `state` above is the coarse
|
|
55367
|
+
* view for compact surfaces; this is what the appliance said.
|
|
55368
|
+
*/
|
|
55369
|
+
var DishwasherOperationStateSchema = _enum([
|
|
55370
|
+
"Inactive",
|
|
55371
|
+
"Ready",
|
|
55372
|
+
"DelayedStart",
|
|
55373
|
+
"Run",
|
|
55374
|
+
"Pause",
|
|
55375
|
+
"ActionRequired",
|
|
55376
|
+
"Finished",
|
|
55377
|
+
"Error",
|
|
55378
|
+
"Aborting"
|
|
55379
|
+
]);
|
|
55380
|
+
/**
|
|
55381
|
+
* Why fields may be `null`:
|
|
55382
|
+
* - `available` — the link is up and the description is loaded;
|
|
55383
|
+
* - `offline` — the local link is down (values are unknown, not last-known);
|
|
55384
|
+
* - `description-missing` — the link is up but the appliance's description could not
|
|
55385
|
+
* be loaded, so its values cannot be decoded.
|
|
55386
|
+
*/
|
|
55387
|
+
var DishwasherAvailabilitySchema = _enum([
|
|
55388
|
+
"available",
|
|
55389
|
+
"offline",
|
|
55390
|
+
"description-missing"
|
|
55391
|
+
]);
|
|
55334
55392
|
var DishwasherConsumableLevelSchema = _enum([
|
|
55335
55393
|
"ok",
|
|
55336
55394
|
"low",
|
|
55337
55395
|
"empty"
|
|
55338
55396
|
]);
|
|
55339
55397
|
var DishwasherStatusSchema = object({
|
|
55398
|
+
availability: DishwasherAvailabilitySchema,
|
|
55399
|
+
/** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
|
|
55340
55400
|
state: DishwasherStateSchema,
|
|
55341
|
-
/**
|
|
55401
|
+
/** The appliance's operation state as reported; null when not known. */
|
|
55402
|
+
operationState: DishwasherOperationStateSchema.nullable(),
|
|
55403
|
+
/** Feature key of the ACTIVE (running) program, or null when none runs / not known. */
|
|
55342
55404
|
program: string().nullable(),
|
|
55343
|
-
/**
|
|
55405
|
+
/** Feature key of the SELECTED program (what Start would run), or null when none / not known. */
|
|
55406
|
+
selectedProgram: string().nullable(),
|
|
55407
|
+
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
55344
55408
|
availablePrograms: array(string()),
|
|
55345
|
-
/**
|
|
55346
|
-
|
|
55409
|
+
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
55410
|
+
remainingSeconds: number().int().nonnegative().nullable(),
|
|
55411
|
+
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
55412
|
+
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
55347
55413
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
55348
55414
|
progressPercent: number().min(0).max(100).nullable(),
|
|
55349
|
-
/** True when the door is reported open. */
|
|
55350
|
-
doorOpen: boolean(),
|
|
55351
|
-
/** True when
|
|
55352
|
-
|
|
55353
|
-
/**
|
|
55354
|
-
|
|
55415
|
+
/** True when the door is reported open; null when the door state is not known. */
|
|
55416
|
+
doorOpen: boolean().nullable(),
|
|
55417
|
+
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
55418
|
+
doorLocked: boolean().nullable(),
|
|
55419
|
+
/** True when remote start is allowed (door closed, power on, etc.); null when not known. */
|
|
55420
|
+
remoteStartAllowed: boolean().nullable(),
|
|
55421
|
+
/** True when the appliance accepts remote control now; null when not known. */
|
|
55422
|
+
remoteControlActive: boolean().nullable(),
|
|
55423
|
+
/** True while somebody operates the appliance at its panel; null when not reported. */
|
|
55424
|
+
localControlActive: boolean().nullable(),
|
|
55425
|
+
/** Main power / switched-on state; null when not known. */
|
|
55426
|
+
powerOn: boolean().nullable(),
|
|
55427
|
+
/** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
|
|
55428
|
+
powerState: string().nullable(),
|
|
55355
55429
|
saltLevel: DishwasherConsumableLevelSchema.nullable(),
|
|
55356
55430
|
rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
|
|
55357
|
-
|
|
55358
|
-
|
|
55431
|
+
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
55432
|
+
halfLoad: boolean().nullable(),
|
|
55433
|
+
hygienePlus: boolean().nullable(),
|
|
55434
|
+
/** Extra dry option when the appliance exposes it. */
|
|
55435
|
+
extraDry: boolean().nullable(),
|
|
55436
|
+
/** Intensive zone (lower basket) when the appliance exposes it. */
|
|
55437
|
+
intensiveZone: boolean().nullable(),
|
|
55438
|
+
/** VarioSpeed / VarioSpeed+ when the appliance exposes it. */
|
|
55439
|
+
varioSpeedPlus: boolean().nullable(),
|
|
55440
|
+
/** Child lock (controls disabled on the appliance); null when not known. */
|
|
55441
|
+
childLock: boolean().nullable(),
|
|
55442
|
+
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
55443
|
+
activeEvents: array(string()),
|
|
55444
|
+
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
55359
55445
|
errorCode: number().nullable(),
|
|
55446
|
+
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
55360
55447
|
errorLabel: string().nullable(),
|
|
55448
|
+
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
55361
55449
|
lastFetchedAt: number()
|
|
55362
55450
|
});
|
|
55451
|
+
var DeviceIdSchema = number().int().nonnegative();
|
|
55452
|
+
/** A value a program option or setting can take. */
|
|
55453
|
+
var DishwasherValueSchema = union([
|
|
55454
|
+
boolean(),
|
|
55455
|
+
string(),
|
|
55456
|
+
number()
|
|
55457
|
+
]);
|
|
55458
|
+
var DishwasherAccessSchema = _enum([
|
|
55459
|
+
"none",
|
|
55460
|
+
"read",
|
|
55461
|
+
"readWrite",
|
|
55462
|
+
"writeOnly",
|
|
55463
|
+
"readStatic"
|
|
55464
|
+
]);
|
|
55465
|
+
/**
|
|
55466
|
+
* One option or setting the appliance declares, with the constraints its description
|
|
55467
|
+
* gives. A `readWrite` descriptor that is `available` is what `setOption` accepts.
|
|
55468
|
+
*/
|
|
55469
|
+
var DishwasherOptionDescriptorSchema = object({
|
|
55470
|
+
/** Feature key (`Dishcare.Dishwasher.Option.ExtraDry`). */
|
|
55471
|
+
key: string(),
|
|
55472
|
+
/** Last segment of the key, for display. */
|
|
55473
|
+
name: string(),
|
|
55474
|
+
type: _enum([
|
|
55475
|
+
"boolean",
|
|
55476
|
+
"number",
|
|
55477
|
+
"enum",
|
|
55478
|
+
"string"
|
|
55479
|
+
]),
|
|
55480
|
+
access: DishwasherAccessSchema,
|
|
55481
|
+
/** The appliance reports this entity as currently available. */
|
|
55482
|
+
available: boolean(),
|
|
55483
|
+
/** Unit the description declares for a number; null when it declares none. */
|
|
55484
|
+
unit: string().nullable(),
|
|
55485
|
+
min: number().nullable(),
|
|
55486
|
+
max: number().nullable(),
|
|
55487
|
+
step: number().nullable(),
|
|
55488
|
+
/** Allowed members of an enum; null for other types. */
|
|
55489
|
+
enumValues: array(string()).nullable(),
|
|
55490
|
+
defaultValue: DishwasherValueSchema.nullable()
|
|
55491
|
+
});
|
|
55492
|
+
var DishwasherProgramSchema = object({
|
|
55493
|
+
/** Feature key (`Dishcare.Dishwasher.Program.Eco50`) — what `setProgram` / `start` take. */
|
|
55494
|
+
key: string(),
|
|
55495
|
+
name: string(),
|
|
55496
|
+
/** The appliance currently offers this program. */
|
|
55497
|
+
available: boolean(),
|
|
55498
|
+
/** The options this program lists, with the program-level access / availability / default. */
|
|
55499
|
+
options: array(DishwasherOptionDescriptorSchema)
|
|
55500
|
+
});
|
|
55501
|
+
var DishwasherOptionsSchema = object({
|
|
55502
|
+
availability: DishwasherAvailabilitySchema,
|
|
55503
|
+
/** What the appliance can be told to do, from the commands its description declares. */
|
|
55504
|
+
supportsStart: boolean(),
|
|
55505
|
+
supportsPause: boolean(),
|
|
55506
|
+
supportsResume: boolean(),
|
|
55507
|
+
supportsStop: boolean(),
|
|
55508
|
+
supportsPower: boolean(),
|
|
55509
|
+
/** Every program the description lists, with its options. */
|
|
55510
|
+
programs: array(DishwasherProgramSchema),
|
|
55511
|
+
/** Every option and setting entity the description lists (programs reference these by key). */
|
|
55512
|
+
options: array(DishwasherOptionDescriptorSchema)
|
|
55513
|
+
});
|
|
55363
55514
|
var dishwasherCapability = {
|
|
55364
55515
|
name: "dishwasher",
|
|
55365
55516
|
scope: "device",
|
|
@@ -55367,58 +55518,102 @@ var dishwasherCapability = {
|
|
|
55367
55518
|
mode: "singleton",
|
|
55368
55519
|
deviceTypes: [DeviceType.Dishwasher],
|
|
55369
55520
|
methods: {
|
|
55370
|
-
|
|
55521
|
+
/**
|
|
55522
|
+
* Start a program. Without `program` the selected one starts. `options` are
|
|
55523
|
+
* option feature keys; each is checked against the program's constraints.
|
|
55524
|
+
*/
|
|
55525
|
+
start: method(object({
|
|
55526
|
+
deviceId: DeviceIdSchema,
|
|
55527
|
+
program: string().min(1).optional(),
|
|
55528
|
+
options: record(string(), DishwasherValueSchema).optional()
|
|
55529
|
+
}), _void(), {
|
|
55371
55530
|
kind: "mutation",
|
|
55372
55531
|
auth: "protected"
|
|
55373
55532
|
}),
|
|
55374
|
-
pause: method(object({ deviceId:
|
|
55533
|
+
pause: method(object({ deviceId: DeviceIdSchema }), _void(), {
|
|
55375
55534
|
kind: "mutation",
|
|
55376
55535
|
auth: "protected"
|
|
55377
55536
|
}),
|
|
55378
|
-
|
|
55537
|
+
resume: method(object({ deviceId: DeviceIdSchema }), _void(), {
|
|
55379
55538
|
kind: "mutation",
|
|
55380
55539
|
auth: "protected"
|
|
55381
55540
|
}),
|
|
55541
|
+
stop: method(object({ deviceId: DeviceIdSchema }), _void(), {
|
|
55542
|
+
kind: "mutation",
|
|
55543
|
+
auth: "protected"
|
|
55544
|
+
}),
|
|
55545
|
+
/** Select (not start) a program; refused when the appliance does not offer it. */
|
|
55382
55546
|
setProgram: method(object({
|
|
55383
|
-
deviceId:
|
|
55547
|
+
deviceId: DeviceIdSchema,
|
|
55384
55548
|
program: string().min(1)
|
|
55385
55549
|
}), _void(), {
|
|
55386
55550
|
kind: "mutation",
|
|
55387
55551
|
auth: "protected"
|
|
55388
55552
|
}),
|
|
55389
55553
|
setPower: method(object({
|
|
55390
|
-
deviceId:
|
|
55554
|
+
deviceId: DeviceIdSchema,
|
|
55391
55555
|
on: boolean()
|
|
55392
55556
|
}), _void(), {
|
|
55393
55557
|
kind: "mutation",
|
|
55394
55558
|
auth: "protected"
|
|
55395
55559
|
}),
|
|
55396
55560
|
setHalfLoad: method(object({
|
|
55397
|
-
deviceId:
|
|
55561
|
+
deviceId: DeviceIdSchema,
|
|
55398
55562
|
on: boolean()
|
|
55399
55563
|
}), _void(), {
|
|
55400
55564
|
kind: "mutation",
|
|
55401
55565
|
auth: "protected"
|
|
55402
55566
|
}),
|
|
55403
55567
|
setHygienePlus: method(object({
|
|
55404
|
-
deviceId:
|
|
55568
|
+
deviceId: DeviceIdSchema,
|
|
55405
55569
|
on: boolean()
|
|
55406
55570
|
}), _void(), {
|
|
55407
55571
|
kind: "mutation",
|
|
55408
55572
|
auth: "protected"
|
|
55409
55573
|
}),
|
|
55574
|
+
setExtraDry: method(object({
|
|
55575
|
+
deviceId: DeviceIdSchema,
|
|
55576
|
+
on: boolean()
|
|
55577
|
+
}), _void(), {
|
|
55578
|
+
kind: "mutation",
|
|
55579
|
+
auth: "protected"
|
|
55580
|
+
}),
|
|
55581
|
+
setIntensiveZone: method(object({
|
|
55582
|
+
deviceId: DeviceIdSchema,
|
|
55583
|
+
on: boolean()
|
|
55584
|
+
}), _void(), {
|
|
55585
|
+
kind: "mutation",
|
|
55586
|
+
auth: "protected"
|
|
55587
|
+
}),
|
|
55588
|
+
setVarioSpeedPlus: method(object({
|
|
55589
|
+
deviceId: DeviceIdSchema,
|
|
55590
|
+
on: boolean()
|
|
55591
|
+
}), _void(), {
|
|
55592
|
+
kind: "mutation",
|
|
55593
|
+
auth: "protected"
|
|
55594
|
+
}),
|
|
55595
|
+
setChildLock: method(object({
|
|
55596
|
+
deviceId: DeviceIdSchema,
|
|
55597
|
+
on: boolean()
|
|
55598
|
+
}), _void(), {
|
|
55599
|
+
kind: "mutation",
|
|
55600
|
+
auth: "protected"
|
|
55601
|
+
}),
|
|
55602
|
+
/**
|
|
55603
|
+
* Write any option or setting by feature key. Refused when the description does
|
|
55604
|
+
* not list it, it is not writable or not available now, or the value is outside
|
|
55605
|
+
* its declared range / members.
|
|
55606
|
+
*/
|
|
55410
55607
|
setOption: method(object({
|
|
55411
|
-
deviceId:
|
|
55608
|
+
deviceId: DeviceIdSchema,
|
|
55412
55609
|
key: string().min(1),
|
|
55413
|
-
value:
|
|
55414
|
-
boolean(),
|
|
55415
|
-
string(),
|
|
55416
|
-
number()
|
|
55417
|
-
])
|
|
55610
|
+
value: DishwasherValueSchema
|
|
55418
55611
|
}), _void(), {
|
|
55419
55612
|
kind: "mutation",
|
|
55420
55613
|
auth: "protected"
|
|
55421
|
-
})
|
|
55614
|
+
}),
|
|
55615
|
+
/** What this appliance can do, from its own description — the UI is derived from it. */
|
|
55616
|
+
getOptions: method(object({ deviceId: DeviceIdSchema }), DishwasherOptionsSchema, { auth: "protected" })
|
|
55422
55617
|
},
|
|
55423
55618
|
status: {
|
|
55424
55619
|
schema: DishwasherStatusSchema,
|
|
@@ -69515,6 +69710,12 @@ Object.freeze({
|
|
|
69515
69710
|
addonId: null,
|
|
69516
69711
|
access: "view"
|
|
69517
69712
|
},
|
|
69713
|
+
"dishwasher.getOptions": {
|
|
69714
|
+
capName: "dishwasher",
|
|
69715
|
+
capScope: "device",
|
|
69716
|
+
addonId: null,
|
|
69717
|
+
access: "view"
|
|
69718
|
+
},
|
|
69518
69719
|
"dishwasher.getStatus": {
|
|
69519
69720
|
capName: "dishwasher",
|
|
69520
69721
|
capScope: "device",
|
|
@@ -69527,6 +69728,24 @@ Object.freeze({
|
|
|
69527
69728
|
addonId: null,
|
|
69528
69729
|
access: "create"
|
|
69529
69730
|
},
|
|
69731
|
+
"dishwasher.resume": {
|
|
69732
|
+
capName: "dishwasher",
|
|
69733
|
+
capScope: "device",
|
|
69734
|
+
addonId: null,
|
|
69735
|
+
access: "create"
|
|
69736
|
+
},
|
|
69737
|
+
"dishwasher.setChildLock": {
|
|
69738
|
+
capName: "dishwasher",
|
|
69739
|
+
capScope: "device",
|
|
69740
|
+
addonId: null,
|
|
69741
|
+
access: "create"
|
|
69742
|
+
},
|
|
69743
|
+
"dishwasher.setExtraDry": {
|
|
69744
|
+
capName: "dishwasher",
|
|
69745
|
+
capScope: "device",
|
|
69746
|
+
addonId: null,
|
|
69747
|
+
access: "create"
|
|
69748
|
+
},
|
|
69530
69749
|
"dishwasher.setHalfLoad": {
|
|
69531
69750
|
capName: "dishwasher",
|
|
69532
69751
|
capScope: "device",
|
|
@@ -69539,6 +69758,12 @@ Object.freeze({
|
|
|
69539
69758
|
addonId: null,
|
|
69540
69759
|
access: "create"
|
|
69541
69760
|
},
|
|
69761
|
+
"dishwasher.setIntensiveZone": {
|
|
69762
|
+
capName: "dishwasher",
|
|
69763
|
+
capScope: "device",
|
|
69764
|
+
addonId: null,
|
|
69765
|
+
access: "create"
|
|
69766
|
+
},
|
|
69542
69767
|
"dishwasher.setOption": {
|
|
69543
69768
|
capName: "dishwasher",
|
|
69544
69769
|
capScope: "device",
|
|
@@ -69557,6 +69782,12 @@ Object.freeze({
|
|
|
69557
69782
|
addonId: null,
|
|
69558
69783
|
access: "create"
|
|
69559
69784
|
},
|
|
69785
|
+
"dishwasher.setVarioSpeedPlus": {
|
|
69786
|
+
capName: "dishwasher",
|
|
69787
|
+
capScope: "device",
|
|
69788
|
+
addonId: null,
|
|
69789
|
+
access: "create"
|
|
69790
|
+
},
|
|
69560
69791
|
"dishwasher.start": {
|
|
69561
69792
|
capName: "dishwasher",
|
|
69562
69793
|
capScope: "device",
|
|
@@ -74003,6 +74234,12 @@ Object.freeze({
|
|
|
74003
74234
|
addonId: null,
|
|
74004
74235
|
access: "view"
|
|
74005
74236
|
},
|
|
74237
|
+
"storageMigration.moverClearance": {
|
|
74238
|
+
capName: "storage-migration",
|
|
74239
|
+
capScope: "system",
|
|
74240
|
+
addonId: null,
|
|
74241
|
+
access: "view"
|
|
74242
|
+
},
|
|
74006
74243
|
"storageMigration.movers": {
|
|
74007
74244
|
capName: "storage-migration",
|
|
74008
74245
|
capScope: "system",
|
|
@@ -76196,6 +76433,11 @@ Object.freeze({
|
|
|
76196
76433
|
form: "single",
|
|
76197
76434
|
optional: false
|
|
76198
76435
|
}],
|
|
76436
|
+
"dishwasher.getOptions": [{
|
|
76437
|
+
name: "deviceId",
|
|
76438
|
+
form: "single",
|
|
76439
|
+
optional: false
|
|
76440
|
+
}],
|
|
76199
76441
|
"dishwasher.getStatus": [{
|
|
76200
76442
|
name: "deviceId",
|
|
76201
76443
|
form: "single",
|
|
@@ -76206,6 +76448,21 @@ Object.freeze({
|
|
|
76206
76448
|
form: "single",
|
|
76207
76449
|
optional: false
|
|
76208
76450
|
}],
|
|
76451
|
+
"dishwasher.resume": [{
|
|
76452
|
+
name: "deviceId",
|
|
76453
|
+
form: "single",
|
|
76454
|
+
optional: false
|
|
76455
|
+
}],
|
|
76456
|
+
"dishwasher.setChildLock": [{
|
|
76457
|
+
name: "deviceId",
|
|
76458
|
+
form: "single",
|
|
76459
|
+
optional: false
|
|
76460
|
+
}],
|
|
76461
|
+
"dishwasher.setExtraDry": [{
|
|
76462
|
+
name: "deviceId",
|
|
76463
|
+
form: "single",
|
|
76464
|
+
optional: false
|
|
76465
|
+
}],
|
|
76209
76466
|
"dishwasher.setHalfLoad": [{
|
|
76210
76467
|
name: "deviceId",
|
|
76211
76468
|
form: "single",
|
|
@@ -76216,6 +76473,11 @@ Object.freeze({
|
|
|
76216
76473
|
form: "single",
|
|
76217
76474
|
optional: false
|
|
76218
76475
|
}],
|
|
76476
|
+
"dishwasher.setIntensiveZone": [{
|
|
76477
|
+
name: "deviceId",
|
|
76478
|
+
form: "single",
|
|
76479
|
+
optional: false
|
|
76480
|
+
}],
|
|
76219
76481
|
"dishwasher.setOption": [{
|
|
76220
76482
|
name: "deviceId",
|
|
76221
76483
|
form: "single",
|
|
@@ -76231,6 +76493,11 @@ Object.freeze({
|
|
|
76231
76493
|
form: "single",
|
|
76232
76494
|
optional: false
|
|
76233
76495
|
}],
|
|
76496
|
+
"dishwasher.setVarioSpeedPlus": [{
|
|
76497
|
+
name: "deviceId",
|
|
76498
|
+
form: "single",
|
|
76499
|
+
optional: false
|
|
76500
|
+
}],
|
|
76234
76501
|
"dishwasher.start": [{
|
|
76235
76502
|
name: "deviceId",
|
|
76236
76503
|
form: "single",
|
|
@@ -78272,6 +78539,9 @@ new Map(Object.entries({
|
|
|
78272
78539
|
"wrapper-update-available": "system",
|
|
78273
78540
|
"backup-completed": "system",
|
|
78274
78541
|
"export-completed": "system",
|
|
78542
|
+
"alert-critical": "system",
|
|
78543
|
+
"alert-error": "system",
|
|
78544
|
+
"alert-critical-resolved": "system",
|
|
78275
78545
|
"storage-location-low": "system",
|
|
78276
78546
|
"storage-location-critical": "system",
|
|
78277
78547
|
"storage-location-ok": "system",
|
|
@@ -78396,6 +78666,16 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
78396
78666
|
"storage-location-ok"
|
|
78397
78667
|
]
|
|
78398
78668
|
},
|
|
78669
|
+
{
|
|
78670
|
+
id: "alerts",
|
|
78671
|
+
family: "system",
|
|
78672
|
+
label: "Alerts",
|
|
78673
|
+
kinds: [
|
|
78674
|
+
"alert-critical",
|
|
78675
|
+
"alert-error",
|
|
78676
|
+
"alert-critical-resolved"
|
|
78677
|
+
]
|
|
78678
|
+
},
|
|
78399
78679
|
{
|
|
78400
78680
|
id: "alarm",
|
|
78401
78681
|
family: "alarm",
|
|
@@ -78440,6 +78720,21 @@ var NC_SENSOR_RAISED_FIELD_BY_KIND = Object.freeze(Object.fromEntries(Object.ent
|
|
|
78440
78720
|
return [[descriptor.kind, field]];
|
|
78441
78721
|
})));
|
|
78442
78722
|
Object.freeze(Object.keys(NC_SENSOR_RAISED_FIELD_BY_KIND));
|
|
78723
|
+
object({
|
|
78724
|
+
phase: _enum(["raised", "resolved"]),
|
|
78725
|
+
episodeId: string().min(1),
|
|
78726
|
+
alertId: string().min(1),
|
|
78727
|
+
severity: AlertSeveritySchema,
|
|
78728
|
+
category: string(),
|
|
78729
|
+
title: string(),
|
|
78730
|
+
message: string(),
|
|
78731
|
+
sourceType: string().optional(),
|
|
78732
|
+
sourceId: string().optional(),
|
|
78733
|
+
nodeId: string().optional(),
|
|
78734
|
+
/** The alert's own action link (where the operator acts on it), when it has one. */
|
|
78735
|
+
actionUrl: string().optional(),
|
|
78736
|
+
at: number()
|
|
78737
|
+
});
|
|
78443
78738
|
var RULE_BODY_ONLY = ["body"];
|
|
78444
78739
|
var RULE_TEXT = ["title", "body"];
|
|
78445
78740
|
var BATTERY = ["device-battery-low", "device-battery-normal"];
|
|
@@ -78449,6 +78744,11 @@ var TANK = [
|
|
|
78449
78744
|
"device-tank-full",
|
|
78450
78745
|
"device-tank-normal"
|
|
78451
78746
|
];
|
|
78747
|
+
var ALERT_EPISODE = [
|
|
78748
|
+
"alert-critical",
|
|
78749
|
+
"alert-error",
|
|
78750
|
+
"alert-critical-resolved"
|
|
78751
|
+
];
|
|
78452
78752
|
var UPDATES = [
|
|
78453
78753
|
"addon-update-available",
|
|
78454
78754
|
"server-update-available",
|
|
@@ -78641,14 +78941,14 @@ var STATE_SUMMARY_VARS = [
|
|
|
78641
78941
|
([...RULE_TEXT], [...CONSUMABLE]),
|
|
78642
78942
|
([...RULE_TEXT], [...TANK]),
|
|
78643
78943
|
[...RULE_TEXT],
|
|
78644
|
-
([...RULE_TEXT], [...UPDATES]),
|
|
78645
|
-
([...RULE_TEXT], [...UPDATES]),
|
|
78646
|
-
[...RULE_TEXT],
|
|
78944
|
+
([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
|
|
78945
|
+
([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
|
|
78647
78946
|
[...RULE_TEXT],
|
|
78648
78947
|
[...RULE_TEXT],
|
|
78649
78948
|
[...RULE_TEXT],
|
|
78650
78949
|
[...RULE_TEXT],
|
|
78651
78950
|
[...RULE_TEXT],
|
|
78951
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78652
78952
|
[...RULE_TEXT],
|
|
78653
78953
|
[...RULE_TEXT],
|
|
78654
78954
|
[...RULE_TEXT],
|
|
@@ -78666,7 +78966,11 @@ var STATE_SUMMARY_VARS = [
|
|
|
78666
78966
|
[...RULE_TEXT],
|
|
78667
78967
|
[...RULE_TEXT],
|
|
78668
78968
|
[...RULE_TEXT],
|
|
78669
|
-
[...RULE_TEXT],
|
|
78969
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78970
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78971
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78972
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78973
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78670
78974
|
[...RULE_TEXT],
|
|
78671
78975
|
[...RULE_TEXT],
|
|
78672
78976
|
[...RULE_TEXT],
|
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.136",
|
|
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",
|