homebridge-midea-platform 0.2.1 → 0.3.0

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 (77) hide show
  1. package/.eslintignore +3 -0
  2. package/.husky/pre-commit +4 -0
  3. package/.prettierrc +18 -0
  4. package/README.md +5 -0
  5. package/config.schema.json +48 -0
  6. package/dist/accessory/AccessoryFactory.d.ts +2 -1
  7. package/dist/accessory/AccessoryFactory.d.ts.map +1 -1
  8. package/dist/accessory/AccessoryFactory.js +3 -0
  9. package/dist/accessory/AccessoryFactory.js.map +1 -1
  10. package/dist/accessory/AirConditionerAccessory.d.ts +23 -0
  11. package/dist/accessory/AirConditionerAccessory.d.ts.map +1 -1
  12. package/dist/accessory/AirConditionerAccessory.js +122 -36
  13. package/dist/accessory/AirConditionerAccessory.js.map +1 -1
  14. package/dist/accessory/BaseAccessory.d.ts.map +1 -1
  15. package/dist/accessory/BaseAccessory.js +2 -16
  16. package/dist/accessory/BaseAccessory.js.map +1 -1
  17. package/dist/accessory/DehumidifierAccessory.d.ts +41 -0
  18. package/dist/accessory/DehumidifierAccessory.d.ts.map +1 -0
  19. package/dist/accessory/DehumidifierAccessory.js +294 -0
  20. package/dist/accessory/DehumidifierAccessory.js.map +1 -0
  21. package/dist/core/MideaCloud.d.ts +11 -0
  22. package/dist/core/MideaCloud.d.ts.map +1 -1
  23. package/dist/core/MideaCloud.js +106 -65
  24. package/dist/core/MideaCloud.js.map +1 -1
  25. package/dist/core/MideaConstants.d.ts +2 -1
  26. package/dist/core/MideaConstants.d.ts.map +1 -1
  27. package/dist/core/MideaConstants.js +12 -16
  28. package/dist/core/MideaConstants.js.map +1 -1
  29. package/dist/core/MideaDevice.d.ts +26 -8
  30. package/dist/core/MideaDevice.d.ts.map +1 -1
  31. package/dist/core/MideaDevice.js +130 -28
  32. package/dist/core/MideaDevice.js.map +1 -1
  33. package/dist/core/MideaDiscover.d.ts +21 -1
  34. package/dist/core/MideaDiscover.d.ts.map +1 -1
  35. package/dist/core/MideaDiscover.js +98 -20
  36. package/dist/core/MideaDiscover.js.map +1 -1
  37. package/dist/core/MideaMessage.d.ts.map +1 -1
  38. package/dist/core/MideaMessage.js +28 -11
  39. package/dist/core/MideaMessage.js.map +1 -1
  40. package/dist/core/MideaPacketBuilder.d.ts.map +1 -1
  41. package/dist/core/MideaPacketBuilder.js +15 -5
  42. package/dist/core/MideaPacketBuilder.js.map +1 -1
  43. package/dist/core/MideaSecurity.d.ts +3 -1
  44. package/dist/core/MideaSecurity.d.ts.map +1 -1
  45. package/dist/core/MideaSecurity.js +41 -16
  46. package/dist/core/MideaSecurity.js.map +1 -1
  47. package/dist/core/MideaUtils.d.ts +21 -6
  48. package/dist/core/MideaUtils.d.ts.map +1 -1
  49. package/dist/core/MideaUtils.js +81 -83
  50. package/dist/core/MideaUtils.js.map +1 -1
  51. package/dist/devices/DeviceFactory.d.ts +3 -2
  52. package/dist/devices/DeviceFactory.d.ts.map +1 -1
  53. package/dist/devices/DeviceFactory.js +5 -2
  54. package/dist/devices/DeviceFactory.js.map +1 -1
  55. package/dist/devices/a1/MideaA1Device.d.ts +77 -0
  56. package/dist/devices/a1/MideaA1Device.d.ts.map +1 -0
  57. package/dist/devices/a1/MideaA1Device.js +144 -0
  58. package/dist/devices/a1/MideaA1Device.js.map +1 -0
  59. package/dist/devices/a1/MideaA1Message.d.ts +41 -0
  60. package/dist/devices/a1/MideaA1Message.d.ts.map +1 -0
  61. package/dist/devices/a1/MideaA1Message.js +206 -0
  62. package/dist/devices/a1/MideaA1Message.js.map +1 -0
  63. package/dist/devices/ac/MideaACDevice.d.ts +21 -7
  64. package/dist/devices/ac/MideaACDevice.d.ts.map +1 -1
  65. package/dist/devices/ac/MideaACDevice.js +82 -30
  66. package/dist/devices/ac/MideaACDevice.js.map +1 -1
  67. package/dist/devices/ac/MideaACMessage.d.ts.map +1 -1
  68. package/dist/devices/ac/MideaACMessage.js +158 -82
  69. package/dist/devices/ac/MideaACMessage.js.map +1 -1
  70. package/dist/platform.d.ts +29 -5
  71. package/dist/platform.d.ts.map +1 -1
  72. package/dist/platform.js +151 -52
  73. package/dist/platform.js.map +1 -1
  74. package/dist/platformUtils.d.ts +6 -1
  75. package/dist/platformUtils.d.ts.map +1 -1
  76. package/dist/platformUtils.js.map +1 -1
  77. package/package.json +12 -5
@@ -0,0 +1,294 @@
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
+ const BaseAccessory_1 = __importDefault(require("./BaseAccessory"));
7
+ const settings_1 = require("../settings");
8
+ class DehumidifierAccessory extends BaseAccessory_1.default {
9
+ /*********************************************************************
10
+ * Constructor registers all the service types with Homebridge, registers
11
+ * a callback function with the MideaDevice class, and requests device status.
12
+ */
13
+ constructor(platform, accessory, device, configDev) {
14
+ super(platform, accessory, device, configDev);
15
+ this.device = device;
16
+ this.configDev = configDev;
17
+ this.service =
18
+ this.accessory.getService(this.platform.Service.HumidifierDehumidifier) ||
19
+ this.accessory.addService(this.platform.Service.HumidifierDehumidifier);
20
+ this.service.setCharacteristic(this.platform.Characteristic.Name, this.device.name);
21
+ this.accessories = this.platform.accessories.filter((acc) => acc.context.id === this.accessory.UUID && acc !== this.accessory);
22
+ this.service
23
+ .getCharacteristic(this.platform.Characteristic.Active)
24
+ .onGet(this.getActive.bind(this))
25
+ .onSet(this.setActive.bind(this));
26
+ this.service
27
+ .getCharacteristic(this.platform.Characteristic.CurrentHumidifierDehumidifierState)
28
+ .onGet(this.getCurrentHumidifierDehumidifierState.bind(this));
29
+ this.service
30
+ .getCharacteristic(this.platform.Characteristic.TargetHumidifierDehumidifierState)
31
+ .onGet(this.getTargetHumidifierDehumidifierState.bind(this))
32
+ .onSet(this.setTargetHumidifierDehumidifierState.bind(this))
33
+ .setProps({
34
+ validValues: [
35
+ this.platform.Characteristic.TargetHumidifierDehumidifierState
36
+ .HUMIDIFIER_OR_DEHUMIDIFIER,
37
+ this.platform.Characteristic.TargetHumidifierDehumidifierState
38
+ .HUMIDIFIER,
39
+ this.platform.Characteristic.TargetHumidifierDehumidifierState
40
+ .DEHUMIDIFIER,
41
+ ],
42
+ });
43
+ this.service
44
+ .getCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity)
45
+ .onGet(this.getCurrentRelativeHumidity.bind(this))
46
+ .setProps({
47
+ minValue: 0,
48
+ maxValue: 100,
49
+ minStep: 1,
50
+ });
51
+ this.service
52
+ .getCharacteristic(this.platform.Characteristic.RelativeHumidityDehumidifierThreshold)
53
+ .onGet(this.getRelativeHumidityDehumidifierThreshold.bind(this))
54
+ .onSet(this.setRelativeHumidityDehumidifierThreshold.bind(this))
55
+ .setProps({
56
+ minValue: 0,
57
+ maxValue: 100,
58
+ minStep: 5,
59
+ });
60
+ this.service
61
+ .getCharacteristic(this.platform.Characteristic.RotationSpeed)
62
+ .onGet(this.getRotationSpeed.bind(this))
63
+ .onSet(this.setRotationSpeed.bind(this));
64
+ this.service
65
+ .getCharacteristic(this.platform.Characteristic.SwingMode)
66
+ .onGet(this.getSwingMode.bind(this))
67
+ .onSet(this.setSwingMode.bind(this));
68
+ this.service
69
+ .getCharacteristic(this.platform.Characteristic.LockPhysicalControls)
70
+ .onGet(this.getChildLockMode.bind(this))
71
+ .onSet(this.setChildLockMode.bind(this));
72
+ this.service
73
+ .getCharacteristic(this.platform.Characteristic.WaterLevel)
74
+ .onGet(this.getWaterLevel.bind(this));
75
+ // Register a callback function with MideaDevice and then refresh device status. The callback
76
+ // is called whenever there is a change in any attribute value from the device.
77
+ this.device.on('update', this.updateCharacteristics.bind(this));
78
+ this.device.refresh_status();
79
+ // Remove unused accessories
80
+ this.platform.api.unregisterPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, this.accessories);
81
+ }
82
+ /*********************************************************************
83
+ * Callback function called by MideaDevice whenever there is a change to
84
+ * any attribute value.
85
+ */
86
+ async updateCharacteristics(attributes) {
87
+ for (const [k, v] of Object.entries(attributes)) {
88
+ this.platform.log.debug(`[${this.device.name}] Set attribute ${k} to: ${v}`);
89
+ let updateState = false;
90
+ switch (k.toLowerCase()) {
91
+ case 'power':
92
+ this.service.updateCharacteristic(this.platform.Characteristic.Active, v
93
+ ? this.platform.Characteristic.Active.ACTIVE
94
+ : this.platform.Characteristic.Active.INACTIVE);
95
+ updateState = true;
96
+ break;
97
+ case 'target_humidity':
98
+ this.service.updateCharacteristic(this.platform.Characteristic.RelativeHumidityDehumidifierThreshold, v);
99
+ updateState = true;
100
+ break;
101
+ case 'fan_speed':
102
+ this.service.updateCharacteristic(this.platform.Characteristic.RotationSpeed, v);
103
+ break;
104
+ case 'current_humidity':
105
+ this.service.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, v);
106
+ updateState = true;
107
+ break;
108
+ case 'mode':
109
+ updateState = true;
110
+ break;
111
+ case 'swing':
112
+ this.service.updateCharacteristic(this.platform.Characteristic.SwingMode, v
113
+ ? this.platform.Characteristic.SwingMode.SWING_ENABLED
114
+ : this.platform.Characteristic.SwingMode.SWING_DISABLED);
115
+ break;
116
+ case 'current_temperature':
117
+ // Not currently supported
118
+ break;
119
+ case 'tank_level':
120
+ this.service.updateCharacteristic(this.platform.Characteristic.WaterLevel, v);
121
+ break;
122
+ case 'tank_full':
123
+ // No HomeKit characteristic
124
+ break;
125
+ case 'water_level_set':
126
+ // No HomeKit characteristic
127
+ break;
128
+ case 'child_lock':
129
+ this.service.updateCharacteristic(this.platform.Characteristic.LockPhysicalControls, v
130
+ ? this.platform.Characteristic.LockPhysicalControls
131
+ .CONTROL_LOCK_ENABLED
132
+ : this.platform.Characteristic.LockPhysicalControls
133
+ .CONTROL_LOCK_DISABLED);
134
+ break;
135
+ default:
136
+ this.platform.log.warn(`[${this.device.name}] Attempt to set unsupported attribute ${k} to ${v}`);
137
+ }
138
+ if (updateState) {
139
+ this.service.updateCharacteristic(this.platform.Characteristic.TargetHumidifierDehumidifierState, this.platform.Characteristic.TargetHumidifierDehumidifierState
140
+ .DEHUMIDIFIER);
141
+ this.service.updateCharacteristic(this.platform.Characteristic.CurrentHumidifierDehumidifierState, this.currentHumidifierDehumidifierState());
142
+ }
143
+ }
144
+ }
145
+ /*********************************************************************
146
+ * Callback functions for each Homebridge/HomeKit service
147
+ *
148
+ */
149
+ async getActive() {
150
+ this.platform.log.debug(`[${this.device.name}] GET Active, value: ${this.device.attributes.POWER}`);
151
+ return this.device.attributes.POWER
152
+ ? this.platform.Characteristic.Active.ACTIVE
153
+ : this.platform.Characteristic.Active.INACTIVE;
154
+ }
155
+ async setActive(value) {
156
+ this.platform.log.debug(`[${this.device.name}] SET Active to: ${value}`);
157
+ await this.device.set_attribute({ POWER: !!value });
158
+ }
159
+ // Handle requests to get the current value of the "HumidifierDehumidifierState" characteristic
160
+ async getCurrentHumidifierDehumidifierState() {
161
+ this.platform.log.debug(`[${this.device.name}] GET CurrentHumidifierDehumidifierState, value: ${this.device.attributes.POWER},${this.device.attributes.MODE}`);
162
+ return this.currentHumidifierDehumidifierState();
163
+ }
164
+ currentHumidifierDehumidifierState() {
165
+ if (!this.device.attributes.POWER) {
166
+ // Powered off, must be inactive
167
+ return this.platform.Characteristic.CurrentHumidifierDehumidifierState
168
+ .INACTIVE;
169
+ }
170
+ else {
171
+ // Powered on, check mode
172
+ if (this.device.attributes.MODE >= 2) {
173
+ // Dehumidifying
174
+ return this.platform.Characteristic.CurrentHumidifierDehumidifierState
175
+ .DEHUMIDIFYING;
176
+ }
177
+ else if (this.device.attributes.MODE === 1) {
178
+ // Whether deumidifying depends on whether we have reached target. This is not
179
+ // always accurate, but is best we can do to signal whether actively dehumidifing or not.
180
+ if (this.device.attributes.CURRENT_HUMIDITY <
181
+ this.device.attributes.TARGET_HUMIDITY) {
182
+ return this.platform.Characteristic.CurrentHumidifierDehumidifierState
183
+ .IDLE;
184
+ }
185
+ else {
186
+ return this.platform.Characteristic.CurrentHumidifierDehumidifierState
187
+ .DEHUMIDIFYING;
188
+ }
189
+ }
190
+ return this.platform.Characteristic.CurrentHumidifierDehumidifierState
191
+ .IDLE;
192
+ }
193
+ }
194
+ // Handle requests to get the target value of the "HumidifierDehumidifierState" characteristic
195
+ async getTargetHumidifierDehumidifierState() {
196
+ this.platform.log.debug(`[${this.device.name}] GET TargetHumidifierDehumidifierState, value:
197
+ ${this.platform.Characteristic.TargetHumidifierDehumidifierState.DEHUMIDIFIER}`);
198
+ // Always return that we are a dehumidifier, other states not supported.
199
+ return this.platform.Characteristic.TargetHumidifierDehumidifierState
200
+ .DEHUMIDIFIER;
201
+ }
202
+ // Handle requests to set the target value of the "HumidifierDehumidifierState" characteristic
203
+ async setTargetHumidifierDehumidifierState(value) {
204
+ this.platform.log.debug(`[${this.device.name}] SET TargetHumidifierDehumidifierState to: ${value}`);
205
+ if (value !==
206
+ this.platform.Characteristic.TargetHumidifierDehumidifierState
207
+ .DEHUMIDIFIER) {
208
+ throw new Error(`Device ${this.device.name} (${this.device.id}) can only be a DeHumidifier, illegal value: ${value}`);
209
+ }
210
+ }
211
+ // Handle requests to get the current value of the "RelativeHumidity" characteristic
212
+ async getCurrentRelativeHumidity() {
213
+ this.platform.log.debug(`[${this.device.name}] GET CurrentRelativeHumidity, value: ${this.device.attributes.CURRENT_HUMIDITY}`);
214
+ return this.device.attributes.CURRENT_HUMIDITY;
215
+ }
216
+ // Handle requests to get the Relative value of the "HumidityDehumidifierThreshold" characteristic
217
+ async getRelativeHumidityDehumidifierThreshold() {
218
+ this.platform.log.debug(`[${this.device.name}] GET RelativeHumidityDehumidifierThreshold, value: ${this.device.attributes.TARGET_HUMIDITY}`);
219
+ return this.device.attributes.TARGET_HUMIDITY;
220
+ }
221
+ // Handle requests to set the Relative value of the "HumidityDehumidifierThreshold" characteristic
222
+ async setRelativeHumidityDehumidifierThreshold(value) {
223
+ let RequestedHumidity = value;
224
+ // valid humidity has to be between min and max values
225
+ RequestedHumidity =
226
+ RequestedHumidity < this.device.MIN_HUMIDITY
227
+ ? this.device.MIN_HUMIDITY
228
+ : RequestedHumidity > this.device.MAX_HUMIDITY
229
+ ? this.device.MAX_HUMIDITY
230
+ : RequestedHumidity;
231
+ this.platform.log.debug(`[${this.device.name}] SET RelativeHumidityDehumidifierThreshold to: ${RequestedHumidity} (${value})`);
232
+ await this.device.set_attribute({ TARGET_HUMIDITY: RequestedHumidity });
233
+ // Update HomeKit in case we adjusted the value outside of min and max values
234
+ if (RequestedHumidity !== value) {
235
+ // We had to adjust the requested value to within permitted range... Update homekit to actual value set.
236
+ // Calling updateCharacteristic within set handler seems to fail, new value is not accepted. Workaround is
237
+ // to request the update after short delay (say 50ms) to allow homebridge/homekit to complete the set handler.
238
+ setTimeout(() => {
239
+ this.service.updateCharacteristic(this.platform.Characteristic.RelativeHumidityDehumidifierThreshold, RequestedHumidity);
240
+ }, 50);
241
+ }
242
+ }
243
+ // Handle requests to get the current value of the "RotationSpeed" characteristic
244
+ async getRotationSpeed() {
245
+ this.platform.log.debug(`[${this.device.name}] GET RotationSpeed, value: ${this.device.attributes.FAN_SPEED}`);
246
+ return this.device.attributes.FAN_SPEED;
247
+ }
248
+ // Handle requests to set the "RotationSpeed" characteristic
249
+ async setRotationSpeed(value) {
250
+ let speed = value;
251
+ speed = speed <= 40 ? 40 : speed > 40 && speed <= 60 ? 60 : 80;
252
+ this.platform.log.debug(`[${this.device.name}] SET RotationSpeed to: ${speed} (${value})`);
253
+ await this.device.set_attribute({ FAN_SPEED: speed });
254
+ if (speed !== value) {
255
+ // We had to adjust the requested value to within permitted range... Update homekit to actual value set.
256
+ // Calling updateCharacteristic within set handler seems to fail, new value is not accepted. Workaround is
257
+ // to request the update after short delay (say 50ms) to allow homebridge/homekit to complete the set handler.
258
+ setTimeout(() => {
259
+ this.service.updateCharacteristic(this.platform.Characteristic.RotationSpeed, speed);
260
+ }, 50);
261
+ }
262
+ }
263
+ // Handle requests to get the current value of the "WaterLevel" characteristic
264
+ async getWaterLevel() {
265
+ this.platform.log.debug(`[${this.device.name}] GET WaterLevel, value: ${this.device.attributes.TANK_LEVEL}`);
266
+ return this.device.attributes.TANK_LEVEL;
267
+ }
268
+ // Handle requests to get the current value of the "swingMode" characteristic
269
+ async getSwingMode() {
270
+ this.platform.log.debug(`[${this.device.name}] GET SwingMode, value: ${this.device.attributes.SWING}`);
271
+ return this.device.attributes.SWING
272
+ ? this.platform.Characteristic.SwingMode.SWING_ENABLED
273
+ : this.platform.Characteristic.SwingMode.SWING_DISABLED;
274
+ }
275
+ // Handle requests to set the "swingMode" characteristic
276
+ async setSwingMode(value) {
277
+ this.platform.log.debug(`[${this.device.name}] SET SwingMode to: ${value}`);
278
+ await this.device.set_attribute({ SWING: !!value });
279
+ }
280
+ // Handle requests to get the current value of the "LockPhysicalControls" characteristic
281
+ async getChildLockMode() {
282
+ this.platform.log.debug(`[${this.device.name}] GET LockPhysicalControls, value: ${this.device.attributes.SWING}`);
283
+ return this.device.attributes.CHILD_LOCK
284
+ ? this.platform.Characteristic.LockPhysicalControls.CONTROL_LOCK_ENABLED
285
+ : this.platform.Characteristic.LockPhysicalControls.CONTROL_LOCK_DISABLED;
286
+ }
287
+ // Handle requests to set the "LockPhysicalControls" characteristic
288
+ async setChildLockMode(value) {
289
+ this.platform.log.debug(`[${this.device.name}] SET LockPhysicalControls to: ${value}`);
290
+ await this.device.set_attribute({ CHILD_LOCK: !!value });
291
+ }
292
+ }
293
+ exports.default = DehumidifierAccessory;
294
+ //# sourceMappingURL=DehumidifierAccessory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DehumidifierAccessory.js","sourceRoot":"","sources":["../../src/accessory/DehumidifierAccessory.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,13 @@
1
1
  /// <reference types="node" />
2
+ /***********************************************************************
3
+ * Midea Cloud access functions
4
+ *
5
+ * Copyright (c) 2023 Kovalovszky Patrik, https://github.com/kovapatrik
6
+ * Portions Copyright (c) 2023 David Kerr, https://github.com/dkerr64
7
+ *
8
+ * With thanks to https://github.com/georgezhao2010/midea_ac_lan
9
+ *
10
+ */
2
11
  import { Logger } from 'homebridge';
3
12
  import { CloudSecurity } from './MideaSecurity';
4
13
  import { Endianness } from './MideaConstants';
@@ -17,6 +26,8 @@ export declare abstract class CloudBase<T extends CloudSecurity> {
17
26
  protected abstract API_URL: string;
18
27
  protected access_token?: string;
19
28
  protected key?: string;
29
+ private semaphore;
30
+ private loggedIn;
20
31
  constructor(account: string, password: string, logger: Logger, security: T);
21
32
  protected timestamp(): string;
22
33
  apiRequest(endpoint: string, args?: {
@@ -1 +1 @@
1
- {"version":3,"file":"MideaCloud.d.ts","sourceRoot":"","sources":["../../src/core/MideaCloud.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAKpC,OAAO,EAAE,aAAa,EAAwC,MAAM,iBAAiB,CAAC;AAEtF,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,8BAAsB,SAAS,CAAC,CAAC,SAAS,aAAa;IAgBnD,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM;IAClC,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM;IACnC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACjC,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;IAlBhC,SAAS,CAAC,QAAQ,CAAC,WAAW,KAAK;IACnC,SAAS,CAAC,QAAQ,CAAC,MAAM,KAAK;IAC9B,SAAS,CAAC,QAAQ,CAAC,OAAO,cAAc;IAExC,SAAS,CAAC,QAAQ,CAAC,QAAQ,WAAW;IACtC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAU;IAC3C,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAU;IACxC,SAAS,CAAC,QAAQ,CAAC,SAAS,SAAkC;IAE9D,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACnC,SAAS,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAChC,SAAS,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;gBAIF,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,CAAC;IAGhC,SAAS,CAAC,SAAS;IAKb,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAC,EAAE,IAAI,CAAC,EAAE;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAC;IA8CrF,UAAU;IAYV,KAAK;IA8BL,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAkBpF;AAyGD,MAAM,CAAC,OAAO,OAAO,YAAY;IAC/B,MAAM,CAAC,WAAW,CAChB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,SAAS,CAAC,aAAa,CAAC;CAc5B"}
1
+ {"version":3,"file":"MideaCloud.d.ts","sourceRoot":"","sources":["../../src/core/MideaCloud.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAKpC,OAAO,EACL,aAAa,EAId,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,8BAAsB,SAAS,CAAC,CAAC,SAAS,aAAa;IAkBnD,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM;IAClC,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM;IACnC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACjC,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;IApBhC,SAAS,CAAC,QAAQ,CAAC,WAAW,KAAK;IACnC,SAAS,CAAC,QAAQ,CAAC,MAAM,KAAK;IAC9B,SAAS,CAAC,QAAQ,CAAC,OAAO,cAAc;IAExC,SAAS,CAAC,QAAQ,CAAC,QAAQ,WAAW;IACtC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAU;IAC3C,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAU;IACxC,SAAS,CAAC,QAAQ,CAAC,SAAS,SAAkC;IAE9D,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACnC,SAAS,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAChC,SAAS,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAEvB,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,QAAQ,CAAS;gBAGJ,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,CAAC;IAMhC,SAAS,CAAC,SAAS;IAIb,UAAU,CACd,QAAQ,EAAE,MAAM,EAEhB,IAAI,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,EAE7B,IAAI,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE;IAmDzB,UAAU;IAaV,KAAK;IAgDL,QAAQ,CACZ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,UAAU,GACpB,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAuB7B;AAmID,MAAM,CAAC,OAAO,OAAO,YAAY;IAC/B,MAAM,CAAC,WAAW,CAChB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,SAAS,CAAC,aAAa,CAAC;CAc5B"}
@@ -9,6 +9,7 @@ const luxon_1 = require("luxon");
9
9
  const axios_1 = __importDefault(require("axios"));
10
10
  const MideaSecurity_1 = require("./MideaSecurity");
11
11
  const MideaUtils_1 = require("./MideaUtils");
12
+ const semaphore_promise_1 = require("semaphore-promise");
12
13
  class CloudBase {
13
14
  constructor(account, password, logger, security) {
14
15
  this.account = account;
@@ -22,21 +23,27 @@ class CloudBase {
22
23
  this.APP_ID = '1010';
23
24
  this.SRC = '1010';
24
25
  this.DEVICE_ID = (0, crypto_1.randomBytes)(8).toString('hex');
26
+ this.loggedIn = false;
27
+ // Required to serialize access to some cloud functions.
28
+ this.semaphore = new semaphore_promise_1.Semaphore();
25
29
  }
26
30
  timestamp() {
27
- return luxon_1.DateTime.utc().toFormat('yyyyMMddHHmmss');
31
+ return luxon_1.DateTime.now().toFormat('yyyyMMddHHmmss');
28
32
  }
33
+ async apiRequest(endpoint,
29
34
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
- async apiRequest(endpoint, args, data) {
35
+ args,
36
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
+ data) {
31
38
  if (data === undefined) {
32
39
  data = {
33
- 'appId': this.APP_ID,
34
- 'format': this.FORMAT,
35
- 'clientType': this.CLIENT_TYPE,
36
- 'language': this.LANGUAGE,
37
- 'src': this.SRC,
38
- 'stamp': this.timestamp(),
39
- 'deviceId': this.DEVICE_ID,
40
+ appId: this.APP_ID,
41
+ format: this.FORMAT,
42
+ clientType: this.CLIENT_TYPE,
43
+ language: this.LANGUAGE,
44
+ src: this.SRC,
45
+ stamp: this.timestamp(),
46
+ deviceId: this.DEVICE_ID,
40
47
  };
41
48
  }
42
49
  data = { ...data, ...args };
@@ -48,10 +55,10 @@ class CloudBase {
48
55
  const sign = this.security.sign(JSON.stringify(data), random);
49
56
  const headers = {
50
57
  'Content-Type': 'application/json',
51
- 'secretVersion': '1',
52
- 'sign': sign,
53
- 'random': random,
54
- 'accessToken': this.access_token,
58
+ secretVersion: '1',
59
+ sign: sign,
60
+ random: random,
61
+ accessToken: this.access_token,
55
62
  };
56
63
  for (let i = 0; i < 3; i++) {
57
64
  try {
@@ -71,52 +78,74 @@ class CloudBase {
71
78
  }
72
79
  async getLoginId() {
73
80
  const response = await this.apiRequest('/v1/user/login/id/get', {
74
- 'loginAccount': this.account,
81
+ loginAccount: this.account,
75
82
  });
76
83
  if (response) {
84
+ this.logger.info('Logged in to Midea Cloud.');
77
85
  return response['loginId'];
78
86
  }
79
87
  throw new Error('Failed to get login ID.');
80
88
  }
81
89
  async login() {
82
- const login_id = await this.getLoginId();
83
- const response = await this.apiRequest('/mj/user/login', {
84
- 'data': {
85
- 'appKey': this.APP_KEY,
86
- 'platform': this.FORMAT,
87
- 'deviceId': this.DEVICE_ID,
88
- },
89
- 'iotData': {
90
- 'appId': this.APP_ID,
91
- 'clientType': this.CLIENT_TYPE,
92
- 'iampwd': this.security.encrpytIAMPassword(login_id, this.password),
93
- 'loginAccount': this.account,
94
- 'password': this.security.encrpytPassword(login_id, this.password),
95
- 'pushToken': (0, crypto_1.randomBytes)(20).toString('base64url'),
96
- 'reqId': (0, crypto_1.randomBytes)(16).toString('hex'),
97
- 'src': this.SRC,
98
- 'stamp': this.timestamp(),
99
- },
100
- });
101
- if (response) {
102
- this.access_token = response['mdata']['accessToken'];
103
- if (response['key'] !== undefined) {
104
- this.key = response['key'];
90
+ // We need to protect against multiple attempts to login, so we only login if not already
91
+ // logged in. Protect this block with a semaphone.
92
+ const releaseSemaphore = await this.semaphore.acquire('Obtain login semaphore');
93
+ try {
94
+ if (this.loggedIn) {
95
+ return;
96
+ }
97
+ // Not logged in so proceed...
98
+ const login_id = await this.getLoginId();
99
+ const response = await this.apiRequest('/mj/user/login', {
100
+ data: {
101
+ appKey: this.APP_KEY,
102
+ platform: this.FORMAT,
103
+ deviceId: this.DEVICE_ID,
104
+ },
105
+ iotData: {
106
+ appId: this.APP_ID,
107
+ clientType: this.CLIENT_TYPE,
108
+ iampwd: this.security.encrpytIAMPassword(login_id, this.password),
109
+ loginAccount: this.account,
110
+ password: this.security.encrpytPassword(login_id, this.password),
111
+ pushToken: (0, crypto_1.randomBytes)(20).toString('base64url'),
112
+ reqId: (0, crypto_1.randomBytes)(16).toString('hex'),
113
+ src: this.SRC,
114
+ stamp: this.timestamp(),
115
+ },
116
+ });
117
+ if (response) {
118
+ this.access_token = response['mdata']['accessToken'];
119
+ if (response['key'] !== undefined) {
120
+ this.key = response['key'];
121
+ }
122
+ this.loggedIn = true;
123
+ }
124
+ else {
125
+ this.loggedIn = false;
126
+ throw new Error('Failed to login.');
105
127
  }
106
128
  }
107
- else {
108
- throw new Error('Failed to login.');
129
+ catch (e) {
130
+ const msg = e instanceof Error ? e.stack : e;
131
+ throw new Error(`Error in Adding new accessory:\n${msg}`);
132
+ }
133
+ finally {
134
+ releaseSemaphore();
109
135
  }
110
136
  }
111
137
  async getToken(device_id, endianess) {
112
138
  const udpid = MideaSecurity_1.CloudSecurity.getUDPID((0, MideaUtils_1.numberToUint8Array)(device_id, 6, endianess));
113
139
  const response = await this.apiRequest('/v1/iot/secure/getToken', {
114
- 'udpid': udpid,
140
+ udpid: udpid,
115
141
  });
116
142
  if (response) {
117
143
  for (const token of response['tokenlist']) {
118
144
  if (token['udpId'] === udpid) {
119
- return [Buffer.from(token['token'], 'hex'), Buffer.from(token['key'], 'hex')];
145
+ return [
146
+ Buffer.from(token['token'], 'hex'),
147
+ Buffer.from(token['key'], 'hex'),
148
+ ];
120
149
  }
121
150
  }
122
151
  }
@@ -139,31 +168,24 @@ class MeijuCloud extends CloudBase {
139
168
  this.API_URL = 'https://mp-prod.smartmidea.net/mas/v5/app/proxy?alias=';
140
169
  }
141
170
  }
142
- class NetHomePlusCloud extends CloudBase {
143
- constructor(account, password, logger) {
144
- super(account, password, logger, new MideaSecurity_1.CloudSecurity('xhdiwjnchekd4d512chdjx5d8e4c394D2D7S'));
145
- this.API_URL = 'https://mapp.appsmb.com';
146
- this.APP_ID = '1017';
147
- this.SRC = '1017';
148
- }
149
- }
150
- class MideaAirCloud extends CloudBase {
151
- constructor(account, password, logger) {
152
- super(account, password, logger, new MideaSecurity_1.MideaAirSecurity('ff0cf6f5f0c3471de36341cab3f7a9af', undefined));
171
+ class UnProxiedCloudBase extends CloudBase {
172
+ constructor(account, password, logger, security) {
173
+ super(account, password, logger, security);
153
174
  this.API_URL = 'https://mapp.appsmb.com';
154
- this.APP_ID = '1117';
155
- this.SRC = '17';
156
175
  }
176
+ async apiRequest(endpoint,
157
177
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
158
- async apiRequest(endpoint, args, data) {
178
+ args,
179
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
180
+ data) {
159
181
  if (data === undefined) {
160
182
  data = {
161
- 'appId': this.APP_ID,
162
- 'format': this.FORMAT,
163
- 'clientType': this.CLIENT_TYPE,
164
- 'language': this.LANGUAGE,
165
- 'src': this.SRC,
166
- 'stamp': this.timestamp(),
183
+ appId: this.APP_ID,
184
+ format: this.FORMAT,
185
+ clientType: this.CLIENT_TYPE,
186
+ language: this.LANGUAGE,
187
+ src: this.SRC,
188
+ stamp: this.timestamp(),
167
189
  };
168
190
  }
169
191
  data = { ...data, ...args };
@@ -172,11 +194,16 @@ class MideaAirCloud extends CloudBase {
172
194
  }
173
195
  const url = `${this.API_URL}${endpoint}`;
174
196
  const queryParams = new URLSearchParams(data);
197
+ queryParams.sort();
175
198
  data['sign'] = this.security.sign(url, queryParams.toString());
199
+ const headers = {
200
+ 'Content-Type': 'application/x-www-form-urlencoded',
201
+ };
176
202
  for (let i = 0; i < 3; i++) {
177
203
  try {
178
- const response = await axios_1.default.post(url, data);
179
- if (response.data['errorCode'] !== undefined && Number.parseInt(response.data['errorCode']) !== 0 &&
204
+ const response = await axios_1.default.post(url, data, { headers: headers });
205
+ if (response.data['errorCode'] !== undefined &&
206
+ Number.parseInt(response.data['errorCode']) === 0 &&
180
207
  response.data['result'] !== undefined) {
181
208
  return response.data['result'];
182
209
  }
@@ -190,8 +217,8 @@ class MideaAirCloud extends CloudBase {
190
217
  async login() {
191
218
  const login_id = await this.getLoginId();
192
219
  const response = await this.apiRequest('/v1/user/login', {
193
- 'loginAccount': this.account,
194
- 'password': this.security.encrpytPassword(login_id, this.password),
220
+ loginAccount: this.account,
221
+ password: this.security.encrpytPassword(login_id, this.password),
195
222
  });
196
223
  if (response) {
197
224
  this.access_token = response['accessToken'];
@@ -202,6 +229,20 @@ class MideaAirCloud extends CloudBase {
202
229
  }
203
230
  }
204
231
  }
232
+ class NetHomePlusCloud extends UnProxiedCloudBase {
233
+ constructor(account, password, logger) {
234
+ super(account, password, logger, new MideaSecurity_1.NetHomePlusSecurity('3742e9e5842d4ad59c2db887e12449f9'));
235
+ this.APP_ID = '1017';
236
+ this.SRC = '1017';
237
+ }
238
+ }
239
+ class MideaAirCloud extends UnProxiedCloudBase {
240
+ constructor(account, password, logger) {
241
+ super(account, password, logger, new MideaSecurity_1.MideaAirSecurity('ff0cf6f5f0c3471de36341cab3f7a9af'));
242
+ this.APP_ID = '1117';
243
+ this.SRC = '17';
244
+ }
245
+ }
205
246
  class CloudFactory {
206
247
  static createCloud(account, password, logger, cloud) {
207
248
  switch (cloud) {