尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

UPC-A转SGTIN-96 EPC完整指南:从条码到RFID标签的编码实现

发布时间:2026/9/16 16:10:28

资讯中心
01
ARTICLE

UPC-A转SGTIN-96 EPC完整指南:从条码到RFID标签的编码实现

UPC-A转SGTIN-96 EPC完整指南:从条码到RFID标签的编码实现
简介面向供应链、仓储及物联网开发人员的C#源码包聚焦UPC编码批量转换SGTIN96也可作为学习EPC编码规则的参考。包内包含完整Visual Studio解决方案工程文件、C#源码、配置文件及依赖库一目了然便于直接调试和二次开发。压缩包共177个文件以dll、xml、cs为主另有config、exe、pdb等辅助文件整体约82.36MB目录结构清晰适合对照源码理解GS1公司前缀扩展、单品标识截取、序列号填充及校验位计算等关键步骤。已有1543人学习/下载。通过实际运行和阅读代码读者可掌握SGTIN96位域布局、UPC到EPC的位运算转换逻辑并能将转换函数集成到库存管理或追溯系统中提升单品级追踪能力。1. SGTIN96 到底解决什么问题UPC 光学码与 EPC 射频标的对接UPC-A 是贴在商品外包装上的 12 位光学条码扫码枪看到的是商品类目不是单件商品。RFID 标签里需要的是 EPC电子产品代码而 SGTIN96 是 EPC 体系里专门给贸易项目做序列化标识的 96 位紧凑格式。UPC 转 EPC 这件事在零售 RFID 项目里几乎绕不开门店要盘点、防损、自动结算后台系统却只认 UPC 编码贴标机、RFID 打印机和读写器又要拿到 24 位十六进制的 EPC 值。SGTIN96 的价值是让同一个商品既能沿用原有 UPC/GTIN 主数据又能在 EPC 里追加唯一序列号。这篇文章把从 UPC-A 到 SGTIN-96 EPC 的完整换算路径讲清楚附带可直接抄的 Python 脚本和排错方法。2. SGTIN-96 的 96 位结构、UPC 到 GTIN-14 的扩展与分区规则做转换之前先把 SGTIN-96 的比特布局记牢。96 位里没有任何一位是多余的少移位一位读写器就会把标签当成未知格式。2.1 96 位切分Header/F 值/Partition/CP/ItemRef/序列号SGTIN-96 从前到后依次是 8 位 Header、3 位 Filter、3 位 Partition、20 到 40 位的公司前缀Company Prefix、4 到 24 位的项目引用Item Reference、38 位序列号。Header 固定为0x30表示这 96 位是 SGTIN-96而不是 SGTIN-198 或 SSCC-96。后三段加起来是 44 位用来表示 13 位十进制基础数据最后的 38 位序列号最多能到2^38 - 1也就是 274877906943。Filter 值不是业务属性它的作用是让读写器在密集 RFID 环境里快速过滤标签类型。比如货架上混着零售单件和组合包装读写器可以只读 Filter1 的标签。Partition 决定公司前缀和项目引用各占多少位两者总和固定在 44 位。公司前缀越长项目引用就越短编码的数字位数也随之变化。UPC-A 转换时通常落到 Partition 6也就是公司前缀 20 位、项目引用 24 位因为 UPC-A 的 6 位“系统字符厂商代码”正好对应 6 位公司前缀。2.2 UPC-A 校验位与 GTIN-14 的展开公式UPC-A 的 12 位数字中最后 1 位是校验位真正参与 SGTIN 编码的是前 11 位。SGTIN-96 并不直接写 GTIN-14 的校验位但编码器必须校验 UPC 原始校验位否则后续反解时导出的 GTIN 会不一致。GTIN-14 校验位的算法是取 13 位基础数字从右往左交替乘 3 和 1累加后取 10 的补数。UPC-A 转 GTIN-14 时常见做法是把 UPC-A 去掉校验位后的 11 位数字拆成两段前 6 位作为公司前缀后 5 位作为项目引用再把项目引用左侧补零到 7 位拼成 13 位基础数字最后重新计算第 14 位校验位。例如012345678905去掉校验位得到01234567890公司前缀012345项目引用67890补零成0067890基础数字是0123450067890重算校验位后 GTIN-14 为01234500678905。注意补零的位置在项目引用左侧不是右侧。求 GTIN 校验位的函数可以直接写成下面的 Python 代码def gs1_check_digit(basic: str) - str: if not basic.isdigit(): raise ValueError(基础数字必须为纯数字) total 0 for idx, ch in enumerate(reversed(basic)): total int(ch) * (3 if idx % 2 0 else 1) return str((10 - total % 10) % 10)代码从字符串最右边开始遍历所以idx0时对应最右侧一位权重是 3。GTIN-14、UPC-A、EAN-13 的校验位计算都遵守这个规律只是位长不同。不要从左往右套公式否则在边界数字上会算错。2.3 分区值与公司前缀长度对照表分区选择的依据是“公司前缀数字长度”和“项目引用数字长度”两者相加必须等于 13。这个 13 对应的是 GTIN-14 中除掉校验位后的 13 位基础数字。GS1 对此有官方分区表编码器在拼位前必须查表。Partition公司前缀位数项目引用位数公司前缀十进制位数项目引用十进制位数04041211377112234101033301494427178552420766202467以分区 6 为例公司前缀只能写 6 位十进制数项目引用只写 7 位十进制数所以项目引用位数是 7。UPC-A 的产品代码只有 5 位不补零就会少两个字符最终位串会短一截。GS1 公司前缀实际长度不一定等于表里这个数因为表里的公司前缀字段已经包含了 GTIN 最左边的包装指示符/系统字符。对 UPC-A 来说第一位系统字符“0”占用这个位置因此 5 位厂商码加上这个“0”正好组成 6 位。3. Python 实现把 UPC-A 编码成 SGTIN-96 EPC编码过程不复杂但位运算一旦写错结果会偏差很远。我一般把整个函数拆成三步先算校验位再构造 GTIN-14 基础数字最后按分区位移入 96 位整数。3.1 先写校验位函数校验位函数在上一章已经给出这里直接复用。为了工程上更严谨函数里会先检查输入是不是数字防止 CSV 里混入空格或字母。用reversed而不是倒序切片是因为对字符串和列表都通用逻辑也更直观。3.2 UPC 转 SGTIN-96 的编码函数下面的函数接受 UPC-A 字符串、序列号、Filter 值返回 GTIN-14 和 24 位十六进制 EPC。为了聚焦核心逻辑这里只覆盖最常见的分区 6也就是公司前缀为 6 位的情况。from typing import Tuple # 分区表: {分区: (公司前缀位数, 公司前缀十进制位数, # 项目引用位数, 项目引用十进制位数)} PARTITION_TABLE { 0: (40, 12, 4, 1), 1: (37, 11, 7, 2), 2: (34, 10, 10, 3), 3: (30, 9, 14, 4), 4: (27, 8, 17, 5), 5: (24, 7, 20, 6), 6: (20, 6, 24, 7), } def upc_to_sgtin96(upc: str, serial: int 1, filter_value: int 1) - Tuple[str, str]: upc upc.strip() if len(upc) 11: # 用户可能已经去掉了UPC校验位 upc upc gs1_check_digit(upc) if len(upc) ! 12 or not upc.isdigit(): raise ValueError(UPC-A 必须是12位纯数字) if upc[-1] ! gs1_check_digit(upc[:11]): raise ValueError(UPC-A 校验位错误) # UPC-A 去校验位取前6位作为公司前缀 data upc[:11] company_prefix data[:6] item_ref data[6:].zfill(7) # 5位产品码左侧补零到7位 # 构造 GTIN-14 基础数字并计算校验位 basic13 company_prefix item_ref gtin14 basic13 gs1_check_digit(basic13) partition 6 cp_bits, cp_digits, item_bits, item_digits PARTITION_TABLE[partition] cp_val int(company_prefix) item_val int(item_ref) # 按位拼装: Header Filter Partition CP ItemRef Serial epc_val 0x30 epc_val (epc_val 3) | (filter_value 0x07) epc_val (epc_val 3) | partition epc_val (epc_val cp_bits) | cp_val epc_val (epc_val item_bits) | item_val if serial 0 or serial 0x3FFFFFFFFF: raise ValueError(序列号必须在 0 到 2^38-1 之间) epc_val (epc_val 38) | serial epc_hex f{epc_val:024X} return gtin14, epc_hex位运算顺序是整段代码的核心。Header 占 8 位所以先左移 3 位放入 Filter再左移 3 位放入 Partition这之后已经用了 14 位。接着左移cp_bits位放入公司前缀再左移item_bits位放入项目引用最后左移 38 位放入序列号。serial 0x3FFFFFFFFF这种写法会静默截断溢出所以这里改成显式判断越界直接抛异常避免生成一个看起来合法但序列号错误的 EPC。3.3 用真实 UPC-A 走一遍编码过程以012345678905、序列号1、Filter1为例函数返回值如下GTIN-14: 01234500678905 EPC(SGTIN-96): 30380C0E40424C800000000130380C0E40424C8000000001正好 24 个十六进制字符对应 96 位。开头的30是 SGTIN-96 的 Header第二个3的高 3 位是 Filter1低 3 位与后面的 bit 拼成分区 6。最后 38 位是序列号 1所以在十六进制尾部体现为0000000001。拿到这个字符串后可以直接用于 RFID 打印机指令、读写器写入命令或 EPC 标签数据管理系统的导入。4. 批量 UPC 转 EPC 命令行脚本参数设计、Filter 选择与常见坑实际项目里不会只转一个 UPC通常是几千行的商品主数据。把转换逻辑封装成命令行脚本输入 CSV输出 GTIN-14、序列号和 EPC才能接进现有流程。4.1 CSV 批量脚本python upc_to_epc.py items.csv --filter 1 --serial-start 1000对应的upc_to_epc.py核心部分如下import argparse import csv def main(): parser argparse.ArgumentParser() parser.add_argument(csv_file) parser.add_argument(--filter, typeint, default1) parser.add_argument(--serial-start, typeint, default1) args parser.parse_args() with open(args.csv_file, newline, encodingutf-8) as f: reader csv.DictReader(f) for line_no, row in enumerate(reader, start2): upc row[upc].strip() serial args.serial_start int(row.get(seq, 0)) try: gtin14, epc upc_to_sgtin96(upc, serial, args.filter) print(f{upc},{gtin14},{serial},{epc}) except ValueError as exc: print(f第{line_no}行错误: {exc}, filesys.stderr)这里的seq列表示同一 UPC 的第几件商品实际序列号可能是流水号也可能是日期门店编号。序列号的设计应遵循企业内部规则但不要出现字母SGTIN-96 的 38 位序列号只接受非负整数。CSV 脚本把错误输出到 stderr成功结果写到 stdout便于后续用管道接进数据库或上传工具。4.2 3 位 Filter 值怎么选Filter 值直接影响读写器盘点时能否快速筛掉无关标签。选错不会导致 EPC 无法解析但会造成漏读或重复盘点。值典型对象0未知或不适用1零售单件例如超市卖的一瓶洗发水2非零售单件例如整箱里的单独电器3零售组合包装例如 6 瓶装饮料4非零售组合包装例如托盘上的箱子5零售构件例如设备中的一个模块6非零售构件7保留不推荐使用与 EAN/UPC 对应的普通零售商品最常用 Filter1。如果同一个 EPC 号码同时出现在门店和仓库建议让后台系统按读写器部署位置区分而不是靠 Filter 值硬顶。4.3 分区、校验位、序列号三个高频坑分区错误是最隐蔽的问题。假设把 UPC-A 的 12 位全部当成公司前缀或者把项目引用补零放在右侧编码结果在表面上看还是 24 位十六进制但用 RFID 读写器反解时GTIN 会变成另一串数字导致仓库主数据查不到。项目引用补零必须放在左侧分区 6 下 5 位产品码要写成 7 位。校验位是第二常见问题。UPC-A 的校验位不能直接搬进 GTIN-14。GTIN-14 的 13 位基础数字重排了结构原来的校验位位置被项目引用占掉必须用基础数字重新计算。常见误用是把 UPC 最后一位作为 GTIN-14 校验位保留这样生成的 EPC 遇到严格校验的解析器会报校验错。序列号溢出排第三。38 位能容纳到 274877906943看似很大但如果有门店代码 9999 日期 9999 流水号 99999强行压缩成 38 位就会出错。脚本里已经做了越界检查生产环境还要在生成序列号前先算最大容量避免写入一半后中断。5. 验证 SGTIN-96 结果反解十六进制 EPC 回到 UPC-A拿到 EPC 字符串后不能只看长度是 24 位就认为没问题。最可靠的验证方式是把 EPC 反解回 GTIN-14再还原成 UPC-A 比对原始输入。5.1 反解函数反解是编码的逆过程先读 Header 确认是0x30再读 Filter 和 Partition根据分区表取出公司前缀和项目引用最后拼出 GTIN-14 并校验。def sgtin96_to_gtin(epc_hex: str) - Tuple[int, int, str, str, str]: epc_val int(epc_hex, 16) header (epc_val 88) 0xFF if header ! 0x30: raise ValueError(Header 不是 0x30不是 SGTIN-96) filter_value (epc_val 85) 0x07 partition (epc_val 82) 0x07 cp_bits, cp_digits, item_bits, item_digits PARTITION_TABLE[partition] cp_val (epc_val (38 item_bits)) ((1 cp_bits) - 1) item_val (epc_val 38) ((1 item_bits) - 1) company_prefix str(cp_val).zfill(cp_digits) item_ref str(item_val).zfill(item_digits) basic13 company_prefix item_ref gtin14 basic13 gs1_check_digit(basic13) return filter_value, partition, company_prefix, item_ref, gtin14针对分区 6 的存货可以再把 GTIN-14 还原成 UPC-A取公司前缀 6 位拼接项目引用的最后 5 位重新计算 UPC-A 校验位。def gtin14_to_upc(gtin14: str, partition: int 6) - str: if gtin14[-1] ! gs1_check_digit(gtin14[:13]): raise ValueError(GTIN-14 校验位错误) basic13 gtin14[:13] company_prefix basic13[:6] product_code basic13[-5:] upc_data company_prefix product_code return upc_data gs1_check_digit(upc_data)用gtin14_to_upc(01234500678905, 6)反推得到012345678905与最初输入一致。这里默认分区 6因为 UCP-A 转换落地几乎都用 6其他分区需要按分区表重新计算前缀和后缀长度不要硬套。5.2 手工检查 96 位二进制如果现场没有 Python可以用任何支持位运算的语言把 EPC 转成二进制人工核对。比如30380C0E40424C8000000001开头 14 位是00110000001110前 8 位00110000是 0x30随后 3 位001是 Filter1再后 3 位110是分区 6。检查完这几项就能确认标签没有被误写成 SGTIN-198 或 SSCC-96。对线上系统还有一种更简单的校验把 EPC 十六进制字符串交给 RFID 读写器读取后再让后台从 EPC 中解析 GTIN看是否落在商品主数据表里。特地说一句话很多打印机指令要求 EPC 连续大写且不带空格例如30380C0E40424C8000000001直接跟在?或指令后面中间插入空格会让读写器按错误长度截断。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。