@camstack/addon-provider-homeassistant 1.2.653 → 1.2.654
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 +7 -0
- package/dist/addon.js +669 -495
- package/dist/addon.mjs +206 -32
- package/dist/ha-export/ha-export.addon.js +382 -130
- package/dist/ha-export/ha-export.addon.mjs +336 -84
- package/dist/{ha-broker-source-DnSL-mbs.js → ha-instance-settings-Bn_Trz6p.js} +464 -218
- package/dist/{ha-broker-source-CKdH9XHn.mjs → ha-instance-settings-g5pwb3Fi.mjs} +446 -218
- package/package.json +2 -2
package/dist/addon.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const
|
|
2
|
+
const require_ha_instance_settings = require("./ha-instance-settings-Bn_Trz6p.js");
|
|
3
3
|
let node_crypto = require("node:crypto");
|
|
4
4
|
let node_zlib = require("node:zlib");
|
|
5
5
|
//#region src/ha-admin-link.ts
|
|
@@ -72,21 +72,21 @@ function registerHaAdminLink(ctx, deviceId, brokerId, subject) {
|
|
|
72
72
|
});
|
|
73
73
|
return null;
|
|
74
74
|
};
|
|
75
|
-
ctx.registerNativeCap(
|
|
75
|
+
ctx.registerNativeCap(require_ha_instance_settings.deviceAdminLinkCapability, { getAdminLink: async (input) => {
|
|
76
76
|
if (input.deviceId !== deviceId) throw new Error(`HaAdminLink: deviceId mismatch, expected ${deviceId}, got ${input.deviceId}`);
|
|
77
77
|
if (cachedBaseUrl === null) {
|
|
78
78
|
const raw = (await ctx.api.broker.getBrokerConfig.query({ id: brokerId }))?.["baseUrl"];
|
|
79
79
|
if (typeof raw !== "string" || raw.length === 0) return refuse("no-base-url");
|
|
80
80
|
cachedBaseUrl = raw;
|
|
81
81
|
}
|
|
82
|
-
const base =
|
|
82
|
+
const base = require_ha_instance_settings.parseAdminBase(cachedBaseUrl);
|
|
83
83
|
if (!base.ok) {
|
|
84
84
|
cachedBaseUrl = null;
|
|
85
85
|
return refuse("base-unusable", { baseReason: base.reason });
|
|
86
86
|
}
|
|
87
87
|
const page = pageFor(subject, base.basePath);
|
|
88
88
|
if (page === null) return refuse("empty-subject");
|
|
89
|
-
const built =
|
|
89
|
+
const built = require_ha_instance_settings.buildDeviceAdminUrl({
|
|
90
90
|
host: base.host,
|
|
91
91
|
port: base.port,
|
|
92
92
|
scheme: base.scheme,
|
|
@@ -114,25 +114,25 @@ function registerHaAdminLink(ctx, deviceId, brokerId, subject) {
|
|
|
114
114
|
* `readHaSource` (returns null) — do NOT use `z.object(haSourceSchemaFields).parse`.
|
|
115
115
|
*/
|
|
116
116
|
var haSourceSchemaFields = {
|
|
117
|
-
system:
|
|
118
|
-
brokerId:
|
|
119
|
-
haDeviceId:
|
|
120
|
-
entityId:
|
|
121
|
-
referenceEntityId:
|
|
122
|
-
capabilities:
|
|
123
|
-
role:
|
|
124
|
-
childDeviceIds:
|
|
125
|
-
unitOfMeasurement:
|
|
126
|
-
deviceClass:
|
|
127
|
-
integrationId:
|
|
128
|
-
options:
|
|
129
|
-
features:
|
|
117
|
+
system: require_ha_instance_settings.literal("homeassistant").optional(),
|
|
118
|
+
brokerId: require_ha_instance_settings.string(),
|
|
119
|
+
haDeviceId: require_ha_instance_settings.string().optional(),
|
|
120
|
+
entityId: require_ha_instance_settings.string().optional(),
|
|
121
|
+
referenceEntityId: require_ha_instance_settings.string().nullable().optional(),
|
|
122
|
+
capabilities: require_ha_instance_settings.array(require_ha_instance_settings.string()).default([]),
|
|
123
|
+
role: require_ha_instance_settings.string().optional(),
|
|
124
|
+
childDeviceIds: require_ha_instance_settings.array(require_ha_instance_settings.number()).default([]),
|
|
125
|
+
unitOfMeasurement: require_ha_instance_settings.string().optional(),
|
|
126
|
+
deviceClass: require_ha_instance_settings.string().optional(),
|
|
127
|
+
integrationId: require_ha_instance_settings.string().optional(),
|
|
128
|
+
options: require_ha_instance_settings.array(require_ha_instance_settings.string()).optional(),
|
|
129
|
+
features: require_ha_instance_settings.array(require_ha_instance_settings.string()).optional(),
|
|
130
130
|
/** Sibling meter sensors whose readings this entity carries as `power-meter` (D951). */
|
|
131
|
-
meterEntities:
|
|
132
|
-
power:
|
|
133
|
-
energy:
|
|
134
|
-
voltage:
|
|
135
|
-
current:
|
|
131
|
+
meterEntities: require_ha_instance_settings.object({
|
|
132
|
+
power: require_ha_instance_settings.string().optional(),
|
|
133
|
+
energy: require_ha_instance_settings.string().optional(),
|
|
134
|
+
voltage: require_ha_instance_settings.string().optional(),
|
|
135
|
+
current: require_ha_instance_settings.string().optional()
|
|
136
136
|
}).optional()
|
|
137
137
|
};
|
|
138
138
|
/** Project a persisted config blob into a typed source, or null when the
|
|
@@ -176,7 +176,7 @@ function readHaSource(config) {
|
|
|
176
176
|
function attachAccessoriesCap(ctx, deviceId, opts) {
|
|
177
177
|
let childIds = [];
|
|
178
178
|
const hidden = new Set(opts.initialHidden);
|
|
179
|
-
ctx.registerNativeCap(
|
|
179
|
+
ctx.registerNativeCap(require_ha_instance_settings.accessoriesCapability, {
|
|
180
180
|
getStatus: async () => ({
|
|
181
181
|
childDeviceIds: childIds,
|
|
182
182
|
hiddenChildIds: [...hidden]
|
|
@@ -193,7 +193,7 @@ function attachAccessoriesCap(ctx, deviceId, opts) {
|
|
|
193
193
|
type: "device",
|
|
194
194
|
id: deviceId
|
|
195
195
|
},
|
|
196
|
-
category:
|
|
196
|
+
category: require_ha_instance_settings.EventCategory.AccessoriesChildVisibilityChanged,
|
|
197
197
|
data: {
|
|
198
198
|
deviceId,
|
|
199
199
|
childDeviceId,
|
|
@@ -211,7 +211,7 @@ function attachAccessoriesCap(ctx, deviceId, opts) {
|
|
|
211
211
|
type: "device",
|
|
212
212
|
id: deviceId
|
|
213
213
|
},
|
|
214
|
-
category:
|
|
214
|
+
category: require_ha_instance_settings.EventCategory.AccessoriesChanged,
|
|
215
215
|
data: {
|
|
216
216
|
deviceId,
|
|
217
217
|
childDeviceIds: childIds,
|
|
@@ -232,23 +232,23 @@ function attachAccessoriesCap(ctx, deviceId, opts) {
|
|
|
232
232
|
* in the materialisation factory (Phase E) where each domain becomes
|
|
233
233
|
* its own DeviceType + cap set.
|
|
234
234
|
*/
|
|
235
|
-
var HaEntityStateSchema =
|
|
236
|
-
entity_id:
|
|
235
|
+
var HaEntityStateSchema = require_ha_instance_settings.object({
|
|
236
|
+
entity_id: require_ha_instance_settings.string().min(1),
|
|
237
237
|
/** Domain-specific state value (`on`/`off`/`open`/temperature
|
|
238
238
|
* number-as-string/etc.). Always a string in HA. */
|
|
239
|
-
state:
|
|
239
|
+
state: require_ha_instance_settings.string(),
|
|
240
240
|
/** Free-form attribute map. Domain-specific. */
|
|
241
|
-
attributes:
|
|
241
|
+
attributes: require_ha_instance_settings.record(require_ha_instance_settings.string(), require_ha_instance_settings.unknown()),
|
|
242
242
|
/** Optional context envelope (user/parent id) the HA server attaches. */
|
|
243
|
-
context:
|
|
244
|
-
id:
|
|
245
|
-
parent_id:
|
|
246
|
-
user_id:
|
|
243
|
+
context: require_ha_instance_settings.object({
|
|
244
|
+
id: require_ha_instance_settings.string(),
|
|
245
|
+
parent_id: require_ha_instance_settings.string().nullable(),
|
|
246
|
+
user_id: require_ha_instance_settings.string().nullable()
|
|
247
247
|
}).optional(),
|
|
248
248
|
/** ISO 8601 timestamp of the last state change. */
|
|
249
|
-
last_changed:
|
|
249
|
+
last_changed: require_ha_instance_settings.string(),
|
|
250
250
|
/** ISO 8601 timestamp of the last update (state OR attributes). */
|
|
251
|
-
last_updated:
|
|
251
|
+
last_updated: require_ha_instance_settings.string()
|
|
252
252
|
});
|
|
253
253
|
/**
|
|
254
254
|
* Auth strategy. Two mutually-exclusive options:
|
|
@@ -259,16 +259,16 @@ var HaEntityStateSchema = require_ha_broker_source.object({
|
|
|
259
259
|
* the addon config; the WS URL points at their HA instance
|
|
260
260
|
* (`ws://ha.example:8123/api/websocket` style).
|
|
261
261
|
*/
|
|
262
|
-
var HaAuthConfigSchema =
|
|
263
|
-
kind:
|
|
262
|
+
var HaAuthConfigSchema = require_ha_instance_settings.discriminatedUnion("kind", [require_ha_instance_settings.object({
|
|
263
|
+
kind: require_ha_instance_settings.literal("supervisor"),
|
|
264
264
|
/** Token injected by the Supervisor at runtime via env. */
|
|
265
|
-
supervisorToken:
|
|
266
|
-
}),
|
|
267
|
-
kind:
|
|
265
|
+
supervisorToken: require_ha_instance_settings.string().min(1).meta({ secret: true })
|
|
266
|
+
}), require_ha_instance_settings.object({
|
|
267
|
+
kind: require_ha_instance_settings.literal("long-lived"),
|
|
268
268
|
/** Origin URL of the HA instance (e.g. `https://ha.example:8123`). */
|
|
269
|
-
baseUrl:
|
|
269
|
+
baseUrl: require_ha_instance_settings.url(),
|
|
270
270
|
/** Long-lived access token issued by the user in their HA profile. */
|
|
271
|
-
accessToken:
|
|
271
|
+
accessToken: require_ha_instance_settings.string().min(1).meta({ secret: true })
|
|
272
272
|
})]);
|
|
273
273
|
/** HA's standard domain enum — supported subset; future domains added
|
|
274
274
|
* as integration coverage grows. */
|
|
@@ -306,7 +306,7 @@ var HaDomain = /* @__PURE__ */ function(HaDomain) {
|
|
|
306
306
|
* an unknown unit is never guessed (D393, D944).
|
|
307
307
|
*/
|
|
308
308
|
function takeReading(logger, deviceId, value, rawUnit, quantity) {
|
|
309
|
-
const result =
|
|
309
|
+
const result = require_ha_instance_settings.ingestReading({
|
|
310
310
|
value,
|
|
311
311
|
rawUnit,
|
|
312
312
|
quantity
|
|
@@ -367,7 +367,7 @@ function applyMeterReading(prev, field, value, lastFetchedAt) {
|
|
|
367
367
|
lastFetchedAt
|
|
368
368
|
};
|
|
369
369
|
}
|
|
370
|
-
var LOAD_TYPES = new Set(
|
|
370
|
+
var LOAD_TYPES = new Set(require_ha_instance_settings.powerMeterCapability.deviceTypes.filter((type) => type !== require_ha_instance_settings.DeviceType.Sensor));
|
|
371
371
|
function isLoad(entity) {
|
|
372
372
|
return LOAD_TYPES.has(entity.deviceType) && entity.entityCategory === void 0 && !entity.capabilities.includes("power-meter");
|
|
373
373
|
}
|
|
@@ -428,7 +428,7 @@ var HaMeterCarrier = class {
|
|
|
428
428
|
const entityId = meters[field];
|
|
429
429
|
return entityId === void 0 ? [] : [[entityId, field]];
|
|
430
430
|
}));
|
|
431
|
-
this.ctx.registerNativeCap(
|
|
431
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.powerMeterCapability, { getStatus: async () => this.runtimeState.getCapState("power-meter") ?? COLD_START$20 });
|
|
432
432
|
this.runtimeState.setCapState("power-meter", {
|
|
433
433
|
...COLD_START$20,
|
|
434
434
|
...this.runtimeState.getCapState("power-meter")
|
|
@@ -469,7 +469,7 @@ var HaMeterCarrier = class {
|
|
|
469
469
|
* and carries `childDeviceIds` so parent-mode devices can host the
|
|
470
470
|
* accessories cap for their entity-children.
|
|
471
471
|
*/
|
|
472
|
-
var haChildDeviceSchema =
|
|
472
|
+
var haChildDeviceSchema = require_ha_instance_settings.object({ ...haSourceSchemaFields });
|
|
473
473
|
/**
|
|
474
474
|
* Abstract base for every HA-entity-backed CamStack accessory device.
|
|
475
475
|
*
|
|
@@ -490,14 +490,14 @@ var haChildDeviceSchema = require_ha_broker_source.object({ ...haSourceSchemaFie
|
|
|
490
490
|
* own (beyond BaseDevice's auto-registered `device-status` /
|
|
491
491
|
* `feature-probe`).
|
|
492
492
|
*/
|
|
493
|
-
var DEVICE_FEATURE_VALUES = new Set(Object.values(
|
|
493
|
+
var DEVICE_FEATURE_VALUES = new Set(Object.values(require_ha_instance_settings.DeviceFeature));
|
|
494
494
|
/** Keep only strings that are valid DeviceFeature enum values (the persisted
|
|
495
495
|
* config stores them as plain strings). */
|
|
496
496
|
function parseDeviceFeatures(raw) {
|
|
497
497
|
if (!Array.isArray(raw)) return [];
|
|
498
498
|
return raw.filter((f) => typeof f === "string" && DEVICE_FEATURE_VALUES.has(f));
|
|
499
499
|
}
|
|
500
|
-
var HaBaseChildDevice = class HaBaseChildDevice extends
|
|
500
|
+
var HaBaseChildDevice = class HaBaseChildDevice extends require_ha_instance_settings.BaseDevice {
|
|
501
501
|
/** Mapping-derived feature flags (e.g. `lock-open`), read from the persisted
|
|
502
502
|
* config at construction. Surfaced on `device.features` (and re-published to
|
|
503
503
|
* the device meta in `onActivate` via `refreshFeatures`) so the UI gates
|
|
@@ -639,7 +639,7 @@ var HaBaseChildDevice = class HaBaseChildDevice extends require_ha_broker_source
|
|
|
639
639
|
this.deviceLogger.warn("ha-child getRawState failed to read cached state", { meta: {
|
|
640
640
|
brokerId: this.brokerId,
|
|
641
641
|
entityId: this.entityId,
|
|
642
|
-
error:
|
|
642
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
643
643
|
} });
|
|
644
644
|
return null;
|
|
645
645
|
}
|
|
@@ -689,7 +689,7 @@ var HaBaseChildDevice = class HaBaseChildDevice extends require_ha_broker_source
|
|
|
689
689
|
entityId: this.entityId,
|
|
690
690
|
domain,
|
|
691
691
|
service,
|
|
692
|
-
error:
|
|
692
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
693
693
|
} });
|
|
694
694
|
throw err;
|
|
695
695
|
}
|
|
@@ -716,7 +716,7 @@ var HaBaseChildDevice = class HaBaseChildDevice extends require_ha_broker_source
|
|
|
716
716
|
this.deviceLogger.warn("ha-child failed to register broker subscription", { meta: {
|
|
717
717
|
entityId: this.entityId,
|
|
718
718
|
brokerId: this.brokerId,
|
|
719
|
-
error:
|
|
719
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
720
720
|
} });
|
|
721
721
|
return false;
|
|
722
722
|
}
|
|
@@ -757,7 +757,7 @@ var HaBaseChildDevice = class HaBaseChildDevice extends require_ha_broker_source
|
|
|
757
757
|
} catch (err) {
|
|
758
758
|
this.deviceLogger.warn("ha-child state-push handler error", { meta: {
|
|
759
759
|
entityId: this.entityId,
|
|
760
|
-
error:
|
|
760
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
761
761
|
} });
|
|
762
762
|
}
|
|
763
763
|
};
|
|
@@ -786,7 +786,7 @@ var HaButtonDevice = class extends HaBaseChildDevice {
|
|
|
786
786
|
this.registerButtonCap();
|
|
787
787
|
}
|
|
788
788
|
registerButtonCap() {
|
|
789
|
-
this.ctx.registerNativeCap(
|
|
789
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.buttonCapability, { press: async () => {
|
|
790
790
|
const domain = this.entityId.split(".")[0] ?? "button";
|
|
791
791
|
if (domain === "scene") {
|
|
792
792
|
await this.callHaService("scene", "turn_on");
|
|
@@ -844,7 +844,7 @@ var HaUpdateDevice = class extends HaBaseChildDevice {
|
|
|
844
844
|
});
|
|
845
845
|
}
|
|
846
846
|
registerUpdateCap() {
|
|
847
|
-
this.ctx.registerNativeCap(
|
|
847
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.updateCapability, {
|
|
848
848
|
getStatus: async () => {
|
|
849
849
|
return this.runtimeState.getCapState(UPDATE_CAP) ?? COLD_START$19;
|
|
850
850
|
},
|
|
@@ -928,7 +928,7 @@ var HaSwitchDevice = class extends HaBaseChildDevice {
|
|
|
928
928
|
});
|
|
929
929
|
}
|
|
930
930
|
registerSwitchCap() {
|
|
931
|
-
this.ctx.registerNativeCap(
|
|
931
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.switchCapability, {
|
|
932
932
|
getStatus: async () => {
|
|
933
933
|
return this.runtimeState.getCapState("switch") ?? {
|
|
934
934
|
on: false,
|
|
@@ -1045,7 +1045,7 @@ var HaNumericSensorDevice = class extends HaBaseChildDevice {
|
|
|
1045
1045
|
const stored = this.sourceInfo.quantity;
|
|
1046
1046
|
if (stored !== void 0 && stored !== "device") return stored;
|
|
1047
1047
|
if (unitRaw === void 0) return "none";
|
|
1048
|
-
const learned =
|
|
1048
|
+
const learned = require_ha_instance_settings.quantityFromUnit(unitRaw);
|
|
1049
1049
|
if (learned === void 0 || learned === "device") {
|
|
1050
1050
|
this.deviceLogger.warn("numeric reading refused", {
|
|
1051
1051
|
tags: { deviceId: this.id },
|
|
@@ -1071,7 +1071,7 @@ var HaNumericSensorDevice = class extends HaBaseChildDevice {
|
|
|
1071
1071
|
value: "",
|
|
1072
1072
|
lastFetchedAt: 0
|
|
1073
1073
|
};
|
|
1074
|
-
this.ctx.registerNativeCap(
|
|
1074
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.enumSensorCapability, { getStatus: async () => {
|
|
1075
1075
|
return this.runtimeState.getCapState("enum-sensor") ?? COLD_START;
|
|
1076
1076
|
} });
|
|
1077
1077
|
this.runtimeState.setCapState("enum-sensor", COLD_START);
|
|
@@ -1083,7 +1083,7 @@ var HaNumericSensorDevice = class extends HaBaseChildDevice {
|
|
|
1083
1083
|
temperature: 0,
|
|
1084
1084
|
lastFetchedAt: 0
|
|
1085
1085
|
};
|
|
1086
|
-
this.ctx.registerNativeCap(
|
|
1086
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.temperatureSensorCapability, { getStatus: async () => this.readSlice(COLD_START) });
|
|
1087
1087
|
return;
|
|
1088
1088
|
}
|
|
1089
1089
|
case "humidity-sensor": {
|
|
@@ -1091,7 +1091,7 @@ var HaNumericSensorDevice = class extends HaBaseChildDevice {
|
|
|
1091
1091
|
humidity: 0,
|
|
1092
1092
|
lastFetchedAt: 0
|
|
1093
1093
|
};
|
|
1094
|
-
this.ctx.registerNativeCap(
|
|
1094
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.humiditySensorCapability, { getStatus: async () => this.readSlice(COLD_START) });
|
|
1095
1095
|
return;
|
|
1096
1096
|
}
|
|
1097
1097
|
case "ambient-light-sensor": {
|
|
@@ -1099,7 +1099,7 @@ var HaNumericSensorDevice = class extends HaBaseChildDevice {
|
|
|
1099
1099
|
illuminance: 0,
|
|
1100
1100
|
lastFetchedAt: 0
|
|
1101
1101
|
};
|
|
1102
|
-
this.ctx.registerNativeCap(
|
|
1102
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.ambientLightSensorCapability, { getStatus: async () => this.readSlice(COLD_START) });
|
|
1103
1103
|
return;
|
|
1104
1104
|
}
|
|
1105
1105
|
case "pressure-sensor": {
|
|
@@ -1107,7 +1107,7 @@ var HaNumericSensorDevice = class extends HaBaseChildDevice {
|
|
|
1107
1107
|
pressure: 0,
|
|
1108
1108
|
lastFetchedAt: 0
|
|
1109
1109
|
};
|
|
1110
|
-
this.ctx.registerNativeCap(
|
|
1110
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.pressureSensorCapability, { getStatus: async () => this.readSlice(COLD_START) });
|
|
1111
1111
|
return;
|
|
1112
1112
|
}
|
|
1113
1113
|
case "numeric-sensor": {
|
|
@@ -1115,7 +1115,7 @@ var HaNumericSensorDevice = class extends HaBaseChildDevice {
|
|
|
1115
1115
|
value: 0,
|
|
1116
1116
|
lastFetchedAt: 0
|
|
1117
1117
|
};
|
|
1118
|
-
this.ctx.registerNativeCap(
|
|
1118
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.numericSensorCapability, { getStatus: async () => this.readSlice(COLD_START) });
|
|
1119
1119
|
return;
|
|
1120
1120
|
}
|
|
1121
1121
|
}
|
|
@@ -1207,61 +1207,61 @@ var HaBinarySensorDevice = class extends HaBaseChildDevice {
|
|
|
1207
1207
|
registerCap(name) {
|
|
1208
1208
|
switch (name) {
|
|
1209
1209
|
case "contact":
|
|
1210
|
-
this.ctx.registerNativeCap(
|
|
1210
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.contactCapability, { getStatus: async () => this.readSlice({
|
|
1211
1211
|
entryOpen: false,
|
|
1212
1212
|
lastChangedAt: 0
|
|
1213
1213
|
}) });
|
|
1214
1214
|
return;
|
|
1215
1215
|
case "flood":
|
|
1216
|
-
this.ctx.registerNativeCap(
|
|
1216
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.floodCapability, { getStatus: async () => this.readSlice({
|
|
1217
1217
|
flooded: false,
|
|
1218
1218
|
lastChangedAt: 0
|
|
1219
1219
|
}) });
|
|
1220
1220
|
return;
|
|
1221
1221
|
case "smoke":
|
|
1222
|
-
this.ctx.registerNativeCap(
|
|
1222
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.smokeCapability, { getStatus: async () => this.readSlice({
|
|
1223
1223
|
detected: false,
|
|
1224
1224
|
lastChangedAt: 0
|
|
1225
1225
|
}) });
|
|
1226
1226
|
return;
|
|
1227
1227
|
case "carbon-monoxide":
|
|
1228
|
-
this.ctx.registerNativeCap(
|
|
1228
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.carbonMonoxideCapability, { getStatus: async () => this.readSlice({
|
|
1229
1229
|
detected: false,
|
|
1230
1230
|
lastChangedAt: 0
|
|
1231
1231
|
}) });
|
|
1232
1232
|
return;
|
|
1233
1233
|
case "gas":
|
|
1234
|
-
this.ctx.registerNativeCap(
|
|
1234
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.gasCapability, { getStatus: async () => this.readSlice({
|
|
1235
1235
|
detected: false,
|
|
1236
1236
|
lastChangedAt: 0
|
|
1237
1237
|
}) });
|
|
1238
1238
|
return;
|
|
1239
1239
|
case "tamper":
|
|
1240
|
-
this.ctx.registerNativeCap(
|
|
1240
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.tamperCapability, { getStatus: async () => this.readSlice({
|
|
1241
1241
|
tampered: false,
|
|
1242
1242
|
lastChangedAt: 0
|
|
1243
1243
|
}) });
|
|
1244
1244
|
return;
|
|
1245
1245
|
case "vibration":
|
|
1246
|
-
this.ctx.registerNativeCap(
|
|
1246
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.vibrationCapability, { getStatus: async () => this.readSlice({
|
|
1247
1247
|
detected: false,
|
|
1248
1248
|
lastChangedAt: 0
|
|
1249
1249
|
}) });
|
|
1250
1250
|
return;
|
|
1251
1251
|
case "connectivity":
|
|
1252
|
-
this.ctx.registerNativeCap(
|
|
1252
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.connectivityCapability, { getStatus: async () => this.readSlice({
|
|
1253
1253
|
connected: false,
|
|
1254
1254
|
lastChangedAt: 0
|
|
1255
1255
|
}) });
|
|
1256
1256
|
return;
|
|
1257
1257
|
case "binary":
|
|
1258
|
-
this.ctx.registerNativeCap(
|
|
1258
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.binaryCapability, { getStatus: async () => this.readSlice({
|
|
1259
1259
|
on: false,
|
|
1260
1260
|
lastChangedAt: 0
|
|
1261
1261
|
}) });
|
|
1262
1262
|
return;
|
|
1263
1263
|
case "motion":
|
|
1264
|
-
this.ctx.registerNativeCap(
|
|
1264
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.motionCapability, {
|
|
1265
1265
|
getStatus: async () => this.readSlice({
|
|
1266
1266
|
detected: false,
|
|
1267
1267
|
lastDetectedAt: null,
|
|
@@ -1434,7 +1434,7 @@ var HaLightDevice = class extends HaBaseChildDevice {
|
|
|
1434
1434
|
}
|
|
1435
1435
|
}
|
|
1436
1436
|
registerSwitchCap() {
|
|
1437
|
-
this.ctx.registerNativeCap(
|
|
1437
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.switchCapability, {
|
|
1438
1438
|
getStatus: async () => {
|
|
1439
1439
|
return this.runtimeState.getCapState("switch") ?? {
|
|
1440
1440
|
on: false,
|
|
@@ -1447,7 +1447,7 @@ var HaLightDevice = class extends HaBaseChildDevice {
|
|
|
1447
1447
|
});
|
|
1448
1448
|
}
|
|
1449
1449
|
registerBrightnessCap() {
|
|
1450
|
-
this.ctx.registerNativeCap(
|
|
1450
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.brightnessCapability, {
|
|
1451
1451
|
getStatus: async () => {
|
|
1452
1452
|
return this.runtimeState.getCapState("brightness") ?? {
|
|
1453
1453
|
level: 0,
|
|
@@ -1460,7 +1460,7 @@ var HaLightDevice = class extends HaBaseChildDevice {
|
|
|
1460
1460
|
});
|
|
1461
1461
|
}
|
|
1462
1462
|
registerColorCap() {
|
|
1463
|
-
this.ctx.registerNativeCap(
|
|
1463
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.colorCapability, {
|
|
1464
1464
|
getStatus: async () => {
|
|
1465
1465
|
return this.runtimeState.getCapState("color") ?? {
|
|
1466
1466
|
mode: "rgb",
|
|
@@ -1590,7 +1590,7 @@ var HaCoverDevice = class extends HaBaseChildDevice {
|
|
|
1590
1590
|
});
|
|
1591
1591
|
}
|
|
1592
1592
|
registerCoverCap() {
|
|
1593
|
-
this.ctx.registerNativeCap(
|
|
1593
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.coverCapability, {
|
|
1594
1594
|
getStatus: async () => {
|
|
1595
1595
|
return this.runtimeState.getCapState("cover") ?? COLD_START$18;
|
|
1596
1596
|
},
|
|
@@ -1661,7 +1661,7 @@ var HaValveDevice = class extends HaBaseChildDevice {
|
|
|
1661
1661
|
});
|
|
1662
1662
|
}
|
|
1663
1663
|
registerValveCap() {
|
|
1664
|
-
this.ctx.registerNativeCap(
|
|
1664
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.valveCapability, {
|
|
1665
1665
|
getStatus: async () => {
|
|
1666
1666
|
return this.runtimeState.getCapState("valve") ?? COLD_START$17;
|
|
1667
1667
|
},
|
|
@@ -1735,7 +1735,7 @@ var HaLockDevice = class extends HaBaseChildDevice {
|
|
|
1735
1735
|
});
|
|
1736
1736
|
}
|
|
1737
1737
|
registerLockCap() {
|
|
1738
|
-
this.ctx.registerNativeCap(
|
|
1738
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.lockControlCapability, {
|
|
1739
1739
|
getStatus: async () => {
|
|
1740
1740
|
return this.runtimeState.getCapState("lock-control") ?? COLD_START$16;
|
|
1741
1741
|
},
|
|
@@ -1819,7 +1819,7 @@ var HaClimateDevice = class extends HaBaseChildDevice {
|
|
|
1819
1819
|
this.swingHorizontalModes = readStringArray$4(state.attributes, "swing_horizontal_modes");
|
|
1820
1820
|
const unit = readStringAttr$6(state.attributes, "temperature_unit");
|
|
1821
1821
|
if (unit !== null) {
|
|
1822
|
-
const probe =
|
|
1822
|
+
const probe = require_ha_instance_settings.ingestReading({
|
|
1823
1823
|
value: 0,
|
|
1824
1824
|
rawUnit: unit,
|
|
1825
1825
|
quantity: "temperature"
|
|
@@ -1836,7 +1836,7 @@ var HaClimateDevice = class extends HaBaseChildDevice {
|
|
|
1836
1836
|
this.runtimeState.setCapState("climate-control", climateSliceFromState(state));
|
|
1837
1837
|
}
|
|
1838
1838
|
registerClimateCap() {
|
|
1839
|
-
this.ctx.registerNativeCap(
|
|
1839
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.climateControlCapability, {
|
|
1840
1840
|
getStatus: async () => {
|
|
1841
1841
|
return this.runtimeState.getCapState("climate-control") ?? COLD_START$15;
|
|
1842
1842
|
},
|
|
@@ -1894,7 +1894,7 @@ function climateSliceFromState(state) {
|
|
|
1894
1894
|
const tempUnit = readStringAttr$6(attrs, "temperature_unit") ?? void 0;
|
|
1895
1895
|
const celsius = (raw) => {
|
|
1896
1896
|
if (raw === null) return null;
|
|
1897
|
-
const result =
|
|
1897
|
+
const result = require_ha_instance_settings.ingestReading({
|
|
1898
1898
|
value: raw,
|
|
1899
1899
|
rawUnit: tempUnit,
|
|
1900
1900
|
quantity: "temperature"
|
|
@@ -2043,7 +2043,7 @@ var HaHumidifierDevice = class extends HaBaseChildDevice {
|
|
|
2043
2043
|
});
|
|
2044
2044
|
}
|
|
2045
2045
|
registerHumidifierCap() {
|
|
2046
|
-
this.ctx.registerNativeCap(
|
|
2046
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.humidifierCapability, {
|
|
2047
2047
|
getStatus: async () => {
|
|
2048
2048
|
return this.runtimeState.getCapState("humidifier") ?? COLD_START$14;
|
|
2049
2049
|
},
|
|
@@ -2123,7 +2123,7 @@ var HaWaterHeaterDevice = class extends HaBaseChildDevice {
|
|
|
2123
2123
|
});
|
|
2124
2124
|
}
|
|
2125
2125
|
registerWaterHeaterCap() {
|
|
2126
|
-
this.ctx.registerNativeCap(
|
|
2126
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.waterHeaterCapability, {
|
|
2127
2127
|
getStatus: async () => {
|
|
2128
2128
|
return this.runtimeState.getCapState("water-heater") ?? COLD_START$13;
|
|
2129
2129
|
},
|
|
@@ -2206,7 +2206,7 @@ var HaFanDevice = class extends HaBaseChildDevice {
|
|
|
2206
2206
|
this.runtimeState.setCapState("fan-control", slice);
|
|
2207
2207
|
}
|
|
2208
2208
|
registerSwitchCap() {
|
|
2209
|
-
this.ctx.registerNativeCap(
|
|
2209
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.switchCapability, {
|
|
2210
2210
|
getStatus: async () => {
|
|
2211
2211
|
return this.runtimeState.getCapState("switch") ?? {
|
|
2212
2212
|
on: false,
|
|
@@ -2219,7 +2219,7 @@ var HaFanDevice = class extends HaBaseChildDevice {
|
|
|
2219
2219
|
});
|
|
2220
2220
|
}
|
|
2221
2221
|
registerFanCap() {
|
|
2222
|
-
this.ctx.registerNativeCap(
|
|
2222
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.fanControlCapability, {
|
|
2223
2223
|
getStatus: async () => {
|
|
2224
2224
|
return this.runtimeState.getCapState("fan-control") ?? FAN_COLD_START;
|
|
2225
2225
|
},
|
|
@@ -2287,7 +2287,7 @@ var HaVacuumDevice = class extends HaBaseChildDevice {
|
|
|
2287
2287
|
this.registerVacuumCap();
|
|
2288
2288
|
this.registerRunningCap();
|
|
2289
2289
|
this.runtimeState.setCapState("vacuum-control", COLD_START$12);
|
|
2290
|
-
this.runtimeState.setCapState("running-state",
|
|
2290
|
+
this.runtimeState.setCapState("running-state", require_ha_instance_settings.RUNNING_STATE_COLD);
|
|
2291
2291
|
}
|
|
2292
2292
|
handleStatePush(state) {
|
|
2293
2293
|
if (state.state === "unavailable" || state.state === "unknown") return;
|
|
@@ -2309,13 +2309,13 @@ var HaVacuumDevice = class extends HaBaseChildDevice {
|
|
|
2309
2309
|
});
|
|
2310
2310
|
const fetchedAt = Date.now();
|
|
2311
2311
|
const previous = this.runtimeState.getCapState("running-state");
|
|
2312
|
-
this.runtimeState.setCapState("running-state",
|
|
2312
|
+
this.runtimeState.setCapState("running-state", require_ha_instance_settings.runningFromVacuumState(lifecycleState, previous, fetchedAt, lastChangedAt));
|
|
2313
2313
|
}
|
|
2314
2314
|
registerRunningCap() {
|
|
2315
|
-
this.ctx.registerNativeCap(
|
|
2315
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.runningStateCapability, { getStatus: async () => this.runtimeState.getCapState("running-state") ?? require_ha_instance_settings.RUNNING_STATE_COLD });
|
|
2316
2316
|
}
|
|
2317
2317
|
registerVacuumCap() {
|
|
2318
|
-
this.ctx.registerNativeCap(
|
|
2318
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.vacuumControlCapability, {
|
|
2319
2319
|
getStatus: async () => {
|
|
2320
2320
|
return this.runtimeState.getCapState("vacuum-control") ?? COLD_START$12;
|
|
2321
2321
|
},
|
|
@@ -2387,7 +2387,7 @@ var HaLawnMowerDevice = class extends HaBaseChildDevice {
|
|
|
2387
2387
|
this.registerLawnMowerCap();
|
|
2388
2388
|
this.registerRunningCap();
|
|
2389
2389
|
this.runtimeState.setCapState("lawn-mower-control", COLD_START$11);
|
|
2390
|
-
this.runtimeState.setCapState("running-state",
|
|
2390
|
+
this.runtimeState.setCapState("running-state", require_ha_instance_settings.RUNNING_STATE_COLD);
|
|
2391
2391
|
}
|
|
2392
2392
|
handleStatePush(state) {
|
|
2393
2393
|
if (state.state === "unavailable" || state.state === "unknown") return;
|
|
@@ -2405,13 +2405,13 @@ var HaLawnMowerDevice = class extends HaBaseChildDevice {
|
|
|
2405
2405
|
});
|
|
2406
2406
|
const fetchedAt = Date.now();
|
|
2407
2407
|
const previous = this.runtimeState.getCapState("running-state");
|
|
2408
|
-
this.runtimeState.setCapState("running-state",
|
|
2408
|
+
this.runtimeState.setCapState("running-state", require_ha_instance_settings.runningFromLawnMower(activity, previous, fetchedAt, lastChangedAt));
|
|
2409
2409
|
}
|
|
2410
2410
|
registerRunningCap() {
|
|
2411
|
-
this.ctx.registerNativeCap(
|
|
2411
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.runningStateCapability, { getStatus: async () => this.runtimeState.getCapState("running-state") ?? require_ha_instance_settings.RUNNING_STATE_COLD });
|
|
2412
2412
|
}
|
|
2413
2413
|
registerLawnMowerCap() {
|
|
2414
|
-
this.ctx.registerNativeCap(
|
|
2414
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.lawnMowerControlCapability, {
|
|
2415
2415
|
getStatus: async () => {
|
|
2416
2416
|
return this.runtimeState.getCapState("lawn-mower-control") ?? COLD_START$11;
|
|
2417
2417
|
},
|
|
@@ -2467,7 +2467,7 @@ var HaMediaPlayerDevice = class extends HaBaseChildDevice {
|
|
|
2467
2467
|
this.registerMediaPlayerCap();
|
|
2468
2468
|
this.registerRunningCap();
|
|
2469
2469
|
this.runtimeState.setCapState("media-player", COLD_START$10);
|
|
2470
|
-
this.runtimeState.setCapState("running-state",
|
|
2470
|
+
this.runtimeState.setCapState("running-state", require_ha_instance_settings.RUNNING_STATE_COLD);
|
|
2471
2471
|
}
|
|
2472
2472
|
handleStatePush(state) {
|
|
2473
2473
|
if (state.state === "unavailable" || state.state === "unknown") return;
|
|
@@ -2492,16 +2492,38 @@ var HaMediaPlayerDevice = class extends HaBaseChildDevice {
|
|
|
2492
2492
|
this.runtimeState.setCapState("media-player", slice);
|
|
2493
2493
|
const fetchedAt = Date.now();
|
|
2494
2494
|
const previous = this.runtimeState.getCapState("running-state");
|
|
2495
|
-
this.runtimeState.setCapState("running-state",
|
|
2495
|
+
this.runtimeState.setCapState("running-state", require_ha_instance_settings.runningFromMediaPlayer(playerState, previous, fetchedAt, lastChangedAt));
|
|
2496
2496
|
}
|
|
2497
2497
|
registerRunningCap() {
|
|
2498
|
-
this.ctx.registerNativeCap(
|
|
2498
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.runningStateCapability, { getStatus: async () => this.runtimeState.getCapState("running-state") ?? require_ha_instance_settings.RUNNING_STATE_COLD });
|
|
2499
|
+
}
|
|
2500
|
+
/** One service call per step, in order: HA has no "N steps" form. */
|
|
2501
|
+
async repeatHaService(service, steps) {
|
|
2502
|
+
for (let step = 0; step < steps; step += 1) await this.callHaService("media_player", service);
|
|
2499
2503
|
}
|
|
2500
2504
|
registerMediaPlayerCap() {
|
|
2501
|
-
this.ctx.registerNativeCap(
|
|
2505
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.mediaPlayerCapability, {
|
|
2502
2506
|
getStatus: async () => {
|
|
2503
2507
|
return this.runtimeState.getCapState("media-player") ?? COLD_START$10;
|
|
2504
2508
|
},
|
|
2509
|
+
turnOn: async () => {
|
|
2510
|
+
await this.callHaService("media_player", "turn_on");
|
|
2511
|
+
},
|
|
2512
|
+
turnOff: async () => {
|
|
2513
|
+
await this.callHaService("media_player", "turn_off");
|
|
2514
|
+
},
|
|
2515
|
+
volumeUp: async ({ steps }) => {
|
|
2516
|
+
await this.repeatHaService("volume_up", steps);
|
|
2517
|
+
},
|
|
2518
|
+
volumeDown: async ({ steps }) => {
|
|
2519
|
+
await this.repeatHaService("volume_down", steps);
|
|
2520
|
+
},
|
|
2521
|
+
channelUp: async ({ steps }) => {
|
|
2522
|
+
await this.repeatHaService("media_next_track", steps);
|
|
2523
|
+
},
|
|
2524
|
+
channelDown: async ({ steps }) => {
|
|
2525
|
+
await this.repeatHaService("media_previous_track", steps);
|
|
2526
|
+
},
|
|
2505
2527
|
play: async () => {
|
|
2506
2528
|
await this.callHaService("media_player", "media_play");
|
|
2507
2529
|
},
|
|
@@ -2630,7 +2652,7 @@ var HaAlarmPanelDevice = class extends HaBaseChildDevice {
|
|
|
2630
2652
|
});
|
|
2631
2653
|
}
|
|
2632
2654
|
registerAlarmCap() {
|
|
2633
|
-
this.ctx.registerNativeCap(
|
|
2655
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.alarmPanelCapability, {
|
|
2634
2656
|
getStatus: async () => {
|
|
2635
2657
|
return this.runtimeState.getCapState("alarm-panel") ?? COLD_START$9;
|
|
2636
2658
|
},
|
|
@@ -2745,7 +2767,7 @@ var HaPresenceDevice = class extends HaBaseChildDevice {
|
|
|
2745
2767
|
});
|
|
2746
2768
|
}
|
|
2747
2769
|
registerBatteryCap() {
|
|
2748
|
-
this.ctx.registerNativeCap(
|
|
2770
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.batteryCapability, {
|
|
2749
2771
|
getStatus: async () => this.runtimeState.getCapState("battery") ?? COLD_BATTERY,
|
|
2750
2772
|
wakeForStream: async () => ({
|
|
2751
2773
|
awoke: true,
|
|
@@ -2754,7 +2776,7 @@ var HaPresenceDevice = class extends HaBaseChildDevice {
|
|
|
2754
2776
|
});
|
|
2755
2777
|
}
|
|
2756
2778
|
registerPresenceCap() {
|
|
2757
|
-
this.ctx.registerNativeCap(
|
|
2779
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.presenceCapability, { getStatus: async () => {
|
|
2758
2780
|
return this.runtimeState.getCapState("presence") ?? COLD_START$8;
|
|
2759
2781
|
} });
|
|
2760
2782
|
}
|
|
@@ -2822,7 +2844,7 @@ var HaControlDevice = class extends HaBaseChildDevice {
|
|
|
2822
2844
|
if (slice !== null) this.runtimeState.setCapState("control", slice);
|
|
2823
2845
|
}
|
|
2824
2846
|
registerControlCap() {
|
|
2825
|
-
this.ctx.registerNativeCap(
|
|
2847
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.controlCapability, {
|
|
2826
2848
|
getStatus: async () => {
|
|
2827
2849
|
return this.runtimeState.getCapState("control") ?? {
|
|
2828
2850
|
kind: this.kind,
|
|
@@ -2861,10 +2883,10 @@ var HaControlDevice = class extends HaBaseChildDevice {
|
|
|
2861
2883
|
/** Base-unit value → the unit the upstream entity still speaks. */
|
|
2862
2884
|
toUpstream(value) {
|
|
2863
2885
|
const quantity = this.sourceInfo.quantity;
|
|
2864
|
-
const base = quantity === void 0 ? void 0 :
|
|
2886
|
+
const base = quantity === void 0 ? void 0 : require_ha_instance_settings.baseUnitOf(quantity);
|
|
2865
2887
|
const upstream = this.upstreamUnit;
|
|
2866
2888
|
if (base === void 0 || upstream === void 0 || upstream === base) return value;
|
|
2867
|
-
const converted =
|
|
2889
|
+
const converted = require_ha_instance_settings.tryConvertUnit(value, base, upstream);
|
|
2868
2890
|
if (converted !== void 0) return converted;
|
|
2869
2891
|
this.deviceLogger.warn("numeric reading refused", {
|
|
2870
2892
|
tags: { deviceId: this.id },
|
|
@@ -2965,7 +2987,7 @@ function decodeNumeric(state, lastChangedAt, decode) {
|
|
|
2965
2987
|
if (!Number.isFinite(v)) return null;
|
|
2966
2988
|
const rawUnit = state.attributes["unit_of_measurement"];
|
|
2967
2989
|
const unit = typeof rawUnit === "string" && rawUnit.length > 0 ? rawUnit : void 0;
|
|
2968
|
-
const incoming = unit === void 0 ? void 0 :
|
|
2990
|
+
const incoming = unit === void 0 ? void 0 : require_ha_instance_settings.quantityFromUnit(unit);
|
|
2969
2991
|
if (unit !== void 0 && (incoming === void 0 || incoming === "device")) {
|
|
2970
2992
|
decode.logger.warn("numeric reading refused", {
|
|
2971
2993
|
tags: { deviceId: decode.deviceId },
|
|
@@ -2992,7 +3014,7 @@ function decodeNumeric(state, lastChangedAt, decode) {
|
|
|
2992
3014
|
}
|
|
2993
3015
|
const value = takeReading(decode.logger, decode.deviceId, v, unit, quantity);
|
|
2994
3016
|
if (value === null) return null;
|
|
2995
|
-
decode.note(quantity, unit === void 0 ? void 0 :
|
|
3017
|
+
decode.note(quantity, unit === void 0 ? void 0 : require_ha_instance_settings.normalizeUnit(unit));
|
|
2996
3018
|
const rawMin = state.attributes["min"];
|
|
2997
3019
|
const rawMax = state.attributes["max"];
|
|
2998
3020
|
const rawStep = state.attributes["step"];
|
|
@@ -3012,10 +3034,10 @@ function decodeNumeric(state, lastChangedAt, decode) {
|
|
|
3012
3034
|
/** A step is a difference: °F's offset must not move it. */
|
|
3013
3035
|
function convertStep(step, unit, quantity) {
|
|
3014
3036
|
if (step === void 0) return void 0;
|
|
3015
|
-
const base =
|
|
3016
|
-
const from = unit === void 0 ? void 0 :
|
|
3037
|
+
const base = require_ha_instance_settings.baseUnitOf(quantity);
|
|
3038
|
+
const from = unit === void 0 ? void 0 : require_ha_instance_settings.normalizeUnit(unit);
|
|
3017
3039
|
if (base === void 0 || from === void 0 || from === base) return step;
|
|
3018
|
-
return
|
|
3040
|
+
return require_ha_instance_settings.tryConvertDelta(step, from, base);
|
|
3019
3041
|
}
|
|
3020
3042
|
//#endregion
|
|
3021
3043
|
//#region src/devices/ha-script-device.ts
|
|
@@ -3058,7 +3080,7 @@ var HaScriptDevice = class extends HaBaseChildDevice {
|
|
|
3058
3080
|
});
|
|
3059
3081
|
}
|
|
3060
3082
|
registerScriptCap() {
|
|
3061
|
-
this.ctx.registerNativeCap(
|
|
3083
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.scriptRunnerCapability, {
|
|
3062
3084
|
getStatus: async () => {
|
|
3063
3085
|
return this.runtimeState.getCapState("script-runner") ?? COLD_START$7;
|
|
3064
3086
|
},
|
|
@@ -3117,7 +3139,7 @@ var HaAutomationDevice = class extends HaBaseChildDevice {
|
|
|
3117
3139
|
});
|
|
3118
3140
|
}
|
|
3119
3141
|
registerAutomationCap() {
|
|
3120
|
-
this.ctx.registerNativeCap(
|
|
3142
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.automationControlCapability, {
|
|
3121
3143
|
getStatus: async () => {
|
|
3122
3144
|
return this.runtimeState.getCapState("automation-control") ?? COLD_START$6;
|
|
3123
3145
|
},
|
|
@@ -3176,7 +3198,7 @@ var HaNotifierDevice = class extends HaBaseChildDevice {
|
|
|
3176
3198
|
handleStatePush(_state) {}
|
|
3177
3199
|
registerNotifierCap() {
|
|
3178
3200
|
const serviceName = this.entityId.split(".")[1] ?? "";
|
|
3179
|
-
this.ctx.registerNativeCap(
|
|
3201
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.notifierCapability, {
|
|
3180
3202
|
getStatus: async () => {
|
|
3181
3203
|
return this.runtimeState.getCapState("notifier") ?? COLD_START$5;
|
|
3182
3204
|
},
|
|
@@ -3272,7 +3294,7 @@ var HaPowerMeterDevice = class extends HaBaseChildDevice {
|
|
|
3272
3294
|
if (update !== null) this.runtimeState.setCapState("power-meter", update);
|
|
3273
3295
|
}
|
|
3274
3296
|
registerPowerMeterCap() {
|
|
3275
|
-
this.ctx.registerNativeCap(
|
|
3297
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.powerMeterCapability, { getStatus: async () => {
|
|
3276
3298
|
return this.runtimeState.getCapState("power-meter") ?? COLD_START$4;
|
|
3277
3299
|
} });
|
|
3278
3300
|
}
|
|
@@ -3351,7 +3373,7 @@ var HaAirQualityDevice = class extends HaBaseChildDevice {
|
|
|
3351
3373
|
if (update !== null) this.runtimeState.setCapState("air-quality-sensor", update);
|
|
3352
3374
|
}
|
|
3353
3375
|
registerCap() {
|
|
3354
|
-
this.ctx.registerNativeCap(
|
|
3376
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.airQualitySensorCapability, { getStatus: async () => {
|
|
3355
3377
|
return this.runtimeState.getCapState("air-quality-sensor") ?? COLD_START$3;
|
|
3356
3378
|
} });
|
|
3357
3379
|
}
|
|
@@ -3426,7 +3448,7 @@ var HaEnumSensorDevice = class extends HaBaseChildDevice {
|
|
|
3426
3448
|
constructor(ctx) {
|
|
3427
3449
|
const persisted = ctx.persistedConfig ?? {};
|
|
3428
3450
|
super(ctx, persisted.role !== void 0 ? { role: persisted.role } : {});
|
|
3429
|
-
const parsedFormat =
|
|
3451
|
+
const parsedFormat = require_ha_instance_settings.EnumSensorDateTimeFormatSchema.safeParse(persisted.dateTimeFormat);
|
|
3430
3452
|
this.dateTimeFormat = parsedFormat.success ? parsedFormat.data : void 0;
|
|
3431
3453
|
if (this.dateTimeFormat !== void 0) this.updateSourceInfo({ dateTimeShape: this.dateTimeFormat });
|
|
3432
3454
|
this.registerCap();
|
|
@@ -3448,7 +3470,7 @@ var HaEnumSensorDevice = class extends HaBaseChildDevice {
|
|
|
3448
3470
|
});
|
|
3449
3471
|
}
|
|
3450
3472
|
registerCap() {
|
|
3451
|
-
this.ctx.registerNativeCap(
|
|
3473
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.enumSensorCapability, { getStatus: async () => {
|
|
3452
3474
|
return this.runtimeState.getCapState("enum-sensor") ?? this.coldStart();
|
|
3453
3475
|
} });
|
|
3454
3476
|
}
|
|
@@ -3547,7 +3569,7 @@ var HaEventEmitterDevice = class extends HaBaseChildDevice {
|
|
|
3547
3569
|
timestamp: Date.now(),
|
|
3548
3570
|
seq: ++this.#seq
|
|
3549
3571
|
};
|
|
3550
|
-
this.ctx.eventBus.emit(
|
|
3572
|
+
this.ctx.eventBus.emit(require_ha_instance_settings.createEvent(require_ha_instance_settings.EventCategory.EventEmitted, {
|
|
3551
3573
|
type: "device",
|
|
3552
3574
|
id: this.stableId,
|
|
3553
3575
|
deviceId: this.id,
|
|
@@ -3561,7 +3583,7 @@ var HaEventEmitterDevice = class extends HaBaseChildDevice {
|
|
|
3561
3583
|
this.runtimeState.setCapState("event-emitter", slice);
|
|
3562
3584
|
}
|
|
3563
3585
|
registerEventEmitterCap() {
|
|
3564
|
-
this.ctx.registerNativeCap(
|
|
3586
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.eventEmitterCapability, { getStatus: async () => this.readSlice() });
|
|
3565
3587
|
}
|
|
3566
3588
|
readSlice() {
|
|
3567
3589
|
return this.runtimeState.getCapState("event-emitter") ?? {
|
|
@@ -3644,7 +3666,7 @@ var HaWeatherDevice = class extends HaBaseChildDevice {
|
|
|
3644
3666
|
this.runtimeState.setCapState("weather", slice);
|
|
3645
3667
|
}
|
|
3646
3668
|
registerWeatherCap() {
|
|
3647
|
-
this.ctx.registerNativeCap(
|
|
3669
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.weatherCapability, { getStatus: async () => {
|
|
3648
3670
|
return this.runtimeState.getCapState("weather") ?? COLD_START$1;
|
|
3649
3671
|
} });
|
|
3650
3672
|
}
|
|
@@ -3742,7 +3764,7 @@ var HaImageDevice = class extends HaBaseChildDevice {
|
|
|
3742
3764
|
this.deviceLogger.warn("ha-image: failed to build absolute image url", { meta: {
|
|
3743
3765
|
entityId: this.entityId,
|
|
3744
3766
|
brokerId: this.brokerId,
|
|
3745
|
-
error:
|
|
3767
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
3746
3768
|
} });
|
|
3747
3769
|
url = null;
|
|
3748
3770
|
}
|
|
@@ -3774,7 +3796,7 @@ var HaImageDevice = class extends HaBaseChildDevice {
|
|
|
3774
3796
|
return typeof raw === "string" && raw.length > 0 ? raw : null;
|
|
3775
3797
|
}
|
|
3776
3798
|
registerImageCap() {
|
|
3777
|
-
this.ctx.registerNativeCap(
|
|
3799
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.imageCapability, { getStatus: async () => {
|
|
3778
3800
|
return this.runtimeState.getCapState("image") ?? COLD_START;
|
|
3779
3801
|
} });
|
|
3780
3802
|
}
|
|
@@ -3868,28 +3890,28 @@ function pickHaChildClass(capabilities) {
|
|
|
3868
3890
|
//#region src/ha-container-reconcile.ts
|
|
3869
3891
|
/** Validates a persisted Container `entities[]` blob (mirrors `haEntitySchema`
|
|
3870
3892
|
* in ha-container-device.ts). Returns `[]` on absent/invalid input. */
|
|
3871
|
-
var containerEntitySchema =
|
|
3872
|
-
entityId:
|
|
3873
|
-
deviceType:
|
|
3874
|
-
capabilities:
|
|
3875
|
-
role:
|
|
3876
|
-
unitOfMeasurement:
|
|
3877
|
-
deviceClass:
|
|
3878
|
-
options:
|
|
3879
|
-
features:
|
|
3880
|
-
name:
|
|
3881
|
-
dateTimeFormat:
|
|
3882
|
-
entityCategory:
|
|
3883
|
-
meterEntities:
|
|
3884
|
-
power:
|
|
3885
|
-
energy:
|
|
3886
|
-
voltage:
|
|
3887
|
-
current:
|
|
3893
|
+
var containerEntitySchema = require_ha_instance_settings.object({
|
|
3894
|
+
entityId: require_ha_instance_settings.string(),
|
|
3895
|
+
deviceType: require_ha_instance_settings._enum(require_ha_instance_settings.DeviceType),
|
|
3896
|
+
capabilities: require_ha_instance_settings.array(require_ha_instance_settings.string()),
|
|
3897
|
+
role: require_ha_instance_settings.string().optional(),
|
|
3898
|
+
unitOfMeasurement: require_ha_instance_settings.string().optional(),
|
|
3899
|
+
deviceClass: require_ha_instance_settings.string().optional(),
|
|
3900
|
+
options: require_ha_instance_settings.array(require_ha_instance_settings.string()).optional(),
|
|
3901
|
+
features: require_ha_instance_settings.array(require_ha_instance_settings.string()).optional(),
|
|
3902
|
+
name: require_ha_instance_settings.string().optional(),
|
|
3903
|
+
dateTimeFormat: require_ha_instance_settings.EnumSensorDateTimeFormatSchema.optional(),
|
|
3904
|
+
entityCategory: require_ha_instance_settings._enum(["config", "diagnostic"]).optional(),
|
|
3905
|
+
meterEntities: require_ha_instance_settings.object({
|
|
3906
|
+
power: require_ha_instance_settings.string().optional(),
|
|
3907
|
+
energy: require_ha_instance_settings.string().optional(),
|
|
3908
|
+
voltage: require_ha_instance_settings.string().optional(),
|
|
3909
|
+
current: require_ha_instance_settings.string().optional()
|
|
3888
3910
|
}).optional(),
|
|
3889
|
-
foldedInto:
|
|
3911
|
+
foldedInto: require_ha_instance_settings.string().optional()
|
|
3890
3912
|
});
|
|
3891
3913
|
function parseContainerEntities(raw) {
|
|
3892
|
-
const result =
|
|
3914
|
+
const result = require_ha_instance_settings.array(containerEntitySchema).safeParse(raw);
|
|
3893
3915
|
return result.success ? result.data : [];
|
|
3894
3916
|
}
|
|
3895
3917
|
/**
|
|
@@ -4043,45 +4065,45 @@ function deriveChildLayout(entities) {
|
|
|
4043
4065
|
}
|
|
4044
4066
|
//#endregion
|
|
4045
4067
|
//#region src/devices/ha-container-device.ts
|
|
4046
|
-
var haEntitySchema =
|
|
4047
|
-
entityId:
|
|
4048
|
-
deviceType:
|
|
4049
|
-
capabilities:
|
|
4050
|
-
role:
|
|
4051
|
-
unitOfMeasurement:
|
|
4052
|
-
deviceClass:
|
|
4068
|
+
var haEntitySchema = require_ha_instance_settings.object({
|
|
4069
|
+
entityId: require_ha_instance_settings.string(),
|
|
4070
|
+
deviceType: require_ha_instance_settings._enum(require_ha_instance_settings.DeviceType),
|
|
4071
|
+
capabilities: require_ha_instance_settings.array(require_ha_instance_settings.string()),
|
|
4072
|
+
role: require_ha_instance_settings.string().optional(),
|
|
4073
|
+
unitOfMeasurement: require_ha_instance_settings.string().optional(),
|
|
4074
|
+
deviceClass: require_ha_instance_settings.string().optional(),
|
|
4053
4075
|
/** HA `options` attribute — present on select / input_select entities.
|
|
4054
4076
|
* Persisted at adoption so the control slice is seeded immediately. */
|
|
4055
|
-
options:
|
|
4077
|
+
options: require_ha_instance_settings.array(require_ha_instance_settings.string()).optional(),
|
|
4056
4078
|
/** Mapping-derived DeviceFeature flags (e.g. `lock-open`) — surfaced on the
|
|
4057
4079
|
* child's `device.features` so the UI gates feature affordances. */
|
|
4058
|
-
features:
|
|
4080
|
+
features: require_ha_instance_settings.array(require_ha_instance_settings.string()).optional(),
|
|
4059
4081
|
/** HA friendly_name — persisted so the child device name survives
|
|
4060
4082
|
* a reboot without a discovery round-trip. Falls back to entityId. */
|
|
4061
|
-
name:
|
|
4083
|
+
name: require_ha_instance_settings.string().optional(),
|
|
4062
4084
|
/** Locale-render shape for a `DateTimeSensor`-role enum sensor
|
|
4063
4085
|
* (`device_class=timestamp` → `'datetime'`, `date` → `'date'`). Seeded into
|
|
4064
4086
|
* the enum-sensor cap slice by the child so the UI renders the ISO `value`. */
|
|
4065
|
-
dateTimeFormat:
|
|
4087
|
+
dateTimeFormat: require_ha_instance_settings.EnumSensorDateTimeFormatSchema.optional(),
|
|
4066
4088
|
/** HA `entity_category` — `config` / `diagnostic` / absent (a normal
|
|
4067
4089
|
* control). Drives the accordion section the child renders in. */
|
|
4068
|
-
entityCategory:
|
|
4090
|
+
entityCategory: require_ha_instance_settings._enum(["config", "diagnostic"]).optional(),
|
|
4069
4091
|
/** Sibling meter sensors this entity reads as its own power-meter (D951). */
|
|
4070
|
-
meterEntities:
|
|
4071
|
-
power:
|
|
4072
|
-
energy:
|
|
4073
|
-
voltage:
|
|
4074
|
-
current:
|
|
4092
|
+
meterEntities: require_ha_instance_settings.object({
|
|
4093
|
+
power: require_ha_instance_settings.string().optional(),
|
|
4094
|
+
energy: require_ha_instance_settings.string().optional(),
|
|
4095
|
+
voltage: require_ha_instance_settings.string().optional(),
|
|
4096
|
+
current: require_ha_instance_settings.string().optional()
|
|
4075
4097
|
}).optional(),
|
|
4076
4098
|
/** Set on a meter sensor folded into another entity: sectioned as Diagnostic. */
|
|
4077
|
-
foldedInto:
|
|
4099
|
+
foldedInto: require_ha_instance_settings.string().optional()
|
|
4078
4100
|
});
|
|
4079
|
-
var haContainerSchema =
|
|
4080
|
-
system:
|
|
4081
|
-
brokerId:
|
|
4082
|
-
haDeviceId:
|
|
4083
|
-
integrationId:
|
|
4084
|
-
entities:
|
|
4101
|
+
var haContainerSchema = require_ha_instance_settings.object({
|
|
4102
|
+
system: require_ha_instance_settings.literal("homeassistant"),
|
|
4103
|
+
brokerId: require_ha_instance_settings.string(),
|
|
4104
|
+
haDeviceId: require_ha_instance_settings.string(),
|
|
4105
|
+
integrationId: require_ha_instance_settings.string().optional(),
|
|
4106
|
+
entities: require_ha_instance_settings.array(haEntitySchema).default([])
|
|
4085
4107
|
});
|
|
4086
4108
|
/**
|
|
4087
4109
|
* A container entity is a battery source when the HA domain mapping
|
|
@@ -4091,7 +4113,7 @@ var haContainerSchema = require_ha_broker_source.object({
|
|
|
4091
4113
|
* device_class is the original HA attribute that drove it.
|
|
4092
4114
|
*/
|
|
4093
4115
|
function isBatteryEntity(entity) {
|
|
4094
|
-
return entity.role ===
|
|
4116
|
+
return entity.role === require_ha_instance_settings.DeviceRole.BatterySensor || entity.deviceClass === "battery";
|
|
4095
4117
|
}
|
|
4096
4118
|
/**
|
|
4097
4119
|
* A battery entity is BINARY when HA exposes it as a `binary_sensor`
|
|
@@ -4183,7 +4205,7 @@ function batteryEntityId(entities) {
|
|
|
4183
4205
|
* persist initial config, build context, construct via factory, then
|
|
4184
4206
|
* run the child's own probe + accessory + activate phases.
|
|
4185
4207
|
*/
|
|
4186
|
-
var HaContainerDevice = class HaContainerDevice extends
|
|
4208
|
+
var HaContainerDevice = class HaContainerDevice extends require_ha_instance_settings.BaseDevice {
|
|
4187
4209
|
features;
|
|
4188
4210
|
brokerId;
|
|
4189
4211
|
integrationId;
|
|
@@ -4204,10 +4226,10 @@ var HaContainerDevice = class HaContainerDevice extends require_ha_broker_source
|
|
|
4204
4226
|
constructor(ctx) {
|
|
4205
4227
|
const cfg = haContainerSchema.parse(ctx.persistedConfig ?? {});
|
|
4206
4228
|
const batteryEntity = selectBatteryEntity(cfg.entities);
|
|
4207
|
-
super(ctx, haContainerSchema, { type:
|
|
4229
|
+
super(ctx, haContainerSchema, { type: require_ha_instance_settings.DeviceType.Container });
|
|
4208
4230
|
this.brokerId = cfg.brokerId;
|
|
4209
4231
|
this.integrationId = cfg.integrationId;
|
|
4210
|
-
this.features = batteryEntity !== null ? [
|
|
4232
|
+
this.features = batteryEntity !== null ? [require_ha_instance_settings.DeviceFeature.Resyncable, require_ha_instance_settings.DeviceFeature.BatteryOperated] : [require_ha_instance_settings.DeviceFeature.Resyncable];
|
|
4211
4233
|
this.entityIds = new Set(cfg.entities.map((e) => e.entityId));
|
|
4212
4234
|
this.online = false;
|
|
4213
4235
|
this.batteryEntityId = batteryEntityId(cfg.entities);
|
|
@@ -4218,7 +4240,7 @@ var HaContainerDevice = class HaContainerDevice extends require_ha_broker_source
|
|
|
4218
4240
|
sleeping: false,
|
|
4219
4241
|
lastUpdated: 0
|
|
4220
4242
|
};
|
|
4221
|
-
this.ctx.registerNativeCap(
|
|
4243
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.batteryCapability, {
|
|
4222
4244
|
getStatus: async () => this.runtimeState.getCapState("battery") ?? COLD,
|
|
4223
4245
|
wakeForStream: async () => ({
|
|
4224
4246
|
awoke: true,
|
|
@@ -4293,7 +4315,7 @@ var HaContainerDevice = class HaContainerDevice extends require_ha_broker_source
|
|
|
4293
4315
|
} catch (err) {
|
|
4294
4316
|
this.ctx.logger.warn("ha-container failed to subscribe entities for availability", { meta: {
|
|
4295
4317
|
brokerId: this.brokerId,
|
|
4296
|
-
error:
|
|
4318
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
4297
4319
|
} });
|
|
4298
4320
|
}
|
|
4299
4321
|
}
|
|
@@ -4334,7 +4356,7 @@ var HaContainerDevice = class HaContainerDevice extends require_ha_broker_source
|
|
|
4334
4356
|
} catch (err) {
|
|
4335
4357
|
this.ctx.logger.warn("ha-container failed to persist childLayout", { meta: {
|
|
4336
4358
|
haDeviceId: this.config.values.haDeviceId,
|
|
4337
|
-
error:
|
|
4359
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
4338
4360
|
} });
|
|
4339
4361
|
}
|
|
4340
4362
|
}
|
|
@@ -4413,10 +4435,10 @@ var HaContainerDevice = class HaContainerDevice extends require_ha_broker_source
|
|
|
4413
4435
|
* entity-backed (no `entityId`), so it does NOT extend the HA child base
|
|
4414
4436
|
* device — it is a thin standalone `BaseDevice` subclass.
|
|
4415
4437
|
*/
|
|
4416
|
-
var haEventBusDeviceSchema =
|
|
4417
|
-
system:
|
|
4418
|
-
brokerId:
|
|
4419
|
-
kind:
|
|
4438
|
+
var haEventBusDeviceSchema = require_ha_instance_settings.object({
|
|
4439
|
+
system: require_ha_instance_settings.literal("homeassistant"),
|
|
4440
|
+
brokerId: require_ha_instance_settings.string(),
|
|
4441
|
+
kind: require_ha_instance_settings.literal("event-bus")
|
|
4420
4442
|
});
|
|
4421
4443
|
/**
|
|
4422
4444
|
* Case 2 — generic per-broker HA bus-event aggregator.
|
|
@@ -4437,7 +4459,7 @@ var haEventBusDeviceSchema = require_ha_broker_source.object({
|
|
|
4437
4459
|
* directly via {@link handleBusEvent} (the integration manager subscribes
|
|
4438
4460
|
* to the curated bus event types and threads each fire through the addon).
|
|
4439
4461
|
*/
|
|
4440
|
-
var HaEventBusDevice = class extends
|
|
4462
|
+
var HaEventBusDevice = class extends require_ha_instance_settings.BaseDevice {
|
|
4441
4463
|
features = [];
|
|
4442
4464
|
/** Monotonic sequence — two identical events still produce distinct slice
|
|
4443
4465
|
* writes / bus emissions. */
|
|
@@ -4476,7 +4498,7 @@ var HaEventBusDevice = class extends require_ha_broker_source.BaseDevice {
|
|
|
4476
4498
|
timestamp: Date.now(),
|
|
4477
4499
|
seq: ++this.#seq
|
|
4478
4500
|
};
|
|
4479
|
-
this.ctx.eventBus.emit(
|
|
4501
|
+
this.ctx.eventBus.emit(require_ha_instance_settings.createEvent(require_ha_instance_settings.EventCategory.EventEmitted, {
|
|
4480
4502
|
type: "device",
|
|
4481
4503
|
id: this.stableId,
|
|
4482
4504
|
deviceId: this.id,
|
|
@@ -4490,7 +4512,7 @@ var HaEventBusDevice = class extends require_ha_broker_source.BaseDevice {
|
|
|
4490
4512
|
this.runtimeState.setCapState("event-emitter", slice);
|
|
4491
4513
|
}
|
|
4492
4514
|
registerEventEmitterCap() {
|
|
4493
|
-
this.ctx.registerNativeCap(
|
|
4515
|
+
this.ctx.registerNativeCap(require_ha_instance_settings.eventEmitterCapability, { getStatus: async () => this.readSlice() });
|
|
4494
4516
|
}
|
|
4495
4517
|
readSlice() {
|
|
4496
4518
|
return this.runtimeState.getCapState("event-emitter") ?? {
|
|
@@ -4525,7 +4547,7 @@ async function cascadeRemoveDevicesForBroker(input) {
|
|
|
4525
4547
|
tags: { deviceId: d.id },
|
|
4526
4548
|
meta: {
|
|
4527
4549
|
brokerId,
|
|
4528
|
-
error:
|
|
4550
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
4529
4551
|
}
|
|
4530
4552
|
});
|
|
4531
4553
|
}
|
|
@@ -5431,7 +5453,7 @@ var HaIntegrationManager = class HaIntegrationManager {
|
|
|
5431
5453
|
} catch (err) {
|
|
5432
5454
|
this.opts.logger.warn("ha-broker onConnected handler threw", { meta: {
|
|
5433
5455
|
brokerId: this.opts.id,
|
|
5434
|
-
error:
|
|
5456
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
5435
5457
|
} });
|
|
5436
5458
|
}
|
|
5437
5459
|
},
|
|
@@ -5446,12 +5468,12 @@ var HaIntegrationManager = class HaIntegrationManager {
|
|
|
5446
5468
|
} catch (err) {
|
|
5447
5469
|
this.opts.logger.warn("ha-broker onDisconnected handler threw", { meta: {
|
|
5448
5470
|
brokerId: this.opts.id,
|
|
5449
|
-
error:
|
|
5471
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
5450
5472
|
} });
|
|
5451
5473
|
}
|
|
5452
5474
|
},
|
|
5453
5475
|
onReconnectError: (err, nextDelayMs) => {
|
|
5454
|
-
this.lastError =
|
|
5476
|
+
this.lastError = require_ha_instance_settings.errMsg(err);
|
|
5455
5477
|
this.opts.logger.warn("ha-broker reconnect attempt failed", { meta: {
|
|
5456
5478
|
brokerId: this.opts.id,
|
|
5457
5479
|
error: this.lastError,
|
|
@@ -5632,7 +5654,7 @@ var HaIntegrationManager = class HaIntegrationManager {
|
|
|
5632
5654
|
this.opts.logger.warn("ha-broker bus-event subscribe failed", { meta: {
|
|
5633
5655
|
brokerId: this.opts.id,
|
|
5634
5656
|
eventType,
|
|
5635
|
-
error:
|
|
5657
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
5636
5658
|
} });
|
|
5637
5659
|
}
|
|
5638
5660
|
}
|
|
@@ -5668,7 +5690,7 @@ var HaIntegrationManager = class HaIntegrationManager {
|
|
|
5668
5690
|
return false;
|
|
5669
5691
|
}
|
|
5670
5692
|
emitBrokerMessage(subscriptionId, entityId, state) {
|
|
5671
|
-
this.opts.eventBus.emit(
|
|
5693
|
+
this.opts.eventBus.emit(require_ha_instance_settings.createEvent("broker.message", {
|
|
5672
5694
|
type: "addon",
|
|
5673
5695
|
id: this.opts.id
|
|
5674
5696
|
}, {
|
|
@@ -5690,7 +5712,7 @@ var HaIntegrationManager = class HaIntegrationManager {
|
|
|
5690
5712
|
} catch (err) {
|
|
5691
5713
|
this.opts.logger.debug("ha get_config probe failed", { meta: {
|
|
5692
5714
|
brokerId: this.opts.id,
|
|
5693
|
-
error:
|
|
5715
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
5694
5716
|
} });
|
|
5695
5717
|
}
|
|
5696
5718
|
}
|
|
@@ -5698,7 +5720,7 @@ var HaIntegrationManager = class HaIntegrationManager {
|
|
|
5698
5720
|
if (this.status === next) return;
|
|
5699
5721
|
this.status = next;
|
|
5700
5722
|
this.lastCheckedAt = Date.now();
|
|
5701
|
-
this.opts.eventBus.emit(
|
|
5723
|
+
this.opts.eventBus.emit(require_ha_instance_settings.createEvent("broker.status-changed", {
|
|
5702
5724
|
type: "addon",
|
|
5703
5725
|
id: this.opts.id
|
|
5704
5726
|
}, {
|
|
@@ -5719,7 +5741,7 @@ var HaIntegrationManager = class HaIntegrationManager {
|
|
|
5719
5741
|
this.lastError = "Home Assistant host / URL is required";
|
|
5720
5742
|
this.setStatus("unreachable");
|
|
5721
5743
|
} else {
|
|
5722
|
-
this.lastError =
|
|
5744
|
+
this.lastError = require_ha_instance_settings.errMsg(err);
|
|
5723
5745
|
this.setStatus("error");
|
|
5724
5746
|
}
|
|
5725
5747
|
}
|
|
@@ -5740,17 +5762,17 @@ var TEST_HANDSHAKE_TIMEOUT_MS = 8e3;
|
|
|
5740
5762
|
* `dataDir` being protected by filesystem permissions. (MQTT broker
|
|
5741
5763
|
* encrypts at rest; HA broker does not yet — TODO for hardening.)
|
|
5742
5764
|
*/
|
|
5743
|
-
var HaBrokerEntrySchema =
|
|
5744
|
-
id:
|
|
5745
|
-
name:
|
|
5765
|
+
var HaBrokerEntrySchema = require_ha_instance_settings.object({
|
|
5766
|
+
id: require_ha_instance_settings.string(),
|
|
5767
|
+
name: require_ha_instance_settings.string(),
|
|
5746
5768
|
/** Either Supervisor (token from env) or long-lived (persisted). */
|
|
5747
|
-
auth:
|
|
5748
|
-
kind:
|
|
5749
|
-
supervisorToken:
|
|
5750
|
-
}),
|
|
5751
|
-
kind:
|
|
5752
|
-
baseUrl:
|
|
5753
|
-
accessToken:
|
|
5769
|
+
auth: require_ha_instance_settings.discriminatedUnion("kind", [require_ha_instance_settings.object({
|
|
5770
|
+
kind: require_ha_instance_settings.literal("supervisor"),
|
|
5771
|
+
supervisorToken: require_ha_instance_settings.string().meta({ secret: true })
|
|
5772
|
+
}), require_ha_instance_settings.object({
|
|
5773
|
+
kind: require_ha_instance_settings.literal("long-lived"),
|
|
5774
|
+
baseUrl: require_ha_instance_settings.string(),
|
|
5775
|
+
accessToken: require_ha_instance_settings.string().meta({ secret: true })
|
|
5754
5776
|
})]),
|
|
5755
5777
|
/** Optional FK to the integration record that spawned this broker.
|
|
5756
5778
|
* Populated when the wizard's "+ New Integration" flow created the
|
|
@@ -5758,7 +5780,7 @@ var HaBrokerEntrySchema = require_ha_broker_source.object({
|
|
|
5758
5780
|
* directly. Used by the integration listener to keep the broker
|
|
5759
5781
|
* list in sync with the integrations table (cascade-delete on
|
|
5760
5782
|
* integration removal). */
|
|
5761
|
-
integrationId:
|
|
5783
|
+
integrationId: require_ha_instance_settings.string().optional()
|
|
5762
5784
|
});
|
|
5763
5785
|
/**
|
|
5764
5786
|
* Validates a `broker.add` `settings` payload for the HA kind. Accepts:
|
|
@@ -5767,10 +5789,10 @@ var HaBrokerEntrySchema = require_ha_broker_source.object({
|
|
|
5767
5789
|
* persisting allows the addon to keep working after the env var
|
|
5768
5790
|
* rotates out of scope)
|
|
5769
5791
|
*/
|
|
5770
|
-
var HaAddSettingsSchema =
|
|
5771
|
-
baseUrl:
|
|
5772
|
-
accessToken:
|
|
5773
|
-
}),
|
|
5792
|
+
var HaAddSettingsSchema = require_ha_instance_settings.union([require_ha_instance_settings.object({
|
|
5793
|
+
baseUrl: require_ha_instance_settings.url(),
|
|
5794
|
+
accessToken: require_ha_instance_settings.string().min(1).meta({ secret: true })
|
|
5795
|
+
}), require_ha_instance_settings.object({ supervisorToken: require_ha_instance_settings.string().min(1).meta({ secret: true }) })]);
|
|
5774
5796
|
function settingsToAuth(settings) {
|
|
5775
5797
|
const parsed = HaAddSettingsSchema.parse(settings);
|
|
5776
5798
|
if ("supervisorToken" in parsed) return {
|
|
@@ -5851,7 +5873,7 @@ var HaBrokerRegistry = class {
|
|
|
5851
5873
|
} catch (err) {
|
|
5852
5874
|
this.logger.warn("ha-broker bootstrap failed", { meta: {
|
|
5853
5875
|
brokerId: entry.id,
|
|
5854
|
-
error:
|
|
5876
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
5855
5877
|
} });
|
|
5856
5878
|
}
|
|
5857
5879
|
}));
|
|
@@ -5945,7 +5967,7 @@ var HaBrokerRegistry = class {
|
|
|
5945
5967
|
} catch (err) {
|
|
5946
5968
|
return {
|
|
5947
5969
|
ok: false,
|
|
5948
|
-
error:
|
|
5970
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
5949
5971
|
};
|
|
5950
5972
|
}
|
|
5951
5973
|
const startedAt = Date.now();
|
|
@@ -5983,7 +6005,7 @@ var HaBrokerRegistry = class {
|
|
|
5983
6005
|
client?.stop();
|
|
5984
6006
|
resolve({
|
|
5985
6007
|
ok: false,
|
|
5986
|
-
error:
|
|
6008
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
5987
6009
|
});
|
|
5988
6010
|
}
|
|
5989
6011
|
}
|
|
@@ -5995,7 +6017,7 @@ var HaBrokerRegistry = class {
|
|
|
5995
6017
|
client?.stop();
|
|
5996
6018
|
resolve({
|
|
5997
6019
|
ok: false,
|
|
5998
|
-
error:
|
|
6020
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
5999
6021
|
});
|
|
6000
6022
|
});
|
|
6001
6023
|
});
|
|
@@ -6190,27 +6212,27 @@ function mapHaEntityToCamStack(input) {
|
|
|
6190
6212
|
const { domain, deviceClass, attributes } = input;
|
|
6191
6213
|
switch (domain) {
|
|
6192
6214
|
case "switch": return {
|
|
6193
|
-
deviceType:
|
|
6194
|
-
role: deviceClass === "outlet" ?
|
|
6215
|
+
deviceType: require_ha_instance_settings.DeviceType.Switch,
|
|
6216
|
+
role: deviceClass === "outlet" ? require_ha_instance_settings.DeviceRole.Outlet : null,
|
|
6195
6217
|
capabilities: ["switch"]
|
|
6196
6218
|
};
|
|
6197
6219
|
case "input_boolean": return {
|
|
6198
|
-
deviceType:
|
|
6199
|
-
role:
|
|
6220
|
+
deviceType: require_ha_instance_settings.DeviceType.Switch,
|
|
6221
|
+
role: require_ha_instance_settings.DeviceRole.BinaryHelper,
|
|
6200
6222
|
capabilities: ["switch"]
|
|
6201
6223
|
};
|
|
6202
6224
|
case "remote": return {
|
|
6203
|
-
deviceType:
|
|
6225
|
+
deviceType: require_ha_instance_settings.DeviceType.Switch,
|
|
6204
6226
|
role: null,
|
|
6205
6227
|
capabilities: ["switch"]
|
|
6206
6228
|
};
|
|
6207
6229
|
case "siren": return {
|
|
6208
|
-
deviceType:
|
|
6230
|
+
deviceType: require_ha_instance_settings.DeviceType.Siren,
|
|
6209
6231
|
role: null,
|
|
6210
6232
|
capabilities: ["switch"]
|
|
6211
6233
|
};
|
|
6212
6234
|
case "update": return {
|
|
6213
|
-
deviceType:
|
|
6235
|
+
deviceType: require_ha_instance_settings.DeviceType.Update,
|
|
6214
6236
|
role: null,
|
|
6215
6237
|
capabilities: ["update"]
|
|
6216
6238
|
};
|
|
@@ -6228,7 +6250,7 @@ function mapHaEntityToCamStack(input) {
|
|
|
6228
6250
|
case "alarm_control_panel": return mapAlarmPanel(attributes);
|
|
6229
6251
|
case "person":
|
|
6230
6252
|
case "device_tracker": return {
|
|
6231
|
-
deviceType:
|
|
6253
|
+
deviceType: require_ha_instance_settings.DeviceType.Presence,
|
|
6232
6254
|
role: null,
|
|
6233
6255
|
capabilities: ["presence"]
|
|
6234
6256
|
};
|
|
@@ -6237,49 +6259,49 @@ function mapHaEntityToCamStack(input) {
|
|
|
6237
6259
|
case "camera": return mapImage(attributes);
|
|
6238
6260
|
case "number":
|
|
6239
6261
|
case "input_number": return {
|
|
6240
|
-
deviceType:
|
|
6241
|
-
role:
|
|
6262
|
+
deviceType: require_ha_instance_settings.DeviceType.Control,
|
|
6263
|
+
role: require_ha_instance_settings.DeviceRole.NumericControl,
|
|
6242
6264
|
capabilities: ["control"]
|
|
6243
6265
|
};
|
|
6244
6266
|
case "select":
|
|
6245
6267
|
case "input_select": return {
|
|
6246
|
-
deviceType:
|
|
6247
|
-
role:
|
|
6268
|
+
deviceType: require_ha_instance_settings.DeviceType.Control,
|
|
6269
|
+
role: require_ha_instance_settings.DeviceRole.SelectControl,
|
|
6248
6270
|
capabilities: ["control"]
|
|
6249
6271
|
};
|
|
6250
6272
|
case "text":
|
|
6251
6273
|
case "input_text": return {
|
|
6252
|
-
deviceType:
|
|
6253
|
-
role:
|
|
6274
|
+
deviceType: require_ha_instance_settings.DeviceType.Control,
|
|
6275
|
+
role: require_ha_instance_settings.DeviceRole.TextControl,
|
|
6254
6276
|
capabilities: ["control"]
|
|
6255
6277
|
};
|
|
6256
6278
|
case "input_datetime":
|
|
6257
6279
|
case "date":
|
|
6258
6280
|
case "time":
|
|
6259
6281
|
case "datetime": return {
|
|
6260
|
-
deviceType:
|
|
6261
|
-
role:
|
|
6282
|
+
deviceType: require_ha_instance_settings.DeviceType.Control,
|
|
6283
|
+
role: require_ha_instance_settings.DeviceRole.DateTimeControl,
|
|
6262
6284
|
capabilities: ["control"]
|
|
6263
6285
|
};
|
|
6264
6286
|
case "button":
|
|
6265
6287
|
case "input_button":
|
|
6266
6288
|
case "scene": return {
|
|
6267
|
-
deviceType:
|
|
6289
|
+
deviceType: require_ha_instance_settings.DeviceType.Button,
|
|
6268
6290
|
role: null,
|
|
6269
6291
|
capabilities: ["button"]
|
|
6270
6292
|
};
|
|
6271
6293
|
case "event": return {
|
|
6272
|
-
deviceType:
|
|
6294
|
+
deviceType: require_ha_instance_settings.DeviceType.EventEmitter,
|
|
6273
6295
|
role: null,
|
|
6274
6296
|
capabilities: ["event-emitter"]
|
|
6275
6297
|
};
|
|
6276
6298
|
case "script": return {
|
|
6277
|
-
deviceType:
|
|
6299
|
+
deviceType: require_ha_instance_settings.DeviceType.Script,
|
|
6278
6300
|
role: null,
|
|
6279
6301
|
capabilities: ["script-runner"]
|
|
6280
6302
|
};
|
|
6281
6303
|
case "automation": return {
|
|
6282
|
-
deviceType:
|
|
6304
|
+
deviceType: require_ha_instance_settings.DeviceType.Automation,
|
|
6283
6305
|
role: null,
|
|
6284
6306
|
capabilities: ["automation-control"]
|
|
6285
6307
|
};
|
|
@@ -6305,12 +6327,12 @@ function mapLight(attributes) {
|
|
|
6305
6327
|
const hasMired = modes.some((m) => m === "color_temp");
|
|
6306
6328
|
if (hasRgb || hasMired) {
|
|
6307
6329
|
capabilities.push("color");
|
|
6308
|
-
if (modes.includes("rgb") || modes.includes("rgbw") || modes.includes("rgbww") || modes.includes("xy")) features.push(
|
|
6309
|
-
if (modes.includes("hs")) features.push(
|
|
6310
|
-
if (hasMired) features.push(
|
|
6330
|
+
if (modes.includes("rgb") || modes.includes("rgbw") || modes.includes("rgbww") || modes.includes("xy")) features.push(require_ha_instance_settings.DeviceFeature.LightColorRgb);
|
|
6331
|
+
if (modes.includes("hs")) features.push(require_ha_instance_settings.DeviceFeature.LightColorHsv);
|
|
6332
|
+
if (hasMired) features.push(require_ha_instance_settings.DeviceFeature.LightColorMired);
|
|
6311
6333
|
}
|
|
6312
6334
|
return {
|
|
6313
|
-
deviceType:
|
|
6335
|
+
deviceType: require_ha_instance_settings.DeviceType.Light,
|
|
6314
6336
|
role: null,
|
|
6315
6337
|
capabilities,
|
|
6316
6338
|
features
|
|
@@ -6318,11 +6340,11 @@ function mapLight(attributes) {
|
|
|
6318
6340
|
}
|
|
6319
6341
|
function mapLock(attributes) {
|
|
6320
6342
|
const features = [];
|
|
6321
|
-
if (attributes["code_format"] !== void 0 && attributes["code_format"] !== null) features.push(
|
|
6343
|
+
if (attributes["code_format"] !== void 0 && attributes["code_format"] !== null) features.push(require_ha_instance_settings.DeviceFeature.LockPinRequired);
|
|
6322
6344
|
const sf = readNumericAttr(attributes, "supported_features");
|
|
6323
|
-
if (sf !== null && (sf & 1) !== 0) features.push(
|
|
6345
|
+
if (sf !== null && (sf & 1) !== 0) features.push(require_ha_instance_settings.DeviceFeature.LockOpen);
|
|
6324
6346
|
return {
|
|
6325
|
-
deviceType:
|
|
6347
|
+
deviceType: require_ha_instance_settings.DeviceType.Lock,
|
|
6326
6348
|
role: null,
|
|
6327
6349
|
capabilities: ["lock-control"],
|
|
6328
6350
|
features
|
|
@@ -6331,11 +6353,11 @@ function mapLock(attributes) {
|
|
|
6331
6353
|
function mapCover(attributes, deviceClass) {
|
|
6332
6354
|
const features = [];
|
|
6333
6355
|
const sf = readNumericAttr(attributes, "supported_features");
|
|
6334
|
-
if (sf !== null && (sf & 4) !== 0) features.push(
|
|
6335
|
-
if (sf !== null && (sf & 8) !== 0) features.push(
|
|
6336
|
-
if (sf !== null && (sf & 128) !== 0) features.push(
|
|
6356
|
+
if (sf !== null && (sf & 4) !== 0) features.push(require_ha_instance_settings.DeviceFeature.CoverPositionable);
|
|
6357
|
+
if (sf !== null && (sf & 8) !== 0) features.push(require_ha_instance_settings.DeviceFeature.CoverStoppable);
|
|
6358
|
+
if (sf !== null && (sf & 128) !== 0) features.push(require_ha_instance_settings.DeviceFeature.CoverTilt);
|
|
6337
6359
|
return {
|
|
6338
|
-
deviceType:
|
|
6360
|
+
deviceType: require_ha_instance_settings.DeviceType.Cover,
|
|
6339
6361
|
role: coverRoleFor(deviceClass),
|
|
6340
6362
|
capabilities: ["cover"],
|
|
6341
6363
|
features
|
|
@@ -6345,23 +6367,23 @@ function mapCover(attributes, deviceClass) {
|
|
|
6345
6367
|
function coverRoleFor(deviceClass) {
|
|
6346
6368
|
switch (deviceClass) {
|
|
6347
6369
|
case "blind":
|
|
6348
|
-
case "shade": return
|
|
6349
|
-
case "shutter": return
|
|
6350
|
-
case "awning": return
|
|
6351
|
-
case "curtain": return
|
|
6352
|
-
case "garage": return
|
|
6353
|
-
case "gate": return
|
|
6354
|
-
case "door": return
|
|
6355
|
-
case "window": return
|
|
6370
|
+
case "shade": return require_ha_instance_settings.DeviceRole.CoverBlind;
|
|
6371
|
+
case "shutter": return require_ha_instance_settings.DeviceRole.CoverShutter;
|
|
6372
|
+
case "awning": return require_ha_instance_settings.DeviceRole.CoverAwning;
|
|
6373
|
+
case "curtain": return require_ha_instance_settings.DeviceRole.CoverCurtain;
|
|
6374
|
+
case "garage": return require_ha_instance_settings.DeviceRole.CoverGarage;
|
|
6375
|
+
case "gate": return require_ha_instance_settings.DeviceRole.CoverGate;
|
|
6376
|
+
case "door": return require_ha_instance_settings.DeviceRole.CoverDoor;
|
|
6377
|
+
case "window": return require_ha_instance_settings.DeviceRole.CoverWindow;
|
|
6356
6378
|
default: return null;
|
|
6357
6379
|
}
|
|
6358
6380
|
}
|
|
6359
6381
|
function mapValve(attributes, _deviceClass) {
|
|
6360
6382
|
const features = [];
|
|
6361
6383
|
const sf = readNumericAttr(attributes, "supported_features");
|
|
6362
|
-
if (sf !== null && (sf & 4) !== 0) features.push(
|
|
6384
|
+
if (sf !== null && (sf & 4) !== 0) features.push(require_ha_instance_settings.DeviceFeature.ValvePositionable);
|
|
6363
6385
|
return {
|
|
6364
|
-
deviceType:
|
|
6386
|
+
deviceType: require_ha_instance_settings.DeviceType.Valve,
|
|
6365
6387
|
role: null,
|
|
6366
6388
|
capabilities: ["valve"],
|
|
6367
6389
|
features
|
|
@@ -6369,7 +6391,7 @@ function mapValve(attributes, _deviceClass) {
|
|
|
6369
6391
|
}
|
|
6370
6392
|
function mapHumidifier(_attributes, _deviceClass) {
|
|
6371
6393
|
return {
|
|
6372
|
-
deviceType:
|
|
6394
|
+
deviceType: require_ha_instance_settings.DeviceType.Humidifier,
|
|
6373
6395
|
role: null,
|
|
6374
6396
|
capabilities: ["humidifier"],
|
|
6375
6397
|
features: []
|
|
@@ -6377,7 +6399,7 @@ function mapHumidifier(_attributes, _deviceClass) {
|
|
|
6377
6399
|
}
|
|
6378
6400
|
function mapWaterHeater(_attributes, _deviceClass) {
|
|
6379
6401
|
return {
|
|
6380
|
-
deviceType:
|
|
6402
|
+
deviceType: require_ha_instance_settings.DeviceType.WaterHeater,
|
|
6381
6403
|
role: null,
|
|
6382
6404
|
capabilities: ["water-heater"],
|
|
6383
6405
|
features: []
|
|
@@ -6387,13 +6409,13 @@ function mapFan(attributes) {
|
|
|
6387
6409
|
const features = [];
|
|
6388
6410
|
const sf = readNumericAttr(attributes, "supported_features");
|
|
6389
6411
|
if (sf !== null) {
|
|
6390
|
-
if ((sf & 1) !== 0) features.push(
|
|
6391
|
-
if ((sf & 2) !== 0) features.push(
|
|
6392
|
-
if ((sf & 4) !== 0) features.push(
|
|
6393
|
-
if ((sf & 8) !== 0) features.push(
|
|
6412
|
+
if ((sf & 1) !== 0) features.push(require_ha_instance_settings.DeviceFeature.FanSpeed);
|
|
6413
|
+
if ((sf & 2) !== 0) features.push(require_ha_instance_settings.DeviceFeature.FanOscillating);
|
|
6414
|
+
if ((sf & 4) !== 0) features.push(require_ha_instance_settings.DeviceFeature.FanDirection);
|
|
6415
|
+
if ((sf & 8) !== 0) features.push(require_ha_instance_settings.DeviceFeature.FanPreset);
|
|
6394
6416
|
}
|
|
6395
6417
|
return {
|
|
6396
|
-
deviceType:
|
|
6418
|
+
deviceType: require_ha_instance_settings.DeviceType.Fan,
|
|
6397
6419
|
role: null,
|
|
6398
6420
|
capabilities: ["switch", "fan-control"],
|
|
6399
6421
|
features
|
|
@@ -6401,7 +6423,7 @@ function mapFan(attributes) {
|
|
|
6401
6423
|
}
|
|
6402
6424
|
function mapVacuum(_attributes) {
|
|
6403
6425
|
return {
|
|
6404
|
-
deviceType:
|
|
6426
|
+
deviceType: require_ha_instance_settings.DeviceType.Vacuum,
|
|
6405
6427
|
role: null,
|
|
6406
6428
|
capabilities: ["vacuum-control"],
|
|
6407
6429
|
features: []
|
|
@@ -6409,7 +6431,7 @@ function mapVacuum(_attributes) {
|
|
|
6409
6431
|
}
|
|
6410
6432
|
function mapLawnMower(_attributes) {
|
|
6411
6433
|
return {
|
|
6412
|
-
deviceType:
|
|
6434
|
+
deviceType: require_ha_instance_settings.DeviceType.LawnMower,
|
|
6413
6435
|
role: null,
|
|
6414
6436
|
capabilities: ["lawn-mower-control"],
|
|
6415
6437
|
features: []
|
|
@@ -6419,13 +6441,13 @@ function mapClimate(attributes) {
|
|
|
6419
6441
|
const features = [];
|
|
6420
6442
|
const sf = readNumericAttr(attributes, "supported_features");
|
|
6421
6443
|
if (sf !== null) {
|
|
6422
|
-
if ((sf & 2) !== 0) features.push(
|
|
6423
|
-
if ((sf & 4) !== 0) features.push(
|
|
6424
|
-
if ((sf & 8) !== 0) features.push(
|
|
6425
|
-
if ((sf & 16) !== 0) features.push(
|
|
6444
|
+
if ((sf & 2) !== 0) features.push(require_ha_instance_settings.DeviceFeature.ClimateDualSetpoint);
|
|
6445
|
+
if ((sf & 4) !== 0) features.push(require_ha_instance_settings.DeviceFeature.ClimateHumidity);
|
|
6446
|
+
if ((sf & 8) !== 0) features.push(require_ha_instance_settings.DeviceFeature.ClimateFanMode);
|
|
6447
|
+
if ((sf & 16) !== 0) features.push(require_ha_instance_settings.DeviceFeature.ClimatePreset);
|
|
6426
6448
|
}
|
|
6427
6449
|
return {
|
|
6428
|
-
deviceType:
|
|
6450
|
+
deviceType: require_ha_instance_settings.DeviceType.Thermostat,
|
|
6429
6451
|
role: null,
|
|
6430
6452
|
capabilities: ["climate-control"],
|
|
6431
6453
|
features
|
|
@@ -6435,19 +6457,21 @@ function mapMediaPlayer(attributes) {
|
|
|
6435
6457
|
const features = [];
|
|
6436
6458
|
const sf = readNumericAttr(attributes, "supported_features");
|
|
6437
6459
|
if (sf !== null) {
|
|
6438
|
-
if ((sf & 2) !== 0) features.push(
|
|
6439
|
-
if ((sf & 4) !== 0) features.push(
|
|
6440
|
-
if ((sf & 8) !== 0) features.push(
|
|
6441
|
-
if ((sf & 16) !== 0) features.push(
|
|
6442
|
-
if ((sf & 32) !== 0) features.push(
|
|
6443
|
-
if ((sf &
|
|
6444
|
-
if ((sf &
|
|
6445
|
-
if ((sf &
|
|
6446
|
-
if ((sf &
|
|
6447
|
-
if ((sf &
|
|
6460
|
+
if ((sf & 2) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerSeek);
|
|
6461
|
+
if ((sf & 4) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerVolume);
|
|
6462
|
+
if ((sf & 8) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerMute);
|
|
6463
|
+
if ((sf & 16) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerPrevious);
|
|
6464
|
+
if ((sf & 32) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerNext);
|
|
6465
|
+
if ((sf & 384) === 384) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerPower);
|
|
6466
|
+
if ((sf & 1024) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerVolumeStep);
|
|
6467
|
+
if ((sf & 512) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerPlayMedia);
|
|
6468
|
+
if ((sf & 2048) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerSelectSource);
|
|
6469
|
+
if ((sf & 4096) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerStop);
|
|
6470
|
+
if ((sf & 32768) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerShuffle);
|
|
6471
|
+
if ((sf & 262144) !== 0) features.push(require_ha_instance_settings.DeviceFeature.MediaPlayerRepeat);
|
|
6448
6472
|
}
|
|
6449
6473
|
return {
|
|
6450
|
-
deviceType:
|
|
6474
|
+
deviceType: require_ha_instance_settings.DeviceType.MediaPlayer,
|
|
6451
6475
|
role: null,
|
|
6452
6476
|
capabilities: ["media-player"],
|
|
6453
6477
|
features
|
|
@@ -6455,9 +6479,9 @@ function mapMediaPlayer(attributes) {
|
|
|
6455
6479
|
}
|
|
6456
6480
|
function mapAlarmPanel(attributes) {
|
|
6457
6481
|
const features = [];
|
|
6458
|
-
if (attributes["code_format"] !== void 0 && attributes["code_format"] !== null) features.push(
|
|
6482
|
+
if (attributes["code_format"] !== void 0 && attributes["code_format"] !== null) features.push(require_ha_instance_settings.DeviceFeature.AlarmPinRequired);
|
|
6459
6483
|
return {
|
|
6460
|
-
deviceType:
|
|
6484
|
+
deviceType: require_ha_instance_settings.DeviceType.AlarmPanel,
|
|
6461
6485
|
role: null,
|
|
6462
6486
|
capabilities: ["alarm-panel"],
|
|
6463
6487
|
features
|
|
@@ -6465,21 +6489,21 @@ function mapAlarmPanel(attributes) {
|
|
|
6465
6489
|
}
|
|
6466
6490
|
function mapNotifier(_attributes) {
|
|
6467
6491
|
return {
|
|
6468
|
-
deviceType:
|
|
6469
|
-
role:
|
|
6492
|
+
deviceType: require_ha_instance_settings.DeviceType.Notifier,
|
|
6493
|
+
role: require_ha_instance_settings.DeviceRole.GenericNotifier,
|
|
6470
6494
|
capabilities: ["notifier"]
|
|
6471
6495
|
};
|
|
6472
6496
|
}
|
|
6473
6497
|
function mapWeather(_attributes) {
|
|
6474
6498
|
return {
|
|
6475
|
-
deviceType:
|
|
6499
|
+
deviceType: require_ha_instance_settings.DeviceType.Weather,
|
|
6476
6500
|
role: null,
|
|
6477
6501
|
capabilities: ["weather"]
|
|
6478
6502
|
};
|
|
6479
6503
|
}
|
|
6480
6504
|
function mapImage(_attributes) {
|
|
6481
6505
|
return {
|
|
6482
|
-
deviceType:
|
|
6506
|
+
deviceType: require_ha_instance_settings.DeviceType.Image,
|
|
6483
6507
|
role: null,
|
|
6484
6508
|
capabilities: ["image"]
|
|
6485
6509
|
};
|
|
@@ -6493,60 +6517,60 @@ function isTemperatureUnit(unit) {
|
|
|
6493
6517
|
function mapNumericSensor(deviceClass, _attributes) {
|
|
6494
6518
|
switch (deviceClass) {
|
|
6495
6519
|
case "temperature": return {
|
|
6496
|
-
deviceType:
|
|
6497
|
-
role:
|
|
6520
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6521
|
+
role: require_ha_instance_settings.DeviceRole.TemperatureSensor,
|
|
6498
6522
|
capabilities: ["temperature-sensor"]
|
|
6499
6523
|
};
|
|
6500
6524
|
case "humidity": return {
|
|
6501
|
-
deviceType:
|
|
6502
|
-
role:
|
|
6525
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6526
|
+
role: require_ha_instance_settings.DeviceRole.HumiditySensor,
|
|
6503
6527
|
capabilities: ["humidity-sensor"]
|
|
6504
6528
|
};
|
|
6505
6529
|
case "illuminance": return {
|
|
6506
|
-
deviceType:
|
|
6507
|
-
role:
|
|
6530
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6531
|
+
role: require_ha_instance_settings.DeviceRole.AmbientLightSensor,
|
|
6508
6532
|
capabilities: ["ambient-light-sensor"]
|
|
6509
6533
|
};
|
|
6510
6534
|
case "pressure":
|
|
6511
6535
|
case "atmospheric_pressure": return {
|
|
6512
|
-
deviceType:
|
|
6513
|
-
role:
|
|
6536
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6537
|
+
role: require_ha_instance_settings.DeviceRole.PressureSensor,
|
|
6514
6538
|
capabilities: ["pressure-sensor"]
|
|
6515
6539
|
};
|
|
6516
6540
|
case "wind_speed": return {
|
|
6517
|
-
deviceType:
|
|
6518
|
-
role:
|
|
6541
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6542
|
+
role: require_ha_instance_settings.DeviceRole.WindSensor,
|
|
6519
6543
|
capabilities: ["numeric-sensor"]
|
|
6520
6544
|
};
|
|
6521
6545
|
case "precipitation":
|
|
6522
6546
|
case "precipitation_intensity": return {
|
|
6523
|
-
deviceType:
|
|
6524
|
-
role:
|
|
6547
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6548
|
+
role: require_ha_instance_settings.DeviceRole.RainSensor,
|
|
6525
6549
|
capabilities: ["numeric-sensor"]
|
|
6526
6550
|
};
|
|
6527
6551
|
case "irradiance": return {
|
|
6528
|
-
deviceType:
|
|
6529
|
-
role:
|
|
6552
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6553
|
+
role: require_ha_instance_settings.DeviceRole.SolarRadiationSensor,
|
|
6530
6554
|
capabilities: ["numeric-sensor"]
|
|
6531
6555
|
};
|
|
6532
6556
|
case "power": return {
|
|
6533
|
-
deviceType:
|
|
6534
|
-
role:
|
|
6557
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6558
|
+
role: require_ha_instance_settings.DeviceRole.PowerSensor,
|
|
6535
6559
|
capabilities: ["power-meter"]
|
|
6536
6560
|
};
|
|
6537
6561
|
case "energy": return {
|
|
6538
|
-
deviceType:
|
|
6539
|
-
role:
|
|
6562
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6563
|
+
role: require_ha_instance_settings.DeviceRole.EnergySensor,
|
|
6540
6564
|
capabilities: ["power-meter"]
|
|
6541
6565
|
};
|
|
6542
6566
|
case "voltage": return {
|
|
6543
|
-
deviceType:
|
|
6544
|
-
role:
|
|
6567
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6568
|
+
role: require_ha_instance_settings.DeviceRole.VoltageSensor,
|
|
6545
6569
|
capabilities: ["power-meter"]
|
|
6546
6570
|
};
|
|
6547
6571
|
case "current": return {
|
|
6548
|
-
deviceType:
|
|
6549
|
-
role:
|
|
6572
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6573
|
+
role: require_ha_instance_settings.DeviceRole.CurrentSensor,
|
|
6550
6574
|
capabilities: ["power-meter"]
|
|
6551
6575
|
};
|
|
6552
6576
|
case "pm1":
|
|
@@ -6559,46 +6583,46 @@ function mapNumericSensor(deviceClass, _attributes) {
|
|
|
6559
6583
|
case "sulphur_dioxide":
|
|
6560
6584
|
case "volatile_organic_compounds":
|
|
6561
6585
|
case "aqi": return {
|
|
6562
|
-
deviceType:
|
|
6563
|
-
role:
|
|
6586
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6587
|
+
role: require_ha_instance_settings.DeviceRole.AirQualitySensor,
|
|
6564
6588
|
capabilities: ["air-quality-sensor"]
|
|
6565
6589
|
};
|
|
6566
6590
|
case "battery": return {
|
|
6567
|
-
deviceType:
|
|
6568
|
-
role:
|
|
6591
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6592
|
+
role: require_ha_instance_settings.DeviceRole.BatterySensor,
|
|
6569
6593
|
capabilities: ["numeric-sensor"]
|
|
6570
6594
|
};
|
|
6571
6595
|
case "enum": return {
|
|
6572
|
-
deviceType:
|
|
6573
|
-
role:
|
|
6596
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6597
|
+
role: require_ha_instance_settings.DeviceRole.EnumSensor,
|
|
6574
6598
|
capabilities: ["enum-sensor"]
|
|
6575
6599
|
};
|
|
6576
6600
|
case "timestamp": return {
|
|
6577
|
-
deviceType:
|
|
6578
|
-
role:
|
|
6601
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6602
|
+
role: require_ha_instance_settings.DeviceRole.DateTimeSensor,
|
|
6579
6603
|
capabilities: ["enum-sensor"],
|
|
6580
6604
|
dateTimeFormat: "datetime"
|
|
6581
6605
|
};
|
|
6582
6606
|
case "date": return {
|
|
6583
|
-
deviceType:
|
|
6584
|
-
role:
|
|
6607
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6608
|
+
role: require_ha_instance_settings.DeviceRole.DateTimeSensor,
|
|
6585
6609
|
capabilities: ["enum-sensor"],
|
|
6586
6610
|
dateTimeFormat: "date"
|
|
6587
6611
|
};
|
|
6588
6612
|
case null:
|
|
6589
6613
|
if (isTemperatureUnit(_attributes["unit_of_measurement"])) return {
|
|
6590
|
-
deviceType:
|
|
6591
|
-
role:
|
|
6614
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6615
|
+
role: require_ha_instance_settings.DeviceRole.TemperatureSensor,
|
|
6592
6616
|
capabilities: ["temperature-sensor"]
|
|
6593
6617
|
};
|
|
6594
6618
|
return {
|
|
6595
|
-
deviceType:
|
|
6596
|
-
role:
|
|
6619
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6620
|
+
role: require_ha_instance_settings.DeviceRole.EnumSensor,
|
|
6597
6621
|
capabilities: ["enum-sensor"]
|
|
6598
6622
|
};
|
|
6599
6623
|
default: return {
|
|
6600
|
-
deviceType:
|
|
6601
|
-
role:
|
|
6624
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6625
|
+
role: require_ha_instance_settings.DeviceRole.NumericSensor,
|
|
6602
6626
|
capabilities: ["numeric-sensor"]
|
|
6603
6627
|
};
|
|
6604
6628
|
}
|
|
@@ -6609,67 +6633,67 @@ function mapBinarySensor(deviceClass) {
|
|
|
6609
6633
|
case "occupancy":
|
|
6610
6634
|
case "presence":
|
|
6611
6635
|
case "moving": return {
|
|
6612
|
-
deviceType:
|
|
6613
|
-
role:
|
|
6636
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6637
|
+
role: require_ha_instance_settings.DeviceRole.MotionSensor,
|
|
6614
6638
|
capabilities: ["motion"]
|
|
6615
6639
|
};
|
|
6616
6640
|
case "door":
|
|
6617
6641
|
case "window":
|
|
6618
6642
|
case "garage_door":
|
|
6619
6643
|
case "opening": return {
|
|
6620
|
-
deviceType:
|
|
6621
|
-
role:
|
|
6644
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6645
|
+
role: require_ha_instance_settings.DeviceRole.ContactSensor,
|
|
6622
6646
|
capabilities: ["contact"]
|
|
6623
6647
|
};
|
|
6624
6648
|
case "moisture": return {
|
|
6625
|
-
deviceType:
|
|
6626
|
-
role:
|
|
6649
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6650
|
+
role: require_ha_instance_settings.DeviceRole.LeakSensor,
|
|
6627
6651
|
capabilities: ["flood"]
|
|
6628
6652
|
};
|
|
6629
6653
|
case "smoke": return {
|
|
6630
|
-
deviceType:
|
|
6631
|
-
role:
|
|
6654
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6655
|
+
role: require_ha_instance_settings.DeviceRole.SmokeSensor,
|
|
6632
6656
|
capabilities: ["smoke"]
|
|
6633
6657
|
};
|
|
6634
6658
|
case "carbon_monoxide": return {
|
|
6635
|
-
deviceType:
|
|
6636
|
-
role:
|
|
6659
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6660
|
+
role: require_ha_instance_settings.DeviceRole.COSensor,
|
|
6637
6661
|
capabilities: ["carbon-monoxide"]
|
|
6638
6662
|
};
|
|
6639
6663
|
case "gas": return {
|
|
6640
|
-
deviceType:
|
|
6641
|
-
role:
|
|
6664
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6665
|
+
role: require_ha_instance_settings.DeviceRole.GasSensor,
|
|
6642
6666
|
capabilities: ["gas"]
|
|
6643
6667
|
};
|
|
6644
6668
|
case "tamper":
|
|
6645
6669
|
case "safety": return {
|
|
6646
|
-
deviceType:
|
|
6647
|
-
role:
|
|
6670
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6671
|
+
role: require_ha_instance_settings.DeviceRole.TamperSensor,
|
|
6648
6672
|
capabilities: ["tamper"]
|
|
6649
6673
|
};
|
|
6650
6674
|
case "vibration": return {
|
|
6651
|
-
deviceType:
|
|
6652
|
-
role:
|
|
6675
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6676
|
+
role: require_ha_instance_settings.DeviceRole.VibrationSensor,
|
|
6653
6677
|
capabilities: ["vibration"]
|
|
6654
6678
|
};
|
|
6655
6679
|
case "connectivity": return {
|
|
6656
|
-
deviceType:
|
|
6657
|
-
role:
|
|
6680
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6681
|
+
role: require_ha_instance_settings.DeviceRole.ConnectivitySensor,
|
|
6658
6682
|
capabilities: ["connectivity"]
|
|
6659
6683
|
};
|
|
6660
6684
|
case "sound": return {
|
|
6661
|
-
deviceType:
|
|
6662
|
-
role:
|
|
6685
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6686
|
+
role: require_ha_instance_settings.DeviceRole.SoundSensor,
|
|
6663
6687
|
capabilities: ["binary"]
|
|
6664
6688
|
};
|
|
6665
6689
|
case "battery": return {
|
|
6666
|
-
deviceType:
|
|
6667
|
-
role:
|
|
6690
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6691
|
+
role: require_ha_instance_settings.DeviceRole.BatterySensor,
|
|
6668
6692
|
capabilities: ["binary"]
|
|
6669
6693
|
};
|
|
6670
6694
|
default: return {
|
|
6671
|
-
deviceType:
|
|
6672
|
-
role:
|
|
6695
|
+
deviceType: require_ha_instance_settings.DeviceType.Sensor,
|
|
6696
|
+
role: require_ha_instance_settings.DeviceRole.BinarySensor,
|
|
6673
6697
|
capabilities: ["binary"]
|
|
6674
6698
|
};
|
|
6675
6699
|
}
|
|
@@ -6692,40 +6716,40 @@ function readNumericAttr(attributes, key) {
|
|
|
6692
6716
|
* Sensor; an HA-tracked light with motion sensor becomes Light).
|
|
6693
6717
|
*/
|
|
6694
6718
|
var PARENT_TYPE_PRIORITY = [
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6719
|
+
require_ha_instance_settings.DeviceType.MediaPlayer,
|
|
6720
|
+
require_ha_instance_settings.DeviceType.AlarmPanel,
|
|
6721
|
+
require_ha_instance_settings.DeviceType.Thermostat,
|
|
6722
|
+
require_ha_instance_settings.DeviceType.Climate,
|
|
6723
|
+
require_ha_instance_settings.DeviceType.Humidifier,
|
|
6724
|
+
require_ha_instance_settings.DeviceType.WaterHeater,
|
|
6725
|
+
require_ha_instance_settings.DeviceType.Lock,
|
|
6726
|
+
require_ha_instance_settings.DeviceType.Cover,
|
|
6727
|
+
require_ha_instance_settings.DeviceType.Valve,
|
|
6728
|
+
require_ha_instance_settings.DeviceType.Fan,
|
|
6729
|
+
require_ha_instance_settings.DeviceType.Vacuum,
|
|
6730
|
+
require_ha_instance_settings.DeviceType.LawnMower,
|
|
6731
|
+
require_ha_instance_settings.DeviceType.Washer,
|
|
6732
|
+
require_ha_instance_settings.DeviceType.Dryer,
|
|
6733
|
+
require_ha_instance_settings.DeviceType.Dishwasher,
|
|
6734
|
+
require_ha_instance_settings.DeviceType.Light,
|
|
6735
|
+
require_ha_instance_settings.DeviceType.Switch,
|
|
6736
|
+
require_ha_instance_settings.DeviceType.Siren,
|
|
6737
|
+
require_ha_instance_settings.DeviceType.Button,
|
|
6738
|
+
require_ha_instance_settings.DeviceType.Control,
|
|
6739
|
+
require_ha_instance_settings.DeviceType.Notifier,
|
|
6740
|
+
require_ha_instance_settings.DeviceType.Script,
|
|
6741
|
+
require_ha_instance_settings.DeviceType.Automation,
|
|
6742
|
+
require_ha_instance_settings.DeviceType.Update,
|
|
6743
|
+
require_ha_instance_settings.DeviceType.Presence,
|
|
6744
|
+
require_ha_instance_settings.DeviceType.Weather,
|
|
6745
|
+
require_ha_instance_settings.DeviceType.Image,
|
|
6746
|
+
require_ha_instance_settings.DeviceType.Sensor
|
|
6723
6747
|
];
|
|
6724
6748
|
function inferParentDeviceType(mappings) {
|
|
6725
6749
|
const set = /* @__PURE__ */ new Set();
|
|
6726
6750
|
for (const m of mappings) if (m) set.add(m.deviceType);
|
|
6727
6751
|
for (const dt of PARENT_TYPE_PRIORITY) if (set.has(dt)) return dt;
|
|
6728
|
-
return
|
|
6752
|
+
return require_ha_instance_settings.DeviceType.Generic;
|
|
6729
6753
|
}
|
|
6730
6754
|
//#endregion
|
|
6731
6755
|
//#region src/ha-candidate-mapper.ts
|
|
@@ -6747,7 +6771,7 @@ function haDeviceToCandidate(dev) {
|
|
|
6747
6771
|
return {
|
|
6748
6772
|
childNativeId: e.entityId,
|
|
6749
6773
|
name: e.name,
|
|
6750
|
-
type: e.mappedTo?.deviceType ??
|
|
6774
|
+
type: e.mappedTo?.deviceType ?? require_ha_instance_settings.DeviceType.Generic,
|
|
6751
6775
|
status: entityStatus$1(e.state),
|
|
6752
6776
|
metadata: e.area !== null ? { externalLocation: e.area } : {},
|
|
6753
6777
|
alreadyAdopted: e.alreadyAdopted,
|
|
@@ -6894,7 +6918,7 @@ function buildDiscoveryCandidates(input) {
|
|
|
6894
6918
|
};
|
|
6895
6919
|
candidates.push({
|
|
6896
6920
|
stableId,
|
|
6897
|
-
type:
|
|
6921
|
+
type: require_ha_instance_settings.DeviceType.Container,
|
|
6898
6922
|
suggestedName,
|
|
6899
6923
|
prefilledConfig,
|
|
6900
6924
|
sourceInfo
|
|
@@ -6922,52 +6946,52 @@ function buildDiscoveryCandidates(input) {
|
|
|
6922
6946
|
* shown as a Devices-tab candidate.
|
|
6923
6947
|
*/
|
|
6924
6948
|
var HA_ORPHAN_ENTITIES_DEVICE_ID = "__ha_orphan_entities__";
|
|
6925
|
-
var HaEntityMappingSchema =
|
|
6949
|
+
var HaEntityMappingSchema = require_ha_instance_settings.object({
|
|
6926
6950
|
/** CamStack DeviceType for the accessory child. */
|
|
6927
|
-
deviceType:
|
|
6951
|
+
deviceType: require_ha_instance_settings._enum(require_ha_instance_settings.DeviceType),
|
|
6928
6952
|
/** Optional CamStack DeviceRole sub-role (e.g. `ContactSensor` for
|
|
6929
6953
|
* a binary_sensor with `device_class: door`). */
|
|
6930
|
-
role:
|
|
6954
|
+
role: require_ha_instance_settings._enum(require_ha_instance_settings.DeviceRole).nullable(),
|
|
6931
6955
|
/** Capability names the accessory child will register
|
|
6932
6956
|
* (`switch` / `temperature-sensor` / …). UI may render the cap
|
|
6933
6957
|
* badges to help the operator decide what to hide. */
|
|
6934
|
-
capabilities:
|
|
6958
|
+
capabilities: require_ha_instance_settings.array(require_ha_instance_settings.string()).readonly(),
|
|
6935
6959
|
/** Mapping-derived DeviceFeature flags (e.g. `lock-open`). Persisted onto
|
|
6936
6960
|
* the child's `device.features` so the UI gates feature affordances. */
|
|
6937
|
-
features:
|
|
6961
|
+
features: require_ha_instance_settings.array(require_ha_instance_settings.string()).readonly().optional(),
|
|
6938
6962
|
/** Locale-render shape for a `DateTimeSensor`-role enum sensor
|
|
6939
6963
|
* (`device_class=timestamp` → `'datetime'`, `date` → `'date'`). Threaded
|
|
6940
6964
|
* onto the child config so the enum-sensor device seeds it into the cap
|
|
6941
6965
|
* slice. Absent for every non-DateTimeSensor mapping. */
|
|
6942
|
-
dateTimeFormat:
|
|
6966
|
+
dateTimeFormat: require_ha_instance_settings.EnumSensorDateTimeFormatSchema.optional()
|
|
6943
6967
|
}).nullable();
|
|
6944
|
-
var HaDiscoveredEntitySchema =
|
|
6968
|
+
var HaDiscoveredEntitySchema = require_ha_instance_settings.object({
|
|
6945
6969
|
/** Fully-qualified HA entity id (`switch.kitchen`). */
|
|
6946
|
-
entityId:
|
|
6970
|
+
entityId: require_ha_instance_settings.string(),
|
|
6947
6971
|
/** HA domain — first segment of entity_id (`switch` / `light` /
|
|
6948
6972
|
* `sensor` / `binary_sensor` / `cover` / …). */
|
|
6949
|
-
domain:
|
|
6973
|
+
domain: require_ha_instance_settings.string(),
|
|
6950
6974
|
/** Operator-visible friendly name (HA `friendly_name` attribute or
|
|
6951
6975
|
* the entity_id when missing). */
|
|
6952
|
-
name:
|
|
6976
|
+
name: require_ha_instance_settings.string(),
|
|
6953
6977
|
/** Current state value (e.g. `'on'`, `'21.5'`, `'open'`). */
|
|
6954
|
-
state:
|
|
6978
|
+
state: require_ha_instance_settings.string(),
|
|
6955
6979
|
/** HA `device_class` attribute when present — drives the role +
|
|
6956
6980
|
* cap mapping for sensors / binary_sensors / covers. */
|
|
6957
|
-
deviceClass:
|
|
6981
|
+
deviceClass: require_ha_instance_settings.string().nullable(),
|
|
6958
6982
|
/** HA `unit_of_measurement` attribute when present. */
|
|
6959
|
-
unitOfMeasurement:
|
|
6983
|
+
unitOfMeasurement: require_ha_instance_settings.string().nullable(),
|
|
6960
6984
|
/** Area name for this entity — the entity's own HA area if set, else its
|
|
6961
6985
|
* parent device's area. Null when neither is assigned. */
|
|
6962
|
-
area:
|
|
6986
|
+
area: require_ha_instance_settings.string().nullable().default(null),
|
|
6963
6987
|
/** HA `options` attribute — present on `select` / `input_select` entities.
|
|
6964
6988
|
* Captured at discovery so the adopt handler can persist them alongside
|
|
6965
6989
|
* other entity config fields. Absent on non-select entities. */
|
|
6966
|
-
options:
|
|
6990
|
+
options: require_ha_instance_settings.array(require_ha_instance_settings.string()).nullable().default(null),
|
|
6967
6991
|
/** HA `entity_category` — `config` / `diagnostic` / null (a normal control).
|
|
6968
6992
|
* Drives the accordion section the adopted child renders in. Null/absent for
|
|
6969
6993
|
* the common control case. */
|
|
6970
|
-
entityCategory:
|
|
6994
|
+
entityCategory: require_ha_instance_settings._enum(["config", "diagnostic"]).nullable().default(null),
|
|
6971
6995
|
/** Pre-computed CamStack mapping. `null` when the entity's domain
|
|
6972
6996
|
* has no supported mapping (the operator may still adopt the
|
|
6973
6997
|
* parent — the entity will be skipped or surfaced as a fallback). */
|
|
@@ -6975,48 +6999,48 @@ var HaDiscoveredEntitySchema = require_ha_broker_source.object({
|
|
|
6975
6999
|
/** When `true`, the entity was already materialised as a CamStack
|
|
6976
7000
|
* accessory child under a prior adoption — surfaced so the UI can
|
|
6977
7001
|
* highlight existing wiring. */
|
|
6978
|
-
alreadyAdopted:
|
|
7002
|
+
alreadyAdopted: require_ha_instance_settings.boolean(),
|
|
6979
7003
|
/** When `alreadyAdopted === true`, the kernel-assigned accessory
|
|
6980
7004
|
* child id. */
|
|
6981
|
-
adoptedCamDeviceId:
|
|
7005
|
+
adoptedCamDeviceId: require_ha_instance_settings.number().int().nonnegative().nullable()
|
|
6982
7006
|
});
|
|
6983
|
-
|
|
7007
|
+
require_ha_instance_settings.object({
|
|
6984
7008
|
/** Stable HA `device_registry` id — survives renames + restarts. */
|
|
6985
|
-
haDeviceId:
|
|
7009
|
+
haDeviceId: require_ha_instance_settings.string(),
|
|
6986
7010
|
/** Operator-visible name (HA device `name` or first entity's
|
|
6987
7011
|
* friendly_name when device has none). */
|
|
6988
|
-
name:
|
|
7012
|
+
name: require_ha_instance_settings.string(),
|
|
6989
7013
|
/** Area name from HA `area_registry` join. Null when unassigned. */
|
|
6990
|
-
area:
|
|
6991
|
-
manufacturer:
|
|
6992
|
-
model:
|
|
6993
|
-
swVersion:
|
|
7014
|
+
area: require_ha_instance_settings.string().nullable(),
|
|
7015
|
+
manufacturer: require_ha_instance_settings.string().nullable(),
|
|
7016
|
+
model: require_ha_instance_settings.string().nullable(),
|
|
7017
|
+
swVersion: require_ha_instance_settings.string().nullable(),
|
|
6994
7018
|
/** Dominant integration / platform domain for this device, derived from its
|
|
6995
7019
|
* entities' HA `entity_registry.platform` (e.g. `dreame_vacuum`). Generic /
|
|
6996
7020
|
* helper platforms (`unifi` / `hacs` / `hassio`) are excluded when a real
|
|
6997
7021
|
* platform is available. Null when the device has no entities. */
|
|
6998
|
-
integration:
|
|
7022
|
+
integration: require_ha_instance_settings.string().nullable().default(null),
|
|
6999
7023
|
/** Convenience field — count of `entities[]`. */
|
|
7000
|
-
entityCount:
|
|
7024
|
+
entityCount: require_ha_instance_settings.number().int().nonnegative(),
|
|
7001
7025
|
/** Every entity HA's `entity_registry` links to this device. The
|
|
7002
7026
|
* list survives row collapse — full devices are returned so
|
|
7003
7027
|
* accordion expansion is a no-roundtrip render. */
|
|
7004
|
-
entities:
|
|
7028
|
+
entities: require_ha_instance_settings.array(HaDiscoveredEntitySchema).readonly(),
|
|
7005
7029
|
/** Whether this HA device has an active CamStack adoption. */
|
|
7006
|
-
alreadyAdopted:
|
|
7030
|
+
alreadyAdopted: require_ha_instance_settings.boolean(),
|
|
7007
7031
|
/** When `alreadyAdopted === true`, the kernel-assigned parent id. */
|
|
7008
|
-
adoptedCamDeviceId:
|
|
7032
|
+
adoptedCamDeviceId: require_ha_instance_settings.number().int().nonnegative().nullable()
|
|
7009
7033
|
});
|
|
7010
|
-
|
|
7034
|
+
require_ha_instance_settings.object({
|
|
7011
7035
|
/** Last refresh timestamp (ms epoch) — null when never refreshed. */
|
|
7012
|
-
lastDiscoveryAt:
|
|
7036
|
+
lastDiscoveryAt: require_ha_instance_settings.number().int().nonnegative().nullable(),
|
|
7013
7037
|
/** Count of HA devices in the discovery cache (across all brokers). */
|
|
7014
|
-
deviceCount:
|
|
7038
|
+
deviceCount: require_ha_instance_settings.number().int().nonnegative(),
|
|
7015
7039
|
/** Count of HA devices currently materialised as CamStack parent
|
|
7016
7040
|
* devices. */
|
|
7017
|
-
adoptedCount:
|
|
7041
|
+
adoptedCount: require_ha_instance_settings.number().int().nonnegative(),
|
|
7018
7042
|
/** Last error message from a refresh attempt. */
|
|
7019
|
-
lastError:
|
|
7043
|
+
lastError: require_ha_instance_settings.string().nullable()
|
|
7020
7044
|
});
|
|
7021
7045
|
//#endregion
|
|
7022
7046
|
//#region src/ha-integration-domain.ts
|
|
@@ -7155,7 +7179,7 @@ function negotiateEncoding(acceptEncoding) {
|
|
|
7155
7179
|
}
|
|
7156
7180
|
/** Build the `addon-routes` provider that serves the bundled Home Assistant icon. */
|
|
7157
7181
|
function createHaIconRouteProvider() {
|
|
7158
|
-
return
|
|
7182
|
+
return require_ha_instance_settings.buildAddonRouteProvider(HA_ROUTE_ID, [{
|
|
7159
7183
|
method: "GET",
|
|
7160
7184
|
path: `/icons/${HA_ICON_KIND}`,
|
|
7161
7185
|
access: "public",
|
|
@@ -7174,11 +7198,11 @@ function createHaIconRouteProvider() {
|
|
|
7174
7198
|
* Broker entry kind (B2): credentials live in records; integrations keep brokerId.
|
|
7175
7199
|
*/
|
|
7176
7200
|
var HA_BROKERS_KIND = "brokers";
|
|
7177
|
-
var HaBrokerBodySchema =
|
|
7201
|
+
var HaBrokerBodySchema = require_ha_instance_settings.entryBody({
|
|
7178
7202
|
auth: HaBrokerEntrySchema.shape.auth,
|
|
7179
|
-
integrationId:
|
|
7203
|
+
integrationId: require_ha_instance_settings.string().optional()
|
|
7180
7204
|
});
|
|
7181
|
-
var haBrokersEntryKind =
|
|
7205
|
+
var haBrokersEntryKind = require_ha_instance_settings.defineEntryKind(HA_BROKERS_KIND, {
|
|
7182
7206
|
title: "Home Assistant brokers",
|
|
7183
7207
|
schema: HaBrokerBodySchema,
|
|
7184
7208
|
writeTrigger: "an operator adds, edits or removes a Home Assistant broker connection"
|
|
@@ -7192,8 +7216,8 @@ var haBrokersEntryKind = require_ha_broker_source.defineEntryKind(HA_BROKERS_KIN
|
|
|
7192
7216
|
* credential — delivery reuses the broker WebSocket connection (the token
|
|
7193
7217
|
* lives in the broker config, not in the target).
|
|
7194
7218
|
*/
|
|
7195
|
-
var HaTargetBodySchema =
|
|
7196
|
-
var haRecordKinds =
|
|
7219
|
+
var HaTargetBodySchema = require_ha_instance_settings.TargetSchema.omit({ id: true });
|
|
7220
|
+
var haRecordKinds = require_ha_instance_settings.defineRecordKinds({
|
|
7197
7221
|
/**
|
|
7198
7222
|
* One row per configured Home Assistant push target. Operator-managed via the
|
|
7199
7223
|
* notification-output cap CRUD; no TTL.
|
|
@@ -7259,7 +7283,7 @@ function haConfigSchema() {
|
|
|
7259
7283
|
labelKey: "provider-homeassistant:haConfig.s_connection.brokerId.label",
|
|
7260
7284
|
description: "The Home Assistant connection the notification goes through.",
|
|
7261
7285
|
descriptionKey: "provider-homeassistant:haConfig.s_connection.brokerId.description",
|
|
7262
|
-
brokerKind:
|
|
7286
|
+
brokerKind: require_ha_instance_settings.HA_BROKER_KIND
|
|
7263
7287
|
}, {
|
|
7264
7288
|
type: "select",
|
|
7265
7289
|
key: "service",
|
|
@@ -7499,7 +7523,7 @@ var HaTargetStore = class HaTargetStore {
|
|
|
7499
7523
|
const page = await this.kind.query({ limit: 1e3 });
|
|
7500
7524
|
const out = [];
|
|
7501
7525
|
for (const record of page.records) {
|
|
7502
|
-
const parsed =
|
|
7526
|
+
const parsed = require_ha_instance_settings.TargetSchema.safeParse({
|
|
7503
7527
|
id: record.id,
|
|
7504
7528
|
...record.data
|
|
7505
7529
|
});
|
|
@@ -7510,7 +7534,7 @@ var HaTargetStore = class HaTargetStore {
|
|
|
7510
7534
|
async getById(id) {
|
|
7511
7535
|
const row = await this.kind.get(id);
|
|
7512
7536
|
if (row === null) return null;
|
|
7513
|
-
const parsed =
|
|
7537
|
+
const parsed = require_ha_instance_settings.TargetSchema.safeParse({
|
|
7514
7538
|
id: row.id,
|
|
7515
7539
|
...row.data
|
|
7516
7540
|
});
|
|
@@ -7571,12 +7595,12 @@ function createHaNotificationOutputProvider(deps) {
|
|
|
7571
7595
|
}
|
|
7572
7596
|
/** Degrade → build → publish. NEVER throws through the cap. */
|
|
7573
7597
|
async function dispatch(target, raw) {
|
|
7574
|
-
const notification = deps.readPublicEndpoint === void 0 ? raw : await
|
|
7598
|
+
const notification = deps.readPublicEndpoint === void 0 ? raw : await require_ha_instance_settings.resolveAttachmentUrls({
|
|
7575
7599
|
notification: raw,
|
|
7576
7600
|
readPublicEndpoint: deps.readPublicEndpoint,
|
|
7577
7601
|
...logger !== void 0 ? { logger } : {}
|
|
7578
7602
|
});
|
|
7579
|
-
const prepared =
|
|
7603
|
+
const prepared = require_ha_instance_settings.prepareNotification(descriptor.caps, notification);
|
|
7580
7604
|
const service = readService(target.config);
|
|
7581
7605
|
if (!service) return {
|
|
7582
7606
|
success: false,
|
|
@@ -7600,11 +7624,11 @@ function createHaNotificationOutputProvider(deps) {
|
|
|
7600
7624
|
logger?.warn("ha notify publish failed", { meta: {
|
|
7601
7625
|
brokerId,
|
|
7602
7626
|
service,
|
|
7603
|
-
error:
|
|
7627
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
7604
7628
|
} });
|
|
7605
7629
|
return {
|
|
7606
7630
|
success: false,
|
|
7607
|
-
error:
|
|
7631
|
+
error: require_ha_instance_settings.errMsg(err),
|
|
7608
7632
|
renderedAs: prepared.renderedAs
|
|
7609
7633
|
};
|
|
7610
7634
|
}
|
|
@@ -7643,7 +7667,7 @@ function createHaNotificationOutputProvider(deps) {
|
|
|
7643
7667
|
} catch (err) {
|
|
7644
7668
|
logger?.warn("ha device registry read failed; naming services from their ids", { meta: {
|
|
7645
7669
|
brokerId,
|
|
7646
|
-
error:
|
|
7670
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
7647
7671
|
} });
|
|
7648
7672
|
return /* @__PURE__ */ new Map();
|
|
7649
7673
|
}
|
|
@@ -7657,7 +7681,7 @@ function createHaNotificationOutputProvider(deps) {
|
|
|
7657
7681
|
} catch (err) {
|
|
7658
7682
|
logger?.warn("ha get_services discovery failed", { meta: {
|
|
7659
7683
|
brokerId,
|
|
7660
|
-
error:
|
|
7684
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
7661
7685
|
} });
|
|
7662
7686
|
}
|
|
7663
7687
|
return out;
|
|
@@ -7735,7 +7759,7 @@ var HaBrokerStore = class HaBrokerStore {
|
|
|
7735
7759
|
const resolved = await this.kind.getResolved(record.id);
|
|
7736
7760
|
if (resolved !== null) data = resolved.data;
|
|
7737
7761
|
} catch (err) {
|
|
7738
|
-
if (!(err instanceof
|
|
7762
|
+
if (!(err instanceof require_ha_instance_settings.RecordSecretUnavailableError)) throw err;
|
|
7739
7763
|
}
|
|
7740
7764
|
const entry = rowToEntry(record.id, data);
|
|
7741
7765
|
if (entry !== null) out.push(entry);
|
|
@@ -7748,7 +7772,7 @@ var HaBrokerStore = class HaBrokerStore {
|
|
|
7748
7772
|
if (row === null) return null;
|
|
7749
7773
|
return rowToEntry(row.id, row.data);
|
|
7750
7774
|
} catch (err) {
|
|
7751
|
-
if (err instanceof
|
|
7775
|
+
if (err instanceof require_ha_instance_settings.RecordSecretUnavailableError) return null;
|
|
7752
7776
|
throw err;
|
|
7753
7777
|
}
|
|
7754
7778
|
}
|
|
@@ -7799,19 +7823,19 @@ var HaBrokerStore = class HaBrokerStore {
|
|
|
7799
7823
|
*/
|
|
7800
7824
|
var INGRESS_PREFIX = "/api/hassio_ingress/";
|
|
7801
7825
|
var ESPHOME_SERVICE = "esphome";
|
|
7802
|
-
var DiscoverySchema =
|
|
7803
|
-
addon:
|
|
7804
|
-
service:
|
|
7826
|
+
var DiscoverySchema = require_ha_instance_settings.object({ discovery: require_ha_instance_settings.array(require_ha_instance_settings.object({
|
|
7827
|
+
addon: require_ha_instance_settings.string(),
|
|
7828
|
+
service: require_ha_instance_settings.string()
|
|
7805
7829
|
})) });
|
|
7806
|
-
var AddonInfoSchema =
|
|
7807
|
-
var SessionSchema =
|
|
7808
|
-
var DevicesSchema =
|
|
7809
|
-
name:
|
|
7810
|
-
configuration:
|
|
7811
|
-
address:
|
|
7830
|
+
var AddonInfoSchema = require_ha_instance_settings.object({ ingress_url: require_ha_instance_settings.string().nullable().optional() });
|
|
7831
|
+
var SessionSchema = require_ha_instance_settings.object({ session: require_ha_instance_settings.string().min(1) });
|
|
7832
|
+
var DevicesSchema = require_ha_instance_settings.object({ configured: require_ha_instance_settings.array(require_ha_instance_settings.object({
|
|
7833
|
+
name: require_ha_instance_settings.string(),
|
|
7834
|
+
configuration: require_ha_instance_settings.string(),
|
|
7835
|
+
address: require_ha_instance_settings.string().nullable().optional()
|
|
7812
7836
|
})) });
|
|
7813
7837
|
/** The ONLY part of `json-config` that is read; every other field is dropped by the parse. */
|
|
7814
|
-
var KeyConfigSchema =
|
|
7838
|
+
var KeyConfigSchema = require_ha_instance_settings.object({ api: require_ha_instance_settings.object({ encryption: require_ha_instance_settings.object({ key: require_ha_instance_settings.string().min(1) }).optional() }).optional() });
|
|
7815
7839
|
var ADMIN_CODES = new Set([
|
|
7816
7840
|
"unauthorized",
|
|
7817
7841
|
"forbidden",
|
|
@@ -7877,7 +7901,7 @@ var HaBoardKeySource = class {
|
|
|
7877
7901
|
}
|
|
7878
7902
|
}
|
|
7879
7903
|
fail(sourceId, op, err) {
|
|
7880
|
-
const failure = err instanceof SourceFailure ? err : new SourceFailure("unreachable",
|
|
7904
|
+
const failure = err instanceof SourceFailure ? err : new SourceFailure("unreachable", require_ha_instance_settings.errMsg(err));
|
|
7881
7905
|
this.deps.logger.warn(`board-key-source ${op} refused`, { meta: {
|
|
7882
7906
|
sourceId,
|
|
7883
7907
|
reason: failure.reason
|
|
@@ -7901,7 +7925,7 @@ var HaBoardKeySource = class {
|
|
|
7901
7925
|
} catch (err) {
|
|
7902
7926
|
const code = errorCode(err);
|
|
7903
7927
|
if (code !== null && ADMIN_CODES.has(code)) throw new SourceFailure("not-admin", "the Home Assistant token is not an administrator");
|
|
7904
|
-
throw new SourceFailure("unreachable",
|
|
7928
|
+
throw new SourceFailure("unreachable", require_ha_instance_settings.errMsg(err));
|
|
7905
7929
|
}
|
|
7906
7930
|
}
|
|
7907
7931
|
async openIngress(sourceId) {
|
|
@@ -7929,7 +7953,7 @@ var HaBoardKeySource = class {
|
|
|
7929
7953
|
Accept: "application/json"
|
|
7930
7954
|
} });
|
|
7931
7955
|
} catch (err) {
|
|
7932
|
-
throw new SourceFailure("unreachable",
|
|
7956
|
+
throw new SourceFailure("unreachable", require_ha_instance_settings.errMsg(err));
|
|
7933
7957
|
}
|
|
7934
7958
|
if (response.status === 404 && configuration !== void 0) throw new SourceFailure("unknown-board", configuration);
|
|
7935
7959
|
if (response.status === 401 || response.status === 403) throw new SourceFailure("not-admin", `the builder answered ${response.status}`);
|
|
@@ -7950,6 +7974,127 @@ function createHaBoardKeyProvider(source) {
|
|
|
7950
7974
|
};
|
|
7951
7975
|
}
|
|
7952
7976
|
//#endregion
|
|
7977
|
+
//#region src/migrations/calendar-ids-to-integration.ts
|
|
7978
|
+
/**
|
|
7979
|
+
* The HA calendars an instance imports are a fact of THAT instance (D985): each Home Assistant
|
|
7980
|
+
* integration carries its own `calendarIds` in its settings, and the addon-level `calendarIds`
|
|
7981
|
+
* setting (one set of `calendar.*` entity ids for every broker) goes away.
|
|
7982
|
+
*
|
|
7983
|
+
* Two migrations, in this order:
|
|
7984
|
+
*
|
|
7985
|
+
* 1. `calendar-ids-to-integration` (procedure) copies the shared set to EVERY integration that
|
|
7986
|
+
* has no `calendarIds` yet. An integration that already has one is never overwritten; one
|
|
7987
|
+
* deleted meanwhile is skipped, never recreated; a stored value that is not a list of strings
|
|
7988
|
+
* is an ambiguity and throws (nothing is guessed).
|
|
7989
|
+
* 2. `drop-shared-calendar-ids` (plan) deletes the shared setting after a read-back: every
|
|
7990
|
+
* integration must show its own set. When one holds a set that differs from the shared one,
|
|
7991
|
+
* the shared value is the loser and stays PARKED in place, never deleted.
|
|
7992
|
+
*
|
|
7993
|
+
* Both are idempotent.
|
|
7994
|
+
*/
|
|
7995
|
+
var HA_PROVIDER_ID = "provider-homeassistant";
|
|
7996
|
+
/** The canonical settings table: one row per key, id `<addonId>.<key>`. */
|
|
7997
|
+
var ADDON_SETTINGS_TABLE = "addon-settings";
|
|
7998
|
+
var SHARED_CALENDAR_IDS_KEY = "calendarIds";
|
|
7999
|
+
async function readSharedSet(ports) {
|
|
8000
|
+
const answer = await ports.readStored(SHARED_CALENDAR_IDS_KEY);
|
|
8001
|
+
if (answer.kind === "unreadable") throw new Error(`provider-homeassistant: the shared calendarIds cannot be read (${answer.reason})`);
|
|
8002
|
+
if (answer.kind === "absent") return null;
|
|
8003
|
+
const value = answer.value;
|
|
8004
|
+
if (!Array.isArray(value) || !value.every((item) => typeof item === "string")) throw new Error("provider-homeassistant: the shared calendarIds is not a list of entity ids — nothing copied");
|
|
8005
|
+
return value;
|
|
8006
|
+
}
|
|
8007
|
+
async function copyCalendarIdsToIntegrations(ports) {
|
|
8008
|
+
const shared = await readSharedSet(ports);
|
|
8009
|
+
if (shared === null) return {
|
|
8010
|
+
outcome: "already-done",
|
|
8011
|
+
summary: { reason: "no-shared-set" }
|
|
8012
|
+
};
|
|
8013
|
+
let copied = 0;
|
|
8014
|
+
let kept = 0;
|
|
8015
|
+
let gone = 0;
|
|
8016
|
+
for (const instance of await ports.listInstances()) {
|
|
8017
|
+
if ("calendarIds" in instance.settings) {
|
|
8018
|
+
kept += 1;
|
|
8019
|
+
continue;
|
|
8020
|
+
}
|
|
8021
|
+
if (await ports.patchInstanceSettings(instance.integrationId, { calendarIds: [...shared] })) copied += 1;
|
|
8022
|
+
else gone += 1;
|
|
8023
|
+
}
|
|
8024
|
+
return {
|
|
8025
|
+
outcome: copied === 0 ? "already-done" : "done",
|
|
8026
|
+
summary: {
|
|
8027
|
+
copied,
|
|
8028
|
+
kept,
|
|
8029
|
+
gone
|
|
8030
|
+
}
|
|
8031
|
+
};
|
|
8032
|
+
}
|
|
8033
|
+
var asIds = (value) => Array.isArray(value) && value.every((item) => typeof item === "string") ? value : null;
|
|
8034
|
+
var sameSet = (a, b) => {
|
|
8035
|
+
const left = new Set(a);
|
|
8036
|
+
const right = new Set(b);
|
|
8037
|
+
return left.size === right.size && [...left].every((id) => right.has(id));
|
|
8038
|
+
};
|
|
8039
|
+
async function planDropSharedCalendarIds(ports) {
|
|
8040
|
+
const shared = await readSharedSet(ports);
|
|
8041
|
+
if (shared === null) return { edits: [] };
|
|
8042
|
+
const instances = await ports.listInstances();
|
|
8043
|
+
if (instances.length === 0) return { edits: [] };
|
|
8044
|
+
const own = instances.map((instance) => ({
|
|
8045
|
+
integrationId: instance.integrationId,
|
|
8046
|
+
ids: asIds(instance.settings[SHARED_CALENDAR_IDS_KEY])
|
|
8047
|
+
}));
|
|
8048
|
+
const missing = own.filter((entry) => entry.ids === null);
|
|
8049
|
+
if (missing.length > 0) throw new Error(`provider-homeassistant: the shared calendarIds is not dropped, ${missing.map((m) => m.integrationId).join(", ")} has no set of its own`);
|
|
8050
|
+
if (!own.every((entry) => sameSet(entry.ids ?? [], shared))) return { edits: [] };
|
|
8051
|
+
const rowId = `${HA_PROVIDER_ID}.${SHARED_CALENDAR_IDS_KEY}`;
|
|
8052
|
+
return { edits: [{
|
|
8053
|
+
op: "deleteKeys",
|
|
8054
|
+
scope: ADDON_SETTINGS_TABLE,
|
|
8055
|
+
keys: [rowId],
|
|
8056
|
+
precondition: require_ha_instance_settings.preconditionOf({ [rowId]: {
|
|
8057
|
+
addonId: HA_PROVIDER_ID,
|
|
8058
|
+
key: SHARED_CALENDAR_IDS_KEY,
|
|
8059
|
+
value: shared
|
|
8060
|
+
} })
|
|
8061
|
+
}] };
|
|
8062
|
+
}
|
|
8063
|
+
//#endregion
|
|
8064
|
+
//#region src/migrations/index.ts
|
|
8065
|
+
/** The `provider-homeassistant` catalogue (D987): offered to the engine when the addon initialises. */
|
|
8066
|
+
var ADDON_MIGRATIONS = [{
|
|
8067
|
+
meta: {
|
|
8068
|
+
id: "provider-homeassistant/2026-11-03-calendar-ids-to-integration",
|
|
8069
|
+
owner: "provider-homeassistant",
|
|
8070
|
+
level: "addon-state",
|
|
8071
|
+
seq: 1,
|
|
8072
|
+
dependsOn: [],
|
|
8073
|
+
store: "settings",
|
|
8074
|
+
scope: "cluster",
|
|
8075
|
+
onFailure: "tolerate",
|
|
8076
|
+
bodyKind: "procedure",
|
|
8077
|
+
description: "Copy the shared calendar set to the settings of every Home Assistant integration that has none",
|
|
8078
|
+
fixtureMark: "the broker link stored beside the calendars of an integration"
|
|
8079
|
+
},
|
|
8080
|
+
procedure: copyCalendarIdsToIntegrations
|
|
8081
|
+
}, {
|
|
8082
|
+
meta: {
|
|
8083
|
+
id: "provider-homeassistant/2026-11-03-drop-shared-calendar-ids",
|
|
8084
|
+
owner: "provider-homeassistant",
|
|
8085
|
+
level: "addon-state",
|
|
8086
|
+
seq: 2,
|
|
8087
|
+
dependsOn: ["provider-homeassistant/2026-11-03-calendar-ids-to-integration"],
|
|
8088
|
+
store: "settings",
|
|
8089
|
+
scope: "cluster",
|
|
8090
|
+
onFailure: "tolerate",
|
|
8091
|
+
bodyKind: "plan",
|
|
8092
|
+
description: "Delete the shared calendar set once every integration shows its own",
|
|
8093
|
+
fixtureMark: "the shared set parked when an integration holds a different one"
|
|
8094
|
+
},
|
|
8095
|
+
plan: planDropSharedCalendarIds
|
|
8096
|
+
}];
|
|
8097
|
+
//#endregion
|
|
7953
8098
|
//#region src/ha-calendar-source.ts
|
|
7954
8099
|
function isCalendarEntity(entityId) {
|
|
7955
8100
|
return entityId.startsWith("calendar.");
|
|
@@ -8060,9 +8205,9 @@ function isSelected(entityId, selected) {
|
|
|
8060
8205
|
function createHaCalendarSource(deps) {
|
|
8061
8206
|
return {
|
|
8062
8207
|
listCalendars: async () => {
|
|
8063
|
-
const selected = deps.selectedCalendarIds();
|
|
8064
8208
|
const out = [];
|
|
8065
|
-
for (const { manager } of deps.brokers.listManagers()) {
|
|
8209
|
+
for (const { brokerId, manager } of deps.brokers.listManagers()) {
|
|
8210
|
+
const selected = deps.selectedCalendarIds(brokerId);
|
|
8066
8211
|
const states = manager.snapshotAllStates();
|
|
8067
8212
|
for (const [entityId, raw] of Object.entries(states)) {
|
|
8068
8213
|
if (!isCalendarEntity(entityId)) continue;
|
|
@@ -8082,10 +8227,10 @@ function createHaCalendarSource(deps) {
|
|
|
8082
8227
|
listEvents: async (input) => {
|
|
8083
8228
|
const startIso = new Date(input.startMs).toISOString();
|
|
8084
8229
|
const endIso = new Date(input.endMs).toISOString();
|
|
8085
|
-
const selected = deps.selectedCalendarIds();
|
|
8086
8230
|
const wanted = input.calendarIds !== void 0 && input.calendarIds.length > 0 ? new Set(input.calendarIds) : null;
|
|
8087
8231
|
const out = [];
|
|
8088
8232
|
for (const { brokerId, manager } of deps.brokers.listManagers()) {
|
|
8233
|
+
const selected = deps.selectedCalendarIds(brokerId);
|
|
8089
8234
|
const states = manager.snapshotAllStates();
|
|
8090
8235
|
const entityIds = Object.keys(states).filter((id) => {
|
|
8091
8236
|
if (!isCalendarEntity(id)) return false;
|
|
@@ -8109,10 +8254,11 @@ function createHaCalendarSource(deps) {
|
|
|
8109
8254
|
};
|
|
8110
8255
|
}
|
|
8111
8256
|
/** Discover every HA calendar entity (ignores the import filter) — for settings catalog. */
|
|
8112
|
-
function listHaCalendarCatalog(brokers) {
|
|
8257
|
+
function listHaCalendarCatalog(brokers, onlyBrokerId) {
|
|
8113
8258
|
const out = [];
|
|
8114
8259
|
const seen = /* @__PURE__ */ new Set();
|
|
8115
|
-
for (const { manager } of brokers.listManagers()) {
|
|
8260
|
+
for (const { brokerId, manager } of brokers.listManagers()) {
|
|
8261
|
+
if (onlyBrokerId !== void 0 && brokerId !== onlyBrokerId) continue;
|
|
8116
8262
|
const states = manager.snapshotAllStates();
|
|
8117
8263
|
for (const [entityId, raw] of Object.entries(states)) {
|
|
8118
8264
|
if (!isCalendarEntity(entityId) || seen.has(entityId)) continue;
|
|
@@ -8283,7 +8429,7 @@ function entityToStandaloneCandidate(entity, alreadyAdopted) {
|
|
|
8283
8429
|
return {
|
|
8284
8430
|
childNativeId: entity.entityId,
|
|
8285
8431
|
name: entity.name,
|
|
8286
|
-
type: entity.mappedTo?.deviceType ??
|
|
8432
|
+
type: entity.mappedTo?.deviceType ?? require_ha_instance_settings.DeviceType.Generic,
|
|
8287
8433
|
status: entityStatus(entity.state),
|
|
8288
8434
|
metadata: entity.area !== null ? { externalLocation: entity.area } : {},
|
|
8289
8435
|
alreadyAdopted,
|
|
@@ -8418,7 +8564,7 @@ function readPersistedStandaloneSpec(device) {
|
|
|
8418
8564
|
* adoption-proof source field), so it is projected directly here, mirroring the
|
|
8419
8565
|
* Container's `EnumSensorDateTimeFormatSchema.safeParse` guard. */
|
|
8420
8566
|
function readDateTimeFormat(config) {
|
|
8421
|
-
const parsed =
|
|
8567
|
+
const parsed = require_ha_instance_settings.EnumSensorDateTimeFormatSchema.safeParse(config["dateTimeFormat"]);
|
|
8422
8568
|
return parsed.success ? parsed.data : void 0;
|
|
8423
8569
|
}
|
|
8424
8570
|
/** Flatten a live device's config into a plain blob for `readHaSource`. */
|
|
@@ -8585,12 +8731,12 @@ var DEFAULT_CONFIG = {
|
|
|
8585
8731
|
* …) and route HA state pushes into runtime-state slices + cap
|
|
8586
8732
|
* mutations into HA call_service.
|
|
8587
8733
|
*/
|
|
8588
|
-
var HaProviderAddon = class HaProviderAddon extends
|
|
8734
|
+
var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings.BaseDeviceProvider {
|
|
8589
8735
|
addonId = "provider-homeassistant";
|
|
8590
8736
|
providerName = "Home Assistant";
|
|
8591
8737
|
deviceClasses = {
|
|
8592
|
-
[
|
|
8593
|
-
[
|
|
8738
|
+
[require_ha_instance_settings.DeviceType.Container]: HaContainerDevice,
|
|
8739
|
+
[require_ha_instance_settings.DeviceType.EventEmitter]: HaEventBusDevice
|
|
8594
8740
|
};
|
|
8595
8741
|
async onGetCreationSchema(_type) {
|
|
8596
8742
|
return null;
|
|
@@ -8646,35 +8792,39 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
8646
8792
|
this.reconcileAllConnectedBrokers();
|
|
8647
8793
|
}, HaProviderAddon.RESYNC_INTERVAL_MS);
|
|
8648
8794
|
this.ctx.logger.info("ha provider initialised", { meta: { brokerCount: this.activeBrokers.length } });
|
|
8795
|
+
await this.runMigrations(require_ha_instance_settings.defineAddonMigrations(ADDON_MIGRATIONS, {
|
|
8796
|
+
readStored: (key) => this.readStoredGlobalKey(key),
|
|
8797
|
+
...require_ha_instance_settings.haInstanceSettingsPortsOver(this.ctx.api.integrations)
|
|
8798
|
+
}));
|
|
8649
8799
|
await this.reconcileIntegrationsToBrokers();
|
|
8650
8800
|
this.subscribeIntegrationLifecycle();
|
|
8651
8801
|
return [
|
|
8652
8802
|
{
|
|
8653
|
-
capability:
|
|
8803
|
+
capability: require_ha_instance_settings.brokerCapability,
|
|
8654
8804
|
provider: this.buildBrokerProvider()
|
|
8655
8805
|
},
|
|
8656
8806
|
{
|
|
8657
|
-
capability:
|
|
8807
|
+
capability: require_ha_instance_settings.deviceAdoptionCapability,
|
|
8658
8808
|
provider: this.buildAdoptionProvider()
|
|
8659
8809
|
},
|
|
8660
8810
|
{
|
|
8661
|
-
capability:
|
|
8811
|
+
capability: require_ha_instance_settings.notificationOutputCapability,
|
|
8662
8812
|
provider: await this.buildNotificationOutputProvider()
|
|
8663
8813
|
},
|
|
8664
8814
|
{
|
|
8665
|
-
capability:
|
|
8815
|
+
capability: require_ha_instance_settings.addonRoutesCapability,
|
|
8666
8816
|
provider: createHaIconRouteProvider()
|
|
8667
8817
|
},
|
|
8668
8818
|
{
|
|
8669
|
-
capability:
|
|
8819
|
+
capability: require_ha_instance_settings.boardKeySourceCapability,
|
|
8670
8820
|
provider: this.buildBoardKeyProvider()
|
|
8671
8821
|
},
|
|
8672
8822
|
{
|
|
8673
|
-
capability:
|
|
8823
|
+
capability: require_ha_instance_settings.calendarSourceCapability,
|
|
8674
8824
|
provider: createHaCalendarSource({
|
|
8675
8825
|
brokers: this.requireRegistry(),
|
|
8676
8826
|
logger: this.ctx.logger.child("calendar-source"),
|
|
8677
|
-
selectedCalendarIds: () =>
|
|
8827
|
+
selectedCalendarIds: (brokerId) => this.calendarIdsOf(brokerId)
|
|
8678
8828
|
})
|
|
8679
8829
|
}
|
|
8680
8830
|
];
|
|
@@ -8722,7 +8872,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
8722
8872
|
return manager.sendMessage({ type: "config/device_registry/list" });
|
|
8723
8873
|
},
|
|
8724
8874
|
listBrokerIds: () => this.activeBrokers.map((b) => b.id),
|
|
8725
|
-
readPublicEndpoint:
|
|
8875
|
+
readPublicEndpoint: require_ha_instance_settings.publicEndpointReaderFrom(this.ctx.api.localNetwork),
|
|
8726
8876
|
logger: this.ctx.logger.child("notification-output")
|
|
8727
8877
|
});
|
|
8728
8878
|
}
|
|
@@ -8772,6 +8922,20 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
8772
8922
|
*
|
|
8773
8923
|
* Idempotent — runs on boot + on every integration.* event.
|
|
8774
8924
|
*/
|
|
8925
|
+
/**
|
|
8926
|
+
* Calendars to import, per broker (D985): the integration's own selection, filled by the
|
|
8927
|
+
* reconcile that already reads each integration's settings. A broker whose integration has no
|
|
8928
|
+
* selection yet (the move has not run) uses the legacy shared set, so a boot mid-move never
|
|
8929
|
+
* changes what is imported.
|
|
8930
|
+
*/
|
|
8931
|
+
calendarIdsByBroker = /* @__PURE__ */ new Map();
|
|
8932
|
+
noteInstanceCalendars(brokerId, raw) {
|
|
8933
|
+
if (Array.isArray(raw) && raw.every((id) => typeof id === "string")) this.calendarIdsByBroker.set(brokerId, new Set(raw));
|
|
8934
|
+
else this.calendarIdsByBroker.delete(brokerId);
|
|
8935
|
+
}
|
|
8936
|
+
calendarIdsOf(brokerId) {
|
|
8937
|
+
return this.calendarIdsByBroker.get(brokerId) ?? new Set(this.config.calendarIds ?? []);
|
|
8938
|
+
}
|
|
8775
8939
|
async reconcileIntegrationsToBrokers() {
|
|
8776
8940
|
const api = this.ctx.api;
|
|
8777
8941
|
if (!api.integrations?.list?.query || !api.integrations.getSettings?.query) return;
|
|
@@ -8783,6 +8947,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
8783
8947
|
const settings = await api.integrations.getSettings.query({ id: integration.id });
|
|
8784
8948
|
const brokerId = typeof settings["brokerId"] === "string" ? settings["brokerId"] : null;
|
|
8785
8949
|
if (!brokerId) continue;
|
|
8950
|
+
this.noteInstanceCalendars(brokerId, settings["calendarIds"]);
|
|
8786
8951
|
if (!this.activeBrokers.find((b) => b.id === brokerId)) {
|
|
8787
8952
|
this.ctx.logger.warn("integration→broker: linked broker not found", { meta: {
|
|
8788
8953
|
integrationId: integration.id,
|
|
@@ -8809,7 +8974,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
8809
8974
|
integrationCount: haIntegrations.length
|
|
8810
8975
|
} });
|
|
8811
8976
|
} catch (err) {
|
|
8812
|
-
this.ctx.logger.warn("integration→broker reconcile failed", { meta: { error:
|
|
8977
|
+
this.ctx.logger.warn("integration→broker reconcile failed", { meta: { error: require_ha_instance_settings.errMsg(err) } });
|
|
8813
8978
|
}
|
|
8814
8979
|
}
|
|
8815
8980
|
subscribeIntegrationLifecycle() {
|
|
@@ -8822,23 +8987,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
8822
8987
|
eb.subscribe({ category: "integration.disabled" }, handler);
|
|
8823
8988
|
eb.subscribe({ category: "integration.deleted" }, handler);
|
|
8824
8989
|
}
|
|
8825
|
-
globalSettingsSchema(
|
|
8826
|
-
if (cap === "calendar-source") return this.schema({ sections: [{
|
|
8827
|
-
id: "ha-calendars-import",
|
|
8828
|
-
title: "Calendars to import",
|
|
8829
|
-
titleKey: "provider-homeassistant:globalSettings.s_ha-calendars-import.title",
|
|
8830
|
-
columns: 1,
|
|
8831
|
-
fields: [{
|
|
8832
|
-
type: "multiselect",
|
|
8833
|
-
key: "calendarIds",
|
|
8834
|
-
label: "Calendars",
|
|
8835
|
-
labelKey: "provider-homeassistant:globalSettings.s_ha-calendars-import.calendarIds.label",
|
|
8836
|
-
options: [],
|
|
8837
|
-
optionsFrom: "_calendarCatalog",
|
|
8838
|
-
description: "Discovered from connected HA brokers. Select at least one to import; leave empty to import none.",
|
|
8839
|
-
descriptionKey: "provider-homeassistant:globalSettings.s_ha-calendars-import.calendarIds.description"
|
|
8840
|
-
}]
|
|
8841
|
-
}] });
|
|
8990
|
+
globalSettingsSchema(_cap) {
|
|
8842
8991
|
return this.schema({ sections: [{
|
|
8843
8992
|
id: "ha-broker",
|
|
8844
8993
|
title: "Home Assistant broker",
|
|
@@ -8853,14 +9002,39 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
8853
9002
|
}]
|
|
8854
9003
|
}] });
|
|
8855
9004
|
}
|
|
8856
|
-
|
|
8857
|
-
|
|
8858
|
-
|
|
8859
|
-
|
|
8860
|
-
|
|
8861
|
-
|
|
8862
|
-
|
|
8863
|
-
|
|
9005
|
+
/**
|
|
9006
|
+
* The calendars of ONE Home Assistant instance (D985): picked on its integration, offered from
|
|
9007
|
+
* that broker's own `calendar.*` entities.
|
|
9008
|
+
*/
|
|
9009
|
+
async integrationSettingsSchema(instance) {
|
|
9010
|
+
if (instance.integrationId === null || !this.registry) return null;
|
|
9011
|
+
let brokerId;
|
|
9012
|
+
try {
|
|
9013
|
+
brokerId = (await this.ctx.api.integrations.getSettings.query({ id: instance.integrationId }))["brokerId"];
|
|
9014
|
+
} catch (err) {
|
|
9015
|
+
this.ctx.logger.warn("HA integration form: instance lookup failed — broker form shown", { meta: {
|
|
9016
|
+
integrationId: instance.integrationId,
|
|
9017
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
9018
|
+
} });
|
|
9019
|
+
return null;
|
|
9020
|
+
}
|
|
9021
|
+
if (typeof brokerId !== "string") return null;
|
|
9022
|
+
const options = listHaCalendarCatalog(this.registry, brokerId);
|
|
9023
|
+
return this.schema({ sections: [{
|
|
9024
|
+
id: "ha-calendars-import",
|
|
9025
|
+
title: "Calendars to import",
|
|
9026
|
+
titleKey: "provider-homeassistant:globalSettings.s_ha-calendars-import.title",
|
|
9027
|
+
columns: 1,
|
|
9028
|
+
fields: [{
|
|
9029
|
+
type: "multiselect",
|
|
9030
|
+
key: "calendarIds",
|
|
9031
|
+
label: "Calendars",
|
|
9032
|
+
labelKey: "provider-homeassistant:globalSettings.s_ha-calendars-import.calendarIds.label",
|
|
9033
|
+
options,
|
|
9034
|
+
description: "Discovered from this Home Assistant instance. Select at least one to import; leave empty to import none.",
|
|
9035
|
+
descriptionKey: "provider-homeassistant:globalSettings.s_ha-calendars-import.calendarIds.description"
|
|
9036
|
+
}]
|
|
9037
|
+
}] });
|
|
8864
9038
|
}
|
|
8865
9039
|
async onShutdown() {
|
|
8866
9040
|
if (this.resyncTimer) {
|
|
@@ -8870,7 +9044,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
8870
9044
|
try {
|
|
8871
9045
|
await this.registry?.shutdown();
|
|
8872
9046
|
} catch (err) {
|
|
8873
|
-
this.ctx.logger.warn("ha provider shutdown error", { meta: { error:
|
|
9047
|
+
this.ctx.logger.warn("ha provider shutdown error", { meta: { error: require_ha_instance_settings.errMsg(err) } });
|
|
8874
9048
|
}
|
|
8875
9049
|
this.registry = null;
|
|
8876
9050
|
await super.onShutdown();
|
|
@@ -8902,7 +9076,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
8902
9076
|
} catch (err) {
|
|
8903
9077
|
this.ctx.logger.warn("ha onConfigChanged: removeEntry failed", { meta: {
|
|
8904
9078
|
brokerId: liveId,
|
|
8905
|
-
error:
|
|
9079
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
8906
9080
|
} });
|
|
8907
9081
|
}
|
|
8908
9082
|
for (const entry of persisted) {
|
|
@@ -8916,7 +9090,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
8916
9090
|
} catch (err) {
|
|
8917
9091
|
this.ctx.logger.warn("ha onConfigChanged: updateEntry failed", { meta: {
|
|
8918
9092
|
brokerId: entry.id,
|
|
8919
|
-
error:
|
|
9093
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
8920
9094
|
} });
|
|
8921
9095
|
}
|
|
8922
9096
|
continue;
|
|
@@ -8937,7 +9111,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
8937
9111
|
} catch (err) {
|
|
8938
9112
|
this.ctx.logger.warn("ha onConfigChanged: failed to start new broker", { meta: {
|
|
8939
9113
|
brokerName: entry.name,
|
|
8940
|
-
error:
|
|
9114
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
8941
9115
|
} });
|
|
8942
9116
|
}
|
|
8943
9117
|
}
|
|
@@ -9087,7 +9261,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
9087
9261
|
const refreshedAt = Date.now();
|
|
9088
9262
|
if (lastDiscoveryAt === null || refreshedAt > lastDiscoveryAt) lastDiscoveryAt = refreshedAt;
|
|
9089
9263
|
} catch (err) {
|
|
9090
|
-
lastError =
|
|
9264
|
+
lastError = require_ha_instance_settings.errMsg(err);
|
|
9091
9265
|
}
|
|
9092
9266
|
const adoptedCount = (await this.ctx.kernel.devices.getAll()).filter((d) => d.parentDeviceId === null && String(d.config.get("system") ?? "") === "homeassistant").length;
|
|
9093
9267
|
return {
|
|
@@ -9233,7 +9407,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
9233
9407
|
name: deviceName
|
|
9234
9408
|
};
|
|
9235
9409
|
const summary = await this.createDevice({
|
|
9236
|
-
type:
|
|
9410
|
+
type: require_ha_instance_settings.DeviceType.Container,
|
|
9237
9411
|
config: containerConfig
|
|
9238
9412
|
});
|
|
9239
9413
|
const accessoryDeviceIds = (await this.ctx.kernel.devices.getChildren(summary.id)).map((c) => c.id);
|
|
@@ -9263,7 +9437,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
9263
9437
|
meta: {
|
|
9264
9438
|
brokerId,
|
|
9265
9439
|
haDeviceId,
|
|
9266
|
-
error:
|
|
9440
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
9267
9441
|
}
|
|
9268
9442
|
});
|
|
9269
9443
|
}
|
|
@@ -9410,7 +9584,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
9410
9584
|
meta: {
|
|
9411
9585
|
brokerId,
|
|
9412
9586
|
entityId,
|
|
9413
|
-
error:
|
|
9587
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
9414
9588
|
}
|
|
9415
9589
|
});
|
|
9416
9590
|
}
|
|
@@ -9431,7 +9605,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
9431
9605
|
*/
|
|
9432
9606
|
async assignImportedLocation(deviceId, externalLocation, knownLocations) {
|
|
9433
9607
|
try {
|
|
9434
|
-
const match =
|
|
9608
|
+
const match = require_ha_instance_settings.bestLocationMatch(externalLocation, knownLocations);
|
|
9435
9609
|
const name = match ?? externalLocation;
|
|
9436
9610
|
let locations = knownLocations;
|
|
9437
9611
|
if (match === null) {
|
|
@@ -9447,7 +9621,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
9447
9621
|
this.ctx.logger.warn("ha-adoption: location import failed (non-fatal)", { meta: {
|
|
9448
9622
|
deviceId,
|
|
9449
9623
|
externalLocation,
|
|
9450
|
-
error:
|
|
9624
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
9451
9625
|
} });
|
|
9452
9626
|
return knownLocations;
|
|
9453
9627
|
}
|
|
@@ -9648,7 +9822,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
9648
9822
|
} catch (err) {
|
|
9649
9823
|
this.ctx.logger.warn("ha bus-event aggregator ensure failed", { meta: {
|
|
9650
9824
|
brokerId,
|
|
9651
|
-
error:
|
|
9825
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
9652
9826
|
} });
|
|
9653
9827
|
}
|
|
9654
9828
|
await reconcileBroker(brokerId, {
|
|
@@ -9658,7 +9832,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
9658
9832
|
onFetchError: (id, error) => {
|
|
9659
9833
|
this.ctx.logger.warn("ha re-sync: inventory fetch failed", { meta: {
|
|
9660
9834
|
brokerId: id,
|
|
9661
|
-
error:
|
|
9835
|
+
error: require_ha_instance_settings.errMsg(error)
|
|
9662
9836
|
} });
|
|
9663
9837
|
}
|
|
9664
9838
|
});
|
|
@@ -9696,7 +9870,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
9696
9870
|
meta: {
|
|
9697
9871
|
brokerId,
|
|
9698
9872
|
haDeviceId,
|
|
9699
|
-
error:
|
|
9873
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
9700
9874
|
}
|
|
9701
9875
|
});
|
|
9702
9876
|
}
|
|
@@ -9741,7 +9915,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
9741
9915
|
tags: { deviceId: action.deviceId },
|
|
9742
9916
|
meta: {
|
|
9743
9917
|
brokerId,
|
|
9744
|
-
error:
|
|
9918
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
9745
9919
|
}
|
|
9746
9920
|
});
|
|
9747
9921
|
}
|
|
@@ -9822,7 +9996,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
9822
9996
|
brokerId,
|
|
9823
9997
|
kind: "event-bus"
|
|
9824
9998
|
}, null, {
|
|
9825
|
-
type:
|
|
9999
|
+
type: require_ha_instance_settings.DeviceType.EventEmitter,
|
|
9826
10000
|
name: "Home Assistant Events"
|
|
9827
10001
|
});
|
|
9828
10002
|
this.eventBusDeviceIds.set(brokerId, device.id);
|
|
@@ -9852,7 +10026,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_broker_source.Bas
|
|
|
9852
10026
|
this.ctx.logger.debug("ha bus-event dropped — aggregator not ready", { meta: {
|
|
9853
10027
|
brokerId,
|
|
9854
10028
|
eventType: ev.eventType,
|
|
9855
|
-
error:
|
|
10029
|
+
error: require_ha_instance_settings.errMsg(err)
|
|
9856
10030
|
} });
|
|
9857
10031
|
return;
|
|
9858
10032
|
}
|