node-switchbot 1.1.3-beta.3 → 1.1.3-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/parameter-checker.js +317 -319
- package/lib/switchbot-advertising.js +190 -192
- package/lib/switchbot-device-wocontact.js +2 -3
- package/lib/switchbot-device-wocurtain.js +51 -52
- package/lib/switchbot-device-wohand.js +37 -38
- package/lib/switchbot-device-wohumi.js +41 -42
- package/lib/switchbot-device-wopresence.js +2 -3
- package/lib/switchbot-device-wosensorth.js +2 -3
- package/lib/switchbot-device.js +437 -438
- package/lib/switchbot.js +237 -238
- package/package.json +9 -2
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
class SwitchbotAdvertising {
|
|
4
|
-
|
|
2
|
+
constructor() { }
|
|
5
3
|
|
|
6
|
-
|
|
4
|
+
/* ------------------------------------------------------------------
|
|
7
5
|
* parse(peripheral)
|
|
8
6
|
* - Parse advertising packets coming from switchbot devices
|
|
9
7
|
*
|
|
@@ -60,222 +58,222 @@ class SwitchbotAdvertising {
|
|
|
60
58
|
* If the specified `Peripheral` does not represent any switchbot
|
|
61
59
|
* device, this method will return `null`.
|
|
62
60
|
* ---------------------------------------------------------------- */
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
61
|
+
parse(peripheral) {
|
|
62
|
+
let ad = peripheral.advertisement;
|
|
63
|
+
if (!ad || !ad.serviceData) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
if (ad.serviceData[0].uuid !== "0d00") {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
let buf = ad.serviceData[0].data;
|
|
70
|
+
if (!buf || !Buffer.isBuffer(buf) || buf.length < 3) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
75
73
|
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
let model = buf.slice(0, 1).toString("utf8");
|
|
75
|
+
let sd = null;
|
|
78
76
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
77
|
+
if (model === "H") { // WoHand
|
|
78
|
+
sd = this._parseServiceDataForWoHand(buf);
|
|
79
|
+
} else if (model === "e") { // WoHumi
|
|
80
|
+
sd = this._parseServiceDataForWoHumi(buf);
|
|
81
|
+
} else if (model === "T") { // WoSensorTH
|
|
82
|
+
sd = this._parseServiceDataForWoSensorTH(buf);
|
|
83
|
+
} else if (model === "c") { // WoCurtain
|
|
84
|
+
sd = this._parseServiceDataForWoCurtain(buf);
|
|
85
|
+
} else if (model === "s") { // WoMotion
|
|
86
|
+
sd = this._parseServiceDataForWoPresence(buf);
|
|
87
|
+
} else if (model === "d") { // WoContact
|
|
88
|
+
sd = this._parseServiceDataForWoContact(buf);
|
|
89
|
+
} else {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
94
92
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
93
|
+
if (!sd) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
let address = peripheral.address || "";
|
|
97
|
+
if (address === "") {
|
|
98
|
+
address = peripheral.advertisement.manufacturerData || "";
|
|
99
|
+
if (address !== "") {
|
|
100
|
+
const str = peripheral.advertisement.manufacturerData.toString("hex").slice(4);
|
|
101
|
+
address = str.substr(0, 2);
|
|
102
|
+
for (var i = 2; i < str.length; i += 2) {
|
|
103
|
+
address = address + ":" + str.substr(i, 2);
|
|
104
|
+
}
|
|
105
|
+
// console.log("address", typeof(address), address);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
address = address.replace(/-/g, ":");
|
|
110
|
+
}
|
|
111
|
+
let data = {
|
|
112
|
+
id: peripheral.id,
|
|
113
|
+
address: address,
|
|
114
|
+
rssi: peripheral.rssi,
|
|
115
|
+
serviceData: sd
|
|
116
|
+
};
|
|
117
|
+
return data;
|
|
118
|
+
}
|
|
121
119
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
120
|
+
_parseServiceDataForWoHand(buf) {
|
|
121
|
+
if (buf.length !== 3) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
let byte1 = buf.readUInt8(1);
|
|
125
|
+
let byte2 = buf.readUInt8(2);
|
|
128
126
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
127
|
+
let mode = (byte1 & 0b10000000) ? true : false; // Whether the light switch Add-on is used or not
|
|
128
|
+
let state = (byte1 & 0b01000000) ? true : false; // Whether the switch status is ON or OFF
|
|
129
|
+
let battery = byte2 & 0b01111111; // %
|
|
132
130
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
131
|
+
let data = {
|
|
132
|
+
model: "H",
|
|
133
|
+
modelName: "WoHand",
|
|
134
|
+
mode: mode,
|
|
135
|
+
state: state,
|
|
136
|
+
battery: battery
|
|
137
|
+
};
|
|
140
138
|
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
return data;
|
|
140
|
+
}
|
|
143
141
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
142
|
+
_parseServiceDataForWoHumi(buf) {
|
|
143
|
+
if (buf.length !== 8) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
let byte1 = buf.readUInt8(1);
|
|
147
|
+
// let byte2 = buf.readUInt8(2);
|
|
148
|
+
let byte3 = buf.readUInt8(3);
|
|
149
|
+
let byte4 = buf.readUInt8(4);
|
|
150
|
+
let byte5 = buf.readUInt8(5);
|
|
153
151
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
152
|
+
let onState = (byte1 & 0b10000000) ? true : false; // 1 - on
|
|
153
|
+
let autoMode = (byte4 & 0b10000000) ? true : false; // 1 - auto
|
|
154
|
+
let percentage = byte4 & 0b01111111; // 0-100%, 101/102/103 - Quick gear 1/2/3
|
|
157
155
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
156
|
+
let data = {
|
|
157
|
+
model: "e",
|
|
158
|
+
modelName: "WoHumi",
|
|
159
|
+
onState: onState,
|
|
160
|
+
autoMode: autoMode,
|
|
161
|
+
percentage: autoMode ? 0 : percentage,
|
|
162
|
+
};
|
|
165
163
|
|
|
166
|
-
|
|
167
|
-
|
|
164
|
+
return data;
|
|
165
|
+
}
|
|
168
166
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
167
|
+
_parseServiceDataForWoSensorTH(buf) {
|
|
168
|
+
if (buf.length !== 6) {
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
let byte2 = buf.readUInt8(2);
|
|
172
|
+
let byte3 = buf.readUInt8(3);
|
|
173
|
+
let byte4 = buf.readUInt8(4);
|
|
174
|
+
let byte5 = buf.readUInt8(5);
|
|
177
175
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
176
|
+
let temp_sign = (byte4 & 0b10000000) ? 1 : -1;
|
|
177
|
+
let temp_c = temp_sign * ((byte4 & 0b01111111) + (byte3 / 10));
|
|
178
|
+
let temp_f = (temp_c * 9 / 5) + 32;
|
|
179
|
+
temp_f = Math.round(temp_f * 10) / 10;
|
|
182
180
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
181
|
+
let data = {
|
|
182
|
+
model: "T",
|
|
183
|
+
modelName: "WoSensorTH",
|
|
184
|
+
temperature: {
|
|
185
|
+
c: temp_c,
|
|
186
|
+
f: temp_f
|
|
187
|
+
},
|
|
188
|
+
fahrenheit: (byte5 & 0b10000000) ? true : false,
|
|
189
|
+
humidity: byte5 & 0b01111111,
|
|
190
|
+
battery: (byte2 & 0b01111111)
|
|
191
|
+
};
|
|
194
192
|
|
|
195
|
-
|
|
196
|
-
|
|
193
|
+
return data;
|
|
194
|
+
}
|
|
197
195
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
196
|
+
_parseServiceDataForWoPresence(buf) {
|
|
197
|
+
if (buf.length !== 6) {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
let byte1 = buf.readUInt8(1);
|
|
201
|
+
let byte2 = buf.readUInt8(2);
|
|
202
|
+
// let byte3 = buf.readUInt8(3);
|
|
203
|
+
// let byte4 = buf.readUInt8(4);
|
|
204
|
+
let byte5 = buf.readUInt8(5);
|
|
207
205
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
206
|
+
let pirState = (byte1 & 0b01000000) ? true : false; // 1 - Movement detected
|
|
207
|
+
let battery = byte2 & 0b01111111; // %
|
|
208
|
+
let lightLevel = byte5 & 0b00000011;
|
|
211
209
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
210
|
+
let data = {
|
|
211
|
+
model: "s",
|
|
212
|
+
modelName: "WoMotion",
|
|
213
|
+
movement: pirState,
|
|
214
|
+
battery: battery,
|
|
215
|
+
lightLevel: (lightLevel == 1) ? "dark" : ((lightLevel == 2) ? "bright" : "unknown"),
|
|
216
|
+
};
|
|
219
217
|
|
|
220
|
-
|
|
221
|
-
|
|
218
|
+
return data;
|
|
219
|
+
}
|
|
222
220
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
221
|
+
_parseServiceDataForWoContact(buf) {
|
|
222
|
+
if (buf.length !== 9) {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
227
225
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
226
|
+
let byte1 = buf.readUInt8(1);
|
|
227
|
+
let byte2 = buf.readUInt8(2);
|
|
228
|
+
let byte3 = buf.readUInt8(3);
|
|
229
|
+
// let byte4 = buf.readUInt8(4);
|
|
230
|
+
// let byte5 = buf.readUInt8(5);
|
|
231
|
+
// let byte6 = buf.readUInt8(6);
|
|
232
|
+
// let byte7 = buf.readUInt8(7);
|
|
233
|
+
// let byte8 = buf.readUInt8(8);
|
|
236
234
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
235
|
+
let pirState = (byte1 & 0b01000000) ? true : false; // 1 - Movement detected
|
|
236
|
+
let battery = byte2 & 0b01111111; // %
|
|
237
|
+
let hallState = (byte3 >> 1) & 0b00000011;
|
|
238
|
+
let lightLevel = byte3 & 0b00000001;
|
|
241
239
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
240
|
+
let data = {
|
|
241
|
+
model: "d",
|
|
242
|
+
modelName: "WoContact",
|
|
243
|
+
movement: pirState,
|
|
244
|
+
battery: battery,
|
|
245
|
+
doorState: (hallState == 0) ? "close" : ((hallState == 1) ? "open" : "timeout no closed"),
|
|
246
|
+
lightLevel: (lightLevel == 0) ? "dark" : "bright",
|
|
247
|
+
};
|
|
250
248
|
|
|
251
|
-
|
|
252
|
-
|
|
249
|
+
return data;
|
|
250
|
+
}
|
|
253
251
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
252
|
+
_parseServiceDataForWoCurtain(buf) {
|
|
253
|
+
if (buf.length !== 5) {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
let byte1 = buf.readUInt8(1);
|
|
257
|
+
let byte2 = buf.readUInt8(2);
|
|
258
|
+
let byte3 = buf.readUInt8(3);
|
|
259
|
+
let byte4 = buf.readUInt8(4);
|
|
262
260
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
261
|
+
let calibration = (byte1 & 0b01000000) ? true : false; // Whether the calibration is completed
|
|
262
|
+
let battery = byte2 & 0b01111111; // %
|
|
263
|
+
let currPosition = byte3 & 0b01111111; // current positon %
|
|
264
|
+
let lightLevel = (byte4 >> 4) & 0b00001111; // light sensor level (1-10)
|
|
267
265
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
266
|
+
let data = {
|
|
267
|
+
model: "c",
|
|
268
|
+
modelName: "WoCurtain",
|
|
269
|
+
calibration: calibration,
|
|
270
|
+
battery: battery,
|
|
271
|
+
position: currPosition,
|
|
272
|
+
lightLevel: lightLevel
|
|
273
|
+
};
|
|
276
274
|
|
|
277
|
-
|
|
278
|
-
|
|
275
|
+
return data;
|
|
276
|
+
}
|
|
279
277
|
}
|
|
280
278
|
|
|
281
279
|
module.exports = new SwitchbotAdvertising();
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
const SwitchbotDevice = require('./switchbot-device.js');
|
|
1
|
+
import SwitchbotDevice from "./switchbot-device.js";
|
|
3
2
|
|
|
4
3
|
class SwitchbotDeviceWoContact extends SwitchbotDevice {
|
|
5
4
|
|
|
6
5
|
|
|
7
6
|
}
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
export default SwitchbotDeviceWoContact;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
const SwitchbotDevice = require('./switchbot-device.js');
|
|
1
|
+
import SwitchbotDevice from "./switchbot-device.js";
|
|
3
2
|
|
|
4
3
|
class SwitchbotDeviceWoCurtain extends SwitchbotDevice {
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
/* ------------------------------------------------------------------
|
|
7
6
|
* open()
|
|
8
7
|
* - Open the curtain
|
|
9
8
|
*
|
|
@@ -14,11 +13,11 @@ class SwitchbotDeviceWoCurtain extends SwitchbotDevice {
|
|
|
14
13
|
* - Promise object
|
|
15
14
|
* Nothing will be passed to the `resolve()`.
|
|
16
15
|
* ---------------------------------------------------------------- */
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
open() {
|
|
17
|
+
return this._operateCurtain([0x57, 0x0f, 0x45, 0x01, 0x05, 0xff, 0x00]);
|
|
18
|
+
}
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
/* ------------------------------------------------------------------
|
|
22
21
|
* close()
|
|
23
22
|
* - close the curtain
|
|
24
23
|
*
|
|
@@ -29,11 +28,11 @@ class SwitchbotDeviceWoCurtain extends SwitchbotDevice {
|
|
|
29
28
|
* - Promise object
|
|
30
29
|
* Nothing will be passed to the `resolve()`.
|
|
31
30
|
* ---------------------------------------------------------------- */
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
close() {
|
|
32
|
+
return this._operateCurtain([0x57, 0x0f, 0x45, 0x01, 0x05, 0xff, 0x64]);
|
|
33
|
+
}
|
|
35
34
|
|
|
36
|
-
|
|
35
|
+
/* ------------------------------------------------------------------
|
|
37
36
|
* pause()
|
|
38
37
|
* - pause the curtain
|
|
39
38
|
*
|
|
@@ -44,11 +43,11 @@ class SwitchbotDeviceWoCurtain extends SwitchbotDevice {
|
|
|
44
43
|
* - Promise object
|
|
45
44
|
* Nothing will be passed to the `resolve()`.
|
|
46
45
|
* ---------------------------------------------------------------- */
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
pause() {
|
|
47
|
+
return this._operateCurtain([0x57, 0x0f, 0x45, 0x01, 0x00, 0xff]);
|
|
48
|
+
}
|
|
50
49
|
|
|
51
|
-
|
|
50
|
+
/* ------------------------------------------------------------------
|
|
52
51
|
* runToPos()
|
|
53
52
|
* - run to the targe position
|
|
54
53
|
*
|
|
@@ -59,44 +58,44 @@ class SwitchbotDeviceWoCurtain extends SwitchbotDevice {
|
|
|
59
58
|
* - Promise object
|
|
60
59
|
* Nothing will be passed to the `resolve()`.
|
|
61
60
|
* ---------------------------------------------------------------- */
|
|
62
|
-
|
|
61
|
+
runToPos(percent, mode) {
|
|
63
62
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
63
|
+
if (typeof percent != "number") {
|
|
64
|
+
return new Promise((resolve, reject) => {
|
|
65
|
+
reject(new Error("The type of target position percentage is incorrent: " + typeof percent));
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
if (mode == null) {
|
|
69
|
+
mode = 0xff;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
if (typeof mode != "number") {
|
|
73
|
+
return new Promise((resolve, reject) => {
|
|
74
|
+
reject(new Error("The type of running mode is incorrent: " + typeof mode));
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
if (mode > 1) { mode = 0xff; }
|
|
78
|
+
}
|
|
79
|
+
if (percent > 100) { percent = 100; }
|
|
80
|
+
else if (percent < 0) { percent = 0; }
|
|
81
|
+
return this._operateCurtain([0x57, 0x0f, 0x45, 0x01, 0x05, mode, percent]);
|
|
82
|
+
}
|
|
84
83
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
84
|
+
_operateCurtain(bytes) {
|
|
85
|
+
return new Promise((resolve, reject) => {
|
|
86
|
+
let req_buf = Buffer.from(bytes);
|
|
87
|
+
this._command(req_buf).then((res_buf) => {
|
|
88
|
+
let code = res_buf.readUInt8(0);
|
|
89
|
+
if (res_buf.length === 3 && code === 0x01) {
|
|
90
|
+
resolve();
|
|
91
|
+
} else {
|
|
92
|
+
reject(new Error("The device returned an error: 0x" + res_buf.toString("hex")));
|
|
93
|
+
}
|
|
94
|
+
}).catch((error) => {
|
|
95
|
+
reject(error);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
}
|
|
100
99
|
}
|
|
101
100
|
|
|
102
|
-
|
|
101
|
+
export default SwitchbotDeviceWoCurtain;
|