node-switchbot 1.0.7

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.
@@ -0,0 +1,255 @@
1
+ /* ------------------------------------------------------------------
2
+ * node-linking - switchbot-advertising.js
3
+ *
4
+ * Copyright (c) 2019, Futomi Hatano, All rights reserved.
5
+ * Released under the MIT license
6
+ * Date: 2020-02-11
7
+ * ---------------------------------------------------------------- */
8
+ 'use strict';
9
+
10
+ class SwitchbotAdvertising {
11
+ constructor() { }
12
+
13
+ /* ------------------------------------------------------------------
14
+ * parse(peripheral)
15
+ * - Parse advertising packets coming from switchbot devices
16
+ *
17
+ * [Arguments]
18
+ * - peripheral | Object | Required | A `Peripheral` object of noble
19
+ *
20
+ * [Returen value]
21
+ * - An object as follows:
22
+ *
23
+ * WoHand
24
+ * {
25
+ * id: 'c12e453e2008',
26
+ * address: 'c1:2e:45:3e:20:08',
27
+ * rssi: -43,
28
+ * serviceData: {
29
+ * model: 'H',
30
+ * modelName: 'WoHand',
31
+ * mode: false,
32
+ * state: false,
33
+ * battery: 95
34
+ * }
35
+ * }
36
+ *
37
+ * WoSensorTH
38
+ * {
39
+ * id: 'cb4eb903c96d',
40
+ * address: 'cb:4e:b9:03:c9:6d',
41
+ * rssi: -54,
42
+ * serviceData: {
43
+ * model: 'T',
44
+ * modelName: 'WoSensorTH',
45
+ * temperature: { c: 26.2, f: 79.2 },
46
+ * fahrenheit: false,
47
+ * humidity: 45,
48
+ * battery: 100
49
+ * }
50
+ * }
51
+ *
52
+ * WoCurtain
53
+ * {
54
+ * id: 'ec58c5d00111',
55
+ * address: 'ec:58:c5:d0:01:11',
56
+ * rssi: -39,
57
+ * serviceData: {
58
+ * model: 'c',
59
+ * modelName: 'WoCurtain',
60
+ * calibration: true,
61
+ * battery: 91,
62
+ * position: 1,
63
+ * lightLevel: 1
64
+ * }
65
+ * }
66
+ *
67
+ * If the specified `Peripheral` does not represent any switchbot
68
+ * device, this method will return `null`.
69
+ * ---------------------------------------------------------------- */
70
+ parse(peripheral) {
71
+ let ad = peripheral.advertisement;
72
+ if (!ad || !ad.serviceData) {
73
+ return null;
74
+ }
75
+ if (ad.serviceData[0].uuid !== '0d00') {
76
+ return null;
77
+ }
78
+ let buf = ad.serviceData[0].data;
79
+ if (!buf || !Buffer.isBuffer(buf) || buf.length < 3) {
80
+ return null;
81
+ }
82
+
83
+ let model = buf.slice(0, 1).toString('utf8');
84
+ let sd = null;
85
+
86
+ if (model === 'H') { // WoHand
87
+ sd = this._parseServiceDataForWoHand(buf);
88
+ } else if (model === 'h') { // WoHumi
89
+ sd = this._parseServiceDataForWoHumi(buf);
90
+ } else if (model === 'T') { // WoSensorTH
91
+ sd = this._parseServiceDataForWoSensorTH(buf);
92
+ } else if (model === 'c') { // WoCurtain
93
+ sd = this._parseServiceDataForWoCurtain(buf);
94
+ } else if (model === 'P') { // WoPresence
95
+ sd = this._parseServiceDataForWoPresence(buf);
96
+ } else if (model === 'C') { // WoContact
97
+ sd = this._parseServiceDataForWoContact(buf);
98
+ } else {
99
+ return null;
100
+ }
101
+
102
+ if (!sd) {
103
+ return null;
104
+ }
105
+ let address = peripheral.address || '';
106
+ if (address === '') {
107
+ address = peripheral.advertisement.manufacturerData || '';
108
+ if (address !== '') {
109
+ const str = peripheral.advertisement.manufacturerData.toString('hex').slice(4);
110
+ address = str.substr(0, 2);
111
+ for (var i = 2; i < str.length; i += 2) {
112
+ address = address + ":" + str.substr(i, 2);
113
+ }
114
+ // console.log("address", typeof(address), address);
115
+ }
116
+ }
117
+ else {
118
+ address = address.replace(/-/g, ':');
119
+ }
120
+ let data = {
121
+ id: peripheral.id,
122
+ address: address,
123
+ rssi: peripheral.rssi,
124
+ serviceData: sd
125
+ };
126
+ return data;
127
+ }
128
+
129
+ _parseServiceDataForWoHand(buf) {
130
+ if (buf.length !== 3) {
131
+ return null;
132
+ }
133
+ let byte1 = buf.readUInt8(1);
134
+ let byte2 = buf.readUInt8(2);
135
+
136
+ let mode = (byte1 & 0b10000000) ? true : false; // Whether the light switch Add-on is used or not
137
+ let state = (byte1 & 0b01000000) ? true : false; // Whether the switch status is ON or OFF
138
+ let battery = byte2 & 0b01111111; // %
139
+
140
+ let data = {
141
+ model: 'H',
142
+ modelName: 'WoHand',
143
+ mode: mode,
144
+ state: state,
145
+ battery: battery
146
+ };
147
+
148
+ return data;
149
+ }
150
+
151
+ _parseServiceDataForWoHumi(buf) {
152
+ if (buf.length !== 3) {
153
+ return null;
154
+ }
155
+ let byte1 = buf.readUInt8(1);
156
+ let byte2 = buf.readUInt8(2);
157
+
158
+ let mode = (byte1 & 0b10000000) ? true : false; // Whether the light switch Add-on is used or not
159
+ let state = (byte1 & 0b01000000) ? true : false; // Whether the switch status is ON or OFF
160
+
161
+ let data = {
162
+ model: 'h',
163
+ modelName: 'WoHumi',
164
+ mode: mode,
165
+ state: state
166
+ };
167
+
168
+ return data;
169
+ }
170
+
171
+ _parseServiceDataForWoSensorTH(buf) {
172
+ if (buf.length !== 6) {
173
+ return null;
174
+ }
175
+ let byte2 = buf.readUInt8(2);
176
+ let byte3 = buf.readUInt8(3);
177
+ let byte4 = buf.readUInt8(4);
178
+ let byte5 = buf.readUInt8(5);
179
+
180
+ let temp_sign = (byte4 & 0b10000000) ? 1 : -1;
181
+ let temp_c = temp_sign * ((byte4 & 0b01111111) + (byte3 / 10));
182
+ let temp_f = (temp_c * 9 / 5) + 32;
183
+ temp_f = Math.round(temp_f * 10) / 10;
184
+
185
+ let data = {
186
+ model: 'T',
187
+ modelName: 'WoSensorTH',
188
+ temperature: {
189
+ c: temp_c,
190
+ f: temp_f
191
+ },
192
+ fahrenheit: (byte5 & 0b10000000) ? true : false,
193
+ humidity: byte5 & 0b01111111,
194
+ battery: (byte2 & 0b01111111)
195
+ };
196
+
197
+ return data;
198
+ }
199
+
200
+ _parseServiceDataForWoPresence(buf) {
201
+ if (buf.length !== 6) {
202
+ return null;
203
+ }
204
+
205
+ let data = {
206
+ model: 'P',
207
+ modelName: 'WoPresence',
208
+ battery: (byte2 & 0b01111111)
209
+ };
210
+
211
+ return data;
212
+ }
213
+
214
+ _parseServiceDataForWoContact(buf) {
215
+ if (buf.length !== 6) {
216
+ return null;
217
+ }
218
+
219
+ let data = {
220
+ model: 'C',
221
+ modelName: 'WoContact',
222
+ battery: (byte2 & 0b01111111)
223
+ };
224
+
225
+ return data;
226
+ }
227
+
228
+ _parseServiceDataForWoCurtain(buf) {
229
+ if (buf.length !== 5) {
230
+ return null;
231
+ }
232
+ let byte1 = buf.readUInt8(1);
233
+ let byte2 = buf.readUInt8(2);
234
+ let byte3 = buf.readUInt8(3);
235
+ let byte4 = buf.readUInt8(4);
236
+
237
+ let calibration = byte1 & 0b01000000; // Whether the calibration is completed
238
+ let battery = byte2 & 0b01111111; // %
239
+ let currPosition = byte3 & 0b01111111; // current positon %
240
+ let lightLevel = (byte4 >> 4) & 0b00001111; // light sensor level (1-10)
241
+
242
+ let data = {
243
+ model: 'c',
244
+ modelName: 'WoCurtain',
245
+ calibration: calibration ? true : false,
246
+ battery: battery,
247
+ position: currPosition,
248
+ lightLevel: lightLevel
249
+ };
250
+
251
+ return data;
252
+ }
253
+ }
254
+
255
+ module.exports = new SwitchbotAdvertising();
@@ -0,0 +1,16 @@
1
+ /* ------------------------------------------------------------------
2
+ * node-linking - switchbot-device-wocontact.js
3
+ *
4
+ * Copyright (c) 2019, Futomi Hatano, All rights reserved.
5
+ * Released under the MIT license
6
+ * Date: 2019-11-16
7
+ * ---------------------------------------------------------------- */
8
+ 'use strict';
9
+ const SwitchbotDevice = require('./switchbot-device.js');
10
+
11
+ class SwitchbotDeviceWoContact extends SwitchbotDevice {
12
+
13
+
14
+ }
15
+
16
+ module.exports = SwitchbotDeviceWoContact;
@@ -0,0 +1,109 @@
1
+ /* ------------------------------------------------------------------
2
+ * node-linking - switchbot-device-wocurtain.js
3
+ *
4
+ * Copyright (c) 2020, SwitchBot, All rights reserved.
5
+ * Released under the MIT license
6
+ * Date: 2020-10-26
7
+ * ---------------------------------------------------------------- */
8
+ 'use strict';
9
+ const SwitchbotDevice = require('./switchbot-device.js');
10
+
11
+ class SwitchbotDeviceWoCurtain extends SwitchbotDevice {
12
+
13
+ /* ------------------------------------------------------------------
14
+ * open()
15
+ * - Open the curtain
16
+ *
17
+ * [Arguments]
18
+ * - none
19
+ *
20
+ * [Returen value]
21
+ * - Promise object
22
+ * Nothing will be passed to the `resolve()`.
23
+ * ---------------------------------------------------------------- */
24
+ open() {
25
+ return this._operateCurtain([0x57, 0x0f, 0x45, 0x01, 0x05, 0xff, 0x00]);
26
+ }
27
+
28
+ /* ------------------------------------------------------------------
29
+ * close()
30
+ * - close the curtain
31
+ *
32
+ * [Arguments]
33
+ * - none
34
+ *
35
+ * [Returen value]
36
+ * - Promise object
37
+ * Nothing will be passed to the `resolve()`.
38
+ * ---------------------------------------------------------------- */
39
+ close() {
40
+ return this._operateCurtain([0x57, 0x0f, 0x45, 0x01, 0x05, 0xff, 0x64]);
41
+ }
42
+
43
+ /* ------------------------------------------------------------------
44
+ * pause()
45
+ * - pause the curtain
46
+ *
47
+ * [Arguments]
48
+ * - none
49
+ *
50
+ * [Returen value]
51
+ * - Promise object
52
+ * Nothing will be passed to the `resolve()`.
53
+ * ---------------------------------------------------------------- */
54
+ pause() {
55
+ return this._operateCurtain([0x57, 0x0f, 0x45, 0x01, 0x00, 0xff]);
56
+ }
57
+
58
+ /* ------------------------------------------------------------------
59
+ * runToPos()
60
+ * - run to the targe position
61
+ *
62
+ * [Arguments]
63
+ * - percent | number | Required | the percentage of target position
64
+ *
65
+ * [Returen value]
66
+ * - Promise object
67
+ * Nothing will be passed to the `resolve()`.
68
+ * ---------------------------------------------------------------- */
69
+ runToPos(percent, mode) {
70
+
71
+ if (typeof percent != 'number') {
72
+ return new Promise((resolve, reject) => {
73
+ reject(new Error('The type of target position percentage is incorrent: ' + typeof percent));
74
+ });
75
+ }
76
+ if (mode == null) {
77
+ mode = 0xff;
78
+ }
79
+ else {
80
+ if (typeof mode != 'number') {
81
+ return new Promise((resolve, reject) => {
82
+ reject(new Error('The type of running mode is incorrent: ' + typeof mode));
83
+ });
84
+ }
85
+ if (mode > 1) { mode = 0xff; }
86
+ }
87
+ if (percent > 100) { percent = 100; }
88
+ else if (percent < 0) { percent = 0; }
89
+ return this._operateCurtain([0x57, 0x0f, 0x45, 0x01, 0x05, mode, percent]);
90
+ }
91
+
92
+ _operateCurtain(bytes) {
93
+ return new Promise((resolve, reject) => {
94
+ let req_buf = Buffer.from(bytes);
95
+ this._command(req_buf).then((res_buf) => {
96
+ let code = res_buf.readUInt8(0);
97
+ if (res_buf.length === 3 && code === 0x01) {
98
+ resolve();
99
+ } else {
100
+ reject(new Error('The device returned an error: 0x' + res_buf.toString('hex')));
101
+ }
102
+ }).catch((error) => {
103
+ reject(error);
104
+ });
105
+ });
106
+ }
107
+ }
108
+
109
+ module.exports = SwitchbotDeviceWoCurtain;
@@ -0,0 +1,106 @@
1
+ /* ------------------------------------------------------------------
2
+ * node-linking - switchbot-device-wohand.js
3
+ *
4
+ * Copyright (c) 2019-2020, Futomi Hatano, All rights reserved.
5
+ * Released under the MIT license
6
+ * Date: 2020-02-10
7
+ * ---------------------------------------------------------------- */
8
+ 'use strict';
9
+ const SwitchbotDevice = require('./switchbot-device.js');
10
+
11
+ class SwitchbotDeviceWoHand extends SwitchbotDevice {
12
+
13
+ /* ------------------------------------------------------------------
14
+ * press()
15
+ * - Press
16
+ *
17
+ * [Arguments]
18
+ * - none
19
+ *
20
+ * [Returen value]
21
+ * - Promise object
22
+ * Nothing will be passed to the `resolve()`.
23
+ * ---------------------------------------------------------------- */
24
+ press() {
25
+ return this._operateBot([0x57, 0x01, 0x00]);
26
+ }
27
+
28
+ /* ------------------------------------------------------------------
29
+ * turnOn()
30
+ * - Turn on
31
+ *
32
+ * [Arguments]
33
+ * - none
34
+ *
35
+ * [Returen value]
36
+ * - Promise object
37
+ * Nothing will be passed to the `resolve()`.
38
+ * ---------------------------------------------------------------- */
39
+ turnOn() {
40
+ return this._operateBot([0x57, 0x01, 0x01]);
41
+ }
42
+
43
+ /* ------------------------------------------------------------------
44
+ * turnOff()
45
+ * - Turn off
46
+ *
47
+ * [Arguments]
48
+ * - none
49
+ *
50
+ * [Returen value]
51
+ * - Promise object
52
+ * Nothing will be passed to the `resolve()`.
53
+ * ---------------------------------------------------------------- */
54
+ turnOff() {
55
+ return this._operateBot([0x57, 0x01, 0x02]);
56
+ }
57
+
58
+ /* ------------------------------------------------------------------
59
+ * down()
60
+ * - Down
61
+ *
62
+ * [Arguments]
63
+ * - none
64
+ *
65
+ * [Returen value]
66
+ * - Promise object
67
+ * Nothing will be passed to the `resolve()`.
68
+ * ---------------------------------------------------------------- */
69
+ down() {
70
+ return this._operateBot([0x57, 0x01, 0x03]);
71
+ }
72
+
73
+ /* ------------------------------------------------------------------
74
+ * up()
75
+ * - Up
76
+ *
77
+ * [Arguments]
78
+ * - none
79
+ *
80
+ * [Returen value]
81
+ * - Promise object
82
+ * Nothing will be passed to the `resolve()`.
83
+ * ---------------------------------------------------------------- */
84
+ up() {
85
+ return this._operateBot([0x57, 0x01, 0x04]);
86
+ }
87
+
88
+ _operateBot(bytes) {
89
+ return new Promise((resolve, reject) => {
90
+ let req_buf = Buffer.from(bytes);
91
+ this._command(req_buf).then((res_buf) => {
92
+ let code = res_buf.readUInt8(0);
93
+ if (res_buf.length === 3 && (code === 0x01 || code === 0x05)) {
94
+ resolve();
95
+ } else {
96
+ reject(new Error('The device returned an error: 0x' + res_buf.toString('hex')));
97
+ }
98
+ }).catch((error) => {
99
+ reject(error);
100
+ });
101
+ });
102
+ }
103
+
104
+ }
105
+
106
+ module.exports = SwitchbotDeviceWoHand;
@@ -0,0 +1,106 @@
1
+ /* ------------------------------------------------------------------
2
+ * node-linking - switchbot-device-wohumi.js
3
+ *
4
+ * Copyright (c) 2019-2020, Futomi Hatano, All rights reserved.
5
+ * Released under the MIT license
6
+ * Date: 2020-02-10
7
+ * ---------------------------------------------------------------- */
8
+ 'use strict';
9
+ const SwitchbotDevice = require('./switchbot-device.js');
10
+
11
+ class SwitchbotDeviceWoHumi extends SwitchbotDevice {
12
+
13
+ /* ------------------------------------------------------------------
14
+ * press()
15
+ * - Press
16
+ *
17
+ * [Arguments]
18
+ * - none
19
+ *
20
+ * [Returen value]
21
+ * - Promise object
22
+ * Nothing will be passed to the `resolve()`.
23
+ * ---------------------------------------------------------------- */
24
+ press() {
25
+ return this._operateBot([0x57, 0x01, 0x00]);
26
+ }
27
+
28
+ /* ------------------------------------------------------------------
29
+ * turnOn()
30
+ * - Turn on
31
+ *
32
+ * [Arguments]
33
+ * - none
34
+ *
35
+ * [Returen value]
36
+ * - Promise object
37
+ * Nothing will be passed to the `resolve()`.
38
+ * ---------------------------------------------------------------- */
39
+ turnOn() {
40
+ return this._operateBot([0x57, 0x01, 0x01]);
41
+ }
42
+
43
+ /* ------------------------------------------------------------------
44
+ * turnOff()
45
+ * - Turn off
46
+ *
47
+ * [Arguments]
48
+ * - none
49
+ *
50
+ * [Returen value]
51
+ * - Promise object
52
+ * Nothing will be passed to the `resolve()`.
53
+ * ---------------------------------------------------------------- */
54
+ turnOff() {
55
+ return this._operateBot([0x57, 0x01, 0x02]);
56
+ }
57
+
58
+ /* ------------------------------------------------------------------
59
+ * down()
60
+ * - Down
61
+ *
62
+ * [Arguments]
63
+ * - none
64
+ *
65
+ * [Returen value]
66
+ * - Promise object
67
+ * Nothing will be passed to the `resolve()`.
68
+ * ---------------------------------------------------------------- */
69
+ down() {
70
+ return this._operateBot([0x57, 0x01, 0x03]);
71
+ }
72
+
73
+ /* ------------------------------------------------------------------
74
+ * up()
75
+ * - Up
76
+ *
77
+ * [Arguments]
78
+ * - none
79
+ *
80
+ * [Returen value]
81
+ * - Promise object
82
+ * Nothing will be passed to the `resolve()`.
83
+ * ---------------------------------------------------------------- */
84
+ up() {
85
+ return this._operateBot([0x57, 0x01, 0x04]);
86
+ }
87
+
88
+ _operateBot(bytes) {
89
+ return new Promise((resolve, reject) => {
90
+ let req_buf = Buffer.from(bytes);
91
+ this._command(req_buf).then((res_buf) => {
92
+ let code = res_buf.readUInt8(0);
93
+ if (res_buf.length === 3 && (code === 0x01 || code === 0x05)) {
94
+ resolve();
95
+ } else {
96
+ reject(new Error('The device returned an error: 0x' + res_buf.toString('hex')));
97
+ }
98
+ }).catch((error) => {
99
+ reject(error);
100
+ });
101
+ });
102
+ }
103
+
104
+ }
105
+
106
+ module.exports = SwitchbotDeviceWoHumi;
@@ -0,0 +1,16 @@
1
+ /* ------------------------------------------------------------------
2
+ * node-linking - switchbot-device-wopresence.js
3
+ *
4
+ * Copyright (c) 2019, Futomi Hatano, All rights reserved.
5
+ * Released under the MIT license
6
+ * Date: 2019-11-16
7
+ * ---------------------------------------------------------------- */
8
+ 'use strict';
9
+ const SwitchbotDevice = require('./switchbot-device.js');
10
+
11
+ class SwitchbotDeviceWoPresence extends SwitchbotDevice {
12
+
13
+
14
+ }
15
+
16
+ module.exports = SwitchbotDeviceWoPresence;
@@ -0,0 +1,16 @@
1
+ /* ------------------------------------------------------------------
2
+ * node-linking - switchbot-device-wosensorth.js
3
+ *
4
+ * Copyright (c) 2019, Futomi Hatano, All rights reserved.
5
+ * Released under the MIT license
6
+ * Date: 2019-11-16
7
+ * ---------------------------------------------------------------- */
8
+ 'use strict';
9
+ const SwitchbotDevice = require('./switchbot-device.js');
10
+
11
+ class SwitchbotDeviceWoSensorTH extends SwitchbotDevice {
12
+
13
+
14
+ }
15
+
16
+ module.exports = SwitchbotDeviceWoSensorTH;