@ray-js/robot-data-stream 0.0.13-beta-6 → 0.0.13-beta-7
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/lib/api/index.d.ts +12 -2
- package/lib/api/index.js +172 -1
- package/lib/api/p2pApi.d.ts +27 -8
- package/lib/api/p2pApi.js +169 -271
- package/lib/api/sweeperP2p.d.ts +21 -54
- package/lib/api/sweeperP2p.js +245 -324
- package/lib/constant.d.ts +52 -0
- package/lib/constant.js +54 -0
- package/lib/index.d.ts +1 -11
- package/lib/index.js +2 -166
- package/lib/mqtt/createCommonOptions.d.ts +56 -15
- package/lib/mqtt/createCommonOptions.js +44 -8
- package/lib/mqtt/mqttProvider.d.ts +23 -15
- package/lib/mqtt/mqttProvider.js +63 -26
- package/lib/mqtt/promise.js +8 -3
- package/lib/mqtt/type/index.d.ts +9 -0
- package/lib/mqtt/type/index.js +8 -0
- package/lib/mqtt/type/requestType.d.ts +3 -0
- package/lib/mqtt/type/requestType.js +4 -0
- package/lib/mqtt/useDevInfo.d.ts +2 -7
- package/lib/mqtt/useDevInfo.js +25 -9
- package/lib/mqtt/useHistoryMap.d.ts +13 -21
- package/lib/mqtt/useHistoryMap.js +82 -32
- package/lib/mqtt/usePartDivision.d.ts +5 -7
- package/lib/mqtt/usePartDivision.js +41 -16
- package/lib/mqtt/usePartMerge.d.ts +5 -7
- package/lib/mqtt/usePartMerge.js +36 -18
- package/lib/mqtt/usePassword.js +59 -28
- package/lib/mqtt/useQuiteHours.d.ts +9 -24
- package/lib/mqtt/useQuiteHours.js +95 -52
- package/lib/mqtt/useResetMap.d.ts +10 -7
- package/lib/mqtt/useResetMap.js +40 -11
- package/lib/mqtt/useRoomProperty.js +23 -16
- package/lib/mqtt/useSchedule.d.ts +17 -4
- package/lib/mqtt/useSchedule.js +101 -49
- package/lib/mqtt/useSelectRoomClean.d.ts +20 -16
- package/lib/mqtt/useSelectRoomClean.js +145 -49
- package/lib/mqtt/useSpotClean.d.ts +3 -3
- package/lib/mqtt/useSpotClean.js +71 -50
- package/lib/mqtt/useVirtualArea.d.ts +6 -9
- package/lib/mqtt/useVirtualArea.js +112 -42
- package/lib/mqtt/useVirtualWall.d.ts +13 -10
- package/lib/mqtt/useVirtualWall.js +97 -34
- package/lib/mqtt/useVoice.d.ts +3 -6
- package/lib/mqtt/useVoice.js +73 -33
- package/lib/mqtt/useWifiMap.js +34 -18
- package/lib/mqtt/useZoneClean.d.ts +13 -13
- package/lib/mqtt/useZoneClean.js +149 -76
- package/lib/ttt/index.d.ts +153 -0
- package/lib/ttt/index.js +458 -0
- package/lib/utils/index.d.ts +20 -1
- package/lib/utils/index.js +19 -0
- package/package.json +1 -1
- package/lib/mqtt/myError.d.ts +0 -4
- package/lib/mqtt/myError.js +0 -6
package/lib/api/sweeperP2p.js
CHANGED
|
@@ -1,55 +1,32 @@
|
|
|
1
1
|
import "core-js/modules/esnext.iterator.constructor.js";
|
|
2
|
+
import "core-js/modules/esnext.iterator.filter.js";
|
|
2
3
|
import "core-js/modules/esnext.iterator.for-each.js";
|
|
3
4
|
import "core-js/modules/esnext.iterator.map.js";
|
|
4
|
-
/* eslint-disable no-shadow */
|
|
5
5
|
import Base64 from 'base64-js';
|
|
6
|
-
import { join, map,
|
|
6
|
+
import { join, map, once, padStart } from 'lodash-es';
|
|
7
|
+
import { FILE_NAME_MAP, FileNameEnum } from '../constant';
|
|
7
8
|
import { trace } from '../trace';
|
|
8
|
-
import {
|
|
9
|
+
import { checkIfDirIsExist, createFilePath } from '../ttt';
|
|
9
10
|
import P2pApi from './p2pApi';
|
|
10
11
|
/**
|
|
11
12
|
* 基于P2p工具类的扫地机扩展实现
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
'map_structured.bin.stream': {
|
|
30
|
-
type: 6
|
|
31
|
-
},
|
|
32
|
-
'cleanPath.bin.stream': {
|
|
33
|
-
type: 1
|
|
34
|
-
},
|
|
35
|
-
'ai.bin': {
|
|
36
|
-
type: 4
|
|
37
|
-
},
|
|
38
|
-
'ai.bin.stream': {
|
|
39
|
-
type: 4
|
|
40
|
-
},
|
|
41
|
-
'aiHD_XXXX_YYYY.bin': {
|
|
42
|
-
type: 5
|
|
43
|
-
},
|
|
44
|
-
'aiHD_XXXX_YYYY.bin.stream': {
|
|
45
|
-
type: 5
|
|
46
|
-
},
|
|
47
|
-
'wifi_map.bin': {
|
|
48
|
-
type: 7
|
|
49
|
-
},
|
|
50
|
-
'wifi_map.bin.stream': {
|
|
51
|
-
type: 7
|
|
52
|
-
}
|
|
15
|
+
// 需要初始化的文件名列表(不包括 wifi_map)
|
|
16
|
+
const FILE_NAMES_TO_INIT = [FileNameEnum.map, FileNameEnum.mapStructured, FileNameEnum.cleanPath, FileNameEnum.ai, FileNameEnum.aiHD, FileNameEnum.mapStream, FileNameEnum.mapStructuredStream, FileNameEnum.cleanPathStream, FileNameEnum.aiStream, FileNameEnum.aiHDStream];
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 创建初始化的 Map,所有键值都设置为初始值
|
|
20
|
+
*/
|
|
21
|
+
const createInitializedMap = initialValue => {
|
|
22
|
+
return new Map(FILE_NAMES_TO_INIT.map(key => [key, initialValue]));
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 创建初始化的 Map,值为新的 Map 实例
|
|
27
|
+
*/
|
|
28
|
+
const createMapOfMaps = () => {
|
|
29
|
+
return new Map(FILE_NAMES_TO_INIT.map(key => [key, new Map()]));
|
|
53
30
|
};
|
|
54
31
|
|
|
55
32
|
// 走p2p流传输(新) or 读取bin文件(旧)
|
|
@@ -67,10 +44,11 @@ export class SweeperP2p extends P2pApi {
|
|
|
67
44
|
this.cacheData = {};
|
|
68
45
|
this.exitFiles = [];
|
|
69
46
|
this.firstPackageTime = Date.now();
|
|
70
|
-
|
|
71
|
-
this.
|
|
72
|
-
this.
|
|
73
|
-
this.
|
|
47
|
+
// 使用辅助函数初始化 Map,减少重复代码
|
|
48
|
+
this.packetTotalMap = createInitializedMap(-1);
|
|
49
|
+
this.packetSerialNumberCacheMap = createInitializedMap(-1);
|
|
50
|
+
this.fileLengthCacheMap = createInitializedMap(-1);
|
|
51
|
+
this.packetDataCacheMap = createMapOfMaps();
|
|
74
52
|
}
|
|
75
53
|
setStreamFilePath = () => {
|
|
76
54
|
// this.streamFilePath = this.cacheDir + `/${this.albumName}/${devId}/stream`;
|
|
@@ -87,7 +65,7 @@ export class SweeperP2p extends P2pApi {
|
|
|
87
65
|
if (/usr/.test(this.cacheDir)) {
|
|
88
66
|
this.dataFilePath = this.cacheDir;
|
|
89
67
|
} else {
|
|
90
|
-
this.
|
|
68
|
+
this.dataFilePath = this.cacheDir + 'usr';
|
|
91
69
|
}
|
|
92
70
|
// 检查存储文件目录是否存在
|
|
93
71
|
// this.initFilePath(this.dataFilePath);
|
|
@@ -111,70 +89,17 @@ export class SweeperP2p extends P2pApi {
|
|
|
111
89
|
return this.dataFilePath + '/' + fileName;
|
|
112
90
|
};
|
|
113
91
|
|
|
114
|
-
/**
|
|
115
|
-
* 创建文件路径文件夹
|
|
116
|
-
* @param filePath
|
|
117
|
-
* @returns
|
|
118
|
-
*/
|
|
119
|
-
createFilePath = filePath => {
|
|
120
|
-
try {
|
|
121
|
-
ty.getFileSystemManager().mkdirSync({
|
|
122
|
-
dirPath: filePath,
|
|
123
|
-
recursive: true
|
|
124
|
-
});
|
|
125
|
-
logger('info', {
|
|
126
|
-
msg: 'mkdirSync success: filePath ==>',
|
|
127
|
-
filePath
|
|
128
|
-
}, this.onLogger);
|
|
129
|
-
return true;
|
|
130
|
-
} catch (e) {
|
|
131
|
-
logger('error', {
|
|
132
|
-
msg: 'mkdirSync error ==>',
|
|
133
|
-
e
|
|
134
|
-
}, this.onLogger);
|
|
135
|
-
return false;
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* 检查当前文件目录是否存在
|
|
141
|
-
* @param filePath
|
|
142
|
-
* @returns
|
|
143
|
-
*/
|
|
144
|
-
checkIfDirIsExist = filePath => {
|
|
145
|
-
return new Promise(resolve => {
|
|
146
|
-
ty.getFileSystemManager().access({
|
|
147
|
-
path: filePath,
|
|
148
|
-
success(params) {
|
|
149
|
-
logger('info', {
|
|
150
|
-
msg: 'file access success ==>',
|
|
151
|
-
params
|
|
152
|
-
}, this.onLogger);
|
|
153
|
-
resolve(true);
|
|
154
|
-
},
|
|
155
|
-
fail(params) {
|
|
156
|
-
logger('warn', {
|
|
157
|
-
msg: 'file access fail ==>',
|
|
158
|
-
params
|
|
159
|
-
}, this.onLogger);
|
|
160
|
-
resolve(false);
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
};
|
|
165
|
-
|
|
166
92
|
/**
|
|
167
93
|
* 初始化文件目录
|
|
168
94
|
* @param filePath
|
|
169
95
|
* @returns
|
|
170
96
|
*/
|
|
171
97
|
initFilePath = async filePath => {
|
|
172
|
-
const isDir = await
|
|
98
|
+
const isDir = await checkIfDirIsExist(filePath);
|
|
173
99
|
if (!isDir) {
|
|
174
|
-
|
|
175
|
-
return result;
|
|
100
|
+
return await createFilePath(filePath, this.onLogger);
|
|
176
101
|
}
|
|
177
|
-
return
|
|
102
|
+
return true;
|
|
178
103
|
};
|
|
179
104
|
|
|
180
105
|
/**
|
|
@@ -182,45 +107,108 @@ export class SweeperP2p extends P2pApi {
|
|
|
182
107
|
* @param filename
|
|
183
108
|
*/
|
|
184
109
|
getFileType = filename => {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
if (filename.indexOf('map.') !== -1) {
|
|
189
|
-
return 0;
|
|
110
|
+
// 首先尝试精确匹配 FILE_NAME_MAP 中的键
|
|
111
|
+
if (filename in FILE_NAME_MAP) {
|
|
112
|
+
return FILE_NAME_MAP[filename].type;
|
|
190
113
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
if (
|
|
195
|
-
return
|
|
196
|
-
}
|
|
197
|
-
if (filename.indexOf('aiHD') !== -1) {
|
|
198
|
-
return 5;
|
|
114
|
+
|
|
115
|
+
// 处理 aiHD_XXXX_YYYY.bin 模式(XXXX_YYYY 会被替换为实际值)
|
|
116
|
+
|
|
117
|
+
if (/^aiHD.*\.bin(\.stream)?$/.test(filename)) {
|
|
118
|
+
return FILE_NAME_MAP[FileNameEnum.aiHD].type;
|
|
199
119
|
}
|
|
200
|
-
|
|
201
|
-
|
|
120
|
+
|
|
121
|
+
// 按优先级顺序匹配文件名(更具体的模式优先)
|
|
122
|
+
// 注意:map_structured 必须在 map 之前匹配
|
|
123
|
+
const matchOrder = [{
|
|
124
|
+
pattern: /map_structured/,
|
|
125
|
+
enumKey: FileNameEnum.mapStructured
|
|
126
|
+
}, {
|
|
127
|
+
pattern: /^map\./,
|
|
128
|
+
enumKey: FileNameEnum.map
|
|
129
|
+
}, {
|
|
130
|
+
pattern: /cleanPath/,
|
|
131
|
+
enumKey: FileNameEnum.cleanPath
|
|
132
|
+
}, {
|
|
133
|
+
pattern: /^ai\./,
|
|
134
|
+
enumKey: FileNameEnum.ai
|
|
135
|
+
}, {
|
|
136
|
+
pattern: /wifi_map/,
|
|
137
|
+
enumKey: FileNameEnum.wifiMap
|
|
138
|
+
}];
|
|
139
|
+
for (const {
|
|
140
|
+
pattern,
|
|
141
|
+
enumKey
|
|
142
|
+
} of matchOrder) {
|
|
143
|
+
if (pattern.test(filename)) {
|
|
144
|
+
return FILE_NAME_MAP[enumKey].type;
|
|
145
|
+
}
|
|
202
146
|
}
|
|
147
|
+
|
|
148
|
+
// 默认返回 2
|
|
203
149
|
return 2;
|
|
204
150
|
};
|
|
205
151
|
|
|
152
|
+
/**
|
|
153
|
+
* 根据文件类型处理数据并调用相应的回调函数
|
|
154
|
+
*/
|
|
155
|
+
handleDataByType = (() => {
|
|
156
|
+
var _this = this;
|
|
157
|
+
return function (type, hexValue) {
|
|
158
|
+
let shouldCache = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
|
159
|
+
if (_this.cacheData[type] === hexValue) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
switch (type) {
|
|
163
|
+
case 0:
|
|
164
|
+
case 6:
|
|
165
|
+
_this.onReceiveMapData(hexValue);
|
|
166
|
+
if (shouldCache) {
|
|
167
|
+
_this.cacheData[type] = hexValue;
|
|
168
|
+
}
|
|
169
|
+
break;
|
|
170
|
+
case 1:
|
|
171
|
+
_this.log.info({
|
|
172
|
+
msg: 'push new path data'
|
|
173
|
+
});
|
|
174
|
+
_this.onReceivePathData(hexValue);
|
|
175
|
+
if (shouldCache) {
|
|
176
|
+
_this.cacheData[type] = hexValue;
|
|
177
|
+
}
|
|
178
|
+
break;
|
|
179
|
+
case 4:
|
|
180
|
+
_this.onReceiveAIPicData(hexValue);
|
|
181
|
+
break;
|
|
182
|
+
case 5:
|
|
183
|
+
_this.onReceiveAIPicHDData(hexValue);
|
|
184
|
+
break;
|
|
185
|
+
case 7:
|
|
186
|
+
_this.onReceiveWifiMapData(hexValue);
|
|
187
|
+
break;
|
|
188
|
+
default:
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
})();
|
|
193
|
+
|
|
206
194
|
/**
|
|
207
195
|
* 设备连接状态发生改变
|
|
208
196
|
* @param data
|
|
209
197
|
*/
|
|
210
198
|
sessionStatusCallback = data => {
|
|
211
|
-
|
|
199
|
+
this.log.info({
|
|
212
200
|
msg: 'sessionStatusCallback ==>',
|
|
213
201
|
data
|
|
214
|
-
}
|
|
202
|
+
});
|
|
215
203
|
if (data) {
|
|
216
204
|
const {
|
|
217
205
|
status
|
|
218
206
|
} = data;
|
|
219
207
|
if (status < 0) {
|
|
220
|
-
|
|
208
|
+
this.log.info({
|
|
221
209
|
msg: 'receive disconnect notice ==>',
|
|
222
210
|
status
|
|
223
|
-
}
|
|
211
|
+
});
|
|
224
212
|
this.isConnected = false;
|
|
225
213
|
if (!this.isConnecting) {
|
|
226
214
|
this.reconnectP2p(() => {
|
|
@@ -228,27 +216,74 @@ export class SweeperP2p extends P2pApi {
|
|
|
228
216
|
this.startObserverSweeperDataByP2P(this.downloadType, this.devId, this.onReceiveMapData, this.onReceivePathData, this.onReceiveAIPicData, this.onReceiveAIPicHDData, this.onReceiveWifiMapData);
|
|
229
217
|
}, '');
|
|
230
218
|
} else {
|
|
231
|
-
|
|
219
|
+
this.log.warn({
|
|
232
220
|
msg: 'receive disconnect notice, but connectDevice is connecting'
|
|
233
|
-
}
|
|
221
|
+
});
|
|
234
222
|
}
|
|
235
223
|
}
|
|
236
224
|
}
|
|
237
225
|
};
|
|
238
226
|
|
|
227
|
+
/**
|
|
228
|
+
* 创建下载失败时的重连回调函数
|
|
229
|
+
*/
|
|
230
|
+
createReconnectCallback = () => {
|
|
231
|
+
return () => {
|
|
232
|
+
this.log.error({
|
|
233
|
+
msg: `${this.downloadType} p2p downloadStream failed and try reConnect Device===>`
|
|
234
|
+
});
|
|
235
|
+
this.removeP2pDownloadEvent();
|
|
236
|
+
this.disconnectDevice().then(() => {
|
|
237
|
+
this.isConnected = false;
|
|
238
|
+
this.isConnecting = false;
|
|
239
|
+
this.connectDevice(() => {
|
|
240
|
+
// 重连之后重新开启文件下载, 这里的成功不需要注册断开事件
|
|
241
|
+
this.startObserverSweeperDataByP2P(this.downloadType, this.devId, this.onReceiveMapData, this.onReceivePathData, this.onReceiveAIPicData, this.onReceiveAIPicHDData, this.onReceiveWifiMapData);
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
};
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* 执行文件下载逻辑
|
|
249
|
+
*/
|
|
250
|
+
async executeDownload(exitFiles, filePath) {
|
|
251
|
+
if (exitFiles.length === 0) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (shouldDownloadStream) {
|
|
255
|
+
// 开启p2p流传输
|
|
256
|
+
await this.downloadStream({
|
|
257
|
+
files: exitFiles
|
|
258
|
+
}, this.albumName, () => {
|
|
259
|
+
this.log.info({
|
|
260
|
+
msg: `${this.downloadType} p2p downloadStream success===>`
|
|
261
|
+
});
|
|
262
|
+
}, this.createReconnectCallback());
|
|
263
|
+
} else if (await this.initFilePath(filePath)) {
|
|
264
|
+
// 每次要下载前都需要先检查文件目录是否存在 防止中间过程被删除掉文件目录
|
|
265
|
+
await this.downloadFile({
|
|
266
|
+
files: exitFiles
|
|
267
|
+
}, this.albumName, filePath);
|
|
268
|
+
}
|
|
269
|
+
this.firstPackageTime = Date.now();
|
|
270
|
+
}
|
|
271
|
+
|
|
239
272
|
/**
|
|
240
273
|
* 开始进行文件下载
|
|
241
274
|
* @param downloadType
|
|
242
275
|
* 0: 下载断开 1: 持续下载
|
|
243
276
|
*/
|
|
244
277
|
startObserverSweeperDataByP2P = async (downloadType, devId, onReceiveMapData, onReceivePathData, onReceiveAIPicData, onReceiveAIPicHDData, onReceiveWifiMapData, onDefineStructuredMode) => {
|
|
245
|
-
var _this$file
|
|
246
|
-
if (![0, 1].
|
|
247
|
-
|
|
278
|
+
var _this$file;
|
|
279
|
+
if (![0, 1].includes(downloadType)) {
|
|
280
|
+
this.log.warn({
|
|
248
281
|
msg: 'download type must be 0 or 1'
|
|
249
|
-
}
|
|
282
|
+
});
|
|
250
283
|
return;
|
|
251
284
|
}
|
|
285
|
+
|
|
286
|
+
// 初始化回调函数
|
|
252
287
|
this.onReceiveMapData = onReceiveMapData;
|
|
253
288
|
this.onReceivePathData = onReceivePathData;
|
|
254
289
|
this.onReceiveWifiMapData = onReceiveWifiMapData;
|
|
@@ -259,9 +294,9 @@ export class SweeperP2p extends P2pApi {
|
|
|
259
294
|
this.onReceiveAIPicHDData = onReceiveAIPicHDData || (() => {
|
|
260
295
|
// do nothing
|
|
261
296
|
});
|
|
262
|
-
|
|
297
|
+
this.log.info({
|
|
263
298
|
msg: 'startObserverSweeperDataByP2P ==>'
|
|
264
|
-
}
|
|
299
|
+
});
|
|
265
300
|
trace.pointFn({
|
|
266
301
|
devId,
|
|
267
302
|
eventName: 'startObserverSweeperDataByP2P'
|
|
@@ -269,85 +304,27 @@ export class SweeperP2p extends P2pApi {
|
|
|
269
304
|
this.downloadType = downloadType;
|
|
270
305
|
this.setDataFilePath(devId);
|
|
271
306
|
this.setStreamFilePath(devId);
|
|
307
|
+
|
|
272
308
|
// 先移除监听,再重新注册
|
|
273
309
|
this.removeP2pDownloadEvent();
|
|
274
310
|
this.registerP2pDownloadEvent();
|
|
311
|
+
|
|
312
|
+
// 查询文件列表
|
|
275
313
|
if (!this.file) {
|
|
276
314
|
// @ts-ignore
|
|
277
315
|
this.file = await this.queryAlbumFileIndexs(this.albumName);
|
|
278
316
|
}
|
|
279
|
-
if (this.file && (
|
|
280
|
-
|
|
281
|
-
const exitFiles = this.queryNeedFiles(this.file.items);
|
|
282
|
-
// 赋值
|
|
283
|
-
this.exitFiles = exitFiles;
|
|
284
|
-
if (exitFiles.length > 0) {
|
|
285
|
-
if (shouldDownloadStream) {
|
|
286
|
-
// 开启p2p流传输
|
|
287
|
-
await this.downloadStream({
|
|
288
|
-
files: exitFiles
|
|
289
|
-
}, this.albumName, () => {
|
|
290
|
-
logger('info', {
|
|
291
|
-
msg: `${downloadType} p2p downloadStream success===>`
|
|
292
|
-
}, this.onLogger);
|
|
293
|
-
}, () => {
|
|
294
|
-
logger('error', {
|
|
295
|
-
msg: `${downloadType} p2p downloadStream failed and try reConnect Device===>`
|
|
296
|
-
}, this.onLogger);
|
|
297
|
-
this.removeP2pDownloadEvent();
|
|
298
|
-
this.disconnectDevice().then(() => {
|
|
299
|
-
this.isConnected = false;
|
|
300
|
-
this.isConnecting = false;
|
|
301
|
-
this.connectDevice(() => {
|
|
302
|
-
// 重连之后重新开启文件下载, 这里的成功不需要注册断开事件
|
|
303
|
-
this.startObserverSweeperDataByP2P(this.downloadType, this.devId, this.onReceiveMapData, this.onReceivePathData, this.onReceiveAIPicData, this.onReceiveAIPicHDData, this.onReceiveWifiMapData);
|
|
304
|
-
});
|
|
305
|
-
});
|
|
306
|
-
});
|
|
307
|
-
} else if (await this.initFilePath(this.dataFilePath)) {
|
|
308
|
-
await this.downloadFile({
|
|
309
|
-
files: exitFiles
|
|
310
|
-
}, this.albumName, this.dataFilePath);
|
|
311
|
-
}
|
|
312
|
-
this.firstPackageTime = Date.now();
|
|
313
|
-
}
|
|
314
|
-
} else if (this.downloadType === 1) {
|
|
315
|
-
const exitFiles = this.queryNeedFiles(this.file.items);
|
|
316
|
-
// 赋值
|
|
317
|
-
this.exitFiles = exitFiles;
|
|
318
|
-
if (exitFiles.length > 0) {
|
|
319
|
-
if (shouldDownloadStream) {
|
|
320
|
-
// 开启p2p流传输
|
|
321
|
-
await this.downloadStream({
|
|
322
|
-
files: exitFiles
|
|
323
|
-
}, this.albumName, () => {
|
|
324
|
-
logger('info', {
|
|
325
|
-
msg: `${downloadType} p2p downloadStream success===>`
|
|
326
|
-
}, this.onLogger);
|
|
327
|
-
}, () => {
|
|
328
|
-
logger('error', {
|
|
329
|
-
msg: `${downloadType} p2p downloadStream failed and try reConnect Device===>`
|
|
330
|
-
}, this.onLogger);
|
|
331
|
-
this.removeP2pDownloadEvent();
|
|
332
|
-
this.disconnectDevice().then(() => {
|
|
333
|
-
this.isConnected = false;
|
|
334
|
-
this.isConnecting = false;
|
|
335
|
-
this.connectDevice(() => {
|
|
336
|
-
// 重连之后重新开启文件下载, 这里的成功不需要注册断开事件
|
|
337
|
-
this.startObserverSweeperDataByP2P(this.downloadType, this.devId, this.onReceiveMapData, this.onReceivePathData, this.onReceiveAIPicData, this.onReceiveAIPicHDData, this.onReceiveWifiMapData);
|
|
338
|
-
});
|
|
339
|
-
});
|
|
340
|
-
});
|
|
341
|
-
} else if (await this.initFilePath(this.streamFilePath)) {
|
|
342
|
-
// 每次要下载前都需要先检查文件目录是否存在 防止中间过程被删除掉文件目录
|
|
343
|
-
await this.downloadFile({
|
|
344
|
-
files: exitFiles
|
|
345
|
-
}, this.albumName, this.streamFilePath);
|
|
346
|
-
}
|
|
347
|
-
this.firstPackageTime = Date.now();
|
|
348
|
-
}
|
|
349
|
-
}
|
|
317
|
+
if (!((_this$file = this.file) !== null && _this$file !== void 0 && (_this$file = _this$file.items) !== null && _this$file !== void 0 && _this$file.length)) {
|
|
318
|
+
return;
|
|
350
319
|
}
|
|
320
|
+
|
|
321
|
+
// 根据 downloadType 选择文件路径
|
|
322
|
+
const filePath = downloadType === 0 ? this.dataFilePath : this.streamFilePath;
|
|
323
|
+
const exitFiles = this.queryNeedFiles(this.file.items);
|
|
324
|
+
this.exitFiles = exitFiles;
|
|
325
|
+
|
|
326
|
+
// 执行下载
|
|
327
|
+
await this.executeDownload(exitFiles, filePath);
|
|
351
328
|
};
|
|
352
329
|
|
|
353
330
|
/**
|
|
@@ -367,9 +344,9 @@ export class SweeperP2p extends P2pApi {
|
|
|
367
344
|
* 注册下载有关的监听
|
|
368
345
|
*/
|
|
369
346
|
registerP2pDownloadEvent = () => {
|
|
370
|
-
|
|
347
|
+
this.log.info({
|
|
371
348
|
msg: 'registerP2pDownloadEvent ==>'
|
|
372
|
-
}
|
|
349
|
+
});
|
|
373
350
|
if (shouldDownloadStream) {
|
|
374
351
|
// p2p数据流监听
|
|
375
352
|
this.offP2pStreamPacketReceive = this.onP2pStreamPacketReceive(this.p2pStreamPacketReceiveCallback);
|
|
@@ -390,29 +367,25 @@ export class SweeperP2p extends P2pApi {
|
|
|
390
367
|
* 移除下载有关的监听
|
|
391
368
|
*/
|
|
392
369
|
removeP2pDownloadEvent = () => {
|
|
393
|
-
|
|
370
|
+
var _this$offFileDownload, _this$offP2pStreamPac;
|
|
371
|
+
this.log.info({
|
|
394
372
|
msg: 'removeP2pDownloadEvent ==>'
|
|
395
|
-
}
|
|
373
|
+
});
|
|
396
374
|
if (shouldDownloadStream) {
|
|
397
|
-
|
|
375
|
+
// 重置所有 Map 的值为初始状态
|
|
376
|
+
FILE_NAMES_TO_INIT.forEach(key => {
|
|
398
377
|
this.packetSerialNumberCacheMap.set(key, -1);
|
|
399
|
-
});
|
|
400
|
-
[...this.fileLengthCacheMap.keys()].forEach(key => {
|
|
401
378
|
this.fileLengthCacheMap.set(key, -1);
|
|
402
|
-
});
|
|
403
|
-
[...this.packetTotalMap.keys()].forEach(key => {
|
|
404
379
|
this.packetTotalMap.set(key, -1);
|
|
405
|
-
});
|
|
406
|
-
[...this.packetDataCacheMap.keys()].forEach(key => {
|
|
407
380
|
this.packetDataCacheMap.set(key, new Map());
|
|
408
381
|
});
|
|
409
382
|
}
|
|
410
383
|
this.cacheData = {};
|
|
411
|
-
this.offFileDownloadComplete
|
|
412
|
-
this.offP2pStreamPacketReceive
|
|
384
|
+
(_this$offFileDownload = this.offFileDownloadComplete) === null || _this$offFileDownload === void 0 || _this$offFileDownload.call(this);
|
|
385
|
+
(_this$offP2pStreamPac = this.offP2pStreamPacketReceive) === null || _this$offP2pStreamPac === void 0 || _this$offP2pStreamPac.call(this);
|
|
413
386
|
|
|
414
|
-
// this.offDownLoadProgressUpdate
|
|
415
|
-
// this.offTotalDownLoadProgressUpdate
|
|
387
|
+
// this.offDownLoadProgressUpdate?.();
|
|
388
|
+
// this.offTotalDownLoadProgressUpdate?.();
|
|
416
389
|
};
|
|
417
390
|
|
|
418
391
|
/**
|
|
@@ -461,15 +434,15 @@ export class SweeperP2p extends P2pApi {
|
|
|
461
434
|
// 因为XXXX_YYYYY会被替换为坐标值,所以这里需要替换一下
|
|
462
435
|
|
|
463
436
|
if (/^aiHD.*\.bin$/.test(fileName)) {
|
|
464
|
-
fileName =
|
|
437
|
+
fileName = FileNameEnum.aiHD;
|
|
465
438
|
} else if (/^aiHD.*\.bin.stream$/.test(fileName)) {
|
|
466
|
-
fileName =
|
|
439
|
+
fileName = FileNameEnum.aiHDStream;
|
|
467
440
|
}
|
|
468
441
|
const cachePacketMap = this.packetDataCacheMap.get(fileName);
|
|
469
442
|
if (!cachePacketMap) {
|
|
470
|
-
|
|
443
|
+
this.log.warn({
|
|
471
444
|
msg: `p2pStreamPacketReceiveCallback: fileName : ${fileName} is not support`
|
|
472
|
-
}
|
|
445
|
+
});
|
|
473
446
|
return;
|
|
474
447
|
}
|
|
475
448
|
const cacheSerialNumber = this.packetSerialNumberCacheMap.get(fileName);
|
|
@@ -503,16 +476,16 @@ export class SweeperP2p extends P2pApi {
|
|
|
503
476
|
}).join('');
|
|
504
477
|
const cacheFileLength = this.fileLengthCacheMap.get(fileName);
|
|
505
478
|
if (cacheFileLength > 0 && hexValue.length !== cacheFileLength * 2) {
|
|
506
|
-
|
|
479
|
+
this.log.warn({
|
|
507
480
|
msg: `p2pStreamPacketReceiveCallback: fileName : ${fileName} length mismatch, expected: ${cacheFileLength * 2}, received: ${hexValue.length}`
|
|
508
|
-
}
|
|
481
|
+
});
|
|
509
482
|
return;
|
|
510
483
|
}
|
|
511
484
|
if (this.firstPackageTime > 0 && fileName.indexOf('map') !== -1) {
|
|
512
485
|
const packageTime = Date.now() - this.firstPackageTime;
|
|
513
|
-
|
|
486
|
+
this.log.info({
|
|
514
487
|
msg: `receive first full package, cost time: ${packageTime} ms, fileName: ${fileName}`
|
|
515
|
-
}
|
|
488
|
+
});
|
|
516
489
|
trace.pointFn({
|
|
517
490
|
devId: this.devId,
|
|
518
491
|
eventName: 'receiveFirstFullPackage'
|
|
@@ -522,28 +495,7 @@ export class SweeperP2p extends P2pApi {
|
|
|
522
495
|
const {
|
|
523
496
|
type
|
|
524
497
|
} = FILE_NAME_MAP[fileName];
|
|
525
|
-
|
|
526
|
-
if (type === 0 || type === 6) {
|
|
527
|
-
this.onReceiveMapData(hexValue);
|
|
528
|
-
this.cacheData[type] = hexValue;
|
|
529
|
-
}
|
|
530
|
-
if (type === 1) {
|
|
531
|
-
logger('info', {
|
|
532
|
-
msg: `push new path data`
|
|
533
|
-
}, this.onLogger);
|
|
534
|
-
this.onReceivePathData(hexValue);
|
|
535
|
-
this.cacheData[type] = hexValue;
|
|
536
|
-
}
|
|
537
|
-
if (type === 4) {
|
|
538
|
-
this.onReceiveAIPicData(hexValue);
|
|
539
|
-
}
|
|
540
|
-
if (type === 5) {
|
|
541
|
-
this.onReceiveAIPicHDData(hexValue);
|
|
542
|
-
}
|
|
543
|
-
if (type === 7) {
|
|
544
|
-
this.onReceiveWifiMapData(hexValue);
|
|
545
|
-
}
|
|
546
|
-
}
|
|
498
|
+
this.handleDataByType(type, hexValue);
|
|
547
499
|
}
|
|
548
500
|
}
|
|
549
501
|
};
|
|
@@ -565,86 +517,65 @@ export class SweeperP2p extends P2pApi {
|
|
|
565
517
|
const bytes = Base64.toByteArray(params.data);
|
|
566
518
|
const hexValue = join(map(bytes, d => padStart(d.toString(16), 2, '0')), '');
|
|
567
519
|
const type = this.getFileType(fileName);
|
|
568
|
-
if (
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
return;
|
|
574
|
-
}
|
|
575
|
-
if (type === 0 || type === 6) {
|
|
576
|
-
this.onReceiveMapData(hexValue);
|
|
577
|
-
}
|
|
578
|
-
if (type === 1) {
|
|
579
|
-
this.onReceivePathData(hexValue);
|
|
580
|
-
}
|
|
581
|
-
if (type === 4) {
|
|
582
|
-
this.onReceiveAIPicData(hexValue);
|
|
583
|
-
}
|
|
584
|
-
if (type === 5) {
|
|
585
|
-
this.onReceiveAIPicHDData(hexValue);
|
|
586
|
-
}
|
|
587
|
-
if (type === 7) {
|
|
588
|
-
this.onReceiveWifiMapData(hexValue);
|
|
589
|
-
}
|
|
590
|
-
this.cacheData[type] = hexValue;
|
|
520
|
+
if (hexValue.length === 0) {
|
|
521
|
+
this.log.warn({
|
|
522
|
+
msg: 'receive empty data'
|
|
523
|
+
});
|
|
524
|
+
return;
|
|
591
525
|
}
|
|
526
|
+
this.handleDataByType(type, hexValue);
|
|
592
527
|
},
|
|
593
528
|
fail: e => {
|
|
594
|
-
|
|
529
|
+
this.log.warn({
|
|
595
530
|
msg: 'readFileFromPath failed ==>',
|
|
596
531
|
e
|
|
597
|
-
}
|
|
532
|
+
});
|
|
598
533
|
this.resetReading(fileName);
|
|
599
534
|
}
|
|
600
535
|
});
|
|
601
536
|
} catch (e) {
|
|
602
537
|
this.resetReading(fileName);
|
|
603
|
-
|
|
538
|
+
this.log.error({
|
|
604
539
|
msg: 'readFileFromPath ==>',
|
|
605
540
|
e
|
|
606
|
-
}
|
|
541
|
+
});
|
|
607
542
|
}
|
|
608
543
|
};
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* 根据文件名获取对应的 reading 状态标志
|
|
547
|
+
*/
|
|
548
|
+
getReadingFlag = fileName => {
|
|
549
|
+
if (fileName.includes('map_structured') || fileName.includes('map.')) {
|
|
550
|
+
return 'readingMap';
|
|
614
551
|
}
|
|
615
|
-
if (fileName.
|
|
616
|
-
|
|
617
|
-
this.readingMap = true;
|
|
618
|
-
return true;
|
|
552
|
+
if (fileName.includes('cleanPath')) {
|
|
553
|
+
return 'readingClean';
|
|
619
554
|
}
|
|
620
|
-
if (fileName.
|
|
621
|
-
|
|
622
|
-
this.readingClean = true;
|
|
623
|
-
return true;
|
|
555
|
+
if (fileName.includes('ai.') && !fileName.includes('aiHD')) {
|
|
556
|
+
return 'readingAI';
|
|
624
557
|
}
|
|
625
|
-
if (fileName.
|
|
626
|
-
|
|
627
|
-
this.readingAI = true;
|
|
628
|
-
return true;
|
|
558
|
+
if (fileName.includes('aiHD')) {
|
|
559
|
+
return 'readingHD';
|
|
629
560
|
}
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
561
|
+
return null;
|
|
562
|
+
};
|
|
563
|
+
setReading = fileName => {
|
|
564
|
+
const flag = this.getReadingFlag(fileName);
|
|
565
|
+
if (!flag) {
|
|
633
566
|
return true;
|
|
634
567
|
}
|
|
568
|
+
const readingState = this[flag];
|
|
569
|
+
if (readingState) {
|
|
570
|
+
return false;
|
|
571
|
+
}
|
|
572
|
+
this[flag] = true;
|
|
635
573
|
return true;
|
|
636
574
|
};
|
|
637
575
|
resetReading = fileName => {
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
this.readingMap = false;
|
|
642
|
-
} else if (fileName.indexOf('cleanPath') !== -1) {
|
|
643
|
-
this.readingClean = false;
|
|
644
|
-
} else if (fileName.indexOf('ai.') !== -1) {
|
|
645
|
-
this.readingAI = false;
|
|
646
|
-
} else if (fileName.indexOf('aiHD') !== -1) {
|
|
647
|
-
this.readingHD = false;
|
|
576
|
+
const flag = this.getReadingFlag(fileName);
|
|
577
|
+
if (flag) {
|
|
578
|
+
this[flag] = false;
|
|
648
579
|
}
|
|
649
580
|
};
|
|
650
581
|
|
|
@@ -653,21 +584,11 @@ export class SweeperP2p extends P2pApi {
|
|
|
653
584
|
* @param fileList
|
|
654
585
|
*/
|
|
655
586
|
queryNeedFiles = fileList => {
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
if (dataPattern.test(item.filename)) {
|
|
662
|
-
exitFiles.push(item.filename);
|
|
663
|
-
}
|
|
664
|
-
} else if (this.downloadType === 1) {
|
|
665
|
-
if (streamPattern.test(item.filename)) {
|
|
666
|
-
exitFiles.push(item.filename);
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
});
|
|
670
|
-
return exitFiles;
|
|
587
|
+
if (!(fileList !== null && fileList !== void 0 && fileList.length)) {
|
|
588
|
+
return [];
|
|
589
|
+
}
|
|
590
|
+
const pattern = this.downloadType === 0 ? /\.bin$/ : /\.bin\.stream$/;
|
|
591
|
+
return fileList.filter(item => pattern.test(item.filename)).map(item => item.filename);
|
|
671
592
|
};
|
|
672
593
|
|
|
673
594
|
/**
|
|
@@ -676,13 +597,13 @@ export class SweeperP2p extends P2pApi {
|
|
|
676
597
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, consistent-return
|
|
677
598
|
stopObserverSweeperDataByP2P = () => {
|
|
678
599
|
try {
|
|
679
|
-
|
|
600
|
+
this.log.info({
|
|
680
601
|
msg: `isConnected: ${this.isConnected}, devId: ${this.devId}`
|
|
681
|
-
}
|
|
602
|
+
});
|
|
682
603
|
if (this.isConnected) {
|
|
683
|
-
|
|
604
|
+
this.log.info({
|
|
684
605
|
msg: `try disconnect device, devId: ${this.devId}`
|
|
685
|
-
}
|
|
606
|
+
});
|
|
686
607
|
this.disconnectDevice();
|
|
687
608
|
}
|
|
688
609
|
this.removeP2pDownloadEvent();
|
|
@@ -693,10 +614,10 @@ export class SweeperP2p extends P2pApi {
|
|
|
693
614
|
typeof this.offSessionStatusChange === 'function' && this.offSessionStatusChange();
|
|
694
615
|
// 销毁初始化时,先进行断连操作
|
|
695
616
|
} catch (e) {
|
|
696
|
-
|
|
617
|
+
this.log.error({
|
|
697
618
|
msg: 'stopObserverSweeperDataByP2P occur error ==>',
|
|
698
619
|
e
|
|
699
|
-
}
|
|
620
|
+
});
|
|
700
621
|
return false;
|
|
701
622
|
}
|
|
702
623
|
};
|