ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

33 嵌入式操作系统 | 模块七验收:端到端一键验收 + 项目答辩

2026/10/3 12:41:36 拓冰建站 浏览量
33 嵌入式操作系统 | 模块七验收:端到端一键验收 + 项目答辩 嵌入式操作系统 | 模块七验收端到端一键验收 项目答辩本课程开源地址Giteehttps://gitee.com/fujianxinxi/qianrushixitongyingyongkaifa.git课件、示例代码与验收脚本都在该仓库可直接git clone或下载 ZIP 使用。模块七 · 2 学时 · 环境Ubuntu完整项目环境 socat 虚拟串口一句话概述这节课不写新功能只做两件事——① 用acceptance.sh一键把整条链路重跑一遍逐项打勾本节实测27 项全通过② 按《验收清单》自评、按《答辩提纲》演练 5 分钟讲解。学完这节你手上有一个能演示、能交付、能自愈的小系统。本节目标会用一条命令 一个现象的方式证明每个功能点这就是回归测试的思路能独立跑通acceptance.sh看懂每一项检查在验什么、失败时怎么查会按《验收清单》给自己打分A 功能 60 / B 健壮性 20 / C 工程化 12 / D 交付答辩 8能按《答辩提纲》讲清架构、演示主流程、回答原理题一、讲解内容1.1 知识讲解① 验收和我觉得能跑的区别.验收的核心是可复现的证据不行的说法验收要的写法“网页能控制设备”执行wget -qO- http://127.0.0.1:5000/cmd?nameled_on4 秒后ubus call device status里led: 1“掉线能发现”杀掉面板6 秒后/api/state里online:0重启面板 6 秒后变回1“挺健壮的”灌一帧坏 CRC网关日志出现串口帧 CRC 失败…丢弃之后ser_rx继续增长②acceptance.sh的设计思路十项27 个检查点段检查什么用到的组件①环境socat / libubox / libubus / Flask / pyserial / uciubus / systemd课时 15、24②虚拟串口建立socat③设备面板在发帧 网关起来了 认到设备课时 26、31④状态表正确online1、ser_rx0课时 29、31ubus⑤每 2 秒0x81上报课时 29⑥网页显示在线 点按钮能改状态课时 30⑦掉线判 0 / 恢复判 1课时 29、30⑧灌坏帧后照常工作课时 32⑨systemd 服务化 kill -9自愈课时 32⑩清理现场进程/端口/服务全部脚本的骨架非常朴素——一个计数器 两种打印PASS0;FAIL0ok(){echo [通过]$1;PASS$((PASS1));}bad(){echo [失败]$1;FAIL$((FAIL1));}command-vsocat/dev/nulloksocat 已安装||badsocat 未安装最后if[$FAIL-eq0];thenecho验收通过;elseecho有$FAIL项没过;fi③ 为什么必须一键十个检查点手工做一遍要十几分钟而且容易漏写成脚本以后每次改代码都重跑一遍回归测试改坏了立刻能发现是哪一项坏了。这也解释了课时 32 为什么要搞故障注入——验收里必须包含坏情况。④ 验收清单100 分与答辩5 分钟见同目录两份文件代码/课时33-项目验收/验收清单.mdA 功能 60 分、B 健壮性 20 分、C 工程化 12 分、D 交付答辩 8 分每项都写了怎么证明代码/课时33-项目验收/答辩提纲.md5 分钟时间分配 12 个常问问题 加分/扣分项⑤ 整个模块七做出来的东西复习地图课时做了什么关键文件24环境 协议契约check_env.py、hello_qt.py、hello_flask.py、协议契约.md25设备面板界面PyQt5device_panel.py/device_panel_full.py26面板接串口半帧/CRC/断线重连device_panel_serial.py、serial_monitor.py27网关雏形串口 ⇄ UDPgateway.c、udp_client.py28网关 TCP 命令通道粘包/半包/多客户端gateway_tcp.c、tcp_client.py29状态表 每 2 秒上报 在线判定gateway_full.c、state_listener.py30网页上位机显示 控制闭环app.py31产品化配置读 uci 状态走 ubusgateway_pro.c、device.conf、ubus_query.sh32可靠性故障注入 systemd 自愈fault_device.py、fault_tcp.py、gateway.service、install_service.sh33验收一键端到端 答辩acceptance.sh、验收清单.md、答辩提纲.md1.2 操作步骤一条命令一步看现象实测环境是在代码/目录下脚本里的路径指向各课时目录同学们按自己的目录改路径即可。第 0 步先把总机和网关程序准备好pgrep-xubusd/dev/null||sudoubusd# ubus 总机课时 31 用过ls~/lab/课时31-网关产品化uci与ubus/gateway_pro# 网关程序课时 32 守护的就是它uci show device|head-3# 配置在位第 1 步★跑一键验收约 1~2 分钟cd~/lab/课时33-项目验收sudo./acceptance.sh# 想快点./acceptance.sh --quick跳过完整故障注入现象实测27 项全通过、0 失败 模块七 综合项目 验收 时间2026-09-26 06:04:04 【① 环境检查】 [通过] socat 已安装 [通过] libubox 头文件在位 [通过] libubus 头文件在位 [通过] Flask 可用 [通过] pyserial 可用 [通过] uci / ubus 可用 [通过] systemd 可用 【② 建立虚拟串口】 [通过] 虚拟串口 /tmp/ttyV0 - /tmp/ttyV1 已建立 【③ 设备面板 网关】 [通过] 设备面板在发 0x80 状态帧 [通过] 网关已启动配置读 /etc/config/device [通过] 网关认到了设备状态表已建立 【④ 网关状态查询ubus】 [通过] ubus call device status 有返回 [通过] online 1设备在线 [通过] ser_rx 3串口确实收到过帧 【⑤ 状态上报每 2 秒 0x81】 [通过] 监听端 5 秒内收到 3 帧 0x81 上报 收到 55 AA 81 05 00 00 00 F7 01 0D AD → 灯 灭 | 风扇 0 档 | 24.7 ℃ | 在线 【⑥ 网页上位机显示 控制】 [通过] /api/state 显示设备在线 [通过] 网页按钮控制成功led1 fan2 【⑦ 设备掉线判定与恢复】 [通过] 设备掉线后 online 变成 0 [通过] 设备回来后 online 自动恢复成 1 【⑧ 故障注入坏帧不影响正常工作】 [通过] 网关识别并丢弃了坏 CRC 帧 [通过] 故障注入后网关照常收帧ser_rx 25 → 50 [通过] 故障注入后设备仍在线 【⑨ systemd 守护与自愈】 [通过] 服务已启动systemctl is-active active [通过] kill -9 后服务被自动拉起active [通过] 重启次数 NRestarts 2 [通过] 服务已卸载现场恢复干净 【⑩ 清理现场】 [通过] 所有进程已停止端口已释放 验收结果 通过27 项 失败0 项 结论模块七 综合项目 验收通过 ✓第 2 步按《验收清单》给自己打分less~/lab/课时33-项目验收/验收清单.md逐条对照把A 功能 60 / B 健壮性 20 / C 工程化 12 / D 交付答辩 8填完。acceptance.sh覆盖了其中绝大部分可自动化的项剩下的代码整洁、README、答辩由老师和同学互评。第 3 步★换一个终端/新环境再跑一遍真正的验收# 换一个干净终端或者在新克隆的目录里按 README 从头跑一遍cd~/lab/课时33-项目验收sudo./acceptance.sh这一步的意义证明你的项目不是只能在你机器上跑。常见翻车点路径写死、忘了装某个包、忘了uci commit、忘了起ubusd。第 4 步答辩演练5 分钟掐表less~/lab/课时33-项目验收/答辩提纲.md按提纲的四段做一遍① 架构图 1 分钟 → ② 主流程演示 2 分钟 → ③ 掉线 自愈 1 分钟 → ④ 坑与收获 1 分钟。再让同桌随机问12 个常问问题里的 3 个答不上来的回去补。第 5 步收工。脚本已自动清理进程/端口/服务都还原ubusd可留可停sudo pkill -x ubusd。1.3 常见错误与排查现象原因解决④ 报ubus 查询没返回ubusd 没启动sudo ubusd 或ls -l /var/run/ubus/ubus.sock确认③ 报设备面板没有发帧面板没起来PyQt/Xvfb 问题看/tmp/acc_panel.log无桌面时用xvfb-run python3 device_panel_serial.py③ 报网关没起来9000 端口被占 / 串口打不开ss -ltnp | grep 9000杀掉旧进程确认 socat 起了⑤ 报5 秒内没收到上报网关的上报目标不是127.0.0.1:9100看/tmp/acc_gw.log的启动行或uci show device | grep report⑥ 报/api/state 不对5000 被占 / 网页没起来看/tmp/acc_app.logss -ltnp | grep 5000⑦ 掉线判不出来offline_ms配得太大uci set device.main.offline_ms3000 uci commit device后重启网关⑨ 服务 self-heal 失败systemd 不可用容器里常见用虚拟机跑或在真机上确认 PID 1 是 systemd脚本跑完端口还被占上一次跑挂了没清理pkill -f gateway_pro; pkill -x socat或重启虚拟机全部失败但手工跑却正常目录不对脚本找各课时目录找错了脚本用$0自动算出C26/C29/C30/C31/C32从脚本所在目录往上两层取代码/仓库 clone 或解压到哪都能跑只有你把某个课时目录搬走时才需要改开头的这几行二、学生练习本节命令速查表命令作用示例sudo ./acceptance.sh一键端到端验收十项 27 检查点--quick快跑sudo ubusd 起 ubus 总机④ 需要早已在课时 31 做过less 验收清单.md/less 答辩提纲.md自评 / 演练边看边填exit $FAIL式的脚本骨架自己写检查脚本见 1.1 的ok/bad编号任务提示预期结果L33.1跑通acceptance.sh第 1 步27 项全通过L33.2故意制造一处失败改offline_ms为 60000 再跑⑦ 报失败学会看哪项红了L33.3给脚本加一个新检查点例如检查/etc/config/device里的report_ms与网关启动行一致脚本变 28 项L33.4写自己的 README别人照着能跑通含依赖、步骤、现象同桌按它跑一遍不出错L33.5按清单自评逐项填自测列分数 ≥ 85L33.6答辩演练掐表 5 分钟 随机抽 3 问讲解流利、问题能答三、作业模块七项目交付物必交按此清单打包命名学号-姓名-模块七项目/#交付物要求1代码课时 24~32 你写/改过的文件gcc -Wall -Wextra零警告2README.md依赖清单、编译命令、运行步骤几个终端分别跑什么、预期现象、常见问题3协议契约.md帧格式、CRC、类型表可沿用课时 24 的版本改动要更新4验收截图/记录acceptance.sh的完整输出27 项 网页界面截图 掉线/自愈各一张5《验收清单》自评表逐项打分并写一句依据6答辩提纲按模板填自己的架构图与两个坑思考题写在 README 末尾验收脚本里哪几项是功能、哪几项是健壮性、哪几项是工程化为什么验收要三者都覆盖如果要把这个项目搬到真实硬件设备换成单片机 真串口网关跑在 ARM 开发板上你需要改哪些地方提示串口路径、交叉编译、systemd、网络这个项目里哪一处最脆弱如果要再加一道保险你会加什么四、模块七小结把整条链路再走一遍①设备面板(PyQt5) ②网关(C, uloop) ③上位机(Flask 网页) ┌───────────────┐ 串口 ┌──────────────────────┐ TCP命令 ┌──────────────┐ │ 灯/风扇/温度 │ 55AA帧 │ 四道防线帧头→LEN→CRC │◀────────│ 按钮(表单) │ │ 0x80 每秒上报 │ ─────▶ │ →类型 │ │ │ │ 收命令改状态 │ ◀───── │ 状态表(灯/风扇/温度/在线)│ UDP上报 │ 页面显示状态 │ └───────────────┘ │ 0x81 每 2 秒上报 │ ──────▶ │ /api/state │ │ 配置读 uci、状态走 ubus │ 0x81 └──────────────┘ └──────────────────────┘ ↑ systemd 守护挂了自动起协议55 AA | TYPE | LEN | PAYLOAD | CRC16(低字节在前)TCP 外加 2 字节大端长度前缀职责划分设备只管状态 执行命令网关管转帧 记状态 判在线 对外提供接口上位机管显示 控制工程化三件套配置外置uci、状态可查ubus、崩溃自愈systemd可靠性三件套帧同步 CRC 校验坏数据不进门、缓冲区上限不被灌爆、在线判定失联能发现全课程回头看模块一~六Ubuntu 基础、C 语言与结构体、进程与服务、网络编程、uloop 事件驱动、uci/ubus/JSON到这里都变成了一个能演示的项目里的一颗螺丝钉——这就是嵌入式 Linux 应用开发的完整套路。继续往哪走选修/毕设方向① 换成真实传感器DHT11/DS18B20与真串口② 用 SQLite 存历史数据 画曲线③ 用 MQTT 把状态发给云平台④ 交叉编译到 ARM 开发板课时 16 起的库要在板子上重新编⑤ 给网页加登录与权限。附录怎么运行 脚本关键代码三个文件在代码/课时33-项目验收/acceptance.sh一键验收十项 27 检查点、验收清单.md100 分自评表、答辩提纲.md5 分钟讲解 12 问。附录 A完整跑一遍含前置依赖# ⓿ 前置课时 24~32 的环境与程序都就位 sudoaptinstall-ysocat python3-pyqt5 python3-serial python3-flask xvfbls/usr/local/lib/libuci.so /usr/local/lib/libubus.so# 课时 15 编的ls~/lab/课时31-网关产品化uci与ubus/gateway_pro# 课时 31 编的uci show device|head-3# 课时 31 装的配置# ① 起 ubus 总机验收第 ④ 项要用sudoubusd# ② 一键验收 cd~/lab/课时33-项目验收sudo./acceptance.sh# 约 1~2 分钟--quick 可跳过完整故障注入# ③ 看结果 # 通过27 项 失败0 项# 结论模块七 综合项目 验收通过 ✓# ④ 自评 答辩演练 less验收清单.mdless答辩提纲.mdacceptance.sh开头的C26/C29/C30/C31/C32按脚本自身位置算脚本在代码/课时33-项目验收/往上两层就是代码/所以整仓库 clone / 解压到任何目录都能直接跑不用改路径。另外仓库里不带 C 编译产物首次运行脚本会自动用 gcc 编译课时 31 的gateway_pro编过了就跳过所以第 ⓿ 步不手工编译也能跑。附录 Bacceptance.sh的关键写法B-1 计数与打印整个脚本的骨架PASS0FAIL0ok(){echo [通过]$1;PASS$((PASS1));}bad(){echo [失败]$1;FAIL$((FAIL1));}# 单项检查条件成立就通过否则失败[-f/usr/local/include/libubus.h]oklibubus 头文件在位||bad缺 libubus回课时 15B-2 把现象变成可判断的条件# 环境是否齐全command-vsocat/dev/nulloksocat 已安装||badsocat 未安装# 设备帧是否真的在发读面板日志grep-aq发送 0x80/tmp/acc_panel.logok设备面板在发 0x80 状态帧||bad设备面板没有发帧# 状态表是否正确从 ubus 的 JSON 里抠字段STATUS$(ubus call device status2/dev/null)echo$STATUS|grep-qonline: 1okonline 1设备在线||badonline 不是 1RX$(echo$STATUS|grep-oser_rx: [0-9]*|grep-o[0-9]*)[${RX:-0}-gt0]okser_rx $RX串口确实收到过帧||badser_rx 0B-3 主动做动作再检查掉线、自愈# 掉线杀掉设备 → 等 6 秒 → 看 online 是否变 0pkill-fdevice_panel_seria[l]sleep6OFF$(wget-qO- http://127.0.0.1:5000/api/state|grep-oonline:[0-9]*|grep-o[0-9]*)[${OFF:-1}0]ok设备掉线后 online 变成 0||bad掉线没判出来online$OFF# 自愈kill -9 → 等 5 秒 → 服务还在 active 且 NRestarts ≥ 1PID1$(systemctl show-pMainPID--valuedevice-gateway)kill-9$PID1sleep5[$(systemctl is-active device-gateway)active]okkill -9 后服务被自动拉起||bad自愈失败NR$(systemctl show-pNRestarts--valuedevice-gateway)[${NR:-0}-ge1]ok重启次数 NRestarts $NR||badNRestarts $NRB-4 收尾一定要清理trap保证异常退出也清理cleanup_all(){[-n${APP:-}]kill$APP2/dev/null[-n${LISTEN:-}]kill$LISTEN2/dev/null[-n${GW:-}]kill$GW2/dev/nullpkill-fdevice_panel_seria[l]2/dev/null$C32/install_service.sh--uninstall/dev/null21pkill-xsocat2/dev/nullsleep1}trapcleanup_all EXIT导出结论exit 0全通过/exit 1有失败—— 这样以后放进 CI比如 gitee 的流水线也能用。