@aiot-toolkit/emulator 2.0.1-alpha.8 → 2.0.2-beta.1

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,184 @@
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 adbMiwt = __importStar(require("@miwt/adb"));
40
+ const child_process_1 = require("child_process");
41
+ const path_1 = __importDefault(require("path"));
42
+ const portfinder_1 = __importDefault(require("portfinder"));
43
+ const constants_1 = require("../static/constants");
44
+ const common_1 = __importDefault(require("./common"));
45
+ class GoldfishInstance extends common_1.default {
46
+ constructor(params) {
47
+ super(params);
48
+ this.appRunDir = '/data/app';
49
+ }
50
+ /** 在goldfish模拟器中运行快应用 */
51
+ start(options) {
52
+ return __awaiter(this, void 0, void 0, function* () {
53
+ this.startOptions = options;
54
+ // 启动模拟器
55
+ yield this.startGoldfish(options);
56
+ const connected = yield this.connectGoldfish();
57
+ if (connected) {
58
+ ColorConsole_1.default.log('### Emulator ### Goldfish emulator connected successfully');
59
+ if (this.isFirstStart && this.startOptions.serverPort) {
60
+ yield this.createWebsockeServer();
61
+ }
62
+ // adb push快应用到模拟器的/data/app目录
63
+ const buildedFilesPath = this.isRpk ? this.projectPath : path_1.default.resolve(this.projectPath, './build');
64
+ yield this.pushRpk(buildedFilesPath);
65
+ // 在模拟器中启动快应用
66
+ this.startupQuickApp(options);
67
+ this.isFirstStart = false;
68
+ }
69
+ else {
70
+ ColorConsole_1.default.throw('### Emulator ### Failed to connect emulator, please check whether the adb is normal');
71
+ }
72
+ });
73
+ }
74
+ /** 在goldfish中启动快应用 */
75
+ startupQuickApp(options) {
76
+ return __awaiter(this, void 0, void 0, function* () {
77
+ try {
78
+ const { package: packageName } = this.projectInfo;
79
+ let vappCmd = `adb -s 127.0.0.1:${this.adbPort} shell vapp app/${packageName} &`;
80
+ if (options.devtool) {
81
+ vappCmd = `adb -s 127.0.0.1:${this.adbPort} shell vapp --jsdebugger=10.0.2.15:101 app/${packageName} &`;
82
+ }
83
+ ColorConsole_1.default.log(`### Emulator ### Excuting adb cmd: ${vappCmd}`);
84
+ // vapp进程会一直pending,不会退出。这里必须加stdio: 'ignore',否则快应用无法运行成功
85
+ adbMiwt.execAdbCmdAsync(vappCmd, { stdio: 'ignore', encoding: 'utf-8' });
86
+ }
87
+ catch (e) {
88
+ ColorConsole_1.default.error(`### Emulator ### Failed to startup quickapp: ${e.message}`);
89
+ }
90
+ });
91
+ }
92
+ /** 启动goldfish模拟器 */
93
+ startGoldfish(options) {
94
+ var _a;
95
+ return __awaiter(this, void 0, void 0, function* () {
96
+ const { avdName, devtool } = options;
97
+ const emulatorBin = this.getEmulatorBinPath();
98
+ ColorConsole_1.default.log(`### Emulator ### emulator path: ${emulatorBin}`);
99
+ const avdInfo = this.velaAvdCls.getVelaAvdInfo(avdName);
100
+ const { avdArch, avdImagePath } = avdInfo;
101
+ this.adbPort = yield portfinder_1.default.getPortPromise({ port: this.adbPort });
102
+ ColorConsole_1.default.log(`### Emulator ### adb port: ${this.adbPort}`);
103
+ if (!avdImagePath) {
104
+ return ColorConsole_1.default.throw(`### Emulator ### Unable to find vela image via avd`);
105
+ }
106
+ const nuttxBinPath = path_1.default.resolve(avdImagePath, 'nuttx');
107
+ ColorConsole_1.default.log(`### Emulator ### nuttx path: ${nuttxBinPath}`);
108
+ // 端口映射
109
+ let portMappingStr = `-network-user-mode-options hostfwd=tcp:127.0.0.1:${this.adbPort}-10.0.2.15:5555`;
110
+ if (devtool) {
111
+ portMappingStr += `,hostfwd=tcp:127.0.0.1:${this.debugPort}-10.0.2.15:101`;
112
+ }
113
+ // 文件系统配置,第一次使用fatfs镜像挂载,后续使用adb push更新应用
114
+ const systemImageBin = path_1.default.resolve(this.sdkHome, 'tools/image/system.img');
115
+ const dataImageBin = path_1.default.resolve(this.sdkHome, 'tools/image/data.img');
116
+ const imageMountStr = `-drive index=0,id=system,if=none,format=raw,file=${systemImageBin} \
117
+ -device virtio-blk-device,bus=virtio-mmio-bus.0,drive=system \
118
+ -drive index=1,id=userdata,if=none,format=raw,file=${dataImageBin} \
119
+ -device virtio-blk-device,bus=virtio-mmio-bus.1,drive=userdata \
120
+ -device virtio-snd,bus=virtio-mmio-bus.2 -allow-host-audio -semihosting`;
121
+ // vnc配置
122
+ let windowStr = '';
123
+ let vncStr = '';
124
+ if ((_a = this.startOptions) === null || _a === void 0 ? void 0 : _a.vncPort) {
125
+ windowStr = '-no-window';
126
+ const portSuffix = this.startOptions.vncPort - constants_1.defaultVncPort;
127
+ vncStr = `-vnc :${portSuffix}`;
128
+ }
129
+ const stdioType = options.disableNSH ? 'pipe' : 'inherit';
130
+ // 启动goldfish的命令和参数
131
+ const cmd = `${emulatorBin} -nuttx -avd ${avdName} -avd-arch ${avdArch} -show-kernel -kernel ${nuttxBinPath} ${portMappingStr} ${windowStr} -qemu ${vncStr} ${imageMountStr}`;
132
+ const spawnArgs = cmd.split(' ');
133
+ const spawnBin = spawnArgs.shift();
134
+ ColorConsole_1.default.log(`### Emulator ### Start CMD: ${cmd}`);
135
+ return new Promise((resolve) => {
136
+ var _a, _b;
137
+ this.goldfishProcess = (0, child_process_1.spawn)(spawnBin, spawnArgs, { stdio: stdioType, shell: true });
138
+ if (options.disableNSH) {
139
+ (_a = this.goldfishProcess.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
140
+ if (options.stdoutCallback) {
141
+ options.stdoutCallback(data);
142
+ }
143
+ else {
144
+ console.log(data.toString());
145
+ }
146
+ if (data.toString().includes('(NSH)')) {
147
+ ColorConsole_1.default.log(`### Emulator ### Goldfish emulator starts successfully`);
148
+ resolve();
149
+ }
150
+ });
151
+ (_b = this.goldfishProcess.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (data) => {
152
+ const stderrCb = options.stderrCallback || console.log;
153
+ stderrCb(data.toString());
154
+ });
155
+ }
156
+ else {
157
+ setTimeout(() => {
158
+ ColorConsole_1.default.log(`### Emulator ### Goldfish emulator starts successfully`);
159
+ resolve();
160
+ }, 2000);
161
+ }
162
+ this.goldfishProcess.on('exit', (code) => {
163
+ ColorConsole_1.default.error(`### Emulator ### Goldfish emulator exited with code ${code}`);
164
+ if (options.exitCallback) {
165
+ options.exitCallback(code);
166
+ }
167
+ });
168
+ });
169
+ });
170
+ }
171
+ /** 将打包后的文件推到挂载的快应用目录 */
172
+ pushRpk(sourceRoot) {
173
+ return __awaiter(this, void 0, void 0, function* () {
174
+ const sn = `127.0.0.1:${this.adbPort}`;
175
+ const { package: appPackageName } = this.projectInfo;
176
+ const sourcePath = path_1.default.resolve(sourceRoot, './*');
177
+ ColorConsole_1.default.log(`### Emulator ### Pushing ${appPackageName} to ${this.appRunDir}`);
178
+ yield adbMiwt.execAdbCmdAsync(`adb -s ${sn} shell mkdir ${this.appRunDir}/${appPackageName}`);
179
+ yield adbMiwt.execAdbCmdAsync(`adb -s ${sn} push ${sourcePath} ${this.appRunDir}/${appPackageName}`);
180
+ ColorConsole_1.default.log(`### Emulator ### Push ${appPackageName} to ${this.appRunDir} successfully`);
181
+ });
182
+ }
183
+ }
184
+ exports.default = GoldfishInstance;
@@ -0,0 +1,7 @@
1
+ import { INewGoldfishInstanceParams } from '../typing/Instance';
2
+ import CommonInstance from './common';
3
+ import GoldfishInstance from './dev';
4
+ import MiwearInstance from "./miwear";
5
+ import OldGoldfishInstance from './preDev';
6
+ declare function findInstance(avdName: string, params: INewGoldfishInstanceParams): GoldfishInstance | MiwearInstance | OldGoldfishInstance | undefined;
7
+ export { CommonInstance, GoldfishInstance, MiwearInstance, OldGoldfishInstance, findInstance };
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.findInstance = exports.OldGoldfishInstance = exports.MiwearInstance = exports.GoldfishInstance = exports.CommonInstance = void 0;
7
+ const ColorConsole_1 = __importDefault(require("@aiot-toolkit/shared-utils/lib/ColorConsole"));
8
+ const avd_1 = __importDefault(require("../avd"));
9
+ const common_1 = __importDefault(require("./common"));
10
+ exports.CommonInstance = common_1.default;
11
+ const dev_1 = __importDefault(require("./dev"));
12
+ exports.GoldfishInstance = dev_1.default;
13
+ const miwear_1 = __importDefault(require("./miwear"));
14
+ exports.MiwearInstance = miwear_1.default;
15
+ const preDev_1 = __importDefault(require("./preDev"));
16
+ exports.OldGoldfishInstance = preDev_1.default;
17
+ function findInstance(avdName, params) {
18
+ const { sdkHome, avdHome } = params;
19
+ const { avdImagePath } = new avd_1.default({ sdkHome, avdHome }).getVelaAvdInfo(avdName);
20
+ if (!avdImagePath) {
21
+ ColorConsole_1.default.throw(`### Emulator ### Unable to find vela image via avd`);
22
+ return;
23
+ }
24
+ if (avdImagePath.includes('release')) {
25
+ return new miwear_1.default(params);
26
+ }
27
+ else if (avdImagePath.match(/0\.0\.2|0\.0\.1/)) {
28
+ return new preDev_1.default(params);
29
+ }
30
+ return new dev_1.default(params);
31
+ }
32
+ exports.findInstance = findInstance;
@@ -0,0 +1,28 @@
1
+ import { INewGoldfishInstanceParams, IStartOptions } from '../typing/Instance';
2
+ import CommonInstance from './common';
3
+ /**
4
+ * MiwearInstance
5
+ * 针对 vela4.0 的镜像
6
+ */
7
+ declare class MiwearInstance extends CommonInstance {
8
+ private appPathInEmulator;
9
+ private debugSocket?;
10
+ private reconnectCount;
11
+ constructor(params: INewGoldfishInstanceParams);
12
+ /** 在goldfish模拟器中运行快应用 */
13
+ start(options: IStartOptions): Promise<void>;
14
+ /** 启动goldfish模拟器 */
15
+ startGoldfish(options: IStartOptions): Promise<void>;
16
+ /** 通过adb连接模拟器 */
17
+ connectGoldfish(): Promise<boolean>;
18
+ /** 在goldfish中启动快应用 */
19
+ startupQuickApp(options: IStartOptions): Promise<void>;
20
+ /** 将快应用安装到应用列表 */
21
+ installRpkToAppList(rpkPath: string, targetDir: string): Promise<void>;
22
+ initDebugSocket(): Promise<void> | undefined;
23
+ /** 通知模拟器更新 */
24
+ handleUpdate(): Promise<void>;
25
+ /** 创建server */
26
+ createWebsockeServer(): Promise<void>;
27
+ }
28
+ export default MiwearInstance;
@@ -0,0 +1,341 @@
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 JavascriptDefaultCompileOption_1 = __importDefault(require("@aiot-toolkit/aiotpack/lib/compiler/javascript/JavascriptDefaultCompileOption"));
39
+ const ColorConsole_1 = __importDefault(require("@aiot-toolkit/shared-utils/lib/ColorConsole"));
40
+ const adbMiwt = __importStar(require("@miwt/adb"));
41
+ const child_process_1 = require("child_process");
42
+ const fs_extra_1 = __importDefault(require("fs-extra"));
43
+ const os_1 = __importDefault(require("os"));
44
+ const path_1 = __importDefault(require("path"));
45
+ const portfinder_1 = __importDefault(require("portfinder"));
46
+ const ws_1 = __importStar(require("ws"));
47
+ const constants_1 = require("../static/constants");
48
+ const utils_1 = require("../utils");
49
+ const common_1 = __importDefault(require("./common"));
50
+ const MAX_RECONNECT_COUNT = 8;
51
+ /**
52
+ * MiwearInstance
53
+ * 针对 vela4.0 的镜像
54
+ */
55
+ class MiwearInstance extends common_1.default {
56
+ constructor(params) {
57
+ super(params);
58
+ this.appPathInEmulator = '/data/quickapp/app';
59
+ this.reconnectCount = 0;
60
+ }
61
+ /** 在goldfish模拟器中运行快应用 */
62
+ start(options) {
63
+ return __awaiter(this, void 0, void 0, function* () {
64
+ this.startOptions = options;
65
+ // 启动模拟器
66
+ yield this.startGoldfish(options);
67
+ // adb连接模拟器
68
+ const connected = yield this.connectGoldfish();
69
+ if (connected) {
70
+ ColorConsole_1.default.info('### Emulator ### Goldfish emulator connected successfully');
71
+ if (this.isFirstStart && this.startOptions.serverPort) {
72
+ yield this.createWebsockeServer();
73
+ }
74
+ this.startupQuickApp(options);
75
+ this.isFirstStart = false;
76
+ }
77
+ else {
78
+ ColorConsole_1.default.throw('### Emulator ### Failed to connect emulator, please check whether the adb is normal');
79
+ }
80
+ });
81
+ }
82
+ /** 启动goldfish模拟器 */
83
+ startGoldfish(options) {
84
+ var _a;
85
+ return __awaiter(this, void 0, void 0, function* () {
86
+ const { avdName, devtool } = options;
87
+ const emulatorBin = this.getEmulatorBinPath();
88
+ ColorConsole_1.default.log(`### Emulator ### emulator path: ${emulatorBin}`);
89
+ const avdInfo = this.velaAvdCls.getVelaAvdInfo(avdName);
90
+ const { avdArch, avdImagePath } = avdInfo;
91
+ this.adbPort = yield portfinder_1.default.getPortPromise({ port: this.adbPort });
92
+ ColorConsole_1.default.log(`### Emulator ### adb port: ${this.adbPort}`);
93
+ if (!avdImagePath) {
94
+ return ColorConsole_1.default.throw(`### Emulator ### Unable to find vela image via avd`);
95
+ }
96
+ const nuttxBinPath = path_1.default.resolve(avdImagePath, 'nuttx');
97
+ ColorConsole_1.default.log(`### Emulator ### nuttx path: ${nuttxBinPath}`);
98
+ // 端口映射
99
+ let portMappingStr = `-network-user-mode-options hostfwd=tcp:127.0.0.1:${this.adbPort}-10.0.2.15:5555`;
100
+ if (devtool) {
101
+ this.debugPort = yield portfinder_1.default.getPortPromise({ port: this.debugPort });
102
+ portMappingStr += `,hostfwd=tcp:127.0.0.1:${this.debugPort}-10.0.2.15:101`;
103
+ }
104
+ // 文件系统配置,第一次使用fatfs镜像挂载,后续使用adb push更新应用
105
+ const systemImageBin = path_1.default.resolve(avdImagePath, 'vela_resource.img');
106
+ const dataImageBin = path_1.default.resolve(avdImagePath, 'data.img');
107
+ const imageMountStr = `-drive index=0,id=system,if=none,format=raw,file=${systemImageBin} \
108
+ -device virtio-blk-device,bus=virtio-mmio-bus.0,drive=system \
109
+ -drive index=1,id=userdata,if=none,format=raw,file=${dataImageBin} \
110
+ -device virtio-blk-device,bus=virtio-mmio-bus.1,drive=userdata \
111
+ -device virtio-snd,bus=virtio-mmio-bus.2 -allow-host-audio -semihosting`;
112
+ // vnc配置
113
+ let windowStr = '';
114
+ let vncStr = '';
115
+ if ((_a = this.startOptions) === null || _a === void 0 ? void 0 : _a.vncPort) {
116
+ windowStr = '-no-window';
117
+ const portSuffix = this.startOptions.vncPort - constants_1.defaultVncPort;
118
+ vncStr = `-vnc :${portSuffix}`;
119
+ }
120
+ const stdioType = options.disableNSH ? 'pipe' : 'inherit';
121
+ // 启动goldfish的命令和参数
122
+ const cmd = `${emulatorBin} -nuttx -avd ${avdName} -avd-arch ${avdArch} -show-kernel -kernel ${nuttxBinPath} ${portMappingStr} ${windowStr} -qemu ${vncStr} ${imageMountStr}`;
123
+ const spawnArgs = cmd.split(' ');
124
+ const spawnBin = spawnArgs.shift();
125
+ ColorConsole_1.default.log(`### Emulator ### Start CMD: ${cmd}`);
126
+ return new Promise((resolve) => {
127
+ var _a, _b, _c;
128
+ this.goldfishProcess = (0, child_process_1.spawn)(spawnBin, spawnArgs, { stdio: stdioType, shell: true });
129
+ (_a = this.goldfishProcess.stderr) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
130
+ const stderrCb = options.stderrCallback || console.log;
131
+ stderrCb(data.toString());
132
+ });
133
+ this.goldfishProcess.on('exit', (code) => {
134
+ ColorConsole_1.default.error(`### Emulator ### Goldfish emulator exited with code ${code}`);
135
+ if (options.exitCallback) {
136
+ options.exitCallback(code);
137
+ }
138
+ });
139
+ if (options.disableNSH) {
140
+ (_c = (_b = this.goldfishProcess) === null || _b === void 0 ? void 0 : _b.stdout) === null || _c === void 0 ? void 0 : _c.on('data', (data) => {
141
+ const msg = data.toString();
142
+ const stdoutCb = options.stdoutCallback || console.log;
143
+ stdoutCb(msg);
144
+ if (msg.match(/quickapp_rpk_installer_init|rpk installer init done/)) {
145
+ ColorConsole_1.default.info(`### Emulator ### Goldfish emulator starts successfully`);
146
+ resolve();
147
+ }
148
+ });
149
+ }
150
+ else {
151
+ setTimeout(() => {
152
+ ColorConsole_1.default.info(`### Emulator ### Goldfish emulator starts successfully`);
153
+ resolve();
154
+ }, 8000);
155
+ ColorConsole_1.default.info(`### Emulator ### Goldfish emulator starts successfully`);
156
+ resolve();
157
+ }
158
+ });
159
+ });
160
+ }
161
+ /** 通过adb连接模拟器 */
162
+ connectGoldfish() {
163
+ return __awaiter(this, void 0, void 0, function* () {
164
+ let adbConnected = false;
165
+ const connectFn = () => __awaiter(this, void 0, void 0, function* () {
166
+ const sn = `127.0.0.1:${this.adbPort}`;
167
+ while (!adbConnected) {
168
+ const adbKillCmd = `adb kill-server`;
169
+ ColorConsole_1.default.log(`### Emulator ### Excuting adb cmd: ${adbKillCmd}`);
170
+ yield adbMiwt.execAdbCmdAsync(adbKillCmd);
171
+ const adbConnectCmd = `adb connect ${sn}`;
172
+ ColorConsole_1.default.log(`### Emulator ### Excuting adb cmd: ${adbConnectCmd}`);
173
+ const str = yield adbMiwt.execAdbCmdAsync(adbConnectCmd);
174
+ ColorConsole_1.default.log(`### Emulator ### ${str}`);
175
+ const devices = yield adbMiwt.getAdbDevices();
176
+ ColorConsole_1.default.log(`### Emulator ### adb devices: ${JSON.stringify(devices)}`);
177
+ adbConnected =
178
+ devices.filter((item) => item.sn === sn && item.status === 'device').length > 0;
179
+ }
180
+ Promise.resolve(adbConnected);
181
+ });
182
+ yield Promise.race([
183
+ connectFn(),
184
+ new Promise((resolve) => {
185
+ setTimeout(() => resolve(false), 600 * 1000);
186
+ })
187
+ ]);
188
+ return adbConnected;
189
+ });
190
+ }
191
+ /** 在goldfish中启动快应用 */
192
+ startupQuickApp(options) {
193
+ return __awaiter(this, void 0, void 0, function* () {
194
+ const { package: appPackageName } = this.projectInfo;
195
+ const releaseDir = path_1.default.resolve(this.projectPath, JavascriptDefaultCompileOption_1.default.releasePath || 'dist');
196
+ const files = fs_extra_1.default
197
+ .readdirSync(releaseDir)
198
+ .filter(item => item.includes(appPackageName) && item.endsWith('.rpk'));
199
+ if (files.length < 0) {
200
+ ColorConsole_1.default.error(`### Emulator the rpk does not exist`);
201
+ }
202
+ const rpkPath = path_1.default.resolve(releaseDir, files[0]);
203
+ // 调试模式需要push一个文件至miwear中
204
+ const sn = `127.0.0.1:${this.adbPort}`;
205
+ if (options.devtool) {
206
+ const debuggerCfgFile = path_1.default.join(__dirname, '../static/debugger_ip.cfg');
207
+ yield adbMiwt.execAdbCmdAsync(`adb -s ${sn} push ${debuggerCfgFile} /data/debugger_ip.cfg`);
208
+ }
209
+ else {
210
+ adbMiwt.execAdbCmdAsync(`adb -s ${sn} shell rm /data/debugger_ip.cfg`);
211
+ }
212
+ this.installRpkToAppList(rpkPath, this.appPathInEmulator);
213
+ });
214
+ }
215
+ /** 将快应用安装到应用列表 */
216
+ installRpkToAppList(rpkPath, targetDir) {
217
+ return __awaiter(this, void 0, void 0, function* () {
218
+ try {
219
+ const sn = `127.0.0.1:${this.adbPort}`;
220
+ const { package: packageName } = this.projectInfo;
221
+ const rpkName = path_1.default.basename(rpkPath);
222
+ // 1. 查询应用是否已经安装,如果安装了,则先卸载
223
+ const lsCmd = `adb -s ${sn} shell ls ${this.appPathInEmulator}`;
224
+ const res = yield adbMiwt.execAdbCmdAsync(lsCmd);
225
+ if (res.includes(packageName)) {
226
+ const uninstallCmd = `adb -s ${sn} shell pm uninstall ${packageName}`;
227
+ ColorConsole_1.default.info(`### Emulator ### Excuting cmd: ${uninstallCmd}`);
228
+ adbMiwt.execAdbCmdAsync(uninstallCmd);
229
+ // 这里等待2s的作用是等qemu执行完uninstall操作的一系列工作
230
+ yield (0, utils_1.sleep)(2000);
231
+ }
232
+ // 2. adb push应用的rpk
233
+ const targetPath = `${targetDir}/${packageName}.rpk`;
234
+ const pushCmd = `adb -s ${sn} push ${rpkPath} ${targetPath}`;
235
+ ColorConsole_1.default.info(`### Emulator ### Excuting cmd: ${pushCmd}`);
236
+ yield adbMiwt.execAdbCmdAsync(pushCmd);
237
+ yield (0, utils_1.sleep)(100);
238
+ // 3. 安装应用
239
+ const installCmd = `adb -s ${sn} shell pm install ${targetPath}`;
240
+ ColorConsole_1.default.info(`### Emulator ### Excuting cmd: ${installCmd}`);
241
+ adbMiwt.execAdbCmdAsync(installCmd);
242
+ }
243
+ catch (e) { }
244
+ });
245
+ }
246
+ initDebugSocket() {
247
+ if (this.debugSocket && this.debugSocket.OPEN) {
248
+ return Promise.resolve();
249
+ }
250
+ this.debugSocket = new ws_1.default(`ws://localhost:${this.debugPort}`);
251
+ this.debugSocket.onopen = () => {
252
+ ColorConsole_1.default.info(`### Emulator debugSocket connect success`);
253
+ return Promise.resolve();
254
+ };
255
+ this.debugSocket.onerror = (e) => {
256
+ var _a;
257
+ // 重连机制
258
+ (_a = this.debugSocket) === null || _a === void 0 ? void 0 : _a.terminate();
259
+ if (this.reconnectCount < MAX_RECONNECT_COUNT) {
260
+ ColorConsole_1.default.info(`### Emulator the ${this.reconnectCount + 1}th time to reconnect debug server`);
261
+ this.reconnectCount++;
262
+ setTimeout(() => this.initDebugSocket(), 2000);
263
+ }
264
+ else {
265
+ this.debugSocket = undefined;
266
+ this.reconnectCount = 0;
267
+ return Promise.reject(`### Emulator debugSocket connect failed`);
268
+ }
269
+ };
270
+ this.debugSocket.onclose = (e) => {
271
+ this.debugSocket = undefined;
272
+ this.reconnectCount = 0;
273
+ ColorConsole_1.default.log(`### Emulator debugSocket connect close: ${e.data}`);
274
+ };
275
+ }
276
+ /** 通知模拟器更新 */
277
+ handleUpdate() {
278
+ var _a, _b;
279
+ return __awaiter(this, void 0, void 0, function* () {
280
+ try {
281
+ this.reconnectCount = 0;
282
+ yield this.initDebugSocket();
283
+ // 1. 将整包重新推到miwear中(TODO:增量更新)
284
+ const sn = `127.0.0.1:${this.adbPort}`;
285
+ const { package: appPackageName } = this.projectInfo;
286
+ // windows平台adb push时无法使用通配符,需另外处理
287
+ if (os_1.default.platform() === 'win32') {
288
+ const rmCmd = `adb -s ${sn} shell rm -r ${this.appPathInEmulator}/${appPackageName}`;
289
+ yield adbMiwt.execAdbCmdAsync(rmCmd);
290
+ const sourcePath = path_1.default.resolve(this.projectPath, './build');
291
+ const pushCmd = `adb -s ${sn} push ${sourcePath} ${this.appPathInEmulator}/${appPackageName}`;
292
+ yield adbMiwt.execAdbCmdAsync(pushCmd);
293
+ }
294
+ else {
295
+ const sourcePath = path_1.default.resolve(this.projectPath, './build/*');
296
+ yield adbMiwt.execAdbCmdAsync(`adb -s ${sn} push ${sourcePath} ${this.appPathInEmulator}/${appPackageName}`);
297
+ }
298
+ ColorConsole_1.default.info(`### Emulator push to ${this.appPathInEmulator}/${appPackageName} successfully`);
299
+ // 2. 下发CDP命令给调试服务告知刷新
300
+ if (((_a = this.debugSocket) === null || _a === void 0 ? void 0 : _a.readyState) === ws_1.default.OPEN) {
301
+ (_b = this.debugSocket) === null || _b === void 0 ? void 0 : _b.send(JSON.stringify({ id: 10000, method: 'Page.reload', params: {} }));
302
+ }
303
+ }
304
+ catch (e) {
305
+ ColorConsole_1.default.error(`${e}`);
306
+ }
307
+ });
308
+ }
309
+ /** 创建server */
310
+ createWebsockeServer() {
311
+ var _a;
312
+ return __awaiter(this, void 0, void 0, function* () {
313
+ const wsServer = new ws_1.WebSocketServer({
314
+ port: (_a = this.startOptions) === null || _a === void 0 ? void 0 : _a.serverPort,
315
+ });
316
+ wsServer.on('connection', socket => {
317
+ ColorConsole_1.default.success(`### App Socket server ### Websocket connects to websocket server`);
318
+ socket.on('error', err => {
319
+ ColorConsole_1.default.error(`### App Socket server ### Websocket server error: ${err.message}`);
320
+ });
321
+ socket.on('message', (data) => __awaiter(this, void 0, void 0, function* () {
322
+ var _a;
323
+ const message = JSON.parse(data.toString());
324
+ ColorConsole_1.default.log(`### App Socket server ### Websocket server get data: ${data}`);
325
+ if (message.type === 'restart') {
326
+ // 非调试模式下无法热更新
327
+ if (!((_a = this.startOptions) === null || _a === void 0 ? void 0 : _a.devtool)) {
328
+ this.restart();
329
+ return;
330
+ }
331
+ this.handleUpdate();
332
+ }
333
+ else if (message.type === 'stop') {
334
+ this.stop();
335
+ }
336
+ }));
337
+ });
338
+ });
339
+ }
340
+ }
341
+ exports.default = MiwearInstance;
@@ -0,0 +1,23 @@
1
+ /// <reference types="node" />
2
+ import { ChildProcess } from 'child_process';
3
+ import { INewGoldfishInstanceParams, IStartOptions } from '../typing/Instance';
4
+ import CommonInstance from './common';
5
+ declare class OldGoldfishInstance extends CommonInstance {
6
+ private host9pPort;
7
+ v9fsProcess: ChildProcess | undefined;
8
+ constructor(params: INewGoldfishInstanceParams);
9
+ /** 在goldfish模拟器中运行快应用 */
10
+ start(options: IStartOptions): Promise<void>;
11
+ /** 在goldfish中启动快应用 */
12
+ startupQuickApp(options: IStartOptions): void;
13
+ /** host启动9pServer */
14
+ ensure9pServerRunnning(): Promise<void>;
15
+ /** 启动goldfish模拟器 */
16
+ startGoldfish(options: IStartOptions): Promise<void>;
17
+ /** 通过adb连接模拟器 */
18
+ connectGoldfish(): Promise<boolean>;
19
+ pushRpk(sourceRoot: string): Promise<void>;
20
+ /** 停止模拟器并释放相关资源 */
21
+ stop(): Promise<void>;
22
+ }
23
+ export default OldGoldfishInstance;