背景

磨坊项目最初使用”有人云”商业物联网平台,后来决定迁移到自建 MQTT + API 服务器,基于以下考虑:

  • 数据自主可控,不依赖第三方平台
  • 定制化需求灵活实现(自定义告警、历史数据、Web SCADA)
  • 与 Varka 现有基础设施统一(VPS 上的 Docker Compose 编排)

关键决策

决策点选择理由
架构路线路线 A:STM32 作 Modbus 聚合从机,G780s 只轮询一台简单可靠,无需在 G780s 上配置多台 Modbus 从机
数据格式G780s 边缘 JSON 组包(AT+EDGERPTMOD=1不写 Modbus 解码器,G780s 直接输出结构化 JSON
MQTT TLS本期一起做安全不能后补,一次到位
多设备单设备 FM001,不做设备管理简化设计,后续需要再扩展
用户体系admin + user 两个固定账号,不开放注册内网系统,无需多租户
Flutter 身份name=mill,bundle id=com.varka.mill,应用名”磨坊系统”从”管道监控”模板独立出来

新链路

传感器(PT100×4 / 称重×4 / 流量 / 继电器)
   │ Modbus RTU

STM32 F1(Modbus 主站采集变送器 + Modbus 从站 addr=10 对 G780s)
   │ USART3 / Modbus RTU

G780s(Modbus 主站轮询 STM32 + 边缘 JSON 组包 + MQTT 客户端)
   │ MQTT 8883 (TLS), topic: device/FM001/up

mqtt.varka.cn(Mosquitto + 密码 + ACL + LE 证书)


mill-api(Node.js:MQTT 订阅 → g780s_mapper.js → tele schema → 写库 → WS 广播)


api.varka.cn(Nginx + LE)


Flutter "磨坊系统"(com.varka.mill)

与旧链路的区别:

对比项旧链路(有人云)新链路(自建)
数据上报G780s 透传 → 有人云平台G780s 边缘 JSON → MQTT → mill-api
数据解析第三方平台内置自写 g780s_mapper.js
客户端有人云 App自研 Flutter 客户端
告警平台规则引擎后端阈值 + 适配器本地双重评估
历史数据平台存储自建 MySQL + API

分阶段实施

阶段 0:准备

  • 用户操作:G780s FOTA 升级到固件 V2.4.01+
  • 部署:VPS 上配置 Mosquitto passwordfile + aclfile(FM001 设备凭据 + mill-api 服务凭据)
  • 联调:本地 docker compose up -d 跑通,用 mosquitto_pub 模拟一帧 G780s 边缘 JSON 验证字段映射

阶段 1:G780s 配置(纯 AT 命令)

MQTT 客户端配置(通道 1):

AT+MQTTCFG=1,broker=mqtt.varka.cn,port=1883,clientid=dr154-fm001,keepalive=60,cleansession=1
AT+MQTTUSER=1,dr154-fm001
AT+MQTTPSW=1,<密码>
AT+MQTTWILL=1,1,device/FM001/up,1,0,{"t":"offline"}
AT+MQTTPUBTP=1,1,device/FM001/up,1,0
AT+MQTTSUBTP=1,1,device/FM001/down,1

边缘采集启用:

AT+EDGEEN=1
AT+EDGERPTMOD=1
AT+COLLECTTIME=2
AT+POLLTIME=100
AT+POLLTIMEOUT=300

16 项点表录入,对应 STM32 寄存器布局(G780s.h:10-25):

nameslavefcregtype倍率
seq100x030x0000uint161
temp0~3100x030x0001~0004int160.1
weight0~3100x030x0005~000Bint32 ABCD1
flow100x030x000Duint16待核
total100x030x000Euint32 ABCD待核
valid100x03扩展位uint161

上线后 G780s 上报的 JSON 格式:

{
  "params": {
    "dir": "up",
    "id": "<SN>",
    "r_data": [
      {"name": "seq", "value": "42", "err": "0"},
      {"name": "temp0", "value": "235", "err": "0"},
      {"name": "weight0", "value": "12345", "err": "0"}
    ]
  }
}

阶段 2:服务端 API 适配

g780s_mapper.js:将 G780s 边缘 JSON 映射为内部 tele schema:

  • isG780sEdgePayload(payload) 判别 {params:{dir:"up", r_data:[...]}} 形态
  • mapG780sEdgePayload(payload, fallbackDeviceId) 按 name 索引出 seq / temp[0-3] / weight[0-3] / flow / total / valid
  • 温度倍率 0.1,err≠"0" 字段置 null,valid 缺省时按各点 err 拼简化 mask

state.js 分流JSON.parse 后立即检测 G780s 形态并归一化,下游 switch 分支无需感知设备厂商,同时保留对 t:"tele" 直发设备的兼容。

用户 seed:启动时若 users 表为空,按 env 创建 admin / user 两个账号,幂等(仅空表插入)。

阶段 3:Flutter 适配

从”管道监控”模板改造为”磨坊系统”:

改动项旧值新值
pubspec nameprojectmill
Application IDcom.varka.pipemonitorcom.varka.mill
应用名管道监控系统磨坊系统
温度通道7 路(T0-T6)4 路(T0-T3)
Dashboard 卡片压力/流速/心跳全显示值为 0/null 时隐藏

阶段 4:CI/CD 部署

  • GitHub Secrets 新增:JWT_SECRETSEED_*MYSQL_*MQTT_*MOSQUITTO_DEVICE_PWD
  • deploy-server.yml:rsync 前 ssh 渲染 /opt/pipe-monitor/.env,VPS 上渲染 Mosquitto passwordfile
  • 健康检查保留 /health,push main 触发部署

阶段 5:MQTT TLS

  • Mosquitto 加 8883 listener,挂 Let’s Encrypt 证书
  • G780s AT:AT+SSLCFG=1,1 + AT+SSLAUTH=1,1(PEER)+ AT+SSLCRT=1,0,<LE root CA>
  • 端口切到 8883,关闭 1883 公网

18 项任务清单

#状态任务
1待处理G780s FOTA 升级
2待处理VPS Mosquitto 配置
3待处理本地 docker-compose 联调
4待处理G780s MQTT 客户端 AT 配置
5待处理G780s 边缘采集 AT 配置
6待处理G780s 16 项点表录入
7待处理上线抓包验证
8✅ 完成g780s_mapper.js 映射器
9✅ 完成state.js 分流接入
10✅ 完成用户 seed
11✅ 完成Flutter 项目改名
12✅ 完成Flutter 温度 4 通道适配
13🟡 进行中Flutter UI 隐藏空值卡片
14待处理Flutter 注册入口复核
15待处理GitHub Secrets 配置
16待处理deploy-server.yml 修改
17待处理端到端验证
18待处理MQTT TLS

工作量

阶段预估
0 准备0.5 天
1 G780s 配置1 天
2 API 适配0.5 天
3 Flutter 适配0.5 天
4 CI/CD0.5 天
5 MQTT TLS0.5 天
合计3.5 天

已确认的非计划信息

  • Flutter 项目原本只有 Android 平台,无 ios/ 目录
  • 原 namespace com.varka.pipemonitor 表明模板源自”管道监控”项目
  • Dart 代码全部使用相对 import,pubspec name 改动不影响任何 import 语句
  • mill-api 的 db.js 已带 findUserByUsername / createUser,seed 直接复用
  • Mosquitto 现有 aclfile.template 已有 FM001 条目,与本期 topic 完全一致
  • state.js 还有一条 gateway 离线告警分支(device/+/gateway/status),用 LWT 实现可触发离线告警