@aiot-toolkit/emulator 2.0.2-beta.1 → 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.
@@ -46,25 +46,40 @@ const path_1 = __importDefault(require("path"));
46
46
  const portfinder_1 = __importDefault(require("portfinder"));
47
47
  const constants_1 = require("../static/constants");
48
48
  const common_1 = __importDefault(require("./common"));
49
+ /**
50
+ * OldGoldfishInstance
51
+ * 针对 Vela开发版(dev, 0.0.2)的镜像
52
+ */
49
53
  class OldGoldfishInstance extends common_1.default {
50
54
  constructor(params) {
51
55
  super(params);
52
56
  this.host9pPort = 7878;
53
57
  }
54
- /** 在goldfish模拟器中运行快应用 */
58
+ /**
59
+ * 1. 启动9p server
60
+ * 2. 将打包好的rpk推到host的挂载目录
61
+ * 3. 启动模拟器
62
+ * 4. 模拟器启动成功后,adb连接模拟器
63
+ * 5. 连接成功后,在模拟器中启动快应用
64
+ */
55
65
  start(options) {
56
66
  return __awaiter(this, void 0, void 0, function* () {
67
+ this.startOptions = options;
68
+ this.sn = `127.0.0.1:${this.startOptions.adbPort}`;
57
69
  // host启动9p server
58
70
  yield this.ensure9pServerRunnning();
59
- this.startOptions = options;
60
71
  // 将rpk推到host的./export/qa/app目录
61
- const buildedFilesPath = this.isRpk ? this.projectPath : path_1.default.resolve(this.projectPath, './build');
72
+ const buildedFilesPath = this.isRpk
73
+ ? this.projectPath
74
+ : path_1.default.resolve(this.projectPath, './build');
62
75
  this.pushRpk(buildedFilesPath);
63
76
  // 启动模拟器
64
77
  yield this.startGoldfish(options);
78
+ // adb连接快应用
65
79
  const connected = yield this.connectGoldfish();
66
80
  if (connected) {
67
81
  ColorConsole_1.default.log('### Emulator ### Goldfish emulator connected successfully');
82
+ // 如果是首次启动,创建server端监听事件
68
83
  if (this.isFirstStart && this.startOptions.serverPort) {
69
84
  yield this.createWebsockeServer();
70
85
  }
@@ -77,17 +92,23 @@ class OldGoldfishInstance extends common_1.default {
77
92
  }
78
93
  });
79
94
  }
80
- /** 在goldfish中启动快应用 */
95
+ /**
96
+ * 在模拟器中启动快应用(快应用都在模拟器的/data/app目录下)
97
+ * 1. 是否为调试模式
98
+ * 若是,在模拟器终端执行vapp app/${packageName} &
99
+ * 若否,在模拟器终端执行vapp --jsdebugger=10.0.2.15:101 app/${packageName} &
100
+ */
81
101
  startupQuickApp(options) {
82
102
  try {
83
103
  const { package: packageName } = this.projectInfo;
84
104
  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`;
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`;
86
106
  ColorConsole_1.default.log(`### Emulator ### Excuting adb cmd: ${mountCmd}`);
87
107
  adbMiwt.execAdbCmdSync(mountCmd);
88
- let vappCmd = `adb -s 127.0.0.1:${this.adbPort} shell vapp app/${packageName} &`;
108
+ let vappCmd = `adb -s 127.0.0.1:${options.adbPort} shell vapp app/${packageName} &`;
109
+ // 调试情况下,需要加--jsdebugger=10.0.2.15:101
89
110
  if (options.devtool) {
90
- vappCmd = `adb -s 127.0.0.1:${this.adbPort} shell vapp --jsdebugger=10.0.2.15:101 app/${packageName} &`;
111
+ vappCmd = `adb -s 127.0.0.1:${options.adbPort} shell vapp --jsdebugger=10.0.2.15:101 app/${packageName} &`;
91
112
  }
92
113
  ColorConsole_1.default.log(`### Emulator ### Excuting adb cmd: ${vappCmd}`);
93
114
  // vapp进程会一直pending,不会退出。这里必须加stdio: 'ignore',否则快应用无法运行成功
@@ -97,7 +118,9 @@ class OldGoldfishInstance extends common_1.default {
97
118
  ColorConsole_1.default.error(`### Emulator ### Failed to startup quickapp: ${e.message}`);
98
119
  }
99
120
  }
100
- /** host启动9pServer */
121
+ /** host启动9pServer
122
+ * 作用是将本地的quickappMountDir目录挂载到模拟器的/data目录
123
+ */
101
124
  ensure9pServerRunnning() {
102
125
  return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
103
126
  var _a;
@@ -121,6 +144,7 @@ class OldGoldfishInstance extends common_1.default {
121
144
  address,
122
145
  '--debug'
123
146
  ]);
147
+ // 监听stderr,判断9p server是否启动成功了
124
148
  (_a = this.v9fsProcess.stderr) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
125
149
  const output = data.toString();
126
150
  if (output.match(/Server started, listening on: 127.0.0.1:(\d+)/)) {
@@ -129,35 +153,45 @@ class OldGoldfishInstance extends common_1.default {
129
153
  return resolve();
130
154
  }
131
155
  });
156
+ // 监听exit事件,判断9p server是否退出了
132
157
  this.v9fsProcess.on('exit', (code) => {
133
158
  ColorConsole_1.default.error(`### Emulator ### ya-vm-file-server exited with code ${code}`);
134
159
  return reject();
135
160
  });
136
161
  }));
137
162
  }
138
- /** 启动goldfish模拟器 */
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
+ */
139
173
  startGoldfish(options) {
140
174
  return __awaiter(this, void 0, void 0, function* () {
141
- const { avdName, devtool } = options;
175
+ const { avdName, devtool, origin = 'terminal' } = options;
176
+ // 获取emulator bin的绝对路径
142
177
  const emulatorBin = this.getEmulatorBinPath();
143
178
  ColorConsole_1.default.log(`### Emulator ### emulator path: ${emulatorBin}`);
179
+ // 获取vela镜像的绝对路径
144
180
  const avdInfo = this.velaAvdCls.getVelaAvdInfo(avdName);
145
181
  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}`);
182
+ ColorConsole_1.default.log(`### Emulator ### adb port: ${options.adbPort}`);
148
183
  if (!avdImagePath) {
149
184
  return ColorConsole_1.default.throw(`### Emulator ### Unable to find vela image via avd`);
150
185
  }
151
186
  const nuttxBinPath = path_1.default.resolve(avdImagePath, 'nuttx');
152
187
  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`;
188
+ // 端口映射,adb端口和debug端口
189
+ let portMappingStr = `user,id=u1,hostfwd=tcp:127.0.0.1:${options.adbPort}-10.0.2.15:5555`;
154
190
  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`;
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`;
158
193
  }
159
194
  ColorConsole_1.default.log(`### Emulator ### Start qemu with TCP: ${portMappingStr}`);
160
- const stdioType = options.disableNSH ? 'pipe' : 'inherit';
161
195
  // vnc配置
162
196
  let noWindow = false;
163
197
  let vncStr = '';
@@ -187,67 +221,43 @@ class OldGoldfishInstance extends common_1.default {
187
221
  ];
188
222
  ColorConsole_1.default.log(`### Emulator ### Start CMD: ${spawnBin} ${spawnArgs.join(' ')}`);
189
223
  return new Promise((resolve) => {
190
- var _a;
191
- this.goldfishProcess = (0, child_process_1.spawn)(spawnBin, spawnArgs, { stdio: stdioType, shell: true });
224
+ var _a, _b, _c, _d;
225
+ this.goldfishProcess = (0, child_process_1.spawn)(spawnBin, spawnArgs, { stdio: 'pipe', shell: true });
226
+ // 监听错误流
192
227
  (_a = this.goldfishProcess.stderr) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
193
228
  const stderrCb = options.stderrCallback || console.log;
194
229
  stderrCb(data.toString());
195
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
+ // 监听模拟器的退出事件
196
236
  this.goldfishProcess.on('exit', (code) => {
197
237
  ColorConsole_1.default.error(`### Emulator ### Goldfish emulator exited with code ${code}`);
198
238
  if (options.exitCallback) {
199
239
  options.exitCallback(code);
200
240
  }
201
241
  });
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) => {
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') {
205
246
  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
- });
247
+ stdoutCb(msg);
248
+ }
249
+ if (msg.includes('(NSH)')) {
250
+ ColorConsole_1.default.log(`### Emulator ### Goldfish emulator starts successfully`);
251
+ resolve();
252
+ }
212
253
  });
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
254
  });
219
255
  });
220
256
  }
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
- }
257
+ /**
258
+ * 推送文件到本地的${sdkHome}/qa/app/${packageName}目录
259
+ * @param sourceRoot 源目录
260
+ */
251
261
  pushRpk(sourceRoot) {
252
262
  return __awaiter(this, void 0, void 0, function* () {
253
263
  const { package: appPackageName } = this.projectInfo;
@@ -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/lib/compiler/javascript/interface/IJavascriptCompileOption';
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
16
  vncPort?: 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,5 @@ 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>;
@@ -79,6 +79,7 @@ function killProcessByCmd(cmd) {
79
79
  });
80
80
  }
81
81
  exports.killProcessByCmd = killProcessByCmd;
82
+ /** 延迟函数 */
82
83
  function sleep(time) {
83
84
  return __awaiter(this, void 0, void 0, function* () {
84
85
  return new Promise(resolve => setTimeout(resolve, time));
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.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.2-beta.1",
39
- "@aiot-toolkit/shared-utils": "2.0.2-beta.1",
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": "9244af36e617295ea4ff11a2f4f07f0e4f9f5f59"
43
+ "devDependencies": {
44
+ "@types/fs-extra": "^11.0.4",
45
+ "fs-extra": "^11.2.0"
46
+ },
47
+ "gitHead": "00d23c1ad1306a6c72bb007685de9fd4a6ee61af"
44
48
  }