mini_program_gizwits_sdk 3.1.12-2 → 3.1.13-1
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/index.ts +1 -1
- package/package.json +3 -3
- package/src/handler/EventListener.ts +44 -0
- package/src/{ble.ts → handler/ble.ts} +13 -54
- package/src/handler/lan.ts +368 -0
- package/src/{socket.ts → handler/socket.ts} +6 -6
- package/src/protocol/DiscoverUDP.ts +80 -0
- package/src/protocol/ProtocolBase.ts +1 -0
- package/src/protocol/tool.ts +10 -1
- package/src/sdk.ts +109 -24
- package/src/utils.ts +1 -1
package/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import 'miniprogram-api-typings';
|
|
2
2
|
import gizwitsSdk from './src/sdk';
|
|
3
3
|
import errorCode from './src/errorCode';
|
|
4
|
-
import { BleHandle } from './src/ble';
|
|
4
|
+
import { BleHandle } from './src/handler/ble';
|
|
5
5
|
|
|
6
6
|
export { errorCode, BleHandle };
|
|
7
7
|
export default gizwitsSdk;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mini_program_gizwits_sdk",
|
|
3
|
-
"version": "3.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "3.1.13-1",
|
|
4
|
+
"description": "增加局域网控制",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "node_modules/mocha/bin/_mocha -r ts-node/register tests/**/*.spec.ts -file ./tests/setup-wx.js -timeout 60s",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"chai": "^4.2.0",
|
|
32
32
|
"coveralls": "^3.0.11",
|
|
33
33
|
"istanbul": "^1.1.0-alpha.1",
|
|
34
|
-
"miniprogram-api-typings": "^3.
|
|
34
|
+
"miniprogram-api-typings": "^3.5.0",
|
|
35
35
|
"mocha": "^7.1.1",
|
|
36
36
|
"release-it": "^14.2.2",
|
|
37
37
|
"sinon": "^9.2.4",
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export default class EventListener<T> {
|
|
2
|
+
public listenerMap: any = {};
|
|
3
|
+
public addEventListener = async <K extends keyof T>(
|
|
4
|
+
type: K,
|
|
5
|
+
func: T[K]
|
|
6
|
+
) => {
|
|
7
|
+
if (!this.listenerMap[type]) {
|
|
8
|
+
// 创建一个新的
|
|
9
|
+
this.listenerMap[type] = [];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (this.listenerMap[type].indexOf(func) === -1) {
|
|
13
|
+
this.listenerMap[type].push(func);
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
success: true,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 移除事件监听
|
|
22
|
+
* @param type 事件监听名称,详见下表
|
|
23
|
+
* @param func 事件监听回调
|
|
24
|
+
* @returns
|
|
25
|
+
*/
|
|
26
|
+
public removeEventListener = <K extends keyof T>(
|
|
27
|
+
type: K,
|
|
28
|
+
func: T[K]
|
|
29
|
+
) => {
|
|
30
|
+
if (this.listenerMap[type]) {
|
|
31
|
+
const index = this.listenerMap[type].indexOf(func);
|
|
32
|
+
if (index !== -1) {
|
|
33
|
+
// 删除数组中的这一行
|
|
34
|
+
this.listenerMap[type].splice(index, 1);
|
|
35
|
+
return {
|
|
36
|
+
success: true,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
success: false,
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
}
|
|
@@ -7,16 +7,17 @@ import {
|
|
|
7
7
|
parseBroadcastData,
|
|
8
8
|
unionBy,
|
|
9
9
|
wrapErrorInfo,
|
|
10
|
-
} from '
|
|
11
|
-
import { unpackWriteBLECharacteristicValue } from '
|
|
12
|
-
import Bind from '
|
|
13
|
-
import { hexStrint2byte } from '
|
|
14
|
-
import ProtocolBase from '
|
|
15
|
-
import Login from '
|
|
16
|
-
import GetDeviceStatus from '
|
|
17
|
-
import Sdk from '
|
|
18
|
-
import { padBoradcastData } from '
|
|
19
|
-
import GizLog from '
|
|
10
|
+
} from '../utils';
|
|
11
|
+
import { unpackWriteBLECharacteristicValue } from '../wechatApi';
|
|
12
|
+
import Bind from '../protocol/Bind';
|
|
13
|
+
import { hexStrint2byte } from '../protocol/tool';
|
|
14
|
+
import ProtocolBase from '../protocol/ProtocolBase';
|
|
15
|
+
import Login from '../protocol/Login';
|
|
16
|
+
import GetDeviceStatus from '../protocol/GetDeviceStatus';
|
|
17
|
+
import Sdk from '../Sdk';
|
|
18
|
+
import { padBoradcastData } from '../protocol/DataPoint';
|
|
19
|
+
import GizLog from '../GizLog';
|
|
20
|
+
import EventListener from './EventListener';
|
|
20
21
|
|
|
21
22
|
type GizBleDeviceListotifications = (devices: IDevice[]) => void;
|
|
22
23
|
type GizBleDeviceDataNotifications = (
|
|
@@ -66,7 +67,7 @@ interface ConstructorParams {
|
|
|
66
67
|
offlineThreshold?: number;
|
|
67
68
|
}
|
|
68
69
|
|
|
69
|
-
export class BleHandle {
|
|
70
|
+
export class BleHandle extends EventListener<TBleHandleEvent> {
|
|
70
71
|
private serviceUUIDSuffix: string;
|
|
71
72
|
// private characteristicUUIDSuffix: string;
|
|
72
73
|
public connectedList: ConnectDevice[] = [];
|
|
@@ -84,7 +85,6 @@ export class BleHandle {
|
|
|
84
85
|
|
|
85
86
|
private isActive = true; // 小程序是否活跃
|
|
86
87
|
|
|
87
|
-
private listenerMap: any = {};
|
|
88
88
|
// private globalListenerMap = {};
|
|
89
89
|
public scanList: IDevice[] = [];
|
|
90
90
|
constructor({
|
|
@@ -95,6 +95,7 @@ export class BleHandle {
|
|
|
95
95
|
},
|
|
96
96
|
offlineThreshold,
|
|
97
97
|
}: ConstructorParams) {
|
|
98
|
+
super();
|
|
98
99
|
const { serviceUUIDSuffix } = bleHandleParams;
|
|
99
100
|
this.serviceUUIDSuffix = serviceUUIDSuffix;
|
|
100
101
|
this.pks = pks;
|
|
@@ -610,48 +611,6 @@ export class BleHandle {
|
|
|
610
611
|
});
|
|
611
612
|
};
|
|
612
613
|
|
|
613
|
-
public addEventListener = async <K extends keyof TBleHandleEvent>(
|
|
614
|
-
type: K,
|
|
615
|
-
func: TBleHandleEvent[K]
|
|
616
|
-
) => {
|
|
617
|
-
if (!this.listenerMap[type]) {
|
|
618
|
-
// 创建一个新的
|
|
619
|
-
this.listenerMap[type] = [];
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
if (this.listenerMap[type].indexOf(func) === -1) {
|
|
623
|
-
this.listenerMap[type].push(func);
|
|
624
|
-
}
|
|
625
|
-
return {
|
|
626
|
-
success: true,
|
|
627
|
-
};
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
/**
|
|
631
|
-
* 移除事件监听
|
|
632
|
-
* @param type 事件监听名称,详见下表
|
|
633
|
-
* @param func 事件监听回调
|
|
634
|
-
* @returns
|
|
635
|
-
*/
|
|
636
|
-
public removeEventListener = <K extends keyof TBleHandleEvent>(
|
|
637
|
-
type: K,
|
|
638
|
-
func: TBleHandleEvent[K]
|
|
639
|
-
) => {
|
|
640
|
-
if (this.listenerMap[type]) {
|
|
641
|
-
const index = this.listenerMap[type].indexOf(func);
|
|
642
|
-
if (index !== -1) {
|
|
643
|
-
// 删除数组中的这一行
|
|
644
|
-
this.listenerMap[type].splice(index, 1);
|
|
645
|
-
return {
|
|
646
|
-
success: true,
|
|
647
|
-
};
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
return {
|
|
651
|
-
success: false,
|
|
652
|
-
};
|
|
653
|
-
};
|
|
654
|
-
|
|
655
614
|
public watchBleDevice = async (
|
|
656
615
|
deviceId,
|
|
657
616
|
func
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import GizLog from "../GizLog";
|
|
2
|
+
import Bind from "../protocol/Bind";
|
|
3
|
+
import DiscoverUDP from "../protocol/DiscoverUdp";
|
|
4
|
+
import Login from "../protocol/Login";
|
|
5
|
+
import ProtocolBase from "../protocol/ProtocolBase";
|
|
6
|
+
import { arrayToString, arrayToUint8 } from "../protocol/tool";
|
|
7
|
+
import { IResult } from "../sdk";
|
|
8
|
+
import sleep from "../sleep";
|
|
9
|
+
import { ab2numbers } from "../utils";
|
|
10
|
+
import EventListener from "./EventListener";
|
|
11
|
+
|
|
12
|
+
// 局域网连接设备结构
|
|
13
|
+
interface ConnectDevice {
|
|
14
|
+
mac: string
|
|
15
|
+
productKey: string
|
|
16
|
+
socketHandle: TCPHandler
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// 局域网设备
|
|
20
|
+
interface ILanDevice extends IDevice {
|
|
21
|
+
expandData: DiscoverUDP
|
|
22
|
+
ip: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type GizLanDeviceDataNotifications = (devices: IDevice[]) => void;
|
|
26
|
+
export interface TLanHandleEvent {
|
|
27
|
+
GizLanDeviceList: GizLanDeviceDataNotifications;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
export class LanHandle extends EventListener<TLanHandleEvent> {
|
|
32
|
+
// private characteristicUUIDSuffix: string;
|
|
33
|
+
public connectedList: ConnectDevice[] = [];
|
|
34
|
+
private pks: string[] = [];
|
|
35
|
+
// private globalListenerMap = {};
|
|
36
|
+
public scanList: ILanDevice[] = [];
|
|
37
|
+
|
|
38
|
+
private boradcastTimer: any;
|
|
39
|
+
|
|
40
|
+
private UDPSocket: WechatMiniprogram.UDPSocket;
|
|
41
|
+
|
|
42
|
+
private deviceUDPPort = 12414
|
|
43
|
+
private appUDPPort = 2415
|
|
44
|
+
private offlineThreshold = 20000 // 超过20s 没有信号,则认为离线
|
|
45
|
+
private isActive = true //当前是否是前台
|
|
46
|
+
|
|
47
|
+
private listenDevOfflineTimer: any = null;
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
constructor({pks}) {
|
|
51
|
+
super();
|
|
52
|
+
this.pks = pks;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
init = () => {
|
|
56
|
+
this.UDPSocket = wx.createUDPSocket();
|
|
57
|
+
this.UDPSocket.bind();
|
|
58
|
+
this.UDPSocket.onMessage(this.onMessage);
|
|
59
|
+
this.UDPSocket.onError(this.onError);
|
|
60
|
+
GizLog.info('Start UDP Discover')
|
|
61
|
+
this.startDiscover();
|
|
62
|
+
this.listenDevOffline(this.offlineThreshold);
|
|
63
|
+
wx.onAppShow(this.onAppShow);
|
|
64
|
+
wx.onAppHide(this.onAppHide);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private onAppShow = () => {
|
|
68
|
+
// 更新所有蓝牙设备的Ctime
|
|
69
|
+
this.isActive = true;
|
|
70
|
+
this.scanList.map(item => {
|
|
71
|
+
item.ctime = Date.now();
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private onAppHide = () => {
|
|
76
|
+
this.isActive = false;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private listenDevOffline = (offlineThreshold: number) => {
|
|
80
|
+
// 定时检查设备列表,移除超时设备
|
|
81
|
+
this.listenDevOfflineTimer = setInterval(() => {
|
|
82
|
+
// 非激活状态不处理
|
|
83
|
+
if (!this.isActive) return;
|
|
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
|
+
GizLog.debug('remove lan device')
|
|
90
|
+
this.scanList = newDeviceList;
|
|
91
|
+
this.notifyDevices();
|
|
92
|
+
}
|
|
93
|
+
}, 500);
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
private notifyDevices = () => {
|
|
97
|
+
if (this.listenerMap['GizLanDeviceList']) {
|
|
98
|
+
this.listenerMap['GizLanDeviceList'].map((item) => {
|
|
99
|
+
item(this.scanList);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
isSameDevice = (deviceA: IDevice, deviceB: IDevice) => {
|
|
105
|
+
return deviceA.mac === deviceB.mac && deviceA.productKey === deviceB.productKey
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// 解除订阅
|
|
109
|
+
disConnectDevice = (target: IDevice) => {
|
|
110
|
+
const index = this.connectedList.findIndex(item => item.productKey === target.productKey && item.mac === target.mac);
|
|
111
|
+
try {
|
|
112
|
+
if (index !== -1) {
|
|
113
|
+
// 删除这个设备
|
|
114
|
+
this.connectedList[index].socketHandle.destory();
|
|
115
|
+
this.connectedList.splice(index, 1);
|
|
116
|
+
}
|
|
117
|
+
return {success: true}
|
|
118
|
+
|
|
119
|
+
} catch (error) {
|
|
120
|
+
return {success: false, err: error}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
connectDevice = async (device) => {
|
|
125
|
+
const target = this.scanList.find(item => this.isSameDevice(device, item));
|
|
126
|
+
// 检查是否有连接
|
|
127
|
+
if (!target) {
|
|
128
|
+
return {
|
|
129
|
+
success: false,
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const connectDevice = this.connectedList.find(item => this.isSameDevice(device, (item as unknown as IDevice)))
|
|
134
|
+
if (connectDevice) {
|
|
135
|
+
return {
|
|
136
|
+
success: true
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
const tcpHandler = new TCPHandler({ip: target.ip, mac: target.mac, productKey: target.productKey, onClose: this.onDeviceClose})
|
|
140
|
+
const res = await tcpHandler.connect()
|
|
141
|
+
if (res.success) {
|
|
142
|
+
this.connectedList.push({
|
|
143
|
+
mac: target.mac,
|
|
144
|
+
productKey: target.productKey,
|
|
145
|
+
socketHandle: tcpHandler,
|
|
146
|
+
})
|
|
147
|
+
} else {
|
|
148
|
+
tcpHandler.destory();
|
|
149
|
+
}
|
|
150
|
+
return res;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
onError = (err) => {
|
|
156
|
+
GizLog.warn('Discover Error', err)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
onMessage = (res: WechatMiniprogram.UDPSocketOnMessageCallbackResult) => {
|
|
160
|
+
const numberArrary = ab2numbers(res.message)
|
|
161
|
+
const discoverPackage = new DiscoverUDP(numberArrary)
|
|
162
|
+
if (discoverPackage.mac !== '' && this.pks.includes(discoverPackage.productKey)) {
|
|
163
|
+
// 合法设备
|
|
164
|
+
this.updateDevice(discoverPackage, res.remoteInfo.address)
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// tcp 设备断开连接
|
|
169
|
+
onDeviceClose = ({productKey, mac}) => {
|
|
170
|
+
const index = this.connectedList.findIndex(item => item.productKey === productKey && item.mac === mac);
|
|
171
|
+
if (index !== -1) {
|
|
172
|
+
// 删除这个设备
|
|
173
|
+
this.connectedList.splice(index, 1);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// 数据点控制
|
|
178
|
+
public write = async (device: IDevice, value: ArrayBuffer) => {
|
|
179
|
+
const index = this.connectedList.findIndex(item => this.isSameDevice(item as unknown as IDevice, device));
|
|
180
|
+
if (index !== -1) {
|
|
181
|
+
const socketHandle = this.connectedList[index].socketHandle;
|
|
182
|
+
socketHandle.write(value)
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
success: false,
|
|
186
|
+
message: 'device not sub',
|
|
187
|
+
};
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
updateDevice = (updateDevice: DiscoverUDP, ip: string) => {
|
|
191
|
+
const target = this.scanList.find(item => item.mac === updateDevice.mac);
|
|
192
|
+
if (!target) {
|
|
193
|
+
const device: ILanDevice = {
|
|
194
|
+
mac: updateDevice.mac,
|
|
195
|
+
ip,
|
|
196
|
+
productKey: updateDevice.productKey,
|
|
197
|
+
did: updateDevice.did,
|
|
198
|
+
expandData: updateDevice,
|
|
199
|
+
name: "",
|
|
200
|
+
isBind: false,
|
|
201
|
+
connectType: "NONE",
|
|
202
|
+
isOnline: false,
|
|
203
|
+
isLanOnline: true,
|
|
204
|
+
isBleOnline: false,
|
|
205
|
+
ctime: Date.now()
|
|
206
|
+
};
|
|
207
|
+
this.scanList.push(device);
|
|
208
|
+
this.notifyDevices();
|
|
209
|
+
} else {
|
|
210
|
+
// 存在设备 更新字段
|
|
211
|
+
target.ctime = Date.now()
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
sendBoradCast = () => {
|
|
216
|
+
// 发送发现包
|
|
217
|
+
if(this.UDPSocket) {
|
|
218
|
+
this.UDPSocket.send({
|
|
219
|
+
address: '255.255.255.255',
|
|
220
|
+
message: DiscoverUDP.pack(),
|
|
221
|
+
port: this.deviceUDPPort
|
|
222
|
+
})
|
|
223
|
+
GizLog.debug('Send UDP Discover')
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
private startDiscover = () => {
|
|
228
|
+
this.sendBoradCast()
|
|
229
|
+
this.boradcastTimer = setInterval(() => {
|
|
230
|
+
this.sendBoradCast()
|
|
231
|
+
}, 5000)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
public destory = () => {
|
|
235
|
+
this.boradcastTimer && clearInterval(this.boradcastTimer);
|
|
236
|
+
this.UDPSocket && this.UDPSocket.close();
|
|
237
|
+
this.listenDevOfflineTimer && clearInterval(this.listenDevOfflineTimer);
|
|
238
|
+
wx.offAppShow(this.onAppShow);
|
|
239
|
+
wx.offAppHide(this.onAppHide);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
interface ITCPHandlerProps {
|
|
245
|
+
ip: string
|
|
246
|
+
mac: string
|
|
247
|
+
productKey: string
|
|
248
|
+
onClose: (ip) => void
|
|
249
|
+
}
|
|
250
|
+
class TCPHandler {
|
|
251
|
+
private deviceTCPPort = 12416
|
|
252
|
+
private ip = ""
|
|
253
|
+
private productKey = ""
|
|
254
|
+
private mac = ""
|
|
255
|
+
private tcpHandler: WechatMiniprogram.TCPSocket = null;
|
|
256
|
+
|
|
257
|
+
private onCloseListener = ({mac, productKey}) => {}
|
|
258
|
+
|
|
259
|
+
constructor({ip, onClose, mac, productKey}: ITCPHandlerProps) {
|
|
260
|
+
this.ip = ip;
|
|
261
|
+
this.mac = mac;
|
|
262
|
+
this.productKey = productKey;
|
|
263
|
+
this.onCloseListener = onClose;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
connect = async () => {
|
|
267
|
+
// 创建
|
|
268
|
+
return new Promise<IResult<any>>(async (res) => {
|
|
269
|
+
const onConnect = () => {
|
|
270
|
+
// 发送绑定
|
|
271
|
+
const config = Bind.pack()
|
|
272
|
+
this.tcpHandler.write(arrayToUint8(config))
|
|
273
|
+
GizLog.debug('connect success try login')
|
|
274
|
+
}
|
|
275
|
+
const onError = (err) => {
|
|
276
|
+
res({
|
|
277
|
+
success: true,
|
|
278
|
+
err: err
|
|
279
|
+
})
|
|
280
|
+
}
|
|
281
|
+
const onMessage = (message: WechatMiniprogram.TCPSocketOnMessageCallbackResult) => {
|
|
282
|
+
// 接收绑定回复
|
|
283
|
+
// 然后再发起登录
|
|
284
|
+
const baseProtocol = new ProtocolBase(ab2numbers(message.message))
|
|
285
|
+
switch (baseProtocol.cmd) {
|
|
286
|
+
case '0007': {
|
|
287
|
+
// 绑定命令字的回复
|
|
288
|
+
const bindRes = new Bind(ab2numbers(message.message));
|
|
289
|
+
const loginPack = Login.pack({passcode: bindRes.passcode})
|
|
290
|
+
this.tcpHandler.write(arrayToUint8(loginPack))
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
case '0009': {
|
|
294
|
+
const loginRes = new Login(ab2numbers(message.message))
|
|
295
|
+
if (loginRes.result) {
|
|
296
|
+
// 登录成功
|
|
297
|
+
res({
|
|
298
|
+
success: true
|
|
299
|
+
})
|
|
300
|
+
// 创建监听
|
|
301
|
+
this.initListener()
|
|
302
|
+
} else {
|
|
303
|
+
// 设备通知登录失败
|
|
304
|
+
res({
|
|
305
|
+
success: false,
|
|
306
|
+
})
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
try {
|
|
313
|
+
this.tcpHandler = wx.createTCPSocket();
|
|
314
|
+
|
|
315
|
+
// 设置监听
|
|
316
|
+
this.tcpHandler.onConnect(onConnect)
|
|
317
|
+
this.tcpHandler.onError(onError)
|
|
318
|
+
this.tcpHandler.onMessage(onMessage)
|
|
319
|
+
|
|
320
|
+
this.tcpHandler.connect({
|
|
321
|
+
address: this.ip,
|
|
322
|
+
port: this.deviceTCPPort,
|
|
323
|
+
timeout: 2
|
|
324
|
+
})
|
|
325
|
+
await sleep(4000)
|
|
326
|
+
res({
|
|
327
|
+
success: false,
|
|
328
|
+
err: null
|
|
329
|
+
})
|
|
330
|
+
} catch(err) {
|
|
331
|
+
GizLog.error("connect lan error", err);
|
|
332
|
+
} finally {
|
|
333
|
+
this.tcpHandler.offConnect(onConnect)
|
|
334
|
+
this.tcpHandler.offError(onError)
|
|
335
|
+
this.tcpHandler.offMessage(onMessage)
|
|
336
|
+
}
|
|
337
|
+
})
|
|
338
|
+
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
write = (data: ArrayBuffer) => {
|
|
342
|
+
this.tcpHandler.write(data);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
onMessage = (message) => {
|
|
346
|
+
const baseProtocol = new ProtocolBase(ab2numbers(message.message))
|
|
347
|
+
GizLog.debug("on tcp message", baseProtocol)
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
onError = () => {}
|
|
351
|
+
|
|
352
|
+
onClose = () => {
|
|
353
|
+
this.onCloseListener({productKey: this.productKey, mac: this.mac})
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
initListener = () => {
|
|
357
|
+
this.tcpHandler.onError(this.onError)
|
|
358
|
+
this.tcpHandler.onMessage(this.onMessage)
|
|
359
|
+
this.tcpHandler.onClose(this.onClose)
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
destory = () => {
|
|
363
|
+
this.tcpHandler && this.tcpHandler.close();
|
|
364
|
+
this.tcpHandler.offError(this.onError)
|
|
365
|
+
this.tcpHandler.offMessage(this.onMessage)
|
|
366
|
+
this.tcpHandler.offClose(this.onClose)
|
|
367
|
+
}
|
|
368
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import errorCode from "
|
|
2
|
-
import GizLog from "
|
|
3
|
-
import request from "
|
|
4
|
-
import sleep from "
|
|
5
|
-
import { compareWXSDKVersion, isError } from '
|
|
1
|
+
import errorCode from "../errorCode";
|
|
2
|
+
import GizLog from "../GizLog";
|
|
3
|
+
import request from "../openApiRequest";
|
|
4
|
+
import sleep from "../sleep";
|
|
5
|
+
import { compareWXSDKVersion, isError } from '../utils';
|
|
6
6
|
|
|
7
7
|
// commType = 'custom' | 'attrs_v4'
|
|
8
8
|
// socketType = 'socket' | 'ssl_socket'
|
|
@@ -146,7 +146,7 @@ export default class GizwitsWS {
|
|
|
146
146
|
return res.success ? null : res.errorCode;
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
send = (did: string, raw:
|
|
149
|
+
send = (did: string, raw: number[]) => {
|
|
150
150
|
const res = this._getDeviceAndConnect(did);
|
|
151
151
|
if (isError(res)) {
|
|
152
152
|
return res;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import GizLog from "../GizLog";
|
|
2
|
+
import ProtocolBase from "./ProtocolBase";
|
|
3
|
+
import { arrayToString } from "./tool";
|
|
4
|
+
|
|
5
|
+
type TDecodeType = 'ASCII' | 'HEX'
|
|
6
|
+
type TDeviceType = 'ASCII' | 'HEX'
|
|
7
|
+
|
|
8
|
+
class DiscoverUDP extends ProtocolBase {
|
|
9
|
+
|
|
10
|
+
did = '';
|
|
11
|
+
mac = '';
|
|
12
|
+
productKey = '';
|
|
13
|
+
deviceType = 0;
|
|
14
|
+
apiUrl = "";
|
|
15
|
+
protocolVersion = ""
|
|
16
|
+
mcuVersion = ""
|
|
17
|
+
moduleVersion = ""
|
|
18
|
+
|
|
19
|
+
constructor(data: number[]) {
|
|
20
|
+
super(data);
|
|
21
|
+
let index = 0;
|
|
22
|
+
try {
|
|
23
|
+
index = this.baseParse(index, 'did')
|
|
24
|
+
index = this.baseParse(index, 'mac', 'HEX')
|
|
25
|
+
index = this.baseParse(index, 'moduleVersion')
|
|
26
|
+
index = this.baseParse(index, 'productKey')
|
|
27
|
+
index += 8
|
|
28
|
+
index = this.parseEndChat(index, 'apiUrl')
|
|
29
|
+
index = this.parseEndChat(index, 'protocolVersion')
|
|
30
|
+
this.mcuVersion = ""
|
|
31
|
+
this.content.slice(index, this.content.length).map(item => {
|
|
32
|
+
this.mcuVersion += String.fromCharCode(item);
|
|
33
|
+
})
|
|
34
|
+
} catch (error) {
|
|
35
|
+
GizLog.warn('Parse DiscoverUDP error', error)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
parseEndChat = (index, key) => {
|
|
40
|
+
let string = ''
|
|
41
|
+
const data = this.content.slice(index, this.content.length);
|
|
42
|
+
for (let i in data) {
|
|
43
|
+
const item = data[i];
|
|
44
|
+
index += 1;
|
|
45
|
+
if (item === 0){
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
string += String.fromCharCode(item);
|
|
49
|
+
}
|
|
50
|
+
this[key] = string
|
|
51
|
+
return index;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
baseParse = (index, key, type:TDecodeType = 'ASCII') => {
|
|
55
|
+
const len = parseInt(arrayToString(this.content.slice(index, index + 2)), 16);
|
|
56
|
+
index += 2;
|
|
57
|
+
let stringData = '';
|
|
58
|
+
this.content.slice(index, index + len).map(item => {
|
|
59
|
+
if (type === 'ASCII') {
|
|
60
|
+
stringData += String.fromCharCode(item);
|
|
61
|
+
} else {
|
|
62
|
+
stringData += item.toString(16);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
this[key] = stringData;
|
|
66
|
+
return index + len;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static pack = () => {
|
|
70
|
+
const config = [0,0,0,3,3,0,0,3];
|
|
71
|
+
const buffer = new ArrayBuffer(config.length);
|
|
72
|
+
const uint8Array = new Uint8Array(buffer);
|
|
73
|
+
for (let i = 0; i < buffer.byteLength; i++) {
|
|
74
|
+
uint8Array[i] = config[i];
|
|
75
|
+
}
|
|
76
|
+
return uint8Array;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export default DiscoverUDP;
|
package/src/protocol/tool.ts
CHANGED
|
@@ -88,4 +88,13 @@ const formatCodesFromStr = (str: string) => {
|
|
|
88
88
|
return [codes, len];
|
|
89
89
|
};
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
const arrayToUint8 = (config: number[]) => {
|
|
92
|
+
const buffer = new ArrayBuffer(config.length);
|
|
93
|
+
const uint8Array = new Uint8Array(buffer);
|
|
94
|
+
for (let i = 0; i < buffer.byteLength; i++) {
|
|
95
|
+
uint8Array[i] = config[i];
|
|
96
|
+
}
|
|
97
|
+
return uint8Array;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export { checkHeader, getProtocolLen, arrayToString, fillString, string2Bytes, hexStrint2byte, formatCodesFromStr, formatCode, arrayToUint8 };
|
package/src/sdk.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { setGlobalData, getGlobalData } from './globalData';
|
|
2
|
-
import { BleHandle } from './ble';
|
|
3
|
-
import GizwitsWS from './socket';
|
|
2
|
+
import { BleHandle } from './handler/ble';
|
|
3
|
+
import GizwitsWS from './handler/socket';
|
|
4
4
|
|
|
5
5
|
import ApConfig from './wifiConfig/ap';
|
|
6
6
|
import BLEConfig from './wifiConfig/ble';
|
|
7
|
-
import
|
|
7
|
+
import GizLog, { TLogType } from './GizLog';
|
|
8
8
|
import { errorCode } from '..';
|
|
9
9
|
import { AnonymousLogin, ILoginRes } from './services/login';
|
|
10
10
|
import {
|
|
@@ -26,10 +26,8 @@ import {
|
|
|
26
26
|
} from './utils';
|
|
27
27
|
import productConfigFileManage from './productConfigFileManage';
|
|
28
28
|
import { IDataPointConfig, pack, unpack } from './protocol/DataPoint';
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import sentry from './sentry';
|
|
32
|
-
import GizLog from './GizLog';
|
|
29
|
+
import { hexStrint2byte } from './protocol/tool';
|
|
30
|
+
import { LanHandle } from './handler/lan';
|
|
33
31
|
|
|
34
32
|
// 接口返回格式
|
|
35
33
|
interface ISDKResult<T> {
|
|
@@ -159,12 +157,12 @@ class GizwitsMiniSDK {
|
|
|
159
157
|
// ble device
|
|
160
158
|
|
|
161
159
|
// udp device
|
|
162
|
-
private
|
|
163
|
-
private get
|
|
164
|
-
return this.
|
|
160
|
+
private _lanDevices: IDevice[] = [];
|
|
161
|
+
private get lanDevices() {
|
|
162
|
+
return this._lanDevices;
|
|
165
163
|
}
|
|
166
|
-
private set
|
|
167
|
-
this.
|
|
164
|
+
private set lanDevices(data: IDevice[]) {
|
|
165
|
+
this._lanDevices = data;
|
|
168
166
|
this.notiDeviceList();
|
|
169
167
|
}
|
|
170
168
|
// udp device
|
|
@@ -174,7 +172,7 @@ class GizwitsMiniSDK {
|
|
|
174
172
|
[...this.deviceList],
|
|
175
173
|
this.bleDevices
|
|
176
174
|
);
|
|
177
|
-
newDevices = merageLanLocalDevices(newDevices, this.
|
|
175
|
+
newDevices = merageLanLocalDevices(newDevices, this.lanDevices);
|
|
178
176
|
/**
|
|
179
177
|
* 只能有一种通讯方式
|
|
180
178
|
* 依次LAN BLE WAN
|
|
@@ -203,6 +201,15 @@ class GizwitsMiniSDK {
|
|
|
203
201
|
}
|
|
204
202
|
});
|
|
205
203
|
|
|
204
|
+
const lanConnected = this.lanHandle.connectedList;
|
|
205
|
+
lanConnected.map(item => {
|
|
206
|
+
const index = newDevices.findIndex(
|
|
207
|
+
(device) => device.mac === item.mac && device.productKey === item.productKey
|
|
208
|
+
);
|
|
209
|
+
if (index !== -1) {
|
|
210
|
+
newDevices[index].connectType = 'LAN';
|
|
211
|
+
}
|
|
212
|
+
})
|
|
206
213
|
return newDevices;
|
|
207
214
|
}
|
|
208
215
|
|
|
@@ -226,6 +233,8 @@ class GizwitsMiniSDK {
|
|
|
226
233
|
private currentWifiConfigHandle: any;
|
|
227
234
|
|
|
228
235
|
private _bleHandle: BleHandle;
|
|
236
|
+
private _lanHandle: LanHandle;
|
|
237
|
+
|
|
229
238
|
// private autoScanInterval: IntervalHandle = null;
|
|
230
239
|
|
|
231
240
|
private _gizSocket: GizwitsWS;
|
|
@@ -241,7 +250,6 @@ class GizwitsMiniSDK {
|
|
|
241
250
|
offlineThreshold,
|
|
242
251
|
}: GizwitsSdkOption) {
|
|
243
252
|
this.productInfo = productInfo;
|
|
244
|
-
|
|
245
253
|
// 保存相关信息
|
|
246
254
|
setGlobalData('appID', appID);
|
|
247
255
|
setGlobalData('appSecret', appSecret);
|
|
@@ -258,6 +266,11 @@ class GizwitsMiniSDK {
|
|
|
258
266
|
|
|
259
267
|
GizLog.debug(`init sdk success, current version: ${this.version}`);
|
|
260
268
|
|
|
269
|
+
/**
|
|
270
|
+
* lan 比较特殊
|
|
271
|
+
* 初始化sdk的时候就要开始扫描设备
|
|
272
|
+
*/
|
|
273
|
+
this.initLan();
|
|
261
274
|
}
|
|
262
275
|
|
|
263
276
|
private get bleHandle() {
|
|
@@ -271,6 +284,15 @@ class GizwitsMiniSDK {
|
|
|
271
284
|
return this._bleHandle;
|
|
272
285
|
}
|
|
273
286
|
|
|
287
|
+
private get lanHandle() {
|
|
288
|
+
if (!this._lanHandle) {
|
|
289
|
+
this._lanHandle = new LanHandle({
|
|
290
|
+
pks: this.specialProductKeys,
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
return this._lanHandle;
|
|
294
|
+
}
|
|
295
|
+
|
|
274
296
|
private get socketHandle() {
|
|
275
297
|
if (!this._gizSocket) {
|
|
276
298
|
this._gizSocket = new GizwitsWS({
|
|
@@ -306,6 +328,10 @@ class GizwitsMiniSDK {
|
|
|
306
328
|
this.bleDevices = devices;
|
|
307
329
|
};
|
|
308
330
|
|
|
331
|
+
handleLanDevices = (devices: IDevice[]) => {
|
|
332
|
+
this.lanDevices = devices;
|
|
333
|
+
}
|
|
334
|
+
|
|
309
335
|
private handleBleDeviceData = async (
|
|
310
336
|
curDevice: WechatMiniprogram.OnBLECharacteristicValueChangeCallbackResult,
|
|
311
337
|
hexString: string
|
|
@@ -368,6 +394,11 @@ class GizwitsMiniSDK {
|
|
|
368
394
|
});
|
|
369
395
|
};
|
|
370
396
|
|
|
397
|
+
private initLan = () => {
|
|
398
|
+
this.lanHandle.init();
|
|
399
|
+
this.lanHandle.addEventListener('GizLanDeviceList', this.handleLanDevices);
|
|
400
|
+
}
|
|
401
|
+
|
|
371
402
|
/**
|
|
372
403
|
* @description 开启后台自动扫描
|
|
373
404
|
*/
|
|
@@ -503,6 +534,49 @@ class GizwitsMiniSDK {
|
|
|
503
534
|
case 'WAN': {
|
|
504
535
|
return this.socketHandle.writeData(target, attrs);
|
|
505
536
|
}
|
|
537
|
+
case 'LAN': {
|
|
538
|
+
return this.lanHandle.write(target, numberArray2Uint8Array(value).buffer);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
return {
|
|
543
|
+
success: false,
|
|
544
|
+
};
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
// 发送原始数据
|
|
548
|
+
writeRaw = async (device: IDevice, data: number[]) => {
|
|
549
|
+
const target = this.allDevices.find((item) => isSameDevice(item, device));
|
|
550
|
+
if (!target) {
|
|
551
|
+
return { success: false, message: 'target is undefind' };
|
|
552
|
+
}
|
|
553
|
+
if (target.connectType !== 'NONE') {
|
|
554
|
+
switch (target.connectType) {
|
|
555
|
+
case 'BLE_BROADCAST':
|
|
556
|
+
// 广播的方式发数据 Action+Flags+DataPoints
|
|
557
|
+
return await this.bleHandle.writeBoradcast(
|
|
558
|
+
target.bleDeviceID,
|
|
559
|
+
data
|
|
560
|
+
);
|
|
561
|
+
case 'BLE': {
|
|
562
|
+
if (data) {
|
|
563
|
+
return await this.bleHandle.write(
|
|
564
|
+
target.bleDeviceID,
|
|
565
|
+
numberArray2Uint8Array(data).buffer
|
|
566
|
+
);
|
|
567
|
+
} else {
|
|
568
|
+
// 解码失败
|
|
569
|
+
return {
|
|
570
|
+
success: false,
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
case 'WAN': {
|
|
575
|
+
return this.socketHandle.send(target.did, data);
|
|
576
|
+
}
|
|
577
|
+
case 'LAN': {
|
|
578
|
+
return this.lanHandle.write(target, numberArray2Uint8Array(data).buffer);
|
|
579
|
+
}
|
|
506
580
|
}
|
|
507
581
|
}
|
|
508
582
|
return {
|
|
@@ -577,7 +651,12 @@ class GizwitsMiniSDK {
|
|
|
577
651
|
connectType?: TConnectType,
|
|
578
652
|
_autoGetDeviceStatus: boolean = true
|
|
579
653
|
) => {
|
|
654
|
+
console.log('this.allDevices', this.allDevices)
|
|
580
655
|
let target = this.allDevices.find((item) => isSameDevice(item, device));
|
|
656
|
+
if (!target) {
|
|
657
|
+
GizLog.warn('Device Target Not Found')
|
|
658
|
+
return { success: false };
|
|
659
|
+
}
|
|
581
660
|
|
|
582
661
|
// 广播模式不需要连接,所以默认是连接状态
|
|
583
662
|
if (target.connectType === 'BLE_BROADCAST') {
|
|
@@ -588,20 +667,14 @@ class GizwitsMiniSDK {
|
|
|
588
667
|
}
|
|
589
668
|
|
|
590
669
|
const type: TConnectType = getFirstConnectType(target, connectType);
|
|
591
|
-
GizLog.log('subscribe', target, connectType);
|
|
592
670
|
if (target.connectType !== 'NONE' && target.connectType !== type) {
|
|
593
671
|
// 已经存在 并且不等于即将订阅的类型
|
|
594
672
|
// 先解除订阅
|
|
595
673
|
await this.unSubscribe(target);
|
|
596
674
|
}
|
|
597
|
-
|
|
598
675
|
switch (type) {
|
|
599
676
|
case 'BLE': {
|
|
600
677
|
// 连接BLE
|
|
601
|
-
|
|
602
|
-
if (!target) {
|
|
603
|
-
return { success: false };
|
|
604
|
-
}
|
|
605
678
|
const data = await this.bleHandle.connectDevice(target.bleDeviceID);
|
|
606
679
|
if (data.success) {
|
|
607
680
|
// 蓝牙设备比较特殊,在get 里面从bleHandle里找到连接的设备,再把connectType 设置成BLE,所以这里更新metaData 要强制更新并推送
|
|
@@ -617,15 +690,19 @@ class GizwitsMiniSDK {
|
|
|
617
690
|
// const target = this.deviceList.find((item) =>
|
|
618
691
|
// isSameDevice(item, device)
|
|
619
692
|
// );
|
|
620
|
-
if (!target) {
|
|
621
|
-
return { success: false };
|
|
622
|
-
}
|
|
623
693
|
const data = this.socketHandle.connectDevice(target);
|
|
624
694
|
if (data.success) {
|
|
625
695
|
this.setDeviceMeta(device, 'connectType', 'WAN', true);
|
|
626
696
|
}
|
|
627
697
|
return data;
|
|
628
698
|
}
|
|
699
|
+
case 'LAN': {
|
|
700
|
+
const data = await this.lanHandle.connectDevice(target);
|
|
701
|
+
if (data.success) {
|
|
702
|
+
this.setDeviceMeta(device, 'connectType', 'LAN', true);
|
|
703
|
+
}
|
|
704
|
+
return data;
|
|
705
|
+
}
|
|
629
706
|
}
|
|
630
707
|
return {
|
|
631
708
|
success: false,
|
|
@@ -658,6 +735,13 @@ class GizwitsMiniSDK {
|
|
|
658
735
|
}
|
|
659
736
|
return res;
|
|
660
737
|
}
|
|
738
|
+
case 'LAN': {
|
|
739
|
+
const res = this.lanHandle.disConnectDevice(target);
|
|
740
|
+
if (res.success) {
|
|
741
|
+
this.setDeviceMeta(target, 'connectType', 'NONE', true);
|
|
742
|
+
}
|
|
743
|
+
return res;
|
|
744
|
+
}
|
|
661
745
|
}
|
|
662
746
|
return {
|
|
663
747
|
success: false,
|
|
@@ -864,7 +948,7 @@ class GizwitsMiniSDK {
|
|
|
864
948
|
* setLogLevel
|
|
865
949
|
*/
|
|
866
950
|
setLogLevel = (level: TLogType) => {
|
|
867
|
-
return
|
|
951
|
+
return GizLog.setLogLevel(level);
|
|
868
952
|
}
|
|
869
953
|
|
|
870
954
|
/**
|
|
@@ -912,6 +996,7 @@ class GizwitsMiniSDK {
|
|
|
912
996
|
|
|
913
997
|
public destory = () => {
|
|
914
998
|
this.bleHandle.destory();
|
|
999
|
+
this.lanHandle.destory();
|
|
915
1000
|
this.socketHandle.destory();
|
|
916
1001
|
this.keepScanTimer && clearInterval(this.keepScanTimer);
|
|
917
1002
|
};
|
package/src/utils.ts
CHANGED