@camstack/addon-import-alexa 0.2.179 → 0.2.180

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.mjs CHANGED
@@ -832,7 +832,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
832
832
  return EventCategory;
833
833
  }({});
834
834
  //#endregion
835
- //#region ../types/dist/device-type-CfHw_quR.mjs
835
+ //#region ../types/dist/device-type-D1fH5kaC.mjs
836
836
  /**
837
837
  import { errMsg } from '@camstack/types'
838
838
  * Extract a human-readable message from an unknown error value.
@@ -1063,6 +1063,12 @@ var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
1063
1063
  DeviceFeature["MediaPlayerPrevious"] = "media-player-previous";
1064
1064
  /** Media player exposes stop distinct from pause. */
1065
1065
  DeviceFeature["MediaPlayerStop"] = "media-player-stop";
1066
+ /** Media player exposes volume up / down in steps (an infrared TV has no level). */
1067
+ DeviceFeature["MediaPlayerVolumeStep"] = "media-player-volume-step";
1068
+ /** Media player exposes channel up / down in steps. */
1069
+ DeviceFeature["MediaPlayerChannelStep"] = "media-player-channel-step";
1070
+ /** Media player exposes power on / off. */
1071
+ DeviceFeature["MediaPlayerPower"] = "media-player-power";
1066
1072
  /** Alarm panel requires a PIN code on arm/disarm. */
1067
1073
  DeviceFeature["AlarmPinRequired"] = "alarm-pin-required";
1068
1074
  /** Presence device carries GPS coordinates (lat/lng/accuracy) in
@@ -6036,7 +6042,7 @@ function number(params) {
6036
6042
  return /* @__PURE__ */ _coercedNumber(ZodNumber, params);
6037
6043
  }
6038
6044
  //#endregion
6039
- //#region ../types/dist/sleep-hmSP-eJt.mjs
6045
+ //#region ../types/dist/sleep-BKClVk0K.mjs
6040
6046
  /**
6041
6047
  * The audio chunk plane's byte format, and the ONE expansion from a coded
6042
6048
  * window to float samples (D455).
@@ -6115,6 +6121,22 @@ function buildAlawTable() {
6115
6121
  }
6116
6122
  buildUlawTable();
6117
6123
  buildAlawTable();
6124
+ /**
6125
+ * An addon whose own migrations did not apply refuses to initialise (D987). The error is typed
6126
+ * so a runner hosting several addons can tell "this addon is blocked" from a crash and keep its
6127
+ * co-located siblings running. Recognised by NAME and shape, never `instanceof`: a forked addon
6128
+ * bundles its own copy of this module, so the class the runner sees is not the one that threw.
6129
+ */
6130
+ var MIGRATIONS_BLOCKED_ERROR_NAME = "AddonMigrationsBlockedError";
6131
+ var AddonMigrationsBlockedError = class extends Error {
6132
+ /** The ledger ids that did not apply and block the owner. */
6133
+ migrationIds;
6134
+ constructor(migrationIds) {
6135
+ super(`migration(s) ${migrationIds.join(", ")} did not apply and block this addon — fix or retry them (migrations.retry), then restart it`);
6136
+ this.name = MIGRATIONS_BLOCKED_ERROR_NAME;
6137
+ this.migrationIds = migrationIds;
6138
+ }
6139
+ };
6118
6140
  /** Is this field's stored value a credential? */
6119
6141
  function isSecretConfigField(field) {
6120
6142
  if (field.type === "password") return true;
@@ -7768,7 +7790,7 @@ var BaseAddon = class {
7768
7790
  startMigration: (input) => api.startMigration.mutate(input),
7769
7791
  finishMigration: (input) => api.finishMigration.mutate(input)
7770
7792
  }, migrations, this.ctx.logger);
7771
- if (report.blockOwner.length > 0) throw new Error(`migration(s) ${report.blockOwner.join(", ")} did not apply and block this addon — fix or retry them (migrations.retry), then restart it`);
7793
+ if (report.blockOwner.length > 0) throw new AddonMigrationsBlockedError(report.blockOwner);
7772
7794
  return report;
7773
7795
  }
7774
7796
  /**
@@ -11764,7 +11786,7 @@ object({
11764
11786
  params: record(string(), union([string(), number$1()])).optional()
11765
11787
  });
11766
11788
  //#endregion
11767
- //#region ../types/dist/composition-Dh3RfMx5.mjs
11789
+ //#region ../types/dist/composition-BodkvOV0.mjs
11768
11790
  /**
11769
11791
  * The ffmpeg build every CamStack node downloads, per platform and arch.
11770
11792
  *
@@ -12901,7 +12923,14 @@ var CompositionForwardCommandSchema = object({
12901
12923
  method: string().min(1),
12902
12924
  args: record(string().min(1), CompositionForwardArgSchema).optional()
12903
12925
  });
12904
- var CompositionCommandTargetSchema = discriminatedUnion("kind", [CompositionForwardCommandSchema, CompositionCodeSourceSchema]);
12926
+ var CompositionCommandTargetSchema = discriminatedUnion("kind", [
12927
+ CompositionForwardCommandSchema,
12928
+ CompositionCodeSourceSchema,
12929
+ object({
12930
+ kind: literal("extension"),
12931
+ target: literal("remote")
12932
+ })
12933
+ ]);
12905
12934
  /** An item key inside an item-array cap (`consumables.items[<key>]`). */
12906
12935
  var COMPOSITION_ITEM_KEY_RE = /^[a-z0-9][a-z0-9-]{0,47}$/;
12907
12936
  /**
@@ -19525,6 +19554,48 @@ var APPLIANCE_CAP_VOCABULARY = {
19525
19554
  scope: "device",
19526
19555
  noun: t("Media player", "Lettore multimediale"),
19527
19556
  actions: [
19557
+ {
19558
+ id: "media.turnOn",
19559
+ method: "turnOn",
19560
+ label: t("Turn on", "Accendi"),
19561
+ phrase: t("Turn on {device}", "Accendi {device}"),
19562
+ icon: "power"
19563
+ },
19564
+ {
19565
+ id: "media.turnOff",
19566
+ method: "turnOff",
19567
+ label: t("Turn off", "Spegni"),
19568
+ phrase: t("Turn off {device}", "Spegni {device}"),
19569
+ icon: "power"
19570
+ },
19571
+ {
19572
+ id: "media.volumeUp",
19573
+ method: "volumeUp",
19574
+ label: t("Volume up", "Alza il volume"),
19575
+ phrase: t("Raise the volume of {device}", "Alza il volume di {device}"),
19576
+ icon: "volume-2"
19577
+ },
19578
+ {
19579
+ id: "media.volumeDown",
19580
+ method: "volumeDown",
19581
+ label: t("Volume down", "Abbassa il volume"),
19582
+ phrase: t("Lower the volume of {device}", "Abbassa il volume di {device}"),
19583
+ icon: "volume-2"
19584
+ },
19585
+ {
19586
+ id: "media.channelUp",
19587
+ method: "channelUp",
19588
+ label: t("Channel up", "Canale successivo"),
19589
+ phrase: t("Go to the next channel on {device}", "Passa al canale successivo su {device}"),
19590
+ icon: "skip-forward"
19591
+ },
19592
+ {
19593
+ id: "media.channelDown",
19594
+ method: "channelDown",
19595
+ label: t("Channel down", "Canale precedente"),
19596
+ phrase: t("Go to the previous channel on {device}", "Torna al canale precedente su {device}"),
19597
+ icon: "skip-back"
19598
+ },
19528
19599
  {
19529
19600
  id: "media.play",
19530
19601
  method: "play",
@@ -49152,6 +49223,244 @@ var controlCapability = {
49152
49223
  */
49153
49224
  history: "none"
49154
49225
  };
49226
+ /**
49227
+ * Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
49228
+ * Apple TV, Spotify, Roku, generic OTT receivers, …) on
49229
+ * `DeviceType.MediaPlayer`. Disjoint from the camera streaming
49230
+ * surface — those use `DeviceType.Camera` + the broker pipeline.
49231
+ *
49232
+ * The cap declares a wide method surface; not every backend supports
49233
+ * every method. Drivers signal sub-capability via the
49234
+ * `DeviceFeature.MediaPlayerXxx` flags (paired one-to-one with the
49235
+ * corresponding method) so the UI gates buttons without a slice
49236
+ * fetch — same pattern as `PanTiltZoom` for cameras.
49237
+ */
49238
+ var MediaPlayerStateSchema = _enum([
49239
+ "off",
49240
+ "on",
49241
+ "idle",
49242
+ "playing",
49243
+ "paused",
49244
+ "buffering",
49245
+ "standby"
49246
+ ]);
49247
+ var MediaPlayerRepeatSchema = _enum([
49248
+ "off",
49249
+ "all",
49250
+ "one"
49251
+ ]);
49252
+ var MediaInfoSchema = object({
49253
+ /** Free-form media kind (`music`, `tvshow`, `movie`, `app`, `channel`,
49254
+ * `podcast`, …). */
49255
+ type: string(),
49256
+ /** Human-readable title. */
49257
+ title: string(),
49258
+ /** Optional artist / channel / station label. */
49259
+ artist: string().optional(),
49260
+ /** Optional album / season / show name. */
49261
+ album: string().optional(),
49262
+ /** Optional cover-art / thumbnail URL. */
49263
+ imageUrl: string().optional()
49264
+ });
49265
+ /**
49266
+ * Where `state`, `volumeLevel`, `isMuted` and `source` come from. `reported`:
49267
+ * the device said so. `assumed`: the driver has no feedback (infrared) and
49268
+ * tracks what it last SENT; it moves only after a send was accepted, and a
49269
+ * human at the real remote makes it wrong. A UI shows an assumed value as a
49270
+ * guess, never as a reading.
49271
+ */
49272
+ var MediaPlayerStateSourceSchema = _enum(["reported", "assumed"]);
49273
+ /** The fields of a media-player status a driver can only guess. */
49274
+ var MediaPlayerAssumedFieldSchema = _enum([
49275
+ "state",
49276
+ "volumeLevel",
49277
+ "isMuted",
49278
+ "source"
49279
+ ]);
49280
+ var MediaPlayerStatusSchema = object({
49281
+ /** Playback lifecycle state. */
49282
+ state: MediaPlayerStateSchema,
49283
+ /**
49284
+ * Whether the state fields are readings or the driver's own bookkeeping.
49285
+ * A slice written before this field existed parses as `reported`.
49286
+ */
49287
+ stateSource: MediaPlayerStateSourceSchema.default("reported"),
49288
+ /**
49289
+ * Which fields are the driver's own guess. `stateSource` is `assumed` when
49290
+ * this is not empty; a field not listed here is a reading even then (power
49291
+ * from a running-state source, mute guessed from the last send).
49292
+ */
49293
+ assumedFields: array(MediaPlayerAssumedFieldSchema).default([]),
49294
+ /** Volume as 0..100 inclusive. Null when the device has no volume
49295
+ * surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
49296
+ volumeLevel: number$1().min(0).max(100).nullable().meta(readingMeta("percentage")),
49297
+ /** Mute toggle distinct from volume=0. Null when no mute surface.
49298
+ * Pair with `DeviceFeature.MediaPlayerMute`. */
49299
+ isMuted: boolean().nullable(),
49300
+ /** Active source / input. Empty when no source surface. */
49301
+ source: string(),
49302
+ /** Selectable sources. Empty when no source surface.
49303
+ * Pair with `DeviceFeature.MediaPlayerSelectSource`. */
49304
+ availableSources: array(string()),
49305
+ /** Currently-playing media info. Null when nothing is playing. */
49306
+ currentMedia: MediaInfoSchema.nullable(),
49307
+ /** Current playback position in ms. Null when not seekable or
49308
+ * nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
49309
+ position: number$1().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
49310
+ /** Total duration of the current media in ms. Null when unknown
49311
+ * (live stream) or nothing is playing. */
49312
+ duration: number$1().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
49313
+ /** Shuffle toggle. Null when no shuffle surface.
49314
+ * Pair with `DeviceFeature.MediaPlayerShuffle`. */
49315
+ shuffle: boolean().nullable(),
49316
+ /** Repeat mode. Null when no repeat surface.
49317
+ * Pair with `DeviceFeature.MediaPlayerRepeat`. */
49318
+ repeat: MediaPlayerRepeatSchema.nullable(),
49319
+ /** Ms epoch when the slice was last updated. */
49320
+ lastChangedAt: number$1()
49321
+ });
49322
+ var stepInput = object({
49323
+ deviceId: number$1().int().nonnegative(),
49324
+ /** How many presses: the caller's count (Alexa `volumeSteps`, `channelCount`). */
49325
+ steps: number$1().int().min(1).max(50).default(1)
49326
+ });
49327
+ var deviceOnly = object({ deviceId: number$1().int().nonnegative() });
49328
+ var mediaPlayerCapability = {
49329
+ name: "media-player",
49330
+ scope: "device",
49331
+ deviceNative: true,
49332
+ mode: "singleton",
49333
+ deviceTypes: [DeviceType.MediaPlayer],
49334
+ methods: {
49335
+ turnOn: method(deviceOnly, _void(), {
49336
+ kind: "mutation",
49337
+ auth: "protected"
49338
+ }),
49339
+ turnOff: method(deviceOnly, _void(), {
49340
+ kind: "mutation",
49341
+ auth: "protected"
49342
+ }),
49343
+ volumeUp: method(stepInput, _void(), {
49344
+ kind: "mutation",
49345
+ auth: "protected"
49346
+ }),
49347
+ volumeDown: method(stepInput, _void(), {
49348
+ kind: "mutation",
49349
+ auth: "protected"
49350
+ }),
49351
+ channelUp: method(stepInput, _void(), {
49352
+ kind: "mutation",
49353
+ auth: "protected"
49354
+ }),
49355
+ channelDown: method(stepInput, _void(), {
49356
+ kind: "mutation",
49357
+ auth: "protected"
49358
+ }),
49359
+ play: method(object({ deviceId: number$1().int().nonnegative() }), _void(), {
49360
+ kind: "mutation",
49361
+ auth: "protected"
49362
+ }),
49363
+ pause: method(object({ deviceId: number$1().int().nonnegative() }), _void(), {
49364
+ kind: "mutation",
49365
+ auth: "protected"
49366
+ }),
49367
+ stop: method(object({ deviceId: number$1().int().nonnegative() }), _void(), {
49368
+ kind: "mutation",
49369
+ auth: "protected"
49370
+ }),
49371
+ next: method(object({ deviceId: number$1().int().nonnegative() }), _void(), {
49372
+ kind: "mutation",
49373
+ auth: "protected"
49374
+ }),
49375
+ previous: method(object({ deviceId: number$1().int().nonnegative() }), _void(), {
49376
+ kind: "mutation",
49377
+ auth: "protected"
49378
+ }),
49379
+ seek: method(object({
49380
+ deviceId: number$1().int().nonnegative(),
49381
+ position: number$1().int().nonnegative()
49382
+ }), _void(), {
49383
+ kind: "mutation",
49384
+ auth: "protected"
49385
+ }),
49386
+ setVolume: method(object({
49387
+ deviceId: number$1().int().nonnegative(),
49388
+ volumeLevel: number$1().min(0).max(100)
49389
+ }), _void(), {
49390
+ kind: "mutation",
49391
+ auth: "protected"
49392
+ }),
49393
+ setMute: method(object({
49394
+ deviceId: number$1().int().nonnegative(),
49395
+ muted: boolean()
49396
+ }), _void(), {
49397
+ kind: "mutation",
49398
+ auth: "protected"
49399
+ }),
49400
+ setShuffle: method(object({
49401
+ deviceId: number$1().int().nonnegative(),
49402
+ shuffle: boolean()
49403
+ }), _void(), {
49404
+ kind: "mutation",
49405
+ auth: "protected"
49406
+ }),
49407
+ setRepeat: method(object({
49408
+ deviceId: number$1().int().nonnegative(),
49409
+ repeat: MediaPlayerRepeatSchema
49410
+ }), _void(), {
49411
+ kind: "mutation",
49412
+ auth: "protected"
49413
+ }),
49414
+ selectSource: method(object({
49415
+ deviceId: number$1().int().nonnegative(),
49416
+ source: string().min(1)
49417
+ }), _void(), {
49418
+ kind: "mutation",
49419
+ auth: "protected"
49420
+ }),
49421
+ playMedia: method(object({
49422
+ deviceId: number$1().int().nonnegative(),
49423
+ /** Media identifier / URL. */
49424
+ mediaId: string().min(1),
49425
+ /** Media kind (`music`, `tvshow`, `movie`, `app`, …) — provider
49426
+ * passes it through to the upstream service. */
49427
+ mediaType: string().min(1)
49428
+ }), _void(), {
49429
+ kind: "mutation",
49430
+ auth: "protected"
49431
+ })
49432
+ },
49433
+ status: {
49434
+ schema: MediaPlayerStatusSchema,
49435
+ kind: "push"
49436
+ },
49437
+ /**
49438
+ * Runtime-state slice — mirrored by the kernel. UI players read the
49439
+ * full slice for live now-playing, volume, and progress updates
49440
+ * without polling.
49441
+ */
49442
+ runtimeState: MediaPlayerStatusSchema,
49443
+ /**
49444
+ * Runtime-state durability: **session** — a restored transport position describes a playback that stopped when the hub did.
49445
+ *
49446
+ * See `RuntimeStateDurability`. Enforced by
49447
+ * `scripts/check-runtime-state-durability.ts`.
49448
+ */
49449
+ durability: "session",
49450
+ /**
49451
+ * History (D850): volume (a level an operator or an automation sets; the
49452
+ * default 10 s floor folds a slider drag into its end value) and mute.
49453
+ * `position` is not recorded: it moves continuously while playing.
49454
+ */
49455
+ history: { fields: {
49456
+ volumeLevel: {
49457
+ kind: "gauge",
49458
+ unit: "%",
49459
+ deadband: 1
49460
+ },
49461
+ isMuted: { kind: "boolean" }
49462
+ } }
49463
+ };
49155
49464
  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.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Heater, DeviceType.Dryer, DeviceType.Gateway, DeviceType.Camera, DeviceType.Fan, DeviceType.Lock, 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.Heater, 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.Heater, 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.Heater, 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.Heater, DeviceType.Gateway, DeviceType.Hub, DeviceType.Camera, DeviceType.Sensor, DeviceType.MediaPlayer, DeviceType.Vacuum, DeviceType.Generic, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.PetFountain, DeviceType.Fan, DeviceType.Humidifier, DeviceType.Climate, DeviceType.WaterHeater, 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, DeviceType.Heater;
49156
49465
  var NUMBER = {
49157
49466
  kind: "fixed",
@@ -57845,214 +58154,6 @@ var LoginMethodContributionSchema = discriminatedUnion("kind", [
57845
58154
  ]);
57846
58155
  method(_void(), array(LoginMethodContributionSchema).readonly());
57847
58156
  /**
57848
- * Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
57849
- * Apple TV, Spotify, Roku, generic OTT receivers, …) on
57850
- * `DeviceType.MediaPlayer`. Disjoint from the camera streaming
57851
- * surface — those use `DeviceType.Camera` + the broker pipeline.
57852
- *
57853
- * The cap declares a wide method surface; not every backend supports
57854
- * every method. Drivers signal sub-capability via the
57855
- * `DeviceFeature.MediaPlayerXxx` flags (paired one-to-one with the
57856
- * corresponding method) so the UI gates buttons without a slice
57857
- * fetch — same pattern as `PanTiltZoom` for cameras.
57858
- */
57859
- var MediaPlayerStateSchema = _enum([
57860
- "off",
57861
- "on",
57862
- "idle",
57863
- "playing",
57864
- "paused",
57865
- "buffering",
57866
- "standby"
57867
- ]);
57868
- var MediaPlayerRepeatSchema = _enum([
57869
- "off",
57870
- "all",
57871
- "one"
57872
- ]);
57873
- var MediaInfoSchema = object({
57874
- /** Free-form media kind (`music`, `tvshow`, `movie`, `app`, `channel`,
57875
- * `podcast`, …). */
57876
- type: string(),
57877
- /** Human-readable title. */
57878
- title: string(),
57879
- /** Optional artist / channel / station label. */
57880
- artist: string().optional(),
57881
- /** Optional album / season / show name. */
57882
- album: string().optional(),
57883
- /** Optional cover-art / thumbnail URL. */
57884
- imageUrl: string().optional()
57885
- });
57886
- /**
57887
- * Where `state`, `volumeLevel`, `isMuted` and `source` come from. `reported`:
57888
- * the device said so. `assumed`: the driver has no feedback (infrared) and
57889
- * tracks what it last SENT; it moves only after a send was accepted, and a
57890
- * human at the real remote makes it wrong. A UI shows an assumed value as a
57891
- * guess, never as a reading.
57892
- */
57893
- var MediaPlayerStateSourceSchema = _enum(["reported", "assumed"]);
57894
- /** The fields of a media-player status a driver can only guess. */
57895
- var MediaPlayerAssumedFieldSchema = _enum([
57896
- "state",
57897
- "volumeLevel",
57898
- "isMuted",
57899
- "source"
57900
- ]);
57901
- var MediaPlayerStatusSchema = object({
57902
- /** Playback lifecycle state. */
57903
- state: MediaPlayerStateSchema,
57904
- /**
57905
- * Whether the state fields are readings or the driver's own bookkeeping.
57906
- * A slice written before this field existed parses as `reported`.
57907
- */
57908
- stateSource: MediaPlayerStateSourceSchema.default("reported"),
57909
- /**
57910
- * Which fields are the driver's own guess. `stateSource` is `assumed` when
57911
- * this is not empty; a field not listed here is a reading even then (power
57912
- * from a running-state source, mute guessed from the last send).
57913
- */
57914
- assumedFields: array(MediaPlayerAssumedFieldSchema).default([]),
57915
- /** Volume as 0..100 inclusive. Null when the device has no volume
57916
- * surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
57917
- volumeLevel: number$1().min(0).max(100).nullable().meta(readingMeta("percentage")),
57918
- /** Mute toggle distinct from volume=0. Null when no mute surface.
57919
- * Pair with `DeviceFeature.MediaPlayerMute`. */
57920
- isMuted: boolean().nullable(),
57921
- /** Active source / input. Empty when no source surface. */
57922
- source: string(),
57923
- /** Selectable sources. Empty when no source surface.
57924
- * Pair with `DeviceFeature.MediaPlayerSelectSource`. */
57925
- availableSources: array(string()),
57926
- /** Currently-playing media info. Null when nothing is playing. */
57927
- currentMedia: MediaInfoSchema.nullable(),
57928
- /** Current playback position in ms. Null when not seekable or
57929
- * nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
57930
- position: number$1().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
57931
- /** Total duration of the current media in ms. Null when unknown
57932
- * (live stream) or nothing is playing. */
57933
- duration: number$1().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
57934
- /** Shuffle toggle. Null when no shuffle surface.
57935
- * Pair with `DeviceFeature.MediaPlayerShuffle`. */
57936
- shuffle: boolean().nullable(),
57937
- /** Repeat mode. Null when no repeat surface.
57938
- * Pair with `DeviceFeature.MediaPlayerRepeat`. */
57939
- repeat: MediaPlayerRepeatSchema.nullable(),
57940
- /** Ms epoch when the slice was last updated. */
57941
- lastChangedAt: number$1()
57942
- });
57943
- var mediaPlayerCapability = {
57944
- name: "media-player",
57945
- scope: "device",
57946
- deviceNative: true,
57947
- mode: "singleton",
57948
- deviceTypes: [DeviceType.MediaPlayer],
57949
- methods: {
57950
- play: method(object({ deviceId: number$1().int().nonnegative() }), _void(), {
57951
- kind: "mutation",
57952
- auth: "protected"
57953
- }),
57954
- pause: method(object({ deviceId: number$1().int().nonnegative() }), _void(), {
57955
- kind: "mutation",
57956
- auth: "protected"
57957
- }),
57958
- stop: method(object({ deviceId: number$1().int().nonnegative() }), _void(), {
57959
- kind: "mutation",
57960
- auth: "protected"
57961
- }),
57962
- next: method(object({ deviceId: number$1().int().nonnegative() }), _void(), {
57963
- kind: "mutation",
57964
- auth: "protected"
57965
- }),
57966
- previous: method(object({ deviceId: number$1().int().nonnegative() }), _void(), {
57967
- kind: "mutation",
57968
- auth: "protected"
57969
- }),
57970
- seek: method(object({
57971
- deviceId: number$1().int().nonnegative(),
57972
- position: number$1().int().nonnegative()
57973
- }), _void(), {
57974
- kind: "mutation",
57975
- auth: "protected"
57976
- }),
57977
- setVolume: method(object({
57978
- deviceId: number$1().int().nonnegative(),
57979
- volumeLevel: number$1().min(0).max(100)
57980
- }), _void(), {
57981
- kind: "mutation",
57982
- auth: "protected"
57983
- }),
57984
- setMute: method(object({
57985
- deviceId: number$1().int().nonnegative(),
57986
- muted: boolean()
57987
- }), _void(), {
57988
- kind: "mutation",
57989
- auth: "protected"
57990
- }),
57991
- setShuffle: method(object({
57992
- deviceId: number$1().int().nonnegative(),
57993
- shuffle: boolean()
57994
- }), _void(), {
57995
- kind: "mutation",
57996
- auth: "protected"
57997
- }),
57998
- setRepeat: method(object({
57999
- deviceId: number$1().int().nonnegative(),
58000
- repeat: MediaPlayerRepeatSchema
58001
- }), _void(), {
58002
- kind: "mutation",
58003
- auth: "protected"
58004
- }),
58005
- selectSource: method(object({
58006
- deviceId: number$1().int().nonnegative(),
58007
- source: string().min(1)
58008
- }), _void(), {
58009
- kind: "mutation",
58010
- auth: "protected"
58011
- }),
58012
- playMedia: method(object({
58013
- deviceId: number$1().int().nonnegative(),
58014
- /** Media identifier / URL. */
58015
- mediaId: string().min(1),
58016
- /** Media kind (`music`, `tvshow`, `movie`, `app`, …) — provider
58017
- * passes it through to the upstream service. */
58018
- mediaType: string().min(1)
58019
- }), _void(), {
58020
- kind: "mutation",
58021
- auth: "protected"
58022
- })
58023
- },
58024
- status: {
58025
- schema: MediaPlayerStatusSchema,
58026
- kind: "push"
58027
- },
58028
- /**
58029
- * Runtime-state slice — mirrored by the kernel. UI players read the
58030
- * full slice for live now-playing, volume, and progress updates
58031
- * without polling.
58032
- */
58033
- runtimeState: MediaPlayerStatusSchema,
58034
- /**
58035
- * Runtime-state durability: **session** — a restored transport position describes a playback that stopped when the hub did.
58036
- *
58037
- * See `RuntimeStateDurability`. Enforced by
58038
- * `scripts/check-runtime-state-durability.ts`.
58039
- */
58040
- durability: "session",
58041
- /**
58042
- * History (D850): volume (a level an operator or an automation sets; the
58043
- * default 10 s floor folds a slider drag into its end value) and mute.
58044
- * `position` is not recorded: it moves continuously while playing.
58045
- */
58046
- history: { fields: {
58047
- volumeLevel: {
58048
- kind: "gauge",
58049
- unit: "%",
58050
- deadband: 1
58051
- },
58052
- isMuted: { kind: "boolean" }
58053
- } }
58054
- };
58055
- /**
58056
58157
  * mesh-network — collection cap for mesh-VPN providers.
58057
58158
  *
58058
58159
  * Different shape from `network-access` (public tunnels):
@@ -66811,6 +66912,21 @@ var NcTemplateVarKindSchema = _enum([
66811
66912
  "sound",
66812
66913
  "system"
66813
66914
  ]);
66915
+ /**
66916
+ * The default title/body a rule of one SITUATION is delivered with when the
66917
+ * operator wrote no template — served so an editor can pre-fill it (and the
66918
+ * operator can rebuild it from placeholders) instead of starting from a blank
66919
+ * box that, once saved, silently replaces it. `id` names the situation inside
66920
+ * a rule `kind`: `appliance-cycle` is a `sensor` rule whose device is an
66921
+ * appliance finishing a cycle. Texts are raw templates (`{{var}}` intact), in
66922
+ * the hub's current language and with its overrides applied.
66923
+ */
66924
+ var NcTemplateDefaultSchema = object({
66925
+ id: _enum(["appliance-cycle"]),
66926
+ kind: NcRuleKindSchema,
66927
+ title: string(),
66928
+ body: string()
66929
+ });
66814
66930
  /** Which producer renders a template: an ordinary rule, a timelapse, a digest. */
66815
66931
  var NcTemplateFamilySchema = _enum([
66816
66932
  "rule",
@@ -67666,7 +67782,11 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
67666
67782
  }), method(object({}), object({
67667
67783
  catalog: array(NcConditionDescriptorSchema),
67668
67784
  taxonomy: NcTaxonomySchema.optional()
67669
- })), method(object({}), object({ vars: array(NcTemplateVarDescriptorSchema) })), method(NcTemplatePreviewInputSchema, NcTemplatePreviewSchema, {
67785
+ })), method(object({}), object({
67786
+ vars: array(NcTemplateVarDescriptorSchema),
67787
+ /** Per-situation default texts; absent on a hub that predates them. */
67788
+ defaults: array(NcTemplateDefaultSchema)
67789
+ })), method(NcTemplatePreviewInputSchema, NcTemplatePreviewSchema, {
67670
67790
  kind: "mutation",
67671
67791
  access: "view"
67672
67792
  }), method(object({ filter: NcHistoryFilterSchema.default({ limit: 100 }) }), object({ entries: array(NcHistoryEntrySchema) }), { auth: "admin" }), method(object({}), NcRuleLastRunsSchema, { auth: "admin" }), method(object({ artifactId: string().min(1) }), object({ url: string().nullable() }), { auth: "admin" }), method(object({}), object({ snoozes: array(NcSnoozeSchema) }), { caller: "required" }), method(object({ snooze: NcSnoozeInputSchema }), object({ snooze: NcSnoozeSchema }), {
@@ -73818,7 +73938,13 @@ var RemoteMediaCommandSchema = _enum([
73818
73938
  "next",
73819
73939
  "previous",
73820
73940
  "setMute",
73821
- "selectSource"
73941
+ "selectSource",
73942
+ "turnOn",
73943
+ "turnOff",
73944
+ "volumeUp",
73945
+ "volumeDown",
73946
+ "channelUp",
73947
+ "channelDown"
73822
73948
  ]);
73823
73949
  /** A send result, or `not-routed`: the role is not bound, so the native cap answers. */
73824
73950
  var RemoteMediaCommandResultSchema = discriminatedUnion("status", [...RemoteSendResultSchema.options, object({ status: literal("not-routed") })]);
@@ -73839,7 +73965,7 @@ method(deviceInput, RemoteConfigSchema, { auth: "admin" }), method(deviceInput.e
73839
73965
  }), RemoteSendResultSchema, {
73840
73966
  kind: "mutation",
73841
73967
  auth: "protected"
73842
- }), method(deviceInput.extend({
73968
+ }), method(deviceInput, MediaPlayerStatusSchema.nullable(), { auth: "protected" }), method(deviceInput.extend({
73843
73969
  command: RemoteMediaCommandSchema,
73844
73970
  muted: boolean().optional(),
73845
73971
  source: string().optional(),
@@ -76085,7 +76211,11 @@ listSignals: method(_void(), array(StreamSignalSchema).readonly()) }
76085
76211
  * `getSettingsUISchema()` surface.
76086
76212
  */
76087
76213
  var SwitchStatusSchema = object({
76088
- on: boolean().meta({ label: "On" }),
76214
+ /**
76215
+ * `null` = the device has never reported its state (a measurement that
76216
+ * has not happened is unknown, never `false`).
76217
+ */
76218
+ on: boolean().nullable().meta({ label: "On" }),
76089
76219
  /** Ms epoch of the last state change. Useful for UI "X minutes ago". */
76090
76220
  lastChangedAt: number$1()
76091
76221
  });
@@ -76110,7 +76240,7 @@ var switchCapability = {
76110
76240
  }) },
76111
76241
  events: { onStateChanged: { data: object({
76112
76242
  deviceId: number$1(),
76113
- on: boolean(),
76243
+ on: boolean().nullable(),
76114
76244
  lastChangedAt: number$1()
76115
76245
  }) } },
76116
76246
  status: {
@@ -79667,6 +79797,7 @@ function buildDescriptor(capName, kind) {
79667
79797
  * contributes one entry per bound cap present in this map.
79668
79798
  */
79669
79799
  var EVENT_KIND_BY_CAP = Object.freeze(Object.fromEntries(Object.entries(CAP_TO_KIND).map(([capName, kind]) => [capName, buildDescriptor(capName, kind)])));
79800
+ DeviceFeature.MediaPlayerPower, DeviceFeature.MediaPlayerVolumeStep, DeviceFeature.MediaPlayerChannelStep, DeviceFeature.MediaPlayerMute, DeviceFeature.MediaPlayerStop, DeviceFeature.MediaPlayerNext, DeviceFeature.MediaPlayerPrevious;
79670
79801
  var btn = (idSuffix, row, col, init) => ({
79671
79802
  idSuffix,
79672
79803
  row,
@@ -85845,6 +85976,20 @@ Object.freeze({
85845
85976
  access: "view",
85846
85977
  role: "admin"
85847
85978
  },
85979
+ "mediaPlayer.channelDown": {
85980
+ capName: "media-player",
85981
+ capScope: "device",
85982
+ addonId: null,
85983
+ access: "create",
85984
+ role: "viewer"
85985
+ },
85986
+ "mediaPlayer.channelUp": {
85987
+ capName: "media-player",
85988
+ capScope: "device",
85989
+ addonId: null,
85990
+ access: "create",
85991
+ role: "viewer"
85992
+ },
85848
85993
  "mediaPlayer.getStatus": {
85849
85994
  capName: "media-player",
85850
85995
  capScope: "device",
@@ -85936,6 +86081,34 @@ Object.freeze({
85936
86081
  access: "create",
85937
86082
  role: "viewer"
85938
86083
  },
86084
+ "mediaPlayer.turnOff": {
86085
+ capName: "media-player",
86086
+ capScope: "device",
86087
+ addonId: null,
86088
+ access: "create",
86089
+ role: "viewer"
86090
+ },
86091
+ "mediaPlayer.turnOn": {
86092
+ capName: "media-player",
86093
+ capScope: "device",
86094
+ addonId: null,
86095
+ access: "create",
86096
+ role: "viewer"
86097
+ },
86098
+ "mediaPlayer.volumeDown": {
86099
+ capName: "media-player",
86100
+ capScope: "device",
86101
+ addonId: null,
86102
+ access: "create",
86103
+ role: "viewer"
86104
+ },
86105
+ "mediaPlayer.volumeUp": {
86106
+ capName: "media-player",
86107
+ capScope: "device",
86108
+ addonId: null,
86109
+ access: "create",
86110
+ role: "viewer"
86111
+ },
85939
86112
  "meshNetwork.getStatus": {
85940
86113
  capName: "mesh-network",
85941
86114
  capScope: "system",
@@ -89492,6 +89665,13 @@ Object.freeze({
89492
89665
  access: "create",
89493
89666
  role: "admin"
89494
89667
  },
89668
+ "remote.getAssumedStatus": {
89669
+ capName: "remote",
89670
+ capScope: "system",
89671
+ addonId: null,
89672
+ access: "view",
89673
+ role: "admin"
89674
+ },
89495
89675
  "remote.getConfig": {
89496
89676
  capName: "remote",
89497
89677
  capScope: "system",
@@ -93158,6 +93338,16 @@ Object.freeze({
93158
93338
  form: "single",
93159
93339
  optional: true
93160
93340
  }],
93341
+ "mediaPlayer.channelDown": [{
93342
+ name: "deviceId",
93343
+ form: "single",
93344
+ optional: false
93345
+ }],
93346
+ "mediaPlayer.channelUp": [{
93347
+ name: "deviceId",
93348
+ form: "single",
93349
+ optional: false
93350
+ }],
93161
93351
  "mediaPlayer.getStatus": [{
93162
93352
  name: "deviceId",
93163
93353
  form: "single",
@@ -93223,6 +93413,26 @@ Object.freeze({
93223
93413
  form: "single",
93224
93414
  optional: false
93225
93415
  }],
93416
+ "mediaPlayer.turnOff": [{
93417
+ name: "deviceId",
93418
+ form: "single",
93419
+ optional: false
93420
+ }],
93421
+ "mediaPlayer.turnOn": [{
93422
+ name: "deviceId",
93423
+ form: "single",
93424
+ optional: false
93425
+ }],
93426
+ "mediaPlayer.volumeDown": [{
93427
+ name: "deviceId",
93428
+ form: "single",
93429
+ optional: false
93430
+ }],
93431
+ "mediaPlayer.volumeUp": [{
93432
+ name: "deviceId",
93433
+ form: "single",
93434
+ optional: false
93435
+ }],
93226
93436
  "meter.getStatus": [{
93227
93437
  name: "deviceId",
93228
93438
  form: "single",
@@ -94388,6 +94598,11 @@ Object.freeze({
94388
94598
  form: "single",
94389
94599
  optional: true
94390
94600
  }],
94601
+ "remote.getAssumedStatus": [{
94602
+ name: "deviceId",
94603
+ form: "single",
94604
+ optional: false
94605
+ }],
94391
94606
  "remote.getConfig": [{
94392
94607
  name: "deviceId",
94393
94608
  form: "single",
@@ -95850,6 +96065,7 @@ var STATE_SUMMARY_VARS = [
95850
96065
  [...RULE_TEXT],
95851
96066
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
95852
96067
  ([...RULE_TEXT], [...COMBINED_ALARM]),
96068
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
95853
96069
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
95854
96070
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
95855
96071
  ([...RULE_TEXT], [...CONSUMABLE]),
@@ -142367,6 +142583,12 @@ var AlexaEchoDevice = class extends BaseDevice {
142367
142583
  this.rereadSoon();
142368
142584
  },
142369
142585
  stop: async () => unsupported("stop"),
142586
+ turnOn: async () => unsupported("power"),
142587
+ turnOff: async () => unsupported("power"),
142588
+ volumeUp: async () => unsupported("volume steps"),
142589
+ volumeDown: async () => unsupported("volume steps"),
142590
+ channelUp: async () => unsupported("channel steps"),
142591
+ channelDown: async () => unsupported("channel steps"),
142370
142592
  seek: async () => unsupported("seek"),
142371
142593
  setMute: async () => unsupported("mute"),
142372
142594
  setShuffle: async () => unsupported("shuffle"),