原文发表于 CSDN(作者:hjz0810),发布日期 2026-04-15。本文为转载备份,已征得作者同意。

第1章 系统的总体架构

本系统采用客户端-服务器-设备端三层架构,各层之间通过WebSocket协议进行实时双向通信,确保指令的低延迟传输。采用B/S(Browser/Server)架构与物联网技术相结合的设计方案。软件系统主要由四部分组成:基于ESP32的下位机控制程序、基于Node.js的WebSocket公网中继服务、基于Python Flask的业务逻辑与支付监控后台、以及基于HTML5/Bootstrap的用户交互前端。

1.1 设备层 (ESP32)

负责硬件控制,包括连接本地Wi-Fi,通过WebSocket连接至公网中继服务器,并接收来自云端的开锁指令以驱动相应电磁锁。

1.2 服务层 (云服务器)

1.2.1 Web前端

提供商品展示与选择的用户界面,负责发起支付订单。

1.2.2 后端服务 (Flask)

生成支付订单链接,并启动图像识别线程监控支付结果。

1.2.3 消息中继服务器 (Node.js)

作为系统的“消息总线”,负责转发后端服务向ESP32发送的出货指令。

1.3 支付层

使用第三方支付平台(易支付),通过图像识别技术自动化确认支付状态。

第2章 嵌入式终端控制程序设计(ESP32)

2.1 主控单元

选用ESP32-WROOM-32模组作为核心控制器。其集成Wi-Fi功能,功耗低,性能足以处理网络通信与GPIO控制任务。下位机主要负责网络连接维护、指令解析及电磁锁驱动。代码基于Arduino框架开发,利用WiFi.h库处理网络连接,WebSocketsClient库实现长连接,ArduinoJson库进行数据解析。

2.2 开锁原理

系统通过电磁锁控制货道门。在代码中,定义了锁控引脚数组 lockPins[] = {2, 4, 5, 18, 19},对应五个商品货道。控制逻辑简洁高效:

void unlockProduct(int productId) {

int pin = lockPins[productId - 1]; // 映射商品ID到物理引脚

digitalWrite(pin, HIGH); // 激活电磁锁(假设高电平触发)

delay(unlockDelay); // 保持激活状态3秒,确保商品掉落

digitalWrite(pin, LOW); // 关闭电磁锁

}

此设计通过商品ID与GPIO引脚的映射关系,实现了软件对硬件的灵活配置。

2.3 网络连接与自动重连机制

为了保证无人售货机在无人值守环境下的高可用性,程序中设计了双重守护机制:

WiFi守护:在主循环loop()中调用reconnectWiFi()函数,实时检测WiFi.status()。一旦检测到连接断开,立即挂起当前任务并尝试重新连接指定SSID,直至连接恢复。

WebSocket心跳保活:通过webSocket.enableHeartbeat(3000, 2000, 1)配置心跳包,每3秒向服务器发送Ping帧。若2秒内未收到Pong响应或连接意外断开(WStype_DISCONNECTED),将触发自动重连逻辑,重连间隔被优化为2秒,以减少掉线时间。

2.4 指令解析与硬件驱动

当收到服务器推送的文本消息(WStype_TEXT)时,系统调用parseLockMessage函数:

反序列化:将JSON字符串解析为对象。

安全校验:首先校验type字段是否为release_product,防止误操作。

执行动作:提取product_id,经有效性校验(1至numLocks)后,通过unlockProduct函数驱动对应GPIO。

电磁锁控制:采用非阻塞延时或同步延时逻辑,将对应引脚拉高(ACTIVE_LEVEL),持续3000ms(unlockDelay)后拉低,完成开锁动作。

第3章 公网通信与指令中继(NodeJS)

由于ESP32通常部署在NAT网络下,无法直接被公网访问,因此在云服务器(IP: 149.104.21.241)搭建Node.js WebSocket中继服务,端口8080。

该服务充当“消息路由”的角色,核心逻辑如下:

3.1 链路映射

维护backendClient和esp32Client两个全局对象,分别存储后台与设备的连接句柄。ESP32连接后发送 register:esp32,后端服务发送 register:backend。中继服务器据此区分客户端身份,并维护两个独立的WebSocket连接句柄。

3.2 定向转发

当收到来自backendClient的消息时,服务判断ESP32是否在线。若在线,且消息类型为release_product,则将指令原样转发给esp32Client。

3.3 异常处理

监听close和error事件,在任意一端断开时及时清空对应的连接句柄,及时释放资源并在控制台打印日志,避免内存泄漏和误发指令。

第4章 前端在线网页

前端采用HTML5结合Bootstrap 5框架,实现了响应式布局,更适配手机的布局页面

4.1 动态交互

商品列表通过Card组件展示,点击商品自动高亮并更新底部支付栏状态。JS脚本实时维护selectedProduct对象,记录用户选择的ID、名称和价格。

4.2 双向通信

4.2.1 HTTP请求

点击“立即支付”后,通过fetch API向后端发送POST请求,携带productValue(ID编号)与productPrice(商品价格)。

4.2.2 WebSocket监听

页面加载时初始化Socket.IO连接,监听payment_success事件。一旦收到后端通知,页面即时弹出“支付成功”提示,并自动更新UI状态,极大地提升了用户体验。

第5章 订单生成与支付监控系统(后端)

后台核心业务运行在Python Flask框架上,采用了RPA(机器人流程自动化)技术解决第三方支付接口的对接难题。

5.1 自动化订单生成

5.1.1 图像识别定位

利用locateOnScreen函数,基于预存的UI截图(如pic1.png~pic5.png)定位支付软件窗口坐标。

5.1.2 参数输入

自动获取并输入前端传递的商品价格(productPrice),实现了价格与货道的解耦。

5.1.3 支付平台链接转发

生成订单并自动转发链接,最终将支付URL返回给前端。 为防止并发冲突,该过程由threading.Lock()互斥锁保护,确保同一时间只能处理一个订单请求。

5.2 异步支付状态监测

为了不阻塞API响应,支付检测在独立线程中运行(check_payment_async):

5.2.1 视觉轮询

由于常规的api获取订单是否完成支付存在安全漏洞,采用api加视觉双重认证的方式确保订单是通过正常手段完成的支付,而非利用漏洞绕过支付,后端持续识屏幕并匹配“支付成功”图标(paid_success)。

5.2.2 超时控制

设置50秒超时阈值,避免长时间占用订单消耗资源,若在规定时间内检测到支付成功,则调用notify_esp32_via_relay函数进行中继发送。

5.2.3 指令下发

该函数建立与8080端口的中继连接,发送包含product_id的出货指令,完成“支付-出货”闭环。

一旦检测到支付成功,后端通过WebSocket向公网中继服务器发送一个标准化的JSON指令

{

"type": "release_product",

"product_id": 1, 订单编号

"order_url": "http://..." 生成的订单链接

}

第6章 通信协议与消息流

为了实现云端服务器与内网设备(ESP32)及前端页面的实时交互,系统定义了一套基于WebSocket的通信协议。采用JSON格式在服务层与中继之间传递结构化数据,而在中继与ESP32之间则传递纯文本或JSON指令,确保了协议的灵活性与可扩展性。

6.1 注册机制

客户端连接中继服务器后,需立即发送身份标识。中继服务器据此区分客户端身份,并维护两个独立的WebSocket连接句柄。

6.2 消息路由

只将来自 backendClient 且类型为 release_product 的指令转发给 esp32Client,起到了消息过滤和路由的安全作用。

6.3 指令格式

控制指令采用JSON格式传输,确保数据结构清晰且易于扩展。

{"type": "release_product","product_id": 1,"order_url": "http://..."}

实际操作:

1.使用ESP32-s3作为主控芯片

2.因电磁锁解锁电压最低一档为5V,而ESP32只能输出3.3V,采用TB6612做继电器使用(因为有四个电磁锁,对应TB6612的AIN1,AIN2,BIN1,BIN2)

3.使用ESP32连接WIFI名称为:宾馆,密码为:12345678的WiFi,发布一个网页,同时从外网拉取商品图片和支付宝二维码

4.采用CDN直链获取图片,因不便于调用wechat和支付宝API,采用更简单的二维码支付,即通过支付宝收钱功能给每个价格都截图,标号,程序中用算法实现精准调用截图

  1. 附件:前端代码.html

附件:后端代码.py

附件:云服务器中继代码.js

附件:ESP32代码.cpp

作者联系方式:hjz0060810(如需完整代码可联系作者)

hjz0810

6

原创

核心速览

代码判官

遇到复杂语法或逻辑?选中代码,AI帮你解释

代码运行代码生成环境配置

知识延伸

读完有疑惑?就像聊天一样追问AI,挖掘博文背后的深度知识

核心速览

目录

  1. 第1章 系统的总体架构

    1. 1.1 设备层 (ESP32)

    2. 1.2 服务层 (云服务器)

      1. 1.2.1 Web前端

      2. 1.2.2 后端服务 (Flask)

      3. 1.2.3 消息中继服务器 (Node.js)

    3. 1.3 支付层

  2. 第2章 嵌入式终端控制程序设计(ESP32)

    1. 2.1 主控单元

    2. 2.2 开锁原理

    3. 2.3 网络连接与自动重连机制

    4. 2.4 指令解析与硬件驱动

  3. 第3章 公网通信与指令中继(NodeJS)

    1. 3.1 链路映射

    2. 3.2 定向转发

    3. 3.3 异常处理

  4. 第4章 前端在线网页

    1. 4.1 动态交互

    2. 4.2 双向通信

      1. 4.2.1 HTTP请求

      2. 4.2.2 WebSocket监听

  5. 第5章 订单生成与支付监控系统(后端)

    1. 5.1 自动化订单生成

      1. 5.1.1 图像识别定位

      2. 5.1.2 参数输入

      3. 5.1.3 支付平台链接转发

    2. 5.2 异步支付状态监测

      1. 5.2.1 视觉轮询

      2. 5.2.2 超时控制

      3. 5.2.3 指令下发

  6. 第6章 通信协议与消息流

    1. 6.1 注册机制

    2. 6.2 消息路由

    3. 6.3 指令格式

分类专栏