feat(panel, PANEL_ENHANCE_PLAN 批2): 崩溃/日志中心 + 音频写 + 后端补缺口

后端(meowpanel.c 0-warning,-Werror 通过):
- /api/system 补 reboot_reason/upgrade_status(svc_power 读级 POWER_REBOOT_REASON(8)/UPGRADE_STATUS(9))
- /api/overview net 块并入 DNS 统计(首页严格单请求;DNS 不可用省略 dns 键不谎报)
- /api/audio 补 vol_max(读 settings audio.volume_max)
- POST /api/audio/route(仅 0=auto/2=3.5/3=4.4,拒 1/4/5;写级 PIN 已护)
- POST /api/audio/volume(clamp 到 vol_max,防炸耳红线;写级 PIN 已护)
- GET /api/logs/crash(崩溃汇总:每实体崩溃数+最近时间/信号 + dmesg 计数;256KB/64 实体/5 行上限)
- /api/logs 文件列表加 group 来源分组
- 顺带补回 批1-B 前端读取的 boot.mode /tmp/meow_boot_mode(此前遗留未提交)

前端(web/meowpanel.js 双主题):
- 音频页:路由选择器(自动/3.5/4.4)+ 音量滑条(上限 vol_max、平方锥度非线性标注、确认弹窗)
- 日志页:崩溃汇总卡 + 崩溃尾巴一键看 stdout 尾部 + 按来源分组 + 前缀过滤
- 首页:netCard 改读 overview net.dns,去掉单独 /api/net/dns

验证:宿主编译 0 warning + -Werror;自建桩测试 24/24(crash 解析/路由 1|4|5 拒 422/音量 clamp 到 50/
reboot_reason+upgrade_status 值/overview net.dns);headless Chromium 渲染 audio/logs/home/system/
light 主题均正确。md5(meowpanel)=aed2ea17a34614acaa26dcbc8965ebb1。
This commit is contained in:
MeowOS committed 2026-09-01 23:15:52 +08:00
1 parent 34f2834704
commit 33d3059038
5 files changed
+547 -59

No files matched your search

+34 -4
View File
@@ -28,7 +28,7 @@ cd /home/Aska/Project/R3ProII/patch_v2/meowpanel
- 两分支均以 `-Os -Wall -Wextra` 复核,**0 warning**(`-Werror` 亦通过)。
- 产出(本次构建实测):
- `meowpanel`:mipsel 静态,`ELF 32-bit LSB executable, MIPS, MIPS32 rel2, statically linked, stripped`,
体积约 **236 KB**(固件阈值内)。md5:`3696e85b5eaf111f530c5c39fa68886e`(批1-A:访问级 **4 位 PIN 鉴权** + `/api/{power,overview,ams,svcd}` + `/api/audio` 补 `rms/peak/lvlseq`。
体积约 **256 KB**(固件阈值内)。md5:`aed2ea17a34614acaa26dcbc8965ebb1`(批2:崩溃/日志中心 `/api/logs/crash` + 日志分组/`group`;`/api/system` 补 `reboot_reason/upgrade_status`;`/api/overview` net 块并入 DNS 统计;音频**写级** `/api/audio/route`(仅 0/2/3,拒 1/4/5)+ `/api/audio/volume`(clamp 到 vol_max)+ `/api/audio` 补 `vol_max`)。
**重防火墙注意**:运行中二进制先 `.new` 再 `mv`,切勿直接覆盖运行中的 `meowpanel`)。
- `meowpanel_host`:aarch64 动态链接(宿主编译,仅供调试),体积约 **148 KB**。
- 依赖:仅 libc + Linux 内核头(`linux/input.h`),零第三方库(设备无 python3/lua)。鉴权用**内联 SHA-256**(拷贝自
@@ -115,7 +115,9 @@ http://<host>.local:8080/
| GET | `/api/fonts` | 字体库列表(扫描 `MeowOS/fonts/<family>/<weight>/` 三件套齐) | ✅(无卡→503) |
| POST | `/api/fonts/import` | 上传字体库 `.tar.gz`(multipart `file`,可带 `?force=1` 覆盖) | ✅(缺件/坏json/穿越→400,冲突→409,超限→413) |
| GET | `/api/fonts/export` | 导出 `<family>/<weight>/` 三件套为 `.tar.gz`(`?family=&weight=`) | ✅(缺件→404) |
| GET | `/api/audio` | 音频状态快照:meow_audiod IPC `MSG_AUDIO_QUERY→STATE` 透传(当前流/路由/音量/underrun + **`rms/peak/lvlseq` 电平**,见 §5.12) | ✅(audiod 不在→`available:false`,不报错) |
| GET | `/api/audio` | 音频状态快照:meow_audiod IPC `MSG_AUDIO_QUERY→STATE` 透传(当前流/路由/音量/underrun + **`rms/peak/lvlseq` 电平 + `vol_max`**,见 §5.12) | ✅(audiod 不在→`available:false`,不报错) |
| POST | `/api/audio/route` | 手动切输出路由(**写级**,PIN 已护):`MSG_AUDIO_ROUTE`,仅接受 `{port: 0\|2\|3}`,**绝不接受 1/4/5**(4=SPDIF、5=audiod 内部强制重烧值);前端切换前确认弹窗(选错口会无声) | ✅(非法端口→422;audiod 不在→503) |
| POST | `/api/audio/volume` | 写音量(**写级**,PIN 已护):`MSG_AUDIO_VOLUME`,**clamp 到系统 vol_max**(读 settings.conf `audio.volume_max`,缺省 100;设备当前 50);audiod 仅 clamp 0-100 无 vol_max 防护,面板是把守方(防炸耳红线) | ✅(clamp 后写;audiod 不在→503) |
| GET | `/api/power` | 功耗管理:meow_powermgr IPC `MSG_PM_QUERY→RESULT`(battery/estimate/breakdown,confidence 原样透传) | ✅(powermgr 不在→503 `POWER_UNAVAILABLE`) |
| GET | `/api/ams` | App 运行表:`am list`(pkg/name/state/pid/launches/crashes/last_kind/last_code) | ✅(amsd 不在→`available:false`) |
| GET | `/api/svcd` | 服务表:`meow_svcd status all`(name/state/pid/restart/backoff_ms/trigger/src/exit/exec) | ✅(svcd 不在→`available:false`) |
@@ -127,7 +129,8 @@ http://<host>.local:8080/
| DELETE | `/api/apps/:pkg` | `nyai remove [--purge]` | ✅ |
| POST | `/api/key/:code` | 按键注入(tap/long) | ✅(物理键红线内) |
| POST | `/api/key` | 批量/顺序注入 | ✅ |
| GET | `/api/logs` | `MeowOS/logs` 文件列表 | ✅(无卡→503) |
| GET | `/api/logs` | `MeowOS/logs` 文件列表(每文件含 `group` 来源分组) | ✅(无卡→503) |
| GET | `/api/logs/crash` | **崩溃汇总**:解析最新 `crash_<bootts>.log`(meow_crash 落盘格式)→ 每实体崩溃数 + 最近崩溃时间/信号 + dmesg 计数 | ✅(无卡→503;无 crash 日志→空汇总) |
| GET | `/api/logs/read?file=&lines=` | 读日志(上限 1000 行;`..`/绝对→403;敏感名→403) | ✅ |
| GET | `/api/notifications` | 通知列表(**优先 launcher IPC 内存活跃集** `source:"ipc"`;IPC 不可达回退 TF 转储日志 `source:"tf"`;见 §5.8) | ✅(无源→空态 `source:none`,不 503) |
| DELETE | `/api/notifications/:id` | 单条删除(**优先 IPC 撤下 launcher 内存**;IPC 不可达回退重写日志移除该 id) | ✅(不存在→404) |
@@ -366,6 +369,33 @@ http://<host>.local:8080/
- **`GET /api/ams`** / **`GET /api/svcd`**:即 overview 的 `ams`/`svcd` 子块;源不在 → `{"available":false}`。
- **`GET /api/audio`**:overview 的 `audio` 子块 + rms/peak/lvlseq 消费说明见 §5.12。
### 5.15 批2:崩溃/日志中心 + 音频写 + 后端补缺口(PANEL_ENHANCE_PLAN 批2)
- **崩溃/日志中心(升级 `#/logs`)**:
- **`GET /api/logs/crash`**:读最新 `crash_<bootts>.log`(meow_crash 落盘格式:`<epoch> <uptime> <svc|dmesg> <detail>`;
svc 的 `detail=<name> exit=<code>`/`<name> signal=<sig>`)。聚合出 `{file,count,dmesg_count,dmesg_tail,entities:[
{name,source:"svc",count,last_epoch,last_kind,last_code,last_time,last_detail}]}`;只读、无副作用。
读取有界 `CRASH_TAIL_MAX`=256KB、实体 `CRASH_ENT_MAX`=64、dmesg 保留最近 `CRASH_DMESG_TAIL`=5 行(行数上限保护)。
- **`/api/logs` 文件列表**每项带 `group`(`meow_*→system`/`crash_*→crash`/`ams_*→ams`/`audio_monitor_*→audio_monitor`/
`net_*→net`/`power_*→power`/其余→`app`),供前端按来源分组 + 前缀过滤;`group` 为追加键,向后兼容。
- **崩溃尾巴前置**:崩溃汇总实体行「stdout 尾部」按钮复用批1-B 读取路径(`/api/files?path=/MeowOS/logs/<name>/`
找最新 `stdout_*.log` → `/api/logs/read?file=<name>/<file>&lines=200` 读尾部)。
- **音频写(写级,PIN 已护;前端切换/调高前确认弹窗)**:
- **`POST /api/audio/route`**:`body {port}`。**仅 0=auto/2=3.5/3=4.4**,其余(含 1=lineout/4=SPDIF、5=audiod 内部
强制重烧 FPGA 值)→ 422。audiod 对非法 port 也回 MEOW_OK(内部仅记录不应用),故面板在**发出前**自行校验。
应答 `{accepted,port}`;audiod 不在 → 503 `AUDIO_UNAVAILABLE`。
- **`POST /api/audio/volume`**:`body {value}`。**clamp 到系统 vol_max**(`settings.audio.volume_max`,缺省
`PANEL_VOL_MAX_DEFAULT`=100;设备当前 50)。audiod 内部仅 clamp 0-100、无 vol_max 防护——面板是唯一把守方
(防炸耳红线:平方锥度 `dac=(100-pct)²×192/10000`,接近 100 极响)。应答 `{accepted,value(clamped),applied,vol_max}`。
- **`/api/audio` 补 `vol_max`**(读 settings `audio.volume_max`),前端滑条上限同步 + 「平方锥度非线性」标注 +
「当前值只读显示锥度后百分比」。
- **后端补缺口**:
- **`/api/system` 补 `reboot_reason`/`upgrade_status`**:svc_power 读级查询 `POWER_REBOOT_REASON(8)`/
`POWER_UPGRADE_STATUS(9)`(`st.msg` 分别为 `coldboot=reboot|shutdown|unknown`、`upgrade=yes|no`);查询失败回空串不谎报。
前端批1-B 已留位(读 `d.reboot_reason`/`d.upgrade_status`),此处点亮。
- **`/api/overview` net 块并入 DNS 统计**:netmgrd 状态 JSON 剥外层括号拼入 `{"net":{…,"dns":{…}}}`(复用 `/api/net/dns`
同款统计);DNS 不可用则省略 `dns` 键仅保留网络状态,**绝不假数据**。首页 netCard 改读 `net.dns`,去掉单独 `/api/net/dns`
(首页严格单请求)。
---
## 6. 与协议的出入(「实现为准 + 原因」,供回改 MEOWPANEL_PROTOCOL.md)
@@ -456,7 +486,7 @@ http://<host>.local:8080/
```
patch_v2/meowpanel/
├── meowpanel.c # 后端源码(约 4650 行,-Wall -Wextra 0 warning;含可选鉴权/内联 SHA-256/实时画面+增量帧/触摸注入/通知 IPC 实时化/字体库 tar.gz 导入导出/自然排序/audiod 状态快照)
├── meowpanel.c # 后端源码(约 5590 行,-Wall -Wextra 0 warning;含可选鉴权/内联 SHA-256/实时画面+增量帧/触摸注入/通知 IPC 实时化/字体库 tar.gz 导入导出/自然排序/audiod 状态快照 + 批2 崩溃/日志中心 + 音频写 + overview DNS 聚合)
├── mp_jpeg.c # 最小 baseline JPEG 编码器(顺序 DCT + 4:2:0 + 标准 Huffman,整数定点,无 libm,-Wall -Wextra 0 warning)
├── mp_jpeg.h # mp_jpeg.c 接口(RGB565 → 内存 JPEG)
├── build_meowpanel.sh # 交叉编译 + host 分支(-Wall -Wextra 0 warning;meowpanel.c + mp_jpeg.c)