Expect TCL发送高值数据自动转为Unicode的问题求助
Expect v5.45 (macOS) 发送二进制数据自动转码问题的解决方法
问题背景
在macOS上使用Expect v5.45操作串口时,所有值大于0x7F的字节会被自动转为UTF-8编码发送(例如0xDB被转为0xC3 0x9B),额外的字节导致接收端异常。即使对串口通道设置了-encoding binary -translation binary,问题依然存在;但改用TCL原生的puts -nonewline命令发送则完全正常。
问题复现代码
set portID [open $serial_dev r+] fconfigure $portID -mode "9600,n,8,1" fconfigure $portID -handshake "rtscts" fconfigure $portID -encoding binary -translation binary spawn -open $portID set send_slow {1 .5} send -s -raw -- [binary format H* DB20DC20DD20100A]
调试信息确认
Expect调试输出显示send命令将二进制数据解析为Unicode字符后发送:
send: sending "\u00db \u00dc \u00dd \u0010\n" to { exp7 }
回环测试收到的转码后数据:
00000000: c3 9b 20 c3 9c 20 c3 9d .. .. .. 00000008: 20 10 0a 0a 0a ....
临时解决方案(使用puts)
直接用TCL的puts命令发送二进制数据可以绕过Expect的转码逻辑:
puts -nonewline $portID [binary format H* DB20DC20DD20100A]
该方式能发送正确的原始字节:
00000000: db 20 dc 20 dd 20 10 0a . . . ..
针对send命令的核心解决方法
问题根源在于spawn -open创建的Expect通道并未继承原串口通道的二进制配置,需要在spawn后重新配置该通道:
set portID [open $serial_dev r+] fconfigure $portID -mode "9600,n,8,1" fconfigure $portID -handshake "rtscts" fconfigure $portID -encoding binary -translation binary spawn -open $portID # 关键:配置spawn生成的Expect通道为二进制模式 fconfigure $spawn_id -encoding binary -translation binary set send_slow {1 .5} send -s -raw -- [binary format H* DB20DC20DD20100A]
原理说明
spawn -open会基于原通道创建一个新的Expect内部通道,默认可能使用系统编码(UTF-8)处理数据- 显式对
$spawn_id设置-encoding binary和-translation binary,强制Expect将数据作为原始字节流发送,避免自动转码 - 配合
send -raw参数,确保数据不被Expect进行任何额外处理
内容的提问来源于stack exchange,提问作者epooch




