homebridge-melcloud-control 4.1.3-beta.9 → 4.2.0-beta.0

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
@@ -22,6 +22,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
22
22
 
23
23
  - Do not use Homebridge UI > v5.5.0 because of break config.json
24
24
 
25
+ ## [4.2.0] - (xx.11.2025)
26
+
27
+ ## Changes
28
+
29
+ - initial support for MELCloud Home ATW device
30
+ - added frost protection control for MELCloud Home ATA device
31
+ - added overheat protection control for MELCloud Home ATA device
32
+ - added holiday mode control MELCloud Home ATA, ERV, ATW devices
33
+ - config schema updated
34
+ - readme updated
35
+ - cleanup
36
+
25
37
  ## [4.1.2] - (11.11.2025)
26
38
 
27
39
  ## Changes
package/README.md CHANGED
@@ -65,6 +65,9 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
65
65
  * Vane V mode `AUTO/1/2/3/4/5/SWING`.
66
66
  * Fan speed mode `AUTO/1/2/3/4/5`.
67
67
  * Presets `SET/UNSET`.
68
+ * Frost protection `ON/OFF`.
69
+ * Overheat protection `ON/OFF`.
70
+ * Holiday mode `ON/OFF`.
68
71
  * Schedule `ON/OFF`.
69
72
  * Sensors:
70
73
  * For automation and notifications.
@@ -79,6 +82,8 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
79
82
  * Outdoor temperature.
80
83
  * Frost protection.
81
84
  * Overheat protection.
85
+ * Frost protection.
86
+ * Overheat protection.
82
87
  * Holiday mode.
83
88
  * Shedule control.
84
89
  * Shedule active
@@ -119,6 +124,7 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
119
124
  * Operating mode `HEAT/COOL/CURVE/HOLIDAY/AUTO HOT WATER/ECO HOT WATER/FORCE HOT WATER`.
120
125
  * Physical lock controls `LOCK/UNLOCK`.
121
126
  * Presets `SET/UNSET`.
127
+ * Holiday mode `ON/OFF`.
122
128
  * Schedule `ON/OFF`.
123
129
  * Sensors:
124
130
  * For automation and notifications.
@@ -132,6 +138,7 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
132
138
  * Water tank temperature.
133
139
  * Flow Temperature Zone 1, 2, Hot Water.
134
140
  * Return Temperature Zone 1, 2, Hot Water.
141
+ * Holiday mode.
135
142
  * Shedule control.
136
143
  * Shedule active
137
144
  * Error
@@ -151,6 +158,7 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
151
158
  * Operating mode `LOSSNAY/BYPASS/AUTO/NIGHT PURGE`.
152
159
  * Fan speed mode `AUTO/1/2/3/4`.
153
160
  * Presets `SET/UNSET`.
161
+ * Holiday mode `ON/OFF`.
154
162
  * Schedule `ON/OFF`.
155
163
  * Sensors:
156
164
  * For automation and notifications.
@@ -165,6 +173,7 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
165
173
  * Filter maintenance.
166
174
  * CO2 detected and level.
167
175
  * PM2.5 air quality and level.
176
+ * Holiday mode.
168
177
  * Shedule control.
169
178
  * Shedule active
170
179
  * Error
@@ -234,10 +243,10 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
234
243
  | `ataDevices[].autoDryFanMode` | Here select the operatiing mode for `Auto`, if this mode is not supported, it will be disabled.. |
235
244
  | `ataDevices[].temperatureSensor` | This enable extra `Room` temperature sensor to use with automations in HomeKit app. |
236
245
  | `ataDevices[].temperatureOutdoorSensor` | This enable extra `Outdoor` temperature sensor to use with automations in HomeKit app. |
237
- | `ataDevices[].frostProtectionSensor` | This enable extra `Frost Protectio` sensor to use with automations in HomeKit app. |
238
- | `ataDevices[].overHeatProtectionSensor` | This enable extra `Overheat Protection` sensor to use with automations in HomeKit app. |
239
- | `ataDevices[].holidayModeSensor` | This enable extra `Holiday Mode` sensor to use with automations in HomeKit app. |
240
246
  | `ataDevices[].errorSensor` | This enable `Error` sensor to use with automations in HomeKit app. |
247
+ | `ataDevices[].frostProtectionSupport` | This enable extra `Frost Protectio` control and sensors to use with automations in HomeKit app. |
248
+ | `ataDevices[].overheatProtectionSupport` | This enable extra `Overheat Protection` control and sensors to use with automations in HomeKit app. |
249
+ | `ataDevices[].holidayModeSupport` | This enable extra `Holiday Mode` control and sensors to use with automations in HomeKit app. |
241
250
  | `ataDevices[].refreshInterval` | Here set the background devices state refresh time in (sec), default `5s`. |
242
251
  | `ataDevices[].presets[]` | Array of ATA device `Presets` created automatically after login to MELCloud from plugin config UI. |
243
252
  | `ataDevices[].presets[].id` | Read only data, do not change it. |
@@ -268,8 +277,8 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
268
277
  | `atwDevices[].temperatureReturnWaterTankSensor` | This enable extra `Return Water Tank` temperature sensor to use with automations in HomeKit app. |
269
278
  | `atwDevices[].temperatureFlowZone2Sensor` | This enable extra `Flow Zone 2` temperature sensor to use with automations in HomeKit app. |
270
279
  | `atwDevices[].temperatureReturnZone2Sensor` | This enable extra `Return Zone 2` temperature sensor to use with automations in HomeKit app. |
271
- | `atwDevices[].holidayModeSensor` | This enable extra `Holiday Mode` sensor to use with automations in HomeKit app. |
272
280
  | `atwDevices[].errorSensor` | This enable `Error` sensors to use with automations in HomeKit app. |
281
+ | `atwDevices[].holidayModeSupport` | This enable extra `Holiday Mode` control and sensors to use with automations in HomeKit app. |
273
282
  | `atwDevices[].refreshInterval` | Here set the background devices state refresh time in (sec), default `5s`. |
274
283
  | `atwDevices[].presets[]` | Array of ATW device `Presets` created automatically after login to MELCloud from plugin config UI. |
275
284
  | `atwDevices[].presets[].id` | Read only data, do not change it. |
@@ -293,8 +302,8 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
293
302
  | `ervDevices[].temperatureSensor` | This enable extra `Room` temperature sensor to use with automations in HomeKit app. |
294
303
  | `ervDevices[].temperatureOutdoorSensor` | This enable extra `Outdoor` temperature sensor to use with automations in HomeKit app. |
295
304
  | `ervDevices[].temperatureSupplySensor` | This enable extra `Supply` temperature sensor to use with automations in HomeKit app. |
296
- | `ervDevices[].holidayModeSensor` | This enable extra `Holiday Mode` sensor to use with automations in HomeKit app. |
297
305
  | `ervDevices[].errorSensor` | This enable `Error` sensors to use with automations in HomeKit app. |
306
+ | `ervDevices[].holidayModeSupport` | This enable extra `Holiday Mode` control and sensors to use with automations in HomeKit app. |
298
307
  | `ervDevices[].refreshInterval` | Here set the background devices state refresh time in (sec), default `5s`. |
299
308
  | `ervDevices[].presets[]` | Array of ERV device `Presets` created automatically after login to MELCloud from plugin config UI. |
300
309
  | `ervDevices[].presets[].id` | Read only data, do not change it. |
@@ -395,38 +395,38 @@
395
395
  "default": false,
396
396
  "description": "This enable extra outdoor temperature sensor to use with automations in HomeKit app."
397
397
  },
398
- "frostProtectionSensor": {
399
- "title": "Frost Protection",
398
+ "errorSensor": {
399
+ "title": "Error",
400
400
  "type": "boolean",
401
401
  "default": false,
402
- "description": "This enable extra frost protection sensor to use with automations in HomeKit app.",
403
- "condition": {
404
- "functionBody": "return model.accounts[arrayIndices[0]].type === 'melcloudhome';"
405
- }
402
+ "description": "This enable error sensor to use with automations in HomeKit app."
406
403
  },
407
- "overheatProtectionSensor": {
408
- "title": "Overheat Protection",
404
+ "frostProtectionSupport": {
405
+ "title": "Frost Protection Support",
409
406
  "type": "boolean",
410
407
  "default": false,
411
- "description": "This enable extra overheat protection sensor to use with automations in HomeKit app.",
408
+ "description": "This enable extra frost protection control and sensors to use with automations in HomeKit app.",
412
409
  "condition": {
413
410
  "functionBody": "return model.accounts[arrayIndices[0]].type === 'melcloudhome';"
414
411
  }
415
412
  },
416
- "holidayModeSensor": {
417
- "title": "Holiday Mode",
413
+ "overheatProtectionSupport": {
414
+ "title": "Overheat Protection Support",
418
415
  "type": "boolean",
419
416
  "default": false,
420
- "description": "This enable extra holiday mode sensor to use with automations in HomeKit app.",
417
+ "description": "This enable extra overheat protection control and sensors to use with automations in HomeKit app.",
421
418
  "condition": {
422
419
  "functionBody": "return model.accounts[arrayIndices[0]].type === 'melcloudhome';"
423
420
  }
424
421
  },
425
- "errorSensor": {
426
- "title": "Error",
422
+ "holidayModeSupport": {
423
+ "title": "Holiday Mode Support",
427
424
  "type": "boolean",
428
425
  "default": false,
429
- "description": "This enable error sensor to use with automations in HomeKit app."
426
+ "description": "This enable extra holiday mode control and sensors to use with automations in HomeKit app.",
427
+ "condition": {
428
+ "functionBody": "return model.accounts[arrayIndices[0]].type === 'melcloudhome';"
429
+ }
430
430
  },
431
431
  "refreshInterval": {
432
432
  "title": "Refresh Interval",
@@ -1107,21 +1107,21 @@
1107
1107
  "default": false,
1108
1108
  "description": "This enable extra Return Zone 2 temperature sensor to use with automations in HomeKit app."
1109
1109
  },
1110
- "holidayModeSensor": {
1111
- "title": "Holiday Mode",
1112
- "type": "boolean",
1113
- "default": false,
1114
- "description": "This enable extra holiday mode sensor to use with automations in HomeKit app.",
1115
- "condition": {
1116
- "functionBody": "return model.accounts[arrayIndices[0]].type === 'melcloudhome';"
1117
- }
1118
- },
1119
1110
  "errorSensor": {
1120
1111
  "title": "Error",
1121
1112
  "type": "boolean",
1122
1113
  "default": false,
1123
1114
  "description": "This enable error sensor to use with automations in HomeKit app."
1124
1115
  },
1116
+ "holidayModeSupport": {
1117
+ "title": "Holiday Mode Support",
1118
+ "type": "boolean",
1119
+ "default": false,
1120
+ "description": "This enable extra holiday mode control and sensors to use with automations in HomeKit app.",
1121
+ "condition": {
1122
+ "functionBody": "return model.accounts[arrayIndices[0]].type === 'melcloudhome';"
1123
+ }
1124
+ },
1125
1125
  "refreshInterval": {
1126
1126
  "title": "Refresh Interval",
1127
1127
  "type": "integer",
@@ -1579,21 +1579,21 @@
1579
1579
  "default": false,
1580
1580
  "description": "This enable extra supply temperature sensor to use with automations in HomeKit app."
1581
1581
  },
1582
- "holidayModeSensor": {
1583
- "title": "Holiday Mode",
1584
- "type": "boolean",
1585
- "default": false,
1586
- "description": "This enable extra holiday mode sensor to use with automations in HomeKit app.",
1587
- "condition": {
1588
- "functionBody": "return model.accounts[arrayIndices[0]].type === 'melcloudhome';"
1589
- }
1590
- },
1591
1582
  "errorSensor": {
1592
1583
  "title": "Error",
1593
1584
  "type": "boolean",
1594
1585
  "default": false,
1595
1586
  "description": "This enable error sensor to use with automations in HomeKit app."
1596
1587
  },
1588
+ "holidayModeSupport": {
1589
+ "title": "Holiday Mode Support",
1590
+ "type": "boolean",
1591
+ "default": false,
1592
+ "description": "This enable extra holiday mode control and sensors to use with automations in HomeKit app.",
1593
+ "condition": {
1594
+ "functionBody": "return model.accounts[arrayIndices[0]].type === 'melcloudhome';"
1595
+ }
1596
+ },
1597
1597
  "refreshInterval": {
1598
1598
  "title": "Refresh Interval",
1599
1599
  "type": "integer",
@@ -2139,6 +2139,9 @@
2139
2139
  "accounts[].ataDevices[].heatDryFanMode",
2140
2140
  "accounts[].ataDevices[].coolDryFanMode",
2141
2141
  "accounts[].ataDevices[].autoDryFanMode",
2142
+ "accounts[].ataDevices[].frostProtectionSupport",
2143
+ "accounts[].ataDevices[].overheatProtectionSupport",
2144
+ "accounts[].ataDevices[].holidayModeSupport",
2142
2145
  "accounts[].ataDevices[].refreshInterval"
2143
2146
  ],
2144
2147
  "condition": {
@@ -2218,9 +2221,6 @@
2218
2221
  {
2219
2222
  "title": "System",
2220
2223
  "items": [
2221
- "accounts[].ataDevices[].frostProtectionSensor",
2222
- "accounts[].ataDevices[].overheatProtectionSensor",
2223
- "accounts[].ataDevices[].holidayModeSensor",
2224
2224
  "accounts[].ataDevices[].errorSensor"
2225
2225
  ]
2226
2226
  },
@@ -2285,6 +2285,7 @@
2285
2285
  "items": [
2286
2286
  "accounts[].atwDevices[].hideZone",
2287
2287
  "accounts[].atwDevices[].name",
2288
+ "accounts[].atwDevices[].holidayModeSupport",
2288
2289
  "accounts[].atwDevices[].refreshInterval"
2289
2290
  ],
2290
2291
  "condition": {
@@ -2371,7 +2372,6 @@
2371
2372
  {
2372
2373
  "title": "System",
2373
2374
  "items": [
2374
- "accounts[].atwDevices[].holidayModeSensor",
2375
2375
  "accounts[].atwDevices[].errorSensor"
2376
2376
  ]
2377
2377
  },
@@ -2435,6 +2435,7 @@
2435
2435
  "expanded": false,
2436
2436
  "items": [
2437
2437
  "accounts[].ervDevices[].name",
2438
+ "accounts[].ervDevices[].holidayModeSupport",
2438
2439
  "accounts[].ervDevices[].refreshInterval"
2439
2440
  ],
2440
2441
  "condition": {
@@ -2515,7 +2516,6 @@
2515
2516
  {
2516
2517
  "title": "System",
2517
2518
  "items": [
2518
- "accounts[].ervDevices[].holidayModeSensor",
2519
2519
  "accounts[].ervDevices[].errorSensor"
2520
2520
  ]
2521
2521
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "MELCloud Control",
3
3
  "name": "homebridge-melcloud-control",
4
- "version": "4.1.3-beta.9",
4
+ "version": "4.2.0-beta.0",
5
5
  "description": "Homebridge plugin to control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.",
6
6
  "license": "MIT",
7
7
  "author": "grzegorz914",
package/src/deviceata.js CHANGED
@@ -29,10 +29,10 @@ class DeviceAta extends EventEmitter {
29
29
  this.displayType = device.displayType;
30
30
  this.temperatureSensor = device.temperatureSensor || false;
31
31
  this.temperatureOutdoorSensor = device.temperatureOutdoorSensor || false;
32
- this.frostProtectionSensor = device.frostProtectionSensor || false;
33
- this.overheatProtectionSensor = device.overheatProtectionSensor || false;
34
- this.holidayModeSensor = device.holidayModeSensor || false;
35
32
  this.errorSensor = device.errorSensor || false;
33
+ this.frostProtectionSupport = device.frostProtectionSupport || false;
34
+ this.overheatProtectionSupport = device.overheatProtectionSupport || false;
35
+ this.holidayModeSupport = device.holidayModeSupport || false;
36
36
  this.heatDryFanMode = device.heatDryFanMode || 1; //NONE, HEAT, DRY, FAN
37
37
  this.coolDryFanMode = device.coolDryFanMode || 1; //NONE, COOL, DRY, FAN
38
38
  this.autoDryFanMode = device.autoDryFanMode || 1; //NONE, AUTO, DRY, FAN
@@ -618,12 +618,59 @@ class DeviceAta extends EventEmitter {
618
618
  accessory.addService(this.outdoorTemperatureSensorService);
619
619
  };
620
620
 
621
- //frost protection sensor
622
- if (this.frostProtectionSensor && this.accessory.frostProtectionEnabled) {
621
+ //error sensor
622
+ if (this.errorSensor && this.accessory.isInError !== null) {
623
+ if (this.logDebug) this.emit('debug', `Prepare error service`);
624
+ this.errorService = new Service.ContactSensor(`${serviceName} Error`, `Error Sensor ${deviceId}`);
625
+ this.errorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
626
+ this.errorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Error`);
627
+ this.errorService.getCharacteristic(Characteristic.ContactSensorState)
628
+ .onGet(async () => {
629
+ const state = this.accessory.isInError;
630
+ return state;
631
+ })
632
+ accessory.addService(this.errorService);
633
+ }
634
+
635
+ //frost protection
636
+ if (this.frostProtectionSupport && this.accessory.frostProtectionEnabled !== null) {
637
+ //control
638
+ if (this.logDebug) this.emit('debug', `Prepare frost protection control service`);
639
+ this.frostProtectionControlService = new Service.Switch(`${serviceName} Frost Protection`, `frostProtectionControlService${deviceId}`);
640
+ this.frostProtectionControlService.addOptionalCharacteristic(Characteristic.ConfiguredName);
641
+ this.frostProtectionControlService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Frost Protection`);
642
+ this.frostProtectionControlService.getCharacteristic(Characteristic.On)
643
+ .onGet(async () => {
644
+ const state = this.accessory.frostProtectionEnabled;
645
+ return state;
646
+ })
647
+ .onSet(async (state) => {
648
+ try {
649
+ deviceData.FrostProtection.Enabled = state;
650
+ await this.melCloudAta.send(this.accountType, this.displayType, deviceData, 'frostprotection');
651
+ if (this.logInfo) this.emit('info', `Frost protection: ${state ? 'Enabled' : 'Disabled'}`);
652
+ } catch (error) {
653
+ if (this.logWarn) this.emit('warn', `Set frost protection error: ${error}`);
654
+ };
655
+ });
656
+ accessory.addService(this.frostProtectionControlService);
657
+
658
+ if (this.logDebug) this.emit('debug', `Prepare frost protection control sensor service`);
659
+ this.frostProtectionControlSensorService = new Service.ContactSensor(`${serviceName} Frost Protection Control`, `frostProtectionControlSensorService${deviceId}`);
660
+ this.frostProtectionControlSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
661
+ this.frostProtectionControlSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Frost Protection Control`);
662
+ this.frostProtectionControlSensorService.getCharacteristic(Characteristic.ContactSensorState)
663
+ .onGet(async () => {
664
+ const state = this.accessory.frostProtectionEnabled;
665
+ return state;
666
+ })
667
+ accessory.addService(this.frostProtectionControlSensorService);
668
+
669
+ //sensor
623
670
  if (this.logDebug) this.emit('debug', `Prepare frost protection service`);
624
- this.frostProtectionSensorService = new Service.ContactSensor(`${serviceName} Frost Protection`, `Frost Protection Sensor ${deviceId}`);
671
+ this.frostProtectionSensorService = new Service.ContactSensor(`${serviceName} Frost Protection`, `frostProtectionSensorService${deviceId}`);
625
672
  this.frostProtectionSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
626
- this.frostProtectionSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Frost Protection`);
673
+ this.frostProtectionSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Frost Protection State`);
627
674
  this.frostProtectionSensorService.getCharacteristic(Characteristic.ContactSensorState)
628
675
  .onGet(async () => {
629
676
  const state = this.accessory.frostProtectionActive;
@@ -632,12 +679,44 @@ class DeviceAta extends EventEmitter {
632
679
  accessory.addService(this.frostProtectionSensorService);
633
680
  }
634
681
 
635
- //overheat sensor
636
- if (this.overheatProtectionSensor && this.accessory.overheatProtectionEnabled !== null) {
637
- if (this.logDebug) this.emit('debug', `Prepare overheat protection service`);
638
- this.overheatProtectionSensorService = new Service.ContactSensor(`${serviceName} Overheat Protection`, `Overheat Protection Sensor ${deviceId}`);
682
+ //overheat protection
683
+ if (this.overheatProtectionSupport && this.accessory.overheatProtectionEnabled !== null) {
684
+ //control
685
+ if (this.logDebug) this.emit('debug', `Prepare overheat protection control service`);
686
+ this.overheatProtectionControlService = new Service.Switch(`${serviceName} Overheat Protection`, `overheatProtectionControlService${deviceId}`);
687
+ this.overheatProtectionControlService.addOptionalCharacteristic(Characteristic.ConfiguredName);
688
+ this.overheatProtectionControlService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Overheat Protection`);
689
+ this.overheatProtectionControlService.getCharacteristic(Characteristic.On)
690
+ .onGet(async () => {
691
+ const state = this.accessory.overheatProtectionEnabled;
692
+ return state;
693
+ })
694
+ .onSet(async (state) => {
695
+ try {
696
+ deviceData.OverheatProtection.Enabled = state;
697
+ await this.melCloudAta.send(this.accountType, this.displayType, deviceData, 'overheatprotection');
698
+ if (this.logInfo) this.emit('info', `Overheat protection: ${state ? 'Enabled' : 'Disabled'}`);
699
+ } catch (error) {
700
+ if (this.logWarn) this.emit('warn', `Set overheat protection error: ${error}`);
701
+ };
702
+ });
703
+ accessory.addService(this.overheatProtectionControlService);
704
+
705
+ if (this.logDebug) this.emit('debug', `Prepare overheat protection control sensor service`);
706
+ this.overheatProtectionControlSensorService = new Service.ContactSensor(`${serviceName} Overheat Protection Control`, `overheatProtectionControlSensorService${deviceId}`);
707
+ this.overheatProtectionControlSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
708
+ this.overheatProtectionControlSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Overheat Protection Control`);
709
+ this.overheatProtectionControlSensorService.getCharacteristic(Characteristic.ContactSensorState)
710
+ .onGet(async () => {
711
+ const state = this.accessory.overheatProtectionEnabled;
712
+ return state;
713
+ })
714
+ accessory.addService(this.overheatProtectionControlSensorService);
715
+
716
+ if (this.logDebug) this.emit('debug', `Prepare overheat protection sensor service`);
717
+ this.overheatProtectionSensorService = new Service.ContactSensor(`${serviceName} Overheat Protection`, `overheatProtectionSensorService${deviceId}`);
639
718
  this.overheatProtectionSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
640
- this.overheatProtectionSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Overheat Protection`);
719
+ this.overheatProtectionSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Overheat Protection State`);
641
720
  this.overheatProtectionSensorService.getCharacteristic(Characteristic.ContactSensorState)
642
721
  .onGet(async () => {
643
722
  const state = this.accessory.overheatProtectionActive;
@@ -646,32 +725,51 @@ class DeviceAta extends EventEmitter {
646
725
  accessory.addService(this.overheatProtectionSensorService);
647
726
  }
648
727
 
649
- //holiday mode sensor
650
- if (this.holidayModeSensor && this.accessory.holidayModeEnabled !== null) {
651
- if (this.logDebug) this.emit('debug', `Prepare holiday mode service`);
652
- this.holidayModeSensorService = new Service.ContactSensor(`${serviceName} Holiday Mode`, `Holiday Mode Sensor ${deviceId}`);
653
- this.holidayModeSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
654
- this.holidayModeSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Holiday Mode`);
655
- this.holidayModeSensorService.getCharacteristic(Characteristic.ContactSensorState)
728
+ //holiday mode
729
+ if (this.holidayModeSupport && this.accessory.holidayModeEnabled !== null) {
730
+ //control
731
+ if (this.logDebug) this.emit('debug', `Prepare holiday mode control service`);
732
+ this.holidayModeControlService = new Service.Switch(`${serviceName} Holiday Mode`, `holidayModeControlService${deviceId}`);
733
+ this.holidayModeControlService.addOptionalCharacteristic(Characteristic.ConfiguredName);
734
+ this.holidayModeControlService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Holiday Mode`);
735
+ this.holidayModeControlService.getCharacteristic(Characteristic.On)
656
736
  .onGet(async () => {
657
- const state = this.accessory.holidayModeActive;
737
+ const state = this.accessory.holidayModeEnabled;
658
738
  return state;
659
739
  })
660
- accessory.addService(this.holidayModeSensorService);
661
- }
740
+ .onSet(async (state) => {
741
+ try {
742
+ deviceData.HolidayMode.Enabled = state;
743
+ await this.melCloudAta.send(this.accountType, this.displayType, deviceData, 'holidaymode');
744
+ if (this.logInfo) this.emit('info', `Holiday mode: ${state ? 'Enabled' : 'Disabled'}`);
745
+ } catch (error) {
746
+ if (this.logWarn) this.emit('warn', `Set holiday mode error: ${error}`);
747
+ };
748
+ });
749
+ accessory.addService(this.holidayModeControlService);
750
+
751
+ if (this.logDebug) this.emit('debug', `Prepare holiday mode control sensor service`);
752
+ this.holidayModeControlSensorService = new Service.ContactSensor(`${serviceName} Holiday Mode Control`, `holidayModeControlSensorService${deviceId}`);
753
+ this.holidayModeControlSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
754
+ this.holidayModeControlSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Holiday Mode Control`);
755
+ this.holidayModeControlSensorService.getCharacteristic(Characteristic.ContactSensorState)
756
+ .onGet(async () => {
757
+ const state = this.accessory.holidayModeEnabled;
758
+ return state;
759
+ })
760
+ accessory.addService(this.holidayModeControlSensorService);
662
761
 
663
- //error sensor
664
- if (this.errorSensor && this.accessory.isInError !== null) {
665
- if (this.logDebug) this.emit('debug', `Prepare error service`);
666
- this.errorService = new Service.ContactSensor(`${serviceName} Error`, `Error Sensor ${deviceId}`);
667
- this.errorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
668
- this.errorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Error`);
669
- this.errorService.getCharacteristic(Characteristic.ContactSensorState)
762
+ //sensors
763
+ if (this.logDebug) this.emit('debug', `Prepare holiday mode sensor service`);
764
+ this.holidayModeSensorService = new Service.ContactSensor(`${serviceName} Holiday Mode`, `holidayModeSensorService${deviceId}`);
765
+ this.holidayModeSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
766
+ this.holidayModeSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Holiday Mode State`);
767
+ this.holidayModeSensorService.getCharacteristic(Characteristic.ContactSensorState)
670
768
  .onGet(async () => {
671
- const state = this.accessory.isInError;
769
+ const state = this.accessory.holidayModeActive;
672
770
  return state;
673
771
  })
674
- accessory.addService(this.errorService);
772
+ accessory.addService(this.holidayModeSensorService);
675
773
  }
676
774
 
677
775
  //presets services
@@ -746,7 +844,7 @@ class DeviceAta extends EventEmitter {
746
844
  if (i === 0) {
747
845
  if (this.logDebug) this.emit('debug', `Prepare schedule control service`);
748
846
  const serviceNameSchedule = namePrefix ? `${accessoryName} Schedule Control` : `Schedule Control`;
749
- this.schedulesControlService = new Service.Switch(serviceNameSchedule, `Schedule Control ${deviceId} ${i}`);
847
+ this.schedulesControlService = new Service.Switch(serviceNameSchedule, `schedulesControlService${deviceId} ${i}`);
750
848
  this.schedulesControlService.addOptionalCharacteristic(Characteristic.ConfiguredName);
751
849
  this.schedulesControlService.setCharacteristic(Characteristic.ConfiguredName, serviceNameSchedule);
752
850
  this.schedulesControlService.getCharacteristic(Characteristic.On)
@@ -757,7 +855,7 @@ class DeviceAta extends EventEmitter {
757
855
  .onSet(async (state) => {
758
856
  try {
759
857
  deviceData.ScheduleEnabled = state;
760
- await this.melCloudAta.send(this.accountType, this.displayType, deviceData, 'scheduleenabled');
858
+ await this.melCloudAta.send(this.accountType, this.displayType, deviceData, 'schedule');
761
859
  if (this.logInfo) this.emit('info', `Schedule: ${state ? 'Enabled' : 'Disabled'}`);
762
860
  } catch (error) {
763
861
  if (this.logWarn) this.emit('warn', `Set schedule error: ${error}`);
@@ -766,22 +864,22 @@ class DeviceAta extends EventEmitter {
766
864
  accessory.addService(this.schedulesControlService);
767
865
 
768
866
  if (this.logDebug) this.emit('debug', `Prepare schedule control sensor service`);
769
- this.scheduleSensorService = new Service.ContactSensor(serviceNameSchedule, `Schedule Control Sensor ${deviceId}`);
770
- this.scheduleSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
771
- this.scheduleSensorService.setCharacteristic(Characteristic.ConfiguredName, serviceNameSchedule);
772
- this.scheduleSensorService.getCharacteristic(Characteristic.ContactSensorState)
867
+ this.schedulesControlSensorService = new Service.ContactSensor(serviceNameSchedule, `schedulesControlSensorService${deviceId}`);
868
+ this.schedulesControlSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
869
+ this.schedulesControlSensorService.setCharacteristic(Characteristic.ConfiguredName, serviceNameSchedule);
870
+ this.schedulesControlSensorService.getCharacteristic(Characteristic.ContactSensorState)
773
871
  .onGet(async () => {
774
872
  const state = this.accessory.scheduleEnabled;
775
873
  return state;
776
874
  })
777
- accessory.addService(this.scheduleSensorService);
875
+ accessory.addService(this.schedulesControlSensorService);
778
876
  }
779
877
 
780
878
  //sensors
781
879
  const serviceName = namePrefix ? `${accessoryName} ${name}` : name;
782
880
  const serviceType = schedule.serviceType;
783
881
  const characteristicType = schedule.characteristicType;
784
- const scheduleService = new serviceType(serviceName, `Schedule Sensor ${deviceId} ${i}`);
882
+ const scheduleService = new serviceType(serviceName, `scheduleService${deviceId} ${i}`);
785
883
  scheduleService.addOptionalCharacteristic(Characteristic.ConfiguredName);
786
884
  scheduleService.setCharacteristic(Characteristic.ConfiguredName, serviceName);
787
885
  scheduleService.getCharacteristic(characteristicType)
@@ -1072,8 +1170,6 @@ class DeviceAta extends EventEmitter {
1072
1170
  this.deviceData = deviceData;
1073
1171
 
1074
1172
  //keys
1075
- const presetsIdKey = this.accountType === 'melcloud' ? 'ID' : 'Id';
1076
- const setTempKey = this.accountType === 'melcloud' ? 'SetTemperature' : 'SetPoint';
1077
1173
  const fanKey = this.accountType === 'melcloud' ? 'FanSpeed' : 'SetFanSpeed';
1078
1174
  const tempStepKey = this.accountType === 'melcloud' ? 'TemperatureIncrement' : 'HasHalfDegreeIncrements';
1079
1175
  const errorKey = this.accountType === 'melcloud' ? 'HasError' : 'IsInError';
@@ -1085,19 +1181,18 @@ class DeviceAta extends EventEmitter {
1085
1181
  const supportDryKey = this.accountType === 'melcloud' ? 'ModelSupportsDry' : 'HasDryOperationMode';
1086
1182
  const supportCoolKey = this.accountType === 'melcloud' ? 'ModelSupportsCool' : 'HasCoolOperationMode';
1087
1183
 
1088
- //presets schedule
1184
+ //presets schedules
1089
1185
  const scheduleEnabled = deviceData.ScheduleEnabled;
1090
1186
  const schedulesOnServer = deviceData.Schedule ?? [];
1091
1187
  const presetsOnServer = deviceData.Presets ?? [];
1092
1188
  const holidayModeEnabled = deviceData.HolidayMode?.Enabled;
1093
- const holidayModeActive = deviceData.HolidayMode?.Active;
1094
-
1189
+ const holidayModeActive = deviceData.HolidayMode?.Active ?? false;
1095
1190
 
1096
1191
  //protection
1097
1192
  const frostProtectionEnabled = deviceData.FrostProtection?.Enabled;
1098
- const frostProtectionActive = deviceData.FrostProtection?.Active;
1193
+ const frostProtectionActive = deviceData.FrostProtection?.Active ?? false;
1099
1194
  const overheatProtectionEnabled = deviceData.OverheatProtection?.Enabled;
1100
- const overheatProtectionActive = deviceData.OverheatProtection?.Active;
1195
+ const overheatProtectionActive = deviceData.OverheatProtection?.Active ?? false;
1101
1196
 
1102
1197
  //device control
1103
1198
  const hideVaneControls = deviceData.HideVaneControls ?? false;
@@ -1331,17 +1426,36 @@ class DeviceAta extends EventEmitter {
1331
1426
  };
1332
1427
  this.accessory = obj;
1333
1428
 
1429
+ //senors
1334
1430
  this.roomTemperatureSensorService?.updateCharacteristic(Characteristic.CurrentTemperature, roomTemperature);
1335
1431
  this.outdoorTemperatureSensorService?.updateCharacteristic(Characteristic.CurrentTemperature, outdoorTemperature);
1336
- this.frostProtectionSensorService?.updateCharacteristic(Characteristic.ContactSensorState, frostProtectionActive);
1337
- this.overheatProtectionSensorService?.updateCharacteristic(Characteristic.ContactSensorState, overheatProtectionActive);
1338
- this.holidayModeSensorService?.updateCharacteristic(Characteristic.ContactSensorState, holidayModeActive);
1339
1432
  this.errorService?.updateCharacteristic(Characteristic.ContactSensorState, isInError);
1340
1433
 
1341
- //update presets state
1434
+ //frost protection
1435
+ if (this.frostProtectionSupport && frostProtectionEnabled !== null) {
1436
+ this.frostProtectionControlService?.updateCharacteristic(Characteristic.On, frostProtectionEnabled);
1437
+ this.frostProtectionControlSensorService?.updateCharacteristic(Characteristic.ContactSensorState, frostProtectionEnabled);
1438
+ this.frostProtectionSensorService?.updateCharacteristic(Characteristic.ContactSensorState, frostProtectionActive);
1439
+ }
1440
+
1441
+ //overheat protection
1442
+ if (this.overheatProtectionSupport && overheatProtectionEnabled !== null) {
1443
+ this.overheatProtectionControlService?.updateCharacteristic(Characteristic.On, overheatProtectionEnabled);
1444
+ this.overheatProtectionControlSensorService?.updateCharacteristic(Characteristic.ContactSensorState, overheatProtectionEnabled);
1445
+ this.overheatProtectionSensorService?.updateCharacteristic(Characteristic.ContactSensorState, overheatProtectionActive);
1446
+ }
1447
+
1448
+ //holiday mode
1449
+ if (this.holidayModeSupport && holidayModeEnabled !== null) {
1450
+ this.holidayModeControlService?.updateCharacteristic(Characteristic.On, holidayModeEnabled);
1451
+ this.holidayModeControlSensorService?.updateCharacteristic(Characteristic.ContactSensorState, holidayModeEnabled);
1452
+ this.holidayModeSensorService?.updateCharacteristic(Characteristic.ContactSensorState, holidayModeActive);
1453
+ }
1454
+
1455
+ //presets
1342
1456
  if (this.presets.length > 0) {
1343
1457
  this.presets.forEach((preset, i) => {
1344
- const presetData = presetsOnServer.find(p => p[presetsIdKey] === preset.id);
1458
+ const presetData = presetsOnServer.find(p => p.ID === preset.id);
1345
1459
 
1346
1460
  preset.state = presetData ? (presetData.Power === power
1347
1461
  && presetData.SetTemperature === setTemperature
@@ -1355,14 +1469,17 @@ class DeviceAta extends EventEmitter {
1355
1469
  });
1356
1470
  };
1357
1471
 
1358
- //update schedules state
1472
+ //schedules
1359
1473
  if (this.schedules.length > 0 && scheduleEnabled !== null) {
1360
1474
  this.schedules.forEach((schedule, i) => {
1361
1475
  //control
1362
- if (i === 0) this.schedulesControlService?.updateCharacteristic(Characteristic.On, scheduleEnabled);
1476
+ if (i === 0) {
1477
+ this.schedulesControlService?.updateCharacteristic(Characteristic.On, scheduleEnabled);
1478
+ this.schedulesControlSensorService?.updateCharacteristic(Characteristic.ContactSensorState, scheduleEnabled);
1479
+ }
1363
1480
 
1364
1481
  //sensors
1365
- const scheduleData = schedulesOnServer.find(s => s[presetsIdKey] === schedule.id);
1482
+ const scheduleData = schedulesOnServer.find(s => s.Id === schedule.id);
1366
1483
  schedule.state = scheduleEnabled ? scheduleData.Enabled ?? false : false;
1367
1484
 
1368
1485
  const characteristicType = schedule.characteristicType;
@@ -1370,7 +1487,7 @@ class DeviceAta extends EventEmitter {
1370
1487
  });
1371
1488
  };
1372
1489
 
1373
- //update buttons state
1490
+ //buttons
1374
1491
  if (this.buttons.length > 0) {
1375
1492
  this.buttons.forEach((button, i) => {
1376
1493
  const mode = button.mode;
package/src/deviceatw.js CHANGED
@@ -37,8 +37,8 @@ class DeviceAtw extends EventEmitter {
37
37
  this.temperatureReturnWaterTankSensor = device.temperatureReturnWaterTankSensor || false;
38
38
  this.temperatureFlowZone2Sensor = device.temperatureFlowZone2Sensor || false;
39
39
  this.temperatureReturnZone2Sensor = device.temperatureReturnZone2Sensor || false;
40
- this.holidayModeSensor = device.holidayModeSensor || false;
41
40
  this.errorSensor = device.errorSensor || false;
41
+ this.holidayModeSupport = device.holidayModeSupport || false;
42
42
  this.presets = this.accountType === 'melcloud' ? (device.presets || []).filter(preset => (preset.displayType ?? 0) > 0 && preset.id !== '0') : [];
43
43
  this.schedules = this.accountType === 'melcloudhome' ? (device.schedules || []).filter(schedule => (schedule.displayType ?? 0) > 0 && schedule.id !== '0') : [];
44
44
  this.buttons = (device.buttonsSensors || []).filter(button => (button.displayType ?? 0) > 0);
@@ -1048,23 +1048,10 @@ class DeviceAtw extends EventEmitter {
1048
1048
  });
1049
1049
  };
1050
1050
 
1051
- //holiday mode sensor
1052
- if (this.holidayModeSensor && this.accessory.holidayModeEnabled !== null) {
1053
- if (this.logDebug) this.emit('debug', `Prepare holiday mode service`);
1054
- this.holidayModeSensorService = new Service.ContactSensor(`${serviceName} Holiday Mode`, `Holiday Mode Sensor ${deviceId}`);
1055
- this.holidayModeSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
1056
- this.holidayModeSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Holiday Mode`);
1057
- this.holidayModeSensorService.getCharacteristic(Characteristic.ContactSensorState)
1058
- .onGet(async () => {
1059
- const state = this.accessory.holidayModeActive;
1060
- return state;
1061
- })
1062
- accessory.addService(this.holidayModeSensorService);
1063
- }
1064
-
1065
1051
  //error sensor
1066
1052
  if (this.errorSensor && this.accessory.isInError !== null) {
1067
1053
  if (this.logDebug) this.emit('debug', `Prepare error service`);
1054
+ const serviceName = `${deviceTypeText} ${accessoryName}`;
1068
1055
  this.errorService = new Service.ContactSensor(`${serviceName} Error`, `Error Sensor ${deviceId}`);
1069
1056
  this.errorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
1070
1057
  this.errorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Error`);
@@ -1076,6 +1063,53 @@ class DeviceAtw extends EventEmitter {
1076
1063
  accessory.addService(this.errorService);
1077
1064
  }
1078
1065
 
1066
+ //holiday mode
1067
+ if (this.holidayModeSupport && this.accessory.holidayModeEnabled !== null) {
1068
+ //control
1069
+ if (this.logDebug) this.emit('debug', `Prepare holiday mode control service`);
1070
+ this.holidayModeControlService = new Service.Switch(`${serviceName} Holiday Mode`, `holidayModeControlService${deviceId}`);
1071
+ this.holidayModeControlService.addOptionalCharacteristic(Characteristic.ConfiguredName);
1072
+ this.holidayModeControlService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Holiday Mode`);
1073
+ this.holidayModeControlService.getCharacteristic(Characteristic.On)
1074
+ .onGet(async () => {
1075
+ const state = this.accessory.holidayModeEnabled;
1076
+ return state;
1077
+ })
1078
+ .onSet(async (state) => {
1079
+ try {
1080
+ deviceData.HolidayMode.Enabled = state;
1081
+ await this.melCloudAta.send(this.accountType, this.displayType, deviceData, 'holidaymode');
1082
+ if (this.logInfo) this.emit('info', `Holiday mode: ${state ? 'Enabled' : 'Disabled'}`);
1083
+ } catch (error) {
1084
+ if (this.logWarn) this.emit('warn', `Set holiday mode error: ${error}`);
1085
+ };
1086
+ });
1087
+ accessory.addService(this.holidayModeControlService);
1088
+
1089
+ if (this.logDebug) this.emit('debug', `Prepare holiday mode control sensor service`);
1090
+ this.holidayModeControlSensorService = new Service.ContactSensor(`${serviceName} Holiday Mode Control`, `holidayModeControlSensorService${deviceId}`);
1091
+ this.holidayModeControlSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
1092
+ this.holidayModeControlSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Holiday Mode Control`);
1093
+ this.holidayModeControlSensorService.getCharacteristic(Characteristic.ContactSensorState)
1094
+ .onGet(async () => {
1095
+ const state = this.accessory.holidayModeEnabled;
1096
+ return state;
1097
+ })
1098
+ accessory.addService(this.holidayModeControlSensorService);
1099
+
1100
+ //sensors
1101
+ if (this.logDebug) this.emit('debug', `Prepare holiday mode sensor service`);
1102
+ this.holidayModeSensorService = new Service.ContactSensor(`${serviceName} Holiday Mode`, `holidayModeSensorService${deviceId}`);
1103
+ this.holidayModeSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
1104
+ this.holidayModeSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Holiday Mode State`);
1105
+ this.holidayModeSensorService.getCharacteristic(Characteristic.ContactSensorState)
1106
+ .onGet(async () => {
1107
+ const state = this.accessory.holidayModeActive;
1108
+ return state;
1109
+ })
1110
+ accessory.addService(this.holidayModeSensorService);
1111
+ }
1112
+
1079
1113
  //presets services
1080
1114
  if (this.presets.length > 0) {
1081
1115
  if (this.logDebug) this.emit('debug', `Prepare presets services`);
@@ -1172,7 +1206,7 @@ class DeviceAtw extends EventEmitter {
1172
1206
  .onSet(async (state) => {
1173
1207
  try {
1174
1208
  deviceData.ScheduleEnabled = state;
1175
- await this.melCloudAta.send(this.accountType, this.displayType, deviceData, 'scheduleenabled');
1209
+ await this.melCloudAta.send(this.accountType, this.displayType, deviceData, 'schedule');
1176
1210
  if (this.logInfo) this.emit('info', `Schedule: ${state ? 'Enabled' : 'Disabled'}`);
1177
1211
  } catch (error) {
1178
1212
  if (this.logWarn) this.emit('warn', `Set schedule error: ${error}`);
@@ -1428,7 +1462,7 @@ class DeviceAtw extends EventEmitter {
1428
1462
  const schedulesOnServer = deviceData.Schedule ?? [];
1429
1463
  const presetsOnServer = deviceData.Presets ?? [];
1430
1464
  const holidayModeEnabled = deviceData.HolidayMode?.Enabled;
1431
- const holidayModeActive = deviceData.HolidayMode?.Active;
1465
+ const holidayModeActive = deviceData.HolidayMode?.Active ?? false;
1432
1466
 
1433
1467
  //device info
1434
1468
  const hasHeatPump = ![1, 2, 3, 4, 5, 6, 7, 15].includes(this.hideZone);
@@ -1911,11 +1945,17 @@ class DeviceAtw extends EventEmitter {
1911
1945
  };
1912
1946
  this.accessory = obj;
1913
1947
 
1914
- //update sensors state
1915
- this.holidayModeSensorService?.updateCharacteristic(Characteristic.ContactSensorState, holidayModeActive);
1948
+ //error sensor
1916
1949
  this.errorService?.updateCharacteristic(Characteristic.ContactSensorState, isInError);
1917
1950
 
1918
- //update presets state
1951
+ //holiday mode
1952
+ if (this.holidayModeSupport && holidayModeEnabled !== null) {
1953
+ this.holidayModeControlService?.updateCharacteristic(Characteristic.On, holidayModeEnabled);
1954
+ this.holidayModeControlSensorService?.updateCharacteristic(Characteristic.ContactSensorState, holidayModeEnabled);
1955
+ this.holidayModeSensorService?.updateCharacteristic(Characteristic.ContactSensorState, holidayModeActive);
1956
+ }
1957
+
1958
+ //presets
1919
1959
  if (this.presets.length > 0) {
1920
1960
  this.presets.forEach((preset, i) => {
1921
1961
  const presetData = presetsOnServer.find(p => p[presetsIdKey] === preset.id);
@@ -1938,7 +1978,7 @@ class DeviceAtw extends EventEmitter {
1938
1978
  });
1939
1979
  };
1940
1980
 
1941
- //update schedules state
1981
+ //schedules
1942
1982
  if (this.schedules.length > 0 && scheduleEnabled !== null) {
1943
1983
  this.schedules.forEach((schedule, i) => {
1944
1984
  //control
@@ -1953,7 +1993,7 @@ class DeviceAtw extends EventEmitter {
1953
1993
  });
1954
1994
  };
1955
1995
 
1956
- //update buttons state
1996
+ //buttons
1957
1997
  if (this.buttons.length > 0) {
1958
1998
  this.buttons.forEach((button, i) => {
1959
1999
  const mode = button.mode;
package/src/deviceerv.js CHANGED
@@ -30,8 +30,8 @@ class DeviceErv extends EventEmitter {
30
30
  this.temperatureSensor = device.temperatureSensor || false;
31
31
  this.temperatureOutdoorSensor = device.temperatureOutdoorSensor || false;
32
32
  this.temperatureSupplySensor = device.temperatureSupplySensor || false;
33
- this.holidayModeSensor = device.holidayModeSensor || false;
34
33
  this.errorSensor = device.errorSensor || false;
34
+ this.holidayModeSupport = device.holidayModeSupport || false;
35
35
  this.presets = this.accountType === 'melcloud' ? (device.presets || []).filter(preset => (preset.displayType ?? 0) > 0 && preset.id !== '0') : [];
36
36
  this.schedules = this.accountType === 'melcloudhome' ? (device.schedules || []).filter(schedule => (schedule.displayType ?? 0) > 0 && schedule.id !== '0') : [];
37
37
  this.buttons = (device.buttonsSensors || []).filter(button => (button.displayType ?? 0) > 0);
@@ -547,7 +547,7 @@ class DeviceErv extends EventEmitter {
547
547
  if (this.logDebug) this.emit('debug', `Prepare room temperature sensor service`);
548
548
  this.roomTemperatureSensorService = new Service.TemperatureSensor(`${serviceName} Room`, `Room Temperature Sensor ${deviceId}`);
549
549
  this.roomTemperatureSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
550
- this.roomTemperatureSensorService.setCharacteristic(Characteristic.ConfiguredName, `${serviceName} Room`);
550
+ this.roomTemperatureSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Room`);
551
551
  this.roomTemperatureSensorService.getCharacteristic(Characteristic.CurrentTemperature)
552
552
  .setProps({
553
553
  minValue: -35,
@@ -566,7 +566,7 @@ class DeviceErv extends EventEmitter {
566
566
  if (this.logDebug) this.emit('debug', `Prepare supply temperature sensor service`);
567
567
  this.supplyTemperatureSensorService = new Service.TemperatureSensor(`${serviceName} Supply`, `Supply Temperature Sensor ${deviceId}`);
568
568
  this.supplyTemperatureSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
569
- this.supplyTemperatureSensorService.setCharacteristic(Characteristic.ConfiguredName, `${serviceName} Supply`);
569
+ this.supplyTemperatureSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Supply`);
570
570
  this.supplyTemperatureSensorService.getCharacteristic(Characteristic.CurrentTemperature)
571
571
  .setProps({
572
572
  minValue: -35,
@@ -585,7 +585,7 @@ class DeviceErv extends EventEmitter {
585
585
  if (this.logDebug) this.emit('debug', `Prepare outdoor temperature sensor service`);
586
586
  this.outdoorTemperatureSensorService = new Service.TemperatureSensor(`${serviceName} Outdoor`, `Outdoor Temperature Sensor ${deviceId}`);
587
587
  this.outdoorTemperatureSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
588
- this.outdoorTemperatureSensorService.setCharacteristic(Characteristic.ConfiguredName, `${serviceName} Outdoor`);
588
+ this.outdoorTemperatureSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Outdoor`);
589
589
  this.outdoorTemperatureSensorService.getCharacteristic(Characteristic.CurrentTemperature)
590
590
  .setProps({
591
591
  minValue: -35,
@@ -603,7 +603,7 @@ class DeviceErv extends EventEmitter {
603
603
  if (this.accessory.coreMaintenanceRequired !== null) {
604
604
  this.coreMaintenanceService = new Service.FilterMaintenance(`${serviceName} Core Maintenance`, `CoreMaintenance ${deviceId}`);
605
605
  this.coreMaintenanceService.addOptionalCharacteristic(Characteristic.ConfiguredName);
606
- this.coreMaintenanceService.setCharacteristic(Characteristic.ConfiguredName, `${serviceName} Core Maintenance`);
606
+ this.coreMaintenanceService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Core Maintenance`);
607
607
  this.coreMaintenanceService.getCharacteristic(Characteristic.FilterChangeIndication)
608
608
  .onGet(async () => {
609
609
  const value = this.accessory.coreMaintenanceRequired;
@@ -619,7 +619,7 @@ class DeviceErv extends EventEmitter {
619
619
  if (this.accessory.filterMaintenanceRequired !== null) {
620
620
  this.filterMaintenanceService = new Service.FilterMaintenance(`${serviceName} Filter Maintenance`, `FilterMaintenance ${deviceId}`);
621
621
  this.filterMaintenanceService.addOptionalCharacteristic(Characteristic.ConfiguredName);
622
- this.filterMaintenanceService.setCharacteristic(Characteristic.ConfiguredName, `${serviceName} Filter Maintenance`);
622
+ this.filterMaintenanceService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Filter Maintenance`);
623
623
  this.filterMaintenanceService.getCharacteristic(Characteristic.FilterChangeIndication)
624
624
  .onGet(async () => {
625
625
  const value = this.accessory.filterMaintenanceRequired;
@@ -635,7 +635,7 @@ class DeviceErv extends EventEmitter {
635
635
  if (hasCO2Sensor) {
636
636
  this.carbonDioxideSensorService = new Service.CarbonDioxideSensor(`${serviceName} CO2 Sensor`, `CO2Sensor ${deviceId}`);
637
637
  this.carbonDioxideSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
638
- this.carbonDioxideSensorService.setCharacteristic(Characteristic.ConfiguredName, `${serviceName} CO2 Sensor`);
638
+ this.carbonDioxideSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} CO2 Sensor`);
639
639
  this.carbonDioxideSensorService.getCharacteristic(Characteristic.CarbonDioxideDetected)
640
640
  .onGet(async () => {
641
641
  const value = this.accessory.roomCO2Detected;
@@ -653,7 +653,7 @@ class DeviceErv extends EventEmitter {
653
653
  if (hasPM25Sensor) {
654
654
  this.airQualitySensorService = new Service.AirQualitySensor(`${serviceName} PM2.5 Sensor`, `PM25Sensor ${deviceId}`);
655
655
  this.airQualitySensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
656
- this.airQualitySensorService.setCharacteristic(Characteristic.ConfiguredName, `${serviceName} PM2.5 Sensor`);
656
+ this.airQualitySensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} PM2.5 Sensor`);
657
657
  this.airQualitySensorService.getCharacteristic(Characteristic.AirQuality)
658
658
  .onGet(async () => {
659
659
  const value = this.accessory.pM25AirQuality;
@@ -667,20 +667,6 @@ class DeviceErv extends EventEmitter {
667
667
  accessory.addService(this.airQualitySensorService);
668
668
  }
669
669
 
670
- //holiday mode sensor
671
- if (this.holidayModeSensor && this.accessory.holidayModeEnabled !== null) {
672
- if (this.logDebug) this.emit('debug', `Prepare holiday mode service`);
673
- this.holidayModeSensorService = new Service.ContactSensor(`${serviceName} Holiday Mode`, `Holiday Mode Sensor ${deviceId}`);
674
- this.holidayModeSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
675
- this.holidayModeSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Holiday Mode`);
676
- this.holidayModeSensorService.getCharacteristic(Characteristic.ContactSensorState)
677
- .onGet(async () => {
678
- const state = this.accessory.holidayModeActive;
679
- return state;
680
- })
681
- accessory.addService(this.holidayModeSensorService);
682
- }
683
-
684
670
  //error sensor
685
671
  if (this.errorSensor && this.accessory.isInError !== null) {
686
672
  if (this.logDebug) this.emit('debug', `Prepare error service`);
@@ -695,6 +681,53 @@ class DeviceErv extends EventEmitter {
695
681
  accessory.addService(this.errorService);
696
682
  }
697
683
 
684
+ //holiday mode
685
+ if (this.holidayModeSupport && this.accessory.holidayModeEnabled !== null) {
686
+ //control
687
+ if (this.logDebug) this.emit('debug', `Prepare holiday mode control service`);
688
+ this.holidayModeControlService = new Service.Switch(`${serviceName} Holiday Mode`, `holidayModeControlService${deviceId}`);
689
+ this.holidayModeControlService.addOptionalCharacteristic(Characteristic.ConfiguredName);
690
+ this.holidayModeControlService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Holiday Mode`);
691
+ this.holidayModeControlService.getCharacteristic(Characteristic.On)
692
+ .onGet(async () => {
693
+ const state = this.accessory.holidayModeEnabled;
694
+ return state;
695
+ })
696
+ .onSet(async (state) => {
697
+ try {
698
+ deviceData.HolidayMode.Enabled = state;
699
+ await this.melCloudAta.send(this.accountType, this.displayType, deviceData, 'holidaymode');
700
+ if (this.logInfo) this.emit('info', `Holiday mode: ${state ? 'Enabled' : 'Disabled'}`);
701
+ } catch (error) {
702
+ if (this.logWarn) this.emit('warn', `Set holiday mode error: ${error}`);
703
+ };
704
+ });
705
+ accessory.addService(this.holidayModeControlService);
706
+
707
+ if (this.logDebug) this.emit('debug', `Prepare holiday mode control sensor service`);
708
+ this.holidayModeControlSensorService = new Service.ContactSensor(`${serviceName} Holiday Mode Control`, `holidayModeControlSensorService${deviceId}`);
709
+ this.holidayModeControlSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
710
+ this.holidayModeControlSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Holiday Mode Control`);
711
+ this.holidayModeControlSensorService.getCharacteristic(Characteristic.ContactSensorState)
712
+ .onGet(async () => {
713
+ const state = this.accessory.holidayModeEnabled;
714
+ return state;
715
+ })
716
+ accessory.addService(this.holidayModeControlSensorService);
717
+
718
+ //sensors
719
+ if (this.logDebug) this.emit('debug', `Prepare holiday mode sensor service`);
720
+ this.holidayModeSensorService = new Service.ContactSensor(`${serviceName} Holiday Mode`, `holidayModeSensorService${deviceId}`);
721
+ this.holidayModeSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
722
+ this.holidayModeSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Holiday Mode State`);
723
+ this.holidayModeSensorService.getCharacteristic(Characteristic.ContactSensorState)
724
+ .onGet(async () => {
725
+ const state = this.accessory.holidayModeActive;
726
+ return state;
727
+ })
728
+ accessory.addService(this.holidayModeSensorService);
729
+ }
730
+
698
731
  //presets services
699
732
  if (this.presets.length > 0) {
700
733
  if (this.logDebug) this.emit('debug', `Prepare presets services`);
@@ -776,7 +809,7 @@ class DeviceErv extends EventEmitter {
776
809
  .onSet(async (state) => {
777
810
  try {
778
811
  deviceData.ScheduleEnabled = state;
779
- await this.melCloudAta.send(this.accountType, this.displayType, deviceData, 'scheduleenabled');
812
+ await this.melCloudAta.send(this.accountType, this.displayType, deviceData, 'schedule');
780
813
  if (this.logInfo) this.emit('info', `Schedule: ${state ? 'Enabled' : 'Disabled'}`);
781
814
  } catch (error) {
782
815
  if (this.logWarn) this.emit('warn', `Set schedule error: ${error}`);
@@ -974,7 +1007,7 @@ class DeviceErv extends EventEmitter {
974
1007
  const schedulesOnServer = deviceData.Schedule ?? [];
975
1008
  const presetsOnServer = deviceData.Presets ?? [];
976
1009
  const holidayModeEnabled = deviceData.HolidayMode?.Enabled;
977
- const holidayModeActive = deviceData.HolidayMode?.Active;
1010
+ const holidayModeActive = deviceData.HolidayMode?.Active ?? false;
978
1011
 
979
1012
  //device control
980
1013
  const hideRoomTemperature = deviceData.HideRoomTemperature;
@@ -1206,10 +1239,16 @@ class DeviceErv extends EventEmitter {
1206
1239
  .updateCharacteristic(Characteristic.PM2_5Density, pM25Level);
1207
1240
 
1208
1241
  //error sensor
1209
- this.holidayModeSensorService?.updateCharacteristic(Characteristic.ContactSensorState, holidayModeActive);
1210
1242
  this.errorService?.updateCharacteristic(Characteristic.ContactSensorState, isInError);
1211
1243
 
1212
- //update presets state
1244
+ //holiday mode
1245
+ if (this.holidayModeSupport && holidayModeEnabled !== null) {
1246
+ this.holidayModeControlService?.updateCharacteristic(Characteristic.On, holidayModeEnabled);
1247
+ this.holidayModeControlSensorService?.updateCharacteristic(Characteristic.ContactSensorState, holidayModeEnabled);
1248
+ this.holidayModeSensorService?.updateCharacteristic(Characteristic.ContactSensorState, holidayModeActive);
1249
+ }
1250
+
1251
+ //presets
1213
1252
  if (this.presets.length > 0) {
1214
1253
  this.presets.forEach((preset, i) => {
1215
1254
  const presetData = presetsOnServer.find(p => p[presetsIdKey] === preset.id);
@@ -1225,7 +1264,7 @@ class DeviceErv extends EventEmitter {
1225
1264
  });
1226
1265
  };
1227
1266
 
1228
- //update schedules state
1267
+ //schedules
1229
1268
  if (this.schedules.length > 0 && scheduleEnabled !== null) {
1230
1269
  this.schedules.forEach((schedule, i) => {
1231
1270
  //control
@@ -1240,7 +1279,7 @@ class DeviceErv extends EventEmitter {
1240
1279
  });
1241
1280
  };
1242
1281
 
1243
- //update buttons state
1282
+ //buttons
1244
1283
  if (this.buttons.length > 0) {
1245
1284
  this.buttons.forEach((button, i) => {
1246
1285
  const mode = button.mode;;
package/src/melcloud.js CHANGED
@@ -168,7 +168,7 @@ class MelCloud extends EventEmitter {
168
168
  const loginData = account.LoginData ?? [];
169
169
  const contextKey = loginData.ContextKey;
170
170
 
171
- const debugData = {
171
+ const safeConfig = {
172
172
  ...loginData,
173
173
  ContextKey: 'removed',
174
174
  ClientId: 'removed',
@@ -177,7 +177,7 @@ class MelCloud extends EventEmitter {
177
177
  MapLongitude: 'removed',
178
178
  MapLatitude: 'removed'
179
179
  };
180
- if (this.logDebug) this.emit('debug', `MELCloud Info: ${JSON.stringify(debugData, null, 2)}`);
180
+ if (this.logDebug) this.emit('debug', `MELCloud Info: ${JSON.stringify(safeConfig, null, 2)}`);
181
181
 
182
182
  if (!contextKey) {
183
183
  accountInfo.Info = 'Context key missing'
@@ -183,14 +183,6 @@ class MelCloudAta extends EventEmitter {
183
183
  this.updateData(deviceData);
184
184
  return true;
185
185
  case "melcloudhome":
186
- const axiosInstancePut = axios.create({
187
- method: 'PUT',
188
- baseURL: ApiUrlsHome.BaseURL,
189
- timeout: 10000,
190
- headers: deviceData.Headers,
191
- withCredentials: true
192
- });
193
-
194
186
  if (displayType === 1 && deviceData.Device.OperationMode === 8) {
195
187
  deviceData.Device.SetTemperature = (deviceData.Device.DefaultCoolingSetTemperature + deviceData.Device.DefaultHeatingSetTemperature) / 2;
196
188
 
@@ -203,15 +195,53 @@ class MelCloudAta extends EventEmitter {
203
195
  }
204
196
  }
205
197
 
198
+ let method = null
206
199
  let settings = {};
207
200
  let path = '';
208
201
  switch (effectiveFlags) {
209
- case 'scheduleenabled':
202
+ case 'frostprotection':
203
+ settings = {
204
+ data: {
205
+ enabled: deviceData.FrostProtection.Enabled,
206
+ min: deviceData.FrostProtection.Min,
207
+ max: deviceData.FrostProtection.Max,
208
+ units: { "ATA": [deviceData.DeviceID] }
209
+ }
210
+ };
211
+ method = 'POST';
212
+ path = ApiUrlsHome.PostProtectionFrost;
213
+ break;
214
+ case 'overheatprotection':
215
+ settings = {
216
+ data: {
217
+ enabled: deviceData.OverheatProtection.Enabled,
218
+ min: deviceData.OverheatProtection.Min,
219
+ max: deviceData.OverheatProtection.Max,
220
+ units: { "ATA": [deviceData.DeviceID] }
221
+ }
222
+ };
223
+ method = 'POST';
224
+ path = ApiUrlsHome.PostProtectionOverheat;
225
+ break;
226
+ case 'holidaymode':
227
+ settings = {
228
+ data: {
229
+ enabled: deviceData.HolidayMode.Enabled,
230
+ startDate: deviceData.HolidayMode.StartDate,
231
+ endDate: deviceData.HolidayMode.EndDate,
232
+ units: { "ATA": [deviceData.DeviceID] }
233
+ }
234
+ };
235
+ method = 'POST';
236
+ path = ApiUrlsHome.PostHolidayMode;
237
+ break;
238
+ case 'schedule':
210
239
  settings = {
211
240
  data: {
212
241
  enabled: deviceData.ScheduleEnabled
213
242
  }
214
243
  };
244
+ method = 'PUT';
215
245
  path = ApiUrlsHome.PutScheduleEnable.replace('deviceid', deviceData.DeviceID);
216
246
  break;
217
247
  default:
@@ -225,10 +255,19 @@ class MelCloudAta extends EventEmitter {
225
255
  VaneVerticalDirection: AirConditioner.VaneVerticalDirectionMapEnumToString[deviceData.Device.VaneVerticalDirection],
226
256
  }
227
257
  };
258
+ method = 'PUT';
228
259
  path = ApiUrlsHome.SetAta.replace('deviceid', deviceData.DeviceID);
229
260
  break
230
261
  }
231
262
 
263
+ const axiosInstancePut = axios.create({
264
+ method: method,
265
+ baseURL: ApiUrlsHome.BaseURL,
266
+ timeout: 10000,
267
+ headers: deviceData.Headers,
268
+ withCredentials: true
269
+ });
270
+
232
271
  if (this.logDebug) this.emit('debug', `Send Data: ${JSON.stringify(settings.data, null, 2)}`);
233
272
  await axiosInstancePut(path, settings);
234
273
  this.updateData(deviceData);
@@ -187,23 +187,24 @@ class MelCloudAtw extends EventEmitter {
187
187
  this.updateData(deviceData);
188
188
  return true;
189
189
  case "melcloudhome":
190
- const axiosInstancePut = axios.create({
191
- method: 'PUT',
192
- baseURL: ApiUrlsHome.BaseURL,
193
- timeout: 10000,
194
- headers: deviceData.Headers,
195
- withCredentials: true
196
- });
197
-
190
+ let method = null
198
191
  let settings = {};
199
192
  let path = '';
200
193
  switch (effectiveFlags) {
201
- case 'scheduleenabled':
194
+ case 'holidaymode':
195
+ settings = {
196
+ data: { enabled: deviceData.HolidayMode.Enabled, startDate: deviceData.HolidayMode.StartDate, endDate: deviceData.HolidayMode.EndDate, units: { "ATW": [deviceData.DeviceID] } }
197
+ };
198
+ method = 'POST';
199
+ path = ApiUrlsHome.PostHolidayMode;
200
+ break;
201
+ case 'schedule':
202
202
  settings = {
203
203
  data: {
204
204
  enabled: deviceData.ScheduleEnabled
205
205
  }
206
206
  };
207
+ method = 'PUT';
207
208
  path = ApiUrlsHome.PutScheduleEnable.replace('deviceid', deviceData.DeviceID);
208
209
  break;
209
210
  default:
@@ -224,10 +225,19 @@ class MelCloudAtw extends EventEmitter {
224
225
  EcoHotWater: deviceData.Device.EcoHotWater,
225
226
  }
226
227
  };
228
+ method = 'PUT';
227
229
  path = ApiUrlsHome.SetAtw.replace('deviceid', deviceData.DeviceID);
228
230
  break
229
231
  }
230
232
 
233
+ const axiosInstancePut = axios.create({
234
+ method: method,
235
+ baseURL: ApiUrlsHome.BaseURL,
236
+ timeout: 10000,
237
+ headers: deviceData.Headers,
238
+ withCredentials: true
239
+ });
240
+
231
241
  if (this.logDebug) this.emit('debug', `Send Data: ${JSON.stringify(settings.data, null, 2)}`);
232
242
  await axiosInstancePut(path, settings);
233
243
  this.updateData(deviceData);
@@ -191,14 +191,6 @@ class MelCloudErv extends EventEmitter {
191
191
  this.updateData(deviceData);
192
192
  return true;
193
193
  case "melcloudhome":
194
- const axiosInstancePut = axios.create({
195
- method: 'PUT',
196
- baseURL: ApiUrlsHome.BaseURL,
197
- timeout: 10000,
198
- headers: deviceData.Headers,
199
- withCredentials: true
200
- });
201
-
202
194
  if (displayType === 1 && deviceData.Device.VentilationMode === 2) {
203
195
  deviceData.Device.SetTemperature = (deviceData.Device.DefaultCoolingSetTemperature + deviceData.Device.DefaultHeatingSetTemperature) / 2;
204
196
 
@@ -211,15 +203,24 @@ class MelCloudErv extends EventEmitter {
211
203
  }
212
204
  }
213
205
 
206
+ let method = null;
214
207
  let settings = {};
215
208
  let path = '';
216
209
  switch (effectiveFlags) {
217
- case 'scheduleenabled':
210
+ case 'holidaymode':
211
+ settings = {
212
+ data: { enabled: deviceData.HolidayMode.Enabled, startDate: deviceData.HolidayMode.StartDate, endDate: deviceData.HolidayMode.EndDate, units: { "ERV": [deviceData.DeviceID] } }
213
+ };
214
+ method = 'POST';
215
+ path = ApiUrlsHome.PostHolidayMode;
216
+ break;
217
+ case 'schedule':
218
218
  settings = {
219
219
  data: {
220
220
  enabled: deviceData.ScheduleEnabled
221
221
  }
222
222
  };
223
+ method = 'PUT';
223
224
  path = ApiUrlsHome.PutScheduleEnable.replace('deviceid', deviceData.DeviceID);
224
225
  break;
225
226
  default:
@@ -232,10 +233,19 @@ class MelCloudErv extends EventEmitter {
232
233
  VentilationMode: Ventilation.VentilationModeMapEnumToString[deviceData.Device.VentilationMode],
233
234
  }
234
235
  };
236
+ method = 'PUT';
235
237
  path = ApiUrlsHome.SetErv.replace('deviceid', deviceData.DeviceID);
236
238
  break
237
239
  }
238
240
 
241
+ const axiosInstancePut = axios.create({
242
+ method: method,
243
+ baseURL: ApiUrlsHome.BaseURL,
244
+ timeout: 10000,
245
+ headers: deviceData.Headers,
246
+ withCredentials: true
247
+ });
248
+
239
249
  if (this.logDebug) this.emit('debug', `Send Data: ${JSON.stringify(settings.data, null, 2)}`);
240
250
  await axiosInstancePut(path, settings);
241
251
  this.updateData(deviceData);