设备 SN 编码规则(内部 / 外部双码)
内部 SN 与外部 SN 的定义、生成方式与使用边界。
一、背景
1.1 现状
- 机器人 2.2 版本正式对外交付。2.1 及更早版本均为内部自用,设备上只有一套 SN(下称「内部 SN」)。
- 内部 SN 采用带语义的明文编码,设备对外交付后,本体铭牌、Web UI、平台界面、售后工单都会暴露型号、版本等信息,不适合对外。
1.2 问题
明文编码的字段可读,客户或竞品对比几台设备的 SN,即可推算出产品型号与版本迭代节奏。
1.3 目标
引入第二套「外部 SN」,形成双码体系:
- 对外只用外部 SN:机器人本体铭牌 / 贴牌、设备 Web UI、平台界面、对外接口与售后工单,全部只出现外部 SN;
- 内部 SN 仅供内部使用:产线、研发、备件、售后排查等内部场景,需要时才凭内部 SN 查询;
- 两套 SN 严格一一对应:一台设备有且只有一个内部 SN、一个外部 SN,双向可查;
- 外部 SN 不可读:不含型号、版本、年份、工厂等任何可读语义,也无从推导;
- 一台设备一个码:外部 SN 每台独立随机,同类设备之间也不存在相同段或可识别的成组规律。
1.4 适用范围
| 场景 | 使用哪个 SN |
|---|---|
| 产线生产、贴标、出厂检验 | 内部 SN(同时生成外部 SN 并绑定) |
| 机器人本体铭牌 / 贴牌二维码 | 外部 SN |
| 设备 Web UI(本地管理页) | 外部 SN |
| 平台设备列表、详情、搜索、导出 | 外部 SN |
| 对外接口、日志、故障包文件名 | 外部 SN |
| 内部备件、维修、返厂、研发定位 | 内部 SN(凭外部 SN 反查) |
二、编码规则
2.1 总览
一台设备同时持有两套编码:
内部 SN:APEX-A21-000001 ← 产线生成,有语义,不对外
外部 SN:DEX-7K4M2X9-QD3F5 ← 产线同步生成,外部唯一、随机
- 生成时机:同一时刻(建档 / 贴标时)。
- 绑定关系:写入设备主数据同一行,
internal_sn与external_sn两列均为全局唯一。 - 变更规则:两套 SN 一经生成终身不变。设备换主板、OTA 升级、改型号均不重新编码。
2.2 内部 SN
2.2.1 结构
APEX - A21 - 000001
└┬─┘ └┬─┘ └──┬──┘
│ │ └── 序号:6 位数字
│ └─────────── 版本号:1 位代系字母 + 2 位主次版本
└────────────────── 产品名称:型号英文名
有效字符 13 位,带分隔符显示为 15 个字符。
2.2.2 各段定义
| 段 | 长度 | 字符集 | 取值规则 | 示例 |
|---|---|---|---|---|
| 产品名称 | 4(按型号可变) | 大写字母 | 产品型号英文名,同一型号固定不变 | APEX、MINT |
| 版本号 | 3 | 1 字母 + 2 数字 | 字母表代系,两位数字表主次版本(2.1 → 21) |
A21 = A 代系 2.1 版 |
| 序号 | 6 | 数字 | 000001–999999,在「产品名称 + 版本号」范围内递增 |
000001 |
2.2.3 版本号口径
- 内部 SN 中的版本号是出厂版本,不随 OTA 升级变化。设备升级到 A22 后,SN 仍是 A21。
- 设备当前版本一律以设备档案的「软件版本 / 固件版本」字段为准。
- 代系字母(A/B/C…)与数字版本的对应关系,由产品侧在《版本号对照表》中登记。
2.2.4 生产信息不进 SN
内部 SN 不再承载批次、工厂、型号代号等生产信息。这些信息改为设备档案字段入库:
| 信息 | 落点 |
|---|---|
| 生产批次(年 + 周) | 设备档案字段 |
| 生产工厂 | 设备档案字段 |
| 型号代号 | 由「产品名称」直接表达,不再单设 |
2.2.5 生成与唯一性
- 内部 SN 由产线系统生成,不手工填写;
- 同一台设备只生成一次,建档后不可修改(与现有「设备编码建档后不可改」口径一致);
- 序号取当前「产品名称 + 版本号」组合下的最大序号 + 1;
- 数据库中
internal_sn建全局唯一索引。
2.2.6 示例
APEX-A21-000001:APEX 型号,A 代系 2.1 版,该版本第 1 台。
2.3 外部 SN
2.3.1 设计原则
外部 SN 不做加密、不做可推导编码,只做两件事:唯一、不可读。
- 型号、版本、年份、工厂不进入编码,改存设备档案字段;
- 码面全部为随机字符,外部拿到 SN 无法推导出任何设备属性;
- 需要解读时只能查系统(凭外部 SN 反查设备档案)。
为什么不设「只有我们知道的编码规则」:规则只要是确定的,被人拿到(研发流动、代码泄露、供应商知情)就能反推,而且反推不需要数据库;一旦反推,已发出的全部设备信息都暴露且无法收回(铭牌收不回来)。随机码没有可反推的东西,攻击面为零。
2.3.2 结构
DEX - 7K4M2X9 - QD3F5
└──┬──┘ └─┬─┘
│ └── 流水码:5 位随机
└─────────── 中间码:7 位随机
有效字符 12 位,带分隔符显示为 14 个字符。
中间码与流水码都是随机生成、都承载零信息。保留两段仅为码面分段易读;若希望码更短,可合并为一段 12 位随机串(
DEX-7K4M2X9QD3F),效果完全等价。
2.3.3 各段定义
| 段 | 长度 | 字符集 | 说明 |
|---|---|---|---|
| 公司标识 | 3 | 大写字母 | 固定 DEX,唯一可读项 |
| 中间码 | 7 | Crockford Base32 | 每台独立随机生成,非递增,不含任何语义 |
| 流水码 | 5 | Crockford Base32 | 每台独立随机生成,非递增,不含任何语义 |
2.3.4 生成规则
- 随机源:密码学安全随机数(服务端
crypto.randomBytes/crypto.randomInt),禁止Math.random; - 禁止递增:不得按扫描顺序、产线队列或时间顺序发放,否则客户对比两台即可排出先后;
- 一次性生成:中间码与流水码同时生成,合起来构成外部 SN;
- 碰撞处理:与库中已有
external_sn重复时重新生成,直至唯一(12 位随机,碰撞概率极低); - 兜底:数据库对
external_sn建全局唯一索引; - 原子性:外部 SN 与内部 SN 在同一事务内落库绑定,不允许只写一个;
- 禁止人工编制:外部 SN 一律由系统生成,产线不得手工填写或修改。
容量:中间码 32⁷ ≈ 343 亿,流水码 32⁵ ≈ 3355 万,合并 32¹² ≈ 1.15 × 10¹⁸。按年产百万台计也无需扩位。
2.3.5 中间码与设备属性的关系
外部 SN 不承载设备属性,以下信息全部存设备档案,凭外部 SN 反查:
| 属性 | 落点 |
|---|---|
| 型号 / 版本 | 设备档案(与内部 SN 一致) |
| 生产年份 / 生产工厂 | 设备档案字段 |
| 生产批次 | 设备档案字段 |
- 中间码每台独立随机,因此同一型号、同一版本、同一年份、同一工厂的多台设备,各自拥有不同的中间码;
- 这四类属性不参与中间码的计算,而是与内部码、外部码一起写入设备档案,成为该设备的属性记录;
- 内部人员凭外部 SN(中间码 + 流水码)即可在平台查出它对应的型号、版本、年份、工厂;
- 中间码不参与反查:查表键是完整的
external_sn,不是中间码本身。若干台设备的中间码恰好相同也不影响识别,各自仍然指向各自的设备记录。 - 必须以整条 SN 查询:查询键是完整的
external_sn(公司标识 + 中间码 + 流水码),缺任何一段都查不到设备; - 不支持按片段查:单独拿中间码、单独拿流水码都无法定位设备。中间码只承载随机,不承载信息,脱离整条 SN 没有意义;
- 售后受理报修、备件、返修时,一律要求提供完整 SN,不接受只给中间几位。
结论:中间码是随机码,不是密码。它不承载属性、也不能被解出属性;属性只能通过查库获得。这一点需在对接文档中向研发与售后写明。
2.3.6 字符集与输入容错
中间码与流水码使用 Crockford Base32:0123456789ABCDEFGHJKMNPQRSTVWXYZ,共 32 个字符。
- 去掉
I、L、O、U:I/L与1、O与0、U与V易混; - 输入容错:系统接收小写及易混字符并归一化 ——
o/O → 0、i/I/l/L → 1、u/U → V; - 公司标识统一大写,用户输入
Dex、dex一律归一化为DEX。
随机段必须使用 32 字符集,不能只用数字。纯数字 7 位仅 1000 万个组合,产量上去后碰撞重试显著增加。
2.3.7 防手误(两项措施)
- 二次确认:录入外部 SN 后不直接跳转,先展示「
DEX-7K4M2X9-QD3F5· 设备名称 · 当前状态」供操作员确认,确认后再进入设备详情; - 查不到时的提示:提示「未找到该设备,请核对 SN 或改用扫码」,并给出扫码入口。
可选:加一位校验位。 随机码没有自校验,手抄错一位表现为「查不到」,无法区分「打错了」还是「设备不存在」。需要区分时可按以下最简规则加 1 位:
除校验位外每个字符在 32 字符表中查序号(
0–31),全部相加,对 32 取模,用该值查表得到校验字符。
该规则可发现全部单字符错误,但发现不了相邻两位写反。是否启用见「三、待确认」。
2.3.8 示例
| 内部 SN | 外部 SN |
|---|---|
APEX-A21-000001 |
DEX-7K4M2X9-QD3F5 |
外部 SN 中只读得出 DEX 公司标识;型号、版本、年份、工厂均需凭 SN 查设备档案。
2.4 双码对应关系
2.4.1 存储
设备主数据新增以下字段,internal_sn 与 external_sn 均全局唯一、不可为空、生成后不可修改:
| 字段 | 说明 | 对外可见 |
|---|---|---|
internal_sn |
内部 SN,形如 APEX-A21-000001 |
否(仅内部角色) |
external_sn |
外部 SN,形如 DEX-7K4M2X9-QD3F5 |
是(所有对外场景) |
| 型号 / 版本 | 沿用设备档案现有字段 | 否 |
production_year |
生产年份 | 否 |
production_factory |
生产工厂 | 否 |
production_batch |
生产批次(年 + 周) | 否 |
上表中除 external_sn 外的字段,共同构成「凭外部 SN 查设备」时返回的属性信息;内部角色在平台输入外部 SN,即可看到该设备的型号、版本、年份、工厂与生产批次。
一一对应由两列各自的唯一索引保证,不需要映射表。若后续内部 SN 与外部 SN 分离到不同系统存放,则另建映射表(external_sn ↔ internal_sn,外部 SN 作唯一键),映射关系仍为 1:1。
2.4.2 查询能力
- 双向可查:输入外部 SN → 内部角色可查到内部 SN;输入内部 SN → 可查到外部 SN;
- 属性查询:凭外部 SN 反查设备档案,得到型号、版本、生产年份、工厂等;
- 整条查询:查询键为完整
external_sn,不接受中间码、流水码等片段查询; - 反查权限:外部 SN → 内部信息的查询能力只对内部角色开放。
2.4.3 使用边界
- 对外一律用外部 SN:铭牌、贴纸、二维码、Web UI、平台列表与详情、导出、接口、日志、故障包文件名、售后工单;
- 内部 SN 不外流:仅产线系统、研发与维修后台可见,平台内按权限收敛 —— 内部角色可查看、可搜索,客户与外部角色不可见。
2.4.4 存量设备
- 2.1 及以前设备为内部自用,不改内部 SN,不追溯补发外部 SN;
- 存量设备如需对外流转(交付客户、返厂维修、接入客户系统),由系统按 2.3 规则补发外部 SN 并记录绑定关系;
- 补发的外部 SN 与 2.2 新设备格式完全一致,不留可识别的新旧差异。
2.5 防泄露约束
外部 SN 的价值在于「内部 SN 不外流」。以下出口需同步改造,漏一个则双码设计失效:
| 出口 | 现状 | 要求 |
|---|---|---|
| 故障日志包文件名 | fault-<设备SN>-<时间>-<随机码>.tar.gz,当前取的是设备编码 |
改用外部 SN |
| OTA 升级包命名 / 升级接口 | 含设备编码 | 改用外部 SN |
| 设备二维码 | 待设计 | 内容为外部 SN 或短链(如 https://.../d/<external_sn>),不得包含可离线解析出内部信息的结构 |
| 平台接口返回 / 服务端日志 | 待确认 | 不得返回或打印内部 SN |
| 售后工单 / 客户报表 | 待确认 | 一律外部 SN |
三、待确认
- 内部 SN 的「产品名称」段长度:现按型号名长度可变(
APEX4 位、MINT4 位),是否统一固定位数; - 版本号的代系字母与数字版本对应关系,由谁维护《版本号对照表》;
- 外部 SN 是否保留「中间码 + 流水码」两段结构。两段均为随机、均无信息,合并成一段 12 位更短且完全等价;
- 外部 SN 是否启用 1 位校验(见 2.3.7),启用则总长变为 13 位;
- 平台字段名是否由「设备编码」统一改为「设备 SN」;
- 存量设备补发外部 SN 的触发条件与操作入口。
已定事项(备查)
- 外部 SN 为纯随机,不做加密、不做可推导编码;型号、版本、年份、工厂均不出现在码面。
- 一台设备一个码:同类设备的外部 SN 之间不存在相同段或可识别的成组规律。
- 设备属性一律存设备档案,凭外部 SN 反查;不提供任何从外部 SN 推导属性的算法。
- 内部 SN 不再承载批次、工厂、型号代号,这些信息改存设备档案字段。
- 内部 SN 的版本号是出厂版本,不随 OTA 升级变化。
- 查询一律以整条外部 SN 为键,不支持中间码、流水码等片段查询;售后受理报修 / 备件 / 返修须索取完整 SN。