mini_program_gizwits_sdk 3.0.1 → 3.0.6
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/dist/index.js +3 -3
- package/dist/src/errorCode.d.ts +5 -0
- package/dist/src/globalData.d.ts +2 -0
- package/dist/src/openApiRequest.d.ts +9 -0
- package/dist/src/productConfigFileManage.d.ts +12 -0
- package/dist/src/protocol/Bind.d.ts +7 -0
- package/dist/src/protocol/DataPoint.d.ts +52 -0
- package/dist/src/protocol/GetDeviceStatus.d.ts +5 -0
- package/dist/src/protocol/Login.d.ts +12 -0
- package/dist/src/protocol/ProtocolBase.d.ts +11 -0
- package/dist/src/protocol/WifiConfig.d.ts +6 -0
- package/dist/src/protocol/tool.d.ts +9 -0
- package/dist/src/randomCode.d.ts +7 -0
- package/dist/src/request.d.ts +1 -0
- package/dist/src/services/devices.d.ts +53 -0
- package/dist/src/services/login.d.ts +8 -0
- package/dist/src/services/tool.d.ts +4 -0
- package/dist/src/sleep.d.ts +2 -0
- package/dist/src/socket.d.ts +107 -0
- package/dist/src/utils.d.ts +29 -0
- package/dist/src/wechatApi.d.ts +33 -0
- package/dist/src/wifiConfig/ConfigBase.d.ts +26 -0
- package/dist/src/wifiConfig/ap.d.ts +21 -0
- package/dist/src/wifiConfig/ble.d.ts +40 -0
- package/global.d.ts +28 -0
- package/index.ts +7 -0
- package/package.json +6 -3
- package/src/ble.ts +566 -0
- package/src/errorCode.ts +60 -0
- package/src/global.d.ts +42 -0
- package/src/globalData.ts +9 -0
- package/src/openApiRequest.ts +103 -0
- package/src/productConfigFileManage.ts +44 -0
- package/src/protocol/Bind.ts +22 -0
- package/src/protocol/GetDeviceStatus.ts +61 -0
- package/src/protocol/Login.ts +43 -0
- package/src/protocol/ProtocolBase.ts +53 -0
- package/src/protocol/WifiConfig.ts +41 -0
- package/src/protocol/dataPoint.ts +663 -0
- package/src/protocol/tool.ts +91 -0
- package/src/randomCode.ts +36 -0
- package/src/request.ts +22 -0
- package/src/sdk.ts +811 -0
- package/src/services/devices.ts +210 -0
- package/src/services/login.ts +15 -0
- package/src/services/tool.ts +10 -0
- package/src/sleep.ts +2 -0
- package/src/socket.ts +449 -0
- package/src/utils.ts +215 -0
- package/src/wechatApi.ts +179 -0
- package/src/wifiConfig/ConfigBase.ts +183 -0
- package/src/wifiConfig/ap.ts +193 -0
- package/src/wifiConfig/ble.ts +417 -0
package/src/ble.ts
ADDED
|
@@ -0,0 +1,566 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ab2hex,
|
|
3
|
+
BTDevice2GDevice,
|
|
4
|
+
numberArray2Uint8Array,
|
|
5
|
+
wrapErrorInfo,
|
|
6
|
+
} from './utils';
|
|
7
|
+
import { unpackWriteBLECharacteristicValue } from './wechatApi';
|
|
8
|
+
import Bind from './protocol/Bind';
|
|
9
|
+
import { hexStrint2byte } from './protocol/tool';
|
|
10
|
+
import ProtocolBase from './protocol/ProtocolBase';
|
|
11
|
+
import Login from './protocol/Login';
|
|
12
|
+
import GetDeviceStatus from './protocol/GetDeviceStatus';
|
|
13
|
+
import sleep from './sleep';
|
|
14
|
+
import Sdk from './Sdk';
|
|
15
|
+
|
|
16
|
+
interface BleHandleParams {
|
|
17
|
+
serviceUUIDSuffix: string;
|
|
18
|
+
characteristicUUIDSuffix: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface IStartScanResult {
|
|
22
|
+
scanList: IDevice[];
|
|
23
|
+
err?: ReturnType<typeof wrapErrorInfo>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface IDeviceReq<T> {
|
|
27
|
+
success: boolean;
|
|
28
|
+
data: T;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// export type BleHandle = ReturnType<typeof createBleHandle>;
|
|
32
|
+
|
|
33
|
+
type OnScanDevice = (scanList: IDevice[]) => void;
|
|
34
|
+
interface ConnectDevice {
|
|
35
|
+
deviceId?: string;
|
|
36
|
+
serviceId?: string;
|
|
37
|
+
characteristicId?: string;
|
|
38
|
+
errMsg?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface ConstructorParams {
|
|
42
|
+
pks: string[];
|
|
43
|
+
bleHandleParams?: BleHandleParams;
|
|
44
|
+
globalListenerMap: object;
|
|
45
|
+
gizSdk: Sdk;
|
|
46
|
+
offlineThreshold?: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export class BleHandle {
|
|
50
|
+
private serviceUUIDSuffix: string;
|
|
51
|
+
// private characteristicUUIDSuffix: string;
|
|
52
|
+
public connectedList: ConnectDevice[] = [];
|
|
53
|
+
private pks: string[] = [];
|
|
54
|
+
|
|
55
|
+
private tmpBleData = ''; // 接收分包数据用
|
|
56
|
+
private tmpDataNum = 0; // 剩余字节数
|
|
57
|
+
|
|
58
|
+
private listenerMap = {};
|
|
59
|
+
private globalListenerMap = {};
|
|
60
|
+
public scanList: IDevice[] = [];
|
|
61
|
+
private gizSdk: Sdk;
|
|
62
|
+
constructor({
|
|
63
|
+
pks = [],
|
|
64
|
+
bleHandleParams = {
|
|
65
|
+
serviceUUIDSuffix: 'abf0',
|
|
66
|
+
characteristicUUIDSuffix: 'abf7',
|
|
67
|
+
},
|
|
68
|
+
globalListenerMap,
|
|
69
|
+
gizSdk,
|
|
70
|
+
offlineThreshold,
|
|
71
|
+
}: ConstructorParams) {
|
|
72
|
+
const { serviceUUIDSuffix } = bleHandleParams;
|
|
73
|
+
this.serviceUUIDSuffix = serviceUUIDSuffix;
|
|
74
|
+
this.pks = pks;
|
|
75
|
+
this.globalListenerMap = globalListenerMap;
|
|
76
|
+
this.gizSdk = gizSdk;
|
|
77
|
+
|
|
78
|
+
this.listenDevOffline(offlineThreshold ?? 10000);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private listenDevOffline = (offlineThreshold: number) => {
|
|
82
|
+
// 定时检查设备列表,移除超时设备
|
|
83
|
+
const timer = setInterval(() => {
|
|
84
|
+
const now = new Date().getTime();
|
|
85
|
+
const newDeviceList = this.scanList.filter((d) => {
|
|
86
|
+
return now - d.ctime < offlineThreshold;
|
|
87
|
+
});
|
|
88
|
+
if (newDeviceList.length !== this.scanList.length) {
|
|
89
|
+
this.scanList = newDeviceList;
|
|
90
|
+
this.gizSdk.bleDevices = newDeviceList;
|
|
91
|
+
}
|
|
92
|
+
}, 500);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
private openBluetoothAdapter = () => {
|
|
96
|
+
return new Promise((resolve, reject) => {
|
|
97
|
+
wx.openBluetoothAdapter({
|
|
98
|
+
success: () => {
|
|
99
|
+
console.log('openBluetoothAdapter success');
|
|
100
|
+
resolve({ success: true });
|
|
101
|
+
wx.onBLECharacteristicValueChange(
|
|
102
|
+
this.handleOnBLECharacteristicValueChange
|
|
103
|
+
);
|
|
104
|
+
},
|
|
105
|
+
fail: (err) => {
|
|
106
|
+
console.log('openBluetoothAdapter fail', err);
|
|
107
|
+
this.notifyError({ errMsg: err.errMsg, errCode: -1 });
|
|
108
|
+
reject(err);
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
private handleOnBLECharacteristicValueChange = (
|
|
115
|
+
curDevice: WechatMiniprogram.OnBLECharacteristicValueChangeCallbackResult
|
|
116
|
+
) => {
|
|
117
|
+
const hexString = ab2hex(curDevice.value);
|
|
118
|
+
try {
|
|
119
|
+
const data = new ProtocolBase(hexStrint2byte(hexString));
|
|
120
|
+
console.log('ProtocolBase', data.len, curDevice.value.byteLength,data);
|
|
121
|
+
// 能解析包头,覆盖数据
|
|
122
|
+
this.tmpBleData = hexString;
|
|
123
|
+
this.tmpDataNum =
|
|
124
|
+
data.len -
|
|
125
|
+
curDevice.value.byteLength +
|
|
126
|
+
4 +
|
|
127
|
+
Math.ceil(data.len.toString(2).length / 8);
|
|
128
|
+
} catch (error) {
|
|
129
|
+
// 无法解析包头
|
|
130
|
+
if (this.tmpBleData) {
|
|
131
|
+
// 有没有接收完的数据
|
|
132
|
+
this.tmpBleData += hexString;
|
|
133
|
+
this.tmpDataNum -= curDevice.value.byteLength;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (this.tmpDataNum > 0 || !this.tmpBleData) {
|
|
138
|
+
// 没有接收完数据 或者没有有效数据
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
console.log('ProtocolBase141', this.tmpBleData, this.tmpDataNum);
|
|
142
|
+
|
|
143
|
+
if (this.listenerMap[curDevice.deviceId]) {
|
|
144
|
+
this.listenerMap[curDevice.deviceId].map((item) => {
|
|
145
|
+
item(curDevice, this.tmpBleData);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
if (this.listenerMap['ALL']) {
|
|
149
|
+
console.log('ProtocolBase1');
|
|
150
|
+
this.listenerMap['ALL'].map((item) => {
|
|
151
|
+
console.log('ProtocolBase2');
|
|
152
|
+
item(curDevice, this.tmpBleData);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
this.tmpBleData = '';
|
|
157
|
+
this.tmpDataNum = 0;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
private notifyError = (err: { errCode: number; errMsg: string }) => {
|
|
161
|
+
// TODO 具体是哪台设备的错误信息
|
|
162
|
+
this.globalListenerMap['onBleHandleError']?.map((notifyFn) => {
|
|
163
|
+
notifyFn(err);
|
|
164
|
+
});
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
private listenConnection = (deviceId: string) => {
|
|
168
|
+
wx.onBLEConnectionStateChange((res) => {
|
|
169
|
+
const isInConnectedList = this.connectedList
|
|
170
|
+
.map((d) => d.deviceId)
|
|
171
|
+
.includes(deviceId);
|
|
172
|
+
|
|
173
|
+
const shouldReConnect =
|
|
174
|
+
isInConnectedList &&
|
|
175
|
+
res.deviceId === deviceId &&
|
|
176
|
+
res.connected === false;
|
|
177
|
+
console.log('蓝牙状态变化', {
|
|
178
|
+
connectedList: this.connectedList,
|
|
179
|
+
res,
|
|
180
|
+
deviceId,
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
if (shouldReConnect) {
|
|
184
|
+
this.connectDevice(deviceId);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
public checkPermission = async () => {
|
|
190
|
+
const settings = await wx.getSetting();
|
|
191
|
+
const hasBlePermission = settings.authSetting['scope.bluetooth'];
|
|
192
|
+
|
|
193
|
+
if (!hasBlePermission) {
|
|
194
|
+
try {
|
|
195
|
+
await wx.authorize({ scope: 'scope.bluetooth' });
|
|
196
|
+
await this.openBluetoothAdapter();
|
|
197
|
+
const res = await this.getBluetoothAdapterState();
|
|
198
|
+
return res;
|
|
199
|
+
} catch (err) {
|
|
200
|
+
console.log('授权失败', err);
|
|
201
|
+
// remove me in the future
|
|
202
|
+
this.openBluetoothAdapter();
|
|
203
|
+
this.notifyError({ errMsg: err.errMsg, errCode: -1 });
|
|
204
|
+
}
|
|
205
|
+
} else {
|
|
206
|
+
await this.openBluetoothAdapter();
|
|
207
|
+
const res = await this.getBluetoothAdapterState();
|
|
208
|
+
return res;
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
private getBluetoothAdapterState = async () => {
|
|
213
|
+
const { errMsg, available, ...adaptState } =
|
|
214
|
+
await wx.getBluetoothAdapterState();
|
|
215
|
+
return {
|
|
216
|
+
data: {
|
|
217
|
+
...adaptState,
|
|
218
|
+
},
|
|
219
|
+
err: wrapErrorInfo(errMsg),
|
|
220
|
+
success: available,
|
|
221
|
+
};
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
getDeviceStatus = async (
|
|
225
|
+
deviceId: string,
|
|
226
|
+
productKey: string,
|
|
227
|
+
gwDid?: string,
|
|
228
|
+
attrNames?: string[]
|
|
229
|
+
) => {
|
|
230
|
+
const value = await GetDeviceStatus.pack(productKey, gwDid, attrNames);
|
|
231
|
+
if (value) {
|
|
232
|
+
return await this.write(deviceId, numberArray2Uint8Array(value).buffer);
|
|
233
|
+
}
|
|
234
|
+
return {
|
|
235
|
+
success: false,
|
|
236
|
+
};
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
private handleBluetoothDeviceFound = (
|
|
240
|
+
resData: WechatMiniprogram.OnBluetoothDeviceFoundCallbackResult,
|
|
241
|
+
onScanDevice: OnScanDevice
|
|
242
|
+
) => {
|
|
243
|
+
const list = resData.devices.filter((device) => {
|
|
244
|
+
const { advertisData, deviceId, name, localName } = device;
|
|
245
|
+
const advertisDataStr = ab2hex(advertisData);
|
|
246
|
+
|
|
247
|
+
const targetBleDev = this.scanList.find(
|
|
248
|
+
(d) => d.bleDeviceID === deviceId
|
|
249
|
+
);
|
|
250
|
+
if (targetBleDev) {
|
|
251
|
+
// 有这台设备,无需重复添加,更新时间戳
|
|
252
|
+
this.gizSdk.setDeviceMeta(targetBleDev, 'ctime', Date.now());
|
|
253
|
+
return false;
|
|
254
|
+
} else {
|
|
255
|
+
// 添加这台设备需要校验广播包
|
|
256
|
+
const isValidDevice = this.pks.some((pk) =>
|
|
257
|
+
advertisDataStr.includes(pk)
|
|
258
|
+
);
|
|
259
|
+
return isValidDevice;
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
if (list.length > 0) {
|
|
264
|
+
const gDevice = list.map((item) => BTDevice2GDevice(item, this.pks));
|
|
265
|
+
this.scanList.push(...gDevice);
|
|
266
|
+
onScanDevice(this.scanList);
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
public startScan = async (
|
|
271
|
+
onScanDevice: OnScanDevice,
|
|
272
|
+
delay: number = 5000
|
|
273
|
+
) => {
|
|
274
|
+
return new Promise<IStartScanResult>(async (res) => {
|
|
275
|
+
wx.onBluetoothDeviceFound((resData) => {
|
|
276
|
+
this.handleBluetoothDeviceFound(resData, onScanDevice);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
await wx.startBluetoothDevicesDiscovery({
|
|
280
|
+
powerLevel: 'high',
|
|
281
|
+
allowDuplicatesKey: true,
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
setTimeout(() => {
|
|
285
|
+
this.stopScan();
|
|
286
|
+
res({
|
|
287
|
+
scanList: this.scanList,
|
|
288
|
+
});
|
|
289
|
+
}, delay);
|
|
290
|
+
});
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
public stopScan = async () => {
|
|
294
|
+
const { errMsg, errCode } = await wx.stopBluetoothDevicesDiscovery();
|
|
295
|
+
return { errMsg, errCode };
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
public connectDevice = async (deviceId: string) => {
|
|
299
|
+
const connectRes = (await wx
|
|
300
|
+
.createBLEConnection({
|
|
301
|
+
deviceId,
|
|
302
|
+
})
|
|
303
|
+
.catch((err) => {
|
|
304
|
+
this.removeDevById(deviceId);
|
|
305
|
+
this.notifyError(err);
|
|
306
|
+
})) as any;
|
|
307
|
+
|
|
308
|
+
if (connectRes.errMsg === 'createBLEConnection:ok') {
|
|
309
|
+
this.listenConnection(deviceId);
|
|
310
|
+
} else {
|
|
311
|
+
return { success: false, message: connectRes?.errMsg };
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const getServicesRes = (await wx
|
|
315
|
+
.getBLEDeviceServices({ deviceId })
|
|
316
|
+
.catch((err) => this.notifyError(err))) as any;
|
|
317
|
+
|
|
318
|
+
const serviceId = getServicesRes?.services.find(
|
|
319
|
+
(service) =>
|
|
320
|
+
service.isPrimary &&
|
|
321
|
+
service.uuid.toLowerCase().includes(this.serviceUUIDSuffix)
|
|
322
|
+
)?.uuid;
|
|
323
|
+
if (!serviceId)
|
|
324
|
+
return {
|
|
325
|
+
message: 'can not find valid serviceId',
|
|
326
|
+
success: false,
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
const getCharRes = (await wx
|
|
330
|
+
.getBLEDeviceCharacteristics({
|
|
331
|
+
deviceId,
|
|
332
|
+
serviceId,
|
|
333
|
+
})
|
|
334
|
+
.catch((err) => this.notifyError(err))) as any;
|
|
335
|
+
|
|
336
|
+
console.log({ getCharRes });
|
|
337
|
+
|
|
338
|
+
const characteristicId = getCharRes?.characteristics[0].uuid!;
|
|
339
|
+
const isNewDevice = this.connectedList.every(
|
|
340
|
+
(device) => device.deviceId !== deviceId
|
|
341
|
+
);
|
|
342
|
+
isNewDevice &&
|
|
343
|
+
this.connectedList.push({ deviceId, serviceId, characteristicId });
|
|
344
|
+
|
|
345
|
+
// 连接成功以后默认监听设备
|
|
346
|
+
const getNotifyRes = await wx
|
|
347
|
+
.notifyBLECharacteristicValueChange({
|
|
348
|
+
deviceId,
|
|
349
|
+
serviceId,
|
|
350
|
+
characteristicId,
|
|
351
|
+
state: true,
|
|
352
|
+
type: 'notification',
|
|
353
|
+
})
|
|
354
|
+
.catch((err) => this.notifyError(err));
|
|
355
|
+
|
|
356
|
+
this.write(deviceId, numberArray2Uint8Array(Bind.pack()).buffer);
|
|
357
|
+
const data = await this.handleBindReq(deviceId);
|
|
358
|
+
console.log('handleBindReq', data);
|
|
359
|
+
|
|
360
|
+
if (data.success) {
|
|
361
|
+
this.write(
|
|
362
|
+
deviceId,
|
|
363
|
+
numberArray2Uint8Array(Login.pack({ passcode: data.data })).buffer
|
|
364
|
+
);
|
|
365
|
+
const loginData = (await this.handleLoginReq(deviceId).catch((err) =>
|
|
366
|
+
this.notifyError(err)
|
|
367
|
+
)) as any;
|
|
368
|
+
console.log('loginData', loginData);
|
|
369
|
+
if (loginData?.success) {
|
|
370
|
+
return {
|
|
371
|
+
success: true,
|
|
372
|
+
message: 'ok',
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return {
|
|
378
|
+
success: false,
|
|
379
|
+
message: 'ok',
|
|
380
|
+
};
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
private handleBindReq = (deviceId: string) => {
|
|
384
|
+
// 处理设备回复绑定消息
|
|
385
|
+
return new Promise<IDeviceReq<string>>((res) => {
|
|
386
|
+
console.log('handleBindReq');
|
|
387
|
+
const onListener = (
|
|
388
|
+
_curDevice: WechatMiniprogram.OnBLECharacteristicValueChangeCallbackResult,
|
|
389
|
+
hexString: string
|
|
390
|
+
) => {
|
|
391
|
+
//TODO 销毁监听
|
|
392
|
+
console.log('监听蓝牙特征值发生变化');
|
|
393
|
+
const bindData = new Bind(hexStrint2byte(hexString));
|
|
394
|
+
this.removeDeviceListener(deviceId, onListener);
|
|
395
|
+
if (bindData.passcode) {
|
|
396
|
+
// 存在passcode
|
|
397
|
+
res({
|
|
398
|
+
success: true,
|
|
399
|
+
data: bindData.passcode,
|
|
400
|
+
});
|
|
401
|
+
} else {
|
|
402
|
+
res({
|
|
403
|
+
success: false,
|
|
404
|
+
data: '',
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
this.addDeviceListener(deviceId, onListener);
|
|
410
|
+
});
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
private handleLoginReq = (deviceId) => {
|
|
414
|
+
return new Promise<IDeviceReq<String>>((res) => {
|
|
415
|
+
const onListener = (
|
|
416
|
+
_curDevice: WechatMiniprogram.OnBLECharacteristicValueChangeCallbackResult,
|
|
417
|
+
hexString: string
|
|
418
|
+
) => {
|
|
419
|
+
//TODO 销毁监听
|
|
420
|
+
console.log('设备回复LoginReq', hexString);
|
|
421
|
+
|
|
422
|
+
const loginData = new Login(hexStrint2byte(hexString));
|
|
423
|
+
this.removeDeviceListener(deviceId, onListener);
|
|
424
|
+
if (loginData.result === true) {
|
|
425
|
+
res({
|
|
426
|
+
success: true,
|
|
427
|
+
data: loginData.did,
|
|
428
|
+
});
|
|
429
|
+
} else {
|
|
430
|
+
res({
|
|
431
|
+
success: false,
|
|
432
|
+
data: '',
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
this.addDeviceListener(deviceId, onListener);
|
|
437
|
+
});
|
|
438
|
+
};
|
|
439
|
+
|
|
440
|
+
public removeDeviceListener = (
|
|
441
|
+
deviceId: string,
|
|
442
|
+
onDeviceStatusChange: any
|
|
443
|
+
) => {
|
|
444
|
+
if (this.listenerMap[deviceId]) {
|
|
445
|
+
const index = this.listenerMap[deviceId].indexOf(onDeviceStatusChange);
|
|
446
|
+
if (index !== -1) {
|
|
447
|
+
// 删除数组中的这一行
|
|
448
|
+
this.listenerMap[deviceId].splice(index, 1);
|
|
449
|
+
return {
|
|
450
|
+
message: 'ok',
|
|
451
|
+
success: true,
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
return {
|
|
457
|
+
message: 'invalid function',
|
|
458
|
+
success: false,
|
|
459
|
+
};
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
public addDeviceListener = async (
|
|
463
|
+
deviceId,
|
|
464
|
+
onDeviceStatusChange: (
|
|
465
|
+
curDevice: WechatMiniprogram.OnBLECharacteristicValueChangeCallbackResult,
|
|
466
|
+
hexString: string
|
|
467
|
+
) => void
|
|
468
|
+
) => {
|
|
469
|
+
// 可以挂载全局监听
|
|
470
|
+
if (deviceId === 'ALL') {
|
|
471
|
+
if (!this.listenerMap['ALL']) this.listenerMap['ALL'] = [];
|
|
472
|
+
this.listenerMap['ALL'].push(onDeviceStatusChange);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const { serviceId, characteristicId, errMsg } =
|
|
476
|
+
this.getTargetDevice(deviceId);
|
|
477
|
+
if (errMsg) return { success: false, message: errMsg };
|
|
478
|
+
|
|
479
|
+
if (!this.listenerMap[deviceId]) {
|
|
480
|
+
// 创建一个新的
|
|
481
|
+
this.listenerMap[deviceId] = [];
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
if (this.listenerMap[deviceId].indexOf(onDeviceStatusChange) === -1) {
|
|
485
|
+
this.listenerMap[deviceId].push(onDeviceStatusChange);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
await wx
|
|
489
|
+
.notifyBLECharacteristicValueChange({
|
|
490
|
+
deviceId,
|
|
491
|
+
serviceId: serviceId!,
|
|
492
|
+
characteristicId: characteristicId!,
|
|
493
|
+
state: true,
|
|
494
|
+
type: 'notification',
|
|
495
|
+
})
|
|
496
|
+
.catch((err) => this.notifyError(err));
|
|
497
|
+
|
|
498
|
+
console.log(`监听设备 ${deviceId} 成功!`);
|
|
499
|
+
|
|
500
|
+
return {
|
|
501
|
+
message: 'ok',
|
|
502
|
+
success: true,
|
|
503
|
+
};
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
public write = async (deviceId: string, value: ArrayBuffer) => {
|
|
507
|
+
console.log('app => dev:', ab2hex(value));
|
|
508
|
+
|
|
509
|
+
const { serviceId, characteristicId } = this.getTargetDevice(deviceId);
|
|
510
|
+
if (serviceId && characteristicId) {
|
|
511
|
+
const unpackRes = await unpackWriteBLECharacteristicValue(
|
|
512
|
+
deviceId,
|
|
513
|
+
serviceId,
|
|
514
|
+
characteristicId,
|
|
515
|
+
value
|
|
516
|
+
);
|
|
517
|
+
|
|
518
|
+
return unpackRes;
|
|
519
|
+
}
|
|
520
|
+
return {
|
|
521
|
+
success: false,
|
|
522
|
+
message: 'serviceId or characteristicId is unvalid!',
|
|
523
|
+
errbody: { serviceId, characteristicId },
|
|
524
|
+
};
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* @description 断开设备连接
|
|
529
|
+
*/
|
|
530
|
+
public disConnectDevice = async (deviceId: string) => {
|
|
531
|
+
this.removeDevById(deviceId);
|
|
532
|
+
const { errMsg } = await wx.closeBLEConnection({
|
|
533
|
+
deviceId,
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
if (errMsg === 'closeBLEConnection:ok') {
|
|
537
|
+
return {
|
|
538
|
+
err: errMsg,
|
|
539
|
+
success: true,
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
return {
|
|
543
|
+
err: errMsg,
|
|
544
|
+
success: false,
|
|
545
|
+
};
|
|
546
|
+
};
|
|
547
|
+
|
|
548
|
+
private removeDevById = (deviceId: string) => {
|
|
549
|
+
const targetIdx = this.connectedList.findIndex(
|
|
550
|
+
(connectedDev) => connectedDev.deviceId === deviceId
|
|
551
|
+
);
|
|
552
|
+
this.connectedList.splice(targetIdx, 1);
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
private getTargetDevice = (deviceId: string) => {
|
|
556
|
+
const targetDevice = this.connectedList.find(
|
|
557
|
+
(device) => deviceId === device.deviceId
|
|
558
|
+
);
|
|
559
|
+
if (!targetDevice)
|
|
560
|
+
return {
|
|
561
|
+
errMsg: 'Unable get this device,maybe you forgot to connect it.',
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
return targetDevice;
|
|
565
|
+
};
|
|
566
|
+
}
|
package/src/errorCode.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
interface IErrorCode {
|
|
2
|
+
[key: string]: IError;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
const errorCode: IErrorCode = {
|
|
6
|
+
GIZ_OPENAPI_DEVICE_NOT_BOUND: {
|
|
7
|
+
errorCode: 9017,
|
|
8
|
+
errorMessage: 'not bind'
|
|
9
|
+
},
|
|
10
|
+
GIZ_SDK_HTTP_REQUEST_FAILED: {
|
|
11
|
+
errorCode: 8099,
|
|
12
|
+
errorMessage: '网络请求失败'
|
|
13
|
+
},
|
|
14
|
+
GIZ_SDK_SDK_NOT_INITIALIZED: {
|
|
15
|
+
errorCode: 8300,
|
|
16
|
+
errorMessage: 'not init'
|
|
17
|
+
},
|
|
18
|
+
CONFIG_TIME_OUT: {
|
|
19
|
+
errorCode: 8023,
|
|
20
|
+
errorMessage: 'Config Timeout'
|
|
21
|
+
},
|
|
22
|
+
WECHAT_ERROR: {
|
|
23
|
+
errorCode: 10000,
|
|
24
|
+
errorMessage: 'wechat error'
|
|
25
|
+
},
|
|
26
|
+
GIZ_SDK_ONBOARDING_STOPPED: {
|
|
27
|
+
errorCode: 8318,
|
|
28
|
+
errorMessage: '配网中断'
|
|
29
|
+
},
|
|
30
|
+
GIZ_SDK_DEVICE_CONFIG_IS_RUNNING: {
|
|
31
|
+
errorCode: 8022,
|
|
32
|
+
errorMessage: '配置正在进行中'
|
|
33
|
+
},
|
|
34
|
+
GIZ_OPENAPI_TOKEN_INVALID: {
|
|
35
|
+
errorCode: 9004,
|
|
36
|
+
errorMessage: 'token 失效'
|
|
37
|
+
},
|
|
38
|
+
GIZ_SDK_BIND_DEVICE_FAILED: {
|
|
39
|
+
errorCode: 8039,
|
|
40
|
+
errorMessage: '设备绑定失败'
|
|
41
|
+
},
|
|
42
|
+
GIZ_SDK_BLE_BLUETOOTH_FUNCTION_NOT_TURNED_ON: {
|
|
43
|
+
errorCode: 8281,
|
|
44
|
+
errorMessage: "蓝牙未启用"
|
|
45
|
+
},
|
|
46
|
+
GIZ_SDK_OTHERWISE: {
|
|
47
|
+
errorCode: 8100,
|
|
48
|
+
errorMessage: ''
|
|
49
|
+
},
|
|
50
|
+
GIZ_SDK_DEVICE_NOT_SUBSCRIBED: {
|
|
51
|
+
errorCode: 8029,
|
|
52
|
+
errorMessage: '设备还未订阅'
|
|
53
|
+
},
|
|
54
|
+
GIZ_SDK_PRODUCTKEY_NOT_IN_SPECIFY: {
|
|
55
|
+
errorCode: 8250,
|
|
56
|
+
errorMessage: '产品类型不在指定范围内',
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export default errorCode;
|
package/src/global.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
interface IError {
|
|
2
|
+
errorCode: number;
|
|
3
|
+
errorMessage?: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
interface ICommonObj {
|
|
7
|
+
[key: string]: any
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface IDeviceStatusChangedProps {
|
|
11
|
+
did: string;
|
|
12
|
+
attrs: ICommonObj;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface IDeviceRawStatusChangedProps {
|
|
16
|
+
did: string;
|
|
17
|
+
raw: Uint8Array;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface IOnDeviceStatusChanged {
|
|
21
|
+
(data: IDeviceStatusChangedProps | IDeviceRawStatusChangedProps): void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface IDevice {
|
|
25
|
+
mac: string;
|
|
26
|
+
productKey: string;
|
|
27
|
+
did: string;
|
|
28
|
+
name: string;
|
|
29
|
+
isBind: boolean;
|
|
30
|
+
rootDeviceId?: string;
|
|
31
|
+
bleDeviceID?: string;
|
|
32
|
+
remark?: string;
|
|
33
|
+
connectType: TConnectType;
|
|
34
|
+
isOnline: boolean; // 代表大循环在线
|
|
35
|
+
isLanOnline: boolean; // 代表小循环在线
|
|
36
|
+
isBleOnline: boolean; // 代表蓝牙在线
|
|
37
|
+
host?: string;
|
|
38
|
+
wss_port?: number;
|
|
39
|
+
ctime?: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
type TConnectType = 'BLE' | 'LAN' | 'WAN' | 'NONE';
|