12 KiB
💧 水厂智能货柜(IoT)分布式终端接入与自动化交付技术白皮书
一、 业务愿景与战略定位
本方案旨在通过 IoT(物联网) 硬件矩阵,实现水厂饮用水交付的全面自动化与去人工化。针对无屏幕、定位提货、套餐保值等核心需求,构建“线上订水、LBS 匹配、无感交付”的智慧物流体系。
二、 核心应用场景与业务需求模型
1. 定位提货与套餐保值逻辑
- 需求: 用户购买桶水套餐,不受后续调价影响;定位用户小区并呈现所有单元楼提水点,实现远程库存预览,防止用户“跑空”。
- 小程序实现:
- 权益钱包:引入“虚拟储水池”概念,用户购买套餐后,账户记录为“待取桶数”,而非金额,实现锁价保值。
- LBS 智能网格:首页通过
uni.getLocation获取坐标,服务器根据经纬度反向检索关联小区,并在地图上以“桩位”形式展示该小区内所有单元楼下对应的提柜状态(空闲/库存数)。 - 【新增机制:空柜自动调导 (Self-Correction)】:当某单元楼货柜库存为 0 时,地图图标转为置灰状态并显示“补货中”,同时系统自动计算并推荐该小区内距离最近的“有货柜机”。
2. 无屏幕式“无感核销”模式(蓝牙/云端直控)
- 需求: 货柜感应 + 云端瞬时指令”**模式。
- 操作流:用户靠近货柜
\rightarrow手机蓝牙自动识别设备号(Beacon 广播)或 LBS 确认经纬度重合\rightarrow小程序自动弹出“当前已到达XX单元提水点”\rightarrow用户在手机点击“开门”\rightarrow云端通过 MQTT 指令开锁。 - 价值:降低硬件成本(无屏、防暴力),提升交互流畅度。
- 操作流:用户靠近货柜
3. 故障闭环与客服联动系统
- 需求: 下单不开门、没电、库存不足等异常,自动切入客服协助。
- 业务逻辑:
- 主动监测:系统 15 秒内未收到门磁反馈,自动触发“开启失败弹窗”。
- 一键路由:弹窗直接集成“在线客服”与“紧急开锁申请”。对于电池电量低于 10% 或库存为 0 的柜体,小程序端自动置灰并置顶显示“联系客服维修/补货”。
4. 商家端(水厂)实时监控看板
- 需求: 实时获取补货、电量、库存等全量信息。
- 技术看板:
- IoT 设备画像:每个柜子都有实时“血条”(电量指示)和“胃容积”(库存比例)。
- 热力算法:根据库存消耗频率,自动标注哪些柜子属于“急需补货”级别。
5. 补货员/检修员管理系统(工单派发制)
- 需求: 考核规定时间内补货及检修。
- 小程序程序设定:
- 强时效工单:系统检测到库存不足或电池耗尽,自动生成“4小时响应工单”指派给最近的运维员。
- 到岗打卡:运维员必须到达柜体 5 米范围内(经纬度校验),才能开启“运维门”进行操作。
- 闭环报告:补货完成后,自动上报最新重量数据,系统同步更新前台库存。
三、 全链路技术架构与数据流向
1. 四层架构模型
- 物理执行层(Edge):基于 ESP32/工业级 4G 模组的主控板,集成继电器、重力传感器、温湿度计。
- 网络传输层(Network):采用 MQTT 协议,基于 TLS/SSL 加密,确保指令在复杂小区环境下的秒级送达。
- 业务逻辑层(Service):负责权益校验、库存动态调拨、支付分账逻辑判断。
- 应用展示层(Application):用户小程序(取水/充值)、商家管理后台(核销)、补货员 App(工单管理)。
2. 高级交互序列图 (Sequence Diagram)
`mermaid sequenceDiagram participant U as 消费者小程序 participant S as 业务中台 (PHP/Node.js) participant M as MQTT 消息总线 (EMQX) participant C as 智能货柜终端 participant P as 微信支付分/代金券接口
U->>S: 1. 扫码查阅柜体 (LBS+设备ID)
S-->>U: 2. 返回可用库存 & 专属优惠券
U->>S: 3. 点击“确认取水” (权益预扣)
S->>P: 4. 冻结余额/校验代金券状态
P-->>S: 5. 状态确认
S->>M: 6. 下发指令 (QoS 1: 至少送达一次)
M->>C: 7. 物理开门指令 (带加密Nonce)
C->>C: 8. 传感器检测门启
C->>M: 9. 实时反馈:门已开
M-->>U: 10. 小程序提示:请取水
Note over C: 用户提取桶装水...
C->>C: 11. 传感器检测门闭 & 重量减扣
C->>M: 12. 最终交易报文 (补货建议点)
M->>S: 13. 结算请求
S->>S: 14. 正式扣减权益 & 生成财务报表
`
四、 通信协议与数据字典规范
1. 指令安全加固
采用 HMAC-SHA256 对指令进行签名,防止中间人攻击或恶意开门。
Payload 样本:
json { "header": { "sn": "WH-CAB-2024-001", "ver": "1.2.0", "nonce": "8h7g2k1l" }, "body": { "action": "REMOTE_OPEN", "params": { "slot": 1, "timeout": 30 }, "sign": "5e8f...f2a1" } }
2. 状态机定义 (State Machine)
- IDLE: 空闲状态,等待指令。
- LOCKED: 权益校验通过,正在下发脉冲。
- BUSY: 用户正在交互(取水进行中)。
- MAINTENANCE: 故障或补货模式,小程序下线该节点。
五、 核心功能模块代码深度实现
1. 智能防刷与补偿逻辑 (小程序/后端)
问题场景:用户点了开门但信号不好,或者门坏了没开,如何保证不误扣费?
`javascript // 后端:具备“事务性”的开门逻辑 async function secureOpenProcess(userId, cabinetId) { const transaction = await db.startTransaction(); try { // 1. 锁券:先将福利券/水票设为“占用中” await transaction.collection('vouchers').update(query, { status: 'PENDING' });
// 2. 下发异步指令,设置 15 秒确认窗口
const result = await mqttService.publishWithAck(cabinetId, 'open', 15000);
if (result.ack === 'SUCCESS') {
await transaction.commit(); // 指令送达,提交事务
return { success: true };
} else {
throw new Error('DEVICE_OFFLINE');
}
} catch (e) { await transaction.rollback(); // 失败回滚,水票自动返还 return { success: false, reason: e.message }; } } `
2. 补货员端:基于路径优化的库存盘点
`python
逻辑伪代码:根据告警级别生成最优补货路径
def generate_refill_route(warn_cabinets): # 排列优先级:告警等级(0-100) > 距离 priority_list = sorted(warn_cabinets, key=lambda x: (x.alert_level, x.distance)) return priority_list # 返回给补货员 App 的任务流 `
六、 智能货柜接入小程序的标准化流程 (Access Standard)
1. 核心逻辑:如何核验并完成取水(从下单到核销)
针对你疑惑的“下单后如何核验取水”,本项目采用 “虚拟权益池 + 动态指令核销” 机制。以下是详细的核验方案:
A. 权益发放(下单阶段)
- 资产化:用户下单购买后,系统不只是生成一个订单,而是在数据库中为用户
OpenID增加“电子水票/桶数”资产(如:可用余额 +10 桶)。 - 权益凭证:系统生成一组不记名的电子权益 ID,状态标记为
UNUSED(未使用)。
B. 身份与位置核验(扫码阶段)
- 设备匹配:用户扫码,小程序获取
cabinet_id。系统即刻下发 MQTT PING 指令确认柜机通讯链路活跃。 - **位置强校验 **(针对无蓝牙环境增强)****:
- 小程序调用
uni.getLocation获取手机经纬度。 - 后端比对:将手机位置与柜子的注册坐标进行计算(Haversine 公式)。
- 判定:距离 < 50 米时,判定为“到店”,激活“开门按钮”;否则提示“请到达柜机旁操作”。
- 小程序调用
- 在线预警:若 MQTT 链路超时未响应,按钮置灰并提示“柜机离线中,请稍后再试”,防止用户重复扣款。
C. 权益核销(开门阶段)
- 预锁定:用户点击“确认开门”,后端立即执行
Transaction(事务):- 查询用户是否有可用余额。
- 将 1 份权益设为
LOCKING(锁定中),防止并发重复开启。
- 指令下发:通过 MQTT 向货柜发送
UNLOCK_CABINET指令。 - 状态反馈:
- 成功:货柜反馈“门已开启”,权益标记为
USED(已使用),生成核销流水。 - 失败:若 15 秒内未收到开门反馈,直接接入客服系统,让客服处理这笔订单。
- 成功:货柜反馈“门已开启”,权益标记为
2. 身份识别与设备绑定(参数二维码体系)
- 二维码本质:机身二维码并非静态图片,而是携带设备 ID 的“动态索引链接”(例如:https://domain.com/q?id=10001)。
- 批量生产规范:
- 映射逻辑:后端建立 设备SN - 设备ID - 二维码URL 的 1:1 映射表。
- 自动化生成:通过 Node.js/Python 脚本调用 qrcode 库,根据数据库 ID 批量生成 100+ 物理贴纸。
- 施工校验:印刷贴纸需附带明文编号,安装时由运维端扫码并上传 LBS 坐标,完成“人-机-地”三位一体绑定。
2. “扫码即看”的信息同步机制
- 跳转逻辑:利用微信“普通链接二维码跳转小程序”协议,所有货柜二维码均指向同一个小程序页面。
- 动态解析流程:
- 取参:小程序在 onLoad(options) 中解析 options.q 获取 cabinet_id。
- 溯源:小程序以该 ID 为 Key,实时请求云端接口 /api/cabinet/info。
- 渲染:后端实时查询该柜体的 IoT 状态(库存剩几桶、电池余量、是否维修),前端实现“千柜千面”的精准显示。
3. 前端交互与权限校验逻辑
`javascript // 基于 UniApp 的扫码取水核心逻辑 async function startWithdrawWater(cabinetId) { // A. 获取用户地理位置,确保在柜机旁 const location = await uni.getLocation({ type: 'gcj02' });
// B. 调用后端校验接口:余额充值情况 + 设备在线状态 const checkRes = await request('/api/cabinet/check', { cabinetId, userId: global.userId, lat: location.latitude, lng: location.longitude });
if (checkRes.status === 'READY') { // C. 唤起蓝牙或网络指令下发确认框 uni.showModal({ title: '发现提水点', content: '确认开启 1 号柜门取水?', success: async (res) => { if (res.confirm) { // D. 下发开门指令 const openRes = await request('/api/cabinet/open', { cabinetId }); if(openRes.code === 0) { // E. 进入倒计时监听,等待设备反馈开门信号 monitorDoorStatus(cabinetId); } } } }); } } `
4. 数据通信闭环(双向反馈)
- 云端指令控制:小程序点击后,通过 HTTPS POST 请求后端,后端转发 MQTT 指令至货柜。
- WebSocket 状态同步:小程序前端通过 Socket 实时监听后端推送。当货柜感应器检测到“物理门已开启”或“门已关闭”,小程序界面同步切换:[待取水] -> [取心中] -> [成功扣费/取水完成]。
七、 企业级安全与高可用保障
- 容灾机制(断网续传):货柜具备离线存储功能。若断网期间发生本地开门(手动/钥匙),恢复后第一时间同步日志。
- 【调整】续航与能源管理:考虑到实际布放环境,设备采用**“大容量工业锂电池 + 定期换电/充电”**模式。系统集成低电量预警:
- 电量梯级预警:低于 20% 时推送后台补货员工单;低于 10% 时小程序端自动置灰并停止接单,防止物理开锁力矩不足。
- 异常处理机制:提供“远程强制开锁”与“一键报漏及退费回滚”功能,确保用户权益不受损。 【新增:离线开门补偿逻辑】
八、 实施路线图 (Roadmap)
- Q1-调研期:完成 4G 模组与主控板的底层通信打通。
- Q2-内测期:完成试点投放,验证传感器精度。
- Q3-商业化:全面对接货柜节点,开启自动化交付。