@camstack/addon-provider-homeassistant 1.2.635 → 1.2.636
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/CHANGELOG.md +6 -0
- package/dist/addon.js +5 -1
- package/dist/addon.mjs +5 -1
- package/dist/{dist-C_PMvyYa.js → dist-BS9DCd76.js} +484 -10
- package/dist/{dist-CYl0u8cF.mjs → dist-BusXPPvn.mjs} +484 -10
- package/dist/ha-export/ha-export.addon.js +5 -1
- package/dist/ha-export/ha-export.addon.mjs +5 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/dist/addon.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_dist = require("./dist-
|
|
2
|
+
const require_dist = require("./dist-BS9DCd76.js");
|
|
3
3
|
let node_crypto = require("node:crypto");
|
|
4
4
|
let node_zlib = require("node:zlib");
|
|
5
5
|
//#region src/ha-admin-link.ts
|
|
@@ -2443,6 +2443,8 @@ function readNumericAttr$1(attrs, key) {
|
|
|
2443
2443
|
//#region src/devices/ha-media-player-device.ts
|
|
2444
2444
|
var COLD_START$10 = {
|
|
2445
2445
|
state: "off",
|
|
2446
|
+
stateSource: "reported",
|
|
2447
|
+
assumedFields: [],
|
|
2446
2448
|
volumeLevel: null,
|
|
2447
2449
|
isMuted: null,
|
|
2448
2450
|
source: "",
|
|
@@ -2474,6 +2476,8 @@ var HaMediaPlayerDevice = class extends HaBaseChildDevice {
|
|
|
2474
2476
|
const playerState = mapHaMediaPlayerState(state.state);
|
|
2475
2477
|
const slice = {
|
|
2476
2478
|
state: playerState ?? "off",
|
|
2479
|
+
stateSource: "reported",
|
|
2480
|
+
assumedFields: [],
|
|
2477
2481
|
volumeLevel: readVolumeAsPercent(attrs),
|
|
2478
2482
|
isMuted: readBooleanAttr(attrs, "is_volume_muted"),
|
|
2479
2483
|
source: readStringAttr$2(attrs, "source") ?? "",
|
package/dist/addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as lawnMowerControlCapability, $t as union, A as buttonCapability, At as weatherCapability, B as coverCapability, Bt as defineRecordKinds, C as batteryCapability, Ct as tryConvertDelta, D as brokerCapability, Dt as valveCapability, E as brightnessCapability, Et as vacuumControlCapability, F as connectivityCapability, G as eventEmitterCapability, Gt as array, H as deviceAdoptionCapability, It as RecordSecretUnavailableError, J as gasCapability, Jt as literal, K as fanControlCapability, Kt as boolean, Lt as baseUnitOf, M as carbonMonoxideCapability, Mt as DeviceRole, N as climateControlCapability, Nt as DeviceType, O as buildAddonRouteProvider, Ot as vibrationCapability, P as colorCapability, Pt as errMsg, Q as ingestReading, Qt as string, R as contactCapability, Rt as createEvent, S as automationControlCapability, St as temperatureSensorCapability, T as binaryCapability, Tt as updateCapability, V as deviceAdminLinkCapability, Vt as entryBody, W as enumSensorCapability, Wt as _enum, X as humiditySensorCapability, Xt as object, Y as humidifierCapability, Yt as number, Z as imageCapability, Zt as record, _ as accessoriesCapability, _t as runningStateCapability, at as notifierCapability, b as alarmPanelCapability, bt as switchCapability, ct as parseAdminBase, dt as presenceCapability, en as unknown, et as lockControlCapability, ft as pressureSensorCapability, g as TargetSchema, gt as runningFromVacuumState, h as RUNNING_STATE_COLD, ht as runningFromMediaPlayer, it as notificationOutputCapability, j as calendarSourceCapability, jt as DeviceFeature, k as buildDeviceAdminUrl, kt as waterHeaterCapability, lt as powerMeterCapability, mt as runningFromLawnMower, n as BaseDevice, nn as EventCategory, nt as motionCapability, ot as numericSensorCapability, pt as quantityFromUnit, q as floodCapability, qt as discriminatedUnion, r as BaseDeviceProvider, rt as normalizeUnit, tn as url, tt as mediaPlayerCapability, u as EnumSensorDateTimeFormatSchema, ut as prepareNotification, v as addonRoutesCapability, vt as scriptRunnerCapability, w as bestLocationMatch, wt as tryConvertUnit, x as ambientLightSensorCapability, xt as tamperCapability, y as airQualitySensorCapability, yt as smokeCapability, z as controlCapability, zt as defineEntryKind } from "./dist-
|
|
1
|
+
import { $ as lawnMowerControlCapability, $t as union, A as buttonCapability, At as weatherCapability, B as coverCapability, Bt as defineRecordKinds, C as batteryCapability, Ct as tryConvertDelta, D as brokerCapability, Dt as valveCapability, E as brightnessCapability, Et as vacuumControlCapability, F as connectivityCapability, G as eventEmitterCapability, Gt as array, H as deviceAdoptionCapability, It as RecordSecretUnavailableError, J as gasCapability, Jt as literal, K as fanControlCapability, Kt as boolean, Lt as baseUnitOf, M as carbonMonoxideCapability, Mt as DeviceRole, N as climateControlCapability, Nt as DeviceType, O as buildAddonRouteProvider, Ot as vibrationCapability, P as colorCapability, Pt as errMsg, Q as ingestReading, Qt as string, R as contactCapability, Rt as createEvent, S as automationControlCapability, St as temperatureSensorCapability, T as binaryCapability, Tt as updateCapability, V as deviceAdminLinkCapability, Vt as entryBody, W as enumSensorCapability, Wt as _enum, X as humiditySensorCapability, Xt as object, Y as humidifierCapability, Yt as number, Z as imageCapability, Zt as record, _ as accessoriesCapability, _t as runningStateCapability, at as notifierCapability, b as alarmPanelCapability, bt as switchCapability, ct as parseAdminBase, dt as presenceCapability, en as unknown, et as lockControlCapability, ft as pressureSensorCapability, g as TargetSchema, gt as runningFromVacuumState, h as RUNNING_STATE_COLD, ht as runningFromMediaPlayer, it as notificationOutputCapability, j as calendarSourceCapability, jt as DeviceFeature, k as buildDeviceAdminUrl, kt as waterHeaterCapability, lt as powerMeterCapability, mt as runningFromLawnMower, n as BaseDevice, nn as EventCategory, nt as motionCapability, ot as numericSensorCapability, pt as quantityFromUnit, q as floodCapability, qt as discriminatedUnion, r as BaseDeviceProvider, rt as normalizeUnit, tn as url, tt as mediaPlayerCapability, u as EnumSensorDateTimeFormatSchema, ut as prepareNotification, v as addonRoutesCapability, vt as scriptRunnerCapability, w as bestLocationMatch, wt as tryConvertUnit, x as ambientLightSensorCapability, xt as tamperCapability, y as airQualitySensorCapability, yt as smokeCapability, z as controlCapability, zt as defineEntryKind } from "./dist-BusXPPvn.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { brotliCompressSync, deflateSync, gzipSync } from "node:zlib";
|
|
4
4
|
//#region src/ha-admin-link.ts
|
|
@@ -2442,6 +2442,8 @@ function readNumericAttr$1(attrs, key) {
|
|
|
2442
2442
|
//#region src/devices/ha-media-player-device.ts
|
|
2443
2443
|
var COLD_START$10 = {
|
|
2444
2444
|
state: "off",
|
|
2445
|
+
stateSource: "reported",
|
|
2446
|
+
assumedFields: [],
|
|
2445
2447
|
volumeLevel: null,
|
|
2446
2448
|
isMuted: null,
|
|
2447
2449
|
source: "",
|
|
@@ -2473,6 +2475,8 @@ var HaMediaPlayerDevice = class extends HaBaseChildDevice {
|
|
|
2473
2475
|
const playerState = mapHaMediaPlayerState(state.state);
|
|
2474
2476
|
const slice = {
|
|
2475
2477
|
state: playerState ?? "off",
|
|
2478
|
+
stateSource: "reported",
|
|
2479
|
+
assumedFields: [],
|
|
2476
2480
|
volumeLevel: readVolumeAsPercent(attrs),
|
|
2477
2481
|
isMuted: readBooleanAttr(attrs, "is_volume_muted"),
|
|
2478
2482
|
source: readStringAttr$2(attrs, "source") ?? "",
|
|
@@ -5580,7 +5580,7 @@ var ZodIssueCode = {
|
|
|
5580
5580
|
var ZodFirstPartyTypeKind;
|
|
5581
5581
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5582
5582
|
//#endregion
|
|
5583
|
-
//#region ../types/dist/sleep-
|
|
5583
|
+
//#region ../types/dist/sleep-DJws6ho7.mjs
|
|
5584
5584
|
/**
|
|
5585
5585
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5586
5586
|
* window to float samples (D455).
|
|
@@ -9094,6 +9094,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
9094
9094
|
"recording-onboard",
|
|
9095
9095
|
"recording-signal",
|
|
9096
9096
|
"records",
|
|
9097
|
+
"remote",
|
|
9097
9098
|
"running-state",
|
|
9098
9099
|
"scene-monitor",
|
|
9099
9100
|
"script-runner",
|
|
@@ -9117,6 +9118,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
9117
9118
|
"system",
|
|
9118
9119
|
"tamper",
|
|
9119
9120
|
"temperature-sensor",
|
|
9121
|
+
"template",
|
|
9120
9122
|
"terminal-session",
|
|
9121
9123
|
"toast",
|
|
9122
9124
|
"training",
|
|
@@ -10057,6 +10059,11 @@ Object.freeze({
|
|
|
10057
10059
|
"standby"
|
|
10058
10060
|
]
|
|
10059
10061
|
},
|
|
10062
|
+
{
|
|
10063
|
+
"path": "stateSource",
|
|
10064
|
+
"valueType": "enum",
|
|
10065
|
+
"enumValues": ["reported", "assumed"]
|
|
10066
|
+
},
|
|
10060
10067
|
{
|
|
10061
10068
|
"path": "volumeLevel",
|
|
10062
10069
|
"valueType": "number"
|
|
@@ -10332,6 +10339,18 @@ Object.freeze({
|
|
|
10332
10339
|
{
|
|
10333
10340
|
"path": "volume",
|
|
10334
10341
|
"valueType": "number"
|
|
10342
|
+
},
|
|
10343
|
+
{
|
|
10344
|
+
"path": "lastFeedGrams",
|
|
10345
|
+
"valueType": "number"
|
|
10346
|
+
},
|
|
10347
|
+
{
|
|
10348
|
+
"path": "lastFeedHopper1",
|
|
10349
|
+
"valueType": "number"
|
|
10350
|
+
},
|
|
10351
|
+
{
|
|
10352
|
+
"path": "lastFeedHopper2",
|
|
10353
|
+
"valueType": "number"
|
|
10335
10354
|
}
|
|
10336
10355
|
],
|
|
10337
10356
|
"power-meter": [
|
|
@@ -16806,9 +16825,21 @@ var AlertSeveritySchema = _enum([
|
|
|
16806
16825
|
"error",
|
|
16807
16826
|
"critical"
|
|
16808
16827
|
]);
|
|
16828
|
+
/**
|
|
16829
|
+
* An action that RUNS something instead of going somewhere: the admin UI calls
|
|
16830
|
+
* the addon's custom action (`addons.custom`) with exactly these fields. The
|
|
16831
|
+
* producer owns the meaning; the UI knows nothing about the addon or the kind.
|
|
16832
|
+
*/
|
|
16833
|
+
var AlertActionInvokeSchema = object({
|
|
16834
|
+
addonId: string().min(1),
|
|
16835
|
+
action: string().min(1),
|
|
16836
|
+
input: record(string(), unknown()).optional()
|
|
16837
|
+
});
|
|
16838
|
+
/** An action has `href` (a link) OR `invoke` (a button that runs a custom action). */
|
|
16809
16839
|
var AlertActionSchema = object({
|
|
16810
16840
|
label: string(),
|
|
16811
16841
|
href: string().optional(),
|
|
16842
|
+
invoke: AlertActionInvokeSchema.optional(),
|
|
16812
16843
|
/**
|
|
16813
16844
|
* How `href` is followed. Absent / `app`: an admin-ui route (client-side).
|
|
16814
16845
|
* `server`: a route the HUB serves (an addon HTTP route such as an OAuth
|
|
@@ -59213,6 +59244,318 @@ onBrightnessChanged: { data: object({
|
|
|
59213
59244
|
} } }
|
|
59214
59245
|
};
|
|
59215
59246
|
/**
|
|
59247
|
+
* The role vocabulary of a remote (D963): what a button MEANS, independent of
|
|
59248
|
+
* how it is wired. A layout template places buttons by role; a device binds a
|
|
59249
|
+
* role to an action; an exporter asks for a role by name. Roles are shared so
|
|
59250
|
+
* one layout fits every appliance and one voice command fits every binding.
|
|
59251
|
+
*
|
|
59252
|
+
* A role outside this list is `custom:<key>` — the operator's own button (a
|
|
59253
|
+
* SmartIR source, a channel preset). The key is a lowercase slug.
|
|
59254
|
+
*/
|
|
59255
|
+
var REMOTE_KNOWN_ROLES = [
|
|
59256
|
+
"power",
|
|
59257
|
+
"power_on",
|
|
59258
|
+
"power_off",
|
|
59259
|
+
"volume_up",
|
|
59260
|
+
"volume_down",
|
|
59261
|
+
"mute",
|
|
59262
|
+
"channel_up",
|
|
59263
|
+
"channel_down",
|
|
59264
|
+
"up",
|
|
59265
|
+
"down",
|
|
59266
|
+
"left",
|
|
59267
|
+
"right",
|
|
59268
|
+
"ok",
|
|
59269
|
+
"back",
|
|
59270
|
+
"home",
|
|
59271
|
+
"menu",
|
|
59272
|
+
"info",
|
|
59273
|
+
"guide",
|
|
59274
|
+
"exit",
|
|
59275
|
+
"input",
|
|
59276
|
+
"play",
|
|
59277
|
+
"pause",
|
|
59278
|
+
"play_pause",
|
|
59279
|
+
"stop",
|
|
59280
|
+
"next",
|
|
59281
|
+
"previous",
|
|
59282
|
+
"fast_forward",
|
|
59283
|
+
"rewind",
|
|
59284
|
+
"digit_0",
|
|
59285
|
+
"digit_1",
|
|
59286
|
+
"digit_2",
|
|
59287
|
+
"digit_3",
|
|
59288
|
+
"digit_4",
|
|
59289
|
+
"digit_5",
|
|
59290
|
+
"digit_6",
|
|
59291
|
+
"digit_7",
|
|
59292
|
+
"digit_8",
|
|
59293
|
+
"digit_9"
|
|
59294
|
+
];
|
|
59295
|
+
var CUSTOM_KEY_RE = /^[a-z0-9][a-z0-9_]{0,47}$/;
|
|
59296
|
+
var KNOWN_ROLES = new Set(REMOTE_KNOWN_ROLES);
|
|
59297
|
+
function isRemoteKnownRole(value) {
|
|
59298
|
+
return KNOWN_ROLES.has(value);
|
|
59299
|
+
}
|
|
59300
|
+
function isRemoteCustomKey(key) {
|
|
59301
|
+
return CUSTOM_KEY_RE.test(key);
|
|
59302
|
+
}
|
|
59303
|
+
/** The key of a `custom:<key>` role, or null for any other string. */
|
|
59304
|
+
function customKeyOfRole(role) {
|
|
59305
|
+
if (!role.startsWith("custom:")) return null;
|
|
59306
|
+
const key = role.slice(7);
|
|
59307
|
+
return isRemoteCustomKey(key) ? key : null;
|
|
59308
|
+
}
|
|
59309
|
+
function isRemoteRole(value) {
|
|
59310
|
+
return isRemoteKnownRole(value) || customKeyOfRole(value) !== null;
|
|
59311
|
+
}
|
|
59312
|
+
var RemoteRoleSchema = string().refine(isRemoteRole, { message: "a role is one of the known roles or custom:<key> (lowercase letters, digits, _)" });
|
|
59313
|
+
var RemoteBindingSchema = object({ action: AutomationCapStepSchema.extend({ deviceId: number().int().nonnegative() }) });
|
|
59314
|
+
var RemoteCustomButtonSchema = object({
|
|
59315
|
+
/** The slug after `custom:` in the role. */
|
|
59316
|
+
key: string().refine(isRemoteCustomKey, { message: "a lowercase slug" }),
|
|
59317
|
+
/** What the operator calls it, and what a voice command may name. */
|
|
59318
|
+
name: string().min(1).max(60)
|
|
59319
|
+
});
|
|
59320
|
+
var RemotePowerModeSchema = _enum(["toggle", "discrete"]);
|
|
59321
|
+
var RemoteConfigSchema = object({
|
|
59322
|
+
layoutTemplateId: string().min(1).nullable(),
|
|
59323
|
+
/**
|
|
59324
|
+
* The transmitter device new bindings and an import send through. A binding
|
|
59325
|
+
* names its own device, so one command may override it.
|
|
59326
|
+
*/
|
|
59327
|
+
defaultTransmitterId: number().int().nonnegative().nullable().default(null),
|
|
59328
|
+
/** Keyed by role. A role with no entry falls back to the native cap. */
|
|
59329
|
+
bindings: record(string(), RemoteBindingSchema),
|
|
59330
|
+
customButtons: array(RemoteCustomButtonSchema).max(100),
|
|
59331
|
+
power: object({ mode: RemotePowerModeSchema })
|
|
59332
|
+
}).superRefine((config, ctx) => {
|
|
59333
|
+
const roles = Object.keys(config.bindings);
|
|
59334
|
+
if (roles.length > 200) ctx.addIssue({
|
|
59335
|
+
code: "custom",
|
|
59336
|
+
message: "too many bindings",
|
|
59337
|
+
path: ["bindings"]
|
|
59338
|
+
});
|
|
59339
|
+
for (const role of roles) if (!isRemoteRole(role)) ctx.addIssue({
|
|
59340
|
+
code: "custom",
|
|
59341
|
+
message: `"${role}" is not a role`,
|
|
59342
|
+
path: ["bindings", role]
|
|
59343
|
+
});
|
|
59344
|
+
const keys = /* @__PURE__ */ new Set();
|
|
59345
|
+
config.customButtons.forEach((button, index) => {
|
|
59346
|
+
if (keys.has(button.key)) ctx.addIssue({
|
|
59347
|
+
code: "custom",
|
|
59348
|
+
message: `custom button "${button.key}" is listed twice`,
|
|
59349
|
+
path: [
|
|
59350
|
+
"customButtons",
|
|
59351
|
+
index,
|
|
59352
|
+
"key"
|
|
59353
|
+
]
|
|
59354
|
+
});
|
|
59355
|
+
keys.add(button.key);
|
|
59356
|
+
});
|
|
59357
|
+
for (const role of roles) {
|
|
59358
|
+
const key = customKeyOfRole(role);
|
|
59359
|
+
if (key !== null && !keys.has(key)) ctx.addIssue({
|
|
59360
|
+
code: "custom",
|
|
59361
|
+
message: `${role} is bound but has no entry in customButtons`,
|
|
59362
|
+
path: ["bindings", role]
|
|
59363
|
+
});
|
|
59364
|
+
}
|
|
59365
|
+
});
|
|
59366
|
+
object({
|
|
59367
|
+
power: object({
|
|
59368
|
+
state: _enum(["on", "off"]),
|
|
59369
|
+
at: number()
|
|
59370
|
+
}).nullable(),
|
|
59371
|
+
muted: object({
|
|
59372
|
+
value: boolean(),
|
|
59373
|
+
at: number()
|
|
59374
|
+
}).nullable()
|
|
59375
|
+
});
|
|
59376
|
+
var RemoteLayoutButtonSchema = object({
|
|
59377
|
+
id: string().min(1).max(40),
|
|
59378
|
+
/** 0-based grid position. */
|
|
59379
|
+
row: number().int().min(0).max(24),
|
|
59380
|
+
col: number().int().min(0).max(24),
|
|
59381
|
+
rowSpan: number().int().min(1).max(24),
|
|
59382
|
+
colSpan: number().int().min(1).max(24),
|
|
59383
|
+
icon: string().min(1).max(60).optional(),
|
|
59384
|
+
label: string().min(1).max(40).optional(),
|
|
59385
|
+
role: RemoteRoleSchema
|
|
59386
|
+
});
|
|
59387
|
+
object({
|
|
59388
|
+
columns: number().int().min(1).max(24),
|
|
59389
|
+
rows: number().int().min(1).max(24),
|
|
59390
|
+
buttons: array(RemoteLayoutButtonSchema).max(200)
|
|
59391
|
+
}).superRefine((grid, ctx) => {
|
|
59392
|
+
const ids = /* @__PURE__ */ new Set();
|
|
59393
|
+
const taken = /* @__PURE__ */ new Map();
|
|
59394
|
+
grid.buttons.forEach((button, index) => {
|
|
59395
|
+
if (ids.has(button.id)) ctx.addIssue({
|
|
59396
|
+
code: "custom",
|
|
59397
|
+
message: `button id "${button.id}" is used twice`,
|
|
59398
|
+
path: [
|
|
59399
|
+
"buttons",
|
|
59400
|
+
index,
|
|
59401
|
+
"id"
|
|
59402
|
+
]
|
|
59403
|
+
});
|
|
59404
|
+
ids.add(button.id);
|
|
59405
|
+
if (button.row + button.rowSpan > grid.rows || button.col + button.colSpan > grid.columns) {
|
|
59406
|
+
ctx.addIssue({
|
|
59407
|
+
code: "custom",
|
|
59408
|
+
message: `button "${button.id}" leaves the grid`,
|
|
59409
|
+
path: ["buttons", index]
|
|
59410
|
+
});
|
|
59411
|
+
return;
|
|
59412
|
+
}
|
|
59413
|
+
for (let r = button.row; r < button.row + button.rowSpan; r += 1) for (let c = button.col; c < button.col + button.colSpan; c += 1) {
|
|
59414
|
+
const cell = `${r}:${c}`;
|
|
59415
|
+
const other = taken.get(cell);
|
|
59416
|
+
if (other !== void 0) {
|
|
59417
|
+
ctx.addIssue({
|
|
59418
|
+
code: "custom",
|
|
59419
|
+
message: `buttons "${other}" and "${button.id}" overlap`,
|
|
59420
|
+
path: ["buttons", index]
|
|
59421
|
+
});
|
|
59422
|
+
return;
|
|
59423
|
+
}
|
|
59424
|
+
taken.set(cell, button.id);
|
|
59425
|
+
}
|
|
59426
|
+
});
|
|
59427
|
+
});
|
|
59428
|
+
var RemoteBoundCommandSchema = object({
|
|
59429
|
+
role: RemoteRoleSchema,
|
|
59430
|
+
/** The operator's name for a custom button; absent for a known role. */
|
|
59431
|
+
label: string().optional(),
|
|
59432
|
+
custom: boolean()
|
|
59433
|
+
});
|
|
59434
|
+
var RemoteCommandListSchema = object({
|
|
59435
|
+
layoutTemplateId: string().nullable(),
|
|
59436
|
+
power: object({ mode: RemotePowerModeSchema }),
|
|
59437
|
+
/** Only the roles that are BOUND — the ones a press can reach. */
|
|
59438
|
+
commands: array(RemoteBoundCommandSchema)
|
|
59439
|
+
});
|
|
59440
|
+
var RemoteRefusalReasonSchema = _enum([
|
|
59441
|
+
"no-remote",
|
|
59442
|
+
"unbound-role",
|
|
59443
|
+
"action-failed"
|
|
59444
|
+
]);
|
|
59445
|
+
var RemoteSendResultSchema = discriminatedUnion("status", [
|
|
59446
|
+
object({
|
|
59447
|
+
status: literal("sent"),
|
|
59448
|
+
/** How many times the action ran. */
|
|
59449
|
+
sends: number().int().min(1)
|
|
59450
|
+
}),
|
|
59451
|
+
object({
|
|
59452
|
+
status: literal("skipped"),
|
|
59453
|
+
reason: literal("already-in-state")
|
|
59454
|
+
}),
|
|
59455
|
+
object({
|
|
59456
|
+
status: literal("refused"),
|
|
59457
|
+
reason: RemoteRefusalReasonSchema,
|
|
59458
|
+
detail: string().optional()
|
|
59459
|
+
})
|
|
59460
|
+
]);
|
|
59461
|
+
var RemoteMediaCommandSchema = _enum([
|
|
59462
|
+
"play",
|
|
59463
|
+
"pause",
|
|
59464
|
+
"stop",
|
|
59465
|
+
"next",
|
|
59466
|
+
"previous",
|
|
59467
|
+
"setMute",
|
|
59468
|
+
"selectSource"
|
|
59469
|
+
]);
|
|
59470
|
+
/** A send result, or `not-routed`: the role is not bound, so the native cap answers. */
|
|
59471
|
+
var RemoteMediaCommandResultSchema = discriminatedUnion("status", [...RemoteSendResultSchema.options, object({ status: literal("not-routed") })]);
|
|
59472
|
+
var RemoteSetConfigResultSchema = discriminatedUnion("status", [object({ status: literal("saved") }), object({
|
|
59473
|
+
status: literal("refused"),
|
|
59474
|
+
reason: _enum(["unknown-template", "not-a-media-player"]),
|
|
59475
|
+
detail: string()
|
|
59476
|
+
})]);
|
|
59477
|
+
var deviceInput = object({ deviceId: number().int().nonnegative() });
|
|
59478
|
+
DeviceType.MediaPlayer;
|
|
59479
|
+
method(deviceInput, RemoteConfigSchema, { auth: "admin" }), method(deviceInput.extend({ config: RemoteConfigSchema }), RemoteSetConfigResultSchema, {
|
|
59480
|
+
kind: "mutation",
|
|
59481
|
+
auth: "admin"
|
|
59482
|
+
}), method(deviceInput, RemoteCommandListSchema, { auth: "protected" }), method(deviceInput.extend({
|
|
59483
|
+
role: RemoteRoleSchema,
|
|
59484
|
+
/** Sends in a row (volume steps). */
|
|
59485
|
+
repeat: number().int().min(1).max(50).default(1)
|
|
59486
|
+
}), RemoteSendResultSchema, {
|
|
59487
|
+
kind: "mutation",
|
|
59488
|
+
auth: "protected"
|
|
59489
|
+
}), method(deviceInput.extend({
|
|
59490
|
+
command: RemoteMediaCommandSchema,
|
|
59491
|
+
muted: boolean().optional(),
|
|
59492
|
+
source: string().optional(),
|
|
59493
|
+
repeat: number().int().min(1).max(50).default(1)
|
|
59494
|
+
}), RemoteMediaCommandResultSchema, {
|
|
59495
|
+
kind: "mutation",
|
|
59496
|
+
auth: "protected"
|
|
59497
|
+
});
|
|
59498
|
+
var TemplateKindSchema = _enum(["remote"]);
|
|
59499
|
+
/**
|
|
59500
|
+
* template — the generic store of reusable, named operator data (D963). A
|
|
59501
|
+
* record is `{ id, kind, name, payload }`; the kinds (today only `remote`, the
|
|
59502
|
+
* button grid of a remote) and the schema each payload must satisfy are
|
|
59503
|
+
* declared by the system in `template-kinds.ts`. Nothing here is specific to a
|
|
59504
|
+
* kind: the engine validates a payload against its kind's schema and, on a
|
|
59505
|
+
* delete, asks the kind's owner whether anything still points at the record.
|
|
59506
|
+
*
|
|
59507
|
+
* Every refusal is a typed result — a UI says "unknown kind" or names the
|
|
59508
|
+
* devices that still use a template, without parsing text.
|
|
59509
|
+
*/
|
|
59510
|
+
var TemplateRecordSchema = object({
|
|
59511
|
+
id: string().min(1),
|
|
59512
|
+
kind: TemplateKindSchema,
|
|
59513
|
+
name: string().min(1).max(120),
|
|
59514
|
+
/** Shaped by the kind; `checkTemplatePayload(kind, payload)` reads it. */
|
|
59515
|
+
payload: unknown(),
|
|
59516
|
+
createdAt: number(),
|
|
59517
|
+
updatedAt: number()
|
|
59518
|
+
});
|
|
59519
|
+
var TemplateWriteResultSchema = discriminatedUnion("status", [object({
|
|
59520
|
+
status: literal("saved"),
|
|
59521
|
+
template: TemplateRecordSchema
|
|
59522
|
+
}), object({
|
|
59523
|
+
status: literal("refused"),
|
|
59524
|
+
reason: _enum(["invalid-payload", "not-found"]),
|
|
59525
|
+
detail: string()
|
|
59526
|
+
})]);
|
|
59527
|
+
/** A device still pointing at a template. */
|
|
59528
|
+
var TemplateUserSchema = object({
|
|
59529
|
+
deviceId: number().int().nonnegative(),
|
|
59530
|
+
name: string()
|
|
59531
|
+
});
|
|
59532
|
+
var TemplateDeleteResultSchema = discriminatedUnion("status", [
|
|
59533
|
+
object({ status: literal("deleted") }),
|
|
59534
|
+
object({ status: literal("not-found") }),
|
|
59535
|
+
object({
|
|
59536
|
+
status: literal("in-use"),
|
|
59537
|
+
devices: array(TemplateUserSchema).min(1)
|
|
59538
|
+
})
|
|
59539
|
+
]);
|
|
59540
|
+
method(object({ kind: TemplateKindSchema.optional() }), array(TemplateRecordSchema), { auth: "protected" }), method(object({ id: string().min(1) }), TemplateRecordSchema.nullable(), { auth: "protected" }), method(object({
|
|
59541
|
+
kind: TemplateKindSchema,
|
|
59542
|
+
name: string().min(1).max(120),
|
|
59543
|
+
payload: unknown()
|
|
59544
|
+
}), TemplateWriteResultSchema, {
|
|
59545
|
+
kind: "mutation",
|
|
59546
|
+
auth: "admin"
|
|
59547
|
+
}), method(object({
|
|
59548
|
+
id: string().min(1),
|
|
59549
|
+
name: string().min(1).max(120).optional(),
|
|
59550
|
+
payload: unknown().optional()
|
|
59551
|
+
}), TemplateWriteResultSchema, {
|
|
59552
|
+
kind: "mutation",
|
|
59553
|
+
auth: "admin"
|
|
59554
|
+
}), method(object({ id: string().min(1) }), TemplateDeleteResultSchema, {
|
|
59555
|
+
kind: "mutation",
|
|
59556
|
+
auth: "admin"
|
|
59557
|
+
});
|
|
59558
|
+
/**
|
|
59216
59559
|
* button — device-scoped capability for HA `button.*` / `input_button.*`
|
|
59217
59560
|
* fire-only actuators. A button entity has no readable state — pressing it
|
|
59218
59561
|
* triggers an action on the HA side. There is no `status` / `runtimeState`:
|
|
@@ -63414,9 +63757,35 @@ var MediaInfoSchema = object({
|
|
|
63414
63757
|
/** Optional cover-art / thumbnail URL. */
|
|
63415
63758
|
imageUrl: string().optional()
|
|
63416
63759
|
});
|
|
63760
|
+
/**
|
|
63761
|
+
* Where `state`, `volumeLevel`, `isMuted` and `source` come from. `reported`:
|
|
63762
|
+
* the device said so. `assumed`: the driver has no feedback (infrared) and
|
|
63763
|
+
* tracks what it last SENT; it moves only after a send was accepted, and a
|
|
63764
|
+
* human at the real remote makes it wrong. A UI shows an assumed value as a
|
|
63765
|
+
* guess, never as a reading.
|
|
63766
|
+
*/
|
|
63767
|
+
var MediaPlayerStateSourceSchema = _enum(["reported", "assumed"]);
|
|
63768
|
+
/** The fields of a media-player status a driver can only guess. */
|
|
63769
|
+
var MediaPlayerAssumedFieldSchema = _enum([
|
|
63770
|
+
"state",
|
|
63771
|
+
"volumeLevel",
|
|
63772
|
+
"isMuted",
|
|
63773
|
+
"source"
|
|
63774
|
+
]);
|
|
63417
63775
|
var MediaPlayerStatusSchema = object({
|
|
63418
63776
|
/** Playback lifecycle state. */
|
|
63419
63777
|
state: MediaPlayerStateSchema,
|
|
63778
|
+
/**
|
|
63779
|
+
* Whether the state fields are readings or the driver's own bookkeeping.
|
|
63780
|
+
* A slice written before this field existed parses as `reported`.
|
|
63781
|
+
*/
|
|
63782
|
+
stateSource: MediaPlayerStateSourceSchema.default("reported"),
|
|
63783
|
+
/**
|
|
63784
|
+
* Which fields are the driver's own guess. `stateSource` is `assumed` when
|
|
63785
|
+
* this is not empty; a field not listed here is a reading even then (power
|
|
63786
|
+
* from a running-state source, mute guessed from the last send).
|
|
63787
|
+
*/
|
|
63788
|
+
assumedFields: array(MediaPlayerAssumedFieldSchema).default([]),
|
|
63420
63789
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
63421
63790
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
63422
63791
|
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
@@ -65379,6 +65748,14 @@ var PetFeederStatusSchema = object({
|
|
|
65379
65748
|
feedSound: boolean(),
|
|
65380
65749
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
65381
65750
|
volume: number().meta(readingMeta("none")),
|
|
65751
|
+
/** Portion (grams) of the last manual feed sent from a single-hopper
|
|
65752
|
+
* stepper — the default the next manual feed starts from. Persisted per
|
|
65753
|
+
* device by the provider; null until a manual feed has been sent. */
|
|
65754
|
+
lastFeedGrams: gramsPortion.nullable(),
|
|
65755
|
+
/** Hopper-1 portion of the last manual feed (dual-hopper); null until sent. */
|
|
65756
|
+
lastFeedHopper1: gramsPortion.nullable(),
|
|
65757
|
+
/** Hopper-2 portion of the last manual feed (dual-hopper); null until sent. */
|
|
65758
|
+
lastFeedHopper2: gramsPortion.nullable(),
|
|
65382
65759
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
65383
65760
|
lastFetchedAt: number()
|
|
65384
65761
|
});
|
|
@@ -71424,6 +71801,14 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
|
|
|
71424
71801
|
kind: "mutation",
|
|
71425
71802
|
auth: "admin"
|
|
71426
71803
|
});
|
|
71804
|
+
discriminatedUnion("kind", [object({
|
|
71805
|
+
kind: literal("raw"),
|
|
71806
|
+
timings: array(number().int()),
|
|
71807
|
+
settings: TransmitSettingsSchema.optional()
|
|
71808
|
+
}), object({
|
|
71809
|
+
kind: literal("pronto"),
|
|
71810
|
+
code: string()
|
|
71811
|
+
})]);
|
|
71427
71812
|
function resolveSince(running, previous, transitionAtMs, bootstrapSinceMs) {
|
|
71428
71813
|
if (running === null) return null;
|
|
71429
71814
|
const prevRunning = previous?.running ?? null;
|
|
@@ -71861,7 +72246,7 @@ function tryConvertDelta(value, from, to) {
|
|
|
71861
72246
|
return shifted - origin;
|
|
71862
72247
|
}
|
|
71863
72248
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
71864
|
-
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Camera, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
72249
|
+
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Camera, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
71865
72250
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
71866
72251
|
DeviceRole.BinarySensor, DeviceRole.MotionSensor;
|
|
71867
72252
|
new Set(CAP_NAMES);
|
|
@@ -81151,6 +81536,41 @@ Object.freeze({
|
|
|
81151
81536
|
access: "create",
|
|
81152
81537
|
role: "admin"
|
|
81153
81538
|
},
|
|
81539
|
+
"remote.getConfig": {
|
|
81540
|
+
capName: "remote",
|
|
81541
|
+
capScope: "system",
|
|
81542
|
+
addonId: null,
|
|
81543
|
+
access: "view",
|
|
81544
|
+
role: "admin"
|
|
81545
|
+
},
|
|
81546
|
+
"remote.listCommands": {
|
|
81547
|
+
capName: "remote",
|
|
81548
|
+
capScope: "system",
|
|
81549
|
+
addonId: null,
|
|
81550
|
+
access: "view",
|
|
81551
|
+
role: "admin"
|
|
81552
|
+
},
|
|
81553
|
+
"remote.sendCommand": {
|
|
81554
|
+
capName: "remote",
|
|
81555
|
+
capScope: "system",
|
|
81556
|
+
addonId: null,
|
|
81557
|
+
access: "create",
|
|
81558
|
+
role: "admin"
|
|
81559
|
+
},
|
|
81560
|
+
"remote.sendMediaCommand": {
|
|
81561
|
+
capName: "remote",
|
|
81562
|
+
capScope: "system",
|
|
81563
|
+
addonId: null,
|
|
81564
|
+
access: "create",
|
|
81565
|
+
role: "admin"
|
|
81566
|
+
},
|
|
81567
|
+
"remote.setConfig": {
|
|
81568
|
+
capName: "remote",
|
|
81569
|
+
capScope: "system",
|
|
81570
|
+
addonId: null,
|
|
81571
|
+
access: "create",
|
|
81572
|
+
role: "admin"
|
|
81573
|
+
},
|
|
81154
81574
|
"runningState.getStatus": {
|
|
81155
81575
|
capName: "running-state",
|
|
81156
81576
|
capScope: "device",
|
|
@@ -82341,6 +82761,41 @@ Object.freeze({
|
|
|
82341
82761
|
access: "view",
|
|
82342
82762
|
role: "viewer"
|
|
82343
82763
|
},
|
|
82764
|
+
"template.create": {
|
|
82765
|
+
capName: "template",
|
|
82766
|
+
capScope: "system",
|
|
82767
|
+
addonId: null,
|
|
82768
|
+
access: "create",
|
|
82769
|
+
role: "admin"
|
|
82770
|
+
},
|
|
82771
|
+
"template.delete": {
|
|
82772
|
+
capName: "template",
|
|
82773
|
+
capScope: "system",
|
|
82774
|
+
addonId: null,
|
|
82775
|
+
access: "delete",
|
|
82776
|
+
role: "admin"
|
|
82777
|
+
},
|
|
82778
|
+
"template.get": {
|
|
82779
|
+
capName: "template",
|
|
82780
|
+
capScope: "system",
|
|
82781
|
+
addonId: null,
|
|
82782
|
+
access: "view",
|
|
82783
|
+
role: "admin"
|
|
82784
|
+
},
|
|
82785
|
+
"template.list": {
|
|
82786
|
+
capName: "template",
|
|
82787
|
+
capScope: "system",
|
|
82788
|
+
addonId: null,
|
|
82789
|
+
access: "view",
|
|
82790
|
+
role: "admin"
|
|
82791
|
+
},
|
|
82792
|
+
"template.update": {
|
|
82793
|
+
capName: "template",
|
|
82794
|
+
capScope: "system",
|
|
82795
|
+
addonId: null,
|
|
82796
|
+
access: "create",
|
|
82797
|
+
role: "admin"
|
|
82798
|
+
},
|
|
82344
82799
|
"terminalSession.adoptLegacyMonitor": {
|
|
82345
82800
|
capName: "terminal-session",
|
|
82346
82801
|
capScope: "system",
|
|
@@ -87172,6 +87627,7 @@ var SYSTEM_CAP_VOCABULARY = {
|
|
|
87172
87627
|
"recording-archive": system(STORAGE),
|
|
87173
87628
|
"recording-export": system("recording exports — requested from the timeline, not an automation step"),
|
|
87174
87629
|
records: system(INTERNAL),
|
|
87630
|
+
remote: system("the per-device remote setup — authored in the Customize remote editor, sent through the remote UI"),
|
|
87175
87631
|
"server-management": system(CLUSTER),
|
|
87176
87632
|
"settings-store": system(INTERNAL),
|
|
87177
87633
|
"smtp-provider": system(INTERNAL),
|
|
@@ -87184,6 +87640,7 @@ var SYSTEM_CAP_VOCABULARY = {
|
|
|
87184
87640
|
"storage-provider": system(STORAGE),
|
|
87185
87641
|
"stream-broker": system(PIPELINE),
|
|
87186
87642
|
system: system(CLUSTER),
|
|
87643
|
+
template: system("operator-authored templates — edited in their own editor, never actuated"),
|
|
87187
87644
|
"terminal-session": system(CLUSTER),
|
|
87188
87645
|
toast: system(UI_PLUMBING),
|
|
87189
87646
|
training: system(ML),
|
|
@@ -89621,6 +90078,31 @@ Object.freeze({
|
|
|
89621
90078
|
form: "single",
|
|
89622
90079
|
optional: true
|
|
89623
90080
|
}],
|
|
90081
|
+
"remote.getConfig": [{
|
|
90082
|
+
name: "deviceId",
|
|
90083
|
+
form: "single",
|
|
90084
|
+
optional: false
|
|
90085
|
+
}],
|
|
90086
|
+
"remote.listCommands": [{
|
|
90087
|
+
name: "deviceId",
|
|
90088
|
+
form: "single",
|
|
90089
|
+
optional: false
|
|
90090
|
+
}],
|
|
90091
|
+
"remote.sendCommand": [{
|
|
90092
|
+
name: "deviceId",
|
|
90093
|
+
form: "single",
|
|
90094
|
+
optional: false
|
|
90095
|
+
}],
|
|
90096
|
+
"remote.sendMediaCommand": [{
|
|
90097
|
+
name: "deviceId",
|
|
90098
|
+
form: "single",
|
|
90099
|
+
optional: false
|
|
90100
|
+
}],
|
|
90101
|
+
"remote.setConfig": [{
|
|
90102
|
+
name: "deviceId",
|
|
90103
|
+
form: "single",
|
|
90104
|
+
optional: false
|
|
90105
|
+
}],
|
|
89624
90106
|
"runningState.getStatus": [{
|
|
89625
90107
|
name: "deviceId",
|
|
89626
90108
|
form: "single",
|
|
@@ -91778,14 +92260,6 @@ function bestLocationMatch(externalName, existing, threshold = .8) {
|
|
|
91778
92260
|
String.raw`(?<=^|["'(\s>,\[{])`;
|
|
91779
92261
|
var MB = 1024 * 1024;
|
|
91780
92262
|
1024 * MB, 3072 * MB;
|
|
91781
|
-
discriminatedUnion("kind", [object({
|
|
91782
|
-
kind: literal("raw"),
|
|
91783
|
-
timings: array(number().int()),
|
|
91784
|
-
settings: TransmitSettingsSchema.optional()
|
|
91785
|
-
}), object({
|
|
91786
|
-
kind: literal("pronto"),
|
|
91787
|
-
code: string()
|
|
91788
|
-
})]);
|
|
91789
92263
|
object({
|
|
91790
92264
|
manufacturer: string().optional(),
|
|
91791
92265
|
supportedModels: array(string()).optional(),
|
|
@@ -5579,7 +5579,7 @@ var ZodIssueCode = {
|
|
|
5579
5579
|
var ZodFirstPartyTypeKind;
|
|
5580
5580
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5581
5581
|
//#endregion
|
|
5582
|
-
//#region ../types/dist/sleep-
|
|
5582
|
+
//#region ../types/dist/sleep-DJws6ho7.mjs
|
|
5583
5583
|
/**
|
|
5584
5584
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5585
5585
|
* window to float samples (D455).
|
|
@@ -9093,6 +9093,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
9093
9093
|
"recording-onboard",
|
|
9094
9094
|
"recording-signal",
|
|
9095
9095
|
"records",
|
|
9096
|
+
"remote",
|
|
9096
9097
|
"running-state",
|
|
9097
9098
|
"scene-monitor",
|
|
9098
9099
|
"script-runner",
|
|
@@ -9116,6 +9117,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
9116
9117
|
"system",
|
|
9117
9118
|
"tamper",
|
|
9118
9119
|
"temperature-sensor",
|
|
9120
|
+
"template",
|
|
9119
9121
|
"terminal-session",
|
|
9120
9122
|
"toast",
|
|
9121
9123
|
"training",
|
|
@@ -10056,6 +10058,11 @@ Object.freeze({
|
|
|
10056
10058
|
"standby"
|
|
10057
10059
|
]
|
|
10058
10060
|
},
|
|
10061
|
+
{
|
|
10062
|
+
"path": "stateSource",
|
|
10063
|
+
"valueType": "enum",
|
|
10064
|
+
"enumValues": ["reported", "assumed"]
|
|
10065
|
+
},
|
|
10059
10066
|
{
|
|
10060
10067
|
"path": "volumeLevel",
|
|
10061
10068
|
"valueType": "number"
|
|
@@ -10331,6 +10338,18 @@ Object.freeze({
|
|
|
10331
10338
|
{
|
|
10332
10339
|
"path": "volume",
|
|
10333
10340
|
"valueType": "number"
|
|
10341
|
+
},
|
|
10342
|
+
{
|
|
10343
|
+
"path": "lastFeedGrams",
|
|
10344
|
+
"valueType": "number"
|
|
10345
|
+
},
|
|
10346
|
+
{
|
|
10347
|
+
"path": "lastFeedHopper1",
|
|
10348
|
+
"valueType": "number"
|
|
10349
|
+
},
|
|
10350
|
+
{
|
|
10351
|
+
"path": "lastFeedHopper2",
|
|
10352
|
+
"valueType": "number"
|
|
10334
10353
|
}
|
|
10335
10354
|
],
|
|
10336
10355
|
"power-meter": [
|
|
@@ -16805,9 +16824,21 @@ var AlertSeveritySchema = _enum([
|
|
|
16805
16824
|
"error",
|
|
16806
16825
|
"critical"
|
|
16807
16826
|
]);
|
|
16827
|
+
/**
|
|
16828
|
+
* An action that RUNS something instead of going somewhere: the admin UI calls
|
|
16829
|
+
* the addon's custom action (`addons.custom`) with exactly these fields. The
|
|
16830
|
+
* producer owns the meaning; the UI knows nothing about the addon or the kind.
|
|
16831
|
+
*/
|
|
16832
|
+
var AlertActionInvokeSchema = object({
|
|
16833
|
+
addonId: string().min(1),
|
|
16834
|
+
action: string().min(1),
|
|
16835
|
+
input: record(string(), unknown()).optional()
|
|
16836
|
+
});
|
|
16837
|
+
/** An action has `href` (a link) OR `invoke` (a button that runs a custom action). */
|
|
16808
16838
|
var AlertActionSchema = object({
|
|
16809
16839
|
label: string(),
|
|
16810
16840
|
href: string().optional(),
|
|
16841
|
+
invoke: AlertActionInvokeSchema.optional(),
|
|
16811
16842
|
/**
|
|
16812
16843
|
* How `href` is followed. Absent / `app`: an admin-ui route (client-side).
|
|
16813
16844
|
* `server`: a route the HUB serves (an addon HTTP route such as an OAuth
|
|
@@ -59212,6 +59243,318 @@ onBrightnessChanged: { data: object({
|
|
|
59212
59243
|
} } }
|
|
59213
59244
|
};
|
|
59214
59245
|
/**
|
|
59246
|
+
* The role vocabulary of a remote (D963): what a button MEANS, independent of
|
|
59247
|
+
* how it is wired. A layout template places buttons by role; a device binds a
|
|
59248
|
+
* role to an action; an exporter asks for a role by name. Roles are shared so
|
|
59249
|
+
* one layout fits every appliance and one voice command fits every binding.
|
|
59250
|
+
*
|
|
59251
|
+
* A role outside this list is `custom:<key>` — the operator's own button (a
|
|
59252
|
+
* SmartIR source, a channel preset). The key is a lowercase slug.
|
|
59253
|
+
*/
|
|
59254
|
+
var REMOTE_KNOWN_ROLES = [
|
|
59255
|
+
"power",
|
|
59256
|
+
"power_on",
|
|
59257
|
+
"power_off",
|
|
59258
|
+
"volume_up",
|
|
59259
|
+
"volume_down",
|
|
59260
|
+
"mute",
|
|
59261
|
+
"channel_up",
|
|
59262
|
+
"channel_down",
|
|
59263
|
+
"up",
|
|
59264
|
+
"down",
|
|
59265
|
+
"left",
|
|
59266
|
+
"right",
|
|
59267
|
+
"ok",
|
|
59268
|
+
"back",
|
|
59269
|
+
"home",
|
|
59270
|
+
"menu",
|
|
59271
|
+
"info",
|
|
59272
|
+
"guide",
|
|
59273
|
+
"exit",
|
|
59274
|
+
"input",
|
|
59275
|
+
"play",
|
|
59276
|
+
"pause",
|
|
59277
|
+
"play_pause",
|
|
59278
|
+
"stop",
|
|
59279
|
+
"next",
|
|
59280
|
+
"previous",
|
|
59281
|
+
"fast_forward",
|
|
59282
|
+
"rewind",
|
|
59283
|
+
"digit_0",
|
|
59284
|
+
"digit_1",
|
|
59285
|
+
"digit_2",
|
|
59286
|
+
"digit_3",
|
|
59287
|
+
"digit_4",
|
|
59288
|
+
"digit_5",
|
|
59289
|
+
"digit_6",
|
|
59290
|
+
"digit_7",
|
|
59291
|
+
"digit_8",
|
|
59292
|
+
"digit_9"
|
|
59293
|
+
];
|
|
59294
|
+
var CUSTOM_KEY_RE = /^[a-z0-9][a-z0-9_]{0,47}$/;
|
|
59295
|
+
var KNOWN_ROLES = new Set(REMOTE_KNOWN_ROLES);
|
|
59296
|
+
function isRemoteKnownRole(value) {
|
|
59297
|
+
return KNOWN_ROLES.has(value);
|
|
59298
|
+
}
|
|
59299
|
+
function isRemoteCustomKey(key) {
|
|
59300
|
+
return CUSTOM_KEY_RE.test(key);
|
|
59301
|
+
}
|
|
59302
|
+
/** The key of a `custom:<key>` role, or null for any other string. */
|
|
59303
|
+
function customKeyOfRole(role) {
|
|
59304
|
+
if (!role.startsWith("custom:")) return null;
|
|
59305
|
+
const key = role.slice(7);
|
|
59306
|
+
return isRemoteCustomKey(key) ? key : null;
|
|
59307
|
+
}
|
|
59308
|
+
function isRemoteRole(value) {
|
|
59309
|
+
return isRemoteKnownRole(value) || customKeyOfRole(value) !== null;
|
|
59310
|
+
}
|
|
59311
|
+
var RemoteRoleSchema = string().refine(isRemoteRole, { message: "a role is one of the known roles or custom:<key> (lowercase letters, digits, _)" });
|
|
59312
|
+
var RemoteBindingSchema = object({ action: AutomationCapStepSchema.extend({ deviceId: number().int().nonnegative() }) });
|
|
59313
|
+
var RemoteCustomButtonSchema = object({
|
|
59314
|
+
/** The slug after `custom:` in the role. */
|
|
59315
|
+
key: string().refine(isRemoteCustomKey, { message: "a lowercase slug" }),
|
|
59316
|
+
/** What the operator calls it, and what a voice command may name. */
|
|
59317
|
+
name: string().min(1).max(60)
|
|
59318
|
+
});
|
|
59319
|
+
var RemotePowerModeSchema = _enum(["toggle", "discrete"]);
|
|
59320
|
+
var RemoteConfigSchema = object({
|
|
59321
|
+
layoutTemplateId: string().min(1).nullable(),
|
|
59322
|
+
/**
|
|
59323
|
+
* The transmitter device new bindings and an import send through. A binding
|
|
59324
|
+
* names its own device, so one command may override it.
|
|
59325
|
+
*/
|
|
59326
|
+
defaultTransmitterId: number().int().nonnegative().nullable().default(null),
|
|
59327
|
+
/** Keyed by role. A role with no entry falls back to the native cap. */
|
|
59328
|
+
bindings: record(string(), RemoteBindingSchema),
|
|
59329
|
+
customButtons: array(RemoteCustomButtonSchema).max(100),
|
|
59330
|
+
power: object({ mode: RemotePowerModeSchema })
|
|
59331
|
+
}).superRefine((config, ctx) => {
|
|
59332
|
+
const roles = Object.keys(config.bindings);
|
|
59333
|
+
if (roles.length > 200) ctx.addIssue({
|
|
59334
|
+
code: "custom",
|
|
59335
|
+
message: "too many bindings",
|
|
59336
|
+
path: ["bindings"]
|
|
59337
|
+
});
|
|
59338
|
+
for (const role of roles) if (!isRemoteRole(role)) ctx.addIssue({
|
|
59339
|
+
code: "custom",
|
|
59340
|
+
message: `"${role}" is not a role`,
|
|
59341
|
+
path: ["bindings", role]
|
|
59342
|
+
});
|
|
59343
|
+
const keys = /* @__PURE__ */ new Set();
|
|
59344
|
+
config.customButtons.forEach((button, index) => {
|
|
59345
|
+
if (keys.has(button.key)) ctx.addIssue({
|
|
59346
|
+
code: "custom",
|
|
59347
|
+
message: `custom button "${button.key}" is listed twice`,
|
|
59348
|
+
path: [
|
|
59349
|
+
"customButtons",
|
|
59350
|
+
index,
|
|
59351
|
+
"key"
|
|
59352
|
+
]
|
|
59353
|
+
});
|
|
59354
|
+
keys.add(button.key);
|
|
59355
|
+
});
|
|
59356
|
+
for (const role of roles) {
|
|
59357
|
+
const key = customKeyOfRole(role);
|
|
59358
|
+
if (key !== null && !keys.has(key)) ctx.addIssue({
|
|
59359
|
+
code: "custom",
|
|
59360
|
+
message: `${role} is bound but has no entry in customButtons`,
|
|
59361
|
+
path: ["bindings", role]
|
|
59362
|
+
});
|
|
59363
|
+
}
|
|
59364
|
+
});
|
|
59365
|
+
object({
|
|
59366
|
+
power: object({
|
|
59367
|
+
state: _enum(["on", "off"]),
|
|
59368
|
+
at: number()
|
|
59369
|
+
}).nullable(),
|
|
59370
|
+
muted: object({
|
|
59371
|
+
value: boolean(),
|
|
59372
|
+
at: number()
|
|
59373
|
+
}).nullable()
|
|
59374
|
+
});
|
|
59375
|
+
var RemoteLayoutButtonSchema = object({
|
|
59376
|
+
id: string().min(1).max(40),
|
|
59377
|
+
/** 0-based grid position. */
|
|
59378
|
+
row: number().int().min(0).max(24),
|
|
59379
|
+
col: number().int().min(0).max(24),
|
|
59380
|
+
rowSpan: number().int().min(1).max(24),
|
|
59381
|
+
colSpan: number().int().min(1).max(24),
|
|
59382
|
+
icon: string().min(1).max(60).optional(),
|
|
59383
|
+
label: string().min(1).max(40).optional(),
|
|
59384
|
+
role: RemoteRoleSchema
|
|
59385
|
+
});
|
|
59386
|
+
object({
|
|
59387
|
+
columns: number().int().min(1).max(24),
|
|
59388
|
+
rows: number().int().min(1).max(24),
|
|
59389
|
+
buttons: array(RemoteLayoutButtonSchema).max(200)
|
|
59390
|
+
}).superRefine((grid, ctx) => {
|
|
59391
|
+
const ids = /* @__PURE__ */ new Set();
|
|
59392
|
+
const taken = /* @__PURE__ */ new Map();
|
|
59393
|
+
grid.buttons.forEach((button, index) => {
|
|
59394
|
+
if (ids.has(button.id)) ctx.addIssue({
|
|
59395
|
+
code: "custom",
|
|
59396
|
+
message: `button id "${button.id}" is used twice`,
|
|
59397
|
+
path: [
|
|
59398
|
+
"buttons",
|
|
59399
|
+
index,
|
|
59400
|
+
"id"
|
|
59401
|
+
]
|
|
59402
|
+
});
|
|
59403
|
+
ids.add(button.id);
|
|
59404
|
+
if (button.row + button.rowSpan > grid.rows || button.col + button.colSpan > grid.columns) {
|
|
59405
|
+
ctx.addIssue({
|
|
59406
|
+
code: "custom",
|
|
59407
|
+
message: `button "${button.id}" leaves the grid`,
|
|
59408
|
+
path: ["buttons", index]
|
|
59409
|
+
});
|
|
59410
|
+
return;
|
|
59411
|
+
}
|
|
59412
|
+
for (let r = button.row; r < button.row + button.rowSpan; r += 1) for (let c = button.col; c < button.col + button.colSpan; c += 1) {
|
|
59413
|
+
const cell = `${r}:${c}`;
|
|
59414
|
+
const other = taken.get(cell);
|
|
59415
|
+
if (other !== void 0) {
|
|
59416
|
+
ctx.addIssue({
|
|
59417
|
+
code: "custom",
|
|
59418
|
+
message: `buttons "${other}" and "${button.id}" overlap`,
|
|
59419
|
+
path: ["buttons", index]
|
|
59420
|
+
});
|
|
59421
|
+
return;
|
|
59422
|
+
}
|
|
59423
|
+
taken.set(cell, button.id);
|
|
59424
|
+
}
|
|
59425
|
+
});
|
|
59426
|
+
});
|
|
59427
|
+
var RemoteBoundCommandSchema = object({
|
|
59428
|
+
role: RemoteRoleSchema,
|
|
59429
|
+
/** The operator's name for a custom button; absent for a known role. */
|
|
59430
|
+
label: string().optional(),
|
|
59431
|
+
custom: boolean()
|
|
59432
|
+
});
|
|
59433
|
+
var RemoteCommandListSchema = object({
|
|
59434
|
+
layoutTemplateId: string().nullable(),
|
|
59435
|
+
power: object({ mode: RemotePowerModeSchema }),
|
|
59436
|
+
/** Only the roles that are BOUND — the ones a press can reach. */
|
|
59437
|
+
commands: array(RemoteBoundCommandSchema)
|
|
59438
|
+
});
|
|
59439
|
+
var RemoteRefusalReasonSchema = _enum([
|
|
59440
|
+
"no-remote",
|
|
59441
|
+
"unbound-role",
|
|
59442
|
+
"action-failed"
|
|
59443
|
+
]);
|
|
59444
|
+
var RemoteSendResultSchema = discriminatedUnion("status", [
|
|
59445
|
+
object({
|
|
59446
|
+
status: literal("sent"),
|
|
59447
|
+
/** How many times the action ran. */
|
|
59448
|
+
sends: number().int().min(1)
|
|
59449
|
+
}),
|
|
59450
|
+
object({
|
|
59451
|
+
status: literal("skipped"),
|
|
59452
|
+
reason: literal("already-in-state")
|
|
59453
|
+
}),
|
|
59454
|
+
object({
|
|
59455
|
+
status: literal("refused"),
|
|
59456
|
+
reason: RemoteRefusalReasonSchema,
|
|
59457
|
+
detail: string().optional()
|
|
59458
|
+
})
|
|
59459
|
+
]);
|
|
59460
|
+
var RemoteMediaCommandSchema = _enum([
|
|
59461
|
+
"play",
|
|
59462
|
+
"pause",
|
|
59463
|
+
"stop",
|
|
59464
|
+
"next",
|
|
59465
|
+
"previous",
|
|
59466
|
+
"setMute",
|
|
59467
|
+
"selectSource"
|
|
59468
|
+
]);
|
|
59469
|
+
/** A send result, or `not-routed`: the role is not bound, so the native cap answers. */
|
|
59470
|
+
var RemoteMediaCommandResultSchema = discriminatedUnion("status", [...RemoteSendResultSchema.options, object({ status: literal("not-routed") })]);
|
|
59471
|
+
var RemoteSetConfigResultSchema = discriminatedUnion("status", [object({ status: literal("saved") }), object({
|
|
59472
|
+
status: literal("refused"),
|
|
59473
|
+
reason: _enum(["unknown-template", "not-a-media-player"]),
|
|
59474
|
+
detail: string()
|
|
59475
|
+
})]);
|
|
59476
|
+
var deviceInput = object({ deviceId: number().int().nonnegative() });
|
|
59477
|
+
DeviceType.MediaPlayer;
|
|
59478
|
+
method(deviceInput, RemoteConfigSchema, { auth: "admin" }), method(deviceInput.extend({ config: RemoteConfigSchema }), RemoteSetConfigResultSchema, {
|
|
59479
|
+
kind: "mutation",
|
|
59480
|
+
auth: "admin"
|
|
59481
|
+
}), method(deviceInput, RemoteCommandListSchema, { auth: "protected" }), method(deviceInput.extend({
|
|
59482
|
+
role: RemoteRoleSchema,
|
|
59483
|
+
/** Sends in a row (volume steps). */
|
|
59484
|
+
repeat: number().int().min(1).max(50).default(1)
|
|
59485
|
+
}), RemoteSendResultSchema, {
|
|
59486
|
+
kind: "mutation",
|
|
59487
|
+
auth: "protected"
|
|
59488
|
+
}), method(deviceInput.extend({
|
|
59489
|
+
command: RemoteMediaCommandSchema,
|
|
59490
|
+
muted: boolean().optional(),
|
|
59491
|
+
source: string().optional(),
|
|
59492
|
+
repeat: number().int().min(1).max(50).default(1)
|
|
59493
|
+
}), RemoteMediaCommandResultSchema, {
|
|
59494
|
+
kind: "mutation",
|
|
59495
|
+
auth: "protected"
|
|
59496
|
+
});
|
|
59497
|
+
var TemplateKindSchema = _enum(["remote"]);
|
|
59498
|
+
/**
|
|
59499
|
+
* template — the generic store of reusable, named operator data (D963). A
|
|
59500
|
+
* record is `{ id, kind, name, payload }`; the kinds (today only `remote`, the
|
|
59501
|
+
* button grid of a remote) and the schema each payload must satisfy are
|
|
59502
|
+
* declared by the system in `template-kinds.ts`. Nothing here is specific to a
|
|
59503
|
+
* kind: the engine validates a payload against its kind's schema and, on a
|
|
59504
|
+
* delete, asks the kind's owner whether anything still points at the record.
|
|
59505
|
+
*
|
|
59506
|
+
* Every refusal is a typed result — a UI says "unknown kind" or names the
|
|
59507
|
+
* devices that still use a template, without parsing text.
|
|
59508
|
+
*/
|
|
59509
|
+
var TemplateRecordSchema = object({
|
|
59510
|
+
id: string().min(1),
|
|
59511
|
+
kind: TemplateKindSchema,
|
|
59512
|
+
name: string().min(1).max(120),
|
|
59513
|
+
/** Shaped by the kind; `checkTemplatePayload(kind, payload)` reads it. */
|
|
59514
|
+
payload: unknown(),
|
|
59515
|
+
createdAt: number(),
|
|
59516
|
+
updatedAt: number()
|
|
59517
|
+
});
|
|
59518
|
+
var TemplateWriteResultSchema = discriminatedUnion("status", [object({
|
|
59519
|
+
status: literal("saved"),
|
|
59520
|
+
template: TemplateRecordSchema
|
|
59521
|
+
}), object({
|
|
59522
|
+
status: literal("refused"),
|
|
59523
|
+
reason: _enum(["invalid-payload", "not-found"]),
|
|
59524
|
+
detail: string()
|
|
59525
|
+
})]);
|
|
59526
|
+
/** A device still pointing at a template. */
|
|
59527
|
+
var TemplateUserSchema = object({
|
|
59528
|
+
deviceId: number().int().nonnegative(),
|
|
59529
|
+
name: string()
|
|
59530
|
+
});
|
|
59531
|
+
var TemplateDeleteResultSchema = discriminatedUnion("status", [
|
|
59532
|
+
object({ status: literal("deleted") }),
|
|
59533
|
+
object({ status: literal("not-found") }),
|
|
59534
|
+
object({
|
|
59535
|
+
status: literal("in-use"),
|
|
59536
|
+
devices: array(TemplateUserSchema).min(1)
|
|
59537
|
+
})
|
|
59538
|
+
]);
|
|
59539
|
+
method(object({ kind: TemplateKindSchema.optional() }), array(TemplateRecordSchema), { auth: "protected" }), method(object({ id: string().min(1) }), TemplateRecordSchema.nullable(), { auth: "protected" }), method(object({
|
|
59540
|
+
kind: TemplateKindSchema,
|
|
59541
|
+
name: string().min(1).max(120),
|
|
59542
|
+
payload: unknown()
|
|
59543
|
+
}), TemplateWriteResultSchema, {
|
|
59544
|
+
kind: "mutation",
|
|
59545
|
+
auth: "admin"
|
|
59546
|
+
}), method(object({
|
|
59547
|
+
id: string().min(1),
|
|
59548
|
+
name: string().min(1).max(120).optional(),
|
|
59549
|
+
payload: unknown().optional()
|
|
59550
|
+
}), TemplateWriteResultSchema, {
|
|
59551
|
+
kind: "mutation",
|
|
59552
|
+
auth: "admin"
|
|
59553
|
+
}), method(object({ id: string().min(1) }), TemplateDeleteResultSchema, {
|
|
59554
|
+
kind: "mutation",
|
|
59555
|
+
auth: "admin"
|
|
59556
|
+
});
|
|
59557
|
+
/**
|
|
59215
59558
|
* button — device-scoped capability for HA `button.*` / `input_button.*`
|
|
59216
59559
|
* fire-only actuators. A button entity has no readable state — pressing it
|
|
59217
59560
|
* triggers an action on the HA side. There is no `status` / `runtimeState`:
|
|
@@ -63413,9 +63756,35 @@ var MediaInfoSchema = object({
|
|
|
63413
63756
|
/** Optional cover-art / thumbnail URL. */
|
|
63414
63757
|
imageUrl: string().optional()
|
|
63415
63758
|
});
|
|
63759
|
+
/**
|
|
63760
|
+
* Where `state`, `volumeLevel`, `isMuted` and `source` come from. `reported`:
|
|
63761
|
+
* the device said so. `assumed`: the driver has no feedback (infrared) and
|
|
63762
|
+
* tracks what it last SENT; it moves only after a send was accepted, and a
|
|
63763
|
+
* human at the real remote makes it wrong. A UI shows an assumed value as a
|
|
63764
|
+
* guess, never as a reading.
|
|
63765
|
+
*/
|
|
63766
|
+
var MediaPlayerStateSourceSchema = _enum(["reported", "assumed"]);
|
|
63767
|
+
/** The fields of a media-player status a driver can only guess. */
|
|
63768
|
+
var MediaPlayerAssumedFieldSchema = _enum([
|
|
63769
|
+
"state",
|
|
63770
|
+
"volumeLevel",
|
|
63771
|
+
"isMuted",
|
|
63772
|
+
"source"
|
|
63773
|
+
]);
|
|
63416
63774
|
var MediaPlayerStatusSchema = object({
|
|
63417
63775
|
/** Playback lifecycle state. */
|
|
63418
63776
|
state: MediaPlayerStateSchema,
|
|
63777
|
+
/**
|
|
63778
|
+
* Whether the state fields are readings or the driver's own bookkeeping.
|
|
63779
|
+
* A slice written before this field existed parses as `reported`.
|
|
63780
|
+
*/
|
|
63781
|
+
stateSource: MediaPlayerStateSourceSchema.default("reported"),
|
|
63782
|
+
/**
|
|
63783
|
+
* Which fields are the driver's own guess. `stateSource` is `assumed` when
|
|
63784
|
+
* this is not empty; a field not listed here is a reading even then (power
|
|
63785
|
+
* from a running-state source, mute guessed from the last send).
|
|
63786
|
+
*/
|
|
63787
|
+
assumedFields: array(MediaPlayerAssumedFieldSchema).default([]),
|
|
63419
63788
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
63420
63789
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
63421
63790
|
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
@@ -65378,6 +65747,14 @@ var PetFeederStatusSchema = object({
|
|
|
65378
65747
|
feedSound: boolean(),
|
|
65379
65748
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
65380
65749
|
volume: number().meta(readingMeta("none")),
|
|
65750
|
+
/** Portion (grams) of the last manual feed sent from a single-hopper
|
|
65751
|
+
* stepper — the default the next manual feed starts from. Persisted per
|
|
65752
|
+
* device by the provider; null until a manual feed has been sent. */
|
|
65753
|
+
lastFeedGrams: gramsPortion.nullable(),
|
|
65754
|
+
/** Hopper-1 portion of the last manual feed (dual-hopper); null until sent. */
|
|
65755
|
+
lastFeedHopper1: gramsPortion.nullable(),
|
|
65756
|
+
/** Hopper-2 portion of the last manual feed (dual-hopper); null until sent. */
|
|
65757
|
+
lastFeedHopper2: gramsPortion.nullable(),
|
|
65381
65758
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
65382
65759
|
lastFetchedAt: number()
|
|
65383
65760
|
});
|
|
@@ -71423,6 +71800,14 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
|
|
|
71423
71800
|
kind: "mutation",
|
|
71424
71801
|
auth: "admin"
|
|
71425
71802
|
});
|
|
71803
|
+
discriminatedUnion("kind", [object({
|
|
71804
|
+
kind: literal("raw"),
|
|
71805
|
+
timings: array(number().int()),
|
|
71806
|
+
settings: TransmitSettingsSchema.optional()
|
|
71807
|
+
}), object({
|
|
71808
|
+
kind: literal("pronto"),
|
|
71809
|
+
code: string()
|
|
71810
|
+
})]);
|
|
71426
71811
|
function resolveSince(running, previous, transitionAtMs, bootstrapSinceMs) {
|
|
71427
71812
|
if (running === null) return null;
|
|
71428
71813
|
const prevRunning = previous?.running ?? null;
|
|
@@ -71860,7 +72245,7 @@ function tryConvertDelta(value, from, to) {
|
|
|
71860
72245
|
return shifted - origin;
|
|
71861
72246
|
}
|
|
71862
72247
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
71863
|
-
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Camera, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
72248
|
+
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Camera, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
71864
72249
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
71865
72250
|
DeviceRole.BinarySensor, DeviceRole.MotionSensor;
|
|
71866
72251
|
new Set(CAP_NAMES);
|
|
@@ -81150,6 +81535,41 @@ Object.freeze({
|
|
|
81150
81535
|
access: "create",
|
|
81151
81536
|
role: "admin"
|
|
81152
81537
|
},
|
|
81538
|
+
"remote.getConfig": {
|
|
81539
|
+
capName: "remote",
|
|
81540
|
+
capScope: "system",
|
|
81541
|
+
addonId: null,
|
|
81542
|
+
access: "view",
|
|
81543
|
+
role: "admin"
|
|
81544
|
+
},
|
|
81545
|
+
"remote.listCommands": {
|
|
81546
|
+
capName: "remote",
|
|
81547
|
+
capScope: "system",
|
|
81548
|
+
addonId: null,
|
|
81549
|
+
access: "view",
|
|
81550
|
+
role: "admin"
|
|
81551
|
+
},
|
|
81552
|
+
"remote.sendCommand": {
|
|
81553
|
+
capName: "remote",
|
|
81554
|
+
capScope: "system",
|
|
81555
|
+
addonId: null,
|
|
81556
|
+
access: "create",
|
|
81557
|
+
role: "admin"
|
|
81558
|
+
},
|
|
81559
|
+
"remote.sendMediaCommand": {
|
|
81560
|
+
capName: "remote",
|
|
81561
|
+
capScope: "system",
|
|
81562
|
+
addonId: null,
|
|
81563
|
+
access: "create",
|
|
81564
|
+
role: "admin"
|
|
81565
|
+
},
|
|
81566
|
+
"remote.setConfig": {
|
|
81567
|
+
capName: "remote",
|
|
81568
|
+
capScope: "system",
|
|
81569
|
+
addonId: null,
|
|
81570
|
+
access: "create",
|
|
81571
|
+
role: "admin"
|
|
81572
|
+
},
|
|
81153
81573
|
"runningState.getStatus": {
|
|
81154
81574
|
capName: "running-state",
|
|
81155
81575
|
capScope: "device",
|
|
@@ -82340,6 +82760,41 @@ Object.freeze({
|
|
|
82340
82760
|
access: "view",
|
|
82341
82761
|
role: "viewer"
|
|
82342
82762
|
},
|
|
82763
|
+
"template.create": {
|
|
82764
|
+
capName: "template",
|
|
82765
|
+
capScope: "system",
|
|
82766
|
+
addonId: null,
|
|
82767
|
+
access: "create",
|
|
82768
|
+
role: "admin"
|
|
82769
|
+
},
|
|
82770
|
+
"template.delete": {
|
|
82771
|
+
capName: "template",
|
|
82772
|
+
capScope: "system",
|
|
82773
|
+
addonId: null,
|
|
82774
|
+
access: "delete",
|
|
82775
|
+
role: "admin"
|
|
82776
|
+
},
|
|
82777
|
+
"template.get": {
|
|
82778
|
+
capName: "template",
|
|
82779
|
+
capScope: "system",
|
|
82780
|
+
addonId: null,
|
|
82781
|
+
access: "view",
|
|
82782
|
+
role: "admin"
|
|
82783
|
+
},
|
|
82784
|
+
"template.list": {
|
|
82785
|
+
capName: "template",
|
|
82786
|
+
capScope: "system",
|
|
82787
|
+
addonId: null,
|
|
82788
|
+
access: "view",
|
|
82789
|
+
role: "admin"
|
|
82790
|
+
},
|
|
82791
|
+
"template.update": {
|
|
82792
|
+
capName: "template",
|
|
82793
|
+
capScope: "system",
|
|
82794
|
+
addonId: null,
|
|
82795
|
+
access: "create",
|
|
82796
|
+
role: "admin"
|
|
82797
|
+
},
|
|
82343
82798
|
"terminalSession.adoptLegacyMonitor": {
|
|
82344
82799
|
capName: "terminal-session",
|
|
82345
82800
|
capScope: "system",
|
|
@@ -87171,6 +87626,7 @@ var SYSTEM_CAP_VOCABULARY = {
|
|
|
87171
87626
|
"recording-archive": system(STORAGE),
|
|
87172
87627
|
"recording-export": system("recording exports — requested from the timeline, not an automation step"),
|
|
87173
87628
|
records: system(INTERNAL),
|
|
87629
|
+
remote: system("the per-device remote setup — authored in the Customize remote editor, sent through the remote UI"),
|
|
87174
87630
|
"server-management": system(CLUSTER),
|
|
87175
87631
|
"settings-store": system(INTERNAL),
|
|
87176
87632
|
"smtp-provider": system(INTERNAL),
|
|
@@ -87183,6 +87639,7 @@ var SYSTEM_CAP_VOCABULARY = {
|
|
|
87183
87639
|
"storage-provider": system(STORAGE),
|
|
87184
87640
|
"stream-broker": system(PIPELINE),
|
|
87185
87641
|
system: system(CLUSTER),
|
|
87642
|
+
template: system("operator-authored templates — edited in their own editor, never actuated"),
|
|
87186
87643
|
"terminal-session": system(CLUSTER),
|
|
87187
87644
|
toast: system(UI_PLUMBING),
|
|
87188
87645
|
training: system(ML),
|
|
@@ -89620,6 +90077,31 @@ Object.freeze({
|
|
|
89620
90077
|
form: "single",
|
|
89621
90078
|
optional: true
|
|
89622
90079
|
}],
|
|
90080
|
+
"remote.getConfig": [{
|
|
90081
|
+
name: "deviceId",
|
|
90082
|
+
form: "single",
|
|
90083
|
+
optional: false
|
|
90084
|
+
}],
|
|
90085
|
+
"remote.listCommands": [{
|
|
90086
|
+
name: "deviceId",
|
|
90087
|
+
form: "single",
|
|
90088
|
+
optional: false
|
|
90089
|
+
}],
|
|
90090
|
+
"remote.sendCommand": [{
|
|
90091
|
+
name: "deviceId",
|
|
90092
|
+
form: "single",
|
|
90093
|
+
optional: false
|
|
90094
|
+
}],
|
|
90095
|
+
"remote.sendMediaCommand": [{
|
|
90096
|
+
name: "deviceId",
|
|
90097
|
+
form: "single",
|
|
90098
|
+
optional: false
|
|
90099
|
+
}],
|
|
90100
|
+
"remote.setConfig": [{
|
|
90101
|
+
name: "deviceId",
|
|
90102
|
+
form: "single",
|
|
90103
|
+
optional: false
|
|
90104
|
+
}],
|
|
89623
90105
|
"runningState.getStatus": [{
|
|
89624
90106
|
name: "deviceId",
|
|
89625
90107
|
form: "single",
|
|
@@ -91777,14 +92259,6 @@ function bestLocationMatch(externalName, existing, threshold = .8) {
|
|
|
91777
92259
|
String.raw`(?<=^|["'(\s>,\[{])`;
|
|
91778
92260
|
var MB = 1024 * 1024;
|
|
91779
92261
|
1024 * MB, 3072 * MB;
|
|
91780
|
-
discriminatedUnion("kind", [object({
|
|
91781
|
-
kind: literal("raw"),
|
|
91782
|
-
timings: array(number().int()),
|
|
91783
|
-
settings: TransmitSettingsSchema.optional()
|
|
91784
|
-
}), object({
|
|
91785
|
-
kind: literal("pronto"),
|
|
91786
|
-
code: string()
|
|
91787
|
-
})]);
|
|
91788
92262
|
object({
|
|
91789
92263
|
manufacturer: string().optional(),
|
|
91790
92264
|
supportedModels: array(string()).optional(),
|
|
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
enumerable: true
|
|
25
25
|
}) : target, mod));
|
|
26
26
|
//#endregion
|
|
27
|
-
const require_dist = require("../dist-
|
|
27
|
+
const require_dist = require("../dist-BS9DCd76.js");
|
|
28
28
|
let node_crypto = require("node:crypto");
|
|
29
29
|
require("node:zlib");
|
|
30
30
|
let node_fs = require("node:fs");
|
|
@@ -3492,6 +3492,10 @@ var CAPS_NOT_EXPORTED = [
|
|
|
3492
3492
|
cap: "ir-transmitter",
|
|
3493
3493
|
reason: "A pulse-train emitter with no state: it is driven by the remote that owns a command table, and a raw send has no meaningful single entity."
|
|
3494
3494
|
},
|
|
3495
|
+
{
|
|
3496
|
+
cap: "remote",
|
|
3497
|
+
reason: "A named command map sent through a transmitter. Its useful surface for an ecosystem is the `media-player` the same device provides (power, volume, source); the free-form command name has no typed entity. Its state (last command, last send time) is session-only bookkeeping."
|
|
3498
|
+
},
|
|
3495
3499
|
{
|
|
3496
3500
|
cap: "group-status",
|
|
3497
3501
|
reason: "Bookkeeping for a helper group (D944): how many members were included, excluded, or named. The value an operator automates on is the output capability (the temperature, the motion, the watts). These counts are session-only, have no history, and would publish a second entity that never means the reading."
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Ft as BaseAddon, Gt as array, Ht as isReadingQuantity, I as consumableFormOf, L as consumableKindOf, Lt as baseUnitOf, O as buildAddonRouteProvider, Qt as string, U as deviceExportCapability, Ut as nodePin, Xt as object, a as COCO_TO_MACRO, c as ConsumableItemSchema, d as FanDirectionSchema, en as unknown, f as HvacModeSchema, i as CAMERA_SWITCH_ORDER, l as ConsumableStatusSchema, m as PLUG_APPLIANCE_TYPES, nn as EventCategory, o as CameraSwitchIdSchema, p as MediaPlayerRepeatSchema, s as ConsumableFormSchema, st as oauthIntegrationCapability, t as AlarmArmModeSchema, v as addonRoutesCapability } from "../dist-
|
|
1
|
+
import { Ft as BaseAddon, Gt as array, Ht as isReadingQuantity, I as consumableFormOf, L as consumableKindOf, Lt as baseUnitOf, O as buildAddonRouteProvider, Qt as string, U as deviceExportCapability, Ut as nodePin, Xt as object, a as COCO_TO_MACRO, c as ConsumableItemSchema, d as FanDirectionSchema, en as unknown, f as HvacModeSchema, i as CAMERA_SWITCH_ORDER, l as ConsumableStatusSchema, m as PLUG_APPLIANCE_TYPES, nn as EventCategory, o as CameraSwitchIdSchema, p as MediaPlayerRepeatSchema, s as ConsumableFormSchema, st as oauthIntegrationCapability, t as AlarmArmModeSchema, v as addonRoutesCapability } from "../dist-BusXPPvn.mjs";
|
|
2
2
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
3
3
|
import "node:zlib";
|
|
4
4
|
import "node:fs";
|
|
@@ -3457,6 +3457,10 @@ var CAPS_NOT_EXPORTED = [
|
|
|
3457
3457
|
cap: "ir-transmitter",
|
|
3458
3458
|
reason: "A pulse-train emitter with no state: it is driven by the remote that owns a command table, and a raw send has no meaningful single entity."
|
|
3459
3459
|
},
|
|
3460
|
+
{
|
|
3461
|
+
cap: "remote",
|
|
3462
|
+
reason: "A named command map sent through a transmitter. Its useful surface for an ecosystem is the `media-player` the same device provides (power, volume, source); the free-form command name has no typed entity. Its state (last command, last send time) is session-only bookkeeping."
|
|
3463
|
+
},
|
|
3460
3464
|
{
|
|
3461
3465
|
cap: "group-status",
|
|
3462
3466
|
reason: "Bookkeeping for a helper group (D944): how many members were included, excluded, or named. The value an operator automates on is the output capability (the temperature, the motion, the watts). These counts are session-only, have no history, and would publish a second entity that never means the reading."
|