@camstack/addon-provider-bosch 0.1.51 → 0.1.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/{account-integration-offline-7CH3r5jI.js → account-integration-offline-BEzGeJcl.js} +1 -1
- package/dist/{account-integration-offline-B1Wgr_rT.mjs → account-integration-offline-D5vjmfia.mjs} +1 -1
- package/dist/{bosch-instances-CdvcBYye.mjs → bosch-instances-DSE6IXdU.mjs} +775 -213
- package/dist/{bosch-instances-CYBnIcHg.js → bosch-instances-LWbVnsaD.js} +780 -212
- package/dist/home-connect/addon.js +2 -2
- package/dist/home-connect/addon.mjs +2 -2
- package/dist/homecom/addon.js +14 -7
- package/dist/homecom/addon.mjs +14 -7
- package/dist/shc/addon.js +163 -133
- package/dist/shc/addon.mjs +163 -133
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_bosch_instances = require("../bosch-instances-
|
|
3
|
-
const require_account_integration_offline = require("../account-integration-offline-
|
|
2
|
+
const require_bosch_instances = require("../bosch-instances-LWbVnsaD.js");
|
|
3
|
+
const require_account_integration_offline = require("../account-integration-offline-BEzGeJcl.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 { $ as
|
|
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-
|
|
1
|
+
import { $ as errMsg, B as _enum, C as powerMeterCapability, D as runningStateCapability, E as runningFromDishwasherOperation, F as defineEntryKind, H as array, I as entryBody, J as string, K as object, L as isSecretMarker, M as createEvent, N as customAction, P as defineCustomActions, Q as DeviceType, R as isSecretMarkerLike, S as numericSensorCapability, W as literal, X as unknown, Y as union, Z as DeviceRole, a as BaseDevice, b as ingestReading, c as RUNNING_STATE_COLD, et as EventCategory, f as consumablesCapability, g as eventEmitterCapability, h as enumSensorCapability, i as testBoschInstance, j as RecordIntegrationInstances, m as dishwasherCapability, n as boschRowsPorts, o as BaseDeviceProvider, p as deviceAdoptionCapability, q as record, r as keepBodyKeys, s as DishwasherOperationStateSchema, t as boschRowsMigration, u as binaryCapability, w as quantityFromUnit, x as integrationInstancesCapability, z as rowsDepsOver } from "../bosch-instances-DSE6IXdU.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-D5vjmfia.mjs";
|
|
3
3
|
import { createHash, randomBytes } from "node:crypto";
|
|
4
4
|
import { connect } from "node:tls";
|
|
5
5
|
import { inflateRawSync } from "node:zlib";
|
package/dist/homecom/addon.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_bosch_instances = require("../bosch-instances-
|
|
3
|
-
const require_account_integration_offline = require("../account-integration-offline-
|
|
2
|
+
const require_bosch_instances = require("../bosch-instances-LWbVnsaD.js");
|
|
3
|
+
const require_account_integration_offline = require("../account-integration-offline-BEzGeJcl.js");
|
|
4
4
|
let node_crypto = require("node:crypto");
|
|
5
5
|
let node_child_process = require("node:child_process");
|
|
6
6
|
let node_fs = require("node:fs");
|
|
@@ -3316,7 +3316,10 @@ var HomeComClimateDevice = class extends require_bosch_instances.BaseDevice {
|
|
|
3316
3316
|
#circuitId;
|
|
3317
3317
|
constructor(ctx) {
|
|
3318
3318
|
const persisted = homeComClimateSchema.parse(ctx.persistedConfig ?? {});
|
|
3319
|
-
super(ctx, homeComClimateSchema, {
|
|
3319
|
+
super(ctx, homeComClimateSchema, {
|
|
3320
|
+
type: ctx.deviceMeta.type,
|
|
3321
|
+
role: require_bosch_instances.DeviceRole.ClimateHeatPumpCircuit
|
|
3322
|
+
});
|
|
3320
3323
|
this.#brokerId = persisted.brokerId;
|
|
3321
3324
|
this.#circuitId = persisted.circuitId;
|
|
3322
3325
|
this.online = true;
|
|
@@ -3348,7 +3351,7 @@ var HomeComClimateDevice = class extends require_bosch_instances.BaseDevice {
|
|
|
3348
3351
|
return client;
|
|
3349
3352
|
}
|
|
3350
3353
|
registerClimateCap() {
|
|
3351
|
-
|
|
3354
|
+
const provider = {
|
|
3352
3355
|
getStatus: async () => {
|
|
3353
3356
|
this.refreshFromSnapshot();
|
|
3354
3357
|
return this.runtimeState.getCapState(CLIMATE_CAP) ?? COLD_START$2;
|
|
@@ -3383,7 +3386,9 @@ var HomeComClimateDevice = class extends require_bosch_instances.BaseDevice {
|
|
|
3383
3386
|
await this.requireClient().setSwingHorizontal(this.#circuitId, on);
|
|
3384
3387
|
this.refreshFromSnapshot();
|
|
3385
3388
|
}
|
|
3386
|
-
}
|
|
3389
|
+
};
|
|
3390
|
+
this.ctx.registerNativeCap(require_bosch_instances.climateControlCapability, provider);
|
|
3391
|
+
require_bosch_instances.registerPowerSwitch(this, require_bosch_instances.climateControlCapability, provider);
|
|
3387
3392
|
}
|
|
3388
3393
|
};
|
|
3389
3394
|
function hvacModeToHomeCom(mode) {
|
|
@@ -3449,7 +3454,7 @@ var HomeComWaterHeaterDevice = class extends require_bosch_instances.BaseDevice
|
|
|
3449
3454
|
return client;
|
|
3450
3455
|
}
|
|
3451
3456
|
registerWaterHeaterCap() {
|
|
3452
|
-
|
|
3457
|
+
const provider = {
|
|
3453
3458
|
getStatus: async () => {
|
|
3454
3459
|
this.refreshFromSnapshot();
|
|
3455
3460
|
return this.runtimeState.getCapState(WH_CAP) ?? COLD_START$1;
|
|
@@ -3465,7 +3470,9 @@ var HomeComWaterHeaterDevice = class extends require_bosch_instances.BaseDevice
|
|
|
3465
3470
|
setAway: async () => {
|
|
3466
3471
|
throw new Error("HomeCom DHW: away mode not supported");
|
|
3467
3472
|
}
|
|
3468
|
-
}
|
|
3473
|
+
};
|
|
3474
|
+
this.ctx.registerNativeCap(require_bosch_instances.waterHeaterCapability, provider);
|
|
3475
|
+
require_bosch_instances.registerPowerSwitch(this, require_bosch_instances.waterHeaterCapability, provider);
|
|
3469
3476
|
}
|
|
3470
3477
|
};
|
|
3471
3478
|
//#endregion
|
package/dist/homecom/addon.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
import { a as loginFailureForAttempt, i as createSignInAttemptStore, n as cascadeRemoveDevicesForIntegration, o as parseOAuthCallback, r as buildSignInGuideFields, s as HOMECOM_REDIRECT_URI, t as setIntegrationDevicesOnline } from "../account-integration-offline-
|
|
1
|
+
import { $ as errMsg, A as waterHeaterCapability, B as _enum, F as defineEntryKind, G as number, H as array, I as entryBody, J as string, K as object, N as customAction, P as defineCustomActions, Q as DeviceType, T as registerPowerSwitch, U as boolean, V as _null, W as literal, Y as union, Z as DeviceRole, _ as heatPumpControlCapability, a as BaseDevice, d as climateControlCapability, et as EventCategory, i as testBoschInstance, j as RecordIntegrationInstances, n as boschRowsPorts, o as BaseDeviceProvider, p as deviceAdoptionCapability, q as record, r as keepBodyKeys, t as boschRowsMigration, v as heatPumpStatusCapability, x as integrationInstancesCapability, z as rowsDepsOver } from "../bosch-instances-DSE6IXdU.mjs";
|
|
2
|
+
import { a as loginFailureForAttempt, i as createSignInAttemptStore, n as cascadeRemoveDevicesForIntegration, o as parseOAuthCallback, r as buildSignInGuideFields, s as HOMECOM_REDIRECT_URI, t as setIntegrationDevicesOnline } from "../account-integration-offline-D5vjmfia.mjs";
|
|
3
3
|
import { createHash, randomBytes } from "node:crypto";
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
5
5
|
import { existsSync } from "node:fs";
|
|
@@ -3315,7 +3315,10 @@ var HomeComClimateDevice = class extends BaseDevice {
|
|
|
3315
3315
|
#circuitId;
|
|
3316
3316
|
constructor(ctx) {
|
|
3317
3317
|
const persisted = homeComClimateSchema.parse(ctx.persistedConfig ?? {});
|
|
3318
|
-
super(ctx, homeComClimateSchema, {
|
|
3318
|
+
super(ctx, homeComClimateSchema, {
|
|
3319
|
+
type: ctx.deviceMeta.type,
|
|
3320
|
+
role: DeviceRole.ClimateHeatPumpCircuit
|
|
3321
|
+
});
|
|
3319
3322
|
this.#brokerId = persisted.brokerId;
|
|
3320
3323
|
this.#circuitId = persisted.circuitId;
|
|
3321
3324
|
this.online = true;
|
|
@@ -3347,7 +3350,7 @@ var HomeComClimateDevice = class extends BaseDevice {
|
|
|
3347
3350
|
return client;
|
|
3348
3351
|
}
|
|
3349
3352
|
registerClimateCap() {
|
|
3350
|
-
|
|
3353
|
+
const provider = {
|
|
3351
3354
|
getStatus: async () => {
|
|
3352
3355
|
this.refreshFromSnapshot();
|
|
3353
3356
|
return this.runtimeState.getCapState(CLIMATE_CAP) ?? COLD_START$2;
|
|
@@ -3382,7 +3385,9 @@ var HomeComClimateDevice = class extends BaseDevice {
|
|
|
3382
3385
|
await this.requireClient().setSwingHorizontal(this.#circuitId, on);
|
|
3383
3386
|
this.refreshFromSnapshot();
|
|
3384
3387
|
}
|
|
3385
|
-
}
|
|
3388
|
+
};
|
|
3389
|
+
this.ctx.registerNativeCap(climateControlCapability, provider);
|
|
3390
|
+
registerPowerSwitch(this, climateControlCapability, provider);
|
|
3386
3391
|
}
|
|
3387
3392
|
};
|
|
3388
3393
|
function hvacModeToHomeCom(mode) {
|
|
@@ -3448,7 +3453,7 @@ var HomeComWaterHeaterDevice = class extends BaseDevice {
|
|
|
3448
3453
|
return client;
|
|
3449
3454
|
}
|
|
3450
3455
|
registerWaterHeaterCap() {
|
|
3451
|
-
|
|
3456
|
+
const provider = {
|
|
3452
3457
|
getStatus: async () => {
|
|
3453
3458
|
this.refreshFromSnapshot();
|
|
3454
3459
|
return this.runtimeState.getCapState(WH_CAP) ?? COLD_START$1;
|
|
@@ -3464,7 +3469,9 @@ var HomeComWaterHeaterDevice = class extends BaseDevice {
|
|
|
3464
3469
|
setAway: async () => {
|
|
3465
3470
|
throw new Error("HomeCom DHW: away mode not supported");
|
|
3466
3471
|
}
|
|
3467
|
-
}
|
|
3472
|
+
};
|
|
3473
|
+
this.ctx.registerNativeCap(waterHeaterCapability, provider);
|
|
3474
|
+
registerPowerSwitch(this, waterHeaterCapability, provider);
|
|
3468
3475
|
}
|
|
3469
3476
|
};
|
|
3470
3477
|
//#endregion
|
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 require_bosch_instances = require("../bosch-instances-
|
|
5
|
+
const require_bosch_instances = require("../bosch-instances-LWbVnsaD.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");
|
|
@@ -38,6 +38,146 @@ var boschShcActions = require_bosch_instances.defineCustomActions({
|
|
|
38
38
|
})
|
|
39
39
|
});
|
|
40
40
|
//#endregion
|
|
41
|
+
//#region src/shc/shc-domain-mapping.ts
|
|
42
|
+
var ROOM_CLIMATE_MODEL = "ROOM_CLIMATE_CONTROL";
|
|
43
|
+
/** Classify a normalised device summary into an adoption / driver kind. */
|
|
44
|
+
function classifyShcDevice(device) {
|
|
45
|
+
const fromModel = shcKindForModel(device.deviceModel);
|
|
46
|
+
if (fromModel !== "unsupported") return fromModel;
|
|
47
|
+
if (device.services.includes("RoomClimateControl")) return "room-climate";
|
|
48
|
+
if (device.services.includes("PowerSwitch")) return "switch";
|
|
49
|
+
if (device.services.includes("TemperatureLevel") || device.services.includes("ValveTappet")) return "trv";
|
|
50
|
+
return "unsupported";
|
|
51
|
+
}
|
|
52
|
+
function shcKindForModel(deviceModel) {
|
|
53
|
+
if (deviceModel === ROOM_CLIMATE_MODEL) return "room-climate";
|
|
54
|
+
if (deviceModel === "TWR_SWITCH" || deviceModel === "DIMMER_LIGHT" || deviceModel === "PLUG_COMPACT" || deviceModel === "PLUG_COMPACT_DUAL") return "switch";
|
|
55
|
+
if (deviceModel === "HEATING_THERMOSTAT" || deviceModel === "RADIATOR_THERMOSTAT" || deviceModel === "TRV_GEN2_DUAL" || deviceModel === "TRV") return "trv";
|
|
56
|
+
return "unsupported";
|
|
57
|
+
}
|
|
58
|
+
function deviceTypeForShcKind(kind) {
|
|
59
|
+
switch (kind) {
|
|
60
|
+
case "room-climate": return require_bosch_instances.DeviceType.Container;
|
|
61
|
+
case "trv": return require_bosch_instances.DeviceType.Climate;
|
|
62
|
+
case "switch": return require_bosch_instances.DeviceType.Switch;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** D1033 — which climate device an SHC kind is: a valve is a radiator, a room a thermostat. */
|
|
66
|
+
function shcClimateRole(kind) {
|
|
67
|
+
return kind === "trv" ? require_bosch_instances.DeviceRole.ClimateRadiator : require_bosch_instances.DeviceRole.ClimateThermostat;
|
|
68
|
+
}
|
|
69
|
+
/** The room-climate accessory's stable-id suffix (`ShcClimateRoomDevice`). */
|
|
70
|
+
var SHC_ROOM_CLIMATE_SUFFIX = "climate";
|
|
71
|
+
/**
|
|
72
|
+
* D1033 — a valve and a room climate share the `climate` type, so a persisted
|
|
73
|
+
* row is told apart by its model when the config carries one, else by the
|
|
74
|
+
* room-climate accessory's stable-id suffix.
|
|
75
|
+
*/
|
|
76
|
+
function shcClimateRowKind(row) {
|
|
77
|
+
const model = row.config?.["deviceModel"];
|
|
78
|
+
if (typeof model === "string") {
|
|
79
|
+
const kind = shcKindForModel(model);
|
|
80
|
+
if (kind === "trv" || kind === "room-climate") return kind;
|
|
81
|
+
}
|
|
82
|
+
return row.stableId.endsWith(`-climate`) ? "room-climate" : "trv";
|
|
83
|
+
}
|
|
84
|
+
function capsForShcKind(kind) {
|
|
85
|
+
switch (kind) {
|
|
86
|
+
case "room-climate": return ["climate-control"];
|
|
87
|
+
case "switch": return ["switch"];
|
|
88
|
+
case "trv": return [
|
|
89
|
+
"temperature-sensor",
|
|
90
|
+
"battery",
|
|
91
|
+
"heating-valve"
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function mapShcModeToHvac(state) {
|
|
96
|
+
if ((state.roomControlMode ?? "").toUpperCase() === "OFF") return "off";
|
|
97
|
+
const upper = (state.operationMode ?? state.mode ?? "").toUpperCase();
|
|
98
|
+
if (upper === "OFF") return "off";
|
|
99
|
+
if (upper === "AUTOMATIC" || upper === "AUTO") return "auto";
|
|
100
|
+
if (upper.includes("COOL")) return "cool";
|
|
101
|
+
if (upper.includes("HEAT")) return "heat";
|
|
102
|
+
return "heat";
|
|
103
|
+
}
|
|
104
|
+
var CLIMATE_MODES = [
|
|
105
|
+
"off",
|
|
106
|
+
"heat",
|
|
107
|
+
"auto"
|
|
108
|
+
];
|
|
109
|
+
/**
|
|
110
|
+
* Setpoint ends the Smart Home Controller app enforces. RoomClimateControl
|
|
111
|
+
* state does not carry them; a value present on the payload still wins.
|
|
112
|
+
*/
|
|
113
|
+
var SHC_SETPOINT_MIN = 5;
|
|
114
|
+
var SHC_SETPOINT_MAX = 30;
|
|
115
|
+
/** Map Bosch RoomClimateControl state JSON → CamStack climate-control slice. */
|
|
116
|
+
function mapRoomClimateStateToSlice(state) {
|
|
117
|
+
const now = Date.now();
|
|
118
|
+
return {
|
|
119
|
+
mode: mapShcModeToHvac(state),
|
|
120
|
+
availableModes: [...CLIMATE_MODES],
|
|
121
|
+
fanMode: "",
|
|
122
|
+
availableFanModes: [],
|
|
123
|
+
preset: "",
|
|
124
|
+
availablePresets: [],
|
|
125
|
+
target: state.setpointTemperature ?? null,
|
|
126
|
+
targetHigh: null,
|
|
127
|
+
targetLow: null,
|
|
128
|
+
targetHumidity: null,
|
|
129
|
+
currentTemp: state.temperature ?? null,
|
|
130
|
+
currentHumidity: null,
|
|
131
|
+
swingVertical: null,
|
|
132
|
+
swingHorizontal: null,
|
|
133
|
+
minTemp: state.minTemperature ?? SHC_SETPOINT_MIN,
|
|
134
|
+
maxTemp: state.maxTemperature ?? SHC_SETPOINT_MAX,
|
|
135
|
+
tempStep: .5,
|
|
136
|
+
lastFetchedAt: now
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* PUT bodies for a mode change, in order.
|
|
141
|
+
* Off is `roomControlMode` alone — `operationMode: OFF` is rejected.
|
|
142
|
+
* Heat and auto must turn heating on first; combining both fields while
|
|
143
|
+
* the room is off returns WRONG_THERMOSTAT_GROUP_MODE.
|
|
144
|
+
*/
|
|
145
|
+
function buildRoomClimateModeBodies(mode) {
|
|
146
|
+
if (mode === "off") return [{
|
|
147
|
+
"@type": "climateControlState",
|
|
148
|
+
roomControlMode: "OFF"
|
|
149
|
+
}];
|
|
150
|
+
return [{
|
|
151
|
+
"@type": "climateControlState",
|
|
152
|
+
roomControlMode: "HEATING"
|
|
153
|
+
}, {
|
|
154
|
+
"@type": "climateControlState",
|
|
155
|
+
operationMode: mode === "auto" ? "AUTOMATIC" : "MANUAL"
|
|
156
|
+
}];
|
|
157
|
+
}
|
|
158
|
+
/** PowerSwitch on the controller is the string `ON` / `OFF`, not a boolean. */
|
|
159
|
+
function readShcSwitchOn(state) {
|
|
160
|
+
if (isShcSwitchOn(state.switchState)) return true;
|
|
161
|
+
return isShcSwitchOn(state.switchStates?.[0]?.switchState);
|
|
162
|
+
}
|
|
163
|
+
function isShcSwitchOn(value) {
|
|
164
|
+
if (value === true) return true;
|
|
165
|
+
return typeof value === "string" && value.toUpperCase() === "ON";
|
|
166
|
+
}
|
|
167
|
+
function buildPowerSwitchPutBody(on) {
|
|
168
|
+
return {
|
|
169
|
+
"@type": "powerSwitchState",
|
|
170
|
+
switchState: on ? "ON" : "OFF"
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
/** Body for PUT RoomClimateControl/state when changing the setpoint. */
|
|
174
|
+
function buildRoomClimatePutBody(input) {
|
|
175
|
+
return {
|
|
176
|
+
"@type": "climateControlState",
|
|
177
|
+
setpointTemperature: input.target
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
//#endregion
|
|
41
181
|
//#region src/shc/config.ts
|
|
42
182
|
/** Operator settings for one SHC integration (local mTLS + optional token). */
|
|
43
183
|
var shcConfigSchema = require_bosch_instances.object({
|
|
@@ -562,9 +702,12 @@ var ShcBaseDevice = class extends require_bosch_instances.BaseDevice {
|
|
|
562
702
|
brokerId;
|
|
563
703
|
deviceModel;
|
|
564
704
|
stateUnsub = null;
|
|
565
|
-
constructor(ctx) {
|
|
705
|
+
constructor(ctx, role) {
|
|
566
706
|
const persisted = shcDeviceSchema.parse(ctx.persistedConfig ?? {});
|
|
567
|
-
super(ctx, shcDeviceSchema, {
|
|
707
|
+
super(ctx, shcDeviceSchema, {
|
|
708
|
+
type: ctx.deviceMeta.type,
|
|
709
|
+
...role !== void 0 ? { role } : {}
|
|
710
|
+
});
|
|
568
711
|
this.shcDeviceId = persisted.shcDeviceId;
|
|
569
712
|
this.brokerId = persisted.brokerId;
|
|
570
713
|
this.deviceModel = persisted.deviceModel;
|
|
@@ -648,127 +791,6 @@ var ShcGatewayDevice = class extends require_bosch_instances.BaseDevice {
|
|
|
648
791
|
}
|
|
649
792
|
};
|
|
650
793
|
//#endregion
|
|
651
|
-
//#region src/shc/shc-domain-mapping.ts
|
|
652
|
-
var ROOM_CLIMATE_MODEL = "ROOM_CLIMATE_CONTROL";
|
|
653
|
-
/** Classify a normalised device summary into an adoption / driver kind. */
|
|
654
|
-
function classifyShcDevice(device) {
|
|
655
|
-
const fromModel = shcKindForModel(device.deviceModel);
|
|
656
|
-
if (fromModel !== "unsupported") return fromModel;
|
|
657
|
-
if (device.services.includes("RoomClimateControl")) return "room-climate";
|
|
658
|
-
if (device.services.includes("PowerSwitch")) return "switch";
|
|
659
|
-
if (device.services.includes("TemperatureLevel") || device.services.includes("ValveTappet")) return "trv";
|
|
660
|
-
return "unsupported";
|
|
661
|
-
}
|
|
662
|
-
function shcKindForModel(deviceModel) {
|
|
663
|
-
if (deviceModel === ROOM_CLIMATE_MODEL) return "room-climate";
|
|
664
|
-
if (deviceModel === "TWR_SWITCH" || deviceModel === "DIMMER_LIGHT" || deviceModel === "PLUG_COMPACT" || deviceModel === "PLUG_COMPACT_DUAL") return "switch";
|
|
665
|
-
if (deviceModel === "HEATING_THERMOSTAT" || deviceModel === "RADIATOR_THERMOSTAT" || deviceModel === "TRV_GEN2_DUAL" || deviceModel === "TRV") return "trv";
|
|
666
|
-
return "unsupported";
|
|
667
|
-
}
|
|
668
|
-
function deviceTypeForShcKind(kind) {
|
|
669
|
-
switch (kind) {
|
|
670
|
-
case "room-climate": return require_bosch_instances.DeviceType.Container;
|
|
671
|
-
case "trv": return require_bosch_instances.DeviceType.Thermostat;
|
|
672
|
-
case "switch": return require_bosch_instances.DeviceType.Switch;
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
function capsForShcKind(kind) {
|
|
676
|
-
switch (kind) {
|
|
677
|
-
case "room-climate": return ["climate-control"];
|
|
678
|
-
case "switch": return ["switch"];
|
|
679
|
-
case "trv": return [
|
|
680
|
-
"temperature-sensor",
|
|
681
|
-
"battery",
|
|
682
|
-
"heating-valve"
|
|
683
|
-
];
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
function mapShcModeToHvac(state) {
|
|
687
|
-
if ((state.roomControlMode ?? "").toUpperCase() === "OFF") return "off";
|
|
688
|
-
const upper = (state.operationMode ?? state.mode ?? "").toUpperCase();
|
|
689
|
-
if (upper === "OFF") return "off";
|
|
690
|
-
if (upper === "AUTOMATIC" || upper === "AUTO") return "auto";
|
|
691
|
-
if (upper.includes("COOL")) return "cool";
|
|
692
|
-
if (upper.includes("HEAT")) return "heat";
|
|
693
|
-
return "heat";
|
|
694
|
-
}
|
|
695
|
-
var CLIMATE_MODES = [
|
|
696
|
-
"off",
|
|
697
|
-
"heat",
|
|
698
|
-
"auto"
|
|
699
|
-
];
|
|
700
|
-
/**
|
|
701
|
-
* Setpoint ends the Smart Home Controller app enforces. RoomClimateControl
|
|
702
|
-
* state does not carry them; a value present on the payload still wins.
|
|
703
|
-
*/
|
|
704
|
-
var SHC_SETPOINT_MIN = 5;
|
|
705
|
-
var SHC_SETPOINT_MAX = 30;
|
|
706
|
-
/** Map Bosch RoomClimateControl state JSON → CamStack climate-control slice. */
|
|
707
|
-
function mapRoomClimateStateToSlice(state) {
|
|
708
|
-
const now = Date.now();
|
|
709
|
-
return {
|
|
710
|
-
mode: mapShcModeToHvac(state),
|
|
711
|
-
availableModes: [...CLIMATE_MODES],
|
|
712
|
-
fanMode: "",
|
|
713
|
-
availableFanModes: [],
|
|
714
|
-
preset: "",
|
|
715
|
-
availablePresets: [],
|
|
716
|
-
target: state.setpointTemperature ?? null,
|
|
717
|
-
targetHigh: null,
|
|
718
|
-
targetLow: null,
|
|
719
|
-
targetHumidity: null,
|
|
720
|
-
currentTemp: state.temperature ?? null,
|
|
721
|
-
currentHumidity: null,
|
|
722
|
-
swingVertical: null,
|
|
723
|
-
swingHorizontal: null,
|
|
724
|
-
minTemp: state.minTemperature ?? SHC_SETPOINT_MIN,
|
|
725
|
-
maxTemp: state.maxTemperature ?? SHC_SETPOINT_MAX,
|
|
726
|
-
tempStep: .5,
|
|
727
|
-
lastFetchedAt: now
|
|
728
|
-
};
|
|
729
|
-
}
|
|
730
|
-
/**
|
|
731
|
-
* PUT bodies for a mode change, in order.
|
|
732
|
-
* Off is `roomControlMode` alone — `operationMode: OFF` is rejected.
|
|
733
|
-
* Heat and auto must turn heating on first; combining both fields while
|
|
734
|
-
* the room is off returns WRONG_THERMOSTAT_GROUP_MODE.
|
|
735
|
-
*/
|
|
736
|
-
function buildRoomClimateModeBodies(mode) {
|
|
737
|
-
if (mode === "off") return [{
|
|
738
|
-
"@type": "climateControlState",
|
|
739
|
-
roomControlMode: "OFF"
|
|
740
|
-
}];
|
|
741
|
-
return [{
|
|
742
|
-
"@type": "climateControlState",
|
|
743
|
-
roomControlMode: "HEATING"
|
|
744
|
-
}, {
|
|
745
|
-
"@type": "climateControlState",
|
|
746
|
-
operationMode: mode === "auto" ? "AUTOMATIC" : "MANUAL"
|
|
747
|
-
}];
|
|
748
|
-
}
|
|
749
|
-
/** PowerSwitch on the controller is the string `ON` / `OFF`, not a boolean. */
|
|
750
|
-
function readShcSwitchOn(state) {
|
|
751
|
-
if (isShcSwitchOn(state.switchState)) return true;
|
|
752
|
-
return isShcSwitchOn(state.switchStates?.[0]?.switchState);
|
|
753
|
-
}
|
|
754
|
-
function isShcSwitchOn(value) {
|
|
755
|
-
if (value === true) return true;
|
|
756
|
-
return typeof value === "string" && value.toUpperCase() === "ON";
|
|
757
|
-
}
|
|
758
|
-
function buildPowerSwitchPutBody(on) {
|
|
759
|
-
return {
|
|
760
|
-
"@type": "powerSwitchState",
|
|
761
|
-
switchState: on ? "ON" : "OFF"
|
|
762
|
-
};
|
|
763
|
-
}
|
|
764
|
-
/** Body for PUT RoomClimateControl/state when changing the setpoint. */
|
|
765
|
-
function buildRoomClimatePutBody(input) {
|
|
766
|
-
return {
|
|
767
|
-
"@type": "climateControlState",
|
|
768
|
-
setpointTemperature: input.target
|
|
769
|
-
};
|
|
770
|
-
}
|
|
771
|
-
//#endregion
|
|
772
794
|
//#region src/shc/shc-discovery.ts
|
|
773
795
|
var GATEWAY_SUFFIX = ":controller";
|
|
774
796
|
/** The `childNativeId` (and `shcDeviceId`) of the controller box itself, one per integration. */
|
|
@@ -799,7 +821,7 @@ function trvCandidate(device) {
|
|
|
799
821
|
return {
|
|
800
822
|
childNativeId: device.id,
|
|
801
823
|
name: device.name.length > 0 ? device.name : device.id,
|
|
802
|
-
type: require_bosch_instances.DeviceType.
|
|
824
|
+
type: require_bosch_instances.DeviceType.Climate,
|
|
803
825
|
status: "online",
|
|
804
826
|
metadata: {
|
|
805
827
|
serialNumber: device.id,
|
|
@@ -992,10 +1014,10 @@ var COLD_START = {
|
|
|
992
1014
|
};
|
|
993
1015
|
var ShcRoomClimateDevice = class extends ShcBaseDevice {
|
|
994
1016
|
constructor(ctx) {
|
|
995
|
-
super(ctx);
|
|
1017
|
+
super(ctx, shcClimateRole("room-climate"));
|
|
996
1018
|
}
|
|
997
1019
|
registerCaps() {
|
|
998
|
-
|
|
1020
|
+
const provider = {
|
|
999
1021
|
getStatus: async () => this.runtimeState.getCapState(CLIMATE_CAP) ?? COLD_START,
|
|
1000
1022
|
setMode: async ({ mode }) => {
|
|
1001
1023
|
const client = this.requireClient();
|
|
@@ -1034,7 +1056,9 @@ var ShcRoomClimateDevice = class extends ShcBaseDevice {
|
|
|
1034
1056
|
setTargetHumidity: async () => this.unsupported("climate humidity"),
|
|
1035
1057
|
setSwingVertical: async () => this.unsupported("climate swing"),
|
|
1036
1058
|
setSwingHorizontal: async () => this.unsupported("climate swing")
|
|
1037
|
-
}
|
|
1059
|
+
};
|
|
1060
|
+
this.ctx.registerNativeCap(require_bosch_instances.climateControlCapability, provider);
|
|
1061
|
+
require_bosch_instances.registerPowerSwitch(this, require_bosch_instances.climateControlCapability, provider);
|
|
1038
1062
|
this.runtimeState.setCapState(CLIMATE_CAP, COLD_START);
|
|
1039
1063
|
}
|
|
1040
1064
|
async refreshFromController() {
|
|
@@ -1092,7 +1116,7 @@ var VALVE_COLD = {
|
|
|
1092
1116
|
/** Radiator TRV — local temperature, valve position, battery (no room setpoint). */
|
|
1093
1117
|
var ShcTrvDevice = class extends ShcBaseDevice {
|
|
1094
1118
|
constructor(ctx) {
|
|
1095
|
-
super(ctx);
|
|
1119
|
+
super(ctx, shcClimateRole("trv"));
|
|
1096
1120
|
}
|
|
1097
1121
|
registerCaps() {
|
|
1098
1122
|
this.ctx.registerNativeCap(require_bosch_instances.temperatureSensorCapability, { getStatus: async () => this.runtimeState.getCapState(TEMP_CAP) ?? TEMP_COLD });
|
|
@@ -1189,9 +1213,10 @@ var ShcClimateRoomDevice = class extends require_bosch_instances.BaseDevice {
|
|
|
1189
1213
|
...this.integrationId !== void 0 ? { integrationId: this.integrationId } : {}
|
|
1190
1214
|
};
|
|
1191
1215
|
return {
|
|
1192
|
-
stableIdSuffix:
|
|
1216
|
+
stableIdSuffix: SHC_ROOM_CLIMATE_SUFFIX,
|
|
1193
1217
|
meta: {
|
|
1194
1218
|
type: require_bosch_instances.DeviceType.Climate,
|
|
1219
|
+
role: shcClimateRole("room-climate"),
|
|
1195
1220
|
name: shcClimateEntityName(containerName),
|
|
1196
1221
|
linkDeviceId: this.id,
|
|
1197
1222
|
...this.integrationId !== void 0 ? { integrationId: this.integrationId } : {}
|
|
@@ -1210,7 +1235,8 @@ var ShcClimateRoomDevice = class extends require_bosch_instances.BaseDevice {
|
|
|
1210
1235
|
return {
|
|
1211
1236
|
stableIdSuffix: `trv-${shcStableIdSuffixFromDeviceId(child.shcDeviceId)}`,
|
|
1212
1237
|
meta: {
|
|
1213
|
-
type: require_bosch_instances.DeviceType.
|
|
1238
|
+
type: require_bosch_instances.DeviceType.Climate,
|
|
1239
|
+
role: shcClimateRole("trv"),
|
|
1214
1240
|
name: child.name,
|
|
1215
1241
|
linkDeviceId: this.id,
|
|
1216
1242
|
...this.integrationId !== void 0 ? { integrationId: this.integrationId } : {}
|
|
@@ -23831,10 +23857,14 @@ var BoschShcProviderAddon = class extends require_bosch_instances.BaseDeviceProv
|
|
|
23831
23857
|
deviceClasses = {
|
|
23832
23858
|
[require_bosch_instances.DeviceType.Gateway]: ShcGatewayDevice,
|
|
23833
23859
|
[require_bosch_instances.DeviceType.Container]: ShcClimateRoomDevice,
|
|
23834
|
-
[require_bosch_instances.DeviceType.Climate]:
|
|
23835
|
-
[require_bosch_instances.DeviceType.Thermostat]: ShcTrvDevice,
|
|
23860
|
+
[require_bosch_instances.DeviceType.Climate]: ShcTrvDevice,
|
|
23836
23861
|
[require_bosch_instances.DeviceType.Switch]: ShcSwitchDevice
|
|
23837
23862
|
};
|
|
23863
|
+
/** D1033 — a valve and a room climate are both `climate`: rebuild each with its class. */
|
|
23864
|
+
deviceClassForRow(row) {
|
|
23865
|
+
if (row.type !== require_bosch_instances.DeviceType.Climate) return super.deviceClassForRow(row);
|
|
23866
|
+
return shcClimateRowKind(row) === "room-climate" ? ShcRoomClimateDevice : ShcTrvDevice;
|
|
23867
|
+
}
|
|
23838
23868
|
clients = null;
|
|
23839
23869
|
instances = null;
|
|
23840
23870
|
constructor() {
|