homebridge-melcloud-control 4.2.3-beta.7 → 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/CHANGELOG.md +11 -0
- package/README.md +36 -21
- package/config.schema.json +433 -25
- package/homebridge-ui/public/index.html +86 -16
- package/index.js +3 -3
- package/package.json +2 -2
- package/src/constants.js +48 -5
- package/src/deviceata.js +274 -155
- package/src/deviceatw.js +334 -218
- package/src/deviceerv.js +250 -126
- package/src/melcloud.js +25 -33
- package/src/melcloudata.js +35 -21
- package/src/melcloudatw.js +46 -29
- package/src/melclouderv.js +37 -21
- package/src/melcloudhome.js +77 -38
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
|
|
56
|
-
preset.serviceType = [
|
|
57
|
-
preset.characteristicType = [
|
|
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
|
|
65
|
-
schedule.serviceType = [
|
|
66
|
-
schedule.characteristicType = [
|
|
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
|
|
180
|
+
let flag = null;
|
|
169
181
|
switch (key) {
|
|
170
182
|
case 'Power':
|
|
171
183
|
deviceData.Device[key] = value;
|
|
172
|
-
|
|
184
|
+
flag = Ventilation.EffectiveFlags.Power;
|
|
173
185
|
break;
|
|
174
186
|
case 'OperationMode':
|
|
175
187
|
deviceData.Device[key] = value;
|
|
176
|
-
|
|
188
|
+
flag = Ventilation.EffectiveFlags.OperationMode;
|
|
177
189
|
break;
|
|
178
190
|
case 'VentilationMode':
|
|
179
191
|
deviceData.Device[key] = value;
|
|
180
|
-
|
|
192
|
+
flag = Ventilation.EffectiveFlags.VentilationMode;
|
|
181
193
|
break;
|
|
182
194
|
case 'SetTemperature':
|
|
183
195
|
deviceData.Device[key] = value;
|
|
184
|
-
|
|
196
|
+
flag = Ventilation.EffectiveFlags.SetTemperature;
|
|
185
197
|
break;
|
|
186
198
|
case 'DefaultCoolingSetTemperature':
|
|
187
199
|
deviceData.Device[key] = value;
|
|
188
|
-
|
|
200
|
+
flag = Ventilation.EffectiveFlags.SetTemperature;
|
|
189
201
|
break;
|
|
190
202
|
case 'DefaultHeatingSetTemperature':
|
|
191
203
|
deviceData.Device[key] = value;
|
|
192
|
-
|
|
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
|
-
|
|
210
|
+
flag = Ventilation.EffectiveFlags.NightPurgeMode;
|
|
199
211
|
break;
|
|
200
212
|
case 'SetFanSpeed':
|
|
201
213
|
deviceData.Device[key] = value;
|
|
202
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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 ? '
|
|
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
|
|
506
|
+
let flag = null;
|
|
496
507
|
switch (value) {
|
|
497
508
|
case 0: //OFF - POWER OFF
|
|
498
509
|
deviceData.Device.Power = false;
|
|
499
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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.
|
|
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
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
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 =
|
|
861
|
+
const state = this.accessory.scheduleEnabled;
|
|
805
862
|
return state;
|
|
806
863
|
})
|
|
807
|
-
|
|
808
|
-
|
|
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.
|
|
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 (
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
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
|
-
|
|
863
|
-
await this.melCloudAta.send(this.accountType, this.displayType, deviceData, '
|
|
864
|
-
if (this.logInfo) this.emit('info', `
|
|
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
|
|
973
|
+
if (this.logWarn) this.emit('warn', `Set scene error: ${error}`);
|
|
867
974
|
};
|
|
868
975
|
});
|
|
869
|
-
|
|
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
|
-
|
|
884
|
-
const
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
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 =
|
|
986
|
+
const state = scene.state;
|
|
893
987
|
return state;
|
|
894
|
-
})
|
|
895
|
-
this.
|
|
896
|
-
accessory.addService(
|
|
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
|
|
1021
|
+
let flag = null;
|
|
928
1022
|
switch (mode) {
|
|
929
1023
|
case 0: //POWER ON,OFF
|
|
930
1024
|
deviceData.Device.Power = state;
|
|
931
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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', (
|
|
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:
|
|
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 =
|
|
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
|
|
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
|
|
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
|
-
|
|
1326
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1341
|
-
|
|
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 ? '
|
|
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}`);
|