@aiot-toolkit/emulator 2.0.5-beta.22 → 2.0.5-beta.23

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.
@@ -57,14 +57,14 @@ const VelaImageVersionList = exports.VelaImageVersionList = [{
57
57
  label: 'vela-miwear-watch-5.0',
58
58
  description: '适用于手表/手环的,带表盘的 vela 5.0 镜像,不可自定义模拟器尺寸',
59
59
  value: _Vvd.VelaImageType.VELA_MIWEAR_WATCH_5,
60
- time: '20250619',
60
+ time: '20250626',
61
61
  hide: false,
62
62
  icon: ''
63
63
  }, {
64
64
  label: 'vela-watch-5.0',
65
65
  description: '适用于手表/手环的,不带表盘的 vela 5.0 镜像,可自定义模拟器尺寸',
66
66
  value: _Vvd.VelaImageType.VELA_WATCH_5,
67
- time: '20250619',
67
+ time: '20250626',
68
68
  hide: false,
69
69
  icon: ''
70
70
  }, {
package/lib/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { VvdManager } from './vvd';
2
- import { getSystemArch, tryRun } from './utils';
2
+ export { getSystemArch, tryRun } from './utils';
3
3
  export * from './instance';
4
4
  export * from './typing/Vvd';
5
5
  export * from './typing/Instance';
6
6
  export * from './emulatorutil';
7
- export { getSystemArch, tryRun };
7
+ export * from './shared';
package/lib/index.js CHANGED
@@ -75,4 +75,16 @@ Object.keys(_emulatorutil).forEach(function (key) {
75
75
  return _emulatorutil[key];
76
76
  }
77
77
  });
78
+ });
79
+ var _shared = require("./shared");
80
+ Object.keys(_shared).forEach(function (key) {
81
+ if (key === "default" || key === "__esModule") return;
82
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
83
+ if (key in exports && exports[key] === _shared[key]) return;
84
+ Object.defineProperty(exports, key, {
85
+ enumerable: true,
86
+ get: function () {
87
+ return _shared[key];
88
+ }
89
+ });
78
90
  });
@@ -10,7 +10,7 @@ declare abstract class CommonEmulatorInstance {
10
10
  static appInstallFailedFlag: RegExp;
11
11
  static appUninstalledFlag: RegExp;
12
12
  static appStartedFlag: RegExp;
13
- static isAppInstalled(log: string): boolean;
13
+ static isAppInstalled(...args: any[]): boolean;
14
14
  static isAppInstallFailed(log: string): boolean;
15
15
  static isAppUninstalled(log: string, packageName: string): boolean;
16
16
  static isEmulatorStarted(log: string): boolean;
@@ -11,6 +11,7 @@ var adbMiwt = _adb;
11
11
  var _utils = require("../utils");
12
12
  var _logcat = require("../vvd/logcat");
13
13
  var _emulatorutil = require("../emulatorutil");
14
+ var _shared = require("../shared");
14
15
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
15
16
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
16
17
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -21,14 +22,15 @@ class CommonEmulatorInstance {
21
22
  static appInstallFailedFlag = /uv_mq_read_cb: install prepare failed/;
22
23
  static appUninstalledFlag = /uninstalled app/;
23
24
  static appStartedFlag = /Start App loop/;
24
- static isAppInstalled(log) {
25
+ static isAppInstalled() {
26
+ const log = arguments.length <= 0 ? undefined : arguments[0];
25
27
  return this.appInstalledFlag.test(log);
26
28
  }
27
29
  static isAppInstallFailed(log) {
28
30
  return this.appInstallFailedFlag.test(log);
29
31
  }
30
32
  static isAppUninstalled(log, packageName) {
31
- return new RegExp(this.appUninstalledFlag + ':\\s+' + packageName).test(log);
33
+ return new RegExp(this.appUninstalledFlag.source + ':\\s+' + packageName).test(log);
32
34
  }
33
35
  static isEmulatorStarted(log) {
34
36
  return this.emulatorStartedFlag.test(log);
@@ -117,7 +119,22 @@ class CommonEmulatorInstance {
117
119
  }
118
120
  async pushAndInstall(rpkPath, appName) {
119
121
  const targetPath = await this.pushRpk(rpkPath, appName);
120
- await this.install(targetPath, appName);
122
+ try {
123
+ await this.install(targetPath, appName);
124
+ } catch (error) {
125
+ let timer;
126
+ if (error === _shared.RpkInstallFailedReason.Busy) {
127
+ this.logger('install process is busy, 3s later retry');
128
+ await new Promise((resolve, rejcet) => {
129
+ timer = setTimeout(() => {
130
+ this.pushAndInstall(rpkPath, appName).then(resolve).catch(rejcet);
131
+ }, 5000);
132
+ });
133
+ } else {
134
+ clearTimeout(timer);
135
+ throw error;
136
+ }
137
+ }
121
138
  }
122
139
 
123
140
  /** 关闭模拟器 */
@@ -9,6 +9,7 @@ declare class MiwearInstance extends CommonEmulatorInstance {
9
9
  static appInstalledFlag: RegExp;
10
10
  imageType: VelaImageType;
11
11
  appDir: string;
12
+ static isAppInstalled(log: string, targetRpk: string): boolean;
12
13
  /**
13
14
  * 使用 pm 安装快应用
14
15
  * @param targeRpk 快应用的rpk文件路径
@@ -9,6 +9,7 @@ var _path = _interopRequireDefault(require("path"));
9
9
  var _utils = require("../utils");
10
10
  var _common = _interopRequireDefault(require("./common"));
11
11
  var _Vvd = require("../typing/Vvd");
12
+ var _shared = require("../shared");
12
13
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
14
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
14
15
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
@@ -21,7 +22,12 @@ class MiwearInstance extends _common.default {
21
22
  static appInstalledFlag = /InstallState_Finished|install finished/;
22
23
  imageType = (() => _Vvd.VelaImageType.REL)();
23
24
  appDir = '/data/quickapp/app';
24
-
25
+ static isAppInstalled(log, targetRpk) {
26
+ // 注意:targetRpk 可能包含特殊字符,需要转义
27
+ const escapedRpk = targetRpk.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
28
+ const reg = new RegExp(`executeInstall: rpk install: ${escapedRpk} .* success`);
29
+ return reg.test(log);
30
+ }
25
31
  /**
26
32
  * 使用 pm 安装快应用
27
33
  * @param targeRpk 快应用的rpk文件路径
@@ -31,30 +37,40 @@ class MiwearInstance extends _common.default {
31
37
  this.logger(`Excuting: ${installCmd}`);
32
38
  adbMiwt.execAdbCmd(installCmd);
33
39
  return new Promise((resolve, reject) => {
40
+ const clearFn = () => {
41
+ clearTimeout(timer);
42
+ this.stdoutReadline.off('line', func);
43
+ };
34
44
  const func = msg => {
35
- if (MiwearInstance.isAppInstalled(msg)) {
36
- clearTimeout(timer);
45
+ if (MiwearInstance.isAppInstalled(msg, targeRpk)) {
37
46
  this.logger(`Install to ${this.vvdName} ${targeRpk} successfully`);
38
- this.stdoutReadline.off('line', func);
47
+ clearFn();
39
48
  resolve();
40
49
  }
41
50
  if (MiwearInstance.isAppInstallFailed(msg)) {
42
- clearTimeout(timer);
43
- this.stdoutReadline.off('line', func);
44
51
  this.logger(`Failed Install to ${this.vvdName} ${targeRpk}`);
45
- reject(msg);
52
+ this.logger(_shared.RpkInstallFailedReason.LowStorage);
53
+ clearFn();
54
+ reject(_shared.RpkInstallFailedReason.LowStorage);
55
+ }
56
+
57
+ // 当前安装进程被占用
58
+ if (msg.includes('installRpk: installation is running, please wait')) {
59
+ this.logger(_shared.RpkInstallFailedReason.Busy);
60
+ clearFn();
61
+ reject(_shared.RpkInstallFailedReason.Busy);
46
62
  }
47
63
  };
48
64
  let timer = setTimeout(() => {
49
65
  this.stdoutReadline.off('line', func);
50
66
  this.logger(`Install to ${this.vvdName} ${targeRpk} timeout`);
51
- reject('Install timeout');
52
- }, 2 * 60 * 1000);
67
+ reject(_shared.RpkInstallFailedReason.Timeout);
68
+ }, 1 * 60 * 1000);
53
69
  this.stdoutReadline.on('line', func);
54
70
  this.stdoutReadline.on('close', () => {
55
- this.stdoutReadline.removeAllListeners();
71
+ this.stdoutReadline.off('line', func);
56
72
  clearTimeout(timer);
57
- reject('Device poweroff');
73
+ reject(_shared.RpkInstallFailedReason.Poweroff);
58
74
  });
59
75
  });
60
76
  }
@@ -98,9 +114,9 @@ class MiwearInstance extends _common.default {
98
114
  }
99
115
  async closeApp(appName) {
100
116
  const stopCmd = `adb -s ${this.sn} shell am stop ${appName}`;
117
+ this.logger(`Excuting: ${stopCmd}`);
101
118
  await adbMiwt.execAdbCmdAsync(stopCmd);
102
119
  this.logger(`Stop ${this.vvdName} ${appName} successfully`);
103
- // 这里是为了等am stop命令清除资源等
104
120
  }
105
121
  async reboot() {
106
122
  await super.reboot();
@@ -3,5 +3,4 @@ import MiwearInstance from './miwear';
3
3
  export declare class VelaMiwear5 extends MiwearInstance {
4
4
  imageType: VelaImageType;
5
5
  appDir: string;
6
- static emulatorStartedFlag: RegExp;
7
6
  }
@@ -10,6 +10,5 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
10
10
  class VelaMiwear5 extends _miwear.default {
11
11
  imageType = (() => _Vvd.VelaImageType.VELA_MIWEAR_WATCH_5)();
12
12
  appDir = '/data/app';
13
- static emulatorStartedFlag = /\[App Active Flag/;
14
13
  }
15
14
  exports.VelaMiwear5 = VelaMiwear5;
@@ -10,4 +10,9 @@ export declare class Vela5Instance extends MiwearInstance {
10
10
  * @param targeRpk 快应用的rpk文件路径
11
11
  */
12
12
  install(targeRpk: string): Promise<void>;
13
+ /** 使用 am start 启动快应用 */
14
+ startApp(packageName: string): Promise<void>;
15
+ /** 重启模拟器 */
16
+ reboot(): Promise<void>;
17
+ closeApp(appName: string): Promise<void>;
13
18
  }
@@ -4,7 +4,9 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.Vela5Instance = void 0;
7
+ var _shared = require("../shared");
7
8
  var _Vvd = require("../typing/Vvd");
9
+ var _logcat = require("../vvd/logcat");
8
10
  var _miwear = _interopRequireDefault(require("./miwear"));
9
11
  var adbMiwt = _interopRequireWildcard(require("@miwt/adb"));
10
12
  var _util = require("util");
@@ -35,5 +37,62 @@ class Vela5Instance extends _miwear.default {
35
37
  return Promise.reject(res);
36
38
  }
37
39
  }
40
+
41
+ /** 使用 am start 启动快应用 */
42
+ async startApp(packageName) {
43
+ const startCmd = `adb -s ${this.sn} shell am start ${packageName}`;
44
+ this.logger(`Excuting: ${startCmd}`);
45
+ adbMiwt.execAdbCmdAsync(startCmd);
46
+ return new Promise((resolve, reject) => {
47
+ const clearFn = () => {
48
+ clearTimeout(timer);
49
+ this.stdoutReadline.off('line', func);
50
+ };
51
+ const func = msg => {
52
+ if (Vela5Instance.appStartedFlag.test(msg)) {
53
+ this.logger(`Start ${packageName} for ${this.vvdName} successfully`);
54
+ clearFn();
55
+ resolve();
56
+ }
57
+ const escapedPackageName = packageName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
58
+ const reg = new RegExp(`Failed to open: .+?/${escapedPackageName}/manifest\.json`);
59
+ if (reg.test(msg)) {
60
+ this.logger(`Failed Start ${packageName} for ${this.vvdName}`);
61
+ clearFn();
62
+ reject(_shared.RpkStartFailedReason.getManifestFailed);
63
+ }
64
+ };
65
+ let timer = setTimeout(() => {
66
+ this.stdoutReadline.off('line', func);
67
+ this.logger(`Start ${packageName} for ${this.vvdName} timeout`);
68
+ reject('Timeout');
69
+ }, 8 * 1000);
70
+ this.stdoutReadline.on('line', func);
71
+ });
72
+ }
73
+
74
+ /** 重启模拟器 */
75
+ async reboot() {
76
+ const rebootCmd = `adb -s ${this.sn} shell reboot`;
77
+ this.logger(`Excuting: ${rebootCmd}`);
78
+ await adbMiwt.execAdbCmdAsync(rebootCmd);
79
+ await this.isConnected();
80
+ if (this.logcatProcess.exitCode !== null) {
81
+ // 如果 logcat 进程被杀死,则重新创建
82
+ const r = (0, _logcat.creatLogcat)(this.sn, this.onStdout, this.onErrout);
83
+ this.logcatProcess = r.logcatProcess;
84
+ this.stdoutReadline = r.stdoutReadline;
85
+ this.stderrReadline = r.stderrReadline;
86
+ this.disposeReadlines = r.dispose;
87
+ }
88
+ }
89
+ async closeApp(appName) {
90
+ await super.closeApp(appName);
91
+ await new Promise(resolve => {
92
+ setTimeout(() => {
93
+ resolve();
94
+ }, 2000);
95
+ });
96
+ }
38
97
  }
39
98
  exports.Vela5Instance = Vela5Instance;
@@ -6,3 +6,12 @@ import { VelaImageType } from '../typing/Vvd';
6
6
  export declare function isVelaImageType(value: any): value is VelaImageType;
7
7
  export declare function isMiwearImageType(val: VelaImageType): boolean;
8
8
  export declare function getDefaultImage(): VelaImageType;
9
+ export declare enum RpkStartFailedReason {
10
+ getManifestFailed = "Get app manifest.json failed"
11
+ }
12
+ export declare enum RpkInstallFailedReason {
13
+ Busy = "Installation process is busy",
14
+ Timeout = "Install timeout",
15
+ Poweroff = "Device poweroff",
16
+ LowStorage = "Application exceeds maximum quantity or remaining space is low"
17
+ }
@@ -3,6 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ exports.RpkStartFailedReason = exports.RpkInstallFailedReason = void 0;
6
7
  exports.getDefaultImage = getDefaultImage;
7
8
  exports.isMiwearImageType = isMiwearImageType;
8
9
  exports.isVelaImageType = isVelaImageType;
@@ -20,4 +21,15 @@ function isMiwearImageType(val) {
20
21
  }
21
22
  function getDefaultImage() {
22
23
  return _Vvd.VelaImageType.VELA_MIWEAR_WATCH_5;
23
- }
24
+ }
25
+ let RpkStartFailedReason = exports.RpkStartFailedReason = /*#__PURE__*/function (RpkStartFailedReason) {
26
+ RpkStartFailedReason["getManifestFailed"] = "Get app manifest.json failed";
27
+ return RpkStartFailedReason;
28
+ }({});
29
+ let RpkInstallFailedReason = exports.RpkInstallFailedReason = /*#__PURE__*/function (RpkInstallFailedReason) {
30
+ RpkInstallFailedReason["Busy"] = "Installation process is busy";
31
+ RpkInstallFailedReason["Timeout"] = "Install timeout";
32
+ RpkInstallFailedReason["Poweroff"] = "Device poweroff";
33
+ RpkInstallFailedReason["LowStorage"] = "Application exceeds maximum quantity or remaining space is low";
34
+ return RpkInstallFailedReason;
35
+ }({});
package/lib/vvd/index.js CHANGED
@@ -394,12 +394,14 @@ class VvdManager {
394
394
  } else continue;
395
395
  if (!_fs.default.existsSync(pOfVvd)) {
396
396
  // 文件不存在则直接复制
397
+ _ColorConsole.default.log(`${file} not found, copy from ${pOfImageDir}`);
397
398
  _fs.default.copyFileSync(pOfImageDir, pOfVvd);
398
399
  } else {
399
400
  // 文件存在但过时
400
401
  const statsInAvd = _fs.default.statSync(pOfVvd);
401
402
  const stats = _fs.default.statSync(pOfImageDir);
402
403
  if ((0, _dayjs.default)(stats.mtime).isAfter(statsInAvd.mtime)) {
404
+ _ColorConsole.default.log(`${file} file is outdate, update from ${pOfImageDir}`);
403
405
  _fs.default.copyFileSync(pOfImageDir, pOfVvd);
404
406
  }
405
407
  }
@@ -745,6 +747,10 @@ class VvdManager {
745
747
  zip.extractAllTo(targetDir, true, true);
746
748
  await _fs.default.promises.rm(zipFile, {
747
749
  force: true
750
+ }).catch(e => {
751
+ _ColorConsole.default.info(`remove ${zipFile} failed: ${e}`);
752
+ // my be failed on windows as resource busy or locked, don't care
753
+ return Promise.resolve();
748
754
  });
749
755
  }
750
756
  const verFile = this.getSDKVersionPath();
@@ -774,6 +780,10 @@ class VvdManager {
774
780
  zip.extractAllTo(_path.default.resolve(this.sdkHome, _Vvd.SDKParts.SYSTEM_IMAGES, imageId), true, true);
775
781
  await _fs.default.promises.rm(zipFile, {
776
782
  force: true
783
+ }).catch(e => {
784
+ _ColorConsole.default.info(`remove ${zipFile} failed: ${e}`);
785
+ // my be failed on windows as resource busy or locked, don't care
786
+ return Promise.resolve();
777
787
  });
778
788
  });
779
789
  return Object.assign(downloader, {
package/lib/vvd/logcat.js CHANGED
@@ -27,7 +27,7 @@ function attachReadline(p, onStdout, onErrout) {
27
27
  let stderrReadline;
28
28
 
29
29
  // 利用 readline 接口可解决子进程日志换行的问题
30
- if (p.stdout) {
30
+ if (p?.stdout) {
31
31
  stdoutReadline = _readline.default.createInterface({
32
32
  input: p.stdout
33
33
  });
@@ -39,7 +39,7 @@ function attachReadline(p, onStdout, onErrout) {
39
39
  stdoutReadline = undefined;
40
40
  });
41
41
  }
42
- if (p.stderr) {
42
+ if (p?.stderr) {
43
43
  stderrReadline = _readline.default.createInterface({
44
44
  input: p.stderr
45
45
  });
@@ -59,7 +59,7 @@ function attachReadline(p, onStdout, onErrout) {
59
59
  stdoutReadline = undefined;
60
60
  stderrReadline = undefined;
61
61
  }
62
- p.on('exit', () => {
62
+ p?.on('exit', () => {
63
63
  dispose();
64
64
  });
65
65
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiot-toolkit/emulator",
3
- "version": "2.0.5-beta.22",
3
+ "version": "2.0.5-beta.23",
4
4
  "description": "vela emulator tool.",
5
5
  "homepage": "",
6
6
  "license": "ISC",
@@ -36,7 +36,7 @@
36
36
  "emulator"
37
37
  ],
38
38
  "dependencies": {
39
- "@aiot-toolkit/shared-utils": "2.0.5-beta.22",
39
+ "@aiot-toolkit/shared-utils": "2.0.5-beta.23",
40
40
  "@grpc/grpc-js": "^1.13.3",
41
41
  "@grpc/proto-loader": "^0.7.13",
42
42
  "@miwt/adb": "0.10.1",
@@ -53,5 +53,5 @@
53
53
  "@types/adm-zip": "^0.5.5",
54
54
  "@types/ini": "^4.1.1"
55
55
  },
56
- "gitHead": "cb8b82107dd1d8e977a529fcd334095627bd5d7c"
56
+ "gitHead": "f4991bcb0dcaab6853597ca07d21a7999649a1cc"
57
57
  }