homebridge-gree-ac 1.0.2 → 2.0.1

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 (46) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/LICENSE +176 -21
  3. package/README.md +189 -42
  4. package/config.schema.json +277 -0
  5. package/dist/commands.d.ts +121 -0
  6. package/dist/commands.d.ts.map +1 -0
  7. package/dist/commands.js +123 -0
  8. package/dist/commands.js.map +1 -0
  9. package/dist/crypto.d.ts +6 -0
  10. package/dist/crypto.d.ts.map +1 -0
  11. package/dist/crypto.js +19 -0
  12. package/dist/crypto.js.map +1 -0
  13. package/dist/index.d.ts +7 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +7 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/platform.d.ts +35 -0
  18. package/dist/platform.d.ts.map +1 -0
  19. package/dist/platform.js +205 -0
  20. package/dist/platform.js.map +1 -0
  21. package/dist/platformAccessory.d.ts +90 -0
  22. package/dist/platformAccessory.d.ts.map +1 -0
  23. package/dist/platformAccessory.js +912 -0
  24. package/dist/platformAccessory.js.map +1 -0
  25. package/dist/settings.d.ts +52 -0
  26. package/dist/settings.d.ts.map +1 -0
  27. package/dist/settings.js +51 -0
  28. package/dist/settings.js.map +1 -0
  29. package/dist/tsAccessory.d.ts +36 -0
  30. package/dist/tsAccessory.d.ts.map +1 -0
  31. package/dist/tsAccessory.js +65 -0
  32. package/dist/tsAccessory.js.map +1 -0
  33. package/greedevice.jpg +0 -0
  34. package/greemac.jpg +0 -0
  35. package/package.json +51 -23
  36. package/uiconfig.jpg +0 -0
  37. package/.idea/homebridge-gree-ac.iml +0 -12
  38. package/.idea/misc.xml +0 -6
  39. package/.idea/modules.xml +0 -8
  40. package/.idea/vcs.xml +0 -6
  41. package/.idea/workspace.xml +0 -208
  42. package/app/commandEnums.js +0 -135
  43. package/app/deviceFactory.js +0 -306
  44. package/app/encryptionService.js +0 -39
  45. package/example.config.json +0 -28
  46. package/index.js +0 -373
@@ -0,0 +1,912 @@
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 crypto_1 = __importDefault(require("./crypto"));
10
+ const commands_1 = __importDefault(require("./commands"));
11
+ /**
12
+ * Platform Accessory
13
+ * An instance of this class is created for each accessory your platform registers
14
+ * Each accessory may expose multiple services of different service types.
15
+ */
16
+ class GreeAirConditioner {
17
+ constructor(platform, accessory, deviceConfig, port, platform_ts) {
18
+ var _a, _b, _c;
19
+ this.platform = platform;
20
+ this.accessory = accessory;
21
+ this.deviceConfig = deviceConfig;
22
+ this.port = port;
23
+ this.platform_ts = platform_ts;
24
+ // device communication functions
25
+ this.handleMessage = (msg, rinfo) => {
26
+ if (this.accessory.context.device.address === rinfo.address) {
27
+ const message = JSON.parse(msg.toString());
28
+ this.platform.log.debug(`[${this.getDeviceLabel()}] handleMessage -> %j`, message);
29
+ const pack = crypto_1.default.decrypt(message.pack, message.i === 1 ? undefined : this.key);
30
+ this.platform.log.debug(`[${this.getDeviceLabel()}] handleMessage - Package -> %j`, pack);
31
+ switch (pack.t) {
32
+ case 'bindok': // package type is binding confirmation
33
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Device binding`);
34
+ this.key = pack.key;
35
+ this.bound = true;
36
+ this.platform.log.info(`[${this.getDeviceLabel()}] Device is bound -> ${pack.mac}`);
37
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Device key -> ${this.key}`);
38
+ if (this.updateTimer) {
39
+ clearInterval(this.updateTimer);
40
+ }
41
+ this.requestDeviceStatus();
42
+ this.updateTimer = setInterval(this.requestDeviceStatus.bind(this), this.deviceConfig.statusUpdateInterval * 1000); // statusUpdateInterval in seconds
43
+ break;
44
+ case 'dat': // package type is device status
45
+ if (this.bound) {
46
+ pack.cols.forEach((col, i) => {
47
+ this.status[col] = pack.dat[i];
48
+ });
49
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Device status -> %j`, this.status);
50
+ if (!pack.cols.includes(commands_1.default.temperature.code) &&
51
+ pack.cols.includes(commands_1.default.targetTemperature.code)) {
52
+ // temperature is not accessible -> use targetTemperature
53
+ this.status[commands_1.default.temperature.code] = this.status[commands_1.default.targetTemperature.code] + this.deviceConfig.sensorOffset;
54
+ if (this.TemperatureSensor !== undefined) {
55
+ this.accessory.removeService(this.TemperatureSensor);
56
+ this.TemperatureSensor = undefined;
57
+ this.platform.log.debug(`[${this.getDeviceLabel()}] temperature is not accessible -> Temperature Sensor removed`);
58
+ }
59
+ }
60
+ this.updateStatus(pack.cols);
61
+ }
62
+ break;
63
+ case 'res': // package type is response
64
+ if (this.bound) {
65
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Device response`);
66
+ const updatedParams = [];
67
+ pack.opt.forEach((opt, i) => {
68
+ const value = pack.p !== undefined ? pack.p[i] : pack.val[i];
69
+ if (this.status[opt] !== value) {
70
+ updatedParams.push(`${this.getKeyName(commands_1.default, opt, 'code')}: ${this.status[opt]} -> ${value}`);
71
+ }
72
+ this.status[opt] = value;
73
+ });
74
+ if (updatedParams.length > 0) {
75
+ this.platform.log.info(`[${this.getDeviceLabel()}] Device updated (%j)`, updatedParams);
76
+ }
77
+ }
78
+ break;
79
+ }
80
+ }
81
+ };
82
+ this.platform.log.debug(`[${this.getDeviceLabel()}] deviceConfig -> %j`, deviceConfig);
83
+ // set accessory information
84
+ this.accessory.getService(this.platform.Service.AccessoryInformation)
85
+ .setCharacteristic(this.platform.Characteristic.Manufacturer, this.accessory.context.device.brand || 'Gree')
86
+ .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')
87
+ .setCharacteristic(this.platform.Characteristic.SerialNumber, this.accessory.context.device.mac)
88
+ .setCharacteristic(this.platform.Characteristic.FirmwareRevision, this.accessory.context.device.hid && this.accessory.context.device.hid.lastIndexOf('V') >= 0 &&
89
+ this.accessory.context.device.hid.lastIndexOf('V') < this.accessory.context.device.hid.lastIndexOf('.') ?
90
+ this.accessory.context.device.hid.substring(this.accessory.context.device.hid.lastIndexOf('V') + 1, this.accessory.context.device.hid.lastIndexOf('.')) : '1.0.0')
91
+ .setCharacteristic(this.platform.Characteristic.HardwareRevision, this.accessory.context.device.ver ?
92
+ this.accessory.context.device.ver.substring(this.accessory.context.device.ver.lastIndexOf('V') + 1) : '1.0.0');
93
+ // get the HeaterCooler service if it exists, otherwise create a new HeaterCooler service
94
+ // we don't use subtype because we add only one service with this type
95
+ this.HeaterCooler = this.accessory.getService(this.platform.Service.HeaterCooler) ||
96
+ this.accessory.addService(this.platform.Service.HeaterCooler, this.accessory.displayName, undefined);
97
+ this.HeaterCooler.displayName = this.accessory.displayName;
98
+ if (deviceConfig.temperatureSensor === 'child') {
99
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Add Temperature Sensor child service`);
100
+ this.TemperatureSensor = this.accessory.getService(this.platform.Service.TemperatureSensor) ||
101
+ this.accessory.addService(this.platform.Service.TemperatureSensor, 'Temperature Sensor - ' + this.accessory.displayName, undefined);
102
+ this.TemperatureSensor.displayName = 'Temperature Sensor - ' + this.accessory.displayName;
103
+ }
104
+ else {
105
+ const ts = this.accessory.getService(this.platform.Service.TemperatureSensor);
106
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Temperature Sensor child service not allowed%s`, (ts === null || ts === void 0 ? void 0 : ts.displayName) !== undefined ? ' (' + (ts === null || ts === void 0 ? void 0 : ts.displayName) + ')' : '');
107
+ if (ts !== undefined) {
108
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Remove Temperature Sensor child service (%s)`, ts.displayName);
109
+ this.accessory.removeService(ts);
110
+ }
111
+ }
112
+ this.HeaterCooler.setPrimaryService(true);
113
+ (_b = this.TemperatureSensor) === null || _b === void 0 ? void 0 : _b.setPrimaryService(false);
114
+ // each service must implement at-minimum the "required characteristics" for the given service type
115
+ // see https://developers.homebridge.io/#/service/HeaterCooler
116
+ // register handlers for the Active Characteristic
117
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.Active)
118
+ .onSet(this.setActive.bind(this))
119
+ .onGet(this.getActive.bind(this));
120
+ // register handlers for the Current Heater-Cooler State Characteristic
121
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState)
122
+ .onGet(this.getCurrentHeaterCoolerState.bind(this));
123
+ // register handlers for the Target Heater-Cooler State Characteristic
124
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState)
125
+ .onGet(this.getTargetHeaterCoolerState.bind(this))
126
+ .onSet(this.setTargetHeaterCoolerState.bind(this));
127
+ // register handlers for the Current Temperature Characteristic
128
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CurrentTemperature)
129
+ .onGet(this.getCurrentTemperature.bind(this, 'Heater Cooler'));
130
+ (_c = this.TemperatureSensor) === null || _c === void 0 ? void 0 : _c.getCharacteristic(this.platform.Characteristic.CurrentTemperature).onGet(this.getCurrentTemperature.bind(this, 'Temperature Sensor'));
131
+ // register handlers for the Cooling Threshold Temperature Characteristic
132
+ // (minValue and maxValue can't be set here, they need an active accessory in cooling sate to set)
133
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature)
134
+ .setProps({ minStep: 0.5 })
135
+ .onGet(this.getTargetTemperature.bind(this, 'CoolingThresholdTemperature'))
136
+ .onSet(this.setTargetTemperature.bind(this));
137
+ // register handlers for the Heating Threshold Temperature Characteristic
138
+ // (minValue and maxValue can't be set here, they need an active accessory in heating sate to set)
139
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature)
140
+ .setProps({ minStep: 0.5 })
141
+ .onGet(this.getTargetTemperature.bind(this, 'HeatingThresholdTemperature'))
142
+ .onSet(this.setTargetTemperature.bind(this));
143
+ // register handlers for the Temperature Display Units Characteristic
144
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits)
145
+ .onGet(this.getTemperatureDisplayUnits.bind(this))
146
+ .onSet(this.setTemperatureDisplayUnits.bind(this));
147
+ // register handlers for the Swing Mode Characteristic
148
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.SwingMode)
149
+ .onGet(this.getSwingMode.bind(this))
150
+ .onSet(this.setSwingMode.bind(this));
151
+ // register handlers for the Rotation Speed Characteristic
152
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.RotationSpeed)
153
+ .setProps({
154
+ minValue: 0,
155
+ maxValue: this.deviceConfig.speedSteps + 3,
156
+ minStep: 1
157
+ })
158
+ .onGet(this.getRotationSpeed.bind(this))
159
+ .onSet(this.setRotationSpeed.bind(this));
160
+ // initialize communication with device
161
+ this.status = {};
162
+ this.bound = false;
163
+ this.socket = dgram_1.default.createSocket({ type: 'udp4', reuseAddr: true });
164
+ this.socket.on('error', (err) => {
165
+ this.platform.log.error(`[${this.getDeviceLabel()}] Network`, err.message);
166
+ });
167
+ this.socket.on('message', this.handleMessage);
168
+ this.socket.bind(this.port + parseInt(this.accessory.context.device.address.split('.')[3]) + 1, '0.0.0.0', () => {
169
+ this.socket.setBroadcast(false);
170
+ this.sendBindRequest();
171
+ });
172
+ }
173
+ /**
174
+ * Handle "SET" requests from HomeKit
175
+ * These are sent when the user changes the state of an accessory
176
+ */
177
+ async setActive(value) {
178
+ const powerValue = (value === this.platform.Characteristic.Active.ACTIVE);
179
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set Active ->`, powerValue ? 'ACTIVE' : 'INACTIVE');
180
+ this.power = powerValue;
181
+ }
182
+ async setTargetHeaterCoolerState(value) {
183
+ let modeValue = commands_1.default.mode.value.auto;
184
+ let logValue = 'AUTO';
185
+ switch (value) {
186
+ case this.platform.Characteristic.TargetHeaterCoolerState.COOL:
187
+ modeValue = commands_1.default.mode.value.cool;
188
+ logValue = 'COOL';
189
+ break;
190
+ case this.platform.Characteristic.TargetHeaterCoolerState.HEAT:
191
+ modeValue = commands_1.default.mode.value.heat;
192
+ logValue = 'HEAT';
193
+ break;
194
+ }
195
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set TargetHeaterCoolerState ->`, logValue);
196
+ this.mode = modeValue;
197
+ }
198
+ async setTargetTemperature(value) {
199
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set ThresholdTemperature ->`, value);
200
+ this.targetTemperature = value;
201
+ }
202
+ async setTemperatureDisplayUnits(value) {
203
+ const logValue = (value === this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS) ? 'CELSIUS' : 'FAHRENHEIT';
204
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set TemperatureDisplayUnits ->`, logValue);
205
+ this.units = (value === this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS) ?
206
+ commands_1.default.units.value.celsius : commands_1.default.units.value.fahrenheit;
207
+ }
208
+ async setSwingMode(value) {
209
+ const logValue = (value === this.platform.Characteristic.SwingMode.SWING_ENABLED) ? 'ENABLED' : 'DISABLED';
210
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set SwingMode ->`, logValue);
211
+ this.swingMode = (value === this.platform.Characteristic.SwingMode.SWING_ENABLED) ?
212
+ commands_1.default.swingVertical.value.full : commands_1.default.swingVertical.value.default;
213
+ }
214
+ async setRotationSpeed(value) {
215
+ switch (value) {
216
+ case 1: // quiet
217
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set RotationSpeed ->`, value + ' (quiet)');
218
+ this.quietMode = commands_1.default.quietMode.value.on;
219
+ break;
220
+ case 2: // auto
221
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set RotationSpeed ->`, value +
222
+ ' (' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.auto) + ')');
223
+ this.speed = commands_1.default.speed.value.auto;
224
+ break;
225
+ case 3: // low
226
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set RotationSpeed ->`, value +
227
+ ' (' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.low) + ')');
228
+ this.speed = commands_1.default.speed.value.low;
229
+ break;
230
+ case 4: // mediumLow / medium
231
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set RotationSpeed ->`, value + ' (' +
232
+ this.getKeyName(commands_1.default.speed.value, (this.deviceConfig.speedSteps === 5) ? commands_1.default.speed.value.mediumLow : commands_1.default.speed.value.medium) + ')');
233
+ this.speed = (this.deviceConfig.speedSteps === 5) ? commands_1.default.speed.value.mediumLow : commands_1.default.speed.value.medium;
234
+ break;
235
+ case 5: // medium / high
236
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set RotationSpeed ->`, value + ' (' +
237
+ this.getKeyName(commands_1.default.speed.value, (this.deviceConfig.speedSteps === 5) ? commands_1.default.speed.value.medium : commands_1.default.speed.value.high) + ')');
238
+ this.speed = (this.deviceConfig.speedSteps === 5) ? commands_1.default.speed.value.medium : commands_1.default.speed.value.high;
239
+ break;
240
+ case 6: // mediumHigh / powerful
241
+ if (this.deviceConfig.speedSteps === 5) {
242
+ // mediumHigh
243
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set RotationSpeed ->`, value +
244
+ ' (' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.mediumHigh) + ')');
245
+ this.speed = commands_1.default.speed.value.mediumHigh;
246
+ }
247
+ else {
248
+ // powerful
249
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set RotationSpeed ->`, value + ' (powerful)');
250
+ this.powerfulMode = commands_1.default.powerfulMode.value.on;
251
+ }
252
+ break;
253
+ case 7: // high
254
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set RotationSpeed ->`, value +
255
+ ' (' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.high) + ')');
256
+ this.speed = commands_1.default.speed.value.high;
257
+ break;
258
+ case 8: // powerful
259
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set RotationSpeed ->`, value + ' (powerful)');
260
+ this.powerfulMode = commands_1.default.powerfulMode.value.on;
261
+ break;
262
+ default: // auto
263
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set RotationSpeed ->`, value +
264
+ ' (' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.auto) + ')');
265
+ this.speed = commands_1.default.speed.value.auto;
266
+ break;
267
+ }
268
+ }
269
+ /**
270
+ * Handle the "GET" requests from HomeKit
271
+ * These are sent when HomeKit wants to know the current state of the accessory
272
+ *
273
+ * GET requests should return as fast as possbile. A long delay here will result in
274
+ * HomeKit being unresponsive and a bad user experience in general.
275
+ *
276
+ * If your device takes time to respond you should update the status of your device
277
+ * asynchronously instead using the `updateCharacteristic` method instead.
278
+
279
+ * @example
280
+ * this.service.updateCharacteristic(this.platform.Characteristic.On, true)
281
+
282
+ * if you need to return an error to show the device as "Not Responding" in the Home app:
283
+ * throw new this.platform.api.hap.HapStatusError(this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
284
+ */
285
+ async getActive() {
286
+ const currentPower = this.power;
287
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get Active ->`, currentPower ? 'ACTIVE' : 'INACTIVE');
288
+ return currentPower ?
289
+ this.platform.Characteristic.Active.ACTIVE : this.platform.Characteristic.Active.INACTIVE;
290
+ }
291
+ async getCurrentHeaterCoolerState() {
292
+ if (this.power) {
293
+ switch (this.mode) {
294
+ case commands_1.default.mode.value.cool:
295
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentHeaterCoolerState -> COOLING`);
296
+ setTimeout(() => this.initThresholdTemperature(this.platform.Characteristic.CurrentHeaterCoolerState.COOLING), settings_1.INIT_TEMP_TRESHOLD_TIMEOUT);
297
+ return this.platform.Characteristic.CurrentHeaterCoolerState.COOLING;
298
+ case commands_1.default.mode.value.heat:
299
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentHeaterCoolerState -> HEATING`);
300
+ setTimeout(() => this.initThresholdTemperature(this.platform.Characteristic.CurrentHeaterCoolerState.HEATING), settings_1.INIT_TEMP_TRESHOLD_TIMEOUT);
301
+ return this.platform.Characteristic.CurrentHeaterCoolerState.HEATING;
302
+ case commands_1.default.mode.value.fan:
303
+ case commands_1.default.mode.value.dry:
304
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentHeaterCoolerState -> IDLE`);
305
+ return this.platform.Characteristic.CurrentHeaterCoolerState.IDLE;
306
+ case commands_1.default.mode.value.auto:
307
+ if (this.currentTemperature > this.status[commands_1.default.targetTemperature.code]) {
308
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentHeaterCoolerState -> COOLING`);
309
+ setTimeout(() => this.initThresholdTemperature(this.platform.Characteristic.CurrentHeaterCoolerState.COOLING), settings_1.INIT_TEMP_TRESHOLD_TIMEOUT);
310
+ return this.platform.Characteristic.CurrentHeaterCoolerState.COOLING;
311
+ }
312
+ if (this.currentTemperature < this.status[commands_1.default.targetTemperature.code]) {
313
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentHeaterCoolerState -> HEATING`);
314
+ setTimeout(() => this.initThresholdTemperature(this.platform.Characteristic.CurrentHeaterCoolerState.HEATING), settings_1.INIT_TEMP_TRESHOLD_TIMEOUT);
315
+ return this.platform.Characteristic.CurrentHeaterCoolerState.HEATING;
316
+ }
317
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentHeaterCoolerState -> IDLE`);
318
+ return this.platform.Characteristic.CurrentHeaterCoolerState.IDLE;
319
+ }
320
+ }
321
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentHeaterCoolerState -> INACTIVE`);
322
+ return this.platform.Characteristic.CurrentHeaterCoolerState.INACTIVE;
323
+ }
324
+ async getTargetHeaterCoolerState() {
325
+ switch (this.mode) {
326
+ case commands_1.default.mode.value.cool:
327
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get TargetHeaterCoolerState -> COOL`);
328
+ return this.platform.Characteristic.TargetHeaterCoolerState.COOL;
329
+ case commands_1.default.mode.value.heat:
330
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get TargetHeaterCoolerState -> HEAT`);
331
+ return this.platform.Characteristic.TargetHeaterCoolerState.HEAT;
332
+ }
333
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get TargetHeaterCoolerState -> AUTO`);
334
+ return this.platform.Characteristic.TargetHeaterCoolerState.AUTO;
335
+ }
336
+ async getCurrentTemperature(service) {
337
+ const currentValue = this.currentTemperature;
338
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get ${service} CurrentTemperature ->`, currentValue);
339
+ return currentValue;
340
+ }
341
+ async getTargetTemperature(target) {
342
+ const currentValue = this.targetTemperature;
343
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get ${target} ->`, currentValue);
344
+ return currentValue;
345
+ }
346
+ async getTemperatureDisplayUnits() {
347
+ const currentValue = (this.units === commands_1.default.units.value.celsius) ?
348
+ this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS : this.platform.Characteristic.TemperatureDisplayUnits.FAHRENHEIT;
349
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get TemperatureDisplayUnits ->`, (currentValue === this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS) ? 'CELSIUS' : 'FAHRENHEIT');
350
+ return currentValue;
351
+ }
352
+ async getSwingMode() {
353
+ switch (this.swingMode || commands_1.default.swingVertical.value.default) {
354
+ case commands_1.default.swingVertical.value.default:
355
+ case commands_1.default.swingVertical.value.fixedHighest:
356
+ case commands_1.default.swingVertical.value.fixedHigher:
357
+ case commands_1.default.swingVertical.value.fixedMiddle:
358
+ case commands_1.default.swingVertical.value.fixedLower:
359
+ case commands_1.default.swingVertical.value.fixedLowest:
360
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get SwingMode -> DISABLED`);
361
+ return this.platform.Characteristic.SwingMode.SWING_DISABLED;
362
+ }
363
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get SwingMode -> ENABLED`);
364
+ return this.platform.Characteristic.SwingMode.SWING_ENABLED;
365
+ }
366
+ async getRotationSpeed() {
367
+ if (this.quietMode === commands_1.default.quietMode.value.on) {
368
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get RotationSpeed -> 1 (quiet)`);
369
+ return 1;
370
+ }
371
+ if (this.powerfulMode === commands_1.default.powerfulMode.value.on) {
372
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get RotationSpeed ->`, (this.deviceConfig.speedSteps + 3) + ' (powerful)');
373
+ return this.deviceConfig.speedSteps + 3;
374
+ }
375
+ let value = 2; // default to auto
376
+ let logValue = this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.auto);
377
+ switch (this.speed) {
378
+ case commands_1.default.speed.value.low:
379
+ value = 3;
380
+ logValue = this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.low);
381
+ break;
382
+ case commands_1.default.speed.value.mediumLow:
383
+ value = 4;
384
+ logValue = this.getKeyName(commands_1.default.speed.value, (this.deviceConfig.speedSteps === 5) ? commands_1.default.speed.value.mediumLow : commands_1.default.speed.value.medium);
385
+ break;
386
+ case commands_1.default.speed.value.medium:
387
+ value = (this.deviceConfig.speedSteps === 5) ? 5 : 4;
388
+ logValue = this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.medium);
389
+ break;
390
+ case commands_1.default.speed.value.mediumHigh:
391
+ value = (this.deviceConfig.speedSteps === 5) ? 6 : 4;
392
+ logValue = this.getKeyName(commands_1.default.speed.value, (this.deviceConfig.speedSteps === 5) ? commands_1.default.speed.value.mediumHigh : commands_1.default.speed.value.medium);
393
+ break;
394
+ case commands_1.default.speed.value.high:
395
+ value = (this.deviceConfig.speedSteps === 5) ? 7 : 5;
396
+ logValue = this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.high);
397
+ break;
398
+ }
399
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Get RotationSpeed ->`, value + ' (' + logValue + ')');
400
+ return value;
401
+ }
402
+ // helper functions
403
+ initThresholdTemperature(HeaterCoolerState) {
404
+ switch (HeaterCoolerState) {
405
+ case this.platform.Characteristic.CurrentHeaterCoolerState.COOLING:
406
+ if (this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).props.minValue !==
407
+ this.deviceConfig.minimumTargetTemperature ||
408
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).props.maxValue !==
409
+ this.deviceConfig.maximumTargetTemperature) {
410
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set CoolingThresholdTemperature minValue -> %i, maxValue -> %i`, this.deviceConfig.minimumTargetTemperature, this.deviceConfig.maximumTargetTemperature);
411
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature)
412
+ .setProps({
413
+ minValue: this.deviceConfig.minimumTargetTemperature,
414
+ maxValue: this.deviceConfig.maximumTargetTemperature
415
+ });
416
+ }
417
+ break;
418
+ case this.platform.Characteristic.CurrentHeaterCoolerState.HEATING:
419
+ if (this.HeaterCooler.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).props.minValue !==
420
+ this.deviceConfig.minimumTargetTemperature ||
421
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).props.maxValue !==
422
+ this.deviceConfig.maximumTargetTemperature) {
423
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Set HeatingThresholdTemperature minValue -> %i, maxValue -> %i`, this.deviceConfig.minimumTargetTemperature, this.deviceConfig.maximumTargetTemperature);
424
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature)
425
+ .setProps({
426
+ minValue: this.deviceConfig.minimumTargetTemperature,
427
+ maxValue: this.deviceConfig.maximumTargetTemperature
428
+ });
429
+ }
430
+ break;
431
+ }
432
+ }
433
+ getDeviceLabel() {
434
+ return `${this.accessory.displayName} -- ${this.accessory.context.device.address}:${this.accessory.context.device.port}`;
435
+ }
436
+ getCols() {
437
+ if (!this.cols) {
438
+ this.cols = Object.keys(commands_1.default).map((k) => commands_1.default[k].code);
439
+ }
440
+ return this.cols;
441
+ }
442
+ getKeyName(obj, value, subkey) {
443
+ let name = '';
444
+ if (subkey === undefined) {
445
+ Object.entries(obj).find(([key, val]) => {
446
+ if (val === value) {
447
+ name = key;
448
+ return true;
449
+ }
450
+ return false;
451
+ });
452
+ }
453
+ else {
454
+ Object.entries(obj).find(([key, val]) => {
455
+ const v = val;
456
+ if (v[subkey] === value) {
457
+ name = key;
458
+ return true;
459
+ }
460
+ return false;
461
+ });
462
+ }
463
+ return name;
464
+ }
465
+ calcDeviceTargetTemp(temp) {
466
+ const baseTemp = Math.round(temp);
467
+ const baseFahrenheit = temp * 9 / 5 + 32;
468
+ const baseFahrenheitDecimalPart = baseFahrenheit - Math.floor(baseFahrenheit);
469
+ const correction = (baseFahrenheitDecimalPart >= 0.05 && baseFahrenheitDecimalPart < 0.15) ||
470
+ (baseFahrenheitDecimalPart >= 0.25 && baseFahrenheitDecimalPart < 0.35) ? 1 : 0;
471
+ return baseTemp - correction;
472
+ }
473
+ calcDeviceTargetOffset(temp) {
474
+ if (temp === 16) {
475
+ return 0;
476
+ }
477
+ const baseFahrenheit = temp * 9 / 5 + 32;
478
+ const baseFahrenheitDecimalPart = baseFahrenheit - Math.floor(baseFahrenheit);
479
+ return (((baseFahrenheitDecimalPart >= 0.05 && baseFahrenheitDecimalPart < 0.15) ||
480
+ (baseFahrenheitDecimalPart >= 0.25 && baseFahrenheitDecimalPart < 0.35) ||
481
+ (baseFahrenheitDecimalPart >= 0.55 && baseFahrenheitDecimalPart < 0.65) ||
482
+ (baseFahrenheitDecimalPart >= 0.75 && baseFahrenheitDecimalPart < 0.85)) ? 1 : 0);
483
+ }
484
+ getTargetTempFromDevice(temp, offset) {
485
+ const key = temp.toString() + ',' + offset.toString();
486
+ const value = settings_1.TEMPERATURE_TABLE[key];
487
+ if (value === undefined) {
488
+ return 25; // default value if invalid data received from device
489
+ }
490
+ // some temperature values are the same on the physical AC unit -> fix this issue:
491
+ const targetValue = this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).value ||
492
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).value;
493
+ if ((targetValue === 17.5 && value === 18) ||
494
+ (targetValue === 22.5 && value === 23) ||
495
+ (targetValue === 27.5 && value === 28)) {
496
+ this.platform.log.debug(`[${this.getDeviceLabel()}] TargetTemperature FIX: %d -> %d`, value, targetValue);
497
+ return targetValue;
498
+ }
499
+ // no fix needed, return original value
500
+ return value;
501
+ }
502
+ // device functions
503
+ get power() {
504
+ return (this.status[commands_1.default.power.code] === commands_1.default.power.value.on);
505
+ }
506
+ set power(value) {
507
+ if (value === this.power) {
508
+ return;
509
+ }
510
+ const powerValue = value ? commands_1.default.power.value.on : commands_1.default.power.value.off;
511
+ const command = { [commands_1.default.power.code]: powerValue };
512
+ let logValue = 'power -> ' + this.getKeyName(commands_1.default.power.value, powerValue);
513
+ if (powerValue === commands_1.default.power.value.on) {
514
+ switch (this.HeaterCooler.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState).value) {
515
+ case this.platform.Characteristic.TargetHeaterCoolerState.COOL:
516
+ if (this.status[commands_1.default.mode.code] !== commands_1.default.mode.value.cool) {
517
+ command[commands_1.default.mode.code] = commands_1.default.mode.value.cool;
518
+ logValue += ', mode -> ' + this.getKeyName(commands_1.default.mode.value, commands_1.default.mode.value.cool);
519
+ if (this.deviceConfig.xFanEnabled && (this.status[commands_1.default.xFan.code] || commands_1.default.xFan.value.off) !== commands_1.default.xFan.value.on) {
520
+ // turn on xFan in Cool mode if xFan is enabled for this device
521
+ logValue += ', xFan -> ' + this.getKeyName(commands_1.default.xFan.value, commands_1.default.xFan.value.on);
522
+ command[commands_1.default.xFan.code] = commands_1.default.xFan.value.on;
523
+ }
524
+ }
525
+ break;
526
+ case this.platform.Characteristic.TargetHeaterCoolerState.HEAT:
527
+ if (this.status[commands_1.default.mode.code] !== commands_1.default.mode.value.heat) {
528
+ command[commands_1.default.mode.code] = commands_1.default.mode.value.heat;
529
+ logValue += ', mode -> ' + this.getKeyName(commands_1.default.mode.value, commands_1.default.mode.value.heat);
530
+ }
531
+ break;
532
+ case this.platform.Characteristic.TargetHeaterCoolerState.AUTO:
533
+ if (this.status[commands_1.default.mode.code] !== commands_1.default.mode.value.auto) {
534
+ command[commands_1.default.mode.code] = commands_1.default.mode.value.auto;
535
+ logValue += ', mode -> ' + this.getKeyName(commands_1.default.mode.value, commands_1.default.mode.value.auto);
536
+ }
537
+ break;
538
+ }
539
+ }
540
+ this.platform.log.info(`[${this.getDeviceLabel()}]`, logValue);
541
+ this.sendCommand(command);
542
+ }
543
+ get mode() {
544
+ return this.status[commands_1.default.mode.code] || commands_1.default.mode.value.auto;
545
+ }
546
+ set mode(value) {
547
+ if (value === this.mode) {
548
+ return;
549
+ }
550
+ let logValue = 'mode -> ' + this.getKeyName(commands_1.default.mode.value, value);
551
+ const command = { [commands_1.default.mode.code]: value };
552
+ if (this.deviceConfig.xFanEnabled && (this.status[commands_1.default.xFan.code] || commands_1.default.xFan.value.off) !== commands_1.default.xFan.value.on &&
553
+ (value === commands_1.default.mode.value.cool || value === commands_1.default.mode.value.dry)) {
554
+ // turn on xFan in Cool and Dry mode if xFan is enabled for this device
555
+ logValue += ', xFan -> ' + this.getKeyName(commands_1.default.xFan.value, commands_1.default.xFan.value.on);
556
+ command[commands_1.default.xFan.code] = commands_1.default.xFan.value.on;
557
+ }
558
+ this.platform.log.info(`[${this.getDeviceLabel()}]`, logValue);
559
+ this.sendCommand(command);
560
+ }
561
+ get currentTemperature() {
562
+ return this.status[commands_1.default.temperature.code] - (this.deviceConfig.sensorOffset) || 25;
563
+ }
564
+ get targetTemperature() {
565
+ let minValue = this.deviceConfig.minimumTargetTemperature;
566
+ let maxValue = this.deviceConfig.maximumTargetTemperature;
567
+ switch (this.status[commands_1.default.mode.code]) {
568
+ case commands_1.default.mode.value.cool:
569
+ minValue = Math.max(this.deviceConfig.minimumTargetTemperature, this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).props.minValue || 10);
570
+ maxValue = Math.min(this.deviceConfig.maximumTargetTemperature, this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature).props.maxValue || 35);
571
+ break;
572
+ case commands_1.default.mode.value.heat:
573
+ minValue = Math.max(this.deviceConfig.minimumTargetTemperature, this.HeaterCooler.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).props.minValue || 0);
574
+ maxValue = Math.min(this.deviceConfig.maximumTargetTemperature, this.HeaterCooler.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature).props.maxValue || 25);
575
+ break;
576
+ }
577
+ return Math.max(Math.min(this.getTargetTempFromDevice(this.status[commands_1.default.targetTemperature.code] || 25, this.status[commands_1.default.temperatureOffset.code] || 0), (maxValue)), (minValue));
578
+ }
579
+ set targetTemperature(value) {
580
+ if (value === this.targetTemperature) {
581
+ return;
582
+ }
583
+ const tempValue = this.calcDeviceTargetTemp(value);
584
+ const command = { [commands_1.default.targetTemperature.code]: tempValue };
585
+ let logValue = 'targetTemperature -> ' + tempValue.toString();
586
+ const tempOffset = this.calcDeviceTargetOffset(value);
587
+ command[commands_1.default.temperatureOffset.code] = tempOffset;
588
+ logValue += ', temperatureOffset -> ' + tempOffset.toString();
589
+ const displayUnits = this.HeaterCooler.getCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits).value;
590
+ const deviceDisplayUnits = (displayUnits === this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS) ?
591
+ commands_1.default.units.value.celsius : commands_1.default.units.value.fahrenheit;
592
+ if (deviceDisplayUnits === commands_1.default.units.value.fahrenheit) {
593
+ logValue += ' (-> ' + Math.round(value * 9 / 5 + 32).toString() + ' °F)';
594
+ }
595
+ else {
596
+ logValue += ' (-> ' + value.toString() + ' °C)';
597
+ }
598
+ if (deviceDisplayUnits !== this.units) {
599
+ command[commands_1.default.units.code] = deviceDisplayUnits;
600
+ logValue += ', units -> ' + this.getKeyName(commands_1.default.units.value, deviceDisplayUnits);
601
+ }
602
+ this.platform.log.info(`[${this.getDeviceLabel()}]`, logValue);
603
+ this.sendCommand(command);
604
+ }
605
+ get units() {
606
+ return this.status[commands_1.default.units.code] || commands_1.default.units.value.celsius;
607
+ }
608
+ set units(value) {
609
+ if (value === this.units) {
610
+ return;
611
+ }
612
+ const command = { [commands_1.default.units.code]: value };
613
+ this.platform.log.info(`[${this.getDeviceLabel()}] units ->`, this.getKeyName(commands_1.default.units.value, value));
614
+ this.sendCommand(command);
615
+ }
616
+ get swingMode() {
617
+ return this.status[commands_1.default.swingVertical.code] || commands_1.default.swingVertical.value.default;
618
+ }
619
+ set swingMode(value) {
620
+ if (value === this.swingMode) {
621
+ return;
622
+ }
623
+ const command = { [commands_1.default.swingVertical.code]: value };
624
+ this.platform.log.info(`[${this.getDeviceLabel()}] swingVertical ->`, this.getKeyName(commands_1.default.swingVertical.value, value));
625
+ this.sendCommand(command);
626
+ }
627
+ get speed() {
628
+ return this.status[commands_1.default.speed.code] || commands_1.default.speed.value.auto;
629
+ }
630
+ set speed(value) {
631
+ if (value === this.speed) {
632
+ return;
633
+ }
634
+ const command = { [commands_1.default.speed.code]: value };
635
+ command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
636
+ command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
637
+ this.platform.log.info(`[${this.getDeviceLabel()}] speed ->`, this.getKeyName(commands_1.default.speed.value, value) +
638
+ ', quietMode -> ' + this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off) +
639
+ ', powerfulMode -> ' + this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off));
640
+ this.sendCommand(command);
641
+ }
642
+ get quietMode() {
643
+ return this.status[commands_1.default.quietMode.code] || commands_1.default.quietMode.value.off;
644
+ }
645
+ set quietMode(value) {
646
+ if (value === this.quietMode) {
647
+ return;
648
+ }
649
+ const command = { [commands_1.default.quietMode.code]: value };
650
+ let logValue = 'quietMode -> ' + this.getKeyName(commands_1.default.quietMode.value, value);
651
+ if (value === commands_1.default.quietMode.value.on) {
652
+ command[commands_1.default.powerfulMode.code] = commands_1.default.powerfulMode.value.off;
653
+ logValue += ', powerfulMode -> ' + this.getKeyName(commands_1.default.powerfulMode.value, commands_1.default.powerfulMode.value.off);
654
+ command[commands_1.default.speed.code] = commands_1.default.speed.value.low;
655
+ logValue += ', speed -> ' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.low);
656
+ }
657
+ else {
658
+ command[commands_1.default.speed.code] = commands_1.default.speed.value.auto;
659
+ logValue += ', speed -> ' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.auto);
660
+ }
661
+ this.platform.log.info(`[${this.getDeviceLabel()}]`, logValue);
662
+ this.sendCommand(command);
663
+ }
664
+ get powerfulMode() {
665
+ return this.status[commands_1.default.powerfulMode.code] || commands_1.default.powerfulMode.value.off;
666
+ }
667
+ set powerfulMode(value) {
668
+ if (value === this.powerfulMode) {
669
+ return;
670
+ }
671
+ let logValue = 'powerfulMode -> ' + this.getKeyName(commands_1.default.powerfulMode.value, value);
672
+ const command = { [commands_1.default.powerfulMode.code]: value };
673
+ if (value === commands_1.default.powerfulMode.value.on) {
674
+ command[commands_1.default.quietMode.code] = commands_1.default.quietMode.value.off;
675
+ logValue += ', quietMode -> ' + this.getKeyName(commands_1.default.quietMode.value, commands_1.default.quietMode.value.off);
676
+ command[commands_1.default.speed.code] = commands_1.default.speed.value.high;
677
+ logValue += ', speed -> ' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.high);
678
+ }
679
+ else {
680
+ command[commands_1.default.speed.code] = commands_1.default.speed.value.auto;
681
+ logValue += ', speed -> ' + this.getKeyName(commands_1.default.speed.value, commands_1.default.speed.value.auto);
682
+ }
683
+ this.platform.log.info(`[${this.getDeviceLabel()}]`, logValue);
684
+ this.sendCommand(command);
685
+ }
686
+ updateStatus(props) {
687
+ var _a, _b, _c;
688
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus -> %j`, props);
689
+ // Active
690
+ if (props.includes(commands_1.default.power.code)) {
691
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Active) ->`, this.power ? 'ACTIVE' : 'INACTIVE');
692
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.Active)
693
+ .updateValue(this.power ?
694
+ this.platform.Characteristic.Active.ACTIVE : this.platform.Characteristic.Active.INACTIVE);
695
+ }
696
+ // Current Heater-Cooler State
697
+ if (props.includes(commands_1.default.mode.code)) {
698
+ if (this.power) {
699
+ switch (this.mode) {
700
+ case commands_1.default.mode.value.cool:
701
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Heater-Cooler State) -> COOLING`);
702
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState)
703
+ .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.COOLING);
704
+ break;
705
+ case commands_1.default.mode.value.heat:
706
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Heater-Cooler State) -> HEATING`);
707
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState)
708
+ .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.HEATING);
709
+ break;
710
+ case commands_1.default.mode.value.fan:
711
+ case commands_1.default.mode.value.dry:
712
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Heater-Cooler State) -> IDLE`);
713
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState)
714
+ .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.IDLE);
715
+ break;
716
+ case commands_1.default.mode.value.auto:
717
+ if (this.currentTemperature > this.targetTemperature + 1.5) {
718
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Heater-Cooler State) -> COOLING`);
719
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState)
720
+ .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.COOLING);
721
+ }
722
+ else if (this.currentTemperature < this.targetTemperature - 1.5) {
723
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Heater-Cooler State) -> HEATING`);
724
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState)
725
+ .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.HEATING);
726
+ }
727
+ else {
728
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Heater-Cooler State) -> IDLE`);
729
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState)
730
+ .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.IDLE);
731
+ }
732
+ break;
733
+ }
734
+ }
735
+ else {
736
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Heater-Cooler State) -> INACTIVE`);
737
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState)
738
+ .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.INACTIVE);
739
+ }
740
+ }
741
+ // Target Heater-Cooler State
742
+ if (props.includes(commands_1.default.mode.code) && this.power) {
743
+ switch (this.mode) {
744
+ case commands_1.default.mode.value.cool:
745
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Target Heater-Cooler State) -> COOL`);
746
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState)
747
+ .updateValue(this.platform.Characteristic.TargetHeaterCoolerState.COOL);
748
+ break;
749
+ case commands_1.default.mode.value.heat:
750
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Target Heater-Cooler State) -> HEAT`);
751
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState)
752
+ .updateValue(this.platform.Characteristic.TargetHeaterCoolerState.HEAT);
753
+ break;
754
+ default:
755
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Target Heater-Cooler State) -> AUTO`);
756
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState)
757
+ .updateValue(this.platform.Characteristic.TargetHeaterCoolerState.AUTO);
758
+ }
759
+ }
760
+ // Current Temperature
761
+ if (props.includes(commands_1.default.temperature.code)) {
762
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Temperature) ->`, this.currentTemperature);
763
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CurrentTemperature)
764
+ .updateValue(this.currentTemperature);
765
+ (_a = this.TemperatureSensor) === null || _a === void 0 ? void 0 : _a.getCharacteristic(this.platform.Characteristic.CurrentTemperature).updateValue(this.currentTemperature);
766
+ (_b = this.platform_ts) === null || _b === void 0 ? void 0 : _b.setCurrentTemperature(this.currentTemperature);
767
+ (_c = this.platform_ts) === null || _c === void 0 ? void 0 : _c.TemperatureSensor.getCharacteristic(this.platform.Characteristic.CurrentTemperature).updateValue(this.currentTemperature);
768
+ }
769
+ else if (props.includes(commands_1.default.targetTemperature.code) && this.TemperatureSensor === undefined) {
770
+ // temperature is not accessible -> targetTemperature is saved as currentTemperature
771
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Temperature) ->`, this.currentTemperature);
772
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CurrentTemperature)
773
+ .updateValue(this.currentTemperature);
774
+ }
775
+ // Cooling Threshold Temperature
776
+ if (props.includes(commands_1.default.targetTemperature.code) && this.power &&
777
+ (this.mode === commands_1.default.mode.value.cool || this.mode === commands_1.default.mode.value.auto)) {
778
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Cooling Threshold Temperature) ->`, this.targetTemperature);
779
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature)
780
+ .updateValue(this.targetTemperature);
781
+ }
782
+ // Heating Threshold Temperature
783
+ if (props.includes(commands_1.default.targetTemperature.code) && this.power &&
784
+ (this.mode === commands_1.default.mode.value.heat || this.mode === commands_1.default.mode.value.auto)) {
785
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Heating Threshold Temperature) ->`, this.targetTemperature);
786
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature)
787
+ .updateValue(this.targetTemperature);
788
+ }
789
+ // Temperature Display Units
790
+ if (props.includes(commands_1.default.units.code)) {
791
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Temperature Display Units) ->`, this.units === commands_1.default.units.value.celsius ? 'CELSIUS' : 'FAHRENHEIT');
792
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits)
793
+ .updateValue(this.units === commands_1.default.units.value.celsius ?
794
+ this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS : this.platform.Characteristic.TemperatureDisplayUnits.FAHRENHEIT);
795
+ }
796
+ // Swing Mode
797
+ if (props.includes(commands_1.default.swingVertical.code) && this.power) {
798
+ let swing = this.platform.Characteristic.SwingMode.SWING_ENABLED;
799
+ let logValue = 'ENABLED';
800
+ switch (this.swingMode) {
801
+ case commands_1.default.swingVertical.value.default:
802
+ case commands_1.default.swingVertical.value.fixedHighest:
803
+ case commands_1.default.swingVertical.value.fixedHigher:
804
+ case commands_1.default.swingVertical.value.fixedMiddle:
805
+ case commands_1.default.swingVertical.value.fixedLower:
806
+ case commands_1.default.swingVertical.value.fixedLowest:
807
+ swing = this.platform.Characteristic.SwingMode.SWING_DISABLED;
808
+ logValue = 'DISABLED';
809
+ break;
810
+ }
811
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Swing Mode) ->`, logValue);
812
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.SwingMode)
813
+ .updateValue(swing);
814
+ }
815
+ // Rotation Speed
816
+ if (this.power) {
817
+ let logValue = '2 (auto)';
818
+ if (props.includes(commands_1.default.quietMode.code) && this.quietMode === commands_1.default.quietMode.value.on) {
819
+ // quietMode -> on
820
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Rotation Speed) -> 1 (quiet)`);
821
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.RotationSpeed)
822
+ .updateValue(1);
823
+ }
824
+ else if (props.includes(commands_1.default.powerfulMode.code) && this.powerfulMode === commands_1.default.powerfulMode.value.on) {
825
+ // powerfulMode -> on
826
+ logValue = `${this.deviceConfig.speedSteps + 3} (powerful)`;
827
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Rotation Speed) ->`, logValue);
828
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.RotationSpeed)
829
+ .updateValue(this.deviceConfig.speedSteps + 3);
830
+ }
831
+ else if (props.includes(commands_1.default.speed.code)) {
832
+ // speed
833
+ let speedValue = 2; // default: auto
834
+ switch (this.speed) {
835
+ case commands_1.default.speed.value.low:
836
+ logValue = '3 (low)';
837
+ speedValue = 3;
838
+ break;
839
+ case commands_1.default.speed.value.mediumLow:
840
+ logValue = '4 (mediumLow)';
841
+ speedValue = 4;
842
+ break;
843
+ case commands_1.default.speed.value.medium:
844
+ logValue = ((this.deviceConfig.speedSteps === 5) ? '5' : '4') + ' (medium)';
845
+ speedValue = (this.deviceConfig.speedSteps === 5) ? 5 : 4;
846
+ break;
847
+ case commands_1.default.speed.value.mediumHigh:
848
+ logValue = ((this.deviceConfig.speedSteps === 5) ? '6' : '4') + ' (mediumHigh)';
849
+ speedValue = (this.deviceConfig.speedSteps === 5) ? 6 : 4;
850
+ break;
851
+ case commands_1.default.speed.value.high:
852
+ logValue = ((this.deviceConfig.speedSteps === 5) ? '7' : '5') + ' (high)';
853
+ speedValue = (this.deviceConfig.speedSteps === 5) ? 7 : 5;
854
+ break;
855
+ }
856
+ this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Rotation Speed) ->`, logValue);
857
+ this.HeaterCooler.getCharacteristic(this.platform.Characteristic.RotationSpeed)
858
+ .updateValue(speedValue);
859
+ }
860
+ }
861
+ }
862
+ sendMessage(message) {
863
+ this.platform.log.debug(`[${this.getDeviceLabel()}] sendMessage - Package -> %j`, message);
864
+ const pack = crypto_1.default.encrypt(message, this.key);
865
+ const payload = {
866
+ cid: 'app',
867
+ i: this.key === undefined ? 1 : 0,
868
+ t: 'pack',
869
+ uid: 0,
870
+ tcid: this.accessory.context.device.mac,
871
+ pack,
872
+ };
873
+ try {
874
+ const msg = JSON.stringify(payload);
875
+ this.platform.log.debug(`[${this.getDeviceLabel()}] sendMessage`, msg);
876
+ this.socket.send(msg, this.accessory.context.device.port, this.accessory.context.device.address);
877
+ }
878
+ catch (err) {
879
+ this.platform.log.error('sendMessage', err.message);
880
+ }
881
+ }
882
+ sendBindRequest() {
883
+ const message = {
884
+ mac: this.accessory.context.device.mac,
885
+ t: 'bind',
886
+ uid: 0,
887
+ };
888
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Bind to device -> ${this.accessory.context.device.mac}`);
889
+ this.sendMessage(message);
890
+ }
891
+ sendCommand(cmd) {
892
+ this.platform.log.debug(`[${this.getDeviceLabel()}] Send commands -> %j`, cmd);
893
+ const keys = Object.keys(cmd);
894
+ const values = keys.map((k) => cmd[k]);
895
+ const message = {
896
+ t: 'cmd',
897
+ opt: keys,
898
+ p: values,
899
+ };
900
+ this.sendMessage(message);
901
+ }
902
+ requestDeviceStatus() {
903
+ const message = {
904
+ mac: this.accessory.context.device.mac,
905
+ t: 'status',
906
+ cols: this.getCols(),
907
+ };
908
+ this.sendMessage(message);
909
+ }
910
+ }
911
+ exports.GreeAirConditioner = GreeAirConditioner;
912
+ //# sourceMappingURL=platformAccessory.js.map