homebridge-melcloud-control 4.9.2-beta.8 → 4.10.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/melcloudhome.js +112 -112
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "MELCloud Control",
3
3
  "name": "homebridge-melcloud-control",
4
- "version": "4.9.2-beta.8",
4
+ "version": "4.10.0-beta.0",
5
5
  "description": "Homebridge plugin to control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.",
6
6
  "license": "MIT",
7
7
  "author": "grzegorz914",
@@ -424,9 +424,9 @@ class MelCloudHome extends EventEmitter {
424
424
  // attachTokenInterceptors() dodaje interceptory tylko przy pierwszym wywołaniu.
425
425
  this.ensureClient();
426
426
  this.attachTokenInterceptors();
427
- this.emit('client', this.client);
428
427
 
429
428
  if (this.pluginStart) {
429
+ this.emit('client', this.client);
430
430
  await this.connectSocket().catch(err => {
431
431
  if (this.logError) this.emit('error', `Initial WebSocket connect failed: ${err.message}`);
432
432
  });
@@ -439,117 +439,6 @@ class MelCloudHome extends EventEmitter {
439
439
  return connectInfo;
440
440
  }
441
441
 
442
- // ── Scenes & Devices ──────────────────────────────────────────────────────
443
-
444
- async checkScenesList() {
445
- try {
446
- if (this.logDebug) this.emit('debug', 'Scanning for scenes');
447
-
448
- const resp = await this.client.get(ApiUrls.Home.Get.Scenes);
449
- const scenesList = resp.data;
450
-
451
- if (this.logDebug) this.emit('debug', `Scenes: ${JSON.stringify(scenesList, null, 2)}`);
452
-
453
- return this.capitalizeKeysDeep(scenesList);
454
- } catch (error) {
455
- throw new Error(`Check scenes list error: ${error.message}`);
456
- }
457
- }
458
-
459
- async checkDevicesList() {
460
- try {
461
- const result = { State: false, Status: null, Buildings: {}, Devices: [], Scenes: [] };
462
- if (this.logDebug) this.emit('debug', 'Scanning for devices');
463
-
464
- const resp = await this.client.get(ApiUrls.Home.Get.Context);
465
- const userContext = resp.data;
466
- //if (this.logDebug) this.emit('debug', `User Context: ${JSON.stringify(userContext, null, 2)}`);
467
-
468
- const buildings = userContext.buildings ?? [];
469
- const guestBuildings = userContext.guestBuildings ?? [];
470
- const buildingsList = [...buildings, ...guestBuildings];
471
-
472
- if (this.logDebug) this.emit('debug', `Buildings: ${JSON.stringify(buildingsList, null, 2)}`);
473
-
474
- if (buildingsList.length === 0) {
475
- result.Status = 'No buildings found';
476
- return result;
477
- }
478
-
479
- const capitalizeKeys = obj => Object.fromEntries(
480
- Object.entries(obj).map(([k, v]) => [k.charAt(0).toUpperCase() + k.slice(1), v])
481
- );
482
-
483
- const createDevice = (device, type) => {
484
- const settingsObject = Object.fromEntries(
485
- (device.Settings || []).map(({ name, value }) => [
486
- name.charAt(0).toUpperCase() + name.slice(1),
487
- this.functions.convertValue(value),
488
- ])
489
- );
490
-
491
- const deviceObject = {
492
- ...capitalizeKeys(device.Capabilities || {}),
493
- ...settingsObject,
494
- DeviceType: type,
495
- FirmwareAppVersion: device.ConnectedInterfaceIdentifier,
496
- IsConnected: device.IsConnected,
497
- };
498
-
499
- if (device.FrostProtection) device.FrostProtection = capitalizeKeys(device.FrostProtection);
500
- if (device.OverheatProtection) device.OverheatProtection = capitalizeKeys(device.OverheatProtection);
501
- if (device.HolidayMode) device.HolidayMode = capitalizeKeys(device.HolidayMode);
502
- if (Array.isArray(device.Schedule)) device.Schedule = device.Schedule.map(s => this.capitalizeKeysDeep(s));
503
-
504
- const { Settings, Capabilities, Id, GivenDisplayName, ...rest } = device;
505
-
506
- return {
507
- ...rest,
508
- Type: type,
509
- DeviceID: Id,
510
- DeviceName: GivenDisplayName,
511
- SerialNumber: Id,
512
- Device: deviceObject,
513
- };
514
- };
515
-
516
- const devices = buildingsList.flatMap(building => [
517
- ...(building.airToAirUnits || []).map(d => createDevice(capitalizeKeys(d), 0)),
518
- ...(building.airToWaterUnits || []).map(d => createDevice(capitalizeKeys(d), 1)),
519
- ...(building.airToVentilationUnits || []).map(d => createDevice(capitalizeKeys(d), 3)),
520
- ]);
521
-
522
- if (devices.length === 0) {
523
- result.Status = 'No devices found';
524
- return result;
525
- }
526
-
527
- // Sceny
528
- let scenes = [];
529
- try {
530
- scenes = await this.checkScenesList();
531
- if (this.logDebug) this.emit('debug', `Found ${scenes.length} scenes`);
532
- } catch (error) {
533
- if (this.logError) this.emit('error', `Get scenes error: ${error}`);
534
- }
535
-
536
- result.State = true;
537
- result.Status = `Found ${devices.length} devices${scenes.length > 0 ? ` and ${scenes.length} scenes` : ''}`;
538
- result.Buildings = userContext;
539
- result.Devices = devices;
540
- result.Scenes = scenes;
541
-
542
- for (const deviceData of result.Devices) {
543
- deviceData.Scenes = result.Scenes;
544
- this.emit(deviceData.DeviceID, 'request', deviceData);
545
- }
546
-
547
- return result;
548
- } catch (error) {
549
- throw new Error(`Check devices list error: ${error.message}`);
550
- }
551
- }
552
-
553
442
  // ── Connect ───────────────────────────────────────────────────────────────
554
443
 
555
444
  async connect() {
@@ -779,6 +668,117 @@ class MelCloudHome extends EventEmitter {
779
668
  throw new Error(`Connect error: ${error.message}`);
780
669
  }
781
670
  }
671
+
672
+ // ── Scenes & Devices ──────────────────────────────────────────────────────
673
+
674
+ async checkScenesList() {
675
+ try {
676
+ if (this.logDebug) this.emit('debug', 'Scanning for scenes');
677
+
678
+ const resp = await this.client.get(ApiUrls.Home.Get.Scenes);
679
+ const scenesList = resp.data;
680
+
681
+ if (this.logDebug) this.emit('debug', `Scenes: ${JSON.stringify(scenesList, null, 2)}`);
682
+
683
+ return this.capitalizeKeysDeep(scenesList);
684
+ } catch (error) {
685
+ throw new Error(`Check scenes list error: ${error.message}`);
686
+ }
687
+ }
688
+
689
+ async checkDevicesList() {
690
+ try {
691
+ const result = { State: false, Status: null, Buildings: {}, Devices: [], Scenes: [] };
692
+ if (this.logDebug) this.emit('debug', 'Scanning for devices');
693
+
694
+ const resp = await this.client.get(ApiUrls.Home.Get.Context);
695
+ const userContext = resp.data;
696
+ //if (this.logDebug) this.emit('debug', `User Context: ${JSON.stringify(userContext, null, 2)}`);
697
+
698
+ const buildings = userContext.buildings ?? [];
699
+ const guestBuildings = userContext.guestBuildings ?? [];
700
+ const buildingsList = [...buildings, ...guestBuildings];
701
+
702
+ if (this.logDebug) this.emit('debug', `Buildings: ${JSON.stringify(buildingsList, null, 2)}`);
703
+
704
+ if (buildingsList.length === 0) {
705
+ result.Status = 'No buildings found';
706
+ return result;
707
+ }
708
+
709
+ const capitalizeKeys = obj => Object.fromEntries(
710
+ Object.entries(obj).map(([k, v]) => [k.charAt(0).toUpperCase() + k.slice(1), v])
711
+ );
712
+
713
+ const createDevice = (device, type) => {
714
+ const settingsObject = Object.fromEntries(
715
+ (device.Settings || []).map(({ name, value }) => [
716
+ name.charAt(0).toUpperCase() + name.slice(1),
717
+ this.functions.convertValue(value),
718
+ ])
719
+ );
720
+
721
+ const deviceObject = {
722
+ ...capitalizeKeys(device.Capabilities || {}),
723
+ ...settingsObject,
724
+ DeviceType: type,
725
+ FirmwareAppVersion: device.ConnectedInterfaceIdentifier,
726
+ IsConnected: device.IsConnected,
727
+ };
728
+
729
+ if (device.FrostProtection) device.FrostProtection = capitalizeKeys(device.FrostProtection);
730
+ if (device.OverheatProtection) device.OverheatProtection = capitalizeKeys(device.OverheatProtection);
731
+ if (device.HolidayMode) device.HolidayMode = capitalizeKeys(device.HolidayMode);
732
+ if (Array.isArray(device.Schedule)) device.Schedule = device.Schedule.map(s => this.capitalizeKeysDeep(s));
733
+
734
+ const { Settings, Capabilities, Id, GivenDisplayName, ...rest } = device;
735
+
736
+ return {
737
+ ...rest,
738
+ Type: type,
739
+ DeviceID: Id,
740
+ DeviceName: GivenDisplayName,
741
+ SerialNumber: Id,
742
+ Device: deviceObject,
743
+ };
744
+ };
745
+
746
+ const devices = buildingsList.flatMap(building => [
747
+ ...(building.airToAirUnits || []).map(d => createDevice(capitalizeKeys(d), 0)),
748
+ ...(building.airToWaterUnits || []).map(d => createDevice(capitalizeKeys(d), 1)),
749
+ ...(building.airToVentilationUnits || []).map(d => createDevice(capitalizeKeys(d), 3)),
750
+ ]);
751
+
752
+ if (devices.length === 0) {
753
+ result.Status = 'No devices found';
754
+ return result;
755
+ }
756
+
757
+ // Sceny
758
+ let scenes = [];
759
+ try {
760
+ scenes = await this.checkScenesList();
761
+ if (this.logDebug) this.emit('debug', `Found ${scenes.length} scenes`);
762
+ } catch (error) {
763
+ if (this.logError) this.emit('error', `Get scenes error: ${error}`);
764
+ }
765
+
766
+ result.State = true;
767
+ result.Status = `Found ${devices.length} devices${scenes.length > 0 ? ` and ${scenes.length} scenes` : ''}`;
768
+ result.Buildings = userContext;
769
+ result.Devices = devices;
770
+ result.Scenes = scenes;
771
+
772
+ for (const deviceData of result.Devices) {
773
+ deviceData.Scenes = result.Scenes;
774
+ this.emit(deviceData.DeviceID, 'request', deviceData);
775
+ }
776
+
777
+ return result;
778
+ } catch (error) {
779
+ throw new Error(`Check devices list error: ${error.message}`);
780
+ }
781
+ }
782
782
  }
783
783
 
784
784
  export default MelCloudHome;