@homebridge-plugins/homebridge-smarthq 0.4.0-beta.7 → 0.4.0-beta.8
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 +15 -0
- package/dist/devices/airConditioner.d.ts +54 -0
- package/dist/devices/airConditioner.d.ts.map +1 -0
- package/dist/devices/airConditioner.js +575 -0
- package/dist/devices/airConditioner.js.map +1 -0
- package/dist/platform.d.ts +2 -1
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +56 -4
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +15 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +8 -0
- package/dist/settings.js.map +1 -1
- package/docs/assets/dmt/dmt-component-data.js +1 -1
- package/docs/assets/dmt/dmt-search.cmp +0 -0
- package/docs/classes/SmartHQPlatform.html +8 -8
- package/docs/functions/default.html +1 -1
- package/docs/interfaces/DeviceOptions.html +2 -2
- package/docs/interfaces/SmartHQPlatformConfig.html +2 -2
- package/docs/interfaces/SmartHqContext.html +2 -2
- package/docs/interfaces/SmartHqERDResponse.html +8 -0
- package/docs/interfaces/credentials.html +2 -2
- package/docs/interfaces/devicesConfig.html +2 -2
- package/docs/interfaces/options.html +2 -2
- package/docs/modules.html +1 -1
- package/docs/variables/API_URL.html +1 -1
- package/docs/variables/ERD_CODES.html +1 -1
- package/docs/variables/ERD_TYPES.html +1 -1
- package/docs/variables/KEEPALIVE_TIMEOUT.html +1 -1
- package/docs/variables/LOGIN_URL.html +1 -1
- package/docs/variables/OAUTH2_CLIENT_ID.html +1 -1
- package/docs/variables/OAUTH2_CLIENT_SECRET.html +1 -1
- package/docs/variables/OAUTH2_REDIRECT_URI.html +1 -1
- package/docs/variables/PLATFORM_NAME.html +1 -1
- package/docs/variables/PLUGIN_NAME.html +1 -1
- package/docs/variables/SECURE_URL.html +1 -1
- package/eslint.config.js +6 -2
- package/package.json +25 -24
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. This project uses [Semantic Versioning](https://semver.org/)
|
|
4
4
|
|
|
5
|
+
## [0.4.0](https://github.com/homebridge-plugins/homebridge-smarthq/releases/tag/v0.4.0) (2025-06-26)
|
|
6
|
+
|
|
7
|
+
### What's Changes
|
|
8
|
+
|
|
9
|
+
- Add air conditioner support [#34](https://github.com/homebridge-plugins/homebridge-smarthq/pull/34), Thanks [@nicholasodonnell](https://github.com/nicholasodonnell)
|
|
10
|
+
- Opal Monitoring Services Improvements [#26](https://github.com/homebridge-plugins/homebridge-smarthq/pull/26), Thanks [@jamesh48](https://github.com/jamesh48)
|
|
11
|
+
- Opal Scheduling Manager [#25](https://github.com/homebridge-plugins/homebridge-smarthq/pull/25), Thanks [@jamesh48](https://github.com/jamesh48)
|
|
12
|
+
- Fast Follower- Remove Unnecessary info logs [#24](https://github.com/homebridge-plugins/homebridge-smarthq/pull/24), Thanks [@jamesh48](https://github.com/jamesh48)
|
|
13
|
+
- Opal Ice Maker- Labels, Sorting, Auto Shutoff Feature, Descale Notification [#23](https://github.com/homebridge-plugins/homebridge-smarthq/pull/23), Thanks [@jamesh48](https://github.com/jamesh48)
|
|
14
|
+
- Favor deviceOptions over options for options that are specific to devices. [#21](https://github.com/homebridge-plugins/homebridge-smarthq/pull/21), Thanks [@jamesh48](https://github.com/jamesh48)
|
|
15
|
+
- Opal Ice Maker Production/Progress Feature [#20](https://github.com/homebridge-plugins/homebridge-smarthq/pull/20), Thanks [@jamesh48](https://github.com/jamesh48)
|
|
16
|
+
- Housekeeping and updated dependencies.
|
|
17
|
+
|
|
18
|
+
**Full Changelog**: https://github.com/homebridge-plugins/homebridge-smarthq/compare/v0.3.0...v0.4.0
|
|
19
|
+
|
|
5
20
|
## [0.3.0](https://github.com/homebridge-plugins/homebridge-smarthq/releases/tag/v0.3.0) (2025-03-04)
|
|
6
21
|
|
|
7
22
|
# *No New Releases During Lent*
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { CharacteristicValue, PlatformAccessory } from 'homebridge';
|
|
2
|
+
import type { SmartHQPlatform } from '../platform.js';
|
|
3
|
+
import type { devicesConfig, SmartHqContext } from '../settings.js';
|
|
4
|
+
import { deviceBase } from './device.js';
|
|
5
|
+
declare enum OperationMode {
|
|
6
|
+
COOL = "00",
|
|
7
|
+
FAN_ONLY = "01",
|
|
8
|
+
ENERGY_SAVER = "02",
|
|
9
|
+
DRY = "04"
|
|
10
|
+
}
|
|
11
|
+
export declare class SmartHQAirConditioner extends deviceBase {
|
|
12
|
+
protected readonly platform: SmartHQPlatform;
|
|
13
|
+
protected readonly accessory: PlatformAccessory<SmartHqContext>;
|
|
14
|
+
protected readonly device: SmartHqContext['device'] & devicesConfig;
|
|
15
|
+
private readonly HEATER_COOLER_SVC_NAME;
|
|
16
|
+
private readonly heaterCoolerSvc;
|
|
17
|
+
private readonly MODE_SWITCH_SVC_PREFIX;
|
|
18
|
+
private readonly modeSwitchSvc;
|
|
19
|
+
constructor(platform: SmartHQPlatform, accessory: PlatformAccessory<SmartHqContext>, device: SmartHqContext['device'] & devicesConfig);
|
|
20
|
+
private getErdValue;
|
|
21
|
+
private setErdValue;
|
|
22
|
+
private getPowerState;
|
|
23
|
+
private setPowerState;
|
|
24
|
+
private getAmbientTemperature;
|
|
25
|
+
private getTemperature;
|
|
26
|
+
private setTemperature;
|
|
27
|
+
private getTemperatureDisplayUnits;
|
|
28
|
+
private setTemperatureDisplayUnits;
|
|
29
|
+
private getOperationMode;
|
|
30
|
+
private setOperationMode;
|
|
31
|
+
private getFanSetting;
|
|
32
|
+
private setFanSetting;
|
|
33
|
+
private getFilterStatus;
|
|
34
|
+
handleGetActive(): Promise<CharacteristicValue>;
|
|
35
|
+
handleSetActive(value: CharacteristicValue): Promise<void>;
|
|
36
|
+
handleGetCurrentHeaterCoolerState(): Promise<number>;
|
|
37
|
+
handleGetTargetHeaterCoolerState(): Promise<CharacteristicValue>;
|
|
38
|
+
handleSetTargetHeaterCoolerState(_value: CharacteristicValue): Promise<void>;
|
|
39
|
+
handleGetCurrentTemperature(): Promise<number>;
|
|
40
|
+
handleGetCoolingThresholdTemperature(): Promise<number>;
|
|
41
|
+
handleSetCoolingThresholdTemperature(value: CharacteristicValue): Promise<void>;
|
|
42
|
+
handleGetRotationSpeed(): Promise<CharacteristicValue>;
|
|
43
|
+
handleSetRotationSpeed(value: CharacteristicValue): Promise<void>;
|
|
44
|
+
handleGetTemperatureDisplayUnits(): Promise<CharacteristicValue>;
|
|
45
|
+
handleSetTemperatureDisplayUnits(value: CharacteristicValue): Promise<void>;
|
|
46
|
+
handleGetFilterChangeIndication(): Promise<CharacteristicValue>;
|
|
47
|
+
handleGetOperationMode(mode: OperationMode): Promise<CharacteristicValue>;
|
|
48
|
+
handleSetOperationMode(mode: OperationMode, value: CharacteristicValue): Promise<void>;
|
|
49
|
+
refreshState(): Promise<void>;
|
|
50
|
+
private fahrenheitToCelsius;
|
|
51
|
+
private celsiusToFahrenheit;
|
|
52
|
+
}
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=airConditioner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"airConditioner.d.ts","sourceRoot":"","sources":["../../src/devices/airConditioner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAW,MAAM,YAAY,CAAA;AAEjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAsB,MAAM,gBAAgB,CAAA;AAUvF,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAwBxC,aAAK,aAAa;IAChB,IAAI,OAAO;IACX,QAAQ,OAAO;IACf,YAAY,OAAO;IACnB,GAAG,OAAO;CACX;AAED,qBAAa,qBAAsB,SAAQ,UAAU;IAUjD,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,eAAe;IAC5C,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC,cAAc,CAAC;IAC/D,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,GAAG,aAAa;IAVrE,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAoB;IAC3D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAU;IAG1C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAyB;IAChE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgC;gBAGzC,QAAQ,EAAE,eAAe,EACzB,SAAS,EAAE,iBAAiB,CAAC,cAAc,CAAC,EAC5C,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,GAAG,aAAa;YAqGvD,WAAW;YAeX,WAAW;YAqBX,aAAa;YAMb,aAAa;YAMb,qBAAqB;YAWrB,cAAc;YAWd,cAAc;YAad,0BAA0B;YAU1B,0BAA0B;YAU1B,gBAAgB;YAUhB,gBAAgB;YAUhB,aAAa;YAUb,aAAa;YAUb,eAAe;IAchB,eAAe,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAe/C,eAAe,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IA+D1D,iCAAiC,IAAI,OAAO,CAAC,MAAM,CAAC;IA+BpD,gCAAgC,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAYhE,gCAAgC,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAsB5E,2BAA2B,IAAI,OAAO,CAAC,MAAM,CAAC;IAa9C,oCAAoC,IAAI,OAAO,CAAC,MAAM,CAAC;IAavD,oCAAoC,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAa/E,sBAAsB,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAwBtD,sBAAsB,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCjE,gCAAgC,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAehE,gCAAgC,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAe3E,+BAA+B,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAe/D,sBAAsB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAgBzE,sBAAsB,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAqEtF,YAAY;IAqEzB,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,mBAAmB;CAG5B"}
|
|
@@ -0,0 +1,575 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { interval, startWith } from 'rxjs';
|
|
3
|
+
import { ERD_TYPES, } from '../settings.js';
|
|
4
|
+
import { deviceBase } from './device.js';
|
|
5
|
+
var PowerState;
|
|
6
|
+
(function (PowerState) {
|
|
7
|
+
PowerState["ON"] = "01";
|
|
8
|
+
PowerState["OFF"] = "00";
|
|
9
|
+
})(PowerState || (PowerState = {}));
|
|
10
|
+
var TemperatureUnit;
|
|
11
|
+
(function (TemperatureUnit) {
|
|
12
|
+
TemperatureUnit["FAHRENHEIT"] = "00";
|
|
13
|
+
TemperatureUnit["CELSIUS"] = "01";
|
|
14
|
+
})(TemperatureUnit || (TemperatureUnit = {}));
|
|
15
|
+
var FanSetting;
|
|
16
|
+
(function (FanSetting) {
|
|
17
|
+
FanSetting["AUTO"] = "01";
|
|
18
|
+
FanSetting["LOW"] = "02";
|
|
19
|
+
FanSetting["MED"] = "04";
|
|
20
|
+
FanSetting["HIGH"] = "08";
|
|
21
|
+
})(FanSetting || (FanSetting = {}));
|
|
22
|
+
var FilterStatus;
|
|
23
|
+
(function (FilterStatus) {
|
|
24
|
+
FilterStatus["OK"] = "00";
|
|
25
|
+
FilterStatus["CLEAN"] = "01";
|
|
26
|
+
})(FilterStatus || (FilterStatus = {}));
|
|
27
|
+
var OperationMode;
|
|
28
|
+
(function (OperationMode) {
|
|
29
|
+
OperationMode["COOL"] = "00";
|
|
30
|
+
OperationMode["FAN_ONLY"] = "01";
|
|
31
|
+
OperationMode["ENERGY_SAVER"] = "02";
|
|
32
|
+
OperationMode["DRY"] = "04";
|
|
33
|
+
})(OperationMode || (OperationMode = {}));
|
|
34
|
+
export class SmartHQAirConditioner extends deviceBase {
|
|
35
|
+
platform;
|
|
36
|
+
accessory;
|
|
37
|
+
device;
|
|
38
|
+
// HeaterCooler service
|
|
39
|
+
HEATER_COOLER_SVC_NAME = 'AIR_CONDITIONER';
|
|
40
|
+
heaterCoolerSvc;
|
|
41
|
+
// Mode SwitchServices
|
|
42
|
+
MODE_SWITCH_SVC_PREFIX = 'AIR_CONDITIONER_MODE';
|
|
43
|
+
modeSwitchSvc;
|
|
44
|
+
constructor(platform, accessory, device) {
|
|
45
|
+
super(platform, accessory, device);
|
|
46
|
+
this.platform = platform;
|
|
47
|
+
this.accessory = accessory;
|
|
48
|
+
this.device = device;
|
|
49
|
+
// HeaterCooler service
|
|
50
|
+
this.heaterCoolerSvc = this.accessory.getService(this.HEATER_COOLER_SVC_NAME)
|
|
51
|
+
?? this.accessory.addService(this.platform.Service.HeaterCooler, accessory.displayName, this.HEATER_COOLER_SVC_NAME);
|
|
52
|
+
// Mode SwitchServices
|
|
53
|
+
this.modeSwitchSvc = {
|
|
54
|
+
[OperationMode.COOL]: this.accessory.getService(`${this.MODE_SWITCH_SVC_PREFIX}_COOL`)
|
|
55
|
+
?? this.accessory.addService(this.platform.Service.Switch, `${accessory.displayName} Cool Mode`, `${this.MODE_SWITCH_SVC_PREFIX}_COOL`),
|
|
56
|
+
[OperationMode.FAN_ONLY]: this.accessory.getService(`${this.MODE_SWITCH_SVC_PREFIX}_FAN_ONLY`)
|
|
57
|
+
?? this.accessory.addService(this.platform.Service.Switch, `${accessory.displayName} Fan Only Mode`, `${this.MODE_SWITCH_SVC_PREFIX}_FAN_ONLY`),
|
|
58
|
+
[OperationMode.ENERGY_SAVER]: this.accessory.getService(`${this.MODE_SWITCH_SVC_PREFIX}_ENERGY_SAVER`)
|
|
59
|
+
?? this.accessory.addService(this.platform.Service.Switch, `${accessory.displayName} Energy Saver Mode`, `${this.MODE_SWITCH_SVC_PREFIX}_ENERGY_SAVER`),
|
|
60
|
+
[OperationMode.DRY]: this.accessory.getService(`${this.MODE_SWITCH_SVC_PREFIX}_DRY`)
|
|
61
|
+
?? this.accessory.addService(this.platform.Service.Switch, `${accessory.displayName} Dry Mode`, `${this.MODE_SWITCH_SVC_PREFIX}_DRY`),
|
|
62
|
+
};
|
|
63
|
+
// Active
|
|
64
|
+
this.heaterCoolerSvc
|
|
65
|
+
.getCharacteristic(this.platform.Characteristic.Active)
|
|
66
|
+
.onGet(this.handleGetActive.bind(this))
|
|
67
|
+
.onSet(this.handleSetActive.bind(this));
|
|
68
|
+
// Current mode
|
|
69
|
+
this.heaterCoolerSvc
|
|
70
|
+
.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState)
|
|
71
|
+
.setProps({
|
|
72
|
+
validValues: [
|
|
73
|
+
this.platform.Characteristic.CurrentHeaterCoolerState.INACTIVE,
|
|
74
|
+
this.platform.Characteristic.CurrentHeaterCoolerState.IDLE,
|
|
75
|
+
this.platform.Characteristic.CurrentHeaterCoolerState.COOLING,
|
|
76
|
+
],
|
|
77
|
+
})
|
|
78
|
+
.onGet(this.handleGetCurrentHeaterCoolerState.bind(this));
|
|
79
|
+
// Target mode (COOL only)
|
|
80
|
+
this.heaterCoolerSvc
|
|
81
|
+
.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState)
|
|
82
|
+
.setProps({
|
|
83
|
+
validValues: [
|
|
84
|
+
this.platform.Characteristic.TargetHeaterCoolerState.COOL,
|
|
85
|
+
],
|
|
86
|
+
})
|
|
87
|
+
.onGet(this.handleGetTargetHeaterCoolerState.bind(this))
|
|
88
|
+
.onSet(this.handleSetTargetHeaterCoolerState.bind(this));
|
|
89
|
+
// Ambient temp
|
|
90
|
+
this.heaterCoolerSvc
|
|
91
|
+
.getCharacteristic(this.platform.Characteristic.CurrentTemperature)
|
|
92
|
+
.onGet(this.handleGetCurrentTemperature.bind(this));
|
|
93
|
+
// Target temperature
|
|
94
|
+
this.heaterCoolerSvc
|
|
95
|
+
.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature)
|
|
96
|
+
.setProps({
|
|
97
|
+
minValue: 17.7778, // 64F
|
|
98
|
+
maxValue: 30, // 86F
|
|
99
|
+
})
|
|
100
|
+
.onGet(this.handleGetCoolingThresholdTemperature.bind(this))
|
|
101
|
+
.onSet(this.handleSetCoolingThresholdTemperature.bind(this));
|
|
102
|
+
// Rotation speed
|
|
103
|
+
this.heaterCoolerSvc
|
|
104
|
+
.getCharacteristic(this.platform.Characteristic.RotationSpeed)
|
|
105
|
+
.onGet(this.handleGetRotationSpeed.bind(this))
|
|
106
|
+
.onSet(this.handleSetRotationSpeed.bind(this));
|
|
107
|
+
// Display units
|
|
108
|
+
this.heaterCoolerSvc
|
|
109
|
+
.getCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits)
|
|
110
|
+
.onGet(this.handleGetTemperatureDisplayUnits.bind(this))
|
|
111
|
+
.onSet(this.handleSetTemperatureDisplayUnits.bind(this));
|
|
112
|
+
// Filter
|
|
113
|
+
this.heaterCoolerSvc
|
|
114
|
+
.getCharacteristic(this.platform.Characteristic.FilterChangeIndication)
|
|
115
|
+
.onGet(this.handleGetFilterChangeIndication.bind(this));
|
|
116
|
+
// Modes
|
|
117
|
+
for (const mode of Object.values(OperationMode)) {
|
|
118
|
+
this.modeSwitchSvc[mode]
|
|
119
|
+
.getCharacteristic(this.platform.Characteristic.On)
|
|
120
|
+
.onGet(this.handleGetOperationMode.bind(this, mode))
|
|
121
|
+
.onSet(this.handleSetOperationMode.bind(this, mode));
|
|
122
|
+
}
|
|
123
|
+
// Start an update interval to refresh state
|
|
124
|
+
interval(this.deviceRefreshRate * 1000)
|
|
125
|
+
.pipe(startWith(0))
|
|
126
|
+
.subscribe(this.refreshState.bind(this));
|
|
127
|
+
}
|
|
128
|
+
// API
|
|
129
|
+
async getErdValue(erd) {
|
|
130
|
+
try {
|
|
131
|
+
const response = await axios.get(`/appliance/${this.accessory.context.device.applianceId}/erd/${erd}`);
|
|
132
|
+
return response.data.value;
|
|
133
|
+
}
|
|
134
|
+
catch (cause) {
|
|
135
|
+
throw new Error(axios.isAxiosError(cause) && cause.response
|
|
136
|
+
? `Failed to fetch ERD: ${cause.response.data.message}`
|
|
137
|
+
: `Failed to fetch ERD: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
async setErdValue(erd, value) {
|
|
141
|
+
try {
|
|
142
|
+
await axios.post(`/appliance/${this.accessory.context.device.applianceId}/erd/${erd}`, {
|
|
143
|
+
kind: 'appliance#erdListEntry',
|
|
144
|
+
userId: this.accessory.context.userId,
|
|
145
|
+
applianceId: this.accessory.context.device.applianceId,
|
|
146
|
+
erd,
|
|
147
|
+
value,
|
|
148
|
+
});
|
|
149
|
+
this.platform.log.debug(`[${this.accessory.displayName}] Set ERD ${erd}=${value}`);
|
|
150
|
+
}
|
|
151
|
+
catch (cause) {
|
|
152
|
+
throw new Error(axios.isAxiosError(cause) && cause.response
|
|
153
|
+
? `Failed to set ERD value for ${erd}: ${cause.response.data.message}`
|
|
154
|
+
: `Failed to set ERD value for ${erd}: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
async getPowerState() {
|
|
158
|
+
const erdValue = await this.getErdValue(ERD_TYPES.AIR_CONDITIONER_POWER_STATUS);
|
|
159
|
+
return erdValue;
|
|
160
|
+
}
|
|
161
|
+
async setPowerState(value) {
|
|
162
|
+
await this.setErdValue(ERD_TYPES.AIR_CONDITIONER_POWER_STATUS, value);
|
|
163
|
+
this.platform.log.debug(`[${this.accessory.displayName}] Set power state to ${value}`);
|
|
164
|
+
}
|
|
165
|
+
async getAmbientTemperature() {
|
|
166
|
+
try {
|
|
167
|
+
const erdValue = await this.getErdValue(ERD_TYPES.AIR_CONDITIONER_AMBIENT_TEMPERATURE);
|
|
168
|
+
const temperatureInFahrenheit = Number.parseInt(erdValue, 16); // erdValue is a hex string representing the temperature in Fahrenheit
|
|
169
|
+
return this.fahrenheitToCelsius(temperatureInFahrenheit); // homekit expects Celsius
|
|
170
|
+
}
|
|
171
|
+
catch (cause) {
|
|
172
|
+
throw new Error(`Failed to get current temperature: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
async getTemperature() {
|
|
176
|
+
try {
|
|
177
|
+
const erdValue = await this.getErdValue(ERD_TYPES.AIR_CONDITIONER_TARGET_TEMPERATURE);
|
|
178
|
+
const temperatureInFahrenheit = Number.parseInt(erdValue, 16); // erdValue is a hex string representing the temperature in Fahrenheit
|
|
179
|
+
return this.fahrenheitToCelsius(temperatureInFahrenheit); // homekit expects Celsius
|
|
180
|
+
}
|
|
181
|
+
catch (cause) {
|
|
182
|
+
throw new Error(`Failed to get target temperature: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
async setTemperature(value) {
|
|
186
|
+
try {
|
|
187
|
+
const temperatureInFahrenheit = this.celsiusToFahrenheit(value);
|
|
188
|
+
const hexTemperature = temperatureInFahrenheit.toString(16).padStart(4, '0').toUpperCase(); // Convert to hex and ensure it's 4 characters long
|
|
189
|
+
await this.setErdValue(ERD_TYPES.AIR_CONDITIONER_TARGET_TEMPERATURE, hexTemperature);
|
|
190
|
+
this.platform.log.debug(`[${this.accessory.displayName}] Set temperature to ${value}°C (${temperatureInFahrenheit}°F)`);
|
|
191
|
+
}
|
|
192
|
+
catch (cause) {
|
|
193
|
+
throw new Error(`Failed to set target temperature: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
async getTemperatureDisplayUnits() {
|
|
197
|
+
try {
|
|
198
|
+
const value = await this.getErdValue(ERD_TYPES.AIR_CONDITIONER_TEMPERATURE_UNIT);
|
|
199
|
+
return value;
|
|
200
|
+
}
|
|
201
|
+
catch (cause) {
|
|
202
|
+
throw new Error(`Failed to get temperature display units: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
async setTemperatureDisplayUnits(value) {
|
|
206
|
+
try {
|
|
207
|
+
await this.setErdValue(ERD_TYPES.AIR_CONDITIONER_TEMPERATURE_UNIT, value);
|
|
208
|
+
this.platform.log.debug(`[${this.accessory.displayName}] Set temperature display units to ${value}`);
|
|
209
|
+
}
|
|
210
|
+
catch (cause) {
|
|
211
|
+
throw new Error(`Failed to set temperature display units: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
async getOperationMode() {
|
|
215
|
+
try {
|
|
216
|
+
const value = await this.getErdValue(ERD_TYPES.AIR_CONDITIONER_OPERATION_MODE);
|
|
217
|
+
return value;
|
|
218
|
+
}
|
|
219
|
+
catch (cause) {
|
|
220
|
+
throw new Error(`Failed to get operation mode: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
async setOperationMode(value) {
|
|
224
|
+
try {
|
|
225
|
+
await this.setErdValue(ERD_TYPES.AIR_CONDITIONER_OPERATION_MODE, value);
|
|
226
|
+
this.platform.log.debug(`[${this.accessory.displayName}] Set operation mode to ${value}`);
|
|
227
|
+
}
|
|
228
|
+
catch (cause) {
|
|
229
|
+
throw new Error(`Failed to set operation mode: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
async getFanSetting() {
|
|
233
|
+
try {
|
|
234
|
+
const value = await this.getErdValue(ERD_TYPES.AIR_CONDITIONER_FAN_SETTING);
|
|
235
|
+
return value;
|
|
236
|
+
}
|
|
237
|
+
catch (cause) {
|
|
238
|
+
throw new Error(`Failed to get fan setting: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
async setFanSetting(value) {
|
|
242
|
+
try {
|
|
243
|
+
await this.setErdValue(ERD_TYPES.AIR_CONDITIONER_FAN_SETTING, value);
|
|
244
|
+
this.platform.log.debug(`[${this.accessory.displayName}] Set fan setting to ${value}`);
|
|
245
|
+
}
|
|
246
|
+
catch (cause) {
|
|
247
|
+
throw new Error(`Failed to set fan setting: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
async getFilterStatus() {
|
|
251
|
+
try {
|
|
252
|
+
const value = await this.getErdValue(ERD_TYPES.AIR_CONDITIONER_FILTER_STATUS);
|
|
253
|
+
return value;
|
|
254
|
+
}
|
|
255
|
+
catch (cause) {
|
|
256
|
+
throw new Error(`Failed to get filter status: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// Characteristic handlers
|
|
260
|
+
// active
|
|
261
|
+
async handleGetActive() {
|
|
262
|
+
try {
|
|
263
|
+
const powerState = await this.getPowerState();
|
|
264
|
+
return powerState === PowerState.ON
|
|
265
|
+
? this.platform.Characteristic.Active.ACTIVE
|
|
266
|
+
: this.platform.Characteristic.Active.INACTIVE;
|
|
267
|
+
}
|
|
268
|
+
catch (cause) {
|
|
269
|
+
const error = new Error(`Failed to handle get active: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
270
|
+
this.platform.log.error(`[${this.accessory.displayName}] ${error.message}`);
|
|
271
|
+
throw error;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
async handleSetActive(value) {
|
|
275
|
+
try {
|
|
276
|
+
const [powerState, ambientTemperature, targetTemperature, operationMode] = await Promise.all([
|
|
277
|
+
this.getPowerState(),
|
|
278
|
+
this.getAmbientTemperature(),
|
|
279
|
+
this.getTemperature(),
|
|
280
|
+
this.getOperationMode(),
|
|
281
|
+
]);
|
|
282
|
+
if (value === this.platform.Characteristic.Active.ACTIVE) {
|
|
283
|
+
// If the air conditioner is currently off, turn it on
|
|
284
|
+
if (powerState === PowerState.OFF) {
|
|
285
|
+
await this.setPowerState(PowerState.ON);
|
|
286
|
+
// There's a bug (feature?) in SmartHQ where it resets operation mode when turning on the air conditioner
|
|
287
|
+
// so we need to set it back to the previous mode
|
|
288
|
+
await this.setOperationMode(operationMode);
|
|
289
|
+
}
|
|
290
|
+
// Keep mode switches in sync
|
|
291
|
+
for (const mode of Object.values(OperationMode)) {
|
|
292
|
+
this.modeSwitchSvc[mode].updateCharacteristic(this.platform.Characteristic.On, mode === operationMode);
|
|
293
|
+
}
|
|
294
|
+
// Update CurrentHeaterCoolerState
|
|
295
|
+
this.heaterCoolerSvc.updateCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState, ambientTemperature <= targetTemperature
|
|
296
|
+
? this.platform.Characteristic.CurrentHeaterCoolerState.IDLE
|
|
297
|
+
: this.platform.Characteristic.CurrentHeaterCoolerState.COOLING);
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
if (powerState === PowerState.ON) {
|
|
301
|
+
await this.setPowerState(PowerState.OFF);
|
|
302
|
+
}
|
|
303
|
+
// Keep mode switches in sync
|
|
304
|
+
for (const mode of Object.values(OperationMode)) {
|
|
305
|
+
this.modeSwitchSvc[mode].updateCharacteristic(this.platform.Characteristic.On, false);
|
|
306
|
+
}
|
|
307
|
+
// Keep TargetHeaterCoolerState in sync
|
|
308
|
+
this.heaterCoolerSvc.updateCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState, this.platform.Characteristic.CurrentHeaterCoolerState.INACTIVE);
|
|
309
|
+
}
|
|
310
|
+
catch (cause) {
|
|
311
|
+
const error = new Error(`Failed to handle set active: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
312
|
+
this.platform.log.error(`[${this.accessory.displayName}] ${error.message}`);
|
|
313
|
+
throw error;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
async handleGetCurrentHeaterCoolerState() {
|
|
317
|
+
try {
|
|
318
|
+
const [powerState, ambientTemperature, targetTemperature] = await Promise.all([
|
|
319
|
+
this.getPowerState(),
|
|
320
|
+
this.getAmbientTemperature(),
|
|
321
|
+
this.getTemperature(),
|
|
322
|
+
]);
|
|
323
|
+
if (powerState === PowerState.OFF) {
|
|
324
|
+
return this.platform.Characteristic.CurrentHeaterCoolerState.INACTIVE;
|
|
325
|
+
}
|
|
326
|
+
if (ambientTemperature <= targetTemperature) {
|
|
327
|
+
return this.platform.Characteristic.CurrentHeaterCoolerState.IDLE;
|
|
328
|
+
}
|
|
329
|
+
// Keep TargetHeaterCoolerState in sync
|
|
330
|
+
this.heaterCoolerSvc.updateCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState, this.platform.Characteristic.TargetHeaterCoolerState.COOL);
|
|
331
|
+
return this.platform.Characteristic.CurrentHeaterCoolerState.COOLING;
|
|
332
|
+
}
|
|
333
|
+
catch (cause) {
|
|
334
|
+
const error = new Error(`Failed to handle get current heater cooler state: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
335
|
+
this.platform.log.error(`[${this.accessory.displayName}] ${error.message}`);
|
|
336
|
+
throw error;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
async handleGetTargetHeaterCoolerState() {
|
|
340
|
+
try {
|
|
341
|
+
// Cool is the only supported state for an air conditioner
|
|
342
|
+
return this.platform.Characteristic.TargetHeaterCoolerState.COOL;
|
|
343
|
+
}
|
|
344
|
+
catch (cause) {
|
|
345
|
+
const error = new Error(`Failed to handle get target heater cooler state: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
346
|
+
this.platform.log.error(`[${this.accessory.displayName}] ${error.message}`);
|
|
347
|
+
throw error;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
async handleSetTargetHeaterCoolerState(_value) {
|
|
351
|
+
try {
|
|
352
|
+
const powerState = await this.getPowerState();
|
|
353
|
+
// Turn on the air conditioner if it's currently off
|
|
354
|
+
if (powerState === PowerState.OFF) {
|
|
355
|
+
await this.setPowerState(PowerState.ON);
|
|
356
|
+
}
|
|
357
|
+
// Keep CurrentHeaterCoolerState in sync with TargetHeaterCoolerState
|
|
358
|
+
this.heaterCoolerSvc.updateCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState, this.platform.Characteristic.CurrentHeaterCoolerState.COOLING);
|
|
359
|
+
}
|
|
360
|
+
catch (cause) {
|
|
361
|
+
const error = new Error(`Failed to handle set target heater cooler state: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
362
|
+
this.platform.log.error(`[${this.accessory.displayName}] ${error.message}`);
|
|
363
|
+
throw error;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
async handleGetCurrentTemperature() {
|
|
367
|
+
try {
|
|
368
|
+
const value = await this.getAmbientTemperature();
|
|
369
|
+
return value;
|
|
370
|
+
}
|
|
371
|
+
catch (cause) {
|
|
372
|
+
const error = new Error(`Failed to handle get current temperature: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
373
|
+
this.platform.log.error(`[${this.accessory.displayName}] ${error.message}`);
|
|
374
|
+
throw error;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
async handleGetCoolingThresholdTemperature() {
|
|
378
|
+
try {
|
|
379
|
+
const value = await this.getTemperature();
|
|
380
|
+
return value;
|
|
381
|
+
}
|
|
382
|
+
catch (cause) {
|
|
383
|
+
const error = new Error(`Failed to handle get cooling threshold temperature: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
384
|
+
this.platform.log.error(`[${this.accessory.displayName}] ${error.message}`);
|
|
385
|
+
throw error;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
async handleSetCoolingThresholdTemperature(value) {
|
|
389
|
+
try {
|
|
390
|
+
const targetTemperature = Number.parseInt(value, 10);
|
|
391
|
+
await this.setTemperature(targetTemperature);
|
|
392
|
+
}
|
|
393
|
+
catch (cause) {
|
|
394
|
+
const error = new Error(`Failed to handle set cooling threshold temperature: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
395
|
+
this.platform.log.error(`[${this.accessory.displayName}] ${error.message}`);
|
|
396
|
+
throw error;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
async handleGetRotationSpeed() {
|
|
400
|
+
try {
|
|
401
|
+
const value = await this.getFanSetting();
|
|
402
|
+
switch (value) {
|
|
403
|
+
case FanSetting.AUTO:
|
|
404
|
+
return 0;
|
|
405
|
+
case FanSetting.LOW:
|
|
406
|
+
return 33;
|
|
407
|
+
case FanSetting.MED:
|
|
408
|
+
return 66;
|
|
409
|
+
case FanSetting.HIGH:
|
|
410
|
+
return 100;
|
|
411
|
+
default:
|
|
412
|
+
throw new Error(`Unknown fan setting: ${value}`);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
catch (cause) {
|
|
416
|
+
const error = new Error(`Failed to handle get fan setting: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
417
|
+
this.platform.log.error(`[${this.accessory.displayName}] ${error.message}`);
|
|
418
|
+
throw error;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
async handleSetRotationSpeed(value) {
|
|
422
|
+
try {
|
|
423
|
+
const speed = value;
|
|
424
|
+
// AUTO
|
|
425
|
+
if (speed === 0) {
|
|
426
|
+
await this.setFanSetting(FanSetting.AUTO);
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
// LOW
|
|
430
|
+
if (speed <= 33) {
|
|
431
|
+
await this.setFanSetting(FanSetting.LOW);
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
// MED
|
|
435
|
+
if (speed <= 66) {
|
|
436
|
+
await this.setFanSetting(FanSetting.MED);
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
// HIGH
|
|
440
|
+
await this.setFanSetting(FanSetting.HIGH);
|
|
441
|
+
}
|
|
442
|
+
catch (cause) {
|
|
443
|
+
const error = new Error(`Failed to handle set fan setting: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
444
|
+
this.platform.log.error(`[${this.accessory.displayName}] ${error.message}`);
|
|
445
|
+
throw error;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
async handleGetTemperatureDisplayUnits() {
|
|
449
|
+
try {
|
|
450
|
+
const value = await this.getTemperatureDisplayUnits();
|
|
451
|
+
return value === TemperatureUnit.FAHRENHEIT
|
|
452
|
+
? this.platform.Characteristic.TemperatureDisplayUnits.FAHRENHEIT
|
|
453
|
+
: this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS;
|
|
454
|
+
}
|
|
455
|
+
catch (cause) {
|
|
456
|
+
const error = new Error(`Failed to handle get temperature display units: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
457
|
+
this.platform.log.error(`[${this.accessory.displayName}] ${error.message}`);
|
|
458
|
+
throw error;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
async handleSetTemperatureDisplayUnits(value) {
|
|
462
|
+
try {
|
|
463
|
+
const temperatureUnit = value === this.platform.Characteristic.TemperatureDisplayUnits.FAHRENHEIT
|
|
464
|
+
? TemperatureUnit.FAHRENHEIT
|
|
465
|
+
: TemperatureUnit.CELSIUS;
|
|
466
|
+
await this.setTemperatureDisplayUnits(temperatureUnit);
|
|
467
|
+
}
|
|
468
|
+
catch (cause) {
|
|
469
|
+
const error = new Error(`Failed to handle set temperature display units: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
470
|
+
this.platform.log.error(`[${this.accessory.displayName}] ${error.message}`);
|
|
471
|
+
throw error;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
async handleGetFilterChangeIndication() {
|
|
475
|
+
try {
|
|
476
|
+
const value = await this.getFilterStatus();
|
|
477
|
+
return value === FilterStatus.OK
|
|
478
|
+
? this.platform.Characteristic.FilterChangeIndication.FILTER_OK
|
|
479
|
+
: this.platform.Characteristic.FilterChangeIndication.CHANGE_FILTER;
|
|
480
|
+
}
|
|
481
|
+
catch (cause) {
|
|
482
|
+
const error = new Error(`Failed to handle get filter change indication: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
483
|
+
this.platform.log.error(`[${this.accessory.displayName}] ${error.message}`);
|
|
484
|
+
throw error;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
async handleGetOperationMode(mode) {
|
|
488
|
+
try {
|
|
489
|
+
const value = await this.getOperationMode();
|
|
490
|
+
return value === mode;
|
|
491
|
+
}
|
|
492
|
+
catch (cause) {
|
|
493
|
+
const error = new Error(`Failed to handle get operation mode ${mode}: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
494
|
+
this.platform.log.error(`[${this.accessory.displayName}] ${error.message}`);
|
|
495
|
+
throw error;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
async handleSetOperationMode(mode, value) {
|
|
499
|
+
try {
|
|
500
|
+
const [powerState, currentOperationMode] = await Promise.all([
|
|
501
|
+
this.getPowerState(),
|
|
502
|
+
this.getOperationMode(),
|
|
503
|
+
]);
|
|
504
|
+
// turn on the Air Conditioner if it's currently off
|
|
505
|
+
if (value && powerState === PowerState.OFF) {
|
|
506
|
+
await this.setPowerState(PowerState.ON);
|
|
507
|
+
// Keep Active in sync
|
|
508
|
+
this.heaterCoolerSvc.updateCharacteristic(this.platform.Characteristic.Active, this.platform.Characteristic.Active.ACTIVE);
|
|
509
|
+
// Keep CurrentHeaterCoolerState in sync
|
|
510
|
+
this.heaterCoolerSvc.updateCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState, this.platform.Characteristic.CurrentHeaterCoolerState.COOLING);
|
|
511
|
+
// Keep TargetHeaterCoolerState in sync
|
|
512
|
+
this.heaterCoolerSvc.updateCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState, this.platform.Characteristic.TargetHeaterCoolerState.COOL);
|
|
513
|
+
// turn off the Air Conditioner if the user turned off the current mode
|
|
514
|
+
}
|
|
515
|
+
else if (!value && currentOperationMode === mode && powerState === PowerState.ON) {
|
|
516
|
+
await this.setPowerState(PowerState.OFF);
|
|
517
|
+
// Keep Active in sync
|
|
518
|
+
this.heaterCoolerSvc.updateCharacteristic(this.platform.Characteristic.Active, this.platform.Characteristic.Active.INACTIVE);
|
|
519
|
+
// Keep CurrentHeaterCoolerState in sync
|
|
520
|
+
this.heaterCoolerSvc.updateCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState, this.platform.Characteristic.CurrentHeaterCoolerState.INACTIVE);
|
|
521
|
+
}
|
|
522
|
+
if (value) {
|
|
523
|
+
await this.setOperationMode(mode);
|
|
524
|
+
}
|
|
525
|
+
// switch the rest off
|
|
526
|
+
for (const m of Object.values(OperationMode)) {
|
|
527
|
+
this.modeSwitchSvc[m].updateCharacteristic(this.platform.Characteristic.On, m === mode);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
catch (cause) {
|
|
531
|
+
const error = new Error(`Failed to handle set operation mode ${mode}: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
532
|
+
this.platform.log.error(`[${this.accessory.displayName}] ${error.message}`);
|
|
533
|
+
throw error;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
// Refresh state
|
|
537
|
+
async refreshState() {
|
|
538
|
+
try {
|
|
539
|
+
// active
|
|
540
|
+
this.heaterCoolerSvc.updateCharacteristic(this.platform.Characteristic.Active, await this.handleGetActive());
|
|
541
|
+
// Current mode
|
|
542
|
+
this.heaterCoolerSvc.updateCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState, await this.handleGetCurrentHeaterCoolerState());
|
|
543
|
+
// Target mode
|
|
544
|
+
this.heaterCoolerSvc.updateCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState, await this.handleGetTargetHeaterCoolerState());
|
|
545
|
+
// Ambient temp
|
|
546
|
+
this.heaterCoolerSvc.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, await this.handleGetCurrentTemperature());
|
|
547
|
+
// Target temperature
|
|
548
|
+
this.heaterCoolerSvc.updateCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature, await this.handleGetCoolingThresholdTemperature());
|
|
549
|
+
// Rotation speed
|
|
550
|
+
this.heaterCoolerSvc.updateCharacteristic(this.platform.Characteristic.RotationSpeed, await this.handleGetRotationSpeed());
|
|
551
|
+
// Display units
|
|
552
|
+
this.heaterCoolerSvc.updateCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits, await this.handleGetTemperatureDisplayUnits());
|
|
553
|
+
// Filter
|
|
554
|
+
this.heaterCoolerSvc.updateCharacteristic(this.platform.Characteristic.FilterChangeIndication, await this.handleGetFilterChangeIndication());
|
|
555
|
+
// Modes
|
|
556
|
+
for (const mode of Object.values(OperationMode)) {
|
|
557
|
+
this.modeSwitchSvc[mode].updateCharacteristic(this.platform.Characteristic.On, await this.handleGetOperationMode(mode));
|
|
558
|
+
}
|
|
559
|
+
this.platform.log.debug(`[${this.accessory.displayName}] Refreshed state`);
|
|
560
|
+
}
|
|
561
|
+
catch (cause) {
|
|
562
|
+
const error = new Error(`Failed to refresh state for ${this.accessory.displayName}: ${cause instanceof Error ? cause.message : 'An unknown error occurred'}`, { cause });
|
|
563
|
+
this.platform.log.error(`[${this.accessory.displayName}] ${error.message}`);
|
|
564
|
+
throw error;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
// Helpers
|
|
568
|
+
fahrenheitToCelsius(fahrenheit) {
|
|
569
|
+
return (fahrenheit - 32) * 5 / 9;
|
|
570
|
+
}
|
|
571
|
+
celsiusToFahrenheit(celsius) {
|
|
572
|
+
return (celsius * 9 / 5) + 32;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
//# sourceMappingURL=airConditioner.js.map
|