homebridge-melcloud-control 4.2.3-beta.8 → 4.2.4

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/src/deviceerv.js CHANGED
@@ -36,6 +36,7 @@ class DeviceErv extends EventEmitter {
36
36
  this.holidayModeSupport = device.holidayModeSupport || false;
37
37
  this.presets = this.accountType === 'melcloud' ? (device.presets || []).filter(preset => (preset.displayType ?? 0) > 0 && preset.id !== '0') : [];
38
38
  this.schedules = this.accountType === 'melcloudhome' ? (device.schedules || []).filter(schedule => (schedule.displayType ?? 0) > 0 && schedule.id !== '0') : [];
39
+ this.scenes = this.accountType === 'melcloudhome' ? (device.scenes || []).filter(scene => (scene.displayType ?? 0) > 0 && scene.id !== '0') : [];
39
40
  this.buttons = (device.buttonsSensors || []).filter(button => (button.displayType ?? 0) > 0);
40
41
  this.deviceId = device.id;
41
42
  this.deviceName = device.name;
@@ -50,23 +51,34 @@ class DeviceErv extends EventEmitter {
50
51
  this.mqtt = account.mqtt ?? {};
51
52
  this.mqttConnected = false;
52
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
+
53
57
  //presets configured
54
58
  for (const preset of this.presets) {
55
- preset.name = preset.name || 'Preset'
56
- preset.serviceType = [null, Service.Outlet, Service.Switch, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][preset.displayType];
57
- 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];
58
62
  preset.state = false;
59
63
  preset.previousSettings = {};
60
64
  }
61
65
 
62
66
  //schedules configured
63
67
  for (const schedule of this.schedules) {
64
- schedule.name = schedule.name || 'Schedule'
65
- schedule.serviceType = [null, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][schedule.displayType];
66
- 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];
67
71
  schedule.state = false;
68
72
  }
69
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
+
70
82
  //buttons configured
71
83
  for (const button of this.buttons) {
72
84
  button.name = button.name || 'Button'
@@ -165,78 +177,78 @@ class DeviceErv extends EventEmitter {
165
177
  async setOverExternalIntegration(integration, deviceData, key, value) {
166
178
  try {
167
179
  let set = false
168
- let effectiveFlags = null;
180
+ let flag = null;
169
181
  switch (key) {
170
182
  case 'Power':
171
183
  deviceData.Device[key] = value;
172
- effectiveFlags = Ventilation.EffectiveFlags.Power;
184
+ flag = Ventilation.EffectiveFlags.Power;
173
185
  break;
174
186
  case 'OperationMode':
175
187
  deviceData.Device[key] = value;
176
- effectiveFlags = Ventilation.EffectiveFlags.OperationMode;
188
+ flag = Ventilation.EffectiveFlags.OperationMode;
177
189
  break;
178
190
  case 'VentilationMode':
179
191
  deviceData.Device[key] = value;
180
- effectiveFlags = Ventilation.EffectiveFlags.VentilationMode;
192
+ flag = Ventilation.EffectiveFlags.VentilationMode;
181
193
  break;
182
194
  case 'SetTemperature':
183
195
  deviceData.Device[key] = value;
184
- effectiveFlags = Ventilation.EffectiveFlags.SetTemperature;
196
+ flag = Ventilation.EffectiveFlags.SetTemperature;
185
197
  break;
186
198
  case 'DefaultCoolingSetTemperature':
187
199
  deviceData.Device[key] = value;
188
- effectiveFlags = Ventilation.EffectiveFlags.SetTemperature;
200
+ flag = Ventilation.EffectiveFlags.SetTemperature;
189
201
  break;
190
202
  case 'DefaultHeatingSetTemperature':
191
203
  deviceData.Device[key] = value;
192
- effectiveFlags = Ventilation.EffectiveFlags.SetTemperature;
204
+ flag = Ventilation.EffectiveFlags.SetTemperature;
193
205
  break;
194
206
  case 'NightPurgeMode':
195
207
  if (this.accountType === 'melcloudhome') return;
196
208
 
197
209
  deviceData.Device[key] = value;
198
- effectiveFlags = Ventilation.EffectiveFlags.NightPurgeMode;
210
+ flag = Ventilation.EffectiveFlags.NightPurgeMode;
199
211
  break;
200
212
  case 'SetFanSpeed':
201
213
  deviceData.Device[key] = value;
202
- effectiveFlags = Ventilation.EffectiveFlags.SetFanSpeed;
214
+ flag = Ventilation.EffectiveFlags.SetFanSpeed;
203
215
  break;
204
216
  case 'HideRoomTemperature':
205
217
  if (this.accountType === 'melcloudhome') return;
206
218
 
207
219
  deviceData[key] = value;
208
- effectiveFlags = Ventilation.EffectiveFlags.Prohibit;
220
+ flag = Ventilation.EffectiveFlags.Prohibit;
209
221
  break;
210
222
  case 'HideSupplyTemperature':
211
223
  if (this.accountType === 'melcloudhome') return;
212
224
 
213
225
  deviceData[key] = value;
214
- effectiveFlags = Ventilation.EffectiveFlags.Prohibit;
226
+ flag = Ventilation.EffectiveFlags.Prohibit;
215
227
  break;
216
228
  case 'HideOutdoorTemperature':
217
229
  if (this.accountType === 'melcloudhome') return;
218
230
 
219
231
  deviceData[key] = value;
220
- effectiveFlags = Ventilation.EffectiveFlags.Prohibit;
232
+ flag = Ventilation.EffectiveFlags.Prohibit;
221
233
  break;
222
234
  case 'ScheduleEnabled':
223
235
  if (this.accountType === 'melcloud') return;
224
236
 
225
237
  deviceData.Device[key].Enabled = value;
226
- effectiveFlags = 'schedule';
238
+ flag = 'schedule';
227
239
  break;
228
240
  case 'HolidayMode':
229
241
  if (this.accountType === 'melcloud') return;
230
242
 
231
243
  deviceData.Device[key].Enabled = value;
232
- effectiveFlags = 'holidaymode';
244
+ flag = 'holidaymode';
233
245
  break;
234
246
  default:
235
247
  this.emit('warn', `${integration}, received key: ${key}, value: ${value}`);
236
248
  break;
237
249
  };
238
250
 
239
- set = await this.melCloudErv.send(this.accountType, this.displayType, deviceData, effectiveFlags);
251
+ set = await this.melCloudErv.send(this.accountType, this.displayType, deviceData, flag);
240
252
  return set;
241
253
  } catch (error) {
242
254
  throw new Error(`${integration} set key: ${key}, value: ${value}, error: ${error.message ?? error}`);
@@ -263,6 +275,7 @@ class DeviceErv extends EventEmitter {
263
275
  const accountName = this.accountName;
264
276
  const presetsOnServer = this.accessory.presets;
265
277
  const schedulesOnServer = this.accessory.schedules;
278
+ const scenesOnServer = this.accessory.scenes;
266
279
  const supportsRoomTemperature = this.accessory.supportsRoomTemperature;
267
280
  const supportsSupplyTemperature = this.accessory.supportsSupplyTemperature;
268
281
  const supportsOutdoorTemperature = this.accessory.supportsOutdoorTemperature;
@@ -305,12 +318,10 @@ class DeviceErv extends EventEmitter {
305
318
  return state;
306
319
  })
307
320
  .onSet(async (state) => {
308
- if (!!state === this.accessory.power) return;
309
-
310
321
  try {
311
322
  deviceData.Device.Power = state ? true : false;
312
323
  await this.melCloudErv.send(this.accountType, this.displayType, deviceData, Ventilation.EffectiveFlags.Power);
313
- if (this.logInfo) this.emit('info', `Set power: ${state ? 'ON' : 'OFF'}`);
324
+ if (this.logInfo) this.emit('info', `Set power: ${state ? 'On' : 'Off'}`);
314
325
  } catch (error) {
315
326
  if (this.logWarn) this.emit('warn', `Set power error: ${error}`);
316
327
  };
@@ -492,30 +503,30 @@ class DeviceErv extends EventEmitter {
492
503
  })
493
504
  .onSet(async (value) => {
494
505
  try {
495
- let effectiveFlags = null;
506
+ let flag = null;
496
507
  switch (value) {
497
508
  case 0: //OFF - POWER OFF
498
509
  deviceData.Device.Power = false;
499
- effectiveFlags = Ventilation.EffectiveFlags.Power;
510
+ flag = Ventilation.EffectiveFlags.Power;
500
511
  break;
501
512
  case 1: //HEAT - LOSSNAY
502
513
  deviceData.Device.Power = true;
503
514
  deviceData.Device.VentilationMode = 0;
504
- effectiveFlags = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.VentilationMode;
515
+ flag = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.VentilationMode;
505
516
  break;
506
517
  case 2: //COOL - BYPASS
507
518
  deviceData.Device.Power = true;
508
519
  deviceData.Device.VentilationMode = supportsBypassVentilationMode ? 1 : 0;
509
- effectiveFlags = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.VentilationMode;
520
+ flag = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.VentilationMode;
510
521
  break;
511
522
  case 3: //AUTO - AUTO
512
523
  deviceData.Device.Power = true;
513
524
  deviceData.Device.VentilationMode = supportsAutoVentilationMode ? 2 : 0;
514
- effectiveFlags = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.VentilationMode;
525
+ flag = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.VentilationMode;
515
526
  break;
516
527
  };
517
528
 
518
- await this.melCloudErv.send(this.accountType, this.displayType, deviceData, effectiveFlags);
529
+ await this.melCloudErv.send(this.accountType, this.displayType, deviceData, flag);
519
530
  const operationModeText = Ventilation.VentilationModeMapEnumToString[deviceData.Device.VentilationMode];
520
531
  if (this.logInfo) this.emit('info', `Set operation mode: ${operationModeText}`);
521
532
  } catch (error) {
@@ -783,7 +794,8 @@ class DeviceErv extends EventEmitter {
783
794
  //presets services
784
795
  if (this.presets.length > 0) {
785
796
  if (this.logDebug) this.emit('debug', `Prepare presets services`);
786
- this.presetsServices = [];
797
+ this.presetControlServices = [];
798
+ this.presetControlSensorServices = [];
787
799
  this.presets.forEach((preset, i) => {
788
800
  const presetData = presetsOnServer.find(p => p.ID === preset.id);
789
801
 
@@ -796,49 +808,68 @@ class DeviceErv extends EventEmitter {
796
808
  const serviceName1 = namePrefix ? `${accessoryName} ${name}` : name;
797
809
  const serviceType = preset.serviceType;
798
810
  const characteristicType = preset.characteristicType;
799
- const presetService = new serviceType(serviceName1, `Preset ${deviceId} ${i}`);
800
- presetService.addOptionalCharacteristic(Characteristic.ConfiguredName);
801
- presetService.setCharacteristic(Characteristic.ConfiguredName, serviceName1);
802
- 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)
803
860
  .onGet(async () => {
804
- const state = preset.state;
861
+ const state = this.accessory.scheduleEnabled;
805
862
  return state;
806
863
  })
807
- .onSet(async (state) => {
808
- try {
809
- switch (state) {
810
- case true:
811
- preset.previousSettings = deviceData.Device;
812
- deviceData.Device.SetTemperature = presetData.SetTemperature;
813
- deviceData.Device.Power = presetData.Power;
814
- deviceData.Device.OperationMode = presetData.OperationMode;
815
- deviceData.Device.VentilationMode = presetData.VentilationMode;
816
- deviceData.Device.SetFanSpeed = presetData.SetFanSpeed;
817
- break;
818
- case false:
819
- deviceData.Device.SetTemperature = preset.previousSettings.SetTemperature;
820
- deviceData.Device.Power = preset.previousSettings.Power;
821
- deviceData.Device.OperationMode = preset.previousSettings.OperationMode;
822
- deviceData.Device.VentilationMode = preset.previousSettings.VentilationMode;
823
- deviceData.Device.SetFanSpeed = preset.previousSettings.SetFanSpeed;
824
- break;
825
- };
826
-
827
- await this.melCloudErv.send(this.accountType, this.displayType, deviceData, Ventilation.EffectiveFlags.Power);
828
- if (this.logInfo) this.emit('info', `${state ? 'Set:' : 'Unset:'} ${name}`);
829
- } catch (error) {
830
- if (this.logWarn) this.emit('warn', `Set preset error: ${error}`);
831
- };
832
- });
864
+ this.presetControlSensorServices.push(presetControlSensorService);
865
+ accessory.addService(presetControlSensorService);
833
866
  });
834
- this.presetsServices.push(presetService);
835
- accessory.addService(presetService);
836
867
  };
837
868
 
838
869
  //schedules services
839
870
  if (this.schedules.length > 0 && this.accessory.scheduleEnabled !== null) {
840
871
  if (this.logDebug) this.emit('debug', `Prepare schedules services`);
841
- this.schedulesServices = [];
872
+ this.scheduleSensorServices = [];
842
873
  this.schedules.forEach((schedule, i) => {
843
874
  //get preset name
844
875
  const name = schedule.name;
@@ -846,54 +877,117 @@ class DeviceErv extends EventEmitter {
846
877
  //get preset name prefix
847
878
  const namePrefix = schedule.namePrefix;
848
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
+
849
886
  //control
850
887
  if (i === 0) {
851
- if (this.logDebug) this.emit('debug', `Prepare schedule control service`);
852
- this.schedulesControlService = new Service.Switch(`${serviceName} Schedule`, `schedulesControlService${deviceId} ${i}`);
853
- this.schedulesControlService.addOptionalCharacteristic(Characteristic.ConfiguredName);
854
- this.schedulesControlService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Schedules`);
855
- 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)
856
916
  .onGet(async () => {
857
917
  const state = this.accessory.scheduleEnabled;
858
918
  return state;
859
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
+ })
860
967
  .onSet(async (state) => {
861
968
  try {
862
- deviceData.ScheduleEnabled = state;
863
- await this.melCloudAta.send(this.accountType, this.displayType, deviceData, 'schedule');
864
- 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'}`);
865
972
  } catch (error) {
866
- if (this.logWarn) this.emit('warn', `Set schedule error: ${error}`);
973
+ if (this.logWarn) this.emit('warn', `Set scene error: ${error}`);
867
974
  };
868
975
  });
869
- accessory.addService(this.schedulesControlService);
870
-
871
- if (this.logDebug) this.emit('debug', `Prepare schedule control sensor service`);
872
- this.schedulesControlSensorService = new Service.ContactSensor(`${serviceName} Schedule Control`, `schedulesControlSensorService${deviceId}`);
873
- this.schedulesControlSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
874
- this.schedulesControlSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Schedule Control`);
875
- this.schedulesControlSensorService.getCharacteristic(Characteristic.ContactSensorState)
876
- .onGet(async () => {
877
- const state = this.accessory.scheduleEnabled;
878
- return state;
879
- })
880
- accessory.addService(this.schedulesControlSensorService);
976
+ this.sceneControlServices.push(sceneControlService);
977
+ accessory.addService(sceneControlService);
881
978
  }
882
979
 
883
- //sensors
884
- const serviceName1 = namePrefix ? `${accessoryName} ${name}` : name;
885
- const serviceType = schedule.serviceType;
886
- const characteristicType = schedule.characteristicType;
887
- const scheduleService = new serviceType(serviceName1, `scheduleService${deviceId} ${i}`);
888
- scheduleService.addOptionalCharacteristic(Characteristic.ConfiguredName);
889
- scheduleService.setCharacteristic(Characteristic.ConfiguredName, serviceName1);
890
- 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)
891
985
  .onGet(async () => {
892
- const state = schedule.state;
986
+ const state = scene.state;
893
987
  return state;
894
- });
895
- this.schedulesServices.push(scheduleService);
896
- accessory.addService(scheduleService);
988
+ })
989
+ this.sceneControlSensorServices.push(sceneControlSensorService);
990
+ accessory.addService(sceneControlSensorService);
897
991
  });
898
992
  };
899
993
 
@@ -924,68 +1018,68 @@ class DeviceErv extends EventEmitter {
924
1018
  })
925
1019
  .onSet(async (state) => {
926
1020
  try {
927
- let effectiveFlags = null;
1021
+ let flag = null;
928
1022
  switch (mode) {
929
1023
  case 0: //POWER ON,OFF
930
1024
  deviceData.Device.Power = state;
931
- effectiveFlags = Ventilation.EffectiveFlags.Power;
1025
+ flag = Ventilation.EffectiveFlags.Power;
932
1026
  break;
933
1027
  case 1: //OPERATING MODE RECOVERY
934
1028
  button.previousValue = state ? deviceData.Device.VentilationMode : button.previousValue ?? deviceData.Device.VentilationMode;
935
1029
  deviceData.Device.Power = true;
936
1030
  deviceData.Device.VentilationMode = state ? 0 : button.previousValue;
937
- effectiveFlags = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.VentilationMode;
1031
+ flag = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.VentilationMode;
938
1032
  break;
939
1033
  case 2: //OPERATING MODE BYPASS
940
1034
  button.previousValue = state ? deviceData.Device.VentilationMode : button.previousValue ?? deviceData.Device.VentilationMode;
941
1035
  deviceData.Device.Power = true;
942
1036
  deviceData.Device.VentilationMode = state ? 1 : button.previousValue;
943
- effectiveFlags = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.VentilationMode;
1037
+ flag = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.VentilationMode;
944
1038
  break
945
1039
  case 3: //OPERATING MODE AUTO
946
1040
  button.previousValue = state ? deviceData.Device.VentilationMode : button.previousValue ?? deviceData.Device.VentilationMode;
947
1041
  deviceData.Device.Power = true;
948
1042
  deviceData.Device.VentilationMode = state ? 2 : button.previousValue;
949
- effectiveFlags = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.VentilationMode;
1043
+ flag = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.VentilationMode;
950
1044
  break;
951
1045
  case 4: //NIGHT PURGE MODE
952
1046
  deviceData.Device.Power = true;
953
1047
  deviceData.Device.NightPurgeMode = state;
954
- effectiveFlags = Ventilation.EffectiveFlags.Power
1048
+ flag = Ventilation.EffectiveFlags.Power
955
1049
  break;
956
1050
  case 10: //FAN SPEED MODE AUTO
957
1051
  button.previousValue = state ? deviceData.Device.SetFanSpeed : button.previousValue ?? deviceData.Device.SetFanSpeed;
958
1052
  deviceData.Device.Power = true;
959
1053
  deviceData.Device.SetFanSpeed = state ? 0 : button.previousValue;
960
- effectiveFlags = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.SetFanSpeed;
1054
+ flag = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.SetFanSpeed;
961
1055
  break;
962
1056
  case 11: //FAN SPEED MODE 1
963
1057
  button.previousValue = state ? deviceData.Device.SetFanSpeed : button.previousValue ?? deviceData.Device.SetFanSpeed;
964
1058
  deviceData.Device.Power = true;
965
1059
  deviceData.Device.SetFanSpeed = state ? 1 : button.previousValue;
966
- effectiveFlags = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.SetFanSpeed;
1060
+ flag = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.SetFanSpeed;
967
1061
  break;
968
1062
  case 12: //FAN SPEED MODE 2
969
1063
  button.previousValue = state ? deviceData.Device.SetFanSpeed : button.previousValue ?? deviceData.Device.SetFanSpeed;
970
1064
  deviceData.Device.Power = true;
971
1065
  deviceData.Device.SetFanSpeed = state ? 2 : button.previousValue;
972
- effectiveFlags = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.SetFanSpeed;
1066
+ flag = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.SetFanSpeed;
973
1067
  break;
974
1068
  case 13: //FAN SPEED MODE 3
975
1069
  button.previousValue = state ? deviceData.Device.SetFanSpeed : button.previousValue ?? deviceData.Device.SetFanSpeed;
976
1070
  deviceData.Device.Power = true;
977
1071
  deviceData.Device.SetFanSpeed = state ? 3 : button.previousValue;
978
- effectiveFlags = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.SetFanSpeed;
1072
+ flag = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.SetFanSpeed;
979
1073
  break;
980
1074
  case 14: //FAN MODE 4
981
1075
  button.previousValue = state ? deviceData.Device.SetFanSpeed : button.previousValue ?? deviceData.Device.SetFanSpeed;
982
1076
  deviceData.Device.Power = true;
983
1077
  deviceData.Device.SetFanSpeed = state ? 4 : button.previousValue;
984
- effectiveFlags = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.SetFanSpeed;
1078
+ flag = Ventilation.EffectiveFlags.Power + Ventilation.EffectiveFlags.SetFanSpeed;
985
1079
  break;
986
1080
  case 15: //PHYSICAL LOCK CONTROLS
987
1081
  deviceData.Device = deviceData.Device;
988
- effectiveFlags = Ventilation.EffectiveFlags.Prohibit;
1082
+ flag = Ventilation.EffectiveFlags.Prohibit;
989
1083
  break;
990
1084
  case 16: //ROOM TEMP HIDE
991
1085
  deviceData.HideRoomTemperature = state;
@@ -1001,7 +1095,7 @@ class DeviceErv extends EventEmitter {
1001
1095
  break;
1002
1096
  };
1003
1097
 
1004
- await this.melCloudErv.send(this.accountType, this.displayType, deviceData, effectiveFlags);
1098
+ await this.melCloudErv.send(this.accountType, this.displayType, deviceData, flag);
1005
1099
  if (this.logInfo) this.emit('info', `${state ? `Set: ${buttonName}` : `Unset: ${buttonName}, Set: ${button.previousValue}`}`);
1006
1100
  } catch (error) {
1007
1101
  if (this.logWarn) this.emit('warn', `Set button error: ${error}`);
@@ -1023,7 +1117,7 @@ class DeviceErv extends EventEmitter {
1023
1117
  try {
1024
1118
  //melcloud device
1025
1119
  this.melCloudErv = new MelCloudErv(this.account, this.device, this.devicesFile, this.defaultTempsFile)
1026
- .on('deviceInfo', (manufacturer, modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion) => {
1120
+ .on('deviceInfo', (modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion) => {
1027
1121
  if (this.logDeviceInfo && this.displayDeviceInfo) {
1028
1122
  this.emit('devInfo', `---- ${this.deviceTypeText}: ${this.deviceName} ----`);
1029
1123
  this.emit('devInfo', `Account: ${this.accountName}`);
@@ -1031,13 +1125,13 @@ class DeviceErv extends EventEmitter {
1031
1125
  if (modelOutdoor) this.emit('devInfo', `Outdoor: ${modelOutdoor}`);
1032
1126
  this.emit('devInfo', `Serial: ${serialNumber}`);
1033
1127
  this.emit('devInfo', `Firmware: ${firmwareAppVersion}`);
1034
- this.emit('devInfo', `Manufacturer: ${manufacturer}`);
1128
+ this.emit('devInfo', `Manufacturer: Mitsubishi`);
1035
1129
  this.emit('devInfo', '----------------------------------');
1036
1130
  this.displayDeviceInfo = false;
1037
1131
  }
1038
1132
 
1039
1133
  //accessory info
1040
- this.manufacturer = manufacturer;
1134
+ this.manufacturer = 'Mitsubishi';
1041
1135
  this.model = modelIndoor ? modelIndoor : modelOutdoor ? modelOutdoor : `${this.deviceTypeText} ${this.deviceId}`;
1042
1136
  this.serialNumber = serialNumber.toString();
1043
1137
  this.firmwareRevision = firmwareAppVersion.toString();
@@ -1055,9 +1149,10 @@ class DeviceErv extends EventEmitter {
1055
1149
  const supportStandbyKey = accountTypeMelcloud ? 'ModelSupportsStandbyMode' : 'HasStandby';
1056
1150
 
1057
1151
  //presets schedule
1152
+ const presetsOnServer = deviceData.Presets ?? [];
1058
1153
  const scheduleEnabled = deviceData.ScheduleEnabled;
1059
1154
  const schedulesOnServer = deviceData.Schedule ?? [];
1060
- const presetsOnServer = deviceData.Presets ?? [];
1155
+ const scenesOnServer = deviceData.Scenes ?? [];
1061
1156
  const holidayModeEnabled = deviceData.HolidayMode?.Enabled;
1062
1157
  const holidayModeActive = deviceData.HolidayMode?.Active ?? false;
1063
1158
 
@@ -1115,6 +1210,7 @@ class DeviceErv extends EventEmitter {
1115
1210
  const obj = {
1116
1211
  presets: presetsOnServer,
1117
1212
  schedules: schedulesOnServer,
1213
+ scenes: scenesOnServer,
1118
1214
  supportsRoomTemperature: supportsRoomTemperature,
1119
1215
  supportsSupplyTemperature: supportsSupplyTemperature,
1120
1216
  supportsOutdoorTemperature: supportsOutdoorTemperature,
@@ -1136,7 +1232,7 @@ class DeviceErv extends EventEmitter {
1136
1232
  actualVentilationMode: actualVentilationMode,
1137
1233
  numberOfFanSpeeds: numberOfFanSpeeds,
1138
1234
  supportsFanSpeed: supportsFanSpeed,
1139
- power: power ? 1 : 0,
1235
+ power: power,
1140
1236
  inStandbyMode: inStandbyMode,
1141
1237
  operationMode: operationMode,
1142
1238
  currentOperationMode: 0,
@@ -1315,6 +1411,7 @@ class DeviceErv extends EventEmitter {
1315
1411
  if (this.presets.length > 0) {
1316
1412
  this.presets.forEach((preset, i) => {
1317
1413
  const presetData = presetsOnServer.find(p => p.ID === preset.id);
1414
+ const characteristicType = preset.characteristicType;
1318
1415
 
1319
1416
  preset.state = presetData ? (presetData.Power === power
1320
1417
  && presetData.SetTemperature === setTemperature
@@ -1322,23 +1419,50 @@ class DeviceErv extends EventEmitter {
1322
1419
  && presetData.VentilationMode === ventilationMode
1323
1420
  && presetData.SetFanSpeed === setFanSpeed) : false;
1324
1421
 
1325
- const characteristicType = preset.characteristicType;
1326
- 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);
1327
1429
  });
1328
1430
  };
1329
1431
 
1330
- //schedules
1432
+ ///schedules
1331
1433
  if (this.schedules.length > 0 && scheduleEnabled !== null) {
1332
1434
  this.schedules.forEach((schedule, i) => {
1333
- //control
1334
- if (i === 0) this.schedulesControlService?.updateCharacteristic(Characteristic.On, scheduleEnabled);
1335
-
1336
- //sensors
1337
1435
  const scheduleData = schedulesOnServer.find(s => s.Id === schedule.id);
1436
+ const characteristicType = schedule.characteristicType;
1338
1437
  schedule.state = scheduleEnabled ? scheduleData.Enabled ?? false : false;
1339
1438
 
1340
- const characteristicType = schedule.characteristicType;
1341
- 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);
1342
1466
  });
1343
1467
  };
1344
1468
 
@@ -1402,7 +1526,7 @@ class DeviceErv extends EventEmitter {
1402
1526
 
1403
1527
  //log current state
1404
1528
  if (this.logInfo) {
1405
- this.emit('info', `Power: ${power ? 'ON' : 'OFF'}`);
1529
+ this.emit('info', `Power: ${power ? 'On' : 'Off'}`);
1406
1530
  this.emit('info', `Target ventilation mode: ${Ventilation.OperationModeMapEnumToString[ventilationMode]}`);
1407
1531
  this.emit('info', `Current ventilation mode: ${Ventilation.OperationModeMapEnumToString[actualVentilationMode]}`);
1408
1532
  this.emit('info', `Target temperature: ${setTemperature}${obj.temperatureUnit}`);