@aiot-toolkit/emulator 2.0.2-dev.7 → 2.0.2

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.
@@ -1,21 +1,51 @@
1
- /// <reference types="node" />
2
1
  import { ChildProcess } from 'child_process';
2
+ import readline from 'readline';
3
3
  import { INewGoldfishInstanceParams, IStartOptions } from '../typing/Instance';
4
4
  import CommonInstance from './common';
5
+ /**
6
+ * OldGoldfishInstance
7
+ * 针对 Vela开发版(dev, 0.0.2)的镜像
8
+ */
5
9
  declare class OldGoldfishInstance extends CommonInstance {
6
10
  private host9pPort;
7
11
  v9fsProcess: ChildProcess | undefined;
12
+ stdoutReadline: readline.Interface;
13
+ stderrReadline: readline.Interface;
8
14
  constructor(params: INewGoldfishInstanceParams);
9
- /** 在goldfish模拟器中运行快应用 */
15
+ /**
16
+ * 1. 启动9p server
17
+ * 2. 将打包好的rpk推到host的挂载目录
18
+ * 3. 启动模拟器
19
+ * 4. 模拟器启动成功后,adb连接模拟器
20
+ * 5. 连接成功后,在模拟器中启动快应用
21
+ */
10
22
  start(options: IStartOptions): Promise<void>;
11
- /** 在goldfish中启动快应用 */
23
+ /**
24
+ * 在模拟器中启动快应用(快应用都在模拟器的/data/app目录下)
25
+ * 1. 是否为调试模式
26
+ * 若是,在模拟器终端执行vapp app/${packageName} &
27
+ * 若否,在模拟器终端执行vapp --jsdebugger=10.0.2.15:101 app/${packageName} &
28
+ */
12
29
  startupQuickApp(options: IStartOptions): void;
13
- /** host启动9pServer */
30
+ /** host启动9pServer
31
+ * 作用是将本地的quickappMountDir目录挂载到模拟器的/data目录
32
+ */
14
33
  ensure9pServerRunnning(): Promise<void>;
15
- /** 启动goldfish模拟器 */
34
+ /**
35
+ * 启动模拟器
36
+ * 1. 通过options生成模拟器的启动命令
37
+ * 2. 执行启动命令
38
+ * 3. 判断模拟器是否启动成功
39
+ * 3.1 若disableNSH=true,输出流中匹配到/quickapp_rpk_installer_init|rpk installer init done/,认为模拟器启动成功了
40
+ * 3.2 若disableNSH=false,认为8s过后模拟器启动成功了
41
+ * @param options
42
+ * @returns
43
+ */
16
44
  startGoldfish(options: IStartOptions): Promise<void>;
17
- /** 通过adb连接模拟器 */
18
- connectGoldfish(): Promise<boolean>;
45
+ /**
46
+ * 推送文件到本地的${sdkHome}/qa/app/${packageName}目录
47
+ * @param sourceRoot 源目录
48
+ */
19
49
  pushRpk(sourceRoot: string): Promise<void>;
20
50
  /** 停止模拟器并释放相关资源 */
21
51
  stop(): Promise<void>;
@@ -44,27 +44,44 @@ const fs_1 = __importDefault(require("fs"));
44
44
  const os_1 = __importDefault(require("os"));
45
45
  const path_1 = __importDefault(require("path"));
46
46
  const portfinder_1 = __importDefault(require("portfinder"));
47
- const constants_1 = require("../static/constants");
47
+ const readline_1 = __importDefault(require("readline"));
48
+ const Instance_1 = require("../typing/Instance");
49
+ const emulatorutil_1 = require("../emulatorutil");
48
50
  const common_1 = __importDefault(require("./common"));
51
+ /**
52
+ * OldGoldfishInstance
53
+ * 针对 Vela开发版(dev, 0.0.2)的镜像
54
+ */
49
55
  class OldGoldfishInstance extends common_1.default {
50
56
  constructor(params) {
51
57
  super(params);
52
58
  this.host9pPort = 7878;
53
59
  }
54
- /** 在goldfish模拟器中运行快应用 */
60
+ /**
61
+ * 1. 启动9p server
62
+ * 2. 将打包好的rpk推到host的挂载目录
63
+ * 3. 启动模拟器
64
+ * 4. 模拟器启动成功后,adb连接模拟器
65
+ * 5. 连接成功后,在模拟器中启动快应用
66
+ */
55
67
  start(options) {
56
68
  return __awaiter(this, void 0, void 0, function* () {
69
+ this.startOptions = options;
70
+ this.sn = `127.0.0.1:${this.startOptions.adbPort}`;
57
71
  // host启动9p server
58
72
  yield this.ensure9pServerRunnning();
59
- this.startOptions = options;
60
73
  // 将rpk推到host的./export/qa/app目录
61
- const buildedFilesPath = this.isRpk ? this.projectPath : path_1.default.resolve(this.projectPath, './build');
74
+ const buildedFilesPath = this.isRpk
75
+ ? this.projectPath
76
+ : path_1.default.resolve(this.projectPath, './build');
62
77
  this.pushRpk(buildedFilesPath);
63
78
  // 启动模拟器
64
79
  yield this.startGoldfish(options);
80
+ // adb连接快应用
65
81
  const connected = yield this.connectGoldfish();
66
82
  if (connected) {
67
83
  ColorConsole_1.default.log('### Emulator ### Goldfish emulator connected successfully');
84
+ // 如果是首次启动,创建server端监听事件
68
85
  if (this.isFirstStart && this.startOptions.serverPort) {
69
86
  yield this.createWebsockeServer();
70
87
  }
@@ -77,17 +94,23 @@ class OldGoldfishInstance extends common_1.default {
77
94
  }
78
95
  });
79
96
  }
80
- /** 在goldfish中启动快应用 */
97
+ /**
98
+ * 在模拟器中启动快应用(快应用都在模拟器的/data/app目录下)
99
+ * 1. 是否为调试模式
100
+ * 若是,在模拟器终端执行vapp app/${packageName} &
101
+ * 若否,在模拟器终端执行vapp --jsdebugger=10.0.2.15:101 app/${packageName} &
102
+ */
81
103
  startupQuickApp(options) {
82
104
  try {
83
105
  const { package: packageName } = this.projectInfo;
84
106
  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`;
107
+ 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`;
86
108
  ColorConsole_1.default.log(`### Emulator ### Excuting adb cmd: ${mountCmd}`);
87
109
  adbMiwt.execAdbCmdSync(mountCmd);
88
- let vappCmd = `adb -s 127.0.0.1:${this.adbPort} shell vapp app/${packageName} &`;
110
+ let vappCmd = `adb -s 127.0.0.1:${options.adbPort} shell vapp app/${packageName} &`;
111
+ // 调试情况下,需要加--jsdebugger=10.0.2.15:101
89
112
  if (options.devtool) {
90
- vappCmd = `adb -s 127.0.0.1:${this.adbPort} shell vapp --jsdebugger=10.0.2.15:101 app/${packageName} &`;
113
+ vappCmd = `adb -s 127.0.0.1:${options.adbPort} shell vapp --jsdebugger=10.0.2.15:101 app/${packageName} &`;
91
114
  }
92
115
  ColorConsole_1.default.log(`### Emulator ### Excuting adb cmd: ${vappCmd}`);
93
116
  // vapp进程会一直pending,不会退出。这里必须加stdio: 'ignore',否则快应用无法运行成功
@@ -97,7 +120,9 @@ class OldGoldfishInstance extends common_1.default {
97
120
  ColorConsole_1.default.error(`### Emulator ### Failed to startup quickapp: ${e.message}`);
98
121
  }
99
122
  }
100
- /** host启动9pServer */
123
+ /** host启动9pServer
124
+ * 作用是将本地的quickappMountDir目录挂载到模拟器的/data目录
125
+ */
101
126
  ensure9pServerRunnning() {
102
127
  return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
103
128
  var _a;
@@ -121,133 +146,82 @@ class OldGoldfishInstance extends common_1.default {
121
146
  address,
122
147
  '--debug'
123
148
  ]);
149
+ // 监听stderr,判断9p server是否启动成功了
124
150
  (_a = this.v9fsProcess.stderr) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
125
151
  const output = data.toString();
126
- if (output.match(/Server started, listening on: 127.0.0.1:(\d+)/)) {
127
- ColorConsole_1.default.log(output);
152
+ if (emulatorutil_1.EmulatorLog.preDevIsStart(output)) {
128
153
  ColorConsole_1.default.log('### Emulator ### 9p server starts successfully');
129
154
  return resolve();
130
155
  }
131
156
  });
157
+ // 监听exit事件,判断9p server是否退出了
132
158
  this.v9fsProcess.on('exit', (code) => {
133
159
  ColorConsole_1.default.error(`### Emulator ### ya-vm-file-server exited with code ${code}`);
134
160
  return reject();
135
161
  });
136
162
  }));
137
163
  }
138
- /** 启动goldfish模拟器 */
164
+ /**
165
+ * 启动模拟器
166
+ * 1. 通过options生成模拟器的启动命令
167
+ * 2. 执行启动命令
168
+ * 3. 判断模拟器是否启动成功
169
+ * 3.1 若disableNSH=true,输出流中匹配到/quickapp_rpk_installer_init|rpk installer init done/,认为模拟器启动成功了
170
+ * 3.2 若disableNSH=false,认为8s过后模拟器启动成功了
171
+ * @param options
172
+ * @returns
173
+ */
139
174
  startGoldfish(options) {
140
175
  return __awaiter(this, void 0, void 0, function* () {
141
- const { avdName, devtool } = options;
142
- const emulatorBin = this.getEmulatorBinPath();
143
- ColorConsole_1.default.log(`### Emulator ### emulator path: ${emulatorBin}`);
144
- const avdInfo = this.velaAvdCls.getVelaAvdInfo(avdName);
145
- 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}`);
148
- if (!avdImagePath) {
149
- return ColorConsole_1.default.throw(`### Emulator ### Unable to find vela image via avd`);
150
- }
151
- 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`;
154
- 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`;
158
- }
159
- ColorConsole_1.default.log(`### Emulator ### Start qemu with TCP: ${portMappingStr}`);
160
- const stdioType = options.disableNSH ? 'pipe' : 'inherit';
161
- // vnc配置
162
- let noWindow = false;
163
- let vncStr = '';
164
- if (options.vncPort) {
165
- noWindow = true;
166
- const portSuffix = options.vncPort - constants_1.defaultVncPort;
167
- vncStr = `-vnc :${portSuffix}`;
168
- }
176
+ const { origin = Instance_1.IStartOrigin.Terminal } = options;
169
177
  // 启动goldfish的命令和参数
170
- const spawnBin = emulatorBin;
171
- const spawnArgs = [
172
- '-nuttx',
173
- '-avd',
174
- avdName,
175
- '-avd-arch',
176
- avdArch,
177
- '-show-kernel',
178
- '-kernel',
179
- nuttxBinPath,
180
- noWindow ? '-no-window' : '',
181
- '-qemu',
182
- vncStr,
183
- '-netdev',
184
- portMappingStr,
185
- '-device',
186
- 'virtio-net-device,netdev=u1,bus=virtio-mmio-bus.3'
187
- ];
188
- ColorConsole_1.default.log(`### Emulator ### Start CMD: ${spawnBin} ${spawnArgs.join(' ')}`);
178
+ const spawnArgs = emulatorutil_1.EmulatorCmd.createPreCmd(options, this.sdkHome, this.avdHome);
179
+ const spawnBin = spawnArgs && spawnArgs.shift();
180
+ if (!spawnArgs || !spawnBin)
181
+ return;
182
+ ColorConsole_1.default.log(`### Emulator ### Start CMD preDev: ${spawnBin} ${spawnArgs.join(' ')}`);
189
183
  return new Promise((resolve) => {
190
- var _a;
191
- this.goldfishProcess = (0, child_process_1.spawn)(spawnBin, spawnArgs, { stdio: stdioType, shell: true });
184
+ var _a, _b, _c;
185
+ this.goldfishProcess = (0, child_process_1.spawn)(spawnBin, spawnArgs, { stdio: 'pipe', shell: true });
186
+ // 监听错误流
192
187
  (_a = this.goldfishProcess.stderr) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
193
188
  const stderrCb = options.stderrCallback || console.log;
194
189
  stderrCb(data.toString());
195
190
  });
191
+ if (origin === Instance_1.IStartOrigin.Terminal) {
192
+ process.stdout.pipe(this.goldfishProcess.stdin);
193
+ }
194
+ // 利用 readline 接口可解决子进程日志换行的问题
195
+ this.stdoutReadline = readline_1.default.createInterface({
196
+ input: this.goldfishProcess.stdout
197
+ });
198
+ this.stderrReadline = readline_1.default.createInterface({
199
+ input: this.goldfishProcess.stderr
200
+ });
201
+ // 监听模拟器的退出事件
196
202
  this.goldfishProcess.on('exit', (code) => {
197
203
  ColorConsole_1.default.error(`### Emulator ### Goldfish emulator exited with code ${code}`);
198
204
  if (options.exitCallback) {
199
205
  options.exitCallback(code);
200
206
  }
201
207
  });
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) => {
205
- 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
- });
208
+ // 监听输出流。输出了'(NSH)'标识后则认为模拟器启动成功
209
+ (_c = (_b = this.goldfishProcess) === null || _b === void 0 ? void 0 : _b.stdout) === null || _c === void 0 ? void 0 : _c.on('data', (data) => {
210
+ const msg = data.toString();
211
+ const stdoutCb = options.stdoutCallback || console.log;
212
+ stdoutCb(msg);
213
+ if (emulatorutil_1.EmulatorLog.devIsStart(msg)) {
214
+ ColorConsole_1.default.log(`### Emulator ### Goldfish emulator starts successfully`);
215
+ resolve();
216
+ }
212
217
  });
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
218
  });
219
219
  });
220
220
  }
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
- }
221
+ /**
222
+ * 推送文件到本地的${sdkHome}/qa/app/${packageName}目录
223
+ * @param sourceRoot 源目录
224
+ */
251
225
  pushRpk(sourceRoot) {
252
226
  return __awaiter(this, void 0, void 0, function* () {
253
227
  const { package: appPackageName } = this.projectInfo;
@@ -0,0 +1 @@
1
+ ModemSimulator = on
@@ -10,14 +10,14 @@
10
10
  "hw.arc": false,
11
11
  "hw.audioInput": "yes",
12
12
  "hw.battery": "yes",
13
- "hw.camera.back": "virtualscene",
14
- "hw.camera.front": "emulated",
13
+ "hw.camera.back": "None",
14
+ "hw.camera.front": "None",
15
15
  "hw.cpu.arch": "arm",
16
16
  "hw.cpu.ncore": 4,
17
17
  "hw.dPad": "no",
18
18
  "hw.gps": "yes",
19
19
  "hw.gpu.enabled": "no",
20
- "hw.gpu.mode ": "off",
20
+ "hw.gpu.mode": "off",
21
21
  "hw.initialOrientation": "Portrait",
22
22
  "hw.keyboard": "yes",
23
23
  "hw.lcd.density": 420,
@@ -36,4 +36,4 @@
36
36
  "skin.dynamic": "no",
37
37
  "skin.name": "",
38
38
  "skin.path": ""
39
- }
39
+ }
@@ -14,6 +14,7 @@ export interface IAvdParams {
14
14
  avdHeight: string;
15
15
  avdSkin?: string;
16
16
  avdImagePath?: string;
17
+ customImagePath?: string;
17
18
  }
18
19
  export interface ISkinInfo {
19
20
  skinName: string;
@@ -1,16 +1,29 @@
1
- /// <reference types="node" />
2
- import { IAvdResourcePaths } from "./Avd";
1
+ import { IJavascriptCompileOption } from '@aiot-toolkit/aiotpack';
2
+ import { IAvdResourcePaths } from './Avd';
3
3
  export interface INewGoldfishInstanceParams extends IAvdResourcePaths {
4
4
  projectPath: string;
5
5
  sourceRoot?: string;
6
+ compilerOption?: Partial<IJavascriptCompileOption>;
6
7
  }
7
8
  export interface IStartOptions {
8
9
  avdName: string;
9
10
  devtool?: string;
11
+ /** @deprecated */
10
12
  disableNSH?: boolean;
13
+ origin?: IStartOrigin;
11
14
  serverPort?: number;
12
- vncPort?: number;
15
+ grpcPort?: number;
16
+ adbPort: number;
17
+ debugPort?: number;
13
18
  stdoutCallback?: (buffer: Buffer) => void;
14
19
  stderrCallback?: (buffer: Buffer) => void;
15
20
  exitCallback?: (code: number | null) => void;
21
+ /** 要推送的目录路径 */
22
+ dist?: string;
23
+ /** 要推送到的目的路径 */
24
+ tar?: string;
25
+ }
26
+ export declare enum IStartOrigin {
27
+ Terminal = "terminal",
28
+ Ide = "ide"
16
29
  }
@@ -1,2 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IStartOrigin = void 0;
4
+ var IStartOrigin;
5
+ (function (IStartOrigin) {
6
+ IStartOrigin["Terminal"] = "terminal";
7
+ IStartOrigin["Ide"] = "ide";
8
+ })(IStartOrigin || (exports.IStartOrigin = IStartOrigin = {}));
@@ -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>;
@@ -12,17 +12,24 @@ 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;
15
+ exports.getSystemArch = getSystemArch;
16
+ exports.killProcessByPid = killProcessByPid;
17
+ exports.killProcessByCmd = killProcessByCmd;
18
+ exports.sleep = sleep;
19
+ exports.tryRun = tryRun;
20
+ exports.delayRun = delayRun;
21
+ exports.getEvenPort = getEvenPort;
16
22
  const ColorConsole_1 = __importDefault(require("@aiot-toolkit/shared-utils/lib/ColorConsole"));
17
23
  const child_process_1 = require("child_process");
18
24
  const find_process_1 = __importDefault(require("find-process"));
19
25
  const os_1 = __importDefault(require("os"));
20
26
  const semver_1 = __importDefault(require("semver"));
27
+ const portfinder_1 = __importDefault(require("portfinder"));
21
28
  const cpuArch = {
22
29
  arm64: 'aarch64',
23
30
  aarch64: 'aarch64',
24
31
  x64: 'x86_64',
25
- x86_64: 'x86_64',
32
+ x86_64: 'x86_64'
26
33
  };
27
34
  /** 获取mac电脑的CPU架构
28
35
  * node 15.0.0之后,m1芯片的mac的os.arch()才是arm64,在这之前都是x86
@@ -46,20 +53,16 @@ function getSystemArch() {
46
53
  }
47
54
  return cpuArch[osArch];
48
55
  }
49
- exports.getSystemArch = getSystemArch;
50
56
  /** 根据PID杀死进程 */
51
57
  function killProcessByPid(pid) {
52
58
  try {
53
- const cmd = os_1.default.platform() === "win32"
54
- ? `taskkill /pid ${pid} /T /F`
55
- : `kill -9 ${pid}`;
59
+ const cmd = os_1.default.platform() === 'win32' ? `taskkill /pid ${pid} /T /F` : `kill -9 ${pid}`;
56
60
  (0, child_process_1.execSync)(cmd);
57
61
  }
58
62
  catch (e) {
59
63
  console.error(`kill process ${pid} get error: ${e}`);
60
64
  }
61
65
  }
62
- exports.killProcessByPid = killProcessByPid;
63
66
  /**
64
67
  * 根据命令杀死进程
65
68
  */
@@ -78,10 +81,64 @@ function killProcessByCmd(cmd) {
78
81
  }
79
82
  });
80
83
  }
81
- exports.killProcessByCmd = killProcessByCmd;
84
+ /** 延迟函数 */
82
85
  function sleep(time) {
83
86
  return __awaiter(this, void 0, void 0, function* () {
84
- return new Promise(resolve => setTimeout(resolve, time));
87
+ return new Promise((resolve) => setTimeout(resolve, time));
88
+ });
89
+ }
90
+ /**
91
+ * 重复执行某个任务直到成功,或者超过最大次数
92
+ * @param task 任务,需要返回 bool 值表示是否执行成功
93
+ * @param {Number=} maxCount 最大重试次数
94
+ * @param {number=} duration 每次重试的间隔
95
+ */
96
+ function tryRun(task_1) {
97
+ return __awaiter(this, arguments, void 0, function* (task, maxCount = 5, duration = 1000, currentCount = 0) {
98
+ if (currentCount > maxCount)
99
+ return false;
100
+ return (Boolean(yield task()) ||
101
+ (yield delayRun(() => tryRun(task, maxCount, duration, currentCount + 1), duration)));
102
+ });
103
+ }
104
+ /**
105
+ * 延迟执行某个任务
106
+ * @param task
107
+ * @param duration
108
+ * @returns
109
+ */
110
+ function delayRun(task_1) {
111
+ return __awaiter(this, arguments, void 0, function* (task, duration = 1000) {
112
+ return new Promise((resolve) => {
113
+ setTimeout(() => __awaiter(this, void 0, void 0, function* () {
114
+ return resolve(task());
115
+ }), duration);
116
+ });
117
+ });
118
+ }
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 = 5556;
127
+ const stopPort = 5584;
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 > 13)
135
+ return false;
136
+ port = yield portfinder_1.default.getPortPromise({
137
+ port: startPort + 2,
138
+ stopPort
139
+ });
140
+ index++;
141
+ }
142
+ return port;
85
143
  });
86
144
  }
87
- exports.sleep = sleep;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiot-toolkit/emulator",
3
- "version": "2.0.2-dev.7",
3
+ "version": "2.0.2",
4
4
  "description": "vela emulator tool.",
5
5
  "homepage": "",
6
6
  "license": "ISC",
@@ -35,9 +35,20 @@
35
35
  "emulator"
36
36
  ],
37
37
  "dependencies": {
38
- "@aiot-toolkit/aiotpack": "2.0.2-dev.7",
39
- "@aiot-toolkit/shared-utils": "2.0.2-dev.7",
38
+ "@aiot-toolkit/aiotpack": "2.0.2",
39
+ "@aiot-toolkit/shared-utils": "2.0.2",
40
+ "@miwt/adb": "^0.9.0",
41
+ "dayjs": "^1.11.12",
40
42
  "find-process": "^1.4.7",
41
- "portfinder": "^1.0.32"
42
- }
43
+ "fs-extra": "^11.2.0",
44
+ "ini": "^4.1.3",
45
+ "portfinder": "^1.0.32",
46
+ "semver": "^7.6.3",
47
+ "ws": "^8.18.0"
48
+ },
49
+ "devDependencies": {
50
+ "@types/fs-extra": "^11.0.4",
51
+ "@types/ini": "^4.1.1"
52
+ },
53
+ "gitHead": "8ca4bf2ed7bcf11911e5c514696951bdba4fc12d"
43
54
  }
@@ -1,19 +0,0 @@
1
- export declare const defaultSDKHome: string;
2
- export declare const defaultAvdHome: string;
3
- export declare const defaultImageHome: string;
4
- export declare const defaultEmulatorHome: string;
5
- export declare const defaultSkinHome: string;
6
- export declare const defaultQuickappHome: string;
7
- export declare const defaultToolsHome: string;
8
- export declare const defaultVncPort = 5900;
9
- export declare const emulatorEnvVersion: {
10
- name: string;
11
- emulator: string;
12
- qa: string;
13
- skins: string;
14
- 'system-images': {
15
- release: string;
16
- dev: string;
17
- };
18
- tools: string;
19
- };
@@ -1,27 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
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;
7
- const os_1 = __importDefault(require("os"));
8
- const path_1 = __importDefault(require("path"));
9
- exports.defaultSDKHome = path_1.default.resolve(os_1.default.homedir(), '.export');
10
- exports.defaultAvdHome = path_1.default.resolve(os_1.default.homedir(), '.android', 'avd');
11
- exports.defaultImageHome = path_1.default.resolve(exports.defaultSDKHome, 'system-images/arm');
12
- exports.defaultEmulatorHome = path_1.default.resolve(exports.defaultSDKHome, 'emulator');
13
- exports.defaultSkinHome = path_1.default.resolve(exports.defaultSDKHome, 'skins');
14
- exports.defaultQuickappHome = path_1.default.resolve(exports.defaultSDKHome, 'qa');
15
- exports.defaultToolsHome = path_1.default.resolve(exports.defaultSDKHome, 'tools');
16
- exports.defaultVncPort = 5900;
17
- exports.emulatorEnvVersion = {
18
- name: '模拟器资源版本管理',
19
- emulator: '0.0.1',
20
- qa: '0.0.1',
21
- skins: '0.0.1',
22
- 'system-images': {
23
- release: '4.0',
24
- dev: '0.0.2'
25
- },
26
- tools: '0.0.2'
27
- };