@aiot-toolkit/emulator 2.0.1-alpha.9 → 2.0.2-beta.10

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.
@@ -0,0 +1,285 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ var __importDefault = (this && this.__importDefault) || function (mod) {
35
+ return (mod && mod.__esModule) ? mod : { "default": mod };
36
+ };
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"));
40
+ const adbMiwt = __importStar(require("@miwt/adb"));
41
+ const child_process_1 = require("child_process");
42
+ const find_process_1 = __importDefault(require("find-process"));
43
+ const fs_1 = __importDefault(require("fs"));
44
+ const os_1 = __importDefault(require("os"));
45
+ const path_1 = __importDefault(require("path"));
46
+ const portfinder_1 = __importDefault(require("portfinder"));
47
+ const constants_1 = require("../static/constants");
48
+ const common_1 = __importDefault(require("./common"));
49
+ /**
50
+ * OldGoldfishInstance
51
+ * 针对 Vela开发版(dev, 0.0.2)的镜像
52
+ */
53
+ class OldGoldfishInstance extends common_1.default {
54
+ constructor(params) {
55
+ super(params);
56
+ this.host9pPort = 7878;
57
+ }
58
+ /**
59
+ * 1. 启动9p server
60
+ * 2. 将打包好的rpk推到host的挂载目录
61
+ * 3. 启动模拟器
62
+ * 4. 模拟器启动成功后,adb连接模拟器
63
+ * 5. 连接成功后,在模拟器中启动快应用
64
+ */
65
+ start(options) {
66
+ return __awaiter(this, void 0, void 0, function* () {
67
+ this.startOptions = options;
68
+ this.sn = `127.0.0.1:${this.startOptions.adbPort}`;
69
+ // host启动9p server
70
+ yield this.ensure9pServerRunnning();
71
+ // 将rpk推到host的./export/qa/app目录
72
+ const buildedFilesPath = this.isRpk
73
+ ? this.projectPath
74
+ : path_1.default.resolve(this.projectPath, './build');
75
+ this.pushRpk(buildedFilesPath);
76
+ // 启动模拟器
77
+ yield this.startGoldfish(options);
78
+ // adb连接快应用
79
+ const connected = yield this.connectGoldfish();
80
+ if (connected) {
81
+ ColorConsole_1.default.log('### Emulator ### Goldfish emulator connected successfully');
82
+ // 如果是首次启动,创建server端监听事件
83
+ if (this.isFirstStart && this.startOptions.serverPort) {
84
+ yield this.createWebsockeServer();
85
+ }
86
+ // 在模拟器中启动快应用
87
+ this.startupQuickApp(options);
88
+ this.isFirstStart = false;
89
+ }
90
+ else {
91
+ ColorConsole_1.default.throw('### Emulator ### Failed to connect emulator, please check whether the adb is normal');
92
+ }
93
+ });
94
+ }
95
+ /**
96
+ * 在模拟器中启动快应用(快应用都在模拟器的/data/app目录下)
97
+ * 1. 是否为调试模式
98
+ * 若是,在模拟器终端执行vapp app/${packageName} &
99
+ * 若否,在模拟器终端执行vapp --jsdebugger=10.0.2.15:101 app/${packageName} &
100
+ */
101
+ startupQuickApp(options) {
102
+ try {
103
+ const { package: packageName } = this.projectInfo;
104
+ const appMountDir = path_1.default.resolve(this.sdkHome, 'qa');
105
+ 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`;
106
+ ColorConsole_1.default.log(`### Emulator ### Excuting adb cmd: ${mountCmd}`);
107
+ adbMiwt.execAdbCmdSync(mountCmd);
108
+ let vappCmd = `adb -s 127.0.0.1:${options.adbPort} shell vapp app/${packageName} &`;
109
+ // 调试情况下,需要加--jsdebugger=10.0.2.15:101
110
+ if (options.devtool) {
111
+ vappCmd = `adb -s 127.0.0.1:${options.adbPort} shell vapp --jsdebugger=10.0.2.15:101 app/${packageName} &`;
112
+ }
113
+ ColorConsole_1.default.log(`### Emulator ### Excuting adb cmd: ${vappCmd}`);
114
+ // vapp进程会一直pending,不会退出。这里必须加stdio: 'ignore',否则快应用无法运行成功
115
+ adbMiwt.execAdbCmdAsync(vappCmd, { stdio: 'ignore', encoding: 'utf-8' });
116
+ }
117
+ catch (e) {
118
+ ColorConsole_1.default.error(`### Emulator ### Failed to startup quickapp: ${e.message}`);
119
+ }
120
+ }
121
+ /** host启动9pServer
122
+ * 作用是将本地的quickappMountDir目录挂载到模拟器的/data目录
123
+ */
124
+ ensure9pServerRunnning() {
125
+ return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
126
+ var _a;
127
+ const yaFileName = os_1.default.platform() === 'win32' ? 'ya-vm-file-server.exe' : 'ya-vm-file-server';
128
+ const pidList = yield (0, find_process_1.default)('name', yaFileName);
129
+ if (pidList.length > 0) {
130
+ ColorConsole_1.default.log('### Emulator ### 9p server started in host');
131
+ return resolve();
132
+ }
133
+ ColorConsole_1.default.log('### Emulator ### Starting 9p server in host');
134
+ const quickappMountDir = path_1.default.resolve(this.sdkHome, 'qa');
135
+ const toolsHome = path_1.default.resolve(this.sdkHome, 'tools');
136
+ const serverBinPath = path_1.default.resolve(toolsHome, yaFileName);
137
+ fs_1.default.chmodSync(serverBinPath, 0o777);
138
+ this.host9pPort = yield portfinder_1.default.getPortPromise({ port: 7878 });
139
+ const address = `127.0.0.1:${this.host9pPort}`;
140
+ this.v9fsProcess = (0, child_process_1.spawn)(serverBinPath, [
141
+ '--mount-point',
142
+ quickappMountDir,
143
+ '--network-address',
144
+ address,
145
+ '--debug'
146
+ ]);
147
+ // 监听stderr,判断9p server是否启动成功了
148
+ (_a = this.v9fsProcess.stderr) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
149
+ const output = data.toString();
150
+ if (output.match(/Server started, listening on: 127.0.0.1:(\d+)/)) {
151
+ ColorConsole_1.default.log(output);
152
+ ColorConsole_1.default.log('### Emulator ### 9p server starts successfully');
153
+ return resolve();
154
+ }
155
+ });
156
+ // 监听exit事件,判断9p server是否退出了
157
+ this.v9fsProcess.on('exit', (code) => {
158
+ ColorConsole_1.default.error(`### Emulator ### ya-vm-file-server exited with code ${code}`);
159
+ return reject();
160
+ });
161
+ }));
162
+ }
163
+ /**
164
+ * 启动模拟器
165
+ * 1. 通过options生成模拟器的启动命令
166
+ * 2. 执行启动命令
167
+ * 3. 判断模拟器是否启动成功
168
+ * 3.1 若disableNSH=true,输出流中匹配到/quickapp_rpk_installer_init|rpk installer init done/,认为模拟器启动成功了
169
+ * 3.2 若disableNSH=false,认为8s过后模拟器启动成功了
170
+ * @param options
171
+ * @returns
172
+ */
173
+ startGoldfish(options) {
174
+ return __awaiter(this, void 0, void 0, function* () {
175
+ const { avdName, devtool, origin = 'terminal' } = options;
176
+ // 获取emulator bin的绝对路径
177
+ const emulatorBin = this.getEmulatorBinPath();
178
+ ColorConsole_1.default.log(`### Emulator ### emulator path: ${emulatorBin}`);
179
+ // 获取vela镜像的绝对路径
180
+ const avdInfo = this.velaAvdCls.getVelaAvdInfo(avdName);
181
+ const { avdArch, avdImagePath } = avdInfo;
182
+ ColorConsole_1.default.log(`### Emulator ### adb port: ${options.adbPort}`);
183
+ if (!avdImagePath) {
184
+ return ColorConsole_1.default.throw(`### Emulator ### Unable to find vela image via avd`);
185
+ }
186
+ const nuttxBinPath = path_1.default.resolve(avdImagePath, 'nuttx');
187
+ ColorConsole_1.default.log(`### Emulator ### nuttx path: ${nuttxBinPath}`);
188
+ // 端口映射,adb端口和debug端口
189
+ let portMappingStr = `user,id=u1,hostfwd=tcp:127.0.0.1:${options.adbPort}-10.0.2.15:5555`;
190
+ if (devtool) {
191
+ ColorConsole_1.default.log(`### Emulator ### debug port: ${options.debugPort}`);
192
+ portMappingStr += `,hostfwd=tcp:127.0.0.1:${options.debugPort}-10.0.2.15:101`;
193
+ }
194
+ ColorConsole_1.default.log(`### Emulator ### Start qemu with TCP: ${portMappingStr}`);
195
+ // vnc配置
196
+ let noWindow = false;
197
+ let vncStr = '';
198
+ if (options.vncPort) {
199
+ noWindow = true;
200
+ const portSuffix = options.vncPort - constants_1.defaultVncPort;
201
+ vncStr = `-vnc :${portSuffix}`;
202
+ }
203
+ // 启动goldfish的命令和参数
204
+ const spawnBin = emulatorBin;
205
+ const spawnArgs = [
206
+ '-nuttx',
207
+ '-avd',
208
+ avdName,
209
+ '-avd-arch',
210
+ avdArch,
211
+ '-show-kernel',
212
+ '-kernel',
213
+ nuttxBinPath,
214
+ noWindow ? '-no-window' : '',
215
+ '-qemu',
216
+ vncStr,
217
+ '-netdev',
218
+ portMappingStr,
219
+ '-device',
220
+ 'virtio-net-device,netdev=u1,bus=virtio-mmio-bus.3'
221
+ ];
222
+ ColorConsole_1.default.log(`### Emulator ### Start CMD: ${spawnBin} ${spawnArgs.join(' ')}`);
223
+ return new Promise((resolve) => {
224
+ var _a, _b, _c, _d;
225
+ this.goldfishProcess = (0, child_process_1.spawn)(spawnBin, spawnArgs, { stdio: 'pipe', shell: true });
226
+ // 监听错误流
227
+ (_a = this.goldfishProcess.stderr) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
228
+ const stderrCb = options.stderrCallback || console.log;
229
+ stderrCb(data.toString());
230
+ });
231
+ if (origin === 'terminal') {
232
+ process.stdout.pipe(this.goldfishProcess.stdin);
233
+ (_b = this.goldfishProcess.stdout) === null || _b === void 0 ? void 0 : _b.pipe(process.stdout);
234
+ }
235
+ // 监听模拟器的退出事件
236
+ this.goldfishProcess.on('exit', (code) => {
237
+ ColorConsole_1.default.error(`### Emulator ### Goldfish emulator exited with code ${code}`);
238
+ if (options.exitCallback) {
239
+ options.exitCallback(code);
240
+ }
241
+ });
242
+ // 监听输出流。输出了'(NSH)'标识后则认为模拟器启动成功
243
+ (_d = (_c = this.goldfishProcess) === null || _c === void 0 ? void 0 : _c.stdout) === null || _d === void 0 ? void 0 : _d.on('data', (data) => {
244
+ const msg = data.toString();
245
+ if (origin === 'ide') {
246
+ const stdoutCb = options.stdoutCallback || console.log;
247
+ stdoutCb(msg);
248
+ }
249
+ if (msg.includes('(NSH)')) {
250
+ ColorConsole_1.default.log(`### Emulator ### Goldfish emulator starts successfully`);
251
+ resolve();
252
+ }
253
+ });
254
+ });
255
+ });
256
+ }
257
+ /**
258
+ * 推送文件到本地的${sdkHome}/qa/app/${packageName}目录
259
+ * @param sourceRoot 源目录
260
+ */
261
+ pushRpk(sourceRoot) {
262
+ return __awaiter(this, void 0, void 0, function* () {
263
+ const { package: appPackageName } = this.projectInfo;
264
+ const appRunDir = path_1.default.resolve(this.sdkHome, 'qa/app', appPackageName);
265
+ ColorConsole_1.default.log(`### Emulator ### Pushing ${appPackageName} to ${appRunDir}`);
266
+ fs_1.default.rmSync(appRunDir, { recursive: true, force: true });
267
+ FileUtil_1.default.copyFiles(sourceRoot, appRunDir);
268
+ ColorConsole_1.default.log(`### Emulator ### Push ${appPackageName} to ${appRunDir} successfully`);
269
+ });
270
+ }
271
+ /** 停止模拟器并释放相关资源 */
272
+ stop() {
273
+ const _super = Object.create(null, {
274
+ stop: { get: () => super.stop }
275
+ });
276
+ return __awaiter(this, void 0, void 0, function* () {
277
+ _super.stop.call(this);
278
+ if (this.v9fsProcess) {
279
+ this.killProcess(this.v9fsProcess);
280
+ this.v9fsProcess = undefined;
281
+ }
282
+ });
283
+ }
284
+ }
285
+ exports.default = OldGoldfishInstance;
@@ -0,0 +1 @@
1
+ ModemSimulator = on
@@ -5,3 +5,20 @@ export declare const defaultEmulatorHome: string;
5
5
  export declare const defaultSkinHome: string;
6
6
  export declare const defaultQuickappHome: string;
7
7
  export declare const defaultToolsHome: string;
8
+ export declare const defaultVncPort = 5900;
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: {
17
+ name: string;
18
+ emulator: string;
19
+ qa: string;
20
+ skins: string;
21
+ 'system-images': string;
22
+ tools: string;
23
+ modem_simulator: string;
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.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');
@@ -13,5 +13,27 @@ exports.defaultEmulatorHome = path_1.default.resolve(exports.defaultSDKHome, 'em
13
13
  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
-
17
- //# sourceMappingURL=constants.js.map
16
+ exports.defaultVncPort = 5900;
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 = {
32
+ name: '模拟器资源版本管理',
33
+ emulator: '0.0.3',
34
+ qa: '0.0.1',
35
+ skins: '0.0.1',
36
+ 'system-images': exports.VelaImageVersionList[0].value,
37
+ tools: '0.0.2',
38
+ modem_simulator: '0.0.1'
39
+ };
@@ -0,0 +1 @@
1
+ 10.0.2.15:101
package/lib/typing/Avd.js CHANGED
@@ -6,5 +6,3 @@ var IAvdArchType;
6
6
  IAvdArchType["arm"] = "arm";
7
7
  IAvdArchType["arm64"] = "arm64";
8
8
  })(IAvdArchType || (exports.IAvdArchType = IAvdArchType = {}));
9
-
10
- //# sourceMappingURL=Avd.js.map
@@ -1,10 +1,26 @@
1
- import { IAvdResourcePaths } from "./Avd";
1
+ /// <reference types="node" />
2
+ import IJavascriptCompileOption from '@aiot-toolkit/aiotpack/lib/compiler/javascript/interface/IJavascriptCompileOption';
3
+ import { IAvdResourcePaths } from './Avd';
2
4
  export interface INewGoldfishInstanceParams extends IAvdResourcePaths {
3
5
  projectPath: string;
4
6
  sourceRoot?: string;
7
+ compilerOption?: Partial<IJavascriptCompileOption>;
5
8
  }
6
9
  export interface IStartOptions {
7
10
  avdName: string;
8
11
  devtool?: string;
12
+ /** @deprecated */
9
13
  disableNSH?: boolean;
14
+ origin?: 'ide' | 'terminal';
15
+ serverPort?: number;
16
+ vncPort?: number;
17
+ adbPort: number;
18
+ debugPort?: number;
19
+ stdoutCallback?: (buffer: Buffer) => void;
20
+ stderrCallback?: (buffer: Buffer) => void;
21
+ exitCallback?: (code: number | null) => void;
22
+ /** 要推送的目录路径 */
23
+ dist?: string;
24
+ /** 要推送到的目的路径 */
25
+ tar?: string;
10
26
  }
@@ -1,4 +1,2 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
-
4
- //# sourceMappingURL=Instance.js.map
@@ -0,0 +1,13 @@
1
+ /** 获取mac电脑的CPU架构
2
+ * node 15.0.0之后,m1芯片的mac的os.arch()才是arm64,在这之前都是x86
3
+ * 所以15.0.0之前无法通过os.arch()区分,也无法通过execSync('uname -m')区分
4
+ */
5
+ export declare function getSystemArch(): string | void;
6
+ /** 根据PID杀死进程 */
7
+ export declare function killProcessByPid(pid: string): void;
8
+ /**
9
+ * 根据命令杀死进程
10
+ */
11
+ export declare function killProcessByCmd(cmd: string): Promise<void>;
12
+ /** 延迟函数 */
13
+ export declare function sleep(time: number): Promise<void>;
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
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"));
17
+ const child_process_1 = require("child_process");
18
+ const find_process_1 = __importDefault(require("find-process"));
19
+ const os_1 = __importDefault(require("os"));
20
+ const semver_1 = __importDefault(require("semver"));
21
+ const cpuArch = {
22
+ arm64: 'aarch64',
23
+ aarch64: 'aarch64',
24
+ x64: 'x86_64',
25
+ x86_64: 'x86_64',
26
+ };
27
+ /** 获取mac电脑的CPU架构
28
+ * node 15.0.0之后,m1芯片的mac的os.arch()才是arm64,在这之前都是x86
29
+ * 所以15.0.0之前无法通过os.arch()区分,也无法通过execSync('uname -m')区分
30
+ */
31
+ function getSystemArch() {
32
+ const platform = os_1.default.platform();
33
+ let osArch = os_1.default.arch();
34
+ const nodeVersion = process.version;
35
+ if (semver_1.default.lt(nodeVersion, '15.0.0') && platform === 'darwin') {
36
+ try {
37
+ (0, child_process_1.execSync)('sysctl -n sysctl.proc_translated');
38
+ osArch = 'arm64';
39
+ }
40
+ catch (_a) {
41
+ osArch = 'x64';
42
+ }
43
+ }
44
+ if (osArch !== 'arm64' && osArch !== 'x64') {
45
+ return ColorConsole_1.default.throw(`unsupport system`);
46
+ }
47
+ return cpuArch[osArch];
48
+ }
49
+ exports.getSystemArch = getSystemArch;
50
+ /** 根据PID杀死进程 */
51
+ function killProcessByPid(pid) {
52
+ try {
53
+ const cmd = os_1.default.platform() === "win32"
54
+ ? `taskkill /pid ${pid} /T /F`
55
+ : `kill -9 ${pid}`;
56
+ (0, child_process_1.execSync)(cmd);
57
+ }
58
+ catch (e) {
59
+ console.error(`kill process ${pid} get error: ${e}`);
60
+ }
61
+ }
62
+ exports.killProcessByPid = killProcessByPid;
63
+ /**
64
+ * 根据命令杀死进程
65
+ */
66
+ function killProcessByCmd(cmd) {
67
+ return __awaiter(this, void 0, void 0, function* () {
68
+ if (!cmd)
69
+ return;
70
+ try {
71
+ const list = yield (0, find_process_1.default)('name', cmd);
72
+ list.forEach((item) => __awaiter(this, void 0, void 0, function* () {
73
+ killProcessByPid(item.pid.toString());
74
+ }));
75
+ }
76
+ catch (e) {
77
+ console.error(`kill process ${cmd} get error: ${e}`);
78
+ }
79
+ });
80
+ }
81
+ exports.killProcessByCmd = killProcessByCmd;
82
+ /** 延迟函数 */
83
+ function sleep(time) {
84
+ return __awaiter(this, void 0, void 0, function* () {
85
+ return new Promise(resolve => setTimeout(resolve, time));
86
+ });
87
+ }
88
+ exports.sleep = sleep;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiot-toolkit/emulator",
3
- "version": "2.0.1-alpha.9",
3
+ "version": "2.0.2-beta.10",
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.1-alpha.9",
39
- "@aiot-toolkit/shared-utils": "2.0.1-alpha.9",
38
+ "@aiot-toolkit/aiotpack": "2.0.2-beta.10",
39
+ "@aiot-toolkit/shared-utils": "2.0.2-beta.10",
40
40
  "find-process": "^1.4.7",
41
41
  "portfinder": "^1.0.32"
42
42
  },
43
- "gitHead": "d593999b9ca345bce8b3ba40a7d11f6685ac03b5"
43
+ "devDependencies": {
44
+ "@types/fs-extra": "^11.0.4",
45
+ "fs-extra": "^11.2.0"
46
+ },
47
+ "gitHead": "00d23c1ad1306a6c72bb007685de9fd4a6ee61af"
44
48
  }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["avd/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import fs from 'fs'\nimport path from 'path'\nimport { defaultAvdHome, defaultImageHome, defaultSDKHome } from '../static/constants'\nimport { IAvdArchType, IAvdParams, IAvdResourcePaths } from '../typing/Avd'\n\nconst EAvdParamsToIni = {\n 'arm': {\n abiType: 'armeabi-v7a',\n },\n 'arm64': {\n abiType: 'arm64-v8a',\n }\n}\n\nclass VelaAvdCls {\n private avdHome: string\n private sdkHome: string\n\n constructor(avdResourcePaths: IAvdResourcePaths) {\n const { avdHome, sdkHome } = avdResourcePaths\n this.avdHome = avdHome || defaultAvdHome\n this.sdkHome = sdkHome || defaultSDKHome\n }\n\n createVelaAvd(avdParams: IAvdParams) {\n const { avdName, avdArch, avdWidth, avdHeight, avdSkin, avdImagePath = defaultImageHome } = avdParams\n const avdDir = path.resolve(this.avdHome, `${avdName}.avd`)\n const avdIni = path.resolve(this.avdHome, `${avdName}.ini`)\n const avdConfigIni = path.resolve(avdDir, 'config.ini')\n const nuttxAvdIniContent = `path=${avdDir}\\npath.rel=avd${path.sep}${avdName}.avd`\n const abiType = EAvdParamsToIni[avdArch]['abiType']\n const configIniJson: any = JSON.parse(fs.readFileSync(path.join(__dirname, '../static/avdConfigIni.json'), 'utf-8'))\n configIniJson['AvdId'] = avdName\n configIniJson['abi.type'] = abiType\n configIniJson['avd.ini.displayname'] = avdName\n configIniJson['hw.cpu.arch'] = avdArch\n if (avdSkin) {\n delete configIniJson['hw.lcd.height']\n delete configIniJson['hw.lcd.width']\n configIniJson['skin.dynamic'] = 'yes'\n configIniJson['skin.name'] = avdSkin\n configIniJson['skin.path'] = path.resolve(this.sdkHome, 'skins', avdSkin)\n } else {\n configIniJson['hw.lcd.height'] = avdHeight\n configIniJson['hw.lcd.width'] = avdWidth\n configIniJson['skin.dynamic'] = 'no'\n delete configIniJson['skin.name']\n delete configIniJson['skin.path']\n }\n configIniJson['image.sysdir.1'] = avdImagePath\n try {\n fs.mkdirSync(avdDir, { recursive: true })\n // 写入Vela_Virtual_Device.ini文件\n fs.writeFileSync(avdIni, nuttxAvdIniContent)\n // 写入Vela_Virtual_Device.avd/config.ini文件\n const fWrite = fs.createWriteStream(avdConfigIni)\n for (const item in configIniJson) {\n const line = `${item} = ${configIniJson[item]}\\n`\n fWrite.write(line);\n }\n fWrite.close();\n return true\n } catch (e) {\n return false\n }\n }\n\n getVelaAvdInfo(avdName: string) {\n const avdInfo: IAvdParams = {\n avdName,\n avdArch: IAvdArchType.arm,\n avdHeight: '',\n avdWidth: '',\n avdSkin: '',\n avdImagePath: ''\n }\n const currAvdDir = path.resolve(this.avdHome, `${avdName}.avd`)\n const configIni = path.resolve(currAvdDir, 'config.ini')\n const contents = fs.readFileSync(configIni, 'utf-8')\n // 这里需要使用惰性匹配\n const archRegex = /hw.cpu.arch = ([\\d\\D]+?)\\n/\n const archMatcher = contents.match(archRegex)\n const heightRegex = /hw.lcd.height = ([\\d\\D]+?)\\n/\n const heightMatcher = contents.match(heightRegex)\n const widthRegex = /hw.lcd.width = ([\\d\\D]+?)\\n/\n const widthMatcher = contents.match(widthRegex)\n const skinRegex = /skin.name = ([\\d\\D]+?)\\n/\n const skinMatcher = contents.match(skinRegex)\n const imagePathRegex = /image.sysdir.1 = ([\\d\\D]+?)\\n/\n const imagePathMather = contents.match(imagePathRegex)\n archMatcher && (avdInfo.avdArch = (archMatcher[1] as IAvdArchType))\n heightMatcher && (avdInfo.avdHeight = heightMatcher[1])\n widthMatcher && (avdInfo.avdWidth = widthMatcher[1])\n skinMatcher && (avdInfo.avdSkin = skinMatcher[1])\n imagePathMather && (avdInfo.avdImagePath = imagePathMather[1])\n return avdInfo\n }\n\n deleteVelaAvd(avdName: string) {\n const avdDir = path.resolve(this.avdHome, `${avdName}.avd`)\n const avdIni = path.resolve(this.avdHome, `${avdName}.ini`);\n try {\n fs.rmSync(avdDir, { recursive: true, force: true });\n fs.rmSync(avdIni, { force: true })\n return true\n } catch (e) {\n return false\n }\n }\n\n getVelaAvdList() {\n try {\n const avdList: IAvdParams[] = [];\n const files = fs.readdirSync(defaultAvdHome);\n const regex = /^(Vela[\\d\\D]*)\\.avd$/;\n for (const fileName of files) {\n const matcher = fileName.match(regex);\n if (matcher) {\n const avdName = matcher[1];\n const avdInfo = this.getVelaAvdInfo(avdName);\n avdList.push(avdInfo);\n }\n }\n return avdList;\n } catch (err) {\n return [];\n }\n }\n\n getVelaSkinList() {\n try {\n const skinList = []\n const skinHome = path.resolve(this.sdkHome, 'skins')\n let files = fs.readdirSync(skinHome)\n for (const fileName of files) {\n !fileName.startsWith('.') && skinList.push(fileName)\n }\n return skinList\n } catch (e) {\n return []\n }\n }\n}\n\nexport default VelaAvdCls\n"],"sourceRoot":"../../src"}
package/lib/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,gDAA8C;AAM1B,2FANA,aAAU,OAMA;AAL9B,mEAAkE;AAKhE,iGALkB,kBAAgB,OAKlB;AAJlB,+CAA6B;AAC7B,oDAAkC","file":"index.js","sourcesContent":["import { default as VelaAvdCls } from './avd';\nimport { default as GoldfishInstance } from './instance/goldfish';\nexport * from './typing/Avd';\nexport * from './typing/Instance';\n\nexport {\n GoldfishInstance, VelaAvdCls\n};\n\n"],"sourceRoot":"../src"}
@@ -1,35 +0,0 @@
1
- /// <reference types="node" />
2
- import { ChildProcess } from 'child_process';
3
- import { INewGoldfishInstanceParams, IStartOptions } from '../typing/Instance';
4
- declare class GoldfishInstance {
5
- private projectPath;
6
- private sdkHome;
7
- private avdHome;
8
- private adbPort;
9
- debugPort: number;
10
- private host9pPort;
11
- private velaAvdCls;
12
- private packageName;
13
- goldfishProcess: ChildProcess | undefined;
14
- v9fsProcess: ChildProcess | undefined;
15
- constructor(params: INewGoldfishInstanceParams);
16
- /** 获取模拟器二进制文件所在位置 */
17
- getEmulatorBinPath(): string;
18
- /** 在goldfish模拟器中运行快应用 */
19
- start(options: IStartOptions): Promise<void>;
20
- /** 在goldfish中启动快应用 */
21
- startupQuickApp(options: IStartOptions): void;
22
- /** host启动9pServer */
23
- ensure9pServerRunnning(): Promise<void>;
24
- /** 启动goldfish模拟器 */
25
- startGoldfish(options: IStartOptions): Promise<void>;
26
- /** 通过adb连接模拟器 */
27
- connectGoldfish(): Promise<boolean>;
28
- /** 将打包后的文件推到挂载的快应用目录 */
29
- pushRpk(): void;
30
- /** 杀死进程 */
31
- killProcess(currProcess?: ChildProcess): void;
32
- /** 停止模拟器并释放相关资源 */
33
- stop(): void;
34
- }
35
- export default GoldfishInstance;