diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 73ba8f8..40c51d3 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,7 +1,5 @@ -# pigway-console-adapter-raspberry-pi v1.6.8 +# PIGWay Raspberry Pi Adapter v1.6.9 -合并主要告警与 OLED/RGB 展示,在线状态右对齐,保留系统配置插件管理;统一现有状态与折叠展示。 - -验证:适配器单元测试及相关桌面、平板、手机浏览器检查通过。 - -发布包可供安装;发布不自动升级生产已安装适配器。树莓派合并展示已单独热更新,Ubuntu/NAS 隐藏空告警块尚未部署。 +- 主要告警标题右侧的硬件可用状态从绿色“在线”改为蓝色“正常”,复用 Console normal 语义。 +- 保留离线、未确认、未接入提示以及 OLED/RGB 内容。 +- 桌面、平板、手机及在线、离线、未接入状态浏览器检查通过。 diff --git a/SHA256SUMS b/SHA256SUMS index 20da690..58ad67b 100644 --- a/SHA256SUMS +++ b/SHA256SUMS @@ -6,7 +6,7 @@ ec04c97e0271455a41328b8d68e8e4a5d0e3ef5782ddb8fc62a08b7bfff2ef9d DEPLOYMENT-v1. 136db6c02d7181085f18c54bf1ca2b0bc56e3aa43e3a71a0e59926fc7fa7b18f DEPLOYMENT-v1.3.2-2026-10-15.md d0870015c81d16af20cf38b775fa95b5ac1619cc5144fcda5007cb2f832e0e33 DEPLOYMENT-v1.3.3-2026-10-15.md 552b66fe8946ea96b12633fcf705c71b14d32679bd57ddd39fd5c4cc8910f1b2 README.md -c7432d981ad0a0bc66cdc6e1915620df60d9e31be4da67ad19dd32ceca92d884 RELEASE_NOTES.md +377762a3427522893090b4bd7ef2d950758692c3b012d9b5b808549dda13cf2b RELEASE_NOTES.md a669ccb22bf3aafec6fa558fd84108dca013cb8dc2988206b7b5fe58a1eb2035 STORAGE-DISCOVERY.md 0cf93f3b3d3219ab8229b59e98cbd82e42647a461231f7c767ea3d120f8e0910 docs/AUDIT-FIXES-2026-10-16.md 1eec71f194bfdd51b6ae5a9063a0760ccf24b46474901defdf19503a680b8fcd docs/HOME-CARD-ORDER-2026-10-17.md @@ -14,18 +14,18 @@ b47aafb725706a03837aceabd1ac59b302ead066bf12bf947326a98cb38963ef docs/OVERVIEW- f0df601aafe839cfe06c069471071023158beced81c5d0b802fa0bb4ed3528bc docs/OVERVIEW-SUMMARY-BADGES-2026-10-16.md d3528d8fd4eed197942e2c9a72d62e6c9ff6b3ab00f4be98c337b6e306d6e177 docs/STATUS-ALIGNMENT-2026-10-16.md d081c599d821149853368b1a8637c57a16995344406ff5ec9d7619b66e0479b3 package.py -7e985bc8ce58c9d83b6e61c5a47e123856f57281c23a389750471f988c13699e plugin/manifest.json +fb2eab0e50e1f0363e89a5df284f609f9a7f911725a81c09d17ea839b78f37ff plugin/manifest.json d6a342605426357da7d2e65daa435e99d7234549cffa52e1a9229ef5bc36f33c plugin/ui/config.js c98f34119436e3020ef20b325f91617943aefe662119cf76738e0226c2e91cbb plugin/ui/device.js 89b9d7994e7477e18c3f43e6f0975e04d5106056ba581b2964db0f39183d6f8a plugin/ui/hardware.js af631694fcd7da21b77b554e6ee1bf2eaa93bd46a0b8b543e367f032d3236ecb plugin/ui/index.js -b1d50c4ba896905b3c3ee8808072dfb41c04486b9364a5f0f49377059e280a78 plugin/ui/overview.js +9c1a488c99a61f78c3a6abaea9ce84e53fc6b73f36dc92c7365136231dc70058 plugin/ui/overview.js 422e1f8323d29a4be757f39e8b60addd7764c436a1302673809e0c547fce5ff4 plugin/ui/schema.js 1bee0f9e5656a52bc97d9fafffbf5157dae062888f618046ad09470dc2685f3c plugin/ui/services.js 6806df689f62de56f7b61f8b3cf3a33c494a09931a14f51d9d71c26d2c1f61ee plugin/ui/storage.js 061f5011b78cedcd0c69a32aa5106889d38f6863f4c613ae326cc9d16f90e2dd plugin/ui/styles.css 0b79b9c5b5f23727164e05b127caca72255416309166ba200ccbd15a9667473c plugin/ui/translations.js d5b22366a2c7b375e6f3e35cefb9f95da0ea3b8390b3ec4d1000492f00128f6e plugin/worker.py -22c913e75736b78c54d90a60c7a2c8f739467dc7f8ed3f46b71be28e4bc3dec5 tests/browser_alert_semantics.cjs +4efdd82aac730361cde262fc55677e965588259064e68bb1b01831d1ba5a157d tests/browser_alert_semantics.cjs 40c038aa7689c127c0d90ddf390674f534a2bdee8fd3c344d09f8fb6d4bb3964 tests/test_metrics.py 40d10555aef08f8132f576976b7205b3e1c16d330196a11c6cc1c5cbc167c670 tests/test_storage_metrics.py diff --git a/plugin/manifest.json b/plugin/manifest.json index d417da4..183faa4 100644 --- a/plugin/manifest.json +++ b/plugin/manifest.json @@ -1,7 +1,7 @@ { "id": "pigway-agent", "name": "PIGWay Raspberry Pi Agent", - "version": "1.6.8", + "version": "1.6.9", "protocol_version": 1, "entrypoint": "worker.py", "runtime": "python3", diff --git a/plugin/ui/overview.js b/plugin/ui/overview.js index 5a72e46..17e9c1a 100644 --- a/plugin/ui/overview.js +++ b/plugin/ui/overview.js @@ -31,9 +31,9 @@ export function agentHostCard(entry) { const displayText = [oled ? `OLED ${ownerName(oled.status.oled_page)}` : ownerName(d.owner), rgb ? `RGB ${rgbName(rgb.status.rgb_mode)}` : ""].filter(Boolean).join(" · "); const hardwareState = !hardware.length ? "unlinked" : !current ? "unknown" : hardware.some(p => p.online === false) ? "offline" : hardware.every(ready) ? "online" : "unknown"; - const hardwareLabel = { online: tr("在线"), offline: tr("离线"), unknown: appState.LANG === "zh" ? "未确认" : "Unconfirmed", unlinked: appState.LANG === "zh" ? "未接入" : "Not connected" }[hardwareState]; + const hardwareLabel = { online: tr("正常"), offline: tr("离线"), unknown: appState.LANG === "zh" ? "未确认" : "Unconfirmed", unlinked: appState.LANG === "zh" ? "未接入" : "Not connected" }[hardwareState]; const hardwareNames = hardware.map(p => p.name).filter(Boolean).join(" · "); const percent = n => Number.isFinite(n) ? `${n.toFixed(1)}%` : "--"; const progress = n => Number.isFinite(n) ? meter(n) : ""; - return `

${esc(m.name || h.name || m.id)}

${esc(formatUptime(s.uptime_seconds))}
ID ${esc(m.id || h.id)}${appState.LANG === "zh" ? "主机名" : "Hostname"} ${esc(m.hostname || v.hostname || "--")}${esc(v.manufacturer || "")} ${esc(v.model || "--")}${appState.LANG === "zh" ? "序列号" : "Serial"} ${esc(v.serial || "--")}${appState.LANG === "zh" ? "硬件版本" : "Revision"} ${esc(v.revision || "--")}${esc(v.os || "--")}${appState.LANG === "zh" ? "内核" : "Kernel"} ${esc(v.kernel || "--")}${esc(v.architecture || "--")} · CPU ${esc(v.cpu_count || "--")}${appState.LANG === "zh" ? "程序版本" : "Agent"} ${esc(s.version || "--")}
${tr("在线")}
${tr("处理器负载")}
${percent(y.cpu_percent)}
${progress(y.cpu_percent)}
${appState.LANG === "zh" ? "频率" : "Frequency"} ${esc(y.cpu_freq_mhz)} MHz · ${esc(y.temperature_c)}°C${fanMetric(s.plugins || {})}
${tr("内存占用")}
${percent(y.memory_percent)}
${progress(y.memory_percent)}
${bytes(memUsed)} / ${bytes(memTotal)} · ${appState.LANG === "zh" ? "可用" : "Available"} ${bytes(y.memory_available_bytes)}
${tr("主网络")}
↓ ${bytes(n.rx_bytes_per_second)}/s · ↑ ${bytes(n.tx_bytes_per_second)}/s
${esc(n.interface || "--")} · ${n.kind === "WIF" ? `${esc(n.metric)} dBm · ` : n.link_speed_mbps ? `${esc(n.link_speed_mbps)} Mbps · ` : ""}${esc(n.ip_label)} ${esc(n.ip)} · ${n.link === true ? (appState.LANG === "zh" ? "已连接" : "Connected") : n.link === false ? (appState.LANG === "zh" ? "已断开" : "Disconnected") : (appState.LANG === "zh" ? "状态未确认" : "Unconfirmed")}
${Array.isArray(y.storage_inventory) ? storageCards(y,entry.snapshot?.resources) : `
${tr("磁盘占用")}
${percent(y.disk_percent)}
${progress(y.disk_percent)}
${bytes(diskUsed)} / ${bytes(diskTotal)} · ${appState.LANG === "zh" ? "剩余" : "Free"} ${bytes(y.disk_free_bytes)}
`}
${appState.LANG === "zh" ? "主要告警" : "Primary alert"}${esc(hardwareLabel)}
${esc(displayText)}
${hardwareNames ? `
${esc(hardwareNames)}
` : ""}
${(d.alerts || []).length || !dataIsCurrent(entry) || !Array.isArray(d.alerts) ? `
${tr("当前告警")}
${(d.alerts || []).length}
${(d.alerts || []).map((a) => esc(ownerName(a.id))).join(" · ") || tr("无告警")}
` : ""}
${tr("服务与进程监控")}${summaryStatus(monitorHealth(s.watches, dataIsCurrent(entry)), appState.LANG)}
${(s.watches || []).map((w) => `
${esc(w.name)} · ${esc(w.target)}${runtimeStatus(w.up, appState.LANG)}
`).join("") || `
${tr("暂无数据")}
`}
`; + return `

${esc(m.name || h.name || m.id)}

${esc(formatUptime(s.uptime_seconds))}
ID ${esc(m.id || h.id)}${appState.LANG === "zh" ? "主机名" : "Hostname"} ${esc(m.hostname || v.hostname || "--")}${esc(v.manufacturer || "")} ${esc(v.model || "--")}${appState.LANG === "zh" ? "序列号" : "Serial"} ${esc(v.serial || "--")}${appState.LANG === "zh" ? "硬件版本" : "Revision"} ${esc(v.revision || "--")}${esc(v.os || "--")}${appState.LANG === "zh" ? "内核" : "Kernel"} ${esc(v.kernel || "--")}${esc(v.architecture || "--")} · CPU ${esc(v.cpu_count || "--")}${appState.LANG === "zh" ? "程序版本" : "Agent"} ${esc(s.version || "--")}
${tr("在线")}
${tr("处理器负载")}
${percent(y.cpu_percent)}
${progress(y.cpu_percent)}
${appState.LANG === "zh" ? "频率" : "Frequency"} ${esc(y.cpu_freq_mhz)} MHz · ${esc(y.temperature_c)}°C${fanMetric(s.plugins || {})}
${tr("内存占用")}
${percent(y.memory_percent)}
${progress(y.memory_percent)}
${bytes(memUsed)} / ${bytes(memTotal)} · ${appState.LANG === "zh" ? "可用" : "Available"} ${bytes(y.memory_available_bytes)}
${tr("主网络")}
↓ ${bytes(n.rx_bytes_per_second)}/s · ↑ ${bytes(n.tx_bytes_per_second)}/s
${esc(n.interface || "--")} · ${n.kind === "WIF" ? `${esc(n.metric)} dBm · ` : n.link_speed_mbps ? `${esc(n.link_speed_mbps)} Mbps · ` : ""}${esc(n.ip_label)} ${esc(n.ip)} · ${n.link === true ? (appState.LANG === "zh" ? "已连接" : "Connected") : n.link === false ? (appState.LANG === "zh" ? "已断开" : "Disconnected") : (appState.LANG === "zh" ? "状态未确认" : "Unconfirmed")}
${Array.isArray(y.storage_inventory) ? storageCards(y,entry.snapshot?.resources) : `
${tr("磁盘占用")}
${percent(y.disk_percent)}
${progress(y.disk_percent)}
${bytes(diskUsed)} / ${bytes(diskTotal)} · ${appState.LANG === "zh" ? "剩余" : "Free"} ${bytes(y.disk_free_bytes)}
`}
${appState.LANG === "zh" ? "主要告警" : "Primary alert"}${esc(hardwareLabel)}
${esc(displayText)}
${hardwareNames ? `
${esc(hardwareNames)}
` : ""}
${(d.alerts || []).length || !dataIsCurrent(entry) || !Array.isArray(d.alerts) ? `
${tr("当前告警")}
${(d.alerts || []).length}
${(d.alerts || []).map((a) => esc(ownerName(a.id))).join(" · ") || tr("无告警")}
` : ""}
${tr("服务与进程监控")}${summaryStatus(monitorHealth(s.watches, dataIsCurrent(entry)), appState.LANG)}
${(s.watches || []).map((w) => `
${esc(w.name)} · ${esc(w.target)}${runtimeStatus(w.up, appState.LANG)}
`).join("") || `
${tr("暂无数据")}
`}
`; } diff --git a/tests/browser_alert_semantics.cjs b/tests/browser_alert_semantics.cjs index 154c3ab..7c4100e 100644 --- a/tests/browser_alert_semantics.cjs +++ b/tests/browser_alert_semantics.cjs @@ -20,7 +20,8 @@ for(const width of [1440,768,390]){ await page.evaluate(p=>render('zh',p),hardware); const primary=page.locator('[data-refresh-group="display"]'); if((await primary.locator('.value').innerText())!=='OLED 正常主页 · RGB 全灭')throw Error('Merged OLED/RGB text'); - if((await primary.locator('.pi-alert-heading .semantic-status').innerText())!=='在线')throw Error('Missing hardware online status'); + if((await primary.locator('.pi-alert-heading .semantic-status').innerText())!=='正常')throw Error('Missing hardware normal status'); + if((await primary.locator('.pi-alert-heading .semantic-status').getAttribute('data-semantic'))!=='normal')throw Error('Hardware status must use normal blue'); if(await page.locator('[data-manage-plugin-host]').count())throw Error('Overview must not expose plugin management'); if(await page.locator('.group.action-row').count())throw Error('Standalone hardware row remains'); if(!(await primary.innerText()).includes('Yahboom RGB Cooling HAT'))throw Error('Hardware name missing');