node-switchbot 1.10.0 → 2.0.0-beta.1

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 (93) hide show
  1. package/.gitattributes +2 -0
  2. package/.github/dependabot.yml +17 -0
  3. package/.github/labeler.yml +38 -0
  4. package/.github/npm-version-script.cjs +81 -0
  5. package/.github/workflows/beta-release.yml +31 -0
  6. package/.github/workflows/build.yml +18 -0
  7. package/.github/workflows/changerelease.yml +13 -0
  8. package/.github/workflows/dependabot.yml +17 -0
  9. package/.github/workflows/labeler.yml +16 -0
  10. package/.github/workflows/release-drafter.yml +14 -0
  11. package/.github/workflows/release.yml +24 -0
  12. package/.github/workflows/stale.yml +12 -0
  13. package/CHANGELOG.md +308 -0
  14. package/dist/advertising.d.ts +172 -0
  15. package/dist/advertising.d.ts.map +1 -0
  16. package/dist/advertising.js +620 -0
  17. package/dist/advertising.js.map +1 -0
  18. package/dist/device/woblindtilt.d.ts +9 -0
  19. package/dist/device/woblindtilt.d.ts.map +1 -0
  20. package/dist/device/woblindtilt.js +108 -0
  21. package/dist/device/woblindtilt.js.map +1 -0
  22. package/dist/device/wobulb.d.ts +39 -0
  23. package/dist/device/wobulb.d.ts.map +1 -0
  24. package/dist/device/wobulb.js +156 -0
  25. package/dist/device/wobulb.js.map +1 -0
  26. package/dist/device/wocontact.d.ts +4 -0
  27. package/dist/device/wocontact.d.ts.map +1 -0
  28. package/dist/device/wocontact.js +8 -0
  29. package/dist/device/wocontact.js.map +1 -0
  30. package/dist/device/wocurtain.d.ts +9 -0
  31. package/dist/device/wocurtain.d.ts.map +1 -0
  32. package/dist/device/wocurtain.js +104 -0
  33. package/dist/device/wocurtain.js.map +1 -0
  34. package/dist/device/wohand.d.ts +10 -0
  35. package/dist/device/wohand.d.ts.map +1 -0
  36. package/dist/device/wohand.js +93 -0
  37. package/dist/device/wohand.js.map +1 -0
  38. package/dist/device/wohumi.d.ts +10 -0
  39. package/dist/device/wohumi.d.ts.map +1 -0
  40. package/dist/device/wohumi.js +93 -0
  41. package/dist/device/wohumi.js.map +1 -0
  42. package/dist/device/woiosensorth.d.ts +4 -0
  43. package/dist/device/woiosensorth.d.ts.map +1 -0
  44. package/dist/device/woiosensorth.js +4 -0
  45. package/dist/device/woiosensorth.js.map +1 -0
  46. package/dist/device/woplugmini.d.ts +31 -0
  47. package/dist/device/woplugmini.d.ts.map +1 -0
  48. package/dist/device/woplugmini.js +68 -0
  49. package/dist/device/woplugmini.js.map +1 -0
  50. package/dist/device/wopresence.d.ts +4 -0
  51. package/dist/device/wopresence.d.ts.map +1 -0
  52. package/dist/device/wopresence.js +4 -0
  53. package/dist/device/wopresence.js.map +1 -0
  54. package/dist/device/wosensorth.d.ts +4 -0
  55. package/dist/device/wosensorth.d.ts.map +1 -0
  56. package/dist/device/wosensorth.js +4 -0
  57. package/dist/device/wosensorth.js.map +1 -0
  58. package/dist/device/wostrip.d.ts +39 -0
  59. package/dist/device/wostrip.d.ts.map +1 -0
  60. package/dist/device/wostrip.js +145 -0
  61. package/dist/device/wostrip.js.map +1 -0
  62. package/dist/device.d.ts +46 -0
  63. package/dist/device.d.ts.map +1 -0
  64. package/dist/device.js +498 -0
  65. package/dist/device.js.map +1 -0
  66. package/dist/index.d.ts +2 -0
  67. package/dist/index.d.ts.map +1 -0
  68. package/dist/index.js +6 -0
  69. package/dist/index.js.map +1 -0
  70. package/dist/parameter-checker.d.ts +25 -0
  71. package/dist/parameter-checker.d.ts.map +1 -0
  72. package/dist/parameter-checker.js +488 -0
  73. package/dist/parameter-checker.js.map +1 -0
  74. package/dist/switchbot.d.ts +29 -0
  75. package/dist/switchbot.d.ts.map +1 -0
  76. package/dist/switchbot.js +461 -0
  77. package/dist/switchbot.js.map +1 -0
  78. package/package.json +19 -12
  79. package/lib/parameter-checker.js +0 -524
  80. package/lib/switchbot-advertising.js +0 -713
  81. package/lib/switchbot-device-woblindtilt.js +0 -120
  82. package/lib/switchbot-device-wobulb.js +0 -188
  83. package/lib/switchbot-device-wocontact.js +0 -6
  84. package/lib/switchbot-device-wocurtain.js +0 -117
  85. package/lib/switchbot-device-wohand.js +0 -106
  86. package/lib/switchbot-device-wohumi.js +0 -106
  87. package/lib/switchbot-device-woiosensorth.js +0 -6
  88. package/lib/switchbot-device-woplugmini.js +0 -84
  89. package/lib/switchbot-device-wopresence.js +0 -6
  90. package/lib/switchbot-device-wosensorth.js +0 -6
  91. package/lib/switchbot-device-wostrip.js +0 -182
  92. package/lib/switchbot-device.js +0 -536
  93. package/lib/switchbot.js +0 -496
@@ -1,536 +0,0 @@
1
- "use strict";
2
-
3
- const { Buffer } = require('buffer');
4
-
5
- const parameterChecker = require("./parameter-checker.js");
6
- const switchbotAdvertising = require("./switchbot-advertising.js");
7
-
8
- class SwitchbotDevice {
9
- /* ------------------------------------------------------------------
10
- * Constructor
11
- *
12
- * [Arguments]
13
- * - peripheral | Object | Required | The `peripheral` object of noble,
14
- * | | | which represents this device
15
- * - noble | Noble | Required | The Noble object created by the noble module.
16
- * ---------------------------------------------------------------- */
17
- constructor(peripheral, noble) {
18
- this._peripheral = peripheral;
19
- this._noble = noble;
20
- this._chars = null;
21
-
22
- this._SERV_UUID_PRIMARY = "cba20d00224d11e69fb80002a5d5c51b";
23
- this._CHAR_UUID_WRITE = "cba20002224d11e69fb80002a5d5c51b";
24
- this._CHAR_UUID_NOTIFY = "cba20003224d11e69fb80002a5d5c51b";
25
- this._CHAR_UUID_DEVICE = "2a00";
26
-
27
- this._READ_TIMEOUT_MSEC = 3000;
28
- this._WRITE_TIMEOUT_MSEC = 3000;
29
- this._COMMAND_TIMEOUT_MSEC = 3000;
30
-
31
- // Save the device information
32
- const ad = switchbotAdvertising.parse(peripheral);
33
- this._id = ad.id;
34
- this._address = ad.address;
35
- this._model = ad.serviceData.model;
36
- this._modelName = ad.serviceData.modelName;
37
-
38
- this._was_connected_explicitly = false;
39
- this._connected = false;
40
-
41
- this._onconnect = () => {};
42
- this._ondisconnect = () => {};
43
- this._ondisconnect_internal = () => {};
44
- this._onnotify_internal = () => {};
45
- }
46
-
47
- // Getters
48
- get id() {
49
- return this._id;
50
- }
51
- get address() {
52
- return this._address;
53
- }
54
- get model() {
55
- return this._model;
56
- }
57
- get modelName() {
58
- return this._modelName;
59
- }
60
- get connectionState() {
61
- if (!this._connected && this._peripheral.state === "disconnecting") {
62
- return "disconnected";
63
- } else {
64
- return this._peripheral.state;
65
- }
66
- }
67
-
68
- // Setters
69
- set onconnect(func) {
70
- if (!func || typeof func !== "function") {
71
- throw new Error("The `onconnect` must be a function.");
72
- }
73
- this._onconnect = func;
74
- }
75
- set ondisconnect(func) {
76
- if (!func || typeof func !== "function") {
77
- throw new Error("The `ondisconnect` must be a function.");
78
- }
79
- this._ondisconnect = func;
80
- }
81
-
82
- /* ------------------------------------------------------------------
83
- * connect()
84
- * - Connect the device
85
- *
86
- * [Arguments]
87
- * - none
88
- *
89
- * [Return value]
90
- * - Promise object
91
- * Nothing will be passed to the `resolve()`.
92
- * ---------------------------------------------------------------- */
93
- connect() {
94
- this._was_connected_explicitly = true;
95
- return this._connect();
96
- }
97
-
98
- _connect() {
99
- return new Promise((resolve, reject) => {
100
- // Check the bluetooth state
101
- if (this._noble.state !== "poweredOn") {
102
- reject(
103
- new Error(
104
- "The Bluetooth status is " + this._noble.state + ", not poweredOn."
105
- )
106
- );
107
- return;
108
- }
109
-
110
- // Check the connection state
111
- const state = this.connectionState;
112
- if (state === "connected") {
113
- resolve();
114
- return;
115
- } else if (state === "connecting" || state === "disconnecting") {
116
- reject(
117
- new Error("Now " + state + ". Wait for a few seconds then try again.")
118
- );
119
- return;
120
- }
121
-
122
- // Set event handlers for events fired on the `Peripheral` object
123
- this._peripheral.once("connect", () => {
124
- this._connected = true;
125
- this._onconnect();
126
- });
127
-
128
- this._peripheral.once("disconnect", () => {
129
- this._connected = false;
130
- this._chars = null;
131
- this._peripheral.removeAllListeners();
132
- this._ondisconnect_internal();
133
- this._ondisconnect();
134
- });
135
-
136
- // Connect
137
- this._peripheral.connect((error) => {
138
- if (error) {
139
- reject(error);
140
- return;
141
- }
142
- this._getCharacteristics()
143
- .then((chars) => {
144
- this._chars = chars;
145
- return this._subscribe();
146
- })
147
- .then(() => {
148
- resolve();
149
- })
150
- .catch((error) => {
151
- this._peripheral.disconnect();
152
- reject(error);
153
- });
154
- });
155
- });
156
- }
157
-
158
- _getCharacteristics() {
159
- return new Promise((resolve, reject) => {
160
- // Set timeout timer
161
- let timer = setTimeout(() => {
162
- this._ondisconnect_internal = () => {};
163
- timer = null;
164
- reject(
165
- new Error("Failed to discover services and characteristics: TIMEOUT")
166
- );
167
- }, 5000);
168
-
169
- // Watch the connection state
170
- this._ondisconnect_internal = () => {
171
- if (timer) {
172
- clearTimeout(timer);
173
- timer = null;
174
- this._ondisconnect_internal = () => {};
175
- }
176
- reject(
177
- new Error(
178
- "Failed to discover services and characteristics: DISCONNECTED"
179
- )
180
- );
181
- };
182
-
183
- // Discover services and characteristics
184
- (async () => {
185
- const service_list = await this._discoverServices();
186
- if (!timer) {
187
- throw new Error("");
188
- }
189
-
190
- const chars = {
191
- write: null,
192
- notify: null,
193
- device: null,
194
- };
195
-
196
- for (let service of service_list) {
197
- const char_list = await this._discoverCharacteristics(service);
198
- for (let char of char_list) {
199
- if (char.uuid === this._CHAR_UUID_WRITE) {
200
- chars.write = char;
201
- } else if (char.uuid === this._CHAR_UUID_NOTIFY) {
202
- chars.notify = char;
203
- } else if (char.uuid === this._CHAR_UUID_DEVICE) {
204
- // Some models of Bot don't seem to support this characteristic UUID
205
- chars.device = char;
206
- }
207
- }
208
- }
209
-
210
- if (chars.write && chars.notify) {
211
- resolve(chars);
212
- } else {
213
- reject(new Error("No characteristic was found."));
214
- }
215
- })().catch((error) => {
216
- if (timer) {
217
- clearTimeout(timer);
218
- timer = null;
219
- this._ondisconnect_internal = () => {};
220
- reject(error);
221
- } else {
222
- // Do nothing
223
- }
224
- });
225
- });
226
- }
227
-
228
- _discoverServices() {
229
- return new Promise((resolve, reject) => {
230
- this._peripheral.discoverServices([], (error, service_list) => {
231
- if (error) {
232
- reject(error);
233
- return;
234
- }
235
-
236
- let service = null;
237
- for (let s of service_list) {
238
- if (s.uuid === this._SERV_UUID_PRIMARY) {
239
- service = s;
240
- break;
241
- }
242
- }
243
- if (service) {
244
- resolve(service_list);
245
- } else {
246
- reject(new Error("No service was found."));
247
- }
248
- });
249
- });
250
- }
251
-
252
- _discoverCharacteristics(service) {
253
- return new Promise((resolve, reject) => {
254
- service.discoverCharacteristics([], (error, char_list) => {
255
- if (error) {
256
- reject(error);
257
- } else {
258
- resolve(char_list);
259
- }
260
- });
261
- });
262
- }
263
-
264
- _subscribe() {
265
- return new Promise((resolve, reject) => {
266
- const char = this._chars.notify;
267
- if (!char) {
268
- reject(new Error("No notify characteristic was found."));
269
- return;
270
- }
271
- char.subscribe((error) => {
272
- if (error) {
273
- reject(error);
274
- return;
275
- }
276
- char.on("data", (buf) => {
277
- this._onnotify_internal(buf);
278
- });
279
- resolve();
280
- });
281
- });
282
- }
283
-
284
- _unsubscribe() {
285
- return new Promise((resolve) => {
286
- const char = this._chars.notify;
287
- if (!char) {
288
- resolve();
289
- return;
290
- }
291
- char.removeAllListeners();
292
- char.unsubscribe(() => {
293
- resolve();
294
- });
295
- });
296
- }
297
-
298
- /* ------------------------------------------------------------------
299
- * disconnect()
300
- * - Disconnect the device
301
- *
302
- * [Arguments]
303
- * - none
304
- *
305
- * [Return value]
306
- * - Promise object
307
- * Nothing will be passed to the `resolve()`.
308
- * ---------------------------------------------------------------- */
309
- disconnect() {
310
- return new Promise((resolve, reject) => {
311
- this._was_connected_explicitly = false;
312
- // Check the connection state
313
- const state = this._peripheral.state;
314
- if (state === "disconnected") {
315
- resolve();
316
- return;
317
- } else if (state === "connecting" || state === "disconnecting") {
318
- reject(
319
- new Error("Now " + state + ". Wait for a few seconds then try again.")
320
- );
321
- return;
322
- }
323
-
324
- // Unsubscribe
325
- this._unsubscribe().then(() => {
326
- // Disconnect
327
- this._peripheral.disconnect(() => {
328
- resolve();
329
- });
330
- });
331
- });
332
- }
333
-
334
- _disconnect() {
335
- if (this._was_connected_explicitly) {
336
- return new Promise((resolve) => {
337
- resolve();
338
- });
339
- } else {
340
- return this.disconnect();
341
- }
342
- }
343
-
344
- /* ------------------------------------------------------------------
345
- * getDeviceName()
346
- * - Retrieve the device name
347
- *
348
- * [Arguments]
349
- * - none
350
- *
351
- * [Return value]
352
- * - Promise object
353
- * The device name will be passed to the `resolve()`.
354
- * ---------------------------------------------------------------- */
355
- getDeviceName() {
356
- return new Promise((resolve, reject) => {
357
- let name = "";
358
- this._connect()
359
- .then(() => {
360
- if (!this._chars.device) {
361
- // Some models of Bot don't seem to support this characteristic UUID
362
- throw new Error(
363
- "The device does not support the characteristic UUID 0x" +
364
- this._CHAR_UUID_DEVICE +
365
- "."
366
- );
367
- }
368
- return this._read(this._chars.device);
369
- })
370
- .then((buf) => {
371
- name = buf.toString("utf8");
372
- return this._disconnect();
373
- })
374
- .then(() => {
375
- resolve(name);
376
- })
377
- .catch((error) => {
378
- reject(error);
379
- });
380
- });
381
- }
382
-
383
- /* ------------------------------------------------------------------
384
- * setDeviceName(name)
385
- * - Set the device name
386
- *
387
- * [Arguments]
388
- * - name | String | Required | Device name. The bytes length of the name
389
- * | | | must be in the range of 1 to 20 bytes.
390
- *
391
- * [Return value]
392
- * - Promise object
393
- * Nothing will be passed to the `resolve()`.
394
- * ---------------------------------------------------------------- */
395
- setDeviceName(name) {
396
- return new Promise((resolve, reject) => {
397
- // Check the parameters
398
- const valid = parameterChecker.check(
399
- { name: name },
400
- {
401
- name: { required: true, type: "string", minBytes: 1, maxBytes: 100 },
402
- }
403
- );
404
-
405
- if (!valid) {
406
- reject(new Error(parameterChecker.error.message));
407
- return;
408
- }
409
-
410
- const buf = Buffer.from(name, "utf8");
411
- this._connect()
412
- .then(() => {
413
- if (!this._chars.device) {
414
- // Some models of Bot don't seem to support this characteristic UUID
415
- throw new Error(
416
- "The device does not support the characteristic UUID 0x" +
417
- this._CHAR_UUID_DEVICE +
418
- "."
419
- );
420
- }
421
- return this._write(this._chars.device, buf);
422
- })
423
- .then(() => {
424
- return this._disconnect();
425
- })
426
- .then(() => {
427
- resolve();
428
- })
429
- .catch((error) => {
430
- reject(error);
431
- });
432
- });
433
- }
434
-
435
- // Write the specified Buffer data to the write characteristic
436
- // and receive the response from the notify characteristic
437
- // with connection handling
438
- _command(req_buf) {
439
- return new Promise((resolve, reject) => {
440
- if (!Buffer.isBuffer(req_buf)) {
441
- reject(new Error("The specified data is not acceptable for writing."));
442
- return;
443
- }
444
-
445
- let res_buf = null;
446
-
447
- this._connect()
448
- .then(() => {
449
- if (!this._chars) {
450
- return reject(new Error("No characteristics available."));
451
- }
452
- return this._write(this._chars.write, req_buf);
453
- })
454
- .then(() => {
455
- return this._waitCommandResponse();
456
- })
457
- .then((buf) => {
458
- res_buf = buf;
459
- return this._disconnect();
460
- })
461
- .then(() => {
462
- resolve(res_buf);
463
- })
464
- .catch((error) => {
465
- reject(error);
466
- });
467
- });
468
- }
469
-
470
- _waitCommandResponse() {
471
- return new Promise((resolve, reject) => {
472
- let timer = setTimeout(() => {
473
- timer = null;
474
- this._onnotify_internal = () => {};
475
- reject(new Error("COMMAND_TIMEOUT"));
476
- }, this._COMMAND_TIMEOUT_MSEC);
477
-
478
- this._onnotify_internal = (buf) => {
479
- if (timer) {
480
- clearTimeout(timer);
481
- timer = null;
482
- }
483
- this._onnotify_internal = () => {};
484
- resolve(buf);
485
- };
486
- });
487
- }
488
-
489
- // Read data from the specified characteristic
490
- _read(char) {
491
- return new Promise((resolve, reject) => {
492
- // Set a timeout timer
493
- let timer = setTimeout(() => {
494
- reject("READ_TIMEOUT");
495
- }, this._READ_TIMEOUT_MSEC);
496
-
497
- // Read charcteristic data
498
- char.read((error, buf) => {
499
- if (timer) {
500
- clearTimeout(timer);
501
- timer = null;
502
- }
503
- if (error) {
504
- reject(error);
505
- } else {
506
- resolve(buf);
507
- }
508
- });
509
- });
510
- }
511
-
512
- // Write the specified Buffer data to the specified characteristic
513
- _write(char, buf) {
514
- return new Promise((resolve, reject) => {
515
- // Set a timeout timer
516
- let timer = setTimeout(() => {
517
- reject("WRITE_TIMEOUT");
518
- }, this._WRITE_TIMEOUT_MSEC);
519
-
520
- // write charcteristic data
521
- char.write(buf, false, (error) => {
522
- if (timer) {
523
- clearTimeout(timer);
524
- timer = null;
525
- }
526
- if (error) {
527
- reject(error);
528
- } else {
529
- resolve();
530
- }
531
- });
532
- });
533
- }
534
- }
535
-
536
- module.exports = SwitchbotDevice;