01-一个Demo如何讲清无人零售三端闭环-URM Ultra全景解读
作者:黒漂技术佬|系列:URM Ultra 方案理念与架构篇
大家好,我是黒漂技术佬。今天开一个新坑——讲讲我自研的无人零售整合方案URM Ultra。
先别被这个名字吓到。“URM” 你可以理解成 Ultra Retail Machine 这一套体系的简称,“Ultra” 是想表达"整合到极致"的意思:把无人售货机、无人车、机械臂三样硬核设备,塞进同一套软件系统里,跑通一条从"卖货"到"补货"的完整闭环。
很多新手一听到"无人零售"脑子里就一个画面:小区门口那个扫码开门的柜子。但真正落地一套无人零售系统,远不止一个柜子那么简单。货卖完了谁去补?补货的人(或者车)怎么调度?仓库里成百上千件商品谁去分拣、谁去往柜子里塞?这套链路如果全靠人,那就不叫"无人"了。
这篇文章就带你从项目名和整体定位出发,把 URM Ultra 的全景先摊开看一遍。后面几篇我会逐个端深挖。
一、先说人话:URM Ultra 到底解决什么问题
传统无人售货柜,痛点其实很碎:
| 痛点 | 说明 |
|---|---|
| 补货靠人 | 货道空了,运营得开车去现场,开门、塞货、关门,费时费力 |
| 调度靠喊 | 哪台柜子快空了、哪台车有空,全靠人工盯后台 |
| 上货靠手 | 仓库里成箱的商品,靠人一箱箱搬到车上、再一件件塞进货道 |
| 识别不统一 | 有的柜子靠重力、有的靠 RFID,视觉识别又各接各的算法 |
URM Ultra 的野心想把上面四件事全部"无人化":
- 售货机负责"卖"(纯视觉识别 + 免密支付);
- 无人车负责"运"(从前置仓把货送到柜子点位);
- 机械臂负责"上"(在前置仓分拣、到柜子点位把货塞进货道)。
三者由一个Spring Boot 后台统一调度,再加一个微信小程序给消费者下单。于是整套系统就有了"销售 → 消耗 → 补货 → 上货"的自循环。
划重点:URM Ultra 的定位是可二次开发的 Demo。它把业务域、状态机、任务编排都真实写出来了,但刻意没有上微服务网关、鉴权中心那一套重基础设施。目的很朴素——让你能跑起来、读得懂、改得动。
二、四个工程,各管一摊
光有后台还不够,真实系统一定是"多端协同"。URM Ultra 一共拆成4 个工程,技术栈刻意选得亲民:
| 端 | 工程名 | 技术栈 | 一句话职责 |
|---|---|---|---|
| 后台 | urm-server | Java 17 / Spring Boot 3.2 / Spring Data JPA | 系统的"大脑",管商品、订单、设备、车辆、机械臂、补货配送 |
| 消费端 | urm-mini | 微信小程序原生 | 消费者扫码、选购、下单、退款 |
| 设备端 1 | urm-vehicle | Python 3(仅标准库) | 无人车仿真 Agent:心跳、领任务、执行、上报 |
| 设备端 2 | urm-robot | Python 3(仅标准库) | 机械臂仿真 Agent:分拣、补货、上货 |
几个新手容易懵的点,我顺手解释一下:
- 为什么后台用单体(一个工程)而不是微服务?因为我参考的体系(urm-cloud)是微服务,但 Demo 阶段把 74 个 Java 文件全塞一个工程里,按业务域分包(product / device / order / vehicle / robot / replenish / vision / payment),你 clone 下来直接
mvn就能跑,不用先搭 Nacos、网关。等以后真要上生产,按包一切就能拆。 - 为什么设备端用 Python 标准库、不引 requests?无人车、机械臂本质是"边缘设备",很多跑在 ARM 板子上,环境越干净越好。这里只用
urllib发 HTTP,模拟"心跳 + 领任务 + 上报"三板斧,零依赖就能跑,重点是讲清楚设备接入的模式而非堆功能。 - 数据库用 H2 还是 MySQL?默认 H2 内存库,启动即灌演示数据,零配置;生产切 MySQL 只需改配置(建表脚本已备好)。这就是"Demo 友好"和"生产可用"的折中。
三、三端角色分工:卖、运、上
把三个硬件端拉出来单列一张表,职责就清楚了:
┌─────────────┐ 消费者 ──▶ │ 无人售货机 │ 卖:视觉识别 + 免密扣款 └──────┬──────┘ │ 库存下降 ▼ ┌─────────────┐ ┌─────────────┐ │ 后台调度 │──────▶│ 无人车 │ 运:前置仓→柜机点位 └──────┬──────┘ └──────┬──────┘ │ │ 到达点位 ▼ ▼ ┌─────────────┐ ┌─────────────┐ │ 机械臂 │◀───────│ 分拣+上货 │ └─────────────┘ 上:塞进货道| 端 | 在闭环里的角色 | 关键能力(来自需求) |
|---|---|---|
| 无人售货机 | 前端销售 | 纯视觉识别、双门 / 2 路锁 / 4 摄、微信支付分免密 |
| 无人车 | 物流执行 | 补货、配送、前置仓中转 |
| 机械臂 | 仓库 / 上货执行 | 分拣、补货、给设备上货 |
注意一个微妙关系:机械臂不是"独立作战",而是和无人车打配合。无人车把整批货从仓运到柜子旁边,机械臂再负责把货"塞"进具体货道。这一段我会在第 05 篇细讲。
四、端到端五步闭环(本文核心)
整套系统最值得讲清楚的,是这条端到端闭环。我把它拆成五步,每一步都对应真实的代码链路:
[1] 上架 ──▶ [2] 扫码 ──▶ [3] 识别 ──▶ [4] 扣款 ──▶ [5] 低库存补货上货 运营配货 用户开柜 视觉算商品 免密扣款 自动派车+臂第 1 步:上架(运营侧)
运营在后台维护商品、把商品绑定到售货机的"货道"(slotNo)。一台柜子有几个格子、每个格子放什么、容量多少、当前库存多少,全部由后台的"设备商品"模块管。这是后续一切的起点。
第 2 步:扫码(消费侧)
消费者用小程序扫柜子上的二维码,二维码内容就是设备编号。小程序拿到编号后跳到该设备的商品页。这一步本质是把"物理柜子"和"后台里的 Device 记录"对上号。
第 3 步:识别(设备 + 后台)
用户开门拿货、关门。关门瞬间,柜内 4 个摄像头采集画面,后台调用视觉识别服务,输出"哪个货道、拿了什么商品、拿了几个、置信度多少"。
第 4 步:扣款(后台 + 支付)
后台拿着识别结果,一次性完成:生成订单 → 微信支付分免密扣款 → 扣减货道库存。用户全程"拿完就走",不用掏手机付款。
第 5 步:低库存补货上货(三端联动)
某货道库存低于阈值,后台自动生成补货计划,派发时同时生成"无人车补货任务 + 机械臂上货任务"。车把货运到、臂把货上架,库存恢复。闭环完成,进入下一轮。
这五步里,[1]~[4] 是"卖货"子闭环,[5] 是"补货"子闭环。两个子闭环合起来,就是无人零售的"永动机"。
五、后台:用三个 API 前缀把端拧成一股绳
新手常问:四个工程之间到底怎么通信?答案在urm-server的路由设计上。后台对外只暴露三类前缀:
| 前缀 | 面向谁 | 干什么 |
|---|---|---|
/admin-api/** | 运营后台 | 商品、设备、订单、车辆、机械臂、补货配送的增删改查 |
/app-api/** | 小程序 | 设备列表、下单、我的订单、退款 |
/device-api/** | 三个设备 Agent | 心跳、领任务、上报状态(HTTP 模拟 MQTT) |
把"人操作的"“消费者用的”"设备上报的"三股流量用 URL 前缀切开,逻辑极度清晰:
小程序 ──/app-api──▶ ┌──────────────┐ ──/device-api──▶ 无人车 Agent 运营端 ──/admin-api─▶│ urm-server │ 机械臂 Agent └──────────────┘ ──/device-api──▶ 售货机 Agent设备接入这里有个设计巧思:用 HTTP 模拟 MQTT。真实物联网设备一般走 MQTT(发布/订阅),但 Demo 阶段用普通 HTTP 接口就能把"心跳→领任务→上报"这套状态机跑通,你本地起一个 Python 脚本就能联调,不用先搭 EMQX broker。等真上生产,把device-api这层换成 MQTT 即可,业务 Service 一行不用改。
六、为什么是 Demo,而不是一上来就微服务
写代码最忌"过度设计"。URM Ultra 在几处做了明确的取舍,我列出来给你参考:
| 取舍 | 选了啥 | 为什么 |
|---|---|---|
| 单体 vs 微服务 | 单体按域分包 | 跑起来零运维,按包可平滑拆分 |
| H2 vs MySQL | H2 默认,MySQL 预留 | 零依赖演示,生产切库有脚本 |
| Mock 支付 / 识别 | 接口抽象 + Mock 实现 | 链路先通,真实微信 / 算法后接 |
| 鉴权 | Demo 不接 | 生产再补 OAuth2 / 多租户 |
这些取舍不是"偷懒",而是把核心业务闭环和生产级基建解耦。Demo 阶段你该验证的是"三端能不能闭环",而不是"网关稳不稳"。
七、怎么跑起来看效果(极简版)
- 后台:
cd urm-server后mvn起项目,默认 H2 自动灌 2 台柜子、2 台车、2 台臂、1 个前置仓的演示数据。 - 设备端:分别跑
urm-vehicle、urm-robot两个 Python 脚本,它们会自己心跳、抢任务、上报。 - 小程序:用开发者工具导入
urm-mini,把 baseUrl 指到后台即可。
(具体命令和接口清单去看项目里的部署文档、API 文档,本篇只讲"全景"。)
八、本系列后续
这篇把全景铺开了,后面四篇我会逐个端"庖丁解牛":
- 第 02 篇:从一份原始需求文档,怎么翻译成软件方案(纯视觉、安卓工控、支付分免密);
- 第 03 篇:售货机的硬件长相(双门两路锁四摄),怎么变成后台的一张
Device表; - 第 04 篇:无人车——前置仓与补货配送任务的枢纽;
- 第 05 篇:机械臂——仓库里"最后十米"的上货执行者。
下一篇见。