@aiot-toolkit/emulator 2.0.2-beta.3 → 2.0.2-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -1
- package/lib/avd/index.d.ts +12 -0
- package/lib/avd/index.js +12 -0
- package/lib/instance/index.d.ts +6 -0
- package/lib/instance/index.js +6 -0
- package/lib/instance/miwear.d.ts +51 -9
- package/lib/instance/miwear.js +108 -61
- package/lib/instance/preDev.d.ts +39 -5
- package/lib/instance/preDev.js +52 -6
- package/lib/static/constants.d.ts +8 -5
- package/lib/static/constants.js +18 -8
- package/lib/typing/Instance.d.ts +2 -0
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.js +1 -0
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -1,2 +1,15 @@
|
|
|
1
|
+
## emulator
|
|
1
2
|
|
|
2
|
-
|
|
3
|
+
QEMU模拟器
|
|
4
|
+
|
|
5
|
+
模拟器的介绍可参考[开发帮助文档](https://xiaomi.f.mioffice.cn/docx/doxk4Rk6x67GanHlzQ8bEOrxtEe)里的「模拟器」章节
|
|
6
|
+
|
|
7
|
+
## 目录结构
|
|
8
|
+
|
|
9
|
+
| 目录 | 描述 |
|
|
10
|
+
| -------- | ------------------------------------------------------------------------------- |
|
|
11
|
+
| avd | 模拟器的AVD,配置统一放置$HOME/.android/avd目录下 |
|
|
12
|
+
| instance | 模拟器实例,不同的Vela镜像版本会使用不同的instance,通过findInstance确定 |
|
|
13
|
+
| static | 创建AVD时需要用到的静态资源,常量配置文件 |
|
|
14
|
+
| typing | 接口定义 |
|
|
15
|
+
| utils | 工具函数 |
|
package/lib/avd/index.d.ts
CHANGED
|
@@ -3,10 +3,22 @@ declare class VelaAvdCls {
|
|
|
3
3
|
private avdHome;
|
|
4
4
|
private sdkHome;
|
|
5
5
|
constructor(avdResourcePaths: IAvdResourcePaths);
|
|
6
|
+
/**
|
|
7
|
+
* 创建Vela端的AVD,统一保存在.android目录下
|
|
8
|
+
* 1. 创建.android/advancedFeatures.ini文件
|
|
9
|
+
* 2. 创建.android/${avdName}.ini文件
|
|
10
|
+
* 3. 创建.android/${avdName}.avd/config.ini文件
|
|
11
|
+
* @param avdParams AVD参数,宽高、绑定的镜像路径等
|
|
12
|
+
* @returns
|
|
13
|
+
*/
|
|
6
14
|
createVelaAvd(avdParams: IAvdParams): boolean;
|
|
15
|
+
/** 根据AVD名字获取模拟器的详细信息 */
|
|
7
16
|
getVelaAvdInfo(avdName: string): IAvdParams;
|
|
17
|
+
/** 根据名字删除AVD */
|
|
8
18
|
deleteVelaAvd(avdName: string): boolean;
|
|
19
|
+
/** 获取已经创建的模拟器列表 */
|
|
9
20
|
getVelaAvdList(): IAvdParams[];
|
|
21
|
+
/** 获取模拟器皮肤列表 */
|
|
10
22
|
getVelaSkinList(): string[];
|
|
11
23
|
}
|
|
12
24
|
export default VelaAvdCls;
|
package/lib/avd/index.js
CHANGED
|
@@ -26,6 +26,14 @@ class VelaAvdCls {
|
|
|
26
26
|
fs_1.default.mkdirSync(this.avdHome, { recursive: true });
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* 创建Vela端的AVD,统一保存在.android目录下
|
|
31
|
+
* 1. 创建.android/advancedFeatures.ini文件
|
|
32
|
+
* 2. 创建.android/${avdName}.ini文件
|
|
33
|
+
* 3. 创建.android/${avdName}.avd/config.ini文件
|
|
34
|
+
* @param avdParams AVD参数,宽高、绑定的镜像路径等
|
|
35
|
+
* @returns
|
|
36
|
+
*/
|
|
29
37
|
createVelaAvd(avdParams) {
|
|
30
38
|
// 在.android下创建advancedFeatures.ini文件
|
|
31
39
|
const advancedFeaturesIni = path_1.default.resolve(os_1.default.homedir(), '.android/advancedFeatures.ini');
|
|
@@ -76,6 +84,7 @@ class VelaAvdCls {
|
|
|
76
84
|
throw (`createVelaAvd: ${e.message}`);
|
|
77
85
|
}
|
|
78
86
|
}
|
|
87
|
+
/** 根据AVD名字获取模拟器的详细信息 */
|
|
79
88
|
getVelaAvdInfo(avdName) {
|
|
80
89
|
const avdInfo = {
|
|
81
90
|
avdName,
|
|
@@ -112,6 +121,7 @@ class VelaAvdCls {
|
|
|
112
121
|
return avdInfo;
|
|
113
122
|
}
|
|
114
123
|
}
|
|
124
|
+
/** 根据名字删除AVD */
|
|
115
125
|
deleteVelaAvd(avdName) {
|
|
116
126
|
const avdDir = path_1.default.resolve(this.avdHome, `${avdName}.avd`);
|
|
117
127
|
const avdIni = path_1.default.resolve(this.avdHome, `${avdName}.ini`);
|
|
@@ -124,6 +134,7 @@ class VelaAvdCls {
|
|
|
124
134
|
return false;
|
|
125
135
|
}
|
|
126
136
|
}
|
|
137
|
+
/** 获取已经创建的模拟器列表 */
|
|
127
138
|
getVelaAvdList() {
|
|
128
139
|
const avdList = [];
|
|
129
140
|
const files = fs_1.default.readdirSync(this.avdHome);
|
|
@@ -138,6 +149,7 @@ class VelaAvdCls {
|
|
|
138
149
|
}
|
|
139
150
|
return avdList;
|
|
140
151
|
}
|
|
152
|
+
/** 获取模拟器皮肤列表 */
|
|
141
153
|
getVelaSkinList() {
|
|
142
154
|
try {
|
|
143
155
|
const skinList = [];
|
package/lib/instance/index.d.ts
CHANGED
|
@@ -3,5 +3,11 @@ import CommonInstance from './common';
|
|
|
3
3
|
import GoldfishInstance from './dev';
|
|
4
4
|
import MiwearInstance from "./miwear";
|
|
5
5
|
import OldGoldfishInstance from './preDev';
|
|
6
|
+
/**
|
|
7
|
+
* 根据镜像决定使用哪个instance
|
|
8
|
+
* Vela正式版(4.0) -> MiwearInstance
|
|
9
|
+
* Vela开发版(dev, 0.0.2) -> OldGoldfishInstance
|
|
10
|
+
* Vela开发版(dev),除0.0.2的其他版本 -> GoldfishInstance
|
|
11
|
+
*/
|
|
6
12
|
declare function findInstance(avdName: string, params: INewGoldfishInstanceParams): GoldfishInstance | MiwearInstance | OldGoldfishInstance | undefined;
|
|
7
13
|
export { CommonInstance, GoldfishInstance, MiwearInstance, OldGoldfishInstance, findInstance };
|
package/lib/instance/index.js
CHANGED
|
@@ -14,6 +14,12 @@ const miwear_1 = __importDefault(require("./miwear"));
|
|
|
14
14
|
exports.MiwearInstance = miwear_1.default;
|
|
15
15
|
const preDev_1 = __importDefault(require("./preDev"));
|
|
16
16
|
exports.OldGoldfishInstance = preDev_1.default;
|
|
17
|
+
/**
|
|
18
|
+
* 根据镜像决定使用哪个instance
|
|
19
|
+
* Vela正式版(4.0) -> MiwearInstance
|
|
20
|
+
* Vela开发版(dev, 0.0.2) -> OldGoldfishInstance
|
|
21
|
+
* Vela开发版(dev),除0.0.2的其他版本 -> GoldfishInstance
|
|
22
|
+
*/
|
|
17
23
|
function findInstance(avdName, params) {
|
|
18
24
|
const { sdkHome, avdHome } = params;
|
|
19
25
|
const { avdImagePath } = new avd_1.default({ sdkHome, avdHome }).getVelaAvdInfo(avdName);
|
package/lib/instance/miwear.d.ts
CHANGED
|
@@ -2,27 +2,69 @@ import { INewGoldfishInstanceParams, IStartOptions } from '../typing/Instance';
|
|
|
2
2
|
import CommonInstance from './common';
|
|
3
3
|
/**
|
|
4
4
|
* MiwearInstance
|
|
5
|
-
* 针对
|
|
5
|
+
* 针对 Vela正式版(4.0)的镜像
|
|
6
6
|
*/
|
|
7
7
|
declare class MiwearInstance extends CommonInstance {
|
|
8
|
+
private params;
|
|
8
9
|
private appPathInEmulator;
|
|
9
10
|
private debugSocket?;
|
|
10
11
|
private reconnectCount;
|
|
11
12
|
constructor(params: INewGoldfishInstanceParams);
|
|
12
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* 1. 启动模拟器
|
|
15
|
+
* 2. 启动成功后,adb连接模拟器
|
|
16
|
+
* 3. 连接成功后,在模拟器中启动快应用
|
|
17
|
+
*/
|
|
13
18
|
start(options: IStartOptions): Promise<void>;
|
|
14
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* 启动模拟器
|
|
21
|
+
* 1. 通过options生成模拟器的启动命令
|
|
22
|
+
* 2. 执行启动命令
|
|
23
|
+
* 3. 判断模拟器是否启动成功
|
|
24
|
+
* 3.1 若disableNSH=true,输出流中匹配到/quickapp_rpk_installer_init|rpk installer init done/,认为模拟器启动成功了
|
|
25
|
+
* 3.2 若disableNSH=false,认为8s过后模拟器启动成功了
|
|
26
|
+
* @param options
|
|
27
|
+
* @returns
|
|
28
|
+
*/
|
|
15
29
|
startGoldfish(options: IStartOptions): Promise<void>;
|
|
16
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* 通过adb连接模拟器。
|
|
32
|
+
* 时间限制为10分钟,超时则表示连接失败
|
|
33
|
+
* @returns
|
|
34
|
+
*/
|
|
17
35
|
connectGoldfish(): Promise<boolean>;
|
|
18
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* 在模拟器中启动快应用
|
|
38
|
+
* 1. 检查release目录是否有打包好的rpk
|
|
39
|
+
* 2. 检查当前是否为调试模式.
|
|
40
|
+
* 若是,将debugger_ip.cfg推到模拟器的/data/目录下
|
|
41
|
+
* 若否,则要删除模拟器中已有的data/debugger_ip.cfg
|
|
42
|
+
* 3. 调用installRpkToAppList将当前快应用安装到模拟器的应用列表中
|
|
43
|
+
* @param options
|
|
44
|
+
*/
|
|
19
45
|
startupQuickApp(options: IStartOptions): Promise<void>;
|
|
20
|
-
/**
|
|
46
|
+
/**
|
|
47
|
+
* 将快应用安装到模拟器的应用列表
|
|
48
|
+
* 1. 使用adb push将打包好的rpk推到模拟器的/data/quickapp/app/
|
|
49
|
+
* 2. nsh中调用pm install命令安装应用
|
|
50
|
+
* @param rpkPath rpk的绝对目录
|
|
51
|
+
* @param targetDir 要将rpk放到模拟器的哪个目录下
|
|
52
|
+
*/
|
|
21
53
|
installRpkToAppList(rpkPath: string, targetDir: string): Promise<void>;
|
|
22
|
-
|
|
23
|
-
|
|
54
|
+
/** 连接模拟器中的调试服务,创建debugSocket
|
|
55
|
+
* 主要用于热更新时,通过debugSocket通知调试服务更新页面
|
|
56
|
+
* 设置了重连机制,会重复连接8次
|
|
57
|
+
*/
|
|
58
|
+
initDebugSocket(): Promise<void>;
|
|
59
|
+
/** 通知模拟器更新
|
|
60
|
+
* 1. 确保已经成功连接模拟器中的调试服务
|
|
61
|
+
* 2. 使用adb push将build文件下的内容推到/data/quickapp/app/${packageName}
|
|
62
|
+
* 3. 发送Page.reload命令给调试服务,通知更新
|
|
63
|
+
*/
|
|
24
64
|
handleUpdate(): Promise<void>;
|
|
25
|
-
/**
|
|
65
|
+
/**
|
|
66
|
+
* 创建server端,监听打包过程中client端发来的消息
|
|
67
|
+
*/
|
|
26
68
|
createWebsockeServer(): Promise<void>;
|
|
27
69
|
}
|
|
28
70
|
export default MiwearInstance;
|
package/lib/instance/miwear.js
CHANGED
|
@@ -35,7 +35,6 @@ 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 JavascriptDefaultCompileOption_1 = __importDefault(require("@aiot-toolkit/aiotpack/lib/compiler/javascript/JavascriptDefaultCompileOption"));
|
|
39
38
|
const ColorConsole_1 = __importDefault(require("@aiot-toolkit/shared-utils/lib/ColorConsole"));
|
|
40
39
|
const adbMiwt = __importStar(require("@miwt/adb"));
|
|
41
40
|
const child_process_1 = require("child_process");
|
|
@@ -50,15 +49,20 @@ const common_1 = __importDefault(require("./common"));
|
|
|
50
49
|
const MAX_RECONNECT_COUNT = 8;
|
|
51
50
|
/**
|
|
52
51
|
* MiwearInstance
|
|
53
|
-
* 针对
|
|
52
|
+
* 针对 Vela正式版(4.0)的镜像
|
|
54
53
|
*/
|
|
55
54
|
class MiwearInstance extends common_1.default {
|
|
56
55
|
constructor(params) {
|
|
57
56
|
super(params);
|
|
57
|
+
this.params = params;
|
|
58
58
|
this.appPathInEmulator = '/data/quickapp/app';
|
|
59
59
|
this.reconnectCount = 0;
|
|
60
60
|
}
|
|
61
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* 1. 启动模拟器
|
|
63
|
+
* 2. 启动成功后,adb连接模拟器
|
|
64
|
+
* 3. 连接成功后,在模拟器中启动快应用
|
|
65
|
+
*/
|
|
62
66
|
start(options) {
|
|
63
67
|
return __awaiter(this, void 0, void 0, function* () {
|
|
64
68
|
this.startOptions = options;
|
|
@@ -68,9 +72,11 @@ class MiwearInstance extends common_1.default {
|
|
|
68
72
|
const connected = yield this.connectGoldfish();
|
|
69
73
|
if (connected) {
|
|
70
74
|
ColorConsole_1.default.info('### Emulator ### Goldfish emulator connected successfully');
|
|
75
|
+
// 如果是首次启动,创建server端监听事件
|
|
71
76
|
if (this.isFirstStart && this.startOptions.serverPort) {
|
|
72
77
|
yield this.createWebsockeServer();
|
|
73
78
|
}
|
|
79
|
+
// 在模拟器中启动快应用
|
|
74
80
|
this.startupQuickApp(options);
|
|
75
81
|
this.isFirstStart = false;
|
|
76
82
|
}
|
|
@@ -79,13 +85,24 @@ class MiwearInstance extends common_1.default {
|
|
|
79
85
|
}
|
|
80
86
|
});
|
|
81
87
|
}
|
|
82
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* 启动模拟器
|
|
90
|
+
* 1. 通过options生成模拟器的启动命令
|
|
91
|
+
* 2. 执行启动命令
|
|
92
|
+
* 3. 判断模拟器是否启动成功
|
|
93
|
+
* 3.1 若disableNSH=true,输出流中匹配到/quickapp_rpk_installer_init|rpk installer init done/,认为模拟器启动成功了
|
|
94
|
+
* 3.2 若disableNSH=false,认为8s过后模拟器启动成功了
|
|
95
|
+
* @param options
|
|
96
|
+
* @returns
|
|
97
|
+
*/
|
|
83
98
|
startGoldfish(options) {
|
|
84
99
|
var _a;
|
|
85
100
|
return __awaiter(this, void 0, void 0, function* () {
|
|
86
101
|
const { avdName, devtool } = options;
|
|
102
|
+
// 获取emulator bin的绝对路径
|
|
87
103
|
const emulatorBin = this.getEmulatorBinPath();
|
|
88
104
|
ColorConsole_1.default.log(`### Emulator ### emulator path: ${emulatorBin}`);
|
|
105
|
+
// 获取vela镜像的绝对路径
|
|
89
106
|
const avdInfo = this.velaAvdCls.getVelaAvdInfo(avdName);
|
|
90
107
|
const { avdArch, avdImagePath } = avdInfo;
|
|
91
108
|
this.adbPort = yield portfinder_1.default.getPortPromise({ port: this.adbPort });
|
|
@@ -95,15 +112,15 @@ class MiwearInstance extends common_1.default {
|
|
|
95
112
|
}
|
|
96
113
|
const nuttxBinPath = path_1.default.resolve(avdImagePath, 'nuttx');
|
|
97
114
|
ColorConsole_1.default.log(`### Emulator ### nuttx path: ${nuttxBinPath}`);
|
|
98
|
-
//
|
|
115
|
+
// 端口映射,adb端口和debug端口
|
|
99
116
|
let portMappingStr = `-network-user-mode-options hostfwd=tcp:127.0.0.1:${this.adbPort}-10.0.2.15:5555`;
|
|
100
117
|
if (devtool) {
|
|
101
118
|
this.debugPort = yield portfinder_1.default.getPortPromise({ port: this.debugPort });
|
|
102
119
|
portMappingStr += `,hostfwd=tcp:127.0.0.1:${this.debugPort}-10.0.2.15:101`;
|
|
103
120
|
}
|
|
104
121
|
// 文件系统配置,第一次使用fatfs镜像挂载,后续使用adb push更新应用
|
|
105
|
-
const systemImageBin = path_1.default.resolve(avdImagePath, 'vela_resource.
|
|
106
|
-
const dataImageBin = path_1.default.resolve(avdImagePath, '
|
|
122
|
+
const systemImageBin = path_1.default.resolve(avdImagePath, 'vela_resource.bin');
|
|
123
|
+
const dataImageBin = path_1.default.resolve(avdImagePath, 'vela_data.bin');
|
|
107
124
|
const coreBin = path_1.default.resolve(avdImagePath, 'coredump.core');
|
|
108
125
|
const imageMountStr = `-drive index=0,id=system,if=none,format=raw,file=${systemImageBin} \
|
|
109
126
|
-device virtio-blk-device,bus=virtio-mmio-bus.0,drive=system \
|
|
@@ -120,8 +137,9 @@ class MiwearInstance extends common_1.default {
|
|
|
120
137
|
const portSuffix = this.startOptions.vncPort - constants_1.defaultVncPort;
|
|
121
138
|
vncStr = `-vnc :${portSuffix}`;
|
|
122
139
|
}
|
|
140
|
+
// 根据disableNSH参数配置stdio
|
|
123
141
|
const stdioType = options.disableNSH ? 'pipe' : 'inherit';
|
|
124
|
-
//
|
|
142
|
+
// 启动模拟器的命令和参数
|
|
125
143
|
const cmd = `${emulatorBin} -nuttx -avd ${avdName} -avd-arch ${avdArch} -show-kernel -kernel ${nuttxBinPath} ${portMappingStr} ${windowStr} -qemu ${vncStr} ${imageMountStr}`;
|
|
126
144
|
const spawnArgs = cmd.split(' ');
|
|
127
145
|
const spawnBin = spawnArgs.shift();
|
|
@@ -129,16 +147,19 @@ class MiwearInstance extends common_1.default {
|
|
|
129
147
|
return new Promise((resolve) => {
|
|
130
148
|
var _a, _b, _c;
|
|
131
149
|
this.goldfishProcess = (0, child_process_1.spawn)(spawnBin, spawnArgs, { stdio: stdioType, shell: true, cwd: this.sdkHome });
|
|
150
|
+
// 监听错误流
|
|
132
151
|
(_a = this.goldfishProcess.stderr) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
|
|
133
152
|
const stderrCb = options.stderrCallback || console.log;
|
|
134
153
|
stderrCb(data.toString());
|
|
135
154
|
});
|
|
155
|
+
// 监听模拟器的退出事件
|
|
136
156
|
this.goldfishProcess.on('exit', (code) => {
|
|
137
157
|
ColorConsole_1.default.error(`### Emulator ### Goldfish emulator exited with code ${code}`);
|
|
138
158
|
if (options.exitCallback) {
|
|
139
159
|
options.exitCallback(code);
|
|
140
160
|
}
|
|
141
161
|
});
|
|
162
|
+
// disableNSH=false时,输出流会直接定向到终端,可在终端输入「回车」进入模拟器的终端,这种情况下无法拿到stdout中的数据
|
|
142
163
|
if (options.disableNSH) {
|
|
143
164
|
(_c = (_b = this.goldfishProcess) === null || _b === void 0 ? void 0 : _b.stdout) === null || _c === void 0 ? void 0 : _c.on('data', (data) => {
|
|
144
165
|
const msg = data.toString();
|
|
@@ -151,17 +172,20 @@ class MiwearInstance extends common_1.default {
|
|
|
151
172
|
});
|
|
152
173
|
}
|
|
153
174
|
else {
|
|
175
|
+
// disableNSH=true时,默认8s后模拟器启动成功
|
|
154
176
|
setTimeout(() => {
|
|
155
177
|
ColorConsole_1.default.info(`### Emulator ### Goldfish emulator starts successfully`);
|
|
156
178
|
resolve();
|
|
157
179
|
}, 8000);
|
|
158
|
-
ColorConsole_1.default.info(`### Emulator ### Goldfish emulator starts successfully`);
|
|
159
|
-
resolve();
|
|
160
180
|
}
|
|
161
181
|
});
|
|
162
182
|
});
|
|
163
183
|
}
|
|
164
|
-
/**
|
|
184
|
+
/**
|
|
185
|
+
* 通过adb连接模拟器。
|
|
186
|
+
* 时间限制为10分钟,超时则表示连接失败
|
|
187
|
+
* @returns
|
|
188
|
+
*/
|
|
165
189
|
connectGoldfish() {
|
|
166
190
|
return __awaiter(this, void 0, void 0, function* () {
|
|
167
191
|
let adbConnected = false;
|
|
@@ -175,6 +199,7 @@ class MiwearInstance extends common_1.default {
|
|
|
175
199
|
ColorConsole_1.default.log(`### Emulator ### Excuting adb cmd: ${adbConnectCmd}`);
|
|
176
200
|
const str = yield adbMiwt.execAdbCmdAsync(adbConnectCmd);
|
|
177
201
|
ColorConsole_1.default.log(`### Emulator ### ${str}`);
|
|
202
|
+
// 查询模拟器的状态是否为“device”
|
|
178
203
|
const devices = yield adbMiwt.getAdbDevices();
|
|
179
204
|
ColorConsole_1.default.log(`### Emulator ### adb devices: ${JSON.stringify(devices)}`);
|
|
180
205
|
adbConnected =
|
|
@@ -191,15 +216,26 @@ class MiwearInstance extends common_1.default {
|
|
|
191
216
|
return adbConnected;
|
|
192
217
|
});
|
|
193
218
|
}
|
|
194
|
-
/**
|
|
219
|
+
/**
|
|
220
|
+
* 在模拟器中启动快应用
|
|
221
|
+
* 1. 检查release目录是否有打包好的rpk
|
|
222
|
+
* 2. 检查当前是否为调试模式.
|
|
223
|
+
* 若是,将debugger_ip.cfg推到模拟器的/data/目录下
|
|
224
|
+
* 若否,则要删除模拟器中已有的data/debugger_ip.cfg
|
|
225
|
+
* 3. 调用installRpkToAppList将当前快应用安装到模拟器的应用列表中
|
|
226
|
+
* @param options
|
|
227
|
+
*/
|
|
195
228
|
startupQuickApp(options) {
|
|
229
|
+
var _a;
|
|
196
230
|
return __awaiter(this, void 0, void 0, function* () {
|
|
197
231
|
const { package: appPackageName } = this.projectInfo;
|
|
198
|
-
const releaseDir =
|
|
232
|
+
const releaseDir = this.isRpk
|
|
233
|
+
? path_1.default.resolve(this.projectPath, '../')
|
|
234
|
+
: path_1.default.resolve(this.projectPath, ((_a = this.params.compilerOption) === null || _a === void 0 ? void 0 : _a.releasePath) || 'dist');
|
|
199
235
|
const files = fs_extra_1.default
|
|
200
236
|
.readdirSync(releaseDir)
|
|
201
237
|
.filter(item => item.includes(appPackageName) && item.endsWith('.rpk'));
|
|
202
|
-
if (files.length
|
|
238
|
+
if (files.length === 0) {
|
|
203
239
|
ColorConsole_1.default.error(`### Emulator the rpk does not exist`);
|
|
204
240
|
}
|
|
205
241
|
const rpkPath = path_1.default.resolve(releaseDir, files[0]);
|
|
@@ -215,68 +251,75 @@ class MiwearInstance extends common_1.default {
|
|
|
215
251
|
this.installRpkToAppList(rpkPath, this.appPathInEmulator);
|
|
216
252
|
});
|
|
217
253
|
}
|
|
218
|
-
/**
|
|
254
|
+
/**
|
|
255
|
+
* 将快应用安装到模拟器的应用列表
|
|
256
|
+
* 1. 使用adb push将打包好的rpk推到模拟器的/data/quickapp/app/
|
|
257
|
+
* 2. nsh中调用pm install命令安装应用
|
|
258
|
+
* @param rpkPath rpk的绝对目录
|
|
259
|
+
* @param targetDir 要将rpk放到模拟器的哪个目录下
|
|
260
|
+
*/
|
|
219
261
|
installRpkToAppList(rpkPath, targetDir) {
|
|
220
262
|
return __awaiter(this, void 0, void 0, function* () {
|
|
221
263
|
try {
|
|
222
264
|
const sn = `127.0.0.1:${this.adbPort}`;
|
|
223
265
|
const { package: packageName } = this.projectInfo;
|
|
224
|
-
|
|
225
|
-
// 1. 查询应用是否已经安装,如果安装了,则先卸载
|
|
226
|
-
const lsCmd = `adb -s ${sn} shell ls ${this.appPathInEmulator}`;
|
|
227
|
-
const res = yield adbMiwt.execAdbCmdAsync(lsCmd);
|
|
228
|
-
if (res.includes(packageName)) {
|
|
229
|
-
const uninstallCmd = `adb -s ${sn} shell pm uninstall ${packageName}`;
|
|
230
|
-
ColorConsole_1.default.info(`### Emulator ### Excuting cmd: ${uninstallCmd}`);
|
|
231
|
-
adbMiwt.execAdbCmdAsync(uninstallCmd);
|
|
232
|
-
// 这里等待2s的作用是等qemu执行完uninstall操作的一系列工作
|
|
233
|
-
yield (0, utils_1.sleep)(2000);
|
|
234
|
-
}
|
|
235
|
-
// 2. adb push应用的rpk
|
|
266
|
+
// 1. adb push应用的rpk
|
|
236
267
|
const targetPath = `${targetDir}/${packageName}.rpk`;
|
|
237
|
-
const pushCmd = `adb -s ${sn} push ${rpkPath} ${targetPath}`;
|
|
268
|
+
const pushCmd = `adb -s ${sn} push "${rpkPath}" ${targetPath}`;
|
|
238
269
|
ColorConsole_1.default.info(`### Emulator ### Excuting cmd: ${pushCmd}`);
|
|
239
270
|
yield adbMiwt.execAdbCmdAsync(pushCmd);
|
|
240
|
-
yield (0, utils_1.sleep)(
|
|
241
|
-
//
|
|
271
|
+
yield (0, utils_1.sleep)(1000);
|
|
272
|
+
// 2. 安装应用(pm install时如何应用重名会覆盖)
|
|
242
273
|
const installCmd = `adb -s ${sn} shell pm install ${targetPath}`;
|
|
243
274
|
ColorConsole_1.default.info(`### Emulator ### Excuting cmd: ${installCmd}`);
|
|
244
275
|
adbMiwt.execAdbCmdAsync(installCmd);
|
|
245
276
|
}
|
|
246
|
-
catch (e) {
|
|
277
|
+
catch (e) {
|
|
278
|
+
ColorConsole_1.default.error(`### Emulator ### ${e.message}`);
|
|
279
|
+
}
|
|
247
280
|
});
|
|
248
281
|
}
|
|
282
|
+
/** 连接模拟器中的调试服务,创建debugSocket
|
|
283
|
+
* 主要用于热更新时,通过debugSocket通知调试服务更新页面
|
|
284
|
+
* 设置了重连机制,会重复连接8次
|
|
285
|
+
*/
|
|
249
286
|
initDebugSocket() {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
this.debugSocket = new ws_1.default(`ws://localhost:${this.debugPort}`);
|
|
254
|
-
this.debugSocket.onopen = () => {
|
|
255
|
-
ColorConsole_1.default.info(`### Emulator debugSocket connect success`);
|
|
256
|
-
return Promise.resolve();
|
|
257
|
-
};
|
|
258
|
-
this.debugSocket.onerror = (e) => {
|
|
259
|
-
var _a;
|
|
260
|
-
// 重连机制
|
|
261
|
-
(_a = this.debugSocket) === null || _a === void 0 ? void 0 : _a.terminate();
|
|
262
|
-
if (this.reconnectCount < MAX_RECONNECT_COUNT) {
|
|
263
|
-
ColorConsole_1.default.info(`### Emulator the ${this.reconnectCount + 1}th time to reconnect debug server`);
|
|
264
|
-
this.reconnectCount++;
|
|
265
|
-
setTimeout(() => this.initDebugSocket(), 2000);
|
|
287
|
+
return new Promise((resolve, reject) => {
|
|
288
|
+
if (this.debugSocket && this.debugSocket.OPEN) {
|
|
289
|
+
return resolve();
|
|
266
290
|
}
|
|
267
|
-
|
|
291
|
+
this.debugSocket = new ws_1.default(`ws://localhost:${this.debugPort}`);
|
|
292
|
+
this.debugSocket.onopen = () => {
|
|
293
|
+
ColorConsole_1.default.info(`### Emulator debugSocket connect success`);
|
|
294
|
+
return resolve();
|
|
295
|
+
};
|
|
296
|
+
this.debugSocket.onerror = (errorEvent) => {
|
|
297
|
+
var _a;
|
|
298
|
+
// 重连机制
|
|
299
|
+
(_a = this.debugSocket) === null || _a === void 0 ? void 0 : _a.terminate();
|
|
300
|
+
if (this.reconnectCount < MAX_RECONNECT_COUNT) {
|
|
301
|
+
ColorConsole_1.default.info(`### Emulator the ${this.reconnectCount + 1}th time to reconnect debug server`);
|
|
302
|
+
this.reconnectCount++;
|
|
303
|
+
setTimeout(() => this.initDebugSocket(), 2000);
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
this.debugSocket = undefined;
|
|
307
|
+
this.reconnectCount = 0;
|
|
308
|
+
return reject(`### Emulator debugSocket connect failed, ${errorEvent.message}`);
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
this.debugSocket.onclose = (closeEvent) => {
|
|
268
312
|
this.debugSocket = undefined;
|
|
269
313
|
this.reconnectCount = 0;
|
|
270
|
-
|
|
271
|
-
}
|
|
272
|
-
};
|
|
273
|
-
this.debugSocket.onclose = (e) => {
|
|
274
|
-
this.debugSocket = undefined;
|
|
275
|
-
this.reconnectCount = 0;
|
|
276
|
-
ColorConsole_1.default.log(`### Emulator debugSocket connect close: ${e.data}`);
|
|
277
|
-
};
|
|
314
|
+
ColorConsole_1.default.log(`### Emulator debugSocket connect close: ${closeEvent.reason}`);
|
|
315
|
+
};
|
|
316
|
+
});
|
|
278
317
|
}
|
|
279
|
-
/** 通知模拟器更新
|
|
318
|
+
/** 通知模拟器更新
|
|
319
|
+
* 1. 确保已经成功连接模拟器中的调试服务
|
|
320
|
+
* 2. 使用adb push将build文件下的内容推到/data/quickapp/app/${packageName}
|
|
321
|
+
* 3. 发送Page.reload命令给调试服务,通知更新
|
|
322
|
+
*/
|
|
280
323
|
handleUpdate() {
|
|
281
324
|
var _a, _b;
|
|
282
325
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -286,12 +329,13 @@ class MiwearInstance extends common_1.default {
|
|
|
286
329
|
// 1. 将整包重新推到miwear中(TODO:增量更新)
|
|
287
330
|
const sn = `127.0.0.1:${this.adbPort}`;
|
|
288
331
|
const { package: appPackageName } = this.projectInfo;
|
|
289
|
-
// windows平台adb push
|
|
290
|
-
|
|
332
|
+
// windows平台adb push时无法使用通配符,需另外处理;
|
|
333
|
+
// 项目路径包含空格时,无法通过加引号来使用 * 通配符
|
|
334
|
+
if (os_1.default.platform() === 'win32' || this.projectPath.indexOf(' ') > 0) {
|
|
291
335
|
const rmCmd = `adb -s ${sn} shell rm -r ${this.appPathInEmulator}/${appPackageName}`;
|
|
292
336
|
yield adbMiwt.execAdbCmdAsync(rmCmd);
|
|
293
337
|
const sourcePath = path_1.default.resolve(this.projectPath, './build');
|
|
294
|
-
const pushCmd = `adb -s ${sn} push ${sourcePath} ${this.appPathInEmulator}/${appPackageName}`;
|
|
338
|
+
const pushCmd = `adb -s ${sn} push "${sourcePath}" ${this.appPathInEmulator}/${appPackageName}`;
|
|
295
339
|
yield adbMiwt.execAdbCmdAsync(pushCmd);
|
|
296
340
|
}
|
|
297
341
|
else {
|
|
@@ -309,7 +353,9 @@ class MiwearInstance extends common_1.default {
|
|
|
309
353
|
}
|
|
310
354
|
});
|
|
311
355
|
}
|
|
312
|
-
/**
|
|
356
|
+
/**
|
|
357
|
+
* 创建server端,监听打包过程中client端发来的消息
|
|
358
|
+
*/
|
|
313
359
|
createWebsockeServer() {
|
|
314
360
|
var _a;
|
|
315
361
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -321,6 +367,7 @@ class MiwearInstance extends common_1.default {
|
|
|
321
367
|
socket.on('error', err => {
|
|
322
368
|
ColorConsole_1.default.error(`### App Socket server ### Websocket server error: ${err.message}`);
|
|
323
369
|
});
|
|
370
|
+
// data的格式:{ type: string, data: any }
|
|
324
371
|
socket.on('message', (data) => __awaiter(this, void 0, void 0, function* () {
|
|
325
372
|
var _a;
|
|
326
373
|
const message = JSON.parse(data.toString());
|
package/lib/instance/preDev.d.ts
CHANGED
|
@@ -2,20 +2,54 @@
|
|
|
2
2
|
import { ChildProcess } from 'child_process';
|
|
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;
|
|
8
12
|
constructor(params: INewGoldfishInstanceParams);
|
|
9
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* 1. 启动9p server
|
|
15
|
+
* 2. 将打包好的rpk推到host的挂载目录
|
|
16
|
+
* 3. 启动模拟器
|
|
17
|
+
* 4. 模拟器启动成功后,adb连接模拟器
|
|
18
|
+
* 5. 连接成功后,在模拟器中启动快应用
|
|
19
|
+
*/
|
|
10
20
|
start(options: IStartOptions): Promise<void>;
|
|
11
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* 在模拟器中启动快应用(快应用都在模拟器的/data/app目录下)
|
|
23
|
+
* 1. 是否为调试模式
|
|
24
|
+
* 若是,在模拟器终端执行vapp app/${packageName} &
|
|
25
|
+
* 若否,在模拟器终端执行vapp --jsdebugger=10.0.2.15:101 app/${packageName} &
|
|
26
|
+
*/
|
|
12
27
|
startupQuickApp(options: IStartOptions): void;
|
|
13
|
-
/** host启动9pServer
|
|
28
|
+
/** host启动9pServer
|
|
29
|
+
* 作用是将本地的quickappMountDir目录挂载到模拟器的/data目录
|
|
30
|
+
*/
|
|
14
31
|
ensure9pServerRunnning(): Promise<void>;
|
|
15
|
-
/**
|
|
32
|
+
/**
|
|
33
|
+
* 启动模拟器
|
|
34
|
+
* 1. 通过options生成模拟器的启动命令
|
|
35
|
+
* 2. 执行启动命令
|
|
36
|
+
* 3. 判断模拟器是否启动成功
|
|
37
|
+
* 3.1 若disableNSH=true,输出流中匹配到/quickapp_rpk_installer_init|rpk installer init done/,认为模拟器启动成功了
|
|
38
|
+
* 3.2 若disableNSH=false,认为8s过后模拟器启动成功了
|
|
39
|
+
* @param options
|
|
40
|
+
* @returns
|
|
41
|
+
*/
|
|
16
42
|
startGoldfish(options: IStartOptions): Promise<void>;
|
|
17
|
-
/**
|
|
43
|
+
/**
|
|
44
|
+
* 通过adb连接模拟器。
|
|
45
|
+
* 时间限制为10分钟,超时则表示连接失败
|
|
46
|
+
* @returns
|
|
47
|
+
*/
|
|
18
48
|
connectGoldfish(): Promise<boolean>;
|
|
49
|
+
/**
|
|
50
|
+
* 推送文件到本地的${sdkHome}/qa/app/${packageName}目录
|
|
51
|
+
* @param sourceRoot 源目录
|
|
52
|
+
*/
|
|
19
53
|
pushRpk(sourceRoot: string): Promise<void>;
|
|
20
54
|
/** 停止模拟器并释放相关资源 */
|
|
21
55
|
stop(): Promise<void>;
|
package/lib/instance/preDev.js
CHANGED
|
@@ -46,12 +46,22 @@ 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
|
-
/**
|
|
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* () {
|
|
57
67
|
// host启动9p server
|
|
@@ -62,9 +72,11 @@ class OldGoldfishInstance extends common_1.default {
|
|
|
62
72
|
this.pushRpk(buildedFilesPath);
|
|
63
73
|
// 启动模拟器
|
|
64
74
|
yield this.startGoldfish(options);
|
|
75
|
+
// adb连接快应用
|
|
65
76
|
const connected = yield this.connectGoldfish();
|
|
66
77
|
if (connected) {
|
|
67
78
|
ColorConsole_1.default.log('### Emulator ### Goldfish emulator connected successfully');
|
|
79
|
+
// 如果是首次启动,创建server端监听事件
|
|
68
80
|
if (this.isFirstStart && this.startOptions.serverPort) {
|
|
69
81
|
yield this.createWebsockeServer();
|
|
70
82
|
}
|
|
@@ -77,7 +89,12 @@ class OldGoldfishInstance extends common_1.default {
|
|
|
77
89
|
}
|
|
78
90
|
});
|
|
79
91
|
}
|
|
80
|
-
/**
|
|
92
|
+
/**
|
|
93
|
+
* 在模拟器中启动快应用(快应用都在模拟器的/data/app目录下)
|
|
94
|
+
* 1. 是否为调试模式
|
|
95
|
+
* 若是,在模拟器终端执行vapp app/${packageName} &
|
|
96
|
+
* 若否,在模拟器终端执行vapp --jsdebugger=10.0.2.15:101 app/${packageName} &
|
|
97
|
+
*/
|
|
81
98
|
startupQuickApp(options) {
|
|
82
99
|
try {
|
|
83
100
|
const { package: packageName } = this.projectInfo;
|
|
@@ -86,6 +103,7 @@ class OldGoldfishInstance extends common_1.default {
|
|
|
86
103
|
ColorConsole_1.default.log(`### Emulator ### Excuting adb cmd: ${mountCmd}`);
|
|
87
104
|
adbMiwt.execAdbCmdSync(mountCmd);
|
|
88
105
|
let vappCmd = `adb -s 127.0.0.1:${this.adbPort} shell vapp app/${packageName} &`;
|
|
106
|
+
// 调试情况下,需要加--jsdebugger=10.0.2.15:101
|
|
89
107
|
if (options.devtool) {
|
|
90
108
|
vappCmd = `adb -s 127.0.0.1:${this.adbPort} shell vapp --jsdebugger=10.0.2.15:101 app/${packageName} &`;
|
|
91
109
|
}
|
|
@@ -97,7 +115,9 @@ class OldGoldfishInstance extends common_1.default {
|
|
|
97
115
|
ColorConsole_1.default.error(`### Emulator ### Failed to startup quickapp: ${e.message}`);
|
|
98
116
|
}
|
|
99
117
|
}
|
|
100
|
-
/** host启动9pServer
|
|
118
|
+
/** host启动9pServer
|
|
119
|
+
* 作用是将本地的quickappMountDir目录挂载到模拟器的/data目录
|
|
120
|
+
*/
|
|
101
121
|
ensure9pServerRunnning() {
|
|
102
122
|
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
|
103
123
|
var _a;
|
|
@@ -121,6 +141,7 @@ class OldGoldfishInstance extends common_1.default {
|
|
|
121
141
|
address,
|
|
122
142
|
'--debug'
|
|
123
143
|
]);
|
|
144
|
+
// 监听stderr,判断9p server是否启动成功了
|
|
124
145
|
(_a = this.v9fsProcess.stderr) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
|
|
125
146
|
const output = data.toString();
|
|
126
147
|
if (output.match(/Server started, listening on: 127.0.0.1:(\d+)/)) {
|
|
@@ -129,18 +150,30 @@ class OldGoldfishInstance extends common_1.default {
|
|
|
129
150
|
return resolve();
|
|
130
151
|
}
|
|
131
152
|
});
|
|
153
|
+
// 监听exit事件,判断9p server是否退出了
|
|
132
154
|
this.v9fsProcess.on('exit', (code) => {
|
|
133
155
|
ColorConsole_1.default.error(`### Emulator ### ya-vm-file-server exited with code ${code}`);
|
|
134
156
|
return reject();
|
|
135
157
|
});
|
|
136
158
|
}));
|
|
137
159
|
}
|
|
138
|
-
/**
|
|
160
|
+
/**
|
|
161
|
+
* 启动模拟器
|
|
162
|
+
* 1. 通过options生成模拟器的启动命令
|
|
163
|
+
* 2. 执行启动命令
|
|
164
|
+
* 3. 判断模拟器是否启动成功
|
|
165
|
+
* 3.1 若disableNSH=true,输出流中匹配到/quickapp_rpk_installer_init|rpk installer init done/,认为模拟器启动成功了
|
|
166
|
+
* 3.2 若disableNSH=false,认为8s过后模拟器启动成功了
|
|
167
|
+
* @param options
|
|
168
|
+
* @returns
|
|
169
|
+
*/
|
|
139
170
|
startGoldfish(options) {
|
|
140
171
|
return __awaiter(this, void 0, void 0, function* () {
|
|
141
172
|
const { avdName, devtool } = options;
|
|
173
|
+
// 获取emulator bin的绝对路径
|
|
142
174
|
const emulatorBin = this.getEmulatorBinPath();
|
|
143
175
|
ColorConsole_1.default.log(`### Emulator ### emulator path: ${emulatorBin}`);
|
|
176
|
+
// 获取vela镜像的绝对路径
|
|
144
177
|
const avdInfo = this.velaAvdCls.getVelaAvdInfo(avdName);
|
|
145
178
|
const { avdArch, avdImagePath } = avdInfo;
|
|
146
179
|
this.adbPort = yield portfinder_1.default.getPortPromise({ port: this.adbPort });
|
|
@@ -150,6 +183,7 @@ class OldGoldfishInstance extends common_1.default {
|
|
|
150
183
|
}
|
|
151
184
|
const nuttxBinPath = path_1.default.resolve(avdImagePath, 'nuttx');
|
|
152
185
|
ColorConsole_1.default.log(`### Emulator ### nuttx path: ${nuttxBinPath}`);
|
|
186
|
+
// 端口映射,adb端口和debug端口
|
|
153
187
|
let portMappingStr = `user,id=u1,hostfwd=tcp:127.0.0.1:${this.adbPort}-10.0.2.15:5555`;
|
|
154
188
|
if (devtool) {
|
|
155
189
|
this.debugPort = yield portfinder_1.default.getPortPromise({ port: this.debugPort });
|
|
@@ -157,7 +191,6 @@ class OldGoldfishInstance extends common_1.default {
|
|
|
157
191
|
portMappingStr += `,hostfwd=tcp:127.0.0.1:${this.debugPort}-10.0.2.15:101`;
|
|
158
192
|
}
|
|
159
193
|
ColorConsole_1.default.log(`### Emulator ### Start qemu with TCP: ${portMappingStr}`);
|
|
160
|
-
const stdioType = options.disableNSH ? 'pipe' : 'inherit';
|
|
161
194
|
// vnc配置
|
|
162
195
|
let noWindow = false;
|
|
163
196
|
let vncStr = '';
|
|
@@ -166,6 +199,8 @@ class OldGoldfishInstance extends common_1.default {
|
|
|
166
199
|
const portSuffix = options.vncPort - constants_1.defaultVncPort;
|
|
167
200
|
vncStr = `-vnc :${portSuffix}`;
|
|
168
201
|
}
|
|
202
|
+
// 根据disableNSH参数配置stdio
|
|
203
|
+
const stdioType = options.disableNSH ? 'pipe' : 'inherit';
|
|
169
204
|
// 启动goldfish的命令和参数
|
|
170
205
|
const spawnBin = emulatorBin;
|
|
171
206
|
const spawnArgs = [
|
|
@@ -189,16 +224,19 @@ class OldGoldfishInstance extends common_1.default {
|
|
|
189
224
|
return new Promise((resolve) => {
|
|
190
225
|
var _a;
|
|
191
226
|
this.goldfishProcess = (0, child_process_1.spawn)(spawnBin, spawnArgs, { stdio: stdioType, shell: true });
|
|
227
|
+
// 监听错误流
|
|
192
228
|
(_a = this.goldfishProcess.stderr) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
|
|
193
229
|
const stderrCb = options.stderrCallback || console.log;
|
|
194
230
|
stderrCb(data.toString());
|
|
195
231
|
});
|
|
232
|
+
// 监听模拟器的退出事件
|
|
196
233
|
this.goldfishProcess.on('exit', (code) => {
|
|
197
234
|
ColorConsole_1.default.error(`### Emulator ### Goldfish emulator exited with code ${code}`);
|
|
198
235
|
if (options.exitCallback) {
|
|
199
236
|
options.exitCallback(code);
|
|
200
237
|
}
|
|
201
238
|
});
|
|
239
|
+
// 监听输出流。输出了'(NSH)'标识或者2s后则认为模拟器启动成功
|
|
202
240
|
const p1 = new Promise((resolve) => {
|
|
203
241
|
var _a, _b;
|
|
204
242
|
(_b = (_a = this.goldfishProcess) === null || _a === void 0 ? void 0 : _a.stdout) === null || _b === void 0 ? void 0 : _b.on('data', (data) => {
|
|
@@ -218,7 +256,11 @@ class OldGoldfishInstance extends common_1.default {
|
|
|
218
256
|
});
|
|
219
257
|
});
|
|
220
258
|
}
|
|
221
|
-
/**
|
|
259
|
+
/**
|
|
260
|
+
* 通过adb连接模拟器。
|
|
261
|
+
* 时间限制为10分钟,超时则表示连接失败
|
|
262
|
+
* @returns
|
|
263
|
+
*/
|
|
222
264
|
connectGoldfish() {
|
|
223
265
|
return __awaiter(this, void 0, void 0, function* () {
|
|
224
266
|
let adbConnected = false;
|
|
@@ -248,6 +290,10 @@ class OldGoldfishInstance extends common_1.default {
|
|
|
248
290
|
return adbConnected;
|
|
249
291
|
});
|
|
250
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* 推送文件到本地的${sdkHome}/qa/app/${packageName}目录
|
|
295
|
+
* @param sourceRoot 源目录
|
|
296
|
+
*/
|
|
251
297
|
pushRpk(sourceRoot) {
|
|
252
298
|
return __awaiter(this, void 0, void 0, function* () {
|
|
253
299
|
const { package: appPackageName } = this.projectInfo;
|
|
@@ -6,14 +6,17 @@ 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
|
|
9
|
+
export declare const VelaImageVersionList: {
|
|
10
|
+
label: string;
|
|
11
|
+
value: string;
|
|
12
|
+
time: string;
|
|
13
|
+
}[];
|
|
14
|
+
export declare const EmulatorEnvVersion: {
|
|
10
15
|
name: string;
|
|
11
16
|
emulator: string;
|
|
12
17
|
qa: string;
|
|
13
18
|
skins: string;
|
|
14
|
-
'system-images':
|
|
15
|
-
release: string;
|
|
16
|
-
dev: string;
|
|
17
|
-
};
|
|
19
|
+
'system-images': string;
|
|
18
20
|
tools: string;
|
|
21
|
+
modem_simulator: string;
|
|
19
22
|
};
|
package/lib/static/constants.js
CHANGED
|
@@ -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.
|
|
6
|
+
exports.EmulatorEnvVersion = exports.VelaImageVersionList = 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,24 @@ 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.
|
|
17
|
+
exports.VelaImageVersionList = [
|
|
18
|
+
{
|
|
19
|
+
label: 'vela正式版(4.0)',
|
|
20
|
+
value: 'vela-release-4.0',
|
|
21
|
+
time: '2024-04-10T04:10:00'
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
label: 'vela开发版(dev, 0.0.2)',
|
|
25
|
+
value: 'vela-dev-0.0.2',
|
|
26
|
+
time: '2023-12-04T16:31:00',
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
exports.EmulatorEnvVersion = {
|
|
18
30
|
name: '模拟器资源版本管理',
|
|
19
|
-
emulator: '0.0.
|
|
31
|
+
emulator: '0.0.3',
|
|
20
32
|
qa: '0.0.1',
|
|
21
33
|
skins: '0.0.1',
|
|
22
|
-
'system-images':
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
},
|
|
26
|
-
tools: '0.0.2'
|
|
34
|
+
'system-images': exports.VelaImageVersionList[0].value,
|
|
35
|
+
tools: '0.0.2',
|
|
36
|
+
modem_simulator: '0.0.1'
|
|
27
37
|
};
|
package/lib/typing/Instance.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
import IJavascriptCompileOption from "@aiot-toolkit/aiotpack/lib/compiler/javascript/interface/IJavascriptCompileOption";
|
|
2
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;
|
package/lib/utils/index.d.ts
CHANGED
package/lib/utils/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiot-toolkit/emulator",
|
|
3
|
-
"version": "2.0.2-beta.
|
|
3
|
+
"version": "2.0.2-beta.5",
|
|
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.
|
|
39
|
-
"@aiot-toolkit/shared-utils": "2.0.2-beta.
|
|
38
|
+
"@aiot-toolkit/aiotpack": "2.0.2-beta.5",
|
|
39
|
+
"@aiot-toolkit/shared-utils": "2.0.2-beta.5",
|
|
40
40
|
"find-process": "^1.4.7",
|
|
41
41
|
"portfinder": "^1.0.32"
|
|
42
42
|
},
|
|
43
|
-
"
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/fs-extra": "^11.0.4",
|
|
45
|
+
"fs-extra": "^11.2.0"
|
|
46
|
+
},
|
|
47
|
+
"gitHead": "8c18753992c453c6569a3125378e75fbf4760a1f"
|
|
44
48
|
}
|