@aiot-toolkit/emulator 2.0.2-beta.10 → 2.0.2-beta.12
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/lib/avd/index.d.ts +4 -0
- package/lib/avd/index.js +35 -30
- package/lib/index.d.ts +3 -1
- package/lib/index.js +4 -1
- package/lib/instance/common.d.ts +5 -0
- package/lib/instance/common.js +25 -11
- package/lib/instance/dev.d.ts +11 -1
- package/lib/instance/dev.js +91 -46
- package/lib/instance/index.d.ts +4 -2
- package/lib/instance/index.js +9 -3
- package/lib/instance/miwear.d.ts +3 -0
- package/lib/instance/miwear.js +68 -97
- package/lib/instance/pre.d.ts +8 -0
- package/lib/instance/pre.js +19 -0
- package/lib/instance/preDev.js +27 -28
- package/lib/static/avdConfigIni.json +3 -3
- package/lib/static/constants.d.ts +7 -0
- package/lib/static/constants.js +30 -6
- package/lib/typing/Avd.d.ts +1 -0
- package/lib/typing/Instance.d.ts +2 -2
- package/lib/utils/index.d.ts +20 -0
- package/lib/utils/index.js +65 -8
- package/package.json +7 -5
package/lib/avd/index.d.ts
CHANGED
|
@@ -20,5 +20,9 @@ declare class VelaAvdCls {
|
|
|
20
20
|
getVelaAvdList(): IAvdParams[];
|
|
21
21
|
/** 获取模拟器皮肤列表 */
|
|
22
22
|
getVelaSkinList(): string[];
|
|
23
|
+
/** 自定义模拟器的镜像目录 */
|
|
24
|
+
customImageDir(avdName: string, target: string): void;
|
|
25
|
+
/** 重置自定义的镜像目录 */
|
|
26
|
+
resetImageDir(avdName: string): void;
|
|
23
27
|
}
|
|
24
28
|
export default VelaAvdCls;
|
package/lib/avd/index.js
CHANGED
|
@@ -3,18 +3,19 @@ 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
|
-
const
|
|
6
|
+
const shared_utils_1 = require("@aiot-toolkit/shared-utils");
|
|
7
7
|
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const os_1 = __importDefault(require("os"));
|
|
8
9
|
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const ini_1 = require("ini");
|
|
9
11
|
const constants_1 = require("../static/constants");
|
|
10
12
|
const Avd_1 = require("../typing/Avd");
|
|
11
|
-
const os_1 = __importDefault(require("os"));
|
|
12
13
|
const EAvdParamsToIni = {
|
|
13
|
-
|
|
14
|
-
abiType: 'armeabi-v7a'
|
|
14
|
+
arm: {
|
|
15
|
+
abiType: 'armeabi-v7a'
|
|
15
16
|
},
|
|
16
|
-
|
|
17
|
-
abiType: 'arm64-v8a'
|
|
17
|
+
arm64: {
|
|
18
|
+
abiType: 'arm64-v8a'
|
|
18
19
|
}
|
|
19
20
|
};
|
|
20
21
|
class VelaAvdCls {
|
|
@@ -72,16 +73,11 @@ class VelaAvdCls {
|
|
|
72
73
|
// 写入Vela_Virtual_Device.ini文件
|
|
73
74
|
fs_1.default.writeFileSync(avdIni, nuttxAvdIniContent);
|
|
74
75
|
// 写入Vela_Virtual_Device.avd/config.ini文件
|
|
75
|
-
|
|
76
|
-
for (const item in configIniJson) {
|
|
77
|
-
const line = `${item} = ${configIniJson[item]}\n`;
|
|
78
|
-
fWrite.write(line);
|
|
79
|
-
}
|
|
80
|
-
fWrite.close();
|
|
76
|
+
fs_1.default.writeFileSync(avdConfigIni, (0, ini_1.stringify)(configIniJson));
|
|
81
77
|
return true;
|
|
82
78
|
}
|
|
83
79
|
catch (e) {
|
|
84
|
-
throw
|
|
80
|
+
throw `createVelaAvd: ${e.message}`;
|
|
85
81
|
}
|
|
86
82
|
}
|
|
87
83
|
/** 根据AVD名字获取模拟器的详细信息 */
|
|
@@ -98,26 +94,17 @@ class VelaAvdCls {
|
|
|
98
94
|
const configIni = path_1.default.resolve(currAvdDir, 'config.ini');
|
|
99
95
|
try {
|
|
100
96
|
const contents = fs_1.default.readFileSync(configIni, 'utf-8');
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const skinRegex = /skin.name = ([\d\D]+?)\n/;
|
|
109
|
-
const skinMatcher = contents.match(skinRegex);
|
|
110
|
-
const imagePathRegex = /image.sysdir.1 = ([\d\D]+?)\n/;
|
|
111
|
-
const imagePathMather = contents.match(imagePathRegex);
|
|
112
|
-
archMatcher && (avdInfo.avdArch = archMatcher[1]);
|
|
113
|
-
heightMatcher && (avdInfo.avdHeight = heightMatcher[1]);
|
|
114
|
-
widthMatcher && (avdInfo.avdWidth = widthMatcher[1]);
|
|
115
|
-
skinMatcher && (avdInfo.avdSkin = skinMatcher[1]);
|
|
116
|
-
imagePathMather && (avdInfo.avdImagePath = imagePathMather[1]);
|
|
97
|
+
const config = (0, ini_1.parse)(contents);
|
|
98
|
+
avdInfo.avdArch = config['hw.cpu.arch'];
|
|
99
|
+
avdInfo.avdHeight = config['hw.lcd.height'];
|
|
100
|
+
avdInfo.avdWidth = config['hw.lcd.width'];
|
|
101
|
+
avdInfo.avdSkin = config['skin.name'];
|
|
102
|
+
avdInfo.avdImagePath = config['image.sysdir.1'];
|
|
103
|
+
avdInfo.customImagePath = config['image.sysdir.2'];
|
|
117
104
|
return avdInfo;
|
|
118
105
|
}
|
|
119
106
|
catch (err) {
|
|
120
|
-
|
|
107
|
+
shared_utils_1.ColorConsole.log(`getVelaAvdInfo: ${err.message}`);
|
|
121
108
|
return avdInfo;
|
|
122
109
|
}
|
|
123
110
|
}
|
|
@@ -164,5 +151,23 @@ class VelaAvdCls {
|
|
|
164
151
|
return [];
|
|
165
152
|
}
|
|
166
153
|
}
|
|
154
|
+
/** 自定义模拟器的镜像目录 */
|
|
155
|
+
customImageDir(avdName, target) {
|
|
156
|
+
const currAvdDir = path_1.default.resolve(this.avdHome, `${avdName}.avd`);
|
|
157
|
+
const configIni = path_1.default.resolve(currAvdDir, 'config.ini');
|
|
158
|
+
const contents = fs_1.default.readFileSync(configIni, 'utf-8');
|
|
159
|
+
const config = (0, ini_1.parse)(contents);
|
|
160
|
+
config['image.sysdir.2'] = target;
|
|
161
|
+
fs_1.default.writeFileSync(configIni, (0, ini_1.stringify)(config));
|
|
162
|
+
}
|
|
163
|
+
/** 重置自定义的镜像目录 */
|
|
164
|
+
resetImageDir(avdName) {
|
|
165
|
+
const currAvdDir = path_1.default.resolve(this.avdHome, `${avdName}.avd`);
|
|
166
|
+
const configIni = path_1.default.resolve(currAvdDir, 'config.ini');
|
|
167
|
+
const contents = fs_1.default.readFileSync(configIni, 'utf-8');
|
|
168
|
+
const config = (0, ini_1.parse)(contents);
|
|
169
|
+
delete config['image.sysdir.2'];
|
|
170
|
+
fs_1.default.writeFileSync(configIni, (0, ini_1.stringify)(config));
|
|
171
|
+
}
|
|
167
172
|
}
|
|
168
173
|
exports.default = VelaAvdCls;
|
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { default as VelaAvdCls } from './avd';
|
|
2
|
+
import { getSystemArch } from './utils';
|
|
2
3
|
export * from './instance';
|
|
3
4
|
export * from './typing/Avd';
|
|
4
5
|
export * from './typing/Instance';
|
|
5
|
-
export
|
|
6
|
+
export * from './static/constants';
|
|
7
|
+
export { VelaAvdCls, getSystemArch };
|
package/lib/index.js
CHANGED
|
@@ -17,9 +17,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
17
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.VelaAvdCls = void 0;
|
|
20
|
+
exports.getSystemArch = exports.VelaAvdCls = void 0;
|
|
21
21
|
const avd_1 = __importDefault(require("./avd"));
|
|
22
22
|
Object.defineProperty(exports, "VelaAvdCls", { enumerable: true, get: function () { return avd_1.default; } });
|
|
23
|
+
const utils_1 = require("./utils");
|
|
24
|
+
Object.defineProperty(exports, "getSystemArch", { enumerable: true, get: function () { return utils_1.getSystemArch; } });
|
|
23
25
|
__exportStar(require("./instance"), exports);
|
|
24
26
|
__exportStar(require("./typing/Avd"), exports);
|
|
25
27
|
__exportStar(require("./typing/Instance"), exports);
|
|
28
|
+
__exportStar(require("./static/constants"), exports);
|
package/lib/instance/common.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { INewGoldfishInstanceParams, IStartOptions } from '../typing/Instance';
|
|
|
7
7
|
* CommonInstance
|
|
8
8
|
*/
|
|
9
9
|
declare class CommonInstance {
|
|
10
|
+
quickappStartedFlag: RegExp;
|
|
10
11
|
projectPath: string;
|
|
11
12
|
sdkHome: string;
|
|
12
13
|
avdHome: string;
|
|
@@ -23,6 +24,10 @@ declare class CommonInstance {
|
|
|
23
24
|
getEmulatorBinPath(): string;
|
|
24
25
|
/** 在goldfish模拟器中运行快应用 */
|
|
25
26
|
start(options: IStartOptions): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* 判断模拟器是否 ready
|
|
29
|
+
*/
|
|
30
|
+
isConnected(): Promise<boolean>;
|
|
26
31
|
/**
|
|
27
32
|
* 通过adb连接模拟器。
|
|
28
33
|
* 时间限制为 @param timeout 秒,超时则表示连接失败
|
package/lib/instance/common.js
CHANGED
|
@@ -36,21 +36,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
};
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
38
|
const UxFileUtils_1 = __importDefault(require("@aiot-toolkit/aiotpack/lib/utils/ux/UxFileUtils"));
|
|
39
|
-
const
|
|
39
|
+
const shared_utils_1 = require("@aiot-toolkit/shared-utils");
|
|
40
40
|
const adbMiwt = __importStar(require("@miwt/adb"));
|
|
41
41
|
const child_process_1 = require("child_process");
|
|
42
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
42
43
|
const os_1 = __importDefault(require("os"));
|
|
43
44
|
const path_1 = __importDefault(require("path"));
|
|
44
45
|
const ws_1 = require("ws");
|
|
45
46
|
const avd_1 = __importDefault(require("../avd"));
|
|
46
47
|
const constants_1 = require("../static/constants");
|
|
47
48
|
const utils_1 = require("../utils");
|
|
48
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
49
49
|
/**
|
|
50
50
|
* CommonInstance
|
|
51
51
|
*/
|
|
52
52
|
class CommonInstance {
|
|
53
53
|
constructor(params) {
|
|
54
|
+
this.quickappStartedFlag = /__loadChunks/;
|
|
54
55
|
this.isFirstStart = true;
|
|
55
56
|
this.isDistributedApp = false;
|
|
56
57
|
this.projectPath = params.projectPath;
|
|
@@ -81,6 +82,19 @@ class CommonInstance {
|
|
|
81
82
|
start(options) {
|
|
82
83
|
return __awaiter(this, void 0, void 0, function* () { });
|
|
83
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* 判断模拟器是否 ready
|
|
87
|
+
*/
|
|
88
|
+
isConnected() {
|
|
89
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
90
|
+
return (0, utils_1.tryRun)(() => __awaiter(this, void 0, void 0, function* () {
|
|
91
|
+
const devices = yield adbMiwt.getAdbDevices();
|
|
92
|
+
shared_utils_1.ColorConsole.log(`### Emulator ### adb devices: ${JSON.stringify(devices)}`);
|
|
93
|
+
const curDev = devices.find((t) => t.sn === this.sn);
|
|
94
|
+
return (curDev === null || curDev === void 0 ? void 0 : curDev.status) === 'device';
|
|
95
|
+
}), 10, 500);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
84
98
|
/**
|
|
85
99
|
* 通过adb连接模拟器。
|
|
86
100
|
* 时间限制为 @param timeout 秒,超时则表示连接失败
|
|
@@ -95,14 +109,14 @@ class CommonInstance {
|
|
|
95
109
|
while (enableLoop && !adbConnected) {
|
|
96
110
|
if (needKill) {
|
|
97
111
|
const adbKillCmd = `adb kill-server`;
|
|
98
|
-
|
|
112
|
+
shared_utils_1.ColorConsole.log(`### Emulator ### Excuting adb cmd: ${adbKillCmd}`);
|
|
99
113
|
yield adbMiwt.execAdbCmdAsync(adbKillCmd);
|
|
100
114
|
}
|
|
101
115
|
const str = yield this.connectDevice();
|
|
102
|
-
|
|
116
|
+
shared_utils_1.ColorConsole.log(`### Emulator ### ${str}`);
|
|
103
117
|
// 查询模拟器的状态是否为“device”
|
|
104
118
|
const devices = yield adbMiwt.getAdbDevices();
|
|
105
|
-
|
|
119
|
+
shared_utils_1.ColorConsole.log(`### Emulator ### adb devices: ${JSON.stringify(devices)}`);
|
|
106
120
|
const curDev = devices.find((t) => t.sn === this.sn);
|
|
107
121
|
if ((curDev === null || curDev === void 0 ? void 0 : curDev.status) === 'offline')
|
|
108
122
|
needKill = true;
|
|
@@ -141,7 +155,7 @@ class CommonInstance {
|
|
|
141
155
|
}
|
|
142
156
|
}
|
|
143
157
|
catch (err) {
|
|
144
|
-
|
|
158
|
+
shared_utils_1.ColorConsole.log(`### Emulator ### kill process get error :\n${err.stack}`);
|
|
145
159
|
}
|
|
146
160
|
}
|
|
147
161
|
}
|
|
@@ -179,13 +193,13 @@ class CommonInstance {
|
|
|
179
193
|
port: (_a = this.startOptions) === null || _a === void 0 ? void 0 : _a.serverPort
|
|
180
194
|
});
|
|
181
195
|
wsServer.on('connection', (socket) => {
|
|
182
|
-
|
|
196
|
+
shared_utils_1.ColorConsole.success(`### App Socket server ### Websocket connects to websocket server`);
|
|
183
197
|
socket.on('error', (err) => {
|
|
184
|
-
|
|
198
|
+
shared_utils_1.ColorConsole.error(`### App Socket server ### Websocket server error: ${err.message}`);
|
|
185
199
|
});
|
|
186
200
|
socket.on('message', (data) => {
|
|
187
201
|
const message = JSON.parse(data.toString());
|
|
188
|
-
|
|
202
|
+
shared_utils_1.ColorConsole.log(`### App Socket server ### Websocket server get data: ${data}`);
|
|
189
203
|
if (message.type === 'restart') {
|
|
190
204
|
this.restart();
|
|
191
205
|
}
|
|
@@ -199,7 +213,7 @@ class CommonInstance {
|
|
|
199
213
|
connectDevice() {
|
|
200
214
|
return __awaiter(this, void 0, void 0, function* () {
|
|
201
215
|
const adbConnectCmd = `adb connect ${this.sn}`;
|
|
202
|
-
|
|
216
|
+
shared_utils_1.ColorConsole.log(`### Emulator ### Excuting adb cmd: ${adbConnectCmd}`);
|
|
203
217
|
let pending = true;
|
|
204
218
|
const p1 = adbMiwt.execAdbCmdAsync(adbConnectCmd);
|
|
205
219
|
let timer;
|
|
@@ -209,7 +223,7 @@ class CommonInstance {
|
|
|
209
223
|
timer = setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
|
210
224
|
if (pending) {
|
|
211
225
|
const adbKillCmd = `adb kill-server`;
|
|
212
|
-
|
|
226
|
+
shared_utils_1.ColorConsole.log(`### Emulator ### Excuting adb cmd: ${adbKillCmd}`);
|
|
213
227
|
yield adbMiwt.execAdbCmdAsync(adbKillCmd);
|
|
214
228
|
}
|
|
215
229
|
resolve();
|
package/lib/instance/dev.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { INewGoldfishInstanceParams, IStartOptions } from '../typing/Instance';
|
|
2
2
|
import CommonInstance from './common';
|
|
3
3
|
declare class GoldfishInstance extends CommonInstance {
|
|
4
|
-
|
|
4
|
+
appRunDir: string;
|
|
5
|
+
emulatorStartedFlag: string;
|
|
5
6
|
constructor(params: INewGoldfishInstanceParams);
|
|
6
7
|
/**
|
|
7
8
|
* 1. 启动模拟器
|
|
@@ -31,5 +32,14 @@ declare class GoldfishInstance extends CommonInstance {
|
|
|
31
32
|
* @param sourceRoot
|
|
32
33
|
*/
|
|
33
34
|
pushRpk(sourceRoot: string): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* 重新推送,然后重启应用
|
|
37
|
+
*/
|
|
38
|
+
pushAndReloadApp(): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* 重启应用
|
|
41
|
+
*/
|
|
42
|
+
reloadApp(): Promise<void>;
|
|
43
|
+
reboot(): Promise<boolean>;
|
|
34
44
|
}
|
|
35
45
|
export default GoldfishInstance;
|
package/lib/instance/dev.js
CHANGED
|
@@ -35,19 +35,19 @@ 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
|
|
38
|
+
const shared_utils_1 = require("@aiot-toolkit/shared-utils");
|
|
39
39
|
const adbMiwt = __importStar(require("@miwt/adb"));
|
|
40
40
|
const child_process_1 = require("child_process");
|
|
41
|
-
const path_1 = require("path");
|
|
42
|
-
const constants_1 = require("../static/constants");
|
|
43
|
-
const common_1 = __importDefault(require("./common"));
|
|
44
|
-
const os_1 = __importDefault(require("os"));
|
|
45
|
-
const fs_1 = __importDefault(require("fs"));
|
|
46
41
|
const dayjs_1 = __importDefault(require("dayjs"));
|
|
42
|
+
const fs_1 = __importDefault(require("fs"));
|
|
43
|
+
const os_1 = __importDefault(require("os"));
|
|
44
|
+
const path_1 = __importDefault(require("path"));
|
|
45
|
+
const common_1 = __importDefault(require("./common"));
|
|
47
46
|
class GoldfishInstance extends common_1.default {
|
|
48
47
|
constructor(params) {
|
|
49
48
|
super(params);
|
|
50
49
|
this.appRunDir = '/data/app';
|
|
50
|
+
this.emulatorStartedFlag = '(NSH)';
|
|
51
51
|
}
|
|
52
52
|
/**
|
|
53
53
|
* 1. 启动模拟器
|
|
@@ -57,12 +57,12 @@ class GoldfishInstance extends common_1.default {
|
|
|
57
57
|
start(options) {
|
|
58
58
|
return __awaiter(this, void 0, void 0, function* () {
|
|
59
59
|
this.startOptions = options;
|
|
60
|
-
this.sn = `
|
|
60
|
+
this.sn = `emulator-${this.startOptions.adbPort}`;
|
|
61
61
|
// 启动模拟器
|
|
62
62
|
yield this.startGoldfish(options);
|
|
63
|
-
const connected = yield this.
|
|
63
|
+
const connected = yield this.isConnected();
|
|
64
64
|
if (connected) {
|
|
65
|
-
|
|
65
|
+
shared_utils_1.ColorConsole.log('### Emulator ### Goldfish emulator connected successfully');
|
|
66
66
|
if (this.isFirstStart && this.startOptions.serverPort) {
|
|
67
67
|
yield this.createWebsockeServer();
|
|
68
68
|
}
|
|
@@ -72,8 +72,8 @@ class GoldfishInstance extends common_1.default {
|
|
|
72
72
|
? this.projectPath
|
|
73
73
|
: this.isDistributedApp
|
|
74
74
|
? options.dist ||
|
|
75
|
-
path_1.
|
|
76
|
-
: path_1.
|
|
75
|
+
path_1.default.join(this.projectPath, './build', `${this.projectInfo.package}.watch`)
|
|
76
|
+
: path_1.default.join(this.projectPath, './build');
|
|
77
77
|
yield this.pushRpk(buildedFilesPath);
|
|
78
78
|
// 在模拟器中启动快应用
|
|
79
79
|
this.startupQuickApp(options);
|
|
@@ -81,7 +81,7 @@ class GoldfishInstance extends common_1.default {
|
|
|
81
81
|
}
|
|
82
82
|
else {
|
|
83
83
|
const msg = '### Emulator ### Failed to connect emulator, please check whether the adb is normal';
|
|
84
|
-
|
|
84
|
+
shared_utils_1.ColorConsole.throw(msg);
|
|
85
85
|
throw new Error(msg);
|
|
86
86
|
}
|
|
87
87
|
});
|
|
@@ -95,16 +95,16 @@ class GoldfishInstance extends common_1.default {
|
|
|
95
95
|
return __awaiter(this, void 0, void 0, function* () {
|
|
96
96
|
try {
|
|
97
97
|
const { package: packageName } = this.projectInfo;
|
|
98
|
-
let vappCmd = `adb -s
|
|
98
|
+
let vappCmd = `adb -s ${this.sn} shell vapp app/${packageName} &`;
|
|
99
99
|
if (options.devtool) {
|
|
100
|
-
vappCmd = `adb -s
|
|
100
|
+
vappCmd = `adb -s ${this.sn} shell vapp --jsdebugger=10.0.2.15:101 app/${packageName} &`;
|
|
101
101
|
}
|
|
102
|
-
|
|
102
|
+
shared_utils_1.ColorConsole.log(`### Emulator ### Excuting adb cmd: ${vappCmd}`);
|
|
103
103
|
// vapp进程会一直pending,不会退出。这里必须加stdio: 'ignore',否则快应用无法运行成功
|
|
104
104
|
adbMiwt.execAdbCmdAsync(vappCmd, { stdio: 'ignore', encoding: 'utf-8' });
|
|
105
105
|
}
|
|
106
106
|
catch (e) {
|
|
107
|
-
|
|
107
|
+
shared_utils_1.ColorConsole.error(`### Emulator ### Failed to startup quickapp: ${e.message}`);
|
|
108
108
|
}
|
|
109
109
|
});
|
|
110
110
|
}
|
|
@@ -123,25 +123,25 @@ class GoldfishInstance extends common_1.default {
|
|
|
123
123
|
return __awaiter(this, void 0, void 0, function* () {
|
|
124
124
|
const { avdName, devtool, origin = 'terminal' } = options;
|
|
125
125
|
const emulatorBin = this.getEmulatorBinPath();
|
|
126
|
-
|
|
126
|
+
shared_utils_1.ColorConsole.log(`### Emulator ### emulator path: ${emulatorBin}`);
|
|
127
127
|
const avdInfo = this.velaAvdCls.getVelaAvdInfo(avdName);
|
|
128
|
-
const { avdArch, avdImagePath } = avdInfo;
|
|
129
|
-
|
|
128
|
+
const { avdArch, avdImagePath, customImagePath } = avdInfo;
|
|
129
|
+
shared_utils_1.ColorConsole.log(`### Emulator ### adb port: ${options.adbPort}`);
|
|
130
130
|
if (!avdImagePath) {
|
|
131
|
-
return
|
|
131
|
+
return shared_utils_1.ColorConsole.throw(`### Emulator ### Unable to find vela image via avd`);
|
|
132
132
|
}
|
|
133
|
-
const nuttxBinPath = path_1.
|
|
134
|
-
|
|
133
|
+
const nuttxBinPath = path_1.default.resolve(customImagePath || avdImagePath, 'nuttx');
|
|
134
|
+
shared_utils_1.ColorConsole.log(`### Emulator ### nuttx path: ${nuttxBinPath}`);
|
|
135
135
|
// 端口映射
|
|
136
|
-
let portMappingStr =
|
|
136
|
+
let portMappingStr = ``;
|
|
137
137
|
if (devtool) {
|
|
138
|
-
portMappingStr +=
|
|
138
|
+
portMappingStr += `-network-user-mode-options hostfwd=tcp:127.0.0.1:${options.debugPort}-10.0.2.15:101`;
|
|
139
139
|
}
|
|
140
140
|
// 文件系统配置,第一次使用fatfs镜像挂载,后续使用adb push更新应用
|
|
141
|
-
const systemImageBin = path_1.
|
|
142
|
-
const dataImageBin = path_1.
|
|
141
|
+
const systemImageBin = path_1.default.join(avdImagePath, 'system.img');
|
|
142
|
+
const dataImageBin = path_1.default.join(avdImagePath, 'data.img');
|
|
143
143
|
// 复制可写文件到AVD目录下(多模拟器实例时需要)
|
|
144
|
-
const dataImageBinInAvd = path_1.
|
|
144
|
+
const dataImageBinInAvd = path_1.default.join(this.avdHome, `${avdName}.avd`, 'data.img');
|
|
145
145
|
if (!fs_1.default.existsSync(dataImageBinInAvd)) {
|
|
146
146
|
// data.img不存在时直接copy
|
|
147
147
|
fs_1.default.copyFileSync(dataImageBin, dataImageBinInAvd);
|
|
@@ -155,7 +155,7 @@ class GoldfishInstance extends common_1.default {
|
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
// 复制可写文件到AVD目录下(多模拟器实例时需要)
|
|
158
|
-
const systemImageBinInAvd = path_1.
|
|
158
|
+
const systemImageBinInAvd = path_1.default.join(this.avdHome, `${avdName}.avd`, 'system.img');
|
|
159
159
|
if (!fs_1.default.existsSync(systemImageBinInAvd)) {
|
|
160
160
|
// data.img不存在时直接copy
|
|
161
161
|
fs_1.default.copyFileSync(systemImageBin, systemImageBinInAvd);
|
|
@@ -186,19 +186,18 @@ class GoldfishInstance extends common_1.default {
|
|
|
186
186
|
-drive index=1,id=userdata,if=none,format=raw,file=${dataImageBinInAvd} \
|
|
187
187
|
-device virtio-blk-device,bus=virtio-mmio-bus.1,drive=userdata \
|
|
188
188
|
-device virtio-snd,bus=virtio-mmio-bus.2 -allow-host-audio -semihosting`;
|
|
189
|
-
//
|
|
189
|
+
// grpc配置
|
|
190
190
|
let windowStr = '';
|
|
191
|
-
let
|
|
192
|
-
if ((_a = this.startOptions) === null || _a === void 0 ? void 0 : _a.
|
|
193
|
-
windowStr = '-
|
|
194
|
-
|
|
195
|
-
vncStr = `-vnc :${portSuffix}`;
|
|
191
|
+
let grpcStr = '';
|
|
192
|
+
if ((_a = this.startOptions) === null || _a === void 0 ? void 0 : _a.grpcPort) {
|
|
193
|
+
windowStr = '-qt-hide-window';
|
|
194
|
+
grpcStr = ` -idle-grpc-timeout 300 -grpc ${this.startOptions.grpcPort}`;
|
|
196
195
|
}
|
|
197
|
-
//
|
|
198
|
-
const cmd = `${emulatorBin} -nuttx -avd ${avdName} -avd-arch ${avdArch} -show-kernel -kernel ${nuttxBinPath} ${portMappingStr} ${windowStr}
|
|
196
|
+
// 启动模拟器的命令和参数
|
|
197
|
+
const cmd = `${emulatorBin} -nuttx -avd ${avdName} -port ${options.adbPort} -avd-arch ${avdArch} -show-kernel -kernel ${nuttxBinPath} ${portMappingStr} ${windowStr} ${grpcStr} -qemu ${imageMountStr}`;
|
|
199
198
|
const spawnArgs = cmd.split(' ');
|
|
200
199
|
const spawnBin = spawnArgs.shift();
|
|
201
|
-
|
|
200
|
+
shared_utils_1.ColorConsole.log(`### Emulator ### Start CMD: ${cmd}`);
|
|
202
201
|
return new Promise((resolve) => {
|
|
203
202
|
var _a, _b, _c;
|
|
204
203
|
this.goldfishProcess = (0, child_process_1.spawn)(spawnBin, spawnArgs, { stdio: 'pipe', shell: true });
|
|
@@ -211,7 +210,7 @@ class GoldfishInstance extends common_1.default {
|
|
|
211
210
|
(_b = this.goldfishProcess.stdout) === null || _b === void 0 ? void 0 : _b.pipe(process.stdout);
|
|
212
211
|
}
|
|
213
212
|
this.goldfishProcess.on('exit', (code) => {
|
|
214
|
-
|
|
213
|
+
shared_utils_1.ColorConsole.error(`### Emulator ### Goldfish emulator exited with code ${code}`);
|
|
215
214
|
if (options.exitCallback) {
|
|
216
215
|
options.exitCallback(code);
|
|
217
216
|
}
|
|
@@ -222,8 +221,8 @@ class GoldfishInstance extends common_1.default {
|
|
|
222
221
|
const stdoutCb = options.stdoutCallback || console.log;
|
|
223
222
|
stdoutCb(msg);
|
|
224
223
|
}
|
|
225
|
-
if (msg.includes(
|
|
226
|
-
|
|
224
|
+
if (msg.includes(this.emulatorStartedFlag)) {
|
|
225
|
+
shared_utils_1.ColorConsole.log(`### Emulator ### Goldfish emulator starts successfully`);
|
|
227
226
|
resolve();
|
|
228
227
|
}
|
|
229
228
|
});
|
|
@@ -236,10 +235,10 @@ class GoldfishInstance extends common_1.default {
|
|
|
236
235
|
*/
|
|
237
236
|
pushRpk(sourceRoot) {
|
|
238
237
|
return __awaiter(this, void 0, void 0, function* () {
|
|
239
|
-
const sn =
|
|
238
|
+
const sn = this.sn;
|
|
240
239
|
const { package: appPackageName } = this.projectInfo;
|
|
241
240
|
// 获取最后一层目录,比如build
|
|
242
|
-
const basename = path_1.
|
|
241
|
+
const basename = path_1.default.basename(sourceRoot);
|
|
243
242
|
if (os_1.default.platform() === 'win32' || this.projectPath.indexOf(' ') > 0) {
|
|
244
243
|
// windows系统或者项目路径有空格:1. adb push目录;2. 在模拟器中使用mv命令重命名
|
|
245
244
|
yield adbMiwt.execAdbCmdAsync(`adb -s ${sn} push ${sourceRoot} ${this.appRunDir}`);
|
|
@@ -247,11 +246,57 @@ class GoldfishInstance extends common_1.default {
|
|
|
247
246
|
}
|
|
248
247
|
else {
|
|
249
248
|
// 支持通配符处理: 1. 模拟器中mkdir创建目录 2. adb push ./XXXXX/* /XXX
|
|
250
|
-
const sourcePath = path_1.
|
|
251
|
-
|
|
252
|
-
|
|
249
|
+
const sourcePath = path_1.default.join(sourceRoot, './*');
|
|
250
|
+
const mkdirCmd = `adb -s ${sn} shell mkdir ${this.appRunDir}/${appPackageName}`;
|
|
251
|
+
shared_utils_1.ColorConsole.log(`### Emulator ### mkdir CMD: ${mkdirCmd}`);
|
|
252
|
+
yield adbMiwt.execAdbCmdAsync(mkdirCmd);
|
|
253
|
+
const pushCmd = `adb -s ${sn} push ${sourcePath} ${this.appRunDir}/${appPackageName}`;
|
|
254
|
+
shared_utils_1.ColorConsole.log(`### Emulator ### pushCmd CMD: ${pushCmd}`);
|
|
255
|
+
yield adbMiwt.execAdbCmdAsync(pushCmd);
|
|
253
256
|
}
|
|
254
|
-
|
|
257
|
+
shared_utils_1.ColorConsole.info(`### Emulator push to ${this.appRunDir}/${appPackageName} successfully`);
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* 重新推送,然后重启应用
|
|
262
|
+
*/
|
|
263
|
+
pushAndReloadApp() {
|
|
264
|
+
var _a;
|
|
265
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
266
|
+
try {
|
|
267
|
+
// 1. 将整包重新推到miwear中(TODO:增量更新)
|
|
268
|
+
// adb push快应用到模拟器的/data/app目录
|
|
269
|
+
// aspect应用后续要考虑各种形状表盘的推包
|
|
270
|
+
const buildedFilesPath = this.isRpk
|
|
271
|
+
? this.projectPath
|
|
272
|
+
: this.isDistributedApp
|
|
273
|
+
? ((_a = this.startOptions) === null || _a === void 0 ? void 0 : _a.dist) ||
|
|
274
|
+
path_1.default.join(this.projectPath, './build', `${this.projectInfo.package}.watch`)
|
|
275
|
+
: path_1.default.join(this.projectPath, './build');
|
|
276
|
+
yield this.pushRpk(buildedFilesPath);
|
|
277
|
+
this.reloadApp();
|
|
278
|
+
}
|
|
279
|
+
catch (e) {
|
|
280
|
+
shared_utils_1.ColorConsole.error(`${e}`);
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* 重启应用
|
|
286
|
+
*/
|
|
287
|
+
reloadApp() {
|
|
288
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
289
|
+
const { package: appPackageName } = this.projectInfo;
|
|
290
|
+
this.startupQuickApp(this.startOptions);
|
|
291
|
+
shared_utils_1.ColorConsole.info(`### Emulator start ${appPackageName} successfully`);
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
reboot() {
|
|
295
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
296
|
+
const rebootCmd = `adb -s ${this.sn} shell reboot`;
|
|
297
|
+
shared_utils_1.ColorConsole.log(`### Emulator ### Excuting adb cmd: ${rebootCmd}`);
|
|
298
|
+
yield adbMiwt.execAdbCmdAsync(rebootCmd);
|
|
299
|
+
return this.isConnected();
|
|
255
300
|
});
|
|
256
301
|
}
|
|
257
302
|
}
|
package/lib/instance/index.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { INewGoldfishInstanceParams } from '../typing/Instance';
|
|
2
2
|
import CommonInstance from './common';
|
|
3
3
|
import GoldfishInstance from './dev';
|
|
4
|
-
import MiwearInstance from
|
|
4
|
+
import MiwearInstance from './miwear';
|
|
5
5
|
import OldGoldfishInstance from './preDev';
|
|
6
|
+
import PreInstance from './pre';
|
|
6
7
|
/**
|
|
7
8
|
* 根据镜像决定使用哪个instance
|
|
8
9
|
* Vela正式版(4.0) -> MiwearInstance
|
|
10
|
+
* Vela正式版(不带 miwear 版本) -> PreInstance
|
|
9
11
|
* Vela开发版(dev, 0.0.2) -> OldGoldfishInstance
|
|
10
12
|
* Vela开发版(dev),除0.0.2的其他版本 -> GoldfishInstance
|
|
11
13
|
*/
|
|
12
14
|
declare function findInstance(avdName: string, params: INewGoldfishInstanceParams): GoldfishInstance | MiwearInstance | OldGoldfishInstance | undefined;
|
|
13
|
-
export { CommonInstance, GoldfishInstance, MiwearInstance, OldGoldfishInstance, findInstance };
|
|
15
|
+
export { CommonInstance, GoldfishInstance, MiwearInstance, OldGoldfishInstance, PreInstance, findInstance };
|
package/lib/instance/index.js
CHANGED
|
@@ -3,8 +3,8 @@ 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.findInstance = exports.OldGoldfishInstance = exports.MiwearInstance = exports.GoldfishInstance = exports.CommonInstance = void 0;
|
|
7
|
-
const
|
|
6
|
+
exports.findInstance = exports.PreInstance = exports.OldGoldfishInstance = exports.MiwearInstance = exports.GoldfishInstance = exports.CommonInstance = void 0;
|
|
7
|
+
const shared_utils_1 = require("@aiot-toolkit/shared-utils");
|
|
8
8
|
const avd_1 = __importDefault(require("../avd"));
|
|
9
9
|
const common_1 = __importDefault(require("./common"));
|
|
10
10
|
exports.CommonInstance = common_1.default;
|
|
@@ -14,9 +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
|
+
const pre_1 = __importDefault(require("./pre"));
|
|
18
|
+
exports.PreInstance = pre_1.default;
|
|
17
19
|
/**
|
|
18
20
|
* 根据镜像决定使用哪个instance
|
|
19
21
|
* Vela正式版(4.0) -> MiwearInstance
|
|
22
|
+
* Vela正式版(不带 miwear 版本) -> PreInstance
|
|
20
23
|
* Vela开发版(dev, 0.0.2) -> OldGoldfishInstance
|
|
21
24
|
* Vela开发版(dev),除0.0.2的其他版本 -> GoldfishInstance
|
|
22
25
|
*/
|
|
@@ -24,9 +27,12 @@ function findInstance(avdName, params) {
|
|
|
24
27
|
const { sdkHome, avdHome } = params;
|
|
25
28
|
const { avdImagePath } = new avd_1.default({ sdkHome, avdHome }).getVelaAvdInfo(avdName);
|
|
26
29
|
if (!avdImagePath) {
|
|
27
|
-
|
|
30
|
+
shared_utils_1.ColorConsole.throw(`### Emulator ### Unable to find vela image via avd`);
|
|
28
31
|
return;
|
|
29
32
|
}
|
|
33
|
+
if (avdImagePath.includes('vela-pre-4.0')) {
|
|
34
|
+
return new pre_1.default(params);
|
|
35
|
+
}
|
|
30
36
|
if (avdImagePath.includes('release')) {
|
|
31
37
|
return new miwear_1.default(params);
|
|
32
38
|
}
|
package/lib/instance/miwear.d.ts
CHANGED
|
@@ -6,9 +6,11 @@ import CommonInstance from './common';
|
|
|
6
6
|
*/
|
|
7
7
|
declare class MiwearInstance extends CommonInstance {
|
|
8
8
|
private params;
|
|
9
|
+
quickappStartedFlag: RegExp;
|
|
9
10
|
private appPathInEmulator;
|
|
10
11
|
private debugSocket?;
|
|
11
12
|
private reconnectCount;
|
|
13
|
+
emulatorStartedFlag: RegExp;
|
|
12
14
|
constructor(params: INewGoldfishInstanceParams);
|
|
13
15
|
/**
|
|
14
16
|
* 1. 启动模拟器
|
|
@@ -65,6 +67,7 @@ declare class MiwearInstance extends CommonInstance {
|
|
|
65
67
|
* 2. nsh中执行am stop命令退出快应用
|
|
66
68
|
* 3. nsh中执行am start命令启动快应用
|
|
67
69
|
*/
|
|
70
|
+
pushAndReloadApp(): Promise<void>;
|
|
68
71
|
reloadApp(): Promise<void>;
|
|
69
72
|
/**
|
|
70
73
|
* 创建server端,监听打包过程中client端发来的消息
|