@camstack/addon-provider-bosch 0.1.46 → 0.1.48

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.
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_bosch_instances = require("../bosch-instances-BD-Valeo.js");
3
- const require_account_integration_offline = require("../account-integration-offline-BfsMnlJo.js");
2
+ const require_bosch_instances = require("../bosch-instances-CRvxRbDk.js");
3
+ const require_account_integration_offline = require("../account-integration-offline-CQ7UB6U_.js");
4
4
  let node_crypto = require("node:crypto");
5
5
  let node_tls = require("node:tls");
6
6
  let node_zlib = require("node:zlib");
@@ -1,5 +1,5 @@
1
- import { A as RecordIntegrationInstances, B as array, C as powerMeterCapability, E as runningStateCapability, F as entryBody, G as string, I as isSecretMarker, J as DeviceRole, K as union, L as isSecretMarkerLike, M as customAction, N as defineCustomActions, P as defineEntryKind, R as rowsDepsOver, S as numericSensorCapability, T as runningFromDishwasherOperation, U as object, V as literal, W as record, X as errMsg, Y as DeviceType, Z as EventCategory, a as BaseDevice, b as ingestReading, c as RUNNING_STATE_COLD, f as consumablesCapability, g as eventEmitterCapability, h as enumSensorCapability, i as testBoschInstance, j as createEvent, m as dishwasherCapability, n as boschRowsPorts, o as BaseDeviceProvider, p as deviceAdoptionCapability, q as unknown, r as keepBodyKeys, s as DishwasherOperationStateSchema, t as boschRowsMigration, u as binaryCapability, w as quantityFromUnit, x as integrationInstancesCapability, z as _enum } from "../bosch-instances-DkUo6BfT.mjs";
2
- import { a as loginFailureForAttempt, c as HOME_CONNECT_REDIRECT_URI, i as createSignInAttemptStore, n as cascadeRemoveDevicesForIntegration, o as parseOAuthCallback, r as buildSignInGuideFields, t as setIntegrationDevicesOnline } from "../account-integration-offline-BGH1q3tj.mjs";
1
+ import { A as RecordIntegrationInstances, B as array, C as powerMeterCapability, E as runningStateCapability, F as entryBody, G as string, I as isSecretMarker, J as DeviceRole, K as union, L as isSecretMarkerLike, M as customAction, N as defineCustomActions, P as defineEntryKind, R as rowsDepsOver, S as numericSensorCapability, T as runningFromDishwasherOperation, U as object, V as literal, W as record, X as errMsg, Y as DeviceType, Z as EventCategory, a as BaseDevice, b as ingestReading, c as RUNNING_STATE_COLD, f as consumablesCapability, g as eventEmitterCapability, h as enumSensorCapability, i as testBoschInstance, j as createEvent, m as dishwasherCapability, n as boschRowsPorts, o as BaseDeviceProvider, p as deviceAdoptionCapability, q as unknown, r as keepBodyKeys, s as DishwasherOperationStateSchema, t as boschRowsMigration, u as binaryCapability, w as quantityFromUnit, x as integrationInstancesCapability, z as _enum } from "../bosch-instances-t9x1fGVW.mjs";
2
+ import { a as loginFailureForAttempt, c as HOME_CONNECT_REDIRECT_URI, i as createSignInAttemptStore, n as cascadeRemoveDevicesForIntegration, o as parseOAuthCallback, r as buildSignInGuideFields, t as setIntegrationDevicesOnline } from "../account-integration-offline-DLCUxCxS.mjs";
3
3
  import { createHash, randomBytes } from "node:crypto";
4
4
  import { connect } from "node:tls";
5
5
  import { inflateRawSync } from "node:zlib";
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_bosch_instances = require("../bosch-instances-BD-Valeo.js");
3
- const require_account_integration_offline = require("../account-integration-offline-BfsMnlJo.js");
2
+ const require_bosch_instances = require("../bosch-instances-CRvxRbDk.js");
3
+ const require_account_integration_offline = require("../account-integration-offline-CQ7UB6U_.js");
4
4
  let node_crypto = require("node:crypto");
5
5
  //#region src/homecom/config.ts
6
6
  var HOMECOM_BRANDS = ["bosch", "buderus"];
@@ -1807,6 +1807,129 @@ function buildHomeComGatewayPersister(deps) {
1807
1807
  return (integrationId, gatewayId) => patch(integrationId, { gatewayId });
1808
1808
  }
1809
1809
  //#endregion
1810
+ //#region src/homecom/homecom-gateway.ts
1811
+ /** Stable id of one HomeCom device. Adoption matches an existing row on this. */
1812
+ function homeComStableId(integrationId, nativeId) {
1813
+ return `homecom:${integrationId}:${nativeId}`;
1814
+ }
1815
+ /** The hot-water child of a heat pump. A boiler's own row keeps its longer name. */
1816
+ var HOMECOM_HOT_WATER_CHILD_NAME = "Hot water";
1817
+ var HomeComConnectionResolver = class {
1818
+ #surfaces = /* @__PURE__ */ new Map();
1819
+ set(integrationId, surface) {
1820
+ if (surface === null) {
1821
+ this.#surfaces.delete(integrationId);
1822
+ return;
1823
+ }
1824
+ this.#surfaces.set(integrationId, surface);
1825
+ }
1826
+ has(integrationId) {
1827
+ return this.#surfaces.has(integrationId);
1828
+ }
1829
+ list() {
1830
+ return Array.from(this.#surfaces.keys()).map((id) => ({ id }));
1831
+ }
1832
+ discoverables(integrationId) {
1833
+ return this.#surfaces.get(integrationId)?.discoverables ?? [];
1834
+ }
1835
+ getClient(integrationId) {
1836
+ return this.#surfaces.get(integrationId)?.client ?? null;
1837
+ }
1838
+ getSnapshot(integrationId) {
1839
+ return this.#surfaces.get(integrationId)?.snapshot ?? null;
1840
+ }
1841
+ updateSnapshot(integrationId, snapshot) {
1842
+ const existing = this.#surfaces.get(integrationId);
1843
+ if (!existing) return;
1844
+ this.#surfaces.set(integrationId, {
1845
+ ...existing,
1846
+ snapshot,
1847
+ discoverables: buildDiscoverables(snapshot)
1848
+ });
1849
+ }
1850
+ clear() {
1851
+ this.#surfaces.clear();
1852
+ }
1853
+ };
1854
+ var BOILER_DHW_NAME = "Domestic hot water";
1855
+ function circuitDiscoverable(circuit) {
1856
+ return {
1857
+ nativeId: `hc:${circuit.id}`,
1858
+ name: circuit.name,
1859
+ kind: "heating-circuit",
1860
+ circuitId: circuit.id
1861
+ };
1862
+ }
1863
+ function dhwDiscoverable(name) {
1864
+ return {
1865
+ nativeId: "dhw:0",
1866
+ name,
1867
+ kind: "dhw"
1868
+ };
1869
+ }
1870
+ /**
1871
+ * A gateway with a heat pump is one pick. A boiler still offers each circuit
1872
+ * and the hot-water row on its own.
1873
+ */
1874
+ function buildDiscoverables(snapshot) {
1875
+ const circuits = snapshot.circuits.map(circuitDiscoverable);
1876
+ if (snapshot.heatPump !== void 0) return [{
1877
+ nativeId: "hp:0",
1878
+ name: "Heat pump",
1879
+ kind: "heat-pump",
1880
+ children: [...circuits, ...snapshot.dhw === null ? [] : [dhwDiscoverable(HOMECOM_HOT_WATER_CHILD_NAME)]]
1881
+ }];
1882
+ return [...circuits, ...snapshot.dhw === null ? [] : [dhwDiscoverable(BOILER_DHW_NAME)]];
1883
+ }
1884
+ var homeComConnections = new HomeComConnectionResolver();
1885
+ //#endregion
1886
+ //#region src/homecom/homecom-adoption-plan.ts
1887
+ function createOf(device, parentNativeId) {
1888
+ return {
1889
+ nativeId: device.nativeId,
1890
+ name: device.name,
1891
+ kind: device.kind,
1892
+ circuitId: device.circuitId,
1893
+ parentNativeId
1894
+ };
1895
+ }
1896
+ /**
1897
+ * The devices one pick creates. A heat pump also creates its children, except
1898
+ * a circuit or hot-water row that already exists: a top-level one is reported
1899
+ * so the caller can log why it stayed there, and any existing row is not
1900
+ * created again.
1901
+ */
1902
+ function planHomeComAdoption(device, integrationId, adopted) {
1903
+ const root = createOf(device, null);
1904
+ if (device.kind !== "heat-pump") return {
1905
+ create: [root],
1906
+ stayedTopLevel: [],
1907
+ alreadyPresent: []
1908
+ };
1909
+ const byStableId = new Map(adopted.map((row) => [row.stableId, row]));
1910
+ const create = [root];
1911
+ const stayedTopLevel = [];
1912
+ const alreadyPresent = [];
1913
+ for (const child of device.children ?? []) {
1914
+ const existing = byStableId.get(homeComStableId(integrationId, child.nativeId));
1915
+ if (existing === void 0) {
1916
+ create.push(createOf(child, device.nativeId));
1917
+ continue;
1918
+ }
1919
+ const skip = {
1920
+ nativeId: child.nativeId,
1921
+ deviceId: existing.id
1922
+ };
1923
+ if (existing.parentDeviceId === null) stayedTopLevel.push(skip);
1924
+ else alreadyPresent.push(skip);
1925
+ }
1926
+ return {
1927
+ create,
1928
+ stayedTopLevel,
1929
+ alreadyPresent
1930
+ };
1931
+ }
1932
+ //#endregion
1810
1933
  //#region src/homecom/homecom-discovery.ts
1811
1934
  function buildHomeComCandidates(input) {
1812
1935
  const out = [];
@@ -1826,6 +1949,9 @@ function buildHomeComCandidates(input) {
1826
1949
  }
1827
1950
  return out;
1828
1951
  }
1952
+ function homeComDeviceType(kind) {
1953
+ return shapeOf(kind).type;
1954
+ }
1829
1955
  function shapeOf(kind) {
1830
1956
  switch (kind) {
1831
1957
  case "heating-circuit": return {
@@ -1849,6 +1975,62 @@ var DEVICES_FILTER = {
1849
1975
  label: "Devices",
1850
1976
  isDefault: true
1851
1977
  };
1978
+ var STAYED_TOP_LEVEL = "HomeCom device stayed top-level: it was already adopted, so it was not created again under the heat pump";
1979
+ var ALREADY_PRESENT = "HomeCom device was not created again: a device with this stable id already exists";
1980
+ async function adoptOne(input) {
1981
+ const { dev, integrationId, name, known, adoptDevice, logger, logOnce } = input;
1982
+ const plan = planHomeComAdoption(dev, integrationId, known);
1983
+ for (const skip of plan.stayedTopLevel) logOnce(skip.deviceId, STAYED_TOP_LEVEL);
1984
+ for (const skip of plan.alreadyPresent) logOnce(skip.deviceId, ALREADY_PRESENT);
1985
+ const root = plan.create[0];
1986
+ if (root === void 0) return { ok: false };
1987
+ let parentDeviceId;
1988
+ try {
1989
+ parentDeviceId = (await adoptDevice({
1990
+ nativeId: root.nativeId,
1991
+ integrationId,
1992
+ type: homeComDeviceType(root.kind),
1993
+ name,
1994
+ kind: root.kind,
1995
+ ...root.circuitId === void 0 ? {} : { circuitId: root.circuitId },
1996
+ parentDeviceId: null
1997
+ })).deviceId;
1998
+ } catch (err) {
1999
+ logger.warn("homecom adopt failed", { meta: {
2000
+ nativeId: root.nativeId,
2001
+ integrationId,
2002
+ error: require_bosch_instances.errMsg(err)
2003
+ } });
2004
+ return { ok: false };
2005
+ }
2006
+ const accessoryDeviceIds = [];
2007
+ for (const child of plan.create.slice(1)) try {
2008
+ const created = await adoptDevice({
2009
+ nativeId: child.nativeId,
2010
+ integrationId,
2011
+ type: homeComDeviceType(child.kind),
2012
+ name: child.name,
2013
+ kind: child.kind,
2014
+ ...child.circuitId === void 0 ? {} : { circuitId: child.circuitId },
2015
+ parentDeviceId
2016
+ });
2017
+ accessoryDeviceIds.push(created.deviceId);
2018
+ } catch (err) {
2019
+ logger.warn("homecom adopt child failed", {
2020
+ tags: { deviceId: parentDeviceId },
2021
+ meta: {
2022
+ nativeId: child.nativeId,
2023
+ integrationId,
2024
+ error: require_bosch_instances.errMsg(err)
2025
+ }
2026
+ });
2027
+ }
2028
+ return {
2029
+ ok: true,
2030
+ parentDeviceId,
2031
+ accessoryDeviceIds
2032
+ };
2033
+ }
1852
2034
  async function adoptedMapForIntegration(integrationId, listAdopted) {
1853
2035
  const all = await listAdopted();
1854
2036
  const map = /* @__PURE__ */ new Map();
@@ -1860,6 +2042,12 @@ async function adoptedMapForIntegration(integrationId, listAdopted) {
1860
2042
  }
1861
2043
  function buildHomeComAdoptionProvider(deps) {
1862
2044
  const { registry, hasIntegration, listIntegrations, listAdopted, adoptDevice, removeDevice, findDeviceConfig, logger } = deps;
2045
+ const logged = /* @__PURE__ */ new Set();
2046
+ const logOnce = (deviceId, message) => {
2047
+ if (logged.has(deviceId)) return;
2048
+ logged.add(deviceId);
2049
+ logger.info(message, { tags: { deviceId } });
2050
+ };
1863
2051
  async function allCandidatesForIntegration(integrationId) {
1864
2052
  return buildHomeComCandidates({
1865
2053
  devices: registry.discoverables(integrationId),
@@ -1914,48 +2102,36 @@ function buildHomeComAdoptionProvider(deps) {
1914
2102
  adopt: async ({ integrationId, childNativeIds, perCandidate }) => {
1915
2103
  if (!registry.has(integrationId)) throw new Error(`homecom adopt: integration ${integrationId} not connected`);
1916
2104
  const devices = registry.discoverables(integrationId);
2105
+ const known = await listAdopted();
1917
2106
  const adopted = [];
1918
2107
  let failures = 0;
1919
- for (const nativeId of childNativeIds) try {
2108
+ for (const nativeId of childNativeIds) {
1920
2109
  const dev = devices.find((d) => d.nativeId === nativeId);
1921
2110
  if (!dev) {
1922
2111
  failures++;
1923
2112
  continue;
1924
2113
  }
1925
- const candidate = buildHomeComCandidates({
1926
- devices: [dev],
1927
- adopted: /* @__PURE__ */ new Map()
1928
- })[0];
1929
- if (!candidate) {
2114
+ const outcome = await adoptOne({
2115
+ dev,
2116
+ integrationId,
2117
+ name: perCandidate?.[nativeId]?.name ?? dev.name,
2118
+ known,
2119
+ adoptDevice,
2120
+ logger,
2121
+ logOnce
2122
+ });
2123
+ if (!outcome.ok) {
1930
2124
  failures++;
1931
2125
  continue;
1932
2126
  }
1933
- const name = perCandidate?.[nativeId]?.name ?? dev.name;
1934
- const { deviceId } = await adoptDevice({
1935
- nativeId,
1936
- integrationId,
1937
- type: candidate.type,
1938
- name,
1939
- kind: dev.kind,
1940
- circuitId: dev.circuitId
1941
- });
1942
2127
  adopted.push({
1943
2128
  childNativeId: nativeId,
1944
- parentDeviceId: deviceId
2129
+ parentDeviceId: outcome.parentDeviceId,
2130
+ accessoryDeviceIds: outcome.accessoryDeviceIds
1945
2131
  });
1946
- } catch (err) {
1947
- logger.warn("homecom adopt failed", { meta: {
1948
- nativeId,
1949
- integrationId,
1950
- error: require_bosch_instances.errMsg(err)
1951
- } });
1952
- failures++;
1953
2132
  }
1954
2133
  if (adopted.length === 0 && failures > 0) throw new Error(`homecom adopt: all ${failures} adopt(s) failed`);
1955
- return { adopted: adopted.map((a) => ({
1956
- ...a,
1957
- accessoryDeviceIds: []
1958
- })) };
2134
+ return { adopted };
1959
2135
  },
1960
2136
  release: async ({ camDeviceId }) => {
1961
2137
  await removeDevice(camDeviceId);
@@ -1975,66 +2151,6 @@ function buildHomeComAdoptionProvider(deps) {
1975
2151
  };
1976
2152
  }
1977
2153
  //#endregion
1978
- //#region src/homecom/homecom-gateway.ts
1979
- var HomeComConnectionResolver = class {
1980
- #surfaces = /* @__PURE__ */ new Map();
1981
- set(integrationId, surface) {
1982
- if (surface === null) {
1983
- this.#surfaces.delete(integrationId);
1984
- return;
1985
- }
1986
- this.#surfaces.set(integrationId, surface);
1987
- }
1988
- has(integrationId) {
1989
- return this.#surfaces.has(integrationId);
1990
- }
1991
- list() {
1992
- return Array.from(this.#surfaces.keys()).map((id) => ({ id }));
1993
- }
1994
- discoverables(integrationId) {
1995
- return this.#surfaces.get(integrationId)?.discoverables ?? [];
1996
- }
1997
- getClient(integrationId) {
1998
- return this.#surfaces.get(integrationId)?.client ?? null;
1999
- }
2000
- getSnapshot(integrationId) {
2001
- return this.#surfaces.get(integrationId)?.snapshot ?? null;
2002
- }
2003
- updateSnapshot(integrationId, snapshot) {
2004
- const existing = this.#surfaces.get(integrationId);
2005
- if (!existing) return;
2006
- this.#surfaces.set(integrationId, {
2007
- ...existing,
2008
- snapshot,
2009
- discoverables: buildDiscoverables(snapshot)
2010
- });
2011
- }
2012
- clear() {
2013
- this.#surfaces.clear();
2014
- }
2015
- };
2016
- function buildDiscoverables(snapshot) {
2017
- const out = [];
2018
- for (const circuit of snapshot.circuits) out.push({
2019
- nativeId: `hc:${circuit.id}`,
2020
- name: circuit.name,
2021
- kind: "heating-circuit",
2022
- circuitId: circuit.id
2023
- });
2024
- if (snapshot.dhw) out.push({
2025
- nativeId: "dhw:0",
2026
- name: "Domestic hot water",
2027
- kind: "dhw"
2028
- });
2029
- if (snapshot.heatPump !== void 0) out.push({
2030
- nativeId: "hp:0",
2031
- name: "Heat pump",
2032
- kind: "heat-pump"
2033
- });
2034
- return out;
2035
- }
2036
- var homeComConnections = new HomeComConnectionResolver();
2037
- //#endregion
2038
2154
  //#region src/homecom/homecom-integration-manager.ts
2039
2155
  var HomeComIntegrationManager = class {
2040
2156
  #id;
@@ -2933,7 +3049,7 @@ var BoschHomeComProviderAddon = class extends require_bosch_instances.BaseDevice
2933
3049
  if (typeof integrationId !== "string" || integrationId.length === 0) throw new Error("homecom generateStableId: brokerId required");
2934
3050
  const nativeId = config?.["nativeId"];
2935
3051
  if (typeof nativeId !== "string" || nativeId.length === 0) throw new Error("homecom generateStableId: nativeId required");
2936
- return `homecom:${integrationId}:${nativeId}`;
3052
+ return homeComStableId(integrationId, nativeId);
2937
3053
  }
2938
3054
  async reconcileIntegrations() {
2939
3055
  const reg = this.requireClients();
@@ -2995,12 +3111,14 @@ var BoschHomeComProviderAddon = class extends require_bosch_instances.BaseDevice
2995
3111
  const config = await devices.loadConfig(d.id).catch(() => ({}));
2996
3112
  out.push({
2997
3113
  id: d.id,
3114
+ stableId: d.stableId,
3115
+ parentDeviceId: d.parentDeviceId,
2998
3116
  config
2999
3117
  });
3000
3118
  }
3001
3119
  return out;
3002
3120
  },
3003
- adoptDevice: async ({ nativeId, integrationId, type, name, kind, circuitId }) => {
3121
+ adoptDevice: async ({ nativeId, integrationId, type, name, kind, circuitId, parentDeviceId }) => {
3004
3122
  const devices = this.ctx.kernel.devices;
3005
3123
  if (!devices) throw new Error("homecom adopt: devices unavailable");
3006
3124
  const config = {
@@ -3014,7 +3132,7 @@ var BoschHomeComProviderAddon = class extends require_bosch_instances.BaseDevice
3014
3132
  const stableId = this.generateStableId(type, config);
3015
3133
  const DeviceClass = this.deviceClasses[type];
3016
3134
  if (!DeviceClass) throw new Error(`homecom adopt: unsupported type ${type}`);
3017
- return { deviceId: (await devices.create(stableId, DeviceClass, config, null, {
3135
+ return { deviceId: (await devices.create(stableId, DeviceClass, config, parentDeviceId, {
3018
3136
  type,
3019
3137
  name,
3020
3138
  integrationId