homebridge-midea-platform 1.2.6-beta.2 → 1.2.6-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.
Files changed (58) hide show
  1. package/.luarc.json +5 -0
  2. package/CHANGELOG.md +3 -0
  3. package/README.md +1 -1
  4. package/ac_00000Q11.lua +5148 -0
  5. package/biome.json +1 -1
  6. package/c3_HeatPump_152832116442666.lua +4681 -0
  7. package/cd_RSJ000CB.lua +4983 -0
  8. package/config.schema.json +66 -2
  9. package/dist/accessory/AccessoryFactory.d.ts +4 -3
  10. package/dist/accessory/AccessoryFactory.js +3 -0
  11. package/dist/accessory/AccessoryFactory.js.map +1 -1
  12. package/dist/accessory/AirConditionerAccessory.js +64 -63
  13. package/dist/accessory/AirConditionerAccessory.js.map +1 -1
  14. package/dist/accessory/BaseAccessory.d.ts +2 -0
  15. package/dist/accessory/BaseAccessory.js +14 -0
  16. package/dist/accessory/BaseAccessory.js.map +1 -1
  17. package/dist/accessory/DehumidifierAccessory.js +23 -18
  18. package/dist/accessory/DehumidifierAccessory.js.map +1 -1
  19. package/dist/accessory/ElectricWaterHeaterAccessory.js +9 -8
  20. package/dist/accessory/ElectricWaterHeaterAccessory.js.map +1 -1
  21. package/dist/accessory/GasWaterHeaterAccessory.js +20 -20
  22. package/dist/accessory/GasWaterHeaterAccessory.js.map +1 -1
  23. package/dist/accessory/HeatPumpWaterHeaterAccessory.d.ts +45 -0
  24. package/dist/accessory/HeatPumpWaterHeaterAccessory.js +167 -0
  25. package/dist/accessory/HeatPumpWaterHeaterAccessory.js.map +1 -0
  26. package/dist/core/MideaCloud.js +2 -2
  27. package/dist/core/MideaCloud.js.map +1 -1
  28. package/dist/core/MideaConstants.d.ts +1 -0
  29. package/dist/core/MideaConstants.js +2 -0
  30. package/dist/core/MideaConstants.js.map +1 -1
  31. package/dist/devices/DeviceFactory.d.ts +2 -1
  32. package/dist/devices/DeviceFactory.js +5 -2
  33. package/dist/devices/DeviceFactory.js.map +1 -1
  34. package/dist/devices/ac/MideaACMessage.js +1 -1
  35. package/dist/devices/ac/MideaACMessage.js.map +1 -1
  36. package/dist/devices/c3/MideaC3Device.d.ts +3 -2
  37. package/dist/devices/c3/MideaC3Device.js +20 -7
  38. package/dist/devices/c3/MideaC3Device.js.map +1 -1
  39. package/dist/devices/c3/MideaC3Message.d.ts +128 -12
  40. package/dist/devices/c3/MideaC3Message.js +283 -35
  41. package/dist/devices/c3/MideaC3Message.js.map +1 -1
  42. package/dist/devices/cd/MideaCDDevice.d.ts +42 -0
  43. package/dist/devices/cd/MideaCDDevice.js +105 -0
  44. package/dist/devices/cd/MideaCDDevice.js.map +1 -0
  45. package/dist/devices/cd/MideaCDMessage.d.ts +101 -0
  46. package/dist/devices/cd/MideaCDMessage.js +237 -0
  47. package/dist/devices/cd/MideaCDMessage.js.map +1 -0
  48. package/dist/devices/ce/MideaCEDevice.js +1 -1
  49. package/dist/platform.d.ts +3 -0
  50. package/dist/platform.js +0 -11
  51. package/dist/platform.js.map +1 -1
  52. package/dist/platformUtils.d.ts +11 -0
  53. package/dist/platformUtils.js +10 -0
  54. package/dist/platformUtils.js.map +1 -1
  55. package/docs/download_lua.md +3 -2
  56. package/homebridge-ui/public/index.html +57 -7
  57. package/homebridge-ui/server.js +94 -146
  58. package/package.json +1 -1
@@ -21,6 +21,7 @@ export type DeviceConfig = {
21
21
  AC_options: ACOptions;
22
22
  A1_options: A1Options;
23
23
  C3_options: C3Options;
24
+ CD_options: CDOptions;
24
25
  CE_options: CEOptions;
25
26
  DB_options: DBOptions;
26
27
  E1_options: E1Options;
@@ -93,6 +94,16 @@ type C3Options = {
93
94
  silentSwitch: boolean;
94
95
  tbhSwitch: boolean;
95
96
  };
97
+ type CDOptions = {
98
+ minTemp: number;
99
+ maxTemp: number;
100
+ tempStep: number;
101
+ energySaveModeSwitch: boolean;
102
+ standardModeSwitch: boolean;
103
+ eHeaterModeSwitch: boolean;
104
+ smartModeSwitch: boolean;
105
+ disinfectionSwitch: boolean;
106
+ };
96
107
  type CEOptions = {
97
108
  silentMode: boolean;
98
109
  autoSetModeSwitch: boolean;
@@ -83,6 +83,16 @@ export const defaultDeviceConfig = {
83
83
  silentSwitch: false,
84
84
  tbhSwitch: false,
85
85
  },
86
+ CD_options: {
87
+ minTemp: 38,
88
+ maxTemp: 70,
89
+ tempStep: 0.5,
90
+ energySaveModeSwitch: false,
91
+ standardModeSwitch: false,
92
+ eHeaterModeSwitch: false,
93
+ smartModeSwitch: false,
94
+ disinfectionSwitch: false,
95
+ },
86
96
  CE_options: {
87
97
  autoSetModeSwitch: false,
88
98
  minTemp: 16,
@@ -1 +1 @@
1
- {"version":3,"file":"platformUtils.js","sourceRoot":"","sources":["../src/platformUtils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"platformUtils.js","sourceRoot":"","sources":["../src/platformUtils.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,aAAa,GAAW;IACnC,eAAe,EAAE,EAAE;IACnB,iBAAiB,EAAE,EAAE;IACrB,OAAO,EAAE,KAAK;IACd,OAAO,EAAE,EAAE;CACZ,CAAC;AA4BF,MAAM,CAAN,IAAY,SAKX;AALD,WAAY,SAAS;IACnB,0BAAa,CAAA;IACb,kCAAqB,CAAA;IACrB,sCAAyB,CAAA;IACzB,0BAAa,CAAA;AACf,CAAC,EALW,SAAS,KAAT,SAAS,QAKpB;AAED,MAAM,CAAN,IAAY,UAGX;AAHD,WAAY,UAAU;IACpB,mCAAqB,CAAA;IACrB,uCAAyB,CAAA;AAC3B,CAAC,EAHW,UAAU,KAAV,UAAU,QAGrB;AAED,MAAM,CAAN,IAAY,eAIX;AAJD,WAAY,eAAe;IACzB,gCAAa,CAAA;IACb,8CAA2B,CAAA;IAC3B,oDAAiC,CAAA;AACnC,CAAC,EAJW,eAAe,KAAf,eAAe,QAI1B;AAsGD,MAAM,CAAC,MAAM,mBAAmB,GAAiB;IAC/C,EAAE,EAAE,CAAC;IACL,IAAI,EAAE,EAAE;IACR,gBAAgB,EAAE;QAChB,EAAE,EAAE,EAAE;QACN,KAAK,EAAE,EAAE;QACT,GAAG,EAAE,EAAE;QACP,OAAO,EAAE,KAAK;QACd,oBAAoB,EAAE,IAAI;QAC1B,sBAAsB,EAAE,IAAI;QAC5B,iBAAiB,EAAE,KAAK;KACzB;IACD,UAAU,EAAE;QACV,KAAK,EAAE;YACL,IAAI,EAAE,SAAS,CAAC,IAAI;YACpB,cAAc,EAAE,KAAK;YACrB,gBAAgB,EAAE,UAAU,CAAC,QAAQ;SACtC;QACD,cAAc,EAAE,IAAI;QACpB,WAAW,EAAE,KAAK;QAClB,aAAa,EAAE,KAAK;QACpB,SAAS,EAAE,KAAK;QAChB,SAAS,EAAE,KAAK;QAChB,aAAa,EAAE,KAAK;QACpB,eAAe,EAAE,KAAK;QACtB,gBAAgB,EAAE,KAAK;QACvB,aAAa,EAAE;YACb,IAAI,EAAE,IAAI;YACV,OAAO,EAAE,KAAK;SACf;QACD,kBAAkB,EAAE,KAAK;QACzB,eAAe,EAAE,KAAK;QACtB,SAAS,EAAE,KAAK;QAChB,YAAY,EAAE,KAAK;QACnB,OAAO,EAAE,EAAE;QACX,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,CAAC;QACX,UAAU,EAAE,KAAK;QACjB,iBAAiB,EAAE,KAAK;QACxB,YAAY,EAAE,KAAK;QACnB,eAAe,EAAE,KAAK;KACvB;IACD,UAAU,EAAE;QACV,iBAAiB,EAAE,KAAK;QACxB,YAAY,EAAE,KAAK;QACnB,cAAc,EAAE,KAAK;QACrB,UAAU,EAAE,KAAK;QACjB,eAAe,EAAE,eAAe,CAAC,IAAI;QACrC,WAAW,EAAE,EAAE;QACf,WAAW,EAAE,EAAE;QACf,YAAY,EAAE,CAAC;QACf,cAAc,EAAE,CAAC;KAClB;IACD,UAAU,EAAE;QACV,KAAK,EAAE,KAAK;QACZ,KAAK,EAAE,KAAK;QACZ,WAAW,EAAE,KAAK;QAClB,SAAS,EAAE,KAAK;QAChB,YAAY,EAAE,KAAK;QACnB,SAAS,EAAE,KAAK;KACjB;IACD,UAAU,EAAE;QACV,OAAO,EAAE,EAAE;QACX,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,GAAG;QACb,oBAAoB,EAAE,KAAK;QAC3B,kBAAkB,EAAE,KAAK;QACzB,iBAAiB,EAAE,KAAK;QACxB,eAAe,EAAE,KAAK;QACtB,kBAAkB,EAAE,KAAK;KAC1B;IACD,UAAU,EAAE;QACV,iBAAiB,EAAE,KAAK;QACxB,OAAO,EAAE,EAAE;QACX,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,CAAC;QACX,UAAU,EAAE,KAAK;KAClB;IACD,UAAU,EAAE,EAAE;IACd,UAAU,EAAE,EAAE;IACd,UAAU,EAAE;QACV,QAAQ,EAAE,MAAM;QAChB,OAAO,EAAE,EAAE;QACX,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,CAAC;QACX,qBAAqB,EAAE,KAAK;QAC5B,sBAAsB,EAAE,KAAK;KAC9B;IACD,UAAU,EAAE;QACV,eAAe,EAAE,KAAK;QACtB,OAAO,EAAE,EAAE;QACX,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,CAAC;QACX,kBAAkB,EAAE,KAAK;QACzB,gBAAgB,EAAE,KAAK;QACvB,mBAAmB,EAAE,KAAK;QAC1B,mBAAmB,EAAE,KAAK;QAC1B,iBAAiB,EAAE,KAAK;KACzB;IACD,UAAU,EAAE,EAAE;IACd,UAAU,EAAE,EAAE;CACf,CAAC"}
@@ -5,5 +5,6 @@ If you need support for a device, or a new feature for an existing one, please d
5
5
  2. Do the discovery process through the UI
6
6
  - Here you must your or the default NetHome Plus account (if you don't have your own account in these apps)
7
7
  3. After the discovery ends, there will be table of discovered devices
8
- 4. In the `Model` column, the model of your device will be a button, which you can click to download the lua script for the device.
9
- 5. After downloading the script, open an issue about the feature you need and attach the lua script to it (or open an issue and send me the script in email, it's `kovapatrik@gmail.com`)
8
+ 4. In the `Model` column, the model of your device will be a button, which you can click top initiate fetching the lua file which will be shown in a modal.
9
+ 5. Save the content of the file in a text file with a `.lua` extension. (there is a suggestion for the file name as well, but you can choose any name you like)
10
+ 6. Open an issue about the feature you need and attach the lua script to it (or open an issue and send me the script in email, it's `kovapatrik@gmail.com`)
@@ -199,6 +199,7 @@
199
199
  createForm(configSchema, configuration);
200
200
  homebridge.hideSpinner();
201
201
 
202
+ const main = document.getElementById('main');
202
203
  const loginSection = document.getElementById('login')
203
204
  const userPass = document.getElementById('userPass');
204
205
 
@@ -286,15 +287,64 @@
286
287
  download_btn.className = 'btn btn-outline-secondary btn-sm';
287
288
  download_btn.addEventListener('click', async () => {
288
289
  try {
290
+ homebridge.showSpinner();
289
291
  const file_data_str = await homebridge.request('/downloadLua', { deviceType: device.type, deviceSn: device.sn });
290
- const a = document.createElement('a');
291
- a.setAttribute('download', `${device.type.toString(16)}_${device.model}.lua`);
292
- const blob = new Blob([file_data_str], { type: 'text/plain' });
293
- const url = window.URL.createObjectURL(blob);
294
- a.href = url
295
- a.click();
296
- window.URL.revokeObjectURL(url);
292
+
293
+ const modal = document.createElement("div");
294
+ modal.className = 'modal fade';
295
+ modal.id = 'luaCodeModal';
296
+ modal.setAttribute('tabindex', '-1');
297
+ modal.setAttribute('aria-labelledby', 'luaCodeModalLabel');
298
+ modal.setAttribute('aria-hidden', 'true');
299
+
300
+ modal.innerHTML = `
301
+ <div class="modal-dialog modal-lg modal-dialog-scrollable">
302
+ <div class="modal-content">
303
+ <div class="modal-header">
304
+ <h5 class="modal-title" id="luaCodeModalLabel">Lua Code for ${device.model}</h5>
305
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
306
+ </div>
307
+ <div class="modal-body">
308
+ <div class="mb-3 btn-toolbar">
309
+ <div class="btn-group me-2">
310
+ <button id="selectAllLuaBtn" class="btn btn-secondary">Select All</button>
311
+ </div>
312
+ <small class="text-warning ms-2 align-self-center">Save this as ${device.type.toString(16)}_${device.model}.lua</small>
313
+ </div>
314
+ <pre id="luaCodePre"><code style="color: var(--bs-body-color);">${file_data_str}</code></pre>
315
+ </div>
316
+ <div class="modal-footer">
317
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
318
+ </div>
319
+ </div>
320
+ </div>
321
+ `;
322
+
323
+ main.appendChild(modal);
324
+
325
+ // Initialize the Bootstrap modal
326
+ const bootstrapModal = new bootstrap.Modal(modal);
327
+ bootstrapModal.show();
328
+
329
+ document.getElementById('selectAllLuaBtn').addEventListener('click', () => {
330
+ const codeElement = document.getElementById('luaCodePre');
331
+ const selection = window.getSelection();
332
+ const range = document.createRange();
333
+
334
+ range.selectNodeContents(codeElement);
335
+ selection.removeAllRanges();
336
+ selection.addRange(range);
337
+ });
338
+
339
+ // Clean up when modal is hidden
340
+ modal.addEventListener('hidden.bs.modal', () => {
341
+ main.removeChild(modal);
342
+ });
343
+
344
+ homebridge.hideSpinner();
345
+
297
346
  } catch (e) {
347
+ homebridge.hideSpinner();
298
348
  homebridge.toast.error(e.message);
299
349
  }
300
350
  });
@@ -7,36 +7,28 @@
7
7
  * Based on https://github.com/homebridge/plugin-ui-utils
8
8
  *
9
9
  */
10
- import {
11
- HomebridgePluginUiServer,
12
- RequestError,
13
- } from "@homebridge/plugin-ui-utils";
14
- import Discover from "../dist/core/MideaDiscover.js";
15
- import CloudFactory from "../dist/core/MideaCloud.js";
16
- import {
17
- DeviceTypeToName,
18
- TCPMessageType,
19
- ProtocolVersion,
20
- Endianness,
21
- } from "../dist/core/MideaConstants.js";
22
- import { LocalSecurity } from "../dist/core/MideaSecurity.js";
23
- import { PromiseSocket } from "../dist/core/MideaUtils.js";
24
- import { defaultConfig, defaultDeviceConfig } from "../dist/platformUtils.js";
25
- import { createRequire } from "node:module";
10
+ import { createRequire } from 'node:module';
11
+ import { HomebridgePluginUiServer, RequestError } from '@homebridge/plugin-ui-utils';
12
+ import CloudFactory from '../dist/core/MideaCloud.js';
13
+ import { DeviceTypeToName, Endianness, ProtocolVersion, TCPMessageType } from '../dist/core/MideaConstants.js';
14
+ import Discover from '../dist/core/MideaDiscover.js';
15
+ import { LocalSecurity } from '../dist/core/MideaSecurity.js';
16
+ import { PromiseSocket } from '../dist/core/MideaUtils.js';
17
+ import { defaultConfig, defaultDeviceConfig } from '../dist/platformUtils.js';
26
18
  const require = createRequire(import.meta.url);
27
19
 
28
- import _ from "lodash";
20
+ import _ from 'lodash';
29
21
 
30
22
  const DEFAULT_ACCOUNT = [
31
- BigInt(
32
- "41136566961777418441619689108052131385308997994436615360276316597550126349990",
33
- ),
34
- BigInt(
35
- "41136566961777418205521495345904086238221761646585049169700858993146668339659",
36
- ),
37
- BigInt(
38
- "41136566961777418441619689108052131385308997994436615362339979365072738212503",
39
- ),
23
+ BigInt('41136566961777418441619689108052131385308997994436615360276316597550126349990'),
24
+ BigInt('41136566961777418205521495345904086238221761646585049169700858993146668339659'),
25
+ BigInt('41136566961777418441619689108052131385308997994436615362339979365072738212503'),
26
+ ];
27
+
28
+ const DEFAULT_SMARTHOME_ACCOUNT = [
29
+ BigInt('4270685954756226103292057380984602745528999549492916172461797725852782444008'),
30
+ BigInt('4270685954756226103289246300068351442953216461967596801287597164299361014405'),
31
+ BigInt('4270685954756226103292057380984602757738380835485182656166614575373678037465'),
40
32
  ];
41
33
 
42
34
  /*********************************************************************
@@ -45,19 +37,19 @@ const DEFAULT_ACCOUNT = [
45
37
  */
46
38
  class Logger {
47
39
  _debug;
48
- _Reset = "\x1b[0m";
49
- _Bright = "\x1b[1m";
50
- _Dim = "\x1b[2m";
40
+ _Reset = '\x1b[0m';
41
+ _Bright = '\x1b[1m';
42
+ _Dim = '\x1b[2m';
51
43
 
52
- _FgBlack = "\x1b[30m";
53
- _FgRed = "\x1b[31m";
54
- _FgGreen = "\x1b[32m";
55
- _FgYellow = "\x1b[33m";
56
- _FgBlue = "\x1b[34m";
57
- _FgMagenta = "\x1b[35m";
58
- _FgCyan = "\x1b[36m";
59
- _FgWhite = "\x1b[37m";
60
- _FgGray = "\x1b[90m";
44
+ _FgBlack = '\x1b[30m';
45
+ _FgRed = '\x1b[31m';
46
+ _FgGreen = '\x1b[32m';
47
+ _FgYellow = '\x1b[33m';
48
+ _FgBlue = '\x1b[34m';
49
+ _FgMagenta = '\x1b[35m';
50
+ _FgCyan = '\x1b[36m';
51
+ _FgWhite = '\x1b[37m';
52
+ _FgGray = '\x1b[90m';
61
53
 
62
54
  constructor(uiDebug = false) {
63
55
  this._debug = uiDebug;
@@ -87,6 +79,7 @@ class Logger {
87
79
  */
88
80
  class UiServer extends HomebridgePluginUiServer {
89
81
  cloud;
82
+ smartHomeCloud;
90
83
  promiseSocket;
91
84
  security;
92
85
  logger;
@@ -95,113 +88,79 @@ class UiServer extends HomebridgePluginUiServer {
95
88
  constructor() {
96
89
  super();
97
90
  // Obtain the plugin configuration from homebridge config JSON file.
98
- const config = require(this.homebridgeConfigPath).platforms.find(
99
- (obj) => obj.platform === "midea-platform",
100
- );
91
+ const config = require(this.homebridgeConfigPath).platforms.find((obj) => obj.platform === 'midea-platform');
101
92
  this.logger = new Logger(config?.uiDebug ?? false);
102
- this.logger.info("Custom UI created.");
93
+ this.logger.info('Custom UI created.');
103
94
  this.logger.debug(`ENV:\n${JSON.stringify(process.env, null, 2)}`);
104
95
  this.security = new LocalSecurity();
105
- this.promiseSocket = new PromiseSocket(
106
- this.logger,
107
- config?.uiDebug ?? false,
108
- );
96
+ this.promiseSocket = new PromiseSocket(this.logger, config?.uiDebug ?? false);
109
97
 
110
- this.onRequest(
111
- "/login",
112
- async ({ username, password, useDefaultProfile }) => {
113
- try {
114
- if (useDefaultProfile) {
115
- this.logger.debug("Using default profile.");
116
- username = Buffer.from(
117
- (DEFAULT_ACCOUNT[0] ^ DEFAULT_ACCOUNT[1]).toString(16),
118
- "hex",
119
- ).toString("ascii");
120
- password = Buffer.from(
121
- (DEFAULT_ACCOUNT[0] ^ DEFAULT_ACCOUNT[2]).toString(16),
122
- "hex",
123
- ).toString("ascii");
124
- }
125
- this.cloud = CloudFactory.createCloud(
126
- username,
127
- password,
128
- "NetHome Plus",
129
- );
130
- if (username && password) {
131
- await this.cloud.login();
132
- }
133
- } catch (e) {
134
- const msg = e instanceof Error ? e.stack : e;
135
- this.logger.warn(`Login failed:\n${msg}`);
136
- throw new RequestError(
137
- "Login failed! Check the logs for more information.",
138
- );
98
+ this.onRequest('/login', async ({ username, password, useDefaultProfile }) => {
99
+ try {
100
+ if (useDefaultProfile) {
101
+ this.logger.debug('Using default profile.');
102
+ username = Buffer.from((DEFAULT_ACCOUNT[0] ^ DEFAULT_ACCOUNT[1]).toString(16), 'hex').toString('ascii');
103
+ password = Buffer.from((DEFAULT_ACCOUNT[0] ^ DEFAULT_ACCOUNT[2]).toString(16), 'hex').toString('ascii');
104
+ }
105
+ this.cloud = CloudFactory.createCloud(username, password, 'NetHome Plus');
106
+ if (username && password) {
107
+ await this.cloud.login();
139
108
  }
140
- },
141
- );
109
+ } catch (e) {
110
+ const msg = e instanceof Error ? e.stack : e;
111
+ this.logger.warn(`Login failed:\n${msg}`);
112
+ throw new RequestError('Login failed! Check the logs for more information.');
113
+ }
114
+ });
142
115
 
143
- this.onRequest("/mergeToDefault", async ({ config }) => {
116
+ this.onRequest('/mergeToDefault', async ({ config }) => {
144
117
  _.defaultsDeep(config, defaultConfig);
145
- config.devices.forEach((device) => {
118
+ for (const device of config.devices) {
146
119
  _.defaultsDeep(device, defaultDeviceConfig);
147
- });
120
+ }
148
121
  this.config = config;
149
122
  this.logger.setDebugEnabled(config.uiDebug ? config.uiDebug : false);
150
123
  this.logger.debug(`Merged config:\n${JSON.stringify(config, null, 2)}`);
151
124
  return config;
152
125
  });
153
126
 
154
- this.onRequest("/getDefaults", async () => {
127
+ this.onRequest('/getDefaults', async () => {
155
128
  return {
156
129
  defaultConfig,
157
130
  defaultDeviceConfig,
158
131
  };
159
132
  });
160
133
 
161
- this.onRequest("/discover", async ({ ip }) => {
134
+ this.onRequest('/discover', async ({ ip }) => {
162
135
  try {
163
136
  const devices = await this.blockingDiscover(ip);
164
137
  for (const device of devices) {
165
138
  if (device.version === ProtocolVersion.V3 && this.cloud.loggedIn) {
166
139
  await this.getNewCredentials(device);
167
140
  } else {
168
- device.token = "";
169
- device.key = "";
141
+ device.token = '';
142
+ device.key = '';
170
143
  }
171
144
  }
172
145
  this.logger.debug(`All devices:\n${JSON.stringify(devices, null, 2)}`);
173
- return devices
174
- .filter((a) => Object.keys(a).length > 0)
175
- .sort((a, b) => a.ip.localeCompare(b.ip));
146
+ return devices.filter((a) => Object.keys(a).length > 0).sort((a, b) => a.ip.localeCompare(b.ip));
176
147
  } catch (e) {
177
148
  const msg = e instanceof Error ? e.stack : e;
178
149
  throw new RequestError(`Device discovery failed:\n${msg}`);
179
150
  }
180
151
  });
181
152
 
182
- this.onRequest("/downloadLua", async ({ deviceType, deviceSn }) => {
153
+ this.onRequest('/downloadLua', async ({ deviceType, deviceSn }) => {
183
154
  try {
184
- if (!this.cloud || !this.cloud.isProxied()) {
185
- this.pushEvent("showToast", {
186
- success: true,
187
- msg: "Currently used cloud provider doesn't support Lua downloading, using the default profile now...",
188
- });
189
- const username = Buffer.from(
190
- (DEFAULT_ACCOUNT[0] ^ DEFAULT_ACCOUNT[1]).toString(16),
191
- "hex",
192
- ).toString("ascii");
193
- const password = Buffer.from(
194
- (DEFAULT_ACCOUNT[0] ^ DEFAULT_ACCOUNT[2]).toString(16),
195
- "hex",
196
- ).toString("ascii");
197
- this.cloud = CloudFactory.createCloud(
198
- username,
199
- password,
200
- "NetHome Plus",
201
- );
202
- await this.cloud.login();
155
+ if (!this.smartHomeCloud) {
156
+ const username = Buffer.from((DEFAULT_SMARTHOME_ACCOUNT[0] ^ DEFAULT_SMARTHOME_ACCOUNT[1]).toString(16), 'hex').toString('ascii');
157
+ const password = Buffer.from((DEFAULT_SMARTHOME_ACCOUNT[0] ^ DEFAULT_SMARTHOME_ACCOUNT[2]).toString(16), 'hex').toString('ascii');
158
+ this.smartHomeCloud = CloudFactory.createCloud(username, password, 'Midea SmartHome (MSmartHome)');
203
159
  }
204
- const lua = await this.cloud.getProtocolLua(deviceType, deviceSn);
160
+ if (!this.smartHomeCloud.loggedIn) {
161
+ await this.smartHomeCloud.login();
162
+ }
163
+ const lua = await this.smartHomeCloud.getProtocolLua(deviceType, deviceSn);
205
164
  return lua;
206
165
  } catch (e) {
207
166
  const msg = e instanceof Error ? e.stack : e;
@@ -229,24 +188,20 @@ class UiServer extends HomebridgePluginUiServer {
229
188
  const endianess = i === 0 ? Endianness.Little : Endianness.Big;
230
189
  try {
231
190
  const [token, key] = await this.cloud.getTokenKey(device.id, endianess);
232
- device.token = token ? token.toString("hex") : undefined;
233
- device.key = key ? key.toString("hex") : undefined;
191
+ device.token = token ? token.toString('hex') : undefined;
192
+ device.key = key ? key.toString('hex') : undefined;
234
193
  await this.authenticate(device);
235
194
  connected = true;
236
195
  } catch (e) {
237
196
  //const msg = e instanceof Error ? e.stack : e;
238
- this.logger.debug(
239
- `[${device.name}] Getting token and key with ${endianess}-endian is not successful.\n${e}`,
240
- );
197
+ this.logger.debug(`[${device.name}] Getting token and key with ${endianess}-endian is not successful.\n${e}`);
241
198
  // if failed then reset token/key
242
199
  device.token = undefined;
243
200
  device.key = undefined;
244
201
  }
245
202
  i++;
246
203
  }
247
- this.logger.debug(
248
- `[${device.name}] Token: ${device.token}, Key: ${device.key}`,
249
- );
204
+ this.logger.debug(`[${device.name}] Token: ${device.token}, Key: ${device.key}`);
250
205
  return;
251
206
  }
252
207
 
@@ -262,10 +217,7 @@ class UiServer extends HomebridgePluginUiServer {
262
217
  // Wrap next block in try/finally so we can destroy the socket if error occurs
263
218
  // let thrown errors cascade up.
264
219
  try {
265
- const request = this.security.encode_8370(
266
- Buffer.from(device.token, "hex"),
267
- TCPMessageType.HANDSHAKE_REQUEST,
268
- );
220
+ const request = this.security.encode_8370(Buffer.from(device.token, 'hex'), TCPMessageType.HANDSHAKE_REQUEST);
269
221
  await this.promiseSocket.write(request);
270
222
  const response = await this.promiseSocket.read();
271
223
  if (response) {
@@ -275,16 +227,12 @@ class UiServer extends HomebridgePluginUiServer {
275
227
  response.length
276
228
  })\n${JSON.stringify(response)}`,
277
229
  );
278
- throw Error(
279
- `[${device.name}] Authenticate error when receiving data from ${device.ip}:${device.port}. (Data length mismatch)`,
280
- );
230
+ throw Error(`[${device.name}] Authenticate error when receiving data from ${device.ip}:${device.port}. (Data length mismatch)`);
281
231
  }
282
232
  const resp = response.subarray(8, 72);
283
- this.security.tcp_key_from_resp(resp, Buffer.from(device.key, "hex"));
233
+ this.security.tcp_key_from_resp(resp, Buffer.from(device.key, 'hex'));
284
234
  } else {
285
- throw Error(
286
- `[${device.name}] Authenticate error when receiving data from ${device.ip}:${device.port}.`,
287
- );
235
+ throw Error(`[${device.name}] Authenticate error when receiving data from ${device.ip}:${device.port}.`);
288
236
  }
289
237
  } finally {
290
238
  this.promiseSocket.destroy();
@@ -297,44 +245,44 @@ class UiServer extends HomebridgePluginUiServer {
297
245
  * for each as discovered.
298
246
  */
299
247
  async blockingDiscover(ipAddrs = undefined) {
300
- let devices = [];
301
- this.logger.debug(
302
- `[blockingDiscover] IP addresses: ${JSON.stringify(ipAddrs)}`,
303
- );
248
+ const devices = [];
249
+ this.logger.debug(`[blockingDiscover] IP addresses: ${JSON.stringify(ipAddrs)}`);
304
250
  const discover = new Discover(this.logger);
305
251
  return new Promise((resolve, reject) => {
306
- this.logger.info("Start device discovery...");
307
- this.pushEvent("showToast", {
252
+ this.logger.info('Start device discovery...');
253
+ this.pushEvent('showToast', {
308
254
  success: true,
309
- msg: "Start device discovery",
255
+ msg: 'Start device discovery',
310
256
  });
311
257
  // If IP addresses provided then probe them directly
312
- ipAddrs?.forEach((ip) => {
313
- discover.discoverDeviceByIP(ip);
314
- });
258
+ if (ipAddrs && ipAddrs.length > 0) {
259
+ for (const ip of ipAddrs) {
260
+ discover.discoverDeviceByIP(ip);
261
+ }
262
+ }
315
263
  // And then send broadcast to network(s)
316
264
  discover.startDiscover();
317
265
 
318
- discover.on("device", async (device) => {
319
- device.displayName = DeviceTypeToName[device.type] ?? "Unknown";
266
+ discover.on('device', async (device) => {
267
+ device.displayName = DeviceTypeToName[device.type] ?? 'Unknown';
320
268
  devices.push(device);
321
269
  // too verbose to post every device as found...
322
270
  // this.pushEvent('showToast', { success: true, msg: `Discovered ${device.name} at ${device.ip}`, device: device });
323
271
  });
324
272
 
325
- discover.on("retry", (nTry, nDevices) => {
326
- this.logger.info("Device discovery complete.");
327
- this.pushEvent("showToast", {
273
+ discover.on('retry', (nTry, nDevices) => {
274
+ this.logger.info('Device discovery complete.');
275
+ this.pushEvent('showToast', {
328
276
  success: true,
329
277
  msg: `Continuing to search for devices (${nDevices} found)`,
330
278
  });
331
279
  });
332
280
 
333
- discover.on("complete", () => {
334
- this.logger.info("Device discovery complete.");
335
- this.pushEvent("showToast", {
281
+ discover.on('complete', () => {
282
+ this.logger.info('Device discovery complete.');
283
+ this.pushEvent('showToast', {
336
284
  success: true,
337
- msg: "Discovery complete",
285
+ msg: 'Discovery complete',
338
286
  });
339
287
  resolve(devices);
340
288
  });
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "displayName": "Homebridge Midea Platform",
3
3
  "name": "homebridge-midea-platform",
4
4
  "type": "module",
5
- "version": "1.2.6-beta.2",
5
+ "version": "1.2.6-beta.21",
6
6
  "description": "Homebridge plugin for Midea devices",
7
7
  "license": "Apache-2.0",
8
8
  "repository": {