一、前期准备:3步凑齐必要软硬件
本次方案用开源工具+百元级设备,无额外授权费,适合中小型档案室快速试水。
1. 硬件清单(附可选替代型号)
- 必选:UHF RFID读写器(桌面式/USB便携式)——推荐型号:Impinj R420 USB Mini(价格约180元,读写距离桌面0.5-1米,可批量绑定标签),替代:国产优博讯DT20 UHF模块(约200元)
- 必选:UHF RFID档案标签——选择纸质不干胶背贴、ISO18000-6C协议、尺寸70×20mm或60×15mm(适配档案盒侧面/背脊),用量按需(1盒1张,约0.15元/张)
- 可选但推荐:条码打印机(普通热敏/热转印均可)——替代方案:手写标签唯一标识后拍照上传OCR(但批量操作慢)
- 必选:Windows/Mac笔记本/台式机——配置无特殊要求,能装Python 3.8+即可
2. 基础软件环境搭建
所有操作均用Windows演示,Mac/Linux仅需调整路径格式
- 安装Python 3.9——下载地址:https://www.python.org/ftp/python/3.9.13/python-3.9.13-amd64.exe,安装时务必勾选Add Python 3.9 to PATH
- 验证Python安装——打开CMD(Windows徽标+R输入cmd回车),输入
python --version,显示Python 3.9.13即为成功
- 安装依赖库——CMD继续输入以下完整命令,复制粘贴即可:
pip install flask flask-sqlalchemy pyserial openpyxl -i https://pypi.tuna.tsinghua.edu.cn/simple
3. 读写器驱动安装
Impinj R420 Mini免驱动,优博讯DT20需下载CH340串口驱动:https://www.wch.cn/downloads/CH341SER_EXE.html,解压后直接运行SETUP.EXE安装,重启电脑后生效。
二、系统代码:复制粘贴即可运行的极简平台
本系统包含标签绑定、档案入库、实时库存查询、简易盘点4个核心功能,代码分3个文件存放,先在桌面建名为archive_iot的文件夹。
1. 数据库配置与初始化文件(config.py)

在archive_iot文件夹新建文本文件,重命名为config.py,粘贴以下完整内容:
```python
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config:
SECRET_KEY = 'your_archive_iot_secret_key_2024' 可随意修改,用于安全加密
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'archive.db')
SQLALCHEMY_TRACK_MODIFICATIONS = False
```
2. 核心业务逻辑与数据库模型(app.py)
在archive_iot文件夹新建文本文件,重命名为app.py,粘贴以下完整内容:
```python
from flask import Flask, render_template_string, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from config import Config
import serial.tools.list_ports
import time
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
档案数据库模型
class Archive(db.Model):
id = db.Column(db.Integer, primary_key=True)
rfid_epc = db.Column(db.String(24), unique=True, nullable=False)
archive_code = db.Column(db.String(50), unique=True, nullable=False)
archive_name = db.Column(db.String(100), nullable=False)
location = db.Column(db.String(50), nullable=False)
status = db.Column(db.String(10), default='在库')
create_time = db.Column(db.DateTime, default=db.func.now())
初始化数据库(仅需运行1次,已注释,首次运行需取消注释)
with app.app_context():
db.create_all()
HTML模板(内置,无需单独建HTML文件)
HTML_TEMPLATE = """
极简档案物联网平台
极简档案物联网平台
1. 读写器连接
{% if serial_status == '已连接' %}
2. 标签绑定+入库
3. 简易盘点
{% endif %}
4. 档案库存查询
| RFID EPC | 档案编号 | 档案名称 | 存放位置 | 状态 | 操作 |
{% for archive in archives %}
| {{ archive.rfid_epc }} |
{{ archive.archive_code }} |
{{ archive.archive_name }} |
{{ archive.location }} |
{{ archive.status }} |
删除 |
{% endfor %}
"""
全局变量
serial_conn = None
serial_status = '未连接'
bind_msg = ''
inventory_msg = ''
获取可用串口
def get_serial_ports():
return list(serial.tools.list_ports.comports())
读写器指令(适用于Impinj R420 Mini和兼容ISO18000-6C的串口读写器,波特率115200)
def send_command(cmd):
if not serial_conn:
return None
serial_conn.write(cmd.encode('ascii') + b'\r\n')
time.sleep(0.2)
return serial_conn.read_all().decode('ascii', errors='ignore')
@app.route('/', methods=['GET', 'POST'])
def index():
global serial_conn, serial_status, bind_msg, inventory_msg
archives = Archive.query.all()
ports = get_serial_ports()
if request.method == 'POST':
action = request.form.get('action')
if action == 'connect':
port = request.form.get('serial_port')
try:
serial_conn = serial.Serial(port, 115200, timeout=1)
serial_status = '已连接'
初始化读写器为EPC读取模式
send_command('N')
except Exception as e:
serial_status = f'连接失败:{str(e)}'
elif action == 'disconnect':
if serial_conn:
serial_conn.close()
serial_conn = None
serial_status = '未连接'
elif action == 'bind_and_add':
读取标签EPC
send_command('R') 不同读写器读取指令可能不同,优博讯DT20用0x02 0x01指令,需自行替换(替换后需调整send_command解码方式)
resp = send_command('')
epc = ''
for line in resp.split('\n'):
if len(line.strip()) == 24:
epc = line.strip()
break
if not epc:
bind_msg = '未检测到标签,请将标签靠近读写器'
else:
code = request.form.get('archive_code')
name = request.form.get('archive_name')
loc = request.form.get('location')
if Archive.query.filter_by(rfid_epc=epc).first():
bind_msg = '该标签已绑定档案'
elif Archive.query.filter_by(archive_code=code).first():
bind_msg = '该档案编号已存在'
else:
new_archive = Archive(rfid_epc=epc, archive_code=code, archive_name=name, location=loc)
db.session.add(new_archive)
db.session.commit()
bind_msg = f'绑定成功!EPC:{epc}'
elif action == 'inventory':
批量读取标签并更新状态
Archive.query.update({'status': '不在库'})
db.session.commit()
读取10秒内的所有标签
start_time = time.time()
detected_epcs = set()
while time.time() - start_time < 10:
send_command('R')
resp = send_command('')
for line in resp.split('\n'):
if len(line.strip()) == 24:
detected_epcs.add(line.strip())
更新检测到的档案状态
for epc in detected_epcs:
archive = Archive.query.filter_by(rfid_epc=epc).first()
if archive:
archive.status = '在库'
db.session.commit()
inventory_msg = f'盘点完成!在库:{len(detected_epcs)},不在库:{len(archives)-len(detected_epcs)}'
return render_template_string(HTML_TEMPLATE, ports=ports, serial_status=serial_status, bind_msg=bind_msg, inventory_msg=inventory_msg, archives=archives)
@app.route('/delete/
')
def delete_archive(id):
archive = Archive.query.get_or_404(id)
db.session.delete(archive)
db.session.commit()
return redirect(url_for('index'))
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')
```
3. 首次运行数据库初始化
打开app.py,找到第20-21行的注释代码:
```python
初始化数据库(仅需运行1次,已注释,首次运行需取消注释)
with app.app_context():
db.create_all()
```
将两行删除(取消注释),保存后打开CMD,进入archive_iot文件夹(输入cd Desktop/archive_iot),输入python app.py运行,看到Running on http://0.0.0.0:5000后立即按Ctrl+C停止,再把刚才取消的注释重新加上(防止重复初始化)。
三、全流程实操:10分钟上手
1. 启动平台并连接读写器
- 重新进入archive_iot文件夹,输入
python app.py启动
- 打开浏览器(Chrome/Edge均可),访问
http://127.0.0.1:5000
- 在“串口选择”下拉框找到读写器对应的端口(Impinj R420 Mini一般显示USB Serial Port),点击连接,状态变为“已连接”即可
2. 标签绑定与档案入库
- 将一张UHF RFID档案标签平放在读写器感应区(距离0-5cm最佳)
- 输入档案编号(如2024-WD-001)、档案名称(如2024年第一季度财务凭证)、存放位置(如1柜1层1格)
- 点击绑定标签并入库,提示绑定成功后,库存表格会自动新增一条记录
- 重复操作完成所有档案的绑定入库
3. 简易盘点
- 将所有已绑定的档案盒移到读写器感应区周围1米内(如放在读写器旁边的桌子上)
- 点击开始盘点,等待10秒(页面会显示等待中,无需刷新)
- 10秒后查看库存表格,不在库的档案会标红(未标红代码里默认在库是正常黑字,如需标红可在HTML_TEMPLATE的td里加style,操作不影响核心功能)
- 如用国产其他读写器,需将app.py里的
send_command('R')替换为对应品牌的读取指令(可查看读写器说明书)
4. 局域网共享(可选)
启动时的host='0.0.0.0'已开启局域网共享,其他同局域网的设备(手机/平板/电脑)可访问本机IP:5000使用,本机IP查询方式:CMD输入ipconfig,找到IPv4地址(如192.168.1.100)。