homebridge-melcloud-control 3.9.8 → 3.9.10-beta.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.
Files changed (2) hide show
  1. package/index.js +107 -104
  2. package/package.json +3 -3
package/index.js CHANGED
@@ -23,7 +23,7 @@ class MelCloudPlatform {
23
23
  //create directory if it doesn't exist
24
24
  mkdirSync(prefDir, { recursive: true });
25
25
  } catch (error) {
26
- log.error(`Prepare directory error: ${error}`);
26
+ log.error(`Prepare directory error: ${error.message ?? error}`);
27
27
  return;
28
28
  }
29
29
 
@@ -36,15 +36,9 @@ class MelCloudPlatform {
36
36
  const language = account.language;
37
37
 
38
38
  //check mandatory properties
39
- if (!accountName || !user || !passwd || !language) {
40
- log.warn(`Name: ${accountName ? 'OK' : accountName}, user: ${user ? 'OK' : user}, password: ${passwd ? 'OK' : passwd}, language: ${language ? 'OK' : language} in config missing.`);
41
- return;
42
- }
43
-
44
- //check duplicate account name
45
- if (accountsName.includes(accountName)) {
46
- log.warn(`Account name: ${accountName}, must be unique.`);
47
- return;
39
+ if (!accountName || accountsName.includes(accountName) || !user || !passwd || !language) {
40
+ log.warn(`Account name: ${accountName ? accountsName.includes(accountName) ? 'Duplicated' : 'OK' : accountName}, user: ${user ? 'OK' : user}, password: ${passwd ? 'OK' : passwd}, language: ${language ? 'OK' : language} in config missing.`);
41
+ continue;
48
42
  }
49
43
  accountsName.push(accountName);
50
44
 
@@ -66,7 +60,7 @@ class MelCloudPlatform {
66
60
  if (logLevel.debug) log.info(`${accountName}, debug: Did finish launching.`);
67
61
 
68
62
  //remove sensitive data
69
- const debugData = {
63
+ const safeConfig = {
70
64
  ...account,
71
65
  passwd: 'removed',
72
66
  mqtt: {
@@ -74,7 +68,7 @@ class MelCloudPlatform {
74
68
  passwd: 'removed'
75
69
  }
76
70
  };
77
- if (logLevel.debug) log.info(`${accountName}, Config: ${JSON.stringify(debugData, null, 2)}`);
71
+ if (logLevel.debug) log.info(`${accountName}, Config: ${JSON.stringify(safeConfig, null, 2)}`);
78
72
 
79
73
  //define directory and file paths
80
74
  const accountFile = `${prefDir}/${accountName}_Account`;
@@ -82,94 +76,106 @@ class MelCloudPlatform {
82
76
  const devicesFile = `${prefDir}/${accountName}_Devices`;
83
77
 
84
78
  //set account refresh interval
85
- const refreshInterval = account.refreshInterval * 1000 || 120000;
79
+ const refreshInterval = (account.refreshInterval ?? 120) * 1000
86
80
 
87
81
  try {
88
- //melcloud account
89
- const melCloud = new MelCloud(user, passwd, language, accountFile, buildingsFile, devicesFile, enableDebugMode, false)
90
- .on('success', (msg) => logLevel.success && log.success(`${accountName}, ${msg}`))
91
- .on('info', (msg) => logLevel.info && log.info(`${accountName}, ${msg}`))
92
- .on('debug', (msg) => logLevel.debug && log.info(`${accountName}, debug: ${msg}`))
93
- .on('warn', (msg) => logLevel.warn && log.warn(`${accountName}, ${msg}`))
94
- .on('error', (msg) => logLevel.error && log.error(`${accountName}, ${msg}`));
95
-
96
-
97
- //connect
98
- const response = await melCloud.connect();
99
- const accountInfo = response.accountInfo ?? false;
100
- const contextKey = response.contextKey ?? false;
101
- const useFahrenheit = response.useFahrenheit ?? false;
102
-
103
- if (contextKey === false) {
104
- return;
105
- }
82
+ //create impulse generator
83
+ const impulseGenerator = new ImpulseGenerator()
84
+ .on('start', async () => {
85
+ try {
86
+ //melcloud account
87
+ const melCloud = new MelCloud(user, passwd, language, accountFile, buildingsFile, devicesFile, enableDebugMode, false)
88
+ .on('success', (msg) => logLevel.success && log.success(`${accountName}, ${msg}`))
89
+ .on('info', (msg) => logLevel.info && log.info(`${accountName}, ${msg}`))
90
+ .on('debug', (msg) => logLevel.debug && log.info(`${accountName}, debug: ${msg}`))
91
+ .on('warn', (msg) => logLevel.warn && log.warn(`${accountName}, ${msg}`))
92
+ .on('error', (msg) => logLevel.error && log.error(`${accountName}, ${msg}`));
93
+
94
+
95
+ //connect
96
+ let response;
97
+ try {
98
+ response = await melCloud.connect();
99
+ } catch (error) {
100
+ if (logLevel.error) log.error(`${accountName}, Connect error: ${error.message ?? error}`);
101
+ return;
102
+ }
106
103
 
107
- //check devices list
108
- const devicesInMelcloud = await melCloud.checkDevicesList(contextKey);
109
- if (devicesInMelcloud === false) {
110
- return;
111
- }
104
+ const accountInfo = response.accountInfo ?? false;
105
+ const contextKey = response.contextKey ?? false;
106
+ const useFahrenheit = response.useFahrenheit ?? false;
112
107
 
113
- //start account impulse generator
114
- await melCloud.impulseGenerator.start([{ name: 'checkDevicesList', sampling: refreshInterval }]);
115
-
116
- //configured devices
117
- const ataDevices = account.ataDevices ?? [];
118
- const atwDevices = account.atwDevices ?? [];
119
- const ervDevices = account.ervDevices ?? [];
120
- const devices = [...ataDevices, ...atwDevices, ...ervDevices];
121
- if (logLevel.debug) log.info(`Found configured devices ATA: ${ataDevices.length}, ATW: ${atwDevices.length}, ERV: ${ervDevices.length}.`);
122
- for (const device of devices) {
123
- //chack device from config exist on melcloud
124
- const deviceId = device.id;
125
- const displayMode = device.displayMode > 0;
126
- const deviceExistInMelCloud = devicesInMelcloud.some(dev => dev.DeviceID === deviceId);
127
- if (!deviceExistInMelCloud || !displayMode) {
128
- continue;
129
- }
130
-
131
- const deviceName = device.name;
132
- const deviceType = device.type;
133
- const deviceTypeText = device.typeString;
134
- const deviceRefreshInterval = device.refreshInterval * 1000 || 5000;
135
- try {
136
- let configuredDevice;
137
- switch (deviceType) {
138
- case 0: //ATA
139
- configuredDevice = new DeviceAta(api, account, device, contextKey, accountName, deviceId, deviceName, deviceTypeText, devicesFile, deviceRefreshInterval, useFahrenheit, restFul, mqtt);
140
- break;
141
- case 1: //ATW
142
- configuredDevice = new DeviceAtw(api, account, device, contextKey, accountName, deviceId, deviceName, deviceTypeText, devicesFile, deviceRefreshInterval, useFahrenheit, restFul, mqtt);
143
- break;
144
- case 2:
145
- break;
146
- case 3: //ERV
147
- configuredDevice = new DeviceErv(api, account, device, contextKey, accountName, deviceId, deviceName, deviceTypeText, devicesFile, deviceRefreshInterval, useFahrenheit, restFul, mqtt);
148
- break;
149
- default:
150
- if (logLevel.warn) log.warn(`${accountName}, ${deviceTypeText}, ${deviceName}, unknown device: ${deviceType}.`);
108
+ if (contextKey === false) {
151
109
  return;
152
- }
110
+ }
153
111
 
154
- configuredDevice.on('melCloud', async (key, value) => {
112
+ //check devices list
113
+ let devicesInMelcloud;
155
114
  try {
156
- accountInfo[key] = value;
157
- await melCloud.send(accountInfo);
115
+ devicesInMelcloud = await melCloud.checkDevicesList(contextKey);
158
116
  } catch (error) {
159
- if (logLevel.error) log.error(`${accountName}, ${deviceTypeText}, ${deviceName}, ${error}.`);
117
+ if (logLevel.error) log.error(`${accountName}, Check devices list error: ${error.message ?? error}`);
118
+ return;
160
119
  }
161
- })
162
- .on('devInfo', (info) => logLevel.devInfo && log.info(info))
163
- .on('success', (msg) => logLevel.success && log.success(`${accountName}, ${deviceTypeText}, ${deviceName}, ${msg}`))
164
- .on('info', (msg) => logLevel.info && log.info(`${accountName}, ${deviceTypeText}, ${deviceName}, ${msg}`))
165
- .on('debug', (msg) => logLevel.debug && log.info(`${accountName}, ${deviceTypeText}, ${deviceName}, debug: ${msg}`))
166
- .on('warn', (msg) => logLevel.warn && log.warn(`${accountName}, ${deviceTypeText}, ${deviceName}, ${msg}`))
167
- .on('error', (msg) => logLevel.error && log.error(`${accountName}, ${deviceTypeText}, ${deviceName}, ${msg}`));
168
-
169
- //create impulse generator
170
- const impulseGenerator = new ImpulseGenerator();
171
- impulseGenerator.on('start', async () => {
172
- try {
120
+ if (!devicesInMelcloud || !Array.isArray(devicesInMelcloud)) return;
121
+
122
+ //start account impulse generator
123
+ await melCloud.impulseGenerator.start([{ name: 'checkDevicesList', sampling: refreshInterval }]);
124
+
125
+ //configured devices
126
+ const ataDevices = account.ataDevices ?? [];
127
+ const atwDevices = account.atwDevices ?? [];
128
+ const ervDevices = account.ervDevices ?? [];
129
+ const devices = [...ataDevices, ...atwDevices, ...ervDevices];
130
+ if (logLevel.debug) log.info(`Found configured devices ATA: ${ataDevices.length}, ATW: ${atwDevices.length}, ERV: ${ervDevices.length}.`);
131
+
132
+ for (const device of devices) {
133
+ //chack device from config exist on melcloud
134
+ const deviceId = device.id;
135
+ const displayMode = device.displayMode > 0;
136
+ const deviceExistInMelCloud = devicesInMelcloud.some(dev => dev.DeviceID === deviceId);
137
+ if (!deviceExistInMelCloud || !displayMode) {
138
+ continue;
139
+ }
140
+
141
+ const deviceName = device.name;
142
+ const deviceType = device.type;
143
+ const deviceTypeText = device.typeString;
144
+ const deviceRefreshInterval = (device.refreshInterval ?? 5) * 1000;
145
+
146
+ let configuredDevice;
147
+ switch (deviceType) {
148
+ case 0: //ATA
149
+ configuredDevice = new DeviceAta(api, account, device, contextKey, accountName, deviceId, deviceName, deviceTypeText, devicesFile, deviceRefreshInterval, useFahrenheit, restFul, mqtt);
150
+ break;
151
+ case 1: //ATW
152
+ configuredDevice = new DeviceAtw(api, account, device, contextKey, accountName, deviceId, deviceName, deviceTypeText, devicesFile, deviceRefreshInterval, useFahrenheit, restFul, mqtt);
153
+ break;
154
+ case 2:
155
+ break;
156
+ case 3: //ERV
157
+ configuredDevice = new DeviceErv(api, account, device, contextKey, accountName, deviceId, deviceName, deviceTypeText, devicesFile, deviceRefreshInterval, useFahrenheit, restFul, mqtt);
158
+ break;
159
+ default:
160
+ if (logLevel.warn) log.warn(`${accountName}, ${deviceTypeText}, ${deviceName}, unknown device: ${deviceType}.`);
161
+ return;
162
+ }
163
+
164
+ configuredDevice.on('melCloud', async (key, value) => {
165
+ try {
166
+ accountInfo[key] = value;
167
+ await melCloud.send(accountInfo);
168
+ } catch (error) {
169
+ if (logLevel.error) log.error(`${accountName}, ${deviceTypeText}, ${deviceName}, ${error}.`);
170
+ }
171
+ })
172
+ .on('devInfo', (info) => logLevel.devInfo && log.info(info))
173
+ .on('success', (msg) => logLevel.success && log.success(`${accountName}, ${deviceTypeText}, ${deviceName}, ${msg}`))
174
+ .on('info', (msg) => logLevel.info && log.info(`${accountName}, ${deviceTypeText}, ${deviceName}, ${msg}`))
175
+ .on('debug', (msg) => logLevel.debug && log.info(`${accountName}, ${deviceTypeText}, ${deviceName}, debug: ${msg}`))
176
+ .on('warn', (msg) => logLevel.warn && log.warn(`${accountName}, ${deviceTypeText}, ${deviceName}, ${msg}`))
177
+ .on('error', (msg) => logLevel.error && log.error(`${accountName}, ${deviceTypeText}, ${deviceName}, ${msg}`));
178
+
173
179
  const accessory = await configuredDevice.start();
174
180
  if (accessory) {
175
181
  api.publishExternalAccessories(PluginName, [accessory]);
@@ -178,21 +184,18 @@ class MelCloudPlatform {
178
184
  await impulseGenerator.stop();
179
185
  await configuredDevice.startImpulseGenerator();
180
186
  }
181
- } catch (error) {
182
- if (logLevel.error) log.error(`${accountName}, ${deviceTypeText}, ${deviceName}, ${error}, trying again.`);
183
187
  }
184
- }).on('state', (state) => {
185
- if (logLevel.debug) log.info(`${accountName}, ${deviceTypeText}, ${deviceName}, Start impulse generator ${state ? 'started' : 'stopped'}.`);
186
- });
187
-
188
- //start impulse generator
189
- await impulseGenerator.start([{ name: 'start', sampling: 45000 }]);
190
- } catch (error) {
191
- if (logLevel.error) log.error(`${accountName}, ${deviceTypeText}, ${deviceName}, did finish launching error: ${error}.`);
192
- }
193
- }
188
+ } catch (error) {
189
+ if (logLevel.error) log.error(`${accountName}, Start impulse generator error, ${error.message ?? error}, trying again.`);
190
+ }
191
+ }).on('state', (state) => {
192
+ if (logLevel.debug) log.info(`${accountName}, Start impulse generator ${state ? 'started' : 'stopped'}.`);
193
+ });
194
+
195
+ //start impulse generator
196
+ await impulseGenerator.start([{ name: 'start', sampling: 60000 }]);
194
197
  } catch (error) {
195
- if (logLevel.error) log.error(`${accountName}, did finish launching error: ${error}.`);
198
+ if (logLevel.error) log.error(`${accountName}, Did finish launching error: ${error.message ?? error}.`);
196
199
  }
197
200
  }
198
201
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "MELCloud Control",
3
3
  "name": "homebridge-melcloud-control",
4
- "version": "3.9.8",
4
+ "version": "3.9.10-beta.2",
5
5
  "description": "Homebridge plugin to control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.",
6
6
  "license": "MIT",
7
7
  "author": "grzegorz914",
@@ -31,13 +31,13 @@
31
31
  "LICENSE"
32
32
  ],
33
33
  "engines": {
34
- "homebridge": "^1.9.0 || ^2.0.0 || ^2.0.0-beta.29",
34
+ "homebridge": "^1.9.0 || ^2.0.0 || ^2.0.0-beta.30 || ^2.0.0-alpha.40",
35
35
  "node": "^20 || ^22 || ^24"
36
36
  },
37
37
  "dependencies": {
38
38
  "@homebridge/plugin-ui-utils": "^2.1.0",
39
39
  "async-mqtt": "^2.6.3",
40
- "axios": "^1.11.0",
40
+ "axios": "^1.12.2",
41
41
  "express": "^5.1.0"
42
42
  },
43
43
  "keywords": [