@camstack/addon-provider-bosch 0.1.34 → 0.1.36
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-R-1-uYH5.mjs → account-integration-offline-9ooJuNrN.mjs} +1 -1
- package/dist/{account-integration-offline-B7f80oHo.js → account-integration-offline-Bnm17sAE.js} +2 -2
- package/dist/{dist-DOr0p9V1.js → bosch-instances-BIvOtuzj.mjs} +34161 -30835
- package/dist/{dist-BV6iLwfA.mjs → bosch-instances-CXmuRkef.js} +36010 -32098
- package/dist/home-connect/addon.js +348 -278
- package/dist/home-connect/addon.mjs +174 -104
- package/dist/homecom/addon.js +246 -117
- package/dist/homecom/addon.mjs +164 -35
- package/dist/shc/addon.js +216 -93
- package/dist/shc/addon.mjs +129 -6
- package/package.json +17 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as createSignInAttemptStore, i as openSignInProxy, n as cascadeRemoveDevicesForIntegration, o as loginFailureForAttempt, r as createSignInClaims, s as parseOAuthCallback, t as setIntegrationDevicesOnline } from "../account-integration-offline-
|
|
1
|
+
import { $ as errMsg, B as isSecretMarkerLike, C as ingestReading, D as quantityFromUnit, E as powerMeterCapability, F as defineAddonMigrations, H as array, I as defineCustomActions, J as string, K as object, L as defineEntryKind, N as createEvent, O as runningFromDishwasherOperation, P as customAction, Q as DeviceType, R as entryBody, T as numericSensorCapability, U as boolean, V as _enum, W as literal, X as unknown, Y as union, Z as DeviceRole, _ as defaultIntegrationApiOver, a as BaseDevice, b as enumSensorCapability, c as RUNNING_STATE_COLD, d as VendorLoginProxy, et as EventCategory, g as consumablesCapability, h as connectionTestCapability, i as testBoschInstance, k as runningStateCapability, l as RecordIntegrationInstances, n as boschRowsPorts, o as BaseDeviceProvider, p as binaryCapability, q as record, r as keepBodyKeys, s as DishwasherOperationStateSchema, t as boschRowsMigration, v as deviceAdoptionCapability, w as integrationInstancesCapability, x as eventEmitterCapability, y as dishwasherCapability, z as isSecretMarker } from "../bosch-instances-BIvOtuzj.mjs";
|
|
2
|
+
import { a as createSignInAttemptStore, i as openSignInProxy, n as cascadeRemoveDevicesForIntegration, o as loginFailureForAttempt, r as createSignInClaims, s as parseOAuthCallback, t as setIntegrationDevicesOnline } from "../account-integration-offline-9ooJuNrN.mjs";
|
|
3
3
|
import { createHash, randomBytes } from "node:crypto";
|
|
4
4
|
import { connect } from "node:tls";
|
|
5
5
|
import { inflateRawSync } from "node:zlib";
|
|
@@ -1017,15 +1017,6 @@ object({
|
|
|
1017
1017
|
});
|
|
1018
1018
|
/** Setting key of the keychain-stored credentials of every paired appliance. */
|
|
1019
1019
|
var APPLIANCE_SECRETS_KEY = "applianceSecrets";
|
|
1020
|
-
/**
|
|
1021
|
-
* The integration-settings keys that hold a credential — what a write from this addon names
|
|
1022
|
-
* as `secretKeys` so the hub moves them into the keychain.
|
|
1023
|
-
*/
|
|
1024
|
-
var HOME_CONNECT_SECRET_KEYS = [
|
|
1025
|
-
"token",
|
|
1026
|
-
"refresh",
|
|
1027
|
-
APPLIANCE_SECRETS_KEY
|
|
1028
|
-
];
|
|
1029
1020
|
/** One appliance as persisted in the integration's `appliances` setting: no credential on it. */
|
|
1030
1021
|
var homeConnectApplianceRowSchema = object({
|
|
1031
1022
|
haId: string().min(1),
|
|
@@ -1127,7 +1118,7 @@ function splitApplianceSecrets(appliances) {
|
|
|
1127
1118
|
};
|
|
1128
1119
|
}
|
|
1129
1120
|
/**
|
|
1130
|
-
* Before
|
|
1121
|
+
* Before the record write: keep objects as-is (serializes as `json`), parse
|
|
1131
1122
|
* textarea JSON strings into objects so they are not re-serialized as `string` and
|
|
1132
1123
|
* corrupted on read by `deserializeSetting(String(object))` — and move any credential
|
|
1133
1124
|
* still sitting on an appliance row into `applianceSecrets`, so a row is never written
|
|
@@ -1184,29 +1175,6 @@ function moveInlineSecrets(settings) {
|
|
|
1184
1175
|
...Object.keys(merged).length > 0 ? { [APPLIANCE_SECRETS_KEY]: JSON.stringify(merged) } : {}
|
|
1185
1176
|
};
|
|
1186
1177
|
}
|
|
1187
|
-
/**
|
|
1188
|
-
* One-time adopt: the settings that must be written so a pairing key found on an appliance
|
|
1189
|
-
* row moves into the keychain. `null` when nothing needs moving. The caller writes it with
|
|
1190
|
-
* {@link HOME_CONNECT_SECRET_KEYS} as `secretKeys`.
|
|
1191
|
-
*/
|
|
1192
|
-
function legacyApplianceSecretPatch(settings) {
|
|
1193
|
-
const moved = moveInlineSecrets({
|
|
1194
|
-
...settings,
|
|
1195
|
-
appliances: parseJsonValue(settings["appliances"])
|
|
1196
|
-
});
|
|
1197
|
-
const rows = moved["appliances"];
|
|
1198
|
-
const secrets = moved[APPLIANCE_SECRETS_KEY];
|
|
1199
|
-
if (!Array.isArray(rows) || typeof secrets !== "string") return null;
|
|
1200
|
-
const parsedRows = [];
|
|
1201
|
-
for (const row of rows) {
|
|
1202
|
-
const parsed = homeConnectApplianceRowSchema.safeParse(row);
|
|
1203
|
-
if (parsed.success) parsedRows.push(parsed.data);
|
|
1204
|
-
}
|
|
1205
|
-
return {
|
|
1206
|
-
appliances: parsedRows,
|
|
1207
|
-
applianceSecrets: secrets
|
|
1208
|
-
};
|
|
1209
|
-
}
|
|
1210
1178
|
function connectionFromSettings(settings) {
|
|
1211
1179
|
const normalized = homeConnectSettingsForPersist(settings);
|
|
1212
1180
|
const rows = legacyRowsOf(normalized["appliances"]);
|
|
@@ -3690,33 +3658,23 @@ function buildHomeConnectConnectionTestProvider(deps) {
|
|
|
3690
3658
|
}
|
|
3691
3659
|
//#endregion
|
|
3692
3660
|
//#region src/home-connect/home-connect-connection-persist.ts
|
|
3693
|
-
function locked(value) {
|
|
3694
|
-
return isSecretMarker(value) || isSecretMarkerLike(value);
|
|
3695
|
-
}
|
|
3696
3661
|
/**
|
|
3697
3662
|
* Persist what a connection learned at runtime — enriched IDDF entity maps and a rotated
|
|
3698
|
-
* access / refresh token — in ONE
|
|
3699
|
-
*
|
|
3700
|
-
*
|
|
3701
|
-
* throws and never logs a value.
|
|
3663
|
+
* access / refresh token — in ONE patch of the record. Writes nothing when the stored secrets
|
|
3664
|
+
* cannot be read right now: the patch would replace a key it cannot see. Never throws and
|
|
3665
|
+
* never logs a value.
|
|
3702
3666
|
*/
|
|
3703
3667
|
function buildHomeConnectConnectionPersister(deps) {
|
|
3704
3668
|
return async (integrationId, connection) => {
|
|
3705
3669
|
if (!connection.appliances || connection.appliances.length === 0) return;
|
|
3706
3670
|
try {
|
|
3707
|
-
const
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
deps.logger.warn("Home Connect not persisting the connection — stored secrets are locked or unreadable", {
|
|
3712
|
-
tags: { integrationId },
|
|
3713
|
-
meta: {
|
|
3714
|
-
applianceSecrets: stored.kind,
|
|
3715
|
-
lockedTokens
|
|
3716
|
-
}
|
|
3717
|
-
});
|
|
3671
|
+
const stored = await deps.read(integrationId);
|
|
3672
|
+
if (stored === null) return;
|
|
3673
|
+
if (stored.locked) {
|
|
3674
|
+
deps.logger.warn("Home Connect not persisting the connection — stored secrets are locked or unreadable", { tags: { integrationId } });
|
|
3718
3675
|
return;
|
|
3719
3676
|
}
|
|
3677
|
+
const settings = stored.settings;
|
|
3720
3678
|
const refresh = connection.refresh ?? "";
|
|
3721
3679
|
const merged = homeConnectSettingsForPersist({
|
|
3722
3680
|
...settings,
|
|
@@ -3724,10 +3682,11 @@ function buildHomeConnectConnectionPersister(deps) {
|
|
|
3724
3682
|
...refresh.length > 0 ? { refresh } : {},
|
|
3725
3683
|
appliances: mergeAppliancesForPersist(settings["appliances"], connection.appliances)
|
|
3726
3684
|
});
|
|
3727
|
-
await deps.
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3685
|
+
await deps.patch(integrationId, {
|
|
3686
|
+
token: merged["token"],
|
|
3687
|
+
...merged["refresh"] !== void 0 ? { refresh: merged["refresh"] } : {},
|
|
3688
|
+
appliances: merged["appliances"],
|
|
3689
|
+
...merged["applianceSecrets"] !== void 0 ? { [APPLIANCE_SECRETS_KEY]: merged[APPLIANCE_SECRETS_KEY] } : {}
|
|
3731
3690
|
});
|
|
3732
3691
|
} catch (err) {
|
|
3733
3692
|
deps.logger.warn("Home Connect failed to persist the connection", {
|
|
@@ -5265,43 +5224,136 @@ var HomeConnectApplianceDevice = class extends BaseDevice {
|
|
|
5265
5224
|
return out;
|
|
5266
5225
|
}
|
|
5267
5226
|
};
|
|
5268
|
-
|
|
5269
|
-
|
|
5227
|
+
var homeConnectConnectionsEntryKind = defineEntryKind("connections", {
|
|
5228
|
+
title: "Home Connect accounts",
|
|
5229
|
+
schema: entryBody({
|
|
5230
|
+
token: string().optional().meta({ secret: true }),
|
|
5231
|
+
refresh: string().optional().meta({ secret: true }),
|
|
5232
|
+
/** JSON of `haId -> { psk, iv64? }`: one string in the keychain. */
|
|
5233
|
+
applianceSecrets: string().optional().meta({ secret: true }),
|
|
5234
|
+
appliances: array(homeConnectApplianceRowSchema).optional(),
|
|
5235
|
+
accountLabel: string().optional()
|
|
5236
|
+
}),
|
|
5237
|
+
writeTrigger: "an operator signs in, edits or removes a Home Connect account, or a connection stores what it learned",
|
|
5238
|
+
maxDataBytes: 1024 * 1024
|
|
5239
|
+
});
|
|
5240
|
+
/** Every kind this addon declares, keyed by its name. */
|
|
5241
|
+
var homeConnectRecordKinds = { connections: homeConnectConnectionsEntryKind };
|
|
5242
|
+
var LEGACY_KEYS = [
|
|
5243
|
+
"token",
|
|
5244
|
+
"refresh",
|
|
5245
|
+
APPLIANCE_SECRETS_KEY,
|
|
5246
|
+
"appliances",
|
|
5247
|
+
"accountLabel",
|
|
5248
|
+
"accountEmail",
|
|
5249
|
+
"accountPassword",
|
|
5250
|
+
"authorizeUrl",
|
|
5251
|
+
"verifier",
|
|
5252
|
+
"callback",
|
|
5253
|
+
"state"
|
|
5254
|
+
];
|
|
5255
|
+
var SECRET_KEYS = [
|
|
5256
|
+
"token",
|
|
5257
|
+
"refresh",
|
|
5258
|
+
APPLIANCE_SECRETS_KEY
|
|
5259
|
+
];
|
|
5260
|
+
/** The `appliances` row value as an array: a JSON string is parsed, anything else is as stored. */
|
|
5261
|
+
function parseStoredRows(raw) {
|
|
5262
|
+
if (typeof raw !== "string") return raw;
|
|
5263
|
+
try {
|
|
5264
|
+
return JSON.parse(raw);
|
|
5265
|
+
} catch {
|
|
5266
|
+
return;
|
|
5267
|
+
}
|
|
5268
|
+
}
|
|
5269
|
+
function text(value) {
|
|
5270
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
5271
|
+
}
|
|
5270
5272
|
/**
|
|
5271
|
-
*
|
|
5272
|
-
*
|
|
5273
|
-
*
|
|
5274
|
-
*
|
|
5275
|
-
* `null` when there is nothing to move — settings already migrated, or the stored keys are
|
|
5276
|
-
* locked (the move could not see what it would replace). Idempotent.
|
|
5273
|
+
* The record body of one account, from its legacy rows (secrets resolved). A pairing key still
|
|
5274
|
+
* sitting on an appliance row (the shape before the keychain move) is carried into
|
|
5275
|
+
* `applianceSecrets` here, once, and never again.
|
|
5277
5276
|
*/
|
|
5278
|
-
function
|
|
5279
|
-
const
|
|
5280
|
-
if (
|
|
5281
|
-
const
|
|
5282
|
-
|
|
5283
|
-
|
|
5277
|
+
function homeConnectBodyFromRows(values, log, integration) {
|
|
5278
|
+
const dropped = Object.keys(values).filter((key) => !LEGACY_KEYS.includes(key));
|
|
5279
|
+
if (dropped.length > 0) log.warn(`integration '${integration.id}': legacy settings nothing reads any more are dropped: ${dropped.join(", ")}`);
|
|
5280
|
+
const normalized = homeConnectSettingsForPersist({ ...values });
|
|
5281
|
+
const storedRows = parseStoredRows(values["appliances"]);
|
|
5282
|
+
if (Array.isArray(storedRows)) for (const row of storedRows) {
|
|
5283
|
+
const parsed = homeConnectApplianceRowSchema.safeParse(row);
|
|
5284
|
+
if (parsed.success) continue;
|
|
5285
|
+
const haId = typeof row === "object" && row !== null && typeof Reflect.get(row, "haId") === "string" ? String(Reflect.get(row, "haId")) : "(no haId)";
|
|
5286
|
+
const paths = parsed.error.issues.map((issue) => issue.path.join(".") || "(row)").join(", ");
|
|
5287
|
+
log.warn(`integration '${integration.id}': appliance row '${haId}' could not be read and is dropped (invalid: ${paths})`);
|
|
5288
|
+
}
|
|
5289
|
+
const appliances = [];
|
|
5290
|
+
const keptRows = normalized["appliances"];
|
|
5291
|
+
if (Array.isArray(keptRows)) for (const row of keptRows) {
|
|
5292
|
+
const parsed = homeConnectApplianceRowSchema.safeParse(row);
|
|
5293
|
+
if (parsed.success) appliances.push(parsed.data);
|
|
5294
|
+
}
|
|
5295
|
+
const token = text(normalized["token"]);
|
|
5296
|
+
const refresh = text(normalized["refresh"]);
|
|
5297
|
+
const applianceSecrets = text(normalized[APPLIANCE_SECRETS_KEY]);
|
|
5298
|
+
const accountLabel = text(normalized["accountLabel"]);
|
|
5299
|
+
return {
|
|
5300
|
+
name: integration.name,
|
|
5301
|
+
...token !== void 0 ? { token } : {},
|
|
5302
|
+
...refresh !== void 0 ? { refresh } : {},
|
|
5303
|
+
...applianceSecrets !== void 0 ? { applianceSecrets } : {},
|
|
5304
|
+
...appliances.length > 0 ? { appliances } : {},
|
|
5305
|
+
...accountLabel !== void 0 ? { accountLabel } : {}
|
|
5284
5306
|
};
|
|
5307
|
+
}
|
|
5308
|
+
/** The whole `bosch-home-connect` catalogue (D987): offered to the engine at `onInitialize`. */
|
|
5309
|
+
var HOME_CONNECT_MIGRATIONS = [boschRowsMigration({
|
|
5310
|
+
addonId: "bosch-home-connect",
|
|
5311
|
+
id: "bosch-home-connect/2026-11-05-integration-rows-to-record",
|
|
5312
|
+
description: "Move every Home Connect account into a typed instance record keyed by its registry id (pairing keys still on an appliance row go to the appliance secrets), then clear the legacy integration settings rows and their keychain values",
|
|
5313
|
+
fixtureMark: "a legacy setting key the migration does not know",
|
|
5314
|
+
kind: homeConnectConnectionsEntryKind,
|
|
5315
|
+
bodyFrom: homeConnectBodyFromRows
|
|
5316
|
+
})];
|
|
5317
|
+
function homeConnectRowsPorts(deps) {
|
|
5318
|
+
return boschRowsPorts({
|
|
5319
|
+
...deps,
|
|
5320
|
+
kind: homeConnectConnectionsEntryKind
|
|
5321
|
+
});
|
|
5322
|
+
}
|
|
5323
|
+
async function homeConnectStoredOf(instances, id) {
|
|
5324
|
+
const read = await instances.readResolved(id);
|
|
5325
|
+
if (read === null) return null;
|
|
5285
5326
|
return {
|
|
5286
|
-
settings:
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
}
|
|
5327
|
+
settings: { ...read.body },
|
|
5328
|
+
locked: read.secrets === "unavailable"
|
|
5329
|
+
};
|
|
5330
|
+
}
|
|
5331
|
+
function buildHomeConnectInstances(records, deps) {
|
|
5332
|
+
const handle = records.kind(homeConnectConnectionsEntryKind);
|
|
5333
|
+
const instances = new RecordIntegrationInstances(records, homeConnectConnectionsEntryKind, {
|
|
5334
|
+
description: {
|
|
5335
|
+
role: "devices",
|
|
5336
|
+
instanceMode: "multiple",
|
|
5337
|
+
kind: "account",
|
|
5338
|
+
canTest: true
|
|
5339
|
+
},
|
|
5340
|
+
formSchema: () => buildHomeConnectFormSchema(),
|
|
5341
|
+
initialBody: (name) => ({ name }),
|
|
5342
|
+
configured: (body) => connectionFromSettings(body) !== null,
|
|
5343
|
+
onChanged: async (_id, change) => {
|
|
5344
|
+
if (change !== "deleted") await deps.onChanged();
|
|
5345
|
+
},
|
|
5346
|
+
test: (input) => testBoschInstance({
|
|
5347
|
+
...input,
|
|
5348
|
+
tester: deps.tester,
|
|
5349
|
+
handle,
|
|
5350
|
+
secretKeys: SECRET_KEYS
|
|
5351
|
+
})
|
|
5352
|
+
});
|
|
5353
|
+
return {
|
|
5354
|
+
instances,
|
|
5355
|
+
handle,
|
|
5356
|
+
provider: keepBodyKeys(instances.toProvider(), new Set(Object.keys(homeConnectConnectionsEntryKind.schema.shape)))
|
|
5305
5357
|
};
|
|
5306
5358
|
}
|
|
5307
5359
|
//#endregion
|
|
@@ -5316,6 +5368,7 @@ var BoschHomeConnectProviderAddon = class extends BaseDeviceProvider {
|
|
|
5316
5368
|
[DeviceType.EventEmitter]: HomeConnectEventDevice
|
|
5317
5369
|
};
|
|
5318
5370
|
clients = null;
|
|
5371
|
+
instances = null;
|
|
5319
5372
|
reconciler = null;
|
|
5320
5373
|
loginProxy = null;
|
|
5321
5374
|
loginPlane = null;
|
|
@@ -5324,6 +5377,19 @@ var BoschHomeConnectProviderAddon = class extends BaseDeviceProvider {
|
|
|
5324
5377
|
}
|
|
5325
5378
|
async onInitialize() {
|
|
5326
5379
|
const regs = this.providerRegistrationsFromSuper(await super.onInitialize());
|
|
5380
|
+
const records = this.ctx.records;
|
|
5381
|
+
if (records === void 0) throw new Error("bosch-home-connect: ctx.records is required (hub-only addon)");
|
|
5382
|
+
await records.declare(homeConnectRecordKinds);
|
|
5383
|
+
await this.runMigrations(defineAddonMigrations(HOME_CONNECT_MIGRATIONS, homeConnectRowsPorts({
|
|
5384
|
+
api: defaultIntegrationApiOver(this.ctx.api),
|
|
5385
|
+
records,
|
|
5386
|
+
warn: (message) => this.ctx.logger.warn(message)
|
|
5387
|
+
})));
|
|
5388
|
+
const built = buildHomeConnectInstances(records, {
|
|
5389
|
+
onChanged: () => this.reconcileIntegrations(),
|
|
5390
|
+
tester: this.buildConnectionTestProvider()
|
|
5391
|
+
});
|
|
5392
|
+
this.instances = built;
|
|
5327
5393
|
await this.serveLoginProxy();
|
|
5328
5394
|
this.clients = new HomeConnectClientRegistry(this.ctx.logger, { onConnectionUpdated: (integrationId, connection) => {
|
|
5329
5395
|
this.persistIntegrationAppliances(integrationId, connection);
|
|
@@ -5349,6 +5415,10 @@ var BoschHomeConnectProviderAddon = class extends BaseDeviceProvider {
|
|
|
5349
5415
|
{
|
|
5350
5416
|
capability: connectionTestCapability,
|
|
5351
5417
|
provider: this.buildConnectionTestProvider()
|
|
5418
|
+
},
|
|
5419
|
+
{
|
|
5420
|
+
capability: integrationInstancesCapability,
|
|
5421
|
+
provider: built.provider
|
|
5352
5422
|
}
|
|
5353
5423
|
],
|
|
5354
5424
|
customActions: homeConnectActions,
|
|
@@ -5408,6 +5478,7 @@ var BoschHomeConnectProviderAddon = class extends BaseDeviceProvider {
|
|
|
5408
5478
|
this.ctx.logger.warn("Home Connect shutdown error", { meta: { error: errMsg(err) } });
|
|
5409
5479
|
}
|
|
5410
5480
|
this.clients = null;
|
|
5481
|
+
this.instances = null;
|
|
5411
5482
|
await super.onShutdown();
|
|
5412
5483
|
}
|
|
5413
5484
|
requireClients() {
|
|
@@ -5425,8 +5496,8 @@ var BoschHomeConnectProviderAddon = class extends BaseDeviceProvider {
|
|
|
5425
5496
|
/** Enriched IDDF maps and a rotated token pair, in one keychain-aware write. */
|
|
5426
5497
|
persistIntegrationAppliances(integrationId, connection) {
|
|
5427
5498
|
return buildHomeConnectConnectionPersister({
|
|
5428
|
-
|
|
5429
|
-
|
|
5499
|
+
read: (id) => homeConnectStoredOf(this.requireInstances().instances, id),
|
|
5500
|
+
patch: (id, patch) => this.requireInstances().handle.patch(id, patch),
|
|
5430
5501
|
logger: this.ctx.logger
|
|
5431
5502
|
})(integrationId, connection);
|
|
5432
5503
|
}
|
|
@@ -5435,15 +5506,14 @@ var BoschHomeConnectProviderAddon = class extends BaseDeviceProvider {
|
|
|
5435
5506
|
try {
|
|
5436
5507
|
const mine = (await this.ctx.api.integrations.list.query()).filter((i) => i.addonId === this.ctx.id && i.enabled);
|
|
5437
5508
|
const surviving = /* @__PURE__ */ new Set();
|
|
5438
|
-
const secretMoves = [];
|
|
5439
5509
|
for (const integration of mine) try {
|
|
5440
|
-
const stored = await this.
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
const settings =
|
|
5510
|
+
const stored = await homeConnectStoredOf(this.requireInstances().instances, integration.id);
|
|
5511
|
+
if (stored === null) continue;
|
|
5512
|
+
if (stored.locked) {
|
|
5513
|
+
this.ctx.logger.warn("Home Connect reconcile skipped: the keychain is locked", { meta: { integrationId: integration.id } });
|
|
5514
|
+
continue;
|
|
5515
|
+
}
|
|
5516
|
+
const settings = stored.settings;
|
|
5447
5517
|
const connection = connectionFromSettings(settings);
|
|
5448
5518
|
if (!connection) {
|
|
5449
5519
|
logHomeConnectSettingsGap(this.ctx.logger, integration.id, settings);
|
|
@@ -5467,7 +5537,6 @@ var BoschHomeConnectProviderAddon = class extends BaseDeviceProvider {
|
|
|
5467
5537
|
error: errMsg(err)
|
|
5468
5538
|
} });
|
|
5469
5539
|
}
|
|
5470
|
-
for (const move of secretMoves) move.persist();
|
|
5471
5540
|
const vanished = reg.list().filter((id) => !surviving.has(id));
|
|
5472
5541
|
await reg.retain(surviving);
|
|
5473
5542
|
const deviceReg = this.ctx.kernel.deviceRegistry;
|
|
@@ -5595,9 +5664,6 @@ var BoschHomeConnectProviderAddon = class extends BaseDeviceProvider {
|
|
|
5595
5664
|
logger: this.ctx.logger
|
|
5596
5665
|
}, trigger);
|
|
5597
5666
|
}
|
|
5598
|
-
globalSettingsSchema() {
|
|
5599
|
-
return buildHomeConnectFormSchema();
|
|
5600
|
-
}
|
|
5601
5667
|
async supportsManualCreation() {
|
|
5602
5668
|
return false;
|
|
5603
5669
|
}
|
|
@@ -5607,6 +5673,10 @@ var BoschHomeConnectProviderAddon = class extends BaseDeviceProvider {
|
|
|
5607
5673
|
async onCreateDevice(_type, _config) {
|
|
5608
5674
|
throw new Error("Home Connect devices are adopted from the gateway");
|
|
5609
5675
|
}
|
|
5676
|
+
requireInstances() {
|
|
5677
|
+
if (!this.instances) throw new Error("Home Connect provider not initialised");
|
|
5678
|
+
return this.instances;
|
|
5679
|
+
}
|
|
5610
5680
|
setIntegrationDevicesOnline(integrationId, online) {
|
|
5611
5681
|
const reg = this.ctx.kernel.deviceRegistry;
|
|
5612
5682
|
if (!reg) return;
|