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