homebridge-melcloud-control 4.2.3-beta.61 → 4.2.3-beta.63

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,17 @@ 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.3] - (15.11.2025)
26
+
27
+ ## Changes
28
+
29
+ - added scenes support for MELCloud Home
30
+ - fix some issues
31
+ - stability and performance improvements
32
+ - config schema updated
33
+ - readme updated
34
+ - cleanup
35
+
25
36
  ## [4.2.2] - (14.11.2025)
26
37
 
27
38
  ## Changes
package/README.md CHANGED
@@ -71,6 +71,7 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
71
71
  * Overheat protection `ON/OFF`.
72
72
  * Holiday mode `ON/OFF`.
73
73
  * Schedule `ON/OFF`.
74
+ * Scene `ON/OFF`.
74
75
  * Sensors:
75
76
  * For automation and notifications.
76
77
  * Power `ON/OFF`.
@@ -88,8 +89,9 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
88
89
  * Overheat protection.
89
90
  * Holiday mode.
90
91
  * Shedule control.
91
- * Shedule active
92
- * Error
92
+ * Shedule active.
93
+ * Scene control.
94
+ * Error.
93
95
  * Heat Pump:
94
96
  * Heater Cooler:
95
97
  * Heat Pump:
@@ -128,6 +130,7 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
128
130
  * Presets `SET/UNSET`.
129
131
  * Holiday mode `ON/OFF`.
130
132
  * Schedule `ON/OFF`.
133
+ * Scene `ON/OFF`.
131
134
  * Sensors:
132
135
  * For automation and notifications.
133
136
  * Power `ON/OFF`.
@@ -142,8 +145,9 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
142
145
  * Return Temperature Zone 1, 2, Hot Water.
143
146
  * Holiday mode.
144
147
  * Shedule control.
145
- * Shedule active
146
- * Error
148
+ * Shedule active.
149
+ * Scene control.
150
+ * Error.
147
151
  * Energy Recovery Ventilation Lossnay:
148
152
  * Heater Cooler:
149
153
  * Power `ON/OFF`.
@@ -162,6 +166,7 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
162
166
  * Presets `SET/UNSET`.
163
167
  * Holiday mode `ON/OFF`.
164
168
  * Schedule `ON/OFF`.
169
+ * Scene `ON/OFF`.
165
170
  * Sensors:
166
171
  * For automation and notifications.
167
172
  * Power `ON/OFF`.
@@ -177,8 +182,9 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
177
182
  * PM2.5 air quality and level.
178
183
  * Holiday mode.
179
184
  * Shedule control.
180
- * Shedule active
181
- * Error
185
+ * Shedule active.
186
+ * Scene control.
187
+ * Error.
182
188
 
183
189
  ### HOME app current device mode display
184
190
 
@@ -238,7 +244,7 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
238
244
  | `ataDevices[].id` | Read only data, do not change it. |
239
245
  | `ataDevices[].type` | Read only data, do not change it. |
240
246
  | `ataDevices[].typeString` | Read only data, do not change it. |
241
- | `ataDevices[].name` | Here You can schange the `Accessory Name` which is exposed to the `Homebridge/HomeKit`. |
247
+ | `ataDevices[].name` | Here You can change the `Accessory Name` which is exposed to the `Homebridge/HomeKit`. |
242
248
  | `ataDevices[].displayType` | Here select device control mode `None/Disabled`, `Heater/Cooler`, `Thermostat`. |
243
249
  | `ataDevices[].heatDryFanMode` | Here select the operatiing mode for `Heat`, if this mode is not supported, it will be disabled. |
244
250
  | `ataDevices[].coolDryFanMode` | Here select the operatiing mode for `Cool`, if this mode is not supported, it will be disabled. |
@@ -254,12 +260,15 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
254
260
  | `ataDevices[].refreshInterval` | Here set the background devices state refresh time in (sec), default `5s`. |
255
261
  | `ataDevices[].presets[]` | Array of ATA device `Presets` created automatically after login to MELCloud from plugin config UI. |
256
262
  | `ataDevices[].presets[].id` | Read only data, do not change it. |
257
- | `ataDevices[].presets[].name` | Here You can schange the `Preset Name` which is exposed to the `Homebridge/HomeKit`. |
258
- | `ataDevices[].presets[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Outlet`, `2 - Switch`, `3 - Motion Sensor`, `4 - Occupancy Sensor`, `5 - Contact Sensor`. |
263
+ | `ataDevices[].presets[].name` | Here You can change the `Preset Name` which is exposed to the `Homebridge/HomeKit`. |
264
+ | `ataDevices[].presets[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Motion Sensor`, `2 - Occupancy Sensor`, `3 - Contact Sensor`, `4 - Switch + Motion Sensor`, `5 - Switch +Occupancy Sensor`, `6 - Switch +Contact Sensor`. |
259
265
  | `ataDevices[].schedules[]` | Array of ATA device `Schedules` created automatically after login to MELCloud Home from plugin config UI. |
260
266
  | `ataDevices[].schedules[].id` | Read only data, do not change it. |
261
- | `ataDevices[].schedules[].name` | Here You can schange the `Schedule Name` which is exposed to the `Homebridge/HomeKit`. |
262
- | `ataDevices[].schedules[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Motion Sensor`, `2 - Occupancy Sensor`, `3 - Contact Sensor`. |
267
+ | `ataDevices[].schedules[].name` | Here You can change the `Schedule Name` which is exposed to the `Homebridge/HomeKit`. |
268
+ | `ataDevices[].schedules[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Motion Sensor`, `2 - Occupancy Sensor`, `3 - Contact Sensor`, `4 - Switch + Motion Sensor`, `5 - Switch +Occupancy Sensor`, `6 - Switch +Contact Sensor`. |
269
+ | `ataDevices[].scenes[].id` | Read only data, do not change it. |
270
+ | `ataDevices[].scenes[].name` | Here You can change the `Scene Name` which is exposed to the `Homebridge/HomeKit`. |
271
+ | `ataDevices[].scenes[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Motion Sensor`, `2 - Occupancy Sensor`, `3 - Contact Sensor`, `4 - Switch + Motion Sensor`, `5 - Switch +Occupancy Sensor`, `6 - Switch +Contact Sensor`. |
263
272
  | `ataDevices[].buttonsSensors[]` | Array of buttons sensors. |
264
273
  | `ataDevices[].buttonsSensors[].name` | Here set `Button Name` which You want expose to the `Homebridge/HomeKit`. |
265
274
  | `ataDevices[].buttonsSensors[].mode` | Here select button mode, VH - Vane Horizontal, VV - Vane Horizontal. |
@@ -269,7 +278,7 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
269
278
  | `atwDevices[].id` | Read only data, do not change it. |
270
279
  | `atwDevices[].type` | Read only data, do not change it. |
271
280
  | `atwDevices[].typeString` | Read only data, do not change it. |
272
- | `atwDevices[].name` | Here You can schange the `Accessory Name` which is exposed to the `Homebridge/HomeKit`. |
281
+ | `atwDevices[].name` | Here You can change the `Accessory Name` which is exposed to the `Homebridge/HomeKit`. |
273
282
  | `atwDevices[].displayType` | Here select main control mode `None/Disabled`, `Heater/Cooler`, `Thermostat`. |
274
283
  | `atwDevices[].hideZone` | Here select which zone need to be hidden `None/Disabled`, `Heat Pump`, `Heat Pump / Zone 1`, `Heat Pump / Zone 1 / Hot Water`, `Heat Pump / Zone 1 / Zone 2`, `Heat Pump / Hot Water`,`Heat Pump / Hot Water / Zone 2`, `Heat Pump / Zone 2`, `Zone 1`, `Zone 1 / Hot Water`, `Zone 1 / Hot Water / Zone 2`, `Zone 1 / Zone 2`, `Hot Water`, `Hot Water / Zone 2`, `Zone 2`, `All`. |
275
284
  | `atwDevices[].temperatureSensor` | This enable extra `Room` temperature sensor to use with automations in HomeKit app. |
@@ -288,12 +297,15 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
288
297
  | `atwDevices[].refreshInterval` | Here set the background devices state refresh time in (sec), default `5s`. |
289
298
  | `atwDevices[].presets[]` | Array of ATW device `Presets` created automatically after login to MELCloud from plugin config UI. |
290
299
  | `atwDevices[].presets[].id` | Read only data, do not change it. |
291
- | `atwDevices[].presets[].name` | Here You can schange the `Preset Name` which is exposed to the `Homebridge/HomeKit`. |
292
- | `atwDevices[].presets[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Outlet`, `2 - Switch`, `3 - Motion Sensor`, `4 - Occupancy Sensor`, `5 - Contact Sensor`. |
300
+ | `atwDevices[].presets[].name` | Here You can change the `Preset Name` which is exposed to the `Homebridge/HomeKit`. |
301
+ | `atwDevices[].presets[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Motion Sensor`, `2 - Occupancy Sensor`, `3 - Contact Sensor`, `4 - Switch + Motion Sensor`, `5 - Switch +Occupancy Sensor`, `6 - Switch +Contact Sensor`. |
293
302
  | `atwDevices[].schedules[]` | Array of ATW device `Schedules` created automatically after login to MELCloud Home from plugin config UI. |
294
303
  | `atwDevices[].schedules[].id` | Read only data, do not change it. |
295
- | `atwDevices[].schedules[].name` | Here You can schange the `Schedule Name` which is exposed to the `Homebridge/HomeKit`. |
296
- | `atwDevices[].schedules[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Motion Sensor`, `2 - Occupancy Sensor`, `3 - Contact Sensor`. |
304
+ | `atwDevices[].schedules[].name` | Here You can change the `Schedule Name` which is exposed to the `Homebridge/HomeKit`. |
305
+ | `atwDevices[].schedules[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Motion Sensor`, `2 - Occupancy Sensor`, `3 - Contact Sensor`, `4 - Switch + Motion Sensor`, `5 - Switch +Occupancy Sensor`, `6 - Switch +Contact Sensor`. |
306
+ | `atwDevices[].scenes[].id` | Read only data, do not change it. |
307
+ | `atwDevices[].scenes[].name` | Here You can change the `Scene Name` which is exposed to the `Homebridge/HomeKit`. |
308
+ | `atwDevices[].scenes[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Motion Sensor`, `2 - Occupancy Sensor`, `3 - Contact Sensor`, `4 - Switch + Motion Sensor`, `5 - Switch +Occupancy Sensor`, `6 - Switch +Contact Sensor`. |
297
309
  | `atwDevices[].buttonsSensors[]` | Array of buttons sensors. |
298
310
  | `atwDevices[].buttonsSensors[].name` | Here set `Button Name` which You want expose to the `Homebridge/HomeKit`. |
299
311
  | `atwDevices[].buttonsSensors[].mode` | Here select button mode. |
@@ -303,7 +315,7 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
303
315
  | `ervDevices[].id` | Read only data, do not change it. |
304
316
  | `ervDevices[].type` | Read only data, do not change it. |
305
317
  | `ervDevices[].typeString` | Read only data, do not change it. |
306
- | `ervDevices[].name` | Here You can schange the `Accessory Name` which is exposed to the `Homebridge/HomeKit`. |
318
+ | `ervDevices[].name` | Here You can change the `Accessory Name` which is exposed to the `Homebridge/HomeKit`. |
307
319
  | `ervDevices[].displayType` | Here select main control mode `None/Disabled`, `Heater/Cooler`, `Thermostat`. |
308
320
  | `ervDevices[].temperatureSensor` | This enable extra `Room` temperature sensor to use with automations in HomeKit app. |
309
321
  | `ervDevices[].temperatureOutdoorSensor` | This enable extra `Outdoor` temperature sensor to use with automations in HomeKit app. |
@@ -315,12 +327,15 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
315
327
  | `ervDevices[].refreshInterval` | Here set the background devices state refresh time in (sec), default `5s`. |
316
328
  | `ervDevices[].presets[]` | Array of ERV device `Presets` created automatically after login to MELCloud from plugin config UI. |
317
329
  | `ervDevices[].presets[].id` | Read only data, do not change it. |
318
- | `ervDevices[].presets[].name` | Here You can schange the `Preset Name` which is exposed to the `Homebridge/HomeKit`. |
319
- | `ervDevices[].presets[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Outlet`, `2 - Switch`, `3 - Motion Sensor`, `4 - Occupancy Sensor`, `5 - Contact Sensor`. |
330
+ | `ervDevices[].presets[].name` | Here You can change the `Preset Name` which is exposed to the `Homebridge/HomeKit`. |
331
+ | `ervDevices[].presets[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Motion Sensor`, `2 - Occupancy Sensor`, `3 - Contact Sensor`, `4 - Switch + Motion Sensor`, `5 - Switch +Occupancy Sensor`, `6 - Switch +Contact Sensor`. |
320
332
  | `ervDevices[].schedules[]` | Array of ERV device `Schedules` created automatically after login to MELCloud Home from plugin config UI. |
321
333
  | `ervDevices[].schedules[].id` | Read only data, do not change it. |
322
- | `ervDevices[].schedules[].name` | Here You can schange the `Schedule Name` which is exposed to the `Homebridge/HomeKit`. |
323
- | `ervDevices[].schedules[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Motion Sensor`, `2 - Occupancy Sensor`, `3 - Contact Sensor`. |
334
+ | `ervDevices[].schedules[].name` | Here You can change the `Schedule Name` which is exposed to the `Homebridge/HomeKit`. |
335
+ | `ervDevices[].schedules[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Motion Sensor`, `2 - Occupancy Sensor`, `3 - Contact Sensor`, `4 - Switch + Motion Sensor`, `5 - Switch +Occupancy Sensor`, `6 - Switch +Contact Sensor`. |
336
+ | `ervDevices[].scenes[].id` | Read only data, do not change it. |
337
+ | `ervDevices[].scenes[].name` | Here You can change the `Scene Name` which is exposed to the `Homebridge/HomeKit`. |
338
+ | `ervDevices[].scenes[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Motion Sensor`, `2 - Occupancy Sensor`, `3 - Contact Sensor`, `4 - Switch + Motion Sensor`, `5 - Switch +Occupancy Sensor`, `6 - Switch +Contact Sensor`. |
324
339
  | `ervDevices[].buttonsSensors[]` | Array of buttons sensors. |
325
340
  | `ervDevices[].buttonsSensors[].name` | Here set `Button Name` which You want expose to the `Homebridge/HomeKit`. |
326
341
  | `ervDevices[].buttonsSensors[].mode` | Here select button mode. |
@@ -414,13 +414,13 @@
414
414
  const newScenesCount = newDevices.scenes.length;
415
415
  const removedDevicesCount = removedAta.length + removedAtw.length + removedErv.length;
416
416
 
417
- if (!newDevicesCount && !newPresetsCount && !removedDevicesCount) {
417
+ if (!newDevicesCount && !newPresetsCount && !newSchedulesCount && !newScenesCount && !removedDevicesCount) {
418
418
  updateInfo('info', 'No changes detected.', 'white');
419
419
  } else {
420
420
  if (newDevicesCount)
421
421
  updateInfo('info', `Found new devices: ATA: ${newDevices.ata.length}, ATW: ${newDevices.atw.length}, ERV: ${newDevices.erv.length}.`, 'green');
422
422
  if (newPresetsCount || newScenesCount || newSchedulesCount)
423
- updateInfo('info1', `Found new ${account.type === 'melcloud' ? 'presets' : 'schedules'}: ATA: ${newDevices.ataPresets.length}, ATW: ${newDevices.atwPresets.length}, ERV: ${newDevices.ervPresets.length}, Scenes: ${newDevices.scenes.length}.`, 'green');
423
+ updateInfo('info1', `Found new ${account.type === 'melcloud' ? 'presets' : 'schedules'}: ATA: ${account.type === 'melcloud' ? newDevices.ataPresets.length : newDevices.ataSchedules.length}, ATW: ${account.type === 'melcloud' ? newDevices.atwPresets.length : newDevices.atwSchedules.length}, ERV: ${account.type === 'melcloud' ? newDevices.ervPresets.length : newDevices.ervSchedules.length}, Scenes: ${newDevices.scenes.length}.`, 'green');
424
424
  if (removedDevicesCount)
425
425
  updateInfo('info2', `Removed devices: ATA: ${removedAta.length}, ATW: ${removedAtw.length}, ERV: ${removedErv.length}.`, 'orange');
426
426
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "MELCloud Control",
3
3
  "name": "homebridge-melcloud-control",
4
- "version": "4.2.3-beta.61",
4
+ "version": "4.2.3-beta.63",
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
@@ -56,6 +56,7 @@ class DeviceAta extends EventEmitter {
56
56
  this.restFulConnected = false;
57
57
  this.mqtt = account.mqtt ?? {};
58
58
  this.mqttConnected = false;
59
+
59
60
  const serviceType = [null, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor];
60
61
  const characteristicType = [null, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState];
61
62
 
package/src/deviceatw.js CHANGED
@@ -58,23 +58,34 @@ class DeviceAtw extends EventEmitter {
58
58
  this.mqtt = account.mqtt ?? {};
59
59
  this.mqttConnected = false;
60
60
 
61
+ const serviceType = [null, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor];
62
+ const characteristicType = [null, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState];
63
+
61
64
  //presets configured
62
65
  for (const preset of this.presets) {
63
- preset.name = preset.name || 'Preset'
64
- preset.serviceType = [null, Service.Outlet, Service.Switch, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][preset.displayType];
65
- preset.characteristicType = [null, Characteristic.On, Characteristic.On, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][preset.displayType];
66
+ preset.name = preset.name;
67
+ preset.serviceType = serviceType[preset.displayType];
68
+ preset.characteristicType = characteristicType[preset.displayType];
66
69
  preset.state = false;
67
70
  preset.previousSettings = {};
68
71
  }
69
72
 
70
73
  //schedules configured
71
74
  for (const schedule of this.schedules) {
72
- schedule.name = schedule.name || 'Schedule'
73
- schedule.serviceType = [null, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][schedule.displayType];
74
- schedule.characteristicType = [null, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][schedule.displayType];
75
+ schedule.name = schedule.name;
76
+ schedule.serviceType = serviceType[schedule.displayType];
77
+ schedule.characteristicType = characteristicType[schedule.displayType];
75
78
  schedule.state = false;
76
79
  }
77
80
 
81
+ //scenes configured
82
+ for (const scene of this.scenes) {
83
+ scene.name = scene.name;
84
+ scene.serviceType = serviceType[scene.displayType];
85
+ scene.characteristicType = characteristicType[scene.displayType];
86
+ scene.state = false;
87
+ }
88
+
78
89
  //buttons configured
79
90
  for (const button of this.buttons) {
80
91
  button.name = button.name || 'Button'
@@ -294,6 +305,7 @@ class DeviceAtw extends EventEmitter {
294
305
  const accountName = this.accountName;
295
306
  const presetsOnServer = this.accessory.presets;
296
307
  const schedulesOnServer = this.accessory.schedules;
308
+ const scenesOnServer = this.accessory.scenes;
297
309
  const zonesCount = this.accessory.zonesCount;
298
310
  const caseHeatPump = this.accessory.caseHeatPump;
299
311
  const caseZone1 = this.accessory.caseZone1;
@@ -1110,7 +1122,6 @@ class DeviceAtw extends EventEmitter {
1110
1122
  accessory.addService(this.errorService);
1111
1123
  }
1112
1124
 
1113
-
1114
1125
  //holiday mode
1115
1126
  if (this.holidayModeSupport && this.accessory.holidayModeEnabled !== null) {
1116
1127
  //control
@@ -1161,7 +1172,8 @@ class DeviceAtw extends EventEmitter {
1161
1172
  //presets services
1162
1173
  if (this.presets.length > 0) {
1163
1174
  if (this.logDebug) this.emit('debug', `Prepare presets services`);
1164
- this.presetsServices = [];
1175
+ this.presetControlServices = [];
1176
+ this.presetControlSensorServices = [];
1165
1177
  this.presets.forEach((preset, i) => {
1166
1178
  const presetData = presetsOnServer.find(p => p.ID === preset.id);
1167
1179
 
@@ -1171,66 +1183,71 @@ class DeviceAtw extends EventEmitter {
1171
1183
  //get preset name prefix
1172
1184
  const namePrefix = preset.namePrefix;
1173
1185
 
1174
- const serviceName = namePrefix ? `${accessoryName} ${name}` : name;
1186
+ const serviceName1 = namePrefix ? `${accessoryName} ${name}` : name;
1175
1187
  const serviceType = preset.serviceType;
1176
1188
  const characteristicType = preset.characteristicType;
1177
- const presetService = new serviceType(serviceName, `Preset ${deviceId} ${i}`);
1178
- presetService.addOptionalCharacteristic(Characteristic.ConfiguredName);
1179
- presetService.setCharacteristic(Characteristic.ConfiguredName, serviceName);
1180
- presetService.getCharacteristic(characteristicType)
1189
+
1190
+ if (preset.displayType > 3) {
1191
+ if (this.logDebug) this.emit('debug', `Prepare preset control ${name} service`);
1192
+ const presetControlService = new Service.Switch(serviceName1, `presetControlService${deviceId} ${i}`);
1193
+ presetControlService.addOptionalCharacteristic(Characteristic.ConfiguredName);
1194
+ presetControlService.setCharacteristic(Characteristic.ConfiguredName, serviceName1);
1195
+ presetControlService.getCharacteristic(Characteristic.On)
1196
+ .onGet(async () => {
1197
+ const state = preset.state;
1198
+ return state;
1199
+ })
1200
+ .onSet(async (state) => {
1201
+ try {
1202
+ switch (state) {
1203
+ case true:
1204
+ preset.previousSettings = deviceData.Device;
1205
+ deviceData.Device.Power = presetData.Power;
1206
+ deviceData.Device.OperationMode = presetData.OperationMode;
1207
+ deviceData.Device.SetTemperature = presetData.SetTemperature;
1208
+ deviceData.Device.VaneHorizontalDirection = presetData.VaneHorizontalDirection;
1209
+ deviceData.Device.VaneVerticalDirection = presetData.VaneVerticalDirection;
1210
+ deviceData.Device.SetFanSpeed = presetData.SetFanSpeed;
1211
+ break;
1212
+ case false:
1213
+ deviceData.Device.Power = preset.previousSettings.Power;
1214
+ deviceData.Device.OperationMode = preset.previousSettings.OperationMode;
1215
+ deviceData.Device.SetTemperature = preset.previousSettings.SetTemperature;
1216
+ deviceData.Device.VaneHorizontalDirection = preset.previousSettings.VaneHorizontalDirection;
1217
+ deviceData.Device.VaneVerticalDirection = preset.previousSettings.VaneVerticalDirection;
1218
+ deviceData.Device.SetFanSpeed = preset.previousSettings.SetFanSpeed;
1219
+ break;
1220
+ };
1221
+
1222
+ await this.melCloudAta.send(this.accountType, this.displayType, deviceData, AirConditioner.EffectiveFlags.Presets);
1223
+ if (this.logInfo) this.emit('info', `Preset ${name}: ${state ? 'Set:' : 'Unset:'} ${name}`);
1224
+ } catch (error) {
1225
+ if (this.logWarn) this.emit('warn', `Set preset error: ${error}`);
1226
+ };
1227
+ });
1228
+ this.presetControlServices.push(presetControlService);
1229
+ accessory.addService(presetControlService);
1230
+ }
1231
+
1232
+ //sensor
1233
+ if (this.logDebug) this.emit('debug', `Prepare preset control sensor s${name} ervice`);
1234
+ const presetControlSensorService = new serviceType(serviceName1, `presetControlSensorService${deviceId} ${i}`);
1235
+ presetControlSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
1236
+ presetControlSensorService.setCharacteristic(Characteristic.ConfiguredName, `${serviceName1} Control`);
1237
+ presetControlSensorService.getCharacteristic(characteristicType)
1181
1238
  .onGet(async () => {
1182
- const state = preset.state;
1239
+ const state = this.accessory.scheduleEnabled;
1183
1240
  return state;
1184
1241
  })
1185
- .onSet(async (state) => {
1186
- try {
1187
- switch (state) {
1188
- case true:
1189
- preset.previousSettings = deviceData.Device;
1190
- deviceData.Device.Power = presetData.Power;
1191
- deviceData.Device.EcoHotWater = presetData.EcoHotWater;
1192
- deviceData.Device.OperationModeZone1 = presetData.OperationModeZone1;
1193
- deviceData.Device.OperationModeZone2 = presetData.OperationModeZone2;
1194
- deviceData.Device.SetTankWaterTemperature = presetData.SetTankWaterTemperature;
1195
- deviceData.Device.SetTemperatureZone1 = presetData.SetTemperatureZone1;
1196
- deviceData.Device.SetTemperatureZone2 = presetData.SetTemperatureZone2;
1197
- deviceData.Device.ForcedHotWaterMode = presetData.ForcedHotWaterMode;
1198
- deviceData.Device.SetHeatFlowTemperatureZone1 = presetData.SetHeatFlowTemperatureZone1;
1199
- deviceData.Device.SetHeatFlowTemperatureZone2 = presetData.SetHeatFlowTemperatureZone2;
1200
- deviceData.Device.SetCoolFlowTemperatureZone1 = presetData.SetCoolFlowTemperatureZone1;
1201
- deviceData.Device.SetCoolFlowTemperatureZone2 = presetData.SetCoolFlowTemperatureZone2;
1202
- break;
1203
- case false:
1204
- deviceData.Device.Power = preset.previousSettings.Power;
1205
- deviceData.Device.EcoHotWater = preset.previousSettings.EcoHotWater;
1206
- deviceData.Device.OperationModeZone1 = preset.previousSettings.OperationModeZone1;
1207
- deviceData.Device.OperationModeZone2 = preset.previousSettings.OperationModeZone2;
1208
- deviceData.Device.SetTankWaterTemperature = preset.previousSettings.SetTankWaterTemperature;
1209
- deviceData.Device.SetTemperatureZone1 = preset.previousSettings.SetTemperatureZone1;
1210
- deviceData.Device.SetTemperatureZone2 = preset.previousSettings.SetTemperatureZone2;
1211
- deviceData.Device.ForcedHotWaterMode = preset.previousSettings.ForcedHotWaterMode;
1212
- deviceData.Device.SetHeatFlowTemperatureZone1 = preset.previousSettings.SetHeatFlowTemperatureZone1;
1213
- deviceData.Device.SetHeatFlowTemperatureZone2 = preset.previousSettings.SetHeatFlowTemperatureZone2;
1214
- deviceData.Device.SetCoolFlowTemperatureZone1 = preset.previousSettings.SetCoolFlowTemperatureZone1;
1215
- deviceData.Device.SetCoolFlowTemperatureZone2 = preset.previousSettings.SetCoolFlowTemperatureZone2;
1216
- break;
1217
- };
1218
-
1219
- await this.melCloudAtw.send(this.accountType, this.displayType, deviceData, HeatPump.EffectiveFlags.Power);
1220
- if (this.logInfo) this.emit('info', `${state ? 'Set:' : 'Unset:'} ${name}`);
1221
- } catch (error) {
1222
- if (this.logWarn) this.emit('warn', `Set preset error: ${error}`);
1223
- };
1224
- });
1225
- this.presetsServices.push(presetService);
1226
- accessory.addService(presetService);
1242
+ this.presetControlSensorServices.push(presetControlSensorService);
1243
+ accessory.addService(presetControlSensorService);
1227
1244
  });
1228
1245
  };
1229
1246
 
1230
1247
  //schedules services
1231
1248
  if (this.schedules.length > 0 && this.accessory.scheduleEnabled !== null) {
1232
1249
  if (this.logDebug) this.emit('debug', `Prepare schedules services`);
1233
- this.schedulesServices = [];
1250
+ this.scheduleSensorServices = [];
1234
1251
  this.schedules.forEach((schedule, i) => {
1235
1252
  //get preset name
1236
1253
  const name = schedule.name;
@@ -1238,54 +1255,117 @@ class DeviceAtw extends EventEmitter {
1238
1255
  //get preset name prefix
1239
1256
  const namePrefix = schedule.namePrefix;
1240
1257
 
1258
+ //control sensor
1259
+ const serviceName1 = namePrefix ? `${accessoryName} ${name}` : name;
1260
+ const serviceName2 = namePrefix ? `${accessoryName} Schedules` : 'Schedules';
1261
+ const serviceType = schedule.serviceType;
1262
+ const characteristicType = schedule.characteristicType;
1263
+
1241
1264
  //control
1242
1265
  if (i === 0) {
1243
- if (this.logDebug) this.emit('debug', `Prepare schedule control service`);
1244
- this.schedulesControlService = new Service.Switch(`${serviceName} Schedule`, `schedulesControlService${deviceId} ${i}`);
1245
- this.schedulesControlService.addOptionalCharacteristic(Characteristic.ConfiguredName);
1246
- this.schedulesControlService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Schedules`);
1247
- this.schedulesControlService.getCharacteristic(Characteristic.On)
1266
+ if (schedule.displayType > 3) {
1267
+ if (this.logDebug) this.emit('debug', `Prepare schedule control ${name} service`);
1268
+ this.scheduleControlService = new Service.Switch(serviceName2, `scheduleControlService${deviceId} ${i}`);
1269
+ this.scheduleControlService.addOptionalCharacteristic(Characteristic.ConfiguredName);
1270
+ this.scheduleControlService.setCharacteristic(Characteristic.ConfiguredName, serviceName2);
1271
+ this.scheduleControlService.getCharacteristic(Characteristic.On)
1272
+ .onGet(async () => {
1273
+ const state = this.accessory.scheduleEnabled;
1274
+ return state;
1275
+ })
1276
+ .onSet(async (state) => {
1277
+ try {
1278
+ deviceData.ScheduleEnabled = state;
1279
+ await this.melCloudAta.send(this.accountType, this.displayType, deviceData, 'schedule');
1280
+ if (this.logInfo) this.emit('info', `Schedule ${name}: ${state ? 'Enabled' : 'Disabled'}`);
1281
+ } catch (error) {
1282
+ if (this.logWarn) this.emit('warn', `Set schedule error: ${error}`);
1283
+ };
1284
+ });
1285
+ accessory.addService(this.scheduleControlService);
1286
+ }
1287
+
1288
+ //sensor
1289
+ if (this.logDebug) this.emit('debug', `Prepare schedule control sensor ${name} service`);
1290
+ this.scheduleControlSensorService = new serviceType(`${serviceName2} Control`, `scheduleControlSensorService${deviceId} ${i}`);
1291
+ this.scheduleControlSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
1292
+ this.scheduleControlSensorService.setCharacteristic(Characteristic.ConfiguredName, `${serviceName2} Control`);
1293
+ this.scheduleControlSensorService.getCharacteristic(characteristicType)
1248
1294
  .onGet(async () => {
1249
1295
  const state = this.accessory.scheduleEnabled;
1250
1296
  return state;
1251
1297
  })
1298
+ accessory.addService(this.scheduleControlSensorService);
1299
+ }
1300
+
1301
+ //sensors
1302
+ if (this.logDebug) this.emit('debug', `Prepare schedule sensor ${name} service`);
1303
+ const scheduleSensorService = new serviceType(serviceName1, `scheduleSensorService${deviceId} ${i}`);
1304
+ scheduleSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
1305
+ scheduleSensorService.setCharacteristic(Characteristic.ConfiguredName, serviceName1);
1306
+ scheduleSensorService.getCharacteristic(characteristicType)
1307
+ .onGet(async () => {
1308
+ const state = schedule.state;
1309
+ return state;
1310
+ });
1311
+ this.scheduleSensorServices.push(scheduleSensorService);
1312
+ accessory.addService(scheduleSensorService);
1313
+ });
1314
+ };
1315
+
1316
+ //scenes
1317
+ if (this.scenes.length > 0) {
1318
+ if (this.logDebug) this.emit('debug', `Prepare scenes services`);
1319
+ this.sceneControlServices = [];
1320
+ this.sceneControlSensorServices = [];
1321
+ this.scenes.forEach((scene, i) => {
1322
+ const sceneData = scenesOnServer.find(s => s.Id === scene.id);
1323
+
1324
+ //get preset name
1325
+ const name = scene.name;
1326
+
1327
+ //get preset name prefix
1328
+ const namePrefix = scene.namePrefix;
1329
+
1330
+ const serviceName1 = namePrefix ? `${accessoryName} ${name}` : name;
1331
+ const serviceType = scene.serviceType;
1332
+ const characteristicType = scene.characteristicType;
1333
+
1334
+ //control
1335
+ if (scene.displayType > 3) {
1336
+ if (this.logDebug) this.emit('debug', `Prepare scene control ${name} service`);
1337
+ const sceneControlService = new Service.Switch(serviceName1, `sceneControlService${deviceId} ${i}`);
1338
+ sceneControlService.addOptionalCharacteristic(Characteristic.ConfiguredName);
1339
+ sceneControlService.setCharacteristic(Characteristic.ConfiguredName, serviceName1);
1340
+ sceneControlService.getCharacteristic(Characteristic.On)
1341
+ .onGet(async () => {
1342
+ const state = scene.state;
1343
+ return state;
1344
+ })
1252
1345
  .onSet(async (state) => {
1253
1346
  try {
1254
- deviceData.ScheduleEnabled = state;
1255
- await this.melCloudAta.send(this.accountType, this.displayType, deviceData, 'schedule');
1256
- if (this.logInfo) this.emit('info', `Schedule: ${state ? 'Enabled' : 'Disabled'}`);
1347
+ sceneData.Enabled = state;
1348
+ await this.melCloudAta.send(this.accountType, this.displayType, deviceData, 'scene', sceneData);
1349
+ if (this.logInfo) this.emit('info', `Scene ${name}: ${state ? 'Enabled' : 'Disabled'}`);
1257
1350
  } catch (error) {
1258
- if (this.logWarn) this.emit('warn', `Set schedule error: ${error}`);
1351
+ if (this.logWarn) this.emit('warn', `Set scene error: ${error}`);
1259
1352
  };
1260
1353
  });
1261
- accessory.addService(this.schedulesControlService);
1262
-
1263
- if (this.logDebug) this.emit('debug', `Prepare schedule control sensor service`);
1264
- this.schedulesControlSensorService = new Service.ContactSensor(`${serviceName} Schedule Control`, `schedulesControlSensorService${deviceId}`);
1265
- this.schedulesControlSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
1266
- this.schedulesControlSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Schedule Control`);
1267
- this.schedulesControlSensorService.getCharacteristic(Characteristic.ContactSensorState)
1268
- .onGet(async () => {
1269
- const state = this.accessory.scheduleEnabled;
1270
- return state;
1271
- })
1272
- accessory.addService(this.schedulesControlSensorService);
1354
+ this.sceneControlServices.push(sceneControlService);
1355
+ accessory.addService(sceneControlService);
1273
1356
  }
1274
1357
 
1275
- //sensors
1276
- const serviceName1 = namePrefix ? `${accessoryName} ${name}` : name;
1277
- const serviceType = schedule.serviceType;
1278
- const characteristicType = schedule.characteristicType;
1279
- const scheduleService = new serviceType(serviceName, `scheduleService${deviceId} ${i}`);
1280
- scheduleService.addOptionalCharacteristic(Characteristic.ConfiguredName);
1281
- scheduleService.setCharacteristic(Characteristic.ConfiguredName, serviceName1);
1282
- scheduleService.getCharacteristic(characteristicType)
1358
+ if (this.logDebug) this.emit('debug', `Prepare scene control sensor ${name} service`);
1359
+ const sceneControlSensorService = new serviceType(`${serviceName1} Control`, `sceneControlSensorService${deviceId} ${i}`);
1360
+ sceneControlSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
1361
+ sceneControlSensorService.setCharacteristic(Characteristic.ConfiguredName, `${serviceName1} Control`);
1362
+ sceneControlSensorService.getCharacteristic(characteristicType)
1283
1363
  .onGet(async () => {
1284
- const state = schedule.state;
1364
+ const state = scene.state;
1285
1365
  return state;
1286
- });
1287
- this.schedulesServices.push(scheduleService);
1288
- accessory.addService(scheduleService);
1366
+ })
1367
+ this.sceneControlSensorServices.push(sceneControlSensorService);
1368
+ accessory.addService(sceneControlSensorService);
1289
1369
  });
1290
1370
  };
1291
1371
 
@@ -1477,7 +1557,7 @@ class DeviceAtw extends EventEmitter {
1477
1557
  try {
1478
1558
  //melcloud device
1479
1559
  this.melCloudAtw = new MelCloudAtw(this.account, this.device, this.devicesFile, this.defaultTempsFile)
1480
- .on('deviceInfo', ( modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion, supportsHotWaterTank, supportsZone2) => {
1560
+ .on('deviceInfo', (modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion, supportsHotWaterTank, supportsZone2) => {
1481
1561
  if (this.logDeviceInfo && this.displayDeviceInfo) {
1482
1562
  this.emit('devInfo', `---- ${this.deviceTypeText}: ${this.deviceName} ----`);
1483
1563
  this.emit('devInfo', `Account: ${this.accountName}`);
@@ -1513,9 +1593,10 @@ class DeviceAtw extends EventEmitter {
1513
1593
  const supportStandbyKey = accountTypeMelcloud ? 'ModelSupportsStandbyMode' : 'HasStandby';
1514
1594
 
1515
1595
  //presets schedule
1596
+ const presetsOnServer = deviceData.Presets ?? [];
1516
1597
  const scheduleEnabled = deviceData.ScheduleEnabled;
1517
1598
  const schedulesOnServer = deviceData.Schedule ?? [];
1518
- const presetsOnServer = deviceData.Presets ?? [];
1599
+ const scenesOnServer = deviceData.Scenes ?? [];
1519
1600
  const holidayMode = deviceData.Device.HolidayMode;
1520
1601
  const holidayModeEnabled = accountTypeMelcloud ? holidayMode : deviceData.HolidayMode?.Enabled;
1521
1602
  const holidayModeActive = deviceData.HolidayMode?.Active ?? false;
@@ -1600,6 +1681,7 @@ class DeviceAtw extends EventEmitter {
1600
1681
  const obj = {
1601
1682
  presets: presetsOnServer,
1602
1683
  schedules: schedulesOnServer,
1684
+ scenes: scenesOnServer,
1603
1685
  power: power,
1604
1686
  inStandbyMode: inStandbyMode,
1605
1687
  unitStatus: unitStatus,
@@ -2022,6 +2104,7 @@ class DeviceAtw extends EventEmitter {
2022
2104
  if (this.presets.length > 0) {
2023
2105
  this.presets.forEach((preset, i) => {
2024
2106
  const presetData = presetsOnServer.find(p => p.ID === preset.id);
2107
+ const characteristicType = preset.characteristicType;
2025
2108
 
2026
2109
  preset.state = presetData ? (presetData.Power === power
2027
2110
  && presetData.EcoHotWater === ecoHotWater
@@ -2036,23 +2119,50 @@ class DeviceAtw extends EventEmitter {
2036
2119
  && presetData.SetCoolFlowTemperatureZone1 === setCoolFlowTemperatureZone1
2037
2120
  && presetData.SetCoolFlowTemperatureZone2 === setCoolFlowTemperatureZone2) : false;
2038
2121
 
2039
- const characteristicType = preset.characteristicType;
2040
- this.presetsServices?.[i]?.updateCharacteristic(characteristicType, preset.state);
2122
+ //control
2123
+ if (preset.displayType > 3) {
2124
+ this.presetControlServices?.[i]?.updateCharacteristic(Characteristic.On, preset.state);
2125
+ }
2126
+
2127
+ //sencor
2128
+ this.presetControlSensorServices?.[i]?.updateCharacteristic(characteristicType, preset.state);
2041
2129
  });
2042
2130
  };
2043
2131
 
2044
2132
  //schedules
2045
2133
  if (this.schedules.length > 0 && scheduleEnabled !== null) {
2046
2134
  this.schedules.forEach((schedule, i) => {
2047
- //control
2048
- if (i === 0) this.schedulesControlService?.updateCharacteristic(Characteristic.On, scheduleEnabled);
2049
-
2050
- //sensors
2051
2135
  const scheduleData = schedulesOnServer.find(s => s.Id === schedule.id);
2136
+ const characteristicType = schedule.characteristicType;
2052
2137
  schedule.state = scheduleEnabled ? scheduleData.Enabled ?? false : false;
2053
2138
 
2054
- const characteristicType = schedule.characteristicType;
2055
- this.schedulesServices?.[i]?.updateCharacteristic(characteristicType, schedule.state);
2139
+ //control
2140
+ if (i === 0) {
2141
+ if (schedule.displayType > 3) {
2142
+ this.scheduleControlService?.updateCharacteristic(Characteristic.On, scheduleEnabled);
2143
+ }
2144
+ this.scheduleControlSensorService?.updateCharacteristic(characteristicType, scheduleEnabled);
2145
+ }
2146
+
2147
+ //sensor
2148
+ this.scheduleSensorServices?.[i]?.updateCharacteristic(characteristicType, schedule.state);
2149
+ });
2150
+ };
2151
+
2152
+ //schedules
2153
+ if (this.scenes.length > 0) {
2154
+ this.scenes.forEach((scene, i) => {
2155
+ const sceneData = scenesOnServer.find(s => s.Id === scene.id);
2156
+ scene.state = sceneData.Enabled;
2157
+
2158
+ //control
2159
+ if (scene.displayType > 3) {
2160
+ this.sceneControlServices?.[i]?.updateCharacteristic(Characteristic.On, scene.state);
2161
+ }
2162
+
2163
+ //sensor
2164
+ const characteristicType = scene.characteristicType;
2165
+ this.sceneControlSensorServices?.[i]?.updateCharacteristic(characteristicType, scene.state);
2056
2166
  });
2057
2167
  };
2058
2168
 
package/src/deviceerv.js CHANGED
@@ -51,23 +51,34 @@ class DeviceErv extends EventEmitter {
51
51
  this.mqtt = account.mqtt ?? {};
52
52
  this.mqttConnected = false;
53
53
 
54
+ const serviceType = [null, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor];
55
+ const characteristicType = [null, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState];
56
+
54
57
  //presets configured
55
58
  for (const preset of this.presets) {
56
- preset.name = preset.name || 'Preset'
57
- preset.serviceType = [null, Service.Outlet, Service.Switch, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][preset.displayType];
58
- preset.characteristicType = [null, Characteristic.On, Characteristic.On, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][preset.displayType];
59
+ preset.name = preset.name;
60
+ preset.serviceType = serviceType[preset.displayType];
61
+ preset.characteristicType = characteristicType[preset.displayType];
59
62
  preset.state = false;
60
63
  preset.previousSettings = {};
61
64
  }
62
65
 
63
66
  //schedules configured
64
67
  for (const schedule of this.schedules) {
65
- schedule.name = schedule.name || 'Schedule'
66
- schedule.serviceType = [null, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][schedule.displayType];
67
- schedule.characteristicType = [null, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][schedule.displayType];
68
+ schedule.name = schedule.name;
69
+ schedule.serviceType = serviceType[schedule.displayType];
70
+ schedule.characteristicType = characteristicType[schedule.displayType];
68
71
  schedule.state = false;
69
72
  }
70
73
 
74
+ //scenes configured
75
+ for (const scene of this.scenes) {
76
+ scene.name = scene.name;
77
+ scene.serviceType = serviceType[scene.displayType];
78
+ scene.characteristicType = characteristicType[scene.displayType];
79
+ scene.state = false;
80
+ }
81
+
71
82
  //buttons configured
72
83
  for (const button of this.buttons) {
73
84
  button.name = button.name || 'Button'
@@ -264,6 +275,7 @@ class DeviceErv extends EventEmitter {
264
275
  const accountName = this.accountName;
265
276
  const presetsOnServer = this.accessory.presets;
266
277
  const schedulesOnServer = this.accessory.schedules;
278
+ const scenesOnServer = this.accessory.scenes;
267
279
  const supportsRoomTemperature = this.accessory.supportsRoomTemperature;
268
280
  const supportsSupplyTemperature = this.accessory.supportsSupplyTemperature;
269
281
  const supportsOutdoorTemperature = this.accessory.supportsOutdoorTemperature;
@@ -782,7 +794,8 @@ class DeviceErv extends EventEmitter {
782
794
  //presets services
783
795
  if (this.presets.length > 0) {
784
796
  if (this.logDebug) this.emit('debug', `Prepare presets services`);
785
- this.presetsServices = [];
797
+ this.presetControlServices = [];
798
+ this.presetControlSensorServices = [];
786
799
  this.presets.forEach((preset, i) => {
787
800
  const presetData = presetsOnServer.find(p => p.ID === preset.id);
788
801
 
@@ -795,49 +808,68 @@ class DeviceErv extends EventEmitter {
795
808
  const serviceName1 = namePrefix ? `${accessoryName} ${name}` : name;
796
809
  const serviceType = preset.serviceType;
797
810
  const characteristicType = preset.characteristicType;
798
- const presetService = new serviceType(serviceName1, `Preset ${deviceId} ${i}`);
799
- presetService.addOptionalCharacteristic(Characteristic.ConfiguredName);
800
- presetService.setCharacteristic(Characteristic.ConfiguredName, serviceName1);
801
- presetService.getCharacteristic(characteristicType)
811
+
812
+ if (preset.displayType > 3) {
813
+ if (this.logDebug) this.emit('debug', `Prepare preset control ${name} service`);
814
+ const presetControlService = new Service.Switch(serviceName1, `presetControlService${deviceId} ${i}`);
815
+ presetControlService.addOptionalCharacteristic(Characteristic.ConfiguredName);
816
+ presetControlService.setCharacteristic(Characteristic.ConfiguredName, serviceName1);
817
+ presetControlService.getCharacteristic(Characteristic.On)
818
+ .onGet(async () => {
819
+ const state = preset.state;
820
+ return state;
821
+ })
822
+ .onSet(async (state) => {
823
+ try {
824
+ switch (state) {
825
+ case true:
826
+ preset.previousSettings = deviceData.Device;
827
+ deviceData.Device.Power = presetData.Power;
828
+ deviceData.Device.OperationMode = presetData.OperationMode;
829
+ deviceData.Device.SetTemperature = presetData.SetTemperature;
830
+ deviceData.Device.VaneHorizontalDirection = presetData.VaneHorizontalDirection;
831
+ deviceData.Device.VaneVerticalDirection = presetData.VaneVerticalDirection;
832
+ deviceData.Device.SetFanSpeed = presetData.SetFanSpeed;
833
+ break;
834
+ case false:
835
+ deviceData.Device.Power = preset.previousSettings.Power;
836
+ deviceData.Device.OperationMode = preset.previousSettings.OperationMode;
837
+ deviceData.Device.SetTemperature = preset.previousSettings.SetTemperature;
838
+ deviceData.Device.VaneHorizontalDirection = preset.previousSettings.VaneHorizontalDirection;
839
+ deviceData.Device.VaneVerticalDirection = preset.previousSettings.VaneVerticalDirection;
840
+ deviceData.Device.SetFanSpeed = preset.previousSettings.SetFanSpeed;
841
+ break;
842
+ };
843
+
844
+ await this.melCloudAta.send(this.accountType, this.displayType, deviceData, AirConditioner.EffectiveFlags.Presets);
845
+ if (this.logInfo) this.emit('info', `Preset ${name}: ${state ? 'Set:' : 'Unset:'} ${name}`);
846
+ } catch (error) {
847
+ if (this.logWarn) this.emit('warn', `Set preset error: ${error}`);
848
+ };
849
+ });
850
+ this.presetControlServices.push(presetControlService);
851
+ accessory.addService(presetControlService);
852
+ }
853
+
854
+ //sensor
855
+ if (this.logDebug) this.emit('debug', `Prepare preset control sensor s${name} ervice`);
856
+ const presetControlSensorService = new serviceType(serviceName1, `presetControlSensorService${deviceId} ${i}`);
857
+ presetControlSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
858
+ presetControlSensorService.setCharacteristic(Characteristic.ConfiguredName, `${serviceName1} Control`);
859
+ presetControlSensorService.getCharacteristic(characteristicType)
802
860
  .onGet(async () => {
803
- const state = preset.state;
861
+ const state = this.accessory.scheduleEnabled;
804
862
  return state;
805
863
  })
806
- .onSet(async (state) => {
807
- try {
808
- switch (state) {
809
- case true:
810
- preset.previousSettings = deviceData.Device;
811
- deviceData.Device.SetTemperature = presetData.SetTemperature;
812
- deviceData.Device.Power = presetData.Power;
813
- deviceData.Device.OperationMode = presetData.OperationMode;
814
- deviceData.Device.VentilationMode = presetData.VentilationMode;
815
- deviceData.Device.SetFanSpeed = presetData.SetFanSpeed;
816
- break;
817
- case false:
818
- deviceData.Device.SetTemperature = preset.previousSettings.SetTemperature;
819
- deviceData.Device.Power = preset.previousSettings.Power;
820
- deviceData.Device.OperationMode = preset.previousSettings.OperationMode;
821
- deviceData.Device.VentilationMode = preset.previousSettings.VentilationMode;
822
- deviceData.Device.SetFanSpeed = preset.previousSettings.SetFanSpeed;
823
- break;
824
- };
825
-
826
- await this.melCloudErv.send(this.accountType, this.displayType, deviceData, Ventilation.EffectiveFlags.Power);
827
- if (this.logInfo) this.emit('info', `${state ? 'Set:' : 'Unset:'} ${name}`);
828
- } catch (error) {
829
- if (this.logWarn) this.emit('warn', `Set preset error: ${error}`);
830
- };
831
- });
864
+ this.presetControlSensorServices.push(presetControlSensorService);
865
+ accessory.addService(presetControlSensorService);
832
866
  });
833
- this.presetsServices.push(presetService);
834
- accessory.addService(presetService);
835
867
  };
836
868
 
837
869
  //schedules services
838
870
  if (this.schedules.length > 0 && this.accessory.scheduleEnabled !== null) {
839
871
  if (this.logDebug) this.emit('debug', `Prepare schedules services`);
840
- this.schedulesServices = [];
872
+ this.scheduleSensorServices = [];
841
873
  this.schedules.forEach((schedule, i) => {
842
874
  //get preset name
843
875
  const name = schedule.name;
@@ -845,54 +877,117 @@ class DeviceErv extends EventEmitter {
845
877
  //get preset name prefix
846
878
  const namePrefix = schedule.namePrefix;
847
879
 
880
+ //control sensor
881
+ const serviceName1 = namePrefix ? `${accessoryName} ${name}` : name;
882
+ const serviceName2 = namePrefix ? `${accessoryName} Schedules` : 'Schedules';
883
+ const serviceType = schedule.serviceType;
884
+ const characteristicType = schedule.characteristicType;
885
+
848
886
  //control
849
887
  if (i === 0) {
850
- if (this.logDebug) this.emit('debug', `Prepare schedule control service`);
851
- this.schedulesControlService = new Service.Switch(`${serviceName} Schedule`, `schedulesControlService${deviceId} ${i}`);
852
- this.schedulesControlService.addOptionalCharacteristic(Characteristic.ConfiguredName);
853
- this.schedulesControlService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Schedules`);
854
- this.schedulesControlService.getCharacteristic(Characteristic.On)
888
+ if (schedule.displayType > 3) {
889
+ if (this.logDebug) this.emit('debug', `Prepare schedule control ${name} service`);
890
+ this.scheduleControlService = new Service.Switch(serviceName2, `scheduleControlService${deviceId} ${i}`);
891
+ this.scheduleControlService.addOptionalCharacteristic(Characteristic.ConfiguredName);
892
+ this.scheduleControlService.setCharacteristic(Characteristic.ConfiguredName, serviceName2);
893
+ this.scheduleControlService.getCharacteristic(Characteristic.On)
894
+ .onGet(async () => {
895
+ const state = this.accessory.scheduleEnabled;
896
+ return state;
897
+ })
898
+ .onSet(async (state) => {
899
+ try {
900
+ deviceData.ScheduleEnabled = state;
901
+ await this.melCloudAta.send(this.accountType, this.displayType, deviceData, 'schedule');
902
+ if (this.logInfo) this.emit('info', `Schedule ${name}: ${state ? 'Enabled' : 'Disabled'}`);
903
+ } catch (error) {
904
+ if (this.logWarn) this.emit('warn', `Set schedule error: ${error}`);
905
+ };
906
+ });
907
+ accessory.addService(this.scheduleControlService);
908
+ }
909
+
910
+ //sensor
911
+ if (this.logDebug) this.emit('debug', `Prepare schedule control sensor ${name} service`);
912
+ this.scheduleControlSensorService = new serviceType(`${serviceName2} Control`, `scheduleControlSensorService${deviceId} ${i}`);
913
+ this.scheduleControlSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
914
+ this.scheduleControlSensorService.setCharacteristic(Characteristic.ConfiguredName, `${serviceName2} Control`);
915
+ this.scheduleControlSensorService.getCharacteristic(characteristicType)
855
916
  .onGet(async () => {
856
917
  const state = this.accessory.scheduleEnabled;
857
918
  return state;
858
919
  })
920
+ accessory.addService(this.scheduleControlSensorService);
921
+ }
922
+
923
+ //sensors
924
+ if (this.logDebug) this.emit('debug', `Prepare schedule sensor ${name} service`);
925
+ const scheduleSensorService = new serviceType(serviceName1, `scheduleSensorService${deviceId} ${i}`);
926
+ scheduleSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
927
+ scheduleSensorService.setCharacteristic(Characteristic.ConfiguredName, serviceName1);
928
+ scheduleSensorService.getCharacteristic(characteristicType)
929
+ .onGet(async () => {
930
+ const state = schedule.state;
931
+ return state;
932
+ });
933
+ this.scheduleSensorServices.push(scheduleSensorService);
934
+ accessory.addService(scheduleSensorService);
935
+ });
936
+ };
937
+
938
+ //scenes
939
+ if (this.scenes.length > 0) {
940
+ if (this.logDebug) this.emit('debug', `Prepare scenes services`);
941
+ this.sceneControlServices = [];
942
+ this.sceneControlSensorServices = [];
943
+ this.scenes.forEach((scene, i) => {
944
+ const sceneData = scenesOnServer.find(s => s.Id === scene.id);
945
+
946
+ //get preset name
947
+ const name = scene.name;
948
+
949
+ //get preset name prefix
950
+ const namePrefix = scene.namePrefix;
951
+
952
+ const serviceName1 = namePrefix ? `${accessoryName} ${name}` : name;
953
+ const serviceType = scene.serviceType;
954
+ const characteristicType = scene.characteristicType;
955
+
956
+ //control
957
+ if (scene.displayType > 3) {
958
+ if (this.logDebug) this.emit('debug', `Prepare scene control ${name} service`);
959
+ const sceneControlService = new Service.Switch(serviceName1, `sceneControlService${deviceId} ${i}`);
960
+ sceneControlService.addOptionalCharacteristic(Characteristic.ConfiguredName);
961
+ sceneControlService.setCharacteristic(Characteristic.ConfiguredName, serviceName1);
962
+ sceneControlService.getCharacteristic(Characteristic.On)
963
+ .onGet(async () => {
964
+ const state = scene.state;
965
+ return state;
966
+ })
859
967
  .onSet(async (state) => {
860
968
  try {
861
- deviceData.ScheduleEnabled = state;
862
- await this.melCloudAta.send(this.accountType, this.displayType, deviceData, 'schedule');
863
- if (this.logInfo) this.emit('info', `Schedule: ${state ? 'Enabled' : 'Disabled'}`);
969
+ sceneData.Enabled = state;
970
+ await this.melCloudAta.send(this.accountType, this.displayType, deviceData, 'scene', sceneData);
971
+ if (this.logInfo) this.emit('info', `Scene ${name}: ${state ? 'Enabled' : 'Disabled'}`);
864
972
  } catch (error) {
865
- if (this.logWarn) this.emit('warn', `Set schedule error: ${error}`);
973
+ if (this.logWarn) this.emit('warn', `Set scene error: ${error}`);
866
974
  };
867
975
  });
868
- accessory.addService(this.schedulesControlService);
869
-
870
- if (this.logDebug) this.emit('debug', `Prepare schedule control sensor service`);
871
- this.schedulesControlSensorService = new Service.ContactSensor(`${serviceName} Schedule Control`, `schedulesControlSensorService${deviceId}`);
872
- this.schedulesControlSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
873
- this.schedulesControlSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Schedule Control`);
874
- this.schedulesControlSensorService.getCharacteristic(Characteristic.ContactSensorState)
875
- .onGet(async () => {
876
- const state = this.accessory.scheduleEnabled;
877
- return state;
878
- })
879
- accessory.addService(this.schedulesControlSensorService);
976
+ this.sceneControlServices.push(sceneControlService);
977
+ accessory.addService(sceneControlService);
880
978
  }
881
979
 
882
- //sensors
883
- const serviceName1 = namePrefix ? `${accessoryName} ${name}` : name;
884
- const serviceType = schedule.serviceType;
885
- const characteristicType = schedule.characteristicType;
886
- const scheduleService = new serviceType(serviceName1, `scheduleService${deviceId} ${i}`);
887
- scheduleService.addOptionalCharacteristic(Characteristic.ConfiguredName);
888
- scheduleService.setCharacteristic(Characteristic.ConfiguredName, serviceName1);
889
- scheduleService.getCharacteristic(characteristicType)
980
+ if (this.logDebug) this.emit('debug', `Prepare scene control sensor ${name} service`);
981
+ const sceneControlSensorService = new serviceType(`${serviceName1} Control`, `sceneControlSensorService${deviceId} ${i}`);
982
+ sceneControlSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
983
+ sceneControlSensorService.setCharacteristic(Characteristic.ConfiguredName, `${serviceName1} Control`);
984
+ sceneControlSensorService.getCharacteristic(characteristicType)
890
985
  .onGet(async () => {
891
- const state = schedule.state;
986
+ const state = scene.state;
892
987
  return state;
893
- });
894
- this.schedulesServices.push(scheduleService);
895
- accessory.addService(scheduleService);
988
+ })
989
+ this.sceneControlSensorServices.push(sceneControlSensorService);
990
+ accessory.addService(sceneControlSensorService);
896
991
  });
897
992
  };
898
993
 
@@ -1054,9 +1149,10 @@ class DeviceErv extends EventEmitter {
1054
1149
  const supportStandbyKey = accountTypeMelcloud ? 'ModelSupportsStandbyMode' : 'HasStandby';
1055
1150
 
1056
1151
  //presets schedule
1152
+ const presetsOnServer = deviceData.Presets ?? [];
1057
1153
  const scheduleEnabled = deviceData.ScheduleEnabled;
1058
1154
  const schedulesOnServer = deviceData.Schedule ?? [];
1059
- const presetsOnServer = deviceData.Presets ?? [];
1155
+ const scenesOnServer = deviceData.Scenes ?? [];
1060
1156
  const holidayModeEnabled = deviceData.HolidayMode?.Enabled;
1061
1157
  const holidayModeActive = deviceData.HolidayMode?.Active ?? false;
1062
1158
 
@@ -1114,6 +1210,7 @@ class DeviceErv extends EventEmitter {
1114
1210
  const obj = {
1115
1211
  presets: presetsOnServer,
1116
1212
  schedules: schedulesOnServer,
1213
+ scenes: scenesOnServer,
1117
1214
  supportsRoomTemperature: supportsRoomTemperature,
1118
1215
  supportsSupplyTemperature: supportsSupplyTemperature,
1119
1216
  supportsOutdoorTemperature: supportsOutdoorTemperature,
@@ -1314,6 +1411,7 @@ class DeviceErv extends EventEmitter {
1314
1411
  if (this.presets.length > 0) {
1315
1412
  this.presets.forEach((preset, i) => {
1316
1413
  const presetData = presetsOnServer.find(p => p.ID === preset.id);
1414
+ const characteristicType = preset.characteristicType;
1317
1415
 
1318
1416
  preset.state = presetData ? (presetData.Power === power
1319
1417
  && presetData.SetTemperature === setTemperature
@@ -1321,23 +1419,50 @@ class DeviceErv extends EventEmitter {
1321
1419
  && presetData.VentilationMode === ventilationMode
1322
1420
  && presetData.SetFanSpeed === setFanSpeed) : false;
1323
1421
 
1324
- const characteristicType = preset.characteristicType;
1325
- this.presetsServices?.[i]?.updateCharacteristic(characteristicType, preset.state);
1422
+ //control
1423
+ if (preset.displayType > 3) {
1424
+ this.presetControlServices?.[i]?.updateCharacteristic(Characteristic.On, preset.state);
1425
+ }
1426
+
1427
+ //sencor
1428
+ this.presetControlSensorServices?.[i]?.updateCharacteristic(characteristicType, preset.state);
1326
1429
  });
1327
1430
  };
1328
1431
 
1329
- //schedules
1432
+ ///schedules
1330
1433
  if (this.schedules.length > 0 && scheduleEnabled !== null) {
1331
1434
  this.schedules.forEach((schedule, i) => {
1332
- //control
1333
- if (i === 0) this.schedulesControlService?.updateCharacteristic(Characteristic.On, scheduleEnabled);
1334
-
1335
- //sensors
1336
1435
  const scheduleData = schedulesOnServer.find(s => s.Id === schedule.id);
1436
+ const characteristicType = schedule.characteristicType;
1337
1437
  schedule.state = scheduleEnabled ? scheduleData.Enabled ?? false : false;
1338
1438
 
1339
- const characteristicType = schedule.characteristicType;
1340
- this.schedulesServices?.[i]?.updateCharacteristic(characteristicType, schedule.state);
1439
+ //control
1440
+ if (i === 0) {
1441
+ if (schedule.displayType > 3) {
1442
+ this.scheduleControlService?.updateCharacteristic(Characteristic.On, scheduleEnabled);
1443
+ }
1444
+ this.scheduleControlSensorService?.updateCharacteristic(characteristicType, scheduleEnabled);
1445
+ }
1446
+
1447
+ //sensor
1448
+ this.scheduleSensorServices?.[i]?.updateCharacteristic(characteristicType, schedule.state);
1449
+ });
1450
+ };
1451
+
1452
+ //schedules
1453
+ if (this.scenes.length > 0) {
1454
+ this.scenes.forEach((scene, i) => {
1455
+ const sceneData = scenesOnServer.find(s => s.Id === scene.id);
1456
+ scene.state = sceneData.Enabled;
1457
+
1458
+ //control
1459
+ if (scene.displayType > 3) {
1460
+ this.sceneControlServices?.[i]?.updateCharacteristic(Characteristic.On, scene.state);
1461
+ }
1462
+
1463
+ //sensor
1464
+ const characteristicType = scene.characteristicType;
1465
+ this.sceneControlSensorServices?.[i]?.updateCharacteristic(characteristicType, scene.state);
1341
1466
  });
1342
1467
  };
1343
1468
 
@@ -52,9 +52,11 @@ class MelCloudAtw extends EventEmitter {
52
52
  try {
53
53
  //read device info from file
54
54
  const devicesData = await this.functions.readData(this.devicesFile, true);
55
+ const scenes = devicesData.Scenes ?? [];
55
56
  const deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
56
57
 
57
58
  if (this.accountType === 'melcloudhome') {
59
+ deviceData.Scenes = scenes;
58
60
  }
59
61
 
60
62
  const safeConfig = {
@@ -119,7 +121,7 @@ class MelCloudAtw extends EventEmitter {
119
121
  };
120
122
  };
121
123
 
122
- async send(accountType, displayType, deviceData, flag) {
124
+ async send(accountType, displayType, deviceData, flag, flagData) {
123
125
  try {
124
126
 
125
127
  //prevent to set out of range temp
@@ -193,6 +195,12 @@ class MelCloudAtw extends EventEmitter {
193
195
  path = ApiUrlsHome.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
194
196
  deviceData.Headers.Referer = ApiUrlsHome.Referers.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
195
197
  break;
198
+ case 'scene':
199
+ method = 'PUT';
200
+ const state = flagData.Enabled ? 'Enable' : 'Disable';
201
+ path = ApiUrlsHome.PutScene[state].replace('sceneid', flagData.Id);
202
+ deviceData.Headers.Referer = ApiUrlsHome.Referers.GetPutScenes;
203
+ break;
196
204
  default:
197
205
  payload = {
198
206
  power: deviceData.Device.Power,
@@ -52,9 +52,12 @@ class MelCloudErv extends EventEmitter {
52
52
  try {
53
53
  //read device info from file
54
54
  const devicesData = await this.functions.readData(this.devicesFile, true);
55
+ const scenes = devicesData.Scenes ?? [];
55
56
  const deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
56
57
 
57
58
  if (this.accountType === 'melcloudhome') {
59
+ deviceData.Scenes = scenes;
60
+
58
61
  //read default temps
59
62
  const temps = await this.functions.readData(this.defaultTempsFile, true);
60
63
  deviceData.Device.DefaultHeatingSetTemperature = temps?.defaultHeatingSetTemperature ?? 20;
@@ -120,7 +123,7 @@ class MelCloudErv extends EventEmitter {
120
123
  };
121
124
  };
122
125
 
123
- async send(accountType, displayType, deviceData, flag) {
126
+ async send(accountType, displayType, deviceData, flag, flagData) {
124
127
  try {
125
128
  let method = null
126
129
  let payload = {};
@@ -207,6 +210,12 @@ class MelCloudErv extends EventEmitter {
207
210
  path = ApiUrlsHome.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
208
211
  deviceData.Headers.Referer = ApiUrlsHome.Referers.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
209
212
  break;
213
+ case 'scene':
214
+ method = 'PUT';
215
+ const state = flagData.Enabled ? 'Enable' : 'Disable';
216
+ path = ApiUrlsHome.PutScene[state].replace('sceneid', flagData.Id);
217
+ deviceData.Headers.Referer = ApiUrlsHome.Referers.GetPutScenes;
218
+ break;
210
219
  default:
211
220
  payload = {
212
221
  power: deviceData.Device.Power,