系统架构设计:三层架构与模块划分
做嵌入式系统这么多年,我有个习惯——拿到需求先画架构图。不是因为我爱画图,而是因为架构一旦定下来,后面80%的坑其实就已经能预见到了。呼吸机数据记录与远程监控系统,说白了就是一个“采集-传输-展示”的闭环。咱们今天就把这个闭环拆开,一层一层讲清楚。
整体架构分层:感知层、网络层、应用层
这个系统我采用的是经典的物联网三层架构。你想想看,为什么非得分三层?因为每一层关注的点完全不同,混在一起只会让代码变成一团乱麻。
| 层级 | 核心职责 | 典型硬件/技术 | 我踩过的坑 |
|---|---|---|---|
| 感知层 | 数据采集与初步处理 | STM32、传感器、ADC | 采样率不够导致波形失真 |
| 网络层 | 数据传输与协议转换 | Wi-Fi/4G、MQTT、TCP | 断网重连逻辑没写好 |
| 应用层 | 数据存储与可视化 | Flask、MySQL、ECharts | 数据库写入太频繁崩了 |
感知层:数据从哪里来
感知层是系统的“眼睛”和“耳朵”。呼吸机的核心数据包括:气道压力、流量、氧浓度、呼吸频率。这些数据通过传感器变成电信号,再经过ADC转换成数字量。
我个人习惯在感知层做两件事:一是数据滤波,二是异常标记。为什么?因为传感器原始数据太“脏”了。我在项目中遇到过,一个松动的接头导致压力波形上全是毛刺,如果不做滤波,网络层传上去的数据全是错的。
网络层:数据怎么传
网络层是系统的“神经”。说白了,就是把感知层处理好的数据,安全、可靠地送到服务器。这里我推荐用MQTT协议,原因很简单——轻量、支持发布/订阅模式、自带心跳保活。
嗯,这里要注意一个关键点:断网重连。我曾经在一个项目中,设备断网后一直卡在重连循环里,导致数据全部丢失。后来我加了一个“指数退避”策略——第一次重连等1秒,第二次等2秒,第三次等4秒……最多等60秒。这样既不会把服务器打爆,也不会错过网络恢复的机会。
// MQTT重连伪代码
int retry_interval = 1;
while (!mqtt_connected) {
if (mqtt_connect() == SUCCESS) {
retry_interval = 1; // 重置
break;
}
delay(retry_interval * 1000);
retry_interval = min(retry_interval * 2, 60);
}
应用层:数据怎么用
应用层是系统的“大脑”。数据到了服务器,要存、要看、要分析。我把它拆成三个子模块:存储模块、Web展示模块、告警模块。
存储模块
呼吸机数据有个特点——高频写入,低频查询。每秒钟可能产生几十条记录,但医生可能一天只看两三次。所以存储方案要针对写入做优化。
我建议用时序数据库,比如InfluxDB。如果团队对SQL更熟悉,MySQL加分区表也行。但千万别用SQLite——并发写入会锁表,我在项目里吃过这个亏。
Web展示模块
Web展示模块我用Flask + ECharts。Flask轻量、灵活,适合做嵌入式系统的后端。ECharts画波形图非常方便,尤其是实时曲线。
你想想看,医生最关心什么?不是原始数据,而是趋势。所以Web页面要展示:实时波形、历史趋势、异常事件列表。我个人习惯把实时波形放在最显眼的位置,因为呼吸机数据变化太快,延迟超过1秒就可能误判病情。
模块划分:各司其职
模块划分的原则是高内聚、低耦合。每个模块只做一件事,模块之间通过接口通信。我把它分成四个模块:
- 数据采集模块:负责传感器驱动、ADC读取、数据滤波。运行在STM32上。
- 通信模块:负责MQTT连接、数据打包、断网重连。运行在ESP32或4G模块上。
- 存储模块:负责数据入库、历史查询、数据压缩。运行在服务器上。
- Web展示模块:负责页面渲染、实时刷新、告警推送。运行在服务器上。
架构图(文字版)
画个简单的架构图,方便你理解:
+------------------+ +------------------+ +------------------+
| 感知层 | | 网络层 | | 应用层 |
| STM32 + 传感器 | ----> | ESP32 + MQTT | ----> | Flask + MySQL |
| 数据采集模块 | | 通信模块 | | 存储模块 |
| | | | | Web展示模块 |
+------------------+ +------------------+ +------------------+
这个架构看起来简单,但实际落地时每个环节都有坑。别急,后面几章我会把每个模块的代码和调试过程一步步拆开讲。你跟着做一遍,就能真正理解这套系统是怎么跑起来的。