|
|
设备档案卡一键采集本机软硬件信息
- /**
- * 案例37:设备档案卡——一键采集本机软硬件信息,生成一张可直接发给客户的档案卡
- *
- * 题材来源:设备农场/客户交付场景的刚需——手里十几台云手机、二手设备,
- * 每台什么型号、什么系统、电池好坏、还剩多少盘、IP 多少,全靠手工记。
- * 本案例把"盘点"这件事自动化:采集 → 排版成卡 → 落盘存档。
- *
- * 典型 AIWROK 用法组合(三件套全带上):
- * ① 日志输出 : printl + 节奏倒计时(关键动作前 3..2..1,行间停顿)
- * ② 数据采集 : device 对象(品牌/型号/系统/IMEI/OAID/电量/充电/IP)
- * + adb.exec 读 df(存储)、/proc/meminfo(内存)
- * ③ 文件落地 : adb.exec 追加写入 /sdcard/auto/设备档案_日期.txt,批量盘点可汇总
- *
- * 只用锤过的 API(全部前 36 个案例实测):
- * device.getBrand/getModel/getVersion/getIMEI/getOAID/getIP/getBatteryLevel/isCharging
- * adb.exec(返回 JSON 包 {errorMsg,success})、printl、sleep.millisecond(毫秒)、Date
- *
- * ★ 2026-11-06 修正:AIWROK 没有 sleep(毫秒) 裸调用,休眠必须写 sleep.millisecond(n);
- * 本脚本原先所有 sleep(n) 已全部改为 sleep.millisecond(n)。
- *
- * 写法约定(Rhino ES5 引擎):全 var、无箭头函数、无模板字符串;
- * 所有函数【先定义后调用】,main() 放在文件末尾统一启动。
- *
- * 用法:直接运行。约 15 秒出卡,手机 /sdcard/auto/ 下会多一份 txt 存档。
- */
- // ========== 配置区 ==========
- var 落盘目录 = "/sdcard/auto";
- var 档案文件名前缀 = "设备档案_";
- var 是否落盘 = true; // 想只看不打文件,改 false
- // ========== 一、节奏输出(项目铁律:关键动作前倒计时,行间留白) ==========
- function 节奏倒计时(秒数, 干什么) {
- for (var i = 秒数; i > 0; i--) {
- printl("⏰ " + i + " 秒后:" + 干什么);
- sleep.second(1); // 整秒等待用 sleep.second,不用 sleep.millisecond(1000)
- }
- printl("🎬 " + 干什么 + " —— 开始");
- sleep.millisecond(400);
- }
- // ========== 二、锤死通道封装 ==========
- // adb.exec 以 App 自身 uid 运行,返回 JSON 包;这里统一剥成 {成, 错}
- function adb跑(命令) {
- try {
- var 数据 = JSON.parse(adb.exec(命令, false));
- var 成 = 数据.success == null ? "" : ("" + 数据.success);
- var 错 = 数据.errorMsg == null ? "" : ("" + 数据.errorMsg).trim();
- return { 成: 成, 错: 错 };
- } catch (e) {
- return { 成: "", 错: "exec异常 " + e };
- }
- }
- // 安全取值:任何一项取不到都不许中断整张卡
- function 安全取值(函数) {
- try {
- var v = 函数();
- if (v == null) return "未知";
- var s = "" + v;
- return s === "" ? "未知" : s;
- } catch (e) {
- return "不可用";
- }
- }
- // ========== 三、采集:软硬件 ==========
- function 采集基础() {
- var 卡 = {};
- 卡.品牌 = 安全取值(function () { return device.getBrand(); });
- 卡.型号 = 安全取值(function () { return device.getModel(); });
- 卡.系统 = 安全取值(function () { return device.getVersion(); });
- 卡.设备号 = 安全取值(function () { return device.getDeviceID(); });
- 卡.IMEI = 安全取值(function () { return device.getIMEI(); });
- 卡.OAID = 安全取值(function () { return device.getOAID(); });
- 卡.IP = 安全取值(function () { return device.getIP(); });
- return 卡;
- }
- function 采集电池() {
- var 电量 = -1;
- try { 电量 = device.getBatteryLevel(); } catch (e) {}
- var 充电 = "未知";
- try { 充电 = device.isCharging() ? "充电中" : "未充电"; } catch (e) {}
- return { 电量: 电量, 充电: 充电 };
- }
- // df /sdcard → 总/已用/可用/使用率(单位换算成 GB)
- function 采集存储() {
- var r = adb跑("df /sdcard");
- var 文本 = r.成;
- if (文本 === "") return null;
- // 形如: /dev/fuse 49387000 101000 47094000 1% /storage/emulated
- var m = 文本.match(/(\d+)\s+(\d+)\s+(\d+)\s+(\d+)%/);
- if (m == null) return null;
- var 总 = parseInt(m[1], 10) / 1024; // 1K-blocks → MB
- var 已用 = parseInt(m[2], 10) / 1024;
- var 可用 = parseInt(m[3], 10) / 1024;
- return {
- 总GB: Math.round(总 / 1024 * 10) / 10,
- 已用GB: Math.round(已用 / 1024 * 100) / 100,
- 可用GB: Math.round(可用 / 1024 * 10) / 10,
- 使用率: m[4]
- };
- }
- // /proc/meminfo → 内存总量与可用(MB)
- function 采集内存() {
- var r = adb跑("cat /proc/meminfo");
- var 文本 = r.成;
- if (文本 === "") return null;
- var 总 = 文本.match(/MemTotal:\s*(\d+)/);
- var 闲 = 文本.match(/MemAvailable:\s*(\d+)/);
- if (总 == null) return null;
- return {
- 总MB: Math.round(parseInt(总[1], 10) / 1024),
- 可用MB: 闲 == null ? -1 : Math.round(parseInt(闲[1], 10) / 1024)
- };
- }
- // ========== 四、组装档案卡(纯字符串排版,不做等宽对齐以免中文错位) ==========
- function 补零(n) { return n < 10 ? "0" + n : "" + n; }
- function 当前时间串() {
- var d = new Date();
- return d.getFullYear() + "-" + 补零(d.getMonth() + 1) + "-" + 补零(d.getDate()) + " " +
- 补零(d.getHours()) + ":" + 补零(d.getMinutes()) + ":" + 补零(d.getSeconds());
- }
- function 拼接档案卡(基础, 电池, 存储, 内存) {
- var 行 = [];
- 行.push("┌ 设备档案 ─────────────────────────");
- 行.push("│ 采集时间 : " + 当前时间串());
- 行.push("│ 品牌型号 : " + 基础.品牌 + " " + 基础.型号);
- 行.push("│ 系统版本 : " + 基础.系统);
- 行.push("│ 设备编号 : " + 基础.设备号);
- 行.push("│ IMEI : " + 基础.IMEI);
- 行.push("│ OAID : " + 基础.OAID);
- 行.push("│ 网络 IP : " + 基础.IP);
- if (电池.电量 >= 0) {
- 行.push("│ 电池 : " + 电池.电量 + "% / " + 电池.充电);
- } else {
- 行.push("│ 电池 : 本机不报电量(模拟器假电池,正常)");
- }
- if (存储 == null) {
- 行.push("│ 存储 : df 读取失败");
- } else {
- 行.push("│ 存储 : 总 " + 存储.总GB + "GB / 已用 " + 存储.已用GB + "GB / 可用 " +
- 存储.可用GB + "GB (使用率 " + 存储.使用率 + "%)");
- }
- if (内存 == null) {
- 行.push("│ 内存 : meminfo 读取失败");
- } else if (内存.可用MB < 0) {
- 行.push("│ 内存 : 总 " + 内存.总MB + "MB");
- } else {
- 行.push("│ 内存 : 总 " + 内存.总MB + "MB / 可用 " + 内存.可用MB + "MB");
- }
- 行.push("└───────────────────────────────────");
- return 行;
- }
- // ========== 五、落盘(逐行追加,失败只报不炸) ==========
- // 除单引号外,档案内容不含 shell 特殊字符;为稳妥先把单引号替换掉
- function 存盘(行表, 文件路径) {
- var 头 = adb跑("mkdir -p " + 落盘目录);
- if (("" + 头.错).indexOf("Permission") >= 0) return "无写权限";
- var 成功行 = 0;
- for (var i = 0; i < 行表.length; i++) {
- var 文本 = ("" + 行表[i]).replace(/'/g, "’");
- var 命令 = "sh -c "echo '" + 文本 + "' >> " + 文件路径 + """;
- var r = adb跑(命令);
- if (("" + r.错).indexOf("error") >= 0 || ("" + r.错).indexOf("denied") >= 0) continue;
- 成功行++;
- }
- return 成功行 === 行表.length ? "成功" : "部分成功(" + 成功行 + "/" + 行表.length + " 行)";
- }
- // ========== 六、主流程 ==========
- function main() {
- printl("=== 案例37 设备档案卡 启动:采集本机信息,约 15 秒出卡 ===");
- sleep.millisecond(600);
- 节奏倒计时(3, "开始采集体检数据");
- var 基础 = 采集基础();
- printl(" ✔ 软硬件基础项采集完成");
- sleep.millisecond(500);
- 节奏倒计时(2, "读电池 / 存储 / 内存");
- var 电池 = 采集电池();
- printl(" ✔ 电池: " + (电池.电量 >= 0 ? 电池.电量 + "%" : "不可用"));
- sleep.millisecond(400);
- var 存储 = 采集存储();
- printl(" ✔ 存储: " + (存储 == null ? "读取失败" : "可用 " + 存储.可用GB + "GB"));
- sleep.millisecond(400);
- var 内存 = 采集内存();
- printl(" ✔ 内存: " + (内存 == null ? "读取失败" : "总 " + 内存.总MB + "MB"));
- sleep.millisecond(600);
- var 行表 = 拼接档案卡(基础, 电池, 存储, 内存);
- printl("========== 📇 设备档案卡 ==========");
- for (var i = 0; i < 行表.length; i++) {
- printl(行表[i]);
- sleep.millisecond(300); // 逐行吐,方便录像和截屏
- }
- sleep.millisecond(600);
- if (是否落盘) {
- var d = new Date();
- var 名 = 档案文件名前缀 + d.getFullYear() + 补零(d.getMonth() + 1) + 补零(d.getDate()) + ".txt";
- var 路径 = 落盘目录 + "/" + 名;
- printl("💾 落盘:" + 路径);
- var 结果 = 存盘(行表, 路径);
- printl(" " + (结果 === "成功" ? "✅" : "⚠") + " 落盘" + 结果);
- if (结果 === "成功") printl(" 👉 多台设备挨个跑一遍,这个文件就是你的设备台账");
- } else {
- printl("ℹ 是否落盘=false,本次只打屏不存档");
- }
- printl("========== ✅ 体检完成 ==========");
- printl("💡 扩展:①外层套循环遍历多台设备 ②档案追加到同一文件做汇总 ③异常项(电量<20%)标红提醒");
- printl("=== 案例37 收工 ===");
- }
- // ========== 启动(Rhino ES5:统一在文件末尾调用,确保上面函数都已定义) ==========
- main();
复制代码
|
|