无人售货柜设备开机自动注册逻辑:唯一标识绑定、防重复、批量铺货适配
大家好,我是黒漂技术佬。上一篇咱们聊了开机自启,今天接着唠------设备起来了,怎么让它自己"报到"?
做过批量铺货的兄弟都懂,一台台去配置设备号、绑定后台,那工作量简直是噩梦。100台柜子还行,1000台呢?全国铺货呢?
今天就给大家拆解一套成熟的设备自动注册方案,开箱插电就能用,全程零人工干预。
一、设备唯一标识:用什么当"身份证"?
注册的第一步,得确定设备的唯一ID。听起来简单,实际坑巨多。
常见的唯一标识方案对比
| 标识类型 | 获取方式 | 优点 | 缺点 |
|---|---|---|---|
| IMEI | TelephonyManager | 原生支持,手机常用 | 工控机很多没有通话模块,拿不到;双卡设备有两个 |
| MAC地址 | WifiInfo.getMacAddress() | 网卡硬件地址,理论唯一 | Android 6.0+ 默认返回假地址;WiFi模块可能没有 |
| 序列号 | Build.SERIAL | 系统属性,方便获取 | 厂商可能不写,或者大量重复(你没看错,真有重复的) |
| Android ID | Settings.Secure.ANDROID_ID | 系统生成,恢复出厂才变 | 刷机、恢复出厂会变;不同厂商ROM有差异 |
| ICCID | SIM卡序列号 | 4G设备必备,跟卡绑定 | 换SIM卡就变,适合卡机绑定场景 |
| 主板SN | 厂商自定义接口 | 真正硬件级唯一 | 需要厂商支持,每家教的接口不一样 |
推荐方案:多维度组合ID
单一标识都不靠谱,我的做法是组合生成设备指纹:
java
public class DeviceIdGenerator {
/**
* 生成设备唯一ID
* 优先级:主板SN > ICCID > MAC地址 > AndroidID
* 最终组合:前缀_主板SN_哈希值
*/
public static String generateDeviceId() {
String boardSn = getBoardSerialNumber();
String iccid = getIccid();
String mac = getWifiMac();
String androidId = getAndroidId();
// 用主板SN作为主键,没有就降级
String primaryId = !TextUtils.isEmpty(boardSn) ? boardSn :
!TextUtils.isEmpty(iccid) ? iccid :
!TextUtils.isEmpty(mac) ? mac : androidId;
// 再加一层哈希,避免泄露原始信息,也统一长度
String hash = md5(boardSn + iccid + mac + androidId);
return "VDG_" + primaryId + "_" + hash.substring(0, 8);
}
}
划重点:
- 主板SN是最靠谱的,一定要跟工控板厂商要读取接口
- 4G设备建议用 ICCID + 主板SN 双绑定,换卡能识别,换主板也能识别
- 最终ID要加前缀,方便后台区分设备类型(售货柜、饮水机、快递柜...)
二、自动注册完整流程设计
整体流程图(文字版)
设备开机
↓
生成本地设备ID
↓
检查本地是否有注册成功标记 → 有 → 跳过注册,直接连MQTT
↓ 没有
检查网络是否可用 → 不可用 → 缓存注册请求,等网络恢复
↓ 可用
调用注册接口,上报设备信息
↓
后台判断设备是否已注册
├── 已注册 → 返回已有设备信息,本地存标记
└── 未注册 → 创建设备,返回设备编号,本地存标记
↓
注册成功,拉取配置,进入正常运行
核心代码结构
java
public class DeviceRegisterManager {
private static final String KEY_REGISTERED = "is_registered";
private static final String KEY_DEVICE_NO = "device_no";
/**
* 启动时检查注册状态
*/
public void checkAndRegister() {
if (isRegistered()) {
// 已注册,直接走正常流程
enterNormalMode();
return;
}
// 未注册,开始注册流程
startRegisterFlow();
}
private void startRegisterFlow() {
if (!NetworkManager.isNetworkAvailable()) {
// 没网,等网络恢复再注册
NetworkManager.addNetworkListener(available -> {
if (available) {
doRegister();
}
});
return;
}
doRegister();
}
}
三、防重复注册的三道闸门
批量铺货最怕的就是重复注册,一台设备在后台出现好几条记录,运维直接疯掉。
第一道:本地标记闸门
注册成功后立刻写本地标记,下次开机直接跳过:
java
public void saveRegisterSuccess(String deviceNo) {
SpUtils.putBoolean(KEY_REGISTERED, true);
SpUtils.putString(KEY_DEVICE_NO, deviceNo);
// 还要存注册时间、注册时的网络信息,方便排查
SpUtils.putLong("register_time", System.currentTimeMillis());
}
注意: 这个标记不能存在容易被清的地方,比如内部存储的SP就行,别存在SD卡上。
第二道:服务端幂等闸门
后台接口必须做幂等,同一个设备ID重复调用返回同一个结果:
sql
-- 后台数据库设计,device_unique_id 加唯一索引
CREATE TABLE device (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
device_no VARCHAR(32) NOT NULL COMMENT '设备编号',
device_unique_id VARCHAR(64) NOT NULL COMMENT '设备唯一指纹',
-- ... 其他字段
UNIQUE KEY uk_unique_id (device_unique_id)
);
接口逻辑:
- 收到注册请求,先按
device_unique_id查 - 查到了就直接返回已有记录
- 查不到就在事务里插入,防止并发重复
第三道:注册防抖闸门
有些设备网络差,会疯狂重试注册,给后台造成压力。加个防抖:
java
// 注册请求间隔限制,最少30秒才能请求一次
private static final long REGISTER_INTERVAL = 30 * 1000;
private long lastRegisterTime = 0;
private boolean canRegister() {
long now = System.currentTimeMillis();
if (now - lastRegisterTime < REGISTER_INTERVAL) {
return false;
}
lastRegisterTime = now;
return true;
}
四、批量铺货场景的特殊适配
做过大规模铺货的都知道,现场环境千奇百怪。
1. 离线注册缓存
铺货现场可能没网,设备先开机,等有网了再自动注册:
java
public class RegisterCache {
// 把注册信息存到本地数据库
public void cacheRegisterRequest(DeviceInfo info) {
RegisterCacheDb db = RegisterCacheDb.getInstance();
db.insertOrUpdate(info);
}
// 网络恢复后扫描缓存,逐个注册
public void processCachedRequests() {
List<DeviceInfo> cached = RegisterCacheDb.getInstance().queryAll();
for (DeviceInfo info : cached) {
boolean success = doRegister(info);
if (success) {
RegisterCacheDb.getInstance().delete(info.getId());
}
}
}
}
2. 设备换绑/解绑场景
设备维修换主板、换4G模块了怎么办?ID变了,原来的设备记录怎么办?
方案:设备码贴纸 + 后台手动绑定
- 每台柜子出厂贴一个二维码,里面有出厂设备号
- 设备自动注册后,运营可以在后台把自动注册的设备和出厂设备号绑定
- 换硬件后重新注册,重新绑定就行,业务数据不丢
3. 预注册模式(可选)
如果铺货量特别大,可以出厂前预注册:
- 工厂生产时就把设备信息录入后台
- 设备开机后只做"激活",不做"创建"
- 适合标准化量产的设备
五、常见踩坑案例
坑1:刷机后Android ID变了,设备变成新的了
- 现象:设备返厂刷机后,回来注册成新设备了
- 解决:优先用主板SN,主板不换ID就不变;或者用出厂贴纸的设备码做绑定
坑2:同一批次工控板序列号全是0
- 现象:100台设备注册上去全是同一个ID
- 解决:别光信厂商说的"序列号唯一",量产前一定要抽检!多维度组合ID能缓解
坑3:注册接口超时,设备反复重试打爆后台
- 现象:几百台设备同时开机,注册接口直接被打挂
- 解决:加随机延迟启动(0~60秒随机),加指数退避重试,服务端做好限流
六、总结
设备自动注册的核心目标:开箱即用,零人工配置。
关键点回顾:
- 唯一ID要多维度组合,不能单吊一个
- 三道闸门防重复:本地标记 + 服务端幂等 + 前端防抖
- 考虑离线场景,注册请求要能缓存
- 预留换绑解绑机制,应对硬件维修场景
做好了注册这一步,后面批量铺货才能跑得起来。不然运维人员天天在外面跑着配设备,成本直接上天。
我是黒漂技术佬,专注无人零售物联网实战。下一篇讲《设备初始化配置固化》,注册成功后参数怎么存、怎么热更新,咱们接着聊。
有售货柜开发的具体问题,欢迎私信交流,看到必回~