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