node-switchbot 1.3.0 → 1.4.2-beta.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.
- package/CHANGELOG.md +41 -23
- package/LICENSE +1 -1
- package/README.md +322 -258
- package/lib/parameter-checker.js +271 -213
- package/lib/switchbot-advertising.js +305 -171
- package/lib/switchbot-device-wocolorbulb.js +81 -0
- package/lib/switchbot-device-wocontact.js +4 -7
- package/lib/switchbot-device-wocurtain.js +106 -91
- package/lib/switchbot-device-wohand.js +69 -65
- package/lib/switchbot-device-wohumi.js +69 -65
- package/lib/switchbot-device-woplugmini.js +81 -0
- package/lib/switchbot-device-wopresence.js +4 -7
- package/lib/switchbot-device-wosensorth.js +4 -7
- package/lib/switchbot-device.js +188 -149
- package/lib/switchbot.js +271 -233
- package/package.json +40 -40
|
@@ -1,162 +1,195 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
3
|
class SwitchbotAdvertising {
|
|
4
|
-
constructor() {
|
|
4
|
+
constructor() {}
|
|
5
5
|
|
|
6
6
|
/* ------------------------------------------------------------------
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
7
|
+
* parse(peripheral)
|
|
8
|
+
* - Parse advertising packets coming from switchbot devices
|
|
9
|
+
*
|
|
10
|
+
* [Arguments]
|
|
11
|
+
* - peripheral | Object | Required | A `Peripheral` object of noble
|
|
12
|
+
*
|
|
13
|
+
* [Return value]
|
|
14
|
+
* - An object as follows:
|
|
15
|
+
*
|
|
16
|
+
* WoHand
|
|
17
|
+
* {
|
|
18
|
+
* id: 'c12e453e2008',
|
|
19
|
+
* address: 'c1:2e:45:3e:20:08',
|
|
20
|
+
* rssi: -43,
|
|
21
|
+
* serviceData: {
|
|
22
|
+
* model: 'H',
|
|
23
|
+
* modelName: 'WoHand',
|
|
24
|
+
* mode: false,
|
|
25
|
+
* state: false,
|
|
26
|
+
* battery: 95
|
|
27
|
+
* }
|
|
28
|
+
* }
|
|
29
|
+
*
|
|
30
|
+
* WoSensorTH
|
|
31
|
+
* {
|
|
32
|
+
* id: 'cb4eb903c96d',
|
|
33
|
+
* address: 'cb:4e:b9:03:c9:6d',
|
|
34
|
+
* rssi: -54,
|
|
35
|
+
* serviceData: {
|
|
36
|
+
* model: 'T',
|
|
37
|
+
* modelName: 'WoSensorTH',
|
|
38
|
+
* temperature: { c: 26.2, f: 79.2 },
|
|
39
|
+
* fahrenheit: false,
|
|
40
|
+
* humidity: 45,
|
|
41
|
+
* battery: 100
|
|
42
|
+
* }
|
|
43
|
+
* }
|
|
44
|
+
*
|
|
45
|
+
* WoCurtain
|
|
46
|
+
* {
|
|
47
|
+
* id: 'ec58c5d00111',
|
|
48
|
+
* address: 'ec:58:c5:d0:01:11',
|
|
49
|
+
* rssi: -39,
|
|
50
|
+
* serviceData: {
|
|
51
|
+
* model: 'c',
|
|
52
|
+
* modelName: 'WoCurtain',
|
|
53
|
+
* calibration: true,
|
|
54
|
+
* battery: 91,
|
|
55
|
+
* position: 1,
|
|
56
|
+
* lightLevel: 1
|
|
57
|
+
* }
|
|
58
|
+
* }
|
|
59
|
+
*
|
|
60
|
+
* If the specified `Peripheral` does not represent any switchbot
|
|
61
|
+
* device, this method will return `null`.
|
|
62
|
+
* ---------------------------------------------------------------- */
|
|
63
63
|
parse(peripheral, onlog) {
|
|
64
64
|
let ad = peripheral.advertisement;
|
|
65
65
|
if (!ad || !ad.serviceData) {
|
|
66
66
|
return null;
|
|
67
67
|
}
|
|
68
68
|
let serviceData = ad.serviceData[0] || ad.serviceData;
|
|
69
|
+
let manufacturerData = ad.manufacturerData;
|
|
69
70
|
let buf = serviceData.data;
|
|
70
|
-
|
|
71
|
+
|
|
72
|
+
const bufIsInvalid = !buf || !Buffer.isBuffer(buf) || buf.length < 3;
|
|
73
|
+
const manufacturerDataIsInvalid =
|
|
74
|
+
!manufacturerData ||
|
|
75
|
+
!Buffer.isBuffer(manufacturerData) ||
|
|
76
|
+
manufacturerData.length < 3;
|
|
77
|
+
|
|
78
|
+
if (bufIsInvalid && manufacturerDataIsInvalid) {
|
|
71
79
|
return null;
|
|
72
80
|
}
|
|
73
81
|
|
|
74
|
-
let model = buf.slice(0, 1).toString(
|
|
82
|
+
let model = buf.slice(0, 1).toString("utf8");
|
|
75
83
|
let sd = null;
|
|
76
84
|
|
|
77
|
-
if (model ===
|
|
85
|
+
if (model === "H") {
|
|
86
|
+
// WoHand
|
|
78
87
|
sd = this._parseServiceDataForWoHand(buf, onlog);
|
|
79
|
-
} else if (model ===
|
|
88
|
+
} else if (model === "T") {
|
|
89
|
+
// WoSensorTH
|
|
80
90
|
sd = this._parseServiceDataForWoSensorTH(buf, onlog);
|
|
81
|
-
} else if (model ===
|
|
91
|
+
} else if (model === "e") {
|
|
92
|
+
// WoHumi
|
|
82
93
|
sd = this._parseServiceDataForWoHumi(buf, onlog);
|
|
83
|
-
} else if (model ===
|
|
94
|
+
} else if (model === "s") {
|
|
95
|
+
// WoMotion
|
|
84
96
|
sd = this._parseServiceDataForWoPresence(buf, onlog);
|
|
85
|
-
} else if (model ===
|
|
97
|
+
} else if (model === "d") {
|
|
98
|
+
// WoContact
|
|
86
99
|
sd = this._parseServiceDataForWoContact(buf, onlog);
|
|
87
|
-
} else if (model ===
|
|
100
|
+
} else if (model === "c") {
|
|
101
|
+
// WoCurtain
|
|
88
102
|
sd = this._parseServiceDataForWoCurtain(buf, onlog);
|
|
89
|
-
} else if (model ===
|
|
103
|
+
} else if (model === "u") {
|
|
104
|
+
// WoColorBulb
|
|
90
105
|
sd = this._parseServiceDataForWoColorBulb(buf, onlog);
|
|
91
|
-
} else if (model ===
|
|
92
|
-
|
|
93
|
-
|
|
106
|
+
} else if (model === "g") {
|
|
107
|
+
// WoPlugMini (US)
|
|
108
|
+
sd = this._parseServiceDataForWoPlugMiniUS(manufacturerData, onlog);
|
|
109
|
+
} else if (model === "j") {
|
|
110
|
+
// WoPlugMini (JP)
|
|
111
|
+
sd = this._parseServiceDataForWoPlugMiniJP(manufacturerData, onlog);
|
|
112
|
+
} else if (model === "o") {
|
|
113
|
+
// WoSmartLock
|
|
94
114
|
sd = this._parseServiceDataForWoSmartLock(buf, onlog);
|
|
95
|
-
} else if (model ===
|
|
115
|
+
} else if (model === "i") {
|
|
116
|
+
// WoMeterPlus
|
|
96
117
|
sd = this._parseServiceDataForWoSensorTHPlus(buf, onlog);
|
|
97
|
-
} else if (model ===
|
|
118
|
+
} else if (model === "r") {
|
|
119
|
+
// WoLEDStripLight
|
|
98
120
|
sd = this._parseServiceDataForWoLEDStripLight(buf, onlog);
|
|
99
121
|
} else {
|
|
100
|
-
if (onlog && typeof onlog ===
|
|
101
|
-
onlog(
|
|
122
|
+
if (onlog && typeof onlog === "function") {
|
|
123
|
+
onlog(
|
|
124
|
+
`[parseAdvertising.${peripheral.id}] return null, model "${model}" not available!`
|
|
125
|
+
);
|
|
102
126
|
}
|
|
103
127
|
return null;
|
|
104
128
|
}
|
|
105
129
|
|
|
106
130
|
if (!sd) {
|
|
107
|
-
if (onlog && typeof onlog ===
|
|
108
|
-
onlog(
|
|
131
|
+
if (onlog && typeof onlog === "function") {
|
|
132
|
+
onlog(
|
|
133
|
+
`[parseAdvertising.${peripheral.id}.${model}] return null, parsed serviceData empty!`
|
|
134
|
+
);
|
|
109
135
|
}
|
|
110
136
|
return null;
|
|
111
137
|
}
|
|
112
|
-
let address = peripheral.address ||
|
|
113
|
-
if (address ===
|
|
114
|
-
address = peripheral.advertisement.manufacturerData ||
|
|
115
|
-
if (address !==
|
|
116
|
-
const str = peripheral.advertisement.manufacturerData
|
|
138
|
+
let address = peripheral.address || "";
|
|
139
|
+
if (address === "") {
|
|
140
|
+
address = peripheral.advertisement.manufacturerData || "";
|
|
141
|
+
if (address !== "") {
|
|
142
|
+
const str = peripheral.advertisement.manufacturerData
|
|
143
|
+
.toString("hex")
|
|
144
|
+
.slice(4, 16);
|
|
117
145
|
address = str.substr(0, 2);
|
|
118
146
|
for (var i = 2; i < str.length; i += 2) {
|
|
119
147
|
address = address + ":" + str.substr(i, 2);
|
|
120
148
|
}
|
|
121
149
|
// console.log("address", typeof(address), address);
|
|
122
150
|
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
address = address.replace(/-/g, ':');
|
|
151
|
+
} else {
|
|
152
|
+
address = address.replace(/-/g, ":");
|
|
126
153
|
}
|
|
127
154
|
let data = {
|
|
128
155
|
id: peripheral.id,
|
|
129
156
|
address: address,
|
|
130
157
|
rssi: peripheral.rssi,
|
|
131
|
-
serviceData: sd
|
|
158
|
+
serviceData: sd,
|
|
132
159
|
};
|
|
133
|
-
|
|
134
|
-
if (onlog && typeof onlog ===
|
|
135
|
-
onlog(
|
|
160
|
+
|
|
161
|
+
if (onlog && typeof onlog === "function") {
|
|
162
|
+
onlog(
|
|
163
|
+
`[parseAdvertising.${peripheral.id}.${model}] return ${JSON.stringify(
|
|
164
|
+
data
|
|
165
|
+
)}`
|
|
166
|
+
);
|
|
136
167
|
}
|
|
137
168
|
return data;
|
|
138
169
|
}
|
|
139
170
|
|
|
140
171
|
_parseServiceDataForWoHand(buf, onlog) {
|
|
141
172
|
if (buf.length !== 3) {
|
|
142
|
-
if (onlog && typeof onlog ===
|
|
143
|
-
onlog(
|
|
173
|
+
if (onlog && typeof onlog === "function") {
|
|
174
|
+
onlog(
|
|
175
|
+
`[_parseServiceDataForWoHand] Buffer length ${buf.length} !== 3!`
|
|
176
|
+
);
|
|
144
177
|
}
|
|
145
178
|
return null;
|
|
146
179
|
}
|
|
147
180
|
let byte1 = buf.readUInt8(1);
|
|
148
181
|
let byte2 = buf.readUInt8(2);
|
|
149
182
|
|
|
150
|
-
let mode =
|
|
151
|
-
let state =
|
|
183
|
+
let mode = byte1 & 0b10000000 ? true : false; // Whether the light switch Add-on is used or not
|
|
184
|
+
let state = byte1 & 0b01000000 ? true : false; // Whether the switch status is ON or OFF
|
|
152
185
|
let battery = byte2 & 0b01111111; // %
|
|
153
186
|
|
|
154
187
|
let data = {
|
|
155
|
-
model:
|
|
156
|
-
modelName:
|
|
188
|
+
model: "H",
|
|
189
|
+
modelName: "WoHand",
|
|
157
190
|
mode: mode,
|
|
158
191
|
state: state,
|
|
159
|
-
battery: battery
|
|
192
|
+
battery: battery,
|
|
160
193
|
};
|
|
161
194
|
|
|
162
195
|
return data;
|
|
@@ -164,8 +197,10 @@ class SwitchbotAdvertising {
|
|
|
164
197
|
|
|
165
198
|
_parseServiceDataForWoSensorTH(buf, onlog) {
|
|
166
199
|
if (buf.length !== 6) {
|
|
167
|
-
if (onlog && typeof onlog ===
|
|
168
|
-
onlog(
|
|
200
|
+
if (onlog && typeof onlog === "function") {
|
|
201
|
+
onlog(
|
|
202
|
+
`[_parseServiceDataForWoSensorTH] Buffer length ${buf.length} !== 6!`
|
|
203
|
+
);
|
|
169
204
|
}
|
|
170
205
|
return null;
|
|
171
206
|
}
|
|
@@ -174,21 +209,21 @@ class SwitchbotAdvertising {
|
|
|
174
209
|
let byte4 = buf.readUInt8(4);
|
|
175
210
|
let byte5 = buf.readUInt8(5);
|
|
176
211
|
|
|
177
|
-
let temp_sign =
|
|
178
|
-
let temp_c = temp_sign * ((byte4 & 0b01111111) +
|
|
179
|
-
let temp_f = (temp_c * 9 / 5
|
|
212
|
+
let temp_sign = byte4 & 0b10000000 ? 1 : -1;
|
|
213
|
+
let temp_c = temp_sign * ((byte4 & 0b01111111) + byte3 / 10);
|
|
214
|
+
let temp_f = (temp_c * 9) / 5 + 32;
|
|
180
215
|
temp_f = Math.round(temp_f * 10) / 10;
|
|
181
216
|
|
|
182
217
|
let data = {
|
|
183
|
-
model:
|
|
184
|
-
modelName:
|
|
218
|
+
model: "T",
|
|
219
|
+
modelName: "WoSensorTH",
|
|
185
220
|
temperature: {
|
|
186
221
|
c: temp_c,
|
|
187
|
-
f: temp_f
|
|
222
|
+
f: temp_f,
|
|
188
223
|
},
|
|
189
|
-
fahrenheit:
|
|
224
|
+
fahrenheit: byte5 & 0b10000000 ? true : false,
|
|
190
225
|
humidity: byte5 & 0b01111111,
|
|
191
|
-
battery:
|
|
226
|
+
battery: byte2 & 0b01111111,
|
|
192
227
|
};
|
|
193
228
|
|
|
194
229
|
return data;
|
|
@@ -196,8 +231,10 @@ class SwitchbotAdvertising {
|
|
|
196
231
|
|
|
197
232
|
_parseServiceDataForWoHumi(buf, onlog) {
|
|
198
233
|
if (buf.length !== 8) {
|
|
199
|
-
if (onlog && typeof onlog ===
|
|
200
|
-
onlog(
|
|
234
|
+
if (onlog && typeof onlog === "function") {
|
|
235
|
+
onlog(
|
|
236
|
+
`[_parseServiceDataForWoHumi] Buffer length ${buf.length} !== 8!`
|
|
237
|
+
);
|
|
201
238
|
}
|
|
202
239
|
return null;
|
|
203
240
|
}
|
|
@@ -207,13 +244,13 @@ class SwitchbotAdvertising {
|
|
|
207
244
|
let byte4 = buf.readUInt8(4);
|
|
208
245
|
let byte5 = buf.readUInt8(5);
|
|
209
246
|
|
|
210
|
-
let onState =
|
|
211
|
-
let autoMode =
|
|
247
|
+
let onState = byte1 & 0b10000000 ? true : false; // 1 - on
|
|
248
|
+
let autoMode = byte4 & 0b10000000 ? true : false; // 1 - auto
|
|
212
249
|
let percentage = byte4 & 0b01111111; // 0-100%, 101/102/103 - Quick gear 1/2/3
|
|
213
250
|
|
|
214
251
|
let data = {
|
|
215
|
-
model:
|
|
216
|
-
modelName:
|
|
252
|
+
model: "e",
|
|
253
|
+
modelName: "WoHumi",
|
|
217
254
|
onState: onState,
|
|
218
255
|
autoMode: autoMode,
|
|
219
256
|
percentage: autoMode ? 0 : percentage,
|
|
@@ -224,8 +261,10 @@ class SwitchbotAdvertising {
|
|
|
224
261
|
|
|
225
262
|
_parseServiceDataForWoPresence(buf, onlog) {
|
|
226
263
|
if (buf.length !== 6) {
|
|
227
|
-
if (onlog && typeof onlog ===
|
|
228
|
-
onlog(
|
|
264
|
+
if (onlog && typeof onlog === "function") {
|
|
265
|
+
onlog(
|
|
266
|
+
`[_parseServiceDataForWoPresence] Buffer length ${buf.length} !== 6!`
|
|
267
|
+
);
|
|
229
268
|
}
|
|
230
269
|
return null;
|
|
231
270
|
}
|
|
@@ -235,16 +274,17 @@ class SwitchbotAdvertising {
|
|
|
235
274
|
// let byte4 = buf.readUInt8(4);
|
|
236
275
|
let byte5 = buf.readUInt8(5);
|
|
237
276
|
|
|
238
|
-
let pirState =
|
|
277
|
+
let pirState = byte1 & 0b01000000 ? true : false; // 1 - Movement detected
|
|
239
278
|
let battery = byte2 & 0b01111111; // %
|
|
240
279
|
let lightLevel = byte5 & 0b00000011;
|
|
241
280
|
|
|
242
281
|
let data = {
|
|
243
|
-
model:
|
|
244
|
-
modelName:
|
|
282
|
+
model: "s",
|
|
283
|
+
modelName: "WoMotion",
|
|
245
284
|
movement: pirState,
|
|
246
285
|
battery: battery,
|
|
247
|
-
lightLevel:
|
|
286
|
+
lightLevel:
|
|
287
|
+
lightLevel == 1 ? "dark" : lightLevel == 2 ? "bright" : "unknown",
|
|
248
288
|
};
|
|
249
289
|
|
|
250
290
|
return data;
|
|
@@ -252,8 +292,10 @@ class SwitchbotAdvertising {
|
|
|
252
292
|
|
|
253
293
|
_parseServiceDataForWoContact(buf, onlog) {
|
|
254
294
|
if (buf.length !== 9) {
|
|
255
|
-
if (onlog && typeof onlog ===
|
|
256
|
-
onlog(
|
|
295
|
+
if (onlog && typeof onlog === "function") {
|
|
296
|
+
onlog(
|
|
297
|
+
`[_parseServiceDataForWoContact] Buffer length ${buf.length} !== 9!`
|
|
298
|
+
);
|
|
257
299
|
}
|
|
258
300
|
return null;
|
|
259
301
|
}
|
|
@@ -267,18 +309,23 @@ class SwitchbotAdvertising {
|
|
|
267
309
|
// let byte7 = buf.readUInt8(7);
|
|
268
310
|
// let byte8 = buf.readUInt8(8);
|
|
269
311
|
|
|
270
|
-
let pirState =
|
|
312
|
+
let pirState = byte1 & 0b01000000 ? true : false; // 1 - Movement detected
|
|
271
313
|
let battery = byte2 & 0b01111111; // %
|
|
272
314
|
let hallState = (byte3 >> 1) & 0b00000011;
|
|
273
315
|
let lightLevel = byte3 & 0b00000001;
|
|
274
316
|
|
|
275
317
|
let data = {
|
|
276
|
-
model:
|
|
277
|
-
modelName:
|
|
318
|
+
model: "d",
|
|
319
|
+
modelName: "WoContact",
|
|
278
320
|
movement: pirState,
|
|
279
321
|
battery: battery,
|
|
280
|
-
doorState:
|
|
281
|
-
|
|
322
|
+
doorState:
|
|
323
|
+
hallState == 0
|
|
324
|
+
? "close"
|
|
325
|
+
: hallState == 1
|
|
326
|
+
? "open"
|
|
327
|
+
: "timeout no closed",
|
|
328
|
+
lightLevel: lightLevel == 0 ? "dark" : "bright",
|
|
282
329
|
};
|
|
283
330
|
|
|
284
331
|
return data;
|
|
@@ -286,8 +333,10 @@ class SwitchbotAdvertising {
|
|
|
286
333
|
|
|
287
334
|
_parseServiceDataForWoCurtain(buf, onlog) {
|
|
288
335
|
if (buf.length !== 5 && buf.length !== 6) {
|
|
289
|
-
if (onlog && typeof onlog ===
|
|
290
|
-
onlog(
|
|
336
|
+
if (onlog && typeof onlog === "function") {
|
|
337
|
+
onlog(
|
|
338
|
+
`[_parseServiceDataForWoCurtain] Buffer length ${buf.length} !== 5 or 6!`
|
|
339
|
+
);
|
|
291
340
|
}
|
|
292
341
|
return null;
|
|
293
342
|
}
|
|
@@ -297,18 +346,18 @@ class SwitchbotAdvertising {
|
|
|
297
346
|
let byte4 = buf.readUInt8(4);
|
|
298
347
|
// let byte5 = buf.readUInt8(5);
|
|
299
348
|
|
|
300
|
-
let calibration =
|
|
349
|
+
let calibration = byte1 & 0b01000000 ? true : false; // Whether the calibration is completed
|
|
301
350
|
let battery = byte2 & 0b01111111; // %
|
|
302
351
|
let currPosition = byte3 & 0b01111111; // current positon %
|
|
303
352
|
let lightLevel = (byte4 >> 4) & 0b00001111; // light sensor level (1-10)
|
|
304
353
|
|
|
305
354
|
let data = {
|
|
306
|
-
model:
|
|
307
|
-
modelName:
|
|
355
|
+
model: "c",
|
|
356
|
+
modelName: "WoCurtain",
|
|
308
357
|
calibration: calibration,
|
|
309
358
|
battery: battery,
|
|
310
359
|
position: currPosition,
|
|
311
|
-
lightLevel: lightLevel
|
|
360
|
+
lightLevel: lightLevel,
|
|
312
361
|
};
|
|
313
362
|
|
|
314
363
|
return data;
|
|
@@ -316,41 +365,120 @@ class SwitchbotAdvertising {
|
|
|
316
365
|
|
|
317
366
|
_parseServiceDataForWoColorBulb(buf, onlog) {
|
|
318
367
|
if (buf.length !== 6) {
|
|
319
|
-
if (onlog && typeof onlog ===
|
|
320
|
-
onlog(
|
|
368
|
+
if (onlog && typeof onlog === "function") {
|
|
369
|
+
onlog(
|
|
370
|
+
`[_parseServiceDataForWoColorBulb] Buffer length ${buf.length} !== 6!`
|
|
371
|
+
);
|
|
321
372
|
}
|
|
322
373
|
return null;
|
|
323
374
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
375
|
+
const byte9 = buf.readUInt8(9); // byte9: color bulb state; 0x00=off, 0x80=on & lightLevel: 1~100%
|
|
376
|
+
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
|
|
377
|
+
const byte11 = buf.readUInt8(11); // byte11: wifi rssi
|
|
378
|
+
const byte12 = buf.readUInt8(12); // byte12: bit7: overload?
|
|
379
|
+
const byte13 = buf.readUInt8(13); // byte12[bit0~6] + byte13: current power value
|
|
380
|
+
|
|
381
|
+
const state = byte9 === 0x00 ? "off" : byte9 === 0x80 ? "on" : null;
|
|
382
|
+
const lightLevel = byte9 & 0b01111111;
|
|
383
|
+
const delay = !!(byte10 & 0b00000001);
|
|
384
|
+
const networkStatus = !!(byte10 & 0b00000001);
|
|
385
|
+
const statePreset = !!(byte10 & 0b00000010);
|
|
386
|
+
const lightState = !!(byte10 & 0b00000100);
|
|
387
|
+
const wifiRssi = byte11;
|
|
388
|
+
const dynamicRate = !!(byte12 & 0b10000000);
|
|
389
|
+
const loopIndex = (((byte12 & 0b01111111) << 8) + byte13) / 10; // in watt
|
|
390
|
+
// TODO: voltage ???
|
|
391
|
+
|
|
392
|
+
const data = {
|
|
393
|
+
model: "u",
|
|
394
|
+
modelName: "WoColorBulb",
|
|
395
|
+
state: state,
|
|
396
|
+
lightLevel: lightLevel,
|
|
397
|
+
delay: delay,
|
|
398
|
+
networkStatus: networkStatus,
|
|
399
|
+
statePreset: statePreset,
|
|
400
|
+
lightState: lightState,
|
|
401
|
+
wifiRssi: wifiRssi,
|
|
402
|
+
dynamicRate: dynamicRate,
|
|
403
|
+
loopIndex: loopIndex,
|
|
333
404
|
};
|
|
334
405
|
|
|
335
406
|
return data;
|
|
336
407
|
}
|
|
337
408
|
|
|
338
|
-
|
|
339
|
-
if (buf.length !==
|
|
340
|
-
if (onlog && typeof onlog ===
|
|
341
|
-
onlog(
|
|
409
|
+
_parseServiceDataForWoPlugMiniUS(buf, onlog) {
|
|
410
|
+
if (buf.length !== 14) {
|
|
411
|
+
if (onlog && typeof onlog === "function") {
|
|
412
|
+
onlog(
|
|
413
|
+
`[_parseServiceDataForWoPlugMiniUS] Buffer length ${buf.length} should be 14`
|
|
414
|
+
);
|
|
342
415
|
}
|
|
343
416
|
return null;
|
|
344
417
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
418
|
+
const byte9 = buf.readUInt8(9); // byte9: plug mini state; 0x00=off, 0x80=on
|
|
419
|
+
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
|
|
420
|
+
const byte11 = buf.readUInt8(11); // byte11: wifi rssi
|
|
421
|
+
const byte12 = buf.readUInt8(12); // byte12: bit7: overload?
|
|
422
|
+
const byte13 = buf.readUInt8(13); // byte12[bit0~6] + byte13: current power value
|
|
423
|
+
|
|
424
|
+
const state = byte9 === 0x00 ? "off" : byte9 === 0x80 ? "on" : null;
|
|
425
|
+
const delay = !!(byte10 & 0b00000001);
|
|
426
|
+
const timer = !!(byte10 & 0b00000010);
|
|
427
|
+
const syncUtcTime = !!(byte10 & 0b00000100);
|
|
428
|
+
const wifiRssi = byte11;
|
|
429
|
+
const overload = !!(byte12 & 0b10000000);
|
|
430
|
+
const currentPower = (((byte12 & 0b01111111) << 8) + byte13) / 10; // in watt
|
|
431
|
+
// TODO: voltage ???
|
|
432
|
+
|
|
433
|
+
const data = {
|
|
434
|
+
model: "g",
|
|
435
|
+
modelName: "WoPlugMini",
|
|
436
|
+
state: state,
|
|
437
|
+
delay: delay,
|
|
438
|
+
timer: timer,
|
|
439
|
+
syncUtcTime: syncUtcTime,
|
|
440
|
+
wifiRssi: wifiRssi,
|
|
441
|
+
overload: overload,
|
|
442
|
+
currentPower: currentPower,
|
|
443
|
+
};
|
|
350
444
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
445
|
+
return data;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
_parseServiceDataForWoPlugMiniJP(buf, onlog) {
|
|
449
|
+
if (buf.length !== 14) {
|
|
450
|
+
if (onlog && typeof onlog === "function") {
|
|
451
|
+
onlog(
|
|
452
|
+
`[_parseServiceDataForWoPlugMiniJP] Buffer length ${buf.length} should be 14`
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
return null;
|
|
456
|
+
}
|
|
457
|
+
const byte9 = buf.readUInt8(9); // byte9: plug mini state; 0x00=off, 0x80=on
|
|
458
|
+
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
|
|
459
|
+
const byte11 = buf.readUInt8(11); // byte11: wifi rssi
|
|
460
|
+
const byte12 = buf.readUInt8(12); // byte12: bit7: overload?
|
|
461
|
+
const byte13 = buf.readUInt8(13); // byte12[bit0~6] + byte13: current power value
|
|
462
|
+
|
|
463
|
+
const state = byte9 === 0x00 ? "off" : byte9 === 0x80 ? "on" : null;
|
|
464
|
+
const delay = !!(byte10 & 0b00000001);
|
|
465
|
+
const timer = !!(byte10 & 0b00000010);
|
|
466
|
+
const syncUtcTime = !!(byte10 & 0b00000100);
|
|
467
|
+
const wifiRssi = byte11;
|
|
468
|
+
const overload = !!(byte12 & 0b10000000);
|
|
469
|
+
const currentPower = (((byte12 & 0b01111111) << 8) + byte13) / 10; // in watt
|
|
470
|
+
// TODO: voltage ???
|
|
471
|
+
|
|
472
|
+
const data = {
|
|
473
|
+
model: "j",
|
|
474
|
+
modelName: "WoPlugMini",
|
|
475
|
+
state: state,
|
|
476
|
+
delay: delay,
|
|
477
|
+
timer: timer,
|
|
478
|
+
syncUtcTime: syncUtcTime,
|
|
479
|
+
wifiRssi: wifiRssi,
|
|
480
|
+
overload: overload,
|
|
481
|
+
currentPower: currentPower,
|
|
354
482
|
};
|
|
355
483
|
|
|
356
484
|
return data;
|
|
@@ -358,8 +486,10 @@ class SwitchbotAdvertising {
|
|
|
358
486
|
|
|
359
487
|
_parseServiceDataForWoSmartLock(buf, onlog) {
|
|
360
488
|
if (buf.length !== 6) {
|
|
361
|
-
if (onlog && typeof onlog ===
|
|
362
|
-
onlog(
|
|
489
|
+
if (onlog && typeof onlog === "function") {
|
|
490
|
+
onlog(
|
|
491
|
+
`[_parseServiceDataForWoSmartLock] Buffer length ${buf.length} !== 6!`
|
|
492
|
+
);
|
|
363
493
|
}
|
|
364
494
|
return null;
|
|
365
495
|
}
|
|
@@ -374,8 +504,8 @@ class SwitchbotAdvertising {
|
|
|
374
504
|
//let lightLevel = byte5 & 0b00000011;
|
|
375
505
|
|
|
376
506
|
let data = {
|
|
377
|
-
model:
|
|
378
|
-
modelName:
|
|
507
|
+
model: "o",
|
|
508
|
+
modelName: "WoSmartLock",
|
|
379
509
|
//movement: pirState,
|
|
380
510
|
battery: battery,
|
|
381
511
|
//lightLevel: (lightLevel == 1) ? 'dark' : ((lightLevel == 2) ? 'bright' : 'unknown'),
|
|
@@ -386,8 +516,10 @@ class SwitchbotAdvertising {
|
|
|
386
516
|
|
|
387
517
|
_parseServiceDataForWoSensorTHPlus(buf, onlog) {
|
|
388
518
|
if (buf.length !== 6) {
|
|
389
|
-
if (onlog && typeof onlog ===
|
|
390
|
-
onlog(
|
|
519
|
+
if (onlog && typeof onlog === "function") {
|
|
520
|
+
onlog(
|
|
521
|
+
`[_parseServiceDataForWoSensorTHPlus] Buffer length ${buf.length} !== 6!`
|
|
522
|
+
);
|
|
391
523
|
}
|
|
392
524
|
return null;
|
|
393
525
|
}
|
|
@@ -396,21 +528,21 @@ class SwitchbotAdvertising {
|
|
|
396
528
|
let byte4 = buf.readUInt8(4);
|
|
397
529
|
let byte5 = buf.readUInt8(5);
|
|
398
530
|
|
|
399
|
-
let temp_sign =
|
|
400
|
-
let temp_c = temp_sign * ((byte4 & 0b01111111) +
|
|
401
|
-
let temp_f = (temp_c * 9 / 5
|
|
531
|
+
let temp_sign = byte4 & 0b10000000 ? 1 : -1;
|
|
532
|
+
let temp_c = temp_sign * ((byte4 & 0b01111111) + byte3 / 10);
|
|
533
|
+
let temp_f = (temp_c * 9) / 5 + 32;
|
|
402
534
|
temp_f = Math.round(temp_f * 10) / 10;
|
|
403
535
|
|
|
404
536
|
let data = {
|
|
405
|
-
model:
|
|
406
|
-
modelName:
|
|
537
|
+
model: "i",
|
|
538
|
+
modelName: "WoSensorTHPlus",
|
|
407
539
|
temperature: {
|
|
408
540
|
c: temp_c,
|
|
409
|
-
f: temp_f
|
|
541
|
+
f: temp_f,
|
|
410
542
|
},
|
|
411
|
-
fahrenheit:
|
|
543
|
+
fahrenheit: byte5 & 0b10000000 ? true : false,
|
|
412
544
|
humidity: byte5 & 0b01111111,
|
|
413
|
-
battery:
|
|
545
|
+
battery: byte2 & 0b01111111,
|
|
414
546
|
};
|
|
415
547
|
|
|
416
548
|
return data;
|
|
@@ -418,8 +550,10 @@ class SwitchbotAdvertising {
|
|
|
418
550
|
|
|
419
551
|
_parseServiceDataForWoLEDStripLight(buf, onlog) {
|
|
420
552
|
if (buf.length !== 6) {
|
|
421
|
-
if (onlog && typeof onlog ===
|
|
422
|
-
onlog(
|
|
553
|
+
if (onlog && typeof onlog === "function") {
|
|
554
|
+
onlog(
|
|
555
|
+
`[_parseServiceDataForWoLEDStripLight] Buffer length ${buf.length} !== 6!`
|
|
556
|
+
);
|
|
423
557
|
}
|
|
424
558
|
return null;
|
|
425
559
|
}
|
|
@@ -430,8 +564,8 @@ class SwitchbotAdvertising {
|
|
|
430
564
|
let byte5 = buf.readUInt8(5);
|
|
431
565
|
|
|
432
566
|
let data = {
|
|
433
|
-
model:
|
|
434
|
-
modelName:
|
|
567
|
+
model: "r",
|
|
568
|
+
modelName: "WoLEDStripLight",
|
|
435
569
|
};
|
|
436
570
|
|
|
437
571
|
return data;
|