NModbus4实战解析:C#实现Modbus RTU/TCP主从通信
简介这是一份面向.NET开发者的Modbus通信协议实现源码由C#编写可无缝集成至ASP.NET、WinForms、WPF、Windows服务及控制台程序封装了底层串口与网络通信细节。库支持Modbus TCP、ASCII、RTU多种传输模式提供主站与从站完整实现覆盖线圈、离散输入、保持寄存器及输入寄存器的读写操作并具备异常诊断与异步通信机制适用于工厂自动化、建筑自动化、能源管理与远程监控等场景。压缩包内含223个文件以104个cs源码文件为核心另有103个html格式的API帮助文档、工程配置、测试用例、CHM手册及解决方案文件分别承担查阅接口、配置环境和快速编译等作用整体仅719KB轻量易部署。目前已有403人学习下载。阅读源码可深入理解Modbus协议栈实现、消息帧构造与解析、主从交互流程结合自带测试夹具可学习创建连接、发起请求、处理异常帧等典型操作为自主扩展和维护工业通信功能打下扎实基础。1. NModbus4 C# 源码一个库解决Modbus RTU/TCP主从通信的完整链路做工业上位机开发只要设备带串口或以太网口Modbus协议基本绕不开。NModbus4这个C#库是我在某车间设备数据采集项目里真正吃透的开源实现。它同时提供主站和从站两种角色RTU、ASCII、TCP三种传输方式都覆盖一套API就能把PLC、仪表、变频器的寄存器数据统一读上来。比起自己拼报文、算CRC、处理超时重试这个库把协议细节封装得很干净。它也不是没有脾气坑主要在串口时序、字节顺序和地址偏移上下面按我拆过的源码和调试经历逐一展开。2. NModbus4 源码结构传输层、主站、从站、事件四块拼图2.1 为什么选NModbus4纯C#实现的主从站协议栈在接触这个库之前我一度用“串口发字节数组手动算CRC”的方式写Modbus写完读保持寄存器还算顺利一旦要同时处理写线圈、读输入寄存器、异常帧返回代码就开始膨胀。换成NModbus4之后发现它把协议栈分层得很清晰主站调用一个方法底层自动完成报文组装、CRC校验、超时重发、异常码解析。选择这个库而不是自己实现的理由有两个。第一它同时支持主站和从站两种模式这在做网关类项目时特别有价值第二整个库是纯C#写的没有Native依赖引用简单单测容易跨平台部署时不用额外装驱动。源码包里还有完整的示例工程照着写基本不会迷路。2.2 核心类与接口Factory、Master、Slave、Transport 的职责我把源码包里最重要的类型分成四块ModbusFactory整个库的入口负责创建主站、从站和传输层对象。拿到一个串口或TCP连接先往工厂里一丢就能得到对应角色。IModbusMaster主站接口定义了我们最常用的方法比如ReadHoldingRegisters、ReadInputRegisters、WriteSingleRegister、WriteMultipleRegisters、WriteSingleCoil、WriteMultipleCoils。ModbusSlave从站抽象基类定义了一组读写方法要求实现者自己维护寄存器内存数组和业务数据。它不是那种开箱即用的“假从站”需要一点工作量。Transport传输层抽象负责字节流的写入和读取并处理协议帧的校验。串口用的是ModbusSerialTransportTCP对应ModbusIpTransport。这个分层带来的直接好处是换传输方式不需要改业务代码。我在项目里先跑了TCP联调然后到现场换成串口只改了创建Master的连接部分其余读取逻辑原封不动。2.3 源码目录怎么看找一个类顺着依赖把链路走通刚拿到源码时别急着从头读到尾我是这样顺着调用链翻的。从自己最常用的IModbusMaster.ReadHoldingRegisters入手找到接口定义再跳到ModbusSerialMaster的实现里面能看到它构造了一个ReadHoldingRegistersRequest然后调用Transport去发送和接收。这样一路追下去很快就会发现所有功能码请求消息都集中在Messages目录下校验相关的工具类在Utility目录。自己翻源码还有个好处能精确掌握一条请求的超时处理逻辑。主站发送请求后Transport会等待从站响应超时时间由串口或Socket的ReadTimeout决定。这个参数在很多隐性问题里是关键的调试入口后面避坑章我会专门讲。3. 主站实战把串口设备寄存器数据读回来3.1 从NuGet拿包还是直接用源码引用方式与编译注意NModbus4的使用方式有两种一种是通过IDE的NuGet包管理器搜索NModbus4直接引用另一种是直接把源码工程加进解决方案。我的建议是如果只是做应用层开发用NuGet包就够了如果要做深度定制比如改写传输层或者抓取完整收发帧就把源码工程引入调试时能直接看到库内部的报文处理过程。用源码工程引用时有一个细节需要注意NModbus4源码里的目标框架可能和你的主工程不一致。我曾经遇到编译时提示某个API不存在后来发现是目标框架版本不匹配把库工程的框架切到和主工程一致之后就正常了。这类问题不算难但第一次遇到确实容易懵。3.2 串口主站连接参数、超时与第一次握手串口通信的第一步是配置SerialPort参数代码里面这样写using System.IO.Ports; SerialPort serialPort new SerialPort(COM3, 9600, Parity.None, 8, StopBits.One); serialPort.ReadTimeout 1000; serialPort.WriteTimeout 1000; serialPort.Open(); serialPort.DiscardInBuffer(); serialPort.DiscardOutBuffer();参数说明9600是波特率要和从站保持一致Parity.None是多数Modbus RTU默认的校验方式部分老设备会用Even校验需要看设备手册8个数据位1个停止位这是最通用的配置。ReadTimeout设成1000毫秒意思是等待从站响应的最长时间。创建主站对象只需要一行ModbusFactory factory new ModbusFactory(); IModbusMaster master factory.CreateMaster(serialPort);这里有个关键点CreateMaster只是把串口对象包装起来真正发数据发生在第一次读写调用时。所以串口打开后不要立刻读写建议先等200毫秒再开始通信让线路稳定。3.3 读寄存器一行代码背后发生了什么读保持寄存器是最常用的操作代码非常简单byte slaveId 1; ushort startAddress 0; ushort numberOfPoints 10; ushort[] registers master.ReadHoldingRegisters(slaveId, startAddress, numberOfPoints); for (int i 0; i registers.Length; i) { Console.WriteLine($寄存器 {startAddress i} {registers[i]}); }逻辑说明slaveId是从站地址现场总线上每个设备一个编号startAddress是起始寄存器地址协议地址从0开始numberOfPoints是要连续读取的寄存器数量。返回值ushort[]就是寄存器原始值。这里需要注意一点ReadHoldingRegisters对应功能码0x03读的是可读可写的保持寄存器区很多仪表把配置参数放在这个区域。如果设备手册里写的是“40001开始”这里的startAddress要填0后面坑章细说。读输入寄存器则换成ReadInputRegisters功能码0x04对应设备的只读测量值区比如电流、电压、温度。3.4 写线圈和写寄存器功能码与参数边界写操作和读操作一样都是调用主站方法。写单个寄存器master.WriteSingleRegister(1, 0, 1000);意思是将从站地址1的寄存器0写为1000。对应功能码0x06适用于单点修改比如修改某个设定值。批量写多个寄存器ushort[] values new ushort[] { 100, 200, 300 }; master.WriteMultipleRegisters(1, 0, values);对应功能码0x10一次最多能写多少寄存器受协议限制因为报文里要携带数据长度字节超过125个寄存器就会超出单帧容量。写线圈类似WriteSingleCoil对应功能码0x05很常用比如控制继电器通断bool isOn true; master.WriteSingleCoil(1, 0, isOn);逻辑说明布尔值true表示线圈通电ONfalse表示断开OFF。多数设备用线圈代表DO输出点。3.5 轮询骨架多设备多寄存器怎么组织真实项目里不会只是读一次而是定时轮询所有设备。我常用下面这个骨架// 设备地址和读取区域配置 var deviceConfigs new List(byte SlaveId, ushort Start, ushort Count) { (1, 0, 10), (2, 0, 20), (3, 100, 5) }; while (true) { foreach (var cfg in deviceConfigs) { try { ushort[] data master.ReadHoldingRegisters(cfg.SlaveId, cfg.Start, cfg.Count); // 处理数据保存入库、更新界面、判断告警 } catch (Exception ex) { Console.WriteLine($设备 {cfg.SlaveId} 读取失败: {ex.Message}); } } Thread.Sleep(1000); }轮询间隔要选好我从现场经验得出的结论是建议不小于500毫秒否则多个从站共用一个串口时容易因为从站响应时间不稳定导致总线上冲突。每个从站的异常处理一定要捕获某个设备掉线不能拖垮整个采集线程。4. 从站实现继承ModbusSlave把设备数据映射成协议寄存器4.1 从站抽象类的抽象方法都在要求什么NModbus4的从站不是配好就能用的需要自己写业务逻辑。ModbusSlave是抽象类继承它之后必须实现八个核心方法读线圈、读输入位、读保持寄存器、读输入寄存器、写单线圈、写单寄存器、写多线圈、写多寄存器。初次实现时不要想得太复杂。这些方法的本质就是“把你的业务数据源暴露成Modbus寄存器视角”。例如设备内部有个温度变量你想让主站通过保持寄存器地址0读到它那就在ReadHoldingRegisters里把温度值塞进返回数组对应位置。4.2 内存映射表寄存器编号、线位编号与真实数据源之间的关系为了让从站代码不至于写成一大坨if-else我建议先设计一张内存映射表比如寄存器地址变量类型读写属性0设备运行状态ushort只读1设定温度ushort可写2-9保留ushort不可用映射表确定之后从站代码就是往数组里读写数据再无其他逻辑。说白了Modbus从站通信没有魔法核心是维护好这张表。4.3 起一个从站实例并和主站联调从站实例通过ModbusFactory创建创建之前要先声明一个继承ModbusSlave的类。我这里写一个最小实现public class DeviceSlave : ModbusSlave { private ushort[] holdingRegisters new ushort[10]; private bool[] coils new bool[8]; public DeviceSlave(ModbusTransport transport) : base(transport) { } public override ushort[] ReadHoldingRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints) { ushort[] result new ushort[numberOfPoints]; Array.Copy(holdingRegisters, startAddress, result, 0, numberOfPoints); return result; } public override void WriteMultipleRegisters(byte slaveAddress, ushort startAddress, ushort[] registers) { for (int i 0; i registers.Length; i) { holdingRegisters[startAddress i] registers[i]; } } public override bool[] ReadCoils(byte slaveAddress, ushort startAddress, ushort numberOfPoints) { bool[] result new bool[numberOfPoints]; Array.Copy(coils, startAddress, result, 0, numberOfPoints); return result; } public override void WriteSingleCoil(byte slaveAddress, ushort coilAddress, bool value) { coils[coilAddress] value; } // 其余公共方法根据业务补全结构类似 }代码逻辑说明继承ModbusSlave后核心是内部维护的holdingRegisters和coils数组。主站发来读请求时直接把数组切片返回主站发来写请求时把数据写入数组。业务线程可以随时修改holdingRegisters数组内容主站下一次读取就能看到最新值。启动从站的代码也很简单SerialPort serverPort new SerialPort(COM4, 9600, Parity.None, 8, StopBits.One); serverPort.Open(); ModbusFactory factory new ModbusFactory(); DeviceSlave slave factory.CreateSlave(new ModbusSerialTransport(serverPort), 1); slave.ListenAsync(CancellationToken.None);注意CreateSlave需要一个传输层对象和从站地址。ListenAsync启动后台监听循环持续解析串口上收到的请求帧。用TCP做从站时Transport换成ModbusIpTransport实际上是监听一个端口通信链路由Socket管理业务代码完全复用。5. 避坑指南五个必须提前知道的坑这一章的价值是我用好几个项目的血泪经验换来的NModbus4本身逻辑没有大坑坑几乎都集中在现场环境、设备厂家习惯和协议边界条件上。5.1 第一次读写必超时现象程序启动后第一次调用ReadHoldingRegisters抛出TimeoutException重试一次就成功后续完全正常。原因串口打开后线路电平还没完全稳定或者串口缓冲区里有上一次通信遗留的脏数据导致第一次请求发出后从站还没来得及响应主站已经判定超时。Windows下SerialPort底层缓冲在Open后需要一点时间进入稳定状态。解决串口Open之后不要立刻发请求先等200到500毫秒再调用DiscardInBuffer清空接收缓冲区。我现在的习惯是封装一个OpenSerialPort方法完成等待和清空动作后再交给ModbusFactory。5.2 读回的大小端不对现象设备手册上写寄存器值0x1234上位机读出来显示0x3412或者反过来。原因Modbus协议本身是大端传输高字节在前。但某些设备厂家用单片机小端模式存储寄存器发送时没有做字节交换导致上位机读到的ushort和手册对不上。另外NModbus4读回来的ushort值在其内部已按网络字节序转换为本地ushort这一步没有问题问题全在设备端。解决拿到设备先做一次“已知值校准”。从设备手册找一个固定寄存器值读出来对比。不一致就做字节交换ushort raw master.ReadHoldingRegisters(1, 0, 1)[0]; ushort fixedValue (ushort)((raw 8) | (raw 8));注意这个转换只对单寄存器有效处理32位浮点数时要考虑双寄存器的高低字顺序更复杂一点建议先理清设备存储布局再写转换层。5.3 地址偏移40001不等于1现象设备手册写“保持寄存器起始地址为40001”按手册填40001结果返回异常或者读到完全不对的数据。原因Modbus协议的数据地址和PLC传统寻址编号是两套体系。协议地址是16位无符号数从0开始PLC习惯用40001表示第一个保持寄存器。NModbus4遵循的是协议地址不是你PLC里面的编号。解决建立转换层把用户输入的PLC地址转换成协议地址。规则很简单保持寄存器区协议地址 PLC地址 - 40001输入寄存器区协议地址 PLC地址 - 30001线圈区协议地址 PLC地址 - 00001。我在项目里加了一个静态方法所有地址都从这里过一遍后面再也没出过偏移类问题。5.4 超过协议限制的批量读写现象一次读500个寄存器直接抛异常或者从站一直不响应。原因Modbus RTU单帧最多携带250字节数据读保持寄存器时每个寄存器占2字节所以最多一次读125个寄存器。线圈一次最多读2000个250字节按位排列多数情况下是从站端不支持这么长的帧。主站库本身不会帮你拆包。解决自己分区读取再把数据拼接起来。比如要读400个寄存器分成4批每批100个每次结果按起始地址写入总数组。我实测这个方案最稳既没超帧长限制也不会因为单次读取时间过长导致从站看门狗超时。5.5 RTU模式下粘包与总线冲突现象整个系统偶尔出现某次读到的数据完全错乱或者CRC校验错误过一会儿又自动恢复。这条串口线上挂了多个从站轮询越快越容易出现。原因RTU协议靠空闲间隔区分帧边界从站响应结束到主站发下一帧之间要有足够的静默时间。Windows下SerialPort缓冲不是实时的多次读写堆在缓冲区里如果主站立刻发下一帧从站和主站都可能把离散的字节误当成同一帧。解决轮询循环里每次读写结束之后加一个短延时我常设20到50毫秒。同时为每个从站的超时时间单独设置不要把全局超时设得过大否则一个设备掉线整条总线都可能被拖慢。6. 进阶技巧字节级抓包、回环测试与自定义功能码6.1 让Transport把收发帧打出来调试协议问题最直接的方法是看底层的原始字节流。我一般会自定义一个Transport类在读写方法里把收发数据打印出来public class LoggingTransport : ModbusSerialTransport { public LoggingTransport(SerialPort serialPort) : base(serialPort) { } public override void Write(byte[] frame) { Debug.WriteLine($TX: {BitConverter.ToString(frame)}); base.Write(frame); } public override byte[] Read() { byte[] response base.Read(); Debug.WriteLine($RX: {BitConverter.ToString(response)}); return response; } }注意重写Write时打印的是发送的原始请求帧Read返回的是从站响应帧。有了这些字节结合Modbus协议文档几乎可以手工解出每一个字段的含义再也不用对着现象瞎猜。6.2 回环测试主从站在本机跑通在没有真实设备的开发环境里可以用两个虚拟串口或者本机TCP端口把主站和从站直接连起来。TCP模式下最简单从站监听本机某个端口主站连到同一个IP和端口两边立刻就能互相通信。我常用的测试方式是单测里写一个从站服务主站连续读写验证数据一致性。这种做法能提前暴露大部分业务逻辑错误等到现场调试时剩下的问题基本只有参数配置和设备差异。6.3 自定义功能码绕开库的封装直接拼帧如果设备用到了Modbus标准外的自定义功能码NModbus4没有现成方法怎么办常见做法是手动构造请求字节数组通过Transport发送并读取响应。例如主站向从站地址1发送一段自定义查询核心代码如下byte[] customRequest new byte[] { 0x01, // 从站地址 0x41, // 自定义功能码 0x00, 0x0A, // 起始地址 0x00, 0x01 // 长度 };发送后自己解析响应帧。这样做的前提是清楚帧格式和CRC校验方式不过一旦掌握等于突破了库本身的边界限制任何非标设备都能从容应对。那次在现场排查粘包问题我花了整整一个下午最后靠LoggingTransport打出来的字节流才确认是轮询间隔太短。从那以后我每次接手Modbus项目都强制走一遍“先抓原始帧、再改业务代码”的流程思路清晰很多。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

XC7A100TFGG484参考设计:从最小系统到稳定启动的FPGA工程实践

XC7A100TFGG484参考设计:从最小系统到稳定启动的FPGA工程实践

简介:面向Xilinx Artix-7系列xc7a100t芯片(FFG484封装)的硬件设计,这一参考设计包完整收录了基于Altium Designer的PCB工程与原理图文件,适合FPGA板卡开发、高速接口布线及电源系统设计人员参考借鉴。压缩包共含58个文…

2026/10/19 8:08:51 阅读更多 →
从关键词到提问:用AI搜索重构信息获取流程的方法与避坑指南

从关键词到提问:用AI搜索重构信息获取流程的方法与避坑指南

最近我把自己的信息获取流程整个重排了一遍。起因是一件小事:我习惯性地打开浏览器搜索框输入一个具体问题,却发现自己已经很难接受那些排了十几条广告和SEO软文的链接页了。我想要的,是一个直接、有依据、还能顺着我的追问继续深入的答案。于…

2026/10/19 8:08:51 阅读更多 →
微信接入OpenClaw智能体:公众号回调验签与会话路由实战

微信接入OpenClaw智能体:公众号回调验签与会话路由实战

要是你手上刚好跑着一个自托管的 OpenClaw 智能体服务,想让它在微信里随叫随到,这篇就是给你准备的。前前后后折腾了三个晚上,从拿到公众号测试号、配置回调 URL、处理验签和 XML 消息,到把不同用户的会话对上号、路由给不同智能体…

2026/10/19 8:08:51 阅读更多 →

最新新闻

Postman接口串联实战:变量作用域、提取脚本与执行顺序控制

Postman接口串联实战:变量作用域、提取脚本与执行顺序控制

1. 接口串联的真实痛点与整体设计思路做过接口测试的人几乎都遇到过这种场景:你手里有两个接口,A接口是业务主流程,B接口是前置依赖。A接口的请求体里有一个必填字段,而这个字段的值必须从B接口的响应里拿。比如下单接口需要一个动…

2026/10/19 20:08:44 阅读更多 →
GitHub热榜观察:AI推理、开发者工具与自托管趋势解读

GitHub热榜观察:AI推理、开发者工具与自托管趋势解读

每天半小时刷一遍 GitHub 热榜,已经成了我雷打不动的习惯。2026年10月10日的这份日榜,我边翻边记了不少笔记,放在草稿箱里两天了,今天终于整理成文。如果你也喜欢半夜逛开源社区、或者最近正愁找不到合适的项目做技术选型和灵感参…

2026/10/19 20:08:44 阅读更多 →
Android通用列表Adapter封装:ListView与RecyclerView复用实践

Android通用列表Adapter封装:ListView与RecyclerView复用实践

自打开始做Android客户端,列表控件这东西就绕不开。早年写代码最常用的就是ListView,后来Google推出了RecyclerView,大家慢慢都切了过去。但不管用哪一个,有个问题始终存在:项目里的列表页面越来越多,每个页…

2026/10/19 20:08:44 阅读更多 →
GitHub热榜观察:AI应用落地与开发者工具新风向

GitHub热榜观察:AI应用落地与开发者工具新风向

每天上午十点左右,我都会习惯性打开 GitHub 的热榜页面,先扫一眼当天的趋势榜单。这个习惯我保持了快十年,早年是为了找好用的轮子,后来慢慢变成一种技术风向的感知方式——热榜上的项目,往往代表着一批开发者正在集中…

2026/10/19 20:08:44 阅读更多 →
SuperTrend+ADX双指标趋势跟随策略原理与Python实现详解

SuperTrend+ADX双指标趋势跟随策略原理与Python实现详解

做趋势交易的人一定绕不开那两个经典问题:趋势到底走没走出来?现在进场是顺势还是接飞刀?我做过一段时间CTA实盘,也把市面上的趋势指标挨个试了个遍,最后长期留在策略里的组合,就是SuperTrend配ADX。这篇文…

2026/10/19 20:08:44 阅读更多 →
YashanDB部署前检查清单:从环境准备到参数调优的完整指南

YashanDB部署前检查清单:从环境准备到参数调优的完整指南

拿到 YashanDB 安装包之后,别急着初始化。我见过太多次这种场景:环境参数没调好,数据库装上去了,跑两周业务量一大就出各种问题,最后排查一圈发现根子都在部署前那半天准备工作上。这篇就来聊聊 YashanDB 部署前必须确…

2026/10/19 20:07:43 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →