@camstack/addon-provider-homeassistant 1.2.653 → 1.2.655
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/addon.js +938 -540
- package/dist/addon.mjs +481 -86
- package/dist/ha-export/ha-export.addon.js +452 -160
- package/dist/ha-export/ha-export.addon.mjs +406 -114
- package/dist/{ha-broker-source-DnSL-mbs.js → ha-instance-settings-5Ms7yRju.js} +1402 -525
- package/dist/{ha-broker-source-CKdH9XHn.mjs → ha-instance-settings-DLDNOmgL.mjs} +1342 -525
- package/package.json +6 -2
|
@@ -785,7 +785,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
785
785
|
return EventCategory;
|
|
786
786
|
}({});
|
|
787
787
|
//#endregion
|
|
788
|
-
//#region ../types/dist/device-type-
|
|
788
|
+
//#region ../types/dist/device-type-D1fH5kaC.mjs
|
|
789
789
|
/**
|
|
790
790
|
import { errMsg } from '@camstack/types'
|
|
791
791
|
* Extract a human-readable message from an unknown error value.
|
|
@@ -1016,6 +1016,12 @@ var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
|
1016
1016
|
DeviceFeature["MediaPlayerPrevious"] = "media-player-previous";
|
|
1017
1017
|
/** Media player exposes stop distinct from pause. */
|
|
1018
1018
|
DeviceFeature["MediaPlayerStop"] = "media-player-stop";
|
|
1019
|
+
/** Media player exposes volume up / down in steps (an infrared TV has no level). */
|
|
1020
|
+
DeviceFeature["MediaPlayerVolumeStep"] = "media-player-volume-step";
|
|
1021
|
+
/** Media player exposes channel up / down in steps. */
|
|
1022
|
+
DeviceFeature["MediaPlayerChannelStep"] = "media-player-channel-step";
|
|
1023
|
+
/** Media player exposes power on / off. */
|
|
1024
|
+
DeviceFeature["MediaPlayerPower"] = "media-player-power";
|
|
1019
1025
|
/** Alarm panel requires a PIN code on arm/disarm. */
|
|
1020
1026
|
DeviceFeature["AlarmPinRequired"] = "alarm-pin-required";
|
|
1021
1027
|
/** Presence device carries GPS coordinates (lat/lng/accuracy) in
|
|
@@ -5975,7 +5981,7 @@ var ZodIssueCode = {
|
|
|
5975
5981
|
var ZodFirstPartyTypeKind;
|
|
5976
5982
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5977
5983
|
//#endregion
|
|
5978
|
-
//#region ../types/dist/sleep-
|
|
5984
|
+
//#region ../types/dist/sleep-BkzQdpzF.mjs
|
|
5979
5985
|
/**
|
|
5980
5986
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5981
5987
|
* window to float samples (D455).
|
|
@@ -6070,6 +6076,16 @@ var AddonMigrationsBlockedError = class extends Error {
|
|
|
6070
6076
|
this.migrationIds = migrationIds;
|
|
6071
6077
|
}
|
|
6072
6078
|
};
|
|
6079
|
+
/**
|
|
6080
|
+
* The value a redacted secret is replaced with on every read surface.
|
|
6081
|
+
*
|
|
6082
|
+
* It is also the WRITE-BACK token: an `upsertLocation` that sends this value
|
|
6083
|
+
* back for a key means "keep what is stored", which is what lets an operator
|
|
6084
|
+
* rename a location without retyping its password. A literal an operator could
|
|
6085
|
+
* plausibly choose as a real password would turn that convenience into a way
|
|
6086
|
+
* to lock yourself out, hence the sentinel shape.
|
|
6087
|
+
*/
|
|
6088
|
+
var REDACTED_SECRET = "__camstack_redacted__";
|
|
6073
6089
|
/** Is this field's stored value a credential? */
|
|
6074
6090
|
function isSecretConfigField(field) {
|
|
6075
6091
|
if (field.type === "password") return true;
|
|
@@ -6123,9 +6139,16 @@ function isSecretMarker(value) {
|
|
|
6123
6139
|
const ref = value["$secret"];
|
|
6124
6140
|
return typeof ref === "string" && ref.length > 0;
|
|
6125
6141
|
}
|
|
6142
|
+
/** Anything carrying a `$secret` key — a stored marker or a UI view of one. */
|
|
6143
|
+
function isSecretMarkerLike(value) {
|
|
6144
|
+
return isRecord$7(value) && Object.prototype.hasOwnProperty.call(value, "$secret");
|
|
6145
|
+
}
|
|
6126
6146
|
function isSecretClear(value) {
|
|
6127
6147
|
return isRecord$7(value) && value["$secretClear"] === true;
|
|
6128
6148
|
}
|
|
6149
|
+
function isSecretFieldView(value) {
|
|
6150
|
+
return isRecord$7(value) && value["set"] === true && isSecretMarkerLike(value);
|
|
6151
|
+
}
|
|
6129
6152
|
/**
|
|
6130
6153
|
* The UI view of a stored secret field value: a marker becomes "set", inline
|
|
6131
6154
|
* plaintext becomes "set (inline)", nothing becomes `null`. A value never
|
|
@@ -6775,11 +6798,36 @@ function projectStore(store, perNodeKeys, nodeId) {
|
|
|
6775
6798
|
}
|
|
6776
6799
|
return out;
|
|
6777
6800
|
}
|
|
6801
|
+
/**
|
|
6802
|
+
* The address of one keychain value: `secret://<owner>/<scope>/<fieldPath>`.
|
|
6803
|
+
*
|
|
6804
|
+
* A ref is DETERMINISTIC from where the value lives — the owner addon, the
|
|
6805
|
+
* scope (global, one node, one device, one integration, one row of a business
|
|
6806
|
+
* collection) and the field path inside that scope — so saving the same field
|
|
6807
|
+
* twice updates the same ref, and the ref itself says which settings blob
|
|
6808
|
+
* points at it. It is also the AAD of the value's ciphertext: a ciphertext
|
|
6809
|
+
* copied onto another ref does not decrypt.
|
|
6810
|
+
*
|
|
6811
|
+
* Array items are addressed by ITEM ID, never by index
|
|
6812
|
+
* (`providers[authentik].clientSecret`), so reordering a list keeps every ref.
|
|
6813
|
+
*
|
|
6814
|
+
* Pure and browser-safe: no node builtins, no I/O.
|
|
6815
|
+
*/
|
|
6816
|
+
/** The URI scheme of every keychain ref. */
|
|
6817
|
+
var SECRET_REF_SCHEME = "secret://";
|
|
6778
6818
|
var GLOBAL_SCOPE = { kind: "global" };
|
|
6779
6819
|
/** The scope every addon-wide (not per-node, not per-device) setting lives in. */
|
|
6780
6820
|
function globalSecretScope() {
|
|
6781
6821
|
return GLOBAL_SCOPE;
|
|
6782
6822
|
}
|
|
6823
|
+
/**
|
|
6824
|
+
* An addon id as a ref owner. A hub in-process builtin's context id is
|
|
6825
|
+
* `addon:<id>`; the owner of its secrets is `<id>`, exactly as for the same
|
|
6826
|
+
* addon running forked.
|
|
6827
|
+
*/
|
|
6828
|
+
function normalizeSecretOwner(addonId) {
|
|
6829
|
+
return addonId.startsWith("addon:") ? addonId.slice(6) : addonId;
|
|
6830
|
+
}
|
|
6783
6831
|
function encodeSegment(value) {
|
|
6784
6832
|
return encodeURIComponent(value);
|
|
6785
6833
|
}
|
|
@@ -6790,6 +6838,16 @@ function decodeSegment(value) {
|
|
|
6790
6838
|
return null;
|
|
6791
6839
|
}
|
|
6792
6840
|
}
|
|
6841
|
+
/** The scope as it appears inside a ref (`global`, `node/<id>`, …). */
|
|
6842
|
+
function formatSecretScope(scope) {
|
|
6843
|
+
switch (scope.kind) {
|
|
6844
|
+
case "global": return "global";
|
|
6845
|
+
case "node": return `node/${encodeSegment(scope.nodeId)}`;
|
|
6846
|
+
case "device": return `device/${scope.deviceId}`;
|
|
6847
|
+
case "integration": return `integration/${encodeSegment(scope.integrationId)}`;
|
|
6848
|
+
case "row": return `row/${encodeSegment(scope.collection)}/${encodeSegment(scope.rowId)}`;
|
|
6849
|
+
}
|
|
6850
|
+
}
|
|
6793
6851
|
/**
|
|
6794
6852
|
* The field path of a value inside an array item, addressed by the item's id:
|
|
6795
6853
|
* `arrayItemFieldPath('providers', 'authentik', 'clientSecret')` →
|
|
@@ -6798,6 +6856,13 @@ function decodeSegment(value) {
|
|
|
6798
6856
|
function arrayItemFieldPath(arrayKey, itemId, fieldKey) {
|
|
6799
6857
|
return `${arrayKey}[${encodeSegment(itemId)}].${fieldKey}`;
|
|
6800
6858
|
}
|
|
6859
|
+
/** Build a ref. Throws on an empty owner or field path — both are bugs. */
|
|
6860
|
+
function buildSecretRef(parts) {
|
|
6861
|
+
const owner = normalizeSecretOwner(parts.owner);
|
|
6862
|
+
if (owner.length === 0) throw new Error("buildSecretRef: owner is empty");
|
|
6863
|
+
if (parts.fieldPath.length === 0) throw new Error("buildSecretRef: fieldPath is empty");
|
|
6864
|
+
return `${SECRET_REF_SCHEME}${encodeSegment(owner)}/${formatSecretScope(parts.scope)}/${parts.fieldPath}`;
|
|
6865
|
+
}
|
|
6801
6866
|
function parseScope(segments) {
|
|
6802
6867
|
switch (segments[0]) {
|
|
6803
6868
|
case "global": return {
|
|
@@ -8063,6 +8128,10 @@ var BaseAddon = class {
|
|
|
8063
8128
|
const stored = keychain ? await this.readAddonStoreWithRetry() : {};
|
|
8064
8129
|
const patch = {};
|
|
8065
8130
|
for (const key of keys) {
|
|
8131
|
+
if (tree.get(key)?.kind === "array") {
|
|
8132
|
+
patch[key] = [];
|
|
8133
|
+
continue;
|
|
8134
|
+
}
|
|
8066
8135
|
const keychainStored = tree.has(key) || collectSecretMarkerRefs(stored[key]).length > 0;
|
|
8067
8136
|
patch[key] = keychain && keychainStored ? SECRET_CLEAR : "";
|
|
8068
8137
|
}
|
|
@@ -8751,6 +8820,8 @@ var RECORD_BATCH_MAX = 1e3;
|
|
|
8751
8820
|
var RECORD_QUERY_MAX = 1e3;
|
|
8752
8821
|
/** A kind in the `settings` file may not bound itself above this (D447: high volume is `events`). */
|
|
8753
8822
|
var RECORD_SETTINGS_MAX_ROWS = 5e4;
|
|
8823
|
+
/** The `Column`-free proof prefix: a ref collection for a kind's secret fields. */
|
|
8824
|
+
var RECORD_SECRET_COLLECTION_PREFIX = "records:";
|
|
8754
8825
|
/**
|
|
8755
8826
|
* Secret fields of a record, addressed the way a Zod schema declares them
|
|
8756
8827
|
* (`collectZodSecretPaths`): dotted keys, `[]` for "each element of this array"
|
|
@@ -8787,6 +8858,112 @@ function secretArrayPrefixes(path) {
|
|
|
8787
8858
|
}
|
|
8788
8859
|
return prefixes;
|
|
8789
8860
|
}
|
|
8861
|
+
function isRecord$4(value) {
|
|
8862
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8863
|
+
}
|
|
8864
|
+
function elementId(element, idKey, declared, prefix) {
|
|
8865
|
+
const id = isRecord$4(element) ? element[idKey] : void 0;
|
|
8866
|
+
if (typeof id !== "string" || id.length === 0) throw new InvalidRecordError(`"${declared}": every element of "${prefix}" needs a non-empty string "${idKey}" to carry a secret`);
|
|
8867
|
+
return id;
|
|
8868
|
+
}
|
|
8869
|
+
/**
|
|
8870
|
+
* Visit every secret leaf PRESENT in `data` (an absent branch has nothing to
|
|
8871
|
+
* visit). `replace` returns the new leaf value, or {@link REMOVE_LEAF}; the
|
|
8872
|
+
* result is a new body, `data` is untouched.
|
|
8873
|
+
*/
|
|
8874
|
+
var REMOVE_LEAF = Symbol("remove-leaf");
|
|
8875
|
+
function mapAt(node, segments, index, walkedKeys, concretePrefix, declared, arrayKeys, visit) {
|
|
8876
|
+
if (!isRecord$4(node)) return node;
|
|
8877
|
+
const segment = segments[index];
|
|
8878
|
+
if (segment === void 0) return node;
|
|
8879
|
+
if (!Object.prototype.hasOwnProperty.call(node, segment.key)) return node;
|
|
8880
|
+
const child = node[segment.key];
|
|
8881
|
+
const keys = [...walkedKeys, segment.key];
|
|
8882
|
+
const last = index === segments.length - 1;
|
|
8883
|
+
if (segment.each) {
|
|
8884
|
+
if (!Array.isArray(child)) return node;
|
|
8885
|
+
const prefix = keys.join(".");
|
|
8886
|
+
const idKey = arrayKeys[prefix];
|
|
8887
|
+
if (idKey === void 0) throw new InvalidRecordError(`"${declared}": no id key declared for the array "${prefix}"`);
|
|
8888
|
+
const mapped = child.map((element) => {
|
|
8889
|
+
const id = elementId(element, idKey, declared, prefix);
|
|
8890
|
+
const concrete = `${concretePrefix}${concretePrefix.length > 0 ? "." : ""}${segment.key}[${encodeURIComponent(id)}]`;
|
|
8891
|
+
return last ? element : mapAt(element, segments, index + 1, keys, concrete, declared, arrayKeys, visit);
|
|
8892
|
+
});
|
|
8893
|
+
return {
|
|
8894
|
+
...node,
|
|
8895
|
+
[segment.key]: mapped
|
|
8896
|
+
};
|
|
8897
|
+
}
|
|
8898
|
+
const concrete = `${concretePrefix}${concretePrefix.length > 0 ? "." : ""}${segment.key}`;
|
|
8899
|
+
if (last) {
|
|
8900
|
+
const replacement = visit({
|
|
8901
|
+
declared,
|
|
8902
|
+
concrete,
|
|
8903
|
+
value: child
|
|
8904
|
+
});
|
|
8905
|
+
if (replacement === REMOVE_LEAF) return Object.fromEntries(Object.entries(node).filter(([key]) => key !== segment.key));
|
|
8906
|
+
return {
|
|
8907
|
+
...node,
|
|
8908
|
+
[segment.key]: replacement
|
|
8909
|
+
};
|
|
8910
|
+
}
|
|
8911
|
+
return {
|
|
8912
|
+
...node,
|
|
8913
|
+
[segment.key]: mapAt(child, segments, index + 1, keys, concrete, declared, arrayKeys, visit)
|
|
8914
|
+
};
|
|
8915
|
+
}
|
|
8916
|
+
/** Replace/remove every present secret leaf; returns a NEW body. */
|
|
8917
|
+
function mapSecretLeaves(data, paths, arrayKeys, visit) {
|
|
8918
|
+
let current = data;
|
|
8919
|
+
for (const declared of paths) current = mapAt(current, parseSecretPath(declared), 0, [], "", declared, arrayKeys, visit);
|
|
8920
|
+
return current;
|
|
8921
|
+
}
|
|
8922
|
+
/**
|
|
8923
|
+
* The keychain collection name a kind's secrets live under. Prefixed so a
|
|
8924
|
+
* record's refs never collide with the refs a legacy collection of the same name
|
|
8925
|
+
* already holds during an adoption.
|
|
8926
|
+
*/
|
|
8927
|
+
function recordSecretCollection(kind) {
|
|
8928
|
+
return `${RECORD_SECRET_COLLECTION_PREFIX}${kind}`;
|
|
8929
|
+
}
|
|
8930
|
+
/** The ONE ref a row's secret field may carry: the engine and the facade both build it here. */
|
|
8931
|
+
function recordSecretRef(owner, kind, rowId, concretePath) {
|
|
8932
|
+
return buildSecretRef({
|
|
8933
|
+
owner,
|
|
8934
|
+
scope: {
|
|
8935
|
+
kind: "row",
|
|
8936
|
+
collection: recordSecretCollection(kind),
|
|
8937
|
+
rowId
|
|
8938
|
+
},
|
|
8939
|
+
fieldPath: concretePath
|
|
8940
|
+
});
|
|
8941
|
+
}
|
|
8942
|
+
/**
|
|
8943
|
+
* A stored secret, as an admin read shows it: a VIEW naming the row's own
|
|
8944
|
+
* keychain ref (`set: true`), never the value and no longer the bare redaction
|
|
8945
|
+
* token. The form hands it to the secret field, which reveals the value by ref
|
|
8946
|
+
* through the audited `keychain-admin.reveal`; sent back untouched it keeps the
|
|
8947
|
+
* stored secret (the records door reads a view as KEEP).
|
|
8948
|
+
*
|
|
8949
|
+
* ONE implementation for the entries service and for every addon that serves
|
|
8950
|
+
* its own instances (`RecordIntegrationInstances`).
|
|
8951
|
+
*/
|
|
8952
|
+
function isRecord$3(value) {
|
|
8953
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8954
|
+
}
|
|
8955
|
+
function secretViewsOf(owner, kind, id, decl, data) {
|
|
8956
|
+
if (decl.secretPaths.length === 0) return data;
|
|
8957
|
+
const shown = mapSecretLeaves(data, decl.secretPaths, decl.secretArrayKeys, (leaf) => {
|
|
8958
|
+
if (leaf.value !== "__camstack_redacted__") return leaf.value;
|
|
8959
|
+
return {
|
|
8960
|
+
$secret: recordSecretRef(owner, kind, id, leaf.concrete),
|
|
8961
|
+
v: 1,
|
|
8962
|
+
set: true
|
|
8963
|
+
};
|
|
8964
|
+
});
|
|
8965
|
+
return isRecord$3(shown) ? shown : data;
|
|
8966
|
+
}
|
|
8790
8967
|
/**
|
|
8791
8968
|
* The share-view scope kinds a share-link token can carry. The hub mints
|
|
8792
8969
|
* and validates them (`ShareViewGrantSchema` builds its
|
|
@@ -9009,7 +9186,7 @@ function defineRecordKinds(specs) {
|
|
|
9009
9186
|
retention: spec.retention,
|
|
9010
9187
|
deviceRemoval: spec.deviceRemoval,
|
|
9011
9188
|
maxDataBytes: spec.maxDataBytes,
|
|
9012
|
-
secretPaths: [...secretPaths],
|
|
9189
|
+
secretPaths: [...new Set([...secretPaths, ...spec.retiredSecretPaths ?? []])],
|
|
9013
9190
|
secretArrayKeys: spec.secretArrayKeys === void 0 ? void 0 : { ...spec.secretArrayKeys },
|
|
9014
9191
|
transactFamily: spec.transactFamily,
|
|
9015
9192
|
entry: spec.entry === void 0 ? void 0 : {
|
|
@@ -9054,6 +9231,7 @@ function defineEntryKind(name, spec) {
|
|
|
9054
9231
|
...spec.database === void 0 ? {} : { database: spec.database },
|
|
9055
9232
|
...spec.indexes === void 0 ? {} : { indexes: spec.indexes },
|
|
9056
9233
|
...spec.secretArrayKeys === void 0 ? {} : { secretArrayKeys: spec.secretArrayKeys },
|
|
9234
|
+
...spec.retiredSecretPaths === void 0 ? {} : { retiredSecretPaths: spec.retiredSecretPaths },
|
|
9057
9235
|
entry: {
|
|
9058
9236
|
title: spec.title,
|
|
9059
9237
|
...spec.nameField === void 0 ? {} : { nameField: spec.nameField }
|
|
@@ -11781,7 +11959,7 @@ object({
|
|
|
11781
11959
|
params: record(string(), union([string(), number()])).optional()
|
|
11782
11960
|
});
|
|
11783
11961
|
//#endregion
|
|
11784
|
-
//#region ../types/dist/composition-
|
|
11962
|
+
//#region ../types/dist/composition-CRNwcFYY.mjs
|
|
11785
11963
|
/**
|
|
11786
11964
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11787
11965
|
*
|
|
@@ -12544,38 +12722,6 @@ function validateExpressionSource(src) {
|
|
|
12544
12722
|
return null;
|
|
12545
12723
|
}
|
|
12546
12724
|
/**
|
|
12547
|
-
* One power reading becomes a washer, dryer or dishwasher (D944 helper).
|
|
12548
|
-
*
|
|
12549
|
-
* Standby of the control board is under 5 W; a motor or a heater is far
|
|
12550
|
-
* above that, so 5 W is the line. A door lock or a short pump spike is not
|
|
12551
|
-
* a cycle, so running starts only after 30 s above the line.
|
|
12552
|
-
*
|
|
12553
|
-
* A wash, dry or dishwasher pause (soak, heat-wait, heater off between
|
|
12554
|
-
* bursts) lasts several minutes. Ending the cycle on the first dip would
|
|
12555
|
-
* report "finished" in the middle of the program, so the stop dwell is
|
|
12556
|
-
* 10 minutes on every type. The number is stored per type so one machine
|
|
12557
|
-
* can move later without moving the others.
|
|
12558
|
-
*/
|
|
12559
|
-
var APPLIANCE_TEMPLATE_ID = "appliance";
|
|
12560
|
-
var APPLIANCE_KINDS = [
|
|
12561
|
-
"washer",
|
|
12562
|
-
"dryer",
|
|
12563
|
-
"dishwasher"
|
|
12564
|
-
];
|
|
12565
|
-
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
12566
|
-
/**
|
|
12567
|
-
* A dumb plug-in stove or heater, built from a smart plug (a `Heater`).
|
|
12568
|
-
*
|
|
12569
|
-
* The plug is the actuator: `switch.setState` is a FORWARD to the plug's own
|
|
12570
|
-
* (D967), so the heater switches exactly as the plug does. Running is the
|
|
12571
|
-
* plug being on; when a power reading is also named, running is the draw
|
|
12572
|
-
* staying above the line instead (a plug left on with the stove's own
|
|
12573
|
-
* thermostat open is not heating). 50 W is far above any standby and below
|
|
12574
|
-
* the smallest radiator.
|
|
12575
|
-
*/
|
|
12576
|
-
var HEATER_TEMPLATE_ID = "heater";
|
|
12577
|
-
DeviceType.Heater;
|
|
12578
|
-
/**
|
|
12579
12725
|
* Statistics and integrals over a history read (D944).
|
|
12580
12726
|
*
|
|
12581
12727
|
* Pure: the same points always give the same answer, so a restart recomputes
|
|
@@ -12719,34 +12865,6 @@ var HelperSpecSchema = discriminatedUnion("kind", [
|
|
|
12719
12865
|
/** Actuator groups only. Readings leave this unset. */
|
|
12720
12866
|
active: ActiveCriterionSchema.optional()
|
|
12721
12867
|
}),
|
|
12722
|
-
object({
|
|
12723
|
-
kind: literal("appliance"),
|
|
12724
|
-
templateId: literal(APPLIANCE_TEMPLATE_ID),
|
|
12725
|
-
appliance: _enum(APPLIANCE_KINDS),
|
|
12726
|
-
thresholdWatts: number().positive(),
|
|
12727
|
-
startDwellMs: number().int().nonnegative(),
|
|
12728
|
-
stopDwellMs: number().int().nonnegative(),
|
|
12729
|
-
member: HelperMemberSchema,
|
|
12730
|
-
/**
|
|
12731
|
-
* The plug that powers the appliance (`switch.on`). Optional: when set, the
|
|
12732
|
-
* composition carries a `power-source` feature, so the hub can cut and restore
|
|
12733
|
-
* that plug (power-source link of a NEW-target composition).
|
|
12734
|
-
*/
|
|
12735
|
-
powerSwitch: HelperMemberSchema.optional(),
|
|
12736
|
-
/** How long a forced restart keeps the plug off; the cap's default when unset. */
|
|
12737
|
-
offSeconds: number().optional()
|
|
12738
|
-
}),
|
|
12739
|
-
object({
|
|
12740
|
-
kind: literal("heater"),
|
|
12741
|
-
templateId: literal(HEATER_TEMPLATE_ID),
|
|
12742
|
-
/** The plug, read and commanded at `switch.on`. */
|
|
12743
|
-
plug: HelperMemberSchema,
|
|
12744
|
-
/** The plug's power reading, when it has one: running is then the draw, not the switch. */
|
|
12745
|
-
meter: HelperMemberSchema.optional(),
|
|
12746
|
-
thresholdWatts: number().positive(),
|
|
12747
|
-
startDwellMs: number().int().nonnegative(),
|
|
12748
|
-
stopDwellMs: number().int().nonnegative()
|
|
12749
|
-
}),
|
|
12750
12868
|
object({
|
|
12751
12869
|
kind: literal("statistic"),
|
|
12752
12870
|
stat: _enum(STATISTIC_STATS),
|
|
@@ -12918,7 +13036,14 @@ var CompositionForwardCommandSchema = object({
|
|
|
12918
13036
|
method: string().min(1),
|
|
12919
13037
|
args: record(string().min(1), CompositionForwardArgSchema).optional()
|
|
12920
13038
|
});
|
|
12921
|
-
var CompositionCommandTargetSchema = discriminatedUnion("kind", [
|
|
13039
|
+
var CompositionCommandTargetSchema = discriminatedUnion("kind", [
|
|
13040
|
+
CompositionForwardCommandSchema,
|
|
13041
|
+
CompositionCodeSourceSchema,
|
|
13042
|
+
object({
|
|
13043
|
+
kind: literal("extension"),
|
|
13044
|
+
target: literal("remote")
|
|
13045
|
+
})
|
|
13046
|
+
]);
|
|
12922
13047
|
/** An item key inside an item-array cap (`consumables.items[<key>]`). */
|
|
12923
13048
|
var COMPOSITION_ITEM_KEY_RE = /^[a-z0-9][a-z0-9-]{0,47}$/;
|
|
12924
13049
|
/**
|
|
@@ -12963,7 +13088,7 @@ var CompositionSchema = object({
|
|
|
12963
13088
|
kind: literal("existing"),
|
|
12964
13089
|
device: CompositionSourceRefSchema
|
|
12965
13090
|
})]),
|
|
12966
|
-
features: array(CompositionFeatureSchema).min(
|
|
13091
|
+
features: array(CompositionFeatureSchema).min(0).max(16),
|
|
12967
13092
|
/**
|
|
12968
13093
|
* Present when the block is a helper template. Absent on a free
|
|
12969
13094
|
* composition (the room example, device 4603). The editor reads this,
|
|
@@ -13298,6 +13423,157 @@ function buildCapturingReply(envelope) {
|
|
|
13298
13423
|
};
|
|
13299
13424
|
return wrapper;
|
|
13300
13425
|
}
|
|
13426
|
+
/** The most instances one addon lists (an integrations page, not a table). */
|
|
13427
|
+
var INSTANCES_LIST_MAX = 1e3;
|
|
13428
|
+
/** The keys of the kind's secret fields that sit at the top level of the body. */
|
|
13429
|
+
function topLevelSecretKeys(paths) {
|
|
13430
|
+
return new Set(paths.filter((p) => !p.includes(".") && !p.includes("[")));
|
|
13431
|
+
}
|
|
13432
|
+
var RecordIntegrationInstances = class {
|
|
13433
|
+
records;
|
|
13434
|
+
kind;
|
|
13435
|
+
hooks;
|
|
13436
|
+
handle;
|
|
13437
|
+
secretKeys;
|
|
13438
|
+
nameField;
|
|
13439
|
+
constructor(records, kind, hooks) {
|
|
13440
|
+
this.records = records;
|
|
13441
|
+
this.kind = kind;
|
|
13442
|
+
this.hooks = hooks;
|
|
13443
|
+
this.handle = records.kind(kind);
|
|
13444
|
+
this.secretKeys = topLevelSecretKeys(kind.declaration.secretPaths);
|
|
13445
|
+
this.nameField = kind.declaration.entry?.nameField ?? "name";
|
|
13446
|
+
}
|
|
13447
|
+
/**
|
|
13448
|
+
* One instance read for the addon's own runtime; null when absent. When the keychain is
|
|
13449
|
+
* locked the row is served WITHOUT its secrets and says so (`secrets: 'unavailable'`), so the
|
|
13450
|
+
* caller can keep what it had instead of reconfiguring with an empty secret (D49).
|
|
13451
|
+
*/
|
|
13452
|
+
async readResolved(id) {
|
|
13453
|
+
try {
|
|
13454
|
+
const record = await this.handle.getResolved(id);
|
|
13455
|
+
return record === null ? null : {
|
|
13456
|
+
id,
|
|
13457
|
+
body: record.data,
|
|
13458
|
+
enabled: record.data.enabled !== false,
|
|
13459
|
+
secrets: "resolved"
|
|
13460
|
+
};
|
|
13461
|
+
} catch (err) {
|
|
13462
|
+
if (!(err instanceof RecordSecretUnavailableError)) throw err;
|
|
13463
|
+
const stored = await this.handle.get(id);
|
|
13464
|
+
if (stored === null) return null;
|
|
13465
|
+
return {
|
|
13466
|
+
id,
|
|
13467
|
+
body: Object.fromEntries(Object.entries(stored.data).filter(([key]) => !this.secretKeys.has(key))),
|
|
13468
|
+
enabled: stored.data.enabled !== false,
|
|
13469
|
+
secrets: "unavailable"
|
|
13470
|
+
};
|
|
13471
|
+
}
|
|
13472
|
+
}
|
|
13473
|
+
/** The body of {@link readResolved} alone; a locked keychain yields the row without secrets. */
|
|
13474
|
+
async getResolved(id) {
|
|
13475
|
+
return (await this.readResolved(id))?.body ?? null;
|
|
13476
|
+
}
|
|
13477
|
+
/** Every instance, secrets resolved where the keychain allows; an absent one is skipped. */
|
|
13478
|
+
async listResolved() {
|
|
13479
|
+
const page = await this.handle.query({ limit: INSTANCES_LIST_MAX });
|
|
13480
|
+
const out = [];
|
|
13481
|
+
for (const record of page.records) {
|
|
13482
|
+
const read = await this.readResolved(record.id);
|
|
13483
|
+
if (read !== null) out.push(read);
|
|
13484
|
+
}
|
|
13485
|
+
return out;
|
|
13486
|
+
}
|
|
13487
|
+
viewOf(record) {
|
|
13488
|
+
const shown = secretViewsOf(this.records.owner, this.kind.name, record.id, this.kind.declaration, record.data);
|
|
13489
|
+
const rawName = record.data[this.nameField];
|
|
13490
|
+
const kind = this.hooks.kindOf?.(record.data);
|
|
13491
|
+
const health = this.hooks.health?.(record.data, record.id);
|
|
13492
|
+
return {
|
|
13493
|
+
id: record.id,
|
|
13494
|
+
name: typeof rawName === "string" ? rawName : record.id,
|
|
13495
|
+
configured: this.hooks.configured(record.data),
|
|
13496
|
+
enabled: record.data.enabled !== false,
|
|
13497
|
+
formValues: shown,
|
|
13498
|
+
...kind !== void 0 ? { kind } : {},
|
|
13499
|
+
...health?.status !== void 0 ? { status: health.status } : {},
|
|
13500
|
+
...health?.lastCheckedAt !== void 0 ? { lastCheckedAt: health.lastCheckedAt } : {}
|
|
13501
|
+
};
|
|
13502
|
+
}
|
|
13503
|
+
describe = async () => this.hooks.mintId === void 0 ? this.hooks.description : {
|
|
13504
|
+
...this.hooks.description,
|
|
13505
|
+
mintsId: true
|
|
13506
|
+
};
|
|
13507
|
+
instanceFormSchema = async ({ id }) => this.hooks.formSchema(id);
|
|
13508
|
+
listInstances = async () => {
|
|
13509
|
+
return (await this.handle.query({ limit: INSTANCES_LIST_MAX })).records.map((record) => this.viewOf(record));
|
|
13510
|
+
};
|
|
13511
|
+
getInstance = async ({ id }) => {
|
|
13512
|
+
const record = await this.handle.get(id);
|
|
13513
|
+
return record === null ? null : this.viewOf(record);
|
|
13514
|
+
};
|
|
13515
|
+
/** Insert ONE row (`ifRev: 0`: an existing id is refused, never overwritten). */
|
|
13516
|
+
createInstance = async ({ id, name, kind }) => {
|
|
13517
|
+
const minted = id ?? this.hooks.mintId?.({
|
|
13518
|
+
name,
|
|
13519
|
+
...kind !== void 0 ? { kind } : {}
|
|
13520
|
+
});
|
|
13521
|
+
if (minted === void 0) throw new Error("createInstance needs an id: this provider does not mint one");
|
|
13522
|
+
await this.handle.put({
|
|
13523
|
+
id: minted,
|
|
13524
|
+
data: this.hooks.initialBody(name, kind)
|
|
13525
|
+
}, { ifRev: 0 });
|
|
13526
|
+
await this.hooks.onChanged?.(minted);
|
|
13527
|
+
return { id: minted };
|
|
13528
|
+
};
|
|
13529
|
+
updateInstance = async ({ id, name, values }) => {
|
|
13530
|
+
const patch = {};
|
|
13531
|
+
for (const [key, value] of Object.entries(values)) {
|
|
13532
|
+
if (value === void 0) continue;
|
|
13533
|
+
if (!this.secretKeys.has(key)) patch[key] = value;
|
|
13534
|
+
else if (isSecretClear(value)) patch[key] = null;
|
|
13535
|
+
else if (typeof value === "string" && value !== "" && value !== "__camstack_redacted__" && !isSecretFieldView(value)) patch[key] = value;
|
|
13536
|
+
}
|
|
13537
|
+
if (name !== void 0) patch[this.nameField] = name;
|
|
13538
|
+
await this.handle.patch(id, patch);
|
|
13539
|
+
await this.hooks.onChanged?.(id);
|
|
13540
|
+
return { ok: true };
|
|
13541
|
+
};
|
|
13542
|
+
/** The switch lives in the record body; the addon is told so it applies it (D996). */
|
|
13543
|
+
setInstanceEnabled = async ({ id, enabled }) => {
|
|
13544
|
+
await this.handle.patch(id, { enabled });
|
|
13545
|
+
await this.hooks.onChanged?.(id);
|
|
13546
|
+
return { ok: true };
|
|
13547
|
+
};
|
|
13548
|
+
/** The row and its keychain refs go together (the records door). */
|
|
13549
|
+
deleteInstance = async ({ id }) => {
|
|
13550
|
+
await this.handle.delete(id);
|
|
13551
|
+
await this.hooks.onChanged?.(id);
|
|
13552
|
+
return { ok: true };
|
|
13553
|
+
};
|
|
13554
|
+
testInstance = async (input) => {
|
|
13555
|
+
if (this.hooks.test === void 0) return {
|
|
13556
|
+
success: false,
|
|
13557
|
+
status: "unsupported",
|
|
13558
|
+
error: "This integration declares no connection test"
|
|
13559
|
+
};
|
|
13560
|
+
return this.hooks.test(input);
|
|
13561
|
+
};
|
|
13562
|
+
/** The flat provider object to hand to `registerProvider`. */
|
|
13563
|
+
toProvider() {
|
|
13564
|
+
return {
|
|
13565
|
+
describe: this.describe,
|
|
13566
|
+
instanceFormSchema: this.instanceFormSchema,
|
|
13567
|
+
listInstances: this.listInstances,
|
|
13568
|
+
getInstance: this.getInstance,
|
|
13569
|
+
createInstance: this.createInstance,
|
|
13570
|
+
updateInstance: this.updateInstance,
|
|
13571
|
+
setInstanceEnabled: this.setInstanceEnabled,
|
|
13572
|
+
deleteInstance: this.deleteInstance,
|
|
13573
|
+
testInstance: this.testInstance
|
|
13574
|
+
};
|
|
13575
|
+
}
|
|
13576
|
+
};
|
|
13301
13577
|
var EncodeProfileSchema = object({
|
|
13302
13578
|
video: object({
|
|
13303
13579
|
codec: _enum([
|
|
@@ -14403,6 +14679,58 @@ var MigrationOwnerStepSchema = object({
|
|
|
14403
14679
|
/** The ledger state the engine found: `pending` has no row yet. */
|
|
14404
14680
|
state: union([literal("pending"), MigrationStatusSchema])
|
|
14405
14681
|
});
|
|
14682
|
+
function isPlain(value) {
|
|
14683
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14684
|
+
}
|
|
14685
|
+
async function flattenNestedRecords(ports, spec) {
|
|
14686
|
+
const ids = await ports.listNested(spec.legacyKey);
|
|
14687
|
+
if (ids.length === 0) return {
|
|
14688
|
+
outcome: "already-done",
|
|
14689
|
+
summary: { converted: 0 }
|
|
14690
|
+
};
|
|
14691
|
+
const rows = /* @__PURE__ */ new Map();
|
|
14692
|
+
for (const id of ids) try {
|
|
14693
|
+
rows.set(id, await ports.readResolved(id));
|
|
14694
|
+
} catch (err) {
|
|
14695
|
+
const why = err instanceof Error ? err.message : String(err);
|
|
14696
|
+
throw new Error(`record '${id}': cannot be read with its secrets (${why}) - nothing moved`);
|
|
14697
|
+
}
|
|
14698
|
+
for (const [id, row] of rows) {
|
|
14699
|
+
const legacy = row[spec.legacyKey];
|
|
14700
|
+
if (!isPlain(legacy)) throw new Error(`record '${id}': '${spec.legacyKey}' is not an object - nothing moved`);
|
|
14701
|
+
const flat = spec.toFlat(legacy, row);
|
|
14702
|
+
await ports.patch(id, flat);
|
|
14703
|
+
const back = await ports.readResolved(id);
|
|
14704
|
+
const wrong = spec.flatSecretKeys.filter((key) => {
|
|
14705
|
+
const sent = flat[key];
|
|
14706
|
+
const got = back[key];
|
|
14707
|
+
return (typeof sent === "string" ? sent : "") !== (typeof got === "string" ? got : "");
|
|
14708
|
+
});
|
|
14709
|
+
if (wrong.length > 0) {
|
|
14710
|
+
await ports.patch(id, Object.fromEntries(Object.keys(flat).map((key) => [key, null])));
|
|
14711
|
+
throw new Error(`record '${id}': ${wrong.join(", ")} did not read back from its new home - the row is unchanged`);
|
|
14712
|
+
}
|
|
14713
|
+
await ports.patch(id, { [spec.legacyKey]: null });
|
|
14714
|
+
}
|
|
14715
|
+
return {
|
|
14716
|
+
outcome: "done",
|
|
14717
|
+
summary: { converted: rows.size }
|
|
14718
|
+
};
|
|
14719
|
+
}
|
|
14720
|
+
/** The ports over one kind's records handle. */
|
|
14721
|
+
function flattenPortsOver(handle) {
|
|
14722
|
+
return {
|
|
14723
|
+
listNested: async (legacyKey) => (await handle.query({ limit: 1e3 })).records.filter((r) => legacyKey in r.data).map((r) => r.id),
|
|
14724
|
+
readResolved: async (id) => {
|
|
14725
|
+
const row = await handle.getResolved(id);
|
|
14726
|
+
if (row === null) throw new Error("the record is gone");
|
|
14727
|
+
return row.data;
|
|
14728
|
+
},
|
|
14729
|
+
patch: async (id, patch) => {
|
|
14730
|
+
await handle.patch(id, patch);
|
|
14731
|
+
}
|
|
14732
|
+
};
|
|
14733
|
+
}
|
|
14406
14734
|
/**
|
|
14407
14735
|
* The trainer contract — what the hub hands the cloud trainer and what it
|
|
14408
14736
|
* gets back (cloud training, D805+).
|
|
@@ -19579,6 +19907,48 @@ var APPLIANCE_CAP_VOCABULARY = {
|
|
|
19579
19907
|
scope: "device",
|
|
19580
19908
|
noun: t("Media player", "Lettore multimediale"),
|
|
19581
19909
|
actions: [
|
|
19910
|
+
{
|
|
19911
|
+
id: "media.turnOn",
|
|
19912
|
+
method: "turnOn",
|
|
19913
|
+
label: t("Turn on", "Accendi"),
|
|
19914
|
+
phrase: t("Turn on {device}", "Accendi {device}"),
|
|
19915
|
+
icon: "power"
|
|
19916
|
+
},
|
|
19917
|
+
{
|
|
19918
|
+
id: "media.turnOff",
|
|
19919
|
+
method: "turnOff",
|
|
19920
|
+
label: t("Turn off", "Spegni"),
|
|
19921
|
+
phrase: t("Turn off {device}", "Spegni {device}"),
|
|
19922
|
+
icon: "power"
|
|
19923
|
+
},
|
|
19924
|
+
{
|
|
19925
|
+
id: "media.volumeUp",
|
|
19926
|
+
method: "volumeUp",
|
|
19927
|
+
label: t("Volume up", "Alza il volume"),
|
|
19928
|
+
phrase: t("Raise the volume of {device}", "Alza il volume di {device}"),
|
|
19929
|
+
icon: "volume-2"
|
|
19930
|
+
},
|
|
19931
|
+
{
|
|
19932
|
+
id: "media.volumeDown",
|
|
19933
|
+
method: "volumeDown",
|
|
19934
|
+
label: t("Volume down", "Abbassa il volume"),
|
|
19935
|
+
phrase: t("Lower the volume of {device}", "Abbassa il volume di {device}"),
|
|
19936
|
+
icon: "volume-2"
|
|
19937
|
+
},
|
|
19938
|
+
{
|
|
19939
|
+
id: "media.channelUp",
|
|
19940
|
+
method: "channelUp",
|
|
19941
|
+
label: t("Channel up", "Canale successivo"),
|
|
19942
|
+
phrase: t("Go to the next channel on {device}", "Passa al canale successivo su {device}"),
|
|
19943
|
+
icon: "skip-forward"
|
|
19944
|
+
},
|
|
19945
|
+
{
|
|
19946
|
+
id: "media.channelDown",
|
|
19947
|
+
method: "channelDown",
|
|
19948
|
+
label: t("Channel down", "Canale precedente"),
|
|
19949
|
+
phrase: t("Go to the previous channel on {device}", "Torna al canale precedente su {device}"),
|
|
19950
|
+
icon: "skip-back"
|
|
19951
|
+
},
|
|
19582
19952
|
{
|
|
19583
19953
|
id: "media.play",
|
|
19584
19954
|
method: "play",
|
|
@@ -49548,6 +49918,244 @@ var controlCapability = {
|
|
|
49548
49918
|
*/
|
|
49549
49919
|
history: "none"
|
|
49550
49920
|
};
|
|
49921
|
+
/**
|
|
49922
|
+
* Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
|
|
49923
|
+
* Apple TV, Spotify, Roku, generic OTT receivers, …) on
|
|
49924
|
+
* `DeviceType.MediaPlayer`. Disjoint from the camera streaming
|
|
49925
|
+
* surface — those use `DeviceType.Camera` + the broker pipeline.
|
|
49926
|
+
*
|
|
49927
|
+
* The cap declares a wide method surface; not every backend supports
|
|
49928
|
+
* every method. Drivers signal sub-capability via the
|
|
49929
|
+
* `DeviceFeature.MediaPlayerXxx` flags (paired one-to-one with the
|
|
49930
|
+
* corresponding method) so the UI gates buttons without a slice
|
|
49931
|
+
* fetch — same pattern as `PanTiltZoom` for cameras.
|
|
49932
|
+
*/
|
|
49933
|
+
var MediaPlayerStateSchema = _enum([
|
|
49934
|
+
"off",
|
|
49935
|
+
"on",
|
|
49936
|
+
"idle",
|
|
49937
|
+
"playing",
|
|
49938
|
+
"paused",
|
|
49939
|
+
"buffering",
|
|
49940
|
+
"standby"
|
|
49941
|
+
]);
|
|
49942
|
+
var MediaPlayerRepeatSchema = _enum([
|
|
49943
|
+
"off",
|
|
49944
|
+
"all",
|
|
49945
|
+
"one"
|
|
49946
|
+
]);
|
|
49947
|
+
var MediaInfoSchema = object({
|
|
49948
|
+
/** Free-form media kind (`music`, `tvshow`, `movie`, `app`, `channel`,
|
|
49949
|
+
* `podcast`, …). */
|
|
49950
|
+
type: string(),
|
|
49951
|
+
/** Human-readable title. */
|
|
49952
|
+
title: string(),
|
|
49953
|
+
/** Optional artist / channel / station label. */
|
|
49954
|
+
artist: string().optional(),
|
|
49955
|
+
/** Optional album / season / show name. */
|
|
49956
|
+
album: string().optional(),
|
|
49957
|
+
/** Optional cover-art / thumbnail URL. */
|
|
49958
|
+
imageUrl: string().optional()
|
|
49959
|
+
});
|
|
49960
|
+
/**
|
|
49961
|
+
* Where `state`, `volumeLevel`, `isMuted` and `source` come from. `reported`:
|
|
49962
|
+
* the device said so. `assumed`: the driver has no feedback (infrared) and
|
|
49963
|
+
* tracks what it last SENT; it moves only after a send was accepted, and a
|
|
49964
|
+
* human at the real remote makes it wrong. A UI shows an assumed value as a
|
|
49965
|
+
* guess, never as a reading.
|
|
49966
|
+
*/
|
|
49967
|
+
var MediaPlayerStateSourceSchema = _enum(["reported", "assumed"]);
|
|
49968
|
+
/** The fields of a media-player status a driver can only guess. */
|
|
49969
|
+
var MediaPlayerAssumedFieldSchema = _enum([
|
|
49970
|
+
"state",
|
|
49971
|
+
"volumeLevel",
|
|
49972
|
+
"isMuted",
|
|
49973
|
+
"source"
|
|
49974
|
+
]);
|
|
49975
|
+
var MediaPlayerStatusSchema = object({
|
|
49976
|
+
/** Playback lifecycle state. */
|
|
49977
|
+
state: MediaPlayerStateSchema,
|
|
49978
|
+
/**
|
|
49979
|
+
* Whether the state fields are readings or the driver's own bookkeeping.
|
|
49980
|
+
* A slice written before this field existed parses as `reported`.
|
|
49981
|
+
*/
|
|
49982
|
+
stateSource: MediaPlayerStateSourceSchema.default("reported"),
|
|
49983
|
+
/**
|
|
49984
|
+
* Which fields are the driver's own guess. `stateSource` is `assumed` when
|
|
49985
|
+
* this is not empty; a field not listed here is a reading even then (power
|
|
49986
|
+
* from a running-state source, mute guessed from the last send).
|
|
49987
|
+
*/
|
|
49988
|
+
assumedFields: array(MediaPlayerAssumedFieldSchema).default([]),
|
|
49989
|
+
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
49990
|
+
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
49991
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
49992
|
+
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
49993
|
+
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
49994
|
+
isMuted: boolean().nullable(),
|
|
49995
|
+
/** Active source / input. Empty when no source surface. */
|
|
49996
|
+
source: string(),
|
|
49997
|
+
/** Selectable sources. Empty when no source surface.
|
|
49998
|
+
* Pair with `DeviceFeature.MediaPlayerSelectSource`. */
|
|
49999
|
+
availableSources: array(string()),
|
|
50000
|
+
/** Currently-playing media info. Null when nothing is playing. */
|
|
50001
|
+
currentMedia: MediaInfoSchema.nullable(),
|
|
50002
|
+
/** Current playback position in ms. Null when not seekable or
|
|
50003
|
+
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
50004
|
+
position: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
50005
|
+
/** Total duration of the current media in ms. Null when unknown
|
|
50006
|
+
* (live stream) or nothing is playing. */
|
|
50007
|
+
duration: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
50008
|
+
/** Shuffle toggle. Null when no shuffle surface.
|
|
50009
|
+
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
50010
|
+
shuffle: boolean().nullable(),
|
|
50011
|
+
/** Repeat mode. Null when no repeat surface.
|
|
50012
|
+
* Pair with `DeviceFeature.MediaPlayerRepeat`. */
|
|
50013
|
+
repeat: MediaPlayerRepeatSchema.nullable(),
|
|
50014
|
+
/** Ms epoch when the slice was last updated. */
|
|
50015
|
+
lastChangedAt: number()
|
|
50016
|
+
});
|
|
50017
|
+
var stepInput = object({
|
|
50018
|
+
deviceId: number().int().nonnegative(),
|
|
50019
|
+
/** How many presses: the caller's count (Alexa `volumeSteps`, `channelCount`). */
|
|
50020
|
+
steps: number().int().min(1).max(50).default(1)
|
|
50021
|
+
});
|
|
50022
|
+
var deviceOnly = object({ deviceId: number().int().nonnegative() });
|
|
50023
|
+
var mediaPlayerCapability = {
|
|
50024
|
+
name: "media-player",
|
|
50025
|
+
scope: "device",
|
|
50026
|
+
deviceNative: true,
|
|
50027
|
+
mode: "singleton",
|
|
50028
|
+
deviceTypes: [DeviceType.MediaPlayer],
|
|
50029
|
+
methods: {
|
|
50030
|
+
turnOn: method(deviceOnly, _void(), {
|
|
50031
|
+
kind: "mutation",
|
|
50032
|
+
auth: "protected"
|
|
50033
|
+
}),
|
|
50034
|
+
turnOff: method(deviceOnly, _void(), {
|
|
50035
|
+
kind: "mutation",
|
|
50036
|
+
auth: "protected"
|
|
50037
|
+
}),
|
|
50038
|
+
volumeUp: method(stepInput, _void(), {
|
|
50039
|
+
kind: "mutation",
|
|
50040
|
+
auth: "protected"
|
|
50041
|
+
}),
|
|
50042
|
+
volumeDown: method(stepInput, _void(), {
|
|
50043
|
+
kind: "mutation",
|
|
50044
|
+
auth: "protected"
|
|
50045
|
+
}),
|
|
50046
|
+
channelUp: method(stepInput, _void(), {
|
|
50047
|
+
kind: "mutation",
|
|
50048
|
+
auth: "protected"
|
|
50049
|
+
}),
|
|
50050
|
+
channelDown: method(stepInput, _void(), {
|
|
50051
|
+
kind: "mutation",
|
|
50052
|
+
auth: "protected"
|
|
50053
|
+
}),
|
|
50054
|
+
play: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
50055
|
+
kind: "mutation",
|
|
50056
|
+
auth: "protected"
|
|
50057
|
+
}),
|
|
50058
|
+
pause: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
50059
|
+
kind: "mutation",
|
|
50060
|
+
auth: "protected"
|
|
50061
|
+
}),
|
|
50062
|
+
stop: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
50063
|
+
kind: "mutation",
|
|
50064
|
+
auth: "protected"
|
|
50065
|
+
}),
|
|
50066
|
+
next: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
50067
|
+
kind: "mutation",
|
|
50068
|
+
auth: "protected"
|
|
50069
|
+
}),
|
|
50070
|
+
previous: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
50071
|
+
kind: "mutation",
|
|
50072
|
+
auth: "protected"
|
|
50073
|
+
}),
|
|
50074
|
+
seek: method(object({
|
|
50075
|
+
deviceId: number().int().nonnegative(),
|
|
50076
|
+
position: number().int().nonnegative()
|
|
50077
|
+
}), _void(), {
|
|
50078
|
+
kind: "mutation",
|
|
50079
|
+
auth: "protected"
|
|
50080
|
+
}),
|
|
50081
|
+
setVolume: method(object({
|
|
50082
|
+
deviceId: number().int().nonnegative(),
|
|
50083
|
+
volumeLevel: number().min(0).max(100)
|
|
50084
|
+
}), _void(), {
|
|
50085
|
+
kind: "mutation",
|
|
50086
|
+
auth: "protected"
|
|
50087
|
+
}),
|
|
50088
|
+
setMute: method(object({
|
|
50089
|
+
deviceId: number().int().nonnegative(),
|
|
50090
|
+
muted: boolean()
|
|
50091
|
+
}), _void(), {
|
|
50092
|
+
kind: "mutation",
|
|
50093
|
+
auth: "protected"
|
|
50094
|
+
}),
|
|
50095
|
+
setShuffle: method(object({
|
|
50096
|
+
deviceId: number().int().nonnegative(),
|
|
50097
|
+
shuffle: boolean()
|
|
50098
|
+
}), _void(), {
|
|
50099
|
+
kind: "mutation",
|
|
50100
|
+
auth: "protected"
|
|
50101
|
+
}),
|
|
50102
|
+
setRepeat: method(object({
|
|
50103
|
+
deviceId: number().int().nonnegative(),
|
|
50104
|
+
repeat: MediaPlayerRepeatSchema
|
|
50105
|
+
}), _void(), {
|
|
50106
|
+
kind: "mutation",
|
|
50107
|
+
auth: "protected"
|
|
50108
|
+
}),
|
|
50109
|
+
selectSource: method(object({
|
|
50110
|
+
deviceId: number().int().nonnegative(),
|
|
50111
|
+
source: string().min(1)
|
|
50112
|
+
}), _void(), {
|
|
50113
|
+
kind: "mutation",
|
|
50114
|
+
auth: "protected"
|
|
50115
|
+
}),
|
|
50116
|
+
playMedia: method(object({
|
|
50117
|
+
deviceId: number().int().nonnegative(),
|
|
50118
|
+
/** Media identifier / URL. */
|
|
50119
|
+
mediaId: string().min(1),
|
|
50120
|
+
/** Media kind (`music`, `tvshow`, `movie`, `app`, …) — provider
|
|
50121
|
+
* passes it through to the upstream service. */
|
|
50122
|
+
mediaType: string().min(1)
|
|
50123
|
+
}), _void(), {
|
|
50124
|
+
kind: "mutation",
|
|
50125
|
+
auth: "protected"
|
|
50126
|
+
})
|
|
50127
|
+
},
|
|
50128
|
+
status: {
|
|
50129
|
+
schema: MediaPlayerStatusSchema,
|
|
50130
|
+
kind: "push"
|
|
50131
|
+
},
|
|
50132
|
+
/**
|
|
50133
|
+
* Runtime-state slice — mirrored by the kernel. UI players read the
|
|
50134
|
+
* full slice for live now-playing, volume, and progress updates
|
|
50135
|
+
* without polling.
|
|
50136
|
+
*/
|
|
50137
|
+
runtimeState: MediaPlayerStatusSchema,
|
|
50138
|
+
/**
|
|
50139
|
+
* Runtime-state durability: **session** — a restored transport position describes a playback that stopped when the hub did.
|
|
50140
|
+
*
|
|
50141
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
50142
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
50143
|
+
*/
|
|
50144
|
+
durability: "session",
|
|
50145
|
+
/**
|
|
50146
|
+
* History (D850): volume (a level an operator or an automation sets; the
|
|
50147
|
+
* default 10 s floor folds a slider drag into its end value) and mute.
|
|
50148
|
+
* `position` is not recorded: it moves continuously while playing.
|
|
50149
|
+
*/
|
|
50150
|
+
history: { fields: {
|
|
50151
|
+
volumeLevel: {
|
|
50152
|
+
kind: "gauge",
|
|
50153
|
+
unit: "%",
|
|
50154
|
+
deadband: 1
|
|
50155
|
+
},
|
|
50156
|
+
isMuted: { kind: "boolean" }
|
|
50157
|
+
} }
|
|
50158
|
+
};
|
|
49551
50159
|
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;
|
|
49552
50160
|
var NUMBER = {
|
|
49553
50161
|
kind: "fixed",
|
|
@@ -49995,117 +50603,6 @@ function actuator(input) {
|
|
|
49995
50603
|
};
|
|
49996
50604
|
}
|
|
49997
50605
|
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
49998
|
-
var PowerSourceRefusalReasonSchema = _enum([
|
|
49999
|
-
"no-power-source",
|
|
50000
|
-
"switch-missing",
|
|
50001
|
-
"switch-offline",
|
|
50002
|
-
"switch-unknown",
|
|
50003
|
-
"restart-in-progress",
|
|
50004
|
-
"switch-call-failed"
|
|
50005
|
-
]);
|
|
50006
|
-
var PowerSourceActionResultSchema = discriminatedUnion("accepted", [object({ accepted: literal(true) }), object({
|
|
50007
|
-
accepted: literal(false),
|
|
50008
|
-
reason: PowerSourceRefusalReasonSchema,
|
|
50009
|
-
/** One line for the operator, naming the switch. */
|
|
50010
|
-
message: string()
|
|
50011
|
-
})]);
|
|
50012
|
-
var PowerSourceInfoSchema = object({
|
|
50013
|
-
/** False when the device has no power source linked; the rest is then empty. */
|
|
50014
|
-
linked: boolean(),
|
|
50015
|
-
switchDeviceId: number().nullable(),
|
|
50016
|
-
switchName: string().nullable(),
|
|
50017
|
-
/** The switch's on/off state, or null when it is unknown. Never false for unknown (D393). */
|
|
50018
|
-
switchOn: boolean().nullable(),
|
|
50019
|
-
switchOnline: boolean().nullable(),
|
|
50020
|
-
restartInProgress: boolean(),
|
|
50021
|
-
offSeconds: number().int()
|
|
50022
|
-
});
|
|
50023
|
-
/** The composed slice: the switch state the link mirrors, plus the stored off time. */
|
|
50024
|
-
var PowerSourceStateSchema = object({
|
|
50025
|
-
/** Null while the switch has not reported: unknown is never `false` (D393). */
|
|
50026
|
-
switchOn: boolean().nullable(),
|
|
50027
|
-
offSeconds: number().int(),
|
|
50028
|
-
lastFetchedAt: number()
|
|
50029
|
-
});
|
|
50030
|
-
var POWER_SOURCE_DEVICE_TYPES = [
|
|
50031
|
-
DeviceType.Gateway,
|
|
50032
|
-
DeviceType.Hub,
|
|
50033
|
-
DeviceType.Camera,
|
|
50034
|
-
DeviceType.Sensor,
|
|
50035
|
-
DeviceType.MediaPlayer,
|
|
50036
|
-
DeviceType.Vacuum,
|
|
50037
|
-
DeviceType.Generic,
|
|
50038
|
-
DeviceType.Washer,
|
|
50039
|
-
DeviceType.Dryer,
|
|
50040
|
-
DeviceType.Dishwasher,
|
|
50041
|
-
DeviceType.PetFountain,
|
|
50042
|
-
DeviceType.Fan,
|
|
50043
|
-
DeviceType.Humidifier,
|
|
50044
|
-
DeviceType.Climate,
|
|
50045
|
-
DeviceType.WaterHeater
|
|
50046
|
-
];
|
|
50047
|
-
var powerSourceCustomize = {
|
|
50048
|
-
version: 1,
|
|
50049
|
-
targets: [{
|
|
50050
|
-
id: "switch",
|
|
50051
|
-
cardinality: "scalar",
|
|
50052
|
-
vocabulary: {
|
|
50053
|
-
cap: "power-source",
|
|
50054
|
-
stateField: "switchOn"
|
|
50055
|
-
},
|
|
50056
|
-
deviceTypes: POWER_SOURCE_DEVICE_TYPES,
|
|
50057
|
-
apply: "add",
|
|
50058
|
-
path: "switchOn",
|
|
50059
|
-
sources: [{
|
|
50060
|
-
kind: "switch",
|
|
50061
|
-
transforms: [{ kind: "identity" }]
|
|
50062
|
-
}],
|
|
50063
|
-
companions: [{
|
|
50064
|
-
kind: "constant",
|
|
50065
|
-
path: "offSeconds",
|
|
50066
|
-
value: 10,
|
|
50067
|
-
when: "add"
|
|
50068
|
-
}, {
|
|
50069
|
-
kind: "clock",
|
|
50070
|
-
path: "lastFetchedAt",
|
|
50071
|
-
when: "always"
|
|
50072
|
-
}],
|
|
50073
|
-
sourceReport: { status: "assignment-status" }
|
|
50074
|
-
}]
|
|
50075
|
-
};
|
|
50076
|
-
var deviceInput$2 = object({ deviceId: number().int().nonnegative() });
|
|
50077
|
-
var powerSourceCapability = {
|
|
50078
|
-
name: "power-source",
|
|
50079
|
-
scope: "device",
|
|
50080
|
-
mode: "singleton",
|
|
50081
|
-
deviceTypes: POWER_SOURCE_DEVICE_TYPES,
|
|
50082
|
-
methods: {
|
|
50083
|
-
getStatus: systemMethod(deviceInput$2, PowerSourceInfoSchema, { auth: "admin" }),
|
|
50084
|
-
powerOn: systemMethod(deviceInput$2, PowerSourceActionResultSchema, {
|
|
50085
|
-
kind: "mutation",
|
|
50086
|
-
auth: "admin"
|
|
50087
|
-
}),
|
|
50088
|
-
powerOff: systemMethod(deviceInput$2, PowerSourceActionResultSchema, {
|
|
50089
|
-
kind: "mutation",
|
|
50090
|
-
auth: "admin"
|
|
50091
|
-
}),
|
|
50092
|
-
forceRestart: systemMethod(deviceInput$2, PowerSourceActionResultSchema, {
|
|
50093
|
-
kind: "mutation",
|
|
50094
|
-
auth: "admin"
|
|
50095
|
-
})
|
|
50096
|
-
},
|
|
50097
|
-
runtimeState: PowerSourceStateSchema,
|
|
50098
|
-
customize: powerSourceCustomize,
|
|
50099
|
-
/**
|
|
50100
|
-
* Runtime-state durability: **session** — mirrored from the linked switch on
|
|
50101
|
-
* its next report; a restored value would outlive the reading it names.
|
|
50102
|
-
*
|
|
50103
|
-
* See `RuntimeStateDurability`. Enforced by
|
|
50104
|
-
* `scripts/check-runtime-state-durability.ts`.
|
|
50105
|
-
*/
|
|
50106
|
-
durability: "session",
|
|
50107
|
-
history: "none"
|
|
50108
|
-
};
|
|
50109
50606
|
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
50110
50607
|
DeviceType.Camera;
|
|
50111
50608
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
@@ -50133,6 +50630,165 @@ var ComposableCapabilitiesSchema = object({ caps: array(object({
|
|
|
50133
50630
|
}).optional()
|
|
50134
50631
|
})) });
|
|
50135
50632
|
/**
|
|
50633
|
+
* A saved Customize assignment (D936). The schema is the type: callers use
|
|
50634
|
+
* `z.infer`, they do not restate the shape.
|
|
50635
|
+
*/
|
|
50636
|
+
var OverrideSourceSchema = object({
|
|
50637
|
+
addonId: string().min(1),
|
|
50638
|
+
stableId: string().min(1),
|
|
50639
|
+
cap: string().min(1),
|
|
50640
|
+
fieldPath: string().min(1)
|
|
50641
|
+
});
|
|
50642
|
+
var IdentityTransformDraftSchema = object({ kind: literal("identity") });
|
|
50643
|
+
var InvertTransformDraftSchema = object({ kind: literal("invert") });
|
|
50644
|
+
var ThresholdTransformDraftSchema = object({
|
|
50645
|
+
kind: literal("threshold"),
|
|
50646
|
+
comparison: _enum(["gte", "lte"]),
|
|
50647
|
+
threshold: number(),
|
|
50648
|
+
startDwellMs: number().nonnegative(),
|
|
50649
|
+
stopDwellMs: number().nonnegative()
|
|
50650
|
+
});
|
|
50651
|
+
var CustomizeTransformDraftSchema = discriminatedUnion("kind", [
|
|
50652
|
+
IdentityTransformDraftSchema,
|
|
50653
|
+
InvertTransformDraftSchema,
|
|
50654
|
+
ThresholdTransformDraftSchema,
|
|
50655
|
+
object({
|
|
50656
|
+
kind: literal("linear"),
|
|
50657
|
+
scale: number(),
|
|
50658
|
+
offset: number(),
|
|
50659
|
+
clampMin: number().optional(),
|
|
50660
|
+
clampMax: number().optional()
|
|
50661
|
+
}),
|
|
50662
|
+
object({
|
|
50663
|
+
kind: literal("enum-map"),
|
|
50664
|
+
mapping: record(string(), string().nullable())
|
|
50665
|
+
}),
|
|
50666
|
+
object({ kind: literal("number") })
|
|
50667
|
+
]);
|
|
50668
|
+
var ScalarOverrideDraftSchema = object({
|
|
50669
|
+
kind: literal("scalar"),
|
|
50670
|
+
cap: string().min(1),
|
|
50671
|
+
targetId: string().min(1),
|
|
50672
|
+
source: OverrideSourceSchema,
|
|
50673
|
+
transform: CustomizeTransformDraftSchema
|
|
50674
|
+
});
|
|
50675
|
+
var KeyedArrayOverrideDraftSchema = object({
|
|
50676
|
+
kind: literal("keyedArray"),
|
|
50677
|
+
cap: string().min(1),
|
|
50678
|
+
targetId: string().min(1),
|
|
50679
|
+
key: string().min(1),
|
|
50680
|
+
label: string().min(1),
|
|
50681
|
+
fieldPath: string().min(1),
|
|
50682
|
+
source: OverrideSourceSchema,
|
|
50683
|
+
transform: CustomizeTransformDraftSchema
|
|
50684
|
+
});
|
|
50685
|
+
var PulseOverrideDraftSchema = object({
|
|
50686
|
+
kind: literal("pulse"),
|
|
50687
|
+
cap: string().min(1),
|
|
50688
|
+
targetId: string().min(1),
|
|
50689
|
+
enabled: boolean(),
|
|
50690
|
+
debounceMs: number().nonnegative(),
|
|
50691
|
+
edges: array(_enum([
|
|
50692
|
+
"rising",
|
|
50693
|
+
"button",
|
|
50694
|
+
"native-event"
|
|
50695
|
+
])).min(1).optional(),
|
|
50696
|
+
sources: array(OverrideSourceSchema).min(1)
|
|
50697
|
+
});
|
|
50698
|
+
var SpanSourceDraftSchema = OverrideSourceSchema.extend({ mode: _enum([
|
|
50699
|
+
"in-addition",
|
|
50700
|
+
"confirm",
|
|
50701
|
+
"replace"
|
|
50702
|
+
]).optional() });
|
|
50703
|
+
discriminatedUnion("kind", [
|
|
50704
|
+
ScalarOverrideDraftSchema,
|
|
50705
|
+
KeyedArrayOverrideDraftSchema,
|
|
50706
|
+
PulseOverrideDraftSchema,
|
|
50707
|
+
object({
|
|
50708
|
+
kind: literal("span"),
|
|
50709
|
+
cap: string().min(1),
|
|
50710
|
+
targetId: string().min(1),
|
|
50711
|
+
timeoutMs: number().nonnegative(),
|
|
50712
|
+
cooldownMs: number().nonnegative().optional(),
|
|
50713
|
+
sources: array(SpanSourceDraftSchema)
|
|
50714
|
+
})
|
|
50715
|
+
]);
|
|
50716
|
+
object({
|
|
50717
|
+
targetId: string().min(1),
|
|
50718
|
+
configured: boolean(),
|
|
50719
|
+
source: _enum(["native", "assigned"]),
|
|
50720
|
+
state: _enum([
|
|
50721
|
+
"active",
|
|
50722
|
+
"stale",
|
|
50723
|
+
"released",
|
|
50724
|
+
"unavailable"
|
|
50725
|
+
]),
|
|
50726
|
+
reason: string().nullable()
|
|
50727
|
+
});
|
|
50728
|
+
/**
|
|
50729
|
+
* What a running-threshold proposal says (planning#405). The schema is the
|
|
50730
|
+
* type: the algorithm, the capability method and the UI all read `z.infer`.
|
|
50731
|
+
*
|
|
50732
|
+
* A proposal is read-only advice: it carries the numbers it was derived from
|
|
50733
|
+
* (`evidence`) so the operator can judge it, and an `insufficient` answer names
|
|
50734
|
+
* WHY with a typed reason and the catalog defaults, never an invented number.
|
|
50735
|
+
*/
|
|
50736
|
+
var RunningProposalTierSchema = _enum(["raw", "5m"]);
|
|
50737
|
+
var RunningProposalConfidenceSchema = _enum([
|
|
50738
|
+
"high",
|
|
50739
|
+
"medium",
|
|
50740
|
+
"low"
|
|
50741
|
+
]);
|
|
50742
|
+
var RunningProposalInsufficientReasonSchema = _enum([
|
|
50743
|
+
"no-history",
|
|
50744
|
+
"span-too-short",
|
|
50745
|
+
"truncated",
|
|
50746
|
+
"no-idle-floor",
|
|
50747
|
+
"no-runs",
|
|
50748
|
+
"no-separation"
|
|
50749
|
+
]);
|
|
50750
|
+
var RunningProposalReplaySchema = object({
|
|
50751
|
+
/** Intervals the real dwell expression held true over the window. */
|
|
50752
|
+
intervals: number().int().nonnegative(),
|
|
50753
|
+
/** Intervals outside every run, or a second interval inside one. */
|
|
50754
|
+
extra: number().int().nonnegative(),
|
|
50755
|
+
/** Runs without an interval of their own (none, or merged into a neighbour). */
|
|
50756
|
+
missed: number().int().nonnegative()
|
|
50757
|
+
});
|
|
50758
|
+
var RunningProposalEvidenceSchema = object({
|
|
50759
|
+
tier: RunningProposalTierSchema,
|
|
50760
|
+
spanMs: number().nonnegative(),
|
|
50761
|
+
from: number(),
|
|
50762
|
+
to: number(),
|
|
50763
|
+
points: number().int().nonnegative(),
|
|
50764
|
+
runsFound: number().int().nonnegative(),
|
|
50765
|
+
pausesFound: number().int().nonnegative(),
|
|
50766
|
+
longestPauseMs: number().nonnegative(),
|
|
50767
|
+
idleFloorW: number(),
|
|
50768
|
+
noiseCeilingW: number(),
|
|
50769
|
+
plateauW: number(),
|
|
50770
|
+
replay: RunningProposalReplaySchema
|
|
50771
|
+
});
|
|
50772
|
+
var RunningProposalInsufficientEvidenceSchema = object({
|
|
50773
|
+
spanMs: number().nonnegative(),
|
|
50774
|
+
points: number().int().nonnegative(),
|
|
50775
|
+
runsFound: number().int().nonnegative()
|
|
50776
|
+
});
|
|
50777
|
+
var RunningThresholdProposalSchema = discriminatedUnion("state", [object({
|
|
50778
|
+
state: literal("proposal"),
|
|
50779
|
+
transform: ThresholdTransformDraftSchema,
|
|
50780
|
+
evidence: RunningProposalEvidenceSchema,
|
|
50781
|
+
confidence: RunningProposalConfidenceSchema,
|
|
50782
|
+
/** Why the confidence is not higher; empty when nothing held it back. */
|
|
50783
|
+
notes: array(string())
|
|
50784
|
+
}), object({
|
|
50785
|
+
state: literal("insufficient"),
|
|
50786
|
+
reason: RunningProposalInsufficientReasonSchema,
|
|
50787
|
+
evidence: RunningProposalInsufficientEvidenceSchema,
|
|
50788
|
+
/** The catalog defaults, offered as what stands when nothing better is known. */
|
|
50789
|
+
fallback: ThresholdTransformDraftSchema
|
|
50790
|
+
})]);
|
|
50791
|
+
/**
|
|
50136
50792
|
* The report of a one-shot "move this owner's plaintext secrets into the
|
|
50137
50793
|
* keychain" run (D878). COUNTS only - never a value, never a ref.
|
|
50138
50794
|
*
|
|
@@ -50422,6 +51078,14 @@ method(object({}), object({ blocks: array(CoreBlockSchema) }), { auth: "admin" }
|
|
|
50422
51078
|
kind: "mutation",
|
|
50423
51079
|
auth: "admin",
|
|
50424
51080
|
access: "view"
|
|
51081
|
+
}), method(object({
|
|
51082
|
+
deviceId: number().int(),
|
|
51083
|
+
cap: string().min(1),
|
|
51084
|
+
fieldPath: string().min(1),
|
|
51085
|
+
deviceType: _enum(DeviceType).optional()
|
|
51086
|
+
}), RunningThresholdProposalSchema, {
|
|
51087
|
+
auth: "admin",
|
|
51088
|
+
access: "view"
|
|
50425
51089
|
}), method(object({
|
|
50426
51090
|
blockId: string().min(1),
|
|
50427
51091
|
trace: AutomationRunTraceSchema.optional(),
|
|
@@ -51398,7 +52062,46 @@ method(object({
|
|
|
51398
52062
|
* exposes only the COMMON surface: link state, supported device
|
|
51399
52063
|
* kinds (so the UI can filter the device picker), and per-device
|
|
51400
52064
|
* expose/unexpose.
|
|
52065
|
+
*
|
|
52066
|
+
* INSTANCES. One export addon can serve several independent targets (a
|
|
52067
|
+
* HomeKit bridge, a Home Assistant broker). `listInstances` names them.
|
|
52068
|
+
* `instanceId` on a READ is optional: absent = the whole addon (linked if any
|
|
52069
|
+
* enabled instance is, `exposedDeviceCount` = distinct devices, `setup` = the
|
|
52070
|
+
* default instance's); present = that instance; an id the provider does not
|
|
52071
|
+
* serve is refused with `ExportInstanceUnknownError` (`export-instance-unknown`),
|
|
52072
|
+
* never answered empty. `instanceId` on a WRITE is REQUIRED: a membership
|
|
52073
|
+
* change always names the target it changes. A single-instance provider
|
|
52074
|
+
* accepts an absent id on a read or its own id, and refuses any other.
|
|
52075
|
+
*/
|
|
52076
|
+
/** Which instance of an export addon a call addresses. Absent on a read = the whole addon. */
|
|
52077
|
+
var InstanceIdSchema$1 = string().min(1);
|
|
52078
|
+
var InstancePinSchema = object({ instanceId: InstanceIdSchema$1.optional() });
|
|
52079
|
+
/** One independent export target of an addon. */
|
|
52080
|
+
var ExportInstanceSchema = object({
|
|
52081
|
+
instanceId: InstanceIdSchema$1,
|
|
52082
|
+
name: string(),
|
|
52083
|
+
enabled: boolean(),
|
|
52084
|
+
kind: string().optional()
|
|
52085
|
+
});
|
|
52086
|
+
var EXPORT_INSTANCE_UNKNOWN = "export-instance-unknown";
|
|
52087
|
+
/** The named failure of an `instanceId` the provider does not serve. The message starts with the code. */
|
|
52088
|
+
var ExportInstanceUnknownError = class extends Error {
|
|
52089
|
+
code = EXPORT_INSTANCE_UNKNOWN;
|
|
52090
|
+
instanceId;
|
|
52091
|
+
constructor(addon, instanceId) {
|
|
52092
|
+
super(`${EXPORT_INSTANCE_UNKNOWN}: ${addon} serves no instance "${instanceId}"`);
|
|
52093
|
+
this.name = "ExportInstanceUnknownError";
|
|
52094
|
+
this.instanceId = instanceId;
|
|
52095
|
+
}
|
|
52096
|
+
};
|
|
52097
|
+
/**
|
|
52098
|
+
* The instance a `getStatus` call names. The cap's `status` block injects a per-device
|
|
52099
|
+
* `getStatus({ deviceId })` beside the method's own `{ instanceId? }`, so the provider sees
|
|
52100
|
+
* both shapes; only the second names an instance (a per-device status read is addon-wide).
|
|
51401
52101
|
*/
|
|
52102
|
+
function statusInstanceOf(input) {
|
|
52103
|
+
return "instanceId" in input ? input.instanceId : void 0;
|
|
52104
|
+
}
|
|
51402
52105
|
var LinkStateSchema = _enum([
|
|
51403
52106
|
"unlinked",
|
|
51404
52107
|
"linked",
|
|
@@ -51449,10 +52152,14 @@ var ExposedDeviceSchema = object({
|
|
|
51449
52152
|
capabilities: array(string()).optional()
|
|
51450
52153
|
});
|
|
51451
52154
|
var ExposeInputSchema = object({
|
|
52155
|
+
instanceId: InstanceIdSchema$1,
|
|
51452
52156
|
deviceId: string(),
|
|
51453
52157
|
capabilities: array(string()).optional()
|
|
51454
52158
|
});
|
|
51455
|
-
var UnexposeInputSchema = object({
|
|
52159
|
+
var UnexposeInputSchema = object({
|
|
52160
|
+
instanceId: InstanceIdSchema$1,
|
|
52161
|
+
deviceId: string()
|
|
52162
|
+
});
|
|
51456
52163
|
/**
|
|
51457
52164
|
* What an exporter may expose besides devices (D968). An action and a
|
|
51458
52165
|
* notification target are LIST ENTRIES, never devices (D954): they enter an
|
|
@@ -51481,8 +52188,14 @@ var ExposedEntitySchema = object({
|
|
|
51481
52188
|
entity: ExportEntityRefSchema,
|
|
51482
52189
|
exposedAs: string().optional()
|
|
51483
52190
|
});
|
|
51484
|
-
var ExposeEntityInputSchema = object({
|
|
51485
|
-
|
|
52191
|
+
var ExposeEntityInputSchema = object({
|
|
52192
|
+
instanceId: InstanceIdSchema$1,
|
|
52193
|
+
entity: ExportEntityRefSchema
|
|
52194
|
+
});
|
|
52195
|
+
var UnexposeEntityInputSchema = object({
|
|
52196
|
+
instanceId: InstanceIdSchema$1,
|
|
52197
|
+
entity: ExportEntityRefSchema
|
|
52198
|
+
});
|
|
51486
52199
|
var deviceExportCapability = {
|
|
51487
52200
|
name: "device-export",
|
|
51488
52201
|
scope: "system",
|
|
@@ -51502,9 +52215,10 @@ var deviceExportCapability = {
|
|
|
51502
52215
|
*/
|
|
51503
52216
|
exposesDeviceSettings: true,
|
|
51504
52217
|
methods: {
|
|
51505
|
-
getStatus: method(
|
|
51506
|
-
|
|
51507
|
-
|
|
52218
|
+
getStatus: method(InstancePinSchema, DeviceExportStatusSchema),
|
|
52219
|
+
listInstances: method(_void(), array(ExportInstanceSchema)),
|
|
52220
|
+
listSupportedDeviceKinds: method(InstancePinSchema, array(DeviceKindSchema)),
|
|
52221
|
+
listExposedDevices: method(InstancePinSchema, array(ExposedDeviceSchema)),
|
|
51508
52222
|
exposeDevice: method(ExposeInputSchema, _void(), {
|
|
51509
52223
|
kind: "mutation",
|
|
51510
52224
|
auth: "admin"
|
|
@@ -51514,7 +52228,7 @@ var deviceExportCapability = {
|
|
|
51514
52228
|
auth: "admin"
|
|
51515
52229
|
}),
|
|
51516
52230
|
listSupportedEntityKinds: optionalMethod(_void(), array(ExportEntityKindSchema)),
|
|
51517
|
-
listExposedEntities: optionalMethod(
|
|
52231
|
+
listExposedEntities: optionalMethod(InstancePinSchema, array(ExposedEntitySchema)),
|
|
51518
52232
|
exposeEntity: optionalMethod(ExposeEntityInputSchema, _void(), {
|
|
51519
52233
|
kind: "mutation",
|
|
51520
52234
|
auth: "admin"
|
|
@@ -55119,15 +55833,15 @@ var FanPresetCaptureResultSchema = object({
|
|
|
55119
55833
|
items: array(FanCaptureItemSchema),
|
|
55120
55834
|
omitted: array(FanCaptureOmissionSchema)
|
|
55121
55835
|
});
|
|
55122
|
-
var deviceInput$
|
|
55836
|
+
var deviceInput$2 = object({ deviceId: number().int().nonnegative() });
|
|
55123
55837
|
DeviceType.Fan;
|
|
55124
|
-
method(deviceInput$
|
|
55838
|
+
method(deviceInput$2, array(FanPresetSchema), { auth: "protected" }), method(deviceInput$2.extend({ presets: array(FanPresetSchema).max(12) }), FanPresetsSetResultSchema, {
|
|
55125
55839
|
kind: "mutation",
|
|
55126
55840
|
auth: "admin"
|
|
55127
|
-
}), method(deviceInput$
|
|
55841
|
+
}), method(deviceInput$2.extend({ presetId: string().min(1) }), FanPresetApplyResultSchema, {
|
|
55128
55842
|
kind: "mutation",
|
|
55129
55843
|
auth: "protected"
|
|
55130
|
-
}), method(deviceInput$
|
|
55844
|
+
}), method(deviceInput$2.extend({
|
|
55131
55845
|
fields: array(FanCaptureFieldSchema).optional(),
|
|
55132
55846
|
steps: array(ActionStepSchema).max(20).default([])
|
|
55133
55847
|
}), FanPresetCaptureResultSchema, { auth: "protected" });
|
|
@@ -56038,13 +56752,50 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
56038
56752
|
*/
|
|
56039
56753
|
var ConfigSchemaPassthrough$3 = custom();
|
|
56040
56754
|
var IntegrationInstanceIdSchema = string().min(1);
|
|
56755
|
+
var IntegrationInstanceModeSchema = _enum(["single", "multiple"]);
|
|
56756
|
+
/**
|
|
56757
|
+
* One kind of instance a provider can create (an adapter, an account type). The sign-in and
|
|
56758
|
+
* connect fields follow the `broker` contract (`broker.cap.ts`): `signIn.basePath` is a
|
|
56759
|
+
* hub-relative route set speaking the sign-in contract, `connectPath` / `disconnectPath` open an
|
|
56760
|
+
* interactive account link (popup) and may carry `{{brokerId}}`, which the UI replaces with the
|
|
56761
|
+
* instance id.
|
|
56762
|
+
*/
|
|
56763
|
+
var IntegrationInstanceKindSchema = object({
|
|
56764
|
+
/** Stable id of the kind, sent back as `createInstance.kind`. */
|
|
56765
|
+
id: string().min(1),
|
|
56766
|
+
label: string().min(1),
|
|
56767
|
+
/** The kind signs in through a server-held interactive session. */
|
|
56768
|
+
signIn: object({
|
|
56769
|
+
basePath: string().min(1),
|
|
56770
|
+
methods: array(_enum(["device-code", "proxy"])).optional()
|
|
56771
|
+
}).optional(),
|
|
56772
|
+
/** Relative hub path to start an interactive account link of an instance of this kind. */
|
|
56773
|
+
connectPath: string().min(1).optional(),
|
|
56774
|
+
/** Relative hub path to disconnect that account. */
|
|
56775
|
+
disconnectPath: string().min(1).optional()
|
|
56776
|
+
});
|
|
56041
56777
|
var IntegrationInstanceDescriptionSchema = object({
|
|
56042
56778
|
/** `single`: at most one instance can exist (Loki). `multiple`: an account each. */
|
|
56043
|
-
instanceMode:
|
|
56779
|
+
instanceMode: IntegrationInstanceModeSchema,
|
|
56044
56780
|
/** What the instance is, for the UI (`destination`, `relay`, `account`). */
|
|
56045
56781
|
kind: string(),
|
|
56046
56782
|
/** True when `testInstance` really probes the remote. */
|
|
56047
|
-
canTest: boolean()
|
|
56783
|
+
canTest: boolean(),
|
|
56784
|
+
/**
|
|
56785
|
+
* The kinds an instance can be of. Absent or one entry: nothing to choose; more than one: the
|
|
56786
|
+
* Add flow asks which first and sends it as `createInstance.kind`.
|
|
56787
|
+
*/
|
|
56788
|
+
kinds: array(IntegrationInstanceKindSchema).optional(),
|
|
56789
|
+
/**
|
|
56790
|
+
* The provider accepts `createInstance.id` for an id that once existed (an adopted id, because
|
|
56791
|
+
* devices carry it). The UI then offers "restore under its old id" on Add. Absent means no.
|
|
56792
|
+
*/
|
|
56793
|
+
allowRestoreId: boolean().optional(),
|
|
56794
|
+
/**
|
|
56795
|
+
* `createInstance` without an `id` works: the provider mints it. Absent means the caller must
|
|
56796
|
+
* send an id (the UI then mints an opaque one).
|
|
56797
|
+
*/
|
|
56798
|
+
mintsId: boolean().optional()
|
|
56048
56799
|
});
|
|
56049
56800
|
var IntegrationInstanceStatusSchema = object({
|
|
56050
56801
|
state: _enum([
|
|
@@ -56053,7 +56804,9 @@ var IntegrationInstanceStatusSchema = object({
|
|
|
56053
56804
|
"error",
|
|
56054
56805
|
"unknown"
|
|
56055
56806
|
]),
|
|
56056
|
-
detail: string().optional()
|
|
56807
|
+
detail: string().optional(),
|
|
56808
|
+
/** A short human word for the state ("Signed in", "Token expired"); shown instead of `state`. */
|
|
56809
|
+
label: string().optional()
|
|
56057
56810
|
});
|
|
56058
56811
|
var IntegrationInstanceSchema = object({
|
|
56059
56812
|
id: IntegrationInstanceIdSchema,
|
|
@@ -56065,9 +56818,13 @@ var IntegrationInstanceSchema = object({
|
|
|
56065
56818
|
* (`enabled !== false`, so a row written before the field existed is on).
|
|
56066
56819
|
*/
|
|
56067
56820
|
enabled: boolean(),
|
|
56821
|
+
/** The kind of this instance (one of `describe().kinds[].id`), when the provider has kinds. */
|
|
56822
|
+
kind: string().optional(),
|
|
56068
56823
|
/** Values for the instance form; a secret is a `SecretFieldView`, never text. */
|
|
56069
56824
|
formValues: record(string(), unknown()),
|
|
56070
|
-
status: IntegrationInstanceStatusSchema.optional()
|
|
56825
|
+
status: IntegrationInstanceStatusSchema.optional(),
|
|
56826
|
+
/** Epoch ms of the last probe of the remote that produced `status`; absent when never checked. */
|
|
56827
|
+
lastCheckedAt: number().optional()
|
|
56071
56828
|
});
|
|
56072
56829
|
var IntegrationInstancePatchSchema = object({
|
|
56073
56830
|
id: IntegrationInstanceIdSchema,
|
|
@@ -56075,31 +56832,57 @@ var IntegrationInstancePatchSchema = object({
|
|
|
56075
56832
|
/** Omitted / '' / redaction token keeps a secret; `{ $secretClear: true }` clears it. */
|
|
56076
56833
|
values: record(string(), unknown())
|
|
56077
56834
|
});
|
|
56078
|
-
|
|
56079
|
-
|
|
56080
|
-
|
|
56081
|
-
|
|
56082
|
-
|
|
56083
|
-
|
|
56084
|
-
|
|
56085
|
-
|
|
56086
|
-
|
|
56087
|
-
|
|
56088
|
-
|
|
56089
|
-
|
|
56090
|
-
|
|
56091
|
-
|
|
56092
|
-
|
|
56093
|
-
|
|
56094
|
-
|
|
56095
|
-
|
|
56096
|
-
}),
|
|
56097
|
-
|
|
56098
|
-
|
|
56099
|
-
}),
|
|
56100
|
-
|
|
56101
|
-
|
|
56102
|
-
|
|
56835
|
+
var integrationInstancesCapability = {
|
|
56836
|
+
name: "integration-instances",
|
|
56837
|
+
scope: "system",
|
|
56838
|
+
mode: "collection",
|
|
56839
|
+
methods: {
|
|
56840
|
+
describe: method(_void(), IntegrationInstanceDescriptionSchema, { auth: "admin" }),
|
|
56841
|
+
/** The form; `id: null` is the create form. */
|
|
56842
|
+
instanceFormSchema: method(object({ id: IntegrationInstanceIdSchema.nullable() }), ConfigSchemaPassthrough$3, { auth: "admin" }),
|
|
56843
|
+
listInstances: method(_void(), array(IntegrationInstanceSchema).readonly(), { auth: "admin" }),
|
|
56844
|
+
getInstance: method(object({ id: IntegrationInstanceIdSchema }), IntegrationInstanceSchema.nullable(), { auth: "admin" }),
|
|
56845
|
+
/**
|
|
56846
|
+
* Insert the typed record. With `id` it is stored under that id (a duplicate id is refused);
|
|
56847
|
+
* without one the PROVIDER mints it and answers it. `kind` picks one of `describe().kinds`.
|
|
56848
|
+
*/
|
|
56849
|
+
createInstance: method(object({
|
|
56850
|
+
id: IntegrationInstanceIdSchema.optional(),
|
|
56851
|
+
name: string().min(1),
|
|
56852
|
+
kind: string().min(1).optional()
|
|
56853
|
+
}), object({ id: string() }), {
|
|
56854
|
+
kind: "mutation",
|
|
56855
|
+
auth: "admin"
|
|
56856
|
+
}),
|
|
56857
|
+
updateInstance: method(IntegrationInstancePatchSchema, object({ ok: literal(true) }), {
|
|
56858
|
+
kind: "mutation",
|
|
56859
|
+
auth: "admin"
|
|
56860
|
+
}),
|
|
56861
|
+
/**
|
|
56862
|
+
* Switch ONE instance on or off. A row control, not a form field: `updateInstance.values` is the
|
|
56863
|
+
* form patch (D62, D996). An off instance keeps its record and secrets and does no work.
|
|
56864
|
+
*/
|
|
56865
|
+
setInstanceEnabled: method(object({
|
|
56866
|
+
id: IntegrationInstanceIdSchema,
|
|
56867
|
+
enabled: boolean()
|
|
56868
|
+
}), object({ ok: literal(true) }), {
|
|
56869
|
+
kind: "mutation",
|
|
56870
|
+
auth: "admin"
|
|
56871
|
+
}),
|
|
56872
|
+
/** Delete the record and its keychain refs together. */
|
|
56873
|
+
deleteInstance: method(object({ id: IntegrationInstanceIdSchema }), object({ ok: literal(true) }), {
|
|
56874
|
+
kind: "mutation",
|
|
56875
|
+
auth: "admin"
|
|
56876
|
+
}),
|
|
56877
|
+
testInstance: optionalMethod(object({
|
|
56878
|
+
id: IntegrationInstanceIdSchema.nullable(),
|
|
56879
|
+
values: record(string(), unknown())
|
|
56880
|
+
}), TestConnectionResultSchema$1, {
|
|
56881
|
+
kind: "mutation",
|
|
56882
|
+
auth: "admin"
|
|
56883
|
+
})
|
|
56884
|
+
}
|
|
56885
|
+
};
|
|
56103
56886
|
/**
|
|
56104
56887
|
* Two-way audio / talk-back cap. Clients open a WebRTC audio-only
|
|
56105
56888
|
* session (server-initiated offer pattern, identical to the main
|
|
@@ -58117,6 +58900,11 @@ var LogEntrySchema = object({
|
|
|
58117
58900
|
* flight, and not asking for the next slice ends the scan.
|
|
58118
58901
|
*/
|
|
58119
58902
|
var LogReadQuerySchema = object({
|
|
58903
|
+
/**
|
|
58904
|
+
* Which destination INSTANCE answers (a destination addon may hold several records). Absent ⇒
|
|
58905
|
+
* the provider's first readable one, so a caller written before instances existed is unchanged.
|
|
58906
|
+
*/
|
|
58907
|
+
instanceId: string().min(1).max(200).optional(),
|
|
58120
58908
|
/** Correlates `cancelRead`. Caller-chosen, unique per in-flight read. */
|
|
58121
58909
|
requestId: string().min(1).max(64).optional(),
|
|
58122
58910
|
/** The device the line is about (`tags.deviceId`, numeric). */
|
|
@@ -58179,6 +58967,8 @@ var LogReadResultSchema = object({
|
|
|
58179
58967
|
/** True when `cancelRead` ended this slice early. */
|
|
58180
58968
|
cancelled: boolean().optional()
|
|
58181
58969
|
});
|
|
58970
|
+
/** Names one destination instance; absent ⇒ the provider's first readable one. */
|
|
58971
|
+
var LogInstanceSelectorSchema = object({ instanceId: string().min(1).max(200).optional() });
|
|
58182
58972
|
var LogReadCapabilitiesSchema = object({
|
|
58183
58973
|
/** False ⇒ this destination only ships lines (console, forwarder, an unconfigured Loki). */
|
|
58184
58974
|
readable: boolean(),
|
|
@@ -58197,7 +58987,7 @@ var LogReadCapabilitiesSchema = object({
|
|
|
58197
58987
|
/** How far back the store reaches, when the provider knows (days). */
|
|
58198
58988
|
retentionDays: number().nullable()
|
|
58199
58989
|
});
|
|
58200
|
-
method(LogEntrySchema, _void(), { kind: "mutation" }), optionalMethod(
|
|
58990
|
+
method(LogEntrySchema, _void(), { kind: "mutation" }), optionalMethod(LogInstanceSelectorSchema, LogReadCapabilitiesSchema, { auth: "admin" }), optionalMethod(LogReadQuerySchema, LogReadResultSchema, { auth: "admin" }), optionalMethod(object({ requestId: string().min(1).max(64) }), object({ cancelled: boolean() }), {
|
|
58201
58991
|
kind: "mutation",
|
|
58202
58992
|
auth: "admin"
|
|
58203
58993
|
});
|
|
@@ -58301,214 +59091,6 @@ var LoginMethodContributionSchema = discriminatedUnion("kind", [
|
|
|
58301
59091
|
]);
|
|
58302
59092
|
method(_void(), array(LoginMethodContributionSchema).readonly());
|
|
58303
59093
|
/**
|
|
58304
|
-
* Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
|
|
58305
|
-
* Apple TV, Spotify, Roku, generic OTT receivers, …) on
|
|
58306
|
-
* `DeviceType.MediaPlayer`. Disjoint from the camera streaming
|
|
58307
|
-
* surface — those use `DeviceType.Camera` + the broker pipeline.
|
|
58308
|
-
*
|
|
58309
|
-
* The cap declares a wide method surface; not every backend supports
|
|
58310
|
-
* every method. Drivers signal sub-capability via the
|
|
58311
|
-
* `DeviceFeature.MediaPlayerXxx` flags (paired one-to-one with the
|
|
58312
|
-
* corresponding method) so the UI gates buttons without a slice
|
|
58313
|
-
* fetch — same pattern as `PanTiltZoom` for cameras.
|
|
58314
|
-
*/
|
|
58315
|
-
var MediaPlayerStateSchema = _enum([
|
|
58316
|
-
"off",
|
|
58317
|
-
"on",
|
|
58318
|
-
"idle",
|
|
58319
|
-
"playing",
|
|
58320
|
-
"paused",
|
|
58321
|
-
"buffering",
|
|
58322
|
-
"standby"
|
|
58323
|
-
]);
|
|
58324
|
-
var MediaPlayerRepeatSchema = _enum([
|
|
58325
|
-
"off",
|
|
58326
|
-
"all",
|
|
58327
|
-
"one"
|
|
58328
|
-
]);
|
|
58329
|
-
var MediaInfoSchema = object({
|
|
58330
|
-
/** Free-form media kind (`music`, `tvshow`, `movie`, `app`, `channel`,
|
|
58331
|
-
* `podcast`, …). */
|
|
58332
|
-
type: string(),
|
|
58333
|
-
/** Human-readable title. */
|
|
58334
|
-
title: string(),
|
|
58335
|
-
/** Optional artist / channel / station label. */
|
|
58336
|
-
artist: string().optional(),
|
|
58337
|
-
/** Optional album / season / show name. */
|
|
58338
|
-
album: string().optional(),
|
|
58339
|
-
/** Optional cover-art / thumbnail URL. */
|
|
58340
|
-
imageUrl: string().optional()
|
|
58341
|
-
});
|
|
58342
|
-
/**
|
|
58343
|
-
* Where `state`, `volumeLevel`, `isMuted` and `source` come from. `reported`:
|
|
58344
|
-
* the device said so. `assumed`: the driver has no feedback (infrared) and
|
|
58345
|
-
* tracks what it last SENT; it moves only after a send was accepted, and a
|
|
58346
|
-
* human at the real remote makes it wrong. A UI shows an assumed value as a
|
|
58347
|
-
* guess, never as a reading.
|
|
58348
|
-
*/
|
|
58349
|
-
var MediaPlayerStateSourceSchema = _enum(["reported", "assumed"]);
|
|
58350
|
-
/** The fields of a media-player status a driver can only guess. */
|
|
58351
|
-
var MediaPlayerAssumedFieldSchema = _enum([
|
|
58352
|
-
"state",
|
|
58353
|
-
"volumeLevel",
|
|
58354
|
-
"isMuted",
|
|
58355
|
-
"source"
|
|
58356
|
-
]);
|
|
58357
|
-
var MediaPlayerStatusSchema = object({
|
|
58358
|
-
/** Playback lifecycle state. */
|
|
58359
|
-
state: MediaPlayerStateSchema,
|
|
58360
|
-
/**
|
|
58361
|
-
* Whether the state fields are readings or the driver's own bookkeeping.
|
|
58362
|
-
* A slice written before this field existed parses as `reported`.
|
|
58363
|
-
*/
|
|
58364
|
-
stateSource: MediaPlayerStateSourceSchema.default("reported"),
|
|
58365
|
-
/**
|
|
58366
|
-
* Which fields are the driver's own guess. `stateSource` is `assumed` when
|
|
58367
|
-
* this is not empty; a field not listed here is a reading even then (power
|
|
58368
|
-
* from a running-state source, mute guessed from the last send).
|
|
58369
|
-
*/
|
|
58370
|
-
assumedFields: array(MediaPlayerAssumedFieldSchema).default([]),
|
|
58371
|
-
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
58372
|
-
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
58373
|
-
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58374
|
-
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
58375
|
-
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
58376
|
-
isMuted: boolean().nullable(),
|
|
58377
|
-
/** Active source / input. Empty when no source surface. */
|
|
58378
|
-
source: string(),
|
|
58379
|
-
/** Selectable sources. Empty when no source surface.
|
|
58380
|
-
* Pair with `DeviceFeature.MediaPlayerSelectSource`. */
|
|
58381
|
-
availableSources: array(string()),
|
|
58382
|
-
/** Currently-playing media info. Null when nothing is playing. */
|
|
58383
|
-
currentMedia: MediaInfoSchema.nullable(),
|
|
58384
|
-
/** Current playback position in ms. Null when not seekable or
|
|
58385
|
-
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
58386
|
-
position: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
58387
|
-
/** Total duration of the current media in ms. Null when unknown
|
|
58388
|
-
* (live stream) or nothing is playing. */
|
|
58389
|
-
duration: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
58390
|
-
/** Shuffle toggle. Null when no shuffle surface.
|
|
58391
|
-
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
58392
|
-
shuffle: boolean().nullable(),
|
|
58393
|
-
/** Repeat mode. Null when no repeat surface.
|
|
58394
|
-
* Pair with `DeviceFeature.MediaPlayerRepeat`. */
|
|
58395
|
-
repeat: MediaPlayerRepeatSchema.nullable(),
|
|
58396
|
-
/** Ms epoch when the slice was last updated. */
|
|
58397
|
-
lastChangedAt: number()
|
|
58398
|
-
});
|
|
58399
|
-
var mediaPlayerCapability = {
|
|
58400
|
-
name: "media-player",
|
|
58401
|
-
scope: "device",
|
|
58402
|
-
deviceNative: true,
|
|
58403
|
-
mode: "singleton",
|
|
58404
|
-
deviceTypes: [DeviceType.MediaPlayer],
|
|
58405
|
-
methods: {
|
|
58406
|
-
play: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
58407
|
-
kind: "mutation",
|
|
58408
|
-
auth: "protected"
|
|
58409
|
-
}),
|
|
58410
|
-
pause: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
58411
|
-
kind: "mutation",
|
|
58412
|
-
auth: "protected"
|
|
58413
|
-
}),
|
|
58414
|
-
stop: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
58415
|
-
kind: "mutation",
|
|
58416
|
-
auth: "protected"
|
|
58417
|
-
}),
|
|
58418
|
-
next: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
58419
|
-
kind: "mutation",
|
|
58420
|
-
auth: "protected"
|
|
58421
|
-
}),
|
|
58422
|
-
previous: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
58423
|
-
kind: "mutation",
|
|
58424
|
-
auth: "protected"
|
|
58425
|
-
}),
|
|
58426
|
-
seek: method(object({
|
|
58427
|
-
deviceId: number().int().nonnegative(),
|
|
58428
|
-
position: number().int().nonnegative()
|
|
58429
|
-
}), _void(), {
|
|
58430
|
-
kind: "mutation",
|
|
58431
|
-
auth: "protected"
|
|
58432
|
-
}),
|
|
58433
|
-
setVolume: method(object({
|
|
58434
|
-
deviceId: number().int().nonnegative(),
|
|
58435
|
-
volumeLevel: number().min(0).max(100)
|
|
58436
|
-
}), _void(), {
|
|
58437
|
-
kind: "mutation",
|
|
58438
|
-
auth: "protected"
|
|
58439
|
-
}),
|
|
58440
|
-
setMute: method(object({
|
|
58441
|
-
deviceId: number().int().nonnegative(),
|
|
58442
|
-
muted: boolean()
|
|
58443
|
-
}), _void(), {
|
|
58444
|
-
kind: "mutation",
|
|
58445
|
-
auth: "protected"
|
|
58446
|
-
}),
|
|
58447
|
-
setShuffle: method(object({
|
|
58448
|
-
deviceId: number().int().nonnegative(),
|
|
58449
|
-
shuffle: boolean()
|
|
58450
|
-
}), _void(), {
|
|
58451
|
-
kind: "mutation",
|
|
58452
|
-
auth: "protected"
|
|
58453
|
-
}),
|
|
58454
|
-
setRepeat: method(object({
|
|
58455
|
-
deviceId: number().int().nonnegative(),
|
|
58456
|
-
repeat: MediaPlayerRepeatSchema
|
|
58457
|
-
}), _void(), {
|
|
58458
|
-
kind: "mutation",
|
|
58459
|
-
auth: "protected"
|
|
58460
|
-
}),
|
|
58461
|
-
selectSource: method(object({
|
|
58462
|
-
deviceId: number().int().nonnegative(),
|
|
58463
|
-
source: string().min(1)
|
|
58464
|
-
}), _void(), {
|
|
58465
|
-
kind: "mutation",
|
|
58466
|
-
auth: "protected"
|
|
58467
|
-
}),
|
|
58468
|
-
playMedia: method(object({
|
|
58469
|
-
deviceId: number().int().nonnegative(),
|
|
58470
|
-
/** Media identifier / URL. */
|
|
58471
|
-
mediaId: string().min(1),
|
|
58472
|
-
/** Media kind (`music`, `tvshow`, `movie`, `app`, …) — provider
|
|
58473
|
-
* passes it through to the upstream service. */
|
|
58474
|
-
mediaType: string().min(1)
|
|
58475
|
-
}), _void(), {
|
|
58476
|
-
kind: "mutation",
|
|
58477
|
-
auth: "protected"
|
|
58478
|
-
})
|
|
58479
|
-
},
|
|
58480
|
-
status: {
|
|
58481
|
-
schema: MediaPlayerStatusSchema,
|
|
58482
|
-
kind: "push"
|
|
58483
|
-
},
|
|
58484
|
-
/**
|
|
58485
|
-
* Runtime-state slice — mirrored by the kernel. UI players read the
|
|
58486
|
-
* full slice for live now-playing, volume, and progress updates
|
|
58487
|
-
* without polling.
|
|
58488
|
-
*/
|
|
58489
|
-
runtimeState: MediaPlayerStatusSchema,
|
|
58490
|
-
/**
|
|
58491
|
-
* Runtime-state durability: **session** — a restored transport position describes a playback that stopped when the hub did.
|
|
58492
|
-
*
|
|
58493
|
-
* See `RuntimeStateDurability`. Enforced by
|
|
58494
|
-
* `scripts/check-runtime-state-durability.ts`.
|
|
58495
|
-
*/
|
|
58496
|
-
durability: "session",
|
|
58497
|
-
/**
|
|
58498
|
-
* History (D850): volume (a level an operator or an automation sets; the
|
|
58499
|
-
* default 10 s floor folds a slider drag into its end value) and mute.
|
|
58500
|
-
* `position` is not recorded: it moves continuously while playing.
|
|
58501
|
-
*/
|
|
58502
|
-
history: { fields: {
|
|
58503
|
-
volumeLevel: {
|
|
58504
|
-
kind: "gauge",
|
|
58505
|
-
unit: "%",
|
|
58506
|
-
deadband: 1
|
|
58507
|
-
},
|
|
58508
|
-
isMuted: { kind: "boolean" }
|
|
58509
|
-
} }
|
|
58510
|
-
};
|
|
58511
|
-
/**
|
|
58512
59094
|
* mesh-network — collection cap for mesh-VPN providers.
|
|
58513
59095
|
*
|
|
58514
59096
|
* Different shape from `network-access` (public tunnels):
|
|
@@ -70748,6 +71330,14 @@ var powerMeterCapability = {
|
|
|
70748
71330
|
deviceNative: true,
|
|
70749
71331
|
mode: "singleton",
|
|
70750
71332
|
deviceTypes: POWER_METER_DEVICE_TYPES,
|
|
71333
|
+
deviceConfig: { ui: {
|
|
71334
|
+
kind: "widget",
|
|
71335
|
+
widgetId: "host/power-meter-line",
|
|
71336
|
+
tab: "power",
|
|
71337
|
+
placement: "hero",
|
|
71338
|
+
label: "Power",
|
|
71339
|
+
order: 4
|
|
71340
|
+
} },
|
|
70751
71341
|
methods: {},
|
|
70752
71342
|
status: {
|
|
70753
71343
|
schema: PowerMeterStatusSchema,
|
|
@@ -70807,6 +71397,117 @@ var powerMeterCapability = {
|
|
|
70807
71397
|
volatileStateFields: ["lastFetchedAt"],
|
|
70808
71398
|
customize: powerMeterCustomize
|
|
70809
71399
|
};
|
|
71400
|
+
var PowerSourceRefusalReasonSchema = _enum([
|
|
71401
|
+
"no-power-source",
|
|
71402
|
+
"switch-missing",
|
|
71403
|
+
"switch-offline",
|
|
71404
|
+
"switch-unknown",
|
|
71405
|
+
"restart-in-progress",
|
|
71406
|
+
"switch-call-failed"
|
|
71407
|
+
]);
|
|
71408
|
+
var PowerSourceActionResultSchema = discriminatedUnion("accepted", [object({ accepted: literal(true) }), object({
|
|
71409
|
+
accepted: literal(false),
|
|
71410
|
+
reason: PowerSourceRefusalReasonSchema,
|
|
71411
|
+
/** One line for the operator, naming the switch. */
|
|
71412
|
+
message: string()
|
|
71413
|
+
})]);
|
|
71414
|
+
var PowerSourceInfoSchema = object({
|
|
71415
|
+
/** False when the device has no power source linked; the rest is then empty. */
|
|
71416
|
+
linked: boolean(),
|
|
71417
|
+
switchDeviceId: number().nullable(),
|
|
71418
|
+
switchName: string().nullable(),
|
|
71419
|
+
/** The switch's on/off state, or null when it is unknown. Never false for unknown (D393). */
|
|
71420
|
+
switchOn: boolean().nullable(),
|
|
71421
|
+
switchOnline: boolean().nullable(),
|
|
71422
|
+
restartInProgress: boolean(),
|
|
71423
|
+
offSeconds: number().int()
|
|
71424
|
+
});
|
|
71425
|
+
/** The composed slice: the switch state the link mirrors, plus the stored off time. */
|
|
71426
|
+
var PowerSourceStateSchema = object({
|
|
71427
|
+
/** Null while the switch has not reported: unknown is never `false` (D393). */
|
|
71428
|
+
switchOn: boolean().nullable(),
|
|
71429
|
+
offSeconds: number().int(),
|
|
71430
|
+
lastFetchedAt: number()
|
|
71431
|
+
});
|
|
71432
|
+
var POWER_SOURCE_DEVICE_TYPES = [
|
|
71433
|
+
DeviceType.Gateway,
|
|
71434
|
+
DeviceType.Hub,
|
|
71435
|
+
DeviceType.Camera,
|
|
71436
|
+
DeviceType.Sensor,
|
|
71437
|
+
DeviceType.MediaPlayer,
|
|
71438
|
+
DeviceType.Vacuum,
|
|
71439
|
+
DeviceType.Generic,
|
|
71440
|
+
DeviceType.Washer,
|
|
71441
|
+
DeviceType.Dryer,
|
|
71442
|
+
DeviceType.Dishwasher,
|
|
71443
|
+
DeviceType.PetFountain,
|
|
71444
|
+
DeviceType.Fan,
|
|
71445
|
+
DeviceType.Humidifier,
|
|
71446
|
+
DeviceType.Climate,
|
|
71447
|
+
DeviceType.WaterHeater
|
|
71448
|
+
];
|
|
71449
|
+
var powerSourceCustomize = {
|
|
71450
|
+
version: 1,
|
|
71451
|
+
targets: [{
|
|
71452
|
+
id: "switch",
|
|
71453
|
+
cardinality: "scalar",
|
|
71454
|
+
vocabulary: {
|
|
71455
|
+
cap: "power-source",
|
|
71456
|
+
stateField: "switchOn"
|
|
71457
|
+
},
|
|
71458
|
+
deviceTypes: POWER_SOURCE_DEVICE_TYPES,
|
|
71459
|
+
apply: "add",
|
|
71460
|
+
path: "switchOn",
|
|
71461
|
+
sources: [{
|
|
71462
|
+
kind: "switch",
|
|
71463
|
+
transforms: [{ kind: "identity" }]
|
|
71464
|
+
}],
|
|
71465
|
+
companions: [{
|
|
71466
|
+
kind: "constant",
|
|
71467
|
+
path: "offSeconds",
|
|
71468
|
+
value: 10,
|
|
71469
|
+
when: "add"
|
|
71470
|
+
}, {
|
|
71471
|
+
kind: "clock",
|
|
71472
|
+
path: "lastFetchedAt",
|
|
71473
|
+
when: "always"
|
|
71474
|
+
}],
|
|
71475
|
+
sourceReport: { status: "assignment-status" }
|
|
71476
|
+
}]
|
|
71477
|
+
};
|
|
71478
|
+
var deviceInput$1 = object({ deviceId: number().int().nonnegative() });
|
|
71479
|
+
var powerSourceCapability = {
|
|
71480
|
+
name: "power-source",
|
|
71481
|
+
scope: "device",
|
|
71482
|
+
mode: "singleton",
|
|
71483
|
+
deviceTypes: POWER_SOURCE_DEVICE_TYPES,
|
|
71484
|
+
methods: {
|
|
71485
|
+
getStatus: systemMethod(deviceInput$1, PowerSourceInfoSchema, { auth: "admin" }),
|
|
71486
|
+
powerOn: systemMethod(deviceInput$1, PowerSourceActionResultSchema, {
|
|
71487
|
+
kind: "mutation",
|
|
71488
|
+
auth: "admin"
|
|
71489
|
+
}),
|
|
71490
|
+
powerOff: systemMethod(deviceInput$1, PowerSourceActionResultSchema, {
|
|
71491
|
+
kind: "mutation",
|
|
71492
|
+
auth: "admin"
|
|
71493
|
+
}),
|
|
71494
|
+
forceRestart: systemMethod(deviceInput$1, PowerSourceActionResultSchema, {
|
|
71495
|
+
kind: "mutation",
|
|
71496
|
+
auth: "admin"
|
|
71497
|
+
})
|
|
71498
|
+
},
|
|
71499
|
+
runtimeState: PowerSourceStateSchema,
|
|
71500
|
+
customize: powerSourceCustomize,
|
|
71501
|
+
/**
|
|
71502
|
+
* Runtime-state durability: **session** — mirrored from the linked switch on
|
|
71503
|
+
* its next report; a restored value would outlive the reading it names.
|
|
71504
|
+
*
|
|
71505
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
71506
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
71507
|
+
*/
|
|
71508
|
+
durability: "session",
|
|
71509
|
+
history: "none"
|
|
71510
|
+
};
|
|
70810
71511
|
/**
|
|
70811
71512
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
70812
71513
|
* on `DeviceType.Presence`. Read-only — no setters: presence is
|
|
@@ -74309,7 +75010,13 @@ var RemoteMediaCommandSchema = _enum([
|
|
|
74309
75010
|
"next",
|
|
74310
75011
|
"previous",
|
|
74311
75012
|
"setMute",
|
|
74312
|
-
"selectSource"
|
|
75013
|
+
"selectSource",
|
|
75014
|
+
"turnOn",
|
|
75015
|
+
"turnOff",
|
|
75016
|
+
"volumeUp",
|
|
75017
|
+
"volumeDown",
|
|
75018
|
+
"channelUp",
|
|
75019
|
+
"channelDown"
|
|
74313
75020
|
]);
|
|
74314
75021
|
/** A send result, or `not-routed`: the role is not bound, so the native cap answers. */
|
|
74315
75022
|
var RemoteMediaCommandResultSchema = discriminatedUnion("status", [...RemoteSendResultSchema.options, object({ status: literal("not-routed") })]);
|
|
@@ -74330,7 +75037,7 @@ method(deviceInput, RemoteConfigSchema, { auth: "admin" }), method(deviceInput.e
|
|
|
74330
75037
|
}), RemoteSendResultSchema, {
|
|
74331
75038
|
kind: "mutation",
|
|
74332
75039
|
auth: "protected"
|
|
74333
|
-
}), method(deviceInput.extend({
|
|
75040
|
+
}), method(deviceInput, MediaPlayerStatusSchema.nullable(), { auth: "protected" }), method(deviceInput.extend({
|
|
74334
75041
|
command: RemoteMediaCommandSchema,
|
|
74335
75042
|
muted: boolean().optional(),
|
|
74336
75043
|
source: string().optional(),
|
|
@@ -76584,7 +77291,11 @@ listSignals: method(_void(), array(StreamSignalSchema).readonly()) }
|
|
|
76584
77291
|
* `getSettingsUISchema()` surface.
|
|
76585
77292
|
*/
|
|
76586
77293
|
var SwitchStatusSchema = object({
|
|
76587
|
-
|
|
77294
|
+
/**
|
|
77295
|
+
* `null` = the device has never reported its state (a measurement that
|
|
77296
|
+
* has not happened is unknown, never `false`).
|
|
77297
|
+
*/
|
|
77298
|
+
on: boolean().nullable().meta({ label: "On" }),
|
|
76588
77299
|
/** Ms epoch of the last state change. Useful for UI "X minutes ago". */
|
|
76589
77300
|
lastChangedAt: number()
|
|
76590
77301
|
});
|
|
@@ -76609,7 +77320,7 @@ var switchCapability = {
|
|
|
76609
77320
|
}) },
|
|
76610
77321
|
events: { onStateChanged: { data: object({
|
|
76611
77322
|
deviceId: number(),
|
|
76612
|
-
on: boolean(),
|
|
77323
|
+
on: boolean().nullable(),
|
|
76613
77324
|
lastChangedAt: number()
|
|
76614
77325
|
}) } },
|
|
76615
77326
|
status: {
|
|
@@ -80292,6 +81003,26 @@ function buildDescriptor(capName, kind) {
|
|
|
80292
81003
|
* contributes one entry per bound cap present in this map.
|
|
80293
81004
|
*/
|
|
80294
81005
|
var EVENT_KIND_BY_CAP = Object.freeze(Object.fromEntries(Object.entries(CAP_TO_KIND).map(([capName, kind]) => [capName, buildDescriptor(capName, kind)])));
|
|
81006
|
+
/**
|
|
81007
|
+
* What a remote key is CALLED and what it LOOKS like, for every role (D963),
|
|
81008
|
+
* shared by the admin UI and the viewer. A role is data on the wire; each
|
|
81009
|
+
* client resolves its name from `label` (English and Italian side by side) and
|
|
81010
|
+
* its glyph from `icon`, a lucide id from the shared icon catalogue — the
|
|
81011
|
+
* server sends an id, a client maps it to its own icon set.
|
|
81012
|
+
*
|
|
81013
|
+
* `legend` is text printed on the key INSTEAD of a glyph (a digit has no
|
|
81014
|
+
* pictogram): a client that can draw text shows it, one that cannot falls back
|
|
81015
|
+
* to `icon`.
|
|
81016
|
+
*/
|
|
81017
|
+
function digit(n) {
|
|
81018
|
+
return {
|
|
81019
|
+
label: t(n, n),
|
|
81020
|
+
icon: "hash",
|
|
81021
|
+
legend: n
|
|
81022
|
+
};
|
|
81023
|
+
}
|
|
81024
|
+
digit("0"), digit("1"), digit("2"), digit("3"), digit("4"), digit("5"), digit("6"), digit("7"), digit("8"), digit("9");
|
|
81025
|
+
DeviceFeature.MediaPlayerPower, DeviceFeature.MediaPlayerVolumeStep, DeviceFeature.MediaPlayerChannelStep, DeviceFeature.MediaPlayerMute, DeviceFeature.MediaPlayerStop, DeviceFeature.MediaPlayerNext, DeviceFeature.MediaPlayerPrevious;
|
|
80295
81026
|
var btn = (idSuffix, row, col, init) => ({
|
|
80296
81027
|
idSuffix,
|
|
80297
81028
|
row,
|
|
@@ -80455,6 +81186,34 @@ function runningFromMediaPlayer(state, previous, fetchedAt, transitionAt) {
|
|
|
80455
81186
|
if (state === "paused") return nativeSlice(false, "paused", previous, transitionAtMs, fetchedAt, null);
|
|
80456
81187
|
return nativeSlice(false, state, previous, transitionAtMs, fetchedAt, null);
|
|
80457
81188
|
}
|
|
81189
|
+
/**
|
|
81190
|
+
* Propose a running threshold from a device's own power history (planning#405).
|
|
81191
|
+
*
|
|
81192
|
+
* Pure and deterministic: the same series gives the same answer. The series is
|
|
81193
|
+
* a HELD-VALUE step series — a point's value stands until the next point — which
|
|
81194
|
+
* is how device-history stores a gauge, so "time at a level" is exact, not a
|
|
81195
|
+
* count of samples.
|
|
81196
|
+
*
|
|
81197
|
+
* 1. idle floor F = time-weighted median; noise ceiling N = highest value seen
|
|
81198
|
+
* near F. A device that is not near one level most of the time has no floor.
|
|
81199
|
+
* 2. coarse activity = above max(2N, N + 5 W); consecutive stretches are episodes.
|
|
81200
|
+
* 3. gaps between episodes split in two by the largest log-scale jump (>= 3x):
|
|
81201
|
+
* the short ones are pauses INSIDE a run (a soak), the long ones separate runs.
|
|
81202
|
+
* 4. T = geometric mean of N and the plateau's 10th percentile, snapped to a
|
|
81203
|
+
* grid a person would type; stop dwell covers the longest pause; start dwell
|
|
81204
|
+
* covers the longest standby blip above T.
|
|
81205
|
+
* 5. the numbers are proved by REPLAY through the real `dwell` evaluation: each
|
|
81206
|
+
* run must hold exactly one true interval and nothing may flap outside.
|
|
81207
|
+
*/
|
|
81208
|
+
var SECOND_MS = 1e3;
|
|
81209
|
+
var MINUTE_MS$1 = 60 * SECOND_MS;
|
|
81210
|
+
24 * (60 * MINUTE_MS$1);
|
|
81211
|
+
10 * MINUTE_MS$1;
|
|
81212
|
+
30 * SECOND_MS;
|
|
81213
|
+
60 * SECOND_MS;
|
|
81214
|
+
20 * MINUTE_MS$1;
|
|
81215
|
+
10 * SECOND_MS;
|
|
81216
|
+
10 * SECOND_MS;
|
|
80458
81217
|
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverStoppable, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
80459
81218
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
80460
81219
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
@@ -83560,6 +84319,13 @@ Object.freeze({
|
|
|
83560
84319
|
access: "create",
|
|
83561
84320
|
role: "admin"
|
|
83562
84321
|
},
|
|
84322
|
+
"coreBlocks.proposeRunningThreshold": {
|
|
84323
|
+
capName: "core-blocks",
|
|
84324
|
+
capScope: "system",
|
|
84325
|
+
addonId: null,
|
|
84326
|
+
access: "view",
|
|
84327
|
+
role: "admin"
|
|
84328
|
+
},
|
|
83563
84329
|
"coreBlocks.reportAutomationRun": {
|
|
83564
84330
|
capName: "core-blocks",
|
|
83565
84331
|
capScope: "system",
|
|
@@ -84071,6 +84837,13 @@ Object.freeze({
|
|
|
84071
84837
|
access: "view",
|
|
84072
84838
|
role: "admin"
|
|
84073
84839
|
},
|
|
84840
|
+
"deviceExport.listInstances": {
|
|
84841
|
+
capName: "device-export",
|
|
84842
|
+
capScope: "system",
|
|
84843
|
+
addonId: null,
|
|
84844
|
+
access: "view",
|
|
84845
|
+
role: "admin"
|
|
84846
|
+
},
|
|
84074
84847
|
"deviceExport.listSupportedDeviceKinds": {
|
|
84075
84848
|
capName: "device-export",
|
|
84076
84849
|
capScope: "system",
|
|
@@ -86507,6 +87280,20 @@ Object.freeze({
|
|
|
86507
87280
|
access: "view",
|
|
86508
87281
|
role: "admin"
|
|
86509
87282
|
},
|
|
87283
|
+
"mediaPlayer.channelDown": {
|
|
87284
|
+
capName: "media-player",
|
|
87285
|
+
capScope: "device",
|
|
87286
|
+
addonId: null,
|
|
87287
|
+
access: "create",
|
|
87288
|
+
role: "viewer"
|
|
87289
|
+
},
|
|
87290
|
+
"mediaPlayer.channelUp": {
|
|
87291
|
+
capName: "media-player",
|
|
87292
|
+
capScope: "device",
|
|
87293
|
+
addonId: null,
|
|
87294
|
+
access: "create",
|
|
87295
|
+
role: "viewer"
|
|
87296
|
+
},
|
|
86510
87297
|
"mediaPlayer.getStatus": {
|
|
86511
87298
|
capName: "media-player",
|
|
86512
87299
|
capScope: "device",
|
|
@@ -86598,6 +87385,34 @@ Object.freeze({
|
|
|
86598
87385
|
access: "create",
|
|
86599
87386
|
role: "viewer"
|
|
86600
87387
|
},
|
|
87388
|
+
"mediaPlayer.turnOff": {
|
|
87389
|
+
capName: "media-player",
|
|
87390
|
+
capScope: "device",
|
|
87391
|
+
addonId: null,
|
|
87392
|
+
access: "create",
|
|
87393
|
+
role: "viewer"
|
|
87394
|
+
},
|
|
87395
|
+
"mediaPlayer.turnOn": {
|
|
87396
|
+
capName: "media-player",
|
|
87397
|
+
capScope: "device",
|
|
87398
|
+
addonId: null,
|
|
87399
|
+
access: "create",
|
|
87400
|
+
role: "viewer"
|
|
87401
|
+
},
|
|
87402
|
+
"mediaPlayer.volumeDown": {
|
|
87403
|
+
capName: "media-player",
|
|
87404
|
+
capScope: "device",
|
|
87405
|
+
addonId: null,
|
|
87406
|
+
access: "create",
|
|
87407
|
+
role: "viewer"
|
|
87408
|
+
},
|
|
87409
|
+
"mediaPlayer.volumeUp": {
|
|
87410
|
+
capName: "media-player",
|
|
87411
|
+
capScope: "device",
|
|
87412
|
+
addonId: null,
|
|
87413
|
+
access: "create",
|
|
87414
|
+
role: "viewer"
|
|
87415
|
+
},
|
|
86601
87416
|
"meshNetwork.getStatus": {
|
|
86602
87417
|
capName: "mesh-network",
|
|
86603
87418
|
capScope: "system",
|
|
@@ -90154,6 +90969,13 @@ Object.freeze({
|
|
|
90154
90969
|
access: "create",
|
|
90155
90970
|
role: "admin"
|
|
90156
90971
|
},
|
|
90972
|
+
"remote.getAssumedStatus": {
|
|
90973
|
+
capName: "remote",
|
|
90974
|
+
capScope: "system",
|
|
90975
|
+
addonId: null,
|
|
90976
|
+
access: "view",
|
|
90977
|
+
role: "admin"
|
|
90978
|
+
},
|
|
90157
90979
|
"remote.getConfig": {
|
|
90158
90980
|
capName: "remote",
|
|
90159
90981
|
capScope: "system",
|
|
@@ -92980,6 +93802,11 @@ Object.freeze({
|
|
|
92980
93802
|
form: "single",
|
|
92981
93803
|
optional: false
|
|
92982
93804
|
}],
|
|
93805
|
+
"coreBlocks.proposeRunningThreshold": [{
|
|
93806
|
+
name: "deviceId",
|
|
93807
|
+
form: "single",
|
|
93808
|
+
optional: false
|
|
93809
|
+
}],
|
|
92983
93810
|
"cover.close": [{
|
|
92984
93811
|
name: "deviceId",
|
|
92985
93812
|
form: "single",
|
|
@@ -93831,6 +94658,16 @@ Object.freeze({
|
|
|
93831
94658
|
form: "single",
|
|
93832
94659
|
optional: true
|
|
93833
94660
|
}],
|
|
94661
|
+
"mediaPlayer.channelDown": [{
|
|
94662
|
+
name: "deviceId",
|
|
94663
|
+
form: "single",
|
|
94664
|
+
optional: false
|
|
94665
|
+
}],
|
|
94666
|
+
"mediaPlayer.channelUp": [{
|
|
94667
|
+
name: "deviceId",
|
|
94668
|
+
form: "single",
|
|
94669
|
+
optional: false
|
|
94670
|
+
}],
|
|
93834
94671
|
"mediaPlayer.getStatus": [{
|
|
93835
94672
|
name: "deviceId",
|
|
93836
94673
|
form: "single",
|
|
@@ -93896,6 +94733,26 @@ Object.freeze({
|
|
|
93896
94733
|
form: "single",
|
|
93897
94734
|
optional: false
|
|
93898
94735
|
}],
|
|
94736
|
+
"mediaPlayer.turnOff": [{
|
|
94737
|
+
name: "deviceId",
|
|
94738
|
+
form: "single",
|
|
94739
|
+
optional: false
|
|
94740
|
+
}],
|
|
94741
|
+
"mediaPlayer.turnOn": [{
|
|
94742
|
+
name: "deviceId",
|
|
94743
|
+
form: "single",
|
|
94744
|
+
optional: false
|
|
94745
|
+
}],
|
|
94746
|
+
"mediaPlayer.volumeDown": [{
|
|
94747
|
+
name: "deviceId",
|
|
94748
|
+
form: "single",
|
|
94749
|
+
optional: false
|
|
94750
|
+
}],
|
|
94751
|
+
"mediaPlayer.volumeUp": [{
|
|
94752
|
+
name: "deviceId",
|
|
94753
|
+
form: "single",
|
|
94754
|
+
optional: false
|
|
94755
|
+
}],
|
|
93899
94756
|
"meter.getStatus": [{
|
|
93900
94757
|
name: "deviceId",
|
|
93901
94758
|
form: "single",
|
|
@@ -95061,6 +95918,11 @@ Object.freeze({
|
|
|
95061
95918
|
form: "single",
|
|
95062
95919
|
optional: true
|
|
95063
95920
|
}],
|
|
95921
|
+
"remote.getAssumedStatus": [{
|
|
95922
|
+
name: "deviceId",
|
|
95923
|
+
form: "single",
|
|
95924
|
+
optional: false
|
|
95925
|
+
}],
|
|
95064
95926
|
"remote.getConfig": [{
|
|
95065
95927
|
name: "deviceId",
|
|
95066
95928
|
form: "single",
|
|
@@ -95608,99 +96470,6 @@ Object.freeze({
|
|
|
95608
96470
|
"network-access": "ingress",
|
|
95609
96471
|
"smtp-provider": "email"
|
|
95610
96472
|
});
|
|
95611
|
-
/**
|
|
95612
|
-
* A saved Customize assignment (D936). The schema is the type: callers use
|
|
95613
|
-
* `z.infer`, they do not restate the shape.
|
|
95614
|
-
*/
|
|
95615
|
-
var OverrideSourceSchema = object({
|
|
95616
|
-
addonId: string().min(1),
|
|
95617
|
-
stableId: string().min(1),
|
|
95618
|
-
cap: string().min(1),
|
|
95619
|
-
fieldPath: string().min(1)
|
|
95620
|
-
});
|
|
95621
|
-
var CustomizeTransformDraftSchema = discriminatedUnion("kind", [
|
|
95622
|
-
object({ kind: literal("identity") }),
|
|
95623
|
-
object({ kind: literal("invert") }),
|
|
95624
|
-
object({
|
|
95625
|
-
kind: literal("threshold"),
|
|
95626
|
-
comparison: _enum(["gte", "lte"]),
|
|
95627
|
-
threshold: number(),
|
|
95628
|
-
startDwellMs: number().nonnegative(),
|
|
95629
|
-
stopDwellMs: number().nonnegative()
|
|
95630
|
-
}),
|
|
95631
|
-
object({
|
|
95632
|
-
kind: literal("linear"),
|
|
95633
|
-
scale: number(),
|
|
95634
|
-
offset: number(),
|
|
95635
|
-
clampMin: number().optional(),
|
|
95636
|
-
clampMax: number().optional()
|
|
95637
|
-
}),
|
|
95638
|
-
object({
|
|
95639
|
-
kind: literal("enum-map"),
|
|
95640
|
-
mapping: record(string(), string().nullable())
|
|
95641
|
-
}),
|
|
95642
|
-
object({ kind: literal("number") })
|
|
95643
|
-
]);
|
|
95644
|
-
var ScalarOverrideDraftSchema = object({
|
|
95645
|
-
kind: literal("scalar"),
|
|
95646
|
-
cap: string().min(1),
|
|
95647
|
-
targetId: string().min(1),
|
|
95648
|
-
source: OverrideSourceSchema,
|
|
95649
|
-
transform: CustomizeTransformDraftSchema
|
|
95650
|
-
});
|
|
95651
|
-
var KeyedArrayOverrideDraftSchema = object({
|
|
95652
|
-
kind: literal("keyedArray"),
|
|
95653
|
-
cap: string().min(1),
|
|
95654
|
-
targetId: string().min(1),
|
|
95655
|
-
key: string().min(1),
|
|
95656
|
-
label: string().min(1),
|
|
95657
|
-
fieldPath: string().min(1),
|
|
95658
|
-
source: OverrideSourceSchema,
|
|
95659
|
-
transform: CustomizeTransformDraftSchema
|
|
95660
|
-
});
|
|
95661
|
-
var PulseOverrideDraftSchema = object({
|
|
95662
|
-
kind: literal("pulse"),
|
|
95663
|
-
cap: string().min(1),
|
|
95664
|
-
targetId: string().min(1),
|
|
95665
|
-
enabled: boolean(),
|
|
95666
|
-
debounceMs: number().nonnegative(),
|
|
95667
|
-
edges: array(_enum([
|
|
95668
|
-
"rising",
|
|
95669
|
-
"button",
|
|
95670
|
-
"native-event"
|
|
95671
|
-
])).min(1).optional(),
|
|
95672
|
-
sources: array(OverrideSourceSchema).min(1)
|
|
95673
|
-
});
|
|
95674
|
-
var SpanSourceDraftSchema = OverrideSourceSchema.extend({ mode: _enum([
|
|
95675
|
-
"in-addition",
|
|
95676
|
-
"confirm",
|
|
95677
|
-
"replace"
|
|
95678
|
-
]).optional() });
|
|
95679
|
-
discriminatedUnion("kind", [
|
|
95680
|
-
ScalarOverrideDraftSchema,
|
|
95681
|
-
KeyedArrayOverrideDraftSchema,
|
|
95682
|
-
PulseOverrideDraftSchema,
|
|
95683
|
-
object({
|
|
95684
|
-
kind: literal("span"),
|
|
95685
|
-
cap: string().min(1),
|
|
95686
|
-
targetId: string().min(1),
|
|
95687
|
-
timeoutMs: number().nonnegative(),
|
|
95688
|
-
cooldownMs: number().nonnegative().optional(),
|
|
95689
|
-
sources: array(SpanSourceDraftSchema)
|
|
95690
|
-
})
|
|
95691
|
-
]);
|
|
95692
|
-
object({
|
|
95693
|
-
targetId: string().min(1),
|
|
95694
|
-
configured: boolean(),
|
|
95695
|
-
source: _enum(["native", "assigned"]),
|
|
95696
|
-
state: _enum([
|
|
95697
|
-
"active",
|
|
95698
|
-
"stale",
|
|
95699
|
-
"released",
|
|
95700
|
-
"unavailable"
|
|
95701
|
-
]),
|
|
95702
|
-
reason: string().nullable()
|
|
95703
|
-
});
|
|
95704
96473
|
var G711_SCALE_CORRECTION_DB = {
|
|
95705
96474
|
PCMU: 20 * Math.log10(4),
|
|
95706
96475
|
PCMA: 20 * Math.log10(8)
|
|
@@ -97484,7 +98253,7 @@ object({
|
|
|
97484
98253
|
* short-circuits any cap the calling process already provides.
|
|
97485
98254
|
*/
|
|
97486
98255
|
/** The addon that owns the import direction, and every `ha_*` broker. */
|
|
97487
|
-
var HA_PROVIDER_ADDON_ID = "provider-homeassistant";
|
|
98256
|
+
var HA_PROVIDER_ADDON_ID$1 = "provider-homeassistant";
|
|
97488
98257
|
/** The `BrokerInfo.kind` tag the Home Assistant provider stamps. */
|
|
97489
98258
|
var HA_BROKER_KIND = "home-assistant";
|
|
97490
98259
|
/**
|
|
@@ -97498,6 +98267,54 @@ var HA_BROKER_KIND = "home-assistant";
|
|
|
97498
98267
|
async function listHomeAssistantBrokers(query) {
|
|
97499
98268
|
return (await query({})).filter((broker) => broker.kind === HA_BROKER_KIND);
|
|
97500
98269
|
}
|
|
98270
|
+
function haInstanceSettingsPortsOver(api) {
|
|
98271
|
+
const listInstances = async () => {
|
|
98272
|
+
const all = await api.list.query();
|
|
98273
|
+
const rows = [];
|
|
98274
|
+
for (const integration of all) {
|
|
98275
|
+
if (integration.addonId !== "provider-homeassistant") continue;
|
|
98276
|
+
const settings = await api.getSettings.query({ id: integration.id });
|
|
98277
|
+
const brokerId = settings["brokerId"];
|
|
98278
|
+
rows.push({
|
|
98279
|
+
integrationId: integration.id,
|
|
98280
|
+
brokerId: typeof brokerId === "string" && brokerId.length > 0 ? brokerId : null,
|
|
98281
|
+
settings
|
|
98282
|
+
});
|
|
98283
|
+
}
|
|
98284
|
+
return rows;
|
|
98285
|
+
};
|
|
98286
|
+
return {
|
|
98287
|
+
listInstances,
|
|
98288
|
+
patchInstanceSettings: async (integrationId, patch) => {
|
|
98289
|
+
if (!(await api.list.query()).some((i) => i.id === integrationId && i.addonId === "provider-homeassistant")) return false;
|
|
98290
|
+
const stored = await api.getSettings.query({ id: integrationId });
|
|
98291
|
+
await api.setSettings.mutate({
|
|
98292
|
+
id: integrationId,
|
|
98293
|
+
settings: {
|
|
98294
|
+
...stored,
|
|
98295
|
+
...patch
|
|
98296
|
+
},
|
|
98297
|
+
skipRestart: true
|
|
98298
|
+
});
|
|
98299
|
+
return true;
|
|
98300
|
+
}
|
|
98301
|
+
};
|
|
98302
|
+
}
|
|
98303
|
+
/** The brokerId → settings view of the instances: what a reader keeps per broker. */
|
|
98304
|
+
function settingsByBroker(rows) {
|
|
98305
|
+
const out = /* @__PURE__ */ new Map();
|
|
98306
|
+
for (const row of rows) if (row.brokerId !== null) out.set(row.brokerId, row.settings);
|
|
98307
|
+
return out;
|
|
98308
|
+
}
|
|
98309
|
+
/** Read the instances, or report why not and answer nothing (a reader falls back to the legacy key). */
|
|
98310
|
+
async function listInstancesOrNothing(ports, onError) {
|
|
98311
|
+
try {
|
|
98312
|
+
return await ports.listInstances();
|
|
98313
|
+
} catch (err) {
|
|
98314
|
+
onError(errMsg(err));
|
|
98315
|
+
return [];
|
|
98316
|
+
}
|
|
98317
|
+
}
|
|
97501
98318
|
//#endregion
|
|
97502
98319
|
Object.defineProperty(exports, "AlarmArmModeSchema", {
|
|
97503
98320
|
enumerable: true,
|
|
@@ -97589,6 +98406,12 @@ Object.defineProperty(exports, "EventCategory", {
|
|
|
97589
98406
|
return EventCategory;
|
|
97590
98407
|
}
|
|
97591
98408
|
});
|
|
98409
|
+
Object.defineProperty(exports, "ExportInstanceUnknownError", {
|
|
98410
|
+
enumerable: true,
|
|
98411
|
+
get: function() {
|
|
98412
|
+
return ExportInstanceUnknownError;
|
|
98413
|
+
}
|
|
98414
|
+
});
|
|
97592
98415
|
Object.defineProperty(exports, "FanDirectionSchema", {
|
|
97593
98416
|
enumerable: true,
|
|
97594
98417
|
get: function() {
|
|
@@ -97604,7 +98427,7 @@ Object.defineProperty(exports, "HA_BROKER_KIND", {
|
|
|
97604
98427
|
Object.defineProperty(exports, "HA_PROVIDER_ADDON_ID", {
|
|
97605
98428
|
enumerable: true,
|
|
97606
98429
|
get: function() {
|
|
97607
|
-
return HA_PROVIDER_ADDON_ID;
|
|
98430
|
+
return HA_PROVIDER_ADDON_ID$1;
|
|
97608
98431
|
}
|
|
97609
98432
|
});
|
|
97610
98433
|
Object.defineProperty(exports, "HvacModeSchema", {
|
|
@@ -97625,12 +98448,24 @@ Object.defineProperty(exports, "PLUG_APPLIANCE_TYPES", {
|
|
|
97625
98448
|
return PLUG_APPLIANCE_TYPES;
|
|
97626
98449
|
}
|
|
97627
98450
|
});
|
|
98451
|
+
Object.defineProperty(exports, "REDACTED_SECRET", {
|
|
98452
|
+
enumerable: true,
|
|
98453
|
+
get: function() {
|
|
98454
|
+
return REDACTED_SECRET;
|
|
98455
|
+
}
|
|
98456
|
+
});
|
|
97628
98457
|
Object.defineProperty(exports, "RUNNING_STATE_COLD", {
|
|
97629
98458
|
enumerable: true,
|
|
97630
98459
|
get: function() {
|
|
97631
98460
|
return RUNNING_STATE_COLD;
|
|
97632
98461
|
}
|
|
97633
98462
|
});
|
|
98463
|
+
Object.defineProperty(exports, "RecordIntegrationInstances", {
|
|
98464
|
+
enumerable: true,
|
|
98465
|
+
get: function() {
|
|
98466
|
+
return RecordIntegrationInstances;
|
|
98467
|
+
}
|
|
98468
|
+
});
|
|
97634
98469
|
Object.defineProperty(exports, "RecordSecretUnavailableError", {
|
|
97635
98470
|
enumerable: true,
|
|
97636
98471
|
get: function() {
|
|
@@ -97895,6 +98730,18 @@ Object.defineProperty(exports, "fanControlCapability", {
|
|
|
97895
98730
|
return fanControlCapability;
|
|
97896
98731
|
}
|
|
97897
98732
|
});
|
|
98733
|
+
Object.defineProperty(exports, "flattenNestedRecords", {
|
|
98734
|
+
enumerable: true,
|
|
98735
|
+
get: function() {
|
|
98736
|
+
return flattenNestedRecords;
|
|
98737
|
+
}
|
|
98738
|
+
});
|
|
98739
|
+
Object.defineProperty(exports, "flattenPortsOver", {
|
|
98740
|
+
enumerable: true,
|
|
98741
|
+
get: function() {
|
|
98742
|
+
return flattenPortsOver;
|
|
98743
|
+
}
|
|
98744
|
+
});
|
|
97898
98745
|
Object.defineProperty(exports, "floodCapability", {
|
|
97899
98746
|
enumerable: true,
|
|
97900
98747
|
get: function() {
|
|
@@ -97907,6 +98754,12 @@ Object.defineProperty(exports, "gasCapability", {
|
|
|
97907
98754
|
return gasCapability;
|
|
97908
98755
|
}
|
|
97909
98756
|
});
|
|
98757
|
+
Object.defineProperty(exports, "haInstanceSettingsPortsOver", {
|
|
98758
|
+
enumerable: true,
|
|
98759
|
+
get: function() {
|
|
98760
|
+
return haInstanceSettingsPortsOver;
|
|
98761
|
+
}
|
|
98762
|
+
});
|
|
97910
98763
|
Object.defineProperty(exports, "humidifierCapability", {
|
|
97911
98764
|
enumerable: true,
|
|
97912
98765
|
get: function() {
|
|
@@ -97931,6 +98784,12 @@ Object.defineProperty(exports, "ingestReading", {
|
|
|
97931
98784
|
return ingestReading;
|
|
97932
98785
|
}
|
|
97933
98786
|
});
|
|
98787
|
+
Object.defineProperty(exports, "integrationInstancesCapability", {
|
|
98788
|
+
enumerable: true,
|
|
98789
|
+
get: function() {
|
|
98790
|
+
return integrationInstancesCapability;
|
|
98791
|
+
}
|
|
98792
|
+
});
|
|
97934
98793
|
Object.defineProperty(exports, "isReadingQuantity", {
|
|
97935
98794
|
enumerable: true,
|
|
97936
98795
|
get: function() {
|
|
@@ -97949,6 +98808,12 @@ Object.defineProperty(exports, "listHomeAssistantBrokers", {
|
|
|
97949
98808
|
return listHomeAssistantBrokers;
|
|
97950
98809
|
}
|
|
97951
98810
|
});
|
|
98811
|
+
Object.defineProperty(exports, "listInstancesOrNothing", {
|
|
98812
|
+
enumerable: true,
|
|
98813
|
+
get: function() {
|
|
98814
|
+
return listInstancesOrNothing;
|
|
98815
|
+
}
|
|
98816
|
+
});
|
|
97952
98817
|
Object.defineProperty(exports, "literal", {
|
|
97953
98818
|
enumerable: true,
|
|
97954
98819
|
get: function() {
|
|
@@ -98129,12 +98994,24 @@ Object.defineProperty(exports, "sendToExportedTarget", {
|
|
|
98129
98994
|
return sendToExportedTarget;
|
|
98130
98995
|
}
|
|
98131
98996
|
});
|
|
98997
|
+
Object.defineProperty(exports, "settingsByBroker", {
|
|
98998
|
+
enumerable: true,
|
|
98999
|
+
get: function() {
|
|
99000
|
+
return settingsByBroker;
|
|
99001
|
+
}
|
|
99002
|
+
});
|
|
98132
99003
|
Object.defineProperty(exports, "smokeCapability", {
|
|
98133
99004
|
enumerable: true,
|
|
98134
99005
|
get: function() {
|
|
98135
99006
|
return smokeCapability;
|
|
98136
99007
|
}
|
|
98137
99008
|
});
|
|
99009
|
+
Object.defineProperty(exports, "statusInstanceOf", {
|
|
99010
|
+
enumerable: true,
|
|
99011
|
+
get: function() {
|
|
99012
|
+
return statusInstanceOf;
|
|
99013
|
+
}
|
|
99014
|
+
});
|
|
98138
99015
|
Object.defineProperty(exports, "string", {
|
|
98139
99016
|
enumerable: true,
|
|
98140
99017
|
get: function() {
|