mini_program_gizwits_sdk 3.7.0-kuka → 3.7.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/README.md +96 -25
- package/{index.ts → dist/index.d.ts} +3 -3
- package/dist/index.js +5 -5
- package/global.d.ts +3 -19
- package/package.json +5 -5
- package/yarn-error.log +34 -34
- package/src/GizLog.ts +0 -51
- package/src/aepApi/aepApiRequest.ts +0 -61
- package/src/crc/calculators/crc16modbus.ts +0 -36
- package/src/crc/calculators/crc32.ts +0 -47
- package/src/crc/crc16modbus.ts +0 -3
- package/src/crc/crc32.ts +0 -4
- package/src/crc/create_buffer.ts +0 -7
- package/src/crc/define_crc.ts +0 -9
- package/src/crc/index.ts +0 -10
- package/src/crc/package.json +0 -3
- package/src/crc/types.ts +0 -10
- package/src/errorCode.ts +0 -84
- package/src/global.d.ts +0 -53
- package/src/globalData.ts +0 -9
- package/src/handler/EventListener.ts +0 -44
- package/src/handler/ble.ts +0 -1485
- package/src/handler/lan.ts +0 -409
- package/src/handler/socket.ts +0 -625
- package/src/openApiRequest.ts +0 -62
- package/src/productConfigFileManage.ts +0 -58
- package/src/protocol/Bind.ts +0 -22
- package/src/protocol/DeviceInfo.ts +0 -36
- package/src/protocol/DiscoverUDP.ts +0 -80
- package/src/protocol/GetDeviceStatus.ts +0 -63
- package/src/protocol/Login.ts +0 -43
- package/src/protocol/Ntp.ts +0 -13
- package/src/protocol/OTA/AwaitNoti.ts +0 -14
- package/src/protocol/OTA/CheckCanOTA.ts +0 -23
- package/src/protocol/OTA/OTAPackPackage.ts +0 -36
- package/src/protocol/OTA/OtaComplete.ts +0 -17
- package/src/protocol/OTA/PreOTA.ts +0 -47
- package/src/protocol/OTA/ResetPosition.ts +0 -14
- package/src/protocol/OffLineData.ts +0 -81
- package/src/protocol/ProtocolBase.ts +0 -54
- package/src/protocol/Reset.ts +0 -15
- package/src/protocol/SetReset.ts +0 -11
- package/src/protocol/WifiConfig.ts +0 -42
- package/src/protocol/dataPoint.ts +0 -769
- package/src/protocol/thirdProtocol/YunZhiMianBleProtocolBase.ts +0 -39
- package/src/protocol/tool.ts +0 -147
- package/src/randomCode.ts +0 -36
- package/src/request.ts +0 -22
- package/src/sdk.ts +0 -1472
- package/src/sentry.ts +0 -55
- package/src/services/devices.ts +0 -309
- package/src/services/login.ts +0 -15
- package/src/services/ota.ts +0 -30
- package/src/services/tool.ts +0 -10
- package/src/services/uploadP0.ts +0 -56
- package/src/sleep.ts +0 -2
- package/src/types/index.ts +0 -48
- package/src/utils.ts +0 -419
- package/src/wechatApi.ts +0 -210
- package/src/wifiConfig/ConfigBase.ts +0 -185
- package/src/wifiConfig/ap.ts +0 -192
- package/src/wifiConfig/ble.ts +0 -436
- package/src/wifiConfig/ble_ailCloud.ts +0 -554
package/src/handler/ble.ts
DELETED
|
@@ -1,1485 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ab2hex,
|
|
3
|
-
ab2numbers,
|
|
4
|
-
arrayBufferToWordArray,
|
|
5
|
-
BTDevice2GDevice,
|
|
6
|
-
convertToServiceUuids,
|
|
7
|
-
isSameDevice,
|
|
8
|
-
numberArray2Uint8Array,
|
|
9
|
-
parseBroadcastData,
|
|
10
|
-
unionBy,
|
|
11
|
-
wrapErrorInfo,
|
|
12
|
-
} from '../utils';
|
|
13
|
-
import { downloadFile, retryConnect, unpackWriteBLECharacteristicValue } from '../wechatApi';
|
|
14
|
-
import Bind from '../protocol/Bind';
|
|
15
|
-
import { hexStrint2byte } from '../protocol/tool';
|
|
16
|
-
import ProtocolBase from '../protocol/ProtocolBase';
|
|
17
|
-
import YunZhiMianBleProtocolBase from '../protocol/thirdProtocol/YunZhiMianBleProtocolBase';
|
|
18
|
-
import Login from '../protocol/Login';
|
|
19
|
-
import GetDeviceStatus from '../protocol/GetDeviceStatus';
|
|
20
|
-
import { padBoradcastData } from '../protocol/DataPoint';
|
|
21
|
-
import GizLog from '../GizLog';
|
|
22
|
-
import EventListener from './EventListener';
|
|
23
|
-
import sleep from '../sleep';
|
|
24
|
-
import Reset from '../protocol/Reset';
|
|
25
|
-
import DeviceInfo from '../protocol/DeviceInfo';
|
|
26
|
-
import { CheckOTAParams, StartUpgradeParams, TBleDataListener } from '../types';
|
|
27
|
-
import { IResult } from '../sdk';
|
|
28
|
-
import errorCode from '../errorCode';
|
|
29
|
-
import { checkUpdate } from '../services/ota';
|
|
30
|
-
import CheckCanOTA from '../protocol/OTA/CheckCanOTA';
|
|
31
|
-
import PreOTA from '../protocol/OTA/PreOTA';
|
|
32
|
-
import AwaitNoti from '../protocol/OTA/AwaitNoti';
|
|
33
|
-
import { MD5 } from 'crypto-js';
|
|
34
|
-
import { crc32 } from '../crc';
|
|
35
|
-
import ResetPosition from '../protocol/OTA/ResetPosition';
|
|
36
|
-
import OTAPackPackage from '../protocol/OTA/OTAPackPackage';
|
|
37
|
-
import OtaComplete from '../protocol/OTA/OtaComplete';
|
|
38
|
-
|
|
39
|
-
type GizBleDeviceListotifications = (devices: IDevice[]) => void;
|
|
40
|
-
type GizBleDeviceDataNotifications = (
|
|
41
|
-
curDevice: WechatMiniprogram.OnBLECharacteristicValueChangeCallbackResult,
|
|
42
|
-
hexString: string
|
|
43
|
-
) => void;
|
|
44
|
-
type GizBleErrorNotifications = (err: { errCode: number; errMsg: string }) => void;
|
|
45
|
-
|
|
46
|
-
export interface TBleHandleEvent {
|
|
47
|
-
GizBleDeviceData: GizBleDeviceDataNotifications;
|
|
48
|
-
GizBleDeviceList: GizBleDeviceListotifications;
|
|
49
|
-
GizBleError: GizBleErrorNotifications;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export interface GizwitsWxBlueToothDevice extends WechatMiniprogram.BlueToothDevice {
|
|
53
|
-
communicationType: 'BLE_BROADCAST' | 'BLE';
|
|
54
|
-
RSSI: number;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
interface BleHandleParams {
|
|
58
|
-
serviceUUIDSuffix: string;
|
|
59
|
-
serviceUUIDSuffix2: string;
|
|
60
|
-
characteristicUUIDSuffix: string;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export interface IStartScanResult {
|
|
64
|
-
scanList: IDevice[];
|
|
65
|
-
err?: ReturnType<typeof wrapErrorInfo>;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
interface IDeviceReq<T> {
|
|
69
|
-
success: boolean;
|
|
70
|
-
data: T;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// export type BleHandle = ReturnType<typeof createBleHandle>;
|
|
74
|
-
|
|
75
|
-
export type OnScanDevice = (scanList: IDevice[]) => void;
|
|
76
|
-
interface ConnectDevice {
|
|
77
|
-
deviceId?: string;
|
|
78
|
-
serviceId?: string;
|
|
79
|
-
characteristicId?: string;
|
|
80
|
-
errMsg?: string;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
interface ConstructorParams {
|
|
84
|
-
pks: string[];
|
|
85
|
-
bleHandleParams?: BleHandleParams;
|
|
86
|
-
offlineThreshold?: number;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
interface IOtaSession {
|
|
90
|
-
cancelled: boolean;
|
|
91
|
-
cancelHandlers: Set<() => void>;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export class BleHandle extends EventListener<TBleHandleEvent> {
|
|
95
|
-
private serviceUUIDSuffix: string;
|
|
96
|
-
private serviceUUIDSuffix2: string;
|
|
97
|
-
// private characteristicUUIDSuffix: string;
|
|
98
|
-
public connectedList: ConnectDevice[] = [];
|
|
99
|
-
private connectingDevId: string | null = null;
|
|
100
|
-
private pks: string[] = [];
|
|
101
|
-
private listenDevOfflineTimer: any = null;
|
|
102
|
-
private listenBluetoothDeviceFoundNoneTimer: any = null;
|
|
103
|
-
private MAX_BLE_SCAN_INVERTER = 1000 * 60 * 5 - 1;
|
|
104
|
-
private startScanParams: any = null;
|
|
105
|
-
// 是否正在执行扫描
|
|
106
|
-
private isScanning = false;
|
|
107
|
-
|
|
108
|
-
private boradcastTimer: any;
|
|
109
|
-
private boradcastDataCache: any = {};
|
|
110
|
-
private baseServices: string[] = [];
|
|
111
|
-
|
|
112
|
-
private tmpBleData = ''; // 接收分包数据用
|
|
113
|
-
private tmpDataNum = 0; // 剩余字节数
|
|
114
|
-
private disableScanFlag = false;
|
|
115
|
-
|
|
116
|
-
private peripheralServer: WechatMiniprogram.BLEPeripheralServer | null = null;
|
|
117
|
-
|
|
118
|
-
private isActive = true; // 小程序是否活跃
|
|
119
|
-
|
|
120
|
-
private otaSessionMap: Record<string, IOtaSession> = {};
|
|
121
|
-
|
|
122
|
-
// private globalListenerMap = {};
|
|
123
|
-
public scanList: IDevice[] = [];
|
|
124
|
-
constructor({
|
|
125
|
-
pks = [],
|
|
126
|
-
bleHandleParams = {
|
|
127
|
-
serviceUUIDSuffix: 'fe60',
|
|
128
|
-
serviceUUIDSuffix2: 'abf0',
|
|
129
|
-
characteristicUUIDSuffix: 'fe61',
|
|
130
|
-
},
|
|
131
|
-
offlineThreshold,
|
|
132
|
-
}: ConstructorParams) {
|
|
133
|
-
super();
|
|
134
|
-
const { serviceUUIDSuffix, serviceUUIDSuffix2 } = bleHandleParams;
|
|
135
|
-
this.serviceUUIDSuffix = serviceUUIDSuffix;
|
|
136
|
-
this.serviceUUIDSuffix2 = serviceUUIDSuffix2;
|
|
137
|
-
this.pks = pks;
|
|
138
|
-
// TODO
|
|
139
|
-
// 不要直接使用 globalListenerMap
|
|
140
|
-
// addDeviceDataListener addDeviceListListener addBleErrorListener
|
|
141
|
-
// 或 addEventListener 参数 deviceData deviceList error
|
|
142
|
-
// this.globalListenerMap = globalListenerMap;
|
|
143
|
-
|
|
144
|
-
this.listenDevOffline(offlineThreshold ?? 10000);
|
|
145
|
-
this.listenConnection();
|
|
146
|
-
this.listenBluetoothDeviceFoundNone();
|
|
147
|
-
|
|
148
|
-
wx.onAppShow(this.onAppShow);
|
|
149
|
-
wx.onAppHide(this.onAppHide);
|
|
150
|
-
|
|
151
|
-
wx.onBluetoothAdapterStateChange(this.onBluetoothAdapterStateChange);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
private onBluetoothAdapterStateChange = (res: WechatMiniprogram.OnBluetoothAdapterStateChangeCallbackResult) => {
|
|
155
|
-
GizLog.debug('onBluetoothAdapterStateChange', res);
|
|
156
|
-
if (res.available) {
|
|
157
|
-
// this.startScan(() => {}, 4000);
|
|
158
|
-
} else {
|
|
159
|
-
// 不可用状态
|
|
160
|
-
this.scanList = [];
|
|
161
|
-
this.notifyDevices();
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
private onAppShow = () => {
|
|
166
|
-
// 更新所有蓝牙设备的Ctime
|
|
167
|
-
this.isActive = true;
|
|
168
|
-
this.scanList.map(item => {
|
|
169
|
-
item.ctime = Date.now();
|
|
170
|
-
});
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
private onAppHide = () => {
|
|
174
|
-
this.isActive = false;
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
private listenDevOffline = (offlineThreshold: number) => {
|
|
178
|
-
// 定时检查设备列表,移除超时设备
|
|
179
|
-
this.listenDevOfflineTimer = setInterval(() => {
|
|
180
|
-
// 非激活状态不处理
|
|
181
|
-
if (!this.isActive) return;
|
|
182
|
-
const now = new Date().getTime();
|
|
183
|
-
const newDeviceList = this.scanList.filter(d => {
|
|
184
|
-
const isConnected = this.connectedList.find(item => d.bleDeviceID == item.deviceId);
|
|
185
|
-
const isConnecting = this.connectingDevId === d.bleDeviceID;
|
|
186
|
-
// 已经连接不删除
|
|
187
|
-
if (isConnected || isConnecting) {
|
|
188
|
-
return true;
|
|
189
|
-
}
|
|
190
|
-
// 广播类型的设备由于性能问题,双倍的时间才触发离线
|
|
191
|
-
if (d.connectType === 'BLE_BROADCAST') {
|
|
192
|
-
return now - d.ctime < offlineThreshold * 2;
|
|
193
|
-
}
|
|
194
|
-
return now - d.ctime < offlineThreshold;
|
|
195
|
-
});
|
|
196
|
-
if (newDeviceList.length !== this.scanList.length) {
|
|
197
|
-
const lossDevices = this.scanList.filter(d => !newDeviceList.find(newD => isSameDevice(newD, d)));
|
|
198
|
-
GizLog.warn('timestamp:', now, '\n', 'BLE devices offline:', lossDevices);
|
|
199
|
-
this.scanList = newDeviceList;
|
|
200
|
-
// TODO 不要直接修改保护的对象
|
|
201
|
-
// this.gizSdk.bleDevices = newDeviceList;
|
|
202
|
-
this.notifyDevices();
|
|
203
|
-
}
|
|
204
|
-
}, 500);
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
private openBluetoothAdapter = (mode: 'central' | 'peripheral' = 'central') => {
|
|
208
|
-
return new Promise((resolve, reject) => {
|
|
209
|
-
wx.openBluetoothAdapter({
|
|
210
|
-
mode,
|
|
211
|
-
success: () => {
|
|
212
|
-
resolve({ success: true });
|
|
213
|
-
wx.onBLECharacteristicValueChange(this.handleOnBLECharacteristicValueChange);
|
|
214
|
-
},
|
|
215
|
-
fail: err => {
|
|
216
|
-
GizLog.error('openBluetoothAdapter fail', new Error(JSON.stringify(err)));
|
|
217
|
-
this.notifyError({ errMsg: err.errMsg, errCode: -1 });
|
|
218
|
-
reject({ success: false, err });
|
|
219
|
-
},
|
|
220
|
-
});
|
|
221
|
-
});
|
|
222
|
-
};
|
|
223
|
-
|
|
224
|
-
private getProtocolBase = ({
|
|
225
|
-
device,
|
|
226
|
-
hexString,
|
|
227
|
-
curDeviceValue,
|
|
228
|
-
}: {
|
|
229
|
-
device: IDevice;
|
|
230
|
-
hexString: any;
|
|
231
|
-
curDeviceValue: ArrayBuffer;
|
|
232
|
-
}) => {
|
|
233
|
-
const hexData = hexStrint2byte(hexString);
|
|
234
|
-
if (
|
|
235
|
-
device.productKey === '67a95f560e464453be079c5723a4a85c' ||
|
|
236
|
-
device.productKey === '0b58c73f12064eb897aa005cf43d6a1b' ||
|
|
237
|
-
device.productKey === '4b286229884f4711bcdbaefdfb5f76b9'
|
|
238
|
-
) {
|
|
239
|
-
const data = new YunZhiMianBleProtocolBase(hexData);
|
|
240
|
-
return {
|
|
241
|
-
data,
|
|
242
|
-
needWaitLen: data.len - curDeviceValue.byteLength,
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
const data = new ProtocolBase(hexData);
|
|
246
|
-
return {
|
|
247
|
-
data,
|
|
248
|
-
needWaitLen: data.len - curDeviceValue.byteLength + 4 + Math.ceil(data.len.toString(2).length / 8), // 还需要等待接收的数据长度
|
|
249
|
-
};
|
|
250
|
-
};
|
|
251
|
-
|
|
252
|
-
private handleOnBLECharacteristicValueChange = async (
|
|
253
|
-
curDevice: WechatMiniprogram.OnBLECharacteristicValueChangeCallbackResult
|
|
254
|
-
) => {
|
|
255
|
-
// 不存在数据
|
|
256
|
-
if (!curDevice.value) {
|
|
257
|
-
return;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
const tagrgetDevice = this.scanList.find(i => i.bleDeviceID === curDevice.deviceId);
|
|
261
|
-
if (tagrgetDevice) {
|
|
262
|
-
const hexString = ab2hex(curDevice.value);
|
|
263
|
-
try {
|
|
264
|
-
const { needWaitLen } = this.getProtocolBase({
|
|
265
|
-
device: tagrgetDevice,
|
|
266
|
-
hexString,
|
|
267
|
-
curDeviceValue: curDevice.value,
|
|
268
|
-
});
|
|
269
|
-
// console.log('需要等待的包的长度', needWaitLen);
|
|
270
|
-
// 能解析包头,覆盖数据
|
|
271
|
-
this.tmpBleData = hexString;
|
|
272
|
-
this.tmpDataNum = needWaitLen;
|
|
273
|
-
} catch (error) {
|
|
274
|
-
// 无法解析包头
|
|
275
|
-
if (this.tmpBleData) {
|
|
276
|
-
// 有没有接收完的数据
|
|
277
|
-
this.tmpBleData += hexString;
|
|
278
|
-
this.tmpDataNum -= curDevice.value.byteLength;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
if (this.tmpDataNum > 0 || !this.tmpBleData) {
|
|
283
|
-
// 没有接收完数据 或者没有有效数据
|
|
284
|
-
return;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
this.notiDeviceDataToSdk(curDevice, this.tmpBleData);
|
|
288
|
-
|
|
289
|
-
this.tmpBleData = '';
|
|
290
|
-
this.tmpDataNum = 0;
|
|
291
|
-
} else {
|
|
292
|
-
GizLog.info('GIZ_SDK: 没有找到设备', curDevice);
|
|
293
|
-
}
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
private notiDeviceDataToSdk = (
|
|
297
|
-
curDevice: WechatMiniprogram.OnBLECharacteristicValueChangeCallbackResult,
|
|
298
|
-
data: string
|
|
299
|
-
) => {
|
|
300
|
-
if (this.listenerMap['GizBleDeviceData']) {
|
|
301
|
-
this.listenerMap['GizBleDeviceData'].map(item => {
|
|
302
|
-
item(curDevice, data);
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
};
|
|
306
|
-
|
|
307
|
-
private notifyError = (err: { errCode: number; errMsg: string }) => {
|
|
308
|
-
// TODO 具体是哪台设备的错误信息
|
|
309
|
-
// this.globalListenerMap['onBleHandleError']?.map((notifyFn) => {
|
|
310
|
-
// notifyFn(err);
|
|
311
|
-
// });
|
|
312
|
-
if (this.listenerMap['GizBleError']) {
|
|
313
|
-
this.listenerMap['GizBleError'].map(item => {
|
|
314
|
-
item(err);
|
|
315
|
-
});
|
|
316
|
-
}
|
|
317
|
-
};
|
|
318
|
-
|
|
319
|
-
private notifyDevices = () => {
|
|
320
|
-
if (this.listenerMap['GizBleDeviceList']) {
|
|
321
|
-
this.listenerMap['GizBleDeviceList'].map(item => {
|
|
322
|
-
item(this.scanList);
|
|
323
|
-
});
|
|
324
|
-
}
|
|
325
|
-
};
|
|
326
|
-
|
|
327
|
-
private listenConnection = () => {
|
|
328
|
-
/**
|
|
329
|
-
* 之前的写法会导致每订阅一个设备都会创建一次监听
|
|
330
|
-
* 监听也不会销毁
|
|
331
|
-
* 但是这里其实sdk来做重连也有一定的歧义
|
|
332
|
-
* 比如说设备被重置之后,假设有逻辑做了解除连接,但是可能会被这里救起来
|
|
333
|
-
* 另一个角度来分析,蓝牙连接上之后,没有那么容易断开
|
|
334
|
-
*/
|
|
335
|
-
wx.onBLEConnectionStateChange(res => {
|
|
336
|
-
if (res.connected === false) {
|
|
337
|
-
const index = this.connectedList.findIndex(item => item.deviceId === res.deviceId);
|
|
338
|
-
if (index !== -1) {
|
|
339
|
-
this.connectedList.splice(index, 1);
|
|
340
|
-
this.notifyDevices();
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
});
|
|
344
|
-
};
|
|
345
|
-
|
|
346
|
-
private init = async () => {
|
|
347
|
-
const { platform } = wx.getSystemInfoSync();
|
|
348
|
-
await this.openBluetoothAdapter();
|
|
349
|
-
if (platform === 'ios') {
|
|
350
|
-
// ios 需要打开两次
|
|
351
|
-
await this.openBluetoothAdapter('peripheral');
|
|
352
|
-
}
|
|
353
|
-
let BLEPeripheralServerRes = true;
|
|
354
|
-
// 初始化广播
|
|
355
|
-
try {
|
|
356
|
-
this.peripheralServer = (await wx.createBLEPeripheralServer()).server;
|
|
357
|
-
GizLog.info('GIZ_SDK: 广播初始化成功', this.peripheralServer);
|
|
358
|
-
} catch (error) {
|
|
359
|
-
GizLog.error('GIZ_SDK: 广播初始化失败', new Error(JSON.stringify(error)));
|
|
360
|
-
BLEPeripheralServerRes = false;
|
|
361
|
-
}
|
|
362
|
-
if (platform === 'android' && BLEPeripheralServerRes === false) {
|
|
363
|
-
/**
|
|
364
|
-
* 安卓 微信拿不到发现附近设备的授权(android version >= 12)
|
|
365
|
-
* init方法的返回值改为false 交给应用层处理
|
|
366
|
-
* 避免安卓无附近设备授权时 蓝牙初始化依旧是成功的(按道理是失败)
|
|
367
|
-
*/
|
|
368
|
-
return { success: false, message: '安卓设备:GIZ_SDK初始化蓝牙广播失败' };
|
|
369
|
-
}
|
|
370
|
-
const res = await this.getBluetoothAdapterState();
|
|
371
|
-
return res;
|
|
372
|
-
};
|
|
373
|
-
|
|
374
|
-
public checkPermission = async () => {
|
|
375
|
-
const settings = await wx.getSetting();
|
|
376
|
-
const hasBlePermission = settings.authSetting['scope.bluetooth'];
|
|
377
|
-
|
|
378
|
-
if (!hasBlePermission) {
|
|
379
|
-
try {
|
|
380
|
-
await wx.authorize({ scope: 'scope.bluetooth' });
|
|
381
|
-
return await this.init();
|
|
382
|
-
} catch (err) {
|
|
383
|
-
GizLog.log('授权失败', err);
|
|
384
|
-
// remove me in the future
|
|
385
|
-
this.openBluetoothAdapter();
|
|
386
|
-
this.notifyError({ errMsg: err.errMsg, errCode: -1 });
|
|
387
|
-
}
|
|
388
|
-
} else {
|
|
389
|
-
return await this.init();
|
|
390
|
-
}
|
|
391
|
-
};
|
|
392
|
-
|
|
393
|
-
private getBluetoothAdapterState = async () => {
|
|
394
|
-
GizLog.log('getBluetoothAdapterState', await wx.getBluetoothAdapterState());
|
|
395
|
-
const { errMsg, available, ...adaptState } = await wx.getBluetoothAdapterState();
|
|
396
|
-
return {
|
|
397
|
-
data: {
|
|
398
|
-
...adaptState,
|
|
399
|
-
},
|
|
400
|
-
err: wrapErrorInfo(errMsg),
|
|
401
|
-
success: available,
|
|
402
|
-
};
|
|
403
|
-
};
|
|
404
|
-
|
|
405
|
-
getDeviceStatus = async (deviceId: string, productKey: string, gwDid?: string, attrNames?: string[]) => {
|
|
406
|
-
const value = await GetDeviceStatus.pack(productKey, gwDid, attrNames);
|
|
407
|
-
if (value) {
|
|
408
|
-
return await this.write(deviceId, numberArray2Uint8Array(value).buffer);
|
|
409
|
-
}
|
|
410
|
-
return {
|
|
411
|
-
success: false,
|
|
412
|
-
};
|
|
413
|
-
};
|
|
414
|
-
|
|
415
|
-
private updateDevice = (device: IDevice) => {
|
|
416
|
-
// 更新蓝牙设备到scanlist
|
|
417
|
-
const id = device.bleDeviceID;
|
|
418
|
-
const index = this.scanList.findIndex(item => id == item.bleDeviceID);
|
|
419
|
-
if (index !== -1) {
|
|
420
|
-
this.scanList[index] = device;
|
|
421
|
-
}
|
|
422
|
-
};
|
|
423
|
-
|
|
424
|
-
private updateCtime = (device: WechatMiniprogram.BlueToothDevice) => {
|
|
425
|
-
const id = device.deviceId;
|
|
426
|
-
const index = this.scanList.findIndex(item => id == item.bleDeviceID);
|
|
427
|
-
if (index !== -1) {
|
|
428
|
-
this.scanList[index].ctime = Date.now();
|
|
429
|
-
}
|
|
430
|
-
};
|
|
431
|
-
|
|
432
|
-
private checkDeviceIsChange = (a: IDevice, b: IDevice) => {
|
|
433
|
-
//检查设备是否发生变更
|
|
434
|
-
|
|
435
|
-
if (
|
|
436
|
-
a.bleWorkStatus !== b.bleWorkStatus ||
|
|
437
|
-
a.name !== b.name ||
|
|
438
|
-
a.isBleOnline !== b.isBleOnline ||
|
|
439
|
-
a.isOnline !== b.isOnline
|
|
440
|
-
) {
|
|
441
|
-
return true;
|
|
442
|
-
}
|
|
443
|
-
return false;
|
|
444
|
-
};
|
|
445
|
-
|
|
446
|
-
private handleBluetoothDeviceFound = (
|
|
447
|
-
resData: WechatMiniprogram.OnBluetoothDeviceFoundCallbackResult,
|
|
448
|
-
onScanDevice: OnScanDevice
|
|
449
|
-
) => {
|
|
450
|
-
/**
|
|
451
|
-
* TODO
|
|
452
|
-
* 流程可以优化
|
|
453
|
-
* 这里多次解析了设备的广播内容
|
|
454
|
-
*/
|
|
455
|
-
(unionBy(resData.devices, 'deviceId') as GizwitsWxBlueToothDevice[]).map(device => {
|
|
456
|
-
const { advertisData, deviceId, name, localName } = device;
|
|
457
|
-
|
|
458
|
-
const advertisDataStr = ab2hex(advertisData);
|
|
459
|
-
|
|
460
|
-
// 从服务uuid里面扫描广播类的设备
|
|
461
|
-
let broadcastCmdData: any = null;
|
|
462
|
-
try {
|
|
463
|
-
broadcastCmdData = parseBroadcastData(ab2numbers(advertisData));
|
|
464
|
-
} catch (error) { }
|
|
465
|
-
|
|
466
|
-
const targetBleDev = this.scanList.find(d => d.bleDeviceID === deviceId);
|
|
467
|
-
// 先检查是否是广播设备的业务指令,如果是就更新数据,不往下判断
|
|
468
|
-
if (broadcastCmdData && broadcastCmdData.cmd === 0x94) {
|
|
469
|
-
// 业务指令
|
|
470
|
-
const advertisDataString = ab2hex(advertisData);
|
|
471
|
-
if (this.boradcastDataCache[deviceId] && this.boradcastDataCache[deviceId] === advertisDataString) {
|
|
472
|
-
// 广播包数据相同,已经处理过了,不再处理
|
|
473
|
-
return false;
|
|
474
|
-
}
|
|
475
|
-
if (!targetBleDev) {
|
|
476
|
-
// 目标设备不存在
|
|
477
|
-
return false;
|
|
478
|
-
}
|
|
479
|
-
this.boradcastDataCache[deviceId] = ab2hex(advertisData);
|
|
480
|
-
const fullData = padBoradcastData(broadcastCmdData.data.map(item => parseInt(item, 16)));
|
|
481
|
-
|
|
482
|
-
this.updateCtime(device);
|
|
483
|
-
this.notiDeviceDataToSdk(device as any, fullData);
|
|
484
|
-
return;
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
// 是广播设备,并且是发现包的命令
|
|
488
|
-
if (broadcastCmdData && broadcastCmdData.cmd === 0x19) {
|
|
489
|
-
const target = this.pks.find(item => item === broadcastCmdData.data.join(''));
|
|
490
|
-
|
|
491
|
-
if (target) {
|
|
492
|
-
// 更新通讯方式
|
|
493
|
-
device.communicationType = 'BLE_BROADCAST';
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
// 开始解析普通设备
|
|
498
|
-
if (targetBleDev) {
|
|
499
|
-
// 存在设备,更新ctime 并更新属性
|
|
500
|
-
const newDevice = BTDevice2GDevice(device, this.pks);
|
|
501
|
-
|
|
502
|
-
if (newDevice.productKey && newDevice.mac) {
|
|
503
|
-
// 广播设备没有 bleWorkStatus
|
|
504
|
-
const isChange = this.checkDeviceIsChange(newDevice, targetBleDev);
|
|
505
|
-
// 更新设备(保留RSSI,因为BTDevice2GDevice会覆盖)
|
|
506
|
-
newDevice.ctime = Date.now();
|
|
507
|
-
// RSSI单独更新,不触发回调
|
|
508
|
-
targetBleDev.RSSI = newDevice.RSSI;
|
|
509
|
-
this.updateDevice(newDevice);
|
|
510
|
-
// GizLog.debug("GIZ_SDK: same device", newDevice, isChange);
|
|
511
|
-
if (isChange) {
|
|
512
|
-
onScanDevice(this.scanList);
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
} else {
|
|
516
|
-
// 新增设备
|
|
517
|
-
let isValidDevice = this.pks.some(pk => advertisDataStr.includes(pk));
|
|
518
|
-
if (isValidDevice) {
|
|
519
|
-
// device.communicationType = 'BLE';
|
|
520
|
-
const newDevice = BTDevice2GDevice(device, this.pks);
|
|
521
|
-
GizLog.debug('insert ble device', newDevice);
|
|
522
|
-
if (newDevice.productKey && newDevice.mac) {
|
|
523
|
-
this.scanList.push(newDevice);
|
|
524
|
-
onScanDevice(this.scanList);
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
});
|
|
529
|
-
};
|
|
530
|
-
|
|
531
|
-
private listenBluetoothDeviceFoundNone = () => {
|
|
532
|
-
this.listenBluetoothDeviceFoundNoneTimer = setInterval(() => {
|
|
533
|
-
const now = new Date().getTime();
|
|
534
|
-
if (!this.startScanParams || !this.startScanParams.lastStartScanTimestamp || !this.isScanning) return;
|
|
535
|
-
const tooLongScanning = now - this.startScanParams.lastStartScanTimestamp > this.MAX_BLE_SCAN_INVERTER;
|
|
536
|
-
if (tooLongScanning && !this.disableScanFlag) {
|
|
537
|
-
this.stopScan();
|
|
538
|
-
this.startScanParams.lastStartScanTimestamp = now;
|
|
539
|
-
GizLog.warn('SDK RESTART SCAN BLE', '\n', 'timestamp:', now);
|
|
540
|
-
sleep(1000).then(() => {
|
|
541
|
-
this.startScan(
|
|
542
|
-
this.startScanParams.onScanDevice,
|
|
543
|
-
this.startScanParams.delay,
|
|
544
|
-
this.startScanParams.services || null
|
|
545
|
-
);
|
|
546
|
-
});
|
|
547
|
-
}
|
|
548
|
-
}, 3000);
|
|
549
|
-
};
|
|
550
|
-
|
|
551
|
-
public startScan = async (onScanDevice: OnScanDevice, delay: number = 5000, services?: string[]) => {
|
|
552
|
-
if (this.disableScanFlag) {
|
|
553
|
-
return {
|
|
554
|
-
scanList: [],
|
|
555
|
-
};
|
|
556
|
-
}
|
|
557
|
-
if (!this.startScanParams) {
|
|
558
|
-
const params = { onScanDevice, delay, services, lastStartScanTimestamp: new Date().getTime() };
|
|
559
|
-
this.startScanParams = params;
|
|
560
|
-
}
|
|
561
|
-
this.isScanning = true;
|
|
562
|
-
return new Promise<IStartScanResult>(async res => {
|
|
563
|
-
wx.onBluetoothDeviceFound(resData => {
|
|
564
|
-
this.handleBluetoothDeviceFound(resData, onScanDevice);
|
|
565
|
-
});
|
|
566
|
-
|
|
567
|
-
GizLog.debug('GIZ_SDK: start scan', delay);
|
|
568
|
-
await wx.startBluetoothDevicesDiscovery({
|
|
569
|
-
// 如果有传的话,就按传入的方式来搜索
|
|
570
|
-
services: services || this.baseServices,
|
|
571
|
-
powerLevel: 'high',
|
|
572
|
-
allowDuplicatesKey: true,
|
|
573
|
-
interval: 200,
|
|
574
|
-
});
|
|
575
|
-
|
|
576
|
-
if (delay > 0) {
|
|
577
|
-
setTimeout(() => {
|
|
578
|
-
this.stopScan();
|
|
579
|
-
res({
|
|
580
|
-
scanList: this.scanList,
|
|
581
|
-
});
|
|
582
|
-
}, delay);
|
|
583
|
-
}
|
|
584
|
-
});
|
|
585
|
-
};
|
|
586
|
-
|
|
587
|
-
public stopScan = async () => {
|
|
588
|
-
try {
|
|
589
|
-
this.isScanning = false;
|
|
590
|
-
return await wx.stopBluetoothDevicesDiscovery();
|
|
591
|
-
} catch (error) {
|
|
592
|
-
return error;
|
|
593
|
-
}
|
|
594
|
-
};
|
|
595
|
-
|
|
596
|
-
public disableScan = async () => {
|
|
597
|
-
this.disableScanFlag = true;
|
|
598
|
-
const data = await wx.stopBluetoothDevicesDiscovery();
|
|
599
|
-
// 等系统通知停止扫描
|
|
600
|
-
await sleep(200);
|
|
601
|
-
return data;
|
|
602
|
-
};
|
|
603
|
-
|
|
604
|
-
public enableScan = () => {
|
|
605
|
-
this.disableScanFlag = false;
|
|
606
|
-
};
|
|
607
|
-
|
|
608
|
-
public connectDevice = async (deviceId: string) => {
|
|
609
|
-
// 先锁定这个设备 防止被剔除
|
|
610
|
-
try {
|
|
611
|
-
this.connectingDevId = deviceId;
|
|
612
|
-
try {
|
|
613
|
-
// 连接前 先停止搜索
|
|
614
|
-
await this.disableScan();
|
|
615
|
-
const connectRes = await retryConnect(deviceId);
|
|
616
|
-
this.enableScan();
|
|
617
|
-
GizLog.debug('connect res', connectRes);
|
|
618
|
-
GizLog.debug('===蓝牙连接成功===', new Date().getTime());
|
|
619
|
-
|
|
620
|
-
// if (connectRes && connectRes.errCode == 0 && connectRes.errMsg === 'createBLEConnection:ok') {
|
|
621
|
-
// this.listenConnection(deviceId);
|
|
622
|
-
// }
|
|
623
|
-
} catch (error) {
|
|
624
|
-
// 已经连接,继续往下走登录流程
|
|
625
|
-
GizLog.error('GIZ_SDK: createBLEConnection error', new Error(JSON.stringify(error)));
|
|
626
|
-
if (error?.errMsg !== 'createBLEConnection:fail:already connect') {
|
|
627
|
-
this.notifyError(error);
|
|
628
|
-
return { success: false, message: error?.errMsg };
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
const getServicesRes = (await wx.getBLEDeviceServices({ deviceId }).catch(err => this.notifyError(err))) as any;
|
|
633
|
-
|
|
634
|
-
const serviceId = getServicesRes?.services.find(
|
|
635
|
-
service =>
|
|
636
|
-
service.isPrimary &&
|
|
637
|
-
(service.uuid.toLowerCase().includes(this.serviceUUIDSuffix) ||
|
|
638
|
-
service.uuid.toLowerCase().includes(this.serviceUUIDSuffix2))
|
|
639
|
-
)?.uuid;
|
|
640
|
-
if (!serviceId) {
|
|
641
|
-
return {
|
|
642
|
-
message: 'can not find valid serviceId',
|
|
643
|
-
success: false,
|
|
644
|
-
};
|
|
645
|
-
}
|
|
646
|
-
const serviceUUIDIsGizwits = getServicesRes?.services.find(
|
|
647
|
-
service => service.isPrimary && service.uuid.toLowerCase().includes(this.serviceUUIDSuffix2)
|
|
648
|
-
);
|
|
649
|
-
|
|
650
|
-
const getCharRes = (await wx
|
|
651
|
-
.getBLEDeviceCharacteristics({
|
|
652
|
-
deviceId,
|
|
653
|
-
serviceId,
|
|
654
|
-
})
|
|
655
|
-
.catch(err => this.notifyError(err))) as any;
|
|
656
|
-
|
|
657
|
-
const characteristicId = getCharRes?.characteristics[0].uuid!;
|
|
658
|
-
|
|
659
|
-
// 登录成功 把设备插入 connectedList
|
|
660
|
-
const isNewDevice = this.connectedList.every(device => device.deviceId !== deviceId);
|
|
661
|
-
isNewDevice && this.connectedList.push({ deviceId, serviceId, characteristicId });
|
|
662
|
-
|
|
663
|
-
// 连接成功以后默认监听设备
|
|
664
|
-
await wx
|
|
665
|
-
.notifyBLECharacteristicValueChange({
|
|
666
|
-
deviceId,
|
|
667
|
-
serviceId,
|
|
668
|
-
characteristicId,
|
|
669
|
-
state: true,
|
|
670
|
-
type: 'notification',
|
|
671
|
-
})
|
|
672
|
-
.catch(err => this.notifyError(err));
|
|
673
|
-
|
|
674
|
-
if (serviceUUIDIsGizwits) {
|
|
675
|
-
this.write(deviceId, numberArray2Uint8Array(Bind.pack()).buffer);
|
|
676
|
-
const data = await this.handleBindReq(deviceId);
|
|
677
|
-
GizLog.log('handleBindReq', data);
|
|
678
|
-
|
|
679
|
-
if (data.success) {
|
|
680
|
-
this.write(deviceId, numberArray2Uint8Array(Login.pack({ passcode: data.data })).buffer);
|
|
681
|
-
const loginData = (await this.handleLoginReq(deviceId).catch(err => this.notifyError(err))) as any;
|
|
682
|
-
if (loginData?.success) {
|
|
683
|
-
// 登录成功后查询一下 重置状态
|
|
684
|
-
// 不主动下发,等设备回复
|
|
685
|
-
// this.write(deviceId, numberArray2Uint8Array(Reset.pack()).buffer);
|
|
686
|
-
return {
|
|
687
|
-
success: true,
|
|
688
|
-
message: 'ok',
|
|
689
|
-
};
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
// 绑定失败,异常退出断开蓝牙
|
|
694
|
-
await wx.closeBLEConnection({
|
|
695
|
-
deviceId,
|
|
696
|
-
});
|
|
697
|
-
|
|
698
|
-
return {
|
|
699
|
-
success: false,
|
|
700
|
-
message: 'ok',
|
|
701
|
-
};
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
return {
|
|
705
|
-
success: true,
|
|
706
|
-
message: 'ok',
|
|
707
|
-
};
|
|
708
|
-
} finally {
|
|
709
|
-
this.connectingDevId = null;
|
|
710
|
-
}
|
|
711
|
-
};
|
|
712
|
-
|
|
713
|
-
/**
|
|
714
|
-
*
|
|
715
|
-
* @param deviceId
|
|
716
|
-
* @param filter
|
|
717
|
-
* @returns
|
|
718
|
-
* 监听指定设备的原始数据
|
|
719
|
-
* 3s超时,用来处理和设备一来一回的交互
|
|
720
|
-
*/
|
|
721
|
-
private handleWatchBleData = async <T>(
|
|
722
|
-
deviceId: string,
|
|
723
|
-
filter: TBleDataListener<T>,
|
|
724
|
-
timeout = 3000,
|
|
725
|
-
session?: IOtaSession
|
|
726
|
-
): Promise<IResult<T>> => {
|
|
727
|
-
return new Promise(res => {
|
|
728
|
-
let resolved = false;
|
|
729
|
-
let timeoutId: ReturnType<typeof setTimeout> | null = null;
|
|
730
|
-
let watchWapper: GizBleDeviceDataNotifications | null = null;
|
|
731
|
-
|
|
732
|
-
const finish = (result: IResult<T>) => {
|
|
733
|
-
if (resolved) {
|
|
734
|
-
return;
|
|
735
|
-
}
|
|
736
|
-
resolved = true;
|
|
737
|
-
if (timeoutId) {
|
|
738
|
-
clearTimeout(timeoutId);
|
|
739
|
-
timeoutId = null;
|
|
740
|
-
}
|
|
741
|
-
if (watchWapper) {
|
|
742
|
-
this.removeEventListener('GizBleDeviceData', watchWapper);
|
|
743
|
-
watchWapper = null;
|
|
744
|
-
}
|
|
745
|
-
if (session) {
|
|
746
|
-
session.cancelHandlers.delete(onSessionCancel);
|
|
747
|
-
}
|
|
748
|
-
res(result);
|
|
749
|
-
};
|
|
750
|
-
|
|
751
|
-
const onSessionCancel = () => {
|
|
752
|
-
finish({
|
|
753
|
-
success: false,
|
|
754
|
-
err: errorCode.GIZ_SDK_OTA_DEVICE_BUSY_IN_UPGRADE,
|
|
755
|
-
});
|
|
756
|
-
};
|
|
757
|
-
|
|
758
|
-
if (session) {
|
|
759
|
-
if (session.cancelled) {
|
|
760
|
-
onSessionCancel();
|
|
761
|
-
return;
|
|
762
|
-
}
|
|
763
|
-
session.cancelHandlers.add(onSessionCancel);
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
watchWapper = (_curDevice, hexString) => {
|
|
767
|
-
if (session?.cancelled) {
|
|
768
|
-
onSessionCancel();
|
|
769
|
-
return;
|
|
770
|
-
}
|
|
771
|
-
if (deviceId !== _curDevice.deviceId) {
|
|
772
|
-
return;
|
|
773
|
-
}
|
|
774
|
-
const resData = filter(_curDevice, hexString);
|
|
775
|
-
if (resData) {
|
|
776
|
-
finish({
|
|
777
|
-
success: true,
|
|
778
|
-
data: resData,
|
|
779
|
-
});
|
|
780
|
-
}
|
|
781
|
-
};
|
|
782
|
-
this.addEventListener('GizBleDeviceData', watchWapper);
|
|
783
|
-
|
|
784
|
-
timeoutId = setTimeout(() => {
|
|
785
|
-
finish({
|
|
786
|
-
success: false,
|
|
787
|
-
err: errorCode.GIZ_SDK_DEVICE_NO_RESPONSE,
|
|
788
|
-
});
|
|
789
|
-
}, timeout);
|
|
790
|
-
});
|
|
791
|
-
};
|
|
792
|
-
|
|
793
|
-
private handleBindReq = (deviceId: string) => {
|
|
794
|
-
// 处理设备回复绑定消息
|
|
795
|
-
return new Promise<IDeviceReq<string>>(res => {
|
|
796
|
-
const onListener = (
|
|
797
|
-
_curDevice: WechatMiniprogram.OnBLECharacteristicValueChangeCallbackResult,
|
|
798
|
-
hexString: string
|
|
799
|
-
) => {
|
|
800
|
-
if (_curDevice.deviceId !== deviceId) {
|
|
801
|
-
return;
|
|
802
|
-
}
|
|
803
|
-
GizLog.log('监听蓝牙特征值发生变化');
|
|
804
|
-
const bindData = new Bind(hexStrint2byte(hexString));
|
|
805
|
-
this.removeEventListener('GizBleDeviceData', onListener);
|
|
806
|
-
if (bindData.passcode) {
|
|
807
|
-
// 存在passcode
|
|
808
|
-
res({
|
|
809
|
-
success: true,
|
|
810
|
-
data: bindData.passcode,
|
|
811
|
-
});
|
|
812
|
-
} else {
|
|
813
|
-
res({
|
|
814
|
-
success: false,
|
|
815
|
-
data: '',
|
|
816
|
-
});
|
|
817
|
-
}
|
|
818
|
-
};
|
|
819
|
-
|
|
820
|
-
this.watchBleDevice(deviceId, onListener);
|
|
821
|
-
});
|
|
822
|
-
};
|
|
823
|
-
|
|
824
|
-
private createOtaSession(deviceId: string): IOtaSession {
|
|
825
|
-
this.cancelOtaSession(deviceId);
|
|
826
|
-
const session: IOtaSession = {
|
|
827
|
-
cancelled: false,
|
|
828
|
-
cancelHandlers: new Set(),
|
|
829
|
-
};
|
|
830
|
-
this.otaSessionMap[deviceId] = session;
|
|
831
|
-
return session;
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
private cancelOtaSession(deviceId: string) {
|
|
835
|
-
const session = this.otaSessionMap[deviceId];
|
|
836
|
-
if (!session) {
|
|
837
|
-
return;
|
|
838
|
-
}
|
|
839
|
-
session.cancelled = true;
|
|
840
|
-
session.cancelHandlers.forEach(handler => handler());
|
|
841
|
-
session.cancelHandlers.clear();
|
|
842
|
-
delete this.otaSessionMap[deviceId];
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
private releaseOtaSession(deviceId: string, session: IOtaSession) {
|
|
846
|
-
const current = this.otaSessionMap[deviceId];
|
|
847
|
-
if (current === session) {
|
|
848
|
-
session.cancelHandlers.clear();
|
|
849
|
-
delete this.otaSessionMap[deviceId];
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
private handleLoginReq = deviceId => {
|
|
854
|
-
return new Promise<IDeviceReq<String>>(res => {
|
|
855
|
-
const onListener = (
|
|
856
|
-
_curDevice: WechatMiniprogram.OnBLECharacteristicValueChangeCallbackResult,
|
|
857
|
-
hexString: string
|
|
858
|
-
) => {
|
|
859
|
-
//TODO 销毁监听
|
|
860
|
-
if (_curDevice.deviceId !== deviceId) {
|
|
861
|
-
return;
|
|
862
|
-
}
|
|
863
|
-
GizLog.log('设备回复LoginReq', hexString);
|
|
864
|
-
const loginData = new Login(hexStrint2byte(hexString));
|
|
865
|
-
this.removeEventListener('GizBleDeviceData', onListener);
|
|
866
|
-
if (loginData.result === true) {
|
|
867
|
-
res({
|
|
868
|
-
success: true,
|
|
869
|
-
data: loginData.did,
|
|
870
|
-
});
|
|
871
|
-
} else {
|
|
872
|
-
res({
|
|
873
|
-
success: false,
|
|
874
|
-
data: '',
|
|
875
|
-
});
|
|
876
|
-
}
|
|
877
|
-
};
|
|
878
|
-
this.watchBleDevice(deviceId, onListener);
|
|
879
|
-
});
|
|
880
|
-
};
|
|
881
|
-
|
|
882
|
-
public startUpgrade = async ({ device, type, onEvent, onProgress, productKey }: StartUpgradeParams) => {
|
|
883
|
-
// 上报开始
|
|
884
|
-
onEvent({ code: 'GizOTAEventPretreatment' });
|
|
885
|
-
const res = await this.checkUpdate({ device, type });
|
|
886
|
-
GizLog.warn('检查设备是否有新固件', res);
|
|
887
|
-
const deviceId = device.bleDeviceID;
|
|
888
|
-
const otaSession = this.createOtaSession(deviceId);
|
|
889
|
-
|
|
890
|
-
const buildBusyResult = () => ({
|
|
891
|
-
success: false,
|
|
892
|
-
err: errorCode.GIZ_SDK_OTA_DEVICE_BUSY_IN_UPGRADE,
|
|
893
|
-
});
|
|
894
|
-
|
|
895
|
-
try {
|
|
896
|
-
if (!res.success) {
|
|
897
|
-
return res;
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
const url = (res.data as any).download_url;
|
|
901
|
-
const softVer = (res.data as any).soft_ver;
|
|
902
|
-
// 开始下载
|
|
903
|
-
onEvent({ code: 'GizOTAEventDownload' });
|
|
904
|
-
let fileUrl = '';
|
|
905
|
-
try {
|
|
906
|
-
const downloadRes = await downloadFile({
|
|
907
|
-
url,
|
|
908
|
-
});
|
|
909
|
-
fileUrl = (downloadRes as any).tempFilePath;
|
|
910
|
-
} catch (error) {
|
|
911
|
-
GizLog.error('固件下载失败', error);
|
|
912
|
-
|
|
913
|
-
return {
|
|
914
|
-
success: false,
|
|
915
|
-
err: errorCode.GIZ_SDK_OTA_FIRMWARE_DOWNLOAD_FAILED,
|
|
916
|
-
};
|
|
917
|
-
}
|
|
918
|
-
GizLog.warn('下载固件成功', fileUrl);
|
|
919
|
-
|
|
920
|
-
if (otaSession.cancelled) {
|
|
921
|
-
GizLog.warn('检测到 OTA 会话被抢占,停止继续处理');
|
|
922
|
-
return buildBusyResult();
|
|
923
|
-
}
|
|
924
|
-
|
|
925
|
-
// 开始传输
|
|
926
|
-
onEvent({ code: 'GizOTAEventTransmit' });
|
|
927
|
-
|
|
928
|
-
/**
|
|
929
|
-
* 询问设备是否可以升级
|
|
930
|
-
*/
|
|
931
|
-
const filterCanUpdateFunc = (_, hexString) => {
|
|
932
|
-
const bleBytesData = hexStrint2byte(hexString);
|
|
933
|
-
const parseData = new ProtocolBase(bleBytesData);
|
|
934
|
-
switch (parseData.cmd) {
|
|
935
|
-
case '0042': {
|
|
936
|
-
const data = new CheckCanOTA(bleBytesData);
|
|
937
|
-
return data;
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
return null;
|
|
941
|
-
};
|
|
942
|
-
/**
|
|
943
|
-
* 监听预升级设备回复
|
|
944
|
-
*/
|
|
945
|
-
const filterPreUpdateFunc = (_, hexString) => {
|
|
946
|
-
const bleBytesData = hexStrint2byte(hexString);
|
|
947
|
-
const parseData = new ProtocolBase(bleBytesData);
|
|
948
|
-
switch (parseData.cmd) {
|
|
949
|
-
case '0044': {
|
|
950
|
-
const data = new PreOTA(bleBytesData);
|
|
951
|
-
return data;
|
|
952
|
-
}
|
|
953
|
-
}
|
|
954
|
-
return null;
|
|
955
|
-
};
|
|
956
|
-
/**
|
|
957
|
-
* 等待设备通知可以继续ota
|
|
958
|
-
*/
|
|
959
|
-
const filterAwaitOtaContinueFunc = (_, hexString) => {
|
|
960
|
-
const bleBytesData = hexStrint2byte(hexString);
|
|
961
|
-
const parseData = new ProtocolBase(bleBytesData);
|
|
962
|
-
switch (parseData.cmd) {
|
|
963
|
-
case '0052': {
|
|
964
|
-
const data = new AwaitNoti(bleBytesData);
|
|
965
|
-
return data;
|
|
966
|
-
}
|
|
967
|
-
}
|
|
968
|
-
return null;
|
|
969
|
-
};
|
|
970
|
-
GizLog.warn('查询设备是否可以OTA');
|
|
971
|
-
|
|
972
|
-
if (otaSession.cancelled) {
|
|
973
|
-
return buildBusyResult();
|
|
974
|
-
}
|
|
975
|
-
const canUpdataData = CheckCanOTA.pack(type);
|
|
976
|
-
await this.write(deviceId, numberArray2Uint8Array(canUpdataData).buffer);
|
|
977
|
-
if (otaSession.cancelled) {
|
|
978
|
-
return buildBusyResult();
|
|
979
|
-
}
|
|
980
|
-
const canUpdateRes = await this.handleWatchBleData<CheckCanOTA>(deviceId, filterCanUpdateFunc, 3000, otaSession);
|
|
981
|
-
|
|
982
|
-
GizLog.warn('设备回复是否可以OTA', canUpdateRes);
|
|
983
|
-
|
|
984
|
-
if (!canUpdateRes.success) {
|
|
985
|
-
return canUpdateRes;
|
|
986
|
-
}
|
|
987
|
-
|
|
988
|
-
if (canUpdateRes.data.type !== type) {
|
|
989
|
-
// 类型不匹配
|
|
990
|
-
GizLog.error(null, new Error('OTA类型不匹配'));
|
|
991
|
-
|
|
992
|
-
return {
|
|
993
|
-
success: false,
|
|
994
|
-
err: errorCode.GIZ_SDK_OTA_FIRMWARE_TYPE_NOT_MATCH,
|
|
995
|
-
};
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
if (canUpdateRes.data.state !== 0) {
|
|
999
|
-
return buildBusyResult();
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
// 允许更新 发送预升级请求
|
|
1003
|
-
// 获取文件 计算md5 和 crc
|
|
1004
|
-
const fs = wx.getFileSystemManager();
|
|
1005
|
-
let fileData: any = [];
|
|
1006
|
-
try {
|
|
1007
|
-
fileData = await fs.readFileSync(fileUrl, 'hex', 0);
|
|
1008
|
-
} catch (error) {
|
|
1009
|
-
GizLog.error('读取固件失败', error);
|
|
1010
|
-
return {
|
|
1011
|
-
success: false,
|
|
1012
|
-
err: errorCode.GIZ_SDK_OTA_FIRMWARE_DOWNLOAD_FAILED,
|
|
1013
|
-
};
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
if (otaSession.cancelled) {
|
|
1017
|
-
return buildBusyResult();
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1020
|
-
const byteArray = fileData.match(/.{1,2}/g).map(function (byte) {
|
|
1021
|
-
return parseInt(byte, 16);
|
|
1022
|
-
});
|
|
1023
|
-
const wordArray = arrayBufferToWordArray(byteArray);
|
|
1024
|
-
const md5 = MD5(wordArray).toString();
|
|
1025
|
-
|
|
1026
|
-
const crc32Data = crc32(byteArray);
|
|
1027
|
-
|
|
1028
|
-
const preOtaData = PreOTA.pack(productKey, softVer, md5, byteArray.length, crc32Data);
|
|
1029
|
-
|
|
1030
|
-
await this.write(deviceId, numberArray2Uint8Array(preOtaData).buffer);
|
|
1031
|
-
if (otaSession.cancelled) {
|
|
1032
|
-
return buildBusyResult();
|
|
1033
|
-
}
|
|
1034
|
-
const preOtaRes = await this.handleWatchBleData<PreOTA>(deviceId, filterPreUpdateFunc, 5 * 1000, otaSession);
|
|
1035
|
-
|
|
1036
|
-
GizLog.warn('设备回复ota 预请求', preOtaRes);
|
|
1037
|
-
|
|
1038
|
-
if (!preOtaRes.success) {
|
|
1039
|
-
return preOtaRes;
|
|
1040
|
-
}
|
|
1041
|
-
|
|
1042
|
-
if (preOtaRes.data.state !== 0) {
|
|
1043
|
-
// pre ota 失败,提示错误
|
|
1044
|
-
return {
|
|
1045
|
-
success: false,
|
|
1046
|
-
};
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
|
-
// 开始位置
|
|
1050
|
-
let startPoint = 0;
|
|
1051
|
-
|
|
1052
|
-
if (preOtaRes.data.processedLen > 0) {
|
|
1053
|
-
// 校对已接收的crc32 和当前文件相同部分的crc32 是否相同
|
|
1054
|
-
const currentProcessedCrc32 = crc32(byteArray.slice(0, preOtaRes.data.processedLen)).toString(16);
|
|
1055
|
-
if (currentProcessedCrc32 === preOtaRes.data.processedCrc32) {
|
|
1056
|
-
//如果相同
|
|
1057
|
-
startPoint = preOtaRes.data.processedLen;
|
|
1058
|
-
GizLog.warn(`断点续传,从 ${startPoint} 开始`);
|
|
1059
|
-
} else {
|
|
1060
|
-
GizLog.warn(`从位置0开始OTA`);
|
|
1061
|
-
|
|
1062
|
-
// 如果不相同,包可能发生了问题,通知设备从0 开始
|
|
1063
|
-
await this.write(deviceId, numberArray2Uint8Array(ResetPosition.pack(0)).buffer);
|
|
1064
|
-
await sleep(100);
|
|
1065
|
-
}
|
|
1066
|
-
}
|
|
1067
|
-
|
|
1068
|
-
/**
|
|
1069
|
-
* 开始发送数据包
|
|
1070
|
-
*/
|
|
1071
|
-
// 总固件长度
|
|
1072
|
-
const fileLen = byteArray.length;
|
|
1073
|
-
// 最大包长度
|
|
1074
|
-
const maxPackageLen = preOtaRes.data.packageMaxLen;
|
|
1075
|
-
// 当前包号
|
|
1076
|
-
let packageIndex = Math.ceil(startPoint / maxPackageLen);
|
|
1077
|
-
|
|
1078
|
-
let repeatNum = 0; // 当前重试次数
|
|
1079
|
-
|
|
1080
|
-
while (startPoint < fileLen) {
|
|
1081
|
-
if (otaSession.cancelled) {
|
|
1082
|
-
GizLog.warn('OTA 会话被新的请求打断,终止数据发送');
|
|
1083
|
-
return buildBusyResult();
|
|
1084
|
-
}
|
|
1085
|
-
const packageData = byteArray.slice(startPoint, startPoint + maxPackageLen);
|
|
1086
|
-
|
|
1087
|
-
// 组包
|
|
1088
|
-
const otaPackage = OTAPackPackage.pack(packageData, packageIndex);
|
|
1089
|
-
// 发送
|
|
1090
|
-
await this.write(deviceId, numberArray2Uint8Array(otaPackage).buffer);
|
|
1091
|
-
if (otaSession.cancelled) {
|
|
1092
|
-
GizLog.warn('OTA 会话被新的请求打断,终止等待反馈');
|
|
1093
|
-
return buildBusyResult();
|
|
1094
|
-
}
|
|
1095
|
-
const filterOtaProgressFunc = (_, hexString) => {
|
|
1096
|
-
const bleBytesData = hexStrint2byte(hexString);
|
|
1097
|
-
const parseData = new ProtocolBase(bleBytesData);
|
|
1098
|
-
switch (parseData.cmd) {
|
|
1099
|
-
case '0048': {
|
|
1100
|
-
const data = new OTAPackPackage(bleBytesData);
|
|
1101
|
-
if (data.packageNum === packageIndex) {
|
|
1102
|
-
// 返回包号相同的数据
|
|
1103
|
-
return data;
|
|
1104
|
-
}
|
|
1105
|
-
return null;
|
|
1106
|
-
}
|
|
1107
|
-
}
|
|
1108
|
-
return null;
|
|
1109
|
-
};
|
|
1110
|
-
// 监听回复
|
|
1111
|
-
const otaRes = await this.handleWatchBleData<OTAPackPackage>(
|
|
1112
|
-
deviceId,
|
|
1113
|
-
filterOtaProgressFunc,
|
|
1114
|
-
5 * 1000,
|
|
1115
|
-
otaSession
|
|
1116
|
-
);
|
|
1117
|
-
let hasError = false;
|
|
1118
|
-
if (otaRes.success === false) {
|
|
1119
|
-
if (otaRes.err === errorCode.GIZ_SDK_OTA_DEVICE_BUSY_IN_UPGRADE) {
|
|
1120
|
-
return otaRes;
|
|
1121
|
-
}
|
|
1122
|
-
hasError = true;
|
|
1123
|
-
}
|
|
1124
|
-
|
|
1125
|
-
if (otaRes.success && otaRes.data.state !== 0 && otaRes.data.state !== 4) hasError = true;
|
|
1126
|
-
if (hasError) {
|
|
1127
|
-
repeatNum += 1;
|
|
1128
|
-
GizLog.warn(`发送OTA包失败,重试次数 ${repeatNum}`, otaRes);
|
|
1129
|
-
|
|
1130
|
-
// 错误计数加1 重试
|
|
1131
|
-
if (repeatNum > 3) {
|
|
1132
|
-
// ota 失败,断开连接,返回错误
|
|
1133
|
-
GizLog.warn(`发送OTA包失败次数超过限制`);
|
|
1134
|
-
return {
|
|
1135
|
-
success: false,
|
|
1136
|
-
};
|
|
1137
|
-
}
|
|
1138
|
-
continue;
|
|
1139
|
-
}
|
|
1140
|
-
|
|
1141
|
-
GizLog.warn('设备接收ota子包成功', otaRes);
|
|
1142
|
-
|
|
1143
|
-
// 发送成功,重新计数
|
|
1144
|
-
repeatNum = 0;
|
|
1145
|
-
|
|
1146
|
-
// 回复成功移动指针
|
|
1147
|
-
startPoint += maxPackageLen;
|
|
1148
|
-
packageIndex += 1;
|
|
1149
|
-
|
|
1150
|
-
let currentProgress = parseInt(`${((packageIndex * maxPackageLen) / fileLen) * 100}`);
|
|
1151
|
-
if (currentProgress > 100) currentProgress = 100;
|
|
1152
|
-
onProgress({
|
|
1153
|
-
firmwareSize: fileLen,
|
|
1154
|
-
packageMaxLen: maxPackageLen,
|
|
1155
|
-
currentNumber: packageIndex,
|
|
1156
|
-
currentProgress,
|
|
1157
|
-
});
|
|
1158
|
-
|
|
1159
|
-
// 等100ms
|
|
1160
|
-
await sleep(100);
|
|
1161
|
-
|
|
1162
|
-
if (otaSession.cancelled) {
|
|
1163
|
-
GizLog.warn('OTA 会话被新的请求打断,停止后续传输');
|
|
1164
|
-
return buildBusyResult();
|
|
1165
|
-
}
|
|
1166
|
-
|
|
1167
|
-
// 这里还需要做个判断,如果进入等待发送状态,需要等设备通知之后再继续发送
|
|
1168
|
-
if (otaRes.data.state === 4) {
|
|
1169
|
-
GizLog.warn(`设备请求等待OTA`);
|
|
1170
|
-
|
|
1171
|
-
const awaitContinueRes = await this.handleWatchBleData<AwaitNoti>(
|
|
1172
|
-
deviceId,
|
|
1173
|
-
filterAwaitOtaContinueFunc,
|
|
1174
|
-
60 * 1000,
|
|
1175
|
-
otaSession
|
|
1176
|
-
);
|
|
1177
|
-
GizLog.warn(`设备回复等待结果`, awaitContinueRes);
|
|
1178
|
-
|
|
1179
|
-
if (!awaitContinueRes.success) {
|
|
1180
|
-
if (awaitContinueRes.err === errorCode.GIZ_SDK_OTA_DEVICE_BUSY_IN_UPGRADE) {
|
|
1181
|
-
return awaitContinueRes;
|
|
1182
|
-
}
|
|
1183
|
-
return {
|
|
1184
|
-
success: false,
|
|
1185
|
-
};
|
|
1186
|
-
}
|
|
1187
|
-
|
|
1188
|
-
if (awaitContinueRes.data.state === 1) {
|
|
1189
|
-
return {
|
|
1190
|
-
success: false,
|
|
1191
|
-
};
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
|
-
}
|
|
1195
|
-
|
|
1196
|
-
if (otaSession.cancelled) {
|
|
1197
|
-
return buildBusyResult();
|
|
1198
|
-
}
|
|
1199
|
-
|
|
1200
|
-
// 发送完所有数据包, 等待监听
|
|
1201
|
-
GizLog.warn('发送完所有数据包,等待设备回复');
|
|
1202
|
-
|
|
1203
|
-
const filterOtaResFunc = (_, hexString) => {
|
|
1204
|
-
const bleBytesData = hexStrint2byte(hexString);
|
|
1205
|
-
const parseData = new ProtocolBase(bleBytesData);
|
|
1206
|
-
switch (parseData.cmd) {
|
|
1207
|
-
case '0050': {
|
|
1208
|
-
const data = new OtaComplete(bleBytesData);
|
|
1209
|
-
return data;
|
|
1210
|
-
}
|
|
1211
|
-
}
|
|
1212
|
-
return null;
|
|
1213
|
-
};
|
|
1214
|
-
const otaCompleteRes = await this.handleWatchBleData<OtaComplete>(
|
|
1215
|
-
deviceId,
|
|
1216
|
-
filterOtaResFunc,
|
|
1217
|
-
10 * 1000,
|
|
1218
|
-
otaSession
|
|
1219
|
-
);
|
|
1220
|
-
|
|
1221
|
-
if (!otaCompleteRes.success) {
|
|
1222
|
-
return otaCompleteRes;
|
|
1223
|
-
}
|
|
1224
|
-
|
|
1225
|
-
if (otaCompleteRes.data.state === 0) {
|
|
1226
|
-
GizLog.warn('设备回复收到固件,准备重启设备');
|
|
1227
|
-
onEvent({ code: 'GizOTAEventReboot' });
|
|
1228
|
-
// 等待10s后去尝试连接设备
|
|
1229
|
-
this.disConnectDevice(deviceId);
|
|
1230
|
-
await sleep(10 * 1000);
|
|
1231
|
-
|
|
1232
|
-
if (otaSession.cancelled) {
|
|
1233
|
-
return buildBusyResult();
|
|
1234
|
-
}
|
|
1235
|
-
|
|
1236
|
-
const connectRes = await this.connectDevice(deviceId);
|
|
1237
|
-
console.log('connectRes', connectRes);
|
|
1238
|
-
if (!connectRes.success) {
|
|
1239
|
-
GizLog.warn('设备重启后,无法连接');
|
|
1240
|
-
|
|
1241
|
-
return {
|
|
1242
|
-
success: false,
|
|
1243
|
-
};
|
|
1244
|
-
}
|
|
1245
|
-
|
|
1246
|
-
// 查询设备版本号
|
|
1247
|
-
const versionRes = await this.getDeviceInfo({ deviceId });
|
|
1248
|
-
if (!versionRes.success) {
|
|
1249
|
-
GizLog.warn('获取设备版本号失败');
|
|
1250
|
-
return {
|
|
1251
|
-
success: false,
|
|
1252
|
-
};
|
|
1253
|
-
}
|
|
1254
|
-
let newSoftVersion = '';
|
|
1255
|
-
if (type === 'MCU') {
|
|
1256
|
-
newSoftVersion = versionRes.data.mcuSoftVersion;
|
|
1257
|
-
} else {
|
|
1258
|
-
newSoftVersion = versionRes.data.moduleSoftVersion;
|
|
1259
|
-
}
|
|
1260
|
-
|
|
1261
|
-
onEvent({ code: 'GizOTAEventFinish' });
|
|
1262
|
-
|
|
1263
|
-
if (newSoftVersion === softVer) {
|
|
1264
|
-
// 版本是正确的
|
|
1265
|
-
return {
|
|
1266
|
-
success: true,
|
|
1267
|
-
};
|
|
1268
|
-
}
|
|
1269
|
-
|
|
1270
|
-
GizLog.warn('设备上报版本号与更新的固件版本号不匹配,更新失败');
|
|
1271
|
-
// 版本对不上
|
|
1272
|
-
return {
|
|
1273
|
-
success: false,
|
|
1274
|
-
};
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
|
-
// 错误
|
|
1278
|
-
return {
|
|
1279
|
-
success: false,
|
|
1280
|
-
};
|
|
1281
|
-
} finally {
|
|
1282
|
-
this.releaseOtaSession(deviceId, otaSession);
|
|
1283
|
-
}
|
|
1284
|
-
};
|
|
1285
|
-
|
|
1286
|
-
public getDeviceInfo = async ({ deviceId }: { deviceId: string }) => {
|
|
1287
|
-
// 发送查询指令
|
|
1288
|
-
const value = DeviceInfo.pack();
|
|
1289
|
-
GizLog.debug('DeviceInfo.pack', value);
|
|
1290
|
-
|
|
1291
|
-
await this.write(deviceId, numberArray2Uint8Array(value).buffer);
|
|
1292
|
-
|
|
1293
|
-
const filterFunc = (_, hexString) => {
|
|
1294
|
-
const bleBytesData = hexStrint2byte(hexString);
|
|
1295
|
-
const parseData = new ProtocolBase(bleBytesData);
|
|
1296
|
-
switch (parseData.cmd) {
|
|
1297
|
-
case '0014': {
|
|
1298
|
-
try {
|
|
1299
|
-
const deviceInfoData = new DeviceInfo(bleBytesData);
|
|
1300
|
-
GizLog.debug('parse DeviceInfo', deviceInfoData);
|
|
1301
|
-
|
|
1302
|
-
return deviceInfoData;
|
|
1303
|
-
} catch (error) {
|
|
1304
|
-
GizLog.debug('parse DeviceInfo error', error);
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
1307
|
-
}
|
|
1308
|
-
return null;
|
|
1309
|
-
};
|
|
1310
|
-
|
|
1311
|
-
const versionRes = await this.handleWatchBleData<DeviceInfo>(deviceId, filterFunc);
|
|
1312
|
-
return versionRes;
|
|
1313
|
-
};
|
|
1314
|
-
|
|
1315
|
-
public checkUpdate = async ({ device, type }: CheckOTAParams) => {
|
|
1316
|
-
/**
|
|
1317
|
-
* 获取设备硬件版本号
|
|
1318
|
-
* 查询云端接口
|
|
1319
|
-
*/
|
|
1320
|
-
|
|
1321
|
-
const versionRes = await this.getDeviceInfo({ deviceId: device.bleDeviceID });
|
|
1322
|
-
|
|
1323
|
-
if (versionRes.success) {
|
|
1324
|
-
let softVersion = '';
|
|
1325
|
-
let hardVersion = '';
|
|
1326
|
-
if (type === 'MCU') {
|
|
1327
|
-
softVersion = versionRes.data.mcuSoftVersion;
|
|
1328
|
-
hardVersion = versionRes.data.mcuHardVersion;
|
|
1329
|
-
} else {
|
|
1330
|
-
softVersion = versionRes.data.moduleSoftVersion;
|
|
1331
|
-
hardVersion = versionRes.data.moduleHardVersion;
|
|
1332
|
-
}
|
|
1333
|
-
const updateRes = await checkUpdate({ did: device.did, type, softVersion, hardVersion });
|
|
1334
|
-
return updateRes;
|
|
1335
|
-
}
|
|
1336
|
-
return {
|
|
1337
|
-
success: false,
|
|
1338
|
-
err: versionRes.err,
|
|
1339
|
-
};
|
|
1340
|
-
};
|
|
1341
|
-
|
|
1342
|
-
public watchBleDevice = async (deviceId, func) => {
|
|
1343
|
-
const { serviceId, characteristicId, errMsg } = this.getTargetDevice(deviceId);
|
|
1344
|
-
if (errMsg) return { success: false, message: errMsg };
|
|
1345
|
-
await wx
|
|
1346
|
-
.notifyBLECharacteristicValueChange({
|
|
1347
|
-
deviceId,
|
|
1348
|
-
serviceId: serviceId!,
|
|
1349
|
-
characteristicId: characteristicId!,
|
|
1350
|
-
state: true,
|
|
1351
|
-
type: 'notification',
|
|
1352
|
-
})
|
|
1353
|
-
.catch(err => this.notifyError(err));
|
|
1354
|
-
|
|
1355
|
-
GizLog.log(`监听设备 ${deviceId} 成功!`);
|
|
1356
|
-
this.addEventListener('GizBleDeviceData', func);
|
|
1357
|
-
return {
|
|
1358
|
-
message: 'ok',
|
|
1359
|
-
success: true,
|
|
1360
|
-
};
|
|
1361
|
-
};
|
|
1362
|
-
|
|
1363
|
-
public writeBoradcast = async (bleDeviceID: string, value: number[]) => {
|
|
1364
|
-
const scanDevice = this.scanList.find(item => item.bleDeviceID === bleDeviceID);
|
|
1365
|
-
if (!scanDevice) {
|
|
1366
|
-
return {
|
|
1367
|
-
success: false,
|
|
1368
|
-
message: 'not found device',
|
|
1369
|
-
};
|
|
1370
|
-
}
|
|
1371
|
-
|
|
1372
|
-
if (this.boradcastTimer) {
|
|
1373
|
-
clearTimeout(this.boradcastTimer);
|
|
1374
|
-
}
|
|
1375
|
-
try {
|
|
1376
|
-
this.peripheralServer.stopAdvertising({});
|
|
1377
|
-
const serviceUuids = convertToServiceUuids({
|
|
1378
|
-
mac: scanDevice.mac,
|
|
1379
|
-
index: 0,
|
|
1380
|
-
data: value,
|
|
1381
|
-
len: value.length,
|
|
1382
|
-
});
|
|
1383
|
-
this.peripheralServer.startAdvertising({
|
|
1384
|
-
advertiseRequest: {
|
|
1385
|
-
connectable: true,
|
|
1386
|
-
serviceUuids,
|
|
1387
|
-
},
|
|
1388
|
-
powerLevel: 'high',
|
|
1389
|
-
success: data => {
|
|
1390
|
-
GizLog.debug('GIZ_SDK: startAdvertising success', data);
|
|
1391
|
-
},
|
|
1392
|
-
fail: err => {
|
|
1393
|
-
GizLog.error('GIZ_SDK: startAdvertising error', new Error(JSON.stringify(err)));
|
|
1394
|
-
},
|
|
1395
|
-
});
|
|
1396
|
-
GizLog.debug('GIZ_SDK: start adv', serviceUuids);
|
|
1397
|
-
|
|
1398
|
-
this.boradcastTimer = setTimeout(() => {
|
|
1399
|
-
this.peripheralServer.stopAdvertising({});
|
|
1400
|
-
this.boradcastTimer = null;
|
|
1401
|
-
}, 1000);
|
|
1402
|
-
return {
|
|
1403
|
-
success: true,
|
|
1404
|
-
};
|
|
1405
|
-
} catch (error) {
|
|
1406
|
-
GizLog.log('GIZ_SDK:', error);
|
|
1407
|
-
clearTimeout(this.boradcastTimer);
|
|
1408
|
-
return {
|
|
1409
|
-
success: false,
|
|
1410
|
-
message: 'send cmd error',
|
|
1411
|
-
};
|
|
1412
|
-
}
|
|
1413
|
-
};
|
|
1414
|
-
|
|
1415
|
-
public write = async (bleDeviceID: string, value: ArrayBuffer) => {
|
|
1416
|
-
GizLog.warn('app => dev:', ab2hex(value), new Date().getTime());
|
|
1417
|
-
console.log('ble write', ab2hex(value));
|
|
1418
|
-
const targetDevice = this.getTargetDevice(bleDeviceID);
|
|
1419
|
-
if (targetDevice.serviceId && targetDevice.characteristicId) {
|
|
1420
|
-
const unpackRes = await unpackWriteBLECharacteristicValue(
|
|
1421
|
-
bleDeviceID,
|
|
1422
|
-
targetDevice.serviceId,
|
|
1423
|
-
targetDevice.characteristicId,
|
|
1424
|
-
value
|
|
1425
|
-
);
|
|
1426
|
-
return unpackRes;
|
|
1427
|
-
}
|
|
1428
|
-
return {
|
|
1429
|
-
success: false,
|
|
1430
|
-
message: 'send cmd error',
|
|
1431
|
-
};
|
|
1432
|
-
};
|
|
1433
|
-
|
|
1434
|
-
/**
|
|
1435
|
-
* @description 断开设备连接
|
|
1436
|
-
*/
|
|
1437
|
-
public disConnectDevice = async (deviceId: string) => {
|
|
1438
|
-
this.removeDevById(deviceId);
|
|
1439
|
-
const { errMsg } = await wx.closeBLEConnection({
|
|
1440
|
-
deviceId,
|
|
1441
|
-
});
|
|
1442
|
-
|
|
1443
|
-
const target = this.scanList.find(item => item.bleDeviceID === deviceId);
|
|
1444
|
-
if (target) {
|
|
1445
|
-
target.ctime = Date.now();
|
|
1446
|
-
this.updateDevice(target);
|
|
1447
|
-
}
|
|
1448
|
-
|
|
1449
|
-
if (errMsg === 'closeBLEConnection:ok') {
|
|
1450
|
-
return {
|
|
1451
|
-
err: errMsg,
|
|
1452
|
-
success: true,
|
|
1453
|
-
};
|
|
1454
|
-
}
|
|
1455
|
-
return {
|
|
1456
|
-
err: errMsg,
|
|
1457
|
-
success: false,
|
|
1458
|
-
};
|
|
1459
|
-
};
|
|
1460
|
-
|
|
1461
|
-
private removeDevById = (deviceId: string) => {
|
|
1462
|
-
const targetIdx = this.connectedList.findIndex(connectedDev => connectedDev.deviceId === deviceId);
|
|
1463
|
-
if (targetIdx !== -1) {
|
|
1464
|
-
this.connectedList.splice(targetIdx, 1);
|
|
1465
|
-
}
|
|
1466
|
-
};
|
|
1467
|
-
|
|
1468
|
-
private getTargetDevice = (deviceId: string) => {
|
|
1469
|
-
const targetDevice = this.connectedList.find(device => deviceId === device.deviceId);
|
|
1470
|
-
if (!targetDevice)
|
|
1471
|
-
return {
|
|
1472
|
-
errMsg: 'Unable get this device,maybe you forgot to connect it.',
|
|
1473
|
-
};
|
|
1474
|
-
|
|
1475
|
-
return targetDevice;
|
|
1476
|
-
};
|
|
1477
|
-
|
|
1478
|
-
public destory = () => {
|
|
1479
|
-
this.listenDevOfflineTimer && clearInterval(this.listenDevOfflineTimer);
|
|
1480
|
-
this.listenBluetoothDeviceFoundNoneTimer && clearInterval(this.listenBluetoothDeviceFoundNoneTimer);
|
|
1481
|
-
wx.offAppShow(this.onAppShow);
|
|
1482
|
-
wx.offAppHide(this.onAppHide);
|
|
1483
|
-
wx.offBluetoothAdapterStateChange(this.onBluetoothAdapterStateChange);
|
|
1484
|
-
};
|
|
1485
|
-
}
|