@camstack/addon-provider-bosch 0.1.35 → 0.1.37
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/{account-integration-offline-De_H_EsP.js → account-integration-offline-VItxeiJg.js} +2 -2
- package/dist/{account-integration-offline-Bt3N9Zdk.mjs → account-integration-offline-nChgZUlC.mjs} +1 -1
- package/dist/{dist-CyZFf49n.js → bosch-instances-BQiyzlPt.mjs} +33936 -31385
- package/dist/{dist-CkMPcvma.mjs → bosch-instances-CO8yIFzJ.js} +34261 -31124
- package/dist/home-connect/addon.js +349 -278
- package/dist/home-connect/addon.mjs +175 -104
- package/dist/homecom/addon.js +247 -117
- package/dist/homecom/addon.mjs +165 -35
- package/dist/shc/addon.js +217 -93
- package/dist/shc/addon.mjs +130 -6
- package/package.json +14 -2
package/dist/shc/addon.js
CHANGED
|
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
2
2
|
//#region \0rolldown/runtime.js
|
|
3
3
|
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
4
4
|
//#endregion
|
|
5
|
-
const
|
|
5
|
+
const require_bosch_instances = require("../bosch-instances-CO8yIFzJ.js");
|
|
6
6
|
let node_crypto = require("node:crypto");
|
|
7
7
|
let node_https = require("node:https");
|
|
8
8
|
let node_child_process = require("node:child_process");
|
|
@@ -11,27 +11,27 @@ let node_os = require("node:os");
|
|
|
11
11
|
let node_path = require("node:path");
|
|
12
12
|
let node_net = require("node:net");
|
|
13
13
|
//#region src/shc/custom-actions.ts
|
|
14
|
-
var boschShcActions =
|
|
15
|
-
discoverController:
|
|
16
|
-
hosts:
|
|
17
|
-
host:
|
|
18
|
-
name:
|
|
19
|
-
id:
|
|
14
|
+
var boschShcActions = require_bosch_instances.defineCustomActions({
|
|
15
|
+
discoverController: require_bosch_instances.customAction(require_bosch_instances.object({}), require_bosch_instances.object({
|
|
16
|
+
hosts: require_bosch_instances.array(require_bosch_instances.object({
|
|
17
|
+
host: require_bosch_instances.string(),
|
|
18
|
+
name: require_bosch_instances.string(),
|
|
19
|
+
id: require_bosch_instances.string()
|
|
20
20
|
})),
|
|
21
|
-
summary:
|
|
21
|
+
summary: require_bosch_instances.string()
|
|
22
22
|
}), {
|
|
23
23
|
kind: "mutation",
|
|
24
24
|
auth: "admin"
|
|
25
25
|
}),
|
|
26
|
-
registerClient:
|
|
27
|
-
host:
|
|
28
|
-
hostManual:
|
|
29
|
-
systemPassword:
|
|
30
|
-
}),
|
|
31
|
-
sslCertificate:
|
|
32
|
-
sslKey:
|
|
33
|
-
token:
|
|
34
|
-
summary:
|
|
26
|
+
registerClient: require_bosch_instances.customAction(require_bosch_instances.object({
|
|
27
|
+
host: require_bosch_instances.string().optional(),
|
|
28
|
+
hostManual: require_bosch_instances.string().optional(),
|
|
29
|
+
systemPassword: require_bosch_instances.string().min(1)
|
|
30
|
+
}), require_bosch_instances.object({
|
|
31
|
+
sslCertificate: require_bosch_instances.string().min(1).meta({ secret: true }),
|
|
32
|
+
sslKey: require_bosch_instances.string().min(1).meta({ secret: true }),
|
|
33
|
+
token: require_bosch_instances.string().min(1).meta({ secret: true }),
|
|
34
|
+
summary: require_bosch_instances.string()
|
|
35
35
|
}), {
|
|
36
36
|
kind: "mutation",
|
|
37
37
|
auth: "admin"
|
|
@@ -40,11 +40,11 @@ var boschShcActions = require_dist.defineCustomActions({
|
|
|
40
40
|
//#endregion
|
|
41
41
|
//#region src/shc/config.ts
|
|
42
42
|
/** Operator settings for one SHC integration (local mTLS + optional token). */
|
|
43
|
-
var shcConfigSchema =
|
|
44
|
-
host:
|
|
45
|
-
sslCertificate:
|
|
46
|
-
sslKey:
|
|
47
|
-
token:
|
|
43
|
+
var shcConfigSchema = require_bosch_instances.object({
|
|
44
|
+
host: require_bosch_instances.string().min(1).describe("SHC hostname or IP"),
|
|
45
|
+
sslCertificate: require_bosch_instances.string().min(1).describe("Client certificate PEM").meta({ secret: true }),
|
|
46
|
+
sslKey: require_bosch_instances.string().min(1).describe("Client private key PEM").meta({ secret: true }),
|
|
47
|
+
token: require_bosch_instances.string().optional().describe("Optional API token from the Bosch app").meta({ secret: true })
|
|
48
48
|
});
|
|
49
49
|
function connectionFromSettings(settings) {
|
|
50
50
|
const parsed = shcConfigSchema.safeParse(settings);
|
|
@@ -197,6 +197,109 @@ function buildConnectionFormSchema() {
|
|
|
197
197
|
}] };
|
|
198
198
|
}
|
|
199
199
|
//#endregion
|
|
200
|
+
//#region src/shc/shc-instances.ts
|
|
201
|
+
/**
|
|
202
|
+
* Bosch Smart Home Controller integrations as `integration-instances` (planning#416, D985,
|
|
203
|
+
* D1007): one `connections` record per controller under the `integrations` registry id. The body
|
|
204
|
+
* IS the connection (host, the client certificate and key and the optional token, all three in
|
|
205
|
+
* the keychain), so the form the instances page edits is the stored shape.
|
|
206
|
+
*/
|
|
207
|
+
var shcConnectionsEntryKind = require_bosch_instances.defineEntryKind("connections", {
|
|
208
|
+
title: "Smart Home Controllers",
|
|
209
|
+
schema: require_bosch_instances.entryBody({
|
|
210
|
+
host: require_bosch_instances.string().optional(),
|
|
211
|
+
sslCertificate: require_bosch_instances.string().optional().meta({ secret: true }),
|
|
212
|
+
sslKey: require_bosch_instances.string().optional().meta({ secret: true }),
|
|
213
|
+
token: require_bosch_instances.string().optional().meta({ secret: true })
|
|
214
|
+
}),
|
|
215
|
+
writeTrigger: "an operator pairs, edits or removes a Smart Home Controller"
|
|
216
|
+
});
|
|
217
|
+
/** Every kind this addon declares, keyed by its name. */
|
|
218
|
+
var shcRecordKinds = { connections: shcConnectionsEntryKind };
|
|
219
|
+
var LEGACY_KEYS = [
|
|
220
|
+
"host",
|
|
221
|
+
"sslCertificate",
|
|
222
|
+
"sslKey",
|
|
223
|
+
"token"
|
|
224
|
+
];
|
|
225
|
+
var SECRET_KEYS = [
|
|
226
|
+
"sslCertificate",
|
|
227
|
+
"sslKey",
|
|
228
|
+
"token"
|
|
229
|
+
];
|
|
230
|
+
function text(value) {
|
|
231
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
232
|
+
}
|
|
233
|
+
/** The record body of one controller, from its legacy rows (secrets resolved). */
|
|
234
|
+
function shcBodyFromRows(values, log, integration) {
|
|
235
|
+
const dropped = Object.keys(values).filter((key) => !LEGACY_KEYS.includes(key));
|
|
236
|
+
if (dropped.length > 0) log.warn(`integration '${integration.id}': legacy settings nothing reads any more are dropped: ${dropped.join(", ")}`);
|
|
237
|
+
const host = text(values["host"]);
|
|
238
|
+
const sslCertificate = text(values["sslCertificate"]);
|
|
239
|
+
const sslKey = text(values["sslKey"]);
|
|
240
|
+
const token = text(values["token"]);
|
|
241
|
+
return {
|
|
242
|
+
name: integration.name,
|
|
243
|
+
...host !== void 0 ? { host } : {},
|
|
244
|
+
...sslCertificate !== void 0 ? { sslCertificate } : {},
|
|
245
|
+
...sslKey !== void 0 ? { sslKey } : {},
|
|
246
|
+
...token !== void 0 ? { token } : {}
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
/** The whole `bosch-shc` catalogue (D987): offered to the engine at `onInitialize`. */
|
|
250
|
+
var SHC_MIGRATIONS = [require_bosch_instances.boschRowsMigration({
|
|
251
|
+
addonId: "bosch-shc",
|
|
252
|
+
id: "bosch-shc/2026-11-05-integration-rows-to-record",
|
|
253
|
+
description: "Move every Smart Home Controller connection into a typed instance record keyed by its registry id, then clear the legacy integration settings rows and their keychain values",
|
|
254
|
+
fixtureMark: "a legacy setting key the migration does not know",
|
|
255
|
+
kind: shcConnectionsEntryKind,
|
|
256
|
+
bodyFrom: shcBodyFromRows
|
|
257
|
+
})];
|
|
258
|
+
function shcRowsPorts(deps) {
|
|
259
|
+
return require_bosch_instances.boschRowsPorts({
|
|
260
|
+
...deps,
|
|
261
|
+
kind: shcConnectionsEntryKind
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* The live connection of one controller, read from its record. null while the connection is
|
|
266
|
+
* incomplete; a locked keychain throws so the caller keeps the client it has instead of
|
|
267
|
+
* reconfiguring it without its certificate (D49).
|
|
268
|
+
*/
|
|
269
|
+
async function shcConnectionOf(instances, id) {
|
|
270
|
+
const read = await instances.readResolved(id);
|
|
271
|
+
if (read === null) return null;
|
|
272
|
+
if (read.secrets === "unavailable") throw new Error("the keychain is locked, the saved controller credentials cannot be read");
|
|
273
|
+
return connectionFromSettings(read.body);
|
|
274
|
+
}
|
|
275
|
+
function buildShcInstances(records, deps) {
|
|
276
|
+
const handle = records.kind(shcConnectionsEntryKind);
|
|
277
|
+
const instances = new require_bosch_instances.RecordIntegrationInstances(records, shcConnectionsEntryKind, {
|
|
278
|
+
description: {
|
|
279
|
+
role: "devices",
|
|
280
|
+
instanceMode: "multiple",
|
|
281
|
+
kind: "controller",
|
|
282
|
+
canTest: true
|
|
283
|
+
},
|
|
284
|
+
formSchema: () => buildConnectionFormSchema(),
|
|
285
|
+
initialBody: (name) => ({ name }),
|
|
286
|
+
configured: (body) => connectionFromSettings(body) !== null,
|
|
287
|
+
onChanged: async (_id, change) => {
|
|
288
|
+
if (change !== "deleted") await deps.onChanged();
|
|
289
|
+
},
|
|
290
|
+
test: (input) => require_bosch_instances.testBoschInstance({
|
|
291
|
+
...input,
|
|
292
|
+
tester: deps.tester,
|
|
293
|
+
handle,
|
|
294
|
+
secretKeys: SECRET_KEYS
|
|
295
|
+
})
|
|
296
|
+
});
|
|
297
|
+
return {
|
|
298
|
+
instances,
|
|
299
|
+
provider: require_bosch_instances.keepBodyKeys(instances.toProvider(), new Set(Object.keys(shcConnectionsEntryKind.schema.shape)))
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
//#endregion
|
|
200
303
|
//#region src/shc/shc-self-signed.ts
|
|
201
304
|
/**
|
|
202
305
|
* RSA-2048 self-signed certificate. The controller stores this certificate;
|
|
@@ -388,7 +491,7 @@ function proposeShcControllers(found, existingHosts) {
|
|
|
388
491
|
function shcDiscoveryCandidates(proposals) {
|
|
389
492
|
return proposals.map((found) => ({
|
|
390
493
|
stableId: `bosch-shc:${found.id}`,
|
|
391
|
-
type:
|
|
494
|
+
type: require_bosch_instances.DeviceType.Gateway,
|
|
392
495
|
suggestedName: found.name,
|
|
393
496
|
prefilledConfig: { host: found.host },
|
|
394
497
|
setupIntegration: true
|
|
@@ -439,15 +542,15 @@ var ShcConnectionResolver = class {
|
|
|
439
542
|
var shcConnections = new ShcConnectionResolver();
|
|
440
543
|
//#endregion
|
|
441
544
|
//#region src/shc/devices/shc-device-base.ts
|
|
442
|
-
var shcDeviceSchema =
|
|
443
|
-
shcDeviceId:
|
|
444
|
-
brokerId:
|
|
445
|
-
deviceModel:
|
|
446
|
-
system:
|
|
447
|
-
integrationId:
|
|
448
|
-
tempStep:
|
|
545
|
+
var shcDeviceSchema = require_bosch_instances.object({
|
|
546
|
+
shcDeviceId: require_bosch_instances.string().min(1).describe("Bosch SHC device id"),
|
|
547
|
+
brokerId: require_bosch_instances.string().min(1).describe("Integration id"),
|
|
548
|
+
deviceModel: require_bosch_instances.string().optional(),
|
|
549
|
+
system: require_bosch_instances.literal("bosch-shc").optional(),
|
|
550
|
+
integrationId: require_bosch_instances.string().optional(),
|
|
551
|
+
tempStep: require_bosch_instances.number().positive().optional()
|
|
449
552
|
});
|
|
450
|
-
var ShcBaseDevice = class extends
|
|
553
|
+
var ShcBaseDevice = class extends require_bosch_instances.BaseDevice {
|
|
451
554
|
features = [];
|
|
452
555
|
shcDeviceId;
|
|
453
556
|
brokerId;
|
|
@@ -495,7 +598,7 @@ var ShcBaseDevice = class extends require_dist.BaseDevice {
|
|
|
495
598
|
this.refreshFromController().catch((err) => {
|
|
496
599
|
this.deviceLog("warn", "SHC refresh after controller event failed", {
|
|
497
600
|
shcDeviceId: this.shcDeviceId,
|
|
498
|
-
error:
|
|
601
|
+
error: require_bosch_instances.errMsg(err)
|
|
499
602
|
});
|
|
500
603
|
});
|
|
501
604
|
};
|
|
@@ -526,11 +629,11 @@ var ShcBaseDevice = class extends require_dist.BaseDevice {
|
|
|
526
629
|
* devices are NOT children of it; they are adopted as their own top-level
|
|
527
630
|
* devices of the same integration.
|
|
528
631
|
*/
|
|
529
|
-
var ShcGatewayDevice = class extends
|
|
632
|
+
var ShcGatewayDevice = class extends require_bosch_instances.BaseDevice {
|
|
530
633
|
features = [];
|
|
531
634
|
constructor(ctx) {
|
|
532
635
|
const cfg = shcDeviceSchema.parse(ctx.persistedConfig ?? {});
|
|
533
|
-
super(ctx, shcDeviceSchema, { type:
|
|
636
|
+
super(ctx, shcDeviceSchema, { type: require_bosch_instances.DeviceType.Gateway });
|
|
534
637
|
this.online = shcConnections.has(cfg.brokerId);
|
|
535
638
|
this.updateSourceInfo({
|
|
536
639
|
id: cfg.shcDeviceId,
|
|
@@ -558,9 +661,9 @@ function shcKindForModel(deviceModel) {
|
|
|
558
661
|
}
|
|
559
662
|
function deviceTypeForShcKind(kind) {
|
|
560
663
|
switch (kind) {
|
|
561
|
-
case "room-climate": return
|
|
562
|
-
case "trv": return
|
|
563
|
-
case "switch": return
|
|
664
|
+
case "room-climate": return require_bosch_instances.DeviceType.Container;
|
|
665
|
+
case "trv": return require_bosch_instances.DeviceType.Thermostat;
|
|
666
|
+
case "switch": return require_bosch_instances.DeviceType.Switch;
|
|
564
667
|
}
|
|
565
668
|
}
|
|
566
669
|
function capsForShcKind(kind) {
|
|
@@ -690,7 +793,7 @@ function trvCandidate(device) {
|
|
|
690
793
|
return {
|
|
691
794
|
childNativeId: device.id,
|
|
692
795
|
name: device.name.length > 0 ? device.name : device.id,
|
|
693
|
-
type:
|
|
796
|
+
type: require_bosch_instances.DeviceType.Thermostat,
|
|
694
797
|
status: "online",
|
|
695
798
|
metadata: {
|
|
696
799
|
serialNumber: device.id,
|
|
@@ -711,7 +814,7 @@ function roomClimateContainerCandidate(device, devices, adoptedId) {
|
|
|
711
814
|
const climateChild = {
|
|
712
815
|
childNativeId: `${device.id}#climate`,
|
|
713
816
|
name: shcClimateEntityName(device.name.length > 0 ? device.name : device.id),
|
|
714
|
-
type:
|
|
817
|
+
type: require_bosch_instances.DeviceType.Climate,
|
|
715
818
|
status: "online",
|
|
716
819
|
metadata: {
|
|
717
820
|
serialNumber: device.id,
|
|
@@ -730,7 +833,7 @@ function roomClimateContainerCandidate(device, devices, adoptedId) {
|
|
|
730
833
|
return {
|
|
731
834
|
childNativeId: device.id,
|
|
732
835
|
name: device.name.length > 0 ? device.name : device.id,
|
|
733
|
-
type:
|
|
836
|
+
type: require_bosch_instances.DeviceType.Container,
|
|
734
837
|
status: "online",
|
|
735
838
|
metadata: {
|
|
736
839
|
serialNumber: device.id,
|
|
@@ -765,7 +868,7 @@ function buildShcCandidates(input) {
|
|
|
765
868
|
const out = [{
|
|
766
869
|
childNativeId: gatewayId,
|
|
767
870
|
name: input.integrationName,
|
|
768
|
-
type:
|
|
871
|
+
type: require_bosch_instances.DeviceType.Gateway,
|
|
769
872
|
status: "online",
|
|
770
873
|
metadata: {
|
|
771
874
|
manufacturer: "Bosch",
|
|
@@ -886,7 +989,7 @@ var ShcRoomClimateDevice = class extends ShcBaseDevice {
|
|
|
886
989
|
super(ctx);
|
|
887
990
|
}
|
|
888
991
|
registerCaps() {
|
|
889
|
-
this.ctx.registerNativeCap(
|
|
992
|
+
this.ctx.registerNativeCap(require_bosch_instances.climateControlCapability, {
|
|
890
993
|
getStatus: async () => this.runtimeState.getCapState(CLIMATE_CAP) ?? COLD_START,
|
|
891
994
|
setMode: async ({ mode }) => {
|
|
892
995
|
const client = this.requireClient();
|
|
@@ -986,9 +1089,9 @@ var ShcTrvDevice = class extends ShcBaseDevice {
|
|
|
986
1089
|
super(ctx);
|
|
987
1090
|
}
|
|
988
1091
|
registerCaps() {
|
|
989
|
-
this.ctx.registerNativeCap(
|
|
1092
|
+
this.ctx.registerNativeCap(require_bosch_instances.temperatureSensorCapability, { getStatus: async () => this.runtimeState.getCapState(TEMP_CAP) ?? TEMP_COLD });
|
|
990
1093
|
this.runtimeState.setCapState(TEMP_CAP, TEMP_COLD);
|
|
991
|
-
this.ctx.registerNativeCap(
|
|
1094
|
+
this.ctx.registerNativeCap(require_bosch_instances.batteryCapability, {
|
|
992
1095
|
getStatus: async () => this.runtimeState.getCapState(BATTERY_CAP) ?? BATTERY_COLD,
|
|
993
1096
|
wakeForStream: async () => ({
|
|
994
1097
|
awoke: true,
|
|
@@ -996,7 +1099,7 @@ var ShcTrvDevice = class extends ShcBaseDevice {
|
|
|
996
1099
|
})
|
|
997
1100
|
});
|
|
998
1101
|
this.runtimeState.setCapState(BATTERY_CAP, BATTERY_COLD);
|
|
999
|
-
this.ctx.registerNativeCap(
|
|
1102
|
+
this.ctx.registerNativeCap(require_bosch_instances.heatingValveCapability, { getStatus: async () => this.runtimeState.getCapState(VALVE_CAP) ?? VALVE_COLD });
|
|
1000
1103
|
this.runtimeState.setCapState(VALVE_CAP, VALVE_COLD);
|
|
1001
1104
|
}
|
|
1002
1105
|
async refreshFromController() {
|
|
@@ -1043,21 +1146,21 @@ var ShcTrvDevice = class extends ShcBaseDevice {
|
|
|
1043
1146
|
};
|
|
1044
1147
|
//#endregion
|
|
1045
1148
|
//#region src/shc/devices/shc-climate-room-device.ts
|
|
1046
|
-
var shcClimateRoomChildSchema =
|
|
1047
|
-
shcDeviceId:
|
|
1048
|
-
name:
|
|
1049
|
-
role:
|
|
1149
|
+
var shcClimateRoomChildSchema = require_bosch_instances.object({
|
|
1150
|
+
shcDeviceId: require_bosch_instances.string().min(1),
|
|
1151
|
+
name: require_bosch_instances.string(),
|
|
1152
|
+
role: require_bosch_instances._enum(["climate", "trv"])
|
|
1050
1153
|
});
|
|
1051
|
-
var shcClimateRoomSchema = shcDeviceSchema.extend({ children:
|
|
1154
|
+
var shcClimateRoomSchema = shcDeviceSchema.extend({ children: require_bosch_instances.array(shcClimateRoomChildSchema).min(1) });
|
|
1052
1155
|
/** One SHC room: climate setpoint child + linked TRV accessories. */
|
|
1053
|
-
var ShcClimateRoomDevice = class extends
|
|
1156
|
+
var ShcClimateRoomDevice = class extends require_bosch_instances.BaseDevice {
|
|
1054
1157
|
features = [];
|
|
1055
1158
|
integrationId;
|
|
1056
1159
|
brokerId;
|
|
1057
1160
|
deviceModel;
|
|
1058
1161
|
constructor(ctx) {
|
|
1059
1162
|
const cfg = shcClimateRoomSchema.parse(ctx.persistedConfig ?? {});
|
|
1060
|
-
super(ctx, shcClimateRoomSchema, { type:
|
|
1163
|
+
super(ctx, shcClimateRoomSchema, { type: require_bosch_instances.DeviceType.Container });
|
|
1061
1164
|
this.brokerId = cfg.brokerId;
|
|
1062
1165
|
this.integrationId = cfg.integrationId;
|
|
1063
1166
|
this.deviceModel = cfg.deviceModel;
|
|
@@ -1082,7 +1185,7 @@ var ShcClimateRoomDevice = class extends require_dist.BaseDevice {
|
|
|
1082
1185
|
return {
|
|
1083
1186
|
stableIdSuffix: "climate",
|
|
1084
1187
|
meta: {
|
|
1085
|
-
type:
|
|
1188
|
+
type: require_bosch_instances.DeviceType.Climate,
|
|
1086
1189
|
name: shcClimateEntityName(containerName),
|
|
1087
1190
|
linkDeviceId: this.id,
|
|
1088
1191
|
...this.integrationId !== void 0 ? { integrationId: this.integrationId } : {}
|
|
@@ -1101,7 +1204,7 @@ var ShcClimateRoomDevice = class extends require_dist.BaseDevice {
|
|
|
1101
1204
|
return {
|
|
1102
1205
|
stableIdSuffix: `trv-${shcStableIdSuffixFromDeviceId(child.shcDeviceId)}`,
|
|
1103
1206
|
meta: {
|
|
1104
|
-
type:
|
|
1207
|
+
type: require_bosch_instances.DeviceType.Thermostat,
|
|
1105
1208
|
name: child.name,
|
|
1106
1209
|
linkDeviceId: this.id,
|
|
1107
1210
|
...this.integrationId !== void 0 ? { integrationId: this.integrationId } : {}
|
|
@@ -1125,7 +1228,7 @@ var ShcSwitchDevice = class extends ShcBaseDevice {
|
|
|
1125
1228
|
super(ctx);
|
|
1126
1229
|
}
|
|
1127
1230
|
registerCaps() {
|
|
1128
|
-
this.ctx.registerNativeCap(
|
|
1231
|
+
this.ctx.registerNativeCap(require_bosch_instances.switchCapability, {
|
|
1129
1232
|
getStatus: async () => this.runtimeState.getCapState(SWITCH_CAP) ?? SWITCH_COLD,
|
|
1130
1233
|
setState: async ({ on }) => {
|
|
1131
1234
|
await this.requireClient().putServiceState(this.shcDeviceId, SERVICE, buildPowerSwitchPutBody(on));
|
|
@@ -1215,12 +1318,12 @@ function buildShcAdoptionProvider(deps) {
|
|
|
1215
1318
|
lastError: null
|
|
1216
1319
|
};
|
|
1217
1320
|
} catch (err) {
|
|
1218
|
-
logger.warn("bosch-shc adoption: getStatus failed", { meta: { error:
|
|
1321
|
+
logger.warn("bosch-shc adoption: getStatus failed", { meta: { error: require_bosch_instances.errMsg(err) } });
|
|
1219
1322
|
return {
|
|
1220
1323
|
lastDiscoveryAt: null,
|
|
1221
1324
|
candidateCount: 0,
|
|
1222
1325
|
adoptedCount: 0,
|
|
1223
|
-
lastError:
|
|
1326
|
+
lastError: require_bosch_instances.errMsg(err)
|
|
1224
1327
|
};
|
|
1225
1328
|
}
|
|
1226
1329
|
},
|
|
@@ -1245,7 +1348,7 @@ function buildShcAdoptionProvider(deps) {
|
|
|
1245
1348
|
const { deviceId } = await adoptDevice({
|
|
1246
1349
|
shcDeviceId,
|
|
1247
1350
|
integrationId,
|
|
1248
|
-
type:
|
|
1351
|
+
type: require_bosch_instances.DeviceType.Gateway,
|
|
1249
1352
|
name,
|
|
1250
1353
|
deviceModel: "Smart Home Controller"
|
|
1251
1354
|
});
|
|
@@ -1283,7 +1386,7 @@ function buildShcAdoptionProvider(deps) {
|
|
|
1283
1386
|
logger.warn("bosch-shc adopt: failed", { meta: {
|
|
1284
1387
|
shcDeviceId,
|
|
1285
1388
|
integrationId,
|
|
1286
|
-
error:
|
|
1389
|
+
error: require_bosch_instances.errMsg(err)
|
|
1287
1390
|
} });
|
|
1288
1391
|
failures++;
|
|
1289
1392
|
}
|
|
@@ -23465,7 +23568,7 @@ var ShcIntegrationManager = class {
|
|
|
23465
23568
|
});
|
|
23466
23569
|
} catch (err) {
|
|
23467
23570
|
this.#status = "error";
|
|
23468
|
-
this.#error =
|
|
23571
|
+
this.#error = require_bosch_instances.errMsg(err);
|
|
23469
23572
|
this.#lastCheckedAt = Date.now();
|
|
23470
23573
|
this.#surfaceSink.set(this.#id, null);
|
|
23471
23574
|
client.close();
|
|
@@ -23489,7 +23592,7 @@ var ShcIntegrationManager = class {
|
|
|
23489
23592
|
} catch (err) {
|
|
23490
23593
|
this.#logger.warn("ShcIntegrationManager: client close failed", {
|
|
23491
23594
|
tags: { integrationId: this.#id },
|
|
23492
|
-
meta: { error:
|
|
23595
|
+
meta: { error: require_bosch_instances.errMsg(err) }
|
|
23493
23596
|
});
|
|
23494
23597
|
}
|
|
23495
23598
|
this.#onDisconnected(this.#id);
|
|
@@ -23548,7 +23651,7 @@ var ShcClientRegistry = class {
|
|
|
23548
23651
|
} catch (err) {
|
|
23549
23652
|
this.#logger.warn("ShcClientRegistry: applyConnection failed", {
|
|
23550
23653
|
tags: { integrationId },
|
|
23551
|
-
meta: { error:
|
|
23654
|
+
meta: { error: require_bosch_instances.errMsg(err) }
|
|
23552
23655
|
});
|
|
23553
23656
|
}
|
|
23554
23657
|
return;
|
|
@@ -23571,7 +23674,7 @@ var ShcClientRegistry = class {
|
|
|
23571
23674
|
} catch (err) {
|
|
23572
23675
|
this.#logger.warn("ShcClientRegistry: manager start failed", {
|
|
23573
23676
|
tags: { integrationId },
|
|
23574
|
-
meta: { error:
|
|
23677
|
+
meta: { error: require_bosch_instances.errMsg(err) }
|
|
23575
23678
|
});
|
|
23576
23679
|
}
|
|
23577
23680
|
}
|
|
@@ -23584,7 +23687,7 @@ var ShcClientRegistry = class {
|
|
|
23584
23687
|
} catch (err) {
|
|
23585
23688
|
this.#logger.warn("ShcClientRegistry: remove stop failed", {
|
|
23586
23689
|
tags: { integrationId },
|
|
23587
|
-
meta: { error:
|
|
23690
|
+
meta: { error: require_bosch_instances.errMsg(err) }
|
|
23588
23691
|
});
|
|
23589
23692
|
}
|
|
23590
23693
|
}
|
|
@@ -23600,7 +23703,7 @@ var ShcClientRegistry = class {
|
|
|
23600
23703
|
} catch (err) {
|
|
23601
23704
|
this.#logger.warn("ShcClientRegistry: shutdown stop failed", {
|
|
23602
23705
|
tags: { integrationId: id },
|
|
23603
|
-
meta: { error:
|
|
23706
|
+
meta: { error: require_bosch_instances.errMsg(err) }
|
|
23604
23707
|
});
|
|
23605
23708
|
}
|
|
23606
23709
|
}));
|
|
@@ -23695,7 +23798,7 @@ async function cascadeRemoveDevicesForIntegration(input) {
|
|
|
23695
23798
|
tags: { deviceId: d.id },
|
|
23696
23799
|
meta: {
|
|
23697
23800
|
integrationId,
|
|
23698
|
-
error:
|
|
23801
|
+
error: require_bosch_instances.errMsg(err)
|
|
23699
23802
|
}
|
|
23700
23803
|
});
|
|
23701
23804
|
}
|
|
@@ -23720,22 +23823,37 @@ function setIntegrationDevicesOnline(devices, integrationId, online) {
|
|
|
23720
23823
|
/**
|
|
23721
23824
|
* Bosch Smart Home Controller — `mode: account`, broker-less multi-integration.
|
|
23722
23825
|
*/
|
|
23723
|
-
var BoschShcProviderAddon = class extends
|
|
23826
|
+
var BoschShcProviderAddon = class extends require_bosch_instances.BaseDeviceProvider {
|
|
23724
23827
|
addonId = "bosch-shc";
|
|
23725
23828
|
providerName = "Bosch SHC";
|
|
23726
23829
|
deviceClasses = {
|
|
23727
|
-
[
|
|
23728
|
-
[
|
|
23729
|
-
[
|
|
23730
|
-
[
|
|
23731
|
-
[
|
|
23830
|
+
[require_bosch_instances.DeviceType.Gateway]: ShcGatewayDevice,
|
|
23831
|
+
[require_bosch_instances.DeviceType.Container]: ShcClimateRoomDevice,
|
|
23832
|
+
[require_bosch_instances.DeviceType.Climate]: ShcRoomClimateDevice,
|
|
23833
|
+
[require_bosch_instances.DeviceType.Thermostat]: ShcTrvDevice,
|
|
23834
|
+
[require_bosch_instances.DeviceType.Switch]: ShcSwitchDevice
|
|
23732
23835
|
};
|
|
23733
23836
|
clients = null;
|
|
23837
|
+
instances = null;
|
|
23734
23838
|
constructor() {
|
|
23735
23839
|
super({});
|
|
23736
23840
|
}
|
|
23737
23841
|
async onInitialize() {
|
|
23738
23842
|
const regs = this.providerRegistrationsFromSuper(await super.onInitialize());
|
|
23843
|
+
const records = this.ctx.records;
|
|
23844
|
+
if (records === void 0) throw new Error("bosch-shc: ctx.records is required (hub-only addon)");
|
|
23845
|
+
await records.declare(shcRecordKinds);
|
|
23846
|
+
await this.runMigrations(require_bosch_instances.defineAddonMigrations(SHC_MIGRATIONS, shcRowsPorts({
|
|
23847
|
+
api: require_bosch_instances.defaultIntegrationApiOver(this.ctx.api),
|
|
23848
|
+
secrets: this.ctx.secrets ?? null,
|
|
23849
|
+
records,
|
|
23850
|
+
warn: (message) => this.ctx.logger.warn(message)
|
|
23851
|
+
})));
|
|
23852
|
+
const built = buildShcInstances(records, {
|
|
23853
|
+
onChanged: () => this.reconcileIntegrations(),
|
|
23854
|
+
tester: this.buildConnectionTestProvider()
|
|
23855
|
+
});
|
|
23856
|
+
this.instances = built.instances;
|
|
23739
23857
|
this.clients = new ShcClientRegistry(this.ctx.logger);
|
|
23740
23858
|
this.clients.setOnConnected((integrationId) => {
|
|
23741
23859
|
this.setIntegrationDevicesOnline(integrationId, true);
|
|
@@ -23749,12 +23867,16 @@ var BoschShcProviderAddon = class extends require_dist.BaseDeviceProvider {
|
|
|
23749
23867
|
providers: [
|
|
23750
23868
|
...regs,
|
|
23751
23869
|
{
|
|
23752
|
-
capability:
|
|
23870
|
+
capability: require_bosch_instances.deviceAdoptionCapability,
|
|
23753
23871
|
provider: this.buildAdoptionProvider()
|
|
23754
23872
|
},
|
|
23755
23873
|
{
|
|
23756
|
-
capability:
|
|
23874
|
+
capability: require_bosch_instances.connectionTestCapability,
|
|
23757
23875
|
provider: this.buildConnectionTestProvider()
|
|
23876
|
+
},
|
|
23877
|
+
{
|
|
23878
|
+
capability: require_bosch_instances.integrationInstancesCapability,
|
|
23879
|
+
provider: built.provider
|
|
23758
23880
|
}
|
|
23759
23881
|
],
|
|
23760
23882
|
customActions: boschShcActions,
|
|
@@ -23793,14 +23915,12 @@ var BoschShcProviderAddon = class extends require_dist.BaseDeviceProvider {
|
|
|
23793
23915
|
try {
|
|
23794
23916
|
await this.clients?.shutdown();
|
|
23795
23917
|
} catch (err) {
|
|
23796
|
-
this.ctx.logger.warn("Bosch SHC: shutdown error", { meta: { error:
|
|
23918
|
+
this.ctx.logger.warn("Bosch SHC: shutdown error", { meta: { error: require_bosch_instances.errMsg(err) } });
|
|
23797
23919
|
}
|
|
23798
23920
|
this.clients = null;
|
|
23921
|
+
this.instances = null;
|
|
23799
23922
|
await super.onShutdown();
|
|
23800
23923
|
}
|
|
23801
|
-
globalSettingsSchema() {
|
|
23802
|
-
return buildConnectionFormSchema();
|
|
23803
|
-
}
|
|
23804
23924
|
async supportsManualCreation() {
|
|
23805
23925
|
return false;
|
|
23806
23926
|
}
|
|
@@ -23843,21 +23963,25 @@ var BoschShcProviderAddon = class extends require_dist.BaseDeviceProvider {
|
|
|
23843
23963
|
for (const integration of all) {
|
|
23844
23964
|
if (integration.addonId !== this.ctx.id) continue;
|
|
23845
23965
|
try {
|
|
23846
|
-
const connection =
|
|
23966
|
+
const connection = await shcConnectionOf(this.requireInstances(), integration.id);
|
|
23847
23967
|
if (connection) hosts.push(connection.host);
|
|
23848
23968
|
} catch (err) {
|
|
23849
23969
|
this.ctx.logger.warn("SHC discovery: settings read failed", { meta: {
|
|
23850
23970
|
integrationId: integration.id,
|
|
23851
|
-
error:
|
|
23971
|
+
error: require_bosch_instances.errMsg(err)
|
|
23852
23972
|
} });
|
|
23853
23973
|
}
|
|
23854
23974
|
}
|
|
23855
23975
|
return hosts;
|
|
23856
23976
|
} catch (err) {
|
|
23857
|
-
this.ctx.logger.warn("SHC discovery: integration list failed", { meta: { error:
|
|
23977
|
+
this.ctx.logger.warn("SHC discovery: integration list failed", { meta: { error: require_bosch_instances.errMsg(err) } });
|
|
23858
23978
|
return [];
|
|
23859
23979
|
}
|
|
23860
23980
|
}
|
|
23981
|
+
requireInstances() {
|
|
23982
|
+
if (!this.instances) throw new Error("Bosch SHC provider not initialised");
|
|
23983
|
+
return this.instances;
|
|
23984
|
+
}
|
|
23861
23985
|
requireClients() {
|
|
23862
23986
|
if (!this.clients) throw new Error("Bosch SHC provider not initialised");
|
|
23863
23987
|
return this.clients;
|
|
@@ -23868,21 +23992,21 @@ var BoschShcProviderAddon = class extends require_dist.BaseDeviceProvider {
|
|
|
23868
23992
|
const mine = (await this.ctx.api.integrations.list.query()).filter((i) => i.addonId === this.ctx.id && i.enabled);
|
|
23869
23993
|
const surviving = /* @__PURE__ */ new Set();
|
|
23870
23994
|
for (const integration of mine) try {
|
|
23871
|
-
const connection =
|
|
23995
|
+
const connection = await shcConnectionOf(this.requireInstances(), integration.id);
|
|
23872
23996
|
if (!connection) continue;
|
|
23873
23997
|
await reg.upsert(integration.id, integration.name, connection);
|
|
23874
23998
|
surviving.add(integration.id);
|
|
23875
23999
|
} catch (err) {
|
|
23876
24000
|
this.ctx.logger.warn("Bosch SHC reconcile: settings read failed", { meta: {
|
|
23877
24001
|
integrationId: integration.id,
|
|
23878
|
-
error:
|
|
24002
|
+
error: require_bosch_instances.errMsg(err)
|
|
23879
24003
|
} });
|
|
23880
24004
|
}
|
|
23881
24005
|
const vanished = reg.list().filter((id) => !surviving.has(id));
|
|
23882
24006
|
await reg.retain(surviving);
|
|
23883
24007
|
for (const integrationId of vanished) await this.cascadeRemoveDevicesForIntegration(integrationId);
|
|
23884
24008
|
} catch (err) {
|
|
23885
|
-
this.ctx.logger.warn("Bosch SHC integration reconcile failed", { meta: { error:
|
|
24009
|
+
this.ctx.logger.warn("Bosch SHC integration reconcile failed", { meta: { error: require_bosch_instances.errMsg(err) } });
|
|
23886
24010
|
}
|
|
23887
24011
|
}
|
|
23888
24012
|
subscribeIntegrationLifecycle() {
|
|
@@ -23891,9 +24015,9 @@ var BoschShcProviderAddon = class extends require_dist.BaseDeviceProvider {
|
|
|
23891
24015
|
if (typeof addonId === "string" && addonId !== this.ctx.id) return;
|
|
23892
24016
|
this.reconcileIntegrations();
|
|
23893
24017
|
};
|
|
23894
|
-
this.ctx.eventBus.subscribe({ category:
|
|
23895
|
-
this.ctx.eventBus.subscribe({ category:
|
|
23896
|
-
this.ctx.eventBus.subscribe({ category:
|
|
24018
|
+
this.ctx.eventBus.subscribe({ category: require_bosch_instances.EventCategory.IntegrationEnabled }, handler);
|
|
24019
|
+
this.ctx.eventBus.subscribe({ category: require_bosch_instances.EventCategory.IntegrationDisabled }, handler);
|
|
24020
|
+
this.ctx.eventBus.subscribe({ category: require_bosch_instances.EventCategory.IntegrationDeleted }, handler);
|
|
23897
24021
|
}
|
|
23898
24022
|
async cascadeRemoveDevicesForIntegration(integrationId) {
|
|
23899
24023
|
const reg = this.ctx.kernel.deviceRegistry;
|
|
@@ -23936,9 +24060,9 @@ var BoschShcProviderAddon = class extends require_dist.BaseDeviceProvider {
|
|
|
23936
24060
|
const devices = this.ctx.kernel.devices;
|
|
23937
24061
|
if (!devices) throw new Error("bosch-shc adopt: kernel.devices unavailable");
|
|
23938
24062
|
const summary = shcConnections.devices(integrationId).find((d) => d.id === shcDeviceId);
|
|
23939
|
-
const kind = type ===
|
|
24063
|
+
const kind = type === require_bosch_instances.DeviceType.Gateway ? "gateway" : summary ? classifyShcDevice(summary) : "unsupported";
|
|
23940
24064
|
if (kind === "unsupported") throw new Error(`bosch-shc adopt: unsupported device ${shcDeviceId}`);
|
|
23941
|
-
if (type ===
|
|
24065
|
+
if (type === require_bosch_instances.DeviceType.Gateway) {
|
|
23942
24066
|
const config = {
|
|
23943
24067
|
shcDeviceId,
|
|
23944
24068
|
brokerId: integrationId,
|
|
@@ -23947,9 +24071,9 @@ var BoschShcProviderAddon = class extends require_dist.BaseDeviceProvider {
|
|
|
23947
24071
|
integrationId,
|
|
23948
24072
|
name
|
|
23949
24073
|
};
|
|
23950
|
-
const stableId = this.generateStableId(
|
|
24074
|
+
const stableId = this.generateStableId(require_bosch_instances.DeviceType.Gateway, config);
|
|
23951
24075
|
const meta = {
|
|
23952
|
-
type:
|
|
24076
|
+
type: require_bosch_instances.DeviceType.Gateway,
|
|
23953
24077
|
name,
|
|
23954
24078
|
integrationId
|
|
23955
24079
|
};
|
|
@@ -23984,9 +24108,9 @@ var BoschShcProviderAddon = class extends require_dist.BaseDeviceProvider {
|
|
|
23984
24108
|
...baseConfig,
|
|
23985
24109
|
children
|
|
23986
24110
|
};
|
|
23987
|
-
const stableId = this.generateStableId(
|
|
24111
|
+
const stableId = this.generateStableId(require_bosch_instances.DeviceType.Container, config);
|
|
23988
24112
|
const meta = {
|
|
23989
|
-
type:
|
|
24113
|
+
type: require_bosch_instances.DeviceType.Container,
|
|
23990
24114
|
name,
|
|
23991
24115
|
integrationId
|
|
23992
24116
|
};
|