homebridge-viessmann-vicare 2.0.76 → 2.0.78

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 CHANGED
@@ -3,6 +3,23 @@
3
3
  All notable changes to homebridge-viessmann-vicare.
4
4
 
5
5
 
6
+ ### [2.0.78] - 2026-09-26
7
+ - fix: **report "Device messages" were frozen**: the plugin stopped writing `viessmann-messages-<installation>-<device>.json` in 2.0.50, so the report showed months-old codes. The writer is back, now also includes fault codes (`device.messages.errors.raw`) and keeps a history (the API only returns current messages)
8
+ - fix: report heating-curve analysis uses only heating-season samples (outdoor < 16 °C): no more "weather compensation not active" advice in summer
9
+ - fix: report annual gas estimate requires ~a full year of data (a few summer weeks gave e.g. 52 m³/year)
10
+ - fix: report comfort-vs-efficiency is not evaluated when there is no space-heating gas in the period (it claimed "system optimisation is working" in summer)
11
+ - fix: report burner runtime shows one decimal below 1 %
12
+
13
+ ### [2.0.77] - 2026-09-26
14
+ - fix: **30/90/365-day reports failed with "Load failed"**: report generation was O(n²) (90 days took ~3 min on a Raspberry Pi, now a few seconds), the browser request stayed open for minutes, and the report tab was opened after the wait (blocked as a pop-up by Safari). Reports now run as background jobs polled by the page, and the tab is opened at click time
15
+ - fix: report analysis: no false "short cycling" alarm when burner hours changed by less than 2 h (integer counter), heating-curve check uses only samples with the circuit in heating mode, 30-day gas forecast uses the period average with fewer than 14 days of data
16
+ - fix (#3): the OAuth authorization URL is now always printed in the log (Docker/Umbrel installs never showed it)
17
+ - fix (#6): no more empty extra "Boiler" accessory for energy devices (e.g. VitoCharge); a stale one is removed automatically
18
+ - fix: room-sensor discovery accessories were never refreshed, and could show a non-temperature value (e.g. 0 °C from heatingCircuitId)
19
+ - feat (#4): **ViCare Smart Climate rooms**: one HomeKit accessory per room (temperature, humidity when connected, window open/closed) with `features.enableRoomSensors: true`; names via `customNames.roomNames`
20
+ - feat (#8): DHW modes other than comfort/eco/off (e.g. `balanced`, `efficient`, `efficientWithMinComfort`) get their own switch; new **one-time hot water charge** switch ("Warm water once") when the device supports `heating.dhw.oneTimeCharge`
21
+ - feat: Grafana dashboard: text tiles (burner, program, modes, status code) no longer show "No data", state timelines stop at "now", sparse series show points
22
+
6
23
  ### [2.0.76] - 2026-09-26
7
24
  - fix: report web server (`reportServerPort`) could stop silently: it was started with `execFile`, which buffers the child output (1 MB max) and kills it when the buffer is full, especially with `debug: true`. It could also fail with the port still held by an orphan process after a restart. The server now runs as a supervised child process: output goes to the Homebridge log, errors and exits are logged, it restarts automatically with back-off (max 5 attempts) and it is stopped when Homebridge shuts down
8
25
 
package/README.md CHANGED
@@ -859,6 +859,8 @@ The plugin automatically creates these accessories (configurable via feature fla
859
859
  - `[Installation] [Custom DHW Name] [Custom Comfort Name]` (Switch)
860
860
  - `[Installation] [Custom DHW Name] [Custom Eco Name]` (Switch)
861
861
  - `[Installation] [Custom DHW Name] [Custom Off Name]` (Switch)
862
+ - one extra switch for every other mode the device reports, e.g. `balanced`, `efficient`, `efficientWithMinComfort` *(v2.0.77+)*
863
+ - **One-time charge** *(v2.0.77+, if the device supports it)*: `[Installation] [Custom DHW Name] Once` (Switch), the "Warm water once" function of the ViCare app. It switches off by itself when the cylinder is charged.
862
864
  - **Sensors**: Current DHW temperature, heating state
863
865
 
864
866
  ### 🏠 Heating Circuits
@@ -875,6 +877,12 @@ The plugin automatically creates these accessories (configurable via feature fla
875
877
  - `[Installation] [Custom Heating Circuit Name] X [Custom Extended Heating Name]` (Switch)
876
878
  - **Sensors**: Room temperature, supply temperature
877
879
 
880
+ ### 🏠 ViCare Smart Climate rooms *(v2.0.77+, opt-in)*
881
+ With a ViCare **RoomControl** and smart radiator valves, set `"features": { "enableRoomSensors": true }` to get one accessory per room:
882
+ - `[Installation] Room N` (or the name from `customNames.roomNames`, in room order)
883
+ - **TemperatureSensor** (room temperature), **HumiditySensor** (only if the room humidity sensor is connected), **ContactSensor** for the window (if available)
884
+ - Room temperature and heating setpoint are logged to CSV/MySQL
885
+
878
886
  ## 🎯 Advanced Features
879
887
 
880
888
  ### Temperature Programs
@@ -1095,6 +1103,23 @@ For issues and questions:
1095
1103
 
1096
1104
  ## 📈 Changelog
1097
1105
 
1106
+ ### [2.0.78] - 2026-09-26
1107
+ - fix: **report "Device messages" were frozen**: the plugin stopped writing `viessmann-messages-<installation>-<device>.json` in 2.0.50, so the report showed months-old codes. The writer is back, now also includes fault codes (`device.messages.errors.raw`) and keeps a history (the API only returns current messages)
1108
+ - fix: report heating-curve analysis uses only heating-season samples (outdoor < 16 °C): no more "weather compensation not active" advice in summer
1109
+ - fix: report annual gas estimate requires ~a full year of data (a few summer weeks gave e.g. 52 m³/year)
1110
+ - fix: report comfort-vs-efficiency is not evaluated when there is no space-heating gas in the period (it claimed "system optimisation is working" in summer)
1111
+ - fix: report burner runtime shows one decimal below 1 %
1112
+
1113
+ ### [2.0.77] - 2026-09-26
1114
+ - fix: **30/90/365-day reports failed with "Load failed"**: report generation was O(n²) (90 days took ~3 min on a Raspberry Pi, now a few seconds), the browser request stayed open for minutes, and the report tab was opened after the wait (blocked as a pop-up by Safari). Reports now run as background jobs polled by the page, and the tab is opened at click time
1115
+ - fix: report analysis: no false "short cycling" alarm when burner hours changed by less than 2 h (integer counter), heating-curve check uses only samples with the circuit in heating mode, 30-day gas forecast uses the period average with fewer than 14 days of data
1116
+ - fix (#3): the OAuth authorization URL is now always printed in the log (Docker/Umbrel installs never showed it)
1117
+ - fix (#6): no more empty extra "Boiler" accessory for energy devices (e.g. VitoCharge); a stale one is removed automatically
1118
+ - fix: room-sensor discovery accessories were never refreshed, and could show a non-temperature value (e.g. 0 °C from heatingCircuitId)
1119
+ - feat (#4): **ViCare Smart Climate rooms**: one HomeKit accessory per room (temperature, humidity when connected, window open/closed) with `features.enableRoomSensors: true`; names via `customNames.roomNames`
1120
+ - feat (#8): DHW modes other than comfort/eco/off (e.g. `balanced`, `efficient`, `efficientWithMinComfort`) get their own switch; new **one-time hot water charge** switch ("Warm water once") when the device supports `heating.dhw.oneTimeCharge`
1121
+ - feat: Grafana dashboard: text tiles (burner, program, modes, status code) no longer show "No data", state timelines stop at "now", sparse series show points
1122
+
1098
1123
  ### [2.0.76] - 2026-09-26
1099
1124
  - fix: report web server (`reportServerPort`) could stop silently: it was started with `execFile`, which buffers the child output (1 MB max) and kills it when the buffer is full, especially with `debug: true`. It could also fail with the port still held by an orphan process after a restart. The server now runs as a supervised child process: output goes to the Homebridge log, errors and exits are logged, it restarts automatically with back-off (max 5 attempts) and it is stopped when Homebridge shuts down
1100
1125
 
package/SETUP-GUIDE.md CHANGED
@@ -1,8 +1,8 @@
1
- # Complete Setup Guide - v2.0.76
1
+ # Complete Setup Guide - v2.0.78
2
2
 
3
3
  ## Overview
4
4
 
5
- This guide will walk you through setting up the Viessmann ViCare plugin v2.0.76 for Homebridge, including all the advanced features like intelligent caching, rate limiting protection, comprehensive configuration options, **complete localization support with custom names**, **CSV history logging**, **HTML diagnostic reports**, **energy system monitoring** (PV, battery, wallbox), and **heating schedule awareness** with visual bands in the HTML report, and **heat pump (Wärmepumpe) support** with automatic device detection.
5
+ This guide will walk you through setting up the Viessmann ViCare plugin v2.0.78 for Homebridge, including all the advanced features like intelligent caching, rate limiting protection, comprehensive configuration options, **complete localization support with custom names**, **CSV history logging**, **HTML diagnostic reports**, **energy system monitoring** (PV, battery, wallbox), and **heating schedule awareness** with visual bands in the HTML report, and **heat pump (Wärmepumpe) support** with automatic device detection.
6
6
 
7
7
  ## Prerequisites
8
8
 
@@ -760,7 +760,16 @@ All energy data (PV production, battery level, charge/discharge, grid, wallbox)
760
760
 
761
761
  > ⚠️ **Beta**: Energy accessory support and history logging are functional but depend on Viessmann API path variants that differ across VitoCharge generations. Enable `debug: true` and share logs if data appears missing.
762
762
 
763
- ### 🌡️ TRV / Room Sensor Accessories *(beta)*
763
+ ### 🏠 ViCare Smart Climate rooms *(v2.0.77+)*
764
+
765
+ For installations with a ViCare **RoomControl** and smart radiator valves, enable:
766
+ ```json
767
+ "features": { "enableRoomSensors": true },
768
+ "customNames": { "roomNames": ["Living room", "Kitchen", "Bedroom"] }
769
+ ```
770
+ One accessory per room is created: **temperature** sensor, **humidity** sensor (only when the room humidity sensor is connected) and **window** contact sensor (when available). Without `roomNames` rooms are called "Room 1", "Room 2", … Room temperatures and setpoints are logged to CSV/MySQL (`room0`, `room1`, …).
771
+
772
+ ### 🌡️ TRV / Room Sensor discovery *(diagnostics)*
764
773
 
765
774
  Enable with `features.enableRoomSensorDiscovery: true` in plugin config. The plugin scans all non-main gateway devices and creates a `TemperatureSensor` accessory for each device with a temperature reading (ViCare Smart Climate TRVs, zone sensors, etc.).
766
775
 
@@ -780,6 +789,8 @@ Temperature history is logged to CSV (`room-<deviceId>` column) and MySQL on eve
780
789
  - `[Installation Prefix] [Custom DHW Name] [Custom Comfort Name]` - Comfort Mode Switch
781
790
  - `[Installation Prefix] [Custom DHW Name] [Custom Eco Name]` - Eco Mode Switch
782
791
  - `[Installation Prefix] [Custom DHW Name] [Custom Off Name]` - Off Mode Switch
792
+ - Other modes reported by the device (e.g. `balanced`, `efficient`, `efficientWithMinComfort`) get their own switch *(v2.0.77+)*
793
+ - **One-time charge** *(v2.0.77+, if supported)*: `[Installation Prefix] [Custom DHW Name] Once` - Switch that starts a single hot-water charge ("Warm water once" in the ViCare app); it turns off by itself when the cylinder is charged
783
794
 
784
795
  ### 🏠 Heating Circuit Accessories
785
796
  - **Main Circuit Control**: `[Installation Prefix] [Custom Heating Circuit Name] X` - HeaterCooler service for circuit temperature
@@ -1281,6 +1292,14 @@ sudo systemctl restart homebridge
1281
1292
 
1282
1293
  ## Changelog
1283
1294
 
1295
+ ### v2.0.78 (2026-09-26)
1296
+ - fix: report device messages up to date again (with fault codes and history); seasonal-aware heating-curve, annual gas and comfort analyses
1297
+
1298
+ ### v2.0.77 (2026-09-26)
1299
+ - fix: long reports (30/90/365 days) — much faster, generated in background, no more "Load failed"
1300
+ - fix: OAuth URL always logged (Docker), no empty extra Boiler for energy devices, report analysis false alarms
1301
+ - feat: ViCare Smart Climate rooms (`features.enableRoomSensors`), extra DHW modes and one-time hot water charge switch
1302
+
1284
1303
  ### v2.0.76 (2026-09-26)
1285
1304
  - fix: report web server supervised (no more silent stop / "Load failed"): logs, automatic restart, clean stop on shutdown
1286
1305
 
@@ -271,6 +271,15 @@
271
271
  "type": "string",
272
272
  "placeholder": "Riscaldamento Extra",
273
273
  "description": "Custom name for extended heating mode (comfort boost). Default: 'Extended Heating'. Italian example: 'Riscaldamento Extra'"
274
+ },
275
+ "roomNames": {
276
+ "title": "Room names (ViCare Smart Climate)",
277
+ "type": "array",
278
+ "items": {
279
+ "type": "string",
280
+ "title": "Room name"
281
+ },
282
+ "description": "Names for the ViCare rooms in order (room 1, room 2, …). Leave empty to use \"Room 1\", \"Room 2\", …"
274
283
  }
275
284
  }
276
285
  },
@@ -439,6 +448,12 @@
439
448
  "type": "boolean",
440
449
  "default": false,
441
450
  "description": "Scan all gateway devices for thermostatic radiator valves (TRVs) or per-room temperature sensors. Creates a HomeKit TemperatureSensor for each discovered device and dumps all API feature paths to the Homebridge log. Enable this if you have Viessmann ViCare Smart Climate and want to help implement full TRV support. Disable in production — generates verbose logs."
451
+ },
452
+ "enableRoomSensors": {
453
+ "title": "Room sensors (ViCare Smart Climate)",
454
+ "type": "boolean",
455
+ "default": false,
456
+ "description": "Create one HomeKit accessory per ViCare room (temperature, humidity when a sensor is connected, window open/closed) for installations with a ViCare RoomControl and smart radiator valves. Room names can be set in Custom Names → Room names."
442
457
  }
443
458
  }
444
459
  },
@@ -688,6 +703,7 @@
688
703
  "customNames.holiday",
689
704
  "customNames.holidayAtHome",
690
705
  "customNames.extendedHeating",
706
+ "customNames.roomNames",
691
707
  "forceServiceRecreation"
692
708
  ]
693
709
  },
@@ -737,7 +753,9 @@
737
753
  "features.enableHeatingCircuitAccessories",
738
754
  "features.enableTemperaturePrograms",
739
755
  "features.enableQuickSelections",
740
- "features.enableBurnerStatus"
756
+ "features.enableBurnerStatus",
757
+ "features.enableRoomSensors",
758
+ "features.enableRoomSensorDiscovery"
741
759
  ]
742
760
  },
743
761
  {
@@ -792,4 +810,4 @@
792
810
  ]
793
811
  }
794
812
  ]
795
- }
813
+ }
@@ -11,6 +11,10 @@ export declare class ViessmannDHWAccessory {
11
11
  private comfortService?;
12
12
  private ecoService?;
13
13
  private offService?;
14
+ private extraModeServices;
15
+ private oneTimeChargeService?;
16
+ private supportsOneTimeCharge;
17
+ private oneTimeChargeActive;
14
18
  private availableModes;
15
19
  private supportsTemperatureControl;
16
20
  private temperatureConstraints;
@@ -33,6 +37,7 @@ export declare class ViessmannDHWAccessory {
33
37
  private setupHeaterCoolerService;
34
38
  private setupModeServices;
35
39
  private removeAllModeServices;
40
+ setOneTimeCharge(value: CharacteristicValue): Promise<void>;
36
41
  setActive(value: CharacteristicValue): Promise<void>;
37
42
  setComfortMode(value: CharacteristicValue): Promise<void>;
38
43
  setEcoMode(value: CharacteristicValue): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"dhw-accessory.d.ts","sourceRoot":"","sources":["../../src/accessories/dhw-accessory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dhw-accessory.d.ts","sourceRoot":"","sources":["../../src/accessories/dhw-accessory.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,12 @@ class ViessmannDHWAccessory {
14
14
  comfortService;
15
15
  ecoService;
16
16
  offService;
17
+ // Extra DHW modes exposed by some devices (e.g. balanced, efficient) — issue #8
18
+ extraModeServices = new Map();
19
+ // One-time DHW charge ("Warm water once" in the ViCare app) — issue #8
20
+ oneTimeChargeService;
21
+ supportsOneTimeCharge = false;
22
+ oneTimeChargeActive = false;
17
23
  availableModes = [];
18
24
  supportsTemperatureControl = false;
19
25
  temperatureConstraints = { min: 30, max: 60 }; // Default DHW temperature range
@@ -140,7 +146,11 @@ class ViessmannDHWAccessory {
140
146
  this.states.HeatingThresholdTemperature = 50;
141
147
  }
142
148
  }
143
- this.platform.log.info(`DHW Capabilities - Modes: [${this.availableModes.join(', ')}], Temperature: ${this.supportsTemperatureControl ? 'Yes' : 'No'}`);
149
+ // One-time charge ("Warm water once")
150
+ const otc = features.find(f => f.feature === 'heating.dhw.oneTimeCharge');
151
+ this.supportsOneTimeCharge = !!(otc?.isEnabled !== false && otc?.commands?.activate);
152
+ this.oneTimeChargeActive = otc?.properties?.active?.value === true;
153
+ this.platform.log.info(`DHW Capabilities - Modes: [${this.availableModes.join(', ')}], Temperature: ${this.supportsTemperatureControl ? 'Yes' : 'No'}, One-time charge: ${this.supportsOneTimeCharge ? 'Yes' : 'No'}`);
144
154
  }
145
155
  setupCharacteristics() {
146
156
  // Remove any existing conflicting services
@@ -308,6 +318,46 @@ class ViessmannDHWAccessory {
308
318
  .onGet(() => this.currentMode === 'off')
309
319
  .onSet(this.setOffMode.bind(this));
310
320
  }
321
+ // Extra modes (balanced, efficient, efficientWithMinComfort, …): one switch each
322
+ const EXTRA_LABELS = {
323
+ balanced: 'Balanced', efficient: 'Efficient', efficientWithMinComfort: 'Efficient+',
324
+ };
325
+ for (const mode of this.availableModes.filter(m => !['comfort', 'eco', 'off'].includes(m))) {
326
+ const label = config.customNames?.[`dhw_${mode}`] || EXTRA_LABELS[mode] || mode;
327
+ const name = `${installationName} ${dhwName} ${label}`;
328
+ this.platform.log.info(`🏷️ Creating ${mode} service: "${name}"`);
329
+ const svc = this.accessory.addService(this.platform.Service.Switch, name, `dhw-${mode}-${subtypeVersion}`);
330
+ svc.setCharacteristic(this.platform.Characteristic.Name, name);
331
+ svc.displayName = name;
332
+ svc.getCharacteristic(this.platform.Characteristic.On)
333
+ .onGet(() => this.currentMode === mode)
334
+ .onSet(async (value) => {
335
+ if (this._updatingCharacteristics)
336
+ return;
337
+ if (value && this.currentMode !== mode) {
338
+ await this.setMode(mode);
339
+ }
340
+ else if (!value && this.currentMode === mode && this.availableModes.includes('off')) {
341
+ await this.setMode('off');
342
+ }
343
+ else if (!value) {
344
+ setImmediate(() => this.updateAllCharacteristics());
345
+ }
346
+ });
347
+ this.extraModeServices.set(mode, svc);
348
+ }
349
+ // One-time charge switch ("Warm water once")
350
+ if (this.supportsOneTimeCharge) {
351
+ const label = config.customNames?.dhw_oneTimeCharge || 'Once';
352
+ const name = `${installationName} ${dhwName} ${label}`;
353
+ this.platform.log.info(`🏷️ Creating one-time charge service: "${name}"`);
354
+ this.oneTimeChargeService = this.accessory.addService(this.platform.Service.Switch, name, `dhw-onetimecharge-${subtypeVersion}`);
355
+ this.oneTimeChargeService.setCharacteristic(this.platform.Characteristic.Name, name);
356
+ this.oneTimeChargeService.displayName = name;
357
+ this.oneTimeChargeService.getCharacteristic(this.platform.Characteristic.On)
358
+ .onGet(() => this.oneTimeChargeActive)
359
+ .onSet(this.setOneTimeCharge.bind(this));
360
+ }
311
361
  this.platform.log.info(`✅ DHW mode services setup completed for modes: [${this.availableModes.join(', ')}] with subtype version: ${subtypeVersion}`);
312
362
  }
313
363
  removeAllModeServices() {
@@ -326,6 +376,26 @@ class ViessmannDHWAccessory {
326
376
  this.comfortService = undefined;
327
377
  this.ecoService = undefined;
328
378
  this.offService = undefined;
379
+ this.extraModeServices.clear();
380
+ this.oneTimeChargeService = undefined;
381
+ }
382
+ // 🚿 One-time DHW charge ("Warm water once") — heating.dhw.oneTimeCharge activate/deactivate
383
+ async setOneTimeCharge(value) {
384
+ if (this._updatingCharacteristics)
385
+ return;
386
+ const on = value;
387
+ try {
388
+ const ok = await this.platform.viessmannAPI.executeCommand(this.installation.id, this.gateway.serial, this.device.id, 'heating.dhw.oneTimeCharge', on ? 'activate' : 'deactivate', {});
389
+ if (!ok)
390
+ throw new Error('command rejected');
391
+ this.oneTimeChargeActive = on;
392
+ this.platform.log.info(`🚿 DHW one-time charge ${on ? 'started' : 'stopped'}`);
393
+ }
394
+ catch (error) {
395
+ this.platform.log.error(`Failed to ${on ? 'start' : 'stop'} DHW one-time charge:`, error instanceof Error ? error.message : error);
396
+ setImmediate(() => this.oneTimeChargeService?.updateCharacteristic(this.platform.Characteristic.On, this.oneTimeChargeActive));
397
+ throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */);
398
+ }
329
399
  }
330
400
  async setActive(value) {
331
401
  const active = value;
@@ -475,6 +545,12 @@ class ViessmannDHWAccessory {
475
545
  if (this.offService) {
476
546
  this.offService.updateCharacteristic(this.platform.Characteristic.On, isOff);
477
547
  }
548
+ for (const [mode, svc] of this.extraModeServices) {
549
+ svc.updateCharacteristic(this.platform.Characteristic.On, this.currentMode === mode);
550
+ }
551
+ if (this.oneTimeChargeService) {
552
+ this.oneTimeChargeService.updateCharacteristic(this.platform.Characteristic.On, this.oneTimeChargeActive);
553
+ }
478
554
  this.platform.log.debug(`DHW States - Mode: ${this.currentMode.toUpperCase()}, Active: ${isActive}, Comfort: ${isComfort}, Eco: ${isEco}, Off: ${isOff}`);
479
555
  }
480
556
  finally {
@@ -640,6 +716,15 @@ class ViessmannDHWAccessory {
640
716
  }
641
717
  async updateFromFeatures(features) {
642
718
  let changed = false;
719
+ // One-time charge state (ends automatically when the cylinder is charged)
720
+ const otcFeature = features.find(f => f.feature === 'heating.dhw.oneTimeCharge');
721
+ if (otcFeature?.properties?.active?.value !== undefined) {
722
+ const otc = otcFeature.properties.active.value === true;
723
+ if (otc !== this.oneTimeChargeActive) {
724
+ this.oneTimeChargeActive = otc;
725
+ changed = true;
726
+ }
727
+ }
643
728
  // Update DHW current temperature
644
729
  const dhwTempFeature = features.find(f => f.feature === 'heating.dhw.sensors.temperature.dhwCylinder' ||
645
730
  f.feature === 'heating.dhw.sensors.temperature.hotWaterStorage' ||
@@ -1 +1 @@
1
- {"version":3,"file":"room-sensor-accessory.d.ts","sourceRoot":"","sources":["../../src/accessories/room-sensor-accessory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,iBAAiB,EAAW,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAkCxH,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,eAAe,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpF,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,gBAAgB,EAAE,GAC3B,yBAAyB,CAsG3B;AAID,qBAAa,4BAA4B;IASrC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAX1B,OAAO,CAAC,kBAAkB,CAAU;IACpC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkB;IACtC,OAAO,CAAC,aAAa,CAAC,CAAyB;IAG/C,OAAO,CAAC,eAAe,CAA4B;gBAGhC,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,EAAE,iBAAiB,EAC5B,YAAY,EAAE,qBAAqB,EACnC,OAAO,EAAE,gBAAgB,EAC1C,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,gBAAgB,EAAE;IA8C9B;;OAEG;IACI,MAAM,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,IAAI;CAsClD"}
1
+ {"version":3,"file":"room-sensor-accessory.d.ts","sourceRoot":"","sources":["../../src/accessories/room-sensor-accessory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,iBAAiB,EAAW,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAkCxH,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,eAAe,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpF,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,gBAAgB,EAAE,GAC3B,yBAAyB,CAyG3B;AAID,qBAAa,4BAA4B;IASrC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAX1B,OAAO,CAAC,kBAAkB,CAAU;IACpC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkB;IACtC,OAAO,CAAC,aAAa,CAAC,CAAyB;IAG/C,OAAO,CAAC,eAAe,CAA4B;gBAGhC,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,EAAE,iBAAiB,EAC5B,YAAY,EAAE,qBAAqB,EACnC,OAAO,EAAE,gBAAgB,EAC1C,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,gBAAgB,EAAE;IA8C9B;;OAEG;IACI,MAAM,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,IAAI;CAsClD"}
@@ -95,7 +95,10 @@ function discoverRoomSensorData(platform, device, features) {
95
95
  const type = p?.type ?? typeof val;
96
96
  if (val !== undefined && val !== null) {
97
97
  // Collect numeric temperature-range values
98
- if (typeof val === 'number' && val > -30 && val < 100 && unit !== '%') {
98
+ // Only real temperatures: unit celsius/fahrenheit or a "temperature" path.
99
+ // (Before 2.0.77 any number matched, e.g. device.heatingCircuitId = 0 → "0 °C".)
100
+ const isTemp = /celsius|fahrenheit/i.test(unit) || /temperature/i.test(f.feature);
101
+ if (typeof val === 'number' && val > -30 && val < 100 && unit !== '%' && isTemp) {
99
102
  allTempFeatures.push({ path: f.feature, prop: pk, value: val, unit });
100
103
  }
101
104
  const display = Array.isArray(val)
@@ -0,0 +1,37 @@
1
+ /**
2
+ * ViessmannRoomAccessory — one HomeKit accessory per room of a ViCare Smart Climate
3
+ * "RoomControl" device (issue #4).
4
+ *
5
+ * Feature paths (confirmed on E3_RoomControl_One_05 with E3_RadiatorActuator TRVs):
6
+ * rooms.N.sensors.temperature value (°C), status connected/notConnected
7
+ * rooms.N.sensors.humidity value (%), status connected/notConnected
8
+ * rooms.N.sensors.window.openState value (boolean) — optional
9
+ * rooms.N.temperature.levels.heating temperature (°C) — current heating setpoint
10
+ *
11
+ * Services per room:
12
+ * - TemperatureSensor (always)
13
+ * - HumiditySensor (only when the room humidity sensor is connected)
14
+ * - ContactSensor (window open/closed, only when the feature exists)
15
+ *
16
+ * Enable with: "features": { "enableRoomSensors": true }
17
+ * Room names: "customNames": { "rooms": { "0": "Living room", "1": "Bedroom" } }
18
+ */
19
+ import { PlatformAccessory } from 'homebridge';
20
+ import { ViessmannPlatform } from '../platform';
21
+ import { ViessmannFeature, ViessmannDevice, ViessmannInstallation, ViessmannGateway } from '../viessmann-api-endpoints';
22
+ /** Room indexes exposed by a device (rooms.N.sensors.temperature present and enabled). */
23
+ export declare function detectRoomIndexes(features: ViessmannFeature[]): number[];
24
+ export declare class ViessmannRoomAccessory {
25
+ private readonly platform;
26
+ private readonly accessory;
27
+ private readonly roomIndex;
28
+ private readonly tempService;
29
+ private humidityService?;
30
+ private windowService?;
31
+ private historyLogger?;
32
+ private readonly TAG;
33
+ constructor(platform: ViessmannPlatform, accessory: PlatformAccessory, installation: ViessmannInstallation, gateway: ViessmannGateway, device: ViessmannDevice, roomIndex: number, features: ViessmannFeature[]);
34
+ private featureGetter;
35
+ update(features: ViessmannFeature[]): void;
36
+ }
37
+ //# sourceMappingURL=rooms-accessory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rooms-accessory.d.ts","sourceRoot":"","sources":["../../src/accessories/rooms-accessory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,iBAAiB,EAAW,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAGxH,0FAA0F;AAC1F,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,MAAM,EAAE,CAOxE;AAED,qBAAa,sBAAsB;IAQ/B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAI1B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAZ5B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAU;IACtC,OAAO,CAAC,eAAe,CAAC,CAAU;IAClC,OAAO,CAAC,aAAa,CAAC,CAAU;IAChC,OAAO,CAAC,aAAa,CAAC,CAAyB;IAC/C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;gBAGV,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,EAAE,iBAAiB,EAC7C,YAAY,EAAE,qBAAqB,EACnC,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,eAAe,EACN,SAAS,EAAE,MAAM,EAClC,QAAQ,EAAE,gBAAgB,EAAE;IAoC9B,OAAO,CAAC,aAAa;IAKd,MAAM,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,IAAI;CAsClD"}
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ /**
3
+ * ViessmannRoomAccessory — one HomeKit accessory per room of a ViCare Smart Climate
4
+ * "RoomControl" device (issue #4).
5
+ *
6
+ * Feature paths (confirmed on E3_RoomControl_One_05 with E3_RadiatorActuator TRVs):
7
+ * rooms.N.sensors.temperature value (°C), status connected/notConnected
8
+ * rooms.N.sensors.humidity value (%), status connected/notConnected
9
+ * rooms.N.sensors.window.openState value (boolean) — optional
10
+ * rooms.N.temperature.levels.heating temperature (°C) — current heating setpoint
11
+ *
12
+ * Services per room:
13
+ * - TemperatureSensor (always)
14
+ * - HumiditySensor (only when the room humidity sensor is connected)
15
+ * - ContactSensor (window open/closed, only when the feature exists)
16
+ *
17
+ * Enable with: "features": { "enableRoomSensors": true }
18
+ * Room names: "customNames": { "rooms": { "0": "Living room", "1": "Bedroom" } }
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.ViessmannRoomAccessory = void 0;
22
+ exports.detectRoomIndexes = detectRoomIndexes;
23
+ const history_logger_1 = require("./history-logger");
24
+ /** Room indexes exposed by a device (rooms.N.sensors.temperature present and enabled). */
25
+ function detectRoomIndexes(features) {
26
+ const idx = new Set();
27
+ for (const f of features) {
28
+ const m = /^rooms\.(\d+)\.sensors\.temperature$/.exec(f.feature);
29
+ if (m && f.isEnabled !== false)
30
+ idx.add(parseInt(m[1], 10));
31
+ }
32
+ return [...idx].sort((a, b) => a - b);
33
+ }
34
+ class ViessmannRoomAccessory {
35
+ platform;
36
+ accessory;
37
+ roomIndex;
38
+ tempService;
39
+ humidityService;
40
+ windowService;
41
+ historyLogger;
42
+ TAG;
43
+ constructor(platform, accessory, installation, gateway, device, roomIndex, features) {
44
+ this.platform = platform;
45
+ this.accessory = accessory;
46
+ this.roomIndex = roomIndex;
47
+ const { Service: Svc, Characteristic: Char } = platform;
48
+ this.TAG = `[Room ${roomIndex}]`;
49
+ accessory.getService(Svc.AccessoryInformation)
50
+ .setCharacteristic(Char.Manufacturer, 'Viessmann')
51
+ .setCharacteristic(Char.Model, device.modelId || 'ViCare Room')
52
+ .setCharacteristic(Char.SerialNumber, `${installation.id}-${device.id}-room${roomIndex}`);
53
+ this.tempService = accessory.getService(Svc.TemperatureSensor)
54
+ || accessory.addService(Svc.TemperatureSensor, accessory.displayName);
55
+ this.tempService.getCharacteristic(Char.CurrentTemperature).setProps({ minValue: -30, maxValue: 60 });
56
+ const feat = this.featureGetter(features);
57
+ // Humidity only if a sensor is actually connected
58
+ if (feat('sensors.humidity')?.properties?.status?.value === 'connected') {
59
+ this.humidityService = accessory.getService(Svc.HumiditySensor)
60
+ || accessory.addService(Svc.HumiditySensor, `${accessory.displayName} Humidity`);
61
+ }
62
+ else {
63
+ const old = accessory.getService(Svc.HumiditySensor);
64
+ if (old)
65
+ accessory.removeService(old);
66
+ }
67
+ // Window open/closed
68
+ if (feat('sensors.window.openState')?.properties?.value?.value !== undefined) {
69
+ this.windowService = accessory.getService(Svc.ContactSensor)
70
+ || accessory.addService(Svc.ContactSensor, `${accessory.displayName} Window`);
71
+ }
72
+ this.historyLogger = new history_logger_1.ViessmannHistoryLogger(platform, accessory, 'thermo', `Room${roomIndex}`, installation.id, gateway.serial);
73
+ // Hook into the platform refresh loop (it calls accessory.context.updateHandler)
74
+ accessory.context.updateHandler = (feats) => this.update(feats);
75
+ this.update(features);
76
+ }
77
+ featureGetter(features) {
78
+ const prefix = `rooms.${this.roomIndex}.`;
79
+ return (suffix) => features.find(f => f.feature === prefix + suffix && f.isEnabled !== false);
80
+ }
81
+ update(features) {
82
+ const Char = this.platform.Characteristic;
83
+ const feat = this.featureGetter(features);
84
+ const t = feat('sensors.temperature');
85
+ const temp = t?.properties?.value?.value;
86
+ const connected = t?.properties?.status?.value !== 'notConnected';
87
+ this.tempService.getCharacteristic(Char.StatusActive).updateValue(connected && typeof temp === 'number');
88
+ if (typeof temp === 'number') {
89
+ this.tempService.getCharacteristic(Char.CurrentTemperature).updateValue(temp);
90
+ }
91
+ if (this.humidityService) {
92
+ const h = feat('sensors.humidity')?.properties?.value?.value;
93
+ if (typeof h === 'number')
94
+ this.humidityService.getCharacteristic(Char.CurrentRelativeHumidity).updateValue(Math.max(0, Math.min(100, h)));
95
+ }
96
+ if (this.windowService) {
97
+ const open = feat('sensors.window.openState')?.properties?.value?.value === true;
98
+ this.windowService.getCharacteristic(Char.ContactSensorState).updateValue(open
99
+ ? Char.ContactSensorState.CONTACT_NOT_DETECTED
100
+ : Char.ContactSensorState.CONTACT_DETECTED);
101
+ }
102
+ const setpoint = feat('temperature.levels.heating')?.properties?.temperature?.value;
103
+ this.platform.log.debug(`${this.TAG} temp=${temp}°C setpoint=${setpoint ?? '-'}°C`);
104
+ if (typeof temp === 'number' && this.historyLogger) {
105
+ this.historyLogger.addThermoEntry({ currentTemp: temp, setTemp: typeof setpoint === 'number' ? setpoint : temp });
106
+ this.historyLogger.appendRow({
107
+ timestamp: new Date().toISOString(),
108
+ accessory: `room${this.roomIndex}`,
109
+ event_type: 'snapshot',
110
+ room_temp: temp,
111
+ target_temp: typeof setpoint === 'number' ? setpoint : undefined,
112
+ });
113
+ }
114
+ }
115
+ }
116
+ exports.ViessmannRoomAccessory = ViessmannRoomAccessory;
@@ -1 +1 @@
1
- {"version":3,"file":"auth-manager.d.ts","sourceRoot":"","sources":["../src/auth-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth-manager.d.ts","sourceRoot":"","sources":["../src/auth-manager.ts"],"names":[],"mappings":"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"}
@@ -675,31 +675,27 @@ class AuthManager {
675
675
  }
676
676
  }
677
677
  openBrowser(url) {
678
- // 🆕 Per servizi systemd: NON tentare di aprire automaticamente
679
- // L'utente può aprire da qualsiasi dispositivo sulla rete
678
+ // Always log the URL first (issue #3): in Docker/Umbrel/other containers the
679
+ // process runs as root without systemd variables, xdg-open does not exist and the
680
+ // URL was never shown, making the OAuth flow unrecoverable.
681
+ this.log.info('='.repeat(80));
682
+ this.log.info('🔐 AUTHENTICATION REQUIRED');
683
+ this.log.info('='.repeat(80));
684
+ this.log.info('');
685
+ this.log.info('📱 Open this URL from ANY device on your network:');
686
+ this.log.info('');
687
+ this.log.info(` ${url}`);
688
+ this.log.info('');
689
+ this.log.info(`🌐 Or open the status page: http://${this.hostIp}:${this.config.redirectPort || 4200}`);
690
+ this.log.info('⏳ Waiting for authentication...');
691
+ this.log.info('='.repeat(80));
692
+ // Try to open a local browser only on interactive desktop installs
680
693
  const isSystemdService = !!(process.env.SYSTEMD_EXEC_PID || process.env.INVOCATION_ID);
681
694
  const isHomebridge = process.env.USER === 'homebridge';
682
- // Se siamo in un servizio systemd o utente homebridge, non aprire automaticamente
683
- if (isSystemdService || isHomebridge) {
684
- this.log.info('='.repeat(80));
685
- this.log.info('🔐 AUTHENTICATION REQUIRED');
686
- this.log.info('='.repeat(80));
687
- this.log.info('');
688
- this.log.info('📱 Open this URL from ANY device on your network:');
689
- this.log.info('');
690
- this.log.info(` ${url}`);
691
- this.log.info('');
692
- this.log.info('✅ You can open it from:');
693
- this.log.info(' • Your computer/laptop');
694
- this.log.info(' • Your smartphone/tablet');
695
- this.log.info(' • This Raspberry Pi (if you have a browser)');
696
- this.log.info('');
697
- this.log.info(`🌐 Auth server is listening on: ${this.hostIp}:${this.config.redirectPort || 4200}`);
698
- this.log.info('⏳ Waiting for authentication...');
699
- this.log.info('='.repeat(80));
695
+ const isContainer = require('fs').existsSync('/.dockerenv') || !!process.env.container;
696
+ if (isSystemdService || isHomebridge || isContainer) {
700
697
  return;
701
698
  }
702
- // Solo per installazioni non-systemd (es. macOS, sviluppo locale)
703
699
  this.tryOpenBrowserDirect(url);
704
700
  }
705
701
  tryOpenBrowserDirect(url) {
@@ -717,7 +713,7 @@ class AuthManager {
717
713
  }
718
714
  exec(command, (error) => {
719
715
  if (error) {
720
- this.log.info('📱 Please open the authentication URL manually in your browser');
716
+ this.log.info(`📱 Could not open a browser automatically — open the URL above manually: ${url}`);
721
717
  }
722
718
  else {
723
719
  this.log.info('🌐 Opening browser...');
@@ -61,7 +61,15 @@ export declare class ViessmannPlatform implements DynamicPlatformPlugin {
61
61
  setupHeatingCircuitAccessories(installation: ViessmannInstallation, gateway: ViessmannGateway, device: ViessmannDevice, features: ViessmannFeature[]): Promise<void>;
62
62
  setupEnergyAccessory(installation: ViessmannInstallation, gateway: ViessmannGateway, device: ViessmannDevice, features: ViessmannFeature[]): Promise<void>;
63
63
  private setupRoomSensorDiscovery;
64
+ private setupRoomAccessories;
64
65
  updateAllDevices(): Promise<void>;
66
+ /**
67
+ * Writes device.messages.* entries (status S.xx, info I.xx, service, errors F.xx) to
68
+ * viessmann-messages-<installationId>-<deviceId>.json, used by viessmann-report.js.
69
+ * The API only returns the CURRENT messages, so entries are merged with the existing
70
+ * file (deduplicated by code+timestamp, newest first, max 200) to keep a history.
71
+ */
72
+ private writeDeviceMessages;
65
73
  private updateCycleComplete;
66
74
  private writeApiStatusFile;
67
75
  private adjustRefreshInterval;
@@ -1 +1 @@
1
- {"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"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"}