一、数据采集:从传感器到屏幕
物联网数据的特点是高频、大量、时序性强。
1.1 端-边-云一体化架构
-
端侧:MCU 采集传感器数据,经通信模组上传。
-
边缘侧:网关/边缘节点负责数据过滤、聚合、本地缓存。例如:每 100ms 采集一次,但只取每秒平均值上报云端;异常值触发本地报警。
-
云端:长期存储、跨设备分析、模型训练。
优势:降低带宽和云端压力,断网时边缘仍可自治。
1.2 数据流处理与时序数据库
典型数据流:
传感器 → MQTT Broker → 数据处理器(如规则引擎)→ 时序数据库 → App 查询
时序数据库推荐:
-
IoTDB:专为物联网设计,压缩比高,支持 SQL-like 语法,可边缘部署。
-
InfluxDB:生态成熟,Grafana 原生支持。
-
TimescaleDB:基于 PostgreSQL,适合习惯 SQL 的团队。
App 端查询示例(伪代码):
javascript
// 查询过去 24 小时的温度数据,每分钟一个点
GET /api/v1/device/{id}/telemetry?metric=temperature&window=1m&duration=24h
踩坑:
-
不要在前端一次性拉取几万条数据点,应使用下采样(downsampling)或滚动加载。
-
时序数据库的 timestamp 建议使用毫秒级时间戳,并注意时区统一为 UTC。
1.3 数据可视化方案
-
专业仪表盘:Grafana(开源,可嵌入 WebView 或直接暴露给用户)。
-
App 原生图表:
-
Android:
MPAndroidChart -
iOS:
Charts(Daniel Gindi 版) -
Flutter:
fl_chart -
React Native:
react-native-svg-charts
-
性能优化 :对高频实时数据(如 10Hz),App 端应使用增量更新而不是全量重绘。
二、远程控制:从指令下发到执行反馈
一个完整的控制闭环包含:指令下发 → 设备执行 → 状态反馈。
2.1 MQTT 实现控制
控制流程:
-
App 向
cmd/deviceId主题发布 JSON 指令(如{"action":"toggle","target":"light"}) -
Broker 推送给设备
-
设备执行后向
stat/deviceId主题发布新状态 -
App 订阅该主题更新 UI
可靠指令设计:
-
每条指令带唯一
msgId,设备回复时带回此 ID,App 可做 ACK 确认。 -
超时重传:若 3 秒内未收到设备回复,App 可重发(需保证幂等)。
2.2 WebRTC 实时音视频控制
对于摄像头、机器人等场景,MQTT 无法满足低延迟视频传输。采用 WebRTC:
-
App 端使用 WebRTC 原生库(Android 官方
libwebrtc,iOS 使用 GoogleWebRTC pod) -
信令交换可通过 MQTT 或 WebSocket 完成
-
媒体流走 UDP,延迟通常低于 500ms
踩坑:STUN/TURN 服务器需要自建或购买服务,否则 NAT 穿透失败率较高。
2.3 安全机制(不可忽视)
| 层面 | 措施 | 常见错误 |
|---|---|---|
| 网络传输 | TLS/DTLS 加密 | 使用 tcp:// 明文传输 |
| 设备认证 | 一机一密(ProductKey + DeviceSecret) | 所有设备共用固定密码 |
| 用户权限 | OAuth2 + RBAC(基于角色的访问控制) | 不校验用户是否有权控制该设备 |
| 指令审计 | 记录操作日志(谁、何时、发了什么指令) | 无日志,出事无法追溯 |
生产级建议:
-
禁止在 App 中硬编码 ProductSecret,应从服务端动态获取临时 token。
-
敏感操作(如开锁、启动电机)需要二次确认或生物认证。
三、实战案例:智能家居控制系统完整实现
3.1 硬件选型
-
主控:STM32F103C8T6(72MHz,32KB SRAM)
-
传感器:DHT11(温湿度)
-
执行器:继电器模块(控制灯/风扇)
-
通信:ESP8266-01S(通过 UART 与 STM32 通信,使用 MQTT 协议)
-
显示:0.96寸 OLED(I2C 接口)
3.2 软件架构
STM32 固件:
每 100ms 读取 DHT11
通过 AT 指令控制 ESP8266 连接 Wi-Fi 和 MQTT Broker
循环解析串口收到的 MQTT 消息,执行继电器动作
App(以 Flutter 为例):
使用 mqtt_client 库连接同一个 Broker
订阅 telemetry/+/temperature 实时绘制曲线
点击按钮发布控制指令到 cmd/light/switch
3.3 关键代码片段
STM32 串口解析 MQTT 指令(伪代码):
cpp
if (strstr(rx_buffer, "cmd/light/switch")) {
if (strstr(rx_buffer, "on")) {
HAL_GPIO_WritePin(RELAY_PIN, GPIO_PIN_SET);
uart_send("stat/light/switch on");
}
}
App 端 MQTT 订阅与发布:
Dart
final client = MqttClient('tcp://broker.emqx.io', 'flutter_client');
await client.connect();
client.subscribe('telemetry/+/temperature', MqttQos.atLeastOnce);
client.publishMessage('cmd/light/switch', 'on', MqttQos.atLeastOnce);
3.4 功能清单
| 功能 | 实现方式 | 数据流向 |
|---|---|---|
| 温湿度上报 | DHT11 + STM32 → ESP8266 → Broker | 上行 |
| App 实时曲线 | 订阅 telemetry 主题,每 1 秒刷新图表 | 下行 |
| 远程开关灯 | App 发布 cmd 主题 → Broker → 设备 | 下行 + 上行确认 |
3.5 自动化扩展(可选)
可在边缘网关或云端配置规则引擎,例如:
-
温度 > 30°C → 自动发送
cmd/fan/on -
光照 < 100 lx → 自动开灯
四、总结与踩坑经验集锦
4.1 开发流程建议
-
先模拟后真机:用 MQTT 客户端软件(如 MQTTX)模拟设备行为,验证 App 逻辑。
-
日志先行:在 App 和设备端都打上完整的收发日志,尤其要包含时间戳和 msgId。
-
弱网测试:使用 Network Link Conditioner(iOS)或 Android 模拟器限速,观察重连和重传行为。
4.2 常见踩坑 Top 5
| 坑 | 表现 | 解决方法 |
|---|---|---|
| BLE 扫描不到设备 | Android 12+ 无回调 | 同时申请 BLUETOOTH_SCAN 和 ACCESS_FINE_LOCATION |
| MQTT 重连后收不到消息 | 设备/App 重启后订阅丢失 | 在连接成功回调中重新订阅所有主题 |
| 控制指令延迟很大 | 默认 keepAlive 太长,或 Broker 负载高 | 使用 QoS 1,并开启 Broker 的持久会话 |
| 时序数据查询慢 | 前端请求全量数据 | 后端实现下采样(如保留每分钟平均值) |
| iOS 上 App 被杀后无法唤醒 | 未使用远程推送(APNs) | 对需要实时响应的控制,配合推送通知唤醒 App |
4.3 推荐学习资源
-
MQTT 协议:官方规范 v5.0 文档
-
BLE 开发 :Android 官方
BluetoothLeGatt示例 -
时序数据库:IoTDB 官方文档中的"物联网场景最佳实践"
-
开源项目:GitHub 上搜索 "SmartHome MQTT Flutter" 可找到完整参考代码
结语
物联网 App 开发是一条需要同时摸到软件和硬件的道路。本文下篇涵盖了数据采集、远程控制、安全机制和完整实战案例,希望能帮助你从"能连接设备"进阶到"能稳定控制和可视化数据"。