homebridge-midea-platform 1.2.0-beta.2 → 1.2.0-beta.4

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 (89) hide show
  1. package/.husky/pre-commit +0 -0
  2. package/AC_ori.lua +5140 -0
  3. package/config.schema.json +14 -2
  4. package/dist/accessory/AccessoryFactory.d.ts +13 -12
  5. package/dist/accessory/AccessoryFactory.d.ts.map +1 -1
  6. package/dist/accessory/AccessoryFactory.js +37 -31
  7. package/dist/accessory/AccessoryFactory.js.map +1 -1
  8. package/dist/accessory/AirConditionerAccessory.d.ts +98 -92
  9. package/dist/accessory/AirConditionerAccessory.d.ts.map +1 -1
  10. package/dist/accessory/AirConditionerAccessory.js +662 -607
  11. package/dist/accessory/AirConditionerAccessory.js.map +1 -1
  12. package/dist/accessory/BaseAccessory.d.ts +11 -11
  13. package/dist/accessory/BaseAccessory.js +21 -21
  14. package/dist/accessory/DehumidifierAccessory.d.ts +45 -45
  15. package/dist/accessory/DehumidifierAccessory.js +344 -344
  16. package/dist/accessory/DishwasherAccessory.d.ts +30 -30
  17. package/dist/accessory/DishwasherAccessory.js +63 -63
  18. package/dist/accessory/ElectricWaterHeaterAccessory.d.ts +44 -44
  19. package/dist/accessory/ElectricWaterHeaterAccessory.js +176 -176
  20. package/dist/accessory/FanAccessory.d.ts +39 -39
  21. package/dist/accessory/FanAccessory.js +123 -123
  22. package/dist/accessory/FrontLoadWasherAccessory.d.ts +30 -30
  23. package/dist/accessory/FrontLoadWasherAccessory.js +66 -66
  24. package/dist/accessory/GasWaterHeaterAccessory.d.ts +51 -51
  25. package/dist/accessory/GasWaterHeaterAccessory.js +216 -216
  26. package/dist/core/MideaCloud.d.ts +35 -35
  27. package/dist/core/MideaCloud.js +350 -350
  28. package/dist/core/MideaConstants.d.ts +50 -50
  29. package/dist/core/MideaConstants.js +58 -58
  30. package/dist/core/MideaDevice.d.ts +76 -76
  31. package/dist/core/MideaDevice.js +409 -409
  32. package/dist/core/MideaDiscover.d.ts +35 -35
  33. package/dist/core/MideaDiscover.js +212 -212
  34. package/dist/core/MideaMessage.d.ts +75 -75
  35. package/dist/core/MideaMessage.js +184 -184
  36. package/dist/core/MideaPacketBuilder.d.ts +10 -10
  37. package/dist/core/MideaPacketBuilder.js +60 -60
  38. package/dist/core/MideaSecurity.d.ts +63 -63
  39. package/dist/core/MideaSecurity.js +251 -251
  40. package/dist/core/MideaUtils.d.ts +32 -32
  41. package/dist/core/MideaUtils.js +181 -181
  42. package/dist/devices/DeviceFactory.d.ts +13 -13
  43. package/dist/devices/DeviceFactory.d.ts.map +1 -1
  44. package/dist/devices/DeviceFactory.js +37 -36
  45. package/dist/devices/DeviceFactory.js.map +1 -1
  46. package/dist/devices/a1/MideaA1Device.d.ts +76 -76
  47. package/dist/devices/a1/MideaA1Device.js +145 -145
  48. package/dist/devices/a1/MideaA1Message.d.ts +40 -40
  49. package/dist/devices/a1/MideaA1Message.js +198 -198
  50. package/dist/devices/ac/MideaACDevice.d.ts +106 -104
  51. package/dist/devices/ac/MideaACDevice.d.ts.map +1 -1
  52. package/dist/devices/ac/MideaACDevice.js +400 -384
  53. package/dist/devices/ac/MideaACDevice.js.map +1 -1
  54. package/dist/devices/ac/MideaACMessage.d.ts +95 -94
  55. package/dist/devices/ac/MideaACMessage.d.ts.map +1 -1
  56. package/dist/devices/ac/MideaACMessage.js +619 -611
  57. package/dist/devices/ac/MideaACMessage.js.map +1 -1
  58. package/dist/devices/db/MideaDBDevice.d.ts +29 -29
  59. package/dist/devices/db/MideaDBDevice.js +100 -100
  60. package/dist/devices/db/MideaDBMessage.d.ts +32 -32
  61. package/dist/devices/db/MideaDBMessage.js +101 -101
  62. package/dist/devices/e1/MideaE1Device.d.ts +56 -56
  63. package/dist/devices/e1/MideaE1Device.js +128 -128
  64. package/dist/devices/e1/MideaE1Message.d.ts +28 -28
  65. package/dist/devices/e1/MideaE1Message.js +107 -107
  66. package/dist/devices/e2/MideaE2Device.d.ts +44 -44
  67. package/dist/devices/e2/MideaE2Device.js +129 -129
  68. package/dist/devices/e2/MideaE2Message.d.ts +33 -33
  69. package/dist/devices/e2/MideaE2Message.js +132 -132
  70. package/dist/devices/e3/MideaE3Device.d.ts +43 -43
  71. package/dist/devices/e3/MideaE3Device.js +137 -137
  72. package/dist/devices/e3/MideaE3Message.d.ts +51 -51
  73. package/dist/devices/e3/MideaE3Message.js +136 -136
  74. package/dist/devices/fa/MideaFADevice.d.ts +36 -36
  75. package/dist/devices/fa/MideaFADevice.js +106 -106
  76. package/dist/devices/fa/MideaFAMessage.d.ts +38 -38
  77. package/dist/devices/fa/MideaFAMessage.js +98 -98
  78. package/dist/index.d.ts +6 -6
  79. package/dist/index.js +6 -6
  80. package/dist/platform.d.ts +60 -60
  81. package/dist/platform.js +212 -212
  82. package/dist/platformUtils.d.ts +108 -106
  83. package/dist/platformUtils.d.ts.map +1 -1
  84. package/dist/platformUtils.js +103 -101
  85. package/dist/platformUtils.js.map +1 -1
  86. package/dist/settings.d.ts +8 -8
  87. package/dist/settings.js +11 -11
  88. package/docs/ac.md +6 -0
  89. package/package.json +1 -1
@@ -1,36 +1,36 @@
1
- /// <reference types="node" />
2
- import { Logger } from 'homebridge';
3
- import EventEmitter from 'events';
4
- export default class Discover extends EventEmitter {
5
- private readonly logger;
6
- private socket;
7
- private readonly xml_parser;
8
- private security;
9
- private ips;
10
- constructor(logger: Logger);
11
- /*********************************************************************
12
- * discoverDeviceByIP
13
- * Sends discover message to a single IP address. Will resend the message
14
- * an additional "retries" times spaced by 3 seconds if the target IP
15
- * address has not responded (recorded in the above callback).
16
- */
17
- discoverDeviceByIP(ip: string, retries?: number, timeout?: number): void;
18
- /*********************************************************************
19
- * ifBroadcastAddrs
20
- * Broadcasts to 255.255.255.255 only gets sent out on the first network inteface.
21
- * This function finds all network interfaces and returns the broadcast address
22
- * for each in an array, e.g. ['192.168.1.255', '192.168.100.255']. If there are
23
- * multiple interfaces this will cause broadcast to be sent out on each interface
24
- * so all appliances are properly discovered.
25
- */
26
- private ifBroadcastAddrs;
27
- /*********************************************************************
28
- * startDiscover
29
- * Sends broadcast to network discover Midea devices. Will continue sending
30
- * up to an additional "retries" times each spaced by 3 seconds.
31
- */
32
- startDiscover(retries?: number, timeout?: number): void;
33
- private getDeviceVersion;
34
- private getDeviceInfo;
35
- }
1
+ /// <reference types="node" />
2
+ import { Logger } from 'homebridge';
3
+ import EventEmitter from 'events';
4
+ export default class Discover extends EventEmitter {
5
+ private readonly logger;
6
+ private socket;
7
+ private readonly xml_parser;
8
+ private security;
9
+ private ips;
10
+ constructor(logger: Logger);
11
+ /*********************************************************************
12
+ * discoverDeviceByIP
13
+ * Sends discover message to a single IP address. Will resend the message
14
+ * an additional "retries" times spaced by 3 seconds if the target IP
15
+ * address has not responded (recorded in the above callback).
16
+ */
17
+ discoverDeviceByIP(ip: string, retries?: number, timeout?: number): void;
18
+ /*********************************************************************
19
+ * ifBroadcastAddrs
20
+ * Broadcasts to 255.255.255.255 only gets sent out on the first network inteface.
21
+ * This function finds all network interfaces and returns the broadcast address
22
+ * for each in an array, e.g. ['192.168.1.255', '192.168.100.255']. If there are
23
+ * multiple interfaces this will cause broadcast to be sent out on each interface
24
+ * so all appliances are properly discovered.
25
+ */
26
+ private ifBroadcastAddrs;
27
+ /*********************************************************************
28
+ * startDiscover
29
+ * Sends broadcast to network discover Midea devices. Will continue sending
30
+ * up to an additional "retries" times each spaced by 3 seconds.
31
+ */
32
+ startDiscover(retries?: number, timeout?: number): void;
33
+ private getDeviceVersion;
34
+ private getDeviceInfo;
35
+ }
36
36
  //# sourceMappingURL=MideaDiscover.d.ts.map
@@ -1,213 +1,213 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- /***********************************************************************
7
- * Midea device discovery class where we broadcast to network to find
8
- * connected devices.
9
- *
10
- * Copyright (c) 2023 Kovalovszky Patrik, https://github.com/kovapatrik
11
- * Portions Copyright (c) 2023 David Kerr, https://github.com/dkerr64
12
- *
13
- * With thanks to https://github.com/georgezhao2010/midea_ac_lan
14
- *
15
- */
16
- const dgram_1 = __importDefault(require("dgram"));
17
- const MideaConstants_1 = require("./MideaConstants");
18
- const fast_xml_parser_1 = require("fast-xml-parser");
19
- const events_1 = __importDefault(require("events"));
20
- const MideaSecurity_1 = require("./MideaSecurity");
21
- // To access network interface detail...
22
- const os_1 = __importDefault(require("os"));
23
- class Discover extends events_1.default {
24
- constructor(logger) {
25
- super();
26
- this.logger = logger;
27
- this.ips = [];
28
- this.security = new MideaSecurity_1.LocalSecurity();
29
- this.xml_parser = new fast_xml_parser_1.XMLParser();
30
- this.socket = dgram_1.default.createSocket('udp4');
31
- this.socket.bind(0, undefined, () => {
32
- this.socket.setBroadcast(true);
33
- });
34
- this.socket.on('error', (err) => {
35
- this.logger.debug(`server error:\n${err.stack}`);
36
- });
37
- // Register callback function executed when message received on the socket as
38
- // result of sending broadcast messages out to network / IP address.
39
- this.socket.on('message', async (msg, rinfo) => {
40
- if (!this.ips.includes(rinfo.address)) {
41
- // Only add device if it has not already been added.
42
- this.ips.push(rinfo.address);
43
- const device_version = this.getDeviceVersion(msg);
44
- const device_info = await this.getDeviceInfo(rinfo.address, device_version, msg);
45
- this.logger.info(`Discovered device: ${JSON.stringify(device_info)}`);
46
- // Send signal to Homebridge platform with details on the discovered device
47
- this.emit('device', device_info);
48
- }
49
- });
50
- }
51
- /*********************************************************************
52
- * discoverDeviceByIP
53
- * Sends discover message to a single IP address. Will resend the message
54
- * an additional "retries" times spaced by 3 seconds if the target IP
55
- * address has not responded (recorded in the above callback).
56
- */
57
- discoverDeviceByIP(ip, retries = 3, timeout = 2000) {
58
- let tries = 0;
59
- function broadcast() {
60
- if (this.ips.includes(ip) || tries++ > retries) {
61
- return;
62
- }
63
- this.logger.debug(`Sending discovery message to ${ip}, try ${tries}...`);
64
- for (const port of [6445, 20086]) {
65
- this.socket.send(Buffer.from(MideaConstants_1.DISCOVERY_MESSAGE), port, ip, (err) => {
66
- if (err) {
67
- this.logger.error(`Error while sending message to ${ip}: ${err}`);
68
- }
69
- });
70
- }
71
- setTimeout(broadcast.bind(this), timeout);
72
- }
73
- broadcast.bind(this)();
74
- }
75
- /*********************************************************************
76
- * ifBroadcastAddrs
77
- * Broadcasts to 255.255.255.255 only gets sent out on the first network inteface.
78
- * This function finds all network interfaces and returns the broadcast address
79
- * for each in an array, e.g. ['192.168.1.255', '192.168.100.255']. If there are
80
- * multiple interfaces this will cause broadcast to be sent out on each interface
81
- * so all appliances are properly discovered.
82
- */
83
- ifBroadcastAddrs() {
84
- const list = [];
85
- try {
86
- const ifaces = os_1.default.networkInterfaces();
87
- for (const iface of Object.values(ifaces)) {
88
- if (iface) {
89
- for (const f of iface) {
90
- if (!f.internal && f.family === 'IPv4') {
91
- // With thanks to https://github.com/aal89/broadcast-address/blob/master/broadcast-address.js
92
- const addr_splitted = f.address.split('.');
93
- const netmask_splitted = f.netmask.split('.');
94
- // Bitwise OR over the splitted NAND netmask, then glue them back together with a dot character to form an ip
95
- // we have to do a NAND operation because of the 2-complements; getting rid of all the 'prepended' 1's with & 0xFF
96
- const broadcast = addr_splitted.map((e, i) => (~netmask_splitted[i] & 0xff) | Number.parseInt(e)).join('.');
97
- list.push(broadcast);
98
- }
99
- }
100
- }
101
- }
102
- }
103
- catch (e) {
104
- const msg = e instanceof Error ? e.stack : e;
105
- this.logger.error(`Fatal error during plugin initialization:\n${msg}`);
106
- }
107
- // this.logger.info(`Broadcast addresses: ${JSON.stringify(list)}`);
108
- return list;
109
- }
110
- /*********************************************************************
111
- * startDiscover
112
- * Sends broadcast to network discover Midea devices. Will continue sending
113
- * up to an additional "retries" times each spaced by 3 seconds.
114
- */
115
- startDiscover(retries = 3, timeout = 2000) {
116
- let tries = 0;
117
- // force timeout to be between 500ms and 5 seconds
118
- timeout = Math.max(500, Math.min(timeout, 5000));
119
- const broadcastAddrs = this.ifBroadcastAddrs();
120
- function broadcast() {
121
- if (tries++ > retries) {
122
- this.logger.debug(`Device discovery complete after ${retries + 1} network broadcasts.`);
123
- this.emit('complete');
124
- return;
125
- }
126
- else {
127
- this.emit('retry', tries, this.ips.length);
128
- }
129
- for (const ip of broadcastAddrs) {
130
- this.logger.debug(`Sending discovery message to ${ip}, try ${tries}...`);
131
- for (const port of [6445, 20086]) {
132
- this.socket.send(Buffer.from(MideaConstants_1.DISCOVERY_MESSAGE), port, ip, (err) => {
133
- if (err) {
134
- const msg = err instanceof Error ? err.stack : err;
135
- this.logger.error(`Error while sending message to ${ip}:${port}:\n${msg}`);
136
- }
137
- });
138
- }
139
- }
140
- setTimeout(broadcast.bind(this), timeout);
141
- }
142
- broadcast.bind(this)();
143
- }
144
- getDeviceVersion(data) {
145
- try {
146
- this.xml_parser.parse(data.toString(), true);
147
- return MideaConstants_1.ProtocolVersion.V1;
148
- }
149
- catch (_a) {
150
- const start_of_packet = data.subarray(0, 2);
151
- if (start_of_packet.compare(Buffer.from([0x5a, 0x5a])) === 0) {
152
- return MideaConstants_1.ProtocolVersion.V2;
153
- }
154
- else if (start_of_packet.compare(Buffer.from([0x83, 0x70])) === 0) {
155
- return MideaConstants_1.ProtocolVersion.V3;
156
- }
157
- }
158
- throw new Error('Unknown device version.');
159
- }
160
- async getDeviceInfo(ip, version, data) {
161
- if (version === MideaConstants_1.ProtocolVersion.V1) {
162
- // const root = this.xml_parser.parse(data.toString());
163
- // const device = root["body"]["device"]
164
- // if (device) {
165
- // const port = device["port"];
166
- // }
167
- // throw new Error("Could not find 'body/device' in XML.");
168
- throw new Error('Version 1 not implemented.');
169
- }
170
- else {
171
- let buffer = data;
172
- // Strip V3 header and hash
173
- if (version === MideaConstants_1.ProtocolVersion.V3) {
174
- buffer = buffer.subarray(8, -16);
175
- }
176
- const encrypted_data = buffer.subarray(40, -16);
177
- const device_id = buffer.readUIntLE(20, 6);
178
- let decrypted_buffer;
179
- try {
180
- decrypted_buffer = this.security.aes_decrypt(encrypted_data);
181
- }
182
- catch (err) {
183
- throw new Error(`Error while decrypting data: ${err}`);
184
- }
185
- // prettier-ignore
186
- // eslint-disable-next-line max-len
187
- const ip_address = `${decrypted_buffer.readUint8(3)}.${decrypted_buffer.readUint8(2)}.${decrypted_buffer.readUint8(1)}.${decrypted_buffer.readUint8(0)}`;
188
- const port = decrypted_buffer.readUIntLE(4, 2);
189
- if (ip_address !== ip) {
190
- this.logger.warn(`IP address mismatch: ${ip_address} != ${ip}`);
191
- }
192
- const model = decrypted_buffer.subarray(17, 25).toString();
193
- // Serial number
194
- const sn = decrypted_buffer.subarray(8, 40).toString();
195
- // Extract name/SSID
196
- const name_length = decrypted_buffer.readUIntLE(40, 1);
197
- const name = decrypted_buffer.subarray(41, 41 + name_length).toString();
198
- const device_type = Number(`0x${name.split('_')[1]}`);
199
- return {
200
- ip: ip,
201
- port: port,
202
- id: device_id,
203
- model: model,
204
- sn: sn,
205
- name: name,
206
- type: device_type,
207
- version: version,
208
- };
209
- }
210
- }
211
- }
212
- exports.default = Discover;
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ /***********************************************************************
7
+ * Midea device discovery class where we broadcast to network to find
8
+ * connected devices.
9
+ *
10
+ * Copyright (c) 2023 Kovalovszky Patrik, https://github.com/kovapatrik
11
+ * Portions Copyright (c) 2023 David Kerr, https://github.com/dkerr64
12
+ *
13
+ * With thanks to https://github.com/georgezhao2010/midea_ac_lan
14
+ *
15
+ */
16
+ const dgram_1 = __importDefault(require("dgram"));
17
+ const MideaConstants_1 = require("./MideaConstants");
18
+ const fast_xml_parser_1 = require("fast-xml-parser");
19
+ const events_1 = __importDefault(require("events"));
20
+ const MideaSecurity_1 = require("./MideaSecurity");
21
+ // To access network interface detail...
22
+ const os_1 = __importDefault(require("os"));
23
+ class Discover extends events_1.default {
24
+ constructor(logger) {
25
+ super();
26
+ this.logger = logger;
27
+ this.ips = [];
28
+ this.security = new MideaSecurity_1.LocalSecurity();
29
+ this.xml_parser = new fast_xml_parser_1.XMLParser();
30
+ this.socket = dgram_1.default.createSocket('udp4');
31
+ this.socket.bind(0, undefined, () => {
32
+ this.socket.setBroadcast(true);
33
+ });
34
+ this.socket.on('error', (err) => {
35
+ this.logger.debug(`server error:\n${err.stack}`);
36
+ });
37
+ // Register callback function executed when message received on the socket as
38
+ // result of sending broadcast messages out to network / IP address.
39
+ this.socket.on('message', async (msg, rinfo) => {
40
+ if (!this.ips.includes(rinfo.address)) {
41
+ // Only add device if it has not already been added.
42
+ this.ips.push(rinfo.address);
43
+ const device_version = this.getDeviceVersion(msg);
44
+ const device_info = await this.getDeviceInfo(rinfo.address, device_version, msg);
45
+ this.logger.info(`Discovered device: ${JSON.stringify(device_info)}`);
46
+ // Send signal to Homebridge platform with details on the discovered device
47
+ this.emit('device', device_info);
48
+ }
49
+ });
50
+ }
51
+ /*********************************************************************
52
+ * discoverDeviceByIP
53
+ * Sends discover message to a single IP address. Will resend the message
54
+ * an additional "retries" times spaced by 3 seconds if the target IP
55
+ * address has not responded (recorded in the above callback).
56
+ */
57
+ discoverDeviceByIP(ip, retries = 3, timeout = 2000) {
58
+ let tries = 0;
59
+ function broadcast() {
60
+ if (this.ips.includes(ip) || tries++ > retries) {
61
+ return;
62
+ }
63
+ this.logger.debug(`Sending discovery message to ${ip}, try ${tries}...`);
64
+ for (const port of [6445, 20086]) {
65
+ this.socket.send(Buffer.from(MideaConstants_1.DISCOVERY_MESSAGE), port, ip, (err) => {
66
+ if (err) {
67
+ this.logger.error(`Error while sending message to ${ip}: ${err}`);
68
+ }
69
+ });
70
+ }
71
+ setTimeout(broadcast.bind(this), timeout);
72
+ }
73
+ broadcast.bind(this)();
74
+ }
75
+ /*********************************************************************
76
+ * ifBroadcastAddrs
77
+ * Broadcasts to 255.255.255.255 only gets sent out on the first network inteface.
78
+ * This function finds all network interfaces and returns the broadcast address
79
+ * for each in an array, e.g. ['192.168.1.255', '192.168.100.255']. If there are
80
+ * multiple interfaces this will cause broadcast to be sent out on each interface
81
+ * so all appliances are properly discovered.
82
+ */
83
+ ifBroadcastAddrs() {
84
+ const list = [];
85
+ try {
86
+ const ifaces = os_1.default.networkInterfaces();
87
+ for (const iface of Object.values(ifaces)) {
88
+ if (iface) {
89
+ for (const f of iface) {
90
+ if (!f.internal && f.family === 'IPv4') {
91
+ // With thanks to https://github.com/aal89/broadcast-address/blob/master/broadcast-address.js
92
+ const addr_splitted = f.address.split('.');
93
+ const netmask_splitted = f.netmask.split('.');
94
+ // Bitwise OR over the splitted NAND netmask, then glue them back together with a dot character to form an ip
95
+ // we have to do a NAND operation because of the 2-complements; getting rid of all the 'prepended' 1's with & 0xFF
96
+ const broadcast = addr_splitted.map((e, i) => (~netmask_splitted[i] & 0xff) | Number.parseInt(e)).join('.');
97
+ list.push(broadcast);
98
+ }
99
+ }
100
+ }
101
+ }
102
+ }
103
+ catch (e) {
104
+ const msg = e instanceof Error ? e.stack : e;
105
+ this.logger.error(`Fatal error during plugin initialization:\n${msg}`);
106
+ }
107
+ // this.logger.info(`Broadcast addresses: ${JSON.stringify(list)}`);
108
+ return list;
109
+ }
110
+ /*********************************************************************
111
+ * startDiscover
112
+ * Sends broadcast to network discover Midea devices. Will continue sending
113
+ * up to an additional "retries" times each spaced by 3 seconds.
114
+ */
115
+ startDiscover(retries = 3, timeout = 2000) {
116
+ let tries = 0;
117
+ // force timeout to be between 500ms and 5 seconds
118
+ timeout = Math.max(500, Math.min(timeout, 5000));
119
+ const broadcastAddrs = this.ifBroadcastAddrs();
120
+ function broadcast() {
121
+ if (tries++ > retries) {
122
+ this.logger.debug(`Device discovery complete after ${retries + 1} network broadcasts.`);
123
+ this.emit('complete');
124
+ return;
125
+ }
126
+ else {
127
+ this.emit('retry', tries, this.ips.length);
128
+ }
129
+ for (const ip of broadcastAddrs) {
130
+ this.logger.debug(`Sending discovery message to ${ip}, try ${tries}...`);
131
+ for (const port of [6445, 20086]) {
132
+ this.socket.send(Buffer.from(MideaConstants_1.DISCOVERY_MESSAGE), port, ip, (err) => {
133
+ if (err) {
134
+ const msg = err instanceof Error ? err.stack : err;
135
+ this.logger.error(`Error while sending message to ${ip}:${port}:\n${msg}`);
136
+ }
137
+ });
138
+ }
139
+ }
140
+ setTimeout(broadcast.bind(this), timeout);
141
+ }
142
+ broadcast.bind(this)();
143
+ }
144
+ getDeviceVersion(data) {
145
+ try {
146
+ this.xml_parser.parse(data.toString(), true);
147
+ return MideaConstants_1.ProtocolVersion.V1;
148
+ }
149
+ catch (_a) {
150
+ const start_of_packet = data.subarray(0, 2);
151
+ if (start_of_packet.compare(Buffer.from([0x5a, 0x5a])) === 0) {
152
+ return MideaConstants_1.ProtocolVersion.V2;
153
+ }
154
+ else if (start_of_packet.compare(Buffer.from([0x83, 0x70])) === 0) {
155
+ return MideaConstants_1.ProtocolVersion.V3;
156
+ }
157
+ }
158
+ throw new Error('Unknown device version.');
159
+ }
160
+ async getDeviceInfo(ip, version, data) {
161
+ if (version === MideaConstants_1.ProtocolVersion.V1) {
162
+ // const root = this.xml_parser.parse(data.toString());
163
+ // const device = root["body"]["device"]
164
+ // if (device) {
165
+ // const port = device["port"];
166
+ // }
167
+ // throw new Error("Could not find 'body/device' in XML.");
168
+ throw new Error('Version 1 not implemented.');
169
+ }
170
+ else {
171
+ let buffer = data;
172
+ // Strip V3 header and hash
173
+ if (version === MideaConstants_1.ProtocolVersion.V3) {
174
+ buffer = buffer.subarray(8, -16);
175
+ }
176
+ const encrypted_data = buffer.subarray(40, -16);
177
+ const device_id = buffer.readUIntLE(20, 6);
178
+ let decrypted_buffer;
179
+ try {
180
+ decrypted_buffer = this.security.aes_decrypt(encrypted_data);
181
+ }
182
+ catch (err) {
183
+ throw new Error(`Error while decrypting data: ${err}`);
184
+ }
185
+ // prettier-ignore
186
+ // eslint-disable-next-line max-len
187
+ const ip_address = `${decrypted_buffer.readUint8(3)}.${decrypted_buffer.readUint8(2)}.${decrypted_buffer.readUint8(1)}.${decrypted_buffer.readUint8(0)}`;
188
+ const port = decrypted_buffer.readUIntLE(4, 2);
189
+ if (ip_address !== ip) {
190
+ this.logger.warn(`IP address mismatch: ${ip_address} != ${ip}`);
191
+ }
192
+ const model = decrypted_buffer.subarray(17, 25).toString();
193
+ // Serial number
194
+ const sn = decrypted_buffer.subarray(8, 40).toString();
195
+ // Extract name/SSID
196
+ const name_length = decrypted_buffer.readUIntLE(40, 1);
197
+ const name = decrypted_buffer.subarray(41, 41 + name_length).toString();
198
+ const device_type = Number(`0x${name.split('_')[1]}`);
199
+ return {
200
+ ip: ip,
201
+ port: port,
202
+ id: device_id,
203
+ model: model,
204
+ sn: sn,
205
+ name: name,
206
+ type: device_type,
207
+ version: version,
208
+ };
209
+ }
210
+ }
211
+ }
212
+ exports.default = Discover;
213
213
  //# sourceMappingURL=MideaDiscover.js.map
@@ -1,76 +1,76 @@
1
- /// <reference types="node" />
2
- import { DeviceType } from './MideaConstants';
3
- export declare enum MessageType {
4
- UNKNOWN = 0,
5
- SET = 2,
6
- QUERY = 3,
7
- NOTIFY1 = 4,
8
- NOTIFY2 = 5,
9
- EXCEPTION = 6,
10
- QUERY_SN = 7,
11
- EXCEPTION2 = 10,
12
- QUERY_SUBTYPE = 160
13
- }
14
- declare abstract class MessageBase {
15
- protected readonly HEADER_LENGTH = 10;
16
- protected abstract device_type: DeviceType;
17
- protected abstract message_type: MessageType;
18
- protected abstract body_type: number | null;
19
- protected abstract device_protocol_version: number;
20
- protected abstract body: Buffer;
21
- checksum(data: Buffer): number;
22
- }
23
- export declare abstract class MessageRequest extends MessageBase {
24
- device_type: DeviceType;
25
- message_type: MessageType;
26
- body_type: number | null;
27
- device_protocol_version: number;
28
- protected abstract _body: Buffer;
29
- constructor(device_type: DeviceType, message_type: MessageType, body_type: number | null, device_protocol_version: number);
30
- get body(): Buffer;
31
- get header(): Buffer;
32
- serialize(): Buffer;
33
- }
34
- export declare class MessageQuerySubtype extends MessageRequest {
35
- protected _body: Buffer;
36
- constructor(device_type: DeviceType);
37
- }
38
- export declare class MessageQuestCustom extends MessageRequest {
39
- protected _body: Buffer;
40
- protected cmd_body: Buffer;
41
- constructor(device_type: DeviceType, message_type: MessageType, cmd_body: Buffer);
42
- get body(): Buffer;
43
- }
44
- export declare class MessageBody {
45
- readonly data: Buffer;
46
- constructor(data: Buffer);
47
- get body_type(): number;
48
- static read_byte(data: Buffer, offset: number, default_value: number): number;
49
- }
50
- export declare class NewProtocolMessageBody extends MessageBody {
51
- protected packet_length: number;
52
- constructor(body: Buffer, body_type: number);
53
- static packet(param: number, value: Buffer, packet_length?: number): Buffer;
54
- parse(): {
55
- [key: string]: any;
56
- };
57
- }
58
- export declare class MessageResponse extends MessageBase {
59
- protected header: Buffer;
60
- protected device_type: DeviceType;
61
- protected message_type: MessageType;
62
- protected body_type: number;
63
- device_protocol_version: number;
64
- protected _body: MessageBody;
65
- constructor(message: Buffer | null | undefined);
66
- get body(): Buffer;
67
- set_body(body: MessageBody): void;
68
- get_body_type(): string;
69
- get_body_attribute(name: string): any;
70
- }
71
- export declare class MessageSubtypeResponse extends MessageResponse {
72
- sub_type: number;
73
- constructor(message: Buffer | null | undefined);
74
- }
75
- export {};
1
+ /// <reference types="node" />
2
+ import { DeviceType } from './MideaConstants';
3
+ export declare enum MessageType {
4
+ UNKNOWN = 0,
5
+ SET = 2,
6
+ QUERY = 3,
7
+ NOTIFY1 = 4,
8
+ NOTIFY2 = 5,
9
+ EXCEPTION = 6,
10
+ QUERY_SN = 7,
11
+ EXCEPTION2 = 10,
12
+ QUERY_SUBTYPE = 160
13
+ }
14
+ declare abstract class MessageBase {
15
+ protected readonly HEADER_LENGTH = 10;
16
+ protected abstract device_type: DeviceType;
17
+ protected abstract message_type: MessageType;
18
+ protected abstract body_type: number | null;
19
+ protected abstract device_protocol_version: number;
20
+ protected abstract body: Buffer;
21
+ checksum(data: Buffer): number;
22
+ }
23
+ export declare abstract class MessageRequest extends MessageBase {
24
+ device_type: DeviceType;
25
+ message_type: MessageType;
26
+ body_type: number | null;
27
+ device_protocol_version: number;
28
+ protected abstract _body: Buffer;
29
+ constructor(device_type: DeviceType, message_type: MessageType, body_type: number | null, device_protocol_version: number);
30
+ get body(): Buffer;
31
+ get header(): Buffer;
32
+ serialize(): Buffer;
33
+ }
34
+ export declare class MessageQuerySubtype extends MessageRequest {
35
+ protected _body: Buffer;
36
+ constructor(device_type: DeviceType);
37
+ }
38
+ export declare class MessageQuestCustom extends MessageRequest {
39
+ protected _body: Buffer;
40
+ protected cmd_body: Buffer;
41
+ constructor(device_type: DeviceType, message_type: MessageType, cmd_body: Buffer);
42
+ get body(): Buffer;
43
+ }
44
+ export declare class MessageBody {
45
+ readonly data: Buffer;
46
+ constructor(data: Buffer);
47
+ get body_type(): number;
48
+ static read_byte(data: Buffer, offset: number, default_value: number): number;
49
+ }
50
+ export declare class NewProtocolMessageBody extends MessageBody {
51
+ protected packet_length: number;
52
+ constructor(body: Buffer, body_type: number);
53
+ static packet(param: number, value: Buffer, packet_length?: number): Buffer;
54
+ parse(): {
55
+ [key: string]: any;
56
+ };
57
+ }
58
+ export declare class MessageResponse extends MessageBase {
59
+ protected header: Buffer;
60
+ protected device_type: DeviceType;
61
+ protected message_type: MessageType;
62
+ protected body_type: number;
63
+ device_protocol_version: number;
64
+ protected _body: MessageBody;
65
+ constructor(message: Buffer | null | undefined);
66
+ get body(): Buffer;
67
+ set_body(body: MessageBody): void;
68
+ get_body_type(): string;
69
+ get_body_attribute(name: string): any;
70
+ }
71
+ export declare class MessageSubtypeResponse extends MessageResponse {
72
+ sub_type: number;
73
+ constructor(message: Buffer | null | undefined);
74
+ }
75
+ export {};
76
76
  //# sourceMappingURL=MideaMessage.d.ts.map