node-switchbot 1.3.0 → 1.4.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 +32 -23
- package/LICENSE +1 -1
- package/README.md +322 -258
- package/lib/parameter-checker.js +271 -213
- package/lib/switchbot-advertising.js +238 -163
- 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 +3 -3
|
@@ -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 ===
|
|
106
|
+
} else if (model === "g") {
|
|
107
|
+
// WoPlugMini
|
|
92
108
|
sd = this._parseServiceDataForWoPlugMini(buf, onlog);
|
|
93
|
-
} else if (model ===
|
|
109
|
+
} else if (model === "j") {
|
|
110
|
+
// WoPlugMini (JP) ??
|
|
111
|
+
sd = this._parseServiceDataForWoPlugMini(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,8 +365,10 @@ 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
|
}
|
|
@@ -328,29 +379,47 @@ class SwitchbotAdvertising {
|
|
|
328
379
|
let byte5 = buf.readUInt8(5);
|
|
329
380
|
|
|
330
381
|
let data = {
|
|
331
|
-
model:
|
|
332
|
-
modelName:
|
|
382
|
+
model: "u",
|
|
383
|
+
modelName: "WoColorBulb",
|
|
333
384
|
};
|
|
334
385
|
|
|
335
386
|
return data;
|
|
336
387
|
}
|
|
337
388
|
|
|
338
389
|
_parseServiceDataForWoPlugMini(buf, onlog) {
|
|
339
|
-
if (buf.length !==
|
|
340
|
-
if (onlog && typeof onlog ===
|
|
341
|
-
onlog(
|
|
390
|
+
if (buf.length !== 14) {
|
|
391
|
+
if (onlog && typeof onlog === "function") {
|
|
392
|
+
onlog(
|
|
393
|
+
`[_parseServiceDataForWoPlugMini] Buffer length ${buf.length} should be 14`
|
|
394
|
+
);
|
|
342
395
|
}
|
|
343
396
|
return null;
|
|
344
397
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
398
|
+
const byte9 = buf.readUInt8(9); // byte9: plug mini state; 0x00=off, 0x80=on
|
|
399
|
+
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
|
|
400
|
+
const byte11 = buf.readUInt8(11); // byte11: wifi rssi
|
|
401
|
+
const byte12 = buf.readUInt8(12); // byte12: bit7: overload?
|
|
402
|
+
const byte13 = buf.readUInt8(13); // byte12[bit0~6] + byte13: current power value
|
|
403
|
+
|
|
404
|
+
const state = byte9 === 0x00 ? "off" : byte9 === 0x80 ? "on" : null;
|
|
405
|
+
const delay = !!(byte10 & 0b00000001);
|
|
406
|
+
const timer = !!(byte10 & 0b00000010);
|
|
407
|
+
const syncUtcTime = !!(byte10 & 0b00000100);
|
|
408
|
+
const wifiRssi = byte11;
|
|
409
|
+
const overload = !!(byte12 & 0b10000000);
|
|
410
|
+
const currentPower = (((byte12 & 0b01111111) << 8) + byte13) / 10; // in watt
|
|
411
|
+
// TODO: voltage ???
|
|
412
|
+
|
|
413
|
+
const data = {
|
|
414
|
+
model: "j",
|
|
415
|
+
modelName: "WoPlugMini",
|
|
416
|
+
state: state,
|
|
417
|
+
delay: delay,
|
|
418
|
+
timer: timer,
|
|
419
|
+
syncUtcTime: syncUtcTime,
|
|
420
|
+
wifiRssi: wifiRssi,
|
|
421
|
+
overload: overload,
|
|
422
|
+
currentPower: currentPower,
|
|
354
423
|
};
|
|
355
424
|
|
|
356
425
|
return data;
|
|
@@ -358,8 +427,10 @@ class SwitchbotAdvertising {
|
|
|
358
427
|
|
|
359
428
|
_parseServiceDataForWoSmartLock(buf, onlog) {
|
|
360
429
|
if (buf.length !== 6) {
|
|
361
|
-
if (onlog && typeof onlog ===
|
|
362
|
-
onlog(
|
|
430
|
+
if (onlog && typeof onlog === "function") {
|
|
431
|
+
onlog(
|
|
432
|
+
`[_parseServiceDataForWoSmartLock] Buffer length ${buf.length} !== 6!`
|
|
433
|
+
);
|
|
363
434
|
}
|
|
364
435
|
return null;
|
|
365
436
|
}
|
|
@@ -374,8 +445,8 @@ class SwitchbotAdvertising {
|
|
|
374
445
|
//let lightLevel = byte5 & 0b00000011;
|
|
375
446
|
|
|
376
447
|
let data = {
|
|
377
|
-
model:
|
|
378
|
-
modelName:
|
|
448
|
+
model: "o",
|
|
449
|
+
modelName: "WoSmartLock",
|
|
379
450
|
//movement: pirState,
|
|
380
451
|
battery: battery,
|
|
381
452
|
//lightLevel: (lightLevel == 1) ? 'dark' : ((lightLevel == 2) ? 'bright' : 'unknown'),
|
|
@@ -386,8 +457,10 @@ class SwitchbotAdvertising {
|
|
|
386
457
|
|
|
387
458
|
_parseServiceDataForWoSensorTHPlus(buf, onlog) {
|
|
388
459
|
if (buf.length !== 6) {
|
|
389
|
-
if (onlog && typeof onlog ===
|
|
390
|
-
onlog(
|
|
460
|
+
if (onlog && typeof onlog === "function") {
|
|
461
|
+
onlog(
|
|
462
|
+
`[_parseServiceDataForWoSensorTHPlus] Buffer length ${buf.length} !== 6!`
|
|
463
|
+
);
|
|
391
464
|
}
|
|
392
465
|
return null;
|
|
393
466
|
}
|
|
@@ -396,21 +469,21 @@ class SwitchbotAdvertising {
|
|
|
396
469
|
let byte4 = buf.readUInt8(4);
|
|
397
470
|
let byte5 = buf.readUInt8(5);
|
|
398
471
|
|
|
399
|
-
let temp_sign =
|
|
400
|
-
let temp_c = temp_sign * ((byte4 & 0b01111111) +
|
|
401
|
-
let temp_f = (temp_c * 9 / 5
|
|
472
|
+
let temp_sign = byte4 & 0b10000000 ? 1 : -1;
|
|
473
|
+
let temp_c = temp_sign * ((byte4 & 0b01111111) + byte3 / 10);
|
|
474
|
+
let temp_f = (temp_c * 9) / 5 + 32;
|
|
402
475
|
temp_f = Math.round(temp_f * 10) / 10;
|
|
403
476
|
|
|
404
477
|
let data = {
|
|
405
|
-
model:
|
|
406
|
-
modelName:
|
|
478
|
+
model: "i",
|
|
479
|
+
modelName: "WoSensorTHPlus",
|
|
407
480
|
temperature: {
|
|
408
481
|
c: temp_c,
|
|
409
|
-
f: temp_f
|
|
482
|
+
f: temp_f,
|
|
410
483
|
},
|
|
411
|
-
fahrenheit:
|
|
484
|
+
fahrenheit: byte5 & 0b10000000 ? true : false,
|
|
412
485
|
humidity: byte5 & 0b01111111,
|
|
413
|
-
battery:
|
|
486
|
+
battery: byte2 & 0b01111111,
|
|
414
487
|
};
|
|
415
488
|
|
|
416
489
|
return data;
|
|
@@ -418,8 +491,10 @@ class SwitchbotAdvertising {
|
|
|
418
491
|
|
|
419
492
|
_parseServiceDataForWoLEDStripLight(buf, onlog) {
|
|
420
493
|
if (buf.length !== 6) {
|
|
421
|
-
if (onlog && typeof onlog ===
|
|
422
|
-
onlog(
|
|
494
|
+
if (onlog && typeof onlog === "function") {
|
|
495
|
+
onlog(
|
|
496
|
+
`[_parseServiceDataForWoLEDStripLight] Buffer length ${buf.length} !== 6!`
|
|
497
|
+
);
|
|
423
498
|
}
|
|
424
499
|
return null;
|
|
425
500
|
}
|
|
@@ -430,8 +505,8 @@ class SwitchbotAdvertising {
|
|
|
430
505
|
let byte5 = buf.readUInt8(5);
|
|
431
506
|
|
|
432
507
|
let data = {
|
|
433
|
-
model:
|
|
434
|
-
modelName:
|
|
508
|
+
model: "r",
|
|
509
|
+
modelName: "WoLEDStripLight",
|
|
435
510
|
};
|
|
436
511
|
|
|
437
512
|
return data;
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
const SwitchbotDevice = require(
|
|
1
|
+
"use strict";
|
|
2
|
+
const SwitchbotDevice = require("./switchbot-device.js");
|
|
3
3
|
|
|
4
|
-
class SwitchbotDeviceWoContact extends SwitchbotDevice {
|
|
4
|
+
class SwitchbotDeviceWoContact extends SwitchbotDevice {}
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
module.exports = SwitchbotDeviceWoContact;
|
|
6
|
+
module.exports = SwitchbotDeviceWoContact;
|