@aiot-toolkit/emulator 2.0.2-beta.1 → 2.0.2-beta.11

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.
@@ -35,8 +35,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
35
35
  return (mod && mod.__esModule) ? mod : { "default": mod };
36
36
  };
37
37
  Object.defineProperty(exports, "__esModule", { value: true });
38
- const ColorConsole_1 = __importDefault(require("@aiot-toolkit/shared-utils/lib/ColorConsole"));
39
- const FileUtil_1 = __importDefault(require("@aiot-toolkit/shared-utils/lib/utils/FileUtil"));
38
+ const shared_utils_1 = require("@aiot-toolkit/shared-utils");
40
39
  const adbMiwt = __importStar(require("@miwt/adb"));
41
40
  const child_process_1 = require("child_process");
42
41
  const find_process_1 = __importDefault(require("find-process"));
@@ -46,25 +45,40 @@ const path_1 = __importDefault(require("path"));
46
45
  const portfinder_1 = __importDefault(require("portfinder"));
47
46
  const constants_1 = require("../static/constants");
48
47
  const common_1 = __importDefault(require("./common"));
48
+ /**
49
+ * OldGoldfishInstance
50
+ * 针对 Vela开发版(dev, 0.0.2)的镜像
51
+ */
49
52
  class OldGoldfishInstance extends common_1.default {
50
53
  constructor(params) {
51
54
  super(params);
52
55
  this.host9pPort = 7878;
53
56
  }
54
- /** 在goldfish模拟器中运行快应用 */
57
+ /**
58
+ * 1. 启动9p server
59
+ * 2. 将打包好的rpk推到host的挂载目录
60
+ * 3. 启动模拟器
61
+ * 4. 模拟器启动成功后,adb连接模拟器
62
+ * 5. 连接成功后,在模拟器中启动快应用
63
+ */
55
64
  start(options) {
56
65
  return __awaiter(this, void 0, void 0, function* () {
66
+ this.startOptions = options;
67
+ this.sn = `127.0.0.1:${this.startOptions.adbPort}`;
57
68
  // host启动9p server
58
69
  yield this.ensure9pServerRunnning();
59
- this.startOptions = options;
60
70
  // 将rpk推到host的./export/qa/app目录
61
- const buildedFilesPath = this.isRpk ? this.projectPath : path_1.default.resolve(this.projectPath, './build');
71
+ const buildedFilesPath = this.isRpk
72
+ ? this.projectPath
73
+ : path_1.default.resolve(this.projectPath, './build');
62
74
  this.pushRpk(buildedFilesPath);
63
75
  // 启动模拟器
64
76
  yield this.startGoldfish(options);
77
+ // adb连接快应用
65
78
  const connected = yield this.connectGoldfish();
66
79
  if (connected) {
67
- ColorConsole_1.default.log('### Emulator ### Goldfish emulator connected successfully');
80
+ shared_utils_1.ColorConsole.log('### Emulator ### Goldfish emulator connected successfully');
81
+ // 如果是首次启动,创建server端监听事件
68
82
  if (this.isFirstStart && this.startOptions.serverPort) {
69
83
  yield this.createWebsockeServer();
70
84
  }
@@ -73,41 +87,49 @@ class OldGoldfishInstance extends common_1.default {
73
87
  this.isFirstStart = false;
74
88
  }
75
89
  else {
76
- ColorConsole_1.default.throw('### Emulator ### Failed to connect emulator, please check whether the adb is normal');
90
+ shared_utils_1.ColorConsole.throw('### Emulator ### Failed to connect emulator, please check whether the adb is normal');
77
91
  }
78
92
  });
79
93
  }
80
- /** 在goldfish中启动快应用 */
94
+ /**
95
+ * 在模拟器中启动快应用(快应用都在模拟器的/data/app目录下)
96
+ * 1. 是否为调试模式
97
+ * 若是,在模拟器终端执行vapp app/${packageName} &
98
+ * 若否,在模拟器终端执行vapp --jsdebugger=10.0.2.15:101 app/${packageName} &
99
+ */
81
100
  startupQuickApp(options) {
82
101
  try {
83
102
  const { package: packageName } = this.projectInfo;
84
103
  const appMountDir = path_1.default.resolve(this.sdkHome, 'qa');
85
- const mountCmd = `adb -s 127.0.0.1:${this.adbPort} shell mount -t v9fs -o tag=10.0.2.2,port=${this.host9pPort},aname=${appMountDir} /data`;
86
- ColorConsole_1.default.log(`### Emulator ### Excuting adb cmd: ${mountCmd}`);
104
+ const mountCmd = `adb -s 127.0.0.1:${options.adbPort} shell mount -t v9fs -o tag=10.0.2.2,port=${this.host9pPort},aname=${appMountDir} /data`;
105
+ shared_utils_1.ColorConsole.log(`### Emulator ### Excuting adb cmd: ${mountCmd}`);
87
106
  adbMiwt.execAdbCmdSync(mountCmd);
88
- let vappCmd = `adb -s 127.0.0.1:${this.adbPort} shell vapp app/${packageName} &`;
107
+ let vappCmd = `adb -s 127.0.0.1:${options.adbPort} shell vapp app/${packageName} &`;
108
+ // 调试情况下,需要加--jsdebugger=10.0.2.15:101
89
109
  if (options.devtool) {
90
- vappCmd = `adb -s 127.0.0.1:${this.adbPort} shell vapp --jsdebugger=10.0.2.15:101 app/${packageName} &`;
110
+ vappCmd = `adb -s 127.0.0.1:${options.adbPort} shell vapp --jsdebugger=10.0.2.15:101 app/${packageName} &`;
91
111
  }
92
- ColorConsole_1.default.log(`### Emulator ### Excuting adb cmd: ${vappCmd}`);
112
+ shared_utils_1.ColorConsole.log(`### Emulator ### Excuting adb cmd: ${vappCmd}`);
93
113
  // vapp进程会一直pending,不会退出。这里必须加stdio: 'ignore',否则快应用无法运行成功
94
114
  adbMiwt.execAdbCmdAsync(vappCmd, { stdio: 'ignore', encoding: 'utf-8' });
95
115
  }
96
116
  catch (e) {
97
- ColorConsole_1.default.error(`### Emulator ### Failed to startup quickapp: ${e.message}`);
117
+ shared_utils_1.ColorConsole.error(`### Emulator ### Failed to startup quickapp: ${e.message}`);
98
118
  }
99
119
  }
100
- /** host启动9pServer */
120
+ /** host启动9pServer
121
+ * 作用是将本地的quickappMountDir目录挂载到模拟器的/data目录
122
+ */
101
123
  ensure9pServerRunnning() {
102
124
  return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
103
125
  var _a;
104
126
  const yaFileName = os_1.default.platform() === 'win32' ? 'ya-vm-file-server.exe' : 'ya-vm-file-server';
105
127
  const pidList = yield (0, find_process_1.default)('name', yaFileName);
106
128
  if (pidList.length > 0) {
107
- ColorConsole_1.default.log('### Emulator ### 9p server started in host');
129
+ shared_utils_1.ColorConsole.log('### Emulator ### 9p server started in host');
108
130
  return resolve();
109
131
  }
110
- ColorConsole_1.default.log('### Emulator ### Starting 9p server in host');
132
+ shared_utils_1.ColorConsole.log('### Emulator ### Starting 9p server in host');
111
133
  const quickappMountDir = path_1.default.resolve(this.sdkHome, 'qa');
112
134
  const toolsHome = path_1.default.resolve(this.sdkHome, 'tools');
113
135
  const serverBinPath = path_1.default.resolve(toolsHome, yaFileName);
@@ -121,49 +143,60 @@ class OldGoldfishInstance extends common_1.default {
121
143
  address,
122
144
  '--debug'
123
145
  ]);
146
+ // 监听stderr,判断9p server是否启动成功了
124
147
  (_a = this.v9fsProcess.stderr) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
125
148
  const output = data.toString();
126
149
  if (output.match(/Server started, listening on: 127.0.0.1:(\d+)/)) {
127
- ColorConsole_1.default.log(output);
128
- ColorConsole_1.default.log('### Emulator ### 9p server starts successfully');
150
+ shared_utils_1.ColorConsole.log(output);
151
+ shared_utils_1.ColorConsole.log('### Emulator ### 9p server starts successfully');
129
152
  return resolve();
130
153
  }
131
154
  });
155
+ // 监听exit事件,判断9p server是否退出了
132
156
  this.v9fsProcess.on('exit', (code) => {
133
- ColorConsole_1.default.error(`### Emulator ### ya-vm-file-server exited with code ${code}`);
157
+ shared_utils_1.ColorConsole.error(`### Emulator ### ya-vm-file-server exited with code ${code}`);
134
158
  return reject();
135
159
  });
136
160
  }));
137
161
  }
138
- /** 启动goldfish模拟器 */
162
+ /**
163
+ * 启动模拟器
164
+ * 1. 通过options生成模拟器的启动命令
165
+ * 2. 执行启动命令
166
+ * 3. 判断模拟器是否启动成功
167
+ * 3.1 若disableNSH=true,输出流中匹配到/quickapp_rpk_installer_init|rpk installer init done/,认为模拟器启动成功了
168
+ * 3.2 若disableNSH=false,认为8s过后模拟器启动成功了
169
+ * @param options
170
+ * @returns
171
+ */
139
172
  startGoldfish(options) {
140
173
  return __awaiter(this, void 0, void 0, function* () {
141
- const { avdName, devtool } = options;
174
+ const { avdName, devtool, origin = 'terminal' } = options;
175
+ // 获取emulator bin的绝对路径
142
176
  const emulatorBin = this.getEmulatorBinPath();
143
- ColorConsole_1.default.log(`### Emulator ### emulator path: ${emulatorBin}`);
177
+ shared_utils_1.ColorConsole.log(`### Emulator ### emulator path: ${emulatorBin}`);
178
+ // 获取vela镜像的绝对路径
144
179
  const avdInfo = this.velaAvdCls.getVelaAvdInfo(avdName);
145
180
  const { avdArch, avdImagePath } = avdInfo;
146
- this.adbPort = yield portfinder_1.default.getPortPromise({ port: this.adbPort });
147
- ColorConsole_1.default.log(`### Emulator ### adb port: ${this.adbPort}`);
181
+ shared_utils_1.ColorConsole.log(`### Emulator ### adb port: ${options.adbPort}`);
148
182
  if (!avdImagePath) {
149
- return ColorConsole_1.default.throw(`### Emulator ### Unable to find vela image via avd`);
183
+ return shared_utils_1.ColorConsole.throw(`### Emulator ### Unable to find vela image via avd`);
150
184
  }
151
185
  const nuttxBinPath = path_1.default.resolve(avdImagePath, 'nuttx');
152
- ColorConsole_1.default.log(`### Emulator ### nuttx path: ${nuttxBinPath}`);
153
- let portMappingStr = `user,id=u1,hostfwd=tcp:127.0.0.1:${this.adbPort}-10.0.2.15:5555`;
186
+ shared_utils_1.ColorConsole.log(`### Emulator ### nuttx path: ${nuttxBinPath}`);
187
+ // 端口映射,adb端口和debug端口
188
+ let portMappingStr = `user,id=u1,hostfwd=tcp:127.0.0.1:${options.adbPort}-10.0.2.15:5555`;
154
189
  if (devtool) {
155
- this.debugPort = yield portfinder_1.default.getPortPromise({ port: this.debugPort });
156
- ColorConsole_1.default.log(`### Emulator ### debug port: ${this.debugPort}`);
157
- portMappingStr += `,hostfwd=tcp:127.0.0.1:${this.debugPort}-10.0.2.15:101`;
190
+ shared_utils_1.ColorConsole.log(`### Emulator ### debug port: ${options.debugPort}`);
191
+ portMappingStr += `,hostfwd=tcp:127.0.0.1:${options.debugPort}-10.0.2.15:101`;
158
192
  }
159
- ColorConsole_1.default.log(`### Emulator ### Start qemu with TCP: ${portMappingStr}`);
160
- const stdioType = options.disableNSH ? 'pipe' : 'inherit';
193
+ shared_utils_1.ColorConsole.log(`### Emulator ### Start qemu with TCP: ${portMappingStr}`);
161
194
  // vnc配置
162
195
  let noWindow = false;
163
196
  let vncStr = '';
164
- if (options.vncPort) {
197
+ if (options.grpcPort) {
165
198
  noWindow = true;
166
- const portSuffix = options.vncPort - constants_1.defaultVncPort;
199
+ const portSuffix = options.grpcPort - constants_1.defaultVncPort;
167
200
  vncStr = `-vnc :${portSuffix}`;
168
201
  }
169
202
  // 启动goldfish的命令和参数
@@ -185,77 +218,53 @@ class OldGoldfishInstance extends common_1.default {
185
218
  '-device',
186
219
  'virtio-net-device,netdev=u1,bus=virtio-mmio-bus.3'
187
220
  ];
188
- ColorConsole_1.default.log(`### Emulator ### Start CMD: ${spawnBin} ${spawnArgs.join(' ')}`);
221
+ shared_utils_1.ColorConsole.log(`### Emulator ### Start CMD: ${spawnBin} ${spawnArgs.join(' ')}`);
189
222
  return new Promise((resolve) => {
190
- var _a;
191
- this.goldfishProcess = (0, child_process_1.spawn)(spawnBin, spawnArgs, { stdio: stdioType, shell: true });
223
+ var _a, _b, _c, _d;
224
+ this.goldfishProcess = (0, child_process_1.spawn)(spawnBin, spawnArgs, { stdio: 'pipe', shell: true });
225
+ // 监听错误流
192
226
  (_a = this.goldfishProcess.stderr) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
193
227
  const stderrCb = options.stderrCallback || console.log;
194
228
  stderrCb(data.toString());
195
229
  });
230
+ if (origin === 'terminal') {
231
+ process.stdout.pipe(this.goldfishProcess.stdin);
232
+ (_b = this.goldfishProcess.stdout) === null || _b === void 0 ? void 0 : _b.pipe(process.stdout);
233
+ }
234
+ // 监听模拟器的退出事件
196
235
  this.goldfishProcess.on('exit', (code) => {
197
- ColorConsole_1.default.error(`### Emulator ### Goldfish emulator exited with code ${code}`);
236
+ shared_utils_1.ColorConsole.error(`### Emulator ### Goldfish emulator exited with code ${code}`);
198
237
  if (options.exitCallback) {
199
238
  options.exitCallback(code);
200
239
  }
201
240
  });
202
- const p1 = new Promise((resolve) => {
203
- var _a, _b;
204
- (_b = (_a = this.goldfishProcess) === null || _a === void 0 ? void 0 : _a.stdout) === null || _b === void 0 ? void 0 : _b.on('data', (data) => {
241
+ // 监听输出流。输出了'(NSH)'标识后则认为模拟器启动成功
242
+ (_d = (_c = this.goldfishProcess) === null || _c === void 0 ? void 0 : _c.stdout) === null || _d === void 0 ? void 0 : _d.on('data', (data) => {
243
+ const msg = data.toString();
244
+ if (origin === 'ide') {
205
245
  const stdoutCb = options.stdoutCallback || console.log;
206
- stdoutCb(data.toString());
207
- if (data.toString().includes('(NSH)')) {
208
- ColorConsole_1.default.log(`### Emulator ### Goldfish emulator starts successfully`);
209
- resolve();
210
- }
211
- });
246
+ stdoutCb(msg);
247
+ }
248
+ if (msg.includes('(NSH)')) {
249
+ shared_utils_1.ColorConsole.log(`### Emulator ### Goldfish emulator starts successfully`);
250
+ resolve();
251
+ }
212
252
  });
213
- const p2 = setTimeout(() => {
214
- ColorConsole_1.default.log(`### Emulator ### Goldfish emulator starts successfully`);
215
- resolve();
216
- }, 2000);
217
- return Promise.race([p1, p2]);
218
253
  });
219
254
  });
220
255
  }
221
- /** 通过adb连接模拟器 */
222
- connectGoldfish() {
223
- return __awaiter(this, void 0, void 0, function* () {
224
- let adbConnected = false;
225
- const connectFn = () => __awaiter(this, void 0, void 0, function* () {
226
- const sn = `127.0.0.1:${this.adbPort}`;
227
- while (!adbConnected) {
228
- const adbKillCmd = `adb kill-server`;
229
- ColorConsole_1.default.log(`### Emulator ### Excuting adb cmd: ${adbKillCmd}`);
230
- adbMiwt.execAdbCmdSync(adbKillCmd);
231
- const adbConnectCmd = `adb connect ${sn}`;
232
- ColorConsole_1.default.log(`### Emulator ### Excuting adb cmd: ${adbConnectCmd}`);
233
- const str = adbMiwt.execAdbCmdSync(adbConnectCmd);
234
- ColorConsole_1.default.log(`### Emulator ### ${str}`);
235
- const devices = yield adbMiwt.getAdbDevices();
236
- ColorConsole_1.default.log(`### Emulator ### adb devices: ${JSON.stringify(devices)}`);
237
- adbConnected =
238
- devices.filter((item) => item.sn === sn && item.status === 'device').length > 0;
239
- }
240
- Promise.resolve(adbConnected);
241
- });
242
- yield Promise.race([
243
- connectFn(),
244
- new Promise((resolve) => {
245
- setTimeout(() => resolve(false), 600 * 1000);
246
- })
247
- ]);
248
- return adbConnected;
249
- });
250
- }
256
+ /**
257
+ * 推送文件到本地的${sdkHome}/qa/app/${packageName}目录
258
+ * @param sourceRoot 源目录
259
+ */
251
260
  pushRpk(sourceRoot) {
252
261
  return __awaiter(this, void 0, void 0, function* () {
253
262
  const { package: appPackageName } = this.projectInfo;
254
263
  const appRunDir = path_1.default.resolve(this.sdkHome, 'qa/app', appPackageName);
255
- ColorConsole_1.default.log(`### Emulator ### Pushing ${appPackageName} to ${appRunDir}`);
264
+ shared_utils_1.ColorConsole.log(`### Emulator ### Pushing ${appPackageName} to ${appRunDir}`);
256
265
  fs_1.default.rmSync(appRunDir, { recursive: true, force: true });
257
- FileUtil_1.default.copyFiles(sourceRoot, appRunDir);
258
- ColorConsole_1.default.log(`### Emulator ### Push ${appPackageName} to ${appRunDir} successfully`);
266
+ shared_utils_1.FileUtil.copyFiles(sourceRoot, appRunDir);
267
+ shared_utils_1.ColorConsole.log(`### Emulator ### Push ${appPackageName} to ${appRunDir} successfully`);
259
268
  });
260
269
  }
261
270
  /** 停止模拟器并释放相关资源 */
@@ -0,0 +1 @@
1
+ ModemSimulator = on
@@ -6,14 +6,19 @@ export declare const defaultSkinHome: string;
6
6
  export declare const defaultQuickappHome: string;
7
7
  export declare const defaultToolsHome: string;
8
8
  export declare const defaultVncPort = 5900;
9
- export declare const emulatorEnvVersion: {
9
+ export declare const defaultAdbPort = 5555;
10
+ export declare const defaultDebugPort = 10055;
11
+ export declare const VelaImageVersionList: {
12
+ label: string;
13
+ value: string;
14
+ time: string;
15
+ }[];
16
+ export declare const EmulatorEnvVersion: {
10
17
  name: string;
11
18
  emulator: string;
12
19
  qa: string;
13
20
  skins: string;
14
- 'system-images': {
15
- release: string;
16
- dev: string;
17
- };
21
+ 'system-images': string;
18
22
  tools: string;
23
+ modem_simulator: string;
19
24
  };
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.emulatorEnvVersion = exports.defaultVncPort = exports.defaultToolsHome = exports.defaultQuickappHome = exports.defaultSkinHome = exports.defaultEmulatorHome = exports.defaultImageHome = exports.defaultAvdHome = exports.defaultSDKHome = void 0;
6
+ exports.EmulatorEnvVersion = exports.VelaImageVersionList = exports.defaultDebugPort = exports.defaultAdbPort = exports.defaultVncPort = exports.defaultToolsHome = exports.defaultQuickappHome = exports.defaultSkinHome = exports.defaultEmulatorHome = exports.defaultImageHome = exports.defaultAvdHome = exports.defaultSDKHome = void 0;
7
7
  const os_1 = __importDefault(require("os"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  exports.defaultSDKHome = path_1.default.resolve(os_1.default.homedir(), '.export');
@@ -14,14 +14,26 @@ exports.defaultSkinHome = path_1.default.resolve(exports.defaultSDKHome, 'skins'
14
14
  exports.defaultQuickappHome = path_1.default.resolve(exports.defaultSDKHome, 'qa');
15
15
  exports.defaultToolsHome = path_1.default.resolve(exports.defaultSDKHome, 'tools');
16
16
  exports.defaultVncPort = 5900;
17
- exports.emulatorEnvVersion = {
17
+ exports.defaultAdbPort = 5555;
18
+ exports.defaultDebugPort = 10055;
19
+ exports.VelaImageVersionList = [
20
+ {
21
+ label: 'vela正式版(4.0)',
22
+ value: 'vela-release-4.0',
23
+ time: '2024-04-10T04:10:00'
24
+ },
25
+ {
26
+ label: 'vela开发版(dev, 0.0.2)',
27
+ value: 'vela-dev-0.0.2',
28
+ time: '2023-12-04T16:31:00'
29
+ }
30
+ ];
31
+ exports.EmulatorEnvVersion = {
18
32
  name: '模拟器资源版本管理',
19
- emulator: '0.0.1',
33
+ emulator: '0.0.3',
20
34
  qa: '0.0.1',
21
35
  skins: '0.0.1',
22
- 'system-images': {
23
- release: '4.0',
24
- dev: '0.0.2'
25
- },
26
- tools: '0.0.2'
36
+ 'system-images': exports.VelaImageVersionList[0].value,
37
+ tools: '0.0.2',
38
+ modem_simulator: '0.0.1'
27
39
  };
@@ -1,16 +1,26 @@
1
1
  /// <reference types="node" />
2
- import { IAvdResourcePaths } from "./Avd";
2
+ import { IJavascriptCompileOption } from '@aiot-toolkit/aiotpack';
3
+ import { IAvdResourcePaths } from './Avd';
3
4
  export interface INewGoldfishInstanceParams extends IAvdResourcePaths {
4
5
  projectPath: string;
5
6
  sourceRoot?: string;
7
+ compilerOption?: Partial<IJavascriptCompileOption>;
6
8
  }
7
9
  export interface IStartOptions {
8
10
  avdName: string;
9
11
  devtool?: string;
12
+ /** @deprecated */
10
13
  disableNSH?: boolean;
14
+ origin?: 'ide' | 'terminal';
11
15
  serverPort?: number;
12
- vncPort?: number;
16
+ grpcPort?: number;
17
+ adbPort: number;
18
+ debugPort?: number;
13
19
  stdoutCallback?: (buffer: Buffer) => void;
14
20
  stderrCallback?: (buffer: Buffer) => void;
15
21
  exitCallback?: (code: number | null) => void;
22
+ /** 要推送的目录路径 */
23
+ dist?: string;
24
+ /** 要推送到的目的路径 */
25
+ tar?: string;
16
26
  }
@@ -9,4 +9,25 @@ export declare function killProcessByPid(pid: string): void;
9
9
  * 根据命令杀死进程
10
10
  */
11
11
  export declare function killProcessByCmd(cmd: string): Promise<void>;
12
+ /** 延迟函数 */
12
13
  export declare function sleep(time: number): Promise<void>;
14
+ /**
15
+ * 重复执行某个任务直到成功,或者超过最大次数
16
+ * @param task 任务,需要返回 bool 值表示是否执行成功
17
+ * @param {Number=} maxCount 最大重试次数
18
+ * @param {number=} duration 每次重试的间隔
19
+ */
20
+ export declare function tryRun(task: (...args: any[]) => Promise<any>, maxCount?: number, duration?: number, currentCount?: number): Promise<boolean>;
21
+ /**
22
+ * 延迟执行某个任务
23
+ * @param task
24
+ * @param duration
25
+ * @returns
26
+ */
27
+ export declare function delayRun<T = any>(task: (...args: any[]) => Promise<T> | T, duration?: number): Promise<T>;
28
+ /**
29
+ * 为avdPort寻找一个不被占用的端口
30
+ * 端口号必须是偶数且在5555和5585之间
31
+ * @returns {number}
32
+ */
33
+ export declare function getEvenPort(): Promise<number | false | undefined>;
@@ -12,17 +12,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.sleep = exports.killProcessByCmd = exports.killProcessByPid = exports.getSystemArch = void 0;
16
- const ColorConsole_1 = __importDefault(require("@aiot-toolkit/shared-utils/lib/ColorConsole"));
15
+ exports.getEvenPort = exports.delayRun = exports.tryRun = exports.sleep = exports.killProcessByCmd = exports.killProcessByPid = exports.getSystemArch = void 0;
16
+ const shared_utils_1 = require("@aiot-toolkit/shared-utils");
17
17
  const child_process_1 = require("child_process");
18
18
  const find_process_1 = __importDefault(require("find-process"));
19
19
  const os_1 = __importDefault(require("os"));
20
20
  const semver_1 = __importDefault(require("semver"));
21
+ const portfinder_1 = __importDefault(require("portfinder"));
21
22
  const cpuArch = {
22
23
  arm64: 'aarch64',
23
24
  aarch64: 'aarch64',
24
25
  x64: 'x86_64',
25
- x86_64: 'x86_64',
26
+ x86_64: 'x86_64'
26
27
  };
27
28
  /** 获取mac电脑的CPU架构
28
29
  * node 15.0.0之后,m1芯片的mac的os.arch()才是arm64,在这之前都是x86
@@ -42,7 +43,7 @@ function getSystemArch() {
42
43
  }
43
44
  }
44
45
  if (osArch !== 'arm64' && osArch !== 'x64') {
45
- return ColorConsole_1.default.throw(`unsupport system`);
46
+ return shared_utils_1.ColorConsole.throw(`unsupport system`);
46
47
  }
47
48
  return cpuArch[osArch];
48
49
  }
@@ -50,9 +51,7 @@ exports.getSystemArch = getSystemArch;
50
51
  /** 根据PID杀死进程 */
51
52
  function killProcessByPid(pid) {
52
53
  try {
53
- const cmd = os_1.default.platform() === "win32"
54
- ? `taskkill /pid ${pid} /T /F`
55
- : `kill -9 ${pid}`;
54
+ const cmd = os_1.default.platform() === 'win32' ? `taskkill /pid ${pid} /T /F` : `kill -9 ${pid}`;
56
55
  (0, child_process_1.execSync)(cmd);
57
56
  }
58
57
  catch (e) {
@@ -79,9 +78,68 @@ function killProcessByCmd(cmd) {
79
78
  });
80
79
  }
81
80
  exports.killProcessByCmd = killProcessByCmd;
81
+ /** 延迟函数 */
82
82
  function sleep(time) {
83
83
  return __awaiter(this, void 0, void 0, function* () {
84
- return new Promise(resolve => setTimeout(resolve, time));
84
+ return new Promise((resolve) => setTimeout(resolve, time));
85
85
  });
86
86
  }
87
87
  exports.sleep = sleep;
88
+ /**
89
+ * 重复执行某个任务直到成功,或者超过最大次数
90
+ * @param task 任务,需要返回 bool 值表示是否执行成功
91
+ * @param {Number=} maxCount 最大重试次数
92
+ * @param {number=} duration 每次重试的间隔
93
+ */
94
+ function tryRun(task, maxCount = 5, duration = 1000, currentCount = 0) {
95
+ return __awaiter(this, void 0, void 0, function* () {
96
+ if (currentCount > maxCount)
97
+ return false;
98
+ return (Boolean(yield task()) ||
99
+ (yield delayRun(() => tryRun(task, maxCount, duration, currentCount + 1), duration)));
100
+ });
101
+ }
102
+ exports.tryRun = tryRun;
103
+ /**
104
+ * 延迟执行某个任务
105
+ * @param task
106
+ * @param duration
107
+ * @returns
108
+ */
109
+ function delayRun(task, duration = 1000) {
110
+ return __awaiter(this, void 0, void 0, function* () {
111
+ return new Promise((resolve) => {
112
+ setTimeout(() => __awaiter(this, void 0, void 0, function* () {
113
+ return resolve(task());
114
+ }), duration);
115
+ });
116
+ });
117
+ }
118
+ exports.delayRun = delayRun;
119
+ /**
120
+ * 为avdPort寻找一个不被占用的端口
121
+ * 端口号必须是偶数且在5555和5585之间
122
+ * @returns {number}
123
+ */
124
+ function getEvenPort() {
125
+ return __awaiter(this, void 0, void 0, function* () {
126
+ const startPort = 5555;
127
+ const stopPort = 5585;
128
+ let index = 1;
129
+ let port = yield portfinder_1.default.getPortPromise({
130
+ port: startPort,
131
+ stopPort
132
+ });
133
+ while (port % 2 !== 0) {
134
+ if (index > 30)
135
+ return false;
136
+ port = yield portfinder_1.default.getPortPromise({
137
+ port: startPort + index,
138
+ stopPort
139
+ });
140
+ index++;
141
+ return port;
142
+ }
143
+ });
144
+ }
145
+ exports.getEvenPort = getEvenPort;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiot-toolkit/emulator",
3
- "version": "2.0.2-beta.1",
3
+ "version": "2.0.2-beta.11",
4
4
  "description": "vela emulator tool.",
5
5
  "homepage": "",
6
6
  "license": "ISC",
@@ -35,10 +35,14 @@
35
35
  "emulator"
36
36
  ],
37
37
  "dependencies": {
38
- "@aiot-toolkit/aiotpack": "2.0.2-beta.1",
39
- "@aiot-toolkit/shared-utils": "2.0.2-beta.1",
38
+ "@aiot-toolkit/aiotpack": "2.0.2-beta.11",
39
+ "@aiot-toolkit/shared-utils": "2.0.2-beta.11",
40
40
  "find-process": "^1.4.7",
41
41
  "portfinder": "^1.0.32"
42
42
  },
43
- "gitHead": "9244af36e617295ea4ff11a2f4f07f0e4f9f5f59"
43
+ "devDependencies": {
44
+ "@types/fs-extra": "^11.0.4",
45
+ "fs-extra": "^11.2.0"
46
+ },
47
+ "gitHead": "07c38dd12ba0d932c6dc1fd16fe25aaf15ab9fbb"
44
48
  }