# 无人自助拼豆系统开发实战 从需求梳理到部署上线全流程指南
随着线下无人自助业态的快速发展,拼豆手工作为低门槛、高趣味性的休闲项目,无人值守模式可以大幅降低门店运营成本,同时给用户提供24小时随到随玩的灵活体验。本文将结合成熟的无人共享类系统开发经验,从需求梳理、架构选型、功能实现到部署上线,完整讲解无人自助拼豆系统的开发全流程。
## 需求梳理与业务域建模
无人自助拼豆系统属于典型的软硬件一体化共享类系统,业务逻辑和现有共享球杆柜、共享文体设备系统有较高的共性,核心是「订单驱动+硬件控制+全端管理」的逻辑,需求梳理可以分为三个核心维度:
### 用户端需求
用户侧核心链路要做到极简操作:扫码进入应用后自动获取LBS定位,展示附近的自助拼豆门店,支持一键导航到店;进入门店页后可以查看当前可用的拼豆套餐(包含不同颗粒度拼豆、配件包、模板等SKU),下单后扫码对应柜子即可开柜取料;使用过程中可以随时查看订单剩余时长,使用完成后将剩余材料放回柜子关柜,系统自动核算损耗后完成结算,同时支持历史订单查询、售后申请等功能。
### 运营端需求
运营侧需要覆盖全链路管理能力:包括门店信息管理、柜组状态管理、拼豆库存SKU管理、订单全生命周期管理、用户权限管理、运营数据统计(客流趋势、订单转化率、库存消耗排行)等,支持多门店分级权限控制,不同门店管理员只能查看对应门店的运营数据。
### 物联网端需求
硬件侧需要实现柜态实时同步、开柜指令毫秒级下发、异常事件主动上报能力:包括柜门开关状态上报、设备离线告警、柜门未关告警、库存重量异常告警等,确保硬件状态和系统数据的一致性。
完成需求梳理后可以进行业务域建模,核心实体包括用户、门店、柜组、库存SKU、订单、柜控设备六大类,实体之间通过门店ID、柜组ID、订单ID进行关联,和常规共享类系统的ER模型基本一致,可以直接复用成熟的建模方案。
## 技术架构选型与分层设计
无人自助拼豆系统可以复用现有无人共享类项目的成熟技术栈,兼顾开发效率和运行稳定性,整体架构采用分层设计:
### 技术栈选型
- 后端服务:采用Spring Boot + MyBatis Plus + MySQL 搭建核心业务逻辑,开发效率高,生态完善,支持后续功能扩展;
- 用户端:采用Uniapp基于Vue语法开发,一次开发可以适配小程序、H5、APP多端,降低多端开发成本;
- 管理后台:采用Vue + Element UI 搭建,组件丰富,适配后台管理类系统的交互需求;
- 物联网通信层:采用EMQX作为MQTT Broker,对接柜控嵌入式设备,支持高并发消息下发与上报,延迟可控制在100ms以内;
- 缓存层:采用Redis缓存柜态、用户信息、热门套餐等高频访问数据,降低数据库压力。
### 分层架构设计
从上到下分为五层:
1. 端侧层:包含用户端、管理后台、柜控终端三类节点,分别面向C端用户、运营人员、硬件设备;
2. 网关层:Nginx负责静态资源代理、接口限流、跨域处理,单体架构下可直接通过Nginx转发后端接口请求;
3. 业务服务层:拆分为用户服务、订单服务、柜控服务、库存服务、统计服务五个独立模块,模块之间通过内部接口调用,降低耦合度;
4. 中间件层:包含MQTT Broker、Redis缓存、对象存储(存储拼豆样品图、门店图片等静态资源)、MySQL持久化存储;
5. 基础设施层:基于云服务器部署,支持弹性扩容,满足业务增长需求。
## 核心功能模块开发实现
核心功能的开发可以参考成熟共享类系统的实现逻辑,重点解决软硬件协同、状态一致性、异常兜底三类问题:
### 开柜链路实现
开柜是核心交互节点,采用异步非阻塞设计避免请求阻塞,核心接口示例如下:
```java
@RestController
@RequestMapping("/api/cabinet")
public class CabinetController {
@Autowired
private CabinetService cabinetService;
@Autowired
private MqttGateway mqttGateway;
@PostMapping("/open")
public ResultVo openCabinet(@RequestBody OpenCabinetDto dto, @RequestHeader("userId") Long userId) {
// 1. 校验订单有效性,是否已支付、是否对应当前柜组
OrderEntity order = cabinetService.checkOrderValid(dto.getOrderId(), userId);
if (Objects.isNull(order)) {
return ResultVo.fail("订单无效,无法开柜");
}
// 2. 校验柜子当前状态是否可用,避免重复开柜
CabinetEntity cabinet = cabinetService.getById(dto.getCabinetId());
if (cabinet.getStatus() != CabinetStatusEnum.USABLE.getCode()) {
return ResultVo.fail("当前柜子暂不可用,请更换");
}
// 3. 组装MQTT指令下发到对应柜控设备
MqttMessageDto message = MqttMessageDto.builder()
.cabinetId(dto.getCabinetId())
.orderId(dto.getOrderId())
.cmd(MqttCmdEnum.OPEN_CABINET.getCode())
.timestamp(System.currentTimeMillis())
.build();
mqttGateway.sendToMqtt("cabinet/cmd/"+dto.getCabinetId(), JSON.toJSONString(message));
// 4. 异步监听设备回调更新状态,不阻塞当前请求
return ResultVo.success("开柜指令已发送,请等待柜门弹出");
}
}
```
柜控设备成功开柜后会向指定MQTT Topic上报开柜成功事件,后端服务监听Topic后更新订单状态为「使用中」,同时更新柜态为「占用」,完成整个开柜链路。
### 状态一致性保障
为了避免网络波动导致的柜态、订单状态不一致问题,采用双校验机制:每次用户操作前先查询Redis缓存的状态,同时柜控设备每5分钟主动上报一次全量柜态,后端对比数据库存储的状态,出现不一致时自动触发告警,同时更新缓存和数据库数据,确保状态终一致。
### 异常兜底逻辑
针对常见异常场景设置兜底策略:开柜指令下发后10秒未收到设备回调,自动重试2次,仍然失败的话自动取消订单,给用户推送通知;柜控设备离线超过30分钟触发运营端告警,安排人员现场排查;用户关柜后重量检测异常,自动推送人工审核通知,避免库存损失。
## 部署上线与运维优化
系统开发完成后,按照开发联调、测试验证、生产部署的流程推进上线:
### 部署流程
采用Docker容器化部署,将后端服务、MySQL、Redis、EMQX都打包成Docker镜像,通过Docker Compose编排,一键启动所有服务,降低部署成本。开发环境本地部署完成功能自测后,在测试环境部署全套服务,搭配模拟柜控设备完成全链路联调,覆盖所有正常、异常场景后再上线生产环境。
### 上线前验证
功能测试覆盖用户全链路操作、运营端所有管理功能、硬件所有上报/指令场景;压力测试模拟1000并发开柜请求,确保接口响应时间在200ms以内,MQTT消息无积压;硬件测试模拟断网、断电恢复场景,验证设备自动重连、状态补报能力。
### 运维优化
采用ELK栈收集所有服务、硬件的日志,统一存储查询,方便问题排查;配置监控告警,对服务CPU/内存/磁盘使用率、MQTT消息积压量、柜控在线率、库存预警阈值设置告警规则,出现异常及时通知运维人员;定期全量备份数据库,同时开启Binlog增量备份,避免数据丢失。
这套开发流程和技术架构经过多个无人共享类项目的验证,稳定性和扩展性都有保障,不仅可以用于无人自助拼豆系统,也可以快速适配其他无人自助手工、文体设备类项目的需求,模块化的设计支持后续新增拼豆成品回收、线上预约留料、会员体系等扩展功能。