@camstack/addon-provider-dreo 0.2.127 → 0.2.129
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
|
@@ -35,7 +35,7 @@ var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["modu
|
|
|
35
35
|
//#endregion
|
|
36
36
|
let crypto$1 = require("crypto");
|
|
37
37
|
let events = require("events");
|
|
38
|
-
//#region ../types/dist/event-category-
|
|
38
|
+
//#region ../types/dist/event-category-DOl51-Ij.mjs
|
|
39
39
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
40
40
|
EventCategory["SystemBoot"] = "system.boot";
|
|
41
41
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -114,9 +114,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
114
114
|
/**
|
|
115
115
|
* The node's one-shot runner boot check (D877): planned runners against the
|
|
116
116
|
* process service, `degraded` when any is failed, refused or missing. The
|
|
117
|
-
* alert centre turns it into one
|
|
117
|
+
* alert centre turns it into one critical alert.
|
|
118
118
|
*/
|
|
119
119
|
EventCategory["SystemRunnerCheck"] = "system.runner-check";
|
|
120
|
+
/**
|
|
121
|
+
* An alert EPISODE opened or closed, emitted by the alert centre for alerts
|
|
122
|
+
* of severity `critical` or `error` (`AlertEpisodePayload`). The alert
|
|
123
|
+
* centre sends no notification of its own: Notification Center turns this
|
|
124
|
+
* into the `alert-critical` / `alert-error` / `alert-critical-resolved`
|
|
125
|
+
* system-event kinds, and reconciles from the alerts store because a bus
|
|
126
|
+
* event may be dropped (D8, D11).
|
|
127
|
+
*/
|
|
128
|
+
EventCategory["AlertEpisode"] = "alert.episode";
|
|
120
129
|
EventCategory["AddonError"] = "addon.error";
|
|
121
130
|
EventCategory["AddonPageReady"] = "addon.page-ready";
|
|
122
131
|
EventCategory["AddonWidgetReady"] = "addon.widget-ready";
|
|
@@ -5441,7 +5450,7 @@ var ZodIssueCode = {
|
|
|
5441
5450
|
var ZodFirstPartyTypeKind;
|
|
5442
5451
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5443
5452
|
//#endregion
|
|
5444
|
-
//#region ../types/dist/sleep-
|
|
5453
|
+
//#region ../types/dist/sleep-BxjU_fJM.mjs
|
|
5445
5454
|
/**
|
|
5446
5455
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5447
5456
|
* window to float samples (D455).
|
|
@@ -13204,7 +13213,14 @@ var AlertSeveritySchema = _enum([
|
|
|
13204
13213
|
]);
|
|
13205
13214
|
var AlertActionSchema = object({
|
|
13206
13215
|
label: string(),
|
|
13207
|
-
href: string().optional()
|
|
13216
|
+
href: string().optional(),
|
|
13217
|
+
/**
|
|
13218
|
+
* How `href` is followed. Absent / `app`: an admin-ui route (client-side).
|
|
13219
|
+
* `server`: a route the HUB serves (an addon HTTP route such as an OAuth
|
|
13220
|
+
* start) — the browser must leave the SPA with a full navigation, because
|
|
13221
|
+
* the SPA has no such route and would bounce to the home page.
|
|
13222
|
+
*/
|
|
13223
|
+
navigation: _enum(["app", "server"]).optional()
|
|
13208
13224
|
});
|
|
13209
13225
|
var AlertStatusSchema = _enum([
|
|
13210
13226
|
"active",
|
|
@@ -17585,7 +17601,11 @@ var deviceDiscoveryCapability = {
|
|
|
17585
17601
|
};
|
|
17586
17602
|
/**
|
|
17587
17603
|
* `device-adoption` — generic discovery + adoption surface,
|
|
17588
|
-
* system-scoped
|
|
17604
|
+
* system-scoped collection (one provider per integration addon), routed
|
|
17605
|
+
* by explicit `{ addonId }` on direct `deviceAdoption.*` calls — the same
|
|
17606
|
+
* pin model as `connection-test`. The admin UI keeps using
|
|
17607
|
+
* `deviceManager.adoption*` (which already threads `addonId`). The de-HA-ified
|
|
17608
|
+
* successor to `ha-discovery`:
|
|
17589
17609
|
* keyed by `integrationId` (the addon resolves integrationId → broker
|
|
17590
17610
|
* internally) rather than a connection-specific `brokerId`, and it
|
|
17591
17611
|
* REUSES the shared `DiscoveredChildDevice` candidate type from
|
|
@@ -17750,7 +17770,7 @@ var ResyncResultSchema = object({
|
|
|
17750
17770
|
var deviceAdoptionCapability = {
|
|
17751
17771
|
name: "device-adoption",
|
|
17752
17772
|
scope: "system",
|
|
17753
|
-
mode: "
|
|
17773
|
+
mode: "collection",
|
|
17754
17774
|
status: {
|
|
17755
17775
|
schema: AdoptionStatusSchema,
|
|
17756
17776
|
kind: "poll"
|
|
@@ -41933,6 +41953,9 @@ var NcSystemEventKindSchema = _enum([
|
|
|
41933
41953
|
"server-updated",
|
|
41934
41954
|
"export-completed",
|
|
41935
41955
|
"backup-completed",
|
|
41956
|
+
"alert-critical",
|
|
41957
|
+
"alert-error",
|
|
41958
|
+
"alert-critical-resolved",
|
|
41936
41959
|
"camera-online",
|
|
41937
41960
|
"camera-offline",
|
|
41938
41961
|
"camera-disabled",
|
|
@@ -51009,7 +51032,10 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
|
|
|
51009
51032
|
}), method(object({ jobId: string().optional() }), StorageMigrationJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
51010
51033
|
kind: "mutation",
|
|
51011
51034
|
auth: "admin"
|
|
51012
|
-
}), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({
|
|
51035
|
+
}), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({ locationIds: array(string()).readonly() }), object({
|
|
51036
|
+
clear: boolean(),
|
|
51037
|
+
repointLocationId: string().optional()
|
|
51038
|
+
}), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
|
|
51013
51039
|
kind: "mutation",
|
|
51014
51040
|
auth: "admin"
|
|
51015
51041
|
}), method(StorageCleanupInputSchema, object({ jobId: string() }), {
|
|
@@ -55273,6 +55299,11 @@ onStatusChanged: { data: object({
|
|
|
55273
55299
|
*
|
|
55274
55300
|
* `kind: 'poll'` — cloud REST APIs typically have no push channel; the
|
|
55275
55301
|
* provider refreshes the slice on an interval and eagerly after commands.
|
|
55302
|
+
*
|
|
55303
|
+
* UNKNOWN IS NOT OFF. Every field the appliance reports separately is
|
|
55304
|
+
* nullable: `null` means "not known right now" (the appliance has not said,
|
|
55305
|
+
* the link is down, or the description does not carry it) and is never
|
|
55306
|
+
* rendered or exported as `false` / `0`. `availability` says why.
|
|
55276
55307
|
*/
|
|
55277
55308
|
var DishwasherStateSchema = _enum([
|
|
55278
55309
|
"idle",
|
|
@@ -55282,35 +55313,155 @@ var DishwasherStateSchema = _enum([
|
|
|
55282
55313
|
"error",
|
|
55283
55314
|
"unavailable"
|
|
55284
55315
|
]);
|
|
55316
|
+
/**
|
|
55317
|
+
* The appliance's own operation state, uncollapsed. `state` above is the coarse
|
|
55318
|
+
* view for compact surfaces; this is what the appliance said.
|
|
55319
|
+
*/
|
|
55320
|
+
var DishwasherOperationStateSchema = _enum([
|
|
55321
|
+
"Inactive",
|
|
55322
|
+
"Ready",
|
|
55323
|
+
"DelayedStart",
|
|
55324
|
+
"Run",
|
|
55325
|
+
"Pause",
|
|
55326
|
+
"ActionRequired",
|
|
55327
|
+
"Finished",
|
|
55328
|
+
"Error",
|
|
55329
|
+
"Aborting"
|
|
55330
|
+
]);
|
|
55331
|
+
/**
|
|
55332
|
+
* Why fields may be `null`:
|
|
55333
|
+
* - `available` — the link is up and the description is loaded;
|
|
55334
|
+
* - `offline` — the local link is down (values are unknown, not last-known);
|
|
55335
|
+
* - `description-missing` — the link is up but the appliance's description could not
|
|
55336
|
+
* be loaded, so its values cannot be decoded.
|
|
55337
|
+
*/
|
|
55338
|
+
var DishwasherAvailabilitySchema = _enum([
|
|
55339
|
+
"available",
|
|
55340
|
+
"offline",
|
|
55341
|
+
"description-missing"
|
|
55342
|
+
]);
|
|
55285
55343
|
var DishwasherConsumableLevelSchema = _enum([
|
|
55286
55344
|
"ok",
|
|
55287
55345
|
"low",
|
|
55288
55346
|
"empty"
|
|
55289
55347
|
]);
|
|
55290
55348
|
var DishwasherStatusSchema = object({
|
|
55349
|
+
availability: DishwasherAvailabilitySchema,
|
|
55350
|
+
/** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
|
|
55291
55351
|
state: DishwasherStateSchema,
|
|
55292
|
-
/**
|
|
55352
|
+
/** The appliance's operation state as reported; null when not known. */
|
|
55353
|
+
operationState: DishwasherOperationStateSchema.nullable(),
|
|
55354
|
+
/** Feature key of the ACTIVE (running) program, or null when none runs / not known. */
|
|
55293
55355
|
program: string().nullable(),
|
|
55294
|
-
/**
|
|
55356
|
+
/** Feature key of the SELECTED program (what Start would run), or null when none / not known. */
|
|
55357
|
+
selectedProgram: string().nullable(),
|
|
55358
|
+
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
55295
55359
|
availablePrograms: array(string()),
|
|
55296
|
-
/**
|
|
55297
|
-
|
|
55360
|
+
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
55361
|
+
remainingSeconds: number().int().nonnegative().nullable(),
|
|
55362
|
+
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
55363
|
+
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
55298
55364
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
55299
55365
|
progressPercent: number().min(0).max(100).nullable(),
|
|
55300
|
-
/** True when the door is reported open. */
|
|
55301
|
-
doorOpen: boolean(),
|
|
55302
|
-
/** True when
|
|
55303
|
-
|
|
55304
|
-
/**
|
|
55305
|
-
|
|
55366
|
+
/** True when the door is reported open; null when the door state is not known. */
|
|
55367
|
+
doorOpen: boolean().nullable(),
|
|
55368
|
+
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
55369
|
+
doorLocked: boolean().nullable(),
|
|
55370
|
+
/** True when remote start is allowed (door closed, power on, etc.); null when not known. */
|
|
55371
|
+
remoteStartAllowed: boolean().nullable(),
|
|
55372
|
+
/** True when the appliance accepts remote control now; null when not known. */
|
|
55373
|
+
remoteControlActive: boolean().nullable(),
|
|
55374
|
+
/** True while somebody operates the appliance at its panel; null when not reported. */
|
|
55375
|
+
localControlActive: boolean().nullable(),
|
|
55376
|
+
/** Main power / switched-on state; null when not known. */
|
|
55377
|
+
powerOn: boolean().nullable(),
|
|
55378
|
+
/** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
|
|
55379
|
+
powerState: string().nullable(),
|
|
55306
55380
|
saltLevel: DishwasherConsumableLevelSchema.nullable(),
|
|
55307
55381
|
rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
|
|
55308
|
-
|
|
55309
|
-
|
|
55382
|
+
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
55383
|
+
halfLoad: boolean().nullable(),
|
|
55384
|
+
hygienePlus: boolean().nullable(),
|
|
55385
|
+
/** Extra dry option when the appliance exposes it. */
|
|
55386
|
+
extraDry: boolean().nullable(),
|
|
55387
|
+
/** Intensive zone (lower basket) when the appliance exposes it. */
|
|
55388
|
+
intensiveZone: boolean().nullable(),
|
|
55389
|
+
/** VarioSpeed / VarioSpeed+ when the appliance exposes it. */
|
|
55390
|
+
varioSpeedPlus: boolean().nullable(),
|
|
55391
|
+
/** Child lock (controls disabled on the appliance); null when not known. */
|
|
55392
|
+
childLock: boolean().nullable(),
|
|
55393
|
+
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
55394
|
+
activeEvents: array(string()),
|
|
55395
|
+
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
55310
55396
|
errorCode: number().nullable(),
|
|
55397
|
+
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
55311
55398
|
errorLabel: string().nullable(),
|
|
55399
|
+
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
55312
55400
|
lastFetchedAt: number()
|
|
55313
55401
|
});
|
|
55402
|
+
var DeviceIdSchema = number().int().nonnegative();
|
|
55403
|
+
/** A value a program option or setting can take. */
|
|
55404
|
+
var DishwasherValueSchema = union([
|
|
55405
|
+
boolean(),
|
|
55406
|
+
string(),
|
|
55407
|
+
number()
|
|
55408
|
+
]);
|
|
55409
|
+
var DishwasherAccessSchema = _enum([
|
|
55410
|
+
"none",
|
|
55411
|
+
"read",
|
|
55412
|
+
"readWrite",
|
|
55413
|
+
"writeOnly",
|
|
55414
|
+
"readStatic"
|
|
55415
|
+
]);
|
|
55416
|
+
/**
|
|
55417
|
+
* One option or setting the appliance declares, with the constraints its description
|
|
55418
|
+
* gives. A `readWrite` descriptor that is `available` is what `setOption` accepts.
|
|
55419
|
+
*/
|
|
55420
|
+
var DishwasherOptionDescriptorSchema = object({
|
|
55421
|
+
/** Feature key (`Dishcare.Dishwasher.Option.ExtraDry`). */
|
|
55422
|
+
key: string(),
|
|
55423
|
+
/** Last segment of the key, for display. */
|
|
55424
|
+
name: string(),
|
|
55425
|
+
type: _enum([
|
|
55426
|
+
"boolean",
|
|
55427
|
+
"number",
|
|
55428
|
+
"enum",
|
|
55429
|
+
"string"
|
|
55430
|
+
]),
|
|
55431
|
+
access: DishwasherAccessSchema,
|
|
55432
|
+
/** The appliance reports this entity as currently available. */
|
|
55433
|
+
available: boolean(),
|
|
55434
|
+
/** Unit the description declares for a number; null when it declares none. */
|
|
55435
|
+
unit: string().nullable(),
|
|
55436
|
+
min: number().nullable(),
|
|
55437
|
+
max: number().nullable(),
|
|
55438
|
+
step: number().nullable(),
|
|
55439
|
+
/** Allowed members of an enum; null for other types. */
|
|
55440
|
+
enumValues: array(string()).nullable(),
|
|
55441
|
+
defaultValue: DishwasherValueSchema.nullable()
|
|
55442
|
+
});
|
|
55443
|
+
var DishwasherProgramSchema = object({
|
|
55444
|
+
/** Feature key (`Dishcare.Dishwasher.Program.Eco50`) — what `setProgram` / `start` take. */
|
|
55445
|
+
key: string(),
|
|
55446
|
+
name: string(),
|
|
55447
|
+
/** The appliance currently offers this program. */
|
|
55448
|
+
available: boolean(),
|
|
55449
|
+
/** The options this program lists, with the program-level access / availability / default. */
|
|
55450
|
+
options: array(DishwasherOptionDescriptorSchema)
|
|
55451
|
+
});
|
|
55452
|
+
var DishwasherOptionsSchema = object({
|
|
55453
|
+
availability: DishwasherAvailabilitySchema,
|
|
55454
|
+
/** What the appliance can be told to do, from the commands its description declares. */
|
|
55455
|
+
supportsStart: boolean(),
|
|
55456
|
+
supportsPause: boolean(),
|
|
55457
|
+
supportsResume: boolean(),
|
|
55458
|
+
supportsStop: boolean(),
|
|
55459
|
+
supportsPower: boolean(),
|
|
55460
|
+
/** Every program the description lists, with its options. */
|
|
55461
|
+
programs: array(DishwasherProgramSchema),
|
|
55462
|
+
/** Every option and setting entity the description lists (programs reference these by key). */
|
|
55463
|
+
options: array(DishwasherOptionDescriptorSchema)
|
|
55464
|
+
});
|
|
55314
55465
|
var dishwasherCapability = {
|
|
55315
55466
|
name: "dishwasher",
|
|
55316
55467
|
scope: "device",
|
|
@@ -55318,58 +55469,102 @@ var dishwasherCapability = {
|
|
|
55318
55469
|
mode: "singleton",
|
|
55319
55470
|
deviceTypes: [DeviceType.Dishwasher],
|
|
55320
55471
|
methods: {
|
|
55321
|
-
|
|
55472
|
+
/**
|
|
55473
|
+
* Start a program. Without `program` the selected one starts. `options` are
|
|
55474
|
+
* option feature keys; each is checked against the program's constraints.
|
|
55475
|
+
*/
|
|
55476
|
+
start: method(object({
|
|
55477
|
+
deviceId: DeviceIdSchema,
|
|
55478
|
+
program: string().min(1).optional(),
|
|
55479
|
+
options: record(string(), DishwasherValueSchema).optional()
|
|
55480
|
+
}), _void(), {
|
|
55322
55481
|
kind: "mutation",
|
|
55323
55482
|
auth: "protected"
|
|
55324
55483
|
}),
|
|
55325
|
-
pause: method(object({ deviceId:
|
|
55484
|
+
pause: method(object({ deviceId: DeviceIdSchema }), _void(), {
|
|
55326
55485
|
kind: "mutation",
|
|
55327
55486
|
auth: "protected"
|
|
55328
55487
|
}),
|
|
55329
|
-
|
|
55488
|
+
resume: method(object({ deviceId: DeviceIdSchema }), _void(), {
|
|
55330
55489
|
kind: "mutation",
|
|
55331
55490
|
auth: "protected"
|
|
55332
55491
|
}),
|
|
55492
|
+
stop: method(object({ deviceId: DeviceIdSchema }), _void(), {
|
|
55493
|
+
kind: "mutation",
|
|
55494
|
+
auth: "protected"
|
|
55495
|
+
}),
|
|
55496
|
+
/** Select (not start) a program; refused when the appliance does not offer it. */
|
|
55333
55497
|
setProgram: method(object({
|
|
55334
|
-
deviceId:
|
|
55498
|
+
deviceId: DeviceIdSchema,
|
|
55335
55499
|
program: string().min(1)
|
|
55336
55500
|
}), _void(), {
|
|
55337
55501
|
kind: "mutation",
|
|
55338
55502
|
auth: "protected"
|
|
55339
55503
|
}),
|
|
55340
55504
|
setPower: method(object({
|
|
55341
|
-
deviceId:
|
|
55505
|
+
deviceId: DeviceIdSchema,
|
|
55342
55506
|
on: boolean()
|
|
55343
55507
|
}), _void(), {
|
|
55344
55508
|
kind: "mutation",
|
|
55345
55509
|
auth: "protected"
|
|
55346
55510
|
}),
|
|
55347
55511
|
setHalfLoad: method(object({
|
|
55348
|
-
deviceId:
|
|
55512
|
+
deviceId: DeviceIdSchema,
|
|
55349
55513
|
on: boolean()
|
|
55350
55514
|
}), _void(), {
|
|
55351
55515
|
kind: "mutation",
|
|
55352
55516
|
auth: "protected"
|
|
55353
55517
|
}),
|
|
55354
55518
|
setHygienePlus: method(object({
|
|
55355
|
-
deviceId:
|
|
55519
|
+
deviceId: DeviceIdSchema,
|
|
55356
55520
|
on: boolean()
|
|
55357
55521
|
}), _void(), {
|
|
55358
55522
|
kind: "mutation",
|
|
55359
55523
|
auth: "protected"
|
|
55360
55524
|
}),
|
|
55525
|
+
setExtraDry: method(object({
|
|
55526
|
+
deviceId: DeviceIdSchema,
|
|
55527
|
+
on: boolean()
|
|
55528
|
+
}), _void(), {
|
|
55529
|
+
kind: "mutation",
|
|
55530
|
+
auth: "protected"
|
|
55531
|
+
}),
|
|
55532
|
+
setIntensiveZone: method(object({
|
|
55533
|
+
deviceId: DeviceIdSchema,
|
|
55534
|
+
on: boolean()
|
|
55535
|
+
}), _void(), {
|
|
55536
|
+
kind: "mutation",
|
|
55537
|
+
auth: "protected"
|
|
55538
|
+
}),
|
|
55539
|
+
setVarioSpeedPlus: method(object({
|
|
55540
|
+
deviceId: DeviceIdSchema,
|
|
55541
|
+
on: boolean()
|
|
55542
|
+
}), _void(), {
|
|
55543
|
+
kind: "mutation",
|
|
55544
|
+
auth: "protected"
|
|
55545
|
+
}),
|
|
55546
|
+
setChildLock: method(object({
|
|
55547
|
+
deviceId: DeviceIdSchema,
|
|
55548
|
+
on: boolean()
|
|
55549
|
+
}), _void(), {
|
|
55550
|
+
kind: "mutation",
|
|
55551
|
+
auth: "protected"
|
|
55552
|
+
}),
|
|
55553
|
+
/**
|
|
55554
|
+
* Write any option or setting by feature key. Refused when the description does
|
|
55555
|
+
* not list it, it is not writable or not available now, or the value is outside
|
|
55556
|
+
* its declared range / members.
|
|
55557
|
+
*/
|
|
55361
55558
|
setOption: method(object({
|
|
55362
|
-
deviceId:
|
|
55559
|
+
deviceId: DeviceIdSchema,
|
|
55363
55560
|
key: string().min(1),
|
|
55364
|
-
value:
|
|
55365
|
-
boolean(),
|
|
55366
|
-
string(),
|
|
55367
|
-
number()
|
|
55368
|
-
])
|
|
55561
|
+
value: DishwasherValueSchema
|
|
55369
55562
|
}), _void(), {
|
|
55370
55563
|
kind: "mutation",
|
|
55371
55564
|
auth: "protected"
|
|
55372
|
-
})
|
|
55565
|
+
}),
|
|
55566
|
+
/** What this appliance can do, from its own description — the UI is derived from it. */
|
|
55567
|
+
getOptions: method(object({ deviceId: DeviceIdSchema }), DishwasherOptionsSchema, { auth: "protected" })
|
|
55373
55568
|
},
|
|
55374
55569
|
status: {
|
|
55375
55570
|
schema: DishwasherStatusSchema,
|
|
@@ -69318,6 +69513,12 @@ Object.freeze({
|
|
|
69318
69513
|
addonId: null,
|
|
69319
69514
|
access: "view"
|
|
69320
69515
|
},
|
|
69516
|
+
"dishwasher.getOptions": {
|
|
69517
|
+
capName: "dishwasher",
|
|
69518
|
+
capScope: "device",
|
|
69519
|
+
addonId: null,
|
|
69520
|
+
access: "view"
|
|
69521
|
+
},
|
|
69321
69522
|
"dishwasher.getStatus": {
|
|
69322
69523
|
capName: "dishwasher",
|
|
69323
69524
|
capScope: "device",
|
|
@@ -69330,6 +69531,24 @@ Object.freeze({
|
|
|
69330
69531
|
addonId: null,
|
|
69331
69532
|
access: "create"
|
|
69332
69533
|
},
|
|
69534
|
+
"dishwasher.resume": {
|
|
69535
|
+
capName: "dishwasher",
|
|
69536
|
+
capScope: "device",
|
|
69537
|
+
addonId: null,
|
|
69538
|
+
access: "create"
|
|
69539
|
+
},
|
|
69540
|
+
"dishwasher.setChildLock": {
|
|
69541
|
+
capName: "dishwasher",
|
|
69542
|
+
capScope: "device",
|
|
69543
|
+
addonId: null,
|
|
69544
|
+
access: "create"
|
|
69545
|
+
},
|
|
69546
|
+
"dishwasher.setExtraDry": {
|
|
69547
|
+
capName: "dishwasher",
|
|
69548
|
+
capScope: "device",
|
|
69549
|
+
addonId: null,
|
|
69550
|
+
access: "create"
|
|
69551
|
+
},
|
|
69333
69552
|
"dishwasher.setHalfLoad": {
|
|
69334
69553
|
capName: "dishwasher",
|
|
69335
69554
|
capScope: "device",
|
|
@@ -69342,6 +69561,12 @@ Object.freeze({
|
|
|
69342
69561
|
addonId: null,
|
|
69343
69562
|
access: "create"
|
|
69344
69563
|
},
|
|
69564
|
+
"dishwasher.setIntensiveZone": {
|
|
69565
|
+
capName: "dishwasher",
|
|
69566
|
+
capScope: "device",
|
|
69567
|
+
addonId: null,
|
|
69568
|
+
access: "create"
|
|
69569
|
+
},
|
|
69345
69570
|
"dishwasher.setOption": {
|
|
69346
69571
|
capName: "dishwasher",
|
|
69347
69572
|
capScope: "device",
|
|
@@ -69360,6 +69585,12 @@ Object.freeze({
|
|
|
69360
69585
|
addonId: null,
|
|
69361
69586
|
access: "create"
|
|
69362
69587
|
},
|
|
69588
|
+
"dishwasher.setVarioSpeedPlus": {
|
|
69589
|
+
capName: "dishwasher",
|
|
69590
|
+
capScope: "device",
|
|
69591
|
+
addonId: null,
|
|
69592
|
+
access: "create"
|
|
69593
|
+
},
|
|
69363
69594
|
"dishwasher.start": {
|
|
69364
69595
|
capName: "dishwasher",
|
|
69365
69596
|
capScope: "device",
|
|
@@ -73806,6 +74037,12 @@ Object.freeze({
|
|
|
73806
74037
|
addonId: null,
|
|
73807
74038
|
access: "view"
|
|
73808
74039
|
},
|
|
74040
|
+
"storageMigration.moverClearance": {
|
|
74041
|
+
capName: "storage-migration",
|
|
74042
|
+
capScope: "system",
|
|
74043
|
+
addonId: null,
|
|
74044
|
+
access: "view"
|
|
74045
|
+
},
|
|
73809
74046
|
"storageMigration.movers": {
|
|
73810
74047
|
capName: "storage-migration",
|
|
73811
74048
|
capScope: "system",
|
|
@@ -75999,6 +76236,11 @@ Object.freeze({
|
|
|
75999
76236
|
form: "single",
|
|
76000
76237
|
optional: false
|
|
76001
76238
|
}],
|
|
76239
|
+
"dishwasher.getOptions": [{
|
|
76240
|
+
name: "deviceId",
|
|
76241
|
+
form: "single",
|
|
76242
|
+
optional: false
|
|
76243
|
+
}],
|
|
76002
76244
|
"dishwasher.getStatus": [{
|
|
76003
76245
|
name: "deviceId",
|
|
76004
76246
|
form: "single",
|
|
@@ -76009,6 +76251,21 @@ Object.freeze({
|
|
|
76009
76251
|
form: "single",
|
|
76010
76252
|
optional: false
|
|
76011
76253
|
}],
|
|
76254
|
+
"dishwasher.resume": [{
|
|
76255
|
+
name: "deviceId",
|
|
76256
|
+
form: "single",
|
|
76257
|
+
optional: false
|
|
76258
|
+
}],
|
|
76259
|
+
"dishwasher.setChildLock": [{
|
|
76260
|
+
name: "deviceId",
|
|
76261
|
+
form: "single",
|
|
76262
|
+
optional: false
|
|
76263
|
+
}],
|
|
76264
|
+
"dishwasher.setExtraDry": [{
|
|
76265
|
+
name: "deviceId",
|
|
76266
|
+
form: "single",
|
|
76267
|
+
optional: false
|
|
76268
|
+
}],
|
|
76012
76269
|
"dishwasher.setHalfLoad": [{
|
|
76013
76270
|
name: "deviceId",
|
|
76014
76271
|
form: "single",
|
|
@@ -76019,6 +76276,11 @@ Object.freeze({
|
|
|
76019
76276
|
form: "single",
|
|
76020
76277
|
optional: false
|
|
76021
76278
|
}],
|
|
76279
|
+
"dishwasher.setIntensiveZone": [{
|
|
76280
|
+
name: "deviceId",
|
|
76281
|
+
form: "single",
|
|
76282
|
+
optional: false
|
|
76283
|
+
}],
|
|
76022
76284
|
"dishwasher.setOption": [{
|
|
76023
76285
|
name: "deviceId",
|
|
76024
76286
|
form: "single",
|
|
@@ -76034,6 +76296,11 @@ Object.freeze({
|
|
|
76034
76296
|
form: "single",
|
|
76035
76297
|
optional: false
|
|
76036
76298
|
}],
|
|
76299
|
+
"dishwasher.setVarioSpeedPlus": [{
|
|
76300
|
+
name: "deviceId",
|
|
76301
|
+
form: "single",
|
|
76302
|
+
optional: false
|
|
76303
|
+
}],
|
|
76037
76304
|
"dishwasher.start": [{
|
|
76038
76305
|
name: "deviceId",
|
|
76039
76306
|
form: "single",
|
|
@@ -78075,6 +78342,9 @@ new Map(Object.entries({
|
|
|
78075
78342
|
"wrapper-update-available": "system",
|
|
78076
78343
|
"backup-completed": "system",
|
|
78077
78344
|
"export-completed": "system",
|
|
78345
|
+
"alert-critical": "system",
|
|
78346
|
+
"alert-error": "system",
|
|
78347
|
+
"alert-critical-resolved": "system",
|
|
78078
78348
|
"storage-location-low": "system",
|
|
78079
78349
|
"storage-location-critical": "system",
|
|
78080
78350
|
"storage-location-ok": "system",
|
|
@@ -78199,6 +78469,16 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
78199
78469
|
"storage-location-ok"
|
|
78200
78470
|
]
|
|
78201
78471
|
},
|
|
78472
|
+
{
|
|
78473
|
+
id: "alerts",
|
|
78474
|
+
family: "system",
|
|
78475
|
+
label: "Alerts",
|
|
78476
|
+
kinds: [
|
|
78477
|
+
"alert-critical",
|
|
78478
|
+
"alert-error",
|
|
78479
|
+
"alert-critical-resolved"
|
|
78480
|
+
]
|
|
78481
|
+
},
|
|
78202
78482
|
{
|
|
78203
78483
|
id: "alarm",
|
|
78204
78484
|
family: "alarm",
|
|
@@ -78243,6 +78523,21 @@ var NC_SENSOR_RAISED_FIELD_BY_KIND = Object.freeze(Object.fromEntries(Object.ent
|
|
|
78243
78523
|
return [[descriptor.kind, field]];
|
|
78244
78524
|
})));
|
|
78245
78525
|
Object.freeze(Object.keys(NC_SENSOR_RAISED_FIELD_BY_KIND));
|
|
78526
|
+
object({
|
|
78527
|
+
phase: _enum(["raised", "resolved"]),
|
|
78528
|
+
episodeId: string().min(1),
|
|
78529
|
+
alertId: string().min(1),
|
|
78530
|
+
severity: AlertSeveritySchema,
|
|
78531
|
+
category: string(),
|
|
78532
|
+
title: string(),
|
|
78533
|
+
message: string(),
|
|
78534
|
+
sourceType: string().optional(),
|
|
78535
|
+
sourceId: string().optional(),
|
|
78536
|
+
nodeId: string().optional(),
|
|
78537
|
+
/** The alert's own action link (where the operator acts on it), when it has one. */
|
|
78538
|
+
actionUrl: string().optional(),
|
|
78539
|
+
at: number()
|
|
78540
|
+
});
|
|
78246
78541
|
var RULE_BODY_ONLY = ["body"];
|
|
78247
78542
|
var RULE_TEXT = ["title", "body"];
|
|
78248
78543
|
var BATTERY = ["device-battery-low", "device-battery-normal"];
|
|
@@ -78252,6 +78547,11 @@ var TANK = [
|
|
|
78252
78547
|
"device-tank-full",
|
|
78253
78548
|
"device-tank-normal"
|
|
78254
78549
|
];
|
|
78550
|
+
var ALERT_EPISODE = [
|
|
78551
|
+
"alert-critical",
|
|
78552
|
+
"alert-error",
|
|
78553
|
+
"alert-critical-resolved"
|
|
78554
|
+
];
|
|
78255
78555
|
var UPDATES = [
|
|
78256
78556
|
"addon-update-available",
|
|
78257
78557
|
"server-update-available",
|
|
@@ -78444,14 +78744,14 @@ var STATE_SUMMARY_VARS = [
|
|
|
78444
78744
|
([...RULE_TEXT], [...CONSUMABLE]),
|
|
78445
78745
|
([...RULE_TEXT], [...TANK]),
|
|
78446
78746
|
[...RULE_TEXT],
|
|
78447
|
-
([...RULE_TEXT], [...UPDATES]),
|
|
78448
|
-
([...RULE_TEXT], [...UPDATES]),
|
|
78449
|
-
[...RULE_TEXT],
|
|
78747
|
+
([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
|
|
78748
|
+
([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
|
|
78450
78749
|
[...RULE_TEXT],
|
|
78451
78750
|
[...RULE_TEXT],
|
|
78452
78751
|
[...RULE_TEXT],
|
|
78453
78752
|
[...RULE_TEXT],
|
|
78454
78753
|
[...RULE_TEXT],
|
|
78754
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78455
78755
|
[...RULE_TEXT],
|
|
78456
78756
|
[...RULE_TEXT],
|
|
78457
78757
|
[...RULE_TEXT],
|
|
@@ -78469,7 +78769,11 @@ var STATE_SUMMARY_VARS = [
|
|
|
78469
78769
|
[...RULE_TEXT],
|
|
78470
78770
|
[...RULE_TEXT],
|
|
78471
78771
|
[...RULE_TEXT],
|
|
78472
|
-
[...RULE_TEXT],
|
|
78772
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78773
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78774
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78775
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78776
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78473
78777
|
[...RULE_TEXT],
|
|
78474
78778
|
[...RULE_TEXT],
|
|
78475
78779
|
[...RULE_TEXT],
|
package/dist/addon.mjs
CHANGED
|
@@ -36,7 +36,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
36
36
|
var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
37
37
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
38
38
|
//#endregion
|
|
39
|
-
//#region ../types/dist/event-category-
|
|
39
|
+
//#region ../types/dist/event-category-DOl51-Ij.mjs
|
|
40
40
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
41
41
|
EventCategory["SystemBoot"] = "system.boot";
|
|
42
42
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -115,9 +115,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
115
115
|
/**
|
|
116
116
|
* The node's one-shot runner boot check (D877): planned runners against the
|
|
117
117
|
* process service, `degraded` when any is failed, refused or missing. The
|
|
118
|
-
* alert centre turns it into one
|
|
118
|
+
* alert centre turns it into one critical alert.
|
|
119
119
|
*/
|
|
120
120
|
EventCategory["SystemRunnerCheck"] = "system.runner-check";
|
|
121
|
+
/**
|
|
122
|
+
* An alert EPISODE opened or closed, emitted by the alert centre for alerts
|
|
123
|
+
* of severity `critical` or `error` (`AlertEpisodePayload`). The alert
|
|
124
|
+
* centre sends no notification of its own: Notification Center turns this
|
|
125
|
+
* into the `alert-critical` / `alert-error` / `alert-critical-resolved`
|
|
126
|
+
* system-event kinds, and reconciles from the alerts store because a bus
|
|
127
|
+
* event may be dropped (D8, D11).
|
|
128
|
+
*/
|
|
129
|
+
EventCategory["AlertEpisode"] = "alert.episode";
|
|
121
130
|
EventCategory["AddonError"] = "addon.error";
|
|
122
131
|
EventCategory["AddonPageReady"] = "addon.page-ready";
|
|
123
132
|
EventCategory["AddonWidgetReady"] = "addon.widget-ready";
|
|
@@ -5442,7 +5451,7 @@ var ZodIssueCode = {
|
|
|
5442
5451
|
var ZodFirstPartyTypeKind;
|
|
5443
5452
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5444
5453
|
//#endregion
|
|
5445
|
-
//#region ../types/dist/sleep-
|
|
5454
|
+
//#region ../types/dist/sleep-BxjU_fJM.mjs
|
|
5446
5455
|
/**
|
|
5447
5456
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5448
5457
|
* window to float samples (D455).
|
|
@@ -13205,7 +13214,14 @@ var AlertSeveritySchema = _enum([
|
|
|
13205
13214
|
]);
|
|
13206
13215
|
var AlertActionSchema = object({
|
|
13207
13216
|
label: string(),
|
|
13208
|
-
href: string().optional()
|
|
13217
|
+
href: string().optional(),
|
|
13218
|
+
/**
|
|
13219
|
+
* How `href` is followed. Absent / `app`: an admin-ui route (client-side).
|
|
13220
|
+
* `server`: a route the HUB serves (an addon HTTP route such as an OAuth
|
|
13221
|
+
* start) — the browser must leave the SPA with a full navigation, because
|
|
13222
|
+
* the SPA has no such route and would bounce to the home page.
|
|
13223
|
+
*/
|
|
13224
|
+
navigation: _enum(["app", "server"]).optional()
|
|
13209
13225
|
});
|
|
13210
13226
|
var AlertStatusSchema = _enum([
|
|
13211
13227
|
"active",
|
|
@@ -17586,7 +17602,11 @@ var deviceDiscoveryCapability = {
|
|
|
17586
17602
|
};
|
|
17587
17603
|
/**
|
|
17588
17604
|
* `device-adoption` — generic discovery + adoption surface,
|
|
17589
|
-
* system-scoped
|
|
17605
|
+
* system-scoped collection (one provider per integration addon), routed
|
|
17606
|
+
* by explicit `{ addonId }` on direct `deviceAdoption.*` calls — the same
|
|
17607
|
+
* pin model as `connection-test`. The admin UI keeps using
|
|
17608
|
+
* `deviceManager.adoption*` (which already threads `addonId`). The de-HA-ified
|
|
17609
|
+
* successor to `ha-discovery`:
|
|
17590
17610
|
* keyed by `integrationId` (the addon resolves integrationId → broker
|
|
17591
17611
|
* internally) rather than a connection-specific `brokerId`, and it
|
|
17592
17612
|
* REUSES the shared `DiscoveredChildDevice` candidate type from
|
|
@@ -17751,7 +17771,7 @@ var ResyncResultSchema = object({
|
|
|
17751
17771
|
var deviceAdoptionCapability = {
|
|
17752
17772
|
name: "device-adoption",
|
|
17753
17773
|
scope: "system",
|
|
17754
|
-
mode: "
|
|
17774
|
+
mode: "collection",
|
|
17755
17775
|
status: {
|
|
17756
17776
|
schema: AdoptionStatusSchema,
|
|
17757
17777
|
kind: "poll"
|
|
@@ -41934,6 +41954,9 @@ var NcSystemEventKindSchema = _enum([
|
|
|
41934
41954
|
"server-updated",
|
|
41935
41955
|
"export-completed",
|
|
41936
41956
|
"backup-completed",
|
|
41957
|
+
"alert-critical",
|
|
41958
|
+
"alert-error",
|
|
41959
|
+
"alert-critical-resolved",
|
|
41937
41960
|
"camera-online",
|
|
41938
41961
|
"camera-offline",
|
|
41939
41962
|
"camera-disabled",
|
|
@@ -51010,7 +51033,10 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
|
|
|
51010
51033
|
}), method(object({ jobId: string().optional() }), StorageMigrationJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
51011
51034
|
kind: "mutation",
|
|
51012
51035
|
auth: "admin"
|
|
51013
|
-
}), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({
|
|
51036
|
+
}), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({ locationIds: array(string()).readonly() }), object({
|
|
51037
|
+
clear: boolean(),
|
|
51038
|
+
repointLocationId: string().optional()
|
|
51039
|
+
}), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
|
|
51014
51040
|
kind: "mutation",
|
|
51015
51041
|
auth: "admin"
|
|
51016
51042
|
}), method(StorageCleanupInputSchema, object({ jobId: string() }), {
|
|
@@ -55274,6 +55300,11 @@ onStatusChanged: { data: object({
|
|
|
55274
55300
|
*
|
|
55275
55301
|
* `kind: 'poll'` — cloud REST APIs typically have no push channel; the
|
|
55276
55302
|
* provider refreshes the slice on an interval and eagerly after commands.
|
|
55303
|
+
*
|
|
55304
|
+
* UNKNOWN IS NOT OFF. Every field the appliance reports separately is
|
|
55305
|
+
* nullable: `null` means "not known right now" (the appliance has not said,
|
|
55306
|
+
* the link is down, or the description does not carry it) and is never
|
|
55307
|
+
* rendered or exported as `false` / `0`. `availability` says why.
|
|
55277
55308
|
*/
|
|
55278
55309
|
var DishwasherStateSchema = _enum([
|
|
55279
55310
|
"idle",
|
|
@@ -55283,35 +55314,155 @@ var DishwasherStateSchema = _enum([
|
|
|
55283
55314
|
"error",
|
|
55284
55315
|
"unavailable"
|
|
55285
55316
|
]);
|
|
55317
|
+
/**
|
|
55318
|
+
* The appliance's own operation state, uncollapsed. `state` above is the coarse
|
|
55319
|
+
* view for compact surfaces; this is what the appliance said.
|
|
55320
|
+
*/
|
|
55321
|
+
var DishwasherOperationStateSchema = _enum([
|
|
55322
|
+
"Inactive",
|
|
55323
|
+
"Ready",
|
|
55324
|
+
"DelayedStart",
|
|
55325
|
+
"Run",
|
|
55326
|
+
"Pause",
|
|
55327
|
+
"ActionRequired",
|
|
55328
|
+
"Finished",
|
|
55329
|
+
"Error",
|
|
55330
|
+
"Aborting"
|
|
55331
|
+
]);
|
|
55332
|
+
/**
|
|
55333
|
+
* Why fields may be `null`:
|
|
55334
|
+
* - `available` — the link is up and the description is loaded;
|
|
55335
|
+
* - `offline` — the local link is down (values are unknown, not last-known);
|
|
55336
|
+
* - `description-missing` — the link is up but the appliance's description could not
|
|
55337
|
+
* be loaded, so its values cannot be decoded.
|
|
55338
|
+
*/
|
|
55339
|
+
var DishwasherAvailabilitySchema = _enum([
|
|
55340
|
+
"available",
|
|
55341
|
+
"offline",
|
|
55342
|
+
"description-missing"
|
|
55343
|
+
]);
|
|
55286
55344
|
var DishwasherConsumableLevelSchema = _enum([
|
|
55287
55345
|
"ok",
|
|
55288
55346
|
"low",
|
|
55289
55347
|
"empty"
|
|
55290
55348
|
]);
|
|
55291
55349
|
var DishwasherStatusSchema = object({
|
|
55350
|
+
availability: DishwasherAvailabilitySchema,
|
|
55351
|
+
/** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
|
|
55292
55352
|
state: DishwasherStateSchema,
|
|
55293
|
-
/**
|
|
55353
|
+
/** The appliance's operation state as reported; null when not known. */
|
|
55354
|
+
operationState: DishwasherOperationStateSchema.nullable(),
|
|
55355
|
+
/** Feature key of the ACTIVE (running) program, or null when none runs / not known. */
|
|
55294
55356
|
program: string().nullable(),
|
|
55295
|
-
/**
|
|
55357
|
+
/** Feature key of the SELECTED program (what Start would run), or null when none / not known. */
|
|
55358
|
+
selectedProgram: string().nullable(),
|
|
55359
|
+
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
55296
55360
|
availablePrograms: array(string()),
|
|
55297
|
-
/**
|
|
55298
|
-
|
|
55361
|
+
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
55362
|
+
remainingSeconds: number().int().nonnegative().nullable(),
|
|
55363
|
+
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
55364
|
+
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
55299
55365
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
55300
55366
|
progressPercent: number().min(0).max(100).nullable(),
|
|
55301
|
-
/** True when the door is reported open. */
|
|
55302
|
-
doorOpen: boolean(),
|
|
55303
|
-
/** True when
|
|
55304
|
-
|
|
55305
|
-
/**
|
|
55306
|
-
|
|
55367
|
+
/** True when the door is reported open; null when the door state is not known. */
|
|
55368
|
+
doorOpen: boolean().nullable(),
|
|
55369
|
+
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
55370
|
+
doorLocked: boolean().nullable(),
|
|
55371
|
+
/** True when remote start is allowed (door closed, power on, etc.); null when not known. */
|
|
55372
|
+
remoteStartAllowed: boolean().nullable(),
|
|
55373
|
+
/** True when the appliance accepts remote control now; null when not known. */
|
|
55374
|
+
remoteControlActive: boolean().nullable(),
|
|
55375
|
+
/** True while somebody operates the appliance at its panel; null when not reported. */
|
|
55376
|
+
localControlActive: boolean().nullable(),
|
|
55377
|
+
/** Main power / switched-on state; null when not known. */
|
|
55378
|
+
powerOn: boolean().nullable(),
|
|
55379
|
+
/** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
|
|
55380
|
+
powerState: string().nullable(),
|
|
55307
55381
|
saltLevel: DishwasherConsumableLevelSchema.nullable(),
|
|
55308
55382
|
rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
|
|
55309
|
-
|
|
55310
|
-
|
|
55383
|
+
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
55384
|
+
halfLoad: boolean().nullable(),
|
|
55385
|
+
hygienePlus: boolean().nullable(),
|
|
55386
|
+
/** Extra dry option when the appliance exposes it. */
|
|
55387
|
+
extraDry: boolean().nullable(),
|
|
55388
|
+
/** Intensive zone (lower basket) when the appliance exposes it. */
|
|
55389
|
+
intensiveZone: boolean().nullable(),
|
|
55390
|
+
/** VarioSpeed / VarioSpeed+ when the appliance exposes it. */
|
|
55391
|
+
varioSpeedPlus: boolean().nullable(),
|
|
55392
|
+
/** Child lock (controls disabled on the appliance); null when not known. */
|
|
55393
|
+
childLock: boolean().nullable(),
|
|
55394
|
+
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
55395
|
+
activeEvents: array(string()),
|
|
55396
|
+
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
55311
55397
|
errorCode: number().nullable(),
|
|
55398
|
+
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
55312
55399
|
errorLabel: string().nullable(),
|
|
55400
|
+
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
55313
55401
|
lastFetchedAt: number()
|
|
55314
55402
|
});
|
|
55403
|
+
var DeviceIdSchema = number().int().nonnegative();
|
|
55404
|
+
/** A value a program option or setting can take. */
|
|
55405
|
+
var DishwasherValueSchema = union([
|
|
55406
|
+
boolean(),
|
|
55407
|
+
string(),
|
|
55408
|
+
number()
|
|
55409
|
+
]);
|
|
55410
|
+
var DishwasherAccessSchema = _enum([
|
|
55411
|
+
"none",
|
|
55412
|
+
"read",
|
|
55413
|
+
"readWrite",
|
|
55414
|
+
"writeOnly",
|
|
55415
|
+
"readStatic"
|
|
55416
|
+
]);
|
|
55417
|
+
/**
|
|
55418
|
+
* One option or setting the appliance declares, with the constraints its description
|
|
55419
|
+
* gives. A `readWrite` descriptor that is `available` is what `setOption` accepts.
|
|
55420
|
+
*/
|
|
55421
|
+
var DishwasherOptionDescriptorSchema = object({
|
|
55422
|
+
/** Feature key (`Dishcare.Dishwasher.Option.ExtraDry`). */
|
|
55423
|
+
key: string(),
|
|
55424
|
+
/** Last segment of the key, for display. */
|
|
55425
|
+
name: string(),
|
|
55426
|
+
type: _enum([
|
|
55427
|
+
"boolean",
|
|
55428
|
+
"number",
|
|
55429
|
+
"enum",
|
|
55430
|
+
"string"
|
|
55431
|
+
]),
|
|
55432
|
+
access: DishwasherAccessSchema,
|
|
55433
|
+
/** The appliance reports this entity as currently available. */
|
|
55434
|
+
available: boolean(),
|
|
55435
|
+
/** Unit the description declares for a number; null when it declares none. */
|
|
55436
|
+
unit: string().nullable(),
|
|
55437
|
+
min: number().nullable(),
|
|
55438
|
+
max: number().nullable(),
|
|
55439
|
+
step: number().nullable(),
|
|
55440
|
+
/** Allowed members of an enum; null for other types. */
|
|
55441
|
+
enumValues: array(string()).nullable(),
|
|
55442
|
+
defaultValue: DishwasherValueSchema.nullable()
|
|
55443
|
+
});
|
|
55444
|
+
var DishwasherProgramSchema = object({
|
|
55445
|
+
/** Feature key (`Dishcare.Dishwasher.Program.Eco50`) — what `setProgram` / `start` take. */
|
|
55446
|
+
key: string(),
|
|
55447
|
+
name: string(),
|
|
55448
|
+
/** The appliance currently offers this program. */
|
|
55449
|
+
available: boolean(),
|
|
55450
|
+
/** The options this program lists, with the program-level access / availability / default. */
|
|
55451
|
+
options: array(DishwasherOptionDescriptorSchema)
|
|
55452
|
+
});
|
|
55453
|
+
var DishwasherOptionsSchema = object({
|
|
55454
|
+
availability: DishwasherAvailabilitySchema,
|
|
55455
|
+
/** What the appliance can be told to do, from the commands its description declares. */
|
|
55456
|
+
supportsStart: boolean(),
|
|
55457
|
+
supportsPause: boolean(),
|
|
55458
|
+
supportsResume: boolean(),
|
|
55459
|
+
supportsStop: boolean(),
|
|
55460
|
+
supportsPower: boolean(),
|
|
55461
|
+
/** Every program the description lists, with its options. */
|
|
55462
|
+
programs: array(DishwasherProgramSchema),
|
|
55463
|
+
/** Every option and setting entity the description lists (programs reference these by key). */
|
|
55464
|
+
options: array(DishwasherOptionDescriptorSchema)
|
|
55465
|
+
});
|
|
55315
55466
|
var dishwasherCapability = {
|
|
55316
55467
|
name: "dishwasher",
|
|
55317
55468
|
scope: "device",
|
|
@@ -55319,58 +55470,102 @@ var dishwasherCapability = {
|
|
|
55319
55470
|
mode: "singleton",
|
|
55320
55471
|
deviceTypes: [DeviceType.Dishwasher],
|
|
55321
55472
|
methods: {
|
|
55322
|
-
|
|
55473
|
+
/**
|
|
55474
|
+
* Start a program. Without `program` the selected one starts. `options` are
|
|
55475
|
+
* option feature keys; each is checked against the program's constraints.
|
|
55476
|
+
*/
|
|
55477
|
+
start: method(object({
|
|
55478
|
+
deviceId: DeviceIdSchema,
|
|
55479
|
+
program: string().min(1).optional(),
|
|
55480
|
+
options: record(string(), DishwasherValueSchema).optional()
|
|
55481
|
+
}), _void(), {
|
|
55323
55482
|
kind: "mutation",
|
|
55324
55483
|
auth: "protected"
|
|
55325
55484
|
}),
|
|
55326
|
-
pause: method(object({ deviceId:
|
|
55485
|
+
pause: method(object({ deviceId: DeviceIdSchema }), _void(), {
|
|
55327
55486
|
kind: "mutation",
|
|
55328
55487
|
auth: "protected"
|
|
55329
55488
|
}),
|
|
55330
|
-
|
|
55489
|
+
resume: method(object({ deviceId: DeviceIdSchema }), _void(), {
|
|
55331
55490
|
kind: "mutation",
|
|
55332
55491
|
auth: "protected"
|
|
55333
55492
|
}),
|
|
55493
|
+
stop: method(object({ deviceId: DeviceIdSchema }), _void(), {
|
|
55494
|
+
kind: "mutation",
|
|
55495
|
+
auth: "protected"
|
|
55496
|
+
}),
|
|
55497
|
+
/** Select (not start) a program; refused when the appliance does not offer it. */
|
|
55334
55498
|
setProgram: method(object({
|
|
55335
|
-
deviceId:
|
|
55499
|
+
deviceId: DeviceIdSchema,
|
|
55336
55500
|
program: string().min(1)
|
|
55337
55501
|
}), _void(), {
|
|
55338
55502
|
kind: "mutation",
|
|
55339
55503
|
auth: "protected"
|
|
55340
55504
|
}),
|
|
55341
55505
|
setPower: method(object({
|
|
55342
|
-
deviceId:
|
|
55506
|
+
deviceId: DeviceIdSchema,
|
|
55343
55507
|
on: boolean()
|
|
55344
55508
|
}), _void(), {
|
|
55345
55509
|
kind: "mutation",
|
|
55346
55510
|
auth: "protected"
|
|
55347
55511
|
}),
|
|
55348
55512
|
setHalfLoad: method(object({
|
|
55349
|
-
deviceId:
|
|
55513
|
+
deviceId: DeviceIdSchema,
|
|
55350
55514
|
on: boolean()
|
|
55351
55515
|
}), _void(), {
|
|
55352
55516
|
kind: "mutation",
|
|
55353
55517
|
auth: "protected"
|
|
55354
55518
|
}),
|
|
55355
55519
|
setHygienePlus: method(object({
|
|
55356
|
-
deviceId:
|
|
55520
|
+
deviceId: DeviceIdSchema,
|
|
55357
55521
|
on: boolean()
|
|
55358
55522
|
}), _void(), {
|
|
55359
55523
|
kind: "mutation",
|
|
55360
55524
|
auth: "protected"
|
|
55361
55525
|
}),
|
|
55526
|
+
setExtraDry: method(object({
|
|
55527
|
+
deviceId: DeviceIdSchema,
|
|
55528
|
+
on: boolean()
|
|
55529
|
+
}), _void(), {
|
|
55530
|
+
kind: "mutation",
|
|
55531
|
+
auth: "protected"
|
|
55532
|
+
}),
|
|
55533
|
+
setIntensiveZone: method(object({
|
|
55534
|
+
deviceId: DeviceIdSchema,
|
|
55535
|
+
on: boolean()
|
|
55536
|
+
}), _void(), {
|
|
55537
|
+
kind: "mutation",
|
|
55538
|
+
auth: "protected"
|
|
55539
|
+
}),
|
|
55540
|
+
setVarioSpeedPlus: method(object({
|
|
55541
|
+
deviceId: DeviceIdSchema,
|
|
55542
|
+
on: boolean()
|
|
55543
|
+
}), _void(), {
|
|
55544
|
+
kind: "mutation",
|
|
55545
|
+
auth: "protected"
|
|
55546
|
+
}),
|
|
55547
|
+
setChildLock: method(object({
|
|
55548
|
+
deviceId: DeviceIdSchema,
|
|
55549
|
+
on: boolean()
|
|
55550
|
+
}), _void(), {
|
|
55551
|
+
kind: "mutation",
|
|
55552
|
+
auth: "protected"
|
|
55553
|
+
}),
|
|
55554
|
+
/**
|
|
55555
|
+
* Write any option or setting by feature key. Refused when the description does
|
|
55556
|
+
* not list it, it is not writable or not available now, or the value is outside
|
|
55557
|
+
* its declared range / members.
|
|
55558
|
+
*/
|
|
55362
55559
|
setOption: method(object({
|
|
55363
|
-
deviceId:
|
|
55560
|
+
deviceId: DeviceIdSchema,
|
|
55364
55561
|
key: string().min(1),
|
|
55365
|
-
value:
|
|
55366
|
-
boolean(),
|
|
55367
|
-
string(),
|
|
55368
|
-
number()
|
|
55369
|
-
])
|
|
55562
|
+
value: DishwasherValueSchema
|
|
55370
55563
|
}), _void(), {
|
|
55371
55564
|
kind: "mutation",
|
|
55372
55565
|
auth: "protected"
|
|
55373
|
-
})
|
|
55566
|
+
}),
|
|
55567
|
+
/** What this appliance can do, from its own description — the UI is derived from it. */
|
|
55568
|
+
getOptions: method(object({ deviceId: DeviceIdSchema }), DishwasherOptionsSchema, { auth: "protected" })
|
|
55374
55569
|
},
|
|
55375
55570
|
status: {
|
|
55376
55571
|
schema: DishwasherStatusSchema,
|
|
@@ -69319,6 +69514,12 @@ Object.freeze({
|
|
|
69319
69514
|
addonId: null,
|
|
69320
69515
|
access: "view"
|
|
69321
69516
|
},
|
|
69517
|
+
"dishwasher.getOptions": {
|
|
69518
|
+
capName: "dishwasher",
|
|
69519
|
+
capScope: "device",
|
|
69520
|
+
addonId: null,
|
|
69521
|
+
access: "view"
|
|
69522
|
+
},
|
|
69322
69523
|
"dishwasher.getStatus": {
|
|
69323
69524
|
capName: "dishwasher",
|
|
69324
69525
|
capScope: "device",
|
|
@@ -69331,6 +69532,24 @@ Object.freeze({
|
|
|
69331
69532
|
addonId: null,
|
|
69332
69533
|
access: "create"
|
|
69333
69534
|
},
|
|
69535
|
+
"dishwasher.resume": {
|
|
69536
|
+
capName: "dishwasher",
|
|
69537
|
+
capScope: "device",
|
|
69538
|
+
addonId: null,
|
|
69539
|
+
access: "create"
|
|
69540
|
+
},
|
|
69541
|
+
"dishwasher.setChildLock": {
|
|
69542
|
+
capName: "dishwasher",
|
|
69543
|
+
capScope: "device",
|
|
69544
|
+
addonId: null,
|
|
69545
|
+
access: "create"
|
|
69546
|
+
},
|
|
69547
|
+
"dishwasher.setExtraDry": {
|
|
69548
|
+
capName: "dishwasher",
|
|
69549
|
+
capScope: "device",
|
|
69550
|
+
addonId: null,
|
|
69551
|
+
access: "create"
|
|
69552
|
+
},
|
|
69334
69553
|
"dishwasher.setHalfLoad": {
|
|
69335
69554
|
capName: "dishwasher",
|
|
69336
69555
|
capScope: "device",
|
|
@@ -69343,6 +69562,12 @@ Object.freeze({
|
|
|
69343
69562
|
addonId: null,
|
|
69344
69563
|
access: "create"
|
|
69345
69564
|
},
|
|
69565
|
+
"dishwasher.setIntensiveZone": {
|
|
69566
|
+
capName: "dishwasher",
|
|
69567
|
+
capScope: "device",
|
|
69568
|
+
addonId: null,
|
|
69569
|
+
access: "create"
|
|
69570
|
+
},
|
|
69346
69571
|
"dishwasher.setOption": {
|
|
69347
69572
|
capName: "dishwasher",
|
|
69348
69573
|
capScope: "device",
|
|
@@ -69361,6 +69586,12 @@ Object.freeze({
|
|
|
69361
69586
|
addonId: null,
|
|
69362
69587
|
access: "create"
|
|
69363
69588
|
},
|
|
69589
|
+
"dishwasher.setVarioSpeedPlus": {
|
|
69590
|
+
capName: "dishwasher",
|
|
69591
|
+
capScope: "device",
|
|
69592
|
+
addonId: null,
|
|
69593
|
+
access: "create"
|
|
69594
|
+
},
|
|
69364
69595
|
"dishwasher.start": {
|
|
69365
69596
|
capName: "dishwasher",
|
|
69366
69597
|
capScope: "device",
|
|
@@ -73807,6 +74038,12 @@ Object.freeze({
|
|
|
73807
74038
|
addonId: null,
|
|
73808
74039
|
access: "view"
|
|
73809
74040
|
},
|
|
74041
|
+
"storageMigration.moverClearance": {
|
|
74042
|
+
capName: "storage-migration",
|
|
74043
|
+
capScope: "system",
|
|
74044
|
+
addonId: null,
|
|
74045
|
+
access: "view"
|
|
74046
|
+
},
|
|
73810
74047
|
"storageMigration.movers": {
|
|
73811
74048
|
capName: "storage-migration",
|
|
73812
74049
|
capScope: "system",
|
|
@@ -76000,6 +76237,11 @@ Object.freeze({
|
|
|
76000
76237
|
form: "single",
|
|
76001
76238
|
optional: false
|
|
76002
76239
|
}],
|
|
76240
|
+
"dishwasher.getOptions": [{
|
|
76241
|
+
name: "deviceId",
|
|
76242
|
+
form: "single",
|
|
76243
|
+
optional: false
|
|
76244
|
+
}],
|
|
76003
76245
|
"dishwasher.getStatus": [{
|
|
76004
76246
|
name: "deviceId",
|
|
76005
76247
|
form: "single",
|
|
@@ -76010,6 +76252,21 @@ Object.freeze({
|
|
|
76010
76252
|
form: "single",
|
|
76011
76253
|
optional: false
|
|
76012
76254
|
}],
|
|
76255
|
+
"dishwasher.resume": [{
|
|
76256
|
+
name: "deviceId",
|
|
76257
|
+
form: "single",
|
|
76258
|
+
optional: false
|
|
76259
|
+
}],
|
|
76260
|
+
"dishwasher.setChildLock": [{
|
|
76261
|
+
name: "deviceId",
|
|
76262
|
+
form: "single",
|
|
76263
|
+
optional: false
|
|
76264
|
+
}],
|
|
76265
|
+
"dishwasher.setExtraDry": [{
|
|
76266
|
+
name: "deviceId",
|
|
76267
|
+
form: "single",
|
|
76268
|
+
optional: false
|
|
76269
|
+
}],
|
|
76013
76270
|
"dishwasher.setHalfLoad": [{
|
|
76014
76271
|
name: "deviceId",
|
|
76015
76272
|
form: "single",
|
|
@@ -76020,6 +76277,11 @@ Object.freeze({
|
|
|
76020
76277
|
form: "single",
|
|
76021
76278
|
optional: false
|
|
76022
76279
|
}],
|
|
76280
|
+
"dishwasher.setIntensiveZone": [{
|
|
76281
|
+
name: "deviceId",
|
|
76282
|
+
form: "single",
|
|
76283
|
+
optional: false
|
|
76284
|
+
}],
|
|
76023
76285
|
"dishwasher.setOption": [{
|
|
76024
76286
|
name: "deviceId",
|
|
76025
76287
|
form: "single",
|
|
@@ -76035,6 +76297,11 @@ Object.freeze({
|
|
|
76035
76297
|
form: "single",
|
|
76036
76298
|
optional: false
|
|
76037
76299
|
}],
|
|
76300
|
+
"dishwasher.setVarioSpeedPlus": [{
|
|
76301
|
+
name: "deviceId",
|
|
76302
|
+
form: "single",
|
|
76303
|
+
optional: false
|
|
76304
|
+
}],
|
|
76038
76305
|
"dishwasher.start": [{
|
|
76039
76306
|
name: "deviceId",
|
|
76040
76307
|
form: "single",
|
|
@@ -78076,6 +78343,9 @@ new Map(Object.entries({
|
|
|
78076
78343
|
"wrapper-update-available": "system",
|
|
78077
78344
|
"backup-completed": "system",
|
|
78078
78345
|
"export-completed": "system",
|
|
78346
|
+
"alert-critical": "system",
|
|
78347
|
+
"alert-error": "system",
|
|
78348
|
+
"alert-critical-resolved": "system",
|
|
78079
78349
|
"storage-location-low": "system",
|
|
78080
78350
|
"storage-location-critical": "system",
|
|
78081
78351
|
"storage-location-ok": "system",
|
|
@@ -78200,6 +78470,16 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
78200
78470
|
"storage-location-ok"
|
|
78201
78471
|
]
|
|
78202
78472
|
},
|
|
78473
|
+
{
|
|
78474
|
+
id: "alerts",
|
|
78475
|
+
family: "system",
|
|
78476
|
+
label: "Alerts",
|
|
78477
|
+
kinds: [
|
|
78478
|
+
"alert-critical",
|
|
78479
|
+
"alert-error",
|
|
78480
|
+
"alert-critical-resolved"
|
|
78481
|
+
]
|
|
78482
|
+
},
|
|
78203
78483
|
{
|
|
78204
78484
|
id: "alarm",
|
|
78205
78485
|
family: "alarm",
|
|
@@ -78244,6 +78524,21 @@ var NC_SENSOR_RAISED_FIELD_BY_KIND = Object.freeze(Object.fromEntries(Object.ent
|
|
|
78244
78524
|
return [[descriptor.kind, field]];
|
|
78245
78525
|
})));
|
|
78246
78526
|
Object.freeze(Object.keys(NC_SENSOR_RAISED_FIELD_BY_KIND));
|
|
78527
|
+
object({
|
|
78528
|
+
phase: _enum(["raised", "resolved"]),
|
|
78529
|
+
episodeId: string().min(1),
|
|
78530
|
+
alertId: string().min(1),
|
|
78531
|
+
severity: AlertSeveritySchema,
|
|
78532
|
+
category: string(),
|
|
78533
|
+
title: string(),
|
|
78534
|
+
message: string(),
|
|
78535
|
+
sourceType: string().optional(),
|
|
78536
|
+
sourceId: string().optional(),
|
|
78537
|
+
nodeId: string().optional(),
|
|
78538
|
+
/** The alert's own action link (where the operator acts on it), when it has one. */
|
|
78539
|
+
actionUrl: string().optional(),
|
|
78540
|
+
at: number()
|
|
78541
|
+
});
|
|
78247
78542
|
var RULE_BODY_ONLY = ["body"];
|
|
78248
78543
|
var RULE_TEXT = ["title", "body"];
|
|
78249
78544
|
var BATTERY = ["device-battery-low", "device-battery-normal"];
|
|
@@ -78253,6 +78548,11 @@ var TANK = [
|
|
|
78253
78548
|
"device-tank-full",
|
|
78254
78549
|
"device-tank-normal"
|
|
78255
78550
|
];
|
|
78551
|
+
var ALERT_EPISODE = [
|
|
78552
|
+
"alert-critical",
|
|
78553
|
+
"alert-error",
|
|
78554
|
+
"alert-critical-resolved"
|
|
78555
|
+
];
|
|
78256
78556
|
var UPDATES = [
|
|
78257
78557
|
"addon-update-available",
|
|
78258
78558
|
"server-update-available",
|
|
@@ -78445,14 +78745,14 @@ var STATE_SUMMARY_VARS = [
|
|
|
78445
78745
|
([...RULE_TEXT], [...CONSUMABLE]),
|
|
78446
78746
|
([...RULE_TEXT], [...TANK]),
|
|
78447
78747
|
[...RULE_TEXT],
|
|
78448
|
-
([...RULE_TEXT], [...UPDATES]),
|
|
78449
|
-
([...RULE_TEXT], [...UPDATES]),
|
|
78450
|
-
[...RULE_TEXT],
|
|
78748
|
+
([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
|
|
78749
|
+
([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
|
|
78451
78750
|
[...RULE_TEXT],
|
|
78452
78751
|
[...RULE_TEXT],
|
|
78453
78752
|
[...RULE_TEXT],
|
|
78454
78753
|
[...RULE_TEXT],
|
|
78455
78754
|
[...RULE_TEXT],
|
|
78755
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78456
78756
|
[...RULE_TEXT],
|
|
78457
78757
|
[...RULE_TEXT],
|
|
78458
78758
|
[...RULE_TEXT],
|
|
@@ -78470,7 +78770,11 @@ var STATE_SUMMARY_VARS = [
|
|
|
78470
78770
|
[...RULE_TEXT],
|
|
78471
78771
|
[...RULE_TEXT],
|
|
78472
78772
|
[...RULE_TEXT],
|
|
78473
|
-
[...RULE_TEXT],
|
|
78773
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78774
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78775
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78776
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78777
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
78474
78778
|
[...RULE_TEXT],
|
|
78475
78779
|
[...RULE_TEXT],
|
|
78476
78780
|
[...RULE_TEXT],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-provider-dreo",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.129",
|
|
4
4
|
"description": "Dreo smart-device (fan / air-circulator / purifier / heater / humidifier) device-provider addon for CamStack — wraps the @apocaliss92/nodedreo Dreo cloud client (REST + WebSocket)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|