homebridge-midea-platform 1.2.10-beta.9 → 1.2.10

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 (36) hide show
  1. package/CHANGELOG.md +4 -1
  2. package/biome.json +16 -6
  3. package/config.schema.json +11 -0
  4. package/dist/accessory/AirConditionerAccessory.d.ts +7 -4
  5. package/dist/accessory/AirConditionerAccessory.js +183 -83
  6. package/dist/accessory/AirConditionerAccessory.js.map +1 -1
  7. package/dist/accessory/DehumidifierAccessory.d.ts +2 -1
  8. package/dist/accessory/DehumidifierAccessory.js +30 -20
  9. package/dist/accessory/DehumidifierAccessory.js.map +1 -1
  10. package/dist/accessory/MDVWiFiControllerAccessory.d.ts +6 -6
  11. package/dist/accessory/MDVWiFiControllerAccessory.js +4 -4
  12. package/dist/accessory/MDVWiFiControllerAccessory.js.map +1 -1
  13. package/dist/core/MideaCloud.js +2 -0
  14. package/dist/core/MideaCloud.js.map +1 -1
  15. package/dist/core/MideaDevice.d.ts +1 -0
  16. package/dist/core/MideaDevice.js +61 -29
  17. package/dist/core/MideaDevice.js.map +1 -1
  18. package/dist/core/MideaMessage.d.ts +1 -0
  19. package/dist/core/MideaMessage.js +6 -2
  20. package/dist/core/MideaMessage.js.map +1 -1
  21. package/dist/devices/ac/MideaACMessage.js +1 -1
  22. package/dist/devices/ac/MideaACMessage.js.map +1 -1
  23. package/dist/devices/cc/MideaCCDevice.d.ts +3 -6
  24. package/dist/devices/cc/MideaCCDevice.js +27 -13
  25. package/dist/devices/cc/MideaCCDevice.js.map +1 -1
  26. package/dist/devices/cc/MideaCCMessage.d.ts +44 -0
  27. package/dist/devices/cc/MideaCCMessage.js +283 -7
  28. package/dist/devices/cc/MideaCCMessage.js.map +1 -1
  29. package/dist/platformUtils.d.ts +6 -0
  30. package/dist/platformUtils.js +6 -0
  31. package/dist/platformUtils.js.map +1 -1
  32. package/package.json +4 -4
  33. package/resources/T_0000_CC_10011006_2025033001.lua +2983 -0
  34. package/.luarc.json +0 -5
  35. package/.zed/settings.json +0 -7
  36. package/cc.lua +0 -988
package/CHANGELOG.md CHANGED
@@ -3,7 +3,10 @@
3
3
  # v1.2.10
4
4
  - fix: added logic to persist fan speed when toggling fan related modes (like sleep mode, boost mode, etc...) in `Air Conditioner` (fixes #158)
5
5
  - feat: added separate switch for setting `Air Conditioner` fan auto mode (fixes #152)
6
- - feat: added support for 0xCC `MDV WiFi Controller` (fixes #126)
6
+ - feat: added basic/partial support for 0xCC `MDV WiFi Controller` (fixes #126)
7
+ - fix: water tank sensors are cleaned up for `Dehumidifier` (fixes #160)
8
+ - fix: authentication and connection logic fixes (by @Ben-Diehlci)
9
+ - feat: added option to set Thermostat as the service type for AC devices (by @Ben-Diehlci)
7
10
 
8
11
  # v1.2.9
9
12
  - feat: added separate temperature sensor creation option for `Air Conditioner` (fixes #141)
package/biome.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
2
+ "$schema": "https://biomejs.dev/schemas/2.0.6/schema.json",
3
3
  "vcs": {
4
4
  "enabled": false,
5
5
  "clientKind": "git",
@@ -7,20 +7,30 @@
7
7
  },
8
8
  "files": {
9
9
  "ignoreUnknown": false,
10
- "ignore": ["dist/**", ".vscode/**", ".github/**", "node_modules/**"]
10
+ "includes": ["**", "!**/dist/**", "!**/.vscode/**", "!**/.github/**", "!**/node_modules/**"]
11
11
  },
12
12
  "formatter": {
13
13
  "enabled": true,
14
14
  "indentStyle": "space",
15
15
  "lineWidth": 160
16
16
  },
17
- "organizeImports": {
18
- "enabled": true
19
- },
17
+ "assist": { "actions": { "source": { "organizeImports": "on" } } },
20
18
  "linter": {
21
19
  "enabled": true,
22
20
  "rules": {
23
- "recommended": true
21
+ "recommended": true,
22
+ "style": {
23
+ "noParameterAssign": "error",
24
+ "useAsConstAssertion": "error",
25
+ "useDefaultParameterLast": "error",
26
+ "useEnumInitializers": "error",
27
+ "useSelfClosingElements": "error",
28
+ "useSingleVarDeclarator": "error",
29
+ "noUnusedTemplateLiteral": "error",
30
+ "useNumberNamespace": "error",
31
+ "noInferrableTypes": "error",
32
+ "noUselessElse": "error"
33
+ }
24
34
  }
25
35
  },
26
36
  "javascript": {
@@ -169,6 +169,16 @@
169
169
  "functionBody": "return model.devices && model.devices[arrayIndices].type === 'Air Conditioner';"
170
170
  },
171
171
  "properties": {
172
+ "serviceType": {
173
+ "title": "HomeKit Service Type",
174
+ "type": "string",
175
+ "default": "HeaterCooler",
176
+ "oneOf": [
177
+ { "title": "Heater/Cooler (range slider)", "enum": ["HeaterCooler"] },
178
+ { "title": "Thermostat (single temperature)", "enum": ["Thermostat"] }
179
+ ],
180
+ "description": "HeaterCooler shows a temperature range slider in AUTO mode. Thermostat shows a single target temperature. Thermostat is recommended for cooling-only units."
181
+ },
172
182
  "swing": {
173
183
  "type": "object",
174
184
  "title": "Swing Options",
@@ -678,6 +688,7 @@
678
688
  "expandable": true,
679
689
  "expanded": false,
680
690
  "items": [
691
+ "devices[].AC_options.serviceType",
681
692
  {
682
693
  "key": "devices[].AC_options.swing",
683
694
  "items": [
@@ -39,6 +39,7 @@ export default class AirConditionerAccessory extends BaseAccessory<MideaACDevice
39
39
  private swingAngleMainControl;
40
40
  private heatingThresholdTemperature;
41
41
  private coolingThresholdTemperature;
42
+ private readonly useThermostat;
42
43
  /*********************************************************************
43
44
  * Constructor registers all the service types with Homebridge, registers
44
45
  * a callback function with the MideaDevice class, and requests device status.
@@ -50,17 +51,19 @@ export default class AirConditionerAccessory extends BaseAccessory<MideaACDevice
50
51
  * any attribute value.
51
52
  */
52
53
  protected updateCharacteristics(attributes: Partial<ACAttributes>): Promise<void>;
54
+ /*********************************************************************
55
+ * Unified state handlers — branch internally based on service type
56
+ */
57
+ getCurrentState(): CharacteristicValue;
58
+ getTargetState(): CharacteristicValue;
59
+ setTargetState(value: CharacteristicValue): Promise<void>;
53
60
  /*********************************************************************
54
61
  * Callback functions for each Homebridge/HomeKit service
55
- *
56
62
  */
57
63
  getActive(): CharacteristicValue;
58
64
  setActive(value: CharacteristicValue): Promise<void>;
59
65
  getTemperatureDisplayUnits(): CharacteristicValue;
60
66
  setTemperatureDisplayUnits(value: CharacteristicValue): Promise<void>;
61
- getCurrentHeaterCoolerState(): CharacteristicValue;
62
- getTargetHeaterCoolerState(): CharacteristicValue;
63
- setTargetHeaterCoolerState(value: CharacteristicValue): Promise<void>;
64
67
  getCurrentTemperature(): CharacteristicValue;
65
68
  getTargetTemperature(): CharacteristicValue;
66
69
  setTargetTemperature(value: CharacteristicValue): Promise<void>;
@@ -1,5 +1,5 @@
1
1
  import { AUTO_FAN_SPEED } from '../devices/ac/MideaACDevice.js';
2
- import { ACMode, SwingAngle, SwingMode } from '../platformUtils.js';
2
+ import { ACMode, ACServiceType, SwingAngle, SwingMode } from '../platformUtils.js';
3
3
  import BaseAccessory, { limitValue } from './BaseAccessory.js';
4
4
  const outDoorTemperatureSubtype = 'outdoor';
5
5
  const displaySubtype = 'display';
@@ -44,6 +44,7 @@ export default class AirConditionerAccessory extends BaseAccessory {
44
44
  swingAngleMainControl;
45
45
  heatingThresholdTemperature;
46
46
  coolingThresholdTemperature;
47
+ useThermostat;
47
48
  /*********************************************************************
48
49
  * Constructor registers all the service types with Homebridge, registers
49
50
  * a callback function with the MideaDevice class, and requests device status.
@@ -52,50 +53,91 @@ export default class AirConditionerAccessory extends BaseAccessory {
52
53
  super(platform, accessory, device, configDev);
53
54
  this.device = device;
54
55
  this.configDev = configDev;
55
- this.service = this.accessory.getService(this.platform.Service.HeaterCooler) || this.accessory.addService(this.platform.Service.HeaterCooler);
56
+ this.useThermostat = this.configDev.AC_options.serviceType === ACServiceType.THERMOSTAT;
57
+ // Remove old service if switching between service types
58
+ const oldService = this.useThermostat
59
+ ? this.accessory.getService(this.platform.Service.HeaterCooler)
60
+ : this.accessory.getService(this.platform.Service.Thermostat);
61
+ if (oldService) {
62
+ this.accessory.removeService(oldService);
63
+ }
64
+ // Create the appropriate service
65
+ this.service = this.useThermostat
66
+ ? (this.accessory.getService(this.platform.Service.Thermostat) || this.accessory.addService(this.platform.Service.Thermostat))
67
+ : (this.accessory.getService(this.platform.Service.HeaterCooler) || this.accessory.addService(this.platform.Service.HeaterCooler));
56
68
  this.service.setCharacteristic(this.platform.Characteristic.Name, this.device.name);
57
- this.service.getCharacteristic(this.platform.Characteristic.Active).onGet(this.getActive.bind(this)).onSet(this.setActive.bind(this));
69
+ // Temperature display units — shared by both service types
58
70
  this.service
59
71
  .getCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits)
60
72
  .onGet(this.getTemperatureDisplayUnits.bind(this))
61
73
  .onSet(this.setTemperatureDisplayUnits.bind(this));
62
- this.service.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState).onGet(this.getCurrentHeaterCoolerState.bind(this));
63
- this.service
64
- .getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState)
65
- .onGet(this.getTargetHeaterCoolerState.bind(this))
66
- .onSet(this.setTargetHeaterCoolerState.bind(this))
67
- .setProps({
68
- validValues: this.configDev.AC_options.heatingCapable
69
- ? [
70
- this.platform.Characteristic.TargetHeaterCoolerState.AUTO,
71
- this.platform.Characteristic.TargetHeaterCoolerState.HEAT,
72
- this.platform.Characteristic.TargetHeaterCoolerState.COOL,
73
- ]
74
- : [this.platform.Characteristic.TargetHeaterCoolerState.AUTO, this.platform.Characteristic.TargetHeaterCoolerState.COOL],
75
- });
74
+ // Current temperature — shared by both service types
76
75
  this.service.getCharacteristic(this.platform.Characteristic.CurrentTemperature).onGet(this.getCurrentTemperature.bind(this));
76
+ // Service-specific characteristic registration
77
77
  this.service
78
- .getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature)
79
- .onGet(this.getCoolingThresholdTemperature.bind(this))
80
- .onSet(this.setCoolingThresholdTemperature.bind(this))
81
- .setProps({
82
- minValue: this.configDev.AC_options.minTemp,
83
- maxValue: this.configDev.AC_options.maxTemp,
84
- minStep: this.configDev.AC_options.tempStep,
85
- });
78
+ .getCharacteristic(this.useThermostat ? this.platform.Characteristic.CurrentHeatingCoolingState : this.platform.Characteristic.CurrentHeaterCoolerState)
79
+ .onGet(this.getCurrentState.bind(this));
80
+ const thermostatStateValues = this.configDev.AC_options.heatingCapable ? [
81
+ this.platform.Characteristic.TargetHeatingCoolingState.OFF,
82
+ this.platform.Characteristic.TargetHeatingCoolingState.HEAT,
83
+ this.platform.Characteristic.TargetHeatingCoolingState.COOL,
84
+ this.platform.Characteristic.TargetHeatingCoolingState.AUTO,
85
+ ]
86
+ : [
87
+ this.platform.Characteristic.TargetHeatingCoolingState.OFF,
88
+ this.platform.Characteristic.TargetHeatingCoolingState.COOL,
89
+ this.platform.Characteristic.TargetHeatingCoolingState.AUTO,
90
+ ];
91
+ const heaterCoolerStateValues = this.configDev.AC_options.heatingCapable
92
+ ? [
93
+ this.platform.Characteristic.TargetHeaterCoolerState.AUTO,
94
+ this.platform.Characteristic.TargetHeaterCoolerState.HEAT,
95
+ this.platform.Characteristic.TargetHeaterCoolerState.COOL,
96
+ ]
97
+ : [this.platform.Characteristic.TargetHeaterCoolerState.AUTO, this.platform.Characteristic.TargetHeaterCoolerState.COOL];
86
98
  this.service
87
- .getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature)
88
- .onGet(this.getHeatingThresholdTemperature.bind(this))
89
- .onSet(this.setHeatingThresholdTemperature.bind(this))
99
+ .getCharacteristic(this.useThermostat ? this.platform.Characteristic.TargetHeatingCoolingState : this.platform.Characteristic.TargetHeaterCoolerState)
100
+ .onGet(this.getTargetState.bind(this))
101
+ .onSet(this.setTargetState.bind(this))
90
102
  .setProps({
91
- minValue: this.configDev.AC_options.minTemp,
92
- maxValue: this.configDev.AC_options.maxTemp,
93
- minStep: this.configDev.AC_options.tempStep,
103
+ validValues: this.useThermostat ? thermostatStateValues : heaterCoolerStateValues
94
104
  });
95
- this.service.getCharacteristic(this.platform.Characteristic.RotationSpeed).onGet(this.getRotationSpeed.bind(this)).onSet(this.setRotationSpeed.bind(this));
96
- // Swing modes
97
- if (this.configDev.AC_options.swing.mode !== SwingMode.NONE) {
98
- this.service.getCharacteristic(this.platform.Characteristic.SwingMode).onGet(this.getSwingMode.bind(this)).onSet(this.setSwingMode.bind(this));
105
+ if (this.useThermostat) {
106
+ this.service
107
+ .getCharacteristic(this.platform.Characteristic.TargetTemperature)
108
+ .onGet(this.getTargetTemperature.bind(this))
109
+ .onSet(this.setTargetTemperature.bind(this))
110
+ .setProps({
111
+ minValue: this.configDev.AC_options.minTemp,
112
+ maxValue: this.configDev.AC_options.maxTemp,
113
+ minStep: this.configDev.AC_options.tempStep,
114
+ });
115
+ }
116
+ else {
117
+ this.service.getCharacteristic(this.platform.Characteristic.Active).onGet(this.getActive.bind(this)).onSet(this.setActive.bind(this));
118
+ this.service
119
+ .getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature)
120
+ .onGet(this.getCoolingThresholdTemperature.bind(this))
121
+ .onSet(this.setCoolingThresholdTemperature.bind(this))
122
+ .setProps({
123
+ minValue: this.configDev.AC_options.minTemp,
124
+ maxValue: this.configDev.AC_options.maxTemp,
125
+ minStep: this.configDev.AC_options.tempStep,
126
+ });
127
+ this.service
128
+ .getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature)
129
+ .onGet(this.getHeatingThresholdTemperature.bind(this))
130
+ .onSet(this.setHeatingThresholdTemperature.bind(this))
131
+ .setProps({
132
+ minValue: this.configDev.AC_options.minTemp,
133
+ maxValue: this.configDev.AC_options.maxTemp,
134
+ minStep: this.configDev.AC_options.tempStep,
135
+ });
136
+ this.service.getCharacteristic(this.platform.Characteristic.RotationSpeed).onGet(this.getRotationSpeed.bind(this)).onSet(this.setRotationSpeed.bind(this));
137
+ // Swing modes (HeaterCooler only — Thermostat uses the fan accessory for swing)
138
+ if (this.configDev.AC_options.swing.mode !== SwingMode.NONE) {
139
+ this.service.getCharacteristic(this.platform.Characteristic.SwingMode).onGet(this.getSwingMode.bind(this)).onSet(this.setSwingMode.bind(this));
140
+ }
99
141
  }
100
142
  // Outdoor temperature sensor
101
143
  this.outDoorTemperatureService = this.accessory.getServiceById(this.platform.Service.TemperatureSensor, outDoorTemperatureSubtype);
@@ -359,20 +401,19 @@ export default class AirConditionerAccessory extends BaseAccessory {
359
401
  break;
360
402
  case 'target_temperature': {
361
403
  const target = Number(this.getTargetTemperature());
362
- /**
363
- * If the device is heating, we map the target temperature to the heating threshold, if cooling we map to the cooling
364
- * threshold and otherwise we assume an auto mode and only adjust the thresholds if the target value is outside their
365
- * range. This should only happen if the temperature is changed outside of HomeKit and in this case we collapse the
366
- * range to the target temperature set by the user.
367
- */
368
- if (this.device.attributes.MODE === ACMode.HEATING) {
369
- this.setHeatingCoolingTemperatureThresholds({ heating: target });
370
- }
371
- else if (this.device.attributes.MODE === ACMode.COOLING) {
372
- this.setHeatingCoolingTemperatureThresholds({ cooling: target });
404
+ if (this.useThermostat) {
405
+ this.service.updateCharacteristic(this.platform.Characteristic.TargetTemperature, target);
373
406
  }
374
- else if (target < this.heatingThresholdTemperature || target > this.coolingThresholdTemperature) {
375
- this.setHeatingCoolingTemperatureThresholds({ heating: target, cooling: target });
407
+ else {
408
+ if (this.device.attributes.MODE === ACMode.HEATING) {
409
+ this.setHeatingCoolingTemperatureThresholds({ heating: target });
410
+ }
411
+ else if (this.device.attributes.MODE === ACMode.COOLING) {
412
+ this.setHeatingCoolingTemperatureThresholds({ cooling: target });
413
+ }
414
+ else if (target < this.heatingThresholdTemperature || target > this.coolingThresholdTemperature) {
415
+ this.setHeatingCoolingTemperatureThresholds({ heating: target, cooling: target });
416
+ }
376
417
  }
377
418
  updateState = true;
378
419
  break;
@@ -381,7 +422,7 @@ export default class AirConditionerAccessory extends BaseAccessory {
381
422
  const temperature = this.getCurrentTemperature();
382
423
  this.service.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, temperature);
383
424
  this.temperatureSensorService?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, temperature);
384
- if (this.device.attributes.POWER && this.device.attributes.MODE === ACMode.AUTO) {
425
+ if (!this.useThermostat && this.device.attributes.POWER && this.device.attributes.MODE === ACMode.AUTO) {
385
426
  await this.withoutPromptTone(this.setTargetTemperatureWithinThresholds.bind(this));
386
427
  updateState = true;
387
428
  }
@@ -395,7 +436,9 @@ export default class AirConditionerAccessory extends BaseAccessory {
395
436
  break;
396
437
  case 'swing_vertical':
397
438
  case 'swing_horizontal':
398
- this.service.updateCharacteristic(this.platform.Characteristic.SwingMode, this.getSwingMode());
439
+ if (!this.useThermostat) {
440
+ this.service.updateCharacteristic(this.platform.Characteristic.SwingMode, this.getSwingMode());
441
+ }
399
442
  break;
400
443
  case 'mode':
401
444
  updateState = true;
@@ -437,10 +480,12 @@ export default class AirConditionerAccessory extends BaseAccessory {
437
480
  this.platform.log.debug(`[${this.device.name}] Attempt to set unsupported attribute ${k} to ${v}`);
438
481
  }
439
482
  if (updateState) {
440
- this.service.updateCharacteristic(this.platform.Characteristic.Active, this.getActive());
441
- this.service.updateCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState, this.getTargetHeaterCoolerState());
442
- this.service.updateCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState, this.getCurrentHeaterCoolerState());
443
- this.service.updateCharacteristic(this.platform.Characteristic.RotationSpeed, this.getRotationSpeed());
483
+ this.service.updateCharacteristic(this.useThermostat ? this.platform.Characteristic.CurrentHeatingCoolingState : this.platform.Characteristic.CurrentHeaterCoolerState, this.getCurrentState());
484
+ this.service.updateCharacteristic(this.useThermostat ? this.platform.Characteristic.TargetHeatingCoolingState : this.platform.Characteristic.TargetHeaterCoolerState, this.getTargetState());
485
+ if (!this.useThermostat) {
486
+ this.service.updateCharacteristic(this.platform.Characteristic.Active, this.getActive());
487
+ this.service.updateCharacteristic(this.platform.Characteristic.RotationSpeed, this.getRotationSpeed());
488
+ }
444
489
  this.fanOnlyService?.updateCharacteristic(this.platform.Characteristic.On, this.getFanOnlyMode());
445
490
  this.fanService?.updateCharacteristic(this.platform.Characteristic.Active, this.getActive());
446
491
  this.fanService?.updateCharacteristic(this.platform.Characteristic.RotationSpeed, this.getRotationSpeed());
@@ -455,32 +500,29 @@ export default class AirConditionerAccessory extends BaseAccessory {
455
500
  }
456
501
  }
457
502
  /*********************************************************************
458
- * Callback functions for each Homebridge/HomeKit service
459
- *
503
+ * Unified state handlers branch internally based on service type
460
504
  */
461
- getActive() {
462
- // Show as inactive if device is off
463
- return this.device.attributes.POWER ? this.platform.Characteristic.Active.ACTIVE : this.platform.Characteristic.Active.INACTIVE;
464
- }
465
- async setActive(value) {
466
- await this.device.set_attribute({ POWER: !!value });
467
- this.device.attributes.SCREEN_DISPLAY = !!value;
468
- this.displayService?.updateCharacteristic(this.platform.Characteristic.On, !!value);
469
- }
470
- getTemperatureDisplayUnits() {
471
- return this.device.attributes.TEMP_FAHRENHEIT
472
- ? this.platform.Characteristic.TemperatureDisplayUnits.FAHRENHEIT
473
- : this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS;
474
- }
475
- async setTemperatureDisplayUnits(value) {
476
- await this.device.set_attribute({
477
- TEMP_FAHRENHEIT: value === this.platform.Characteristic.TemperatureDisplayUnits.FAHRENHEIT,
478
- });
479
- }
480
- getCurrentHeaterCoolerState() {
481
- const { CurrentHeaterCoolerState } = this.platform.Characteristic;
505
+ getCurrentState() {
506
+ if (this.useThermostat) {
507
+ if (!this.device.attributes.POWER) {
508
+ return this.platform.Characteristic.CurrentHeatingCoolingState.OFF;
509
+ }
510
+ const currentTemp = Number(this.getCurrentTemperature());
511
+ const targetTemp = Number(this.getTargetTemperature());
512
+ if ([ACMode.COOLING, ACMode.AUTO, ACMode.DRY].includes(this.device.attributes.MODE)) {
513
+ if (currentTemp > targetTemp) {
514
+ return this.platform.Characteristic.CurrentHeatingCoolingState.COOL;
515
+ }
516
+ }
517
+ if ([ACMode.HEATING].includes(this.device.attributes.MODE) && this.configDev.AC_options.heatingCapable) {
518
+ if (currentTemp < targetTemp) {
519
+ return this.platform.Characteristic.CurrentHeatingCoolingState.HEAT;
520
+ }
521
+ }
522
+ return this.platform.Characteristic.CurrentHeatingCoolingState.OFF;
523
+ }
482
524
  if (!this.device.attributes.POWER || !this.device.attributes.MODE) {
483
- return CurrentHeaterCoolerState.INACTIVE;
525
+ return this.platform.Characteristic.CurrentHeaterCoolerState.INACTIVE;
484
526
  }
485
527
  const isPossiblyCooling = [ACMode.COOLING, ACMode.AUTO].includes(this.device.attributes.MODE);
486
528
  const isPossiblyHeating = [ACMode.HEATING, ACMode.AUTO].includes(this.device.attributes.MODE) && this.configDev.AC_options.heatingCapable;
@@ -488,14 +530,29 @@ export default class AirConditionerAccessory extends BaseAccessory {
488
530
  const heatingThresholdTemperature = Number(this.getHeatingThresholdTemperature());
489
531
  const coolingThresholdTemperature = Number(this.getCoolingThresholdTemperature());
490
532
  if (isPossiblyCooling && currentTemperature > coolingThresholdTemperature) {
491
- return CurrentHeaterCoolerState.COOLING;
533
+ return this.platform.Characteristic.CurrentHeaterCoolerState.COOLING;
492
534
  }
493
535
  if (isPossiblyHeating && currentTemperature < heatingThresholdTemperature) {
494
- return CurrentHeaterCoolerState.HEATING;
536
+ return this.platform.Characteristic.CurrentHeaterCoolerState.HEATING;
495
537
  }
496
- return CurrentHeaterCoolerState.IDLE;
538
+ return this.platform.Characteristic.CurrentHeaterCoolerState.IDLE;
497
539
  }
498
- getTargetHeaterCoolerState() {
540
+ getTargetState() {
541
+ if (this.useThermostat) {
542
+ if (!this.device.attributes.POWER) {
543
+ return this.platform.Characteristic.TargetHeatingCoolingState.OFF;
544
+ }
545
+ switch (this.device.attributes.MODE) {
546
+ case ACMode.COOLING:
547
+ return this.platform.Characteristic.TargetHeatingCoolingState.COOL;
548
+ case ACMode.HEATING:
549
+ return this.platform.Characteristic.TargetHeatingCoolingState.HEAT;
550
+ case ACMode.AUTO:
551
+ return this.platform.Characteristic.TargetHeatingCoolingState.AUTO;
552
+ default:
553
+ return this.platform.Characteristic.TargetHeatingCoolingState.AUTO;
554
+ }
555
+ }
499
556
  switch (this.device.attributes.MODE) {
500
557
  case ACMode.COOLING:
501
558
  return this.platform.Characteristic.TargetHeaterCoolerState.COOL;
@@ -505,7 +562,24 @@ export default class AirConditionerAccessory extends BaseAccessory {
505
562
  return this.platform.Characteristic.TargetHeaterCoolerState.AUTO;
506
563
  }
507
564
  }
508
- async setTargetHeaterCoolerState(value) {
565
+ async setTargetState(value) {
566
+ if (this.useThermostat) {
567
+ switch (value) {
568
+ case this.platform.Characteristic.TargetHeatingCoolingState.OFF:
569
+ await this.device.set_attribute({ POWER: false });
570
+ break;
571
+ case this.platform.Characteristic.TargetHeatingCoolingState.COOL:
572
+ await this.device.set_attribute({ POWER: true, MODE: ACMode.COOLING });
573
+ break;
574
+ case this.platform.Characteristic.TargetHeatingCoolingState.HEAT:
575
+ await this.device.set_attribute({ POWER: true, MODE: ACMode.HEATING });
576
+ break;
577
+ case this.platform.Characteristic.TargetHeatingCoolingState.AUTO:
578
+ await this.device.set_attribute({ POWER: true, MODE: ACMode.AUTO });
579
+ break;
580
+ }
581
+ return;
582
+ }
509
583
  switch (value) {
510
584
  case this.platform.Characteristic.TargetHeaterCoolerState.AUTO:
511
585
  await this.device.set_attribute({ POWER: true, MODE: ACMode.AUTO });
@@ -519,6 +593,27 @@ export default class AirConditionerAccessory extends BaseAccessory {
519
593
  }
520
594
  await this.setTargetTemperatureWithinThresholds();
521
595
  }
596
+ /*********************************************************************
597
+ * Callback functions for each Homebridge/HomeKit service
598
+ */
599
+ getActive() {
600
+ return this.device.attributes.POWER ? this.platform.Characteristic.Active.ACTIVE : this.platform.Characteristic.Active.INACTIVE;
601
+ }
602
+ async setActive(value) {
603
+ await this.device.set_attribute({ POWER: !!value });
604
+ this.device.attributes.SCREEN_DISPLAY = !!value;
605
+ this.displayService?.updateCharacteristic(this.platform.Characteristic.On, !!value);
606
+ }
607
+ getTemperatureDisplayUnits() {
608
+ return this.device.attributes.TEMP_FAHRENHEIT
609
+ ? this.platform.Characteristic.TemperatureDisplayUnits.FAHRENHEIT
610
+ : this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS;
611
+ }
612
+ async setTemperatureDisplayUnits(value) {
613
+ await this.device.set_attribute({
614
+ TEMP_FAHRENHEIT: value === this.platform.Characteristic.TemperatureDisplayUnits.FAHRENHEIT,
615
+ });
616
+ }
522
617
  getCurrentTemperature() {
523
618
  return this.device.attributes.INDOOR_TEMPERATURE ?? this.configDev.AC_options.minTemp;
524
619
  }
@@ -542,6 +637,11 @@ export default class AirConditionerAccessory extends BaseAccessory {
542
637
  await this.setTargetTemperature(this.getHeatingThresholdTemperature());
543
638
  return;
544
639
  }
640
+ // For cooling-only units in AUTO mode, treat like COOL
641
+ if (!this.configDev.AC_options.heatingCapable) {
642
+ await this.setTargetTemperature(this.getCoolingThresholdTemperature());
643
+ return;
644
+ }
545
645
  if (this.getCurrentTemperature() > this.getCoolingThresholdTemperature()) {
546
646
  await this.setTargetTemperature(this.getCoolingThresholdTemperature());
547
647
  return;