主题
B8. 串口 ↔ 网口互转框架(把现场串口设备搬到远端)
综合例程。同组其余例程、以及这个库的函数说明在
05-03-tcp-client。 这一页给的是可直接照搬的框架,不是单点示例:下面的代码除了改地址/波特率,基本不用动。
适用:带 RS485/232 串口的机型 | 依赖模块:tcp_client com | 难度:★★☆
场景:现场的仪表/PLC 只出 RS485,远端上位机或服务器想直接跟它对话。两套做法:
- 透传模式:固件直接把"串口收到的字节"原样转发出去、"网口收到的字节"原样写回串口,你不用写任何收发逻辑。
- 代理模式:你想在设备里拦一道(加校验、改内容、做协议转换)时用,自己
send/recv+ 分帧 + 重连。
框架 A:透传模式(最简单,推荐先用)
lua
-- 串口 ↔ TCP 全双工透传;两侧的 set_transparent 都要调
local com1 = com.setup(1, 9600, com.NONE, 8, 1) -- 串口号/波特率/校验/数据位/停止位 按现场仪表改
if not com1 then
print("串口打开失败,检查串口号与波特率档位")
return
end
local tc = tcp_client.creat("192.168.1.100", 9000) -- 远端透传服务端地址
tc:reg(tcp_client.CONNECTED, function()
print("透传通道已建立")
end)
tc:reg(tcp_client.DISCONNECTED, function()
print("透传断开,固件会在重连后自动恢复")
end)
tc:start()
tc:set_transparent() -- ① TCP 侧:这条连接用于透传
com1:set_transparent() -- ② 串口侧:设为透传口并自动起轮询线程要点:
- 两个
set_transparent()缺一不可;顺序无所谓,但两边都要有。 - 设成透传口后不要再自己
send/recv(会抢数据、打乱时序),固件直接转发。 - 波特率必须是允许档位(见
com.setup),填错不报错只返回nil,所以上面判了空。 - TCP 断开重连后透传自动恢复,不用重下脚本。
验证方法:PC 起一个监听 9000 的 TCP 服务端;串口挂一块 Modbus 仪表。服务端发 Modbus 查询帧 → 串口侧原样出去;仪表应答 → 原样回服务端。确认固件没有插入任何多余字节。
注意事项:只用了一侧 set_transparent 会"一边通、一边没反应";透传期间对同串口再 send 数据链路会乱。
框架 B:代理模式(要拦一道内容时)
lua
-- 串口 ↔ TCP 代理:自己收发,可加校验/改内容/做协议转换
local com1 = com.setup(1, 9600, com.NONE, 8, 1)
if not com1 then print("串口打开失败"); return end
com1:set_timeout(1000)
local tc = tcp_client.creat("192.168.1.100", 9000)
local netbuf = "" -- 网口侧待转发到串口的缓冲
tc:reg(tcp_client.RECVDATA, function(data)
if data and #data > 0 then
com1:send(data) -- 网口来的字节 → 写进串口
end
end)
tc:reg(tcp_client.DISCONNECTED, function()
print("TCP 断开")
end)
tc:start()
-- 串口来的字节 → 转发出去(这里原样转发,要改内容就在发出前处理)
com1:reg(function(data)
if data and #data > 0 then
if tc:is_linked() == 1 then -- 返回整数,必须 == 1
tc:send(data)
end
end
end)要点:
- 代理模式不要调
set_transparent,否则串口数据被固件直接吞掉,你的回调收不到。 - 网口侧用
tc:is_linked() == 1判在线再发,断线期间的字节直接丢弃(透传缓冲交给业务层自己管)。 - 串口回调里只做"搬运",别在里面跑长逻辑;要处理内容用
timer或协程。
验证方法:同框架 A,但这次在 com1:reg 回调里加一行 print(string.tohex(data)) 能看到串口原始字节,确认转发链路通。
注意事项:串口回调和 TCP 回调不在同一线程上下文,共享变量(如 netbuf)要注意读写时机;简单转发不需要 netbuf,直接 com1:send(data) 即可。
什么时候用哪种
| 需求 | 选 |
|---|---|
| 仪表只出 RS485,远端直接对话,不改内容 | 框架 A 透传 |
| 要在设备里加校验/做协议转换/记录日志 | 框架 B 代理 |
| 免脚本、纯配置 | 上位机 远程串口透传 |