# 💧 水厂智能货柜（IoT）分布式终端接入与自动化交付技术白皮书

## 一、 业务愿景与战略定位
本方案旨在通过 **IoT（物联网）** 硬件矩阵，实现水厂饮用水交付的全面自动化与去人工化。针对**无屏幕、定位提货、套餐保值**等核心需求，构建“线上订水、LBS 匹配、无感交付”的智慧物流体系。

---

## 二、 核心应用场景与业务需求模型

### 1. 定位提货与套餐保值逻辑
*   **需求：** 用户购买桶水套餐，不受后续调价影响；定位用户小区并呈现所有单元楼提水点，实现远程库存预览，防止用户“跑空”。
*   **小程序实现：**
    *   **权益钱包**：引入“虚拟储水池”概念，用户购买套餐后，账户记录为“待取桶数”，而非金额，实现锁价保值。
    *   **LBS 智能网格**：首页通过 `uni.getLocation` 获取坐标，服务器根据经纬度反向检索关联小区，并在地图上以“桩位”形式展示该小区内所有单元楼下对应的提柜状态（空闲/库存数）。
    *   ****【新增机制：空柜自动调导 (Self-Correction)】****：当某单元楼货柜库存为 0 时，地图图标转为置灰状态并显示“补货中”，同时系统自动计算并推荐该小区内距离最近的“有货柜机”。

### 2. 无屏幕式“无感核销”模式（蓝牙/云端直控）
*   **需求：** 货柜感应 + 云端瞬时指令”**模式。
    *   **操作流**：用户靠近货柜 $\rightarrow$ 手机蓝牙自动识别设备号（Beacon 广播）或 LBS 确认经纬度重合 $\rightarrow$ 小程序自动弹出“当前已到达XX单元提水点” $\rightarrow$ 用户在手机点击“开门” $\rightarrow$ 云端通过 MQTT 指令开锁。
    *   **价值**：降低硬件成本（无屏、防暴力），提升交互流畅度。

### 3. 故障闭环与客服联动系统
*   **需求：** 下单不开门、没电、库存不足等异常，自动切入客服协助。
*   **业务逻辑：**
    1.  **主动监测**：系统 15 秒内未收到门磁反馈，自动触发“开启失败弹窗”。
    2.  **一键路由**：弹窗直接集成“在线客服”与“紧急开锁申请”。对于电池电量低于 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. 权益发放（下单阶段）
1.  **资产化**：用户下单购买后，系统不只是生成一个订单，而是在数据库中为用户 `OpenID` 增加“电子水票/桶数”资产（如：可用余额 +10 桶）。
2.  **权益凭证**：系统生成一组不记名的电子权益 ID，状态标记为 `UNUSED`（未使用）。

#### B. 身份与位置核验（扫码阶段）
1.  **设备匹配**：用户扫码，小程序获取 `cabinet_id`。系统即刻下发 **MQTT PING** 指令确认柜机通讯链路活跃。
2.  **位置强校验 **(针对无蓝牙环境增强)****：
    *   小程序调用 `uni.getLocation` 获取手机经纬度。
    *   **后端比对**：将手机位置与柜子的注册坐标进行计算（Haversine 公式）。
    *   **判定**：距离 < 50 米时，判定为“到店”，激活“开门按钮”；否则提示“请到达柜机旁操作”。
3.  **在线预警**：若 MQTT 链路超时未响应，按钮置灰并提示“柜机离线中，请稍后再试”，防止用户重复扣款。

#### C. 权益核销（开门阶段）
1.  **预锁定**：用户点击“确认开门”，后端立即执行 `Transaction`（事务）：
    *   查询用户是否有可用余额。
    *   将 1 份权益设为 `LOCKING`（锁定中），防止并发重复开启。
2.  **指令下发**：通过 MQTT 向货柜发送 `UNLOCK_CABINET` 指令。
3.  **状态反馈**：
    *   **成功**：货柜反馈“门已开启”，权益标记为 `USED`（已使用），生成核销流水。
    *   **失败**：若 15 秒内未收到开门反馈，直接接入客服系统，让客服处理这笔订单。

### 2. 身份识别与设备绑定（参数二维码体系）
*   **二维码本质**：机身二维码并非静态图片，而是携带设备 ID 的“动态索引链接”（例如：https://domain.com/q?id=10001）。
*   **批量生产规范**：
    *   **映射逻辑**：后端建立 设备SN - 设备ID - 二维码URL 的 1:1 映射表。
    *   **自动化生成**：通过 Node.js/Python 脚本调用 qrcode 库，根据数据库 ID 批量生成 100+ 物理贴纸。
    *   **施工校验**：印刷贴纸需附带明文编号，安装时由运维端扫码并上传 LBS 坐标，完成“人-机-地”三位一体绑定。

### 2. “扫码即看”的信息同步机制
*   **跳转逻辑**：利用微信“普通链接二维码跳转小程序”协议，所有货柜二维码均指向同一个小程序页面。
*   **动态解析流程**：
    1.  **取参**：小程序在 onLoad(options) 中解析 options.q 获取 cabinet_id。
    2.  **溯源**：小程序以该 ID 为 Key，实时请求云端接口 /api/cabinet/info。
    3.  **渲染**：后端实时查询该柜体的 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 实时监听后端推送。当货柜感应器检测到“物理门已开启”或“门已关闭”，小程序界面同步切换：**[待取水] -> [取心中] -> [成功扣费/取水完成]**。

---

## 七、 企业级安全与高可用保障

1.  **容灾机制（断网续传）**：货柜具备离线存储功能。若断网期间发生本地开门（手动/钥匙），恢复后第一时间同步日志。
2.  **【调整】续航与能源管理**：考虑到实际布放环境，设备采用**“大容量工业锂电池 + 定期换电/充电”**模式。系统集成低电量预警：
    *   **电量梯级预警**：低于 20% 时推送后台补货员工单；低于 10% 时小程序端自动置灰并停止接单，防止物理开锁力矩不足。
3.  **异常处理机制**：提供“远程强制开锁”与“一键报漏及退费回滚”功能，确保用户权益不受损。 **【新增：离线开门补偿逻辑】**

---

## 八、 实施路线图 (Roadmap)
*   **Q1-调研期**：完成 4G 模组与主控板的底层通信打通。
*   **Q2-内测期**：完成试点投放，验证传感器精度。
*   **Q3-商业化**：全面对接货柜节点，开启自动化交付。







