树莓派对接RFID读卡器实现标签读取与POST请求上传方案咨询
树莓派RFID读卡器读卡上报实现方案
一、前期环境与硬件准备
- 优先选用串口模式连接读卡器:读卡器插树莓派USB口后,在终端执行
ls /dev/ttyUSB*即可识别到对应设备,默认设备名多为/dev/ttyUSB0。执行sudo usermod -aG dialout $USER给当前用户开放串口操作权限,重启树莓派后生效,后续运行程序无需加sudo。 - 树莓派提前安装.NET 6运行时,和你参考的SerialPort文档版本匹配,兼容性最好。
- 别用浏览器端的Web Serial API实现,该API仅支持桌面端Chrome/Edge内核浏览器,在树莓派上跑服务场景稳定性极差。你有C#基础、又有厂商提供的C#版SDK,直接用.NET开发是成本最低、踩坑最少的选择。
二、核心实现步骤(C# 稳定版)
- 第一步:先跑通厂商SDK的官方Demo
从厂商SDK里找到默认串口配置参数(波特率、数据位、停止位、校验位),这类RFID读卡器常见默认波特率为9600或115200,Demo内会写死默认值。先把Demo跑通,确认树莓派上能正常读到标签卡号,这步别跳过,先排除硬件连接、参数配置错误的问题,再写后续业务逻辑。 - 第二步:封装读卡逻辑加重复过滤
不要用轮询方式读串口,直接绑定SDK提供的「标签读取完成」事件回调即可。读到卡号后先做去重判断:同一张卡3秒内重复读到直接忽略,避免标签一直放在读卡器上重复触发上报请求。 - 第三步:实现HTTP POST上报逻辑
用.NET内置的HttpClient发送请求,注意不要每次发请求都新建HttpClient实例,全局定义一个单例对象即可,避免频繁占用端口导致资源耗尽。请求体按数据库端接口要求构造,一般用JSON格式,加上超时控制和异常捕获,网络闪断时可以做2次重试,不要直接抛异常导致程序退出。
最简实现代码参考:using System.IO.Ports; using System.Net.Http; using System.Text; using System.Text.Json; // 全局单例HttpClient,设置5秒请求超时 private static readonly HttpClient httpClient = new HttpClient() { Timeout = TimeSpan.FromSeconds(5) }; // 读卡去重用变量 private static string _lastCardId = string.Empty; private static DateTime _lastReadTime = DateTime.MinValue; private const int RepeatReadInterval = 3; // 重复读卡过滤间隔3秒 static void Main(string[] args) { // --- 以下二选一 --- // 1. 用厂商SDK的话,替换成SDK初始化逻辑,绑定读卡回调 // RfidReader reader = new RfidReader(); // reader.OnTagReceived += TagReadHandler; // reader.Connect("/dev/ttyUSB0"); // 2. 不用SDK直接用原生SerialPort的话,取消注释下面代码,参数按读卡器实际配置修改 // using SerialPort sp = new SerialPort("/dev/ttyUSB0", 9600, Parity.None, 8, StopBits.One); // sp.DataReceived += (sender, e) => // { // string cardId = sp.ReadExisting().Trim(); // _ = TagReadHandler(cardId); // }; // sp.Open(); Console.WriteLine("读卡器服务已启动,等待读卡..."); Console.ReadLine(); } private static async Task TagReadHandler(string cardId) { // 过滤重复读卡 if (cardId == _lastCardId && (DateTime.Now - _lastReadTime).TotalSeconds < RepeatReadInterval) { return; } _lastCardId = cardId; _lastReadTime = DateTime.Now; Console.WriteLine($"检测到标签,卡号:{cardId},开始上报"); try { // 按接口要求构造请求体 var postBody = new { cardNo = cardId, readTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), deviceCode = "rpi-rfid-01" }; string jsonStr = JsonSerializer.Serialize(postBody); var requestContent = new StringContent(jsonStr, Encoding.UTF8, "application/json"); // 替换为你自己的数据库端接口地址 HttpResponseMessage resp = await httpClient.PostAsync("http://你的服务端接口地址/rfid/upload", requestContent); resp.EnsureSuccessStatusCode(); Console.WriteLine("数据上报成功"); } catch (Exception ex) { Console.WriteLine($"上报失败:{ex.Message}"); // 此处可扩展离线缓存、失败重试逻辑 } } - 第四步:配置开机自启
程序发布完成后,在树莓派上通过systemd配置系统服务,设置程序开机自动启动、异常退出自动重启,无需人工登录维护。
三、常见踩坑排查
- 串口打开报权限错误:先确认当前用户已加入dialout用户组,不要直接用sudo运行程序,容易引发路径、权限依赖问题。
- 读到的数据是乱码:如果不用SDK直接读串口,先核对波特率、编码格式是否和读卡器匹配,这类读卡器默认多输出ASCII格式的卡号,无需额外转码。
- 请求发送失败:先在树莓派终端用curl命令测试接口连通性,排查防火墙、端口、接口地址写错的问题,再调整代码逻辑。
- 如果更熟悉JS想基于Node.js开发,逻辑和上述C#版本完全一致:安装
serialport包做串口监听、用axios发POST请求即可,但没有厂商SDK的话需要自己处理串口粘包、数据截断问题,对新手来说门槛更高。
内容的提问来源于stack exchange,提问作者pro_jfk
相关产品推荐
相关产品推荐

