GitHub 项目地址https://github.com/lidecong133/YModbus写库的时候很多例子都是 C# 代码。但现场排查时你不一定想新建一个项目也不一定想打开 Visual Studio。很多时候只是想确认一句话这个设备现在到底能不能读这时候命令行工具就很顺手。YModbus.Cli的定位不是替代主站调试软件而是提供一个可以复制、可以脚本化、可以被自动化工具调用的入口。先跑一个最小读取开发阶段可以直接用dotnet run。dotnet run--project.\src\YModbus.Cli\YModbus.Cli.csproj--read-holding-registers--host 127.0.0.1--port 1502--unit-id 1--address 0--quantity 2注意中间的--。前面是dotnet run的参数后面才是传给 YModbus.Cli 的参数。如果你已经发布或安装成ymodbus命令命令会更短ymodbusread-holding-registers--host 127.0.0.1--port 1502--unit-id 1--address 0--quantity 2我一般第一次测试只读 1 个或 2 个寄存器。数量小问题更容易判断。读通以后再扩大范围。CLI输出为什么用JSON读保持寄存器时CLI 会返回类似这样的结果{success:true,operation:read-holding-registers,transport:tcp,endpoint:127.0.0.1:1502,unitId:1,address:0,quantity:2,values:[1234,5678],hexValues:[0x04D2,0x162E]}这个格式对人也能看对脚本也好处理。比如你想在 PowerShell 里判断读取是否成功可以把 JSON 转成对象。以后做批量测试、自动报告、AI Agent 调用也不用再去解析一堆控制台文本。十六进制也很重要。现场看状态字时0x0005比十进制5更直观因为你能马上想到 bit0 和 bit2 置位。TCP、RTU、ASCII怎么写TCP 最常见ymodbusread-holding-registers--transport tcp--host 192.168.1.10--port 502--unit-id 1--address 0--quantity 10RTU 要带串口参数ymodbusread-holding-registers--transport rtu--serial-port COM3--baud-rate 9600--data-bits 8--parity none--stop-bitsone--slave-id 1--address 0--quantity 10ASCII 只是 transport 和串口参数不同ymodbusread-coils--transport ascii--serial-port COM3--baud-rate 9600--data-bits 7--parity even--stop-bitsone--slave-id 1--address 0--quantity 8如果设备手册只写 RS485 Modbus大多数时候是 RTU。只有明确写 Modbus ASCII才按 ASCII 处理。一个很实用的小场景判断地址差1手册写40001 当前值你不知道程序里填0还是1。可以先用 CLI 快速试两次ymodbusread-holding-registers--host 192.168.1.10--port 502--unit-id 1--address 0--quantity 1 ymodbusread-holding-registers--host 192.168.1.10--port 502--unit-id 1--address 1--quantity 1如果地址0有值地址1也有值还不能直接下结论。最好找一个设备屏幕上能看到的已知值比如温度、压力、计数器再对照哪个地址更像。这比在主程序里改来改去方便很多。写入为什么默认dry-runCLI 的写命令默认不真正写设备。比如ymodbuswrite-single-register--host 127.0.0.1--port 1502--unit-id 1--address 0--value 123不加--confirm它按 dry-run 处理。真正写入要明确加ymodbuswrite-single-register--host 127.0.0.1--port 1502--unit-id 1--address 0--value 123--confirm这个设计看起来啰嗦但我觉得是必要的。现场复制命令很容易复制错。读错最多是结果不对写错可能真的改变设备参数。让写操作必须显式确认可以挡住一部分低级事故。批量写也是一样ymodbuswrite-registers--host 127.0.0.1--port 1502--unit-id 1--address 0--values 1,2,0x0003--confirm ymodbuswrite-coils--host 127.0.0.1--port 1502--unit-id 1--address 0--values 1,0,true,false--confirm第一次建议先对 YModbus 从站模拟器写。确认写入逻辑和地址没问题再考虑真实设备。扫描站号别贪大不知道 UnitId / SlaveId 时可以扫小范围ymodbus scan-units--host 192.168.1.10--port 502--start-unit-id 1--end-unit-id 10--function03--address 0--quantity 1我不建议一上来扫1..247。如果每个站号超时 1 秒扫完整个范围要等很久。设备慢一点、网关再慢一点现场人会以为软件卡死了。更好的做法是先根据设备拨码、手册、网关配置缩小范围。比如客户说大概是 1 到 8那就先扫 1 到 8。扫地址也要克制站号确定但不知道地址可以用ymodbus scan-addresses--unit-id 1--function03--address 0--end-address 100--quantity 1这个适合判断某段地址是否可读。但不要拿真实设备盲扫大范围。尤其是老设备和串口网关连续请求太密可能让设备响应变慢甚至影响现场业务。我的习惯是先找手册上最可能的几段地址小范围扫确认以后再做完整地址表。厂家私有功能码有些厂家会给私有功能码。YModbus.Cli 提供customymodbus custom--unit-id 1--function-code 65--payload 01-02-03--response-bytes 2RTU / ASCII 自定义功能码一定要知道响应长度或者知道它的长度规则。因为 RTU 帧本身没有 TCP 那种 MBAP length 字段不告诉工具读多少很难可靠判断一帧到哪里结束。我会怎么用CLI现场排查时我一般这样用先读一个保持寄存器确认链路通不通再试03和04确认数据区再试地址0和1判断地址基准如果是网关再扫小范围 UnitId确认读没问题以后再考虑写写操作先对从站模拟器做再对真实设备做CLI 的价值就在这里每一步都有一条命令每一步结果都能保留下来。它不像手动点界面那样容易忘记刚才改了什么。
(十一)YModbus CLI命令行工具使用
GitHub 项目地址https://github.com/lidecong133/YModbus写库的时候很多例子都是 C# 代码。但现场排查时你不一定想新建一个项目也不一定想打开 Visual Studio。很多时候只是想确认一句话这个设备现在到底能不能读这时候命令行工具就很顺手。YModbus.Cli的定位不是替代主站调试软件而是提供一个可以复制、可以脚本化、可以被自动化工具调用的入口。先跑一个最小读取开发阶段可以直接用dotnet run。dotnet run--project.\src\YModbus.Cli\YModbus.Cli.csproj--read-holding-registers--host 127.0.0.1--port 1502--unit-id 1--address 0--quantity 2注意中间的--。前面是dotnet run的参数后面才是传给 YModbus.Cli 的参数。如果你已经发布或安装成ymodbus命令命令会更短ymodbusread-holding-registers--host 127.0.0.1--port 1502--unit-id 1--address 0--quantity 2我一般第一次测试只读 1 个或 2 个寄存器。数量小问题更容易判断。读通以后再扩大范围。CLI输出为什么用JSON读保持寄存器时CLI 会返回类似这样的结果{success:true,operation:read-holding-registers,transport:tcp,endpoint:127.0.0.1:1502,unitId:1,address:0,quantity:2,values:[1234,5678],hexValues:[0x04D2,0x162E]}这个格式对人也能看对脚本也好处理。比如你想在 PowerShell 里判断读取是否成功可以把 JSON 转成对象。以后做批量测试、自动报告、AI Agent 调用也不用再去解析一堆控制台文本。十六进制也很重要。现场看状态字时0x0005比十进制5更直观因为你能马上想到 bit0 和 bit2 置位。TCP、RTU、ASCII怎么写TCP 最常见ymodbusread-holding-registers--transport tcp--host 192.168.1.10--port 502--unit-id 1--address 0--quantity 10RTU 要带串口参数ymodbusread-holding-registers--transport rtu--serial-port COM3--baud-rate 9600--data-bits 8--parity none--stop-bitsone--slave-id 1--address 0--quantity 10ASCII 只是 transport 和串口参数不同ymodbusread-coils--transport ascii--serial-port COM3--baud-rate 9600--data-bits 7--parity even--stop-bitsone--slave-id 1--address 0--quantity 8如果设备手册只写 RS485 Modbus大多数时候是 RTU。只有明确写 Modbus ASCII才按 ASCII 处理。一个很实用的小场景判断地址差1手册写40001 当前值你不知道程序里填0还是1。可以先用 CLI 快速试两次ymodbusread-holding-registers--host 192.168.1.10--port 502--unit-id 1--address 0--quantity 1 ymodbusread-holding-registers--host 192.168.1.10--port 502--unit-id 1--address 1--quantity 1如果地址0有值地址1也有值还不能直接下结论。最好找一个设备屏幕上能看到的已知值比如温度、压力、计数器再对照哪个地址更像。这比在主程序里改来改去方便很多。写入为什么默认dry-runCLI 的写命令默认不真正写设备。比如ymodbuswrite-single-register--host 127.0.0.1--port 1502--unit-id 1--address 0--value 123不加--confirm它按 dry-run 处理。真正写入要明确加ymodbuswrite-single-register--host 127.0.0.1--port 1502--unit-id 1--address 0--value 123--confirm这个设计看起来啰嗦但我觉得是必要的。现场复制命令很容易复制错。读错最多是结果不对写错可能真的改变设备参数。让写操作必须显式确认可以挡住一部分低级事故。批量写也是一样ymodbuswrite-registers--host 127.0.0.1--port 1502--unit-id 1--address 0--values 1,2,0x0003--confirm ymodbuswrite-coils--host 127.0.0.1--port 1502--unit-id 1--address 0--values 1,0,true,false--confirm第一次建议先对 YModbus 从站模拟器写。确认写入逻辑和地址没问题再考虑真实设备。扫描站号别贪大不知道 UnitId / SlaveId 时可以扫小范围ymodbus scan-units--host 192.168.1.10--port 502--start-unit-id 1--end-unit-id 10--function03--address 0--quantity 1我不建议一上来扫1..247。如果每个站号超时 1 秒扫完整个范围要等很久。设备慢一点、网关再慢一点现场人会以为软件卡死了。更好的做法是先根据设备拨码、手册、网关配置缩小范围。比如客户说大概是 1 到 8那就先扫 1 到 8。扫地址也要克制站号确定但不知道地址可以用ymodbus scan-addresses--unit-id 1--function03--address 0--end-address 100--quantity 1这个适合判断某段地址是否可读。但不要拿真实设备盲扫大范围。尤其是老设备和串口网关连续请求太密可能让设备响应变慢甚至影响现场业务。我的习惯是先找手册上最可能的几段地址小范围扫确认以后再做完整地址表。厂家私有功能码有些厂家会给私有功能码。YModbus.Cli 提供customymodbus custom--unit-id 1--function-code 65--payload 01-02-03--response-bytes 2RTU / ASCII 自定义功能码一定要知道响应长度或者知道它的长度规则。因为 RTU 帧本身没有 TCP 那种 MBAP length 字段不告诉工具读多少很难可靠判断一帧到哪里结束。我会怎么用CLI现场排查时我一般这样用先读一个保持寄存器确认链路通不通再试03和04确认数据区再试地址0和1判断地址基准如果是网关再扫小范围 UnitId确认读没问题以后再考虑写写操作先对从站模拟器做再对真实设备做CLI 的价值就在这里每一步都有一条命令每一步结果都能保留下来。它不像手动点界面那样容易忘记刚才改了什么。