homebridge-melcloud-control 4.2.3-beta.44 → 4.2.3-beta.45

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.
@@ -598,6 +598,75 @@
598
598
  ]
599
599
  }
600
600
  },
601
+ "scenes": {
602
+ "title": "Scenes",
603
+ "type": "array",
604
+ "items": {
605
+ "type": "object",
606
+ "properties": {
607
+ "id": {
608
+ "title": "Id",
609
+ "type": "string",
610
+ "default": "0"
611
+ },
612
+ "displayType": {
613
+ "title": "Display Type",
614
+ "type": "integer",
615
+ "minimum": 0,
616
+ "maximum": 3,
617
+ "default": 0,
618
+ "description": "Select the characteristic type to be displayed in HomeKit app.",
619
+ "anyOf": [
620
+ {
621
+ "title": "None/Disabled",
622
+ "enum": [
623
+ 0
624
+ ]
625
+ },
626
+ {
627
+ "title": "Motion Sensor",
628
+ "enum": [
629
+ 1
630
+ ]
631
+ },
632
+ {
633
+ "title": "Occupancy Sensor",
634
+ "enum": [
635
+ 2
636
+ ]
637
+ },
638
+ {
639
+ "title": "Contact Sensor",
640
+ "enum": [
641
+ 3
642
+ ]
643
+ }
644
+ ]
645
+ },
646
+ "name": {
647
+ "title": "Name",
648
+ "type": "string",
649
+ "default": "Schedule",
650
+ "description": "Your own name displayed in Homebridge/HomeKit app.",
651
+ "condition": {
652
+ "functionBody": "return model.accounts[arrayIndices[0]].ataDevices[arrayIndices[1]].scenes[arrayIndices[2]].displayType > 0;"
653
+ }
654
+ },
655
+ "namePrefix": {
656
+ "title": "Prefix",
657
+ "type": "boolean",
658
+ "default": false,
659
+ "description": "Enable/disable the accessory name as a prefix for schedule name.",
660
+ "condition": {
661
+ "functionBody": "return model.accounts[arrayIndices[0]].ataDevices[arrayIndices[1]].scenes[arrayIndices[2]].displayType > 0;"
662
+ }
663
+ }
664
+ },
665
+ "required": [
666
+ "displayType"
667
+ ]
668
+ }
669
+ },
601
670
  "buttonsSensors": {
602
671
  "title": "Button / Sensor",
603
672
  "type": "array",
@@ -1304,6 +1373,75 @@
1304
1373
  ]
1305
1374
  }
1306
1375
  },
1376
+ "scenes": {
1377
+ "title": "Scenes",
1378
+ "type": "array",
1379
+ "items": {
1380
+ "type": "object",
1381
+ "properties": {
1382
+ "id": {
1383
+ "title": "Id",
1384
+ "type": "string",
1385
+ "default": "0"
1386
+ },
1387
+ "displayType": {
1388
+ "title": "Display Type",
1389
+ "type": "integer",
1390
+ "minimum": 0,
1391
+ "maximum": 3,
1392
+ "default": 0,
1393
+ "description": "Select the characteristic type to be displayed in HomeKit app.",
1394
+ "anyOf": [
1395
+ {
1396
+ "title": "None/Disabled",
1397
+ "enum": [
1398
+ 0
1399
+ ]
1400
+ },
1401
+ {
1402
+ "title": "Motion Sensor",
1403
+ "enum": [
1404
+ 1
1405
+ ]
1406
+ },
1407
+ {
1408
+ "title": "Occupancy Sensor",
1409
+ "enum": [
1410
+ 2
1411
+ ]
1412
+ },
1413
+ {
1414
+ "title": "Contact Sensor",
1415
+ "enum": [
1416
+ 3
1417
+ ]
1418
+ }
1419
+ ]
1420
+ },
1421
+ "name": {
1422
+ "title": "Name",
1423
+ "type": "string",
1424
+ "default": "Schedule",
1425
+ "description": "Your own name displayed in Homebridge/HomeKit app.",
1426
+ "condition": {
1427
+ "functionBody": "return model.accounts[arrayIndices[0]].atwDevices[arrayIndices[1]].scenes[arrayIndices[2]].displayType > 0;"
1428
+ }
1429
+ },
1430
+ "namePrefix": {
1431
+ "title": "Prefix",
1432
+ "type": "boolean",
1433
+ "default": false,
1434
+ "description": "Enable/disable the accessory name as a prefix for schedule name.",
1435
+ "condition": {
1436
+ "functionBody": "return model.accounts[arrayIndices[0]].atwDevices[arrayIndices[1]].scenes[arrayIndices[2]].displayType > 0;"
1437
+ }
1438
+ }
1439
+ },
1440
+ "required": [
1441
+ "displayType"
1442
+ ]
1443
+ }
1444
+ },
1307
1445
  "buttonsSensors": {
1308
1446
  "title": "Button",
1309
1447
  "type": "array",
@@ -1792,6 +1930,75 @@
1792
1930
  ]
1793
1931
  }
1794
1932
  },
1933
+ "scenes": {
1934
+ "title": "Scenes",
1935
+ "type": "array",
1936
+ "items": {
1937
+ "type": "object",
1938
+ "properties": {
1939
+ "id": {
1940
+ "title": "Id",
1941
+ "type": "string",
1942
+ "default": "0"
1943
+ },
1944
+ "displayType": {
1945
+ "title": "Display Type",
1946
+ "type": "integer",
1947
+ "minimum": 0,
1948
+ "maximum": 3,
1949
+ "default": 0,
1950
+ "description": "Select the characteristic type to be displayed in HomeKit app.",
1951
+ "anyOf": [
1952
+ {
1953
+ "title": "None/Disabled",
1954
+ "enum": [
1955
+ 0
1956
+ ]
1957
+ },
1958
+ {
1959
+ "title": "Motion Sensor",
1960
+ "enum": [
1961
+ 1
1962
+ ]
1963
+ },
1964
+ {
1965
+ "title": "Occupancy Sensor",
1966
+ "enum": [
1967
+ 2
1968
+ ]
1969
+ },
1970
+ {
1971
+ "title": "Contact Sensor",
1972
+ "enum": [
1973
+ 3
1974
+ ]
1975
+ }
1976
+ ]
1977
+ },
1978
+ "name": {
1979
+ "title": "Name",
1980
+ "type": "string",
1981
+ "default": "Schedule",
1982
+ "description": "Your own name displayed in Homebridge/HomeKit app.",
1983
+ "condition": {
1984
+ "functionBody": "return model.accounts[arrayIndices[0]].ervDevices[arrayIndices[1]].scenes[arrayIndices[2]].displayType > 0;"
1985
+ }
1986
+ },
1987
+ "namePrefix": {
1988
+ "title": "Prefix",
1989
+ "type": "boolean",
1990
+ "default": false,
1991
+ "description": "Enable/disable the accessory name as a prefix for schedule name.",
1992
+ "condition": {
1993
+ "functionBody": "return model.accounts[arrayIndices[0]].ervDevices[arrayIndices[1]].scenes[arrayIndices[2]].displayType > 0;"
1994
+ }
1995
+ }
1996
+ },
1997
+ "required": [
1998
+ "displayType"
1999
+ ]
2000
+ }
2001
+ },
1795
2002
  "buttonsSensors": {
1796
2003
  "title": "Buttons",
1797
2004
  "type": "array",
@@ -2236,6 +2443,32 @@
2236
2443
  "functionBody": "return model.accounts[arrayIndices[0]].type === 'melcloudhome' && model.accounts[arrayIndices[0]].ataDevices[arrayIndices[1]].displayType > 0;"
2237
2444
  }
2238
2445
  },
2446
+ {
2447
+ "title": "Scenes",
2448
+ "type": "section",
2449
+ "description": "Section for setup device scenes",
2450
+ "expandable": true,
2451
+ "expanded": false,
2452
+ "items": [
2453
+ {
2454
+ "key": "accounts[].ataDevices[].scenes",
2455
+ "type": "tabarray",
2456
+ "title": "{{ value.name }}",
2457
+ "items": [
2458
+ {
2459
+ "key": "accounts[].ataDevices[].scenes[].id",
2460
+ "readonly": true
2461
+ },
2462
+ "accounts[].ataDevices[].scenes[].displayType",
2463
+ "accounts[].ataDevices[].scenes[].name",
2464
+ "accounts[].ataDevices[].scenes[].namePrefix"
2465
+ ]
2466
+ }
2467
+ ],
2468
+ "condition": {
2469
+ "functionBody": "return model.accounts[arrayIndices[0]].type === 'melcloudhome' && model.accounts[arrayIndices[0]].ataDevices[arrayIndices[1]].displayType > 0;"
2470
+ }
2471
+ },
2239
2472
  {
2240
2473
  "title": "Buttons / Sensors",
2241
2474
  "type": "section",
@@ -2382,6 +2615,32 @@
2382
2615
  "functionBody": "return model.accounts[arrayIndices[0]].type === 'melcloudhome' && model.accounts[arrayIndices[0]].atwDevices[arrayIndices[1]].displayType > 0;"
2383
2616
  }
2384
2617
  },
2618
+ {
2619
+ "title": "Scenes",
2620
+ "type": "section",
2621
+ "description": "Section for setup device scenes",
2622
+ "expandable": true,
2623
+ "expanded": false,
2624
+ "items": [
2625
+ {
2626
+ "key": "accounts[].atwDevices[].scenes",
2627
+ "type": "tabarray",
2628
+ "title": "{{ value.name }}",
2629
+ "items": [
2630
+ {
2631
+ "key": "accounts[].atwDevices[].scenes[].id",
2632
+ "readonly": true
2633
+ },
2634
+ "accounts[].atwDevices[].scenes[].displayType",
2635
+ "accounts[].atwDevices[].scenes[].name",
2636
+ "accounts[].atwDevices[].scenes[].namePrefix"
2637
+ ]
2638
+ }
2639
+ ],
2640
+ "condition": {
2641
+ "functionBody": "return model.accounts[arrayIndices[0]].type === 'melcloudhome' && model.accounts[arrayIndices[0]].atwDevices[arrayIndices[1]].displayType > 0;"
2642
+ }
2643
+ },
2385
2644
  {
2386
2645
  "title": "Buttons / Sensors",
2387
2646
  "type": "section",
@@ -2534,6 +2793,32 @@
2534
2793
  "functionBody": "return model.accounts[arrayIndices[0]].type === 'melcloudhome' && model.accounts[arrayIndices[0]].ervDevices[arrayIndices[1]].displayType > 0;"
2535
2794
  }
2536
2795
  },
2796
+ {
2797
+ "title": "Scenes",
2798
+ "type": "section",
2799
+ "description": "Section for setup device scenes",
2800
+ "expandable": true,
2801
+ "expanded": false,
2802
+ "items": [
2803
+ {
2804
+ "key": "accounts[].ervDevices[].scenes",
2805
+ "type": "tabarray",
2806
+ "title": "{{ value.name }}",
2807
+ "items": [
2808
+ {
2809
+ "key": "accounts[].ervDevices[].scenes[].id",
2810
+ "readonly": true
2811
+ },
2812
+ "accounts[].ervDevices[].scenes[].displayType",
2813
+ "accounts[].ervDevices[].scenes[].name",
2814
+ "accounts[].ervDevices[].scenes[].namePrefix"
2815
+ ]
2816
+ }
2817
+ ],
2818
+ "condition": {
2819
+ "functionBody": "return model.accounts[arrayIndices[0]].type === 'melcloudhome' && model.accounts[arrayIndices[0]].ervDevices[arrayIndices[1]].displayType > 0;"
2820
+ }
2821
+ },
2537
2822
  {
2538
2823
  "title": "Buttons / Sensors",
2539
2824
  "type": "section",
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.44",
4
+ "version": "4.2.3-beta.45",
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
@@ -43,6 +43,7 @@ class DeviceAta extends EventEmitter {
43
43
  this.holidayModeSupport = device.holidayModeSupport || false;
44
44
  this.presets = this.accountType === 'melcloud' ? (device.presets || []).filter(preset => (preset.displayType ?? 0) > 0 && preset.id !== '0') : [];
45
45
  this.schedules = this.accountType === 'melcloudhome' ? (device.schedules || []).filter(schedule => (schedule.displayType ?? 0) > 0 && schedule.id !== '0') : [];
46
+ this.scenes = this.accountType === 'melcloudhome' ? (device.scenes || []).filter(scene => (scene.displayType ?? 0) > 0 && scene.id !== '0') : [];
46
47
  this.buttons = (device.buttonsSensors || []).filter(sensor => (sensor.displayType ?? 0) > 0);
47
48
 
48
49
  //files
@@ -73,6 +74,14 @@ class DeviceAta extends EventEmitter {
73
74
  schedule.state = false;
74
75
  }
75
76
 
77
+ //scenes configured
78
+ for (const scene of this.scenes) {
79
+ scene.name = schedule.name || 'Schedule'
80
+ scene.serviceType = [null, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][scene.displayType];
81
+ scene.characteristicType = [null, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][scene.displayType];
82
+ scene.state = false;
83
+ }
84
+
76
85
  //buttons configured
77
86
  for (const button of this.buttons) {
78
87
  button.name = button.name || 'Button'
@@ -292,6 +301,7 @@ class DeviceAta extends EventEmitter {
292
301
  const accountName = this.accountName;
293
302
  const presetsOnServer = this.accessory.presets;
294
303
  const schedulesOnServer = this.accessory.schedules;
304
+ const scenesOnServer = this.accessory.scenes;
295
305
  const supportsHeat = this.accessory.supportsHeat;
296
306
  const supportsDry = this.accessory.supportsDry;
297
307
  const supportsCool = this.accessory.supportsCool;
@@ -908,7 +918,7 @@ class DeviceAta extends EventEmitter {
908
918
  //control
909
919
  if (i === 0) {
910
920
  if (this.logDebug) this.emit('debug', `Prepare schedule control service`);
911
- this.schedulesControlService = new Service.Switch(`${serviceName} Schedule`, `schedulesControlService${deviceId} ${i}`);
921
+ this.schedulesControlService = new Service.Switch(`${serviceName} Schedule`, `schedulesControlService${deviceId}`);
912
922
  this.schedulesControlService.addOptionalCharacteristic(Characteristic.ConfiguredName);
913
923
  this.schedulesControlService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Schedule`);
914
924
  this.schedulesControlService.getCharacteristic(Characteristic.On)
@@ -956,6 +966,60 @@ class DeviceAta extends EventEmitter {
956
966
  });
957
967
  };
958
968
 
969
+ //scenes
970
+ if (this.scenes.length > 0) {
971
+ if (this.logDebug) this.emit('debug', `Prepare scenes services`);
972
+ this.scenesControlServices = [];
973
+ this.scenesControlSensorServices = [];
974
+ this.sccenes.forEach((scene, i) => {
975
+ const sceneData = scenesOnServer.find(s => s.Id === scene.id);
976
+
977
+ //get id
978
+ const id = scene.id;
979
+
980
+ //get preset name
981
+ const name = scene.name;
982
+
983
+ //get preset name prefix
984
+ const namePrefix = scene.namePrefix;
985
+
986
+ //control
987
+ if (this.logDebug) this.emit('debug', `Prepare scene control service`);
988
+ const serviceName1 = namePrefix ? `${accessoryName} ${name}` : name;
989
+ const sceneControlService = new Service.Switch(serviceName1, `sceneControlService${id}`);
990
+ sceneControlService.addOptionalCharacteristic(Characteristic.ConfiguredName);
991
+ sceneControlService.setCharacteristic(Characteristic.ConfiguredName, serviceName1);
992
+ sceneControlService.getCharacteristic(Characteristic.On)
993
+ .onGet(async () => {
994
+ const state = scene.state;
995
+ return state;
996
+ })
997
+ .onSet(async (state) => {
998
+ try {
999
+ sceneData.Enabled = state;
1000
+ await this.melCloudAta.send(this.accountType, this.displayType, sceneData, 'scene');
1001
+ if (this.logInfo) this.emit('info', `Scene ${name}: ${state ? 'Enabled' : 'Disabled'}`);
1002
+ } catch (error) {
1003
+ if (this.logWarn) this.emit('warn', `Set scene error: ${error}`);
1004
+ };
1005
+ });
1006
+ this.scenesControlServices.push(sceneControlService);
1007
+ accessory.addService(sceneControlService);
1008
+
1009
+ if (this.logDebug) this.emit('debug', `Prepare scene control sensor service`);
1010
+ const sceneControlSensorService = new Service.ContactSensor(serviceName1, `sceneControlSensorService${id}`);
1011
+ sceneControlSensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
1012
+ sceneControlSensorService.setCharacteristic(Characteristic.ConfiguredName, serviceName1);
1013
+ sceneControlSensorService.getCharacteristic(Characteristic.ContactSensorState)
1014
+ .onGet(async () => {
1015
+ const state = scene.state;
1016
+ return state;
1017
+ })
1018
+ this.scenesControlSensorServices.push(sceneControlSensorService);
1019
+ accessory.addService(sceneControlSensorService);
1020
+ });
1021
+ };
1022
+
959
1023
  //buttons services
960
1024
  if (this.buttons.length > 0) {
961
1025
  if (this.logDebug) this.emit('debug', `Prepare buttons/sensors services`);
@@ -1249,9 +1313,10 @@ class DeviceAta extends EventEmitter {
1249
1313
  const supportStandbyKey = accountTypeMelcloud ? 'ModelSupportsStandbyMode' : 'HasStandby';
1250
1314
 
1251
1315
  //presets schedules
1316
+ const presetsOnServer = deviceData.Presets ?? [];
1252
1317
  const scheduleEnabled = deviceData.ScheduleEnabled;
1253
1318
  const schedulesOnServer = deviceData.Schedule ?? [];
1254
- const presetsOnServer = deviceData.Presets ?? [];
1319
+ const scenesOnServer = deviceData.Scenes ?? [];
1255
1320
  const holidayModeEnabled = deviceData.HolidayMode?.Enabled;
1256
1321
  const holidayModeActive = deviceData.HolidayMode?.Active ?? false;
1257
1322
 
@@ -1313,6 +1378,7 @@ class DeviceAta extends EventEmitter {
1313
1378
  const obj = {
1314
1379
  presets: presetsOnServer,
1315
1380
  schedules: schedulesOnServer,
1381
+ scenes: scenesOnServer,
1316
1382
  supportsAutomaticFanSpeed: supportsAutomaticFanSpeed,
1317
1383
  supportsAirDirectionFunction: supportsAirDirectionFunction,
1318
1384
  supportsSwingFunction: supportsSwingFunction,
@@ -1568,6 +1634,21 @@ class DeviceAta extends EventEmitter {
1568
1634
  });
1569
1635
  };
1570
1636
 
1637
+ //schedules
1638
+ if (this.scenes.length > 0) {
1639
+ this.scenes.forEach((scene, i) => {
1640
+ const sceneData = scenesOnServer.find(s => s.Id === scene.id);
1641
+ scene.state = sceneData.Enabled;
1642
+
1643
+ //control
1644
+ this.scenesControlServices?.[i]?.updateCharacteristic(Characteristic.On, scene.state);
1645
+
1646
+ //sensors
1647
+ const characteristicType = scene.characteristicType;
1648
+ this.scenesControlSensorServices?.[i]?.updateCharacteristic(characteristicType, scene.state);
1649
+ });
1650
+ };
1651
+
1571
1652
  //buttons
1572
1653
  if (this.buttons.length > 0) {
1573
1654
  this.buttons.forEach((button, i) => {
package/src/deviceatw.js CHANGED
@@ -43,6 +43,7 @@ class DeviceAtw extends EventEmitter {
43
43
  this.holidayModeSupport = device.holidayModeSupport || false;
44
44
  this.presets = this.accountType === 'melcloud' ? (device.presets || []).filter(preset => (preset.displayType ?? 0) > 0 && preset.id !== '0') : [];
45
45
  this.schedules = this.accountType === 'melcloudhome' ? (device.schedules || []).filter(schedule => (schedule.displayType ?? 0) > 0 && schedule.id !== '0') : [];
46
+ this.scenes = this.accountType === 'melcloudhome' ? (device.scenes || []).filter(scene => (scene.displayType ?? 0) > 0 && scene.id !== '0') : [];
46
47
  this.buttons = (device.buttonsSensors || []).filter(button => (button.displayType ?? 0) > 0);
47
48
  this.deviceId = device.id;
48
49
  this.deviceName = device.name;
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;
@@ -52,9 +52,11 @@ class MelCloudAta 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
  deviceData.Device.OperationMode = AirConditioner.OperationModeMapStringToEnum[deviceData.Device.OperationMode] ?? deviceData.Device.OperationMode;
59
61
  deviceData.Device.ActualFanSpeed = AirConditioner.FanSpeedMapStringToEnum[deviceData.Device.ActualFanSpeed] ?? deviceData.Device.ActualFanSpeed;
60
62
  deviceData.Device.SetFanSpeed = AirConditioner.FanSpeedMapStringToEnum[deviceData.Device.SetFanSpeed] ?? deviceData.Device.SetFanSpeed;
@@ -223,7 +225,7 @@ class MelCloudAta extends EventEmitter {
223
225
  break;
224
226
  case 'scene':
225
227
  method = 'PUT';
226
- path = ApiUrlsHome.PutScene[deviceData.Scene.Enabled].replace('sceneid', deviceData.Scene.Id);
228
+ path = ApiUrlsHome.PutScene[deviceData.Enabled ? 'Eneble' : 'Disable'].replace('sceneid', deviceData.Id);
227
229
  deviceData.Headers.Referer = ApiUrlsHome.Referers.GetPutScenes;
228
230
  break;
229
231
  default: