Java解析电力规约:从101/104报文到ASDU/APCI的实战指南
简介基于Java语言开发的电网101规约DLT634.5101-2002与104规约DLT634.5104-2009解析和组装工具主要面向电力系统专业学生、Java开发人员及相关行业工程师解决IEC 60870-5-101/104报文的编解码、链路解析与打包组帧问题。压缩包共64个文件体积仅147KB以54个Java源码为主体辅以XML工程配置、Markdown说明文档、Excel规约解析细则和TXT运行注意事项从工程搭建到规约细节均有覆盖。内部按Maven标准结构组织划分iec104-core核心模块与测试目录方便定位协议解析、报文组装等关键代码随包提供的规约解析细则可帮助理解不同报文类型的字段结构与生成流程。项目难度适中易上手适合毕业设计、课程设计或二次开发也可作为变电站监控、配电终端等场景下的协议参考目前已有81人学习下载。1. 电网规约解析工具不是玩具为什么电力自动化要单独做一个Java包电力调度数据网里101规约和104规约DL/T 634.5104-2009是变电站、站端设备和主站之间对话的“母语”。很多Java工程师刚接触这个领域时手里只有几百页国标文档和一个抓包文件不知道怎么把十六进制字节变成遥测值也不知道怎么把命令组帧发出去。这个工具解决的就是这件事用Java解析和组装规约报文供电网调度、配电自动化、新能源接入使用。它适合正在做电力项目的Java工程师、测试人员和想转电力方向的开发者。对新手代码比文档更快让你明白ASDU和APCI长什么样对熟手组件可以直接嵌进通道层做二次开发。网上聊Java面试题的多但把DL/T 634.5104-2009写成可复现工程的不多我尽量讲透。2. 先看懂报文的骨架101与104的帧格式、ASDU字段和APCI序号2.1 101规约走串口104规约走网络两种帧格式的分界线101规约DL/T 634.5101设计给串行链路用比如RS-232/RS-485物理层之上是FT1.2帧格式。FT1.2有两种帧。固定帧长用于链路确认、请求链路状态这类链路层服务帧结构是启动字符10H、控制域、链路地址、校验和、结束字符16H一共五个字节不携带应用数据。可变帧长用于承载ASDU结构是启动字符68H、帧长L重复两次、控制域、链路地址、链路用户数据、校验和、结束字符16H。这里的帧长L指从控制域开始到链路用户数据末尾的字节数不包含启动字符、L本身、校验和和结束字符。校验和的计算方式是控制域到链路用户数据逐字节累加取模256。这个“按字节累加”的规则经常被当成CRC是最容易翻车的地方之一。101的链路层控制域还有一层作用主站侧每发送一帧请求会把FCB位翻转一次站端没回应时主站重发上一帧且FCB保持不变。站端根据FCB是否变化判断是新的请求还是重发的旧帧这就是101链路层的重发机制。对应地站端上报的响应帧里ACD位表示是否有新的事件数据要上报DFC位告诉主站自己的接收缓冲区是否快满了。解析101报文时控制域里的这几个位不能忽略否则重发和流量控制逻辑会乱。104规约DL/T 634.5104-2009等同IEC 60870-5-104:2006为TCP/IP网络设计把链路层的可靠性交给TCP因此没有FT1.2帧和链路层重发机制。104线路上跑的是APDU应用规约数据单元结构为启动字符68H、APDU长度、APCI控制域4字节、ASDU。APDU长度指从APCI第一字节到ASDU最后一字节的总长度最大253字节。两种规约的ASDU结构高度一致区别主要在传输方式。104没有链路地址站端身份靠ASDU里的公共地址体现101的链路地址在帧的地址域里公共地址也出现在ASDU里。选型上站内装置用101串口很常见远距离和主站侧基本都走104。2.2 ASDU才是真正干活的数据类型标识、公共地址、信息对象地址ASDU是应用层数据的统一容器结构固定类型标识1字节、可变结构限定词1字节、传送原因2字节、公共地址2字节、信息对象地址3字节、信息元素、时标可选。类型标识决定数据是什么比如01H是单点遥信、0DH是短浮点遥测、2DH是单点遥控这些都在DL/T 634.5104里定义好。我常用的几个类型标识列在下面类型标识十六进制含义常见方向M_SP_NA_10x01单点遥信站端→主站M_DP_NA_10x03双点遥信站端→主站M_ME_NC_10x0D短浮点遥测站端→主站C_SC_NA_10x2D单点遥控主站→站端C_DC_NA_10x2E双点遥控主站→站端C_SE_NC_10x32短浮点设定值主站→站端可变结构限定词是很多新手搞错的地方。它的低7位表示信息对象个数最高位是SQ位。SQ0表示信息对象是“非顺序”的每个对象都要单独带三字节信息对象地址SQ1表示“顺序”的只有一个起始地址后续对象的地址连续递增。解析带时标顺序表报文时如果忽略SQ位地址步进和字节偏移全都会错。信息对象地址固定三字节按低字节在前存放。不少工程师习惯用ByteBuffer默认的大端序读结果IOA变成巨大数字或者直接是0。我一般在工具里封装readUInt24LE这类方法专门处理这种小端字段。传送原因占两字节bit0到bit5是原因码bit6是S/N标志0来自站端1来自主站bit7保留为0。常见原因码有0x06激活、0x07激活确认、0x08停止激活、0x0A停止激活确认等。命令帧和确认帧的区别就在这里组帧时写错原因码主站会当成无效响应丢弃。2.3 104规约的APCI控制域I帧、S帧、U帧与序号机制104规约的APCI控制域是四个字节它承载帧类型和序号信息。第一字节的bit0决定类型bit00是I帧带ASDU的应用数据帧bit01且bit10是S帧监视帧只做确认不带数据bit01且bit11是U帧控制帧用于启动、停止、测试。I帧的发送序号N(S)存放在第一字节的bit1到bit7接收序号N(R)存放在第三字节的bit1到bit7。因为它们都左移了一位所以取序号时要右移一次也就是“c1 1”。序号范围是0到127发完一帧加一达到128就回到0取模128循环。S帧的第一字节固定是01H只有N(R)。U帧第一字节通常是03H启动命令、0BH启动确认等表示命令或确认。U帧用于链路控制。主站侧上电后先发启动命令STARTDT act控制域第一字节0x07站端确认后回STARTDT con0x0B之后才能传输I帧。停止传输则用STOPDT act0x13和STOPDT con0x23。我见过有人把U帧和I帧混用在未启动数据传输前就发I帧设备直接丢弃。所以工具里至少要在通道状态机上区分ACT和CON。序号机制是104规约最考验代码功底的地方。TCP本身可靠但应用层还是要求主站每发一帧I帧站端要回S帧或凭I帧捎带确认如果发现N(S)不连续说明有丢帧要等待重发。我见过不少工具把序号写死为0结果接上真实设备后主站收到连续两帧就报序号错误直接断开。所以解析工具里序号解析和组装时的自增逻辑一定要按标准保留。3. Java实现的架构选型用Netty还是裸Socket类怎么划分3.1 传输层选型NIO框架与纯Java IO的取舍规约工具的传输层选型要分场景。如果你要接入几十上百个站端的长连接常见做法是用Netty用LengthFieldBasedFrameDecoder做拆包再挂一个自定义的ChannelHandler把APDU字节交给解析器。Netty的好处是线程模型、背压、断线重连都成熟不用自己造轮子。如果只是离线分析抓包、做一个调试小工具纯Java的ServerSocket和InputStream就够。一个单线程while循环按长度字段读满字节即可代码简单出问题也好排查。我的习惯是解析和组装的核心逻辑不依赖任何框架做成纯Java类Netty只是外层传输壳。这样即使项目里没有Netty也能在单元测试里直接new一个Parser传byte[]测。顺便说一句网上经常搜到spring boot mybatis这类Java开源项目但电网规约这块几乎没有流行的现成库Maven上的一些104实现要么年代久远要么只覆盖部分类型标识。自己基于标准实现一套核心解析反而是电力项目里最可控的做法。串口场景下可以选择jSerialComm或Netty的串口模块但串口通道上的半包处理比TCP更娇气建议把101的帧切分逻辑单独隔离。3.2 核心类设计Parser分离与ByteBuffer缓冲区管理我习惯把工具拆成四部分。FrameParser负责从字节流里切出完整报文处理半包ASDUParser负责把ASDU拆成类型标识、传送原因、公共地址、信息对象地址和信息元素FrameAssembler负责把业务对象组帧InfoObjectFactory是路由工厂按类型标识找到对应的信息元素解析器。缓冲区管理是Java规约工具里容易忽略的地方。规约报文大量使用小端序一个float遥测用4字节小端表示IOA是三字节小端。为了不把ByteBuffer的状态搞乱我封装了一个BufferUtil内部显式设置ByteOrder.LITTLE_ENDIAN。有人喜欢字节数组直接位移拼数也可以但可读性差。我通常优先用ByteBuffer只有三字节这种非对齐场景才手工处理。public class BufferUtil { public static int readUInt8(ByteBuffer buf) { return buf.get() 0xFF; } public static int readUInt16LE(ByteBuffer buf) { return (buf.get() 0xFF) | ((buf.get() 0xFF) 8); } public static long readUInt24LE(ByteBuffer buf) { return (buf.get() 0xFF) | ((buf.get() 0xFF) 8) | ((buf.get() 0xFF) 16); } }readUInt8返回0到255处理Java byte的符号位readUInt16LE读小端16位readUInt24LE用于信息对象地址的三字节小端读取。这三个方法在解析报文时会高频使用命名里带LE能提醒自己和同事别误用大端。实际调试中把IOA读成0的大量案例都是字节序错误引起。3.3 策略模式处理类型标识switch-case之外的路由方案类型标识有几十种信息元素的长度和结构各不相同。很多人一开始用switch-case按类型标识写分支结果每个分支里还得嵌套SQ判断、带时标判断一个方法膨胀到两百行。我改用工厂注册表把每种类型标识对应一个InfoObjectParser实现注册到Map里。public interface InfoObjectParser { int typeId(); ListInfoObject parse(ByteBuffer buf, int numObj, boolean sq); }实现类通过typeId返回自己处理的类型标识启动时注册进Map。路由时用map.get(typeId)取实现拿不到就返回一个UnknownParser把原始字节记录下来尽量避免整帧解析失败。这样加新类型时不动已有代码新增一个类注册即可符合开闭原则。这种设计的好处不只可维护。电力项目里厂站可能只实现局部类型标识不一定需要全协议支持用注册表可以让不同项目裁剪不同的解析集合比一大串if-else灵活得多。我在做接入层时还会给每个Parser加一个“是否带时标”的开关因为同一种类型标识在不同厂家的规约里时标可有可无不加开关就只能猜着解析。4. 手写解析与组装的可用代码104报文最小实现4.1 解析APDU半包处理与ASDU拆解这一节先给出解析APDU的最小代码。传输层把完整帧交给parse方法这里只负责校验和拆字段。public class Iec104Parser { private static final int START 0x68; public Apdu parse(byte[] frame) { if (frame.length 8) { throw new IllegalArgumentException(小于最小APDU长度); } if ((frame[0] 0xFF) ! START) { throw new IllegalArgumentException(启动字符必须为0x68); } int len frame[1] 0xFF; if (frame.length 2 len) { throw new IllegalArgumentException(数据长度不足); } ByteBuffer buf ByteBuffer.wrap(frame, 2, len) .order(ByteOrder.LITTLE_ENDIAN); Apdu apdu new Apdu(); apdu.control readControl(buf); if (buf.remaining() 0) { apdu.asdu parseAsdu(buf); } return apdu; } private Control readControl(ByteBuffer buf) { int b0 buf.get() 0xFF; buf.get(); int b2 buf.get() 0xFF; buf.get(); Control c new Control(); if ((b0 0x01) 0) { c.type Control.I_FRAME; c.sendSeq b0 1; c.recvSeq b2 1; } else if ((b0 0x02) 0) { c.type Control.S_FRAME; c.recvSeq b2 1; } else { c.type Control.U_FRAME; c.uCmd b0; } return c; } }启动字符0x68和长度字段是104报文的固定头。长度len表示APCI与ASDU的总长所以ByteBuffer.wrap偏移量是2长度是len。这里不做粘包处理因为上层如果已经按帧切好数据这里只管校验完整性。解析I帧时N(S)和N(R)都右移一位才是真实序号因为最低位被帧类型标识占了。S帧和U帧没有数据不用解析ASDU。private Asdu parseAsdu(ByteBuffer buf) { Asdu asdu new Asdu(); asdu.typeId buf.get() 0xFF; int vsq buf.get() 0xFF; asdu.sq (vsq 0x80) ! 0; asdu.infoCount vsq 0x7F; asdu.cause readUInt16LE(buf); asdu.commonAddr readUInt16LE(buf); asdu.infos new ArrayList(); if (asdu.sq) { long startAddr readUInt24LE(buf); for (int i 0; i asdu.infoCount; i) { asdu.infos.add(readInfoElement(buf, asdu.typeId, startAddr i)); } } else { for (int i 0; i asdu.infoCount; i) { long ioa readUInt24LE(buf); asdu.infos.add(readInfoElement(buf, asdu.typeId, ioa)); } } return asdu; }这里的关键是SQ分支。SQ1时只读一次起始IOA后续对象地址按步进1递增不再读地址。SQ0时每个对象前都要读三字节IOA。信息元素解析函数按类型标识分流符合第3章的注册表设计。4.2 组装遥测上送报文短浮点测量值的组装流程组装是从业务对象到字节流的反向过程。以站端上送浮点遥测类型标识0x0DM_ME_NC_1为例一条典型的带时标上送帧信息元素是4字节短浮点、1字节品质描述和7字节CP56Time2a时标。public class Iec104Assembler { private int sendSeq 0; private int recvSeq 0; public byte[] buildFloatTelemetry(int commonAddr, long ioa, float value) { int asduLen 1 1 2 2 3 4 1 7; int len 4 asduLen; ByteBuffer buf ByteBuffer.allocate(2 len) .order(ByteOrder.LITTLE_ENDIAN); buf.put((byte) 0x68); buf.put((byte) len); buf.put((byte) ((sendSeq 0x7F) 1)); buf.put((byte) 0x00); buf.put((byte) ((recvSeq 0x7F) 1)); buf.put((byte) 0x00); buf.put((byte) 0x0D); buf.put((byte) 0x01); buf.putShort((short) 0x03); buf.putShort((short) commonAddr); putUInt24(buf, ioa); buf.putFloat(value); buf.put((byte) 0x00); encodeTime(buf, System.currentTimeMillis()); sendSeq (sendSeq 1) 0x7F; return buf.array(); } }样式说明commonAddr是站端公共地址通常取值1到255ioa是信息对象地址三字节小端写入value是实际浮点值。buf.putFloat在ByteOrder.LITTLE_ENDIAN下会把IEEE 754位模式按小端存好。sendSeq每次发I帧加一并取模128recvSeq这里保持当前确认值真正工程里由通道管理类更新。private void encodeTime(ByteBuffer buf, long ts) { Calendar cal Calendar.getInstance(); cal.setTimeInMillis(ts); int ms cal.get(Calendar.SECOND) * 1000 cal.get(Calendar.MILLISECOND); buf.put((byte) (ms 0xFF)); buf.put((byte) ((ms 8) 0xFF)); buf.put((byte) cal.get(Calendar.MINUTE)); buf.put((byte) cal.get(Calendar.HOUR_OF_DAY)); int dow (cal.get(Calendar.DAY_OF_WEEK) 5) % 7; buf.put((byte) (cal.get(Calendar.DAY_OF_MONTH) | (dow 5))); buf.put((byte) (cal.get(Calendar.MONTH) 1)); buf.put((byte) (cal.get(Calendar.YEAR) - 2000)); }CP56Time2a是7字节前两字节为毫秒值之后是分、时第5字节低5位是日、高3位是星期第6字节是月第7字节是年减2000。很多设备端只看毫秒和日但主站侧会把年解析出来做历史数据归档所以年份不能省。4.3 把101规约的FT1.2帧做串口收发校验和与重发机制101的串口收发和104差别很大。104没有链路地址101必须把控制域、链路地址、ASDU都放进可变帧长帧里并且计算累加校验和追加结束字符16H。下面的方法组装一帧101可变帧长帧public byte[] build101Frame(int control, int linkAddr, byte[] asdu) { int dataLen 1 1 asdu.length; ByteBuffer buf ByteBuffer.allocate(2 dataLen 2) .order(ByteOrder.BIG_ENDIAN); buf.put((byte) 0x68); buf.put((byte) dataLen); buf.put((byte) dataLen); buf.put((byte) control); buf.put((byte) linkAddr); buf.put(asdu); int cs 0; cs control 0xFF; cs linkAddr 0xFF; for (byte b : asdu) { cs b 0xFF; } buf.put((byte) cs); buf.put((byte) 0x16); return buf.array(); }校验和控制域链路地址ASDU逐字节累加取低8位。control参数由上层按链路功能码填充具体值要对照DL/T 634.5101里的功能码表不要自己猜。FCB位决定这帧是新请求还是重发FCB变化的重发逻辑要在发送线程里维护。接收侧校验时先判断启动字符0x68再按第3字节的长度读取data部分最后做同样的累加和对比。这样做的好处是串口的一帧数据可能分多次到达也可以一次给全校验放在凑满完整帧之后统一做避免读到一半就把错误字节当成ASDU内容。5. 避坑手册解析电力规约最容易翻车的5个细节下面五条是我在实际联调里真实踩过的坑。每条按现象、原因、解决展开后面再接类似需求时能少走弯路。5.1 可变结构限定词SQ位被忽略导致后续对象全部错位现象解析多对象遥信类型0x01时前两个对象正常第三个开始地址和值完全错乱甚至抛出缓冲区越界。原因VSQ的bit7为1时表示顺序模式信息对象地址只给起始地址后续地址按1递增但解析器依然为每个对象读取三字节地址等于多读了几个字节后续字段全部错位。解决解析ASDU前先判SQSQ1时只读一次IOA然后每个对象只读信息元素部分。写单元测试时专门准备一份VSQ为0x81的报文把顺序模式和非顺序模式各测一遍防止以后改动回归。5.2 用CRC算法算101校验和越算越不对现象组帧发给串口调试助手后对端一直回NACK日志里报校验错误。原因101规约的FT1.2校验不是CRC16而是简单累加和——从控制域到链路用户数据的每个字节相加取低8位。很多人沿用Modbus的CRC习惯两者计算方式完全不同算出来的字节自然对不上。解决把校验逻辑改成逐字节累加同时注意校验和与结束字符16H都不参与累加。另外重发机制靠FCB翻转而不是把整帧原样再发一遍这两件事别混在一起。5.3 104发送序号没有取模循环被对端判定序号错误断链现象连接建立后前几帧正常发到第128帧时对端直接断开TCP日志显示接收序号异常。原因规范里序号范围只到127超出必须回绕到0。很多实现用一个int一直加没有做“0x7F”导致序号超过127对端认为非法直接断链。解决发送和接收计数每次操作后都取模128。我一般在组装器里把序号运算集中写成“sendSeq (sendSeq 1) 0x7F”并额外加注释。还要注意U帧和S帧不消耗发送序号只有I帧才加一别把确认帧也算进去。5.4 小端字节序被Java默认大端覆盖浮点读数变成天文数字现象解析短浮点遥测数据明明是24.5输出却是3.7E-9之类的值。原因104/101的ASDU里浮点、IOA、公共地址、传送原因都是低位在前。ByteBuffer默认是BIG_ENDIAN直接getFloat会读出错误的位模式。解决创建ByteBuffer后显式调用order(ByteOrder.LITTLE_ENDIAN)。如果是byte[]手动组装先拼成int再Float.intBitsToFloat。这个坑在联调中最难发现因为报文看起来“格式正确”所以我把字节序检查写进了代码规范和测试断言。5.5 半包与粘包把两个相邻APDU当成一个ASDU解析现象Netty环境里偶发整帧被丢弃或者解析出的ASDU长度大于本帧应长出现“死包”。原因104基于TCP流没有消息边界。如果接收侧按一次read的字节数直接当成一帧去解析就容易发生半包——长度字段读到了但数据还没到齐或者粘包——两个APDU挤进一个数组。解决在传输层按“68长度字段”来切帧。我常用的做法是循环先读2字节确认0x68后读第2字节得到len再用InputStream的readFully读满len字节凑够后才交给Parser。粘包时剩余字节保留在缓冲区等下一轮消费。这个逻辑放在FrameParser里不放到ASDU解析层。6. 验证与进阶没有真实设备时怎么证明工具能用6.1 用报文回放做回归测试没有真实站端设备时最有效的验证方式是从抓包里捞典型报文做回放。用Wireshark过滤104流量挑出周期遥测、变位遥信、遥控命令各一条导出hex字符串整理成JUnit参数化测试。ParameterizedTest CsvSource({ 68 0B 02 00 06 00 0D 01 03 00 01 00 00 00 00 00 00, 68 0A 02 00 04 00 01 01 03 00 01 00 20 00 00 00 }) void parseHexFrame(String hex) { byte[] frame hexToBytes(hex); Apdu apdu parser.parse(frame); assertNotNull(apdu.asdu); }这类断言和接口自动化测试框架思路一样输入固定、输出可校验。给每个类型标识准备一条正向一条反向用例数据类型长度变化时能第一时间发现解析偏移错误。报文不要只留一条时标、SQ1顺序模式、多对象非顺序模式各留一份才能覆盖大多数回归风险。6.2 性能与扩展ByteBuffer复用和新增类型标识高频遥测刷新场景下每帧重复allocate会造成明显的GC压力。我一般在通道线程里复用ByteBuffer解析完成后重置position和limit或者用Netty的堆外内存池。组装侧同理预先算好最大帧长避免扩容拷贝。扩展新类型标识时实现InfoObjectParser并在工厂注册即可不用改解析主链路。我自己在第一次做104接入时栽过浮点字节序的跟头一个遥测全部变成天文数字抓包对了一个晚上才发现是ByteBuffer大端默认姿势惹的祸。从那次之后我强制给所有解析器配上固定hex的回归用例每次改代码先跑一遍回放再也没翻过这个车。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

2026年腾讯云服务器调价解读:计费模式与优惠活动选购指南

2026年腾讯云服务器调价解读:计费模式与优惠活动选购指南

1. 2026年腾讯云服务器调价,先弄明白这轮变化到底改了啥每年年底到次年年初,都是云厂商调价和放活动的时间窗口。很多人一看到"2026年腾讯云服务器费用调整"这几个字就紧张,第一反应是"是不是要涨价了"。我这两周把腾讯云…

2026/10/7 11:55:39 阅读更多 →
PT1-SIP实验考试攻略:从日志接入到告警闭环的交付实战

PT1-SIP实验考试攻略:从日志接入到告警闭环的交付实战

简介:这是一份面向深信服PT1认证备考者与SIP平台运维人员的实验考试题库文档。文档先用表格完整列出总部AF、总部AC、总部EDR、SIP01、SIP02及总部Windows等设备的端口类型、端口描述、IP地址和管理密码,为搭建实验环境提供可直接对照的参数基线。实验部…

2026/10/7 11:55:39 阅读更多 →
recon分类Payload全景清单:USB Rubber Ducky侦察能力完全图谱

recon分类Payload全景清单:USB Rubber Ducky侦察能力完全图谱

recon分类Payload全景清单:USB Rubber Ducky侦察能力完全图谱 【免费下载链接】usbrubberducky-payloads The Official USB Rubber Ducky Payload Repository 项目地址: https://gitcode.com/GitHub_Trending/us/usbrubberducky-payloads USB Rubber Ducky 的…

2026/10/7 11:55:38 阅读更多 →

最新新闻

基于爬虫的全网自动比价系统:从数据采集到比价引擎的完整实践

基于爬虫的全网自动比价系统:从数据采集到比价引擎的完整实践

1. 项目定位与整体设计1.1 核心需求解析你手上这个“基于爬虫的全网自动比价系统”,光看名字就知道是典型的三件套组合:爬虫采集、数据清洗、比价展示。但它能成为计算机毕设里的热门选题,原因不只是技术栈齐全,更在于它天然自带“…

2026/10/7 12:28:28 阅读更多 →
营销方法论拆解为可复用技能包:基于Claude Code的SEO与CRO自动化实践

营销方法论拆解为可复用技能包:基于Claude Code的SEO与CRO自动化实践

1. 项目缘起:为什么我要把营销方法论拆成可复用的技能包做增长和SEO这行十来年,最头疼的一件事从来不是“不知道怎么做”,而是“知道怎么做,但每次都要重新讲一遍”。团队里新来的同学问“落地页标题怎么写”,我翻出去…

2026/10/7 12:28:28 阅读更多 →
四款 Agent 处理同一份 Excel:逐格比较公式、常量和缓存

四款 Agent 处理同一份 Excel:逐格比较公式、常量和缓存

同一张日期积分表,千问办公、WorkBuddy 和豆包工作把 16 个目标格全部写成了公式;WPS 灵犀补了后八格,保留中间五个数值,也留下了开头三个 n/a。 三份完整交付的计算结果一致,但公式的引用范围和文件保存的计算缓存并不…

2026/10/7 12:28:28 阅读更多 →
MarketingSkills实战:用Claude Code将SEO与CRO拆解为AI代理技能

MarketingSkills实战:用Claude Code将SEO与CRO拆解为AI代理技能

1. 从“marketingskills”说起:一个被低估的增长工具箱第一次看到marketingskills这个词,很多人会下意识以为它只是某个营销课程或者一份技能清单。但如果你最近在折腾 Claude Code、AI agents,或者正在给独立站做 SEO、CRO 和数据分析&#…

2026/10/7 12:28:28 阅读更多 →
C#教务系统详细设计文档:从选课并发到多校区隔离的工程实践

C#教务系统详细设计文档:从选课并发到多校区隔离的工程实践

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

2026/10/7 12:28:28 阅读更多 →
用术语统计拆解学术标题:以高压混合式UPFC拓扑为例

用术语统计拆解学术标题:以高压混合式UPFC拓扑为例

拿到一个学术标题,大多数人第一反应是用它去检索文献,或者照着写引言。我做的第一件事不太一样:先把它当成一个统计样本拆开——数词、切词、记频次、看词与词怎么连。这篇博文就是拿“高压混合式统一潮流控制器拓扑及其潮流调控应用研究”这…

2026/10/7 12:27:27 阅读更多 →

日新闻

ROS2机械臂仿真与运动控制:从URDF建模到Gazebo实战全解析

ROS2机械臂仿真与运动控制:从URDF建模到Gazebo实战全解析

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

2026/10/7 1:01:58 阅读更多 →
用浏览器直接改ESP32的WiFi密码:NVS键值配置工具设计与实现

用浏览器直接改ESP32的WiFi密码:NVS键值配置工具设计与实现

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

2026/10/7 1:02:00 阅读更多 →
芯片封装缺陷检测:扫描声学显微镜(SAT)原理与实操指南

芯片封装缺陷检测:扫描声学显微镜(SAT)原理与实操指南

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

2026/10/7 1:02:00 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

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

2026/10/6 7:15:40 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

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

2026/10/6 5:29:09 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

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

2026/10/7 9:29:10 阅读更多 →

月新闻

我发现了一个新思路:用 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/6 8:21:32 阅读更多 →
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/7 11:43:46 阅读更多 →
黑夜航拍船只数据集训练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/6 1:18:13 阅读更多 →