@camstack/addon-provider-velux 0.2.156 → 0.2.157

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
@@ -821,7 +821,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
821
821
  return EventCategory;
822
822
  }({});
823
823
  //#endregion
824
- //#region ../types/dist/device-type-CfHw_quR.mjs
824
+ //#region ../types/dist/device-type-D1fH5kaC.mjs
825
825
  /**
826
826
  import { errMsg } from '@camstack/types'
827
827
  * Extract a human-readable message from an unknown error value.
@@ -1052,6 +1052,12 @@ var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
1052
1052
  DeviceFeature["MediaPlayerPrevious"] = "media-player-previous";
1053
1053
  /** Media player exposes stop distinct from pause. */
1054
1054
  DeviceFeature["MediaPlayerStop"] = "media-player-stop";
1055
+ /** Media player exposes volume up / down in steps (an infrared TV has no level). */
1056
+ DeviceFeature["MediaPlayerVolumeStep"] = "media-player-volume-step";
1057
+ /** Media player exposes channel up / down in steps. */
1058
+ DeviceFeature["MediaPlayerChannelStep"] = "media-player-channel-step";
1059
+ /** Media player exposes power on / off. */
1060
+ DeviceFeature["MediaPlayerPower"] = "media-player-power";
1055
1061
  /** Alarm panel requires a PIN code on arm/disarm. */
1056
1062
  DeviceFeature["AlarmPinRequired"] = "alarm-pin-required";
1057
1063
  /** Presence device carries GPS coordinates (lat/lng/accuracy) in
@@ -5878,7 +5884,7 @@ var ZodIssueCode = {
5878
5884
  var ZodFirstPartyTypeKind;
5879
5885
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5880
5886
  //#endregion
5881
- //#region ../types/dist/sleep-QsoHs66J.mjs
5887
+ //#region ../types/dist/sleep-DV4qxEyD.mjs
5882
5888
  /**
5883
5889
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5884
5890
  * window to float samples (D455).
@@ -5957,6 +5963,22 @@ function buildAlawTable() {
5957
5963
  }
5958
5964
  buildUlawTable();
5959
5965
  buildAlawTable();
5966
+ /**
5967
+ * An addon whose own migrations did not apply refuses to initialise (D987). The error is typed
5968
+ * so a runner hosting several addons can tell "this addon is blocked" from a crash and keep its
5969
+ * co-located siblings running. Recognised by NAME and shape, never `instanceof`: a forked addon
5970
+ * bundles its own copy of this module, so the class the runner sees is not the one that threw.
5971
+ */
5972
+ var MIGRATIONS_BLOCKED_ERROR_NAME = "AddonMigrationsBlockedError";
5973
+ var AddonMigrationsBlockedError = class extends Error {
5974
+ /** The ledger ids that did not apply and block the owner. */
5975
+ migrationIds;
5976
+ constructor(migrationIds) {
5977
+ super(`migration(s) ${migrationIds.join(", ")} did not apply and block this addon — fix or retry them (migrations.retry), then restart it`);
5978
+ this.name = MIGRATIONS_BLOCKED_ERROR_NAME;
5979
+ this.migrationIds = migrationIds;
5980
+ }
5981
+ };
5960
5982
  /** Is this field's stored value a credential? */
5961
5983
  function isSecretConfigField(field) {
5962
5984
  if (field.type === "password") return true;
@@ -7563,7 +7585,7 @@ var BaseAddon = class {
7563
7585
  startMigration: (input) => api.startMigration.mutate(input),
7564
7586
  finishMigration: (input) => api.finishMigration.mutate(input)
7565
7587
  }, migrations, this.ctx.logger);
7566
- 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`);
7588
+ if (report.blockOwner.length > 0) throw new AddonMigrationsBlockedError(report.blockOwner);
7567
7589
  return report;
7568
7590
  }
7569
7591
  /**
@@ -7903,6 +7925,10 @@ var BaseAddon = class {
7903
7925
  const stored = keychain ? await this.readAddonStoreWithRetry() : {};
7904
7926
  const patch = {};
7905
7927
  for (const key of keys) {
7928
+ if (tree.get(key)?.kind === "array") {
7929
+ patch[key] = [];
7930
+ continue;
7931
+ }
7906
7932
  const keychainStored = tree.has(key) || collectSecretMarkerRefs(stored[key]).length > 0;
7907
7933
  patch[key] = keychain && keychainStored ? SECRET_CLEAR : "";
7908
7934
  }
@@ -9392,6 +9418,7 @@ var CAP_NAMES = Object.freeze([
9392
9418
  "backup",
9393
9419
  "battery",
9394
9420
  "binary",
9421
+ "board-key-source",
9395
9422
  "brightness",
9396
9423
  "broker",
9397
9424
  "button",
@@ -9513,6 +9540,7 @@ var CAP_NAMES = Object.freeze([
9513
9540
  "privacy-mask",
9514
9541
  "ptz",
9515
9542
  "ptz-autotrack",
9543
+ "pump-cycle",
9516
9544
  "reboot",
9517
9545
  "record-entries",
9518
9546
  "recording",
@@ -10805,18 +10833,6 @@ Object.freeze({
10805
10833
  "path": "pumpRunning",
10806
10834
  "valueType": "boolean"
10807
10835
  },
10808
- {
10809
- "path": "pumpIntervalEnabled",
10810
- "valueType": "boolean"
10811
- },
10812
- {
10813
- "path": "pumpOnTime",
10814
- "valueType": "number"
10815
- },
10816
- {
10817
- "path": "pumpOffTime",
10818
- "valueType": "number"
10819
- },
10820
10836
  {
10821
10837
  "path": "lastDrink",
10822
10838
  "valueType": "number"
@@ -10940,6 +10956,20 @@ Object.freeze({
10940
10956
  "valueType": "number"
10941
10957
  }
10942
10958
  ],
10959
+ "pump-cycle": [
10960
+ {
10961
+ "path": "enabled",
10962
+ "valueType": "boolean"
10963
+ },
10964
+ {
10965
+ "path": "onTime",
10966
+ "valueType": "number"
10967
+ },
10968
+ {
10969
+ "path": "offTime",
10970
+ "valueType": "number"
10971
+ }
10972
+ ],
10943
10973
  "recording-archive": [
10944
10974
  {
10945
10975
  "path": "deviceId",
@@ -11389,7 +11419,7 @@ object({
11389
11419
  params: record(string(), union([string(), number()])).optional()
11390
11420
  });
11391
11421
  //#endregion
11392
- //#region ../types/dist/composition-Dh3RfMx5.mjs
11422
+ //#region ../types/dist/composition-BodkvOV0.mjs
11393
11423
  /**
11394
11424
  * The ffmpeg build every CamStack node downloads, per platform and arch.
11395
11425
  *
@@ -12526,7 +12556,14 @@ var CompositionForwardCommandSchema = object({
12526
12556
  method: string().min(1),
12527
12557
  args: record(string().min(1), CompositionForwardArgSchema).optional()
12528
12558
  });
12529
- var CompositionCommandTargetSchema = discriminatedUnion("kind", [CompositionForwardCommandSchema, CompositionCodeSourceSchema]);
12559
+ var CompositionCommandTargetSchema = discriminatedUnion("kind", [
12560
+ CompositionForwardCommandSchema,
12561
+ CompositionCodeSourceSchema,
12562
+ object({
12563
+ kind: literal("extension"),
12564
+ target: literal("remote")
12565
+ })
12566
+ ]);
12530
12567
  /** An item key inside an item-array cap (`consumables.items[<key>]`). */
12531
12568
  var COMPOSITION_ITEM_KEY_RE = /^[a-z0-9][a-z0-9-]{0,47}$/;
12532
12569
  /**
@@ -12603,6 +12640,73 @@ var NodeColorIdSchema = _enum([
12603
12640
  "node-g",
12604
12641
  "node-h"
12605
12642
  ]);
12643
+ //#endregion
12644
+ //#region ../types/dist/index.mjs
12645
+ var SMTP_INBOUND_DEFAULT_PORT = 2525;
12646
+ var SMTP_INBOUND_DEFAULT_DOMAIN = "camstack.local";
12647
+ var SMTP_INBOUND_DEFAULT_MAX_MESSAGE_BYTES = 25 * 1024 * 1024;
12648
+ /** The text excerpt a message carries on the bus. */
12649
+ var SMTP_INBOUND_TEXT_MAX_CHARS = 4096;
12650
+ var PortSchema = number().int().min(1).max(65535);
12651
+ /** A recipient local-part: what stands before the `@`. */
12652
+ var SmtpRecipientSchema = string().min(1).max(64).regex(/^[A-Za-z0-9._+-]+$/);
12653
+ object({
12654
+ port: PortSchema.default(SMTP_INBOUND_DEFAULT_PORT),
12655
+ bindHost: string().min(1).default("0.0.0.0"),
12656
+ domain: string().min(1).default(SMTP_INBOUND_DEFAULT_DOMAIN),
12657
+ requireAuth: boolean().default(true),
12658
+ username: string().default(""),
12659
+ password: string().default("").meta({ secret: true }),
12660
+ starttls: boolean().default(false),
12661
+ maxMessageBytes: number().int().positive().default(SMTP_INBOUND_DEFAULT_MAX_MESSAGE_BYTES)
12662
+ });
12663
+ object({
12664
+ host: string().min(1).nullable(),
12665
+ hostReason: string().nullable(),
12666
+ port: PortSchema,
12667
+ domain: string().min(1),
12668
+ requireAuth: boolean(),
12669
+ username: string(),
12670
+ password: string(),
12671
+ starttls: boolean()
12672
+ });
12673
+ object({
12674
+ recipients: array(SmtpRecipientSchema).min(1),
12675
+ /**
12676
+ * Who is subscribing. A second `subscribe` with the same id REPLACES that subscriber's
12677
+ * recipients (the way a consumer that restarted, or lost a device, declares its set again);
12678
+ * a recipient held by another subscriber is refused with `smtp-inbound/recipient-claimed`.
12679
+ * Absent, the subscriber is anonymous and unique.
12680
+ */
12681
+ subscriberId: string().min(1).max(64).optional()
12682
+ });
12683
+ var SmtpInboundAttachmentSchema = object({
12684
+ filename: string(),
12685
+ contentType: string(),
12686
+ bytes: number().int().nonnegative()
12687
+ });
12688
+ /** The payload of one `broker.message` (the key is the recipient local-part). */
12689
+ var SmtpInboundMessageSchema = object({
12690
+ /** Monotonic per mailbox; a gap tells a consumer it missed an event. */
12691
+ seq: number().int().positive(),
12692
+ messageId: string(),
12693
+ receivedAt: number().int().nonnegative(),
12694
+ from: string(),
12695
+ to: string(),
12696
+ subject: string(),
12697
+ text: string().max(SMTP_INBOUND_TEXT_MAX_CHARS),
12698
+ attachments: array(SmtpInboundAttachmentSchema)
12699
+ });
12700
+ object({
12701
+ /** The newest seq issued so far (0 before any mail). */
12702
+ lastSeq: number().int().nonnegative(),
12703
+ /** The oldest seq still retained; messages below it are gone. */
12704
+ oldestSeq: number().int().nonnegative(),
12705
+ messages: array(object({
12706
+ key: string(),
12707
+ message: SmtpInboundMessageSchema
12708
+ }))
12709
+ });
12606
12710
  new Set([
12607
12711
  "track",
12608
12712
  "face",
@@ -18875,24 +18979,52 @@ var APPLIANCE_CAP_VOCABULARY = {
18875
18979
  args: { on: false }
18876
18980
  },
18877
18981
  {
18878
- id: "petFountain.intervalOn",
18879
- method: "setPumpInterval",
18982
+ id: "petFountain.resetDailyConsumption",
18983
+ method: "resetDailyConsumption",
18984
+ label: t("Clear daily consumption", "Azzera il consumo giornaliero"),
18985
+ phrase: t("Clear the daily water consumption of {device}", "Azzera il consumo giornaliero di acqua di {device}"),
18986
+ icon: "rotate-ccw"
18987
+ }
18988
+ ],
18989
+ state: [{
18990
+ kind: "boolean",
18991
+ field: "empty",
18992
+ label: t("Tank empty", "Serbatoio vuoto"),
18993
+ whenTrue: t("When the tank of {device} is empty", "Quando il serbatoio di {device} è vuoto"),
18994
+ whenFalse: t("When the tank of {device} is refilled", "Quando il serbatoio di {device} viene riempito"),
18995
+ icon: "droplet"
18996
+ }, {
18997
+ kind: "numeric",
18998
+ field: "waterLevel",
18999
+ quantity: t("the water level", "il livello dell’acqua"),
19000
+ label: t("Water level", "Livello dell’acqua"),
19001
+ unit: "%",
19002
+ icon: "droplets"
19003
+ }]
19004
+ },
19005
+ "pump-cycle": {
19006
+ scope: "device",
19007
+ noun: t("Pump cycle", "Ciclo della pompa"),
19008
+ actions: [
19009
+ {
19010
+ id: "pumpCycle.on",
19011
+ method: "setEnabled",
18880
19012
  label: t("Pump cycle on", "Ciclo pompa attivo"),
18881
19013
  phrase: t("Run the pump of {device} on its on/off cycle", "Fai lavorare la pompa di {device} a ciclo acceso/spento"),
18882
19014
  icon: "timer",
18883
19015
  args: { on: true }
18884
19016
  },
18885
19017
  {
18886
- id: "petFountain.intervalOff",
18887
- method: "setPumpInterval",
19018
+ id: "pumpCycle.off",
19019
+ method: "setEnabled",
18888
19020
  label: t("Pump cycle off", "Ciclo pompa spento"),
18889
19021
  phrase: t("Run the pump of {device} continuously", "Fai lavorare la pompa di {device} in continuo"),
18890
19022
  icon: "timer-off",
18891
19023
  args: { on: false }
18892
19024
  },
18893
19025
  {
18894
- id: "petFountain.pumpOnMinutes",
18895
- method: "setPumpOnMinutes",
19026
+ id: "pumpCycle.onMinutes",
19027
+ method: "setOnMinutes",
18896
19028
  label: t("Set pump run time", "Imposta il tempo di lavoro della pompa"),
18897
19029
  phrase: t("Set the pump of {device} to run {minutes} minutes per cycle", "Imposta la pompa di {device} a lavorare {minutes} minuti per ciclo"),
18898
19030
  icon: "timer",
@@ -18908,8 +19040,8 @@ var APPLIANCE_CAP_VOCABULARY = {
18908
19040
  }]
18909
19041
  },
18910
19042
  {
18911
- id: "petFountain.pumpOffMinutes",
18912
- method: "setPumpOffMinutes",
19043
+ id: "pumpCycle.offMinutes",
19044
+ method: "setOffMinutes",
18913
19045
  label: t("Set pump rest time", "Imposta il tempo di riposo della pompa"),
18914
19046
  phrase: t("Set the pump of {device} to rest {minutes} minutes per cycle", "Imposta la pompa di {device} a riposare {minutes} minuti per ciclo"),
18915
19047
  icon: "timer-off",
@@ -18923,35 +19055,63 @@ var APPLIANCE_CAP_VOCABULARY = {
18923
19055
  unit: "min"
18924
19056
  }
18925
19057
  }]
18926
- },
18927
- {
18928
- id: "petFountain.resetDailyConsumption",
18929
- method: "resetDailyConsumption",
18930
- label: t("Clear daily consumption", "Azzera il consumo giornaliero"),
18931
- phrase: t("Clear the daily water consumption of {device}", "Azzera il consumo giornaliero di acqua di {device}"),
18932
- icon: "rotate-ccw"
18933
19058
  }
18934
19059
  ],
18935
19060
  state: [{
18936
19061
  kind: "boolean",
18937
- field: "empty",
18938
- label: t("Tank empty", "Serbatoio vuoto"),
18939
- whenTrue: t("When the tank of {device} is empty", "Quando il serbatoio di {device} è vuoto"),
18940
- whenFalse: t("When the tank of {device} is refilled", "Quando il serbatoio di {device} viene riempito"),
18941
- icon: "droplet"
18942
- }, {
18943
- kind: "numeric",
18944
- field: "waterLevel",
18945
- quantity: t("the water level", "il livello dell’acqua"),
18946
- label: t("Water level", "Livello dell’acqua"),
18947
- unit: "%",
18948
- icon: "droplets"
19062
+ field: "enabled",
19063
+ label: t("Pump cycle", "Ciclo pompa"),
19064
+ whenTrue: t("When {device} starts running its pump on a cycle", "Quando {device} inizia a far lavorare la pompa a ciclo"),
19065
+ whenFalse: t("When {device} runs its pump continuously", "Quando {device} fa lavorare la pompa in continuo"),
19066
+ icon: "timer"
18949
19067
  }]
18950
19068
  },
18951
19069
  "media-player": {
18952
19070
  scope: "device",
18953
19071
  noun: t("Media player", "Lettore multimediale"),
18954
19072
  actions: [
19073
+ {
19074
+ id: "media.turnOn",
19075
+ method: "turnOn",
19076
+ label: t("Turn on", "Accendi"),
19077
+ phrase: t("Turn on {device}", "Accendi {device}"),
19078
+ icon: "power"
19079
+ },
19080
+ {
19081
+ id: "media.turnOff",
19082
+ method: "turnOff",
19083
+ label: t("Turn off", "Spegni"),
19084
+ phrase: t("Turn off {device}", "Spegni {device}"),
19085
+ icon: "power"
19086
+ },
19087
+ {
19088
+ id: "media.volumeUp",
19089
+ method: "volumeUp",
19090
+ label: t("Volume up", "Alza il volume"),
19091
+ phrase: t("Raise the volume of {device}", "Alza il volume di {device}"),
19092
+ icon: "volume-2"
19093
+ },
19094
+ {
19095
+ id: "media.volumeDown",
19096
+ method: "volumeDown",
19097
+ label: t("Volume down", "Abbassa il volume"),
19098
+ phrase: t("Lower the volume of {device}", "Abbassa il volume di {device}"),
19099
+ icon: "volume-2"
19100
+ },
19101
+ {
19102
+ id: "media.channelUp",
19103
+ method: "channelUp",
19104
+ label: t("Channel up", "Canale successivo"),
19105
+ phrase: t("Go to the next channel on {device}", "Passa al canale successivo su {device}"),
19106
+ icon: "skip-forward"
19107
+ },
19108
+ {
19109
+ id: "media.channelDown",
19110
+ method: "channelDown",
19111
+ label: t("Channel down", "Canale precedente"),
19112
+ phrase: t("Go to the previous channel on {device}", "Torna al canale precedente su {device}"),
19113
+ icon: "skip-back"
19114
+ },
18955
19115
  {
18956
19116
  id: "media.play",
18957
19117
  method: "play",
@@ -20838,6 +20998,7 @@ var SYSTEM_CAP_VOCABULARY = {
20838
20998
  "audio-analyzer": system(PIPELINE),
20839
20999
  "audio-codec": system(INTERNAL),
20840
21000
  "auth-provider": system(IDENTITY),
21001
+ "board-key-source": system(INTERNAL),
20841
21002
  backup: system("system backups — run and restored from the Backups page"),
20842
21003
  broker: system("message-broker connections — configured, not actuated"),
20843
21004
  "calendar-source": system(INTERNAL),
@@ -45747,6 +45908,49 @@ var binaryCapability = {
45747
45908
  volatileStateFields: ["lastChangedAt"]
45748
45909
  };
45749
45910
  /**
45911
+ * Why a board key could not be read. Typed so a caller reports the cause and
45912
+ * never treats "could not read" as "has no key" (D49).
45913
+ */
45914
+ var BoardKeyFailureReasonSchema = _enum([
45915
+ "unknown-source",
45916
+ "not-admin",
45917
+ "no-builder",
45918
+ "no-ingress-url",
45919
+ "unreachable",
45920
+ "unknown-board",
45921
+ "no-encryption-key",
45922
+ "unreadable-config"
45923
+ ]);
45924
+ var BoardKeySourceSchema = object({
45925
+ sourceId: string(),
45926
+ name: string()
45927
+ });
45928
+ var BoardKeyBoardSchema = object({
45929
+ /** The builder's file name, e.g. `kitchen.yaml`: the handle `getBoardKey` takes. */
45930
+ configuration: string(),
45931
+ /** The node name the builder gives the board. */
45932
+ name: string(),
45933
+ /** The address the builder knows the board by, when it has one. */
45934
+ address: string().nullable()
45935
+ });
45936
+ var BoardKeyFailureSchema = object({
45937
+ ok: literal(false),
45938
+ reason: BoardKeyFailureReasonSchema,
45939
+ detail: string().optional()
45940
+ });
45941
+ var ListBoardsResultSchema = discriminatedUnion("ok", [object({
45942
+ ok: literal(true),
45943
+ boards: array(BoardKeyBoardSchema).readonly()
45944
+ }), BoardKeyFailureSchema]);
45945
+ var GetBoardKeyResultSchema = discriminatedUnion("ok", [object({
45946
+ ok: literal(true),
45947
+ key: string()
45948
+ }), BoardKeyFailureSchema]);
45949
+ method(_void(), array(BoardKeySourceSchema).readonly(), { auth: "admin" }), method(object({ sourceId: string().min(1) }), ListBoardsResultSchema, { auth: "admin" }), method(object({
45950
+ sourceId: string().min(1),
45951
+ configuration: string().min(1)
45952
+ }), GetBoardKeyResultSchema, { auth: "admin" });
45953
+ /**
45750
45954
  * Dimmable-light brightness control. Co-exists with `switch` on the
45751
45955
  * same device — the switch toggles on/off, this cap sets the level
45752
45956
  * applied when the light is on. Drivers map their per-vendor dim
@@ -48490,6 +48694,244 @@ var controlCapability = {
48490
48694
  */
48491
48695
  history: "none"
48492
48696
  };
48697
+ /**
48698
+ * Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
48699
+ * Apple TV, Spotify, Roku, generic OTT receivers, …) on
48700
+ * `DeviceType.MediaPlayer`. Disjoint from the camera streaming
48701
+ * surface — those use `DeviceType.Camera` + the broker pipeline.
48702
+ *
48703
+ * The cap declares a wide method surface; not every backend supports
48704
+ * every method. Drivers signal sub-capability via the
48705
+ * `DeviceFeature.MediaPlayerXxx` flags (paired one-to-one with the
48706
+ * corresponding method) so the UI gates buttons without a slice
48707
+ * fetch — same pattern as `PanTiltZoom` for cameras.
48708
+ */
48709
+ var MediaPlayerStateSchema = _enum([
48710
+ "off",
48711
+ "on",
48712
+ "idle",
48713
+ "playing",
48714
+ "paused",
48715
+ "buffering",
48716
+ "standby"
48717
+ ]);
48718
+ var MediaPlayerRepeatSchema = _enum([
48719
+ "off",
48720
+ "all",
48721
+ "one"
48722
+ ]);
48723
+ var MediaInfoSchema = object({
48724
+ /** Free-form media kind (`music`, `tvshow`, `movie`, `app`, `channel`,
48725
+ * `podcast`, …). */
48726
+ type: string(),
48727
+ /** Human-readable title. */
48728
+ title: string(),
48729
+ /** Optional artist / channel / station label. */
48730
+ artist: string().optional(),
48731
+ /** Optional album / season / show name. */
48732
+ album: string().optional(),
48733
+ /** Optional cover-art / thumbnail URL. */
48734
+ imageUrl: string().optional()
48735
+ });
48736
+ /**
48737
+ * Where `state`, `volumeLevel`, `isMuted` and `source` come from. `reported`:
48738
+ * the device said so. `assumed`: the driver has no feedback (infrared) and
48739
+ * tracks what it last SENT; it moves only after a send was accepted, and a
48740
+ * human at the real remote makes it wrong. A UI shows an assumed value as a
48741
+ * guess, never as a reading.
48742
+ */
48743
+ var MediaPlayerStateSourceSchema = _enum(["reported", "assumed"]);
48744
+ /** The fields of a media-player status a driver can only guess. */
48745
+ var MediaPlayerAssumedFieldSchema = _enum([
48746
+ "state",
48747
+ "volumeLevel",
48748
+ "isMuted",
48749
+ "source"
48750
+ ]);
48751
+ var MediaPlayerStatusSchema = object({
48752
+ /** Playback lifecycle state. */
48753
+ state: MediaPlayerStateSchema,
48754
+ /**
48755
+ * Whether the state fields are readings or the driver's own bookkeeping.
48756
+ * A slice written before this field existed parses as `reported`.
48757
+ */
48758
+ stateSource: MediaPlayerStateSourceSchema.default("reported"),
48759
+ /**
48760
+ * Which fields are the driver's own guess. `stateSource` is `assumed` when
48761
+ * this is not empty; a field not listed here is a reading even then (power
48762
+ * from a running-state source, mute guessed from the last send).
48763
+ */
48764
+ assumedFields: array(MediaPlayerAssumedFieldSchema).default([]),
48765
+ /** Volume as 0..100 inclusive. Null when the device has no volume
48766
+ * surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
48767
+ volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
48768
+ /** Mute toggle distinct from volume=0. Null when no mute surface.
48769
+ * Pair with `DeviceFeature.MediaPlayerMute`. */
48770
+ isMuted: boolean().nullable(),
48771
+ /** Active source / input. Empty when no source surface. */
48772
+ source: string(),
48773
+ /** Selectable sources. Empty when no source surface.
48774
+ * Pair with `DeviceFeature.MediaPlayerSelectSource`. */
48775
+ availableSources: array(string()),
48776
+ /** Currently-playing media info. Null when nothing is playing. */
48777
+ currentMedia: MediaInfoSchema.nullable(),
48778
+ /** Current playback position in ms. Null when not seekable or
48779
+ * nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
48780
+ position: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
48781
+ /** Total duration of the current media in ms. Null when unknown
48782
+ * (live stream) or nothing is playing. */
48783
+ duration: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
48784
+ /** Shuffle toggle. Null when no shuffle surface.
48785
+ * Pair with `DeviceFeature.MediaPlayerShuffle`. */
48786
+ shuffle: boolean().nullable(),
48787
+ /** Repeat mode. Null when no repeat surface.
48788
+ * Pair with `DeviceFeature.MediaPlayerRepeat`. */
48789
+ repeat: MediaPlayerRepeatSchema.nullable(),
48790
+ /** Ms epoch when the slice was last updated. */
48791
+ lastChangedAt: number()
48792
+ });
48793
+ var stepInput = object({
48794
+ deviceId: number().int().nonnegative(),
48795
+ /** How many presses: the caller's count (Alexa `volumeSteps`, `channelCount`). */
48796
+ steps: number().int().min(1).max(50).default(1)
48797
+ });
48798
+ var deviceOnly = object({ deviceId: number().int().nonnegative() });
48799
+ var mediaPlayerCapability = {
48800
+ name: "media-player",
48801
+ scope: "device",
48802
+ deviceNative: true,
48803
+ mode: "singleton",
48804
+ deviceTypes: [DeviceType.MediaPlayer],
48805
+ methods: {
48806
+ turnOn: method(deviceOnly, _void(), {
48807
+ kind: "mutation",
48808
+ auth: "protected"
48809
+ }),
48810
+ turnOff: method(deviceOnly, _void(), {
48811
+ kind: "mutation",
48812
+ auth: "protected"
48813
+ }),
48814
+ volumeUp: method(stepInput, _void(), {
48815
+ kind: "mutation",
48816
+ auth: "protected"
48817
+ }),
48818
+ volumeDown: method(stepInput, _void(), {
48819
+ kind: "mutation",
48820
+ auth: "protected"
48821
+ }),
48822
+ channelUp: method(stepInput, _void(), {
48823
+ kind: "mutation",
48824
+ auth: "protected"
48825
+ }),
48826
+ channelDown: method(stepInput, _void(), {
48827
+ kind: "mutation",
48828
+ auth: "protected"
48829
+ }),
48830
+ play: method(object({ deviceId: number().int().nonnegative() }), _void(), {
48831
+ kind: "mutation",
48832
+ auth: "protected"
48833
+ }),
48834
+ pause: method(object({ deviceId: number().int().nonnegative() }), _void(), {
48835
+ kind: "mutation",
48836
+ auth: "protected"
48837
+ }),
48838
+ stop: method(object({ deviceId: number().int().nonnegative() }), _void(), {
48839
+ kind: "mutation",
48840
+ auth: "protected"
48841
+ }),
48842
+ next: method(object({ deviceId: number().int().nonnegative() }), _void(), {
48843
+ kind: "mutation",
48844
+ auth: "protected"
48845
+ }),
48846
+ previous: method(object({ deviceId: number().int().nonnegative() }), _void(), {
48847
+ kind: "mutation",
48848
+ auth: "protected"
48849
+ }),
48850
+ seek: method(object({
48851
+ deviceId: number().int().nonnegative(),
48852
+ position: number().int().nonnegative()
48853
+ }), _void(), {
48854
+ kind: "mutation",
48855
+ auth: "protected"
48856
+ }),
48857
+ setVolume: method(object({
48858
+ deviceId: number().int().nonnegative(),
48859
+ volumeLevel: number().min(0).max(100)
48860
+ }), _void(), {
48861
+ kind: "mutation",
48862
+ auth: "protected"
48863
+ }),
48864
+ setMute: method(object({
48865
+ deviceId: number().int().nonnegative(),
48866
+ muted: boolean()
48867
+ }), _void(), {
48868
+ kind: "mutation",
48869
+ auth: "protected"
48870
+ }),
48871
+ setShuffle: method(object({
48872
+ deviceId: number().int().nonnegative(),
48873
+ shuffle: boolean()
48874
+ }), _void(), {
48875
+ kind: "mutation",
48876
+ auth: "protected"
48877
+ }),
48878
+ setRepeat: method(object({
48879
+ deviceId: number().int().nonnegative(),
48880
+ repeat: MediaPlayerRepeatSchema
48881
+ }), _void(), {
48882
+ kind: "mutation",
48883
+ auth: "protected"
48884
+ }),
48885
+ selectSource: method(object({
48886
+ deviceId: number().int().nonnegative(),
48887
+ source: string().min(1)
48888
+ }), _void(), {
48889
+ kind: "mutation",
48890
+ auth: "protected"
48891
+ }),
48892
+ playMedia: method(object({
48893
+ deviceId: number().int().nonnegative(),
48894
+ /** Media identifier / URL. */
48895
+ mediaId: string().min(1),
48896
+ /** Media kind (`music`, `tvshow`, `movie`, `app`, …) — provider
48897
+ * passes it through to the upstream service. */
48898
+ mediaType: string().min(1)
48899
+ }), _void(), {
48900
+ kind: "mutation",
48901
+ auth: "protected"
48902
+ })
48903
+ },
48904
+ status: {
48905
+ schema: MediaPlayerStatusSchema,
48906
+ kind: "push"
48907
+ },
48908
+ /**
48909
+ * Runtime-state slice — mirrored by the kernel. UI players read the
48910
+ * full slice for live now-playing, volume, and progress updates
48911
+ * without polling.
48912
+ */
48913
+ runtimeState: MediaPlayerStatusSchema,
48914
+ /**
48915
+ * Runtime-state durability: **session** — a restored transport position describes a playback that stopped when the hub did.
48916
+ *
48917
+ * See `RuntimeStateDurability`. Enforced by
48918
+ * `scripts/check-runtime-state-durability.ts`.
48919
+ */
48920
+ durability: "session",
48921
+ /**
48922
+ * History (D850): volume (a level an operator or an automation sets; the
48923
+ * default 10 s floor folds a slider drag into its end value) and mute.
48924
+ * `position` is not recorded: it moves continuously while playing.
48925
+ */
48926
+ history: { fields: {
48927
+ volumeLevel: {
48928
+ kind: "gauge",
48929
+ unit: "%",
48930
+ deadband: 1
48931
+ },
48932
+ isMuted: { kind: "boolean" }
48933
+ } }
48934
+ };
48493
48935
  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;
48494
48936
  var NUMBER = {
48495
48937
  kind: "fixed",
@@ -52433,7 +52875,7 @@ var DishwasherStatusSchema = object({
52433
52875
  /** Ms epoch of the last value received from the appliance; 0 = never. */
52434
52876
  lastFetchedAt: number()
52435
52877
  });
52436
- var DeviceIdSchema$1 = number().int().nonnegative();
52878
+ var DeviceIdSchema$2 = number().int().nonnegative();
52437
52879
  /** A value a program option or setting can take. */
52438
52880
  var DishwasherValueSchema = union([
52439
52881
  boolean(),
@@ -52508,77 +52950,77 @@ var dishwasherCapability = {
52508
52950
  * option feature keys; each is checked against the program's constraints.
52509
52951
  */
52510
52952
  start: method(object({
52511
- deviceId: DeviceIdSchema$1,
52953
+ deviceId: DeviceIdSchema$2,
52512
52954
  program: string().min(1).optional(),
52513
52955
  options: record(string(), DishwasherValueSchema).optional()
52514
52956
  }), _void(), {
52515
52957
  kind: "mutation",
52516
52958
  auth: "protected"
52517
52959
  }),
52518
- pause: method(object({ deviceId: DeviceIdSchema$1 }), _void(), {
52960
+ pause: method(object({ deviceId: DeviceIdSchema$2 }), _void(), {
52519
52961
  kind: "mutation",
52520
52962
  auth: "protected"
52521
52963
  }),
52522
- resume: method(object({ deviceId: DeviceIdSchema$1 }), _void(), {
52964
+ resume: method(object({ deviceId: DeviceIdSchema$2 }), _void(), {
52523
52965
  kind: "mutation",
52524
52966
  auth: "protected"
52525
52967
  }),
52526
- stop: method(object({ deviceId: DeviceIdSchema$1 }), _void(), {
52968
+ stop: method(object({ deviceId: DeviceIdSchema$2 }), _void(), {
52527
52969
  kind: "mutation",
52528
52970
  auth: "protected"
52529
52971
  }),
52530
52972
  /** Select (not start) a program; refused when the appliance does not offer it. */
52531
52973
  setProgram: method(object({
52532
- deviceId: DeviceIdSchema$1,
52974
+ deviceId: DeviceIdSchema$2,
52533
52975
  program: string().min(1)
52534
52976
  }), _void(), {
52535
52977
  kind: "mutation",
52536
52978
  auth: "protected"
52537
52979
  }),
52538
52980
  setPower: method(object({
52539
- deviceId: DeviceIdSchema$1,
52981
+ deviceId: DeviceIdSchema$2,
52540
52982
  on: boolean()
52541
52983
  }), _void(), {
52542
52984
  kind: "mutation",
52543
52985
  auth: "protected"
52544
52986
  }),
52545
52987
  setHalfLoad: method(object({
52546
- deviceId: DeviceIdSchema$1,
52988
+ deviceId: DeviceIdSchema$2,
52547
52989
  on: boolean()
52548
52990
  }), _void(), {
52549
52991
  kind: "mutation",
52550
52992
  auth: "protected"
52551
52993
  }),
52552
52994
  setHygienePlus: method(object({
52553
- deviceId: DeviceIdSchema$1,
52995
+ deviceId: DeviceIdSchema$2,
52554
52996
  on: boolean()
52555
52997
  }), _void(), {
52556
52998
  kind: "mutation",
52557
52999
  auth: "protected"
52558
53000
  }),
52559
53001
  setExtraDry: method(object({
52560
- deviceId: DeviceIdSchema$1,
53002
+ deviceId: DeviceIdSchema$2,
52561
53003
  on: boolean()
52562
53004
  }), _void(), {
52563
53005
  kind: "mutation",
52564
53006
  auth: "protected"
52565
53007
  }),
52566
53008
  setIntensiveZone: method(object({
52567
- deviceId: DeviceIdSchema$1,
53009
+ deviceId: DeviceIdSchema$2,
52568
53010
  on: boolean()
52569
53011
  }), _void(), {
52570
53012
  kind: "mutation",
52571
53013
  auth: "protected"
52572
53014
  }),
52573
53015
  setVarioSpeedPlus: method(object({
52574
- deviceId: DeviceIdSchema$1,
53016
+ deviceId: DeviceIdSchema$2,
52575
53017
  on: boolean()
52576
53018
  }), _void(), {
52577
53019
  kind: "mutation",
52578
53020
  auth: "protected"
52579
53021
  }),
52580
53022
  setChildLock: method(object({
52581
- deviceId: DeviceIdSchema$1,
53023
+ deviceId: DeviceIdSchema$2,
52582
53024
  on: boolean()
52583
53025
  }), _void(), {
52584
53026
  kind: "mutation",
@@ -52590,7 +53032,7 @@ var dishwasherCapability = {
52590
53032
  * its declared range / members.
52591
53033
  */
52592
53034
  setOption: method(object({
52593
- deviceId: DeviceIdSchema$1,
53035
+ deviceId: DeviceIdSchema$2,
52594
53036
  key: string().min(1),
52595
53037
  value: DishwasherValueSchema
52596
53038
  }), _void(), {
@@ -52598,7 +53040,7 @@ var dishwasherCapability = {
52598
53040
  auth: "protected"
52599
53041
  }),
52600
53042
  /** What this appliance can do, from its own description — the UI is derived from it. */
52601
- getOptions: method(object({ deviceId: DeviceIdSchema$1 }), DishwasherOptionsSchema, { auth: "protected" })
53043
+ getOptions: method(object({ deviceId: DeviceIdSchema$2 }), DishwasherOptionsSchema, { auth: "protected" })
52602
53044
  },
52603
53045
  status: {
52604
53046
  schema: DishwasherStatusSchema,
@@ -54963,6 +55405,11 @@ var IntegrationInstanceSchema = object({
54963
55405
  name: string(),
54964
55406
  /** The addon's own rule (an URL is present, a client id is present...). */
54965
55407
  configured: boolean(),
55408
+ /**
55409
+ * The instance's own on/off switch (D996): always present, derived from the record body
55410
+ * (`enabled !== false`, so a row written before the field existed is on).
55411
+ */
55412
+ enabled: boolean(),
54966
55413
  /** Values for the instance form; a secret is a `SecretFieldView`, never text. */
54967
55414
  formValues: record(string(), unknown()),
54968
55415
  status: IntegrationInstanceStatusSchema.optional()
@@ -54982,6 +55429,12 @@ method(_void(), IntegrationInstanceDescriptionSchema, { auth: "admin" }), method
54982
55429
  }), method(IntegrationInstancePatchSchema, object({ ok: literal(true) }), {
54983
55430
  kind: "mutation",
54984
55431
  auth: "admin"
55432
+ }), method(object({
55433
+ id: IntegrationInstanceIdSchema,
55434
+ enabled: boolean()
55435
+ }), object({ ok: literal(true) }), {
55436
+ kind: "mutation",
55437
+ auth: "admin"
54985
55438
  }), method(object({ id: IntegrationInstanceIdSchema }), object({ ok: literal(true) }), {
54986
55439
  kind: "mutation",
54987
55440
  auth: "admin"
@@ -57193,214 +57646,6 @@ var LoginMethodContributionSchema = discriminatedUnion("kind", [
57193
57646
  ]);
57194
57647
  method(_void(), array(LoginMethodContributionSchema).readonly());
57195
57648
  /**
57196
- * Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
57197
- * Apple TV, Spotify, Roku, generic OTT receivers, …) on
57198
- * `DeviceType.MediaPlayer`. Disjoint from the camera streaming
57199
- * surface — those use `DeviceType.Camera` + the broker pipeline.
57200
- *
57201
- * The cap declares a wide method surface; not every backend supports
57202
- * every method. Drivers signal sub-capability via the
57203
- * `DeviceFeature.MediaPlayerXxx` flags (paired one-to-one with the
57204
- * corresponding method) so the UI gates buttons without a slice
57205
- * fetch — same pattern as `PanTiltZoom` for cameras.
57206
- */
57207
- var MediaPlayerStateSchema = _enum([
57208
- "off",
57209
- "on",
57210
- "idle",
57211
- "playing",
57212
- "paused",
57213
- "buffering",
57214
- "standby"
57215
- ]);
57216
- var MediaPlayerRepeatSchema = _enum([
57217
- "off",
57218
- "all",
57219
- "one"
57220
- ]);
57221
- var MediaInfoSchema = object({
57222
- /** Free-form media kind (`music`, `tvshow`, `movie`, `app`, `channel`,
57223
- * `podcast`, …). */
57224
- type: string(),
57225
- /** Human-readable title. */
57226
- title: string(),
57227
- /** Optional artist / channel / station label. */
57228
- artist: string().optional(),
57229
- /** Optional album / season / show name. */
57230
- album: string().optional(),
57231
- /** Optional cover-art / thumbnail URL. */
57232
- imageUrl: string().optional()
57233
- });
57234
- /**
57235
- * Where `state`, `volumeLevel`, `isMuted` and `source` come from. `reported`:
57236
- * the device said so. `assumed`: the driver has no feedback (infrared) and
57237
- * tracks what it last SENT; it moves only after a send was accepted, and a
57238
- * human at the real remote makes it wrong. A UI shows an assumed value as a
57239
- * guess, never as a reading.
57240
- */
57241
- var MediaPlayerStateSourceSchema = _enum(["reported", "assumed"]);
57242
- /** The fields of a media-player status a driver can only guess. */
57243
- var MediaPlayerAssumedFieldSchema = _enum([
57244
- "state",
57245
- "volumeLevel",
57246
- "isMuted",
57247
- "source"
57248
- ]);
57249
- var MediaPlayerStatusSchema = object({
57250
- /** Playback lifecycle state. */
57251
- state: MediaPlayerStateSchema,
57252
- /**
57253
- * Whether the state fields are readings or the driver's own bookkeeping.
57254
- * A slice written before this field existed parses as `reported`.
57255
- */
57256
- stateSource: MediaPlayerStateSourceSchema.default("reported"),
57257
- /**
57258
- * Which fields are the driver's own guess. `stateSource` is `assumed` when
57259
- * this is not empty; a field not listed here is a reading even then (power
57260
- * from a running-state source, mute guessed from the last send).
57261
- */
57262
- assumedFields: array(MediaPlayerAssumedFieldSchema).default([]),
57263
- /** Volume as 0..100 inclusive. Null when the device has no volume
57264
- * surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
57265
- volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
57266
- /** Mute toggle distinct from volume=0. Null when no mute surface.
57267
- * Pair with `DeviceFeature.MediaPlayerMute`. */
57268
- isMuted: boolean().nullable(),
57269
- /** Active source / input. Empty when no source surface. */
57270
- source: string(),
57271
- /** Selectable sources. Empty when no source surface.
57272
- * Pair with `DeviceFeature.MediaPlayerSelectSource`. */
57273
- availableSources: array(string()),
57274
- /** Currently-playing media info. Null when nothing is playing. */
57275
- currentMedia: MediaInfoSchema.nullable(),
57276
- /** Current playback position in ms. Null when not seekable or
57277
- * nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
57278
- position: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
57279
- /** Total duration of the current media in ms. Null when unknown
57280
- * (live stream) or nothing is playing. */
57281
- duration: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
57282
- /** Shuffle toggle. Null when no shuffle surface.
57283
- * Pair with `DeviceFeature.MediaPlayerShuffle`. */
57284
- shuffle: boolean().nullable(),
57285
- /** Repeat mode. Null when no repeat surface.
57286
- * Pair with `DeviceFeature.MediaPlayerRepeat`. */
57287
- repeat: MediaPlayerRepeatSchema.nullable(),
57288
- /** Ms epoch when the slice was last updated. */
57289
- lastChangedAt: number()
57290
- });
57291
- var mediaPlayerCapability = {
57292
- name: "media-player",
57293
- scope: "device",
57294
- deviceNative: true,
57295
- mode: "singleton",
57296
- deviceTypes: [DeviceType.MediaPlayer],
57297
- methods: {
57298
- play: method(object({ deviceId: number().int().nonnegative() }), _void(), {
57299
- kind: "mutation",
57300
- auth: "protected"
57301
- }),
57302
- pause: method(object({ deviceId: number().int().nonnegative() }), _void(), {
57303
- kind: "mutation",
57304
- auth: "protected"
57305
- }),
57306
- stop: method(object({ deviceId: number().int().nonnegative() }), _void(), {
57307
- kind: "mutation",
57308
- auth: "protected"
57309
- }),
57310
- next: method(object({ deviceId: number().int().nonnegative() }), _void(), {
57311
- kind: "mutation",
57312
- auth: "protected"
57313
- }),
57314
- previous: method(object({ deviceId: number().int().nonnegative() }), _void(), {
57315
- kind: "mutation",
57316
- auth: "protected"
57317
- }),
57318
- seek: method(object({
57319
- deviceId: number().int().nonnegative(),
57320
- position: number().int().nonnegative()
57321
- }), _void(), {
57322
- kind: "mutation",
57323
- auth: "protected"
57324
- }),
57325
- setVolume: method(object({
57326
- deviceId: number().int().nonnegative(),
57327
- volumeLevel: number().min(0).max(100)
57328
- }), _void(), {
57329
- kind: "mutation",
57330
- auth: "protected"
57331
- }),
57332
- setMute: method(object({
57333
- deviceId: number().int().nonnegative(),
57334
- muted: boolean()
57335
- }), _void(), {
57336
- kind: "mutation",
57337
- auth: "protected"
57338
- }),
57339
- setShuffle: method(object({
57340
- deviceId: number().int().nonnegative(),
57341
- shuffle: boolean()
57342
- }), _void(), {
57343
- kind: "mutation",
57344
- auth: "protected"
57345
- }),
57346
- setRepeat: method(object({
57347
- deviceId: number().int().nonnegative(),
57348
- repeat: MediaPlayerRepeatSchema
57349
- }), _void(), {
57350
- kind: "mutation",
57351
- auth: "protected"
57352
- }),
57353
- selectSource: method(object({
57354
- deviceId: number().int().nonnegative(),
57355
- source: string().min(1)
57356
- }), _void(), {
57357
- kind: "mutation",
57358
- auth: "protected"
57359
- }),
57360
- playMedia: method(object({
57361
- deviceId: number().int().nonnegative(),
57362
- /** Media identifier / URL. */
57363
- mediaId: string().min(1),
57364
- /** Media kind (`music`, `tvshow`, `movie`, `app`, …) — provider
57365
- * passes it through to the upstream service. */
57366
- mediaType: string().min(1)
57367
- }), _void(), {
57368
- kind: "mutation",
57369
- auth: "protected"
57370
- })
57371
- },
57372
- status: {
57373
- schema: MediaPlayerStatusSchema,
57374
- kind: "push"
57375
- },
57376
- /**
57377
- * Runtime-state slice — mirrored by the kernel. UI players read the
57378
- * full slice for live now-playing, volume, and progress updates
57379
- * without polling.
57380
- */
57381
- runtimeState: MediaPlayerStatusSchema,
57382
- /**
57383
- * Runtime-state durability: **session** — a restored transport position describes a playback that stopped when the hub did.
57384
- *
57385
- * See `RuntimeStateDurability`. Enforced by
57386
- * `scripts/check-runtime-state-durability.ts`.
57387
- */
57388
- durability: "session",
57389
- /**
57390
- * History (D850): volume (a level an operator or an automation sets; the
57391
- * default 10 s floor folds a slider drag into its end value) and mute.
57392
- * `position` is not recorded: it moves continuously while playing.
57393
- */
57394
- history: { fields: {
57395
- volumeLevel: {
57396
- kind: "gauge",
57397
- unit: "%",
57398
- deadband: 1
57399
- },
57400
- isMuted: { kind: "boolean" }
57401
- } }
57402
- };
57403
- /**
57404
57649
  * mesh-network — collection cap for mesh-VPN providers.
57405
57650
  *
57406
57651
  * Different shape from `network-access` (public tunnels):
@@ -66159,6 +66404,21 @@ var NcTemplateVarKindSchema = _enum([
66159
66404
  "sound",
66160
66405
  "system"
66161
66406
  ]);
66407
+ /**
66408
+ * The default title/body a rule of one SITUATION is delivered with when the
66409
+ * operator wrote no template — served so an editor can pre-fill it (and the
66410
+ * operator can rebuild it from placeholders) instead of starting from a blank
66411
+ * box that, once saved, silently replaces it. `id` names the situation inside
66412
+ * a rule `kind`: `appliance-cycle` is a `sensor` rule whose device is an
66413
+ * appliance finishing a cycle. Texts are raw templates (`{{var}}` intact), in
66414
+ * the hub's current language and with its overrides applied.
66415
+ */
66416
+ var NcTemplateDefaultSchema = object({
66417
+ id: _enum(["appliance-cycle"]),
66418
+ kind: NcRuleKindSchema,
66419
+ title: string(),
66420
+ body: string()
66421
+ });
66162
66422
  /** Which producer renders a template: an ordinary rule, a timelapse, a digest. */
66163
66423
  var NcTemplateFamilySchema = _enum([
66164
66424
  "rule",
@@ -67014,7 +67274,11 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
67014
67274
  }), method(object({}), object({
67015
67275
  catalog: array(NcConditionDescriptorSchema),
67016
67276
  taxonomy: NcTaxonomySchema.optional()
67017
- })), method(object({}), object({ vars: array(NcTemplateVarDescriptorSchema) })), method(NcTemplatePreviewInputSchema, NcTemplatePreviewSchema, {
67277
+ })), method(object({}), object({
67278
+ vars: array(NcTemplateVarDescriptorSchema),
67279
+ /** Per-situation default texts; absent on a hub that predates them. */
67280
+ defaults: array(NcTemplateDefaultSchema)
67281
+ })), method(NcTemplatePreviewInputSchema, NcTemplatePreviewSchema, {
67018
67282
  kind: "mutation",
67019
67283
  access: "view"
67020
67284
  }), 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 }), {
@@ -67910,7 +68174,7 @@ var petFeederCapability = {
67910
68174
  /**
67911
68175
  * Pet water-fountain cap. Models the telemetry and the control surface of a
67912
68176
  * circulating drinking fountain: how much water is in the tank, how much the
67913
- * pet drank, whether the pump runs and on what duty cycle.
68177
+ * pet drank, whether the pump runs.
67914
68178
  *
67915
68179
  * It has no native vendor provider of its own: a fountain reaches CamStack as
67916
68180
  * a container of loose entities (a pump switch, two number boxes, a "filter
@@ -67926,8 +68190,10 @@ var petFeederCapability = {
67926
68190
  * never here. Every reading may be `null`: a source that is offline or does
67927
68191
  * not report is unknown, never zero.
67928
68192
  *
67929
- * The filter is not a field of this cap: it is an item of the `consumables`
67930
- * cap on the same device (kind `wear`), reset by the same forward mechanism.
68193
+ * The pump's on/off duty cycle is model-specific and lives in the optional
68194
+ * `pump-cycle` cap. The filter, the cleaning and the water change are not
68195
+ * fields of this cap: they are items of the `consumables` cap on the same
68196
+ * device (kind `wear`), reset by the same forward mechanism.
67931
68197
  */
67932
68198
  var PetFountainStatusSchema = object({
67933
68199
  /** Water in the tank, 0..100 (%). Null while the source has not reported. */
@@ -67938,27 +68204,20 @@ var PetFountainStatusSchema = object({
67938
68204
  empty: boolean().nullable(),
67939
68205
  /** True while the pump is running. Null while unknown. */
67940
68206
  pumpRunning: boolean().nullable(),
67941
- /** True when the pump works on an on/off duty cycle rather than continuously. */
67942
- pumpIntervalEnabled: boolean().nullable(),
67943
- /** How long the pump runs per cycle, in seconds. */
67944
- pumpOnTime: number().min(0).nullable().meta(readingMeta("duration")),
67945
- /** How long the pump rests per cycle, in seconds. */
67946
- pumpOffTime: number().min(0).nullable().meta(readingMeta("duration")),
67947
68207
  /** Water drunk in the last drink, in litres. */
67948
68208
  lastDrink: number().min(0).nullable().meta(readingMeta("volume")),
67949
68209
  /** Water drunk in the current hour, in litres. */
67950
68210
  currentHourDrink: number().min(0).nullable().meta(readingMeta("volume")),
67951
68211
  /** Water drunk over the last 24 hours (rolling), in litres. */
67952
68212
  last24hDrink: number().min(0).nullable().meta(readingMeta("volume")),
67953
- /** Water drunk since local midnight, in litres. */
68213
+ /** Water drunk since local midnight, in litres. Null when the fountain has no such sensor. */
67954
68214
  todayDrink: number().min(0).nullable().meta(readingMeta("volume")),
67955
68215
  /** Decoded fault message. Null means healthy; a non-null string is an active fault. */
67956
68216
  error: string().nullable(),
67957
68217
  /** Ms epoch when the slice was last refreshed. */
67958
68218
  lastFetchedAt: number()
67959
68219
  });
67960
- var DeviceIdSchema = number().int().nonnegative();
67961
- var MinutesSchema = number().int().min(0);
68220
+ var DeviceIdSchema$1 = number().int().nonnegative();
67962
68221
  var petFountainCapability = {
67963
68222
  name: "pet-fountain",
67964
68223
  scope: "device",
@@ -67968,38 +68227,14 @@ var petFountainCapability = {
67968
68227
  methods: {
67969
68228
  /** Start or stop the pump. */
67970
68229
  setPump: method(object({
67971
- deviceId: DeviceIdSchema,
67972
- on: boolean()
67973
- }), _void(), {
67974
- kind: "mutation",
67975
- auth: "protected"
67976
- }),
67977
- /** Switch the on/off duty cycle on or off (off = the pump runs continuously). */
67978
- setPumpInterval: method(object({
67979
- deviceId: DeviceIdSchema,
68230
+ deviceId: DeviceIdSchema$1,
67980
68231
  on: boolean()
67981
68232
  }), _void(), {
67982
68233
  kind: "mutation",
67983
68234
  auth: "protected"
67984
68235
  }),
67985
- /** Set how many minutes the pump runs per cycle. */
67986
- setPumpOnMinutes: method(object({
67987
- deviceId: DeviceIdSchema,
67988
- minutes: MinutesSchema
67989
- }), _void(), {
67990
- kind: "mutation",
67991
- auth: "protected"
67992
- }),
67993
- /** Set how many minutes the pump rests per cycle. */
67994
- setPumpOffMinutes: method(object({
67995
- deviceId: DeviceIdSchema,
67996
- minutes: MinutesSchema
67997
- }), _void(), {
67998
- kind: "mutation",
67999
- auth: "protected"
68000
- }),
68001
68236
  /** Clear the rolling daily consumption counters on the device. */
68002
- resetDailyConsumption: method(object({ deviceId: DeviceIdSchema }), _void(), {
68237
+ resetDailyConsumption: method(object({ deviceId: DeviceIdSchema$1 }), _void(), {
68003
68238
  kind: "mutation",
68004
68239
  auth: "protected"
68005
68240
  })
@@ -70333,6 +70568,79 @@ var ptzAutotrackCapability = {
70333
70568
  history: "none"
70334
70569
  };
70335
70570
  /**
70571
+ * The on/off duty cycle of a pet fountain's pump. Some models run the pump
70572
+ * continuously and have nothing to configure; others can alternate a run time
70573
+ * and a rest time. That is model-specific, so it is its own optional cap on the
70574
+ * fountain device: a fountain without cycle entities simply never composes it
70575
+ * (planning#366), and the `pet-fountain` cap stays the model-independent core.
70576
+ *
70577
+ * Like `pet-fountain` it has no native vendor provider: an operator BUILDS the
70578
+ * cycle from loose entities (a cycle switch and two number boxes) and every
70579
+ * method is a forward to one source entity (D659, D967). Durations are stored
70580
+ * in SECONDS (D944); a number box that cannot be read back leaves them `null`
70581
+ * — unknown, never zero (D393).
70582
+ */
70583
+ var PumpCycleStatusSchema = object({
70584
+ /** True when the pump works on the on/off cycle, false when it runs continuously. Null while unknown. */
70585
+ enabled: boolean().nullable(),
70586
+ /** How long the pump runs per cycle, in seconds. Null while unknown. */
70587
+ onTime: number().min(0).nullable().meta(readingMeta("duration")),
70588
+ /** How long the pump rests per cycle, in seconds. Null while unknown. */
70589
+ offTime: number().min(0).nullable().meta(readingMeta("duration")),
70590
+ /** Ms epoch when the slice was last refreshed. */
70591
+ lastFetchedAt: number()
70592
+ });
70593
+ var DeviceIdSchema = number().int().nonnegative();
70594
+ var MinutesSchema = number().int().min(0);
70595
+ var pumpCycleCapability = {
70596
+ name: "pump-cycle",
70597
+ scope: "device",
70598
+ deviceNative: true,
70599
+ mode: "singleton",
70600
+ deviceTypes: [DeviceType.PetFountain],
70601
+ methods: {
70602
+ /** Switch the on/off duty cycle on or off (off = the pump runs continuously). */
70603
+ setEnabled: method(object({
70604
+ deviceId: DeviceIdSchema,
70605
+ on: boolean()
70606
+ }), _void(), {
70607
+ kind: "mutation",
70608
+ auth: "protected"
70609
+ }),
70610
+ /** Set how many minutes the pump runs per cycle. */
70611
+ setOnMinutes: method(object({
70612
+ deviceId: DeviceIdSchema,
70613
+ minutes: MinutesSchema
70614
+ }), _void(), {
70615
+ kind: "mutation",
70616
+ auth: "protected"
70617
+ }),
70618
+ /** Set how many minutes the pump rests per cycle. */
70619
+ setOffMinutes: method(object({
70620
+ deviceId: DeviceIdSchema,
70621
+ minutes: MinutesSchema
70622
+ }), _void(), {
70623
+ kind: "mutation",
70624
+ auth: "protected"
70625
+ })
70626
+ },
70627
+ status: {
70628
+ schema: PumpCycleStatusSchema,
70629
+ kind: "push"
70630
+ },
70631
+ /** Runtime-state slice — mirrored by the kernel; the hero card reads it whole. */
70632
+ runtimeState: PumpCycleStatusSchema,
70633
+ /**
70634
+ * Runtime-state durability: **session** — live appliance state re-published on connect.
70635
+ *
70636
+ * See `RuntimeStateDurability`. Enforced by
70637
+ * `scripts/check-runtime-state-durability.ts`.
70638
+ */
70639
+ durability: "session",
70640
+ /** History (D850): a duty-cycle setting is not a series worth recording. */
70641
+ history: "none"
70642
+ };
70643
+ /**
70336
70644
  * reboot — device-scoped capability for "soft" device reboots (firmware
70337
70645
  * reboot via vendor protocol; cameras, NVRs, doorbells). Surfaces a
70338
70646
  * single mutation so the UI can offer a confirm-and-reboot button for
@@ -73148,7 +73456,13 @@ var RemoteMediaCommandSchema = _enum([
73148
73456
  "next",
73149
73457
  "previous",
73150
73458
  "setMute",
73151
- "selectSource"
73459
+ "selectSource",
73460
+ "turnOn",
73461
+ "turnOff",
73462
+ "volumeUp",
73463
+ "volumeDown",
73464
+ "channelUp",
73465
+ "channelDown"
73152
73466
  ]);
73153
73467
  /** A send result, or `not-routed`: the role is not bound, so the native cap answers. */
73154
73468
  var RemoteMediaCommandResultSchema = discriminatedUnion("status", [...RemoteSendResultSchema.options, object({ status: literal("not-routed") })]);
@@ -73169,7 +73483,7 @@ method(deviceInput, RemoteConfigSchema, { auth: "admin" }), method(deviceInput.e
73169
73483
  }), RemoteSendResultSchema, {
73170
73484
  kind: "mutation",
73171
73485
  auth: "protected"
73172
- }), method(deviceInput.extend({
73486
+ }), method(deviceInput, MediaPlayerStatusSchema.nullable(), { auth: "protected" }), method(deviceInput.extend({
73173
73487
  command: RemoteMediaCommandSchema,
73174
73488
  muted: boolean().optional(),
73175
73489
  source: string().optional(),
@@ -75415,7 +75729,11 @@ listSignals: method(_void(), array(StreamSignalSchema).readonly()) }
75415
75729
  * `getSettingsUISchema()` surface.
75416
75730
  */
75417
75731
  var SwitchStatusSchema = object({
75418
- on: boolean().meta({ label: "On" }),
75732
+ /**
75733
+ * `null` = the device has never reported its state (a measurement that
75734
+ * has not happened is unknown, never `false`).
75735
+ */
75736
+ on: boolean().nullable().meta({ label: "On" }),
75419
75737
  /** Ms epoch of the last state change. Useful for UI "X minutes ago". */
75420
75738
  lastChangedAt: number()
75421
75739
  });
@@ -75440,7 +75758,7 @@ var switchCapability = {
75440
75758
  }) },
75441
75759
  events: { onStateChanged: { data: object({
75442
75760
  deviceId: number(),
75443
- on: boolean(),
75761
+ on: boolean().nullable(),
75444
75762
  lastChangedAt: number()
75445
75763
  }) } },
75446
75764
  status: {
@@ -79089,6 +79407,7 @@ function buildDescriptor(capName, kind) {
79089
79407
  * contributes one entry per bound cap present in this map.
79090
79408
  */
79091
79409
  var EVENT_KIND_BY_CAP = Object.freeze(Object.fromEntries(Object.entries(CAP_TO_KIND).map(([capName, kind]) => [capName, buildDescriptor(capName, kind)])));
79410
+ DeviceFeature.MediaPlayerPower, DeviceFeature.MediaPlayerVolumeStep, DeviceFeature.MediaPlayerChannelStep, DeviceFeature.MediaPlayerMute, DeviceFeature.MediaPlayerStop, DeviceFeature.MediaPlayerNext, DeviceFeature.MediaPlayerPrevious;
79092
79411
  var btn = (idSuffix, row, col, init) => ({
79093
79412
  idSuffix,
79094
79413
  row,
@@ -79575,6 +79894,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
79575
79894
  pressureSensor: pressureSensorCapability,
79576
79895
  privacyMask: privacyMaskCapability,
79577
79896
  ptzAutotrack: ptzAutotrackCapability,
79897
+ pumpCycle: pumpCycleCapability,
79578
79898
  recordingOnboard: recordingOnboardCapability,
79579
79899
  recordingSignal: recordingSignalCapability,
79580
79900
  runningState: runningStateCapability,
@@ -81759,6 +82079,27 @@ Object.freeze({
81759
82079
  access: "view",
81760
82080
  role: "viewer"
81761
82081
  },
82082
+ "boardKeySource.getBoardKey": {
82083
+ capName: "board-key-source",
82084
+ capScope: "system",
82085
+ addonId: null,
82086
+ access: "view",
82087
+ role: "admin"
82088
+ },
82089
+ "boardKeySource.listBoards": {
82090
+ capName: "board-key-source",
82091
+ capScope: "system",
82092
+ addonId: null,
82093
+ access: "view",
82094
+ role: "admin"
82095
+ },
82096
+ "boardKeySource.listSources": {
82097
+ capName: "board-key-source",
82098
+ capScope: "system",
82099
+ addonId: null,
82100
+ access: "view",
82101
+ role: "admin"
82102
+ },
81762
82103
  "brightness.getStatus": {
81763
82104
  capName: "brightness",
81764
82105
  capScope: "device",
@@ -84440,6 +84781,13 @@ Object.freeze({
84440
84781
  access: "view",
84441
84782
  role: "admin"
84442
84783
  },
84784
+ "integrationInstances.setInstanceEnabled": {
84785
+ capName: "integration-instances",
84786
+ capScope: "system",
84787
+ addonId: null,
84788
+ access: "create",
84789
+ role: "admin"
84790
+ },
84443
84791
  "integrationInstances.testInstance": {
84444
84792
  capName: "integration-instances",
84445
84793
  capScope: "system",
@@ -85238,6 +85586,20 @@ Object.freeze({
85238
85586
  access: "view",
85239
85587
  role: "admin"
85240
85588
  },
85589
+ "mediaPlayer.channelDown": {
85590
+ capName: "media-player",
85591
+ capScope: "device",
85592
+ addonId: null,
85593
+ access: "create",
85594
+ role: "viewer"
85595
+ },
85596
+ "mediaPlayer.channelUp": {
85597
+ capName: "media-player",
85598
+ capScope: "device",
85599
+ addonId: null,
85600
+ access: "create",
85601
+ role: "viewer"
85602
+ },
85241
85603
  "mediaPlayer.getStatus": {
85242
85604
  capName: "media-player",
85243
85605
  capScope: "device",
@@ -85329,6 +85691,34 @@ Object.freeze({
85329
85691
  access: "create",
85330
85692
  role: "viewer"
85331
85693
  },
85694
+ "mediaPlayer.turnOff": {
85695
+ capName: "media-player",
85696
+ capScope: "device",
85697
+ addonId: null,
85698
+ access: "create",
85699
+ role: "viewer"
85700
+ },
85701
+ "mediaPlayer.turnOn": {
85702
+ capName: "media-player",
85703
+ capScope: "device",
85704
+ addonId: null,
85705
+ access: "create",
85706
+ role: "viewer"
85707
+ },
85708
+ "mediaPlayer.volumeDown": {
85709
+ capName: "media-player",
85710
+ capScope: "device",
85711
+ addonId: null,
85712
+ access: "create",
85713
+ role: "viewer"
85714
+ },
85715
+ "mediaPlayer.volumeUp": {
85716
+ capName: "media-player",
85717
+ capScope: "device",
85718
+ addonId: null,
85719
+ access: "create",
85720
+ role: "viewer"
85721
+ },
85332
85722
  "meshNetwork.getStatus": {
85333
85723
  capName: "mesh-network",
85334
85724
  capScope: "system",
@@ -86575,27 +86965,6 @@ Object.freeze({
86575
86965
  access: "create",
86576
86966
  role: "viewer"
86577
86967
  },
86578
- "petFountain.setPumpInterval": {
86579
- capName: "pet-fountain",
86580
- capScope: "device",
86581
- addonId: null,
86582
- access: "create",
86583
- role: "viewer"
86584
- },
86585
- "petFountain.setPumpOffMinutes": {
86586
- capName: "pet-fountain",
86587
- capScope: "device",
86588
- addonId: null,
86589
- access: "create",
86590
- role: "viewer"
86591
- },
86592
- "petFountain.setPumpOnMinutes": {
86593
- capName: "pet-fountain",
86594
- capScope: "device",
86595
- addonId: null,
86596
- access: "create",
86597
- role: "viewer"
86598
- },
86599
86968
  "pipelineAnalytics.addRetrainFrameFromRecording": {
86600
86969
  capName: "pipeline-analytics",
86601
86970
  capScope: "device",
@@ -88374,6 +88743,34 @@ Object.freeze({
88374
88743
  access: "create",
88375
88744
  role: "admin"
88376
88745
  },
88746
+ "pumpCycle.getStatus": {
88747
+ capName: "pump-cycle",
88748
+ capScope: "device",
88749
+ addonId: null,
88750
+ access: "view",
88751
+ role: "viewer"
88752
+ },
88753
+ "pumpCycle.setEnabled": {
88754
+ capName: "pump-cycle",
88755
+ capScope: "device",
88756
+ addonId: null,
88757
+ access: "create",
88758
+ role: "viewer"
88759
+ },
88760
+ "pumpCycle.setOffMinutes": {
88761
+ capName: "pump-cycle",
88762
+ capScope: "device",
88763
+ addonId: null,
88764
+ access: "create",
88765
+ role: "viewer"
88766
+ },
88767
+ "pumpCycle.setOnMinutes": {
88768
+ capName: "pump-cycle",
88769
+ capScope: "device",
88770
+ addonId: null,
88771
+ access: "create",
88772
+ role: "viewer"
88773
+ },
88377
88774
  "reboot.reboot": {
88378
88775
  capName: "reboot",
88379
88776
  capScope: "device",
@@ -88878,6 +89275,13 @@ Object.freeze({
88878
89275
  access: "create",
88879
89276
  role: "admin"
88880
89277
  },
89278
+ "remote.getAssumedStatus": {
89279
+ capName: "remote",
89280
+ capScope: "system",
89281
+ addonId: null,
89282
+ access: "view",
89283
+ role: "admin"
89284
+ },
88881
89285
  "remote.getConfig": {
88882
89286
  capName: "remote",
88883
89287
  capScope: "system",
@@ -92544,6 +92948,16 @@ Object.freeze({
92544
92948
  form: "single",
92545
92949
  optional: true
92546
92950
  }],
92951
+ "mediaPlayer.channelDown": [{
92952
+ name: "deviceId",
92953
+ form: "single",
92954
+ optional: false
92955
+ }],
92956
+ "mediaPlayer.channelUp": [{
92957
+ name: "deviceId",
92958
+ form: "single",
92959
+ optional: false
92960
+ }],
92547
92961
  "mediaPlayer.getStatus": [{
92548
92962
  name: "deviceId",
92549
92963
  form: "single",
@@ -92609,6 +93023,26 @@ Object.freeze({
92609
93023
  form: "single",
92610
93024
  optional: false
92611
93025
  }],
93026
+ "mediaPlayer.turnOff": [{
93027
+ name: "deviceId",
93028
+ form: "single",
93029
+ optional: false
93030
+ }],
93031
+ "mediaPlayer.turnOn": [{
93032
+ name: "deviceId",
93033
+ form: "single",
93034
+ optional: false
93035
+ }],
93036
+ "mediaPlayer.volumeDown": [{
93037
+ name: "deviceId",
93038
+ form: "single",
93039
+ optional: false
93040
+ }],
93041
+ "mediaPlayer.volumeUp": [{
93042
+ name: "deviceId",
93043
+ form: "single",
93044
+ optional: false
93045
+ }],
92612
93046
  "meter.getStatus": [{
92613
93047
  name: "deviceId",
92614
93048
  form: "single",
@@ -92918,21 +93352,6 @@ Object.freeze({
92918
93352
  form: "single",
92919
93353
  optional: false
92920
93354
  }],
92921
- "petFountain.setPumpInterval": [{
92922
- name: "deviceId",
92923
- form: "single",
92924
- optional: false
92925
- }],
92926
- "petFountain.setPumpOffMinutes": [{
92927
- name: "deviceId",
92928
- form: "single",
92929
- optional: false
92930
- }],
92931
- "petFountain.setPumpOnMinutes": [{
92932
- name: "deviceId",
92933
- form: "single",
92934
- optional: false
92935
- }],
92936
93355
  "pipelineAnalytics.addRetrainFrameFromRecording": [{
92937
93356
  name: "deviceId",
92938
93357
  form: "single",
@@ -93568,6 +93987,26 @@ Object.freeze({
93568
93987
  form: "single",
93569
93988
  optional: false
93570
93989
  }],
93990
+ "pumpCycle.getStatus": [{
93991
+ name: "deviceId",
93992
+ form: "single",
93993
+ optional: false
93994
+ }],
93995
+ "pumpCycle.setEnabled": [{
93996
+ name: "deviceId",
93997
+ form: "single",
93998
+ optional: false
93999
+ }],
94000
+ "pumpCycle.setOffMinutes": [{
94001
+ name: "deviceId",
94002
+ form: "single",
94003
+ optional: false
94004
+ }],
94005
+ "pumpCycle.setOnMinutes": [{
94006
+ name: "deviceId",
94007
+ form: "single",
94008
+ optional: false
94009
+ }],
93571
94010
  "reboot.reboot": [{
93572
94011
  name: "deviceId",
93573
94012
  form: "single",
@@ -93769,6 +94208,11 @@ Object.freeze({
93769
94208
  form: "single",
93770
94209
  optional: true
93771
94210
  }],
94211
+ "remote.getAssumedStatus": [{
94212
+ name: "deviceId",
94213
+ form: "single",
94214
+ optional: false
94215
+ }],
93772
94216
  "remote.getConfig": [{
93773
94217
  name: "deviceId",
93774
94218
  form: "single",
@@ -95024,6 +95468,7 @@ var STATE_SUMMARY_VARS = [
95024
95468
  [...RULE_TEXT],
95025
95469
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
95026
95470
  ([...RULE_TEXT], [...COMBINED_ALARM]),
95471
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
95027
95472
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
95028
95473
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
95029
95474
  ([...RULE_TEXT], [...CONSUMABLE]),
@@ -96644,6 +97089,7 @@ var VeluxWindowDevice = class extends BaseDevice {
96644
97089
  stableIdSuffix: "rain",
96645
97090
  meta: {
96646
97091
  type: DeviceType.Sensor,
97092
+ role: DeviceRole.LeakSensor,
96647
97093
  name: `${this.name} rain`,
96648
97094
  ...link
96649
97095
  },