homebridge-melcloud-control 4.3.3-beta.2 → 4.3.3-beta.21

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 CHANGED
@@ -22,6 +22,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
22
22
 
23
23
  - Do not use Homebridge UI > v5.5.0 because of break config.json
24
24
 
25
+ # [4.3.2] - (xx.11.2025)
26
+
27
+ ## Changes
28
+
29
+ - fix presets report wrong state
30
+ - stability improvements
31
+ - bump dependencies
32
+ - cleanup
33
+
25
34
  # [4.3.2] - (21.11.2025)
26
35
 
27
36
  ## Changes
@@ -250,7 +250,7 @@
250
250
  const devicesByType = { ata: [], atw: [], erv: [] };
251
251
 
252
252
  response.Devices.forEach(d => {
253
- d.Scenes = response.Scenes ?? [];
253
+ d.Scenes = Array.isArray(response.Scenes) ? [...response.Scenes] : [];
254
254
  if (d.Type === 0) devicesByType.ata.push(d);
255
255
  if (d.Type === 1) devicesByType.atw.push(d);
256
256
  if (d.Type === 3) devicesByType.erv.push(d);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "MELCloud Control",
3
3
  "name": "homebridge-melcloud-control",
4
- "version": "4.3.3-beta.2",
4
+ "version": "4.3.3-beta.21",
5
5
  "description": "Homebridge plugin to control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.",
6
6
  "license": "MIT",
7
7
  "author": "grzegorz914",
@@ -35,7 +35,7 @@
35
35
  "node": "^20 || ^22 || ^24 || ^25"
36
36
  },
37
37
  "dependencies": {
38
- "@homebridge/plugin-ui-utils": "^2.1.1",
38
+ "@homebridge/plugin-ui-utils": "^2.1.2",
39
39
  "async-mqtt": "^2.6.3",
40
40
  "axios": "^1.13.2",
41
41
  "express": "^5.1.0",
package/src/deviceata.js CHANGED
@@ -915,7 +915,7 @@ class DeviceAta extends EventEmitter {
915
915
  presetControlSensorService.setCharacteristic(Characteristic.ConfiguredName, `${serviceName1} Control`);
916
916
  presetControlSensorService.getCharacteristic(characteristicType)
917
917
  .onGet(async () => {
918
- const state = this.accessory.scheduleEnabled;
918
+ const state = preset.state;
919
919
  return state;
920
920
  })
921
921
  this.presetControlSensorServices.push(presetControlSensorService);
package/src/deviceatw.js CHANGED
@@ -1230,7 +1230,7 @@ class DeviceAtw extends EventEmitter {
1230
1230
  presetControlSensorService.setCharacteristic(Characteristic.ConfiguredName, `${serviceName1} Control`);
1231
1231
  presetControlSensorService.getCharacteristic(characteristicType)
1232
1232
  .onGet(async () => {
1233
- const state = this.accessory.scheduleEnabled;
1233
+ const state = preset.state;
1234
1234
  return state;
1235
1235
  })
1236
1236
  this.presetControlSensorServices.push(presetControlSensorService);
package/src/deviceerv.js CHANGED
@@ -842,7 +842,7 @@ class DeviceErv extends EventEmitter {
842
842
  presetControlSensorService.setCharacteristic(Characteristic.ConfiguredName, `${serviceName1} Control`);
843
843
  presetControlSensorService.getCharacteristic(characteristicType)
844
844
  .onGet(async () => {
845
- const state = this.accessory.scheduleEnabled;
845
+ const state = preset.state;
846
846
  return state;
847
847
  })
848
848
  this.presetControlSensorServices.push(presetControlSensorService);
package/src/functions.js CHANGED
@@ -167,5 +167,16 @@ class Functions extends EventEmitter {
167
167
  else if (!isNaN(v) && v !== "") parsedValue = Number(v);
168
168
  return parsedValue;
169
169
  }
170
+
171
+ parseArrayNameValue(data) {
172
+ if (!Array.isArray(data)) return {};
173
+
174
+ return Object.fromEntries(
175
+ data.map(({ name, value }) => {
176
+ const parsedValue = this.convertValue(value);
177
+ return [name, parsedValue];
178
+ })
179
+ );
180
+ }
170
181
  }
171
182
  export default Functions
package/src/melcloud.js CHANGED
@@ -143,7 +143,7 @@ class MelCloud extends EventEmitter {
143
143
  data: payload
144
144
  });
145
145
  const account = accountData.data;
146
- const loginData = account.LoginData ?? [];
146
+ const loginData = account.LoginData ?? {};
147
147
  const contextKey = loginData.ContextKey;
148
148
 
149
149
  const safeConfig = {
@@ -76,8 +76,8 @@ class MelCloudAta extends EventEmitter {
76
76
  deviceData.Device.OperationMode = AirConditioner.OperationModeMapStringToEnum[deviceData.Device.OperationMode] ?? deviceData.Device.OperationMode;
77
77
  deviceData.Device.ActualFanSpeed = AirConditioner.FanSpeedMapStringToEnum[deviceData.Device.ActualFanSpeed] ?? deviceData.Device.ActualFanSpeed;
78
78
  deviceData.Device.SetFanSpeed = AirConditioner.FanSpeedMapStringToEnum[deviceData.Device.SetFanSpeed] ?? deviceData.Device.SetFanSpeed;
79
- deviceData.Device.VaneVerticalDirection = AirConditioner.VaneVerticalDirectionMapStringToEnum[deviceData.Device.VaneVerticalDirection] ?? deviceData.Device.VaneVerticalDirection;
80
79
  deviceData.Device.VaneHorizontalDirection = AirConditioner.VaneHorizontalDirectionMapStringToEnum[deviceData.Device.VaneHorizontalDirection] ?? deviceData.Device.VaneHorizontalDirection
80
+ deviceData.Device.VaneVerticalDirection = AirConditioner.VaneVerticalDirectionMapStringToEnum[deviceData.Device.VaneVerticalDirection] ?? deviceData.Device.VaneVerticalDirection;
81
81
 
82
82
  //read default temps
83
83
  const temps = await this.functions.readData(this.defaultTempsFile, true);
@@ -151,6 +151,7 @@ class MelCloudAta extends EventEmitter {
151
151
 
152
152
  this.headers = devicesData.Headers;
153
153
  const deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
154
+ if (!deviceData) return;
154
155
  deviceData.Scenes = devicesData.Scenes ?? [];
155
156
 
156
157
  //web cocket connection
@@ -188,7 +189,6 @@ class MelCloudAta extends EventEmitter {
188
189
  .on('message', async (message) => {
189
190
  const parsedMessage = JSON.parse(message);
190
191
  const stringifyMessage = JSON.stringify(parsedMessage, null, 2);
191
- if (this.logDebug) this.emit('debug', `Incoming message: ${stringifyMessage}`);
192
192
  if (parsedMessage.message === 'Forbidden') return;
193
193
 
194
194
  const messageData = parsedMessage?.[0]?.Data;
@@ -198,16 +198,32 @@ class MelCloudAta extends EventEmitter {
198
198
  const unitId = messageData?.id;
199
199
  switch (unitId) {
200
200
  case this.deviceId:
201
+ if (!this.logDebug) this.emit('debug', `Incoming message: ${stringifyMessage}`);
201
202
  const messageType = parsedMessage[0].messageType;
203
+ const settings = this.functions.parseArrayNameValue(messageData.settings);
202
204
  switch (messageType) {
203
205
  case 'unitStateChanged':
204
- const settings = Object.fromEntries(
205
- messageData.settings.map(({ name, value }) => {
206
- let parsedValue = this.functions.convertValue(value);
207
- return [name, parsedValue];
208
- })
209
- );
210
- Object.assign(deviceData.Device, settings);
206
+
207
+ //update values
208
+ for (const [key, value] of Object.entries(settings)) {
209
+ if (!this.functions.isValidValue(value)) continue;
210
+
211
+ if (key === 'HolidayMode') {
212
+ deviceData.HolidayMode.Enabled = value;
213
+ continue;
214
+ }
215
+
216
+ //skip HolidayMode, update generic device fields
217
+ if (key in deviceData.Device) {
218
+ deviceData.Device[key] = value;
219
+ }
220
+ }
221
+ updateState = true;
222
+ break;
223
+ case 'unitHolidayModeTriggered':
224
+ deviceData.Device.Power = settings.Power;
225
+ deviceData.HolidayMode.Enabled = settings.HolidayMode;
226
+ deviceData.HolidayMode.Active = messageData.active;
211
227
  updateState = true;
212
228
  break;
213
229
  case 'unitWifiSignalChanged':
@@ -215,12 +231,12 @@ class MelCloudAta extends EventEmitter {
215
231
  updateState = true;
216
232
  break;
217
233
  default:
218
- if (!this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${stringifyMessage}`);
234
+ if (this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${stringifyMessage}`);
219
235
  return;
220
236
  }
221
237
  break;
222
238
  default:
223
- if (!this.logDebug) this.emit('debug', `Incoming unknown unit id: ${stringifyMessage}`);
239
+ if (this.logDebug) this.emit('debug', `Incoming unknown unit id: ${stringifyMessage}`);
224
240
  return;
225
241
  }
226
242
 
@@ -329,6 +345,7 @@ class MelCloudAta extends EventEmitter {
329
345
  method = 'POST';
330
346
  path = ApiUrlsHome.PostHolidayMode;
331
347
  headers.Referer = ApiUrlsHome.Referers.PostHolidayMode.replace('deviceid', deviceData.DeviceID);
348
+ updateState = false;
332
349
  break;
333
350
  case 'schedule':
334
351
  payload = { enabled: deviceData.ScheduleEnabled };
@@ -368,14 +385,7 @@ class MelCloudAta extends EventEmitter {
368
385
  path = ApiUrlsHome.PutAta.replace('deviceid', deviceData.DeviceID);
369
386
  headers.Referer = ApiUrlsHome.Referers.PutDeviceSettings;
370
387
  updateState = false;
371
- this.socket.send(JSON.stringify([{
372
- messageType: 'setUnitSettings',
373
- Data: {
374
- id: deviceData.DeviceID,
375
- settings: payload
376
- }
377
- }]));
378
- return;
388
+ break;
379
389
  }
380
390
 
381
391
  //sens payload
@@ -145,6 +145,7 @@ class MelCloudAtw extends EventEmitter {
145
145
 
146
146
  this.headers = devicesData.Headers;
147
147
  const deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
148
+ if (!deviceData) return;
148
149
  deviceData.Scenes = devicesData.Scenes ?? [];
149
150
 
150
151
  //web cocket connection
@@ -60,6 +60,7 @@ class MelCloudErv extends EventEmitter {
60
60
 
61
61
  this.headers = devicesData.Headers;
62
62
  const deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
63
+ if (!deviceData) return;
63
64
  if (this.accountType === 'melcloudhome') {
64
65
  deviceData.Scenes = devicesData.Scenes ?? [];
65
66
 
@@ -142,7 +142,6 @@ class MelCloudHome extends EventEmitter {
142
142
  const createDevice = (device, type) => {
143
143
  // Settings już kapitalizowane w nazwach
144
144
  const settingsArray = device.Settings || [];
145
-
146
145
  const settingsObject = Object.fromEntries(
147
146
  settingsArray.map(({ name, value }) => {
148
147
  let parsedValue = this.functions.convertValue(value);