homebridge-gree-ac 2.2.2-beta.5 → 2.2.2-beta.6

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 (45) hide show
  1. package/CHANGELOG.md +8 -4
  2. package/LICENSE +175 -175
  3. package/README.md +511 -500
  4. package/config.schema.json +520 -509
  5. package/dist/commands.d.ts +35 -160
  6. package/dist/commands.js +160 -162
  7. package/dist/commands.js.map +1 -1
  8. package/dist/crypto.d.ts +10 -11
  9. package/dist/crypto.js +28 -33
  10. package/dist/crypto.js.map +1 -1
  11. package/dist/index.d.ts +6 -7
  12. package/dist/index.js +8 -6
  13. package/dist/index.js.map +1 -1
  14. package/dist/platform.d.ts +47 -43
  15. package/dist/platform.js +585 -549
  16. package/dist/platform.js.map +1 -1
  17. package/dist/platformAccessory.d.ts +108 -102
  18. package/dist/platformAccessory.js +1763 -1726
  19. package/dist/platformAccessory.js.map +1 -1
  20. package/dist/settings.d.ts +72 -113
  21. package/dist/settings.js +97 -103
  22. package/dist/settings.js.map +1 -1
  23. package/dist/tsAccessory.d.ts +32 -34
  24. package/dist/tsAccessory.js +69 -71
  25. package/dist/tsAccessory.js.map +1 -1
  26. package/dist/version.d.ts +1 -2
  27. package/dist/version.js +2 -5
  28. package/dist/version.js.map +1 -1
  29. package/greedevice.jpg +0 -0
  30. package/greedevinfo.jpg +0 -0
  31. package/greemac.jpg +0 -0
  32. package/ha_fan.jpg +0 -0
  33. package/ha_settings.jpg +0 -0
  34. package/package.json +56 -52
  35. package/uiconfig.jpg +0 -0
  36. package/uiconfigcustdef.jpg +0 -0
  37. package/uiconfigmin.jpg +0 -0
  38. package/dist/commands.d.ts.map +0 -1
  39. package/dist/crypto.d.ts.map +0 -1
  40. package/dist/index.d.ts.map +0 -1
  41. package/dist/platform.d.ts.map +0 -1
  42. package/dist/platformAccessory.d.ts.map +0 -1
  43. package/dist/settings.d.ts.map +0 -1
  44. package/dist/tsAccessory.d.ts.map +0 -1
  45. package/dist/version.d.ts.map +0 -1
@@ -1,1727 +1,1764 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.GreeAirConditioner = void 0;
7
- const dgram_1 = __importDefault(require("dgram"));
8
- const settings_1 = require("./settings");
9
- const tsAccessory_1 = require("./tsAccessory");
10
- const crypto_1 = __importDefault(require("./crypto"));
11
- const commands_1 = __importDefault(require("./commands"));
12
- /**
13
- * Platform Accessory
14
- * An instance of this class is created for each accessory your platform registers
15
- * Each accessory may expose multiple services of different service types.
16
- */
17
- class GreeAirConditioner {
18
- constructor(platform, accessory, deviceConfig, tsAccessoryMac) {
19
- var _a;
20
- this.platform = platform;
21
- this.accessory = accessory;
22
- this.deviceConfig = deviceConfig;
23
- this.tsAccessoryMac = tsAccessoryMac;
24
- this.tsAccessory = null;
25
- this.powerPending = -1;
26
- this.modePending = -1;
27
- // device communication functions
28
- this.handleMessage = (msg, rinfo) => {
29
- var _a;
30
- if (this.accessory.context.device.address === rinfo.address) {
31
- this.platform.log.debug(`[${this.getDeviceLabel()}] handleMessage -> %s`, msg.toString());
32
- this.platform.log.debug(`[${this.getDeviceLabel()}] handleMessage -> Encryption version: %i`, this.accessory.context.device.encryptionVersion);
33
- const message = JSON.parse(msg.toString());
34
- if (!message.pack) {
35
- this.platform.log.debug(`[${this.getDeviceLabel()}] handleMessage - Unknown message: %j`, message);
36
- this.platform.log.warn(`[${this.getDeviceLabel()}] Warning: handleMessage - Unknown response from device`);
37
- return;
38
- }
39
- let pack;
40
- if (this.accessory.context.device.encryptionVersion === 1) {
41
- pack = crypto_1.default.decrypt_v1(message.pack, message.i === 1 ? undefined : this.key);
42
- }
43
- else if (this.accessory.context.device.encryptionVersion === 2 && message.tag !== undefined) {
44
- pack = crypto_1.default.decrypt_v2(message.pack, message.tag, message.i === 1 ? undefined : this.key);
45
- }
46
- else {
47
- this.platform.log.debug(`[${this.getDeviceLabel()}] handleMessage - Unknown message: %j`, message);
48
- this.platform.log.warn(`[${this.getDeviceLabel()}] Warning: handleMessage - Unknown response from device`);
49
- return;
50
- }
51
- this.platform.log.debug(`[${this.getDeviceLabel()}] handleMessage - Package -> %j`, pack);
52
- switch (pack.t.toLowerCase()) {
53
- case 'bindok': // package type is binding confirmation
54
- if (!this.accessory.bound) {
55
- this.platform.log.debug(`[${this.getDeviceLabel()}] Device binding in progress`);
56
- this.key = pack.key;
57
- this.initAccessory();
58
- this.accessory.bound = true;
59
- this.platform.log.success(`[${this.getDeviceLabel()}] Device is bound -> ${pack.mac} (`, ((_a = this.accessory.context.device.uid) !== null && _a !== void 0 ? _a : 0).toString(), ')');
60
- this.platform.log.debug(`[${this.getDeviceLabel()}] Device key -> ${this.key}`);
61
- this.requestDeviceStatus();
62
- setInterval(this.requestDeviceStatus.bind(this), this.deviceConfig.statusUpdateInterval * 1000); // statusUpdateInterval in seconds
63
- }
64
- else {
65
- this.platform.log.debug(`[${this.getDeviceLabel()}] Binding response received from already bound device`);
66
- }
67
- break;
68
- case 'dat': // package type is device status
69
- if (this.accessory.bound) {
70
- let invalidTempFromDevice = false;
71
- pack.cols.forEach((col, i) => {
72
- if (col === commands_1.default.temperature.code && (pack.dat[i] <= 0 || pack.dat[i] >= 100)) {
73
- // temperature value outside of valid range (1-99 -> -39°C - +59°C) should be ignored (means: no sensor data)
74
- invalidTempFromDevice = true;
75
- }
76
- else {
77
- this.status[col] = pack.dat[i];
78
- }
79
- if (col === commands_1.default.power.code) {
80
- // power status received -> no more power change pending state
81
- this.powerPending = -1;
82
- }
83
- if (col === commands_1.default.mode.code) {
84
- // mode status received -> no more mode change pending state
85
- this.modePending = -1;
86
- }
87
- if (col === commands_1.default.buzzer.code && pack.dat[i] !== commands_1.default.buzzer.value.off && pack.dat[i] !== commands_1.default.buzzer.value.on &&
88
- this.silentTimeRanges !== undefined) {
89
- // invalid buzzer status -> disable silent time
90
- this.platform.log.warn(`[${this.getDeviceLabel()}] Warning: Device does not support command muting`);
91
- delete this.silentTimeRanges;
92
- }
93
- });
94
- if (this.silentTimeRanges !== undefined && pack.cols.find((col) => col === commands_1.default.buzzer.code) === undefined) {
95
- // status pack does not contain buzzer status -> disable silent time
96
- this.platform.log.warn(`[${this.getDeviceLabel()}] Warning: Device does not support command muting`);
97
- delete this.silentTimeRanges;
98
- }
99
- this.platform.log.debug(`[${this.getDeviceLabel()}] Device status -> %j`, this.status);
100
- if (!pack.cols.includes(commands_1.default.temperature.code) || invalidTempFromDevice) {
101
- // temperature is not accessible -> use targetTemperature
102
- const targetTemp = this.status[commands_1.default.targetTemperature.code] !== undefined ?
103
- this.status[commands_1.default.targetTemperature.code] : 25; // use default if target temperature is also unknown
104
- this.status[commands_1.default.temperature.code] = targetTemp + this.deviceConfig.sensorOffset;
105
- this.platform.log.debug(`[${this.getDeviceLabel()}] Current temperature not available`, '- Threshold temperature is used as current (' + commands_1.default.targetTemperature.code + '->' + commands_1.default.temperature.code + ')');
106
- if (this.TemperatureSensor !== undefined) {
107
- this.accessory.removeService(this.TemperatureSensor);
108
- this.TemperatureSensor = undefined;
109
- this.platform.log.debug(`[${this.getDeviceLabel()}] temperature is not accessible -> Temperature Sensor removed`);
110
- }
111
- }
112
- this.updateStatus(pack.cols);
113
- }
114
- break;
115
- case 'res': // package type is response
116
- if (this.accessory.bound) {
117
- this.platform.log.debug(`[${this.getDeviceLabel()}] Device response`, pack.opt, pack.p || pack.val);
118
- const updatedParams = [];
119
- pack.opt.forEach((opt, i) => {
120
- const value = pack.p !== undefined ? pack.p[i] : pack.val[i];
121
- if (this.status[opt] !== value) {
122
- const cmd = this.getKeyName(commands_1.default, opt, 'code');
123
- const oldval = this.getKeyName(commands_1.default[cmd].value, this.status[opt]) || this.status[opt];
124
- const newval = this.getKeyName(commands_1.default[cmd].value, value) || value;
125
- updatedParams.push(`${cmd}: ${oldval} -> ${newval}`);
126
- }
127
- this.status[opt] = value;
128
- if (opt === commands_1.default.power.code) {
129
- // response to power command -> no more power change pending state
130
- this.powerPending = -1;
131
- }
132
- if (opt === commands_1.default.mode.code) {
133
- // response to mode command -> no more mode change pending state
134
- this.modePending = -1;
135
- }
136
- });
137
- if (updatedParams.length > 0) {
138
- this.platform.log.info(`[${this.getDeviceLabel()}] Device updated (%j)`, updatedParams);
139
- }
140
- this.updateStatus(pack.opt);
141
- }
142
- break;
143
- default:
144
- this.platform.log.debug(`[${this.getDeviceLabel()}] handleMessage - Unknown message: %j`, message);
145
- this.platform.log.warn(`[${this.getDeviceLabel()}] Warning: handleMessage - Unknown response from device`);
146
- break;
147
- }
148
- }
149
- };
150
- // platform, accessory and service initialization is implemented in a separate funcion (initAccessory), because
151
- // it should be made only on successful binding with network device
152
- this.platform.log.debug(`[${this.getDeviceLabel()}] deviceConfig -> %j`, deviceConfig);
153
- // calculate silent time ranges
154
- if (deviceConfig.silentTimeRange) {
155
- const time1 = +(deviceConfig.silentTimeRange.substring(0, 5).replace(':', ''));
156
- const time2 = +(deviceConfig.silentTimeRange.substring(6).replace(':', ''));
157
- if (time1 < time2) {
158
- this.silentTimeRanges = [[time1, time2 < 2400 ? time2 + 1 : time2]];
159
- }
160
- else if (time1 > time2) {
161
- this.silentTimeRanges = [[time1, 2400], [0, time2 < 2400 ? time2 + 1 : time2]];
162
- }
163
- this.platform.log.debug(`[${this.getDeviceLabel()}] silentTimeRanges:`, (_a = this.silentTimeRanges) !== null && _a !== void 0 ? _a : 'Zero length silentTimeRange is defined - ignoring');
164
- }
165
- else {
166
- this.platform.log.debug(`[${this.getDeviceLabel()}] silentTimeRanges: No silentTimeRange is defined`);
167
- }
168
- // initialize communication with device
169
- this.status = {};
170
- this.socket = dgram_1.default.createSocket({ type: 'udp4', reuseAddr: true });
171
- this.socket.on('error', (err) => {
172
- this.platform.log.error(`[${this.getDeviceLabel()}] Network - Error:`, err.message);
173
- });
174
- this.socket.on('message', this.handleMessage);
175
- this.socket.on('close', () => {
176
- this.platform.log.error(`[${this.getDeviceLabel()}] Network - Connection closed`);
177
- });
178
- if (this.platform.ports.indexOf(this.deviceConfig.port || 0) >= 0) {
179
- this.platform.log.warn(`[${this.getDeviceLabel()}] Warning: Configured port (%i) is already used - replacing with auto assigned port`, this.deviceConfig.port);
180
- this.deviceConfig.port = undefined;
181
- }
182
- this.socket.bind(this.deviceConfig.port, undefined, () => {
183
- this.platform.log.info(`[${this.getDeviceLabel()}] Device handler is listening on UDP port %d`, this.socket.address().port);
184
- this.platform.ports.push(this.socket.address().port);
185
- this.socket.setBroadcast(false);
186
- this.sendBindRequest();
187
- setTimeout(this.checkBindingStatus.bind(this, 1), settings_1.BINDING_TIMEOUT);
188
- });
189
- }
190
- initCharacteristics() {
191
- // these characteristic properties are not updated by HomeKit, they are initialized only once
192
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
193
- // Cooling Threshold Temperature Characteristic
194
- // minValue / maxValue usually generates error messages in debug log:
195
- // "Characteristic 'Cooling Threshold Temperature': characteristic was supplied illegal value ..."
196
- // this is not a problem, this is information only that GREE is more restricitive than Apple's default
197
- (_a = this.HeaterCooler) === null || _a === void 0 ? void 0 : _a.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).setProps({
198
- minStep: this.deviceConfig.temperatureStepSize,
199
- minValue: Math.max(this.deviceConfig.minimumTargetTemperature, settings_1.TEMPERATURE_LIMITS.coolingMinimum),
200
- maxValue: Math.min(this.deviceConfig.maximumTargetTemperature, settings_1.TEMPERATURE_LIMITS.coolingMaximum),
201
- });
202
- this.platform.log.debug(`[${this.getDeviceLabel()}] CoolingThresholdTemperature - minValue: %s, maxValue: %s, minStep: %s`, (_c = (_b = this.HeaterCooler) === null || _b === void 0 ? void 0 : _b.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).props.minValue) === null || _c === void 0 ? void 0 : _c.toString(), (_e = (_d = this.HeaterCooler) === null || _d === void 0 ? void 0 : _d.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).props.maxValue) === null || _e === void 0 ? void 0 : _e.toString(), (_g = (_f = this.HeaterCooler) === null || _f === void 0 ? void 0 : _f.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).props.minStep) === null || _g === void 0 ? void 0 : _g.toString());
203
- // Heating Threshold Temperature Characteristic
204
- // minValue / maxValue usually generates error messages in debug log:
205
- // "Characteristic 'Heating Threshold Temperature': characteristic was supplied illegal value ..."
206
- // this is not a problem, this is information only that GREE is more restricitive than Apple's default
207
- (_h = this.HeaterCooler) === null || _h === void 0 ? void 0 : _h.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).setProps({
208
- minStep: this.deviceConfig.temperatureStepSize,
209
- minValue: Math.max(this.deviceConfig.minimumTargetTemperature, settings_1.TEMPERATURE_LIMITS.heatingMinimum),
210
- maxValue: Math.min(this.deviceConfig.maximumTargetTemperature, settings_1.TEMPERATURE_LIMITS.heatingMaximum),
211
- });
212
- this.platform.log.debug(`[${this.getDeviceLabel()}] HeatingThresholdTemperature - minValue: %s, maxValue: %s, minStep: %s`, (_k = (_j = this.HeaterCooler) === null || _j === void 0 ? void 0 : _j.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).props.minValue) === null || _k === void 0 ? void 0 : _k.toString(), (_m = (_l = this.HeaterCooler) === null || _l === void 0 ? void 0 : _l.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).props.maxValue) === null || _m === void 0 ? void 0 : _m.toString(), (_p = (_o = this.HeaterCooler) === null || _o === void 0 ? void 0 : _o.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).props.minStep) === null || _p === void 0 ? void 0 : _p.toString());
213
- // Rotation Speed Characteristic
214
- (_q = this.HeaterCooler) === null || _q === void 0 ? void 0 : _q.getCharacteristic(this.platform.Characteristic.RotationSpeed).setProps({
215
- minValue: 0,
216
- maxValue: this.deviceConfig.speedSteps + 3,
217
- minStep: 1
218
- });
219
- this.platform.log.debug(`[${this.getDeviceLabel()}] RotationSpeed - minValue: %s, maxValue: %s, minStep: %s`, (_s = (_r = this.HeaterCooler) === null || _r === void 0 ? void 0 : _r.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.minValue) === null || _s === void 0 ? void 0 : _s.toString(), (_u = (_t = this.HeaterCooler) === null || _t === void 0 ? void 0 : _t.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.maxValue) === null || _u === void 0 ? void 0 : _u.toString(), (_w = (_v = this.HeaterCooler) === null || _v === void 0 ? void 0 : _v.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.minStep) === null || _w === void 0 ? void 0 : _w.toString());
220
- }
221
- // All platform, accessory and service initialization is made in initAccessory function
222
- initAccessory() {
223
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
224
- // register accessory in homebridge by api if not registered before
225
- if (!this.accessory.registered) {
226
- this.platform.log.debug(`[${this.getDeviceLabel()}] Registering new accessory in homebridge:`, this.accessory.context.device.mac, this.accessory.UUID);
227
- this.platform.api.registerPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, [this.accessory]);
228
- // set static accessory information
229
- this.accessory.getService(this.platform.Service.AccessoryInformation)
230
- .setCharacteristic(this.platform.Characteristic.Manufacturer, this.accessory.context.device.brand || 'Gree')
231
- .setCharacteristic(this.platform.Characteristic.SerialNumber, this.accessory.context.device.mac)
232
- .setCharacteristic(this.platform.Characteristic.Model, ((_a = this.deviceConfig) === null || _a === void 0 ? void 0 : _a.model) || this.accessory.context.device.model || this.accessory.context.device.name || 'Air Conditioner')
233
- .setCharacteristic(this.platform.Characteristic.HardwareRevision, this.accessory.context.device.ver ?
234
- this.accessory.context.device.ver.substring(this.accessory.context.device.ver.lastIndexOf('V') + 1) : '1.0.0')
235
- .setCharacteristic(this.platform.Characteristic.Name, this.accessory.displayName);
236
- // get the HeaterCooler service if it exists, otherwise create a new HeaterCooler service
237
- // we don't use subtype because we add only one service with this type
238
- this.HeaterCooler = this.accessory.getService(this.platform.Service.HeaterCooler) ||
239
- this.accessory.addService(this.platform.Service.HeaterCooler, this.accessory.displayName, undefined);
240
- // set static characeristics
241
- this.initCharacteristics();
242
- }
243
- if (this.tsAccessoryMac) {
244
- this.tsAccessory = new tsAccessory_1.GreeAirConditionerTS(this.platform, this.platform.getAccessory(this.accessory.context.device.mac + '_ts'));
245
- }
246
- // init TargetHeaterCoolerState default value
247
- if (!this.accessory.context.TargetHeaterCoolerState) {
248
- this.accessory.context.TargetHeaterCoolerState =
249
- ((_b = this.HeaterCooler) === null || _b === void 0 ? void 0 : _b.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState).value) ||
250
- this.platform.Characteristic.TargetHeaterCoolerState.AUTO;
251
- }
252
- // init HeaterCoolerRotationSpeed default value
253
- if (this.accessory.context.HeaterCoolerRotationSpeed === undefined) {
254
- this.accessory.context.HeaterCoolerRotationSpeed =
255
- ((_c = this.HeaterCooler) === null || _c === void 0 ? void 0 : _c.getCharacteristic(this.platform.Characteristic.RotationSpeed).value) ||
256
- ((_d = this.HeaterCooler) === null || _d === void 0 ? void 0 : _d.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.minValue) || 0;
257
- }
258
- // set accessory information
259
- this.accessory.getService(this.platform.Service.AccessoryInformation)
260
- .setCharacteristic(this.platform.Characteristic.FirmwareRevision, this.accessory.context.device.hid && this.accessory.context.device.hid.lastIndexOf('V') >= 0 &&
261
- this.accessory.context.device.hid.lastIndexOf('V') < this.accessory.context.device.hid.lastIndexOf('.') ?
262
- this.accessory.context.device.hid.substring(this.accessory.context.device.hid.lastIndexOf('V') + 1, this.accessory.context.device.hid.lastIndexOf('.')) : '1.0.0');
263
- // get the HeaterCooler service if it exists, otherwise create a new HeaterCooler service
264
- // we don't use subtype because we add only one service with this type
265
- if (!this.HeaterCooler) {
266
- this.HeaterCooler = this.accessory.getService(this.platform.Service.HeaterCooler);
267
- if (!this.HeaterCooler) {
268
- this.platform.log.debug(`[${this.getDeviceLabel()}] HeaterCooler service doesn't exist - adding service`);
269
- this.HeaterCooler = this.accessory.addService(this.platform.Service.HeaterCooler, this.accessory.displayName);
270
- // set static characeristics
271
- this.initCharacteristics();
272
- }
273
- }
274
- // TemperatureSensor service
275
- // we don't use subtype because we add only one service with this type
276
- const tss = this.accessory.getService(this.platform.Service.TemperatureSensor);
277
- if (this.deviceConfig.temperatureSensor === settings_1.TS_TYPE.child) {
278
- if (tss) {
279
- this.TemperatureSensor = tss;
280
- }
281
- else {
282
- this.platform.log.debug(`[${this.getDeviceLabel()}] Add Temperature Sensor child service`);
283
- this.TemperatureSensor =
284
- this.accessory.addService(this.platform.Service.TemperatureSensor, 'Temperature Sensor ' + this.HeaterCooler.displayName);
285
- }
286
- }
287
- else {
288
- this.platform.log.debug(`[${this.getDeviceLabel()}] Temperature Sensor child service not allowed`, (tss === null || tss === void 0 ? void 0 : tss.displayName) !== undefined ? '(' + (tss === null || tss === void 0 ? void 0 : tss.displayName) + ')' : '');
289
- if (tss !== undefined) {
290
- this.platform.log.debug(`[${this.getDeviceLabel()}] Remove Temperature Sensor child service (%s)`, tss.displayName);
291
- this.accessory.removeService(tss);
292
- }
293
- }
294
- // Fan service
295
- // we don't use subtype because we add only one service with this type
296
- const fs = this.accessory.getService(this.platform.Service.Fanv2);
297
- if (this.deviceConfig.fanControlEnabled) {
298
- if (fs) {
299
- this.Fan = fs;
300
- }
301
- else {
302
- this.platform.log.debug(`[${this.getDeviceLabel()}] Add Fan child service`);
303
- this.Fan =
304
- this.accessory.addService(this.platform.Service.Fanv2, 'Fan ' + this.HeaterCooler.displayName);
305
- // set static characeristics
306
- (_e = this.Fan) === null || _e === void 0 ? void 0 : _e.getCharacteristic(this.platform.Characteristic.RotationSpeed).setProps({
307
- minValue: 0,
308
- maxValue: 100,
309
- minStep: 100 / (this.deviceConfig.speedSteps + 1)
310
- });
311
- this.platform.log.debug(`[${this.getDeviceLabel()}] Fan RotationSpeed - minValue: %s, maxValue: %s, minStep: %s`, (_g = (_f = this.Fan) === null || _f === void 0 ? void 0 : _f.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.minValue) === null || _g === void 0 ? void 0 : _g.toString(), (_j = (_h = this.Fan) === null || _h === void 0 ? void 0 : _h.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.maxValue) === null || _j === void 0 ? void 0 : _j.toString(), (_l = (_k = this.Fan) === null || _k === void 0 ? void 0 : _k.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.minStep) === null || _l === void 0 ? void 0 : _l.toString());
312
- }
313
- }
314
- else {
315
- this.platform.log.debug(`[${this.getDeviceLabel()}] Fan child service not allowed`, (fs === null || fs === void 0 ? void 0 : fs.displayName) !== undefined ? '(' + (fs === null || fs === void 0 ? void 0 : fs.displayName) + ')' : '');
316
- if (fs !== undefined) {
317
- this.platform.log.debug(`[${this.getDeviceLabel()}] Remove Fan child service (%s)`, fs.displayName);
318
- this.accessory.removeService(fs);
319
- }
320
- }
321
- this.HeaterCooler.setPrimaryService(true);
322
- (_m = this.TemperatureSensor) === null || _m === void 0 ? void 0 : _m.setPrimaryService(false);
323
- (_o = this.Fan) === null || _o === void 0 ? void 0 : _o.setPrimaryService(false);
324
- this.platform.api.updatePlatformAccessories([this.accessory]);
325
- // each service must implement at-minimum the "required characteristics" for the given service type
326
- // see https://developers.homebridge.io/#/service/HeaterCooler
327
- // register handlers for the Active Characteristic
328
- this.HeaterCooler.getCharacteristic(this.platform.Characteristic.Active)
329
- .onSet(this.setActive.bind(this))
330
- .onGet(this.getActive.bind(this));
331
- (_p = this.Fan) === null || _p === void 0 ? void 0 : _p.getCharacteristic(this.platform.Characteristic.Active).onSet(this.setFanActive.bind(this)).onGet(this.getFanActive.bind(this));
332
- // register handlers for the Current Heater-Cooler State Characteristic
333
- this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState)
334
- .onGet(this.getCurrentHeaterCoolerState.bind(this));
335
- // register handlers for the Current Fan State Characteristic
336
- (_q = this.Fan) === null || _q === void 0 ? void 0 : _q.getCharacteristic(this.platform.Characteristic.CurrentFanState).onGet(this.getCurrentFanState.bind(this));
337
- // register handlers for the Target Heater-Cooler State Characteristic
338
- this.HeaterCooler.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState)
339
- .onGet(this.getTargetHeaterCoolerState.bind(this))
340
- .onSet(this.setTargetHeaterCoolerState.bind(this));
341
- // register handlers for the Current Temperature Characteristic
342
- this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CurrentTemperature)
343
- .onGet(this.getCurrentTemperature.bind(this, 'Heater-Cooler'));
344
- (_r = this.TemperatureSensor) === null || _r === void 0 ? void 0 : _r.getCharacteristic(this.platform.Characteristic.CurrentTemperature).onGet(this.getCurrentTemperature.bind(this, 'Temperature Sensor'));
345
- // register handlers for the Cooling Threshold Temperature Characteristic
346
- this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature)
347
- .onGet(this.getTargetTemperature.bind(this, 'CoolingThresholdTemperature'))
348
- .onSet(this.setTargetTemperature.bind(this));
349
- // register handlers for the Heating Threshold Temperature Characteristic
350
- this.HeaterCooler.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature)
351
- .onGet(this.getTargetTemperature.bind(this, 'HeatingThresholdTemperature'))
352
- .onSet(this.setTargetTemperature.bind(this));
353
- // register handlers for the Temperature Display Units Characteristic
354
- this.HeaterCooler.getCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits)
355
- .onGet(this.getTemperatureDisplayUnits.bind(this))
356
- .onSet(this.setTemperatureDisplayUnits.bind(this));
357
- // register handlers for the Swing Mode Characteristic
358
- this.HeaterCooler.getCharacteristic(this.platform.Characteristic.SwingMode)
359
- .onGet(this.getSwingMode.bind(this))
360
- .onSet(this.setSwingMode.bind(this));
361
- (_s = this.Fan) === null || _s === void 0 ? void 0 : _s.getCharacteristic(this.platform.Characteristic.SwingMode).onGet(this.getSwingMode.bind(this)).onSet(this.setFanSwingMode.bind(this));
362
- // register handlers for the Rotation Speed Characteristic
363
- this.HeaterCooler.getCharacteristic(this.platform.Characteristic.RotationSpeed)
364
- .onGet(this.getRotationSpeed.bind(this))
365
- .onSet(this.setRotationSpeed.bind(this));
366
- (_t = this.Fan) === null || _t === void 0 ? void 0 : _t.getCharacteristic(this.platform.Characteristic.RotationSpeed).onGet(this.getFanRotationSpeed.bind(this)).onSet(this.setFanRotationSpeed.bind(this));
367
- // register handlers for the Name Characteristic
368
- this.HeaterCooler.getCharacteristic(this.platform.Characteristic.Name)
369
- .onGet(this.getName.bind(this));
370
- }
371
- // this function is a callback to check the status of binding after timeout period has ellapsed
372
- checkBindingStatus(bindNo) {
373
- if (!this.accessory.bound) {
374
- this.platform.log.debug(`[${this.getDeviceLabel()}] Device binding timeout`);
375
- switch (bindNo) {
376
- case 1: {
377
- // 1. timeout -> repeat bind request with alternate encryption version
378
- if (this.accessory.context.device.encryptionVersion === 1) {
379
- this.accessory.context.device.encryptionVersion = 2;
380
- }
381
- else {
382
- this.accessory.context.device.encryptionVersion = 1;
383
- }
384
- this.sendBindRequest();
385
- setTimeout(this.checkBindingStatus.bind(this, bindNo + 1), settings_1.BINDING_TIMEOUT);
386
- break;
387
- }
388
- default: {
389
- this.platform.log.error(`[${this.getDeviceLabel()}] Error: Device is not bound`, '(unknown device type or device is malfunctioning [turning the power supply off and on may help])', '- Restart homebridge when issue has fixed!');
390
- }
391
- }
392
- }
393
- }
394
- /**
395
- * Handle "SET" requests from HomeKit
396
- * These are sent when the user changes the state of an accessory
397
- */
398
- async setActive(value) {
399
- var _a, _b;
400
- const powerValue = (value === this.platform.Characteristic.Active.ACTIVE);
401
- this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler Active ->`, powerValue ? 'ACTIVE' : 'INACTIVE');
402
- this.power = powerValue;
403
- if (powerValue &&
404
- ((_a = this.Fan) === null || _a === void 0 ? void 0 : _a.getCharacteristic(this.platform.Characteristic.Active).value) === this.platform.Characteristic.Active.ACTIVE) {
405
- (_b = this.Fan) === null || _b === void 0 ? void 0 : _b.getCharacteristic(this.platform.Characteristic.Active).updateValue(this.platform.Characteristic.Active.INACTIVE);
406
- }
407
- }
408
- async setFanActive(value) {
409
- var _a, _b;
410
- const powerValue = (value === this.platform.Characteristic.Active.ACTIVE);
411
- this.platform.log.debug(`[${this.getDeviceLabel()}] Set Fan Active ->`, powerValue ? 'ACTIVE' : 'INACTIVE');
412
- this.fanpower = powerValue;
413
- if (powerValue &&
414
- ((_a = this.HeaterCooler) === null || _a === void 0 ? void 0 : _a.getCharacteristic(this.platform.Characteristic.Active).value) === this.platform.Characteristic.Active.ACTIVE) {
415
- (_b = this.HeaterCooler) === null || _b === void 0 ? void 0 : _b.getCharacteristic(this.platform.Characteristic.Active).updateValue(this.platform.Characteristic.Active.INACTIVE);
416
- }
417
- }
418
- async setTargetHeaterCoolerState(value) {
419
- let modeValue = commands_1.default.mode.value.auto;
420
- let logValue = 'AUTO';
421
- switch (value) {
422
- case this.platform.Characteristic.TargetHeaterCoolerState.COOL:
423
- modeValue = commands_1.default.mode.value.cool;
424
- logValue = 'COOL';
425
- break;
426
- case this.platform.Characteristic.TargetHeaterCoolerState.HEAT:
427
- modeValue = commands_1.default.mode.value.heat;
428
- logValue = 'HEAT';
429
- break;
430
- }
431
- this.platform.log.debug(`[${this.getDeviceLabel()}] Set TargetHeaterCoolerState ->`, logValue);
432
- this.mode = modeValue;
433
- this.accessory.context.TargetHeaterCoolerState = value;
434
- this.platform.api.updatePlatformAccessories([this.accessory]);
435
- }
436
- async setTargetTemperature(value) {
437
- this.platform.log.debug(`[${this.getDeviceLabel()}] Set ThresholdTemperature ->`, value);
438
- this.targetTemperature = value;
439
- }
440
- async setTemperatureDisplayUnits(value) {
441
- const logValue = (value === this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS) ? 'CELSIUS' : 'FAHRENHEIT';
442
- this.platform.log.debug(`[${this.getDeviceLabel()}] Set TemperatureDisplayUnits ->`, logValue);
443
- this.units = (value === this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS) ?
444
- commands_1.default.units.value.celsius : commands_1.default.units.value.fahrenheit;
445
- }
446
- async setSwingMode(value) {
447
- const logValue = (value === this.platform.Characteristic.SwingMode.SWING_ENABLED) ? 'ENABLED' : 'DISABLED';
448
- this.swingMode = (value === this.platform.Characteristic.SwingMode.SWING_ENABLED) ?
449
- commands_1.default.swingVertical.value.full : ([settings_1.MODIFY_VERTICAL_SWING_POSITION.overrideDefPowerOnOscDisable,
450
- settings_1.MODIFY_VERTICAL_SWING_POSITION.setPowerOnOscDisable].includes(this.deviceConfig.modifyVerticalSwingPosition ||
451
- settings_1.DEFAULT_DEVICE_CONFIG.modifyVerticalSwingPosition) ? this.deviceConfig.defaultVerticalSwing ||
452
- settings_1.DEFAULT_DEVICE_CONFIG.defaultVerticalSwing : settings_1.DEFAULT_DEVICE_CONFIG.defaultVerticalSwing);
453
- this.platform.log.debug(`[${this.getDeviceLabel()}] Set SwingMode ->`, logValue + (logValue === 'DISABLED' ?
454
- ` (Position: ${this.getKeyName(commands_1.default.swingVertical.value, this.swingMode)})` : ''));
455
- }
456
- async setFanSwingMode(value) {
457
- const logValue = (value === this.platform.Characteristic.SwingMode.SWING_ENABLED) ? 'ENABLED' : 'DISABLED';
458
- this.swingMode = (value === this.platform.Characteristic.SwingMode.SWING_ENABLED) ?
459
- commands_1.default.swingVertical.value.full : (this.deviceConfig.modifyVerticalSwingPosition ===
460
- settings_1.MODIFY_VERTICAL_SWING_POSITION.overrideDefPowerOnOscDisable ? this.deviceConfig.defaultVerticalSwing ||
461
- settings_1.DEFAULT_DEVICE_CONFIG.defaultVerticalSwing : (this.deviceConfig.modifyVerticalSwingPosition ===
462
- settings_1.MODIFY_VERTICAL_SWING_POSITION.setPowerOnOscDisable ? this.deviceConfig.defaultFanVerticalSwing ||
463
- settings_1.DEFAULT_DEVICE_CONFIG.defaultFanVerticalSwing : settings_1.DEFAULT_DEVICE_CONFIG.defaultFanVerticalSwing));
464
- this.platform.log.debug(`[${this.getDeviceLabel()}] Set Fan SwingMode ->`, logValue + (logValue === 'DISABLED' ?
465
- ` (Position: ${this.getKeyName(commands_1.default.swingVertical.value, this.swingMode)})` : ''));
466
- }
467
- async setRotationSpeed(value) {
468
- var _a;
469
- const maxSpeed = ((_a = this.HeaterCooler) === null || _a === void 0 ? void 0 : _a.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.maxValue) ||
470
- this.deviceConfig.speedSteps + 3;
471
- switch (value) {
472
- case 0: // inactive -> rotation speed change not needed
473
- return;
474
- case 1: // quiet
475
- this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler RotationSpeed ->`, value + ' (quiet)');
476
- this.quietMode = commands_1.default.quietMode.value.on;
477
- break;
478
- case 2: // auto
479
- this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler RotationSpeed ->`, value +
480
- ' (' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.auto) + ')');
481
- this.speed = commands_1.default.speed.value.auto;
482
- break;
483
- case 3: // low
484
- this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler RotationSpeed ->`, value +
485
- ' (' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.low) + ')');
486
- this.speed = commands_1.default.speed.value.low;
487
- break;
488
- case 4: // mediumLow / medium
489
- this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler RotationSpeed ->`, value + ' (' +
490
- this.getKeyName(commands_1.default.speed.value, (maxSpeed === 8) ? commands_1.default.speed.value.mediumLow : commands_1.default.speed.value.medium) + ')');
491
- this.speed = (maxSpeed === 8) ? commands_1.default.speed.value.mediumLow : commands_1.default.speed.value.medium;
492
- break;
493
- case 5: // medium / high
494
- this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler RotationSpeed ->`, value + ' (' +
495
- this.getKeyName(commands_1.default.speed.value, (maxSpeed === 8) ? commands_1.default.speed.value.medium : commands_1.default.speed.value.high) + ')');
496
- this.speed = (maxSpeed === 8) ? commands_1.default.speed.value.medium : commands_1.default.speed.value.high;
497
- break;
498
- case 6: // mediumHigh / powerful
499
- if (maxSpeed === 8) {
500
- // mediumHigh
501
- this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler RotationSpeed ->`, value +
502
- ' (' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.mediumHigh) + ')');
503
- this.speed = commands_1.default.speed.value.mediumHigh;
504
- }
505
- else {
506
- // powerful
507
- this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler RotationSpeed ->`, value + ' (powerful)');
508
- this.powerfulMode = commands_1.default.powerfulMode.value.on;
509
- }
510
- break;
511
- case 7: // high
512
- this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler RotationSpeed ->`, value +
513
- ' (' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.high) + ')');
514
- this.speed = commands_1.default.speed.value.high;
515
- break;
516
- case 8: // powerful
517
- this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler RotationSpeed ->`, value + ' (powerful)');
518
- this.powerfulMode = commands_1.default.powerfulMode.value.on;
519
- break;
520
- default: // auto
521
- this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler RotationSpeed ->`, value +
522
- ' (' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.auto) + ')');
523
- this.speed = commands_1.default.speed.value.auto;
524
- break;
525
- }
526
- this.accessory.context.HeaterCoolerRotationSpeed = value;
527
- this.platform.api.updatePlatformAccessories([this.accessory]);
528
- }
529
- async setFanRotationSpeed(value) {
530
- var _a, _b;
531
- if (value !== 0 &&
532
- ((_a = this.Fan) === null || _a === void 0 ? void 0 : _a.getCharacteristic(this.platform.Characteristic.Active).value) !== this.platform.Characteristic.Active.ACTIVE) {
533
- (_b = this.Fan) === null || _b === void 0 ? void 0 : _b.getCharacteristic(this.platform.Characteristic.Active).setValue(this.platform.Characteristic.Active.ACTIVE);
534
- }
535
- let logMsg = `[${this.getDeviceLabel()}] Set Fan RotationSpeed -> ${Math.round(value)}%`;
536
- switch (Math.round(value)) {
537
- case 0: // inactive -> rotation speed change not needed
538
- return;
539
- case 17: // low - 5 step model
540
- case 25: // low - 3 step model
541
- logMsg += ` (${this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.low)})`;
542
- this.speed = commands_1.default.speed.value.low;
543
- break;
544
- case 33: // mediumLow
545
- logMsg += ` (${this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.mediumLow)})`;
546
- this.speed = commands_1.default.speed.value.mediumLow;
547
- break;
548
- case 50: // medium
549
- logMsg += ` (${this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.medium)}) - ${Math.round(value)}%`;
550
- this.speed = commands_1.default.speed.value.medium;
551
- break;
552
- case 67: // mediumHigh
553
- logMsg += ` (${this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.mediumHigh)}) - ${Math.round(value)}%`;
554
- this.speed = commands_1.default.speed.value.mediumHigh;
555
- break;
556
- case 75: // high - 3 step model
557
- case 83: // high - 5 step model
558
- logMsg += ` (${this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.high)}) - ${Math.round(value)}%`;
559
- this.speed = commands_1.default.speed.value.high;
560
- break;
561
- default: // auto
562
- logMsg += ` (${this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.auto)}) - ${Math.round(value)}%`;
563
- this.speed = commands_1.default.speed.value.auto;
564
- break;
565
- }
566
- this.platform.log.debug(logMsg);
567
- }
568
- /**
569
- * Handle the "GET" requests from HomeKit
570
- * These are sent when HomeKit wants to know the current state of the accessory
571
- *
572
- * GET requests should return as fast as possbile. A long delay here will result in
573
- * HomeKit being unresponsive and a bad user experience in general.
574
- *
575
- * If your device takes time to respond you should update the status of your device
576
- * asynchronously instead using the `updateCharacteristic` method instead.
577
-
578
- * @example
579
- * this.service.updateCharacteristic(this.platform.Characteristic.On, true)
580
-
581
- * if you need to return an error to show the device as "Not Responding" in the Home app:
582
- * throw new this.platform.api.hap.HapStatusError(this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
583
- */
584
- async getActive() {
585
- const currentPower = this.power && [commands_1.default.mode.value.cool, commands_1.default.mode.value.heat, commands_1.default.mode.value.auto].includes(this.mode);
586
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get Heater-Cooler Active ->`, currentPower ? 'ACTIVE' : 'INACTIVE');
587
- return currentPower ? this.platform.Characteristic.Active.ACTIVE : this.platform.Characteristic.Active.INACTIVE;
588
- }
589
- async getFanActive() {
590
- const currentPower = this.power && this.mode === commands_1.default.mode.value.fan;
591
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get Fan Active ->`, currentPower ? 'ACTIVE' : 'INACTIVE');
592
- return currentPower ? this.platform.Characteristic.Active.ACTIVE : this.platform.Characteristic.Active.INACTIVE;
593
- }
594
- async getCurrentHeaterCoolerState() {
595
- if (this.power) {
596
- switch (this.mode) {
597
- case commands_1.default.mode.value.cool:
598
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentHeaterCoolerState -> COOLING`);
599
- return this.platform.Characteristic.CurrentHeaterCoolerState.COOLING;
600
- case commands_1.default.mode.value.heat:
601
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentHeaterCoolerState -> HEATING`);
602
- return this.platform.Characteristic.CurrentHeaterCoolerState.HEATING;
603
- case commands_1.default.mode.value.auto:
604
- if (this.currentTemperature > this.status[commands_1.default.targetTemperature.code]) {
605
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentHeaterCoolerState -> COOLING`);
606
- return this.platform.Characteristic.CurrentHeaterCoolerState.COOLING;
607
- }
608
- if (this.currentTemperature < this.status[commands_1.default.targetTemperature.code]) {
609
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentHeaterCoolerState -> HEATING`);
610
- return this.platform.Characteristic.CurrentHeaterCoolerState.HEATING;
611
- }
612
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentHeaterCoolerState -> IDLE`);
613
- return this.platform.Characteristic.CurrentHeaterCoolerState.IDLE;
614
- }
615
- }
616
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentHeaterCoolerState -> INACTIVE`);
617
- return this.platform.Characteristic.CurrentHeaterCoolerState.INACTIVE;
618
- }
619
- async getCurrentFanState() {
620
- if (this.power && this.mode === commands_1.default.mode.value.fan) {
621
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentFanState -> BLOWING_AIR`);
622
- return this.platform.Characteristic.CurrentFanState.BLOWING_AIR;
623
- }
624
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentFanState -> INACTIVE`);
625
- return this.platform.Characteristic.CurrentFanState.INACTIVE;
626
- }
627
- async getTargetHeaterCoolerState() {
628
- switch (this.mode) {
629
- case commands_1.default.mode.value.cool:
630
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get TargetHeaterCoolerState -> COOL`);
631
- return this.platform.Characteristic.TargetHeaterCoolerState.COOL;
632
- case commands_1.default.mode.value.heat:
633
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get TargetHeaterCoolerState -> HEAT`);
634
- return this.platform.Characteristic.TargetHeaterCoolerState.HEAT;
635
- case commands_1.default.mode.value.auto:
636
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get TargetHeaterCoolerState -> AUTO`);
637
- return this.platform.Characteristic.TargetHeaterCoolerState.AUTO;
638
- }
639
- // not in heating-cooling mode (e.g. fan mode)
640
- switch (this.accessory.context.TargetHeaterCoolerState) {
641
- case this.platform.Characteristic.TargetHeaterCoolerState.COOL:
642
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get TargetHeaterCoolerState -> COOL`);
643
- break;
644
- case this.platform.Characteristic.TargetHeaterCoolerState.HEAT:
645
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get TargetHeaterCoolerState -> HEAT`);
646
- break;
647
- case this.platform.Characteristic.TargetHeaterCoolerState.AUTO:
648
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get TargetHeaterCoolerState -> AUTO`);
649
- break;
650
- }
651
- return this.accessory.context.TargetHeaterCoolerState;
652
- }
653
- async getCurrentTemperature(service) {
654
- const currentValue = this.currentTemperature;
655
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get ${service} CurrentTemperature ->`, currentValue);
656
- return currentValue;
657
- }
658
- async getTargetTemperature(target) {
659
- const currentValue = this.targetTemperature;
660
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get ${target} ->`, currentValue);
661
- return currentValue;
662
- }
663
- async getTemperatureDisplayUnits() {
664
- const currentValue = (this.units === commands_1.default.units.value.celsius) ?
665
- this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS : this.platform.Characteristic.TemperatureDisplayUnits.FAHRENHEIT;
666
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get TemperatureDisplayUnits ->`, (currentValue === this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS) ? 'CELSIUS' : 'FAHRENHEIT');
667
- return currentValue;
668
- }
669
- async getSwingMode() {
670
- switch (this.swingMode || commands_1.default.swingVertical.value.default) {
671
- case commands_1.default.swingVertical.value.default:
672
- case commands_1.default.swingVertical.value.fixedHighest:
673
- case commands_1.default.swingVertical.value.fixedHigher:
674
- case commands_1.default.swingVertical.value.fixedMiddle:
675
- case commands_1.default.swingVertical.value.fixedLower:
676
- case commands_1.default.swingVertical.value.fixedLowest:
677
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get SwingMode -> DISABLED`);
678
- return this.platform.Characteristic.SwingMode.SWING_DISABLED;
679
- }
680
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get SwingMode -> ENABLED`);
681
- return this.platform.Characteristic.SwingMode.SWING_ENABLED;
682
- }
683
- async getRotationSpeed() {
684
- var _a;
685
- const maxSpeed = ((_a = this.HeaterCooler) === null || _a === void 0 ? void 0 : _a.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.maxValue) ||
686
- this.deviceConfig.speedSteps + 3;
687
- if (this.quietMode === commands_1.default.quietMode.value.on) {
688
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get Heater-Cooler RotationSpeed -> 1 (quiet)`);
689
- return 1;
690
- }
691
- if (this.powerfulMode === commands_1.default.powerfulMode.value.on) {
692
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get Heater-Cooler RotationSpeed -> ${maxSpeed} (powerful)`);
693
- return maxSpeed;
694
- }
695
- let value = 2; // default to auto
696
- let logValue = this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.auto);
697
- switch (this.speed) {
698
- case commands_1.default.speed.value.low:
699
- value = 3;
700
- logValue = this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.low);
701
- break;
702
- case commands_1.default.speed.value.mediumLow:
703
- value = 4;
704
- logValue = this.getKeyName(commands_1.default.speed.value, (maxSpeed === 8) ? commands_1.default.speed.value.mediumLow : commands_1.default.speed.value.medium);
705
- break;
706
- case commands_1.default.speed.value.medium:
707
- value = (maxSpeed === 8) ? 5 : 4;
708
- logValue = this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.medium);
709
- break;
710
- case commands_1.default.speed.value.mediumHigh:
711
- value = (maxSpeed === 8) ? 6 : 4;
712
- logValue = this.getKeyName(commands_1.default.speed.value, (maxSpeed === 8) ? commands_1.default.speed.value.mediumHigh : commands_1.default.speed.value.medium);
713
- break;
714
- case commands_1.default.speed.value.high:
715
- value = (maxSpeed === 8) ? 7 : 5;
716
- logValue = this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.high);
717
- break;
718
- }
719
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get Heater-Cooler RotationSpeed ->`, value + ' (' + logValue + ')');
720
- return value;
721
- }
722
- async getFanRotationSpeed() {
723
- var _a;
724
- const minStep = ((_a = this.Fan) === null || _a === void 0 ? void 0 : _a.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.minStep) ||
725
- 100 / (this.deviceConfig.speedSteps + 1);
726
- let value = 100; // default to auto
727
- let logValueName = this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.auto);
728
- switch (this.speed) {
729
- case commands_1.default.speed.value.low:
730
- value = minStep;
731
- logValueName = this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.low);
732
- break;
733
- case commands_1.default.speed.value.mediumLow:
734
- value = 2 * minStep;
735
- logValueName = this.getKeyName(commands_1.default.speed.value, (minStep !== 25) ? commands_1.default.speed.value.mediumLow : commands_1.default.speed.value.medium);
736
- break;
737
- case commands_1.default.speed.value.medium:
738
- value = (minStep !== 25 ? 3 : 2) * minStep;
739
- logValueName = this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.medium);
740
- break;
741
- case commands_1.default.speed.value.mediumHigh:
742
- value = (minStep !== 25 ? 4 : 2) * minStep;
743
- logValueName = this.getKeyName(commands_1.default.speed.value, (minStep !== 25) ? commands_1.default.speed.value.mediumHigh : commands_1.default.speed.value.medium);
744
- break;
745
- case commands_1.default.speed.value.high:
746
- value = (minStep !== 25 ? 5 : 3) * minStep;
747
- logValueName = this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.high);
748
- break;
749
- }
750
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get Fan RotationSpeed -> ${Math.round(value)}% (${logValueName})`);
751
- return value;
752
- }
753
- async getName() {
754
- //this.platform.api.updatePlatformAccessories([this.accessory]);
755
- this.platform.log.debug(`[${this.getDeviceLabel()}] Get Name ->`, this.accessory.displayName);
756
- return this.accessory.displayName;
757
- }
758
- // helper functions
759
- isSilentTime() {
760
- const currentTime = new Date();
761
- const currentTimeNum = currentTime.getHours() * 100 + currentTime.getMinutes();
762
- return (this.silentTimeRanges !== undefined &&
763
- this.silentTimeRanges.find((element) => element[0] <= currentTimeNum && currentTimeNum < element[1]) !== undefined);
764
- }
765
- getDeviceLabel() {
766
- return `${this.accessory.displayName} -- ${this.accessory.context.device.address}`;
767
- }
768
- getCols() {
769
- if (!this.cols) {
770
- this.cols = Object.keys(commands_1.default).map((k) => commands_1.default[k].code);
771
- }
772
- return this.cols;
773
- }
774
- getKeyName(obj, value, subkey) {
775
- let name = '';
776
- if (obj !== undefined) {
777
- if (subkey === undefined) {
778
- Object.entries(obj).find(([key, val]) => {
779
- if (val === value) {
780
- name = key;
781
- return true;
782
- }
783
- return false;
784
- });
785
- }
786
- else {
787
- Object.entries(obj).find(([key, val]) => {
788
- const v = val;
789
- if (v[subkey] === value) {
790
- name = key;
791
- return true;
792
- }
793
- return false;
794
- });
795
- }
796
- }
797
- return name;
798
- }
799
- calcDeviceTargetTemp(temp, unit) {
800
- var _a;
801
- if (unit === commands_1.default.units.value.celsius ||
802
- (unit === undefined && ((_a = this.HeaterCooler) === null || _a === void 0 ? void 0 : _a.getCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits).value) ===
803
- this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS)) {
804
- return Math.floor(temp);
805
- }
806
- if (temp >= 15.25 && temp < 15.75) {
807
- // execption
808
- return 15;
809
- }
810
- const baseTemp = Math.round(temp);
811
- const baseFahrenheit = temp * 9 / 5 + 32;
812
- const baseFahrenheitDecimalPart = baseFahrenheit - Math.floor(baseFahrenheit);
813
- const correction = (baseFahrenheitDecimalPart >= 0.05 && baseFahrenheitDecimalPart < 0.15) ||
814
- (baseFahrenheitDecimalPart >= 0.25 && baseFahrenheitDecimalPart < 0.35) ? 1 : 0;
815
- return baseTemp - correction;
816
- }
817
- calcDeviceTargetOffset(temp, unit) {
818
- var _a;
819
- if (unit === commands_1.default.units.value.celsius ||
820
- (unit === undefined && ((_a = this.HeaterCooler) === null || _a === void 0 ? void 0 : _a.getCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits).value) ===
821
- this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS)) {
822
- return 0;
823
- }
824
- if (temp === 16) {
825
- // exception
826
- return 0;
827
- }
828
- const baseFahrenheit = temp * 9 / 5 + 32;
829
- const baseFahrenheitDecimalPart = baseFahrenheit - Math.floor(baseFahrenheit);
830
- const offset = (((baseFahrenheitDecimalPart >= 0.05 && baseFahrenheitDecimalPart < 0.15) ||
831
- (baseFahrenheitDecimalPart >= 0.25 && baseFahrenheitDecimalPart < 0.35) ||
832
- (baseFahrenheitDecimalPart >= 0.55 && baseFahrenheitDecimalPart < 0.65) ||
833
- (baseFahrenheitDecimalPart >= 0.75 && baseFahrenheitDecimalPart < 0.85)) ? 1 : 0);
834
- return temp >= 15.25 && temp < 16.25 ? 1 - offset : offset;
835
- }
836
- getTargetTempFromDevice(temp, offset, unit) {
837
- var _a, _b;
838
- let targetValue;
839
- const heatingTargetValue = ((_a = this.HeaterCooler) === null || _a === void 0 ? void 0 : _a.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).value) || 25;
840
- const coolingTargetValue = ((_b = this.HeaterCooler) === null || _b === void 0 ? void 0 : _b.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).value) || 25;
841
- switch (this.mode) {
842
- case commands_1.default.mode.value.heat:
843
- targetValue = heatingTargetValue;
844
- break;
845
- case commands_1.default.mode.value.cool:
846
- targetValue = coolingTargetValue;
847
- break;
848
- default:
849
- targetValue = (coolingTargetValue + heatingTargetValue) / 2;
850
- break;
851
- }
852
- if (unit === commands_1.default.units.value.celsius) {
853
- if (Math.floor(targetValue) === +temp && targetValue !== +temp) {
854
- this.platform.log.debug(`[${this.getDeviceLabel()}] TargetTemperature FIX: %f -> %f`, +temp, targetValue);
855
- return targetValue;
856
- }
857
- return +temp;
858
- }
859
- const key = temp.toString() + ',' + offset.toString();
860
- const value = settings_1.TEMPERATURE_TABLE[key];
861
- if (value === undefined) {
862
- this.platform.log.debug(`[${this.getDeviceLabel()}] TargetTemperature FIX: invalid -> %f`, +temp);
863
- return +temp; // invalid temperature-offset pair received from device -> return temperature value
864
- }
865
- // some temperature values are the same on the physical AC unit -> fix this issue:
866
- if ((targetValue === 12.5 && value === 13) || (targetValue === 17.5 && value === 18) ||
867
- (targetValue === 22.5 && value === 23) || (targetValue === 27.5 && value === 28)) {
868
- this.platform.log.debug(`[${this.getDeviceLabel()}] TargetTemperature FIX: %f -> %f`, value, targetValue);
869
- return targetValue;
870
- }
871
- // no fix needed, return original value
872
- return value;
873
- }
874
- // device functions
875
- get power() {
876
- return (this.status[commands_1.default.power.code] === commands_1.default.power.value.on);
877
- }
878
- set power(value) {
879
- var _a, _b, _c, _d, _e;
880
- if ((value === this.power && [commands_1.default.mode.value.cool, commands_1.default.mode.value.heat, commands_1.default.mode.value.auto].includes(this.mode)) ||
881
- this.powerPending !== -1 || this.modePending !== -1) {
882
- this.platform.log.debug(`[${this.getDeviceLabel()}] power -> no change (${this.power}, ${this.powerPending}, ${this.mode},`, `${this.modePending})`);
883
- return;
884
- }
885
- if (!value && ![commands_1.default.mode.value.cool, commands_1.default.mode.value.heat, commands_1.default.mode.value.auto].includes(this.mode)) {
886
- this.platform.log.debug(`[${this.getDeviceLabel()}] power -> set inactive but no power off (${this.mode})`);
887
- return;
888
- }
889
- const powerValue = value ? commands_1.default.power.value.on : commands_1.default.power.value.off;
890
- const command = {};
891
- let logValue = '';
892
- if (value !== this.power) {
893
- command[commands_1.default.power.code] = powerValue;
894
- logValue += (logValue ? ', ' : '') + 'power -> ' + this.getKeyName(commands_1.default.power.value, powerValue);
895
- }
896
- if (powerValue === commands_1.default.power.value.on) {
897
- switch (((_a = this.HeaterCooler) === null || _a === void 0 ? void 0 : _a.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState).value) ||
898
- this.accessory.context.TargetHeaterCoolerState) {
899
- case this.platform.Characteristic.TargetHeaterCoolerState.COOL:
900
- if (this.mode !== commands_1.default.mode.value.cool) {
901
- command[commands_1.default.mode.code] = commands_1.default.mode.value.cool;
902
- logValue += (logValue ? ', ' : '') + 'mode -> ' + this.getKeyName(commands_1.default.mode.value, commands_1.default.mode.value.cool);
903
- if (this.deviceConfig.xFanEnabled && (this.status[commands_1.default.xFan.code] || commands_1.default.xFan.value.off) !== commands_1.default.xFan.value.on) {
904
- // turn on xFan in Cool mode if xFan is enabled for this device
905
- logValue += (logValue ? ', ' : '') + 'xFan -> ' + this.getKeyName(commands_1.default.xFan.value, commands_1.default.xFan.value.on);
906
- command[commands_1.default.xFan.code] = commands_1.default.xFan.value.on;
907
- }
908
- }
909
- break;
910
- case this.platform.Characteristic.TargetHeaterCoolerState.HEAT:
911
- if (this.mode !== commands_1.default.mode.value.heat) {
912
- command[commands_1.default.mode.code] = commands_1.default.mode.value.heat;
913
- logValue += (logValue ? ', ' : '') + 'mode -> ' + this.getKeyName(commands_1.default.mode.value, commands_1.default.mode.value.heat);
914
- if (this.deviceConfig.xFanEnabled && (this.status[commands_1.default.xFan.code] || commands_1.default.xFan.value.on) !== commands_1.default.xFan.value.off) {
915
- // turn off xFan in unsupported modes (only Cool and Dry modes support xFan)
916
- logValue += (logValue ? ', ' : '') + 'xFan -> ' + this.getKeyName(commands_1.default.xFan.value, commands_1.default.xFan.value.off);
917
- command[commands_1.default.xFan.code] = commands_1.default.xFan.value.off;
918
- }
919
- }
920
- break;
921
- case this.platform.Characteristic.TargetHeaterCoolerState.AUTO:
922
- if (this.mode !== commands_1.default.mode.value.auto) {
923
- command[commands_1.default.mode.code] = commands_1.default.mode.value.auto;
924
- logValue += (logValue ? ', ' : '') + 'mode -> ' + this.getKeyName(commands_1.default.mode.value, commands_1.default.mode.value.auto);
925
- if (this.deviceConfig.xFanEnabled && (this.status[commands_1.default.xFan.code] || commands_1.default.xFan.value.on) !== commands_1.default.xFan.value.off) {
926
- // turn off xFan in unsupported modes (only Cool and Dry modes support xFan)
927
- logValue += (logValue ? ', ' : '') + 'xFan -> ' + this.getKeyName(commands_1.default.xFan.value, commands_1.default.xFan.value.off);
928
- command[commands_1.default.xFan.code] = commands_1.default.xFan.value.off;
929
- }
930
- }
931
- break;
932
- }
933
- }
934
- if (logValue) {
935
- if (powerValue === commands_1.default.power.value.on) {
936
- if (this.accessory.context.HeaterCoolerRotationSpeed !== 0) {
937
- // restore rotation speed on power on
938
- const maxSpeed = ((_b = this.HeaterCooler) === null || _b === void 0 ? void 0 : _b.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.maxValue) ||
939
- this.deviceConfig.speedSteps + 3;
940
- switch (this.accessory.context.HeaterCoolerRotationSpeed) {
941
- case 1: // quiet
942
- if ([this.platform.Characteristic.TargetHeaterCoolerState.COOL, this.platform.Characteristic.TargetHeaterCoolerState.HEAT]
943
- .includes(((_c = this.HeaterCooler) === null || _c === void 0 ? void 0 : _c.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState).value) ||
944
- this.accessory.context.TargetHeaterCoolerState)) {
945
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.on;
946
- logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
947
- this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.on);
948
- }
949
- else {
950
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
951
- logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
952
- this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
953
- }
954
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
955
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
956
- this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off);
957
- command[commands_1.default.speed.code] = commands_1.default.speed.value.low;
958
- logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.low);
959
- break;
960
- case 2: // auto
961
- if (this.quietMode !== commands_1.default.quietMode.value.off || this.powerfulMode !== commands_1.default.powerfulMode.value.off) {
962
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
963
- logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
964
- this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
965
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
966
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
967
- this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off);
968
- }
969
- command[commands_1.default.speed.code] = commands_1.default.speed.value.auto;
970
- logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.auto);
971
- break;
972
- case 3: // low
973
- if (this.quietMode !== commands_1.default.quietMode.value.off || this.powerfulMode !== commands_1.default.powerfulMode.value.off) {
974
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
975
- logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
976
- this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
977
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
978
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
979
- this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off);
980
- }
981
- command[commands_1.default.speed.code] = commands_1.default.speed.value.low;
982
- logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.low);
983
- break;
984
- case 4: // mediumLow / medium
985
- if (this.quietMode !== commands_1.default.quietMode.value.off || this.powerfulMode !== commands_1.default.powerfulMode.value.off) {
986
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
987
- logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
988
- this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
989
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
990
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
991
- this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off);
992
- }
993
- command[commands_1.default.speed.code] = maxSpeed === 8 ? commands_1.default.speed.value.mediumLow : commands_1.default.speed.value.medium;
994
- logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands_1.default.speed.value, command[commands_1.default.speed.code]);
995
- break;
996
- case 5: // medium / high
997
- if (this.quietMode !== commands_1.default.quietMode.value.off || this.powerfulMode !== commands_1.default.powerfulMode.value.off) {
998
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
999
- logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1000
- this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
1001
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
1002
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1003
- this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off);
1004
- }
1005
- command[commands_1.default.speed.code] = maxSpeed === 8 ? commands_1.default.speed.value.medium : commands_1.default.speed.value.high;
1006
- logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands_1.default.speed.value, command[commands_1.default.speed.code]);
1007
- break;
1008
- case 6: // mediumHigh / powerful
1009
- if (maxSpeed === 8) {
1010
- if (this.quietMode !== commands_1.default.quietMode.value.off || this.powerfulMode !== commands_1.default.powerfulMode.value.off) {
1011
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
1012
- logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1013
- this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
1014
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
1015
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1016
- this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off);
1017
- }
1018
- command[commands_1.default.speed.code] = commands_1.default.speed.value.mediumHigh;
1019
- logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.mediumHigh);
1020
- }
1021
- else {
1022
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
1023
- logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1024
- this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
1025
- if ([this.platform.Characteristic.TargetHeaterCoolerState.COOL, this.platform.Characteristic.TargetHeaterCoolerState.HEAT]
1026
- .includes(((_d = this.HeaterCooler) === null || _d === void 0 ? void 0 : _d.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState).value) ||
1027
- this.accessory.context.TargetHeaterCoolerState)) {
1028
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.on;
1029
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1030
- this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.on);
1031
- }
1032
- else {
1033
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
1034
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1035
- this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off);
1036
- }
1037
- command[commands_1.default.speed.code] = commands_1.default.speed.value.high;
1038
- logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.high);
1039
- }
1040
- break;
1041
- case 7: // high
1042
- if (this.quietMode !== commands_1.default.quietMode.value.off || this.powerfulMode !== commands_1.default.powerfulMode.value.off) {
1043
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
1044
- logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1045
- this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
1046
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
1047
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1048
- this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off);
1049
- }
1050
- command[commands_1.default.speed.code] = commands_1.default.speed.value.high;
1051
- logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.high);
1052
- break;
1053
- case 8: // powerful
1054
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
1055
- logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1056
- this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
1057
- if ([this.platform.Characteristic.TargetHeaterCoolerState.COOL, this.platform.Characteristic.TargetHeaterCoolerState.HEAT]
1058
- .includes(((_e = this.HeaterCooler) === null || _e === void 0 ? void 0 : _e.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState).value) ||
1059
- this.accessory.context.TargetHeaterCoolerState)) {
1060
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.on;
1061
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1062
- this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.on);
1063
- }
1064
- else {
1065
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
1066
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1067
- this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off);
1068
- }
1069
- command[commands_1.default.speed.code] = commands_1.default.speed.value.high;
1070
- logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.high);
1071
- break;
1072
- }
1073
- }
1074
- if (([settings_1.MODIFY_VERTICAL_SWING_POSITION.overrideDefPowerOnOscDisable, settings_1.MODIFY_VERTICAL_SWING_POSITION.overrideDefPowerOn].includes(this.deviceConfig.modifyVerticalSwingPosition || settings_1.DEFAULT_DEVICE_CONFIG.modifyVerticalSwingPosition) &&
1075
- this.swingMode === commands_1.default.swingVertical.value.default) || ([settings_1.MODIFY_VERTICAL_SWING_POSITION.setPowerOnOscDisable,
1076
- settings_1.MODIFY_VERTICAL_SWING_POSITION.setPowerOn].includes(this.deviceConfig.modifyVerticalSwingPosition ||
1077
- settings_1.DEFAULT_DEVICE_CONFIG.modifyVerticalSwingPosition))) {
1078
- const value = this.deviceConfig.defaultVerticalSwing || settings_1.DEFAULT_DEVICE_CONFIG.defaultVerticalSwing;
1079
- command[commands_1.default.swingVertical.code] = value;
1080
- logValue += (logValue ? ', ' : '') + 'swingVertical -> ' + this.getKeyName(commands_1.default.swingVertical.value, value);
1081
- }
1082
- }
1083
- this.platform.log.info(`[${this.getDeviceLabel()}]`, logValue);
1084
- this.sendCommand(command);
1085
- }
1086
- }
1087
- set fanpower(value) {
1088
- if (this.powerPending !== -1 || this.modePending !== -1) {
1089
- this.platform.log.debug(`[${this.getDeviceLabel()}] fanpower -> no change (${this.powerPending}, ${this.modePending})`);
1090
- return;
1091
- }
1092
- if (!value && this.mode !== commands_1.default.mode.value.fan) {
1093
- this.platform.log.debug(`[${this.getDeviceLabel()}] fanpower -> set inactive but no power off (${this.mode})`);
1094
- return;
1095
- }
1096
- const powerValue = value ? commands_1.default.power.value.on : commands_1.default.power.value.off;
1097
- const command = {};
1098
- let logValue = '';
1099
- if (value !== this.power) {
1100
- command[commands_1.default.power.code] = powerValue;
1101
- logValue += (logValue ? ', ' : '') + 'power -> ' + this.getKeyName(commands_1.default.power.value, powerValue);
1102
- }
1103
- if (powerValue === commands_1.default.power.value.on && this.mode !== commands_1.default.mode.value.fan) {
1104
- command[commands_1.default.mode.code] = commands_1.default.mode.value.fan;
1105
- logValue += (logValue ? ', ' : '') + 'mode -> ' + this.getKeyName(commands_1.default.mode.value, commands_1.default.mode.value.fan);
1106
- }
1107
- if (logValue) {
1108
- if (powerValue === commands_1.default.power.value.on) {
1109
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
1110
- logValue += (logValue ? ', ' : '') + 'quietMode -> ' + this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
1111
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
1112
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1113
- this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off);
1114
- if ([settings_1.MODIFY_VERTICAL_SWING_POSITION.overrideDefPowerOnOscDisable, settings_1.MODIFY_VERTICAL_SWING_POSITION.overrideDefPowerOn].includes(this.deviceConfig.modifyVerticalSwingPosition || settings_1.DEFAULT_DEVICE_CONFIG.modifyVerticalSwingPosition) &&
1115
- this.swingMode === commands_1.default.swingVertical.value.default) {
1116
- const value = this.deviceConfig.defaultVerticalSwing || settings_1.DEFAULT_DEVICE_CONFIG.defaultVerticalSwing;
1117
- command[commands_1.default.swingVertical.code] = value;
1118
- logValue += (logValue ? ', ' : '') + 'swingVertical -> ' + this.getKeyName(commands_1.default.swingVertical.value, value);
1119
- }
1120
- else if ([settings_1.MODIFY_VERTICAL_SWING_POSITION.setPowerOnOscDisable, settings_1.MODIFY_VERTICAL_SWING_POSITION.setPowerOn].includes(this.deviceConfig.modifyVerticalSwingPosition || settings_1.DEFAULT_DEVICE_CONFIG.modifyVerticalSwingPosition)) {
1121
- const value = this.deviceConfig.defaultFanVerticalSwing || settings_1.DEFAULT_DEVICE_CONFIG.defaultFanVerticalSwing;
1122
- command[commands_1.default.swingVertical.code] = value;
1123
- logValue += (logValue ? ', ' : '') + 'swingVertical -> ' + this.getKeyName(commands_1.default.swingVertical.value, value);
1124
- }
1125
- }
1126
- this.platform.log.info(`[${this.getDeviceLabel()}]`, logValue);
1127
- this.sendCommand(command);
1128
- }
1129
- }
1130
- get mode() {
1131
- return this.status[commands_1.default.mode.code] || commands_1.default.mode.value.auto;
1132
- }
1133
- set mode(value) {
1134
- var _a;
1135
- if (value === this.mode || this.modePending !== -1) {
1136
- this.platform.log.debug(`[${this.getDeviceLabel()}] mode -> no change (${value}, ${this.modePending})`);
1137
- return;
1138
- }
1139
- let logValue = 'mode -> ' + this.getKeyName(commands_1.default.mode.value, value);
1140
- const command = { [commands_1.default.mode.code]: value };
1141
- if (this.deviceConfig.xFanEnabled && (this.status[commands_1.default.xFan.code] || commands_1.default.xFan.value.off) !== commands_1.default.xFan.value.on &&
1142
- [commands_1.default.mode.value.cool, commands_1.default.mode.value.dry].includes(value)) {
1143
- // turn on xFan in Cool and Dry mode if xFan is enabled for this device
1144
- logValue += ', xFan -> ' + this.getKeyName(commands_1.default.xFan.value, commands_1.default.xFan.value.on);
1145
- command[commands_1.default.xFan.code] = commands_1.default.xFan.value.on;
1146
- }
1147
- else if (this.deviceConfig.xFanEnabled && (this.status[commands_1.default.xFan.code] || commands_1.default.xFan.value.on) !== commands_1.default.xFan.value.off &&
1148
- ![commands_1.default.mode.value.cool, commands_1.default.mode.value.dry].includes(value)) {
1149
- // turn off xFan in unsupported modes (only Cool and Dry modes support xFan)
1150
- logValue += ', xFan -> ' + this.getKeyName(commands_1.default.xFan.value, commands_1.default.xFan.value.off);
1151
- command[commands_1.default.xFan.code] = commands_1.default.xFan.value.off;
1152
- }
1153
- if (this.accessory.context.HeaterCoolerRotationSpeed !== 0 &&
1154
- [commands_1.default.mode.value.cool, commands_1.default.mode.value.heat, commands_1.default.mode.value.auto].includes(value)) {
1155
- // restore rotation speed on mode change
1156
- const maxSpeed = ((_a = this.HeaterCooler) === null || _a === void 0 ? void 0 : _a.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.maxValue) ||
1157
- this.deviceConfig.speedSteps + 3;
1158
- switch (this.accessory.context.HeaterCoolerRotationSpeed) {
1159
- case 1: // quiet
1160
- command[commands_1.default.quietMode.code] = value === commands_1.default.mode.value.auto ? commands_1.default.quietMode.value.off :
1161
- commands_1.default.quietMode.value.on;
1162
- logValue += (logValue ? ', ' : '') + 'quietMode -> ' + this.getKeyName(commands_1.default.quietMode.value, value === commands_1.default.mode.value.auto ? commands_1.default.quietMode.value.off : commands_1.default.quietMode.value.on);
1163
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
1164
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1165
- this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off);
1166
- command[commands_1.default.speed.code] = commands_1.default.speed.value.low;
1167
- logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.low);
1168
- break;
1169
- case 2: // auto
1170
- if (this.quietMode !== commands_1.default.quietMode.value.off || this.powerfulMode !== commands_1.default.powerfulMode.value.off) {
1171
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
1172
- logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1173
- this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
1174
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
1175
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1176
- this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off);
1177
- }
1178
- command[commands_1.default.speed.code] = commands_1.default.speed.value.auto;
1179
- logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.auto);
1180
- break;
1181
- case 3: // low
1182
- if (this.quietMode !== commands_1.default.quietMode.value.off || this.powerfulMode !== commands_1.default.powerfulMode.value.off) {
1183
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
1184
- logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1185
- this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
1186
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
1187
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1188
- this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off);
1189
- }
1190
- command[commands_1.default.speed.code] = commands_1.default.speed.value.low;
1191
- logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.low);
1192
- break;
1193
- case 4: // mediumLow / medium
1194
- if (this.quietMode !== commands_1.default.quietMode.value.off || this.powerfulMode !== commands_1.default.powerfulMode.value.off) {
1195
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
1196
- logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1197
- this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
1198
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
1199
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1200
- this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off);
1201
- }
1202
- command[commands_1.default.speed.code] = maxSpeed === 8 ? commands_1.default.speed.value.mediumLow : commands_1.default.speed.value.medium;
1203
- logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands_1.default.speed.value, command[commands_1.default.speed.code]);
1204
- break;
1205
- case 5: // medium / high
1206
- if (this.quietMode !== commands_1.default.quietMode.value.off || this.powerfulMode !== commands_1.default.powerfulMode.value.off) {
1207
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
1208
- logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1209
- this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
1210
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
1211
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1212
- this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off);
1213
- }
1214
- command[commands_1.default.speed.code] = maxSpeed === 8 ? commands_1.default.speed.value.medium : commands_1.default.speed.value.high;
1215
- logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands_1.default.speed.value, command[commands_1.default.speed.code]);
1216
- break;
1217
- case 6: // mediumHigh / powerful
1218
- if (maxSpeed === 8) {
1219
- if (this.quietMode !== commands_1.default.quietMode.value.off || this.powerfulMode !== commands_1.default.powerfulMode.value.off) {
1220
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
1221
- logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1222
- this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
1223
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
1224
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1225
- this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off);
1226
- }
1227
- command[commands_1.default.speed.code] = commands_1.default.speed.value.mediumHigh;
1228
- logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.mediumHigh);
1229
- }
1230
- else {
1231
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
1232
- logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1233
- this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
1234
- command[commands_1.default.powerfulMode.code] = value === commands_1.default.mode.value.auto ? commands_1.default.powerfulMode.value.off :
1235
- commands_1.default.powerfulMode.value.on;
1236
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1237
- this.getKeyName(commands_1.default.powerfulMode.value, value === commands_1.default.mode.value.auto ? commands_1.default.powerfulMode.value.off :
1238
- commands_1.default.powerfulMode.value.on);
1239
- command[commands_1.default.speed.code] = commands_1.default.speed.value.high;
1240
- logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.high);
1241
- }
1242
- break;
1243
- case 7: // high
1244
- if (this.quietMode !== commands_1.default.quietMode.value.off || this.powerfulMode !== commands_1.default.powerfulMode.value.off) {
1245
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
1246
- logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1247
- this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
1248
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
1249
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1250
- this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off);
1251
- }
1252
- command[commands_1.default.speed.code] = commands_1.default.speed.value.high;
1253
- logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.high);
1254
- break;
1255
- case 8: // powerful
1256
- if ([commands_1.default.mode.value.cool, commands_1.default.mode.value.heat].includes(value)) {
1257
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
1258
- logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1259
- this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
1260
- command[commands_1.default.powerfulMode.code] = value === commands_1.default.mode.value.auto ? commands_1.default.powerfulMode.value.off :
1261
- commands_1.default.powerfulMode.value.on;
1262
- logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1263
- this.getKeyName(commands_1.default.powerfulMode.value, value === commands_1.default.mode.value.auto ? commands_1.default.powerfulMode.value.off :
1264
- commands_1.default.powerfulMode.value.on);
1265
- }
1266
- command[commands_1.default.speed.code] = commands_1.default.speed.value.high;
1267
- logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.high);
1268
- break;
1269
- }
1270
- }
1271
- this.platform.log.info(`[${this.getDeviceLabel()}]`, logValue);
1272
- this.sendCommand(command);
1273
- }
1274
- get currentTemperature() {
1275
- return this.status[commands_1.default.temperature.code] - (this.deviceConfig.sensorOffset) || 25;
1276
- }
1277
- get targetTemperature() {
1278
- var _a, _b, _c, _d, _e, _f, _g, _h;
1279
- let minValue = this.deviceConfig.minimumTargetTemperature;
1280
- let maxValue = this.deviceConfig.maximumTargetTemperature;
1281
- switch (this.mode) {
1282
- case commands_1.default.mode.value.cool:
1283
- minValue = Math.max(this.deviceConfig.minimumTargetTemperature, ((_a = this.HeaterCooler) === null || _a === void 0 ? void 0 : _a.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).props.minValue) || 10);
1284
- maxValue = Math.min(this.deviceConfig.maximumTargetTemperature, ((_b = this.HeaterCooler) === null || _b === void 0 ? void 0 : _b.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).props.maxValue) || 35);
1285
- break;
1286
- case commands_1.default.mode.value.heat:
1287
- minValue = Math.max(this.deviceConfig.minimumTargetTemperature, ((_c = this.HeaterCooler) === null || _c === void 0 ? void 0 : _c.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).props.minValue) || 0);
1288
- maxValue = Math.min(this.deviceConfig.maximumTargetTemperature, ((_d = this.HeaterCooler) === null || _d === void 0 ? void 0 : _d.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).props.maxValue) || 25);
1289
- break;
1290
- case commands_1.default.mode.value.auto:
1291
- minValue = Math.max(this.deviceConfig.minimumTargetTemperature, Math.min(((_e = this.HeaterCooler) === null || _e === void 0 ? void 0 : _e.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).props.minValue) || 10, ((_f = this.HeaterCooler) === null || _f === void 0 ? void 0 : _f.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).props.minValue) || 0));
1292
- maxValue = Math.min(this.deviceConfig.maximumTargetTemperature, Math.max(((_g = this.HeaterCooler) === null || _g === void 0 ? void 0 : _g.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).props.maxValue) || 35, ((_h = this.HeaterCooler) === null || _h === void 0 ? void 0 : _h.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).props.maxValue) || 25));
1293
- }
1294
- return Math.max(Math.min(this.getTargetTempFromDevice(this.status[commands_1.default.targetTemperature.code] || 25, this.status[commands_1.default.temperatureOffset.code] || 0, this.status[commands_1.default.units.code]), (maxValue)), (minValue));
1295
- }
1296
- set targetTemperature(value) {
1297
- var _a;
1298
- if (value === this.targetTemperature) {
1299
- this.platform.log.debug(`[${this.getDeviceLabel()}] targetTemperature -> no change (${value})`);
1300
- return;
1301
- }
1302
- const tempValue = this.calcDeviceTargetTemp(value);
1303
- const command = { [commands_1.default.targetTemperature.code]: tempValue };
1304
- let logValue = 'targetTemperature -> ' + tempValue.toString();
1305
- const tempOffset = this.calcDeviceTargetOffset(value);
1306
- command[commands_1.default.temperatureOffset.code] = tempOffset;
1307
- logValue += ', temperatureOffset -> ' + tempOffset.toString();
1308
- const displayUnits = (_a = this.HeaterCooler) === null || _a === void 0 ? void 0 : _a.getCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits).value;
1309
- const deviceDisplayUnits = (displayUnits === this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS) ?
1310
- commands_1.default.units.value.celsius : commands_1.default.units.value.fahrenheit;
1311
- if (deviceDisplayUnits === commands_1.default.units.value.fahrenheit) {
1312
- logValue += ' (-> ' + Math.round(value * 9 / 5 + 32).toString() + ' °F)';
1313
- }
1314
- else {
1315
- logValue += ' (-> ' + value.toString() + ' °C)';
1316
- }
1317
- if (deviceDisplayUnits !== this.units) {
1318
- command[commands_1.default.units.code] = deviceDisplayUnits;
1319
- logValue += ', units -> ' + this.getKeyName(commands_1.default.units.value, deviceDisplayUnits);
1320
- }
1321
- this.platform.log.info(`[${this.getDeviceLabel()}]`, logValue);
1322
- this.sendCommand(command);
1323
- }
1324
- get units() {
1325
- return this.status[commands_1.default.units.code] || commands_1.default.units.value.celsius;
1326
- }
1327
- set units(value) {
1328
- if (value === this.units) {
1329
- this.platform.log.debug(`[${this.getDeviceLabel()}] units -> no change (${value})`);
1330
- return;
1331
- }
1332
- const command = { [commands_1.default.units.code]: value };
1333
- let logValue = 'units -> ' + this.getKeyName(commands_1.default.units.value, value);
1334
- // convert target temperature to new unit
1335
- const actTemp = this.getTargetTempFromDevice(this.status[commands_1.default.targetTemperature.code], this.status[commands_1.default.temperatureOffset.code], this.units);
1336
- const tempValue = this.calcDeviceTargetTemp(actTemp, value);
1337
- if (tempValue !== this.status[commands_1.default.targetTemperature.code]) {
1338
- command[commands_1.default.targetTemperature.code] = tempValue;
1339
- logValue += ', targetTemperature -> ' + tempValue.toString();
1340
- }
1341
- const tempOffset = this.calcDeviceTargetOffset(actTemp, value);
1342
- if (tempOffset !== this.status[commands_1.default.temperatureOffset.code]) {
1343
- command[commands_1.default.temperatureOffset.code] = tempOffset;
1344
- logValue += ', temperatureOffset -> ' + tempOffset.toString();
1345
- }
1346
- this.platform.log.info(`[${this.getDeviceLabel()}]`, logValue);
1347
- this.sendCommand(command);
1348
- }
1349
- get swingMode() {
1350
- return this.status[commands_1.default.swingVertical.code] || commands_1.default.swingVertical.value.default;
1351
- }
1352
- set swingMode(value) {
1353
- if (value === this.swingMode) {
1354
- this.platform.log.debug(`[${this.getDeviceLabel()}] swingMode -> no change (${value})`);
1355
- return;
1356
- }
1357
- const command = { [commands_1.default.swingVertical.code]: value };
1358
- this.platform.log.info(`[${this.getDeviceLabel()}] swingVertical ->`, this.getKeyName(commands_1.default.swingVertical.value, value));
1359
- this.sendCommand(command);
1360
- }
1361
- get speed() {
1362
- return this.status[commands_1.default.speed.code] || commands_1.default.speed.value.auto;
1363
- }
1364
- set speed(value) {
1365
- if (value === this.speed && this.quietMode === commands_1.default.quietMode.value.off && this.powerfulMode === commands_1.default.powerfulMode.value.off) {
1366
- this.platform.log.debug(`[${this.getDeviceLabel()}] speed -> no change (${value}, ${this.quietMode}, ${this.powerfulMode})`);
1367
- return;
1368
- }
1369
- const command = { [commands_1.default.speed.code]: value };
1370
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
1371
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
1372
- this.platform.log.info(`[${this.getDeviceLabel()}] speed ->`, this.getKeyName(commands_1.default.speed.value, value) +
1373
- ', quietMode -> ' + this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off) +
1374
- ', powerfulMode -> ' + this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off));
1375
- this.sendCommand(command);
1376
- }
1377
- get quietMode() {
1378
- return this.status[commands_1.default.quietMode.code] || commands_1.default.quietMode.value.off;
1379
- }
1380
- set quietMode(value) {
1381
- var _a;
1382
- if (value === this.quietMode || value !== commands_1.default.quietMode.value.on) {
1383
- this.platform.log.debug(`[${this.getDeviceLabel()}] quietMode -> not turning on (${value})`);
1384
- return;
1385
- }
1386
- let logValue = '';
1387
- const command = {};
1388
- if ([this.platform.Characteristic.TargetHeaterCoolerState.COOL, this.platform.Characteristic.TargetHeaterCoolerState.HEAT]
1389
- .includes(((_a = this.HeaterCooler) === null || _a === void 0 ? void 0 : _a.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState).value) ||
1390
- this.accessory.context.TargetHeaterCoolerState)) {
1391
- command[commands_1.default.quietMode.code] = value;
1392
- logValue += 'quietMode -> ' + this.getKeyName(commands_1.default.quietMode.value, value);
1393
- }
1394
- else {
1395
- // quiet mode is supported only in heating and cooling mode
1396
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
1397
- logValue += 'quietMode -> ' + this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
1398
- }
1399
- if (value === commands_1.default.quietMode.value.on) {
1400
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
1401
- logValue += ', powerfulMode -> ' + this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off);
1402
- command[commands_1.default.speed.code] = commands_1.default.speed.value.low;
1403
- logValue += ', speed -> ' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.low);
1404
- this.platform.log.info(`[${this.getDeviceLabel()}]`, logValue);
1405
- this.sendCommand(command);
1406
- }
1407
- }
1408
- get powerfulMode() {
1409
- return this.status[commands_1.default.powerfulMode.code] || commands_1.default.powerfulMode.value.off;
1410
- }
1411
- set powerfulMode(value) {
1412
- var _a;
1413
- if (value === this.powerfulMode || value !== commands_1.default.powerfulMode.value.on) {
1414
- this.platform.log.debug(`[${this.getDeviceLabel()}] powerfulMode -> not turning on (${value})`);
1415
- return;
1416
- }
1417
- let logValue = '';
1418
- const command = {};
1419
- if ([this.platform.Characteristic.TargetHeaterCoolerState.COOL, this.platform.Characteristic.TargetHeaterCoolerState.HEAT]
1420
- .includes(((_a = this.HeaterCooler) === null || _a === void 0 ? void 0 : _a.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState).value) ||
1421
- this.accessory.context.TargetHeaterCoolerState)) {
1422
- command[commands_1.default.powerfulMode.code] = value;
1423
- logValue += 'powerfulMode -> ' + this.getKeyName(commands_1.default.powerfulMode.value, value);
1424
- }
1425
- else {
1426
- // powerful mode is supported only in heating and cooling mode
1427
- command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
1428
- logValue += 'powerfulMode -> ' + this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off);
1429
- }
1430
- if (value === commands_1.default.powerfulMode.value.on) {
1431
- command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
1432
- logValue += ', quietMode -> ' + this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
1433
- command[commands_1.default.speed.code] = commands_1.default.speed.value.high;
1434
- logValue += ', speed -> ' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.high);
1435
- this.platform.log.info(`[${this.getDeviceLabel()}]`, logValue);
1436
- this.sendCommand(command);
1437
- }
1438
- }
1439
- updateStatus(props) {
1440
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3;
1441
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus -> %j`, props);
1442
- const hcActive = this.power && [commands_1.default.mode.value.cool, commands_1.default.mode.value.heat, commands_1.default.mode.value.auto].includes(this.mode);
1443
- const fanActive = this.power && this.mode === commands_1.default.mode.value.fan;
1444
- // Heater-Cooler Active
1445
- if (props.includes(commands_1.default.power.code) || props.includes(commands_1.default.mode.code)) {
1446
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Heater-Cooler Active) ->`, hcActive ? 'ACTIVE' : 'INACTIVE');
1447
- (_a = this.HeaterCooler) === null || _a === void 0 ? void 0 : _a.getCharacteristic(this.platform.Characteristic.Active).updateValue(hcActive ? this.platform.Characteristic.Active.ACTIVE : this.platform.Characteristic.Active.INACTIVE);
1448
- }
1449
- // Fan Active
1450
- if (this.Fan && (props.includes(commands_1.default.power.code) || props.includes(commands_1.default.mode.code))) {
1451
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Fan Active) ->`, fanActive ? 'ACTIVE' : 'INACTIVE');
1452
- (_b = this.Fan) === null || _b === void 0 ? void 0 : _b.getCharacteristic(this.platform.Characteristic.Active).updateValue(fanActive ? this.platform.Characteristic.Active.ACTIVE : this.platform.Characteristic.Active.INACTIVE);
1453
- }
1454
- // Current Heater-Cooler State
1455
- if (props.includes(commands_1.default.mode.code)) {
1456
- if (this.power) {
1457
- switch (this.mode) {
1458
- case commands_1.default.mode.value.cool:
1459
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Heater-Cooler State) -> COOLING`);
1460
- (_c = this.HeaterCooler) === null || _c === void 0 ? void 0 : _c.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState).updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.COOLING);
1461
- break;
1462
- case commands_1.default.mode.value.heat:
1463
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Heater-Cooler State) -> HEATING`);
1464
- (_d = this.HeaterCooler) === null || _d === void 0 ? void 0 : _d.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState).updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.HEATING);
1465
- break;
1466
- case commands_1.default.mode.value.auto:
1467
- if (this.currentTemperature > this.targetTemperature + 1.5) {
1468
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Heater-Cooler State) -> COOLING`);
1469
- (_e = this.HeaterCooler) === null || _e === void 0 ? void 0 : _e.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState).updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.COOLING);
1470
- }
1471
- else if (this.currentTemperature < this.targetTemperature - 1.5) {
1472
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Heater-Cooler State) -> HEATING`);
1473
- (_f = this.HeaterCooler) === null || _f === void 0 ? void 0 : _f.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState).updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.HEATING);
1474
- }
1475
- else {
1476
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Heater-Cooler State) -> IDLE`);
1477
- (_g = this.HeaterCooler) === null || _g === void 0 ? void 0 : _g.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState).updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.IDLE);
1478
- }
1479
- break;
1480
- }
1481
- }
1482
- else {
1483
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Heater-Cooler State) -> INACTIVE`);
1484
- (_h = this.HeaterCooler) === null || _h === void 0 ? void 0 : _h.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState).updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.INACTIVE);
1485
- }
1486
- }
1487
- // Current Fan State
1488
- if (this.Fan && props.includes(commands_1.default.mode.code)) {
1489
- if (this.power && this.mode === commands_1.default.mode.value.fan) {
1490
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Fan State) -> BLOWING_AIR`);
1491
- (_j = this.Fan) === null || _j === void 0 ? void 0 : _j.getCharacteristic(this.platform.Characteristic.CurrentFanState).updateValue(this.platform.Characteristic.CurrentFanState.BLOWING_AIR);
1492
- }
1493
- else {
1494
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Fan State) -> INACTIVE`);
1495
- (_k = this.Fan) === null || _k === void 0 ? void 0 : _k.getCharacteristic(this.platform.Characteristic.CurrentFanState).updateValue(this.platform.Characteristic.CurrentFanState.INACTIVE);
1496
- }
1497
- }
1498
- // Target Heater-Cooler State
1499
- if (props.includes(commands_1.default.mode.code) && this.power &&
1500
- [commands_1.default.mode.value.cool, commands_1.default.mode.value.heat, commands_1.default.mode.value.auto].includes(this.mode)) {
1501
- switch (this.mode) {
1502
- case commands_1.default.mode.value.cool:
1503
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Target Heater-Cooler State) -> COOL`);
1504
- (_l = this.HeaterCooler) === null || _l === void 0 ? void 0 : _l.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState).updateValue(this.platform.Characteristic.TargetHeaterCoolerState.COOL);
1505
- this.accessory.context.TargetHeaterCoolerState = this.platform.Characteristic.TargetHeaterCoolerState.COOL;
1506
- break;
1507
- case commands_1.default.mode.value.heat:
1508
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Target Heater-Cooler State) -> HEAT`);
1509
- (_m = this.HeaterCooler) === null || _m === void 0 ? void 0 : _m.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState).updateValue(this.platform.Characteristic.TargetHeaterCoolerState.HEAT);
1510
- this.accessory.context.TargetHeaterCoolerState = this.platform.Characteristic.TargetHeaterCoolerState.HEAT;
1511
- break;
1512
- case commands_1.default.mode.value.auto:
1513
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Target Heater-Cooler State) -> AUTO`);
1514
- (_o = this.HeaterCooler) === null || _o === void 0 ? void 0 : _o.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState).updateValue(this.platform.Characteristic.TargetHeaterCoolerState.AUTO);
1515
- this.accessory.context.TargetHeaterCoolerState = this.platform.Characteristic.TargetHeaterCoolerState.AUTO;
1516
- break;
1517
- }
1518
- this.platform.api.updatePlatformAccessories([this.accessory]);
1519
- }
1520
- // Current Temperature
1521
- if (props.includes(commands_1.default.temperature.code)) {
1522
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Temperature) ->`, this.currentTemperature);
1523
- (_p = this.HeaterCooler) === null || _p === void 0 ? void 0 : _p.getCharacteristic(this.platform.Characteristic.CurrentTemperature).updateValue(this.currentTemperature);
1524
- (_q = this.TemperatureSensor) === null || _q === void 0 ? void 0 : _q.getCharacteristic(this.platform.Characteristic.CurrentTemperature).updateValue(this.currentTemperature);
1525
- (_r = this.tsAccessory) === null || _r === void 0 ? void 0 : _r.setCurrentTemperature(this.currentTemperature);
1526
- (_s = this.tsAccessory) === null || _s === void 0 ? void 0 : _s.TemperatureSensor.getCharacteristic(this.platform.Characteristic.CurrentTemperature).updateValue(this.currentTemperature);
1527
- }
1528
- else if (props.includes(commands_1.default.targetTemperature.code) && this.TemperatureSensor === undefined) {
1529
- // temperature is not accessible -> targetTemperature is saved as currentTemperature
1530
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Temperature) ->`, this.currentTemperature);
1531
- (_t = this.HeaterCooler) === null || _t === void 0 ? void 0 : _t.getCharacteristic(this.platform.Characteristic.CurrentTemperature).updateValue(this.currentTemperature);
1532
- }
1533
- // Cooling Threshold Temperature
1534
- if (props.includes(commands_1.default.targetTemperature.code) && this.power &&
1535
- (this.mode === commands_1.default.mode.value.cool || this.mode === commands_1.default.mode.value.auto)) {
1536
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Cooling Threshold Temperature) ->`, this.targetTemperature);
1537
- (_u = this.HeaterCooler) === null || _u === void 0 ? void 0 : _u.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).updateValue(this.targetTemperature);
1538
- }
1539
- // Heating Threshold Temperature
1540
- if (props.includes(commands_1.default.targetTemperature.code) && this.power &&
1541
- (this.mode === commands_1.default.mode.value.heat || this.mode === commands_1.default.mode.value.auto)) {
1542
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Heating Threshold Temperature) ->`, this.targetTemperature);
1543
- (_v = this.HeaterCooler) === null || _v === void 0 ? void 0 : _v.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).updateValue(this.targetTemperature);
1544
- }
1545
- // Temperature Display Units
1546
- if (props.includes(commands_1.default.units.code)) {
1547
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Temperature Display Units) ->`, this.units === commands_1.default.units.value.celsius ? 'CELSIUS' : 'FAHRENHEIT');
1548
- (_w = this.HeaterCooler) === null || _w === void 0 ? void 0 : _w.getCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits).updateValue(this.units === commands_1.default.units.value.celsius ?
1549
- this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS : this.platform.Characteristic.TemperatureDisplayUnits.FAHRENHEIT);
1550
- }
1551
- // Swing Mode
1552
- if (props.includes(commands_1.default.swingVertical.code) && this.power) {
1553
- let swing = this.platform.Characteristic.SwingMode.SWING_ENABLED;
1554
- let logValue = 'ENABLED';
1555
- if ([commands_1.default.swingVertical.value.full, commands_1.default.swingVertical.value.swingHigher,
1556
- commands_1.default.swingVertical.value.swingHighest, commands_1.default.swingVertical.value.swingLower, commands_1.default.swingVertical.value.swingLowest,
1557
- commands_1.default.swingVertical.value.swingMiddle].includes(this.swingMode)) {
1558
- logValue += ` (type: ${this.getKeyName(commands_1.default.swingVertical.value, this.swingMode)})`;
1559
- }
1560
- switch (this.swingMode) {
1561
- case commands_1.default.swingVertical.value.default:
1562
- case commands_1.default.swingVertical.value.fixedHighest:
1563
- case commands_1.default.swingVertical.value.fixedHigher:
1564
- case commands_1.default.swingVertical.value.fixedMiddle:
1565
- case commands_1.default.swingVertical.value.fixedLower:
1566
- case commands_1.default.swingVertical.value.fixedLowest:
1567
- swing = this.platform.Characteristic.SwingMode.SWING_DISABLED;
1568
- logValue = `DISABLED (position: ${this.getKeyName(commands_1.default.swingVertical.value, this.swingMode)})`;
1569
- break;
1570
- }
1571
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Swing Mode) ->`, logValue);
1572
- (_x = this.HeaterCooler) === null || _x === void 0 ? void 0 : _x.getCharacteristic(this.platform.Characteristic.SwingMode).updateValue(swing);
1573
- }
1574
- // Heater-Cooler Rotation Speed
1575
- if (hcActive) {
1576
- const maxSpeed = ((_y = this.HeaterCooler) === null || _y === void 0 ? void 0 : _y.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.maxValue) ||
1577
- this.deviceConfig.speedSteps + 3;
1578
- if (props.includes(commands_1.default.quietMode.code) && this.quietMode === commands_1.default.quietMode.value.on) {
1579
- // quietMode -> on
1580
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Heater-Cooler Rotation Speed) -> 1 (quiet)`);
1581
- (_z = this.HeaterCooler) === null || _z === void 0 ? void 0 : _z.getCharacteristic(this.platform.Characteristic.RotationSpeed).updateValue(1);
1582
- this.accessory.context.HeaterCoolerRotationSpeed = 1;
1583
- }
1584
- else if (props.includes(commands_1.default.powerfulMode.code) && this.powerfulMode === commands_1.default.powerfulMode.value.on) {
1585
- // powerfulMode -> on
1586
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Heater-Cooler Rotation Speed) ->`, `${maxSpeed.toString()} (powerful)`);
1587
- (_0 = this.HeaterCooler) === null || _0 === void 0 ? void 0 : _0.getCharacteristic(this.platform.Characteristic.RotationSpeed).updateValue(maxSpeed);
1588
- this.accessory.context.HeaterCoolerRotationSpeed = maxSpeed;
1589
- }
1590
- else if (props.includes(commands_1.default.speed.code)) {
1591
- let speedValue = 2; // default: auto
1592
- switch (this.speed) {
1593
- case commands_1.default.speed.value.low:
1594
- speedValue = 3;
1595
- break;
1596
- case commands_1.default.speed.value.mediumLow:
1597
- speedValue = 4;
1598
- break;
1599
- case commands_1.default.speed.value.medium:
1600
- speedValue = (maxSpeed === 8) ? 5 : 4;
1601
- break;
1602
- case commands_1.default.speed.value.mediumHigh:
1603
- speedValue = (maxSpeed === 8) ? 6 : 4;
1604
- break;
1605
- case commands_1.default.speed.value.high:
1606
- speedValue = (maxSpeed === 8) ? 7 : 5;
1607
- break;
1608
- }
1609
- const speedName = this.getKeyName(commands_1.default.speed.value, this.speed);
1610
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Heater-Cooler Rotation Speed) ->`, `${speedValue.toString()} (${speedName})`);
1611
- (_1 = this.HeaterCooler) === null || _1 === void 0 ? void 0 : _1.getCharacteristic(this.platform.Characteristic.RotationSpeed).updateValue(speedValue);
1612
- this.accessory.context.HeaterCoolerRotationSpeed = speedValue;
1613
- }
1614
- this.platform.api.updatePlatformAccessories([this.accessory]);
1615
- }
1616
- // Fan Rotation Speed
1617
- if (fanActive) {
1618
- const minStep = ((_2 = this.Fan) === null || _2 === void 0 ? void 0 : _2.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.minStep) ||
1619
- 100 / (this.deviceConfig.speedSteps + 1);
1620
- let fanSpeedValue = 100; // default: auto
1621
- switch (this.speed) {
1622
- case commands_1.default.speed.value.low:
1623
- fanSpeedValue = minStep;
1624
- break;
1625
- case commands_1.default.speed.value.mediumLow:
1626
- fanSpeedValue = 2 * minStep;
1627
- break;
1628
- case commands_1.default.speed.value.medium:
1629
- fanSpeedValue = (minStep !== 25 ? 3 : 2) * minStep;
1630
- break;
1631
- case commands_1.default.speed.value.mediumHigh:
1632
- fanSpeedValue = (minStep !== 25 ? 4 : 2) * minStep;
1633
- break;
1634
- case commands_1.default.speed.value.high:
1635
- fanSpeedValue = (minStep !== 25 ? 5 : 3) * minStep;
1636
- break;
1637
- }
1638
- const speedName = this.getKeyName(commands_1.default.speed.value, this.speed);
1639
- this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Fan Rotation Speed) ->`, `${Math.round(fanSpeedValue)}% (${speedName})`);
1640
- (_3 = this.Fan) === null || _3 === void 0 ? void 0 : _3.getCharacteristic(this.platform.Characteristic.RotationSpeed).updateValue(fanSpeedValue);
1641
- }
1642
- }
1643
- sendMessage(message) {
1644
- var _a, _b;
1645
- this.platform.log.debug(`[${this.getDeviceLabel()}] sendMessage - Package -> %j`, message);
1646
- this.platform.log.debug(`[${this.getDeviceLabel()}] sendMessage -> Encryption version: %i`, this.accessory.context.device.encryptionVersion);
1647
- let pack, tag;
1648
- if (this.accessory.context.device.encryptionVersion === 1) {
1649
- pack = crypto_1.default.encrypt_v1(message, this.key);
1650
- tag = '';
1651
- }
1652
- else if (this.accessory.context.device.encryptionVersion === 2) {
1653
- const encrypted = crypto_1.default.encrypt_v2(message, this.key);
1654
- pack = encrypted.pack;
1655
- tag = encrypted.tag;
1656
- }
1657
- else {
1658
- this.platform.log.warn(`[${this.getDeviceLabel()}] Warning: sendMessage -> Unsupported encryption version`);
1659
- return;
1660
- }
1661
- const payload = (tag === '') ? {
1662
- tcid: this.accessory.context.device.mac.substring(this.accessory.context.device.mac.indexOf('@') + 1),
1663
- uid: (_a = this.accessory.context.device.uid) !== null && _a !== void 0 ? _a : 0,
1664
- t: 'pack',
1665
- pack,
1666
- i: this.key === undefined ? 1 : 0,
1667
- cid: 'app',
1668
- } : {
1669
- tcid: this.accessory.context.device.mac.substring(this.accessory.context.device.mac.indexOf('@') + 1),
1670
- uid: (_b = this.accessory.context.device.uid) !== null && _b !== void 0 ? _b : 0,
1671
- t: 'pack',
1672
- pack,
1673
- i: this.key === undefined ? 1 : 0,
1674
- tag,
1675
- cid: 'app',
1676
- };
1677
- try {
1678
- const msg = JSON.stringify(payload);
1679
- this.platform.log.debug(`[${this.getDeviceLabel()}] sendMessage`, msg);
1680
- this.socket.send(msg, this.accessory.context.device.port, this.accessory.context.device.address);
1681
- }
1682
- catch (err) {
1683
- this.platform.log.error(`[${this.getDeviceLabel()}] sendMessage - Error:`, err.message);
1684
- }
1685
- }
1686
- sendBindRequest() {
1687
- const message = {
1688
- mac: this.accessory.context.device.mac.substring(this.accessory.context.device.mac.indexOf('@') + 1),
1689
- t: 'bind',
1690
- uid: this.accessory.context.device.mac.indexOf('@') < 0 ? 0 :
1691
- this.accessory.context.device.mac.substring(0, this.accessory.context.device.mac.indexOf('@')),
1692
- };
1693
- this.platform.log.debug(`[${this.getDeviceLabel()}] Bind to device -> ${this.accessory.context.device.mac}`);
1694
- this.sendMessage(message);
1695
- }
1696
- sendCommand(cmd) {
1697
- if (this.isSilentTime()) {
1698
- // add buzzer off command if current time is in silent time range
1699
- cmd[commands_1.default.buzzer.code] = commands_1.default.buzzer.value.off;
1700
- }
1701
- this.platform.log.debug(`[${this.getDeviceLabel()}] Send commands -> %j`, cmd);
1702
- const keys = Object.keys(cmd);
1703
- const values = keys.map((k) => cmd[k]);
1704
- const message = {
1705
- t: 'cmd',
1706
- opt: keys,
1707
- p: values,
1708
- };
1709
- if (keys.includes(commands_1.default.power.code)) {
1710
- this.powerPending = values[keys.indexOf(commands_1.default.power.code)];
1711
- }
1712
- if (keys.includes(commands_1.default.mode.code)) {
1713
- this.modePending = values[keys.indexOf(commands_1.default.mode.code)];
1714
- }
1715
- this.sendMessage(message);
1716
- }
1717
- requestDeviceStatus() {
1718
- const message = {
1719
- mac: this.accessory.context.device.mac,
1720
- t: 'status',
1721
- cols: this.getCols(),
1722
- };
1723
- this.sendMessage(message);
1724
- }
1725
- }
1726
- exports.GreeAirConditioner = GreeAirConditioner;
1
+ import dgram from 'dgram';
2
+ import { PLATFORM_NAME, PLUGIN_NAME, TEMPERATURE_TABLE, MODIFY_VERTICAL_SWING_POSITION, TS_TYPE, BINDING_TIMEOUT, TEMPERATURE_LIMITS, DEFAULT_DEVICE_CONFIG } from './settings.js';
3
+ import { GreeAirConditionerTS } from './tsAccessory.js';
4
+ import crypto from './crypto.js';
5
+ import commands from './commands.js';
6
+ /**
7
+ * Platform Accessory
8
+ * An instance of this class is created for each accessory your platform registers
9
+ * Each accessory may expose multiple services of different service types.
10
+ */
11
+ export class GreeAirConditioner {
12
+ platform;
13
+ accessory;
14
+ deviceConfig;
15
+ tsAccessoryMac;
16
+ HeaterCooler;
17
+ TemperatureSensor;
18
+ Fan;
19
+ socket;
20
+ key;
21
+ cols;
22
+ status;
23
+ tsAccessory = null;
24
+ powerPending = -1;
25
+ modePending = -1;
26
+ silentTimeRanges;
27
+ constructor(platform, accessory, deviceConfig, tsAccessoryMac) {
28
+ this.platform = platform;
29
+ this.accessory = accessory;
30
+ this.deviceConfig = deviceConfig;
31
+ this.tsAccessoryMac = tsAccessoryMac;
32
+ // platform, accessory and service initialization is implemented in a separate funcion (initAccessory), because
33
+ // it should be made only on successful binding with network device
34
+ this.platform.log.debug(`[${this.getDeviceLabel()}] deviceConfig -> %j`, deviceConfig);
35
+ // calculate silent time ranges
36
+ if (deviceConfig.silentTimeRange) {
37
+ const time1 = +(deviceConfig.silentTimeRange.substring(0, 5).replace(':', ''));
38
+ const time2 = +(deviceConfig.silentTimeRange.substring(6).replace(':', ''));
39
+ if (time1 < time2) {
40
+ this.silentTimeRanges = [[time1, time2 < 2400 ? time2 + 1 : time2]];
41
+ }
42
+ else if (time1 > time2) {
43
+ this.silentTimeRanges = [[time1, 2400], [0, time2 < 2400 ? time2 + 1 : time2]];
44
+ }
45
+ this.platform.log.debug(`[${this.getDeviceLabel()}] silentTimeRanges:`, this.silentTimeRanges ??
46
+ 'Zero length silentTimeRange is defined - ignoring');
47
+ }
48
+ else {
49
+ this.platform.log.debug(`[${this.getDeviceLabel()}] silentTimeRanges: No silentTimeRange is defined`);
50
+ }
51
+ // initialize communication with device
52
+ this.status = {};
53
+ this.socket = dgram.createSocket({ type: 'udp4', reuseAddr: true });
54
+ this.socket.on('error', (err) => {
55
+ this.platform.log.error(`[${this.getDeviceLabel()}] Network - Error:`, err.message);
56
+ });
57
+ this.socket.on('message', this.handleMessage);
58
+ this.socket.on('close', () => {
59
+ this.platform.log.error(`[${this.getDeviceLabel()}] Network - Connection closed`);
60
+ });
61
+ if (this.platform.ports.indexOf(this.deviceConfig.port || 0) >= 0) {
62
+ this.platform.log.warn(`[${this.getDeviceLabel()}] Warning: Configured port (%i) is already used - replacing with auto assigned port`, this.deviceConfig.port);
63
+ this.deviceConfig.port = undefined;
64
+ }
65
+ this.socket.bind(this.deviceConfig.port, undefined, () => {
66
+ this.platform.log.info(`[${this.getDeviceLabel()}] Device handler is listening on UDP port %d`, this.socket.address().port);
67
+ this.platform.ports.push(this.socket.address().port);
68
+ this.socket.setBroadcast(false);
69
+ this.sendBindRequest();
70
+ setTimeout(this.checkBindingStatus.bind(this, 1), BINDING_TIMEOUT);
71
+ });
72
+ }
73
+ initCharacteristics() {
74
+ // these characteristic properties are not updated by HomeKit, they are initialized only once
75
+ // Cooling Threshold Temperature Characteristic
76
+ // minValue / maxValue usually generates error messages in debug log:
77
+ // "Characteristic 'Cooling Threshold Temperature': characteristic was supplied illegal value ..."
78
+ // this is not a problem, this is information only that GREE is more restricitive than Apple's default
79
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature)
80
+ .setProps({
81
+ minStep: this.deviceConfig.temperatureStepSize,
82
+ minValue: Math.max(this.deviceConfig.minimumTargetTemperature, TEMPERATURE_LIMITS.coolingMinimum),
83
+ maxValue: Math.min(this.deviceConfig.maximumTargetTemperature, TEMPERATURE_LIMITS.coolingMaximum),
84
+ });
85
+ this.platform.log.debug(`[${this.getDeviceLabel()}] CoolingThresholdTemperature - minValue: %s, maxValue: %s, minStep: %s`, this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).props.minValue?.toString(), this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).props.maxValue?.toString(), this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).props.minStep?.toString());
86
+ // Heating Threshold Temperature Characteristic
87
+ // minValue / maxValue usually generates error messages in debug log:
88
+ // "Characteristic 'Heating Threshold Temperature': characteristic was supplied illegal value ..."
89
+ // this is not a problem, this is information only that GREE is more restricitive than Apple's default
90
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature)
91
+ .setProps({
92
+ minStep: this.deviceConfig.temperatureStepSize,
93
+ minValue: Math.max(this.deviceConfig.minimumTargetTemperature, TEMPERATURE_LIMITS.heatingMinimum),
94
+ maxValue: Math.min(this.deviceConfig.maximumTargetTemperature, TEMPERATURE_LIMITS.heatingMaximum),
95
+ });
96
+ this.platform.log.debug(`[${this.getDeviceLabel()}] HeatingThresholdTemperature - minValue: %s, maxValue: %s, minStep: %s`, this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).props.minValue?.toString(), this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).props.maxValue?.toString(), this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).props.minStep?.toString());
97
+ // Rotation Speed Characteristic
98
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.RotationSpeed)
99
+ .setProps({
100
+ minValue: 0,
101
+ maxValue: this.deviceConfig.speedSteps + 3,
102
+ minStep: 1
103
+ });
104
+ this.platform.log.debug(`[${this.getDeviceLabel()}] RotationSpeed - minValue: %s, maxValue: %s, minStep: %s`, this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.minValue?.toString(), this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.maxValue?.toString(), this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.minStep?.toString());
105
+ }
106
+ // All platform, accessory and service initialization is made in initAccessory function
107
+ initAccessory() {
108
+ // register accessory in homebridge by api if not registered before
109
+ if (!this.accessory.registered) {
110
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Registering new accessory in homebridge:`, this.accessory.context.device.mac, this.accessory.UUID);
111
+ this.platform.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [this.accessory]);
112
+ // set static accessory information
113
+ this.accessory.getService(this.platform.Service.AccessoryInformation)
114
+ .setCharacteristic(this.platform.Characteristic.Manufacturer, this.accessory.context.device.brand || 'Gree')
115
+ .setCharacteristic(this.platform.Characteristic.SerialNumber, this.accessory.context.device.mac)
116
+ .setCharacteristic(this.platform.Characteristic.Model, this.deviceConfig?.model || this.accessory.context.device.model || this.accessory.context.device.name || 'Air Conditioner')
117
+ .setCharacteristic(this.platform.Characteristic.HardwareRevision, this.accessory.context.device.ver ?
118
+ this.accessory.context.device.ver.substring(this.accessory.context.device.ver.lastIndexOf('V') + 1) : '1.0.0')
119
+ .setCharacteristic(this.platform.Characteristic.Name, this.accessory.displayName);
120
+ // get the HeaterCooler service if it exists, otherwise create a new HeaterCooler service
121
+ // we don't use subtype because we add only one service with this type
122
+ this.HeaterCooler = this.accessory.getService(this.platform.Service.HeaterCooler) ||
123
+ this.accessory.addService(this.platform.Service.HeaterCooler, this.accessory.displayName, undefined);
124
+ // set static characeristics
125
+ this.initCharacteristics();
126
+ }
127
+ if (this.tsAccessoryMac) {
128
+ this.tsAccessory = new GreeAirConditionerTS(this.platform, this.platform.getAccessory(this.accessory.context.device.mac + '_ts'));
129
+ }
130
+ // init TargetHeaterCoolerState default value
131
+ if (!this.accessory.context.TargetHeaterCoolerState) {
132
+ this.accessory.context.TargetHeaterCoolerState =
133
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState).value ||
134
+ this.platform.Characteristic.TargetHeaterCoolerState.AUTO;
135
+ }
136
+ // init HeaterCoolerRotationSpeed default value
137
+ if (this.accessory.context.HeaterCoolerRotationSpeed === undefined) {
138
+ this.accessory.context.HeaterCoolerRotationSpeed =
139
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.RotationSpeed).value ||
140
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.minValue || 0;
141
+ }
142
+ // set accessory information
143
+ this.accessory.getService(this.platform.Service.AccessoryInformation)
144
+ .setCharacteristic(this.platform.Characteristic.FirmwareRevision, this.accessory.context.device.hid && this.accessory.context.device.hid.lastIndexOf('V') >= 0 &&
145
+ this.accessory.context.device.hid.lastIndexOf('V') < this.accessory.context.device.hid.lastIndexOf('.') ?
146
+ this.accessory.context.device.hid.substring(this.accessory.context.device.hid.lastIndexOf('V') + 1, this.accessory.context.device.hid.lastIndexOf('.')) : '1.0.0');
147
+ // get the HeaterCooler service if it exists, otherwise create a new HeaterCooler service
148
+ // we don't use subtype because we add only one service with this type
149
+ if (!this.HeaterCooler) {
150
+ this.HeaterCooler = this.accessory.getService(this.platform.Service.HeaterCooler);
151
+ if (!this.HeaterCooler) {
152
+ this.platform.log.debug(`[${this.getDeviceLabel()}] HeaterCooler service doesn't exist - adding service`);
153
+ this.HeaterCooler = this.accessory.addService(this.platform.Service.HeaterCooler, this.accessory.displayName);
154
+ // set static characeristics
155
+ this.initCharacteristics();
156
+ }
157
+ }
158
+ // TemperatureSensor service
159
+ // we don't use subtype because we add only one service with this type
160
+ const tss = this.accessory.getService(this.platform.Service.TemperatureSensor);
161
+ if (this.deviceConfig.temperatureSensor === TS_TYPE.child) {
162
+ if (tss) {
163
+ this.TemperatureSensor = tss;
164
+ }
165
+ else {
166
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Add Temperature Sensor child service`);
167
+ this.TemperatureSensor =
168
+ this.accessory.addService(this.platform.Service.TemperatureSensor, 'Temperature Sensor ' + this.HeaterCooler.displayName);
169
+ }
170
+ }
171
+ else {
172
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Temperature Sensor child service not allowed`, tss?.displayName !== undefined ? '(' + tss?.displayName + ')' : '');
173
+ if (tss !== undefined) {
174
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Remove Temperature Sensor child service (%s)`, tss.displayName);
175
+ this.accessory.removeService(tss);
176
+ }
177
+ }
178
+ // Fan service
179
+ // we don't use subtype because we add only one service with this type
180
+ const fs = this.accessory.getService(this.platform.Service.Fanv2);
181
+ if (this.deviceConfig.fanControlEnabled) {
182
+ if (fs) {
183
+ this.Fan = fs;
184
+ }
185
+ else {
186
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Add Fan child service`);
187
+ this.Fan =
188
+ this.accessory.addService(this.platform.Service.Fanv2, 'Fan ' + this.HeaterCooler.displayName);
189
+ // set static characeristics
190
+ this.Fan?.getCharacteristic(this.platform.Characteristic.RotationSpeed)
191
+ .setProps({
192
+ minValue: 0,
193
+ maxValue: 100,
194
+ minStep: 100 / (this.deviceConfig.speedSteps + 1)
195
+ });
196
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Fan RotationSpeed - minValue: %s, maxValue: %s, minStep: %s`, this.Fan?.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.minValue?.toString(), this.Fan?.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.maxValue?.toString(), this.Fan?.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.minStep?.toString());
197
+ }
198
+ }
199
+ else {
200
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Fan child service not allowed`, fs?.displayName !== undefined ? '(' + fs?.displayName + ')' : '');
201
+ if (fs !== undefined) {
202
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Remove Fan child service (%s)`, fs.displayName);
203
+ this.accessory.removeService(fs);
204
+ }
205
+ }
206
+ this.HeaterCooler.setPrimaryService(true);
207
+ this.TemperatureSensor?.setPrimaryService(false);
208
+ this.Fan?.setPrimaryService(false);
209
+ this.platform.api.updatePlatformAccessories([this.accessory]);
210
+ // each service must implement at-minimum the "required characteristics" for the given service type
211
+ // see https://developers.homebridge.io/#/service/HeaterCooler
212
+ // register handlers for the Active Characteristic
213
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.Active)
214
+ .onSet(this.setActive.bind(this))
215
+ .onGet(this.getActive.bind(this));
216
+ this.Fan?.getCharacteristic(this.platform.Characteristic.Active)
217
+ .onSet(this.setFanActive.bind(this))
218
+ .onGet(this.getFanActive.bind(this));
219
+ // register handlers for the Current Heater-Cooler State Characteristic
220
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState)
221
+ .onGet(this.getCurrentHeaterCoolerState.bind(this));
222
+ // register handlers for the Current Fan State Characteristic
223
+ this.Fan?.getCharacteristic(this.platform.Characteristic.CurrentFanState)
224
+ .onGet(this.getCurrentFanState.bind(this));
225
+ // register handlers for the Target Heater-Cooler State Characteristic
226
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState)
227
+ .onGet(this.getTargetHeaterCoolerState.bind(this))
228
+ .onSet(this.setTargetHeaterCoolerState.bind(this));
229
+ // register handlers for the Current Temperature Characteristic
230
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CurrentTemperature)
231
+ .onGet(this.getCurrentTemperature.bind(this, 'Heater-Cooler'));
232
+ this.TemperatureSensor?.getCharacteristic(this.platform.Characteristic.CurrentTemperature)
233
+ .onGet(this.getCurrentTemperature.bind(this, 'Temperature Sensor'));
234
+ // register handlers for the Cooling Threshold Temperature Characteristic
235
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature)
236
+ .onGet(this.getTargetTemperature.bind(this, 'CoolingThresholdTemperature'))
237
+ .onSet(this.setTargetTemperature.bind(this));
238
+ // register handlers for the Heating Threshold Temperature Characteristic
239
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature)
240
+ .onGet(this.getTargetTemperature.bind(this, 'HeatingThresholdTemperature'))
241
+ .onSet(this.setTargetTemperature.bind(this));
242
+ // register handlers for the Temperature Display Units Characteristic
243
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits)
244
+ .onGet(this.getTemperatureDisplayUnits.bind(this))
245
+ .onSet(this.setTemperatureDisplayUnits.bind(this));
246
+ // register handlers for the Swing Mode Characteristic
247
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.SwingMode)
248
+ .onGet(this.getSwingMode.bind(this))
249
+ .onSet(this.setSwingMode.bind(this));
250
+ this.Fan?.getCharacteristic(this.platform.Characteristic.SwingMode)
251
+ .onGet(this.getSwingMode.bind(this))
252
+ .onSet(this.setFanSwingMode.bind(this));
253
+ // register handlers for the Rotation Speed Characteristic
254
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.RotationSpeed)
255
+ .onGet(this.getRotationSpeed.bind(this))
256
+ .onSet(this.setRotationSpeed.bind(this));
257
+ this.Fan?.getCharacteristic(this.platform.Characteristic.RotationSpeed)
258
+ .onGet(this.getFanRotationSpeed.bind(this))
259
+ .onSet(this.setFanRotationSpeed.bind(this));
260
+ // register handlers for the Name Characteristic
261
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.Name)
262
+ .onGet(this.getName.bind(this));
263
+ }
264
+ // this function is a callback to check the status of binding after timeout period has ellapsed
265
+ checkBindingStatus(bindNo) {
266
+ if (!this.accessory.bound) {
267
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Device binding timeout`);
268
+ switch (bindNo) {
269
+ case 1: {
270
+ // 1. timeout -> repeat bind request with alternate encryption version
271
+ if (this.accessory.context.device.encryptionVersion === 1) {
272
+ this.accessory.context.device.encryptionVersion = 2;
273
+ }
274
+ else {
275
+ this.accessory.context.device.encryptionVersion = 1;
276
+ }
277
+ this.sendBindRequest();
278
+ setTimeout(this.checkBindingStatus.bind(this, bindNo + 1), BINDING_TIMEOUT);
279
+ break;
280
+ }
281
+ default: {
282
+ this.platform.log.error(`[${this.getDeviceLabel()}] Error: Device is not bound`, '(unknown device type or device is malfunctioning [turning the power supply off and on may help])', '- Restart homebridge when issue has fixed!');
283
+ }
284
+ }
285
+ }
286
+ }
287
+ /**
288
+ * Handle "SET" requests from HomeKit
289
+ * These are sent when the user changes the state of an accessory, for example, turning on a Light bulb.
290
+ */
291
+ async setActive(value) {
292
+ const powerValue = (value === this.platform.Characteristic.Active.ACTIVE);
293
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler Active ->`, powerValue ? 'ACTIVE' : 'INACTIVE');
294
+ this.power = powerValue;
295
+ if (powerValue &&
296
+ this.Fan?.getCharacteristic(this.platform.Characteristic.Active).value === this.platform.Characteristic.Active.ACTIVE) {
297
+ this.Fan?.getCharacteristic(this.platform.Characteristic.Active).updateValue(this.platform.Characteristic.Active.INACTIVE);
298
+ }
299
+ }
300
+ async setFanActive(value) {
301
+ const powerValue = (value === this.platform.Characteristic.Active.ACTIVE);
302
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set Fan Active ->`, powerValue ? 'ACTIVE' : 'INACTIVE');
303
+ this.fanpower = powerValue;
304
+ if (powerValue &&
305
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.Active).value === this.platform.Characteristic.Active.ACTIVE) {
306
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.Active).updateValue(this.platform.Characteristic.Active.INACTIVE);
307
+ }
308
+ }
309
+ async setTargetHeaterCoolerState(value) {
310
+ let modeValue = commands.mode.value.auto;
311
+ let logValue = 'AUTO';
312
+ switch (value) {
313
+ case this.platform.Characteristic.TargetHeaterCoolerState.COOL:
314
+ modeValue = commands.mode.value.cool;
315
+ logValue = 'COOL';
316
+ break;
317
+ case this.platform.Characteristic.TargetHeaterCoolerState.HEAT:
318
+ modeValue = commands.mode.value.heat;
319
+ logValue = 'HEAT';
320
+ break;
321
+ }
322
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set TargetHeaterCoolerState ->`, logValue);
323
+ this.mode = modeValue;
324
+ this.accessory.context.TargetHeaterCoolerState = value;
325
+ this.platform.api.updatePlatformAccessories([this.accessory]);
326
+ }
327
+ async setTargetTemperature(value) {
328
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set ThresholdTemperature ->`, value);
329
+ this.targetTemperature = value;
330
+ }
331
+ async setTemperatureDisplayUnits(value) {
332
+ const logValue = (value === this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS) ? 'CELSIUS' : 'FAHRENHEIT';
333
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set TemperatureDisplayUnits ->`, logValue);
334
+ this.units = (value === this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS) ?
335
+ commands.units.value.celsius : commands.units.value.fahrenheit;
336
+ }
337
+ async setSwingMode(value) {
338
+ const logValue = (value === this.platform.Characteristic.SwingMode.SWING_ENABLED) ? 'ENABLED' : 'DISABLED';
339
+ this.swingMode = (value === this.platform.Characteristic.SwingMode.SWING_ENABLED) ?
340
+ commands.swingVertical.value.full : ([MODIFY_VERTICAL_SWING_POSITION.overrideDefPowerOnOscDisable,
341
+ MODIFY_VERTICAL_SWING_POSITION.setPowerOnOscDisable].includes(this.deviceConfig.modifyVerticalSwingPosition ||
342
+ DEFAULT_DEVICE_CONFIG.modifyVerticalSwingPosition) ? this.deviceConfig.defaultVerticalSwing ||
343
+ DEFAULT_DEVICE_CONFIG.defaultVerticalSwing : DEFAULT_DEVICE_CONFIG.defaultVerticalSwing);
344
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set SwingMode ->`, logValue + (logValue === 'DISABLED' ?
345
+ ` (Position: ${this.getKeyName(commands.swingVertical.value, this.swingMode)})` : ''));
346
+ }
347
+ async setFanSwingMode(value) {
348
+ const logValue = (value === this.platform.Characteristic.SwingMode.SWING_ENABLED) ? 'ENABLED' : 'DISABLED';
349
+ this.swingMode = (value === this.platform.Characteristic.SwingMode.SWING_ENABLED) ?
350
+ commands.swingVertical.value.full : (this.deviceConfig.modifyVerticalSwingPosition ===
351
+ MODIFY_VERTICAL_SWING_POSITION.overrideDefPowerOnOscDisable ? this.deviceConfig.defaultVerticalSwing ||
352
+ DEFAULT_DEVICE_CONFIG.defaultVerticalSwing : (this.deviceConfig.modifyVerticalSwingPosition ===
353
+ MODIFY_VERTICAL_SWING_POSITION.setPowerOnOscDisable ? this.deviceConfig.defaultFanVerticalSwing ||
354
+ DEFAULT_DEVICE_CONFIG.defaultFanVerticalSwing : DEFAULT_DEVICE_CONFIG.defaultFanVerticalSwing));
355
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set Fan SwingMode ->`, logValue + (logValue === 'DISABLED' ?
356
+ ` (Position: ${this.getKeyName(commands.swingVertical.value, this.swingMode)})` : ''));
357
+ }
358
+ async setRotationSpeed(value) {
359
+ const maxSpeed = this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.maxValue ||
360
+ this.deviceConfig.speedSteps + 3;
361
+ switch (value) {
362
+ case 0: // inactive -> rotation speed change not needed
363
+ return;
364
+ case 1: // quiet
365
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler RotationSpeed ->`, value + ' (quiet)');
366
+ this.quietMode = commands.quietMode.value.on;
367
+ break;
368
+ case 2: // auto
369
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler RotationSpeed ->`, value +
370
+ ' (' + this.getKeyName(commands.speed.value, commands.speed.value.auto) + ')');
371
+ this.speed = commands.speed.value.auto;
372
+ break;
373
+ case 3: // low
374
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler RotationSpeed ->`, value +
375
+ ' (' + this.getKeyName(commands.speed.value, commands.speed.value.low) + ')');
376
+ this.speed = commands.speed.value.low;
377
+ break;
378
+ case 4: // mediumLow / medium
379
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler RotationSpeed ->`, value + ' (' +
380
+ this.getKeyName(commands.speed.value, (maxSpeed === 8) ? commands.speed.value.mediumLow : commands.speed.value.medium) + ')');
381
+ this.speed = (maxSpeed === 8) ? commands.speed.value.mediumLow : commands.speed.value.medium;
382
+ break;
383
+ case 5: // medium / high
384
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler RotationSpeed ->`, value + ' (' +
385
+ this.getKeyName(commands.speed.value, (maxSpeed === 8) ? commands.speed.value.medium : commands.speed.value.high) + ')');
386
+ this.speed = (maxSpeed === 8) ? commands.speed.value.medium : commands.speed.value.high;
387
+ break;
388
+ case 6: // mediumHigh / powerful
389
+ if (maxSpeed === 8) {
390
+ // mediumHigh
391
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler RotationSpeed ->`, value +
392
+ ' (' + this.getKeyName(commands.speed.value, commands.speed.value.mediumHigh) + ')');
393
+ this.speed = commands.speed.value.mediumHigh;
394
+ }
395
+ else {
396
+ // powerful
397
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler RotationSpeed ->`, value + ' (powerful)');
398
+ this.powerfulMode = commands.powerfulMode.value.on;
399
+ }
400
+ break;
401
+ case 7: // high
402
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler RotationSpeed ->`, value +
403
+ ' (' + this.getKeyName(commands.speed.value, commands.speed.value.high) + ')');
404
+ this.speed = commands.speed.value.high;
405
+ break;
406
+ case 8: // powerful
407
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler RotationSpeed ->`, value + ' (powerful)');
408
+ this.powerfulMode = commands.powerfulMode.value.on;
409
+ break;
410
+ default: // auto
411
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set Heater-Cooler RotationSpeed ->`, value +
412
+ ' (' + this.getKeyName(commands.speed.value, commands.speed.value.auto) + ')');
413
+ this.speed = commands.speed.value.auto;
414
+ break;
415
+ }
416
+ this.accessory.context.HeaterCoolerRotationSpeed = value;
417
+ this.platform.api.updatePlatformAccessories([this.accessory]);
418
+ }
419
+ async setFanRotationSpeed(value) {
420
+ if (value !== 0 &&
421
+ this.Fan?.getCharacteristic(this.platform.Characteristic.Active).value !== this.platform.Characteristic.Active.ACTIVE) {
422
+ this.Fan?.getCharacteristic(this.platform.Characteristic.Active).setValue(this.platform.Characteristic.Active.ACTIVE);
423
+ }
424
+ let logMsg = `[${this.getDeviceLabel()}] Set Fan RotationSpeed -> ${Math.round(value)}%`;
425
+ switch (Math.round(value)) {
426
+ case 0: // inactive -> rotation speed change not needed
427
+ return;
428
+ case 17: // low - 5 step model
429
+ case 25: // low - 3 step model
430
+ logMsg += ` (${this.getKeyName(commands.speed.value, commands.speed.value.low)})`;
431
+ this.speed = commands.speed.value.low;
432
+ break;
433
+ case 33: // mediumLow
434
+ logMsg += ` (${this.getKeyName(commands.speed.value, commands.speed.value.mediumLow)})`;
435
+ this.speed = commands.speed.value.mediumLow;
436
+ break;
437
+ case 50: // medium
438
+ logMsg += ` (${this.getKeyName(commands.speed.value, commands.speed.value.medium)}) - ${Math.round(value)}%`;
439
+ this.speed = commands.speed.value.medium;
440
+ break;
441
+ case 67: // mediumHigh
442
+ logMsg += ` (${this.getKeyName(commands.speed.value, commands.speed.value.mediumHigh)}) - ${Math.round(value)}%`;
443
+ this.speed = commands.speed.value.mediumHigh;
444
+ break;
445
+ case 75: // high - 3 step model
446
+ case 83: // high - 5 step model
447
+ logMsg += ` (${this.getKeyName(commands.speed.value, commands.speed.value.high)}) - ${Math.round(value)}%`;
448
+ this.speed = commands.speed.value.high;
449
+ break;
450
+ default: // auto
451
+ logMsg += ` (${this.getKeyName(commands.speed.value, commands.speed.value.auto)}) - ${Math.round(value)}%`;
452
+ this.speed = commands.speed.value.auto;
453
+ break;
454
+ }
455
+ this.platform.log.debug(logMsg);
456
+ }
457
+ /**
458
+ * Handle the "GET" requests from HomeKit
459
+ * These are sent when HomeKit wants to know the current state of the accessory, for example, checking if a Light bulb is on.
460
+ *
461
+ * GET requests should return as fast as possible. A long delay here will result in
462
+ * HomeKit being unresponsive and a bad user experience in general.
463
+ *
464
+ * If your device takes time to respond you should update the status of your device
465
+ * asynchronously instead using the `updateCharacteristic` method instead.
466
+ * In this case, you may decide not to implement `onGet` handlers, which may speed up
467
+ * the responsiveness of your device in the Home app.
468
+
469
+ * @example
470
+ * this.service.updateCharacteristic(this.platform.Characteristic.On, true)
471
+ */
472
+ async getActive() {
473
+ const currentPower = this.power && [commands.mode.value.cool, commands.mode.value.heat, commands.mode.value.auto].includes(this.mode);
474
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get Heater-Cooler Active ->`, currentPower ? 'ACTIVE' : 'INACTIVE');
475
+ return currentPower ? this.platform.Characteristic.Active.ACTIVE : this.platform.Characteristic.Active.INACTIVE;
476
+ }
477
+ async getFanActive() {
478
+ const currentPower = this.power && this.mode === commands.mode.value.fan;
479
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get Fan Active ->`, currentPower ? 'ACTIVE' : 'INACTIVE');
480
+ return currentPower ? this.platform.Characteristic.Active.ACTIVE : this.platform.Characteristic.Active.INACTIVE;
481
+ }
482
+ async getCurrentHeaterCoolerState() {
483
+ if (this.power) {
484
+ switch (this.mode) {
485
+ case commands.mode.value.cool:
486
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentHeaterCoolerState -> COOLING`);
487
+ return this.platform.Characteristic.CurrentHeaterCoolerState.COOLING;
488
+ case commands.mode.value.heat:
489
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentHeaterCoolerState -> HEATING`);
490
+ return this.platform.Characteristic.CurrentHeaterCoolerState.HEATING;
491
+ case commands.mode.value.auto:
492
+ if (this.currentTemperature > this.status[commands.targetTemperature.code]) {
493
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentHeaterCoolerState -> COOLING`);
494
+ return this.platform.Characteristic.CurrentHeaterCoolerState.COOLING;
495
+ }
496
+ if (this.currentTemperature < this.status[commands.targetTemperature.code]) {
497
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentHeaterCoolerState -> HEATING`);
498
+ return this.platform.Characteristic.CurrentHeaterCoolerState.HEATING;
499
+ }
500
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentHeaterCoolerState -> IDLE`);
501
+ return this.platform.Characteristic.CurrentHeaterCoolerState.IDLE;
502
+ }
503
+ }
504
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentHeaterCoolerState -> INACTIVE`);
505
+ return this.platform.Characteristic.CurrentHeaterCoolerState.INACTIVE;
506
+ }
507
+ async getCurrentFanState() {
508
+ if (this.power && this.mode === commands.mode.value.fan) {
509
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentFanState -> BLOWING_AIR`);
510
+ return this.platform.Characteristic.CurrentFanState.BLOWING_AIR;
511
+ }
512
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentFanState -> INACTIVE`);
513
+ return this.platform.Characteristic.CurrentFanState.INACTIVE;
514
+ }
515
+ async getTargetHeaterCoolerState() {
516
+ switch (this.mode) {
517
+ case commands.mode.value.cool:
518
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get TargetHeaterCoolerState -> COOL`);
519
+ return this.platform.Characteristic.TargetHeaterCoolerState.COOL;
520
+ case commands.mode.value.heat:
521
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get TargetHeaterCoolerState -> HEAT`);
522
+ return this.platform.Characteristic.TargetHeaterCoolerState.HEAT;
523
+ case commands.mode.value.auto:
524
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get TargetHeaterCoolerState -> AUTO`);
525
+ return this.platform.Characteristic.TargetHeaterCoolerState.AUTO;
526
+ }
527
+ // not in heating-cooling mode (e.g. fan mode)
528
+ switch (this.accessory.context.TargetHeaterCoolerState) {
529
+ case this.platform.Characteristic.TargetHeaterCoolerState.COOL:
530
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get TargetHeaterCoolerState -> COOL`);
531
+ break;
532
+ case this.platform.Characteristic.TargetHeaterCoolerState.HEAT:
533
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get TargetHeaterCoolerState -> HEAT`);
534
+ break;
535
+ case this.platform.Characteristic.TargetHeaterCoolerState.AUTO:
536
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get TargetHeaterCoolerState -> AUTO`);
537
+ break;
538
+ }
539
+ return this.accessory.context.TargetHeaterCoolerState;
540
+ }
541
+ async getCurrentTemperature(service) {
542
+ const currentValue = this.currentTemperature;
543
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get ${service} CurrentTemperature ->`, currentValue);
544
+ return currentValue;
545
+ }
546
+ async getTargetTemperature(target) {
547
+ const currentValue = this.targetTemperature;
548
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get ${target} ->`, currentValue);
549
+ return currentValue;
550
+ }
551
+ async getTemperatureDisplayUnits() {
552
+ const currentValue = (this.units === commands.units.value.celsius) ?
553
+ this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS : this.platform.Characteristic.TemperatureDisplayUnits.FAHRENHEIT;
554
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get TemperatureDisplayUnits ->`, (currentValue === this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS) ? 'CELSIUS' : 'FAHRENHEIT');
555
+ return currentValue;
556
+ }
557
+ async getSwingMode() {
558
+ switch (this.swingMode || commands.swingVertical.value.default) {
559
+ case commands.swingVertical.value.default:
560
+ case commands.swingVertical.value.fixedHighest:
561
+ case commands.swingVertical.value.fixedHigher:
562
+ case commands.swingVertical.value.fixedMiddle:
563
+ case commands.swingVertical.value.fixedLower:
564
+ case commands.swingVertical.value.fixedLowest:
565
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get SwingMode -> DISABLED`);
566
+ return this.platform.Characteristic.SwingMode.SWING_DISABLED;
567
+ }
568
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get SwingMode -> ENABLED`);
569
+ return this.platform.Characteristic.SwingMode.SWING_ENABLED;
570
+ }
571
+ async getRotationSpeed() {
572
+ const maxSpeed = this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.maxValue ||
573
+ this.deviceConfig.speedSteps + 3;
574
+ if (this.quietMode === commands.quietMode.value.on) {
575
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get Heater-Cooler RotationSpeed -> 1 (quiet)`);
576
+ return 1;
577
+ }
578
+ if (this.powerfulMode === commands.powerfulMode.value.on) {
579
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get Heater-Cooler RotationSpeed -> ${maxSpeed} (powerful)`);
580
+ return maxSpeed;
581
+ }
582
+ let value = 2; // default to auto
583
+ let logValue = this.getKeyName(commands.speed.value, commands.speed.value.auto);
584
+ switch (this.speed) {
585
+ case commands.speed.value.low:
586
+ value = 3;
587
+ logValue = this.getKeyName(commands.speed.value, commands.speed.value.low);
588
+ break;
589
+ case commands.speed.value.mediumLow:
590
+ value = 4;
591
+ logValue = this.getKeyName(commands.speed.value, (maxSpeed === 8) ? commands.speed.value.mediumLow : commands.speed.value.medium);
592
+ break;
593
+ case commands.speed.value.medium:
594
+ value = (maxSpeed === 8) ? 5 : 4;
595
+ logValue = this.getKeyName(commands.speed.value, commands.speed.value.medium);
596
+ break;
597
+ case commands.speed.value.mediumHigh:
598
+ value = (maxSpeed === 8) ? 6 : 4;
599
+ logValue = this.getKeyName(commands.speed.value, (maxSpeed === 8) ? commands.speed.value.mediumHigh : commands.speed.value.medium);
600
+ break;
601
+ case commands.speed.value.high:
602
+ value = (maxSpeed === 8) ? 7 : 5;
603
+ logValue = this.getKeyName(commands.speed.value, commands.speed.value.high);
604
+ break;
605
+ }
606
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get Heater-Cooler RotationSpeed ->`, value + ' (' + logValue + ')');
607
+ return value;
608
+ }
609
+ async getFanRotationSpeed() {
610
+ const minStep = this.Fan?.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.minStep ||
611
+ 100 / (this.deviceConfig.speedSteps + 1);
612
+ let value = 100; // default to auto
613
+ let logValueName = this.getKeyName(commands.speed.value, commands.speed.value.auto);
614
+ switch (this.speed) {
615
+ case commands.speed.value.low:
616
+ value = minStep;
617
+ logValueName = this.getKeyName(commands.speed.value, commands.speed.value.low);
618
+ break;
619
+ case commands.speed.value.mediumLow:
620
+ value = 2 * minStep;
621
+ logValueName = this.getKeyName(commands.speed.value, (minStep !== 25) ? commands.speed.value.mediumLow : commands.speed.value.medium);
622
+ break;
623
+ case commands.speed.value.medium:
624
+ value = (minStep !== 25 ? 3 : 2) * minStep;
625
+ logValueName = this.getKeyName(commands.speed.value, commands.speed.value.medium);
626
+ break;
627
+ case commands.speed.value.mediumHigh:
628
+ value = (minStep !== 25 ? 4 : 2) * minStep;
629
+ logValueName = this.getKeyName(commands.speed.value, (minStep !== 25) ? commands.speed.value.mediumHigh : commands.speed.value.medium);
630
+ break;
631
+ case commands.speed.value.high:
632
+ value = (minStep !== 25 ? 5 : 3) * minStep;
633
+ logValueName = this.getKeyName(commands.speed.value, commands.speed.value.high);
634
+ break;
635
+ }
636
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get Fan RotationSpeed -> ${Math.round(value)}% (${logValueName})`);
637
+ return value;
638
+ }
639
+ async getName() {
640
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get Name ->`, this.accessory.displayName);
641
+ return this.accessory.displayName;
642
+ }
643
+ // helper functions
644
+ isSilentTime() {
645
+ const currentTime = new Date();
646
+ const currentTimeNum = currentTime.getHours() * 100 + currentTime.getMinutes();
647
+ return (this.silentTimeRanges !== undefined &&
648
+ this.silentTimeRanges.find((element) => element[0] <= currentTimeNum && currentTimeNum < element[1]) !== undefined);
649
+ }
650
+ getDeviceLabel() {
651
+ return `${this.accessory.displayName} -- ${this.accessory.context.device.address}`;
652
+ }
653
+ getCols() {
654
+ if (!this.cols) {
655
+ this.cols = Object.keys(commands).map((k) => commands[k].code);
656
+ }
657
+ return this.cols;
658
+ }
659
+ getKeyName(obj, value) {
660
+ let name = '';
661
+ if (obj !== undefined) {
662
+ Object.entries(obj).find(([key, val]) => {
663
+ if (val === value) {
664
+ name = key;
665
+ return true;
666
+ }
667
+ return false;
668
+ });
669
+ }
670
+ return name;
671
+ }
672
+ getValueName(obj, code, value) {
673
+ let name;
674
+ if (obj !== undefined) {
675
+ const command = Object.values(obj).find(c => c.code === code);
676
+ if (command && command.value !== undefined) {
677
+ Object.entries(command.value).find(([key, val]) => {
678
+ if (val === value) {
679
+ name = key;
680
+ return true;
681
+ }
682
+ return false;
683
+ });
684
+ }
685
+ }
686
+ return name;
687
+ }
688
+ getCommandName(obj, code) {
689
+ let name;
690
+ if (obj !== undefined) {
691
+ Object.entries(obj).find(([key, val]) => {
692
+ if (val && val.code === code) {
693
+ name = key;
694
+ return true;
695
+ }
696
+ return false;
697
+ });
698
+ }
699
+ return name;
700
+ }
701
+ calcDeviceTargetTemp(temp, unit) {
702
+ if (unit === commands.units.value.celsius ||
703
+ (unit === undefined && this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits).value ===
704
+ this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS)) {
705
+ return Math.floor(temp);
706
+ }
707
+ if (temp >= 15.25 && temp < 15.75) {
708
+ // execption
709
+ return 15;
710
+ }
711
+ const baseTemp = Math.round(temp);
712
+ const baseFahrenheit = temp * 9 / 5 + 32;
713
+ const baseFahrenheitDecimalPart = baseFahrenheit - Math.floor(baseFahrenheit);
714
+ const correction = (baseFahrenheitDecimalPart >= 0.05 && baseFahrenheitDecimalPart < 0.15) ||
715
+ (baseFahrenheitDecimalPart >= 0.25 && baseFahrenheitDecimalPart < 0.35) ? 1 : 0;
716
+ return baseTemp - correction;
717
+ }
718
+ calcDeviceTargetOffset(temp, unit) {
719
+ if (unit === commands.units.value.celsius ||
720
+ (unit === undefined && this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits).value ===
721
+ this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS)) {
722
+ return 0;
723
+ }
724
+ if (temp === 16) {
725
+ // exception
726
+ return 0;
727
+ }
728
+ const baseFahrenheit = temp * 9 / 5 + 32;
729
+ const baseFahrenheitDecimalPart = baseFahrenheit - Math.floor(baseFahrenheit);
730
+ const offset = (((baseFahrenheitDecimalPart >= 0.05 && baseFahrenheitDecimalPart < 0.15) ||
731
+ (baseFahrenheitDecimalPart >= 0.25 && baseFahrenheitDecimalPart < 0.35) ||
732
+ (baseFahrenheitDecimalPart >= 0.55 && baseFahrenheitDecimalPart < 0.65) ||
733
+ (baseFahrenheitDecimalPart >= 0.75 && baseFahrenheitDecimalPart < 0.85)) ? 1 : 0);
734
+ return temp >= 15.25 && temp < 16.25 ? 1 - offset : offset;
735
+ }
736
+ getTargetTempFromDevice(temp, offset, unit) {
737
+ let targetValue;
738
+ const heatingTargetValue = this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).value || 25;
739
+ const coolingTargetValue = this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).value || 25;
740
+ switch (this.mode) {
741
+ case commands.mode.value.heat:
742
+ targetValue = heatingTargetValue;
743
+ break;
744
+ case commands.mode.value.cool:
745
+ targetValue = coolingTargetValue;
746
+ break;
747
+ default:
748
+ targetValue = (coolingTargetValue + heatingTargetValue) / 2;
749
+ break;
750
+ }
751
+ if (unit === commands.units.value.celsius) {
752
+ if (Math.floor(targetValue) === +temp && targetValue !== +temp) {
753
+ this.platform.log.debug(`[${this.getDeviceLabel()}] TargetTemperature FIX: %f -> %f`, +temp, targetValue);
754
+ return targetValue;
755
+ }
756
+ return +temp;
757
+ }
758
+ const key = temp.toString() + ',' + offset.toString();
759
+ const value = TEMPERATURE_TABLE[key];
760
+ if (value === undefined) {
761
+ this.platform.log.debug(`[${this.getDeviceLabel()}] TargetTemperature FIX: invalid -> %f`, +temp);
762
+ return +temp; // invalid temperature-offset pair received from device -> return temperature value
763
+ }
764
+ // some temperature values are the same on the physical AC unit -> fix this issue:
765
+ if ((targetValue === 12.5 && value === 13) || (targetValue === 17.5 && value === 18) ||
766
+ (targetValue === 22.5 && value === 23) || (targetValue === 27.5 && value === 28)) {
767
+ this.platform.log.debug(`[${this.getDeviceLabel()}] TargetTemperature FIX: %f -> %f`, value, targetValue);
768
+ return targetValue;
769
+ }
770
+ // no fix needed, return original value
771
+ return value;
772
+ }
773
+ // device functions
774
+ get power() {
775
+ return (this.status[commands.power.code] === commands.power.value.on);
776
+ }
777
+ set power(value) {
778
+ if ((value === this.power && [commands.mode.value.cool, commands.mode.value.heat, commands.mode.value.auto].includes(this.mode)) ||
779
+ this.powerPending !== -1 || this.modePending !== -1) {
780
+ this.platform.log.debug(`[${this.getDeviceLabel()}] power -> no change (${this.power}, ${this.powerPending}, ${this.mode},`, `${this.modePending})`);
781
+ return;
782
+ }
783
+ if (!value && ![commands.mode.value.cool, commands.mode.value.heat, commands.mode.value.auto].includes(this.mode)) {
784
+ this.platform.log.debug(`[${this.getDeviceLabel()}] power -> set inactive but no power off (${this.mode})`);
785
+ return;
786
+ }
787
+ const powerValue = value ? commands.power.value.on : commands.power.value.off;
788
+ const command = {};
789
+ let logValue = '';
790
+ if (value !== this.power) {
791
+ command[commands.power.code] = powerValue;
792
+ logValue += (logValue ? ', ' : '') + 'power -> ' + this.getKeyName(commands.power.value, powerValue);
793
+ }
794
+ if (powerValue === commands.power.value.on) {
795
+ switch (this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState).value ||
796
+ this.accessory.context.TargetHeaterCoolerState) {
797
+ case this.platform.Characteristic.TargetHeaterCoolerState.COOL:
798
+ if (this.mode !== commands.mode.value.cool) {
799
+ command[commands.mode.code] = commands.mode.value.cool;
800
+ logValue += (logValue ? ', ' : '') + 'mode -> ' + this.getKeyName(commands.mode.value, commands.mode.value.cool);
801
+ if (this.deviceConfig.xFanEnabled && (this.status[commands.xFan.code] || commands.xFan.value.off) !== commands.xFan.value.on) {
802
+ // turn on xFan in Cool mode if xFan is enabled for this device
803
+ logValue += (logValue ? ', ' : '') + 'xFan -> ' + this.getKeyName(commands.xFan.value, commands.xFan.value.on);
804
+ command[commands.xFan.code] = commands.xFan.value.on;
805
+ }
806
+ }
807
+ break;
808
+ case this.platform.Characteristic.TargetHeaterCoolerState.HEAT:
809
+ if (this.mode !== commands.mode.value.heat) {
810
+ command[commands.mode.code] = commands.mode.value.heat;
811
+ logValue += (logValue ? ', ' : '') + 'mode -> ' + this.getKeyName(commands.mode.value, commands.mode.value.heat);
812
+ if (this.deviceConfig.xFanEnabled && (this.status[commands.xFan.code] || commands.xFan.value.on) !== commands.xFan.value.off) {
813
+ // turn off xFan in unsupported modes (only Cool and Dry modes support xFan)
814
+ logValue += (logValue ? ', ' : '') + 'xFan -> ' + this.getKeyName(commands.xFan.value, commands.xFan.value.off);
815
+ command[commands.xFan.code] = commands.xFan.value.off;
816
+ }
817
+ }
818
+ break;
819
+ case this.platform.Characteristic.TargetHeaterCoolerState.AUTO:
820
+ if (this.mode !== commands.mode.value.auto) {
821
+ command[commands.mode.code] = commands.mode.value.auto;
822
+ logValue += (logValue ? ', ' : '') + 'mode -> ' + this.getKeyName(commands.mode.value, commands.mode.value.auto);
823
+ if (this.deviceConfig.xFanEnabled && (this.status[commands.xFan.code] || commands.xFan.value.on) !== commands.xFan.value.off) {
824
+ // turn off xFan in unsupported modes (only Cool and Dry modes support xFan)
825
+ logValue += (logValue ? ', ' : '') + 'xFan -> ' + this.getKeyName(commands.xFan.value, commands.xFan.value.off);
826
+ command[commands.xFan.code] = commands.xFan.value.off;
827
+ }
828
+ }
829
+ break;
830
+ }
831
+ }
832
+ if (logValue) {
833
+ if (powerValue === commands.power.value.on) {
834
+ if (this.accessory.context.HeaterCoolerRotationSpeed !== 0) {
835
+ // restore rotation speed on power on
836
+ const maxSpeed = this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.maxValue ||
837
+ this.deviceConfig.speedSteps + 3;
838
+ switch (this.accessory.context.HeaterCoolerRotationSpeed) {
839
+ case 1: // quiet
840
+ if ([this.platform.Characteristic.TargetHeaterCoolerState.COOL, this.platform.Characteristic.TargetHeaterCoolerState.HEAT]
841
+ .includes(this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState).value ||
842
+ this.accessory.context.TargetHeaterCoolerState)) {
843
+ command[commands.quietMode.code] = commands.quietMode.value.on;
844
+ logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
845
+ this.getKeyName(commands.quietMode.value, commands.quietMode.value.on);
846
+ }
847
+ else {
848
+ command[commands.quietMode.code] = commands.quietMode.value.off;
849
+ logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
850
+ this.getKeyName(commands.quietMode.value, commands.quietMode.value.off);
851
+ }
852
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.off;
853
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
854
+ this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.off);
855
+ command[commands.speed.code] = commands.speed.value.low;
856
+ logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands.speed.value, commands.speed.value.low);
857
+ break;
858
+ case 2: // auto
859
+ if (this.quietMode !== commands.quietMode.value.off || this.powerfulMode !== commands.powerfulMode.value.off) {
860
+ command[commands.quietMode.code] = commands.quietMode.value.off;
861
+ logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
862
+ this.getKeyName(commands.quietMode.value, commands.quietMode.value.off);
863
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.off;
864
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
865
+ this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.off);
866
+ }
867
+ command[commands.speed.code] = commands.speed.value.auto;
868
+ logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands.speed.value, commands.speed.value.auto);
869
+ break;
870
+ case 3: // low
871
+ if (this.quietMode !== commands.quietMode.value.off || this.powerfulMode !== commands.powerfulMode.value.off) {
872
+ command[commands.quietMode.code] = commands.quietMode.value.off;
873
+ logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
874
+ this.getKeyName(commands.quietMode.value, commands.quietMode.value.off);
875
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.off;
876
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
877
+ this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.off);
878
+ }
879
+ command[commands.speed.code] = commands.speed.value.low;
880
+ logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands.speed.value, commands.speed.value.low);
881
+ break;
882
+ case 4: // mediumLow / medium
883
+ if (this.quietMode !== commands.quietMode.value.off || this.powerfulMode !== commands.powerfulMode.value.off) {
884
+ command[commands.quietMode.code] = commands.quietMode.value.off;
885
+ logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
886
+ this.getKeyName(commands.quietMode.value, commands.quietMode.value.off);
887
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.off;
888
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
889
+ this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.off);
890
+ }
891
+ command[commands.speed.code] = maxSpeed === 8 ? commands.speed.value.mediumLow : commands.speed.value.medium;
892
+ logValue += (logValue ? ', ' : '') + 'speed -> ' +
893
+ this.getKeyName(commands.speed.value, command[commands.speed.code]);
894
+ break;
895
+ case 5: // medium / high
896
+ if (this.quietMode !== commands.quietMode.value.off || this.powerfulMode !== commands.powerfulMode.value.off) {
897
+ command[commands.quietMode.code] = commands.quietMode.value.off;
898
+ logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
899
+ this.getKeyName(commands.quietMode.value, commands.quietMode.value.off);
900
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.off;
901
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
902
+ this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.off);
903
+ }
904
+ command[commands.speed.code] = maxSpeed === 8 ? commands.speed.value.medium : commands.speed.value.high;
905
+ logValue += (logValue ? ', ' : '') + 'speed -> ' +
906
+ this.getKeyName(commands.speed.value, command[commands.speed.code]);
907
+ break;
908
+ case 6: // mediumHigh / powerful
909
+ if (maxSpeed === 8) {
910
+ if (this.quietMode !== commands.quietMode.value.off || this.powerfulMode !== commands.powerfulMode.value.off) {
911
+ command[commands.quietMode.code] = commands.quietMode.value.off;
912
+ logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
913
+ this.getKeyName(commands.quietMode.value, commands.quietMode.value.off);
914
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.off;
915
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
916
+ this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.off);
917
+ }
918
+ command[commands.speed.code] = commands.speed.value.mediumHigh;
919
+ logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands.speed.value, commands.speed.value.mediumHigh);
920
+ }
921
+ else {
922
+ command[commands.quietMode.code] = commands.quietMode.value.off;
923
+ logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
924
+ this.getKeyName(commands.quietMode.value, commands.quietMode.value.off);
925
+ if ([this.platform.Characteristic.TargetHeaterCoolerState.COOL, this.platform.Characteristic.TargetHeaterCoolerState.HEAT]
926
+ .includes(this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState).value ||
927
+ this.accessory.context.TargetHeaterCoolerState)) {
928
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.on;
929
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
930
+ this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.on);
931
+ }
932
+ else {
933
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.off;
934
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
935
+ this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.off);
936
+ }
937
+ command[commands.speed.code] = commands.speed.value.high;
938
+ logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands.speed.value, commands.speed.value.high);
939
+ }
940
+ break;
941
+ case 7: // high
942
+ if (this.quietMode !== commands.quietMode.value.off || this.powerfulMode !== commands.powerfulMode.value.off) {
943
+ command[commands.quietMode.code] = commands.quietMode.value.off;
944
+ logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
945
+ this.getKeyName(commands.quietMode.value, commands.quietMode.value.off);
946
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.off;
947
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
948
+ this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.off);
949
+ }
950
+ command[commands.speed.code] = commands.speed.value.high;
951
+ logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands.speed.value, commands.speed.value.high);
952
+ break;
953
+ case 8: // powerful
954
+ command[commands.quietMode.code] = commands.quietMode.value.off;
955
+ logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
956
+ this.getKeyName(commands.quietMode.value, commands.quietMode.value.off);
957
+ if ([this.platform.Characteristic.TargetHeaterCoolerState.COOL, this.platform.Characteristic.TargetHeaterCoolerState.HEAT]
958
+ .includes(this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState).value ||
959
+ this.accessory.context.TargetHeaterCoolerState)) {
960
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.on;
961
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
962
+ this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.on);
963
+ }
964
+ else {
965
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.off;
966
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
967
+ this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.off);
968
+ }
969
+ command[commands.speed.code] = commands.speed.value.high;
970
+ logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands.speed.value, commands.speed.value.high);
971
+ break;
972
+ }
973
+ }
974
+ if (([MODIFY_VERTICAL_SWING_POSITION.overrideDefPowerOnOscDisable, MODIFY_VERTICAL_SWING_POSITION.overrideDefPowerOn].includes(this.deviceConfig.modifyVerticalSwingPosition || DEFAULT_DEVICE_CONFIG.modifyVerticalSwingPosition) &&
975
+ this.swingMode === commands.swingVertical.value.default) || ([MODIFY_VERTICAL_SWING_POSITION.setPowerOnOscDisable,
976
+ MODIFY_VERTICAL_SWING_POSITION.setPowerOn].includes(this.deviceConfig.modifyVerticalSwingPosition ||
977
+ DEFAULT_DEVICE_CONFIG.modifyVerticalSwingPosition))) {
978
+ const value = this.deviceConfig.defaultVerticalSwing || DEFAULT_DEVICE_CONFIG.defaultVerticalSwing;
979
+ command[commands.swingVertical.code] = value;
980
+ logValue += (logValue ? ', ' : '') + 'swingVertical -> ' + this.getKeyName(commands.swingVertical.value, value);
981
+ }
982
+ }
983
+ this.platform.log.info(`[${this.getDeviceLabel()}]`, logValue);
984
+ this.sendCommand(command);
985
+ }
986
+ }
987
+ set fanpower(value) {
988
+ if (this.powerPending !== -1 || this.modePending !== -1) {
989
+ this.platform.log.debug(`[${this.getDeviceLabel()}] fanpower -> no change (${this.powerPending}, ${this.modePending})`);
990
+ return;
991
+ }
992
+ if (!value && this.mode !== commands.mode.value.fan) {
993
+ this.platform.log.debug(`[${this.getDeviceLabel()}] fanpower -> set inactive but no power off (${this.mode})`);
994
+ return;
995
+ }
996
+ const powerValue = value ? commands.power.value.on : commands.power.value.off;
997
+ const command = {};
998
+ let logValue = '';
999
+ if (value !== this.power) {
1000
+ command[commands.power.code] = powerValue;
1001
+ logValue += (logValue ? ', ' : '') + 'power -> ' + this.getKeyName(commands.power.value, powerValue);
1002
+ }
1003
+ if (powerValue === commands.power.value.on && this.mode !== commands.mode.value.fan) {
1004
+ command[commands.mode.code] = commands.mode.value.fan;
1005
+ logValue += (logValue ? ', ' : '') + 'mode -> ' + this.getKeyName(commands.mode.value, commands.mode.value.fan);
1006
+ }
1007
+ if (logValue) {
1008
+ if (powerValue === commands.power.value.on) {
1009
+ command[commands.quietMode.code] = commands.quietMode.value.off;
1010
+ logValue += (logValue ? ', ' : '') + 'quietMode -> ' + this.getKeyName(commands.quietMode.value, commands.quietMode.value.off);
1011
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.off;
1012
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1013
+ this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.off);
1014
+ if ([MODIFY_VERTICAL_SWING_POSITION.overrideDefPowerOnOscDisable, MODIFY_VERTICAL_SWING_POSITION.overrideDefPowerOn].includes(this.deviceConfig.modifyVerticalSwingPosition || DEFAULT_DEVICE_CONFIG.modifyVerticalSwingPosition) &&
1015
+ this.swingMode === commands.swingVertical.value.default) {
1016
+ const value = this.deviceConfig.defaultVerticalSwing || DEFAULT_DEVICE_CONFIG.defaultVerticalSwing;
1017
+ command[commands.swingVertical.code] = value;
1018
+ logValue += (logValue ? ', ' : '') + 'swingVertical -> ' + this.getKeyName(commands.swingVertical.value, value);
1019
+ }
1020
+ else if ([MODIFY_VERTICAL_SWING_POSITION.setPowerOnOscDisable, MODIFY_VERTICAL_SWING_POSITION.setPowerOn].includes(this.deviceConfig.modifyVerticalSwingPosition || DEFAULT_DEVICE_CONFIG.modifyVerticalSwingPosition)) {
1021
+ const value = this.deviceConfig.defaultFanVerticalSwing || DEFAULT_DEVICE_CONFIG.defaultFanVerticalSwing;
1022
+ command[commands.swingVertical.code] = value;
1023
+ logValue += (logValue ? ', ' : '') + 'swingVertical -> ' + this.getKeyName(commands.swingVertical.value, value);
1024
+ }
1025
+ }
1026
+ this.platform.log.info(`[${this.getDeviceLabel()}]`, logValue);
1027
+ this.sendCommand(command);
1028
+ }
1029
+ }
1030
+ get mode() {
1031
+ return this.status[commands.mode.code] || commands.mode.value.auto;
1032
+ }
1033
+ set mode(value) {
1034
+ if (value === this.mode || this.modePending !== -1) {
1035
+ this.platform.log.debug(`[${this.getDeviceLabel()}] mode -> no change (${value}, ${this.modePending})`);
1036
+ return;
1037
+ }
1038
+ let logValue = 'mode -> ' + this.getKeyName(commands.mode.value, value);
1039
+ const command = { [commands.mode.code]: value };
1040
+ if (this.deviceConfig.xFanEnabled && (this.status[commands.xFan.code] || commands.xFan.value.off) !== commands.xFan.value.on &&
1041
+ [commands.mode.value.cool, commands.mode.value.dry].includes(value)) {
1042
+ // turn on xFan in Cool and Dry mode if xFan is enabled for this device
1043
+ logValue += ', xFan -> ' + this.getKeyName(commands.xFan.value, commands.xFan.value.on);
1044
+ command[commands.xFan.code] = commands.xFan.value.on;
1045
+ }
1046
+ else if (this.deviceConfig.xFanEnabled && (this.status[commands.xFan.code] || commands.xFan.value.on) !== commands.xFan.value.off &&
1047
+ ![commands.mode.value.cool, commands.mode.value.dry].includes(value)) {
1048
+ // turn off xFan in unsupported modes (only Cool and Dry modes support xFan)
1049
+ logValue += ', xFan -> ' + this.getKeyName(commands.xFan.value, commands.xFan.value.off);
1050
+ command[commands.xFan.code] = commands.xFan.value.off;
1051
+ }
1052
+ if (this.accessory.context.HeaterCoolerRotationSpeed !== 0 &&
1053
+ [commands.mode.value.cool, commands.mode.value.heat, commands.mode.value.auto].includes(value)) {
1054
+ // restore rotation speed on mode change
1055
+ const maxSpeed = this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.maxValue ||
1056
+ this.deviceConfig.speedSteps + 3;
1057
+ switch (this.accessory.context.HeaterCoolerRotationSpeed) {
1058
+ case 1: // quiet
1059
+ command[commands.quietMode.code] = value === commands.mode.value.auto ? commands.quietMode.value.off :
1060
+ commands.quietMode.value.on;
1061
+ logValue += (logValue ? ', ' : '') + 'quietMode -> ' + this.getKeyName(commands.quietMode.value, value === commands.mode.value.auto ? commands.quietMode.value.off : commands.quietMode.value.on);
1062
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.off;
1063
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1064
+ this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.off);
1065
+ command[commands.speed.code] = commands.speed.value.low;
1066
+ logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands.speed.value, commands.speed.value.low);
1067
+ break;
1068
+ case 2: // auto
1069
+ if (this.quietMode !== commands.quietMode.value.off || this.powerfulMode !== commands.powerfulMode.value.off) {
1070
+ command[commands.quietMode.code] = commands.quietMode.value.off;
1071
+ logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1072
+ this.getKeyName(commands.quietMode.value, commands.quietMode.value.off);
1073
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.off;
1074
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1075
+ this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.off);
1076
+ }
1077
+ command[commands.speed.code] = commands.speed.value.auto;
1078
+ logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands.speed.value, commands.speed.value.auto);
1079
+ break;
1080
+ case 3: // low
1081
+ if (this.quietMode !== commands.quietMode.value.off || this.powerfulMode !== commands.powerfulMode.value.off) {
1082
+ command[commands.quietMode.code] = commands.quietMode.value.off;
1083
+ logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1084
+ this.getKeyName(commands.quietMode.value, commands.quietMode.value.off);
1085
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.off;
1086
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1087
+ this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.off);
1088
+ }
1089
+ command[commands.speed.code] = commands.speed.value.low;
1090
+ logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands.speed.value, commands.speed.value.low);
1091
+ break;
1092
+ case 4: // mediumLow / medium
1093
+ if (this.quietMode !== commands.quietMode.value.off || this.powerfulMode !== commands.powerfulMode.value.off) {
1094
+ command[commands.quietMode.code] = commands.quietMode.value.off;
1095
+ logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1096
+ this.getKeyName(commands.quietMode.value, commands.quietMode.value.off);
1097
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.off;
1098
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1099
+ this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.off);
1100
+ }
1101
+ command[commands.speed.code] = maxSpeed === 8 ? commands.speed.value.mediumLow : commands.speed.value.medium;
1102
+ logValue += (logValue ? ', ' : '') + 'speed -> ' +
1103
+ this.getKeyName(commands.speed.value, command[commands.speed.code]);
1104
+ break;
1105
+ case 5: // medium / high
1106
+ if (this.quietMode !== commands.quietMode.value.off || this.powerfulMode !== commands.powerfulMode.value.off) {
1107
+ command[commands.quietMode.code] = commands.quietMode.value.off;
1108
+ logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1109
+ this.getKeyName(commands.quietMode.value, commands.quietMode.value.off);
1110
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.off;
1111
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1112
+ this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.off);
1113
+ }
1114
+ command[commands.speed.code] = maxSpeed === 8 ? commands.speed.value.medium : commands.speed.value.high;
1115
+ logValue += (logValue ? ', ' : '') + 'speed -> ' +
1116
+ this.getKeyName(commands.speed.value, command[commands.speed.code]);
1117
+ break;
1118
+ case 6: // mediumHigh / powerful
1119
+ if (maxSpeed === 8) {
1120
+ if (this.quietMode !== commands.quietMode.value.off || this.powerfulMode !== commands.powerfulMode.value.off) {
1121
+ command[commands.quietMode.code] = commands.quietMode.value.off;
1122
+ logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1123
+ this.getKeyName(commands.quietMode.value, commands.quietMode.value.off);
1124
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.off;
1125
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1126
+ this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.off);
1127
+ }
1128
+ command[commands.speed.code] = commands.speed.value.mediumHigh;
1129
+ logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands.speed.value, commands.speed.value.mediumHigh);
1130
+ }
1131
+ else {
1132
+ command[commands.quietMode.code] = commands.quietMode.value.off;
1133
+ logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1134
+ this.getKeyName(commands.quietMode.value, commands.quietMode.value.off);
1135
+ command[commands.powerfulMode.code] = value === commands.mode.value.auto ? commands.powerfulMode.value.off :
1136
+ commands.powerfulMode.value.on;
1137
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1138
+ this.getKeyName(commands.powerfulMode.value, value === commands.mode.value.auto ? commands.powerfulMode.value.off :
1139
+ commands.powerfulMode.value.on);
1140
+ command[commands.speed.code] = commands.speed.value.high;
1141
+ logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands.speed.value, commands.speed.value.high);
1142
+ }
1143
+ break;
1144
+ case 7: // high
1145
+ if (this.quietMode !== commands.quietMode.value.off || this.powerfulMode !== commands.powerfulMode.value.off) {
1146
+ command[commands.quietMode.code] = commands.quietMode.value.off;
1147
+ logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1148
+ this.getKeyName(commands.quietMode.value, commands.quietMode.value.off);
1149
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.off;
1150
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1151
+ this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.off);
1152
+ }
1153
+ command[commands.speed.code] = commands.speed.value.high;
1154
+ logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands.speed.value, commands.speed.value.high);
1155
+ break;
1156
+ case 8: // powerful
1157
+ if ([commands.mode.value.cool, commands.mode.value.heat].includes(value)) {
1158
+ command[commands.quietMode.code] = commands.quietMode.value.off;
1159
+ logValue += (logValue ? ', ' : '') + 'quietMode -> ' +
1160
+ this.getKeyName(commands.quietMode.value, commands.quietMode.value.off);
1161
+ command[commands.powerfulMode.code] = value === commands.mode.value.auto ? commands.powerfulMode.value.off :
1162
+ commands.powerfulMode.value.on;
1163
+ logValue += (logValue ? ', ' : '') + 'powerfulMode -> ' +
1164
+ this.getKeyName(commands.powerfulMode.value, value === commands.mode.value.auto ? commands.powerfulMode.value.off :
1165
+ commands.powerfulMode.value.on);
1166
+ }
1167
+ command[commands.speed.code] = commands.speed.value.high;
1168
+ logValue += (logValue ? ', ' : '') + 'speed -> ' + this.getKeyName(commands.speed.value, commands.speed.value.high);
1169
+ break;
1170
+ }
1171
+ }
1172
+ this.platform.log.info(`[${this.getDeviceLabel()}]`, logValue);
1173
+ this.sendCommand(command);
1174
+ }
1175
+ get currentTemperature() {
1176
+ return this.status[commands.temperature.code] - (this.deviceConfig.sensorOffset) || 25;
1177
+ }
1178
+ get targetTemperature() {
1179
+ let minValue = this.deviceConfig.minimumTargetTemperature;
1180
+ let maxValue = this.deviceConfig.maximumTargetTemperature;
1181
+ switch (this.mode) {
1182
+ case commands.mode.value.cool:
1183
+ minValue = Math.max(this.deviceConfig.minimumTargetTemperature, this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).props.minValue || 10);
1184
+ maxValue = Math.min(this.deviceConfig.maximumTargetTemperature, this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).props.maxValue || 35);
1185
+ break;
1186
+ case commands.mode.value.heat:
1187
+ minValue = Math.max(this.deviceConfig.minimumTargetTemperature, this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).props.minValue || 0);
1188
+ maxValue = Math.min(this.deviceConfig.maximumTargetTemperature, this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).props.maxValue || 25);
1189
+ break;
1190
+ case commands.mode.value.auto:
1191
+ minValue = Math.max(this.deviceConfig.minimumTargetTemperature, Math.min(this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).props.minValue || 10, this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).props.minValue || 0));
1192
+ maxValue = Math.min(this.deviceConfig.maximumTargetTemperature, Math.max(this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).props.maxValue || 35, this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).props.maxValue || 25));
1193
+ }
1194
+ return Math.max(Math.min(this.getTargetTempFromDevice(this.status[commands.targetTemperature.code] || 25, this.status[commands.temperatureOffset.code] || 0, this.status[commands.units.code]), maxValue), minValue);
1195
+ }
1196
+ set targetTemperature(value) {
1197
+ if (value === this.targetTemperature) {
1198
+ this.platform.log.debug(`[${this.getDeviceLabel()}] targetTemperature -> no change (${value})`);
1199
+ return;
1200
+ }
1201
+ const tempValue = this.calcDeviceTargetTemp(value);
1202
+ const command = { [commands.targetTemperature.code]: tempValue };
1203
+ let logValue = 'targetTemperature -> ' + tempValue.toString();
1204
+ const tempOffset = this.calcDeviceTargetOffset(value);
1205
+ command[commands.temperatureOffset.code] = tempOffset;
1206
+ logValue += ', temperatureOffset -> ' + tempOffset.toString();
1207
+ const displayUnits = this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits).value;
1208
+ const deviceDisplayUnits = (displayUnits === this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS) ?
1209
+ commands.units.value.celsius : commands.units.value.fahrenheit;
1210
+ if (deviceDisplayUnits === commands.units.value.fahrenheit) {
1211
+ logValue += ' (-> ' + Math.round(value * 9 / 5 + 32).toString() + ' °F)';
1212
+ }
1213
+ else {
1214
+ logValue += ' (-> ' + value.toString() + ' °C)';
1215
+ }
1216
+ if (deviceDisplayUnits !== this.units) {
1217
+ command[commands.units.code] = deviceDisplayUnits;
1218
+ logValue += ', units -> ' + this.getKeyName(commands.units.value, deviceDisplayUnits);
1219
+ }
1220
+ this.platform.log.info(`[${this.getDeviceLabel()}]`, logValue);
1221
+ this.sendCommand(command);
1222
+ }
1223
+ get units() {
1224
+ return this.status[commands.units.code] || commands.units.value.celsius;
1225
+ }
1226
+ set units(value) {
1227
+ if (value === this.units) {
1228
+ this.platform.log.debug(`[${this.getDeviceLabel()}] units -> no change (${value})`);
1229
+ return;
1230
+ }
1231
+ const command = { [commands.units.code]: value };
1232
+ let logValue = 'units -> ' + this.getKeyName(commands.units.value, value);
1233
+ // convert target temperature to new unit
1234
+ const actTemp = this.getTargetTempFromDevice(this.status[commands.targetTemperature.code], this.status[commands.temperatureOffset.code], this.units);
1235
+ const tempValue = this.calcDeviceTargetTemp(actTemp, value);
1236
+ if (tempValue !== this.status[commands.targetTemperature.code]) {
1237
+ command[commands.targetTemperature.code] = tempValue;
1238
+ logValue += ', targetTemperature -> ' + tempValue.toString();
1239
+ }
1240
+ const tempOffset = this.calcDeviceTargetOffset(actTemp, value);
1241
+ if (tempOffset !== this.status[commands.temperatureOffset.code]) {
1242
+ command[commands.temperatureOffset.code] = tempOffset;
1243
+ logValue += ', temperatureOffset -> ' + tempOffset.toString();
1244
+ }
1245
+ this.platform.log.info(`[${this.getDeviceLabel()}]`, logValue);
1246
+ this.sendCommand(command);
1247
+ }
1248
+ get swingMode() {
1249
+ return this.status[commands.swingVertical.code] || commands.swingVertical.value.default;
1250
+ }
1251
+ set swingMode(value) {
1252
+ if (value === this.swingMode) {
1253
+ this.platform.log.debug(`[${this.getDeviceLabel()}] swingMode -> no change (${value})`);
1254
+ return;
1255
+ }
1256
+ const command = { [commands.swingVertical.code]: value };
1257
+ this.platform.log.info(`[${this.getDeviceLabel()}] swingVertical ->`, this.getKeyName(commands.swingVertical.value, value));
1258
+ this.sendCommand(command);
1259
+ }
1260
+ get speed() {
1261
+ return this.status[commands.speed.code] || commands.speed.value.auto;
1262
+ }
1263
+ set speed(value) {
1264
+ if (value === this.speed && this.quietMode === commands.quietMode.value.off && this.powerfulMode === commands.powerfulMode.value.off) {
1265
+ this.platform.log.debug(`[${this.getDeviceLabel()}] speed -> no change (${value}, ${this.quietMode}, ${this.powerfulMode})`);
1266
+ return;
1267
+ }
1268
+ const command = { [commands.speed.code]: value };
1269
+ command[commands.quietMode.code] = commands.quietMode.value.off;
1270
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.off;
1271
+ this.platform.log.info(`[${this.getDeviceLabel()}] speed ->`, this.getKeyName(commands.speed.value, value) +
1272
+ ', quietMode -> ' + this.getKeyName(commands.quietMode.value, commands.quietMode.value.off) +
1273
+ ', powerfulMode -> ' + this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.off));
1274
+ this.sendCommand(command);
1275
+ }
1276
+ get quietMode() {
1277
+ return this.status[commands.quietMode.code] || commands.quietMode.value.off;
1278
+ }
1279
+ set quietMode(value) {
1280
+ if (value === this.quietMode || value !== commands.quietMode.value.on) {
1281
+ this.platform.log.debug(`[${this.getDeviceLabel()}] quietMode -> not turning on (${value})`);
1282
+ return;
1283
+ }
1284
+ let logValue = '';
1285
+ const command = {};
1286
+ if ([this.platform.Characteristic.TargetHeaterCoolerState.COOL, this.platform.Characteristic.TargetHeaterCoolerState.HEAT]
1287
+ .includes(this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState).value ||
1288
+ this.accessory.context.TargetHeaterCoolerState)) {
1289
+ command[commands.quietMode.code] = value;
1290
+ logValue += 'quietMode -> ' + this.getKeyName(commands.quietMode.value, value);
1291
+ }
1292
+ else {
1293
+ // quiet mode is supported only in heating and cooling mode
1294
+ command[commands.quietMode.code] = commands.quietMode.value.off;
1295
+ logValue += 'quietMode -> ' + this.getKeyName(commands.quietMode.value, commands.quietMode.value.off);
1296
+ }
1297
+ if (value === commands.quietMode.value.on) {
1298
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.off;
1299
+ logValue += ', powerfulMode -> ' + this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.off);
1300
+ command[commands.speed.code] = commands.speed.value.low;
1301
+ logValue += ', speed -> ' + this.getKeyName(commands.speed.value, commands.speed.value.low);
1302
+ this.platform.log.info(`[${this.getDeviceLabel()}]`, logValue);
1303
+ this.sendCommand(command);
1304
+ }
1305
+ }
1306
+ get powerfulMode() {
1307
+ return this.status[commands.powerfulMode.code] || commands.powerfulMode.value.off;
1308
+ }
1309
+ set powerfulMode(value) {
1310
+ if (value === this.powerfulMode || value !== commands.powerfulMode.value.on) {
1311
+ this.platform.log.debug(`[${this.getDeviceLabel()}] powerfulMode -> not turning on (${value})`);
1312
+ return;
1313
+ }
1314
+ let logValue = '';
1315
+ const command = {};
1316
+ if ([this.platform.Characteristic.TargetHeaterCoolerState.COOL, this.platform.Characteristic.TargetHeaterCoolerState.HEAT]
1317
+ .includes(this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState).value ||
1318
+ this.accessory.context.TargetHeaterCoolerState)) {
1319
+ command[commands.powerfulMode.code] = value;
1320
+ logValue += 'powerfulMode -> ' + this.getKeyName(commands.powerfulMode.value, value);
1321
+ }
1322
+ else {
1323
+ // powerful mode is supported only in heating and cooling mode
1324
+ command[commands.powerfulMode.code] = commands.powerfulMode.value.off;
1325
+ logValue += 'powerfulMode -> ' + this.getKeyName(commands.powerfulMode.value, commands.powerfulMode.value.off);
1326
+ }
1327
+ if (value === commands.powerfulMode.value.on) {
1328
+ command[commands.quietMode.code] = commands.quietMode.value.off;
1329
+ logValue += ', quietMode -> ' + this.getKeyName(commands.quietMode.value, commands.quietMode.value.off);
1330
+ command[commands.speed.code] = commands.speed.value.high;
1331
+ logValue += ', speed -> ' + this.getKeyName(commands.speed.value, commands.speed.value.high);
1332
+ this.platform.log.info(`[${this.getDeviceLabel()}]`, logValue);
1333
+ this.sendCommand(command);
1334
+ }
1335
+ }
1336
+ updateStatus(props) {
1337
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus -> %j`, props);
1338
+ const hcActive = this.power && [commands.mode.value.cool, commands.mode.value.heat, commands.mode.value.auto].includes(this.mode);
1339
+ const fanActive = this.power && this.mode === commands.mode.value.fan;
1340
+ // Heater-Cooler Active
1341
+ if (props.includes(commands.power.code) || props.includes(commands.mode.code)) {
1342
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Heater-Cooler Active) ->`, hcActive ? 'ACTIVE' : 'INACTIVE');
1343
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.Active)
1344
+ .updateValue(hcActive ? this.platform.Characteristic.Active.ACTIVE : this.platform.Characteristic.Active.INACTIVE);
1345
+ }
1346
+ // Fan Active
1347
+ if (this.Fan && (props.includes(commands.power.code) || props.includes(commands.mode.code))) {
1348
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Fan Active) ->`, fanActive ? 'ACTIVE' : 'INACTIVE');
1349
+ this.Fan?.getCharacteristic(this.platform.Characteristic.Active)
1350
+ .updateValue(fanActive ? this.platform.Characteristic.Active.ACTIVE : this.platform.Characteristic.Active.INACTIVE);
1351
+ }
1352
+ // Current Heater-Cooler State
1353
+ if (props.includes(commands.mode.code)) {
1354
+ if (this.power) {
1355
+ switch (this.mode) {
1356
+ case commands.mode.value.cool:
1357
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Heater-Cooler State) -> COOLING`);
1358
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState)
1359
+ .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.COOLING);
1360
+ break;
1361
+ case commands.mode.value.heat:
1362
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Heater-Cooler State) -> HEATING`);
1363
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState)
1364
+ .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.HEATING);
1365
+ break;
1366
+ case commands.mode.value.auto:
1367
+ if (this.currentTemperature > this.targetTemperature + 1.5) {
1368
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Heater-Cooler State) -> COOLING`);
1369
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState)
1370
+ .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.COOLING);
1371
+ }
1372
+ else if (this.currentTemperature < this.targetTemperature - 1.5) {
1373
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Heater-Cooler State) -> HEATING`);
1374
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState)
1375
+ .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.HEATING);
1376
+ }
1377
+ else {
1378
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Heater-Cooler State) -> IDLE`);
1379
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState)
1380
+ .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.IDLE);
1381
+ }
1382
+ break;
1383
+ }
1384
+ }
1385
+ else {
1386
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Heater-Cooler State) -> INACTIVE`);
1387
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState)
1388
+ .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.INACTIVE);
1389
+ }
1390
+ }
1391
+ // Current Fan State
1392
+ if (this.Fan && props.includes(commands.mode.code)) {
1393
+ if (this.power && this.mode === commands.mode.value.fan) {
1394
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Fan State) -> BLOWING_AIR`);
1395
+ this.Fan?.getCharacteristic(this.platform.Characteristic.CurrentFanState)
1396
+ .updateValue(this.platform.Characteristic.CurrentFanState.BLOWING_AIR);
1397
+ }
1398
+ else {
1399
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Fan State) -> INACTIVE`);
1400
+ this.Fan?.getCharacteristic(this.platform.Characteristic.CurrentFanState)
1401
+ .updateValue(this.platform.Characteristic.CurrentFanState.INACTIVE);
1402
+ }
1403
+ }
1404
+ // Target Heater-Cooler State
1405
+ if (props.includes(commands.mode.code) && this.power &&
1406
+ [commands.mode.value.cool, commands.mode.value.heat, commands.mode.value.auto].includes(this.mode)) {
1407
+ switch (this.mode) {
1408
+ case commands.mode.value.cool:
1409
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Target Heater-Cooler State) -> COOL`);
1410
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState)
1411
+ .updateValue(this.platform.Characteristic.TargetHeaterCoolerState.COOL);
1412
+ this.accessory.context.TargetHeaterCoolerState = this.platform.Characteristic.TargetHeaterCoolerState.COOL;
1413
+ break;
1414
+ case commands.mode.value.heat:
1415
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Target Heater-Cooler State) -> HEAT`);
1416
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState)
1417
+ .updateValue(this.platform.Characteristic.TargetHeaterCoolerState.HEAT);
1418
+ this.accessory.context.TargetHeaterCoolerState = this.platform.Characteristic.TargetHeaterCoolerState.HEAT;
1419
+ break;
1420
+ case commands.mode.value.auto:
1421
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Target Heater-Cooler State) -> AUTO`);
1422
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState)
1423
+ .updateValue(this.platform.Characteristic.TargetHeaterCoolerState.AUTO);
1424
+ this.accessory.context.TargetHeaterCoolerState = this.platform.Characteristic.TargetHeaterCoolerState.AUTO;
1425
+ break;
1426
+ }
1427
+ this.platform.api.updatePlatformAccessories([this.accessory]);
1428
+ }
1429
+ // Current Temperature
1430
+ if (props.includes(commands.temperature.code)) {
1431
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Temperature) ->`, this.currentTemperature);
1432
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.CurrentTemperature)
1433
+ .updateValue(this.currentTemperature);
1434
+ this.TemperatureSensor?.getCharacteristic(this.platform.Characteristic.CurrentTemperature)
1435
+ .updateValue(this.currentTemperature);
1436
+ this.tsAccessory?.setCurrentTemperature(this.currentTemperature);
1437
+ this.tsAccessory?.TemperatureSensor.getCharacteristic(this.platform.Characteristic.CurrentTemperature)
1438
+ .updateValue(this.currentTemperature);
1439
+ }
1440
+ else if (props.includes(commands.targetTemperature.code) && this.TemperatureSensor === undefined) {
1441
+ // temperature is not accessible -> targetTemperature is saved as currentTemperature
1442
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Temperature) ->`, this.currentTemperature);
1443
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.CurrentTemperature)
1444
+ .updateValue(this.currentTemperature);
1445
+ }
1446
+ // Cooling Threshold Temperature
1447
+ if (props.includes(commands.targetTemperature.code) && this.power &&
1448
+ (this.mode === commands.mode.value.cool || this.mode === commands.mode.value.auto)) {
1449
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Cooling Threshold Temperature) ->`, this.targetTemperature);
1450
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature)
1451
+ .updateValue(this.targetTemperature);
1452
+ }
1453
+ // Heating Threshold Temperature
1454
+ if (props.includes(commands.targetTemperature.code) && this.power &&
1455
+ (this.mode === commands.mode.value.heat || this.mode === commands.mode.value.auto)) {
1456
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Heating Threshold Temperature) ->`, this.targetTemperature);
1457
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature)
1458
+ .updateValue(this.targetTemperature);
1459
+ }
1460
+ // Temperature Display Units
1461
+ if (props.includes(commands.units.code)) {
1462
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Temperature Display Units) ->`, this.units === commands.units.value.celsius ? 'CELSIUS' : 'FAHRENHEIT');
1463
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits)
1464
+ .updateValue(this.units === commands.units.value.celsius ?
1465
+ this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS : this.platform.Characteristic.TemperatureDisplayUnits.FAHRENHEIT);
1466
+ }
1467
+ // Swing Mode
1468
+ if (props.includes(commands.swingVertical.code) && this.power) {
1469
+ let swing = this.platform.Characteristic.SwingMode.SWING_ENABLED;
1470
+ let logValue = 'ENABLED';
1471
+ if ([commands.swingVertical.value.full, commands.swingVertical.value.swingHigher,
1472
+ commands.swingVertical.value.swingHighest, commands.swingVertical.value.swingLower, commands.swingVertical.value.swingLowest,
1473
+ commands.swingVertical.value.swingMiddle].includes(this.swingMode)) {
1474
+ logValue += ` (type: ${this.getKeyName(commands.swingVertical.value, this.swingMode)})`;
1475
+ }
1476
+ switch (this.swingMode) {
1477
+ case commands.swingVertical.value.default:
1478
+ case commands.swingVertical.value.fixedHighest:
1479
+ case commands.swingVertical.value.fixedHigher:
1480
+ case commands.swingVertical.value.fixedMiddle:
1481
+ case commands.swingVertical.value.fixedLower:
1482
+ case commands.swingVertical.value.fixedLowest:
1483
+ swing = this.platform.Characteristic.SwingMode.SWING_DISABLED;
1484
+ logValue = `DISABLED (position: ${this.getKeyName(commands.swingVertical.value, this.swingMode)})`;
1485
+ break;
1486
+ }
1487
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Swing Mode) ->`, logValue);
1488
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.SwingMode)
1489
+ .updateValue(swing);
1490
+ }
1491
+ // Heater-Cooler Rotation Speed
1492
+ if (hcActive) {
1493
+ const maxSpeed = this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.maxValue ||
1494
+ this.deviceConfig.speedSteps + 3;
1495
+ if (props.includes(commands.quietMode.code) && this.quietMode === commands.quietMode.value.on) {
1496
+ // quietMode -> on
1497
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Heater-Cooler Rotation Speed) -> 1 (quiet)`);
1498
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.RotationSpeed).updateValue(1);
1499
+ this.accessory.context.HeaterCoolerRotationSpeed = 1;
1500
+ }
1501
+ else if (props.includes(commands.powerfulMode.code) && this.powerfulMode === commands.powerfulMode.value.on) {
1502
+ // powerfulMode -> on
1503
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Heater-Cooler Rotation Speed) ->`, `${maxSpeed.toString()} (powerful)`);
1504
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.RotationSpeed).updateValue(maxSpeed);
1505
+ this.accessory.context.HeaterCoolerRotationSpeed = maxSpeed;
1506
+ }
1507
+ else if (props.includes(commands.speed.code)) {
1508
+ let speedValue = 2; // default: auto
1509
+ switch (this.speed) {
1510
+ case commands.speed.value.low:
1511
+ speedValue = 3;
1512
+ break;
1513
+ case commands.speed.value.mediumLow:
1514
+ speedValue = 4;
1515
+ break;
1516
+ case commands.speed.value.medium:
1517
+ speedValue = (maxSpeed === 8) ? 5 : 4;
1518
+ break;
1519
+ case commands.speed.value.mediumHigh:
1520
+ speedValue = (maxSpeed === 8) ? 6 : 4;
1521
+ break;
1522
+ case commands.speed.value.high:
1523
+ speedValue = (maxSpeed === 8) ? 7 : 5;
1524
+ break;
1525
+ }
1526
+ const speedName = this.getKeyName(commands.speed.value, this.speed);
1527
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Heater-Cooler Rotation Speed) ->`, `${speedValue.toString()} (${speedName})`);
1528
+ this.HeaterCooler?.getCharacteristic(this.platform.Characteristic.RotationSpeed).updateValue(speedValue);
1529
+ this.accessory.context.HeaterCoolerRotationSpeed = speedValue;
1530
+ }
1531
+ this.platform.api.updatePlatformAccessories([this.accessory]);
1532
+ }
1533
+ // Fan Rotation Speed
1534
+ if (fanActive) {
1535
+ const minStep = this.Fan?.getCharacteristic(this.platform.Characteristic.RotationSpeed).props.minStep ||
1536
+ 100 / (this.deviceConfig.speedSteps + 1);
1537
+ let fanSpeedValue = 100; // default: auto
1538
+ switch (this.speed) {
1539
+ case commands.speed.value.low:
1540
+ fanSpeedValue = minStep;
1541
+ break;
1542
+ case commands.speed.value.mediumLow:
1543
+ fanSpeedValue = 2 * minStep;
1544
+ break;
1545
+ case commands.speed.value.medium:
1546
+ fanSpeedValue = (minStep !== 25 ? 3 : 2) * minStep;
1547
+ break;
1548
+ case commands.speed.value.mediumHigh:
1549
+ fanSpeedValue = (minStep !== 25 ? 4 : 2) * minStep;
1550
+ break;
1551
+ case commands.speed.value.high:
1552
+ fanSpeedValue = (minStep !== 25 ? 5 : 3) * minStep;
1553
+ break;
1554
+ }
1555
+ const speedName = this.getKeyName(commands.speed.value, this.speed);
1556
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Fan Rotation Speed) ->`, `${Math.round(fanSpeedValue)}% (${speedName})`);
1557
+ this.Fan?.getCharacteristic(this.platform.Characteristic.RotationSpeed).updateValue(fanSpeedValue);
1558
+ }
1559
+ }
1560
+ // device communication functions
1561
+ handleMessage = (msg, rinfo) => {
1562
+ if (this.accessory.context.device.address === rinfo.address) {
1563
+ this.platform.log.debug(`[${this.getDeviceLabel()}] handleMessage -> %s`, msg.toString());
1564
+ this.platform.log.debug(`[${this.getDeviceLabel()}] handleMessage -> Encryption version: %i`, this.accessory.context.device.encryptionVersion);
1565
+ const message = JSON.parse(msg.toString());
1566
+ if (!message.pack) {
1567
+ this.platform.log.debug(`[${this.getDeviceLabel()}] handleMessage - Unknown message: %j`, message);
1568
+ this.platform.log.warn(`[${this.getDeviceLabel()}] Warning: handleMessage - Unknown response from device`);
1569
+ return;
1570
+ }
1571
+ let pack;
1572
+ if (this.accessory.context.device.encryptionVersion === 1) {
1573
+ pack = crypto.decrypt_v1(message.pack, message.i === 1 ? undefined : this.key);
1574
+ }
1575
+ else if (this.accessory.context.device.encryptionVersion === 2 && message.tag !== undefined) {
1576
+ pack = crypto.decrypt_v2(message.pack, message.tag, message.i === 1 ? undefined : this.key);
1577
+ }
1578
+ else {
1579
+ this.platform.log.debug(`[${this.getDeviceLabel()}] handleMessage - Unknown message: %j`, message);
1580
+ this.platform.log.warn(`[${this.getDeviceLabel()}] Warning: handleMessage - Unknown response from device`);
1581
+ return;
1582
+ }
1583
+ this.platform.log.debug(`[${this.getDeviceLabel()}] handleMessage - Package -> %j`, pack);
1584
+ switch (pack.t.toLowerCase()) {
1585
+ case 'bindok': // package type is binding confirmation
1586
+ if (!this.accessory.bound) {
1587
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Device binding in progress`);
1588
+ this.key = pack.key;
1589
+ this.initAccessory();
1590
+ this.accessory.bound = true;
1591
+ this.platform.log.success(`[${this.getDeviceLabel()}] Device is bound -> ${pack.mac} (`, (this.accessory.context.device.uid ?? 0).toString(), ')');
1592
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Device key -> ${this.key}`);
1593
+ this.requestDeviceStatus();
1594
+ setInterval(this.requestDeviceStatus.bind(this), this.deviceConfig.statusUpdateInterval * 1000); // statusUpdateInterval in seconds
1595
+ }
1596
+ else {
1597
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Binding response received from already bound device`);
1598
+ }
1599
+ break;
1600
+ case 'dat': // package type is device status
1601
+ if (this.accessory.bound) {
1602
+ let invalidTempFromDevice = false;
1603
+ pack.cols.forEach((col, i) => {
1604
+ if (col === commands.temperature.code && (pack.dat[i] <= 0 || pack.dat[i] >= 100)) {
1605
+ // temperature value outside of valid range (1-99 -> -39°C - +59°C) should be ignored (means: no sensor data)
1606
+ invalidTempFromDevice = true;
1607
+ }
1608
+ else {
1609
+ this.status[col] = pack.dat[i];
1610
+ }
1611
+ if (col === commands.power.code) {
1612
+ // power status received -> no more power change pending state
1613
+ this.powerPending = -1;
1614
+ }
1615
+ if (col === commands.mode.code) {
1616
+ // mode status received -> no more mode change pending state
1617
+ this.modePending = -1;
1618
+ }
1619
+ if (col === commands.buzzer.code && pack.dat[i] !== commands.buzzer.value.off && pack.dat[i] !== commands.buzzer.value.on &&
1620
+ this.silentTimeRanges !== undefined) {
1621
+ // invalid buzzer status -> disable silent time
1622
+ this.platform.log.warn(`[${this.getDeviceLabel()}] Warning: Device does not support command muting`);
1623
+ delete this.silentTimeRanges;
1624
+ }
1625
+ });
1626
+ if (this.silentTimeRanges !== undefined && pack.cols.find((col) => col === commands.buzzer.code) === undefined) {
1627
+ // status pack does not contain buzzer status -> disable silent time
1628
+ this.platform.log.warn(`[${this.getDeviceLabel()}] Warning: Device does not support command muting`);
1629
+ delete this.silentTimeRanges;
1630
+ }
1631
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Device status -> %j`, this.status);
1632
+ if (!pack.cols.includes(commands.temperature.code) || invalidTempFromDevice) {
1633
+ // temperature is not accessible -> use targetTemperature
1634
+ const targetTemp = this.status[commands.targetTemperature.code] !== undefined ?
1635
+ this.status[commands.targetTemperature.code] : 25; // use default if target temperature is also unknown
1636
+ this.status[commands.temperature.code] = targetTemp + this.deviceConfig.sensorOffset;
1637
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Current temperature not available`, '- Threshold temperature is used as current (' + commands.targetTemperature.code + '->' + commands.temperature.code + ')');
1638
+ if (this.TemperatureSensor !== undefined) {
1639
+ this.accessory.removeService(this.TemperatureSensor);
1640
+ this.TemperatureSensor = undefined;
1641
+ this.platform.log.debug(`[${this.getDeviceLabel()}] temperature is not accessible -> Temperature Sensor removed`);
1642
+ }
1643
+ }
1644
+ this.updateStatus(pack.cols);
1645
+ }
1646
+ break;
1647
+ case 'res': // package type is response
1648
+ if (this.accessory.bound) {
1649
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Device response`, pack.opt, pack.p || pack.val);
1650
+ const updatedParams = [];
1651
+ pack.opt.forEach((opt, i) => {
1652
+ const value = pack.p !== undefined ? pack.p[i] : pack.val[i];
1653
+ if (this.status[opt] !== value) {
1654
+ const cmd = this.getCommandName(commands, opt) || opt;
1655
+ const oldval = this.getValueName(commands, opt, this.status[opt]) || this.status[opt];
1656
+ const newval = this.getValueName(commands, opt, value) || value;
1657
+ updatedParams.push(`${cmd}: ${oldval} -> ${newval}`);
1658
+ }
1659
+ this.status[opt] = value;
1660
+ if (opt === commands.power.code) {
1661
+ // response to power command -> no more power change pending state
1662
+ this.powerPending = -1;
1663
+ }
1664
+ if (opt === commands.mode.code) {
1665
+ // response to mode command -> no more mode change pending state
1666
+ this.modePending = -1;
1667
+ }
1668
+ });
1669
+ if (updatedParams.length > 0) {
1670
+ this.platform.log.info(`[${this.getDeviceLabel()}] Device updated (%j)`, updatedParams);
1671
+ }
1672
+ this.updateStatus(pack.opt);
1673
+ }
1674
+ break;
1675
+ default:
1676
+ this.platform.log.debug(`[${this.getDeviceLabel()}] handleMessage - Unknown message: %j`, message);
1677
+ this.platform.log.warn(`[${this.getDeviceLabel()}] Warning: handleMessage - Unknown response from device`);
1678
+ break;
1679
+ }
1680
+ }
1681
+ };
1682
+ sendMessage(message) {
1683
+ this.platform.log.debug(`[${this.getDeviceLabel()}] sendMessage - Package -> %j`, message);
1684
+ this.platform.log.debug(`[${this.getDeviceLabel()}] sendMessage -> Encryption version: %i`, this.accessory.context.device.encryptionVersion);
1685
+ let pack, tag;
1686
+ if (this.accessory.context.device.encryptionVersion === 1) {
1687
+ pack = crypto.encrypt_v1(message, this.key);
1688
+ tag = '';
1689
+ }
1690
+ else if (this.accessory.context.device.encryptionVersion === 2) {
1691
+ const encrypted = crypto.encrypt_v2(message, this.key);
1692
+ pack = encrypted.pack;
1693
+ tag = encrypted.tag;
1694
+ }
1695
+ else {
1696
+ this.platform.log.warn(`[${this.getDeviceLabel()}] Warning: sendMessage -> Unsupported encryption version`);
1697
+ return;
1698
+ }
1699
+ const payload = (tag === '') ? {
1700
+ tcid: this.accessory.context.device.mac.substring(this.accessory.context.device.mac.indexOf('@') + 1),
1701
+ uid: this.accessory.context.device.uid ?? 0,
1702
+ t: 'pack',
1703
+ pack,
1704
+ i: this.key === undefined ? 1 : 0,
1705
+ cid: 'app',
1706
+ } : {
1707
+ tcid: this.accessory.context.device.mac.substring(this.accessory.context.device.mac.indexOf('@') + 1),
1708
+ uid: this.accessory.context.device.uid ?? 0,
1709
+ t: 'pack',
1710
+ pack,
1711
+ i: this.key === undefined ? 1 : 0,
1712
+ tag,
1713
+ cid: 'app',
1714
+ };
1715
+ try {
1716
+ const msg = JSON.stringify(payload);
1717
+ this.platform.log.debug(`[${this.getDeviceLabel()}] sendMessage`, msg);
1718
+ this.socket.send(msg, this.accessory.context.device.port, this.accessory.context.device.address);
1719
+ }
1720
+ catch (err) {
1721
+ this.platform.log.error(`[${this.getDeviceLabel()}] sendMessage - Error:`, err.message);
1722
+ }
1723
+ }
1724
+ sendBindRequest() {
1725
+ const message = {
1726
+ mac: this.accessory.context.device.mac.substring(this.accessory.context.device.mac.indexOf('@') + 1),
1727
+ t: 'bind',
1728
+ uid: this.accessory.context.device.mac.indexOf('@') < 0 ? 0 :
1729
+ this.accessory.context.device.mac.substring(0, this.accessory.context.device.mac.indexOf('@')),
1730
+ };
1731
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Bind to device -> ${this.accessory.context.device.mac}`);
1732
+ this.sendMessage(message);
1733
+ }
1734
+ sendCommand(cmd) {
1735
+ if (this.isSilentTime()) {
1736
+ // add buzzer off command if current time is in silent time range
1737
+ cmd[commands.buzzer.code] = commands.buzzer.value.off;
1738
+ }
1739
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Send commands -> %j`, cmd);
1740
+ const keys = Object.keys(cmd);
1741
+ const values = keys.map((k) => cmd[k]);
1742
+ const message = {
1743
+ t: 'cmd',
1744
+ opt: keys,
1745
+ p: values,
1746
+ };
1747
+ if (keys.includes(commands.power.code)) {
1748
+ this.powerPending = values[keys.indexOf(commands.power.code)];
1749
+ }
1750
+ if (keys.includes(commands.mode.code)) {
1751
+ this.modePending = values[keys.indexOf(commands.mode.code)];
1752
+ }
1753
+ this.sendMessage(message);
1754
+ }
1755
+ requestDeviceStatus() {
1756
+ const message = {
1757
+ mac: this.accessory.context.device.mac,
1758
+ t: 'status',
1759
+ cols: this.getCols(),
1760
+ };
1761
+ this.sendMessage(message);
1762
+ }
1763
+ }
1727
1764
  //# sourceMappingURL=platformAccessory.js.map