要加一个 Android 客户端,让手机也能看实时数据、报警、历史,能问问题、能控制风扇。 设备通过串口接在 PC 上。
| 方案 | 取舍 |
|---|---|
| 手机直连设备(USB OTG 或蓝牙) | 手机要重新实现一遍串口、拼帧、协议、报警、统计。两份实现迟早不一致;而且串口是独占的,手机和电脑不能同时连 |
| 独立的网关服务进程 | 标准做法,可伸缩;但 PC 上位机已经实现了设备管理、数据处理、报警、控制的全部职责,另起一个进程只是把它们再搬一遍 |
| PC 上位机进程内加一层网络接口 | 一台 PC 加几台手机的规模不需要网关与客户端分离的伸缩性;局域网内也不需要公网服务器 |
网关是 PC 上位机的又一个呈现端,与桌面界面平级,同样只经 api.ApiInterface 访问系统:
┌─► ui (转成 Qt 信号,给桌面界面)
api.ApiInterface ┤
└─► gateway (转成 HTTP 响应与 WebSocket 消息,给手机和浏览器)
ui,也不被 ui import。两个呈现端互相不知道对方存在每个端点都是某个已有 ApiInterface 方法的直译,网关里不写业务逻辑。
同步回调到异步推送的桥。 数据回调是同步的,跑在采集线程上;WebSocket 发送是异步的。
EventHub 用 call_soon_threadsafe 把消息投递到事件循环,再扇出给每个客户端:
/health 暴露,丢弃是可观测的,不是静默的publish() 承诺永不抛出异常:它在数据管线上被同步调用,事件循环关闭之类的情况静默返回问答分两段。 REST 立即返回模板答案(毫秒级),模型改写好之后(数秒)经 WebSocket 补送替换。 如果让请求挂着等模型,没接模型的部署也会变慢,手机端一旦超时就什么都拿不到。分成两段之后, 只调 REST 的客户端总能拿到正确答案,接了 WebSocket 的多收一条更自然的版本。
串口只有一个。 桌面界面和网关要同时看数据,只能在一个进程里同时承载两者(run_all.py),
数据只解码一次,再扇出给两边——不能起两个程序去抢同一个 COM 口。
向后兼容靠”只增不改”。 后来为浏览器控制台加的接口与消息类型,REST 只增字段、WebSocket 只增类型。 Android 的消息解析器对不认识的类型返回”未知”并忽略,旧版 App 不受影响。
api 以下六层零改动。这是”呈现端按平台并列实现、共用一个概念接口”这条设计的实证