aiot-toolkit 2.0.6-beta.25 → 2.0.6-beta.28
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/bin.js +46 -19
- package/lib/starter/VelaUxStarter.d.ts +2 -1
- package/lib/starter/VelaUxStarter.js +122 -7
- package/package.json +7 -8
package/lib/bin.js
CHANGED
|
@@ -10,7 +10,6 @@ var _VelaUxBuilder = _interopRequireDefault(require("./builder/VelaUxBuilder"));
|
|
|
10
10
|
var _AndroidUxStart = _interopRequireDefault(require("./starter/AndroidUxStart"));
|
|
11
11
|
var _VelaUxStarter = _interopRequireDefault(require("./starter/VelaUxStarter"));
|
|
12
12
|
var _DeviceUtil = _interopRequireDefault(require("./utils/DeviceUtil"));
|
|
13
|
-
var _VelaAvdUtils = _interopRequireDefault(require("./utils/VelaAvdUtils"));
|
|
14
13
|
var _ZipUtil = _interopRequireDefault(require("@aiot-toolkit/aiotpack/lib/compiler/javascript/vela/utils/ZipUtil"));
|
|
15
14
|
var _BuildNameFormatType = _interopRequireDefault(require("@aiot-toolkit/aiotpack/lib/compiler/javascript/vela/enum/BuildNameFormatType"));
|
|
16
15
|
var _Jsc = _interopRequireDefault(require("@aiot-toolkit/aiotpack/lib/compiler/javascript/vela/utils/Jsc"));
|
|
@@ -20,6 +19,9 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
20
19
|
// 支持的最低node版本
|
|
21
20
|
const NODE_MINIMUM_VERSION = '18.0.0';
|
|
22
21
|
checkVersion();
|
|
22
|
+
|
|
23
|
+
// VelaAvdUtil is lazy-imported in emulator commands to avoid loading emulator code for build/release
|
|
24
|
+
|
|
23
25
|
// 校验当前环境中的node
|
|
24
26
|
function checkVersion() {
|
|
25
27
|
const currentVersion = process.versions.node;
|
|
@@ -142,36 +144,61 @@ async function main() {
|
|
|
142
144
|
name: 'createVVD',
|
|
143
145
|
description: 'create a vela virtual device',
|
|
144
146
|
action: async () => {
|
|
145
|
-
|
|
147
|
+
const VelaAvdUtil = (await import('./utils/VelaAvdUtils')).default;
|
|
148
|
+
await VelaAvdUtil.createVelaVvdByInquire();
|
|
146
149
|
}
|
|
147
150
|
}, {
|
|
148
151
|
name: 'deleteVVD',
|
|
149
152
|
description: 'delete vela virtual device(s)',
|
|
150
|
-
|
|
151
|
-
name: 'avdNames',
|
|
152
|
-
description: 'avd names to delete',
|
|
153
|
-
enableInquirer: true,
|
|
154
|
-
type: 'checkbox',
|
|
155
|
-
choices: _VelaAvdUtils.default.vvdManager.getVvdList().map(item => {
|
|
156
|
-
return {
|
|
157
|
-
name: item.name,
|
|
158
|
-
value: item.name
|
|
159
|
-
};
|
|
160
|
-
})
|
|
161
|
-
}],
|
|
162
|
-
action: async option => {
|
|
153
|
+
action: async () => {
|
|
163
154
|
const {
|
|
164
|
-
|
|
165
|
-
} =
|
|
155
|
+
checkbox
|
|
156
|
+
} = await import('@inquirer/prompts');
|
|
157
|
+
const VelaAvdUtil = (await import('./utils/VelaAvdUtils')).default;
|
|
158
|
+
const vvdList = VelaAvdUtil.vvdManager.getVvdList();
|
|
159
|
+
const avdNames = await checkbox({
|
|
160
|
+
message: 'avd names to delete',
|
|
161
|
+
choices: vvdList.map(item => {
|
|
162
|
+
return {
|
|
163
|
+
name: item.name,
|
|
164
|
+
value: item.name
|
|
165
|
+
};
|
|
166
|
+
})
|
|
167
|
+
});
|
|
166
168
|
avdNames.forEach(avdName => {
|
|
167
|
-
|
|
169
|
+
VelaAvdUtil.vvdManager.deleteVvd(avdName);
|
|
168
170
|
});
|
|
169
171
|
}
|
|
172
|
+
}, {
|
|
173
|
+
name: 'status',
|
|
174
|
+
description: 'show active running sessions',
|
|
175
|
+
action: async () => {
|
|
176
|
+
const os = await import('os');
|
|
177
|
+
const sessionDir = _path.default.join(os.homedir(), '.aiot-toolkit', 'running-sessions');
|
|
178
|
+
if (!_fsExtra.default.existsSync(sessionDir)) {
|
|
179
|
+
console.log(JSON.stringify([]));
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const files = _fsExtra.default.readdirSync(sessionDir).filter(f => f.endsWith('.json'));
|
|
183
|
+
const active = [];
|
|
184
|
+
for (const file of files) {
|
|
185
|
+
try {
|
|
186
|
+
const session = _fsExtra.default.readJsonSync(_path.default.join(sessionDir, file));
|
|
187
|
+
process.kill(session.pid, 0);
|
|
188
|
+
active.push(session);
|
|
189
|
+
} catch {
|
|
190
|
+
// pid not alive, clean up stale session file
|
|
191
|
+
_fsExtra.default.removeSync(_path.default.join(sessionDir, file));
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
console.log(JSON.stringify(active, null, 2));
|
|
195
|
+
}
|
|
170
196
|
}, {
|
|
171
197
|
name: 'initEmulatorEnv',
|
|
172
198
|
description: 'init/reset emulator environment',
|
|
173
199
|
action: async () => {
|
|
174
|
-
|
|
200
|
+
const VelaAvdUtil = (await import('./utils/VelaAvdUtils')).default;
|
|
201
|
+
await VelaAvdUtil.initEmulatorEnv();
|
|
175
202
|
}
|
|
176
203
|
}, {
|
|
177
204
|
name: 'resign',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IParam } from '@aiot-toolkit/commander';
|
|
2
|
-
import { IStartOptions, CommonInstance } from '@aiot-toolkit/emulator';
|
|
2
|
+
import { IStartOptions, CommonInstance, BrokerInstance } from '@aiot-toolkit/emulator';
|
|
3
3
|
import VelaUxBuilder from '../builder/VelaUxBuilder';
|
|
4
4
|
import IStarter from './IStarter';
|
|
5
5
|
import Event from 'events';
|
|
@@ -11,6 +11,7 @@ declare class VelaUxStarter extends IStarter<IStartOptions> {
|
|
|
11
11
|
protected name: string;
|
|
12
12
|
protected description: string;
|
|
13
13
|
emulatorInstance?: CommonInstance;
|
|
14
|
+
brokerInstance?: BrokerInstance;
|
|
14
15
|
builder: VelaUxBuilder;
|
|
15
16
|
event: Event;
|
|
16
17
|
lastRpk?: string;
|
|
@@ -14,6 +14,7 @@ var _VelaUxBuilder = _interopRequireDefault(require("../builder/VelaUxBuilder"))
|
|
|
14
14
|
var _VelaAvdUtils = _interopRequireDefault(require("../utils/VelaAvdUtils"));
|
|
15
15
|
var _IStarter = _interopRequireDefault(require("./IStarter"));
|
|
16
16
|
var _fsExtra = _interopRequireDefault(require("fs-extra"));
|
|
17
|
+
var _os = _interopRequireDefault(require("os"));
|
|
17
18
|
var _aiotpack = require("@aiot-toolkit/aiotpack");
|
|
18
19
|
var _events = _interopRequireDefault(require("events"));
|
|
19
20
|
var _FileLaneTriggerType = _interopRequireDefault(require("file-lane/lib/enum/FileLaneTriggerType"));
|
|
@@ -60,6 +61,14 @@ class VelaUxStarter extends _IStarter.default {
|
|
|
60
61
|
description: 'deprecated',
|
|
61
62
|
deprecated: 'please remove it now',
|
|
62
63
|
deprecatedVersion: '2.1.0'
|
|
64
|
+
}, {
|
|
65
|
+
name: 'device',
|
|
66
|
+
description: 'name of the emulator (VVD) to start, skips interactive selection',
|
|
67
|
+
type: 'string'
|
|
68
|
+
}, {
|
|
69
|
+
name: 'mqttPort',
|
|
70
|
+
description: 'MQTT broker port',
|
|
71
|
+
type: 'string'
|
|
63
72
|
}, ..._IVelaUxBuilderOption.velaUxBuilderParams])();
|
|
64
73
|
async start(projectPath, options) {
|
|
65
74
|
const check = await _VelaAvdUtils.default.checkEmulatorEnv();
|
|
@@ -71,7 +80,18 @@ class VelaUxStarter extends _IStarter.default {
|
|
|
71
80
|
// 获取已经创建的模拟器列表
|
|
72
81
|
const vvdList = _VelaAvdUtils.default.vvdManager.getVvdList();
|
|
73
82
|
let vvdName;
|
|
74
|
-
if (
|
|
83
|
+
if (options.device) {
|
|
84
|
+
// --device specified: use it directly, skip interactive selection
|
|
85
|
+
const match = vvdList.find(v => v.name === options.device);
|
|
86
|
+
if (!match) {
|
|
87
|
+
const available = vvdList.map(v => v.name).join(', ');
|
|
88
|
+
const errorMsg = `Emulator "${options.device}" not found. Available: ${available || 'none'}`;
|
|
89
|
+
_sharedUtils.ColorConsole.throw(errorMsg);
|
|
90
|
+
throw new Error(errorMsg);
|
|
91
|
+
}
|
|
92
|
+
vvdName = options.device;
|
|
93
|
+
_sharedUtils.ColorConsole.warn(`Start run by: ${vvdName}`);
|
|
94
|
+
} else if (vvdList.length === 0) {
|
|
75
95
|
_sharedUtils.ColorConsole.error('no vela emulator available, please create it first.');
|
|
76
96
|
_VelaAvdUtils.default.createVelaVvdByInquire();
|
|
77
97
|
return;
|
|
@@ -96,11 +116,27 @@ class VelaUxStarter extends _IStarter.default {
|
|
|
96
116
|
})
|
|
97
117
|
});
|
|
98
118
|
}
|
|
119
|
+
if (!vvdName) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
99
122
|
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
123
|
+
// Step 1: Start MQTT broker first
|
|
124
|
+
this.brokerInstance = await (0, _emulator.startBroker)(options.mqttPort ? {
|
|
125
|
+
preferredMqttPort: Number(options.mqttPort)
|
|
126
|
+
} : undefined);
|
|
127
|
+
_sharedUtils.ColorConsole.success({
|
|
128
|
+
word: 'MQTT broker started: '
|
|
129
|
+
}, `${this.brokerInstance.mqttHost}:${this.brokerInstance.mqttPort}`);
|
|
130
|
+
|
|
131
|
+
// Step 2: Generate debug config (contains MQTT address and port)
|
|
132
|
+
const deviceId = `vela_emulator_${vvdName}`;
|
|
133
|
+
const debugCfg = {
|
|
134
|
+
mqttHost: this.brokerInstance.mqttHost,
|
|
135
|
+
mqttPort: this.brokerInstance.mqttPort,
|
|
136
|
+
device: deviceId
|
|
137
|
+
};
|
|
138
|
+
const cfgPath = _path.default.join(_os.default.tmpdir(), `quickapp_debug_cfg_${vvdName}.json`);
|
|
139
|
+
await _fsExtra.default.writeFile(cfgPath, JSON.stringify(debugCfg, undefined, 2));
|
|
104
140
|
|
|
105
141
|
// 设置 debugPort
|
|
106
142
|
let debugPort;
|
|
@@ -110,16 +146,95 @@ class VelaUxStarter extends _IStarter.default {
|
|
|
110
146
|
});
|
|
111
147
|
}
|
|
112
148
|
|
|
113
|
-
//
|
|
149
|
+
// Step 3: Start emulator with stdoutCallback to push debug config on boot
|
|
150
|
+
// quickapp_debug_cfg.json is in /tmp which gets wiped on reboot,
|
|
151
|
+
// so we push it when emulator outputs "Start Debug Server" (same as core plugin)
|
|
152
|
+
const pushDebugConfig = async () => {
|
|
153
|
+
if (!this.emulatorInstance) return;
|
|
154
|
+
await this.emulatorInstance.push(cfgPath, '/tmp/quickapp_debug_cfg.json');
|
|
155
|
+
_sharedUtils.ColorConsole.success({
|
|
156
|
+
word: 'Debug config pushed to emulator'
|
|
157
|
+
});
|
|
158
|
+
};
|
|
114
159
|
const startRes = await _VelaAvdUtils.default.vvdManager.startVvd({
|
|
115
160
|
vvdName,
|
|
116
161
|
origin: _emulator.IStartOrigin.Terminal,
|
|
117
|
-
debugPort
|
|
162
|
+
debugPort,
|
|
163
|
+
stdoutCallback: msg => {
|
|
164
|
+
// 模拟器启动/重启时推送 debug config(参考 core 插件做法)
|
|
165
|
+
if (msg.includes('Start Debug Server')) {
|
|
166
|
+
pushDebugConfig();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
118
169
|
});
|
|
119
170
|
this.emulatorInstance = startRes.emulatorInstance;
|
|
120
171
|
if (!this.emulatorInstance) {
|
|
121
172
|
throw new Error('emulatorInstance is undefined');
|
|
122
173
|
}
|
|
174
|
+
|
|
175
|
+
// 如果是冷启动,stdoutCallback 会在启动过程中触发推送
|
|
176
|
+
// 如果模拟器已经在运行(非冷启动),需要手动推送一次
|
|
177
|
+
if (!startRes.coldBoot) {
|
|
178
|
+
await pushDebugConfig();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Step 4: Wait for VelaJS runtime to connect to MQTT broker
|
|
182
|
+
await new Promise(resolve => {
|
|
183
|
+
if (this.brokerInstance.aedes.connectedClients > 0) {
|
|
184
|
+
resolve();
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const onClient = () => {
|
|
188
|
+
this.brokerInstance.aedes.removeListener('client', onClient);
|
|
189
|
+
resolve();
|
|
190
|
+
};
|
|
191
|
+
this.brokerInstance.aedes.on('client', onClient);
|
|
192
|
+
});
|
|
193
|
+
_sharedUtils.ColorConsole.success({
|
|
194
|
+
word: 'VelaJS runtime connected to MQTT broker'
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// Output MCP config for AI agent
|
|
198
|
+
_sharedUtils.ColorConsole.success({
|
|
199
|
+
word: 'MCP config: '
|
|
200
|
+
}, `--device ${deviceId} --mqttPort ${this.brokerInstance.mqttPort}`);
|
|
201
|
+
|
|
202
|
+
// Write session file for status tracking
|
|
203
|
+
const sessionDir = _path.default.join(_os.default.homedir(), '.vela', 'sessions');
|
|
204
|
+
const sessionFile = _path.default.join(sessionDir, `${deviceId}.json`);
|
|
205
|
+
await _fsExtra.default.ensureDir(sessionDir);
|
|
206
|
+
await _fsExtra.default.writeJson(sessionFile, {
|
|
207
|
+
pid: process.pid,
|
|
208
|
+
device: deviceId,
|
|
209
|
+
mqttHost: this.brokerInstance.mqttHost,
|
|
210
|
+
mqttPort: this.brokerInstance.mqttPort,
|
|
211
|
+
grpcPort: Number(startRes.grpcConfig['grpc.port']),
|
|
212
|
+
vvdName,
|
|
213
|
+
source: 'cli',
|
|
214
|
+
startedAt: new Date().toISOString()
|
|
215
|
+
}, {
|
|
216
|
+
spaces: 2
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
// Clean up session file on exit
|
|
220
|
+
const cleanup = () => {
|
|
221
|
+
try {
|
|
222
|
+
_fsExtra.default.removeSync(sessionFile);
|
|
223
|
+
} catch {}
|
|
224
|
+
};
|
|
225
|
+
process.on('exit', cleanup);
|
|
226
|
+
process.on('SIGINT', () => {
|
|
227
|
+
cleanup();
|
|
228
|
+
process.exit();
|
|
229
|
+
});
|
|
230
|
+
process.on('SIGTERM', () => {
|
|
231
|
+
cleanup();
|
|
232
|
+
process.exit();
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// Step 7: Build + push rpk + start app
|
|
236
|
+
const compilerOption = this.builder.getCompilerOption(projectPath, options);
|
|
237
|
+
await this.builder.build(projectPath, options);
|
|
123
238
|
const projectInfo = _aiotpack.UxFileUtils.getManifestInfo(projectPath, compilerOption.sourceRoot);
|
|
124
239
|
if (this.lastRpk && _fsExtra.default.existsSync(this.lastRpk)) {
|
|
125
240
|
const targetPath = await this.emulatorInstance?.pushRpk(this.lastRpk, projectInfo.package);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiot-toolkit",
|
|
3
|
-
"version": "2.0.6-beta.
|
|
3
|
+
"version": "2.0.6-beta.28",
|
|
4
4
|
"description": "Tools for creating, developing, and packaging aiot applications.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"aiot"
|
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
"test": "node ./__tests__/aiot-toolkit.test.js"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@aiot-toolkit/aiotpack": "2.0.6-beta.
|
|
26
|
-
"@aiot-toolkit/commander": "2.0.6-beta.
|
|
27
|
-
"@aiot-toolkit/emulator": "2.0.6-beta.
|
|
28
|
-
"@aiot-toolkit/shared-utils": "2.0.6-beta.
|
|
25
|
+
"@aiot-toolkit/aiotpack": "2.0.6-beta.28",
|
|
26
|
+
"@aiot-toolkit/commander": "2.0.6-beta.28",
|
|
27
|
+
"@aiot-toolkit/emulator": "2.0.6-beta.28",
|
|
28
|
+
"@aiot-toolkit/shared-utils": "2.0.6-beta.28",
|
|
29
29
|
"@inquirer/prompts": "^5.3.0",
|
|
30
30
|
"@miwt/adb": "^0.9.0",
|
|
31
31
|
"axios": "^1.7.4",
|
|
32
|
-
"file-lane": "2.0.6-beta.
|
|
32
|
+
"file-lane": "2.0.6-beta.28",
|
|
33
33
|
"fs-extra": "^11.2.0",
|
|
34
34
|
"koa-router": "^13.0.1",
|
|
35
35
|
"lodash": "^4.17.21",
|
|
@@ -42,6 +42,5 @@
|
|
|
42
42
|
"@types/koa-router": "^7.4.8",
|
|
43
43
|
"@types/qr-image": "^3.2.9",
|
|
44
44
|
"@types/semver": "^7.5.8"
|
|
45
|
-
}
|
|
46
|
-
"gitHead": "25b954200dd056d25c2c9fa2c2ccd04f261d57af"
|
|
45
|
+
}
|
|
47
46
|
}
|