homebridge-melcloud-control 3.5.1 → 3.5.2

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/src/deviceata.js CHANGED
@@ -96,713 +96,167 @@ class DeviceAta extends EventEmitter {
96
96
  this.accessory.temperatureUnit = TemperatureDisplayUnits[this.accessory.useFahrenheit];
97
97
  };
98
98
 
99
- async start() {
99
+ async setOverExternalIntegration(integration, deviceData, key, value) {
100
100
  try {
101
- //melcloud device
102
- this.melCloudAta = new MelCloudAta({
103
- contextKey: this.contextKey,
104
- devicesFile: this.devicesFile,
105
- deviceId: this.deviceId,
106
- debugLog: this.enableDebugMode
107
- });
108
-
109
- this.melCloudAta.on('externalIntegrations', (deviceData) => {
110
- try {
111
- //RESTFul server
112
- const restFulEnabled = this.restFul.enable || false;
113
- if (restFulEnabled) {
114
- if (!this.restFulConnected) {
115
- this.restFul1 = new RestFul({
116
- port: this.deviceId.slice(-4),
117
- debug: this.restFul.debug || false
118
- });
119
-
120
- this.restFul1.on('connected', (message) => {
121
- this.restFulConnected = true;
122
- this.emit('success', message);
123
- })
124
- .on('set', async (key, value) => {
125
- try {
126
- await this.setOverExternalIntegration('RESTFul', deviceData, key, value);
127
- } catch (error) {
128
- this.emit('warn', error);
129
- };
130
- })
131
- .on('debug', (debug) => {
132
- this.emit('debug', debug);
133
- })
134
- .on('error', (error) => {
135
- this.emit('warn', error);
136
- });
137
- }
138
- const restFul0 = this.restFulConnected ? this.restFul1.update('info', deviceData) : false;
139
- const restFul1 = this.restFulConnected ? this.restFul1.update('state', deviceData.Device) : false;
140
- }
101
+ let set = false
102
+ switch (key) {
103
+ case 'Power':
104
+ deviceData.Device[key] = value;
105
+ deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Power;
106
+ set = await this.melCloudAta.send(deviceData, this.displayMode);
107
+ break;
108
+ case 'OperationMode':
109
+ deviceData.Device[key] = value;
110
+ deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.OperationModeSetTemperature;
111
+ set = await this.melCloudAta.send(deviceData, this.displayMode);
112
+ break;
113
+ case 'SetTemperature':
114
+ deviceData.Device[key] = value;
115
+ deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.SetTemperature;
116
+ set = await this.melCloudAta.send(deviceData, this.displayMode);
117
+ break;
118
+ case 'DefaultCoolingSetTemperature':
119
+ deviceData.Device[key] = value;
120
+ deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.SetTemperature;
121
+ set = await this.melCloudAta.send(deviceData, this.displayMode);
122
+ break;
123
+ case 'DefaultHeatingSetTemperature':
124
+ deviceData.Device[key] = value;
125
+ deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.SetTemperature;
126
+ set = await this.melCloudAta.send(deviceData, this.displayMode);
127
+ break;
128
+ case 'FanSpeed':
129
+ deviceData.Device[key] = value;
130
+ deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.SetFanSpeed;
131
+ set = await this.melCloudAta.send(deviceData, this.displayMode);
132
+ break;
133
+ case 'VaneHorizontalDirection':
134
+ deviceData.Device[key] = value;
135
+ deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.VaneHorizontal;
136
+ set = await this.melCloudAta.send(deviceData, this.displayMode);
137
+ break;
138
+ case 'VaneVerticalDirection':
139
+ deviceData.Device[key] = value;
140
+ deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.VaneVertical;
141
+ set = await this.melCloudAta.send(deviceData, this.displayMode);
142
+ break;
143
+ case 'HideVaneControls':
144
+ deviceData[key] = value;
145
+ deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Prohibit;
146
+ set = await this.melCloudAta.send(deviceData, this.displayMode);
147
+ break;
148
+ case 'HideDryModeControl':
149
+ deviceData[key] = value;
150
+ deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Prohibit;
151
+ await this.melCloudAta.send(deviceData, this.displayMode);
152
+ break;
153
+ case 'ProhibitSetTemperature':
154
+ deviceData.Device[key] = value;
155
+ deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Prohibit;
156
+ set = await this.melCloudAta.send(deviceData, this.displayMode);
157
+ break;
158
+ case 'ProhibitOperationMode':
159
+ deviceData.Device[key] = value;
160
+ deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Prohibit;
161
+ await this.melCloudAta.send(deviceData, this.displayMode);
162
+ break;
163
+ case 'ProhibitPower':
164
+ deviceData.Device[key] = value;
165
+ deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Prohibit;
166
+ set = await this.melCloudAta.send(deviceData, this.displayMode);
167
+ break;
168
+ default:
169
+ this.emit('warn', `${integration}, received key: ${key}, value: ${value}`);
170
+ break;
171
+ };
172
+ return set;
173
+ } catch (error) {
174
+ throw new Error(`${integration} set key: ${key}, value: ${value}, error: ${error.message ?? error}`);
175
+ };
176
+ }
141
177
 
142
- //MQTT client
143
- const mqttEnabled = this.mqtt.enable || false;
144
- if (mqttEnabled) {
145
- if (!this.mqttConnected) {
146
- this.mqtt1 = new Mqtt({
147
- host: this.mqtt.host,
148
- port: this.mqtt.port || 1883,
149
- clientId: `${this.mqtt.clientId}_${this.deviceId}` || `${this.deviceTypeText}_${this.deviceName}_${this.deviceId}`,
150
- prefix: `${this.mqtt.prefix}/${this.deviceTypeText}/${this.deviceName}`,
151
- user: this.mqtt.user,
152
- passwd: this.mqtt.pass,
153
- debug: this.mqtt.debug || false
154
- });
178
+ //prepare accessory
179
+ async prepareAccessory(accountInfo, deviceData, deviceId, deviceTypeText, deviceName, accountName) {
180
+ try {
181
+ const presetsOnServer = this.accessory.presets;
182
+ const modelSupportsHeat = this.accessory.modelSupportsHeat;
183
+ const modelSupportsDry = this.accessory.modelSupportsDry;
184
+ const modelSupportsCool = this.accessory.modelSupportsCool;
185
+ const modelSupportsAuto = this.accessory.modelSupportsAuto;
186
+ const modelSupportsFanSpeed = this.accessory.modelSupportsFanSpeed;
187
+ const hasAutomaticFanSpeed = this.accessory.hasAutomaticFanSpeed;
188
+ const hasOutdoorTemperature = this.accessory.hasOutdoorTemperature;
189
+ const numberOfFanSpeeds = this.accessory.numberOfFanSpeeds;
190
+ const swingFunction = this.accessory.swingFunction;
191
+ const autoDryFanMode = [this.accessory.operationMode, 8, modelSupportsDry ? 2 : 8, 7][this.autoDryFanMode]; //NONE, AUTO - 8, DRY - 2, FAN - 7
192
+ const heatDryFanMode = [this.accessory.operationMode, 1, modelSupportsDry ? 2 : 1, 7][this.heatDryFanMode]; //NONE, HEAT - 1, DRY - 2, FAN - 7
193
+ const coolDryFanMode = [this.accessory.operationMode, 3, modelSupportsDry ? 2 : 3, 7][this.coolDryFanMode]; //NONE, COOL - 3, DRY - 2, FAN - 7
155
194
 
156
- this.mqtt1.on('connected', (message) => {
157
- this.mqttConnected = true;
158
- this.emit('success', message);
159
- })
160
- .on('subscribed', (message) => {
161
- this.emit('success', message);
162
- })
163
- .on('set', async (key, value) => {
164
- try {
165
- await this.setOverExternalIntegration('MQTT', deviceData, key, value);
166
- } catch (error) {
167
- this.emit('warn', error);
168
- };
169
- })
170
- .on('debug', (debug) => {
171
- this.emit('debug', debug);
172
- })
173
- .on('error', (error) => {
174
- this.emit('warn', error);
175
- });
176
- }
177
- const mqtt0 = this.mqttConnected ? this.mqtt1.emit('publish', `Info`, deviceData) : false;
178
- const mqtt1 = this.mqttConnected ? this.mqtt1.emit('publish', `State`, deviceData.Device) : false;
179
- }
195
+ //accessory
196
+ const debug = this.enableDebugMode ? this.emit('debug', `Prepare accessory`) : false;
197
+ const accessoryName = deviceName;
198
+ const accessoryUUID = AccessoryUUID.generate(accountName + deviceId.toString());
199
+ const accessoryCategory = Categories.AIR_CONDITIONER;
200
+ const accessory = new Accessory(accessoryName, accessoryUUID, accessoryCategory);
180
201
 
181
- } catch (error) {
182
- this.emit('warn', `External integration start error: ${error}.`);
183
- };
184
- })
185
- .on('deviceInfo', (manufacturer, modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion) => {
186
- if (!this.displayDeviceInfo) {
187
- return;
188
- }
202
+ //information service
203
+ const debug1 = this.enableDebugMode ? this.emit('debug', `Prepare information service`) : false;
204
+ accessory.getService(Service.AccessoryInformation)
205
+ .setCharacteristic(Characteristic.Manufacturer, this.manufacturer)
206
+ .setCharacteristic(Characteristic.Model, this.model)
207
+ .setCharacteristic(Characteristic.SerialNumber, this.serialNumber)
208
+ .setCharacteristic(Characteristic.FirmwareRevision, this.firmwareRevision)
209
+ .setCharacteristic(Characteristic.ConfiguredName, accessoryName);
189
210
 
190
- if (!this.disableLogDeviceInfo) {
191
- this.emit('devInfo', `---- ${this.deviceTypeText}: ${this.deviceName} ----`);
192
- this.emit('devInfo', `Account: ${this.accountName}`);
193
- const indoor = modelIndoor ? this.emit('devInfo', `Indoor: ${modelIndoor}`) : false;
194
- const outdoor = modelOutdoor ? this.emit('devInfo', `Outdoor: ${modelOutdoor}`) : false
195
- this.emit('devInfo', `Serial: ${serialNumber}`);
196
- this.emit('devInfo', `Firmware: ${firmwareAppVersion}`);
197
- this.emit('devInfo', `Manufacturer: ${manufacturer}`);
198
- this.emit('devInfo', '----------------------------------');
199
- };
200
-
201
- //accessory info
202
- this.manufacturer = manufacturer;
203
- this.model = modelIndoor ? modelIndoor : modelOutdoor ? modelOutdoor : `${this.deviceTypeText} ${this.deviceId}`;
204
- this.serialNumber = serialNumber;
205
- this.firmwareRevision = firmwareAppVersion;
206
- this.displayDeviceInfo = false;
207
- })
208
- .on('deviceState', async (deviceData) => {
209
- //presets
210
- const presetsOnServer = deviceData.Presets ?? [];
211
-
212
- //device control
213
- const hideVaneControls = deviceData.HideVaneControls ?? false;
214
- const hideDryModeControl = deviceData.HideDryModeControl ?? false;
215
-
216
- //device info
217
- const hasAutomaticFanSpeed = deviceData.Device.HasAutomaticFanSpeed ?? false;
218
- const airDirectionFunction = deviceData.Device.AirDirectionFunction ?? false;
219
- const swingFunction = deviceData.Device.SwingFunction ?? false;
220
- const hasOutdoorTemperature = deviceData.Device.HasOutdoorTemperature ?? false;
221
- const numberOfFanSpeeds = deviceData.Device.NumberOfFanSpeeds ?? 0;
222
- const modelSupportsFanSpeed = deviceData.Device.ModelSupportsFanSpeed ?? false;
223
- const modelSupportsAuto1 = deviceData.Device.ModelSupportsAuto ?? false;
224
- const modelSupportsAuto = this.autoDryFanMode >= 1 && modelSupportsAuto1
225
- const modelSupportsHeat1 = deviceData.Device.ModelSupportsHeat ?? false;
226
- const modelSupportsHeat = this.heatDryFanMode >= 1 && modelSupportsHeat1;
227
- const modelSupportsDry = deviceData.Device.ModelSupportsDry ?? false;
228
- const modelSupportsCool = this.coolDryFanMode >= 1;
229
- const minTempHeat = 10;
230
- const maxTempHeat = 31;
231
- const minTempCoolDry = 16;
232
- const maxTempCoolDry = 31;
233
-
234
- //device state
235
- const power = deviceData.Device.Power ?? false;
236
- const inStandbyMode = deviceData.Device.InStandbyMode ?? false;
237
- const roomTemperature = deviceData.Device.RoomTemperature;
238
- const setTemperature = deviceData.Device.SetTemperature ?? 20;
239
- const defaultHeatingSetTemperature = deviceData.Device.DefaultHeatingSetTemperature ?? 20;
240
- const defaultCoolingSetTemperature = deviceData.Device.DefaultCoolingSetTemperature ?? 23;
241
- const actualFanSpeed = deviceData.Device.ActualFanSpeed;
242
- const automaticFanSpeed = deviceData.Device.AutomaticFanSpeed;
243
- const fanSpeed = deviceData.Device.FanSpeed ?? 0;
244
- const operationMode = deviceData.Device.OperationMode;
245
- const vaneVerticalDirection = deviceData.Device.VaneVerticalDirection;
246
- const vaneVerticalSwing = deviceData.Device.VaneVerticalSwing;
247
- const vaneHorizontalDirection = deviceData.Device.VaneHorizontalDirection;
248
- const vaneHorizontalSwing = deviceData.Device.VaneHorizontalSwing;
249
- const prohibitSetTemperature = deviceData.Device.ProhibitSetTemperature ?? false;
250
- const prohibitOperationMode = deviceData.Device.ProhibitOperationMode ?? false;
251
- const prohibitPower = deviceData.Device.ProhibitPower ?? false;
252
- const temperatureIncrement = deviceData.Device.TemperatureIncrement ?? 1;
253
- const outdoorTemperature = deviceData.Device.OutdoorTemperature;
254
-
255
- //accessory
256
- this.accessory.presets = presetsOnServer;
257
- this.accessory.hasAutomaticFanSpeed = hasAutomaticFanSpeed;
258
- this.accessory.airDirectionFunction = airDirectionFunction;
259
- this.accessory.swingFunction = swingFunction;
260
- this.accessory.hasOutdoorTemperature = hasOutdoorTemperature;
261
- this.accessory.numberOfFanSpeeds = numberOfFanSpeeds;
262
- this.accessory.modelSupportsFanSpeed = modelSupportsFanSpeed;
263
- this.accessory.modelSupportsAuto = modelSupportsAuto;
264
- this.accessory.modelSupportsHeat = modelSupportsHeat;
265
- this.accessory.modelSupportsDry = modelSupportsDry;
266
- this.accessory.modelSupportsCool = modelSupportsCool;
267
- this.accessory.minTempHeat = minTempHeat;
268
- this.accessory.maxTempHeat = maxTempHeat;
269
- this.accessory.minTempCoolDry = minTempCoolDry;
270
- this.accessory.maxTempCoolDry = maxTempCoolDry;
271
-
272
- this.accessory.power = power ? 1 : 0;
273
- this.accessory.inStandbyMode = inStandbyMode;
274
- this.accessory.operationMode = operationMode;
275
- this.accessory.roomTemperature = roomTemperature;
276
- this.accessory.outdoorTemperature = outdoorTemperature;
277
- this.accessory.setTemperature = setTemperature;
278
- this.accessory.defaultHeatingSetTemperature = defaultHeatingSetTemperature;
279
- this.accessory.defaultCoolingSetTemperature = defaultCoolingSetTemperature;
280
- this.accessory.actualFanSpeed = actualFanSpeed;
281
- this.accessory.automaticFanSpeed = automaticFanSpeed;
282
- this.accessory.vaneVerticalSwing = vaneVerticalSwing;
283
- this.accessory.vaneHorizontalSwing = vaneHorizontalSwing;
284
- this.accessory.swingMode = swingFunction && vaneHorizontalDirection === 12 && vaneVerticalDirection === 7 ? 1 : 0;
285
- this.accessory.lockPhysicalControl = prohibitSetTemperature && prohibitOperationMode && prohibitPower ? 1 : 0;
286
- this.accessory.temperatureIncrement = temperatureIncrement;
287
-
288
- //operating mode 0, HEAT, DRY, COOL, 4, 5, 6, FAN, AUTO, ISEE HEAT, ISEE DRY, ISEE COOL
289
- switch (this.displayMode) {
290
- case 1: //Heater Cooler
291
- switch (operationMode) {
292
- case 1: //HEAT
293
- this.accessory.currentOperationMode = roomTemperature > setTemperature ? 1 : 2; //INACTIVE, IDLE, HEATING, COOLING
294
- this.accessory.targetOperationMode = 1; //AUTO, HEAT, COOL
295
- break;
296
- case 2: //DRY
297
- this.accessory.currentOperationMode = 1;
298
- this.accessory.targetOperationMode = this.autoDryFanMode === 2 ? 0 : this.heatDryFanMode === 2 ? 1 : this.coolDryFanMode === 2 ? 2 : this.accessory.targetOperationMode ?? 0;
299
- break;
300
- case 3: //COOL
301
- this.accessory.currentOperationMode = roomTemperature < setTemperature ? 1 : 3;
302
- this.accessory.targetOperationMode = 2;
303
- break;
304
- case 7: //FAN
305
- this.accessory.currentOperationMode = 1;
306
- this.accessory.targetOperationMode = this.autoDryFanMode === 3 ? 0 : this.heatDryFanMode === 3 ? 1 : this.coolDryFanMode === 3 ? 2 : this.accessory.targetOperationMode ?? 0;
307
- break;
308
- case 8: //AUTO
309
- this.accessory.currentOperationMode = roomTemperature > setTemperature ? 3 : roomTemperature < setTemperature ? 2 : 1;
310
- this.accessory.targetOperationMode = 0;
311
- break;
312
- case 9: //ISEE HEAT
313
- this.accessory.currentOperationMode = roomTemperature > setTemperature ? 1 : 2
314
- this.accessory.targetOperationMode = 1;
315
- break;
316
- case 10: //ISEE DRY
317
- this.accessory.currentOperationMode = 1;
318
- this.accessory.targetOperationMode = this.autoDryFanMode === 2 ? 0 : this.heatDryFanMode === 2 ? 1 : this.coolDryFanMode === 2 ? 2 : this.accessory.targetOperationMode ?? 0;
319
- break;
320
- case 11: //ISEE COOL;
321
- this.accessory.currentOperationMode = roomTemperature < setTemperature ? 1 : 3;
322
- this.accessory.targetOperationMode = 2;
323
- break;
324
- default:
325
- this.emit('warn', `Unknown operating mode: ${operationMode}`);
326
- return
327
- };
328
-
329
- this.accessory.currentOperationMode = !power ? 0 : inStandbyMode ? 1 : this.accessory.currentOperationMode;
330
- this.accessory.operationModeSetPropsMinValue = modelSupportsAuto && modelSupportsHeat ? 0 : !modelSupportsAuto && modelSupportsHeat ? 1 : modelSupportsAuto && !modelSupportsHeat ? 0 : 2;
331
- this.accessory.operationModeSetPropsMaxValue = 2
332
- this.accessory.operationModeSetPropsValidValues = modelSupportsAuto && modelSupportsHeat ? [0, 1, 2] : !modelSupportsAuto && modelSupportsHeat ? [1, 2] : modelSupportsAuto && !modelSupportsHeat ? [0, 2] : [2];
333
-
334
- //fan speed mode
335
- if (modelSupportsFanSpeed) {
336
- switch (numberOfFanSpeeds) {
337
- case 2: //Fan speed mode 2
338
- this.accessory.fanSpeed = hasAutomaticFanSpeed ? [3, 1, 2][fanSpeed] : [0, 1, 2][fanSpeed];
339
- this.accessory.fanSpeedSetPropsMaxValue = hasAutomaticFanSpeed ? 3 : 2;
340
- break;
341
- case 3: //Fan speed mode 3
342
- this.accessory.fanSpeed = hasAutomaticFanSpeed ? [4, 1, 2, 3][fanSpeed] : [0, 1, 2, 3][fanSpeed];
343
- this.accessory.fanSpeedSetPropsMaxValue = hasAutomaticFanSpeed ? 4 : 3;
344
- break;
345
- case 4: //Fan speed mode 4
346
- this.accessory.fanSpeed = hasAutomaticFanSpeed ? [5, 1, 2, 3, 4][fanSpeed] : [0, 1, 2, 3, 4][fanSpeed];
347
- this.accessory.fanSpeedSetPropsMaxValue = hasAutomaticFanSpeed ? 5 : 4;
348
- break;
349
- case 5: //Fan speed mode 5
350
- this.accessory.fanSpeed = hasAutomaticFanSpeed ? [6, 1, 2, 3, 4, 5][fanSpeed] : [0, 1, 2, 3, 4, 5][fanSpeed];
351
- this.accessory.fanSpeedSetPropsMaxValue = hasAutomaticFanSpeed ? 6 : 5;
352
- break;
353
- case 6: //Fan speed mode 6
354
- this.accessory.fanSpeed = hasAutomaticFanSpeed ? [7, 1, 2, 3, 4, 5, 6][fanSpeed] : [0, 1, 2, 3, 4, 5, 6][fanSpeed];
355
- this.accessory.fanSpeedSetPropsMaxValue = hasAutomaticFanSpeed ? 7 : 6;
356
- break;
357
- };
358
- };
359
-
360
- //update characteristics
361
- if (this.melCloudService) {
362
- this.melCloudService
363
- .updateCharacteristic(Characteristic.Active, power ? 1 : 0)
364
- .updateCharacteristic(Characteristic.CurrentHeaterCoolerState, this.accessory.currentOperationMode)
365
- .updateCharacteristic(Characteristic.TargetHeaterCoolerState, this.accessory.targetOperationMode)
366
- .updateCharacteristic(Characteristic.CurrentTemperature, roomTemperature)
367
- .updateCharacteristic(Characteristic.LockPhysicalControls, this.accessory.lockPhysicalControl)
368
- .updateCharacteristic(Characteristic.TemperatureDisplayUnits, this.accessory.useFahrenheit)
369
- .updateCharacteristic(Characteristic.CoolingThresholdTemperature, defaultCoolingSetTemperature);
370
- const updateDefHeat = modelSupportsHeat ? this.melCloudService.updateCharacteristic(Characteristic.HeatingThresholdTemperature, defaultHeatingSetTemperature) : false;
371
- const updateRS = modelSupportsFanSpeed ? this.melCloudService.updateCharacteristic(Characteristic.RotationSpeed, this.accessory.fanSpeed) : false;
372
- const updateSM = swingFunction ? this.melCloudService.updateCharacteristic(Characteristic.SwingMode, this.accessory.swingMode) : false;
373
- };
374
- break;
375
- case 2: //Thermostat
376
- switch (operationMode) {
377
- case 1: //HEAT
378
- this.accessory.currentOperationMode = roomTemperature > setTemperature ? 0 : 1; //OFF, HEATING, COOLING
379
- this.accessory.targetOperationMode = 1; //OFF, HEAT, COOL, AUTO
380
- break;
381
- case 2: //DRY
382
- this.accessory.currentOperationMode = 0;
383
- this.accessory.targetOperationMode = this.autoDryFanMode === 2 ? 3 : this.heatDryFanMode === 2 ? 1 : this.coolDryFanMode === 2 ? 2 : this.accessory.targetOperationMode ?? 0;
384
- break;
385
- case 3: //COOL
386
- this.accessory.currentOperationMode = roomTemperature < setTemperature ? 0 : 2;
387
- this.accessory.targetOperationMode = 2;
388
- break;
389
- case 7: //FAN
390
- this.accessory.currentOperationMode = 0;
391
- this.accessory.targetOperationMode = this.autoDryFanMode === 3 ? 3 : this.heatDryFanMode === 3 ? 1 : this.coolDryFanMode === 3 ? 2 : this.accessory.targetOperationMode ?? 0;
392
- break;
393
- case 8: //AUTO
394
- this.accessory.currentOperationMode = roomTemperature < setTemperature ? 1 : roomTemperature > setTemperature ? 2 : 0;
395
- this.accessory.targetOperationMode = 3;
396
- break;
397
- case 9: //ISEE HEAT
398
- this.accessory.currentOperationMode = roomTemperature > setTemperature ? 0 : 1;
399
- this.accessory.targetOperationMode = 1;
400
- break;
401
- case 10: //ISEE DRY
402
- this.accessory.currentOperationMode = 0;
403
- this.accessory.targetOperationMode = this.autoDryFanMode === 2 ? 3 : this.heatDryFanMode === 2 ? 1 : this.coolDryFanMode === 2 ? 2 : this.accessory.targetOperationMode ?? 0;
404
- break;
405
- case 11: //ISEE COOL;
406
- this.accessory.currentOperationMode = roomTemperature < setTemperature ? 0 : 2;
407
- this.accessory.targetOperationMode = 2;
408
- break;
409
- default:
410
- this.emit('warn', `Unknown operating mode: ${operationMode}`);
411
- break;
412
- };
413
-
414
- this.accessory.currentOperationMode = !power ? 0 : this.accessory.currentOperationMode;
415
- this.accessory.targetOperationMode = !power ? 0 : this.accessory.targetOperationMode;
416
- this.accessory.operationModeSetPropsMinValue = 0
417
- this.accessory.operationModeSetPropsMaxValue = modelSupportsAuto && modelSupportsHeat ? 3 : !modelSupportsAuto && modelSupportsHeat ? 2 : modelSupportsAuto && !modelSupportsHeat ? 3 : 2;
418
- this.accessory.operationModeSetPropsValidValues = modelSupportsAuto && modelSupportsHeat ? [0, 1, 2, 3] : !modelSupportsAuto && modelSupportsHeat ? [0, 1, 2] : modelSupportsAuto && !modelSupportsHeat ? [0, 2, 3] : [0, 2];
419
-
420
- //update characteristics
421
- if (this.melCloudService) {
422
- this.melCloudService
423
- .updateCharacteristic(Characteristic.CurrentHeatingCoolingState, this.accessory.currentOperationMode)
424
- .updateCharacteristic(Characteristic.TargetHeatingCoolingState, this.accessory.targetOperationMode)
425
- .updateCharacteristic(Characteristic.CurrentTemperature, roomTemperature)
426
- .updateCharacteristic(Characteristic.TargetTemperature, setTemperature)
427
- .updateCharacteristic(Characteristic.TemperatureDisplayUnits, this.accessory.useFahrenheit);
428
- };
429
- break;
430
- };
431
-
432
- if (this.roomTemperatureSensorService) {
433
- this.roomTemperatureSensorService
434
- .updateCharacteristic(Characteristic.CurrentTemperature, roomTemperature)
435
- };
436
-
437
- if (this.outdoorTemperatureSensorService) {
438
- this.outdoorTemperatureSensorService
439
- .updateCharacteristic(Characteristic.CurrentTemperature, outdoorTemperature)
440
- };
441
-
442
- //update presets state
443
- if (this.presetsConfigured.length > 0) {
444
- for (let i = 0; i < this.presetsConfigured.length; i++) {
445
- const preset = this.presetsConfigured[i];
446
- const presetData = presetsOnServer.find(p => p.ID === preset.Id);
447
-
448
- preset.state = presetData ? (presetData.Power === power
449
- && presetData.SetTemperature === setTemperature
450
- && presetData.OperationMode === operationMode
451
- && presetData.VaneHorizontal === vaneHorizontalDirection
452
- && presetData.VaneVertical === vaneVerticalDirection
453
- && presetData.FanSpeed === fanSpeed) : false;
454
-
455
- if (this.presetsServices) {
456
- const characteristicType = preset.characteristicType;
457
- this.presetsServices[i]
458
- .updateCharacteristic(characteristicType, preset.state)
459
- };
460
- };
461
- };
462
-
463
- //update buttons state
464
- if (this.buttonsConfiguredCount > 0) {
465
- for (let i = 0; i < this.buttonsConfiguredCount; i++) {
466
- const button = this.buttonsConfigured[i];
467
- const mode = button.mode;
468
- switch (mode) {
469
- case 0: //POWER ON,OFF
470
- button.state = (power === true);
471
- break;
472
- case 1: //OPERATING MODE HEAT
473
- button.state = power ? (operationMode === 1 || operationMode === 9) : false;
474
- break;
475
- case 2: //OPERATING MODE DRY
476
- button.state = power ? (operationMode === 2 || operationMode === 10) : false;
477
- break
478
- case 3: //OPERATING MODE COOL
479
- button.state = power ? (operationMode === 3 || operationMode === 11) : false;
480
- break;
481
- case 4: //OPERATING MODE FAN
482
- button.state = power ? (operationMode === 7) : false;
483
- break;
484
- case 5: //OPERATING MODE AUTO
485
- button.state = power ? (operationMode === 8) : false;
486
- break;
487
- case 6: //OPERATING MODE PURIFY
488
- button.state = power ? (operationMode === 12) : false;
489
- break;
490
- case 7: //OPERATING MODE DRY CONTROL HIDE
491
- button.state = power ? (hideDryModeControl === true) : false;
492
- break;
493
- case 10: //VANE H SWING MODE AUTO
494
- button.state = power ? (vaneHorizontalDirection === 0) : false;
495
- break;
496
- case 11: //VANE H SWING MODE 1
497
- button.state = power ? (vaneHorizontalDirection === 1) : false;
498
- break;
499
- case 12: //VANE H SWING MODE 2
500
- button.state = power ? (vaneHorizontalDirection === 2) : false;
501
- break;
502
- case 13: //VANE H SWING MODE 3
503
- button.state = power ? (vaneHorizontalDirection === 3) : false;
504
- break;
505
- case 14: //VANE H SWING MODE 4
506
- button.state = power ? (vaneHorizontalDirection === 4) : false;
507
- break;
508
- case 15: //VANE H SWING MODE 5
509
- button.state = power ? (vaneHorizontalDirection === 5) : false;
510
- break;
511
- case 16: //VANE H SWING MODE SPLIT
512
- button.state = power ? (vaneHorizontalDirection === 8) : false;
513
- break;
514
- case 17: //VANE H SWING MODE SWING
515
- button.state = power ? (vaneHorizontalDirection === 12) : false;
516
- break;
517
- case 20: //VANE V SWING MODE AUTO
518
- button.state = power ? (vaneVerticalDirection === 0) : false;
519
- break;
520
- case 21: //VANE V SWING MODE 1
521
- button.state = power ? (vaneVerticalDirection === 1) : false;
522
- break;
523
- case 22: //VANE V SWING MODE 2
524
- button.state = power ? (vaneVerticalDirection === 2) : false;
525
- break;
526
- case 23: //VANE V SWING MODE 3
527
- button.state = power ? (vaneVerticalDirection === 3) : false;
528
- break;
529
- case 24: //VANE V SWING MODE 4
530
- button.state = power ? (vaneVerticalDirection === 4) : false;
531
- break;
532
- case 25: //VANE V SWING MODE 5
533
- button.state = power ? (vaneVerticalDirection === 5) : false;
534
- break;
535
- case 26: //VANE V SWING MODE SWING
536
- button.state = power ? (vaneVerticalDirection === 7) : false;
537
- break;
538
- case 27: //VANE H/V CONTROLS HIDE
539
- button.state = power ? (hideVaneControls === true) : false;
540
- break;
541
- case 30: //FAN SPEED MODE AUTO
542
- button.state = power ? (fanSpeed === 0) : false;
543
- break;
544
- case 31: //FAN SPEED MODE 1
545
- button.state = power ? (fanSpeed === 1) : false;
546
- break;
547
- case 32: //FAN SPEED MODE 2
548
- button.state = power ? (fanSpeed === 2) : false;
549
- break;
550
- case 33: //FAN SPEED MODE 3
551
- button.state = power ? (fanSpeed === 3) : false;
552
- break;
553
- case 34: //FAN SPEED MODE 4
554
- button.state = power ? (fanSpeed === 4) : false;
555
- break;
556
- case 35: //FAN SPEED MODE 5
557
- button.state = power ? (fanSpeed === 5) : false;
558
- break;
559
- case 36: //FAN SPEED MODE 6
560
- button.state = power ? (fanSpeed === 6) : false;
561
- break;
562
- case 37: //PHYSICAL LOCK CONTROLS ALL
563
- button.state = (this.accessory.lockPhysicalControl === 1);
564
- break;
565
- case 38: //PHYSICAL LOCK CONTROLS POWER
566
- button.state = (prohibitPower === true);
567
- break;
568
- case 39: //PHYSICAL LOCK CONTROLS MODE
569
- button.state = (prohibitOperationMode === true);
570
- break;
571
- case 40: //PHYSICAL LOCK CONTROLS TEMP
572
- button.state = (prohibitSetTemperature === true);
573
- break;
574
- default: //Unknown button
575
- this.emit('message', `Unknown button mode: ${mode} detected.`);
576
- break;
577
- };
578
-
579
- //update services
580
- if (this.buttonsServices) {
581
- const characteristicType = button.characteristicType;
582
- this.buttonsServices[i]
583
- .updateCharacteristic(characteristicType, button.state)
584
- };
585
- };
586
- };
587
-
588
- //log current state
589
- if (!this.disableLogInfo) {
590
- this.emit('message', `Power: ${power ? 'ON' : 'OFF'}`);
591
- this.emit('message', `Target operation mode: ${AirConditioner.DriveMode[operationMode]}`);
592
- this.emit('message', `Current operation mode: ${this.displayMode === 1 ? AirConditioner.CurrentOperationModeHeatherCooler[this.accessory.currentOperationMode] : AirConditioner.CurrentOperationModeThermostat[this.accessory.currentOperationMode]}`);
593
- this.emit('message', `Target temperature: ${setTemperature}${this.accessory.temperatureUnit}`);
594
- this.emit('message', `Current temperature: ${roomTemperature}${this.accessory.temperatureUnit}`);
595
- const info = hasOutdoorTemperature && outdoorTemperature !== null ? this.emit('message', `Outdoor temperature: ${outdoorTemperature}${this.accessory.temperatureUnit}`) : false;
596
- const info3 = modelSupportsFanSpeed ? this.emit('message', `Target fan speed: ${AirConditioner.FanSpeed[fanSpeed]}`) : false;
597
- const info4 = modelSupportsFanSpeed ? this.emit('message', `Current fan speed: ${AirConditioner.FanSpeed[actualFanSpeed]}`) : false;
598
- const info5 = vaneHorizontalDirection !== null ? this.emit('message', `Vane horizontal: ${AirConditioner.HorizontalVane[vaneHorizontalDirection] ?? vaneHorizontalDirection}`) : false;
599
- const info6 = vaneVerticalDirection !== null ? this.emit('message', `Vane vertical: ${AirConditioner.VerticalVane[vaneVerticalDirection] ?? vaneVerticalDirection}`) : false;
600
- const info7 = swingFunction ? this.emit('message', `Air direction: ${AirConditioner.AirDirection[this.accessory.swingMode]}`) : false;
601
- this.emit('message', `Temperature display unit: ${this.accessory.temperatureUnit}`);
602
- this.emit('message', `Lock physical controls: ${this.accessory.lockPhysicalControl ? 'LOCKED' : 'UNLOCKED'}`);
603
- };
604
-
605
- //start prepare accessory
606
- if (!this.startPrepareAccessory) {
607
- return;
608
- }
609
- try {
610
- const accessory = await this.prepareAccessory(this.accountInfo, deviceData, this.deviceId, this.deviceTypeText, this.deviceName, this.accountName);
611
- this.emit('publishAccessory', accessory);
612
- this.startPrepareAccessory = false;
613
- } catch (error) {
614
- this.emit('error', error);
615
- };
616
- })
617
- .on('success', (message) => {
618
- this.emit('success', message);
619
- })
620
- .on('message', (message) => {
621
- this.emit('message', message);
622
- })
623
- .on('debug', (debug) => {
624
- this.emit('debug', debug);
625
- })
626
- .on('warn', async (warn) => {
627
- this.emit('warn', warn);
628
- })
629
- .on('error', async (error) => {
630
- this.emit('error', error);
631
- });
632
-
633
- //check state
634
- await this.melCloudAta.checkState();
635
-
636
- //start impule generator
637
- await this.melCloudAta.impulseGenerator.start([{ name: 'checkState', sampling: this.refreshInterval }]);
638
-
639
- return true;
640
- } catch (error) {
641
- throw new Error(`Start error: ${error}`);
642
- };
643
- };
644
-
645
- async setOverExternalIntegration(integration, deviceData, key, value) {
646
- try {
647
- let set = false
648
- switch (key) {
649
- case 'Power':
650
- deviceData.Device[key] = value;
651
- deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Power;
652
- set = await this.melCloudAta.send(deviceData, this.displayMode);
653
- break;
654
- case 'OperationMode':
655
- deviceData.Device[key] = value;
656
- deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.OperationModeSetTemperature;
657
- set = await this.melCloudAta.send(deviceData, this.displayMode);
658
- break;
659
- case 'SetTemperature':
660
- deviceData.Device[key] = value;
661
- deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.SetTemperature;
662
- set = await this.melCloudAta.send(deviceData, this.displayMode);
663
- break;
664
- case 'DefaultCoolingSetTemperature':
665
- deviceData.Device[key] = value;
666
- deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.SetTemperature;
667
- set = await this.melCloudAta.send(deviceData, this.displayMode);
668
- break;
669
- case 'DefaultHeatingSetTemperature':
670
- deviceData.Device[key] = value;
671
- deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.SetTemperature;
672
- set = await this.melCloudAta.send(deviceData, this.displayMode);
673
- break;
674
- case 'FanSpeed':
675
- deviceData.Device[key] = value;
676
- deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.SetFanSpeed;
677
- set = await this.melCloudAta.send(deviceData, this.displayMode);
678
- break;
679
- case 'VaneHorizontalDirection':
680
- deviceData.Device[key] = value;
681
- deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.VaneHorizontal;
682
- set = await this.melCloudAta.send(deviceData, this.displayMode);
683
- break;
684
- case 'VaneVerticalDirection':
685
- deviceData.Device[key] = value;
686
- deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.VaneVertical;
687
- set = await this.melCloudAta.send(deviceData, this.displayMode);
688
- break;
689
- case 'HideVaneControls':
690
- deviceData[key] = value;
691
- deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Prohibit;
692
- set = await this.melCloudAta.send(deviceData, this.displayMode);
693
- break;
694
- case 'HideDryModeControl':
695
- deviceData[key] = value;
696
- deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Prohibit;
697
- await this.melCloudAta.send(deviceData, this.displayMode);
698
- break;
699
- case 'ProhibitSetTemperature':
700
- deviceData.Device[key] = value;
701
- deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Prohibit;
702
- set = await this.melCloudAta.send(deviceData, this.displayMode);
703
- break;
704
- case 'ProhibitOperationMode':
705
- deviceData.Device[key] = value;
706
- deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Prohibit;
707
- await this.melCloudAta.send(deviceData, this.displayMode);
708
- break;
709
- case 'ProhibitPower':
710
- deviceData.Device[key] = value;
711
- deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Prohibit;
712
- set = await this.melCloudAta.send(deviceData, this.displayMode);
713
- break;
714
- default:
715
- this.emit('warn', `${integration}, received key: ${key}, value: ${value}`);
716
- break;
717
- };
718
- return set;
719
- } catch (error) {
720
- throw new Error(`${integration} set key: ${key}, value: ${value}, error: ${error.message ?? error}`);
721
- };
722
- }
723
-
724
- //prepare accessory
725
- async prepareAccessory(accountInfo, deviceData, deviceId, deviceTypeText, deviceName, accountName) {
726
- try {
727
- const presetsOnServer = this.accessory.presets;
728
- const modelSupportsHeat = this.accessory.modelSupportsHeat;
729
- const modelSupportsDry = this.accessory.modelSupportsDry;
730
- const modelSupportsCool = this.accessory.modelSupportsCool;
731
- const modelSupportsAuto = this.accessory.modelSupportsAuto;
732
- const modelSupportsFanSpeed = this.accessory.modelSupportsFanSpeed;
733
- const hasAutomaticFanSpeed = this.accessory.hasAutomaticFanSpeed;
734
- const hasOutdoorTemperature = this.accessory.hasOutdoorTemperature;
735
- const numberOfFanSpeeds = this.accessory.numberOfFanSpeeds;
736
- const swingFunction = this.accessory.swingFunction;
737
- const autoDryFanMode = [this.accessory.operationMode, 8, modelSupportsDry ? 2 : 8, 7][this.autoDryFanMode]; //NONE, AUTO - 8, DRY - 2, FAN - 7
738
- const heatDryFanMode = [this.accessory.operationMode, 1, modelSupportsDry ? 2 : 1, 7][this.heatDryFanMode]; //NONE, HEAT - 1, DRY - 2, FAN - 7
739
- const coolDryFanMode = [this.accessory.operationMode, 3, modelSupportsDry ? 2 : 3, 7][this.coolDryFanMode]; //NONE, COOL - 3, DRY - 2, FAN - 7
740
-
741
- //accessory
742
- const debug = this.enableDebugMode ? this.emit('debug', `Prepare accessory`) : false;
743
- const accessoryName = deviceName;
744
- const accessoryUUID = AccessoryUUID.generate(accountName + deviceId.toString());
745
- const accessoryCategory = Categories.AIR_CONDITIONER;
746
- const accessory = new Accessory(accessoryName, accessoryUUID, accessoryCategory);
747
-
748
- //information service
749
- const debug1 = this.enableDebugMode ? this.emit('debug', `Prepare information service`) : false;
750
- accessory.getService(Service.AccessoryInformation)
751
- .setCharacteristic(Characteristic.Manufacturer, this.manufacturer)
752
- .setCharacteristic(Characteristic.Model, this.model)
753
- .setCharacteristic(Characteristic.SerialNumber, this.serialNumber)
754
- .setCharacteristic(Characteristic.FirmwareRevision, this.firmwareRevision)
755
- .setCharacteristic(Characteristic.ConfiguredName, accessoryName);
756
-
757
- //melcloud services
758
- const serviceName = `${deviceTypeText} ${accessoryName}`;
759
- switch (this.displayMode) {
760
- case 1: //Heater Cooler
761
- const debug = this.enableDebugMode ? this.emit('debug', `Prepare heater/cooler service`) : false;
762
- this.melCloudService = new Service.HeaterCooler(serviceName, `HeaterCooler ${deviceId}`);
763
- this.melCloudService.getCharacteristic(Characteristic.Active)
764
- .onGet(async () => {
765
- const state = this.accessory.power;
766
- return state;
767
- })
768
- .onSet(async (state) => {
769
- try {
770
- deviceData.Device.Power = [false, true][state];
771
- deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Power;
772
- await this.melCloudAta.send(deviceData, this.displayMode);
773
- const info = this.disableLogInfo ? false : this.emit('message', `Set power: ${state ? 'ON' : 'OFF'}`);
774
- } catch (error) {
775
- this.emit('warn', `Set power error: ${error}`);
776
- };
777
- });
778
- this.melCloudService.getCharacteristic(Characteristic.CurrentHeaterCoolerState)
779
- .onGet(async () => {
780
- const value = this.accessory.currentOperationMode;
781
- return value;
782
- });
783
- this.melCloudService.getCharacteristic(Characteristic.TargetHeaterCoolerState)
784
- .setProps({
785
- minValue: this.accessory.operationModeSetPropsMinValue,
786
- maxValue: this.accessory.operationModeSetPropsMaxValue,
787
- validValues: this.accessory.operationModeSetPropsValidValues
788
- })
789
- .onGet(async () => {
790
- const value = this.accessory.targetOperationMode; //1 = HEAT, 2 = DRY 3 = COOL, 7 = FAN, 8 = AUTO
791
- return value;
792
- })
793
- .onSet(async (value) => {
794
- try {
795
- switch (value) {
796
- case 0: //AUTO - AUTO
797
- deviceData.Device.OperationMode = autoDryFanMode;
798
- break;
799
- case 1: //HEAT - HEAT
800
- deviceData.Device.OperationMode = heatDryFanMode;
801
- break;
802
- case 2: //COOL - COOL
803
- deviceData.Device.OperationMode = coolDryFanMode;
804
- break;
805
- };
211
+ //melcloud services
212
+ const serviceName = `${deviceTypeText} ${accessoryName}`;
213
+ switch (this.displayMode) {
214
+ case 1: //Heater Cooler
215
+ const debug = this.enableDebugMode ? this.emit('debug', `Prepare heater/cooler service`) : false;
216
+ this.melCloudService = new Service.HeaterCooler(serviceName, `HeaterCooler ${deviceId}`);
217
+ this.melCloudService.getCharacteristic(Characteristic.Active)
218
+ .onGet(async () => {
219
+ const state = this.accessory.power;
220
+ return state;
221
+ })
222
+ .onSet(async (state) => {
223
+ try {
224
+ deviceData.Device.Power = [false, true][state];
225
+ deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Power;
226
+ await this.melCloudAta.send(deviceData, this.displayMode);
227
+ const info = this.disableLogInfo ? false : this.emit('message', `Set power: ${state ? 'ON' : 'OFF'}`);
228
+ } catch (error) {
229
+ this.emit('warn', `Set power error: ${error}`);
230
+ };
231
+ });
232
+ this.melCloudService.getCharacteristic(Characteristic.CurrentHeaterCoolerState)
233
+ .onGet(async () => {
234
+ const value = this.accessory.currentOperationMode;
235
+ return value;
236
+ });
237
+ this.melCloudService.getCharacteristic(Characteristic.TargetHeaterCoolerState)
238
+ .setProps({
239
+ minValue: this.accessory.operationModeSetPropsMinValue,
240
+ maxValue: this.accessory.operationModeSetPropsMaxValue,
241
+ validValues: this.accessory.operationModeSetPropsValidValues
242
+ })
243
+ .onGet(async () => {
244
+ const value = this.accessory.targetOperationMode; //1 = HEAT, 2 = DRY 3 = COOL, 7 = FAN, 8 = AUTO
245
+ return value;
246
+ })
247
+ .onSet(async (value) => {
248
+ try {
249
+ switch (value) {
250
+ case 0: //AUTO - AUTO
251
+ deviceData.Device.OperationMode = autoDryFanMode;
252
+ break;
253
+ case 1: //HEAT - HEAT
254
+ deviceData.Device.OperationMode = heatDryFanMode;
255
+ break;
256
+ case 2: //COOL - COOL
257
+ deviceData.Device.OperationMode = coolDryFanMode;
258
+ break;
259
+ };
806
260
 
807
261
  deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.OperationModeSetTemperature;
808
262
  await this.melCloudAta.send(deviceData, this.displayMode);
@@ -1363,37 +817,584 @@ class DeviceAta extends EventEmitter {
1363
817
  deviceData.Device.ProhibitPower = state;
1364
818
  deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Prohibit;
1365
819
  break;
1366
- case 38: //PHYSICAL LOCK CONTROLS POWER
1367
- deviceData.Device.ProhibitPower = state;
1368
- deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Prohibit;
820
+ case 38: //PHYSICAL LOCK CONTROLS POWER
821
+ deviceData.Device.ProhibitPower = state;
822
+ deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Prohibit;
823
+ break;
824
+ case 39: //PHYSICAL LOCK CONTROLS MODE
825
+ deviceData.Device.ProhibitOperationMode = state;
826
+ deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Prohibit;
827
+ break;
828
+ case 40: //PHYSICAL LOCK CONTROLS TEMP
829
+ deviceData.Device.ProhibitSetTemperature = state;
830
+ deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Prohibit;
831
+ break;
832
+ default:
833
+ this.emit('message', `Unknown button mode: ${mode}`);
834
+ break;
835
+ };
836
+
837
+ await this.melCloudAta.send(deviceData, this.displayMode);
838
+ const info = this.disableLogInfo ? false : this.emit('message', `${state ? `Set: ${buttonName}` : `Unset: ${buttonName}, Set: ${button.previousValue}`}`);
839
+ } catch (error) {
840
+ this.emit('warn', `Set button error: ${error}`);
841
+ };
842
+ });
843
+ this.buttonsServices.push(buttonService);
844
+ accessory.addService(buttonService);
845
+ };
846
+ };
847
+
848
+ return accessory;
849
+ } catch (error) {
850
+ throw new Error(`Prepare accessory error: ${error.message || error}`);
851
+ };
852
+ };
853
+
854
+ //start
855
+ async start() {
856
+ try {
857
+ //melcloud device
858
+ this.melCloudAta = new MelCloudAta({
859
+ contextKey: this.contextKey,
860
+ devicesFile: this.devicesFile,
861
+ deviceId: this.deviceId,
862
+ debugLog: this.enableDebugMode
863
+ });
864
+
865
+ this.melCloudAta.on('externalIntegrations', (deviceData) => {
866
+ try {
867
+ //RESTFul server
868
+ const restFulEnabled = this.restFul.enable || false;
869
+ if (restFulEnabled) {
870
+ if (!this.restFulConnected) {
871
+ this.restFul1 = new RestFul({
872
+ port: this.deviceId.slice(-4),
873
+ debug: this.restFul.debug || false
874
+ });
875
+
876
+ this.restFul1.on('connected', (message) => {
877
+ this.restFulConnected = true;
878
+ this.emit('success', message);
879
+ })
880
+ .on('set', async (key, value) => {
881
+ try {
882
+ await this.setOverExternalIntegration('RESTFul', deviceData, key, value);
883
+ } catch (error) {
884
+ this.emit('warn', error);
885
+ };
886
+ })
887
+ .on('debug', (debug) => {
888
+ this.emit('debug', debug);
889
+ })
890
+ .on('error', (error) => {
891
+ this.emit('warn', error);
892
+ });
893
+ }
894
+ const restFul0 = this.restFulConnected ? this.restFul1.update('info', deviceData) : false;
895
+ const restFul1 = this.restFulConnected ? this.restFul1.update('state', deviceData.Device) : false;
896
+ }
897
+
898
+ //MQTT client
899
+ const mqttEnabled = this.mqtt.enable || false;
900
+ if (mqttEnabled) {
901
+ if (!this.mqttConnected) {
902
+ this.mqtt1 = new Mqtt({
903
+ host: this.mqtt.host,
904
+ port: this.mqtt.port || 1883,
905
+ clientId: `${this.mqtt.clientId}_${this.deviceId}` || `${this.deviceTypeText}_${this.deviceName}_${this.deviceId}`,
906
+ prefix: `${this.mqtt.prefix}/${this.deviceTypeText}/${this.deviceName}`,
907
+ user: this.mqtt.user,
908
+ passwd: this.mqtt.pass,
909
+ debug: this.mqtt.debug || false
910
+ });
911
+
912
+ this.mqtt1.on('connected', (message) => {
913
+ this.mqttConnected = true;
914
+ this.emit('success', message);
915
+ })
916
+ .on('subscribed', (message) => {
917
+ this.emit('success', message);
918
+ })
919
+ .on('set', async (key, value) => {
920
+ try {
921
+ await this.setOverExternalIntegration('MQTT', deviceData, key, value);
922
+ } catch (error) {
923
+ this.emit('warn', error);
924
+ };
925
+ })
926
+ .on('debug', (debug) => {
927
+ this.emit('debug', debug);
928
+ })
929
+ .on('error', (error) => {
930
+ this.emit('warn', error);
931
+ });
932
+ }
933
+ const mqtt0 = this.mqttConnected ? this.mqtt1.emit('publish', `Info`, deviceData) : false;
934
+ const mqtt1 = this.mqttConnected ? this.mqtt1.emit('publish', `State`, deviceData.Device) : false;
935
+ }
936
+
937
+ } catch (error) {
938
+ this.emit('warn', `External integration start error: ${error}.`);
939
+ };
940
+ })
941
+ .on('deviceInfo', (manufacturer, modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion) => {
942
+ if (!this.displayDeviceInfo) {
943
+ return;
944
+ }
945
+
946
+ if (!this.disableLogDeviceInfo) {
947
+ this.emit('devInfo', `---- ${this.deviceTypeText}: ${this.deviceName} ----`);
948
+ this.emit('devInfo', `Account: ${this.accountName}`);
949
+ const indoor = modelIndoor ? this.emit('devInfo', `Indoor: ${modelIndoor}`) : false;
950
+ const outdoor = modelOutdoor ? this.emit('devInfo', `Outdoor: ${modelOutdoor}`) : false
951
+ this.emit('devInfo', `Serial: ${serialNumber}`);
952
+ this.emit('devInfo', `Firmware: ${firmwareAppVersion}`);
953
+ this.emit('devInfo', `Manufacturer: ${manufacturer}`);
954
+ this.emit('devInfo', '----------------------------------');
955
+ };
956
+
957
+ //accessory info
958
+ this.manufacturer = manufacturer;
959
+ this.model = modelIndoor ? modelIndoor : modelOutdoor ? modelOutdoor : `${this.deviceTypeText} ${this.deviceId}`;
960
+ this.serialNumber = serialNumber;
961
+ this.firmwareRevision = firmwareAppVersion;
962
+ this.displayDeviceInfo = false;
963
+ })
964
+ .on('deviceState', async (deviceData) => {
965
+ //presets
966
+ const presetsOnServer = deviceData.Presets ?? [];
967
+
968
+ //device control
969
+ const hideVaneControls = deviceData.HideVaneControls ?? false;
970
+ const hideDryModeControl = deviceData.HideDryModeControl ?? false;
971
+
972
+ //device info
973
+ const hasAutomaticFanSpeed = deviceData.Device.HasAutomaticFanSpeed ?? false;
974
+ const airDirectionFunction = deviceData.Device.AirDirectionFunction ?? false;
975
+ const swingFunction = deviceData.Device.SwingFunction ?? false;
976
+ const hasOutdoorTemperature = deviceData.Device.HasOutdoorTemperature ?? false;
977
+ const numberOfFanSpeeds = deviceData.Device.NumberOfFanSpeeds ?? 0;
978
+ const modelSupportsFanSpeed = deviceData.Device.ModelSupportsFanSpeed ?? false;
979
+ const modelSupportsAuto1 = deviceData.Device.ModelSupportsAuto ?? false;
980
+ const modelSupportsAuto = this.autoDryFanMode >= 1 && modelSupportsAuto1
981
+ const modelSupportsHeat1 = deviceData.Device.ModelSupportsHeat ?? false;
982
+ const modelSupportsHeat = this.heatDryFanMode >= 1 && modelSupportsHeat1;
983
+ const modelSupportsDry = deviceData.Device.ModelSupportsDry ?? false;
984
+ const modelSupportsCool = this.coolDryFanMode >= 1;
985
+ const minTempHeat = 10;
986
+ const maxTempHeat = 31;
987
+ const minTempCoolDry = 16;
988
+ const maxTempCoolDry = 31;
989
+
990
+ //device state
991
+ const power = deviceData.Device.Power ?? false;
992
+ const inStandbyMode = deviceData.Device.InStandbyMode ?? false;
993
+ const roomTemperature = deviceData.Device.RoomTemperature;
994
+ const setTemperature = deviceData.Device.SetTemperature ?? 20;
995
+ const defaultHeatingSetTemperature = deviceData.Device.DefaultHeatingSetTemperature ?? 20;
996
+ const defaultCoolingSetTemperature = deviceData.Device.DefaultCoolingSetTemperature ?? 23;
997
+ const actualFanSpeed = deviceData.Device.ActualFanSpeed;
998
+ const automaticFanSpeed = deviceData.Device.AutomaticFanSpeed;
999
+ const fanSpeed = deviceData.Device.FanSpeed ?? 0;
1000
+ const operationMode = deviceData.Device.OperationMode;
1001
+ const vaneVerticalDirection = deviceData.Device.VaneVerticalDirection;
1002
+ const vaneVerticalSwing = deviceData.Device.VaneVerticalSwing;
1003
+ const vaneHorizontalDirection = deviceData.Device.VaneHorizontalDirection;
1004
+ const vaneHorizontalSwing = deviceData.Device.VaneHorizontalSwing;
1005
+ const prohibitSetTemperature = deviceData.Device.ProhibitSetTemperature ?? false;
1006
+ const prohibitOperationMode = deviceData.Device.ProhibitOperationMode ?? false;
1007
+ const prohibitPower = deviceData.Device.ProhibitPower ?? false;
1008
+ const temperatureIncrement = deviceData.Device.TemperatureIncrement ?? 1;
1009
+ const outdoorTemperature = deviceData.Device.OutdoorTemperature;
1010
+
1011
+ //accessory
1012
+ this.accessory.presets = presetsOnServer;
1013
+ this.accessory.hasAutomaticFanSpeed = hasAutomaticFanSpeed;
1014
+ this.accessory.airDirectionFunction = airDirectionFunction;
1015
+ this.accessory.swingFunction = swingFunction;
1016
+ this.accessory.hasOutdoorTemperature = hasOutdoorTemperature;
1017
+ this.accessory.numberOfFanSpeeds = numberOfFanSpeeds;
1018
+ this.accessory.modelSupportsFanSpeed = modelSupportsFanSpeed;
1019
+ this.accessory.modelSupportsAuto = modelSupportsAuto;
1020
+ this.accessory.modelSupportsHeat = modelSupportsHeat;
1021
+ this.accessory.modelSupportsDry = modelSupportsDry;
1022
+ this.accessory.modelSupportsCool = modelSupportsCool;
1023
+ this.accessory.minTempHeat = minTempHeat;
1024
+ this.accessory.maxTempHeat = maxTempHeat;
1025
+ this.accessory.minTempCoolDry = minTempCoolDry;
1026
+ this.accessory.maxTempCoolDry = maxTempCoolDry;
1027
+
1028
+ this.accessory.power = power ? 1 : 0;
1029
+ this.accessory.inStandbyMode = inStandbyMode;
1030
+ this.accessory.operationMode = operationMode;
1031
+ this.accessory.roomTemperature = roomTemperature;
1032
+ this.accessory.outdoorTemperature = outdoorTemperature;
1033
+ this.accessory.setTemperature = setTemperature;
1034
+ this.accessory.defaultHeatingSetTemperature = defaultHeatingSetTemperature;
1035
+ this.accessory.defaultCoolingSetTemperature = defaultCoolingSetTemperature;
1036
+ this.accessory.actualFanSpeed = actualFanSpeed;
1037
+ this.accessory.automaticFanSpeed = automaticFanSpeed;
1038
+ this.accessory.vaneVerticalSwing = vaneVerticalSwing;
1039
+ this.accessory.vaneHorizontalSwing = vaneHorizontalSwing;
1040
+ this.accessory.swingMode = swingFunction && vaneHorizontalDirection === 12 && vaneVerticalDirection === 7 ? 1 : 0;
1041
+ this.accessory.lockPhysicalControl = prohibitSetTemperature && prohibitOperationMode && prohibitPower ? 1 : 0;
1042
+ this.accessory.temperatureIncrement = temperatureIncrement;
1043
+
1044
+ //operating mode 0, HEAT, DRY, COOL, 4, 5, 6, FAN, AUTO, ISEE HEAT, ISEE DRY, ISEE COOL
1045
+ switch (this.displayMode) {
1046
+ case 1: //Heater Cooler
1047
+ switch (operationMode) {
1048
+ case 1: //HEAT
1049
+ this.accessory.currentOperationMode = roomTemperature > setTemperature ? 1 : 2; //INACTIVE, IDLE, HEATING, COOLING
1050
+ this.accessory.targetOperationMode = 1; //AUTO, HEAT, COOL
1051
+ break;
1052
+ case 2: //DRY
1053
+ this.accessory.currentOperationMode = 1;
1054
+ this.accessory.targetOperationMode = this.autoDryFanMode === 2 ? 0 : this.heatDryFanMode === 2 ? 1 : this.coolDryFanMode === 2 ? 2 : this.accessory.targetOperationMode ?? 0;
1055
+ break;
1056
+ case 3: //COOL
1057
+ this.accessory.currentOperationMode = roomTemperature < setTemperature ? 1 : 3;
1058
+ this.accessory.targetOperationMode = 2;
1059
+ break;
1060
+ case 7: //FAN
1061
+ this.accessory.currentOperationMode = 1;
1062
+ this.accessory.targetOperationMode = this.autoDryFanMode === 3 ? 0 : this.heatDryFanMode === 3 ? 1 : this.coolDryFanMode === 3 ? 2 : this.accessory.targetOperationMode ?? 0;
1063
+ break;
1064
+ case 8: //AUTO
1065
+ this.accessory.currentOperationMode = roomTemperature > setTemperature ? 3 : roomTemperature < setTemperature ? 2 : 1;
1066
+ this.accessory.targetOperationMode = 0;
1067
+ break;
1068
+ case 9: //ISEE HEAT
1069
+ this.accessory.currentOperationMode = roomTemperature > setTemperature ? 1 : 2
1070
+ this.accessory.targetOperationMode = 1;
1071
+ break;
1072
+ case 10: //ISEE DRY
1073
+ this.accessory.currentOperationMode = 1;
1074
+ this.accessory.targetOperationMode = this.autoDryFanMode === 2 ? 0 : this.heatDryFanMode === 2 ? 1 : this.coolDryFanMode === 2 ? 2 : this.accessory.targetOperationMode ?? 0;
1075
+ break;
1076
+ case 11: //ISEE COOL;
1077
+ this.accessory.currentOperationMode = roomTemperature < setTemperature ? 1 : 3;
1078
+ this.accessory.targetOperationMode = 2;
1079
+ break;
1080
+ default:
1081
+ this.emit('warn', `Unknown operating mode: ${operationMode}`);
1082
+ return
1083
+ };
1084
+
1085
+ this.accessory.currentOperationMode = !power ? 0 : inStandbyMode ? 1 : this.accessory.currentOperationMode;
1086
+ this.accessory.operationModeSetPropsMinValue = modelSupportsAuto && modelSupportsHeat ? 0 : !modelSupportsAuto && modelSupportsHeat ? 1 : modelSupportsAuto && !modelSupportsHeat ? 0 : 2;
1087
+ this.accessory.operationModeSetPropsMaxValue = 2
1088
+ this.accessory.operationModeSetPropsValidValues = modelSupportsAuto && modelSupportsHeat ? [0, 1, 2] : !modelSupportsAuto && modelSupportsHeat ? [1, 2] : modelSupportsAuto && !modelSupportsHeat ? [0, 2] : [2];
1089
+
1090
+ //fan speed mode
1091
+ if (modelSupportsFanSpeed) {
1092
+ switch (numberOfFanSpeeds) {
1093
+ case 2: //Fan speed mode 2
1094
+ this.accessory.fanSpeed = hasAutomaticFanSpeed ? [3, 1, 2][fanSpeed] : [0, 1, 2][fanSpeed];
1095
+ this.accessory.fanSpeedSetPropsMaxValue = hasAutomaticFanSpeed ? 3 : 2;
1096
+ break;
1097
+ case 3: //Fan speed mode 3
1098
+ this.accessory.fanSpeed = hasAutomaticFanSpeed ? [4, 1, 2, 3][fanSpeed] : [0, 1, 2, 3][fanSpeed];
1099
+ this.accessory.fanSpeedSetPropsMaxValue = hasAutomaticFanSpeed ? 4 : 3;
1369
1100
  break;
1370
- case 39: //PHYSICAL LOCK CONTROLS MODE
1371
- deviceData.Device.ProhibitOperationMode = state;
1372
- deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Prohibit;
1101
+ case 4: //Fan speed mode 4
1102
+ this.accessory.fanSpeed = hasAutomaticFanSpeed ? [5, 1, 2, 3, 4][fanSpeed] : [0, 1, 2, 3, 4][fanSpeed];
1103
+ this.accessory.fanSpeedSetPropsMaxValue = hasAutomaticFanSpeed ? 5 : 4;
1373
1104
  break;
1374
- case 40: //PHYSICAL LOCK CONTROLS TEMP
1375
- deviceData.Device.ProhibitSetTemperature = state;
1376
- deviceData.Device.EffectiveFlags = AirConditioner.EffectiveFlags.Prohibit;
1105
+ case 5: //Fan speed mode 5
1106
+ this.accessory.fanSpeed = hasAutomaticFanSpeed ? [6, 1, 2, 3, 4, 5][fanSpeed] : [0, 1, 2, 3, 4, 5][fanSpeed];
1107
+ this.accessory.fanSpeedSetPropsMaxValue = hasAutomaticFanSpeed ? 6 : 5;
1377
1108
  break;
1378
- default:
1379
- this.emit('message', `Unknown button mode: ${mode}`);
1109
+ case 6: //Fan speed mode 6
1110
+ this.accessory.fanSpeed = hasAutomaticFanSpeed ? [7, 1, 2, 3, 4, 5, 6][fanSpeed] : [0, 1, 2, 3, 4, 5, 6][fanSpeed];
1111
+ this.accessory.fanSpeedSetPropsMaxValue = hasAutomaticFanSpeed ? 7 : 6;
1380
1112
  break;
1381
1113
  };
1114
+ };
1115
+
1116
+ //update characteristics
1117
+ if (this.melCloudService) {
1118
+ this.melCloudService
1119
+ .updateCharacteristic(Characteristic.Active, power ? 1 : 0)
1120
+ .updateCharacteristic(Characteristic.CurrentHeaterCoolerState, this.accessory.currentOperationMode)
1121
+ .updateCharacteristic(Characteristic.TargetHeaterCoolerState, this.accessory.targetOperationMode)
1122
+ .updateCharacteristic(Characteristic.CurrentTemperature, roomTemperature)
1123
+ .updateCharacteristic(Characteristic.LockPhysicalControls, this.accessory.lockPhysicalControl)
1124
+ .updateCharacteristic(Characteristic.TemperatureDisplayUnits, this.accessory.useFahrenheit)
1125
+ .updateCharacteristic(Characteristic.CoolingThresholdTemperature, defaultCoolingSetTemperature);
1126
+ const updateDefHeat = modelSupportsHeat ? this.melCloudService.updateCharacteristic(Characteristic.HeatingThresholdTemperature, defaultHeatingSetTemperature) : false;
1127
+ const updateRS = modelSupportsFanSpeed ? this.melCloudService.updateCharacteristic(Characteristic.RotationSpeed, this.accessory.fanSpeed) : false;
1128
+ const updateSM = swingFunction ? this.melCloudService.updateCharacteristic(Characteristic.SwingMode, this.accessory.swingMode) : false;
1129
+ };
1130
+ break;
1131
+ case 2: //Thermostat
1132
+ switch (operationMode) {
1133
+ case 1: //HEAT
1134
+ this.accessory.currentOperationMode = roomTemperature > setTemperature ? 0 : 1; //OFF, HEATING, COOLING
1135
+ this.accessory.targetOperationMode = 1; //OFF, HEAT, COOL, AUTO
1136
+ break;
1137
+ case 2: //DRY
1138
+ this.accessory.currentOperationMode = 0;
1139
+ this.accessory.targetOperationMode = this.autoDryFanMode === 2 ? 3 : this.heatDryFanMode === 2 ? 1 : this.coolDryFanMode === 2 ? 2 : this.accessory.targetOperationMode ?? 0;
1140
+ break;
1141
+ case 3: //COOL
1142
+ this.accessory.currentOperationMode = roomTemperature < setTemperature ? 0 : 2;
1143
+ this.accessory.targetOperationMode = 2;
1144
+ break;
1145
+ case 7: //FAN
1146
+ this.accessory.currentOperationMode = 0;
1147
+ this.accessory.targetOperationMode = this.autoDryFanMode === 3 ? 3 : this.heatDryFanMode === 3 ? 1 : this.coolDryFanMode === 3 ? 2 : this.accessory.targetOperationMode ?? 0;
1148
+ break;
1149
+ case 8: //AUTO
1150
+ this.accessory.currentOperationMode = roomTemperature < setTemperature ? 1 : roomTemperature > setTemperature ? 2 : 0;
1151
+ this.accessory.targetOperationMode = 3;
1152
+ break;
1153
+ case 9: //ISEE HEAT
1154
+ this.accessory.currentOperationMode = roomTemperature > setTemperature ? 0 : 1;
1155
+ this.accessory.targetOperationMode = 1;
1156
+ break;
1157
+ case 10: //ISEE DRY
1158
+ this.accessory.currentOperationMode = 0;
1159
+ this.accessory.targetOperationMode = this.autoDryFanMode === 2 ? 3 : this.heatDryFanMode === 2 ? 1 : this.coolDryFanMode === 2 ? 2 : this.accessory.targetOperationMode ?? 0;
1160
+ break;
1161
+ case 11: //ISEE COOL;
1162
+ this.accessory.currentOperationMode = roomTemperature < setTemperature ? 0 : 2;
1163
+ this.accessory.targetOperationMode = 2;
1164
+ break;
1165
+ default:
1166
+ this.emit('warn', `Unknown operating mode: ${operationMode}`);
1167
+ break;
1168
+ };
1382
1169
 
1383
- await this.melCloudAta.send(deviceData, this.displayMode);
1384
- const info = this.disableLogInfo ? false : this.emit('message', `${state ? `Set: ${buttonName}` : `Unset: ${buttonName}, Set: ${button.previousValue}`}`);
1385
- } catch (error) {
1386
- this.emit('warn', `Set button error: ${error}`);
1170
+ this.accessory.currentOperationMode = !power ? 0 : this.accessory.currentOperationMode;
1171
+ this.accessory.targetOperationMode = !power ? 0 : this.accessory.targetOperationMode;
1172
+ this.accessory.operationModeSetPropsMinValue = 0
1173
+ this.accessory.operationModeSetPropsMaxValue = modelSupportsAuto && modelSupportsHeat ? 3 : !modelSupportsAuto && modelSupportsHeat ? 2 : modelSupportsAuto && !modelSupportsHeat ? 3 : 2;
1174
+ this.accessory.operationModeSetPropsValidValues = modelSupportsAuto && modelSupportsHeat ? [0, 1, 2, 3] : !modelSupportsAuto && modelSupportsHeat ? [0, 1, 2] : modelSupportsAuto && !modelSupportsHeat ? [0, 2, 3] : [0, 2];
1175
+
1176
+ //update characteristics
1177
+ if (this.melCloudService) {
1178
+ this.melCloudService
1179
+ .updateCharacteristic(Characteristic.CurrentHeatingCoolingState, this.accessory.currentOperationMode)
1180
+ .updateCharacteristic(Characteristic.TargetHeatingCoolingState, this.accessory.targetOperationMode)
1181
+ .updateCharacteristic(Characteristic.CurrentTemperature, roomTemperature)
1182
+ .updateCharacteristic(Characteristic.TargetTemperature, setTemperature)
1183
+ .updateCharacteristic(Characteristic.TemperatureDisplayUnits, this.accessory.useFahrenheit);
1387
1184
  };
1388
- });
1389
- this.buttonsServices.push(buttonService);
1390
- accessory.addService(buttonService);
1391
- };
1392
- };
1185
+ break;
1186
+ };
1393
1187
 
1394
- return accessory;
1188
+ if (this.roomTemperatureSensorService) {
1189
+ this.roomTemperatureSensorService
1190
+ .updateCharacteristic(Characteristic.CurrentTemperature, roomTemperature)
1191
+ };
1192
+
1193
+ if (this.outdoorTemperatureSensorService) {
1194
+ this.outdoorTemperatureSensorService
1195
+ .updateCharacteristic(Characteristic.CurrentTemperature, outdoorTemperature)
1196
+ };
1197
+
1198
+ //update presets state
1199
+ if (this.presetsConfigured.length > 0) {
1200
+ for (let i = 0; i < this.presetsConfigured.length; i++) {
1201
+ const preset = this.presetsConfigured[i];
1202
+ const presetData = presetsOnServer.find(p => p.ID === preset.Id);
1203
+
1204
+ preset.state = presetData ? (presetData.Power === power
1205
+ && presetData.SetTemperature === setTemperature
1206
+ && presetData.OperationMode === operationMode
1207
+ && presetData.VaneHorizontal === vaneHorizontalDirection
1208
+ && presetData.VaneVertical === vaneVerticalDirection
1209
+ && presetData.FanSpeed === fanSpeed) : false;
1210
+
1211
+ if (this.presetsServices) {
1212
+ const characteristicType = preset.characteristicType;
1213
+ this.presetsServices[i]
1214
+ .updateCharacteristic(characteristicType, preset.state)
1215
+ };
1216
+ };
1217
+ };
1218
+
1219
+ //update buttons state
1220
+ if (this.buttonsConfiguredCount > 0) {
1221
+ for (let i = 0; i < this.buttonsConfiguredCount; i++) {
1222
+ const button = this.buttonsConfigured[i];
1223
+ const mode = button.mode;
1224
+ switch (mode) {
1225
+ case 0: //POWER ON,OFF
1226
+ button.state = (power === true);
1227
+ break;
1228
+ case 1: //OPERATING MODE HEAT
1229
+ button.state = power ? (operationMode === 1 || operationMode === 9) : false;
1230
+ break;
1231
+ case 2: //OPERATING MODE DRY
1232
+ button.state = power ? (operationMode === 2 || operationMode === 10) : false;
1233
+ break
1234
+ case 3: //OPERATING MODE COOL
1235
+ button.state = power ? (operationMode === 3 || operationMode === 11) : false;
1236
+ break;
1237
+ case 4: //OPERATING MODE FAN
1238
+ button.state = power ? (operationMode === 7) : false;
1239
+ break;
1240
+ case 5: //OPERATING MODE AUTO
1241
+ button.state = power ? (operationMode === 8) : false;
1242
+ break;
1243
+ case 6: //OPERATING MODE PURIFY
1244
+ button.state = power ? (operationMode === 12) : false;
1245
+ break;
1246
+ case 7: //OPERATING MODE DRY CONTROL HIDE
1247
+ button.state = power ? (hideDryModeControl === true) : false;
1248
+ break;
1249
+ case 10: //VANE H SWING MODE AUTO
1250
+ button.state = power ? (vaneHorizontalDirection === 0) : false;
1251
+ break;
1252
+ case 11: //VANE H SWING MODE 1
1253
+ button.state = power ? (vaneHorizontalDirection === 1) : false;
1254
+ break;
1255
+ case 12: //VANE H SWING MODE 2
1256
+ button.state = power ? (vaneHorizontalDirection === 2) : false;
1257
+ break;
1258
+ case 13: //VANE H SWING MODE 3
1259
+ button.state = power ? (vaneHorizontalDirection === 3) : false;
1260
+ break;
1261
+ case 14: //VANE H SWING MODE 4
1262
+ button.state = power ? (vaneHorizontalDirection === 4) : false;
1263
+ break;
1264
+ case 15: //VANE H SWING MODE 5
1265
+ button.state = power ? (vaneHorizontalDirection === 5) : false;
1266
+ break;
1267
+ case 16: //VANE H SWING MODE SPLIT
1268
+ button.state = power ? (vaneHorizontalDirection === 8) : false;
1269
+ break;
1270
+ case 17: //VANE H SWING MODE SWING
1271
+ button.state = power ? (vaneHorizontalDirection === 12) : false;
1272
+ break;
1273
+ case 20: //VANE V SWING MODE AUTO
1274
+ button.state = power ? (vaneVerticalDirection === 0) : false;
1275
+ break;
1276
+ case 21: //VANE V SWING MODE 1
1277
+ button.state = power ? (vaneVerticalDirection === 1) : false;
1278
+ break;
1279
+ case 22: //VANE V SWING MODE 2
1280
+ button.state = power ? (vaneVerticalDirection === 2) : false;
1281
+ break;
1282
+ case 23: //VANE V SWING MODE 3
1283
+ button.state = power ? (vaneVerticalDirection === 3) : false;
1284
+ break;
1285
+ case 24: //VANE V SWING MODE 4
1286
+ button.state = power ? (vaneVerticalDirection === 4) : false;
1287
+ break;
1288
+ case 25: //VANE V SWING MODE 5
1289
+ button.state = power ? (vaneVerticalDirection === 5) : false;
1290
+ break;
1291
+ case 26: //VANE V SWING MODE SWING
1292
+ button.state = power ? (vaneVerticalDirection === 7) : false;
1293
+ break;
1294
+ case 27: //VANE H/V CONTROLS HIDE
1295
+ button.state = power ? (hideVaneControls === true) : false;
1296
+ break;
1297
+ case 30: //FAN SPEED MODE AUTO
1298
+ button.state = power ? (fanSpeed === 0) : false;
1299
+ break;
1300
+ case 31: //FAN SPEED MODE 1
1301
+ button.state = power ? (fanSpeed === 1) : false;
1302
+ break;
1303
+ case 32: //FAN SPEED MODE 2
1304
+ button.state = power ? (fanSpeed === 2) : false;
1305
+ break;
1306
+ case 33: //FAN SPEED MODE 3
1307
+ button.state = power ? (fanSpeed === 3) : false;
1308
+ break;
1309
+ case 34: //FAN SPEED MODE 4
1310
+ button.state = power ? (fanSpeed === 4) : false;
1311
+ break;
1312
+ case 35: //FAN SPEED MODE 5
1313
+ button.state = power ? (fanSpeed === 5) : false;
1314
+ break;
1315
+ case 36: //FAN SPEED MODE 6
1316
+ button.state = power ? (fanSpeed === 6) : false;
1317
+ break;
1318
+ case 37: //PHYSICAL LOCK CONTROLS ALL
1319
+ button.state = (this.accessory.lockPhysicalControl === 1);
1320
+ break;
1321
+ case 38: //PHYSICAL LOCK CONTROLS POWER
1322
+ button.state = (prohibitPower === true);
1323
+ break;
1324
+ case 39: //PHYSICAL LOCK CONTROLS MODE
1325
+ button.state = (prohibitOperationMode === true);
1326
+ break;
1327
+ case 40: //PHYSICAL LOCK CONTROLS TEMP
1328
+ button.state = (prohibitSetTemperature === true);
1329
+ break;
1330
+ default: //Unknown button
1331
+ this.emit('message', `Unknown button mode: ${mode} detected.`);
1332
+ break;
1333
+ };
1334
+
1335
+ //update services
1336
+ if (this.buttonsServices) {
1337
+ const characteristicType = button.characteristicType;
1338
+ this.buttonsServices[i]
1339
+ .updateCharacteristic(characteristicType, button.state)
1340
+ };
1341
+ };
1342
+ };
1343
+
1344
+ //log current state
1345
+ if (!this.disableLogInfo) {
1346
+ this.emit('message', `Power: ${power ? 'ON' : 'OFF'}`);
1347
+ this.emit('message', `Target operation mode: ${AirConditioner.DriveMode[operationMode]}`);
1348
+ this.emit('message', `Current operation mode: ${this.displayMode === 1 ? AirConditioner.CurrentOperationModeHeatherCooler[this.accessory.currentOperationMode] : AirConditioner.CurrentOperationModeThermostat[this.accessory.currentOperationMode]}`);
1349
+ this.emit('message', `Target temperature: ${setTemperature}${this.accessory.temperatureUnit}`);
1350
+ this.emit('message', `Current temperature: ${roomTemperature}${this.accessory.temperatureUnit}`);
1351
+ const info = hasOutdoorTemperature && outdoorTemperature !== null ? this.emit('message', `Outdoor temperature: ${outdoorTemperature}${this.accessory.temperatureUnit}`) : false;
1352
+ const info3 = modelSupportsFanSpeed ? this.emit('message', `Target fan speed: ${AirConditioner.FanSpeed[fanSpeed]}`) : false;
1353
+ const info4 = modelSupportsFanSpeed ? this.emit('message', `Current fan speed: ${AirConditioner.FanSpeed[actualFanSpeed]}`) : false;
1354
+ const info5 = vaneHorizontalDirection !== null ? this.emit('message', `Vane horizontal: ${AirConditioner.HorizontalVane[vaneHorizontalDirection] ?? vaneHorizontalDirection}`) : false;
1355
+ const info6 = vaneVerticalDirection !== null ? this.emit('message', `Vane vertical: ${AirConditioner.VerticalVane[vaneVerticalDirection] ?? vaneVerticalDirection}`) : false;
1356
+ const info7 = swingFunction ? this.emit('message', `Air direction: ${AirConditioner.AirDirection[this.accessory.swingMode]}`) : false;
1357
+ this.emit('message', `Temperature display unit: ${this.accessory.temperatureUnit}`);
1358
+ this.emit('message', `Lock physical controls: ${this.accessory.lockPhysicalControl ? 'LOCKED' : 'UNLOCKED'}`);
1359
+ };
1360
+
1361
+ //start prepare accessory
1362
+ if (!this.startPrepareAccessory) {
1363
+ return;
1364
+ }
1365
+ try {
1366
+ const accessory = await this.prepareAccessory(this.accountInfo, deviceData, this.deviceId, this.deviceTypeText, this.deviceName, this.accountName);
1367
+ this.emit('publishAccessory', accessory);
1368
+ this.startPrepareAccessory = false;
1369
+ } catch (error) {
1370
+ this.emit('error', error);
1371
+ };
1372
+ })
1373
+ .on('success', (message) => {
1374
+ this.emit('success', message);
1375
+ })
1376
+ .on('message', (message) => {
1377
+ this.emit('message', message);
1378
+ })
1379
+ .on('debug', (debug) => {
1380
+ this.emit('debug', debug);
1381
+ })
1382
+ .on('warn', async (warn) => {
1383
+ this.emit('warn', warn);
1384
+ })
1385
+ .on('error', async (error) => {
1386
+ this.emit('error', error);
1387
+ });
1388
+
1389
+ //check state
1390
+ await this.melCloudAta.checkState();
1391
+
1392
+ //start impule generator
1393
+ await this.melCloudAta.impulseGenerator.start([{ name: 'checkState', sampling: this.refreshInterval }]);
1394
+
1395
+ return true;
1395
1396
  } catch (error) {
1396
- throw new Error(`Prepare accessory error: ${error.message || error}`);
1397
+ throw new Error(`Start error: ${error}`);
1397
1398
  };
1398
1399
  };
1399
1400
  };