@camstack/addon-provider-homeassistant 1.2.658 → 1.2.660
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 +12 -0
- package/dist/addon.js +661 -553
- package/dist/addon.mjs +191 -83
- package/dist/ha-export/ha-export.addon.js +639 -432
- package/dist/ha-export/ha-export.addon.mjs +585 -367
- package/dist/{ha-instance-settings-qhCNJbbn.mjs → legacy-integration-rows-BIbFoT26.mjs} +27 -5
- package/dist/{ha-instance-settings-CRvQ5rH6.js → legacy-integration-rows-BWVmjfDO.js} +27 -5
- package/i18n/en.json +18 -4
- package/i18n/it.json +18 -4
- package/package.json +5 -2
package/dist/addon.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const
|
|
2
|
+
const require_legacy_integration_rows = require("./legacy-integration-rows-BWVmjfDO.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.literal("homeassistant").optional(),
|
|
118
|
+
brokerId: require_legacy_integration_rows.string(),
|
|
119
|
+
haDeviceId: require_legacy_integration_rows.string().optional(),
|
|
120
|
+
entityId: require_legacy_integration_rows.string().optional(),
|
|
121
|
+
referenceEntityId: require_legacy_integration_rows.string().nullable().optional(),
|
|
122
|
+
capabilities: require_legacy_integration_rows.array(require_legacy_integration_rows.string()).default([]),
|
|
123
|
+
role: require_legacy_integration_rows.string().optional(),
|
|
124
|
+
childDeviceIds: require_legacy_integration_rows.array(require_legacy_integration_rows.number()).default([]),
|
|
125
|
+
unitOfMeasurement: require_legacy_integration_rows.string().optional(),
|
|
126
|
+
deviceClass: require_legacy_integration_rows.string().optional(),
|
|
127
|
+
integrationId: require_legacy_integration_rows.string().optional(),
|
|
128
|
+
options: require_legacy_integration_rows.array(require_legacy_integration_rows.string()).optional(),
|
|
129
|
+
features: require_legacy_integration_rows.array(require_legacy_integration_rows.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_legacy_integration_rows.object({
|
|
132
|
+
power: require_legacy_integration_rows.string().optional(),
|
|
133
|
+
energy: require_legacy_integration_rows.string().optional(),
|
|
134
|
+
voltage: require_legacy_integration_rows.string().optional(),
|
|
135
|
+
current: require_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.object({
|
|
236
|
+
entity_id: require_legacy_integration_rows.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_legacy_integration_rows.string(),
|
|
240
240
|
/** Free-form attribute map. Domain-specific. */
|
|
241
|
-
attributes:
|
|
241
|
+
attributes: require_legacy_integration_rows.record(require_legacy_integration_rows.string(), require_legacy_integration_rows.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_legacy_integration_rows.object({
|
|
244
|
+
id: require_legacy_integration_rows.string(),
|
|
245
|
+
parent_id: require_legacy_integration_rows.string().nullable(),
|
|
246
|
+
user_id: require_legacy_integration_rows.string().nullable()
|
|
247
247
|
}).optional(),
|
|
248
248
|
/** ISO 8601 timestamp of the last state change. */
|
|
249
|
-
last_changed:
|
|
249
|
+
last_changed: require_legacy_integration_rows.string(),
|
|
250
250
|
/** ISO 8601 timestamp of the last update (state OR attributes). */
|
|
251
|
-
last_updated:
|
|
251
|
+
last_updated: require_legacy_integration_rows.string()
|
|
252
252
|
});
|
|
253
253
|
/**
|
|
254
254
|
* Auth strategy. Two mutually-exclusive options:
|
|
@@ -259,16 +259,16 @@ var HaEntityStateSchema = require_ha_instance_settings.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_legacy_integration_rows.discriminatedUnion("kind", [require_legacy_integration_rows.object({
|
|
263
|
+
kind: require_legacy_integration_rows.literal("supervisor"),
|
|
264
264
|
/** Token injected by the Supervisor at runtime via env. */
|
|
265
|
-
supervisorToken:
|
|
266
|
-
}),
|
|
267
|
-
kind:
|
|
265
|
+
supervisorToken: require_legacy_integration_rows.string().min(1).meta({ secret: true })
|
|
266
|
+
}), require_legacy_integration_rows.object({
|
|
267
|
+
kind: require_legacy_integration_rows.literal("long-lived"),
|
|
268
268
|
/** Origin URL of the HA instance (e.g. `https://ha.example:8123`). */
|
|
269
|
-
baseUrl:
|
|
269
|
+
baseUrl: require_legacy_integration_rows.url(),
|
|
270
270
|
/** Long-lived access token issued by the user in their HA profile. */
|
|
271
|
-
accessToken:
|
|
271
|
+
accessToken: require_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.powerMeterCapability.deviceTypes.filter((type) => type !== require_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_instance_settings.object({ ...haSourceSchem
|
|
|
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_legacy_integration_rows.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_legacy_integration_rows.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_instance_sett
|
|
|
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_legacy_integration_rows.errMsg(err)
|
|
643
643
|
} });
|
|
644
644
|
return null;
|
|
645
645
|
}
|
|
@@ -689,7 +689,7 @@ var HaBaseChildDevice = class HaBaseChildDevice extends require_ha_instance_sett
|
|
|
689
689
|
entityId: this.entityId,
|
|
690
690
|
domain,
|
|
691
691
|
service,
|
|
692
|
-
error:
|
|
692
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
693
693
|
} });
|
|
694
694
|
throw err;
|
|
695
695
|
}
|
|
@@ -716,7 +716,7 @@ var HaBaseChildDevice = class HaBaseChildDevice extends require_ha_instance_sett
|
|
|
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_legacy_integration_rows.errMsg(err)
|
|
720
720
|
} });
|
|
721
721
|
return false;
|
|
722
722
|
}
|
|
@@ -757,7 +757,7 @@ var HaBaseChildDevice = class HaBaseChildDevice extends require_ha_instance_sett
|
|
|
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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.runningFromVacuumState(lifecycleState, previous, fetchedAt, lastChangedAt));
|
|
2313
2313
|
}
|
|
2314
2314
|
registerRunningCap() {
|
|
2315
|
-
this.ctx.registerNativeCap(
|
|
2315
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.runningStateCapability, { getStatus: async () => this.runtimeState.getCapState("running-state") ?? require_legacy_integration_rows.RUNNING_STATE_COLD });
|
|
2316
2316
|
}
|
|
2317
2317
|
registerVacuumCap() {
|
|
2318
|
-
this.ctx.registerNativeCap(
|
|
2318
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.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_legacy_integration_rows.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_legacy_integration_rows.runningFromLawnMower(activity, previous, fetchedAt, lastChangedAt));
|
|
2409
2409
|
}
|
|
2410
2410
|
registerRunningCap() {
|
|
2411
|
-
this.ctx.registerNativeCap(
|
|
2411
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.runningStateCapability, { getStatus: async () => this.runtimeState.getCapState("running-state") ?? require_legacy_integration_rows.RUNNING_STATE_COLD });
|
|
2412
2412
|
}
|
|
2413
2413
|
registerLawnMowerCap() {
|
|
2414
|
-
this.ctx.registerNativeCap(
|
|
2414
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.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_legacy_integration_rows.RUNNING_STATE_COLD);
|
|
2471
2471
|
}
|
|
2472
2472
|
handleStatePush(state) {
|
|
2473
2473
|
if (state.state === "unavailable" || state.state === "unknown") return;
|
|
@@ -2492,17 +2492,17 @@ 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_legacy_integration_rows.runningFromMediaPlayer(playerState, previous, fetchedAt, lastChangedAt));
|
|
2496
2496
|
}
|
|
2497
2497
|
registerRunningCap() {
|
|
2498
|
-
this.ctx.registerNativeCap(
|
|
2498
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.runningStateCapability, { getStatus: async () => this.runtimeState.getCapState("running-state") ?? require_legacy_integration_rows.RUNNING_STATE_COLD });
|
|
2499
2499
|
}
|
|
2500
2500
|
/** One service call per step, in order: HA has no "N steps" form. */
|
|
2501
2501
|
async repeatHaService(service, steps) {
|
|
2502
2502
|
for (let step = 0; step < steps; step += 1) await this.callHaService("media_player", service);
|
|
2503
2503
|
}
|
|
2504
2504
|
registerMediaPlayerCap() {
|
|
2505
|
-
this.ctx.registerNativeCap(
|
|
2505
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.mediaPlayerCapability, {
|
|
2506
2506
|
getStatus: async () => {
|
|
2507
2507
|
return this.runtimeState.getCapState("media-player") ?? COLD_START$10;
|
|
2508
2508
|
},
|
|
@@ -2652,7 +2652,7 @@ var HaAlarmPanelDevice = class extends HaBaseChildDevice {
|
|
|
2652
2652
|
});
|
|
2653
2653
|
}
|
|
2654
2654
|
registerAlarmCap() {
|
|
2655
|
-
this.ctx.registerNativeCap(
|
|
2655
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.alarmPanelCapability, {
|
|
2656
2656
|
getStatus: async () => {
|
|
2657
2657
|
return this.runtimeState.getCapState("alarm-panel") ?? COLD_START$9;
|
|
2658
2658
|
},
|
|
@@ -2767,7 +2767,7 @@ var HaPresenceDevice = class extends HaBaseChildDevice {
|
|
|
2767
2767
|
});
|
|
2768
2768
|
}
|
|
2769
2769
|
registerBatteryCap() {
|
|
2770
|
-
this.ctx.registerNativeCap(
|
|
2770
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.batteryCapability, {
|
|
2771
2771
|
getStatus: async () => this.runtimeState.getCapState("battery") ?? COLD_BATTERY,
|
|
2772
2772
|
wakeForStream: async () => ({
|
|
2773
2773
|
awoke: true,
|
|
@@ -2776,7 +2776,7 @@ var HaPresenceDevice = class extends HaBaseChildDevice {
|
|
|
2776
2776
|
});
|
|
2777
2777
|
}
|
|
2778
2778
|
registerPresenceCap() {
|
|
2779
|
-
this.ctx.registerNativeCap(
|
|
2779
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.presenceCapability, { getStatus: async () => {
|
|
2780
2780
|
return this.runtimeState.getCapState("presence") ?? COLD_START$8;
|
|
2781
2781
|
} });
|
|
2782
2782
|
}
|
|
@@ -2844,7 +2844,7 @@ var HaControlDevice = class extends HaBaseChildDevice {
|
|
|
2844
2844
|
if (slice !== null) this.runtimeState.setCapState("control", slice);
|
|
2845
2845
|
}
|
|
2846
2846
|
registerControlCap() {
|
|
2847
|
-
this.ctx.registerNativeCap(
|
|
2847
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.controlCapability, {
|
|
2848
2848
|
getStatus: async () => {
|
|
2849
2849
|
return this.runtimeState.getCapState("control") ?? {
|
|
2850
2850
|
kind: this.kind,
|
|
@@ -2883,10 +2883,10 @@ var HaControlDevice = class extends HaBaseChildDevice {
|
|
|
2883
2883
|
/** Base-unit value → the unit the upstream entity still speaks. */
|
|
2884
2884
|
toUpstream(value) {
|
|
2885
2885
|
const quantity = this.sourceInfo.quantity;
|
|
2886
|
-
const base = quantity === void 0 ? void 0 :
|
|
2886
|
+
const base = quantity === void 0 ? void 0 : require_legacy_integration_rows.baseUnitOf(quantity);
|
|
2887
2887
|
const upstream = this.upstreamUnit;
|
|
2888
2888
|
if (base === void 0 || upstream === void 0 || upstream === base) return value;
|
|
2889
|
-
const converted =
|
|
2889
|
+
const converted = require_legacy_integration_rows.tryConvertUnit(value, base, upstream);
|
|
2890
2890
|
if (converted !== void 0) return converted;
|
|
2891
2891
|
this.deviceLogger.warn("numeric reading refused", {
|
|
2892
2892
|
tags: { deviceId: this.id },
|
|
@@ -2987,7 +2987,7 @@ function decodeNumeric(state, lastChangedAt, decode) {
|
|
|
2987
2987
|
if (!Number.isFinite(v)) return null;
|
|
2988
2988
|
const rawUnit = state.attributes["unit_of_measurement"];
|
|
2989
2989
|
const unit = typeof rawUnit === "string" && rawUnit.length > 0 ? rawUnit : void 0;
|
|
2990
|
-
const incoming = unit === void 0 ? void 0 :
|
|
2990
|
+
const incoming = unit === void 0 ? void 0 : require_legacy_integration_rows.quantityFromUnit(unit);
|
|
2991
2991
|
if (unit !== void 0 && (incoming === void 0 || incoming === "device")) {
|
|
2992
2992
|
decode.logger.warn("numeric reading refused", {
|
|
2993
2993
|
tags: { deviceId: decode.deviceId },
|
|
@@ -3014,7 +3014,7 @@ function decodeNumeric(state, lastChangedAt, decode) {
|
|
|
3014
3014
|
}
|
|
3015
3015
|
const value = takeReading(decode.logger, decode.deviceId, v, unit, quantity);
|
|
3016
3016
|
if (value === null) return null;
|
|
3017
|
-
decode.note(quantity, unit === void 0 ? void 0 :
|
|
3017
|
+
decode.note(quantity, unit === void 0 ? void 0 : require_legacy_integration_rows.normalizeUnit(unit));
|
|
3018
3018
|
const rawMin = state.attributes["min"];
|
|
3019
3019
|
const rawMax = state.attributes["max"];
|
|
3020
3020
|
const rawStep = state.attributes["step"];
|
|
@@ -3034,10 +3034,10 @@ function decodeNumeric(state, lastChangedAt, decode) {
|
|
|
3034
3034
|
/** A step is a difference: °F's offset must not move it. */
|
|
3035
3035
|
function convertStep(step, unit, quantity) {
|
|
3036
3036
|
if (step === void 0) return void 0;
|
|
3037
|
-
const base =
|
|
3038
|
-
const from = unit === void 0 ? void 0 :
|
|
3037
|
+
const base = require_legacy_integration_rows.baseUnitOf(quantity);
|
|
3038
|
+
const from = unit === void 0 ? void 0 : require_legacy_integration_rows.normalizeUnit(unit);
|
|
3039
3039
|
if (base === void 0 || from === void 0 || from === base) return step;
|
|
3040
|
-
return
|
|
3040
|
+
return require_legacy_integration_rows.tryConvertDelta(step, from, base);
|
|
3041
3041
|
}
|
|
3042
3042
|
//#endregion
|
|
3043
3043
|
//#region src/devices/ha-script-device.ts
|
|
@@ -3080,7 +3080,7 @@ var HaScriptDevice = class extends HaBaseChildDevice {
|
|
|
3080
3080
|
});
|
|
3081
3081
|
}
|
|
3082
3082
|
registerScriptCap() {
|
|
3083
|
-
this.ctx.registerNativeCap(
|
|
3083
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.scriptRunnerCapability, {
|
|
3084
3084
|
getStatus: async () => {
|
|
3085
3085
|
return this.runtimeState.getCapState("script-runner") ?? COLD_START$7;
|
|
3086
3086
|
},
|
|
@@ -3139,7 +3139,7 @@ var HaAutomationDevice = class extends HaBaseChildDevice {
|
|
|
3139
3139
|
});
|
|
3140
3140
|
}
|
|
3141
3141
|
registerAutomationCap() {
|
|
3142
|
-
this.ctx.registerNativeCap(
|
|
3142
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.automationControlCapability, {
|
|
3143
3143
|
getStatus: async () => {
|
|
3144
3144
|
return this.runtimeState.getCapState("automation-control") ?? COLD_START$6;
|
|
3145
3145
|
},
|
|
@@ -3198,7 +3198,7 @@ var HaNotifierDevice = class extends HaBaseChildDevice {
|
|
|
3198
3198
|
handleStatePush(_state) {}
|
|
3199
3199
|
registerNotifierCap() {
|
|
3200
3200
|
const serviceName = this.entityId.split(".")[1] ?? "";
|
|
3201
|
-
this.ctx.registerNativeCap(
|
|
3201
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.notifierCapability, {
|
|
3202
3202
|
getStatus: async () => {
|
|
3203
3203
|
return this.runtimeState.getCapState("notifier") ?? COLD_START$5;
|
|
3204
3204
|
},
|
|
@@ -3294,7 +3294,7 @@ var HaPowerMeterDevice = class extends HaBaseChildDevice {
|
|
|
3294
3294
|
if (update !== null) this.runtimeState.setCapState("power-meter", update);
|
|
3295
3295
|
}
|
|
3296
3296
|
registerPowerMeterCap() {
|
|
3297
|
-
this.ctx.registerNativeCap(
|
|
3297
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.powerMeterCapability, { getStatus: async () => {
|
|
3298
3298
|
return this.runtimeState.getCapState("power-meter") ?? COLD_START$4;
|
|
3299
3299
|
} });
|
|
3300
3300
|
}
|
|
@@ -3373,7 +3373,7 @@ var HaAirQualityDevice = class extends HaBaseChildDevice {
|
|
|
3373
3373
|
if (update !== null) this.runtimeState.setCapState("air-quality-sensor", update);
|
|
3374
3374
|
}
|
|
3375
3375
|
registerCap() {
|
|
3376
|
-
this.ctx.registerNativeCap(
|
|
3376
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.airQualitySensorCapability, { getStatus: async () => {
|
|
3377
3377
|
return this.runtimeState.getCapState("air-quality-sensor") ?? COLD_START$3;
|
|
3378
3378
|
} });
|
|
3379
3379
|
}
|
|
@@ -3448,7 +3448,7 @@ var HaEnumSensorDevice = class extends HaBaseChildDevice {
|
|
|
3448
3448
|
constructor(ctx) {
|
|
3449
3449
|
const persisted = ctx.persistedConfig ?? {};
|
|
3450
3450
|
super(ctx, persisted.role !== void 0 ? { role: persisted.role } : {});
|
|
3451
|
-
const parsedFormat =
|
|
3451
|
+
const parsedFormat = require_legacy_integration_rows.EnumSensorDateTimeFormatSchema.safeParse(persisted.dateTimeFormat);
|
|
3452
3452
|
this.dateTimeFormat = parsedFormat.success ? parsedFormat.data : void 0;
|
|
3453
3453
|
if (this.dateTimeFormat !== void 0) this.updateSourceInfo({ dateTimeShape: this.dateTimeFormat });
|
|
3454
3454
|
this.registerCap();
|
|
@@ -3470,7 +3470,7 @@ var HaEnumSensorDevice = class extends HaBaseChildDevice {
|
|
|
3470
3470
|
});
|
|
3471
3471
|
}
|
|
3472
3472
|
registerCap() {
|
|
3473
|
-
this.ctx.registerNativeCap(
|
|
3473
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.enumSensorCapability, { getStatus: async () => {
|
|
3474
3474
|
return this.runtimeState.getCapState("enum-sensor") ?? this.coldStart();
|
|
3475
3475
|
} });
|
|
3476
3476
|
}
|
|
@@ -3569,7 +3569,7 @@ var HaEventEmitterDevice = class extends HaBaseChildDevice {
|
|
|
3569
3569
|
timestamp: Date.now(),
|
|
3570
3570
|
seq: ++this.#seq
|
|
3571
3571
|
};
|
|
3572
|
-
this.ctx.eventBus.emit(
|
|
3572
|
+
this.ctx.eventBus.emit(require_legacy_integration_rows.createEvent(require_legacy_integration_rows.EventCategory.EventEmitted, {
|
|
3573
3573
|
type: "device",
|
|
3574
3574
|
id: this.stableId,
|
|
3575
3575
|
deviceId: this.id,
|
|
@@ -3583,7 +3583,7 @@ var HaEventEmitterDevice = class extends HaBaseChildDevice {
|
|
|
3583
3583
|
this.runtimeState.setCapState("event-emitter", slice);
|
|
3584
3584
|
}
|
|
3585
3585
|
registerEventEmitterCap() {
|
|
3586
|
-
this.ctx.registerNativeCap(
|
|
3586
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.eventEmitterCapability, { getStatus: async () => this.readSlice() });
|
|
3587
3587
|
}
|
|
3588
3588
|
readSlice() {
|
|
3589
3589
|
return this.runtimeState.getCapState("event-emitter") ?? {
|
|
@@ -3666,7 +3666,7 @@ var HaWeatherDevice = class extends HaBaseChildDevice {
|
|
|
3666
3666
|
this.runtimeState.setCapState("weather", slice);
|
|
3667
3667
|
}
|
|
3668
3668
|
registerWeatherCap() {
|
|
3669
|
-
this.ctx.registerNativeCap(
|
|
3669
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.weatherCapability, { getStatus: async () => {
|
|
3670
3670
|
return this.runtimeState.getCapState("weather") ?? COLD_START$1;
|
|
3671
3671
|
} });
|
|
3672
3672
|
}
|
|
@@ -3764,7 +3764,7 @@ var HaImageDevice = class extends HaBaseChildDevice {
|
|
|
3764
3764
|
this.deviceLogger.warn("ha-image: failed to build absolute image url", { meta: {
|
|
3765
3765
|
entityId: this.entityId,
|
|
3766
3766
|
brokerId: this.brokerId,
|
|
3767
|
-
error:
|
|
3767
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
3768
3768
|
} });
|
|
3769
3769
|
url = null;
|
|
3770
3770
|
}
|
|
@@ -3796,7 +3796,7 @@ var HaImageDevice = class extends HaBaseChildDevice {
|
|
|
3796
3796
|
return typeof raw === "string" && raw.length > 0 ? raw : null;
|
|
3797
3797
|
}
|
|
3798
3798
|
registerImageCap() {
|
|
3799
|
-
this.ctx.registerNativeCap(
|
|
3799
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.imageCapability, { getStatus: async () => {
|
|
3800
3800
|
return this.runtimeState.getCapState("image") ?? COLD_START;
|
|
3801
3801
|
} });
|
|
3802
3802
|
}
|
|
@@ -3890,28 +3890,28 @@ function pickHaChildClass(capabilities) {
|
|
|
3890
3890
|
//#region src/ha-container-reconcile.ts
|
|
3891
3891
|
/** Validates a persisted Container `entities[]` blob (mirrors `haEntitySchema`
|
|
3892
3892
|
* in ha-container-device.ts). Returns `[]` on absent/invalid input. */
|
|
3893
|
-
var containerEntitySchema =
|
|
3894
|
-
entityId:
|
|
3895
|
-
deviceType:
|
|
3896
|
-
capabilities:
|
|
3897
|
-
role:
|
|
3898
|
-
unitOfMeasurement:
|
|
3899
|
-
deviceClass:
|
|
3900
|
-
options:
|
|
3901
|
-
features:
|
|
3902
|
-
name:
|
|
3903
|
-
dateTimeFormat:
|
|
3904
|
-
entityCategory:
|
|
3905
|
-
meterEntities:
|
|
3906
|
-
power:
|
|
3907
|
-
energy:
|
|
3908
|
-
voltage:
|
|
3909
|
-
current:
|
|
3893
|
+
var containerEntitySchema = require_legacy_integration_rows.object({
|
|
3894
|
+
entityId: require_legacy_integration_rows.string(),
|
|
3895
|
+
deviceType: require_legacy_integration_rows._enum(require_legacy_integration_rows.DeviceType),
|
|
3896
|
+
capabilities: require_legacy_integration_rows.array(require_legacy_integration_rows.string()),
|
|
3897
|
+
role: require_legacy_integration_rows.string().optional(),
|
|
3898
|
+
unitOfMeasurement: require_legacy_integration_rows.string().optional(),
|
|
3899
|
+
deviceClass: require_legacy_integration_rows.string().optional(),
|
|
3900
|
+
options: require_legacy_integration_rows.array(require_legacy_integration_rows.string()).optional(),
|
|
3901
|
+
features: require_legacy_integration_rows.array(require_legacy_integration_rows.string()).optional(),
|
|
3902
|
+
name: require_legacy_integration_rows.string().optional(),
|
|
3903
|
+
dateTimeFormat: require_legacy_integration_rows.EnumSensorDateTimeFormatSchema.optional(),
|
|
3904
|
+
entityCategory: require_legacy_integration_rows._enum(["config", "diagnostic"]).optional(),
|
|
3905
|
+
meterEntities: require_legacy_integration_rows.object({
|
|
3906
|
+
power: require_legacy_integration_rows.string().optional(),
|
|
3907
|
+
energy: require_legacy_integration_rows.string().optional(),
|
|
3908
|
+
voltage: require_legacy_integration_rows.string().optional(),
|
|
3909
|
+
current: require_legacy_integration_rows.string().optional()
|
|
3910
3910
|
}).optional(),
|
|
3911
|
-
foldedInto:
|
|
3911
|
+
foldedInto: require_legacy_integration_rows.string().optional()
|
|
3912
3912
|
});
|
|
3913
3913
|
function parseContainerEntities(raw) {
|
|
3914
|
-
const result =
|
|
3914
|
+
const result = require_legacy_integration_rows.array(containerEntitySchema).safeParse(raw);
|
|
3915
3915
|
return result.success ? result.data : [];
|
|
3916
3916
|
}
|
|
3917
3917
|
/**
|
|
@@ -4065,45 +4065,45 @@ function deriveChildLayout(entities) {
|
|
|
4065
4065
|
}
|
|
4066
4066
|
//#endregion
|
|
4067
4067
|
//#region src/devices/ha-container-device.ts
|
|
4068
|
-
var haEntitySchema =
|
|
4069
|
-
entityId:
|
|
4070
|
-
deviceType:
|
|
4071
|
-
capabilities:
|
|
4072
|
-
role:
|
|
4073
|
-
unitOfMeasurement:
|
|
4074
|
-
deviceClass:
|
|
4068
|
+
var haEntitySchema = require_legacy_integration_rows.object({
|
|
4069
|
+
entityId: require_legacy_integration_rows.string(),
|
|
4070
|
+
deviceType: require_legacy_integration_rows._enum(require_legacy_integration_rows.DeviceType),
|
|
4071
|
+
capabilities: require_legacy_integration_rows.array(require_legacy_integration_rows.string()),
|
|
4072
|
+
role: require_legacy_integration_rows.string().optional(),
|
|
4073
|
+
unitOfMeasurement: require_legacy_integration_rows.string().optional(),
|
|
4074
|
+
deviceClass: require_legacy_integration_rows.string().optional(),
|
|
4075
4075
|
/** HA `options` attribute — present on select / input_select entities.
|
|
4076
4076
|
* Persisted at adoption so the control slice is seeded immediately. */
|
|
4077
|
-
options:
|
|
4077
|
+
options: require_legacy_integration_rows.array(require_legacy_integration_rows.string()).optional(),
|
|
4078
4078
|
/** Mapping-derived DeviceFeature flags (e.g. `lock-open`) — surfaced on the
|
|
4079
4079
|
* child's `device.features` so the UI gates feature affordances. */
|
|
4080
|
-
features:
|
|
4080
|
+
features: require_legacy_integration_rows.array(require_legacy_integration_rows.string()).optional(),
|
|
4081
4081
|
/** HA friendly_name — persisted so the child device name survives
|
|
4082
4082
|
* a reboot without a discovery round-trip. Falls back to entityId. */
|
|
4083
|
-
name:
|
|
4083
|
+
name: require_legacy_integration_rows.string().optional(),
|
|
4084
4084
|
/** Locale-render shape for a `DateTimeSensor`-role enum sensor
|
|
4085
4085
|
* (`device_class=timestamp` → `'datetime'`, `date` → `'date'`). Seeded into
|
|
4086
4086
|
* the enum-sensor cap slice by the child so the UI renders the ISO `value`. */
|
|
4087
|
-
dateTimeFormat:
|
|
4087
|
+
dateTimeFormat: require_legacy_integration_rows.EnumSensorDateTimeFormatSchema.optional(),
|
|
4088
4088
|
/** HA `entity_category` — `config` / `diagnostic` / absent (a normal
|
|
4089
4089
|
* control). Drives the accordion section the child renders in. */
|
|
4090
|
-
entityCategory:
|
|
4090
|
+
entityCategory: require_legacy_integration_rows._enum(["config", "diagnostic"]).optional(),
|
|
4091
4091
|
/** Sibling meter sensors this entity reads as its own power-meter (D951). */
|
|
4092
|
-
meterEntities:
|
|
4093
|
-
power:
|
|
4094
|
-
energy:
|
|
4095
|
-
voltage:
|
|
4096
|
-
current:
|
|
4092
|
+
meterEntities: require_legacy_integration_rows.object({
|
|
4093
|
+
power: require_legacy_integration_rows.string().optional(),
|
|
4094
|
+
energy: require_legacy_integration_rows.string().optional(),
|
|
4095
|
+
voltage: require_legacy_integration_rows.string().optional(),
|
|
4096
|
+
current: require_legacy_integration_rows.string().optional()
|
|
4097
4097
|
}).optional(),
|
|
4098
4098
|
/** Set on a meter sensor folded into another entity: sectioned as Diagnostic. */
|
|
4099
|
-
foldedInto:
|
|
4099
|
+
foldedInto: require_legacy_integration_rows.string().optional()
|
|
4100
4100
|
});
|
|
4101
|
-
var haContainerSchema =
|
|
4102
|
-
system:
|
|
4103
|
-
brokerId:
|
|
4104
|
-
haDeviceId:
|
|
4105
|
-
integrationId:
|
|
4106
|
-
entities:
|
|
4101
|
+
var haContainerSchema = require_legacy_integration_rows.object({
|
|
4102
|
+
system: require_legacy_integration_rows.literal("homeassistant"),
|
|
4103
|
+
brokerId: require_legacy_integration_rows.string(),
|
|
4104
|
+
haDeviceId: require_legacy_integration_rows.string(),
|
|
4105
|
+
integrationId: require_legacy_integration_rows.string().optional(),
|
|
4106
|
+
entities: require_legacy_integration_rows.array(haEntitySchema).default([])
|
|
4107
4107
|
});
|
|
4108
4108
|
/**
|
|
4109
4109
|
* A container entity is a battery source when the HA domain mapping
|
|
@@ -4113,7 +4113,7 @@ var haContainerSchema = require_ha_instance_settings.object({
|
|
|
4113
4113
|
* device_class is the original HA attribute that drove it.
|
|
4114
4114
|
*/
|
|
4115
4115
|
function isBatteryEntity(entity) {
|
|
4116
|
-
return entity.role ===
|
|
4116
|
+
return entity.role === require_legacy_integration_rows.DeviceRole.BatterySensor || entity.deviceClass === "battery";
|
|
4117
4117
|
}
|
|
4118
4118
|
/**
|
|
4119
4119
|
* A battery entity is BINARY when HA exposes it as a `binary_sensor`
|
|
@@ -4205,7 +4205,7 @@ function batteryEntityId(entities) {
|
|
|
4205
4205
|
* persist initial config, build context, construct via factory, then
|
|
4206
4206
|
* run the child's own probe + accessory + activate phases.
|
|
4207
4207
|
*/
|
|
4208
|
-
var HaContainerDevice = class HaContainerDevice extends
|
|
4208
|
+
var HaContainerDevice = class HaContainerDevice extends require_legacy_integration_rows.BaseDevice {
|
|
4209
4209
|
features;
|
|
4210
4210
|
brokerId;
|
|
4211
4211
|
integrationId;
|
|
@@ -4226,10 +4226,10 @@ var HaContainerDevice = class HaContainerDevice extends require_ha_instance_sett
|
|
|
4226
4226
|
constructor(ctx) {
|
|
4227
4227
|
const cfg = haContainerSchema.parse(ctx.persistedConfig ?? {});
|
|
4228
4228
|
const batteryEntity = selectBatteryEntity(cfg.entities);
|
|
4229
|
-
super(ctx, haContainerSchema, { type:
|
|
4229
|
+
super(ctx, haContainerSchema, { type: require_legacy_integration_rows.DeviceType.Container });
|
|
4230
4230
|
this.brokerId = cfg.brokerId;
|
|
4231
4231
|
this.integrationId = cfg.integrationId;
|
|
4232
|
-
this.features = batteryEntity !== null ? [
|
|
4232
|
+
this.features = batteryEntity !== null ? [require_legacy_integration_rows.DeviceFeature.Resyncable, require_legacy_integration_rows.DeviceFeature.BatteryOperated] : [require_legacy_integration_rows.DeviceFeature.Resyncable];
|
|
4233
4233
|
this.entityIds = new Set(cfg.entities.map((e) => e.entityId));
|
|
4234
4234
|
this.online = false;
|
|
4235
4235
|
this.batteryEntityId = batteryEntityId(cfg.entities);
|
|
@@ -4240,7 +4240,7 @@ var HaContainerDevice = class HaContainerDevice extends require_ha_instance_sett
|
|
|
4240
4240
|
sleeping: false,
|
|
4241
4241
|
lastUpdated: 0
|
|
4242
4242
|
};
|
|
4243
|
-
this.ctx.registerNativeCap(
|
|
4243
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.batteryCapability, {
|
|
4244
4244
|
getStatus: async () => this.runtimeState.getCapState("battery") ?? COLD,
|
|
4245
4245
|
wakeForStream: async () => ({
|
|
4246
4246
|
awoke: true,
|
|
@@ -4315,7 +4315,7 @@ var HaContainerDevice = class HaContainerDevice extends require_ha_instance_sett
|
|
|
4315
4315
|
} catch (err) {
|
|
4316
4316
|
this.ctx.logger.warn("ha-container failed to subscribe entities for availability", { meta: {
|
|
4317
4317
|
brokerId: this.brokerId,
|
|
4318
|
-
error:
|
|
4318
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
4319
4319
|
} });
|
|
4320
4320
|
}
|
|
4321
4321
|
}
|
|
@@ -4356,7 +4356,7 @@ var HaContainerDevice = class HaContainerDevice extends require_ha_instance_sett
|
|
|
4356
4356
|
} catch (err) {
|
|
4357
4357
|
this.ctx.logger.warn("ha-container failed to persist childLayout", { meta: {
|
|
4358
4358
|
haDeviceId: this.config.values.haDeviceId,
|
|
4359
|
-
error:
|
|
4359
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
4360
4360
|
} });
|
|
4361
4361
|
}
|
|
4362
4362
|
}
|
|
@@ -4435,10 +4435,10 @@ var HaContainerDevice = class HaContainerDevice extends require_ha_instance_sett
|
|
|
4435
4435
|
* entity-backed (no `entityId`), so it does NOT extend the HA child base
|
|
4436
4436
|
* device — it is a thin standalone `BaseDevice` subclass.
|
|
4437
4437
|
*/
|
|
4438
|
-
var haEventBusDeviceSchema =
|
|
4439
|
-
system:
|
|
4440
|
-
brokerId:
|
|
4441
|
-
kind:
|
|
4438
|
+
var haEventBusDeviceSchema = require_legacy_integration_rows.object({
|
|
4439
|
+
system: require_legacy_integration_rows.literal("homeassistant"),
|
|
4440
|
+
brokerId: require_legacy_integration_rows.string(),
|
|
4441
|
+
kind: require_legacy_integration_rows.literal("event-bus")
|
|
4442
4442
|
});
|
|
4443
4443
|
/**
|
|
4444
4444
|
* Case 2 — generic per-broker HA bus-event aggregator.
|
|
@@ -4459,7 +4459,7 @@ var haEventBusDeviceSchema = require_ha_instance_settings.object({
|
|
|
4459
4459
|
* directly via {@link handleBusEvent} (the integration manager subscribes
|
|
4460
4460
|
* to the curated bus event types and threads each fire through the addon).
|
|
4461
4461
|
*/
|
|
4462
|
-
var HaEventBusDevice = class extends
|
|
4462
|
+
var HaEventBusDevice = class extends require_legacy_integration_rows.BaseDevice {
|
|
4463
4463
|
features = [];
|
|
4464
4464
|
/** Monotonic sequence — two identical events still produce distinct slice
|
|
4465
4465
|
* writes / bus emissions. */
|
|
@@ -4498,7 +4498,7 @@ var HaEventBusDevice = class extends require_ha_instance_settings.BaseDevice {
|
|
|
4498
4498
|
timestamp: Date.now(),
|
|
4499
4499
|
seq: ++this.#seq
|
|
4500
4500
|
};
|
|
4501
|
-
this.ctx.eventBus.emit(
|
|
4501
|
+
this.ctx.eventBus.emit(require_legacy_integration_rows.createEvent(require_legacy_integration_rows.EventCategory.EventEmitted, {
|
|
4502
4502
|
type: "device",
|
|
4503
4503
|
id: this.stableId,
|
|
4504
4504
|
deviceId: this.id,
|
|
@@ -4512,7 +4512,7 @@ var HaEventBusDevice = class extends require_ha_instance_settings.BaseDevice {
|
|
|
4512
4512
|
this.runtimeState.setCapState("event-emitter", slice);
|
|
4513
4513
|
}
|
|
4514
4514
|
registerEventEmitterCap() {
|
|
4515
|
-
this.ctx.registerNativeCap(
|
|
4515
|
+
this.ctx.registerNativeCap(require_legacy_integration_rows.eventEmitterCapability, { getStatus: async () => this.readSlice() });
|
|
4516
4516
|
}
|
|
4517
4517
|
readSlice() {
|
|
4518
4518
|
return this.runtimeState.getCapState("event-emitter") ?? {
|
|
@@ -4547,7 +4547,7 @@ async function cascadeRemoveDevicesForBroker(input) {
|
|
|
4547
4547
|
tags: { deviceId: d.id },
|
|
4548
4548
|
meta: {
|
|
4549
4549
|
brokerId,
|
|
4550
|
-
error:
|
|
4550
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
4551
4551
|
}
|
|
4552
4552
|
});
|
|
4553
4553
|
}
|
|
@@ -5453,7 +5453,7 @@ var HaIntegrationManager = class HaIntegrationManager {
|
|
|
5453
5453
|
} catch (err) {
|
|
5454
5454
|
this.opts.logger.warn("ha-broker onConnected handler threw", { meta: {
|
|
5455
5455
|
brokerId: this.opts.id,
|
|
5456
|
-
error:
|
|
5456
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
5457
5457
|
} });
|
|
5458
5458
|
}
|
|
5459
5459
|
},
|
|
@@ -5468,12 +5468,12 @@ var HaIntegrationManager = class HaIntegrationManager {
|
|
|
5468
5468
|
} catch (err) {
|
|
5469
5469
|
this.opts.logger.warn("ha-broker onDisconnected handler threw", { meta: {
|
|
5470
5470
|
brokerId: this.opts.id,
|
|
5471
|
-
error:
|
|
5471
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
5472
5472
|
} });
|
|
5473
5473
|
}
|
|
5474
5474
|
},
|
|
5475
5475
|
onReconnectError: (err, nextDelayMs) => {
|
|
5476
|
-
this.lastError =
|
|
5476
|
+
this.lastError = require_legacy_integration_rows.errMsg(err);
|
|
5477
5477
|
this.opts.logger.warn("ha-broker reconnect attempt failed", { meta: {
|
|
5478
5478
|
brokerId: this.opts.id,
|
|
5479
5479
|
error: this.lastError,
|
|
@@ -5654,7 +5654,7 @@ var HaIntegrationManager = class HaIntegrationManager {
|
|
|
5654
5654
|
this.opts.logger.warn("ha-broker bus-event subscribe failed", { meta: {
|
|
5655
5655
|
brokerId: this.opts.id,
|
|
5656
5656
|
eventType,
|
|
5657
|
-
error:
|
|
5657
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
5658
5658
|
} });
|
|
5659
5659
|
}
|
|
5660
5660
|
}
|
|
@@ -5690,7 +5690,7 @@ var HaIntegrationManager = class HaIntegrationManager {
|
|
|
5690
5690
|
return false;
|
|
5691
5691
|
}
|
|
5692
5692
|
emitBrokerMessage(subscriptionId, entityId, state) {
|
|
5693
|
-
this.opts.eventBus.emit(
|
|
5693
|
+
this.opts.eventBus.emit(require_legacy_integration_rows.createEvent("broker.message", {
|
|
5694
5694
|
type: "addon",
|
|
5695
5695
|
id: this.opts.id
|
|
5696
5696
|
}, {
|
|
@@ -5712,7 +5712,7 @@ var HaIntegrationManager = class HaIntegrationManager {
|
|
|
5712
5712
|
} catch (err) {
|
|
5713
5713
|
this.opts.logger.debug("ha get_config probe failed", { meta: {
|
|
5714
5714
|
brokerId: this.opts.id,
|
|
5715
|
-
error:
|
|
5715
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
5716
5716
|
} });
|
|
5717
5717
|
}
|
|
5718
5718
|
}
|
|
@@ -5720,7 +5720,7 @@ var HaIntegrationManager = class HaIntegrationManager {
|
|
|
5720
5720
|
if (this.status === next) return;
|
|
5721
5721
|
this.status = next;
|
|
5722
5722
|
this.lastCheckedAt = Date.now();
|
|
5723
|
-
this.opts.eventBus.emit(
|
|
5723
|
+
this.opts.eventBus.emit(require_legacy_integration_rows.createEvent("broker.status-changed", {
|
|
5724
5724
|
type: "addon",
|
|
5725
5725
|
id: this.opts.id
|
|
5726
5726
|
}, {
|
|
@@ -5741,7 +5741,7 @@ var HaIntegrationManager = class HaIntegrationManager {
|
|
|
5741
5741
|
this.lastError = "Home Assistant host / URL is required";
|
|
5742
5742
|
this.setStatus("unreachable");
|
|
5743
5743
|
} else {
|
|
5744
|
-
this.lastError =
|
|
5744
|
+
this.lastError = require_legacy_integration_rows.errMsg(err);
|
|
5745
5745
|
this.setStatus("error");
|
|
5746
5746
|
}
|
|
5747
5747
|
}
|
|
@@ -5762,19 +5762,21 @@ var TEST_HANDSHAKE_TIMEOUT_MS = 8e3;
|
|
|
5762
5762
|
* `dataDir` being protected by filesystem permissions. (MQTT broker
|
|
5763
5763
|
* encrypts at rest; HA broker does not yet — TODO for hardening.)
|
|
5764
5764
|
*/
|
|
5765
|
-
var HaBrokerEntrySchema =
|
|
5766
|
-
id:
|
|
5767
|
-
name:
|
|
5765
|
+
var HaBrokerEntrySchema = require_legacy_integration_rows.object({
|
|
5766
|
+
id: require_legacy_integration_rows.string(),
|
|
5767
|
+
name: require_legacy_integration_rows.string(),
|
|
5768
5768
|
/** Supervisor (token from env) or long-lived (persisted); picks which fields below are used. */
|
|
5769
|
-
authKind:
|
|
5769
|
+
authKind: require_legacy_integration_rows._enum(["long-lived", "supervisor"]),
|
|
5770
5770
|
/** Origin URL of the HA instance; long-lived only. */
|
|
5771
|
-
baseUrl:
|
|
5772
|
-
accessToken:
|
|
5773
|
-
supervisorToken:
|
|
5771
|
+
baseUrl: require_legacy_integration_rows.string().optional(),
|
|
5772
|
+
accessToken: require_legacy_integration_rows.string().optional().meta({ secret: true }),
|
|
5773
|
+
supervisorToken: require_legacy_integration_rows.string().optional().meta({ secret: true }),
|
|
5774
5774
|
/** Optional FK to the integration record that spawned this broker. */
|
|
5775
|
-
integrationId:
|
|
5775
|
+
integrationId: require_legacy_integration_rows.string().optional(),
|
|
5776
5776
|
/** The instance's own switch (D996); absent means on. */
|
|
5777
|
-
enabled:
|
|
5777
|
+
enabled: require_legacy_integration_rows.boolean().optional(),
|
|
5778
|
+
/** The `calendar.*` entity ids this instance imports (planning#416); absent means the addon default. */
|
|
5779
|
+
calendarIds: require_legacy_integration_rows.array(require_legacy_integration_rows.string()).optional()
|
|
5778
5780
|
});
|
|
5779
5781
|
/**
|
|
5780
5782
|
* Validates a `broker.add` `settings` payload for the HA kind. Accepts:
|
|
@@ -5783,10 +5785,10 @@ var HaBrokerEntrySchema = require_ha_instance_settings.object({
|
|
|
5783
5785
|
* persisting allows the addon to keep working after the env var
|
|
5784
5786
|
* rotates out of scope)
|
|
5785
5787
|
*/
|
|
5786
|
-
var HaAddSettingsSchema =
|
|
5787
|
-
baseUrl:
|
|
5788
|
-
accessToken:
|
|
5789
|
-
}),
|
|
5788
|
+
var HaAddSettingsSchema = require_legacy_integration_rows.union([require_legacy_integration_rows.object({
|
|
5789
|
+
baseUrl: require_legacy_integration_rows.url(),
|
|
5790
|
+
accessToken: require_legacy_integration_rows.string().min(1).meta({ secret: true })
|
|
5791
|
+
}), require_legacy_integration_rows.object({ supervisorToken: require_legacy_integration_rows.string().min(1).meta({ secret: true }) })]);
|
|
5790
5792
|
function settingsToAuth(settings) {
|
|
5791
5793
|
const parsed = HaAddSettingsSchema.parse(settings);
|
|
5792
5794
|
if ("supervisorToken" in parsed) return {
|
|
@@ -5895,7 +5897,7 @@ var HaBrokerRegistry = class {
|
|
|
5895
5897
|
} catch (err) {
|
|
5896
5898
|
this.logger.warn("ha-broker bootstrap failed", { meta: {
|
|
5897
5899
|
brokerId: entry.id,
|
|
5898
|
-
error:
|
|
5900
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
5899
5901
|
} });
|
|
5900
5902
|
}
|
|
5901
5903
|
}));
|
|
@@ -5989,7 +5991,7 @@ var HaBrokerRegistry = class {
|
|
|
5989
5991
|
} catch (err) {
|
|
5990
5992
|
return {
|
|
5991
5993
|
ok: false,
|
|
5992
|
-
error:
|
|
5994
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
5993
5995
|
};
|
|
5994
5996
|
}
|
|
5995
5997
|
const startedAt = Date.now();
|
|
@@ -6027,7 +6029,7 @@ var HaBrokerRegistry = class {
|
|
|
6027
6029
|
client?.stop();
|
|
6028
6030
|
resolve({
|
|
6029
6031
|
ok: false,
|
|
6030
|
-
error:
|
|
6032
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
6031
6033
|
});
|
|
6032
6034
|
}
|
|
6033
6035
|
}
|
|
@@ -6039,7 +6041,7 @@ var HaBrokerRegistry = class {
|
|
|
6039
6041
|
client?.stop();
|
|
6040
6042
|
resolve({
|
|
6041
6043
|
ok: false,
|
|
6042
|
-
error:
|
|
6044
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
6043
6045
|
});
|
|
6044
6046
|
});
|
|
6045
6047
|
});
|
|
@@ -6230,33 +6232,54 @@ var haBrokerSettingsSchema = { sections: [{
|
|
|
6230
6232
|
}
|
|
6231
6233
|
]
|
|
6232
6234
|
}] };
|
|
6235
|
+
/**
|
|
6236
|
+
* The calendars one instance imports (planning#416): a field of the instance record, offered from
|
|
6237
|
+
* that broker's own `calendar.*` entities, so it sits in the instance form beside the connection.
|
|
6238
|
+
*/
|
|
6239
|
+
function haCalendarsSection(options) {
|
|
6240
|
+
return {
|
|
6241
|
+
id: "ha-calendars-import",
|
|
6242
|
+
title: "Calendars to import",
|
|
6243
|
+
titleKey: "provider-homeassistant:globalSettings.s_ha-calendars-import.title",
|
|
6244
|
+
columns: 1,
|
|
6245
|
+
fields: [{
|
|
6246
|
+
type: "multiselect",
|
|
6247
|
+
key: "calendarIds",
|
|
6248
|
+
label: "Calendars",
|
|
6249
|
+
labelKey: "provider-homeassistant:globalSettings.s_ha-calendars-import.calendarIds.label",
|
|
6250
|
+
options: [...options],
|
|
6251
|
+
description: "Discovered from this Home Assistant instance. Select at least one to import; leave empty to import none.",
|
|
6252
|
+
descriptionKey: "provider-homeassistant:globalSettings.s_ha-calendars-import.calendarIds.description"
|
|
6253
|
+
}]
|
|
6254
|
+
};
|
|
6255
|
+
}
|
|
6233
6256
|
//#endregion
|
|
6234
6257
|
//#region src/ha-domain-mapping.ts
|
|
6235
6258
|
function mapHaEntityToCamStack(input) {
|
|
6236
6259
|
const { domain, deviceClass, attributes } = input;
|
|
6237
6260
|
switch (domain) {
|
|
6238
6261
|
case "switch": return {
|
|
6239
|
-
deviceType:
|
|
6240
|
-
role: deviceClass === "outlet" ?
|
|
6262
|
+
deviceType: require_legacy_integration_rows.DeviceType.Switch,
|
|
6263
|
+
role: deviceClass === "outlet" ? require_legacy_integration_rows.DeviceRole.Outlet : null,
|
|
6241
6264
|
capabilities: ["switch"]
|
|
6242
6265
|
};
|
|
6243
6266
|
case "input_boolean": return {
|
|
6244
|
-
deviceType:
|
|
6245
|
-
role:
|
|
6267
|
+
deviceType: require_legacy_integration_rows.DeviceType.Switch,
|
|
6268
|
+
role: require_legacy_integration_rows.DeviceRole.BinaryHelper,
|
|
6246
6269
|
capabilities: ["switch"]
|
|
6247
6270
|
};
|
|
6248
6271
|
case "remote": return {
|
|
6249
|
-
deviceType:
|
|
6272
|
+
deviceType: require_legacy_integration_rows.DeviceType.Switch,
|
|
6250
6273
|
role: null,
|
|
6251
6274
|
capabilities: ["switch"]
|
|
6252
6275
|
};
|
|
6253
6276
|
case "siren": return {
|
|
6254
|
-
deviceType:
|
|
6277
|
+
deviceType: require_legacy_integration_rows.DeviceType.Siren,
|
|
6255
6278
|
role: null,
|
|
6256
6279
|
capabilities: ["switch"]
|
|
6257
6280
|
};
|
|
6258
6281
|
case "update": return {
|
|
6259
|
-
deviceType:
|
|
6282
|
+
deviceType: require_legacy_integration_rows.DeviceType.Update,
|
|
6260
6283
|
role: null,
|
|
6261
6284
|
capabilities: ["update"]
|
|
6262
6285
|
};
|
|
@@ -6274,7 +6297,7 @@ function mapHaEntityToCamStack(input) {
|
|
|
6274
6297
|
case "alarm_control_panel": return mapAlarmPanel(attributes);
|
|
6275
6298
|
case "person":
|
|
6276
6299
|
case "device_tracker": return {
|
|
6277
|
-
deviceType:
|
|
6300
|
+
deviceType: require_legacy_integration_rows.DeviceType.Presence,
|
|
6278
6301
|
role: null,
|
|
6279
6302
|
capabilities: ["presence"]
|
|
6280
6303
|
};
|
|
@@ -6283,49 +6306,49 @@ function mapHaEntityToCamStack(input) {
|
|
|
6283
6306
|
case "camera": return mapImage(attributes);
|
|
6284
6307
|
case "number":
|
|
6285
6308
|
case "input_number": return {
|
|
6286
|
-
deviceType:
|
|
6287
|
-
role:
|
|
6309
|
+
deviceType: require_legacy_integration_rows.DeviceType.Control,
|
|
6310
|
+
role: require_legacy_integration_rows.DeviceRole.NumericControl,
|
|
6288
6311
|
capabilities: ["control"]
|
|
6289
6312
|
};
|
|
6290
6313
|
case "select":
|
|
6291
6314
|
case "input_select": return {
|
|
6292
|
-
deviceType:
|
|
6293
|
-
role:
|
|
6315
|
+
deviceType: require_legacy_integration_rows.DeviceType.Control,
|
|
6316
|
+
role: require_legacy_integration_rows.DeviceRole.SelectControl,
|
|
6294
6317
|
capabilities: ["control"]
|
|
6295
6318
|
};
|
|
6296
6319
|
case "text":
|
|
6297
6320
|
case "input_text": return {
|
|
6298
|
-
deviceType:
|
|
6299
|
-
role:
|
|
6321
|
+
deviceType: require_legacy_integration_rows.DeviceType.Control,
|
|
6322
|
+
role: require_legacy_integration_rows.DeviceRole.TextControl,
|
|
6300
6323
|
capabilities: ["control"]
|
|
6301
6324
|
};
|
|
6302
6325
|
case "input_datetime":
|
|
6303
6326
|
case "date":
|
|
6304
6327
|
case "time":
|
|
6305
6328
|
case "datetime": return {
|
|
6306
|
-
deviceType:
|
|
6307
|
-
role:
|
|
6329
|
+
deviceType: require_legacy_integration_rows.DeviceType.Control,
|
|
6330
|
+
role: require_legacy_integration_rows.DeviceRole.DateTimeControl,
|
|
6308
6331
|
capabilities: ["control"]
|
|
6309
6332
|
};
|
|
6310
6333
|
case "button":
|
|
6311
6334
|
case "input_button":
|
|
6312
6335
|
case "scene": return {
|
|
6313
|
-
deviceType:
|
|
6336
|
+
deviceType: require_legacy_integration_rows.DeviceType.Button,
|
|
6314
6337
|
role: null,
|
|
6315
6338
|
capabilities: ["button"]
|
|
6316
6339
|
};
|
|
6317
6340
|
case "event": return {
|
|
6318
|
-
deviceType:
|
|
6341
|
+
deviceType: require_legacy_integration_rows.DeviceType.EventEmitter,
|
|
6319
6342
|
role: null,
|
|
6320
6343
|
capabilities: ["event-emitter"]
|
|
6321
6344
|
};
|
|
6322
6345
|
case "script": return {
|
|
6323
|
-
deviceType:
|
|
6346
|
+
deviceType: require_legacy_integration_rows.DeviceType.Script,
|
|
6324
6347
|
role: null,
|
|
6325
6348
|
capabilities: ["script-runner"]
|
|
6326
6349
|
};
|
|
6327
6350
|
case "automation": return {
|
|
6328
|
-
deviceType:
|
|
6351
|
+
deviceType: require_legacy_integration_rows.DeviceType.Automation,
|
|
6329
6352
|
role: null,
|
|
6330
6353
|
capabilities: ["automation-control"]
|
|
6331
6354
|
};
|
|
@@ -6351,12 +6374,12 @@ function mapLight(attributes) {
|
|
|
6351
6374
|
const hasMired = modes.some((m) => m === "color_temp");
|
|
6352
6375
|
if (hasRgb || hasMired) {
|
|
6353
6376
|
capabilities.push("color");
|
|
6354
|
-
if (modes.includes("rgb") || modes.includes("rgbw") || modes.includes("rgbww") || modes.includes("xy")) features.push(
|
|
6355
|
-
if (modes.includes("hs")) features.push(
|
|
6356
|
-
if (hasMired) features.push(
|
|
6377
|
+
if (modes.includes("rgb") || modes.includes("rgbw") || modes.includes("rgbww") || modes.includes("xy")) features.push(require_legacy_integration_rows.DeviceFeature.LightColorRgb);
|
|
6378
|
+
if (modes.includes("hs")) features.push(require_legacy_integration_rows.DeviceFeature.LightColorHsv);
|
|
6379
|
+
if (hasMired) features.push(require_legacy_integration_rows.DeviceFeature.LightColorMired);
|
|
6357
6380
|
}
|
|
6358
6381
|
return {
|
|
6359
|
-
deviceType:
|
|
6382
|
+
deviceType: require_legacy_integration_rows.DeviceType.Light,
|
|
6360
6383
|
role: null,
|
|
6361
6384
|
capabilities,
|
|
6362
6385
|
features
|
|
@@ -6364,11 +6387,11 @@ function mapLight(attributes) {
|
|
|
6364
6387
|
}
|
|
6365
6388
|
function mapLock(attributes) {
|
|
6366
6389
|
const features = [];
|
|
6367
|
-
if (attributes["code_format"] !== void 0 && attributes["code_format"] !== null) features.push(
|
|
6390
|
+
if (attributes["code_format"] !== void 0 && attributes["code_format"] !== null) features.push(require_legacy_integration_rows.DeviceFeature.LockPinRequired);
|
|
6368
6391
|
const sf = readNumericAttr(attributes, "supported_features");
|
|
6369
|
-
if (sf !== null && (sf & 1) !== 0) features.push(
|
|
6392
|
+
if (sf !== null && (sf & 1) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.LockOpen);
|
|
6370
6393
|
return {
|
|
6371
|
-
deviceType:
|
|
6394
|
+
deviceType: require_legacy_integration_rows.DeviceType.Lock,
|
|
6372
6395
|
role: null,
|
|
6373
6396
|
capabilities: ["lock-control"],
|
|
6374
6397
|
features
|
|
@@ -6377,11 +6400,11 @@ function mapLock(attributes) {
|
|
|
6377
6400
|
function mapCover(attributes, deviceClass) {
|
|
6378
6401
|
const features = [];
|
|
6379
6402
|
const sf = readNumericAttr(attributes, "supported_features");
|
|
6380
|
-
if (sf !== null && (sf & 4) !== 0) features.push(
|
|
6381
|
-
if (sf !== null && (sf & 8) !== 0) features.push(
|
|
6382
|
-
if (sf !== null && (sf & 128) !== 0) features.push(
|
|
6403
|
+
if (sf !== null && (sf & 4) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.CoverPositionable);
|
|
6404
|
+
if (sf !== null && (sf & 8) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.CoverStoppable);
|
|
6405
|
+
if (sf !== null && (sf & 128) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.CoverTilt);
|
|
6383
6406
|
return {
|
|
6384
|
-
deviceType:
|
|
6407
|
+
deviceType: require_legacy_integration_rows.DeviceType.Cover,
|
|
6385
6408
|
role: coverRoleFor(deviceClass),
|
|
6386
6409
|
capabilities: ["cover"],
|
|
6387
6410
|
features
|
|
@@ -6391,23 +6414,23 @@ function mapCover(attributes, deviceClass) {
|
|
|
6391
6414
|
function coverRoleFor(deviceClass) {
|
|
6392
6415
|
switch (deviceClass) {
|
|
6393
6416
|
case "blind":
|
|
6394
|
-
case "shade": return
|
|
6395
|
-
case "shutter": return
|
|
6396
|
-
case "awning": return
|
|
6397
|
-
case "curtain": return
|
|
6398
|
-
case "garage": return
|
|
6399
|
-
case "gate": return
|
|
6400
|
-
case "door": return
|
|
6401
|
-
case "window": return
|
|
6417
|
+
case "shade": return require_legacy_integration_rows.DeviceRole.CoverBlind;
|
|
6418
|
+
case "shutter": return require_legacy_integration_rows.DeviceRole.CoverShutter;
|
|
6419
|
+
case "awning": return require_legacy_integration_rows.DeviceRole.CoverAwning;
|
|
6420
|
+
case "curtain": return require_legacy_integration_rows.DeviceRole.CoverCurtain;
|
|
6421
|
+
case "garage": return require_legacy_integration_rows.DeviceRole.CoverGarage;
|
|
6422
|
+
case "gate": return require_legacy_integration_rows.DeviceRole.CoverGate;
|
|
6423
|
+
case "door": return require_legacy_integration_rows.DeviceRole.CoverDoor;
|
|
6424
|
+
case "window": return require_legacy_integration_rows.DeviceRole.CoverWindow;
|
|
6402
6425
|
default: return null;
|
|
6403
6426
|
}
|
|
6404
6427
|
}
|
|
6405
6428
|
function mapValve(attributes, _deviceClass) {
|
|
6406
6429
|
const features = [];
|
|
6407
6430
|
const sf = readNumericAttr(attributes, "supported_features");
|
|
6408
|
-
if (sf !== null && (sf & 4) !== 0) features.push(
|
|
6431
|
+
if (sf !== null && (sf & 4) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.ValvePositionable);
|
|
6409
6432
|
return {
|
|
6410
|
-
deviceType:
|
|
6433
|
+
deviceType: require_legacy_integration_rows.DeviceType.Valve,
|
|
6411
6434
|
role: null,
|
|
6412
6435
|
capabilities: ["valve"],
|
|
6413
6436
|
features
|
|
@@ -6415,7 +6438,7 @@ function mapValve(attributes, _deviceClass) {
|
|
|
6415
6438
|
}
|
|
6416
6439
|
function mapHumidifier(_attributes, _deviceClass) {
|
|
6417
6440
|
return {
|
|
6418
|
-
deviceType:
|
|
6441
|
+
deviceType: require_legacy_integration_rows.DeviceType.Humidifier,
|
|
6419
6442
|
role: null,
|
|
6420
6443
|
capabilities: ["humidifier"],
|
|
6421
6444
|
features: []
|
|
@@ -6423,7 +6446,7 @@ function mapHumidifier(_attributes, _deviceClass) {
|
|
|
6423
6446
|
}
|
|
6424
6447
|
function mapWaterHeater(_attributes, _deviceClass) {
|
|
6425
6448
|
return {
|
|
6426
|
-
deviceType:
|
|
6449
|
+
deviceType: require_legacy_integration_rows.DeviceType.WaterHeater,
|
|
6427
6450
|
role: null,
|
|
6428
6451
|
capabilities: ["water-heater"],
|
|
6429
6452
|
features: []
|
|
@@ -6433,13 +6456,13 @@ function mapFan(attributes) {
|
|
|
6433
6456
|
const features = [];
|
|
6434
6457
|
const sf = readNumericAttr(attributes, "supported_features");
|
|
6435
6458
|
if (sf !== null) {
|
|
6436
|
-
if ((sf & 1) !== 0) features.push(
|
|
6437
|
-
if ((sf & 2) !== 0) features.push(
|
|
6438
|
-
if ((sf & 4) !== 0) features.push(
|
|
6439
|
-
if ((sf & 8) !== 0) features.push(
|
|
6459
|
+
if ((sf & 1) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.FanSpeed);
|
|
6460
|
+
if ((sf & 2) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.FanOscillating);
|
|
6461
|
+
if ((sf & 4) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.FanDirection);
|
|
6462
|
+
if ((sf & 8) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.FanPreset);
|
|
6440
6463
|
}
|
|
6441
6464
|
return {
|
|
6442
|
-
deviceType:
|
|
6465
|
+
deviceType: require_legacy_integration_rows.DeviceType.Fan,
|
|
6443
6466
|
role: null,
|
|
6444
6467
|
capabilities: ["switch", "fan-control"],
|
|
6445
6468
|
features
|
|
@@ -6447,7 +6470,7 @@ function mapFan(attributes) {
|
|
|
6447
6470
|
}
|
|
6448
6471
|
function mapVacuum(_attributes) {
|
|
6449
6472
|
return {
|
|
6450
|
-
deviceType:
|
|
6473
|
+
deviceType: require_legacy_integration_rows.DeviceType.Vacuum,
|
|
6451
6474
|
role: null,
|
|
6452
6475
|
capabilities: ["vacuum-control"],
|
|
6453
6476
|
features: []
|
|
@@ -6455,7 +6478,7 @@ function mapVacuum(_attributes) {
|
|
|
6455
6478
|
}
|
|
6456
6479
|
function mapLawnMower(_attributes) {
|
|
6457
6480
|
return {
|
|
6458
|
-
deviceType:
|
|
6481
|
+
deviceType: require_legacy_integration_rows.DeviceType.LawnMower,
|
|
6459
6482
|
role: null,
|
|
6460
6483
|
capabilities: ["lawn-mower-control"],
|
|
6461
6484
|
features: []
|
|
@@ -6465,13 +6488,13 @@ function mapClimate(attributes) {
|
|
|
6465
6488
|
const features = [];
|
|
6466
6489
|
const sf = readNumericAttr(attributes, "supported_features");
|
|
6467
6490
|
if (sf !== null) {
|
|
6468
|
-
if ((sf & 2) !== 0) features.push(
|
|
6469
|
-
if ((sf & 4) !== 0) features.push(
|
|
6470
|
-
if ((sf & 8) !== 0) features.push(
|
|
6471
|
-
if ((sf & 16) !== 0) features.push(
|
|
6491
|
+
if ((sf & 2) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.ClimateDualSetpoint);
|
|
6492
|
+
if ((sf & 4) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.ClimateHumidity);
|
|
6493
|
+
if ((sf & 8) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.ClimateFanMode);
|
|
6494
|
+
if ((sf & 16) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.ClimatePreset);
|
|
6472
6495
|
}
|
|
6473
6496
|
return {
|
|
6474
|
-
deviceType:
|
|
6497
|
+
deviceType: require_legacy_integration_rows.DeviceType.Thermostat,
|
|
6475
6498
|
role: null,
|
|
6476
6499
|
capabilities: ["climate-control"],
|
|
6477
6500
|
features
|
|
@@ -6481,21 +6504,21 @@ function mapMediaPlayer(attributes) {
|
|
|
6481
6504
|
const features = [];
|
|
6482
6505
|
const sf = readNumericAttr(attributes, "supported_features");
|
|
6483
6506
|
if (sf !== null) {
|
|
6484
|
-
if ((sf & 2) !== 0) features.push(
|
|
6485
|
-
if ((sf & 4) !== 0) features.push(
|
|
6486
|
-
if ((sf & 8) !== 0) features.push(
|
|
6487
|
-
if ((sf & 16) !== 0) features.push(
|
|
6488
|
-
if ((sf & 32) !== 0) features.push(
|
|
6489
|
-
if ((sf & 384) === 384) features.push(
|
|
6490
|
-
if ((sf & 1024) !== 0) features.push(
|
|
6491
|
-
if ((sf & 512) !== 0) features.push(
|
|
6492
|
-
if ((sf & 2048) !== 0) features.push(
|
|
6493
|
-
if ((sf & 4096) !== 0) features.push(
|
|
6494
|
-
if ((sf & 32768) !== 0) features.push(
|
|
6495
|
-
if ((sf & 262144) !== 0) features.push(
|
|
6507
|
+
if ((sf & 2) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.MediaPlayerSeek);
|
|
6508
|
+
if ((sf & 4) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.MediaPlayerVolume);
|
|
6509
|
+
if ((sf & 8) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.MediaPlayerMute);
|
|
6510
|
+
if ((sf & 16) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.MediaPlayerPrevious);
|
|
6511
|
+
if ((sf & 32) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.MediaPlayerNext);
|
|
6512
|
+
if ((sf & 384) === 384) features.push(require_legacy_integration_rows.DeviceFeature.MediaPlayerPower);
|
|
6513
|
+
if ((sf & 1024) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.MediaPlayerVolumeStep);
|
|
6514
|
+
if ((sf & 512) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.MediaPlayerPlayMedia);
|
|
6515
|
+
if ((sf & 2048) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.MediaPlayerSelectSource);
|
|
6516
|
+
if ((sf & 4096) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.MediaPlayerStop);
|
|
6517
|
+
if ((sf & 32768) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.MediaPlayerShuffle);
|
|
6518
|
+
if ((sf & 262144) !== 0) features.push(require_legacy_integration_rows.DeviceFeature.MediaPlayerRepeat);
|
|
6496
6519
|
}
|
|
6497
6520
|
return {
|
|
6498
|
-
deviceType:
|
|
6521
|
+
deviceType: require_legacy_integration_rows.DeviceType.MediaPlayer,
|
|
6499
6522
|
role: null,
|
|
6500
6523
|
capabilities: ["media-player"],
|
|
6501
6524
|
features
|
|
@@ -6503,9 +6526,9 @@ function mapMediaPlayer(attributes) {
|
|
|
6503
6526
|
}
|
|
6504
6527
|
function mapAlarmPanel(attributes) {
|
|
6505
6528
|
const features = [];
|
|
6506
|
-
if (attributes["code_format"] !== void 0 && attributes["code_format"] !== null) features.push(
|
|
6529
|
+
if (attributes["code_format"] !== void 0 && attributes["code_format"] !== null) features.push(require_legacy_integration_rows.DeviceFeature.AlarmPinRequired);
|
|
6507
6530
|
return {
|
|
6508
|
-
deviceType:
|
|
6531
|
+
deviceType: require_legacy_integration_rows.DeviceType.AlarmPanel,
|
|
6509
6532
|
role: null,
|
|
6510
6533
|
capabilities: ["alarm-panel"],
|
|
6511
6534
|
features
|
|
@@ -6513,21 +6536,21 @@ function mapAlarmPanel(attributes) {
|
|
|
6513
6536
|
}
|
|
6514
6537
|
function mapNotifier(_attributes) {
|
|
6515
6538
|
return {
|
|
6516
|
-
deviceType:
|
|
6517
|
-
role:
|
|
6539
|
+
deviceType: require_legacy_integration_rows.DeviceType.Notifier,
|
|
6540
|
+
role: require_legacy_integration_rows.DeviceRole.GenericNotifier,
|
|
6518
6541
|
capabilities: ["notifier"]
|
|
6519
6542
|
};
|
|
6520
6543
|
}
|
|
6521
6544
|
function mapWeather(_attributes) {
|
|
6522
6545
|
return {
|
|
6523
|
-
deviceType:
|
|
6546
|
+
deviceType: require_legacy_integration_rows.DeviceType.Weather,
|
|
6524
6547
|
role: null,
|
|
6525
6548
|
capabilities: ["weather"]
|
|
6526
6549
|
};
|
|
6527
6550
|
}
|
|
6528
6551
|
function mapImage(_attributes) {
|
|
6529
6552
|
return {
|
|
6530
|
-
deviceType:
|
|
6553
|
+
deviceType: require_legacy_integration_rows.DeviceType.Image,
|
|
6531
6554
|
role: null,
|
|
6532
6555
|
capabilities: ["image"]
|
|
6533
6556
|
};
|
|
@@ -6541,60 +6564,60 @@ function isTemperatureUnit(unit) {
|
|
|
6541
6564
|
function mapNumericSensor(deviceClass, _attributes) {
|
|
6542
6565
|
switch (deviceClass) {
|
|
6543
6566
|
case "temperature": return {
|
|
6544
|
-
deviceType:
|
|
6545
|
-
role:
|
|
6567
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6568
|
+
role: require_legacy_integration_rows.DeviceRole.TemperatureSensor,
|
|
6546
6569
|
capabilities: ["temperature-sensor"]
|
|
6547
6570
|
};
|
|
6548
6571
|
case "humidity": return {
|
|
6549
|
-
deviceType:
|
|
6550
|
-
role:
|
|
6572
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6573
|
+
role: require_legacy_integration_rows.DeviceRole.HumiditySensor,
|
|
6551
6574
|
capabilities: ["humidity-sensor"]
|
|
6552
6575
|
};
|
|
6553
6576
|
case "illuminance": return {
|
|
6554
|
-
deviceType:
|
|
6555
|
-
role:
|
|
6577
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6578
|
+
role: require_legacy_integration_rows.DeviceRole.AmbientLightSensor,
|
|
6556
6579
|
capabilities: ["ambient-light-sensor"]
|
|
6557
6580
|
};
|
|
6558
6581
|
case "pressure":
|
|
6559
6582
|
case "atmospheric_pressure": return {
|
|
6560
|
-
deviceType:
|
|
6561
|
-
role:
|
|
6583
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6584
|
+
role: require_legacy_integration_rows.DeviceRole.PressureSensor,
|
|
6562
6585
|
capabilities: ["pressure-sensor"]
|
|
6563
6586
|
};
|
|
6564
6587
|
case "wind_speed": return {
|
|
6565
|
-
deviceType:
|
|
6566
|
-
role:
|
|
6588
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6589
|
+
role: require_legacy_integration_rows.DeviceRole.WindSensor,
|
|
6567
6590
|
capabilities: ["numeric-sensor"]
|
|
6568
6591
|
};
|
|
6569
6592
|
case "precipitation":
|
|
6570
6593
|
case "precipitation_intensity": return {
|
|
6571
|
-
deviceType:
|
|
6572
|
-
role:
|
|
6594
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6595
|
+
role: require_legacy_integration_rows.DeviceRole.RainSensor,
|
|
6573
6596
|
capabilities: ["numeric-sensor"]
|
|
6574
6597
|
};
|
|
6575
6598
|
case "irradiance": return {
|
|
6576
|
-
deviceType:
|
|
6577
|
-
role:
|
|
6599
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6600
|
+
role: require_legacy_integration_rows.DeviceRole.SolarRadiationSensor,
|
|
6578
6601
|
capabilities: ["numeric-sensor"]
|
|
6579
6602
|
};
|
|
6580
6603
|
case "power": return {
|
|
6581
|
-
deviceType:
|
|
6582
|
-
role:
|
|
6604
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6605
|
+
role: require_legacy_integration_rows.DeviceRole.PowerSensor,
|
|
6583
6606
|
capabilities: ["power-meter"]
|
|
6584
6607
|
};
|
|
6585
6608
|
case "energy": return {
|
|
6586
|
-
deviceType:
|
|
6587
|
-
role:
|
|
6609
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6610
|
+
role: require_legacy_integration_rows.DeviceRole.EnergySensor,
|
|
6588
6611
|
capabilities: ["power-meter"]
|
|
6589
6612
|
};
|
|
6590
6613
|
case "voltage": return {
|
|
6591
|
-
deviceType:
|
|
6592
|
-
role:
|
|
6614
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6615
|
+
role: require_legacy_integration_rows.DeviceRole.VoltageSensor,
|
|
6593
6616
|
capabilities: ["power-meter"]
|
|
6594
6617
|
};
|
|
6595
6618
|
case "current": return {
|
|
6596
|
-
deviceType:
|
|
6597
|
-
role:
|
|
6619
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6620
|
+
role: require_legacy_integration_rows.DeviceRole.CurrentSensor,
|
|
6598
6621
|
capabilities: ["power-meter"]
|
|
6599
6622
|
};
|
|
6600
6623
|
case "pm1":
|
|
@@ -6607,46 +6630,46 @@ function mapNumericSensor(deviceClass, _attributes) {
|
|
|
6607
6630
|
case "sulphur_dioxide":
|
|
6608
6631
|
case "volatile_organic_compounds":
|
|
6609
6632
|
case "aqi": return {
|
|
6610
|
-
deviceType:
|
|
6611
|
-
role:
|
|
6633
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6634
|
+
role: require_legacy_integration_rows.DeviceRole.AirQualitySensor,
|
|
6612
6635
|
capabilities: ["air-quality-sensor"]
|
|
6613
6636
|
};
|
|
6614
6637
|
case "battery": return {
|
|
6615
|
-
deviceType:
|
|
6616
|
-
role:
|
|
6638
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6639
|
+
role: require_legacy_integration_rows.DeviceRole.BatterySensor,
|
|
6617
6640
|
capabilities: ["numeric-sensor"]
|
|
6618
6641
|
};
|
|
6619
6642
|
case "enum": return {
|
|
6620
|
-
deviceType:
|
|
6621
|
-
role:
|
|
6643
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6644
|
+
role: require_legacy_integration_rows.DeviceRole.EnumSensor,
|
|
6622
6645
|
capabilities: ["enum-sensor"]
|
|
6623
6646
|
};
|
|
6624
6647
|
case "timestamp": return {
|
|
6625
|
-
deviceType:
|
|
6626
|
-
role:
|
|
6648
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6649
|
+
role: require_legacy_integration_rows.DeviceRole.DateTimeSensor,
|
|
6627
6650
|
capabilities: ["enum-sensor"],
|
|
6628
6651
|
dateTimeFormat: "datetime"
|
|
6629
6652
|
};
|
|
6630
6653
|
case "date": return {
|
|
6631
|
-
deviceType:
|
|
6632
|
-
role:
|
|
6654
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6655
|
+
role: require_legacy_integration_rows.DeviceRole.DateTimeSensor,
|
|
6633
6656
|
capabilities: ["enum-sensor"],
|
|
6634
6657
|
dateTimeFormat: "date"
|
|
6635
6658
|
};
|
|
6636
6659
|
case null:
|
|
6637
6660
|
if (isTemperatureUnit(_attributes["unit_of_measurement"])) return {
|
|
6638
|
-
deviceType:
|
|
6639
|
-
role:
|
|
6661
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6662
|
+
role: require_legacy_integration_rows.DeviceRole.TemperatureSensor,
|
|
6640
6663
|
capabilities: ["temperature-sensor"]
|
|
6641
6664
|
};
|
|
6642
6665
|
return {
|
|
6643
|
-
deviceType:
|
|
6644
|
-
role:
|
|
6666
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6667
|
+
role: require_legacy_integration_rows.DeviceRole.EnumSensor,
|
|
6645
6668
|
capabilities: ["enum-sensor"]
|
|
6646
6669
|
};
|
|
6647
6670
|
default: return {
|
|
6648
|
-
deviceType:
|
|
6649
|
-
role:
|
|
6671
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6672
|
+
role: require_legacy_integration_rows.DeviceRole.NumericSensor,
|
|
6650
6673
|
capabilities: ["numeric-sensor"]
|
|
6651
6674
|
};
|
|
6652
6675
|
}
|
|
@@ -6657,67 +6680,67 @@ function mapBinarySensor(deviceClass) {
|
|
|
6657
6680
|
case "occupancy":
|
|
6658
6681
|
case "presence":
|
|
6659
6682
|
case "moving": return {
|
|
6660
|
-
deviceType:
|
|
6661
|
-
role:
|
|
6683
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6684
|
+
role: require_legacy_integration_rows.DeviceRole.MotionSensor,
|
|
6662
6685
|
capabilities: ["motion"]
|
|
6663
6686
|
};
|
|
6664
6687
|
case "door":
|
|
6665
6688
|
case "window":
|
|
6666
6689
|
case "garage_door":
|
|
6667
6690
|
case "opening": return {
|
|
6668
|
-
deviceType:
|
|
6669
|
-
role:
|
|
6691
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6692
|
+
role: require_legacy_integration_rows.DeviceRole.ContactSensor,
|
|
6670
6693
|
capabilities: ["contact"]
|
|
6671
6694
|
};
|
|
6672
6695
|
case "moisture": return {
|
|
6673
|
-
deviceType:
|
|
6674
|
-
role:
|
|
6696
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6697
|
+
role: require_legacy_integration_rows.DeviceRole.LeakSensor,
|
|
6675
6698
|
capabilities: ["flood"]
|
|
6676
6699
|
};
|
|
6677
6700
|
case "smoke": return {
|
|
6678
|
-
deviceType:
|
|
6679
|
-
role:
|
|
6701
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6702
|
+
role: require_legacy_integration_rows.DeviceRole.SmokeSensor,
|
|
6680
6703
|
capabilities: ["smoke"]
|
|
6681
6704
|
};
|
|
6682
6705
|
case "carbon_monoxide": return {
|
|
6683
|
-
deviceType:
|
|
6684
|
-
role:
|
|
6706
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6707
|
+
role: require_legacy_integration_rows.DeviceRole.COSensor,
|
|
6685
6708
|
capabilities: ["carbon-monoxide"]
|
|
6686
6709
|
};
|
|
6687
6710
|
case "gas": return {
|
|
6688
|
-
deviceType:
|
|
6689
|
-
role:
|
|
6711
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6712
|
+
role: require_legacy_integration_rows.DeviceRole.GasSensor,
|
|
6690
6713
|
capabilities: ["gas"]
|
|
6691
6714
|
};
|
|
6692
6715
|
case "tamper":
|
|
6693
6716
|
case "safety": return {
|
|
6694
|
-
deviceType:
|
|
6695
|
-
role:
|
|
6717
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6718
|
+
role: require_legacy_integration_rows.DeviceRole.TamperSensor,
|
|
6696
6719
|
capabilities: ["tamper"]
|
|
6697
6720
|
};
|
|
6698
6721
|
case "vibration": return {
|
|
6699
|
-
deviceType:
|
|
6700
|
-
role:
|
|
6722
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6723
|
+
role: require_legacy_integration_rows.DeviceRole.VibrationSensor,
|
|
6701
6724
|
capabilities: ["vibration"]
|
|
6702
6725
|
};
|
|
6703
6726
|
case "connectivity": return {
|
|
6704
|
-
deviceType:
|
|
6705
|
-
role:
|
|
6727
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6728
|
+
role: require_legacy_integration_rows.DeviceRole.ConnectivitySensor,
|
|
6706
6729
|
capabilities: ["connectivity"]
|
|
6707
6730
|
};
|
|
6708
6731
|
case "sound": return {
|
|
6709
|
-
deviceType:
|
|
6710
|
-
role:
|
|
6732
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6733
|
+
role: require_legacy_integration_rows.DeviceRole.SoundSensor,
|
|
6711
6734
|
capabilities: ["binary"]
|
|
6712
6735
|
};
|
|
6713
6736
|
case "battery": return {
|
|
6714
|
-
deviceType:
|
|
6715
|
-
role:
|
|
6737
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6738
|
+
role: require_legacy_integration_rows.DeviceRole.BatterySensor,
|
|
6716
6739
|
capabilities: ["binary"]
|
|
6717
6740
|
};
|
|
6718
6741
|
default: return {
|
|
6719
|
-
deviceType:
|
|
6720
|
-
role:
|
|
6742
|
+
deviceType: require_legacy_integration_rows.DeviceType.Sensor,
|
|
6743
|
+
role: require_legacy_integration_rows.DeviceRole.BinarySensor,
|
|
6721
6744
|
capabilities: ["binary"]
|
|
6722
6745
|
};
|
|
6723
6746
|
}
|
|
@@ -6740,40 +6763,40 @@ function readNumericAttr(attributes, key) {
|
|
|
6740
6763
|
* Sensor; an HA-tracked light with motion sensor becomes Light).
|
|
6741
6764
|
*/
|
|
6742
6765
|
var PARENT_TYPE_PRIORITY = [
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
6770
|
-
|
|
6766
|
+
require_legacy_integration_rows.DeviceType.MediaPlayer,
|
|
6767
|
+
require_legacy_integration_rows.DeviceType.AlarmPanel,
|
|
6768
|
+
require_legacy_integration_rows.DeviceType.Thermostat,
|
|
6769
|
+
require_legacy_integration_rows.DeviceType.Climate,
|
|
6770
|
+
require_legacy_integration_rows.DeviceType.Humidifier,
|
|
6771
|
+
require_legacy_integration_rows.DeviceType.WaterHeater,
|
|
6772
|
+
require_legacy_integration_rows.DeviceType.Lock,
|
|
6773
|
+
require_legacy_integration_rows.DeviceType.Cover,
|
|
6774
|
+
require_legacy_integration_rows.DeviceType.Valve,
|
|
6775
|
+
require_legacy_integration_rows.DeviceType.Fan,
|
|
6776
|
+
require_legacy_integration_rows.DeviceType.Vacuum,
|
|
6777
|
+
require_legacy_integration_rows.DeviceType.LawnMower,
|
|
6778
|
+
require_legacy_integration_rows.DeviceType.Washer,
|
|
6779
|
+
require_legacy_integration_rows.DeviceType.Dryer,
|
|
6780
|
+
require_legacy_integration_rows.DeviceType.Dishwasher,
|
|
6781
|
+
require_legacy_integration_rows.DeviceType.Light,
|
|
6782
|
+
require_legacy_integration_rows.DeviceType.Switch,
|
|
6783
|
+
require_legacy_integration_rows.DeviceType.Siren,
|
|
6784
|
+
require_legacy_integration_rows.DeviceType.Button,
|
|
6785
|
+
require_legacy_integration_rows.DeviceType.Control,
|
|
6786
|
+
require_legacy_integration_rows.DeviceType.Notifier,
|
|
6787
|
+
require_legacy_integration_rows.DeviceType.Script,
|
|
6788
|
+
require_legacy_integration_rows.DeviceType.Automation,
|
|
6789
|
+
require_legacy_integration_rows.DeviceType.Update,
|
|
6790
|
+
require_legacy_integration_rows.DeviceType.Presence,
|
|
6791
|
+
require_legacy_integration_rows.DeviceType.Weather,
|
|
6792
|
+
require_legacy_integration_rows.DeviceType.Image,
|
|
6793
|
+
require_legacy_integration_rows.DeviceType.Sensor
|
|
6771
6794
|
];
|
|
6772
6795
|
function inferParentDeviceType(mappings) {
|
|
6773
6796
|
const set = /* @__PURE__ */ new Set();
|
|
6774
6797
|
for (const m of mappings) if (m) set.add(m.deviceType);
|
|
6775
6798
|
for (const dt of PARENT_TYPE_PRIORITY) if (set.has(dt)) return dt;
|
|
6776
|
-
return
|
|
6799
|
+
return require_legacy_integration_rows.DeviceType.Generic;
|
|
6777
6800
|
}
|
|
6778
6801
|
//#endregion
|
|
6779
6802
|
//#region src/ha-candidate-mapper.ts
|
|
@@ -6795,7 +6818,7 @@ function haDeviceToCandidate(dev) {
|
|
|
6795
6818
|
return {
|
|
6796
6819
|
childNativeId: e.entityId,
|
|
6797
6820
|
name: e.name,
|
|
6798
|
-
type: e.mappedTo?.deviceType ??
|
|
6821
|
+
type: e.mappedTo?.deviceType ?? require_legacy_integration_rows.DeviceType.Generic,
|
|
6799
6822
|
status: entityStatus$1(e.state),
|
|
6800
6823
|
metadata: e.area !== null ? { externalLocation: e.area } : {},
|
|
6801
6824
|
alreadyAdopted: e.alreadyAdopted,
|
|
@@ -6942,7 +6965,7 @@ function buildDiscoveryCandidates(input) {
|
|
|
6942
6965
|
};
|
|
6943
6966
|
candidates.push({
|
|
6944
6967
|
stableId,
|
|
6945
|
-
type:
|
|
6968
|
+
type: require_legacy_integration_rows.DeviceType.Container,
|
|
6946
6969
|
suggestedName,
|
|
6947
6970
|
prefilledConfig,
|
|
6948
6971
|
sourceInfo
|
|
@@ -6970,52 +6993,52 @@ function buildDiscoveryCandidates(input) {
|
|
|
6970
6993
|
* shown as a Devices-tab candidate.
|
|
6971
6994
|
*/
|
|
6972
6995
|
var HA_ORPHAN_ENTITIES_DEVICE_ID = "__ha_orphan_entities__";
|
|
6973
|
-
var HaEntityMappingSchema =
|
|
6996
|
+
var HaEntityMappingSchema = require_legacy_integration_rows.object({
|
|
6974
6997
|
/** CamStack DeviceType for the accessory child. */
|
|
6975
|
-
deviceType:
|
|
6998
|
+
deviceType: require_legacy_integration_rows._enum(require_legacy_integration_rows.DeviceType),
|
|
6976
6999
|
/** Optional CamStack DeviceRole sub-role (e.g. `ContactSensor` for
|
|
6977
7000
|
* a binary_sensor with `device_class: door`). */
|
|
6978
|
-
role:
|
|
7001
|
+
role: require_legacy_integration_rows._enum(require_legacy_integration_rows.DeviceRole).nullable(),
|
|
6979
7002
|
/** Capability names the accessory child will register
|
|
6980
7003
|
* (`switch` / `temperature-sensor` / …). UI may render the cap
|
|
6981
7004
|
* badges to help the operator decide what to hide. */
|
|
6982
|
-
capabilities:
|
|
7005
|
+
capabilities: require_legacy_integration_rows.array(require_legacy_integration_rows.string()).readonly(),
|
|
6983
7006
|
/** Mapping-derived DeviceFeature flags (e.g. `lock-open`). Persisted onto
|
|
6984
7007
|
* the child's `device.features` so the UI gates feature affordances. */
|
|
6985
|
-
features:
|
|
7008
|
+
features: require_legacy_integration_rows.array(require_legacy_integration_rows.string()).readonly().optional(),
|
|
6986
7009
|
/** Locale-render shape for a `DateTimeSensor`-role enum sensor
|
|
6987
7010
|
* (`device_class=timestamp` → `'datetime'`, `date` → `'date'`). Threaded
|
|
6988
7011
|
* onto the child config so the enum-sensor device seeds it into the cap
|
|
6989
7012
|
* slice. Absent for every non-DateTimeSensor mapping. */
|
|
6990
|
-
dateTimeFormat:
|
|
7013
|
+
dateTimeFormat: require_legacy_integration_rows.EnumSensorDateTimeFormatSchema.optional()
|
|
6991
7014
|
}).nullable();
|
|
6992
|
-
var HaDiscoveredEntitySchema =
|
|
7015
|
+
var HaDiscoveredEntitySchema = require_legacy_integration_rows.object({
|
|
6993
7016
|
/** Fully-qualified HA entity id (`switch.kitchen`). */
|
|
6994
|
-
entityId:
|
|
7017
|
+
entityId: require_legacy_integration_rows.string(),
|
|
6995
7018
|
/** HA domain — first segment of entity_id (`switch` / `light` /
|
|
6996
7019
|
* `sensor` / `binary_sensor` / `cover` / …). */
|
|
6997
|
-
domain:
|
|
7020
|
+
domain: require_legacy_integration_rows.string(),
|
|
6998
7021
|
/** Operator-visible friendly name (HA `friendly_name` attribute or
|
|
6999
7022
|
* the entity_id when missing). */
|
|
7000
|
-
name:
|
|
7023
|
+
name: require_legacy_integration_rows.string(),
|
|
7001
7024
|
/** Current state value (e.g. `'on'`, `'21.5'`, `'open'`). */
|
|
7002
|
-
state:
|
|
7025
|
+
state: require_legacy_integration_rows.string(),
|
|
7003
7026
|
/** HA `device_class` attribute when present — drives the role +
|
|
7004
7027
|
* cap mapping for sensors / binary_sensors / covers. */
|
|
7005
|
-
deviceClass:
|
|
7028
|
+
deviceClass: require_legacy_integration_rows.string().nullable(),
|
|
7006
7029
|
/** HA `unit_of_measurement` attribute when present. */
|
|
7007
|
-
unitOfMeasurement:
|
|
7030
|
+
unitOfMeasurement: require_legacy_integration_rows.string().nullable(),
|
|
7008
7031
|
/** Area name for this entity — the entity's own HA area if set, else its
|
|
7009
7032
|
* parent device's area. Null when neither is assigned. */
|
|
7010
|
-
area:
|
|
7033
|
+
area: require_legacy_integration_rows.string().nullable().default(null),
|
|
7011
7034
|
/** HA `options` attribute — present on `select` / `input_select` entities.
|
|
7012
7035
|
* Captured at discovery so the adopt handler can persist them alongside
|
|
7013
7036
|
* other entity config fields. Absent on non-select entities. */
|
|
7014
|
-
options:
|
|
7037
|
+
options: require_legacy_integration_rows.array(require_legacy_integration_rows.string()).nullable().default(null),
|
|
7015
7038
|
/** HA `entity_category` — `config` / `diagnostic` / null (a normal control).
|
|
7016
7039
|
* Drives the accordion section the adopted child renders in. Null/absent for
|
|
7017
7040
|
* the common control case. */
|
|
7018
|
-
entityCategory:
|
|
7041
|
+
entityCategory: require_legacy_integration_rows._enum(["config", "diagnostic"]).nullable().default(null),
|
|
7019
7042
|
/** Pre-computed CamStack mapping. `null` when the entity's domain
|
|
7020
7043
|
* has no supported mapping (the operator may still adopt the
|
|
7021
7044
|
* parent — the entity will be skipped or surfaced as a fallback). */
|
|
@@ -7023,48 +7046,48 @@ var HaDiscoveredEntitySchema = require_ha_instance_settings.object({
|
|
|
7023
7046
|
/** When `true`, the entity was already materialised as a CamStack
|
|
7024
7047
|
* accessory child under a prior adoption — surfaced so the UI can
|
|
7025
7048
|
* highlight existing wiring. */
|
|
7026
|
-
alreadyAdopted:
|
|
7049
|
+
alreadyAdopted: require_legacy_integration_rows.boolean(),
|
|
7027
7050
|
/** When `alreadyAdopted === true`, the kernel-assigned accessory
|
|
7028
7051
|
* child id. */
|
|
7029
|
-
adoptedCamDeviceId:
|
|
7052
|
+
adoptedCamDeviceId: require_legacy_integration_rows.number().int().nonnegative().nullable()
|
|
7030
7053
|
});
|
|
7031
|
-
|
|
7054
|
+
require_legacy_integration_rows.object({
|
|
7032
7055
|
/** Stable HA `device_registry` id — survives renames + restarts. */
|
|
7033
|
-
haDeviceId:
|
|
7056
|
+
haDeviceId: require_legacy_integration_rows.string(),
|
|
7034
7057
|
/** Operator-visible name (HA device `name` or first entity's
|
|
7035
7058
|
* friendly_name when device has none). */
|
|
7036
|
-
name:
|
|
7059
|
+
name: require_legacy_integration_rows.string(),
|
|
7037
7060
|
/** Area name from HA `area_registry` join. Null when unassigned. */
|
|
7038
|
-
area:
|
|
7039
|
-
manufacturer:
|
|
7040
|
-
model:
|
|
7041
|
-
swVersion:
|
|
7061
|
+
area: require_legacy_integration_rows.string().nullable(),
|
|
7062
|
+
manufacturer: require_legacy_integration_rows.string().nullable(),
|
|
7063
|
+
model: require_legacy_integration_rows.string().nullable(),
|
|
7064
|
+
swVersion: require_legacy_integration_rows.string().nullable(),
|
|
7042
7065
|
/** Dominant integration / platform domain for this device, derived from its
|
|
7043
7066
|
* entities' HA `entity_registry.platform` (e.g. `dreame_vacuum`). Generic /
|
|
7044
7067
|
* helper platforms (`unifi` / `hacs` / `hassio`) are excluded when a real
|
|
7045
7068
|
* platform is available. Null when the device has no entities. */
|
|
7046
|
-
integration:
|
|
7069
|
+
integration: require_legacy_integration_rows.string().nullable().default(null),
|
|
7047
7070
|
/** Convenience field — count of `entities[]`. */
|
|
7048
|
-
entityCount:
|
|
7071
|
+
entityCount: require_legacy_integration_rows.number().int().nonnegative(),
|
|
7049
7072
|
/** Every entity HA's `entity_registry` links to this device. The
|
|
7050
7073
|
* list survives row collapse — full devices are returned so
|
|
7051
7074
|
* accordion expansion is a no-roundtrip render. */
|
|
7052
|
-
entities:
|
|
7075
|
+
entities: require_legacy_integration_rows.array(HaDiscoveredEntitySchema).readonly(),
|
|
7053
7076
|
/** Whether this HA device has an active CamStack adoption. */
|
|
7054
|
-
alreadyAdopted:
|
|
7077
|
+
alreadyAdopted: require_legacy_integration_rows.boolean(),
|
|
7055
7078
|
/** When `alreadyAdopted === true`, the kernel-assigned parent id. */
|
|
7056
|
-
adoptedCamDeviceId:
|
|
7079
|
+
adoptedCamDeviceId: require_legacy_integration_rows.number().int().nonnegative().nullable()
|
|
7057
7080
|
});
|
|
7058
|
-
|
|
7081
|
+
require_legacy_integration_rows.object({
|
|
7059
7082
|
/** Last refresh timestamp (ms epoch) — null when never refreshed. */
|
|
7060
|
-
lastDiscoveryAt:
|
|
7083
|
+
lastDiscoveryAt: require_legacy_integration_rows.number().int().nonnegative().nullable(),
|
|
7061
7084
|
/** Count of HA devices in the discovery cache (across all brokers). */
|
|
7062
|
-
deviceCount:
|
|
7085
|
+
deviceCount: require_legacy_integration_rows.number().int().nonnegative(),
|
|
7063
7086
|
/** Count of HA devices currently materialised as CamStack parent
|
|
7064
7087
|
* devices. */
|
|
7065
|
-
adoptedCount:
|
|
7088
|
+
adoptedCount: require_legacy_integration_rows.number().int().nonnegative(),
|
|
7066
7089
|
/** Last error message from a refresh attempt. */
|
|
7067
|
-
lastError:
|
|
7090
|
+
lastError: require_legacy_integration_rows.string().nullable()
|
|
7068
7091
|
});
|
|
7069
7092
|
//#endregion
|
|
7070
7093
|
//#region src/ha-integration-domain.ts
|
|
@@ -7203,7 +7226,7 @@ function negotiateEncoding(acceptEncoding) {
|
|
|
7203
7226
|
}
|
|
7204
7227
|
/** Build the `addon-routes` provider that serves the bundled Home Assistant icon. */
|
|
7205
7228
|
function createHaIconRouteProvider() {
|
|
7206
|
-
return
|
|
7229
|
+
return require_legacy_integration_rows.buildAddonRouteProvider(HA_ROUTE_ID, [{
|
|
7207
7230
|
method: "GET",
|
|
7208
7231
|
path: `/icons/${HA_ICON_KIND}`,
|
|
7209
7232
|
access: "public",
|
|
@@ -7225,15 +7248,16 @@ function createHaIconRouteProvider() {
|
|
|
7225
7248
|
* with the two tokens at the top level where the records door keeps them in the keychain.
|
|
7226
7249
|
*/
|
|
7227
7250
|
var HA_BROKERS_KIND = "brokers";
|
|
7228
|
-
var HaBrokerBodySchema =
|
|
7251
|
+
var HaBrokerBodySchema = require_legacy_integration_rows.entryBody({
|
|
7229
7252
|
authKind: HaBrokerEntrySchema.shape.authKind,
|
|
7230
7253
|
baseUrl: HaBrokerEntrySchema.shape.baseUrl,
|
|
7231
7254
|
accessToken: HaBrokerEntrySchema.shape.accessToken,
|
|
7232
7255
|
supervisorToken: HaBrokerEntrySchema.shape.supervisorToken,
|
|
7233
7256
|
integrationId: HaBrokerEntrySchema.shape.integrationId,
|
|
7234
|
-
enabled: HaBrokerEntrySchema.shape.enabled
|
|
7257
|
+
enabled: HaBrokerEntrySchema.shape.enabled,
|
|
7258
|
+
calendarIds: HaBrokerEntrySchema.shape.calendarIds
|
|
7235
7259
|
});
|
|
7236
|
-
var haBrokersEntryKind =
|
|
7260
|
+
var haBrokersEntryKind = require_legacy_integration_rows.defineEntryKind(HA_BROKERS_KIND, {
|
|
7237
7261
|
title: "Home Assistant brokers",
|
|
7238
7262
|
schema: HaBrokerBodySchema,
|
|
7239
7263
|
writeTrigger: "an operator adds, edits or removes a Home Assistant broker connection",
|
|
@@ -7248,8 +7272,8 @@ var haBrokersEntryKind = require_ha_instance_settings.defineEntryKind(HA_BROKERS
|
|
|
7248
7272
|
* credential — delivery reuses the broker WebSocket connection (the token
|
|
7249
7273
|
* lives in the broker config, not in the target).
|
|
7250
7274
|
*/
|
|
7251
|
-
var HaTargetBodySchema =
|
|
7252
|
-
var haRecordKinds =
|
|
7275
|
+
var HaTargetBodySchema = require_legacy_integration_rows.TargetSchema.omit({ id: true });
|
|
7276
|
+
var haRecordKinds = require_legacy_integration_rows.defineRecordKinds({
|
|
7253
7277
|
/**
|
|
7254
7278
|
* One row per configured Home Assistant push target. Operator-managed via the
|
|
7255
7279
|
* notification-output cap CRUD; no TTL.
|
|
@@ -7315,7 +7339,7 @@ function haConfigSchema() {
|
|
|
7315
7339
|
labelKey: "provider-homeassistant:haConfig.s_connection.brokerId.label",
|
|
7316
7340
|
description: "The Home Assistant connection the notification goes through.",
|
|
7317
7341
|
descriptionKey: "provider-homeassistant:haConfig.s_connection.brokerId.description",
|
|
7318
|
-
brokerKind:
|
|
7342
|
+
brokerKind: require_legacy_integration_rows.HA_BROKER_KIND
|
|
7319
7343
|
}, {
|
|
7320
7344
|
type: "select",
|
|
7321
7345
|
key: "service",
|
|
@@ -7555,7 +7579,7 @@ var HaTargetStore = class HaTargetStore {
|
|
|
7555
7579
|
const page = await this.kind.query({ limit: 1e3 });
|
|
7556
7580
|
const out = [];
|
|
7557
7581
|
for (const record of page.records) {
|
|
7558
|
-
const parsed =
|
|
7582
|
+
const parsed = require_legacy_integration_rows.TargetSchema.safeParse({
|
|
7559
7583
|
id: record.id,
|
|
7560
7584
|
...record.data
|
|
7561
7585
|
});
|
|
@@ -7566,7 +7590,7 @@ var HaTargetStore = class HaTargetStore {
|
|
|
7566
7590
|
async getById(id) {
|
|
7567
7591
|
const row = await this.kind.get(id);
|
|
7568
7592
|
if (row === null) return null;
|
|
7569
|
-
const parsed =
|
|
7593
|
+
const parsed = require_legacy_integration_rows.TargetSchema.safeParse({
|
|
7570
7594
|
id: row.id,
|
|
7571
7595
|
...row.data
|
|
7572
7596
|
});
|
|
@@ -7627,12 +7651,12 @@ function createHaNotificationOutputProvider(deps) {
|
|
|
7627
7651
|
}
|
|
7628
7652
|
/** Degrade → build → publish. NEVER throws through the cap. */
|
|
7629
7653
|
async function dispatch(target, raw) {
|
|
7630
|
-
const notification = deps.readPublicEndpoint === void 0 ? raw : await
|
|
7654
|
+
const notification = deps.readPublicEndpoint === void 0 ? raw : await require_legacy_integration_rows.resolveAttachmentUrls({
|
|
7631
7655
|
notification: raw,
|
|
7632
7656
|
readPublicEndpoint: deps.readPublicEndpoint,
|
|
7633
7657
|
...logger !== void 0 ? { logger } : {}
|
|
7634
7658
|
});
|
|
7635
|
-
const prepared =
|
|
7659
|
+
const prepared = require_legacy_integration_rows.prepareNotification(descriptor.caps, notification);
|
|
7636
7660
|
const service = readService(target.config);
|
|
7637
7661
|
if (!service) return {
|
|
7638
7662
|
success: false,
|
|
@@ -7656,11 +7680,11 @@ function createHaNotificationOutputProvider(deps) {
|
|
|
7656
7680
|
logger?.warn("ha notify publish failed", { meta: {
|
|
7657
7681
|
brokerId,
|
|
7658
7682
|
service,
|
|
7659
|
-
error:
|
|
7683
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
7660
7684
|
} });
|
|
7661
7685
|
return {
|
|
7662
7686
|
success: false,
|
|
7663
|
-
error:
|
|
7687
|
+
error: require_legacy_integration_rows.errMsg(err),
|
|
7664
7688
|
renderedAs: prepared.renderedAs
|
|
7665
7689
|
};
|
|
7666
7690
|
}
|
|
@@ -7699,7 +7723,7 @@ function createHaNotificationOutputProvider(deps) {
|
|
|
7699
7723
|
} catch (err) {
|
|
7700
7724
|
logger?.warn("ha device registry read failed; naming services from their ids", { meta: {
|
|
7701
7725
|
brokerId,
|
|
7702
|
-
error:
|
|
7726
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
7703
7727
|
} });
|
|
7704
7728
|
return /* @__PURE__ */ new Map();
|
|
7705
7729
|
}
|
|
@@ -7713,7 +7737,7 @@ function createHaNotificationOutputProvider(deps) {
|
|
|
7713
7737
|
} catch (err) {
|
|
7714
7738
|
logger?.warn("ha get_services discovery failed", { meta: {
|
|
7715
7739
|
brokerId,
|
|
7716
|
-
error:
|
|
7740
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
7717
7741
|
} });
|
|
7718
7742
|
}
|
|
7719
7743
|
return out;
|
|
@@ -7774,7 +7798,8 @@ function rowToEntry(id, data) {
|
|
|
7774
7798
|
accessToken: data.accessToken,
|
|
7775
7799
|
supervisorToken: data.supervisorToken,
|
|
7776
7800
|
integrationId: data.integrationId,
|
|
7777
|
-
enabled: data.enabled
|
|
7801
|
+
enabled: data.enabled,
|
|
7802
|
+
calendarIds: data.calendarIds
|
|
7778
7803
|
});
|
|
7779
7804
|
return parsed.success ? parsed.data : null;
|
|
7780
7805
|
}
|
|
@@ -7795,7 +7820,7 @@ var HaBrokerStore = class HaBrokerStore {
|
|
|
7795
7820
|
const resolved = await this.kind.getResolved(record.id);
|
|
7796
7821
|
if (resolved !== null) data = resolved.data;
|
|
7797
7822
|
} catch (err) {
|
|
7798
|
-
if (!(err instanceof
|
|
7823
|
+
if (!(err instanceof require_legacy_integration_rows.RecordSecretUnavailableError)) throw err;
|
|
7799
7824
|
}
|
|
7800
7825
|
const entry = rowToEntry(record.id, data);
|
|
7801
7826
|
if (entry !== null) out.push(entry);
|
|
@@ -7808,7 +7833,7 @@ var HaBrokerStore = class HaBrokerStore {
|
|
|
7808
7833
|
if (row === null) return null;
|
|
7809
7834
|
return rowToEntry(row.id, row.data);
|
|
7810
7835
|
} catch (err) {
|
|
7811
|
-
if (err instanceof
|
|
7836
|
+
if (err instanceof require_legacy_integration_rows.RecordSecretUnavailableError) return null;
|
|
7812
7837
|
throw err;
|
|
7813
7838
|
}
|
|
7814
7839
|
}
|
|
@@ -7866,7 +7891,7 @@ function statusOf(info) {
|
|
|
7866
7891
|
};
|
|
7867
7892
|
}
|
|
7868
7893
|
function buildHaInstances(records, deps) {
|
|
7869
|
-
return new
|
|
7894
|
+
return new require_legacy_integration_rows.RecordIntegrationInstances(records, haBrokersEntryKind, {
|
|
7870
7895
|
description: {
|
|
7871
7896
|
role: "both",
|
|
7872
7897
|
instanceMode: "multiple",
|
|
@@ -7878,7 +7903,10 @@ function buildHaInstances(records, deps) {
|
|
|
7878
7903
|
}],
|
|
7879
7904
|
allowRestoreId: true
|
|
7880
7905
|
},
|
|
7881
|
-
formSchema: () =>
|
|
7906
|
+
formSchema: (id) => {
|
|
7907
|
+
const options = id === null ? [] : deps.calendarOptions(id);
|
|
7908
|
+
return options.length === 0 ? haBrokerSettingsSchema : { sections: [...haBrokerSettingsSchema.sections, haCalendarsSection(options)] };
|
|
7909
|
+
},
|
|
7882
7910
|
initialBody: (name) => ({
|
|
7883
7911
|
name,
|
|
7884
7912
|
authKind: "long-lived"
|
|
@@ -7950,19 +7978,19 @@ function buildHaInstances(records, deps) {
|
|
|
7950
7978
|
*/
|
|
7951
7979
|
var INGRESS_PREFIX = "/api/hassio_ingress/";
|
|
7952
7980
|
var ESPHOME_SERVICE = "esphome";
|
|
7953
|
-
var DiscoverySchema =
|
|
7954
|
-
addon:
|
|
7955
|
-
service:
|
|
7981
|
+
var DiscoverySchema = require_legacy_integration_rows.object({ discovery: require_legacy_integration_rows.array(require_legacy_integration_rows.object({
|
|
7982
|
+
addon: require_legacy_integration_rows.string(),
|
|
7983
|
+
service: require_legacy_integration_rows.string()
|
|
7956
7984
|
})) });
|
|
7957
|
-
var AddonInfoSchema =
|
|
7958
|
-
var SessionSchema =
|
|
7959
|
-
var DevicesSchema =
|
|
7960
|
-
name:
|
|
7961
|
-
configuration:
|
|
7962
|
-
address:
|
|
7985
|
+
var AddonInfoSchema = require_legacy_integration_rows.object({ ingress_url: require_legacy_integration_rows.string().nullable().optional() });
|
|
7986
|
+
var SessionSchema = require_legacy_integration_rows.object({ session: require_legacy_integration_rows.string().min(1) });
|
|
7987
|
+
var DevicesSchema = require_legacy_integration_rows.object({ configured: require_legacy_integration_rows.array(require_legacy_integration_rows.object({
|
|
7988
|
+
name: require_legacy_integration_rows.string(),
|
|
7989
|
+
configuration: require_legacy_integration_rows.string(),
|
|
7990
|
+
address: require_legacy_integration_rows.string().nullable().optional()
|
|
7963
7991
|
})) });
|
|
7964
7992
|
/** The ONLY part of `json-config` that is read; every other field is dropped by the parse. */
|
|
7965
|
-
var KeyConfigSchema =
|
|
7993
|
+
var KeyConfigSchema = require_legacy_integration_rows.object({ api: require_legacy_integration_rows.object({ encryption: require_legacy_integration_rows.object({ key: require_legacy_integration_rows.string().min(1) }).optional() }).optional() });
|
|
7966
7994
|
var ADMIN_CODES = new Set([
|
|
7967
7995
|
"unauthorized",
|
|
7968
7996
|
"forbidden",
|
|
@@ -8028,7 +8056,7 @@ var HaBoardKeySource = class {
|
|
|
8028
8056
|
}
|
|
8029
8057
|
}
|
|
8030
8058
|
fail(sourceId, op, err) {
|
|
8031
|
-
const failure = err instanceof SourceFailure ? err : new SourceFailure("unreachable",
|
|
8059
|
+
const failure = err instanceof SourceFailure ? err : new SourceFailure("unreachable", require_legacy_integration_rows.errMsg(err));
|
|
8032
8060
|
this.deps.logger.warn(`board-key-source ${op} refused`, { meta: {
|
|
8033
8061
|
sourceId,
|
|
8034
8062
|
reason: failure.reason
|
|
@@ -8052,7 +8080,7 @@ var HaBoardKeySource = class {
|
|
|
8052
8080
|
} catch (err) {
|
|
8053
8081
|
const code = errorCode(err);
|
|
8054
8082
|
if (code !== null && ADMIN_CODES.has(code)) throw new SourceFailure("not-admin", "the Home Assistant token is not an administrator");
|
|
8055
|
-
throw new SourceFailure("unreachable",
|
|
8083
|
+
throw new SourceFailure("unreachable", require_legacy_integration_rows.errMsg(err));
|
|
8056
8084
|
}
|
|
8057
8085
|
}
|
|
8058
8086
|
async openIngress(sourceId) {
|
|
@@ -8080,7 +8108,7 @@ var HaBoardKeySource = class {
|
|
|
8080
8108
|
Accept: "application/json"
|
|
8081
8109
|
} });
|
|
8082
8110
|
} catch (err) {
|
|
8083
|
-
throw new SourceFailure("unreachable",
|
|
8111
|
+
throw new SourceFailure("unreachable", require_legacy_integration_rows.errMsg(err));
|
|
8084
8112
|
}
|
|
8085
8113
|
if (response.status === 404 && configuration !== void 0) throw new SourceFailure("unknown-board", configuration);
|
|
8086
8114
|
if (response.status === 401 || response.status === 403) throw new SourceFailure("not-admin", `the builder answered ${response.status}`);
|
|
@@ -8101,6 +8129,28 @@ function createHaBoardKeyProvider(source) {
|
|
|
8101
8129
|
};
|
|
8102
8130
|
}
|
|
8103
8131
|
//#endregion
|
|
8132
|
+
//#region src/ha-instance-settings.ts
|
|
8133
|
+
function valuesOf(body) {
|
|
8134
|
+
return {
|
|
8135
|
+
...body.integrationId !== void 0 ? { integrationId: body.integrationId } : {},
|
|
8136
|
+
...body.calendarIds !== void 0 ? { calendarIds: body.calendarIds } : {}
|
|
8137
|
+
};
|
|
8138
|
+
}
|
|
8139
|
+
function haInstanceRecordPortsOver(kind) {
|
|
8140
|
+
return {
|
|
8141
|
+
readInstance: async (brokerId) => {
|
|
8142
|
+
const row = await kind.get(brokerId);
|
|
8143
|
+
return row === null ? null : valuesOf(row.data);
|
|
8144
|
+
},
|
|
8145
|
+
patchInstance: async (brokerId, patch) => {
|
|
8146
|
+
const row = await kind.get(brokerId);
|
|
8147
|
+
if (row === null) return false;
|
|
8148
|
+
await kind.patch(brokerId, patch, { ifRev: row.rev });
|
|
8149
|
+
return true;
|
|
8150
|
+
}
|
|
8151
|
+
};
|
|
8152
|
+
}
|
|
8153
|
+
//#endregion
|
|
8104
8154
|
//#region src/migrations/flatten-broker-records.ts
|
|
8105
8155
|
/**
|
|
8106
8156
|
* The Home Assistant broker records keep their connection flat (planning#408 P3): the nested
|
|
@@ -8115,7 +8165,7 @@ function text(value) {
|
|
|
8115
8165
|
return typeof value === "string" ? value : void 0;
|
|
8116
8166
|
}
|
|
8117
8167
|
async function flattenBrokerRecords(ports) {
|
|
8118
|
-
return
|
|
8168
|
+
return require_legacy_integration_rows.flattenNestedRecords(ports, {
|
|
8119
8169
|
legacyKey: "auth",
|
|
8120
8170
|
flatSecretKeys: ["accessToken", "supervisorToken"],
|
|
8121
8171
|
toFlat: (legacy) => {
|
|
@@ -8133,6 +8183,98 @@ async function flattenBrokerRecords(ports) {
|
|
|
8133
8183
|
});
|
|
8134
8184
|
}
|
|
8135
8185
|
//#endregion
|
|
8186
|
+
//#region src/migrations/instance-settings-to-record.ts
|
|
8187
|
+
var INSTANCE_SETTINGS_TO_RECORD_ID = "provider-homeassistant/2026-11-05-instance-settings-to-record";
|
|
8188
|
+
var CLEAR_INSTANCE_SETTINGS_ROWS_ID = "provider-homeassistant/2026-11-05-clear-instance-settings-rows";
|
|
8189
|
+
/** The legacy row key the clearing migration removes once the record carries it. */
|
|
8190
|
+
var MOVED_ROW_KEYS = ["calendarIds"];
|
|
8191
|
+
var asIds$1 = (value) => Array.isArray(value) && value.every((item) => typeof item === "string") ? value : null;
|
|
8192
|
+
var sameSet$1 = (a, b) => {
|
|
8193
|
+
const left = new Set(a);
|
|
8194
|
+
const right = new Set(b);
|
|
8195
|
+
return left.size === right.size && [...left].every((id) => right.has(id));
|
|
8196
|
+
};
|
|
8197
|
+
/** What the rows of one integration say about its record. */
|
|
8198
|
+
function wanted(row) {
|
|
8199
|
+
const calendarIds = asIds$1(row.settings["calendarIds"]);
|
|
8200
|
+
return {
|
|
8201
|
+
integrationId: row.integrationId,
|
|
8202
|
+
...calendarIds !== null ? { calendarIds } : {}
|
|
8203
|
+
};
|
|
8204
|
+
}
|
|
8205
|
+
function assertNoAmbiguity(rows) {
|
|
8206
|
+
const seen = /* @__PURE__ */ new Map();
|
|
8207
|
+
for (const row of rows) {
|
|
8208
|
+
if (row.brokerId === null) continue;
|
|
8209
|
+
const other = seen.get(row.brokerId);
|
|
8210
|
+
if (other === void 0) {
|
|
8211
|
+
seen.set(row.brokerId, row);
|
|
8212
|
+
continue;
|
|
8213
|
+
}
|
|
8214
|
+
throw new Error(`provider-homeassistant: integrations ${other.integrationId} and ${row.integrationId} both link broker ${row.brokerId} — nothing moved`);
|
|
8215
|
+
}
|
|
8216
|
+
}
|
|
8217
|
+
async function moveInstanceSettingsToRecords(ports) {
|
|
8218
|
+
const rows = await ports.listInstances();
|
|
8219
|
+
assertNoAmbiguity(rows);
|
|
8220
|
+
let moved = 0;
|
|
8221
|
+
let kept = 0;
|
|
8222
|
+
let gone = 0;
|
|
8223
|
+
for (const row of rows) {
|
|
8224
|
+
if (row.brokerId === null) continue;
|
|
8225
|
+
const record = await ports.readInstance(row.brokerId);
|
|
8226
|
+
if (record === null) {
|
|
8227
|
+
gone += 1;
|
|
8228
|
+
continue;
|
|
8229
|
+
}
|
|
8230
|
+
const want = wanted(row);
|
|
8231
|
+
const patch = {
|
|
8232
|
+
...record.integrationId === void 0 && want.integrationId !== void 0 ? { integrationId: want.integrationId } : {},
|
|
8233
|
+
...record.calendarIds === void 0 && want.calendarIds !== void 0 ? { calendarIds: want.calendarIds } : {}
|
|
8234
|
+
};
|
|
8235
|
+
if (Object.keys(patch).length === 0) {
|
|
8236
|
+
kept += 1;
|
|
8237
|
+
continue;
|
|
8238
|
+
}
|
|
8239
|
+
if (!await ports.patchInstance(row.brokerId, patch)) {
|
|
8240
|
+
gone += 1;
|
|
8241
|
+
continue;
|
|
8242
|
+
}
|
|
8243
|
+
const back = await ports.readInstance(row.brokerId);
|
|
8244
|
+
if (back === null || patch.integrationId !== void 0 && back.integrationId !== patch.integrationId || patch.calendarIds !== void 0 && !(back.calendarIds !== void 0 && sameSet$1(back.calendarIds, patch.calendarIds))) throw new Error(`provider-homeassistant: record ${row.brokerId} does not show the values of integration ${row.integrationId} after the write — rows kept`);
|
|
8245
|
+
moved += 1;
|
|
8246
|
+
}
|
|
8247
|
+
return {
|
|
8248
|
+
outcome: moved === 0 ? "already-done" : "done",
|
|
8249
|
+
summary: {
|
|
8250
|
+
moved,
|
|
8251
|
+
kept,
|
|
8252
|
+
gone
|
|
8253
|
+
}
|
|
8254
|
+
};
|
|
8255
|
+
}
|
|
8256
|
+
async function clearInstanceSettingsRows(ports) {
|
|
8257
|
+
let cleared = 0;
|
|
8258
|
+
let parked = 0;
|
|
8259
|
+
for (const row of await ports.listInstances()) {
|
|
8260
|
+
if (!MOVED_ROW_KEYS.some((key) => key in row.settings)) continue;
|
|
8261
|
+
const own = asIds$1(row.settings["calendarIds"]);
|
|
8262
|
+
const onRecord = (row.brokerId === null ? null : await ports.readInstance(row.brokerId))?.calendarIds;
|
|
8263
|
+
if (own === null || onRecord === void 0 || !sameSet$1(own, onRecord)) {
|
|
8264
|
+
parked += 1;
|
|
8265
|
+
continue;
|
|
8266
|
+
}
|
|
8267
|
+
if (await ports.clearInstanceSettingsKeys(row.integrationId, MOVED_ROW_KEYS)) cleared += 1;
|
|
8268
|
+
}
|
|
8269
|
+
return {
|
|
8270
|
+
outcome: cleared === 0 ? "already-done" : "done",
|
|
8271
|
+
summary: {
|
|
8272
|
+
cleared,
|
|
8273
|
+
parked
|
|
8274
|
+
}
|
|
8275
|
+
};
|
|
8276
|
+
}
|
|
8277
|
+
//#endregion
|
|
8136
8278
|
//#region src/migrations/calendar-ids-to-integration.ts
|
|
8137
8279
|
/**
|
|
8138
8280
|
* The HA calendars an instance imports are a fact of THAT instance (D985): each Home Assistant
|
|
@@ -8212,7 +8354,7 @@ async function planDropSharedCalendarIds(ports) {
|
|
|
8212
8354
|
op: "deleteKeys",
|
|
8213
8355
|
scope: ADDON_SETTINGS_TABLE,
|
|
8214
8356
|
keys: [rowId],
|
|
8215
|
-
precondition:
|
|
8357
|
+
precondition: require_legacy_integration_rows.preconditionOf({ [rowId]: {
|
|
8216
8358
|
addonId: HA_PROVIDER_ID,
|
|
8217
8359
|
key: SHARED_CALENDAR_IDS_KEY,
|
|
8218
8360
|
value: shared
|
|
@@ -8270,6 +8412,38 @@ var ADDON_MIGRATIONS = [
|
|
|
8270
8412
|
fixtureMark: "a non-secret field stored beside the auth of a broker record"
|
|
8271
8413
|
},
|
|
8272
8414
|
procedure: flattenBrokerRecords
|
|
8415
|
+
},
|
|
8416
|
+
{
|
|
8417
|
+
meta: {
|
|
8418
|
+
id: INSTANCE_SETTINGS_TO_RECORD_ID,
|
|
8419
|
+
owner: "provider-homeassistant",
|
|
8420
|
+
level: "addon-state",
|
|
8421
|
+
seq: 4,
|
|
8422
|
+
dependsOn: ["provider-homeassistant/2026-11-03-drop-shared-calendar-ids", FLATTEN_BROKER_RECORDS_ID],
|
|
8423
|
+
store: "settings",
|
|
8424
|
+
scope: "cluster",
|
|
8425
|
+
onFailure: "block-owner",
|
|
8426
|
+
bodyKind: "procedure",
|
|
8427
|
+
description: "Merge the calendars and the integration link of every Home Assistant integration into the instance record its broker link names; a field the record holds wins; read back",
|
|
8428
|
+
fixtureMark: "a calendar id stored in the integration settings of an instance"
|
|
8429
|
+
},
|
|
8430
|
+
procedure: moveInstanceSettingsToRecords
|
|
8431
|
+
},
|
|
8432
|
+
{
|
|
8433
|
+
meta: {
|
|
8434
|
+
id: CLEAR_INSTANCE_SETTINGS_ROWS_ID,
|
|
8435
|
+
owner: "provider-homeassistant",
|
|
8436
|
+
level: "addon-state",
|
|
8437
|
+
seq: 5,
|
|
8438
|
+
dependsOn: [INSTANCE_SETTINGS_TO_RECORD_ID],
|
|
8439
|
+
store: "settings",
|
|
8440
|
+
scope: "cluster",
|
|
8441
|
+
onFailure: "block-owner",
|
|
8442
|
+
bodyKind: "procedure",
|
|
8443
|
+
description: "Clear the calendars from the integration settings of every Home Assistant instance whose record reads back the same set",
|
|
8444
|
+
fixtureMark: "a calendar set the instance record holds differently"
|
|
8445
|
+
},
|
|
8446
|
+
procedure: clearInstanceSettingsRows
|
|
8273
8447
|
}
|
|
8274
8448
|
];
|
|
8275
8449
|
//#endregion
|
|
@@ -8492,24 +8666,6 @@ async function reconcileBroker(brokerId, deps) {
|
|
|
8492
8666
|
function computeBrokerCleanup(brokers, survivingIntegrationIds) {
|
|
8493
8667
|
return brokers.filter((b) => b.integrationId !== void 0 && !survivingIntegrationIds.has(b.integrationId)).map((b) => b.id);
|
|
8494
8668
|
}
|
|
8495
|
-
/**
|
|
8496
|
-
* Stamp the integrationId FK onto each broker that an integration references
|
|
8497
|
-
* via its settings.brokerId, so cleanup-on-delete can later collect orphans.
|
|
8498
|
-
* Pure: returns a NEW array; does not mutate. Only the entries that change are
|
|
8499
|
-
* replaced (immutably) — unchanged entries keep their original object reference.
|
|
8500
|
-
*/
|
|
8501
|
-
function linkBrokersToIntegrations(brokers, integrations) {
|
|
8502
|
-
const brokerToIntegration = /* @__PURE__ */ new Map();
|
|
8503
|
-
for (const integration of integrations) if (integration.brokerId !== void 0) brokerToIntegration.set(integration.brokerId, integration.id);
|
|
8504
|
-
return brokers.map((b) => {
|
|
8505
|
-
const integrationId = brokerToIntegration.get(b.id);
|
|
8506
|
-
if (integrationId !== void 0 && b.integrationId !== integrationId) return {
|
|
8507
|
-
...b,
|
|
8508
|
-
integrationId
|
|
8509
|
-
};
|
|
8510
|
-
return b;
|
|
8511
|
-
});
|
|
8512
|
-
}
|
|
8513
8669
|
//#endregion
|
|
8514
8670
|
//#region src/ha-standalone-entity.ts
|
|
8515
8671
|
/**
|
|
@@ -8607,7 +8763,7 @@ function entityToStandaloneCandidate(entity, alreadyAdopted) {
|
|
|
8607
8763
|
return {
|
|
8608
8764
|
childNativeId: entity.entityId,
|
|
8609
8765
|
name: entity.name,
|
|
8610
|
-
type: entity.mappedTo?.deviceType ??
|
|
8766
|
+
type: entity.mappedTo?.deviceType ?? require_legacy_integration_rows.DeviceType.Generic,
|
|
8611
8767
|
status: entityStatus(entity.state),
|
|
8612
8768
|
metadata: entity.area !== null ? { externalLocation: entity.area } : {},
|
|
8613
8769
|
alreadyAdopted,
|
|
@@ -8742,7 +8898,7 @@ function readPersistedStandaloneSpec(device) {
|
|
|
8742
8898
|
* adoption-proof source field), so it is projected directly here, mirroring the
|
|
8743
8899
|
* Container's `EnumSensorDateTimeFormatSchema.safeParse` guard. */
|
|
8744
8900
|
function readDateTimeFormat(config) {
|
|
8745
|
-
const parsed =
|
|
8901
|
+
const parsed = require_legacy_integration_rows.EnumSensorDateTimeFormatSchema.safeParse(config["dateTimeFormat"]);
|
|
8746
8902
|
return parsed.success ? parsed.data : void 0;
|
|
8747
8903
|
}
|
|
8748
8904
|
/** Flatten a live device's config into a plain blob for `readHaSource`. */
|
|
@@ -8906,12 +9062,12 @@ var DEFAULT_CONFIG = { calendarIds: [] };
|
|
|
8906
9062
|
* …) and route HA state pushes into runtime-state slices + cap
|
|
8907
9063
|
* mutations into HA call_service.
|
|
8908
9064
|
*/
|
|
8909
|
-
var HaProviderAddon = class HaProviderAddon extends
|
|
9065
|
+
var HaProviderAddon = class HaProviderAddon extends require_legacy_integration_rows.BaseDeviceProvider {
|
|
8910
9066
|
addonId = "provider-homeassistant";
|
|
8911
9067
|
providerName = "Home Assistant";
|
|
8912
9068
|
deviceClasses = {
|
|
8913
|
-
[
|
|
8914
|
-
[
|
|
9069
|
+
[require_legacy_integration_rows.DeviceType.Container]: HaContainerDevice,
|
|
9070
|
+
[require_legacy_integration_rows.DeviceType.EventEmitter]: HaEventBusDevice
|
|
8915
9071
|
};
|
|
8916
9072
|
async onGetCreationSchema(_type) {
|
|
8917
9073
|
return null;
|
|
@@ -8951,8 +9107,9 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
8951
9107
|
if (this.ctx.secrets === void 0) throw new Error("provider-homeassistant: ctx.secrets is required");
|
|
8952
9108
|
return {
|
|
8953
9109
|
readStored: (key) => this.readStoredGlobalKey(key),
|
|
8954
|
-
...
|
|
8955
|
-
...
|
|
9110
|
+
...require_legacy_integration_rows.haInstanceSettingsPortsOver(this.ctx.api.integrations),
|
|
9111
|
+
...haInstanceRecordPortsOver(records.kind(haBrokersEntryKind)),
|
|
9112
|
+
...require_legacy_integration_rows.flattenPortsOver(records.kind(haBrokersEntryKind))
|
|
8956
9113
|
};
|
|
8957
9114
|
}
|
|
8958
9115
|
async onInitialize() {
|
|
@@ -8963,10 +9120,11 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
8963
9120
|
this.instances = buildHaInstances(records, {
|
|
8964
9121
|
mintId: () => this.requireRegistry().allocateId(),
|
|
8965
9122
|
infoOf: (id) => this.registry?.get(id) ?? null,
|
|
9123
|
+
calendarOptions: (id) => this.registry ? listHaCalendarCatalog(this.registry, id) : [],
|
|
8966
9124
|
onChanged: (id) => this.syncBrokerRuntime(id),
|
|
8967
9125
|
probe: (settings) => this.requireRegistry().testSettings(settings)
|
|
8968
9126
|
});
|
|
8969
|
-
await this.runMigrations(
|
|
9127
|
+
await this.runMigrations(require_legacy_integration_rows.defineAddonMigrations(ADDON_MIGRATIONS, this.flattenPorts(records)), { only: [FLATTEN_BROKER_RECORDS_ID] });
|
|
8970
9128
|
this.activeBrokers = await this.loadPersistedBrokers();
|
|
8971
9129
|
this.registry = new HaBrokerRegistry(this.ctx.logger, this.ctx.eventBus);
|
|
8972
9130
|
this.registry.setOnBrokerConnected((brokerId) => {
|
|
@@ -8983,36 +9141,36 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
8983
9141
|
this.reconcileAllConnectedBrokers();
|
|
8984
9142
|
}, HaProviderAddon.RESYNC_INTERVAL_MS);
|
|
8985
9143
|
this.ctx.logger.info("ha provider initialised", { meta: { brokerCount: this.activeBrokers.length } });
|
|
8986
|
-
await this.runMigrations(
|
|
9144
|
+
await this.runMigrations(require_legacy_integration_rows.defineAddonMigrations(ADDON_MIGRATIONS, this.flattenPorts(records)), { only: ADDON_MIGRATIONS.map((m) => m.meta.id).filter((id) => id !== FLATTEN_BROKER_RECORDS_ID) });
|
|
8987
9145
|
await this.reconcileIntegrationsToBrokers();
|
|
8988
9146
|
this.subscribeIntegrationLifecycle();
|
|
8989
9147
|
return [
|
|
8990
9148
|
{
|
|
8991
|
-
capability:
|
|
9149
|
+
capability: require_legacy_integration_rows.brokerCapability,
|
|
8992
9150
|
provider: this.buildBrokerProvider()
|
|
8993
9151
|
},
|
|
8994
9152
|
{
|
|
8995
|
-
capability:
|
|
9153
|
+
capability: require_legacy_integration_rows.integrationInstancesCapability,
|
|
8996
9154
|
provider: this.requireInstances().toProvider()
|
|
8997
9155
|
},
|
|
8998
9156
|
{
|
|
8999
|
-
capability:
|
|
9157
|
+
capability: require_legacy_integration_rows.deviceAdoptionCapability,
|
|
9000
9158
|
provider: this.buildAdoptionProvider()
|
|
9001
9159
|
},
|
|
9002
9160
|
{
|
|
9003
|
-
capability:
|
|
9161
|
+
capability: require_legacy_integration_rows.notificationOutputCapability,
|
|
9004
9162
|
provider: await this.buildNotificationOutputProvider()
|
|
9005
9163
|
},
|
|
9006
9164
|
{
|
|
9007
|
-
capability:
|
|
9165
|
+
capability: require_legacy_integration_rows.addonRoutesCapability,
|
|
9008
9166
|
provider: createHaIconRouteProvider()
|
|
9009
9167
|
},
|
|
9010
9168
|
{
|
|
9011
|
-
capability:
|
|
9169
|
+
capability: require_legacy_integration_rows.boardKeySourceCapability,
|
|
9012
9170
|
provider: this.buildBoardKeyProvider()
|
|
9013
9171
|
},
|
|
9014
9172
|
{
|
|
9015
|
-
capability:
|
|
9173
|
+
capability: require_legacy_integration_rows.calendarSourceCapability,
|
|
9016
9174
|
provider: createHaCalendarSource({
|
|
9017
9175
|
brokers: this.requireRegistry(),
|
|
9018
9176
|
logger: this.ctx.logger.child("calendar-source"),
|
|
@@ -9064,7 +9222,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
9064
9222
|
return manager.sendMessage({ type: "config/device_registry/list" });
|
|
9065
9223
|
},
|
|
9066
9224
|
listBrokerIds: () => this.activeBrokers.map((b) => b.id),
|
|
9067
|
-
readPublicEndpoint:
|
|
9225
|
+
readPublicEndpoint: require_legacy_integration_rows.publicEndpointReaderFrom(this.ctx.api.localNetwork),
|
|
9068
9226
|
logger: this.ctx.logger.child("notification-output")
|
|
9069
9227
|
});
|
|
9070
9228
|
}
|
|
@@ -9120,41 +9278,25 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
9120
9278
|
* selection yet (the move has not run) uses the legacy shared set, so a boot mid-move never
|
|
9121
9279
|
* changes what is imported.
|
|
9122
9280
|
*/
|
|
9123
|
-
|
|
9124
|
-
noteInstanceCalendars(brokerId, raw) {
|
|
9125
|
-
if (Array.isArray(raw) && raw.every((id) => typeof id === "string")) this.calendarIdsByBroker.set(brokerId, new Set(raw));
|
|
9126
|
-
else this.calendarIdsByBroker.delete(brokerId);
|
|
9127
|
-
}
|
|
9281
|
+
/** The calendars one instance imports: its record's set, else the addon default. */
|
|
9128
9282
|
calendarIdsOf(brokerId) {
|
|
9129
|
-
|
|
9283
|
+
const own = this.activeBrokers.find((b) => b.id === brokerId)?.calendarIds;
|
|
9284
|
+
return new Set(own ?? this.config.calendarIds ?? []);
|
|
9130
9285
|
}
|
|
9131
9286
|
async reconcileIntegrationsToBrokers() {
|
|
9132
|
-
const api = this.ctx.api;
|
|
9133
|
-
if (!api
|
|
9287
|
+
const api = this.ctx.api.integrations;
|
|
9288
|
+
if (!api?.list?.query) return;
|
|
9134
9289
|
try {
|
|
9135
|
-
const haIntegrations = (await api.
|
|
9290
|
+
const haIntegrations = (await api.list.query()).filter((i) => i.addonId === this.ctx.id);
|
|
9136
9291
|
const survivingIntegrationIds = new Set(haIntegrations.map((i) => i.id));
|
|
9137
|
-
const integrationsWithBrokerId = [];
|
|
9138
9292
|
for (const integration of haIntegrations) {
|
|
9139
|
-
const
|
|
9140
|
-
|
|
9141
|
-
|
|
9142
|
-
this.noteInstanceCalendars(brokerId, settings["calendarIds"]);
|
|
9143
|
-
if (!this.activeBrokers.find((b) => b.id === brokerId)) {
|
|
9144
|
-
this.ctx.logger.warn("integration→broker: linked broker not found", { meta: {
|
|
9145
|
-
integrationId: integration.id,
|
|
9146
|
-
brokerId
|
|
9147
|
-
} });
|
|
9293
|
+
const matching = this.activeBrokers.find((b) => b.integrationId === integration.id);
|
|
9294
|
+
if (!matching) {
|
|
9295
|
+
this.ctx.logger.warn("integration→broker: no instance record names this integration", { meta: { integrationId: integration.id } });
|
|
9148
9296
|
continue;
|
|
9149
9297
|
}
|
|
9150
|
-
this.requireRegistry().linkIntegration(integration.id,
|
|
9151
|
-
integrationsWithBrokerId.push({
|
|
9152
|
-
id: integration.id,
|
|
9153
|
-
brokerId
|
|
9154
|
-
});
|
|
9298
|
+
this.requireRegistry().linkIntegration(integration.id, matching.id);
|
|
9155
9299
|
}
|
|
9156
|
-
const linkedBrokers = linkBrokersToIntegrations(this.activeBrokers, integrationsWithBrokerId);
|
|
9157
|
-
if (linkedBrokers.some((b, i) => b !== this.activeBrokers[i])) await this.persistBrokerEntries(linkedBrokers);
|
|
9158
9300
|
const orphans = computeBrokerCleanup(this.activeBrokers, survivingIntegrationIds);
|
|
9159
9301
|
this.ctx.logger.info("integration→broker reconcile", { meta: {
|
|
9160
9302
|
brokerCount: this.activeBrokers.length,
|
|
@@ -9166,7 +9308,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
9166
9308
|
integrationCount: haIntegrations.length
|
|
9167
9309
|
} });
|
|
9168
9310
|
} catch (err) {
|
|
9169
|
-
this.ctx.logger.warn("integration→broker reconcile failed", { meta: { error:
|
|
9311
|
+
this.ctx.logger.warn("integration→broker reconcile failed", { meta: { error: require_legacy_integration_rows.errMsg(err) } });
|
|
9170
9312
|
}
|
|
9171
9313
|
}
|
|
9172
9314
|
subscribeIntegrationLifecycle() {
|
|
@@ -9194,40 +9336,6 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
9194
9336
|
}]
|
|
9195
9337
|
}] });
|
|
9196
9338
|
}
|
|
9197
|
-
/**
|
|
9198
|
-
* The calendars of ONE Home Assistant instance (D985): picked on its integration, offered from
|
|
9199
|
-
* that broker's own `calendar.*` entities.
|
|
9200
|
-
*/
|
|
9201
|
-
async integrationSettingsSchema(instance) {
|
|
9202
|
-
if (instance.integrationId === null || !this.registry) return null;
|
|
9203
|
-
let brokerId;
|
|
9204
|
-
try {
|
|
9205
|
-
brokerId = (await this.ctx.api.integrations.getSettings.query({ id: instance.integrationId }))["brokerId"];
|
|
9206
|
-
} catch (err) {
|
|
9207
|
-
this.ctx.logger.warn("HA integration form: instance lookup failed — broker form shown", { meta: {
|
|
9208
|
-
integrationId: instance.integrationId,
|
|
9209
|
-
error: require_ha_instance_settings.errMsg(err)
|
|
9210
|
-
} });
|
|
9211
|
-
return null;
|
|
9212
|
-
}
|
|
9213
|
-
if (typeof brokerId !== "string") return null;
|
|
9214
|
-
const options = listHaCalendarCatalog(this.registry, brokerId);
|
|
9215
|
-
return this.schema({ sections: [{
|
|
9216
|
-
id: "ha-calendars-import",
|
|
9217
|
-
title: "Calendars to import",
|
|
9218
|
-
titleKey: "provider-homeassistant:globalSettings.s_ha-calendars-import.title",
|
|
9219
|
-
columns: 1,
|
|
9220
|
-
fields: [{
|
|
9221
|
-
type: "multiselect",
|
|
9222
|
-
key: "calendarIds",
|
|
9223
|
-
label: "Calendars",
|
|
9224
|
-
labelKey: "provider-homeassistant:globalSettings.s_ha-calendars-import.calendarIds.label",
|
|
9225
|
-
options,
|
|
9226
|
-
description: "Discovered from this Home Assistant instance. Select at least one to import; leave empty to import none.",
|
|
9227
|
-
descriptionKey: "provider-homeassistant:globalSettings.s_ha-calendars-import.calendarIds.description"
|
|
9228
|
-
}]
|
|
9229
|
-
}] });
|
|
9230
|
-
}
|
|
9231
9339
|
async onShutdown() {
|
|
9232
9340
|
if (this.resyncTimer) {
|
|
9233
9341
|
clearInterval(this.resyncTimer);
|
|
@@ -9236,7 +9344,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
9236
9344
|
try {
|
|
9237
9345
|
await this.registry?.shutdown();
|
|
9238
9346
|
} catch (err) {
|
|
9239
|
-
this.ctx.logger.warn("ha provider shutdown error", { meta: { error:
|
|
9347
|
+
this.ctx.logger.warn("ha provider shutdown error", { meta: { error: require_legacy_integration_rows.errMsg(err) } });
|
|
9240
9348
|
}
|
|
9241
9349
|
this.registry = null;
|
|
9242
9350
|
await super.onShutdown();
|
|
@@ -9268,7 +9376,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
9268
9376
|
} catch (err) {
|
|
9269
9377
|
this.ctx.logger.warn("ha onConfigChanged: removeEntry failed", { meta: {
|
|
9270
9378
|
brokerId: liveId,
|
|
9271
|
-
error:
|
|
9379
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
9272
9380
|
} });
|
|
9273
9381
|
}
|
|
9274
9382
|
for (const entry of persisted) {
|
|
@@ -9279,7 +9387,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
9279
9387
|
} catch (err) {
|
|
9280
9388
|
this.ctx.logger.warn("ha onConfigChanged: updateEntry failed", { meta: {
|
|
9281
9389
|
brokerId: entry.id,
|
|
9282
|
-
error:
|
|
9390
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
9283
9391
|
} });
|
|
9284
9392
|
}
|
|
9285
9393
|
continue;
|
|
@@ -9298,7 +9406,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
9298
9406
|
} catch (err) {
|
|
9299
9407
|
this.ctx.logger.warn("ha onConfigChanged: failed to start new broker", { meta: {
|
|
9300
9408
|
brokerName: entry.name,
|
|
9301
|
-
error:
|
|
9409
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
9302
9410
|
} });
|
|
9303
9411
|
}
|
|
9304
9412
|
}
|
|
@@ -9346,7 +9454,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
9346
9454
|
} catch (err) {
|
|
9347
9455
|
this.ctx.logger.warn("ha instance: could not start the broker", { meta: {
|
|
9348
9456
|
brokerId: id,
|
|
9349
|
-
error:
|
|
9457
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
9350
9458
|
} });
|
|
9351
9459
|
}
|
|
9352
9460
|
}
|
|
@@ -9486,7 +9594,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
9486
9594
|
const refreshedAt = Date.now();
|
|
9487
9595
|
if (lastDiscoveryAt === null || refreshedAt > lastDiscoveryAt) lastDiscoveryAt = refreshedAt;
|
|
9488
9596
|
} catch (err) {
|
|
9489
|
-
lastError =
|
|
9597
|
+
lastError = require_legacy_integration_rows.errMsg(err);
|
|
9490
9598
|
}
|
|
9491
9599
|
const adoptedCount = (await this.ctx.kernel.devices.getAll()).filter((d) => d.parentDeviceId === null && String(d.config.get("system") ?? "") === "homeassistant").length;
|
|
9492
9600
|
return {
|
|
@@ -9632,7 +9740,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
9632
9740
|
name: deviceName
|
|
9633
9741
|
};
|
|
9634
9742
|
const summary = await this.createDevice({
|
|
9635
|
-
type:
|
|
9743
|
+
type: require_legacy_integration_rows.DeviceType.Container,
|
|
9636
9744
|
config: containerConfig
|
|
9637
9745
|
});
|
|
9638
9746
|
const accessoryDeviceIds = (await this.ctx.kernel.devices.getChildren(summary.id)).map((c) => c.id);
|
|
@@ -9662,7 +9770,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
9662
9770
|
meta: {
|
|
9663
9771
|
brokerId,
|
|
9664
9772
|
haDeviceId,
|
|
9665
|
-
error:
|
|
9773
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
9666
9774
|
}
|
|
9667
9775
|
});
|
|
9668
9776
|
}
|
|
@@ -9809,7 +9917,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
9809
9917
|
meta: {
|
|
9810
9918
|
brokerId,
|
|
9811
9919
|
entityId,
|
|
9812
|
-
error:
|
|
9920
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
9813
9921
|
}
|
|
9814
9922
|
});
|
|
9815
9923
|
}
|
|
@@ -9830,7 +9938,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
9830
9938
|
*/
|
|
9831
9939
|
async assignImportedLocation(deviceId, externalLocation, knownLocations) {
|
|
9832
9940
|
try {
|
|
9833
|
-
const match =
|
|
9941
|
+
const match = require_legacy_integration_rows.bestLocationMatch(externalLocation, knownLocations);
|
|
9834
9942
|
const name = match ?? externalLocation;
|
|
9835
9943
|
let locations = knownLocations;
|
|
9836
9944
|
if (match === null) {
|
|
@@ -9846,7 +9954,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
9846
9954
|
this.ctx.logger.warn("ha-adoption: location import failed (non-fatal)", { meta: {
|
|
9847
9955
|
deviceId,
|
|
9848
9956
|
externalLocation,
|
|
9849
|
-
error:
|
|
9957
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
9850
9958
|
} });
|
|
9851
9959
|
return knownLocations;
|
|
9852
9960
|
}
|
|
@@ -10047,7 +10155,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
10047
10155
|
} catch (err) {
|
|
10048
10156
|
this.ctx.logger.warn("ha bus-event aggregator ensure failed", { meta: {
|
|
10049
10157
|
brokerId,
|
|
10050
|
-
error:
|
|
10158
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
10051
10159
|
} });
|
|
10052
10160
|
}
|
|
10053
10161
|
await reconcileBroker(brokerId, {
|
|
@@ -10057,7 +10165,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
10057
10165
|
onFetchError: (id, error) => {
|
|
10058
10166
|
this.ctx.logger.warn("ha re-sync: inventory fetch failed", { meta: {
|
|
10059
10167
|
brokerId: id,
|
|
10060
|
-
error:
|
|
10168
|
+
error: require_legacy_integration_rows.errMsg(error)
|
|
10061
10169
|
} });
|
|
10062
10170
|
}
|
|
10063
10171
|
});
|
|
@@ -10095,7 +10203,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
10095
10203
|
meta: {
|
|
10096
10204
|
brokerId,
|
|
10097
10205
|
haDeviceId,
|
|
10098
|
-
error:
|
|
10206
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
10099
10207
|
}
|
|
10100
10208
|
});
|
|
10101
10209
|
}
|
|
@@ -10140,7 +10248,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
10140
10248
|
tags: { deviceId: action.deviceId },
|
|
10141
10249
|
meta: {
|
|
10142
10250
|
brokerId,
|
|
10143
|
-
error:
|
|
10251
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
10144
10252
|
}
|
|
10145
10253
|
});
|
|
10146
10254
|
}
|
|
@@ -10221,7 +10329,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
10221
10329
|
brokerId,
|
|
10222
10330
|
kind: "event-bus"
|
|
10223
10331
|
}, null, {
|
|
10224
|
-
type:
|
|
10332
|
+
type: require_legacy_integration_rows.DeviceType.EventEmitter,
|
|
10225
10333
|
name: "Home Assistant Events"
|
|
10226
10334
|
});
|
|
10227
10335
|
this.eventBusDeviceIds.set(brokerId, device.id);
|
|
@@ -10251,7 +10359,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
|
|
|
10251
10359
|
this.ctx.logger.debug("ha bus-event dropped — aggregator not ready", { meta: {
|
|
10252
10360
|
brokerId,
|
|
10253
10361
|
eventType: ev.eventType,
|
|
10254
|
-
error:
|
|
10362
|
+
error: require_legacy_integration_rows.errMsg(err)
|
|
10255
10363
|
} });
|
|
10256
10364
|
return;
|
|
10257
10365
|
}
|