node-switchbot 1.6.0-beta.12 → 1.6.0-beta.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/parameter-checker.js +10 -10
- package/lib/switchbot-advertising.js +158 -159
- package/lib/switchbot-device-wobulb.js +1 -1
- package/lib/switchbot-device-wocurtain.js +2 -2
- package/lib/switchbot-device-wohand.js +2 -2
- package/lib/switchbot-device-wohumi.js +2 -2
- package/lib/switchbot-device-woplugmini.js +1 -1
- package/lib/switchbot-device-wostrip.js +1 -1
- package/lib/switchbot-device.js +20 -20
- package/lib/switchbot.js +22 -22
- package/package.json +1 -1
package/lib/parameter-checker.js
CHANGED
|
@@ -37,7 +37,7 @@ class ParameterChecker {
|
|
|
37
37
|
* an `Error` object will be set to `this._error`.
|
|
38
38
|
*
|
|
39
39
|
* [Usage]
|
|
40
|
-
*
|
|
40
|
+
* const valid = parameterChecker.check(params, {
|
|
41
41
|
* level: {
|
|
42
42
|
* required: false,
|
|
43
43
|
* type: 'integer',
|
|
@@ -50,7 +50,7 @@ class ParameterChecker {
|
|
|
50
50
|
* }
|
|
51
51
|
* });
|
|
52
52
|
* if(!valid) {
|
|
53
|
-
*
|
|
53
|
+
* const e = parameterChecker.error.message;
|
|
54
54
|
* throw new Error(message);
|
|
55
55
|
* }
|
|
56
56
|
* ---------------------------------------------------------------- */
|
|
@@ -78,13 +78,13 @@ class ParameterChecker {
|
|
|
78
78
|
return false;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
const result = true;
|
|
82
|
+
const name_list = Object.keys(rules);
|
|
83
83
|
|
|
84
|
-
for (
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
for (const i = 0; i < name_list.length; i++) {
|
|
85
|
+
const name = name_list[i];
|
|
86
|
+
const v = obj[name];
|
|
87
|
+
const rule = rules[name];
|
|
88
88
|
|
|
89
89
|
if (!rule) {
|
|
90
90
|
rule = {};
|
|
@@ -458,7 +458,7 @@ class ParameterChecker {
|
|
|
458
458
|
}
|
|
459
459
|
}
|
|
460
460
|
if (typeof rule.minBytes === "number") {
|
|
461
|
-
|
|
461
|
+
const blen = Buffer.from(value, "utf8").length;
|
|
462
462
|
if (blen < rule.minBytes) {
|
|
463
463
|
this._error = {
|
|
464
464
|
code: "LENGTH_UNDERFLOW",
|
|
@@ -475,7 +475,7 @@ class ParameterChecker {
|
|
|
475
475
|
}
|
|
476
476
|
}
|
|
477
477
|
if (typeof rule.maxBytes === "number") {
|
|
478
|
-
|
|
478
|
+
const blen = Buffer.from(value, "utf8").length;
|
|
479
479
|
if (blen > rule.maxBytes) {
|
|
480
480
|
this._error = {
|
|
481
481
|
code: "LENGTH_OVERFLOW",
|
|
@@ -61,13 +61,13 @@ class SwitchbotAdvertising {
|
|
|
61
61
|
* device, this method will return `null`.
|
|
62
62
|
* ---------------------------------------------------------------- */
|
|
63
63
|
parse(peripheral, onlog) {
|
|
64
|
-
|
|
64
|
+
const ad = peripheral.advertisement;
|
|
65
65
|
if (!ad || !ad.serviceData) {
|
|
66
66
|
return null;
|
|
67
67
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
const serviceData = ad.serviceData[0] || ad.serviceData;
|
|
69
|
+
const manufacturerData = ad.manufacturerData;
|
|
70
|
+
const buf = serviceData.data;
|
|
71
71
|
|
|
72
72
|
const bufIsInvalid = !buf || !Buffer.isBuffer(buf) || buf.length < 3;
|
|
73
73
|
const manufacturerDataIsInvalid =
|
|
@@ -79,8 +79,8 @@ class SwitchbotAdvertising {
|
|
|
79
79
|
return null;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
const model = buf.slice(0, 1).toString("utf8");
|
|
83
|
+
const sd = null;
|
|
84
84
|
|
|
85
85
|
if (model === "H") {
|
|
86
86
|
sd = this._parseServiceDataForWoHand(buf, onlog);//WoHand
|
|
@@ -123,7 +123,7 @@ class SwitchbotAdvertising {
|
|
|
123
123
|
}
|
|
124
124
|
return null;
|
|
125
125
|
}
|
|
126
|
-
|
|
126
|
+
const address = peripheral.address || "";
|
|
127
127
|
if (address === "") {
|
|
128
128
|
address = peripheral.advertisement.manufacturerData || "";
|
|
129
129
|
if (address !== "") {
|
|
@@ -139,7 +139,7 @@ class SwitchbotAdvertising {
|
|
|
139
139
|
} else {
|
|
140
140
|
address = address.replace(/-/g, ":");
|
|
141
141
|
}
|
|
142
|
-
|
|
142
|
+
const data = {
|
|
143
143
|
id: peripheral.id,
|
|
144
144
|
address: address,
|
|
145
145
|
rssi: peripheral.rssi,
|
|
@@ -165,14 +165,14 @@ class SwitchbotAdvertising {
|
|
|
165
165
|
}
|
|
166
166
|
return null;
|
|
167
167
|
}
|
|
168
|
-
|
|
169
|
-
|
|
168
|
+
const byte1 = buf.readUInt8(1);
|
|
169
|
+
const byte2 = buf.readUInt8(2);
|
|
170
170
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
171
|
+
const mode = byte1 & 0b10000000 ? true : false; // Whether the light switch Add-on is used or not
|
|
172
|
+
const state = byte1 & 0b01000000 ? true : false; // Whether the switch status is ON or OFF
|
|
173
|
+
const battery = byte2 & 0b01111111; // %
|
|
174
174
|
|
|
175
|
-
|
|
175
|
+
const data = {
|
|
176
176
|
model: "H",
|
|
177
177
|
modelName: "WoHand",
|
|
178
178
|
mode: mode,
|
|
@@ -192,17 +192,17 @@ class SwitchbotAdvertising {
|
|
|
192
192
|
}
|
|
193
193
|
return null;
|
|
194
194
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
195
|
+
const byte2 = buf.readUInt8(2);
|
|
196
|
+
const byte3 = buf.readUInt8(3);
|
|
197
|
+
const byte4 = buf.readUInt8(4);
|
|
198
|
+
const byte5 = buf.readUInt8(5);
|
|
199
|
+
|
|
200
|
+
const temp_sign = byte4 & 0b10000000 ? 1 : -1;
|
|
201
|
+
const temp_c = temp_sign * ((byte4 & 0b01111111) + (byte3 & 0b00001111) / 10);
|
|
202
|
+
const temp_f = (temp_c * 9 / 5) + 32;
|
|
203
203
|
temp_f = Math.round(temp_f * 10) / 10;
|
|
204
204
|
|
|
205
|
-
|
|
205
|
+
const data = {
|
|
206
206
|
model: "T",
|
|
207
207
|
modelName: "WoSensorTH",
|
|
208
208
|
temperature: {
|
|
@@ -226,15 +226,15 @@ class SwitchbotAdvertising {
|
|
|
226
226
|
}
|
|
227
227
|
return null;
|
|
228
228
|
}
|
|
229
|
-
|
|
230
|
-
|
|
229
|
+
const byte1 = buf.readUInt8(1);
|
|
230
|
+
const byte4 = buf.readUInt8(4);
|
|
231
231
|
|
|
232
232
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
233
|
+
const onState = byte1 & 0b10000000 ? true : false; // 1 - on
|
|
234
|
+
const autoMode = byte4 & 0b10000000 ? true : false; // 1 - auto
|
|
235
|
+
const percentage = byte4 & 0b01111111; // 0-100%, 101/102/103 - Quick gear 1/2/3
|
|
236
236
|
|
|
237
|
-
|
|
237
|
+
const data = {
|
|
238
238
|
model: "e",
|
|
239
239
|
modelName: "WoHumi",
|
|
240
240
|
onState: onState,
|
|
@@ -255,20 +255,20 @@ class SwitchbotAdvertising {
|
|
|
255
255
|
return null;
|
|
256
256
|
}
|
|
257
257
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
258
|
+
const byte1 = buf.readUInt8(1);
|
|
259
|
+
const byte2 = buf.readUInt8(2);
|
|
260
|
+
const byte5 = buf.readUInt8(5);
|
|
261
261
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
262
|
+
const tested = byte1 & 0b10000000 ? true : false;
|
|
263
|
+
const movement = byte1 & 0b01000000 ? true : false;
|
|
264
|
+
const battery = byte2 & 0b01111111;
|
|
265
|
+
const led = (byte5 & 0b00100000) >> 5;
|
|
266
|
+
const iot = (byte5 & 0b00010000) >> 4;
|
|
267
|
+
const sense_distance = (byte5 & 0b00001100) >> 2;
|
|
268
|
+
const lightLevel = byte5 & 0b00000011;
|
|
269
|
+
const is_light = byte5 & 0b00000010 ? true : false;
|
|
270
270
|
|
|
271
|
-
|
|
271
|
+
const data = {
|
|
272
272
|
model: "s",
|
|
273
273
|
modelName: "WoMotion",
|
|
274
274
|
tested: tested,
|
|
@@ -295,21 +295,21 @@ class SwitchbotAdvertising {
|
|
|
295
295
|
return null;
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
298
|
+
const byte1 = buf.readUInt8(1);
|
|
299
|
+
const byte2 = buf.readUInt8(2);
|
|
300
|
+
const byte3 = buf.readUInt8(3);
|
|
301
|
+
const byte8 = buf.readUInt8(8);
|
|
302
|
+
|
|
303
|
+
const hallState = (byte3 >> 1) & 0b00000011;
|
|
304
|
+
const tested = byte1 & 0b10000000;
|
|
305
|
+
const movement = byte1 & 0b01000000 ? true : false; // 1 - Movement detected
|
|
306
|
+
const battery = byte2 & 0b01111111; // %
|
|
307
|
+
const contact_open = byte3 & 0b00000010 == 0b00000010;
|
|
308
|
+
const contact_timeout = byte3 & 0b00000100 == 0b00000100;
|
|
309
|
+
const lightLevel = byte3 & 0b00000001;
|
|
310
|
+
const button_count = byte8 & 0b00001111;
|
|
311
|
+
|
|
312
|
+
const data = {
|
|
313
313
|
model: "d",
|
|
314
314
|
modelName: "WoContact",
|
|
315
315
|
movement: movement,
|
|
@@ -339,20 +339,19 @@ class SwitchbotAdvertising {
|
|
|
339
339
|
}
|
|
340
340
|
return null;
|
|
341
341
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
let data = {
|
|
342
|
+
const byte1 = buf.readUInt8(1);
|
|
343
|
+
const byte2 = buf.readUInt8(2);
|
|
344
|
+
const byte3 = buf.readUInt8(3);
|
|
345
|
+
const byte4 = buf.readUInt8(4);
|
|
346
|
+
|
|
347
|
+
const calibration = byte1 & 0b01000000 ? true : false; // Whether the calibration is completed
|
|
348
|
+
const battery = byte2 & 0b01111111; // %
|
|
349
|
+
const inMotion = byte3 & 0b10000000 ? true : false;
|
|
350
|
+
const currPosition = byte3 & 0b01111111; // current positon %
|
|
351
|
+
const lightLevel = (byte4 >> 4) & 0b00001111; // light sensor level (1-10)
|
|
352
|
+
const deviceChain = byte4 & 0b00000111;
|
|
353
|
+
|
|
354
|
+
const data = {
|
|
356
355
|
model: "c",
|
|
357
356
|
modelName: "WoCurtain",
|
|
358
357
|
calibration: calibration,
|
|
@@ -375,31 +374,31 @@ class SwitchbotAdvertising {
|
|
|
375
374
|
}
|
|
376
375
|
return null;
|
|
377
376
|
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
377
|
+
const byte1 = buf.readUInt8(1);//power and light status
|
|
378
|
+
const byte2 = buf.readUInt8(2);//bulb brightness
|
|
379
|
+
const byte3 = buf.readUInt8(3);//bulb R
|
|
380
|
+
const byte4 = buf.readUInt8(4);//bulb G
|
|
381
|
+
const byte5 = buf.readUInt8(5);//bulb B
|
|
382
|
+
const byte6 = buf.readUInt8(6);//bulb temperature
|
|
383
|
+
const byte7 = buf.readUInt8(7);
|
|
384
|
+
const byte8 = buf.readUInt8(8);
|
|
385
|
+
const byte9 = buf.readUInt8(9);
|
|
386
|
+
const byte10 = buf.readUInt8(10);//bulb mode
|
|
387
|
+
|
|
388
|
+
const power = byte1;
|
|
389
|
+
const red = byte3;
|
|
390
|
+
const green = byte4;
|
|
391
|
+
const blue = byte5;
|
|
392
|
+
const color_temperature = byte6;
|
|
393
|
+
const state = byte7 & 0b01111111 ? true : false;
|
|
394
|
+
const brightness = byte7 & 0b01111111;
|
|
395
|
+
const delay = byte8 & 0b10000000;
|
|
396
|
+
const preset = byte8 & 0b00001000;
|
|
397
|
+
const color_mode = byte8 & 0b00000111;
|
|
398
|
+
const speed = byte9 & 0b01111111;
|
|
399
|
+
const loop_index = byte10 & 0b11111110;
|
|
400
|
+
|
|
401
|
+
const data = {
|
|
403
402
|
model: "u",
|
|
404
403
|
modelName: "WoBulb",
|
|
405
404
|
color_temperature: color_temperature,
|
|
@@ -428,22 +427,22 @@ class SwitchbotAdvertising {
|
|
|
428
427
|
}
|
|
429
428
|
return null;
|
|
430
429
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
430
|
+
const byte9 = buf.readUInt8(9); // byte9: plug mini state; 0x00=off, 0x80=on
|
|
431
|
+
const byte10 = buf.readUInt8(10); // byte10: bit0: 0=no delay,1=delay, bit1:0=no timer, 1=timer; bit2:0=no sync time, 1=sync'ed time
|
|
432
|
+
const byte11 = buf.readUInt8(11); // byte11: wifi rssi
|
|
433
|
+
const byte12 = buf.readUInt8(12); // byte12: bit7: overload?
|
|
434
|
+
const byte13 = buf.readUInt8(13); // byte12[bit0~6] + byte13: current power value
|
|
435
|
+
|
|
436
|
+
const state = byte9 === 0x00 ? "off" : byte9 === 0x80 ? "on" : null;
|
|
437
|
+
const delay = !!(byte10 & 0b00000001);
|
|
438
|
+
const timer = !!(byte10 & 0b00000010);
|
|
439
|
+
const syncUtcTime = !!(byte10 & 0b00000100);
|
|
440
|
+
const wifiRssi = byte11;
|
|
441
|
+
const overload = !!(byte12 & 0b10000000);
|
|
442
|
+
const currentPower = (((byte12 & 0b01111111) << 8) + byte13) / 10; // in watt
|
|
444
443
|
// TODO: voltage ???
|
|
445
444
|
|
|
446
|
-
|
|
445
|
+
const data = {
|
|
447
446
|
model: "g",
|
|
448
447
|
modelName: "WoPlugMini",
|
|
449
448
|
state: state,
|
|
@@ -467,22 +466,22 @@ class SwitchbotAdvertising {
|
|
|
467
466
|
}
|
|
468
467
|
return null;
|
|
469
468
|
}
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
469
|
+
const byte9 = buf.readUInt8(9); // byte9: plug mini state; 0x00=off, 0x80=on
|
|
470
|
+
const byte10 = buf.readUInt8(10); // byte10: bit0: 0=no delay,1=delay, bit1:0=no timer, 1=timer; bit2:0=no sync time, 1=sync'ed time
|
|
471
|
+
const byte11 = buf.readUInt8(11); // byte11: wifi rssi
|
|
472
|
+
const byte12 = buf.readUInt8(12); // byte12: bit7: overload?
|
|
473
|
+
const byte13 = buf.readUInt8(13); // byte12[bit0~6] + byte13: current power value
|
|
474
|
+
|
|
475
|
+
const state = byte9 === 0x00 ? "off" : byte9 === 0x80 ? "on" : null;
|
|
476
|
+
const delay = !!(byte10 & 0b00000001);
|
|
477
|
+
const timer = !!(byte10 & 0b00000010);
|
|
478
|
+
const syncUtcTime = !!(byte10 & 0b00000100);
|
|
479
|
+
const wifiRssi = byte11;
|
|
480
|
+
const overload = !!(byte12 & 0b10000000);
|
|
481
|
+
const currentPower = (((byte12 & 0b01111111) << 8) + byte13) / 10; // in watt
|
|
483
482
|
// TODO: voltage ???
|
|
484
483
|
|
|
485
|
-
|
|
484
|
+
const data = {
|
|
486
485
|
model: "j",
|
|
487
486
|
modelName: "WoPlugMini",
|
|
488
487
|
state: state,
|
|
@@ -506,13 +505,13 @@ class SwitchbotAdvertising {
|
|
|
506
505
|
}
|
|
507
506
|
return null;
|
|
508
507
|
}
|
|
509
|
-
|
|
510
|
-
|
|
508
|
+
const byte1 = buf.readUInt8(1);
|
|
509
|
+
const byte2 = buf.readUInt8(2);
|
|
511
510
|
|
|
512
|
-
|
|
513
|
-
|
|
511
|
+
const movement = (byte1 & 0b01000000) ? true : false; // 1 - Movement detected
|
|
512
|
+
const battery = byte2 & 0b01111111; // %
|
|
514
513
|
|
|
515
|
-
|
|
514
|
+
const data = {
|
|
516
515
|
model: "o",
|
|
517
516
|
modelName: "WoSmartLock",
|
|
518
517
|
battery: battery,
|
|
@@ -531,17 +530,17 @@ class SwitchbotAdvertising {
|
|
|
531
530
|
}
|
|
532
531
|
return null;
|
|
533
532
|
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
533
|
+
const byte2 = buf.readUInt8(2);
|
|
534
|
+
const byte3 = buf.readUInt8(3);
|
|
535
|
+
const byte4 = buf.readUInt8(4);
|
|
536
|
+
const byte5 = buf.readUInt8(5);
|
|
537
|
+
|
|
538
|
+
const temp_sign = byte4 & 0b10000000 ? 1 : -1;
|
|
539
|
+
const temp_c = temp_sign * ((byte4 & 0b01111111) + (byte3 & 0b00001111) / 10);
|
|
540
|
+
const temp_f = (temp_c * 9 / 5) + 32;
|
|
542
541
|
temp_f = Math.round(temp_f * 10) / 10;
|
|
543
542
|
|
|
544
|
-
|
|
543
|
+
const data = {
|
|
545
544
|
model: "i",
|
|
546
545
|
modelName: "WoSensorTHPlus",
|
|
547
546
|
temperature: {
|
|
@@ -566,28 +565,28 @@ class SwitchbotAdvertising {
|
|
|
566
565
|
return null;
|
|
567
566
|
}
|
|
568
567
|
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
568
|
+
const byte1 = buf.readUInt8(1);//power and light status
|
|
569
|
+
const byte2 = buf.readUInt8(2);//bulb brightness
|
|
570
|
+
const byte3 = buf.readUInt8(3);//bulb R
|
|
571
|
+
const byte4 = buf.readUInt8(4);//bulb G
|
|
572
|
+
const byte5 = buf.readUInt8(5);//bulb B
|
|
573
|
+
const byte7 = buf.readUInt8(7);
|
|
574
|
+
const byte8 = buf.readUInt8(8);
|
|
575
|
+
const byte9 = buf.readUInt8(9);
|
|
576
|
+
const byte10 = buf.readUInt8(10);
|
|
577
|
+
|
|
578
|
+
const state = byte7 & 0b10000000 ? true : false;
|
|
579
|
+
const brightness = byte7 & 0b01111111;
|
|
580
|
+
const red = byte3;
|
|
581
|
+
const green = byte4;
|
|
582
|
+
const blue = byte5;
|
|
583
|
+
const delay = byte8 & 0b10000000;
|
|
584
|
+
const preset = byte8 & 0b00001000;
|
|
585
|
+
const color_mode = byte8 & 0b00000111;
|
|
586
|
+
const speed = byte9 & 0b01111111;
|
|
587
|
+
const loop_index = byte10 & 0b11111110;
|
|
588
|
+
|
|
589
|
+
const data = {
|
|
591
590
|
model: "r",
|
|
592
591
|
modelName: "WoStrip",
|
|
593
592
|
state: state,
|
|
@@ -155,7 +155,7 @@ class SwitchbotDeviceWoBulb extends SwitchbotDevice {
|
|
|
155
155
|
.then((res_bytes) => {
|
|
156
156
|
const res_buf = Buffer.from(res_bytes);
|
|
157
157
|
if (res_buf.length === 2) {
|
|
158
|
-
|
|
158
|
+
const code = res_buf.readUInt8(1);
|
|
159
159
|
if (code === 0x00 || code === 0x80) {
|
|
160
160
|
const is_on = code === 0x80;
|
|
161
161
|
resolve(is_on);
|
|
@@ -93,10 +93,10 @@ class SwitchbotDeviceWoCurtain extends SwitchbotDevice {
|
|
|
93
93
|
|
|
94
94
|
_operateCurtain(bytes) {
|
|
95
95
|
return new Promise((resolve, reject) => {
|
|
96
|
-
|
|
96
|
+
const req_buf = Buffer.from(bytes);
|
|
97
97
|
this._command(req_buf)
|
|
98
98
|
.then((res_buf) => {
|
|
99
|
-
|
|
99
|
+
const code = res_buf.readUInt8(0);
|
|
100
100
|
if (res_buf.length === 3 && code === 0x01) {
|
|
101
101
|
resolve();
|
|
102
102
|
} else {
|
|
@@ -79,10 +79,10 @@ class SwitchbotDeviceWoHand extends SwitchbotDevice {
|
|
|
79
79
|
|
|
80
80
|
_operateBot(bytes) {
|
|
81
81
|
return new Promise((resolve, reject) => {
|
|
82
|
-
|
|
82
|
+
const req_buf = Buffer.from(bytes);
|
|
83
83
|
this._command(req_buf)
|
|
84
84
|
.then((res_buf) => {
|
|
85
|
-
|
|
85
|
+
const code = res_buf.readUInt8(0);
|
|
86
86
|
if (res_buf.length === 3 && (code === 0x01 || code === 0x05)) {
|
|
87
87
|
resolve();
|
|
88
88
|
} else {
|
|
@@ -79,10 +79,10 @@ class SwitchbotDeviceWoHumi extends SwitchbotDevice {
|
|
|
79
79
|
|
|
80
80
|
_operateBot(bytes) {
|
|
81
81
|
return new Promise((resolve, reject) => {
|
|
82
|
-
|
|
82
|
+
const req_buf = Buffer.from(bytes);
|
|
83
83
|
this._command(req_buf)
|
|
84
84
|
.then((res_buf) => {
|
|
85
|
-
|
|
85
|
+
const code = res_buf.readUInt8(0);
|
|
86
86
|
if (res_buf.length === 3 && (code === 0x01 || code === 0x05)) {
|
|
87
87
|
resolve();
|
|
88
88
|
} else {
|
|
@@ -51,7 +51,7 @@ class SwitchbotDeviceWoPlugMini extends SwitchbotDevice {
|
|
|
51
51
|
.then((res_bytes) => {
|
|
52
52
|
const res_buf = Buffer.from(res_bytes);
|
|
53
53
|
if (res_buf.length === 2) {
|
|
54
|
-
|
|
54
|
+
const code = res_buf.readUInt8(1);
|
|
55
55
|
if (code === 0x00 || code === 0x80) {
|
|
56
56
|
const is_on = code === 0x80;
|
|
57
57
|
resolve(is_on);
|
|
@@ -149,7 +149,7 @@ class SwitchbotDeviceWoStrip extends SwitchbotDevice {
|
|
|
149
149
|
.then((res_bytes) => {
|
|
150
150
|
const res_buf = Buffer.from(res_bytes);
|
|
151
151
|
if (res_buf.length === 2) {
|
|
152
|
-
|
|
152
|
+
const code = res_buf.readUInt8(1);
|
|
153
153
|
if (code === 0x00 || code === 0x80) {
|
|
154
154
|
const is_on = code === 0x80;
|
|
155
155
|
resolve(is_on);
|
package/lib/switchbot-device.js
CHANGED
|
@@ -26,7 +26,7 @@ class SwitchbotDevice {
|
|
|
26
26
|
this._COMMAND_TIMEOUT_MSEC = 3000;
|
|
27
27
|
|
|
28
28
|
// Save the device information
|
|
29
|
-
|
|
29
|
+
const ad = switchbotAdvertising.parse(peripheral);
|
|
30
30
|
this._id = ad.id;
|
|
31
31
|
this._address = ad.address;
|
|
32
32
|
this._model = ad.serviceData.model;
|
|
@@ -105,7 +105,7 @@ class SwitchbotDevice {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
// Check the connection state
|
|
108
|
-
|
|
108
|
+
const state = this.connectionState;
|
|
109
109
|
if (state === "connected") {
|
|
110
110
|
resolve();
|
|
111
111
|
return;
|
|
@@ -155,7 +155,7 @@ class SwitchbotDevice {
|
|
|
155
155
|
_getCharacteristics() {
|
|
156
156
|
return new Promise((resolve, reject) => {
|
|
157
157
|
// Set timeout timer
|
|
158
|
-
|
|
158
|
+
const timer = setTimeout(() => {
|
|
159
159
|
this._ondisconnect_internal = () => {};
|
|
160
160
|
timer = null;
|
|
161
161
|
reject(
|
|
@@ -179,20 +179,20 @@ class SwitchbotDevice {
|
|
|
179
179
|
|
|
180
180
|
// Discover services and characteristics
|
|
181
181
|
(async () => {
|
|
182
|
-
|
|
182
|
+
const service_list = await this._discoverServices();
|
|
183
183
|
if (!timer) {
|
|
184
184
|
throw new Error("");
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
|
|
187
|
+
const chars = {
|
|
188
188
|
write: null,
|
|
189
189
|
notify: null,
|
|
190
190
|
device: null,
|
|
191
191
|
};
|
|
192
192
|
|
|
193
|
-
for (
|
|
194
|
-
|
|
195
|
-
for (
|
|
193
|
+
for (const service of service_list) {
|
|
194
|
+
const char_list = await this._discoverCharacteristics(service);
|
|
195
|
+
for (const char of char_list) {
|
|
196
196
|
if (char.uuid === this._CHAR_UUID_WRITE) {
|
|
197
197
|
chars.write = char;
|
|
198
198
|
} else if (char.uuid === this._CHAR_UUID_NOTIFY) {
|
|
@@ -230,8 +230,8 @@ class SwitchbotDevice {
|
|
|
230
230
|
return;
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
-
|
|
234
|
-
for (
|
|
233
|
+
const service = null;
|
|
234
|
+
for (const s of service_list) {
|
|
235
235
|
if (s.uuid === this._SERV_UUID_PRIMARY) {
|
|
236
236
|
service = s;
|
|
237
237
|
break;
|
|
@@ -260,7 +260,7 @@ class SwitchbotDevice {
|
|
|
260
260
|
|
|
261
261
|
_subscribe() {
|
|
262
262
|
return new Promise((resolve, reject) => {
|
|
263
|
-
|
|
263
|
+
const char = this._chars.notify;
|
|
264
264
|
if (!char) {
|
|
265
265
|
reject(new Error("No notify characteristic was found."));
|
|
266
266
|
return;
|
|
@@ -280,7 +280,7 @@ class SwitchbotDevice {
|
|
|
280
280
|
|
|
281
281
|
_unsubscribe() {
|
|
282
282
|
return new Promise((resolve) => {
|
|
283
|
-
|
|
283
|
+
const char = this._chars.notify;
|
|
284
284
|
if (!char) {
|
|
285
285
|
resolve();
|
|
286
286
|
return;
|
|
@@ -307,7 +307,7 @@ class SwitchbotDevice {
|
|
|
307
307
|
return new Promise((resolve, reject) => {
|
|
308
308
|
this._was_connected_explicitly = false;
|
|
309
309
|
// Check the connection state
|
|
310
|
-
|
|
310
|
+
const state = this._peripheral.state;
|
|
311
311
|
if (state === "disconnected") {
|
|
312
312
|
resolve();
|
|
313
313
|
return;
|
|
@@ -351,7 +351,7 @@ class SwitchbotDevice {
|
|
|
351
351
|
* ---------------------------------------------------------------- */
|
|
352
352
|
getDeviceName() {
|
|
353
353
|
return new Promise((resolve, reject) => {
|
|
354
|
-
|
|
354
|
+
const name = "";
|
|
355
355
|
this._connect()
|
|
356
356
|
.then(() => {
|
|
357
357
|
if (!this._chars.device) {
|
|
@@ -392,7 +392,7 @@ class SwitchbotDevice {
|
|
|
392
392
|
setDeviceName(name) {
|
|
393
393
|
return new Promise((resolve, reject) => {
|
|
394
394
|
// Check the parameters
|
|
395
|
-
|
|
395
|
+
const valid = parameterChecker.check(
|
|
396
396
|
{ name: name },
|
|
397
397
|
{
|
|
398
398
|
name: { required: true, type: "string", minBytes: 1, maxBytes: 100 },
|
|
@@ -404,7 +404,7 @@ class SwitchbotDevice {
|
|
|
404
404
|
return;
|
|
405
405
|
}
|
|
406
406
|
|
|
407
|
-
|
|
407
|
+
const buf = Buffer.from(name, "utf8");
|
|
408
408
|
this._connect()
|
|
409
409
|
.then(() => {
|
|
410
410
|
if (!this._chars.device) {
|
|
@@ -439,7 +439,7 @@ class SwitchbotDevice {
|
|
|
439
439
|
return;
|
|
440
440
|
}
|
|
441
441
|
|
|
442
|
-
|
|
442
|
+
const res_buf = null;
|
|
443
443
|
|
|
444
444
|
this._connect()
|
|
445
445
|
.then(() => {
|
|
@@ -463,7 +463,7 @@ class SwitchbotDevice {
|
|
|
463
463
|
|
|
464
464
|
_waitCommandResponse() {
|
|
465
465
|
return new Promise((resolve, reject) => {
|
|
466
|
-
|
|
466
|
+
const timer = setTimeout(() => {
|
|
467
467
|
timer = null;
|
|
468
468
|
this._onnotify_internal = () => {};
|
|
469
469
|
reject(new Error("COMMAND_TIMEOUT"));
|
|
@@ -484,7 +484,7 @@ class SwitchbotDevice {
|
|
|
484
484
|
_read(char) {
|
|
485
485
|
return new Promise((resolve, reject) => {
|
|
486
486
|
// Set a timeout timer
|
|
487
|
-
|
|
487
|
+
const timer = setTimeout(() => {
|
|
488
488
|
reject("READ_TIMEOUT");
|
|
489
489
|
}, this._READ_TIMEOUT_MSEC);
|
|
490
490
|
|
|
@@ -507,7 +507,7 @@ class SwitchbotDevice {
|
|
|
507
507
|
_write(char, buf) {
|
|
508
508
|
return new Promise((resolve, reject) => {
|
|
509
509
|
// Set a timeout timer
|
|
510
|
-
|
|
510
|
+
const timer = setTimeout(() => {
|
|
511
511
|
reject("WRITE_TIMEOUT");
|
|
512
512
|
}, this._WRITE_TIMEOUT_MSEC);
|
|
513
513
|
|
package/lib/switchbot.js
CHANGED
|
@@ -26,7 +26,7 @@ class Switchbot {
|
|
|
26
26
|
* ---------------------------------------------------------------- */
|
|
27
27
|
constructor(params) {
|
|
28
28
|
// Check parameters
|
|
29
|
-
|
|
29
|
+
const noble = null;
|
|
30
30
|
if (params && params.noble) {
|
|
31
31
|
noble = params.noble;
|
|
32
32
|
} else {
|
|
@@ -83,9 +83,9 @@ class Switchbot {
|
|
|
83
83
|
* `SwitchbotDevice` objects representing the found devices.
|
|
84
84
|
* ---------------------------------------------------------------- */
|
|
85
85
|
discover(params = {}) {
|
|
86
|
-
|
|
86
|
+
const promise = new Promise((resolve, reject) => {
|
|
87
87
|
// Check the parameters
|
|
88
|
-
|
|
88
|
+
const valid = parameterChecker.check(
|
|
89
89
|
params,
|
|
90
90
|
{
|
|
91
91
|
duration: { required: false, type: "integer", min: 1, max: 60000 },
|
|
@@ -110,7 +110,7 @@ class Switchbot {
|
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
// Determine the values of the parameters
|
|
113
|
-
|
|
113
|
+
const p = {
|
|
114
114
|
duration: params.duration || this._DEFAULT_DISCOVERY_DURATION,
|
|
115
115
|
model: params.model || "",
|
|
116
116
|
id: params.id || "",
|
|
@@ -120,16 +120,16 @@ class Switchbot {
|
|
|
120
120
|
// Initialize the noble object
|
|
121
121
|
this._init()
|
|
122
122
|
.then(() => {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
123
|
+
const peripherals = {};
|
|
124
|
+
const timer = null;
|
|
125
|
+
const finishDiscovery = () => {
|
|
126
126
|
if (timer) {
|
|
127
127
|
clearTimeout(timer);
|
|
128
128
|
}
|
|
129
129
|
this.noble.removeAllListeners("discover");
|
|
130
130
|
this.noble.stopScanning();
|
|
131
|
-
|
|
132
|
-
for (
|
|
131
|
+
const device_list = [];
|
|
132
|
+
for (const addr in peripherals) {
|
|
133
133
|
device_list.push(peripherals[addr]);
|
|
134
134
|
}
|
|
135
135
|
resolve(device_list);
|
|
@@ -137,11 +137,11 @@ class Switchbot {
|
|
|
137
137
|
|
|
138
138
|
// Set a handler for the 'discover' event
|
|
139
139
|
this.noble.on("discover", (peripheral) => {
|
|
140
|
-
|
|
140
|
+
const device = this._getDeviceObject(peripheral, p.id, p.model);
|
|
141
141
|
if (!device) {
|
|
142
142
|
return;
|
|
143
143
|
}
|
|
144
|
-
|
|
144
|
+
const id = device.id;
|
|
145
145
|
peripherals[id] = device;
|
|
146
146
|
|
|
147
147
|
if (this.ondiscover && typeof this.ondiscover === "function") {
|
|
@@ -177,13 +177,13 @@ class Switchbot {
|
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
_init() {
|
|
180
|
-
|
|
180
|
+
const promise = new Promise((resolve, reject) => {
|
|
181
181
|
switch (this.noble.state) {
|
|
182
182
|
case "poweredOn":
|
|
183
183
|
resolve();
|
|
184
184
|
return;
|
|
185
185
|
case ("unsupported", "unauthorized", "poweredOff"):
|
|
186
|
-
|
|
186
|
+
const err = new Error(
|
|
187
187
|
"Failed to initialize the Noble object: " + this.noble.state
|
|
188
188
|
);
|
|
189
189
|
reject(err);
|
|
@@ -193,7 +193,7 @@ class Switchbot {
|
|
|
193
193
|
if (state === "poweredOn") {
|
|
194
194
|
resolve();
|
|
195
195
|
} else {
|
|
196
|
-
|
|
196
|
+
const err = new Error(
|
|
197
197
|
"Failed to initialize the Noble object: " + state
|
|
198
198
|
);
|
|
199
199
|
reject(err);
|
|
@@ -205,9 +205,9 @@ class Switchbot {
|
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
_getDeviceObject(peripheral, id, model) {
|
|
208
|
-
|
|
208
|
+
const ad = switchbotAdvertising.parse(peripheral, this.onlog);
|
|
209
209
|
if (this._filterAdvertising(ad, id, model)) {
|
|
210
|
-
|
|
210
|
+
const device = null;
|
|
211
211
|
switch (ad.serviceData.model) {
|
|
212
212
|
case "H":
|
|
213
213
|
device = new SwitchbotDeviceWoHand(peripheral, this.noble);
|
|
@@ -258,7 +258,7 @@ class Switchbot {
|
|
|
258
258
|
}
|
|
259
259
|
if (id) {
|
|
260
260
|
id = id.toLowerCase().replace(/\:/g, "");
|
|
261
|
-
|
|
261
|
+
const ad_id = ad.address.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
262
262
|
if (ad_id !== id) {
|
|
263
263
|
return false;
|
|
264
264
|
}
|
|
@@ -324,9 +324,9 @@ class Switchbot {
|
|
|
324
324
|
* Nothing will be passed to the `resolve()`.
|
|
325
325
|
* ---------------------------------------------------------------- */
|
|
326
326
|
startScan(params) {
|
|
327
|
-
|
|
327
|
+
const promise = new Promise((resolve, reject) => {
|
|
328
328
|
// Check the parameters
|
|
329
|
-
|
|
329
|
+
const valid = parameterChecker.check(
|
|
330
330
|
params,
|
|
331
331
|
{
|
|
332
332
|
model: {
|
|
@@ -352,14 +352,14 @@ class Switchbot {
|
|
|
352
352
|
this._init()
|
|
353
353
|
.then(() => {
|
|
354
354
|
// Determine the values of the parameters
|
|
355
|
-
|
|
355
|
+
const p = {
|
|
356
356
|
model: params.model || "",
|
|
357
357
|
id: params.id || "",
|
|
358
358
|
};
|
|
359
359
|
|
|
360
360
|
// Set a handler for the 'discover' event
|
|
361
361
|
this.noble.on("discover", (peripheral) => {
|
|
362
|
-
|
|
362
|
+
const ad = switchbotAdvertising.parse(peripheral, this.onlog);
|
|
363
363
|
if (this._filterAdvertising(ad, p.id, p.model)) {
|
|
364
364
|
if (
|
|
365
365
|
this.onadvertisement &&
|
|
@@ -419,7 +419,7 @@ class Switchbot {
|
|
|
419
419
|
wait(msec) {
|
|
420
420
|
return new Promise((resolve, reject) => {
|
|
421
421
|
// Check the parameters
|
|
422
|
-
|
|
422
|
+
const valid = parameterChecker.check(
|
|
423
423
|
{ msec: msec },
|
|
424
424
|
{
|
|
425
425
|
msec: { required: true, type: "integer", min: 0 },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-switchbot",
|
|
3
|
-
"version": "1.6.0-beta.
|
|
3
|
+
"version": "1.6.0-beta.13",
|
|
4
4
|
"description": "The node-switchbot is a Node.js module which allows you to control your Switchbot Devices through Bluetooth (BLE).",
|
|
5
5
|
"main": "./lib/switchbot.js",
|
|
6
6
|
"files": [
|