云光伏监控DREAMS并网验收:基于JavaScript的联测存储库
简介面向光伏监控系统测试人员的DREAMS云端对接测试程式用于验证云光伏电站监控系统是否满足台电DREAMS规范。其核心能力是通过DNP 3.0将发电数据上传至台电DREAMS系统同时接收台电下发的控制指令调整变流器的有功/无功功率、功率因数上限或VPset设定可帮助监控业者对旗下电站完成合规接入验证。资源包共147个文件压缩后仅351KB文件以JavaScript、JSON、C头文件/源文件hpp/cpp、Shell脚本及Dockerfile为主覆盖前端交互、通信逻辑、容器化部署与环境配置等用途。目前已有141人学习/下载适合需要开展DNP 3.0对接测试或排查通信细节的光伏监控开发与测试人员。包内除完整测试程序源码外还提供Docker编排配置、SSL证书/密钥样例、监听事件处理模块及消息发送工具脚本便于快速搭建Linux测试环境并验证实功/虚功调节等关键场景。1. 云光伏监控系统过 DREAMS 验收先过这套 JavaScript 联测存储库某电网集团的 DREAMS 并网验收系统是云光伏监控系统并网前必须过的一道闸。很多开发团队在验收前夜才发现问题本地测试一切正常DREAMS 侧看到的却是曲线断断续续、控制指令超时、补报窗口不达标。这类问题背后的共性是——测试停留在功能正常层面没有站在 DREAMS 的视角去验证规约、字段和时间窗口。这个存储库就是干这个的一套以 JavaScript 和 Node.js 为主的联测脚手架把并网验收规范转成可重复执行的脚本、模拟器和断言用例。适合并网接入工程师、云监控后端开发、测试工程师直接拿去改造成自己项目的验收基线。2. 拆验收域、定测试栈DREAMS 联测为什么用 JavaScript 与 JestDREAMS 这类并网验收系统校验的不是界面长什么样而是云光伏监控系统能不能按规约把数据送上来、按指令把功率调下去。换句话说这是规约验收不是功能验收。所以拿到存储库之后第一步不是看代码而是把验收要覆盖的数据域拆开再对照你自己接入省份发布的并网技术规范逐项勾选。拆完域选型理由自然就清楚了。2.1 验收到底验什么五个数据域和两条通信链路我把 DREAMS 联测相关的验收内容梳理成五个数据域这是我拿到一套新规范时习惯性的整理方式具体字段定义以你接入的省级并网技术规范为准。数据域核心内容常见验收周期或阈值实时运行数据有功、无功、电压、电流、功率因数、日发电量1~5 分钟上报周期周期可配置并网状态与告警并网/离网状态、通信状态、保护动作、越限告警事件即时上送带状态码功率控制AGC/AVC 指令接收、回执、执行结果控制指令响应时间、调节完成度数据质量时间戳格式、值域范围、重复帧、乱序帧时间戳 ISO8601 带时区数据连续断点续传网络中断期间缓存、恢复后补报缓存窗口不小于 15 分钟两条链路分别指上行和下行上行链路负责把监控数据从云平台推到 DREAMS 侧下行链路把 DREAMS 的功率控制指令拉到逆变器。很多验收不通过问题不在功能实现而在两条链路之间某个字段的映射对不上。比如上行链路里时间戳字段格式不统一或者下行链路里回执和结果状态码合在一个字段里都会导致 DREAMS 侧判定异常。这里有一个可以少走弯路的思路把五个数据域映射成用例的优先级不要平均用力。我一般先做实时运行数据和断点续传因为这两个域是验收退回的高发区而且很容易用自动化用例覆盖功率控制域放到第二步因为它强依赖模拟器和指令下发链路数据质量域则穿插在前两个域的用例里用异常注入的方式去验证。2.2 为什么选 JavaScript 而不是跑一遍就扔的脚本这个存储库以 JavaScript 为主选型理由有三点。第一云光伏监控系统的后端如果是 Node.js测试脚本和业务服务共用一套调试栈联调时可以直接在同一个进程里打断点比跨语言切换省很多事。第二Node.js 对 TCP、WebSocket、HTTP/2 的支持比较完整后面要模拟 Modbus TCP 采集器或者轮询式网关不用再引一大堆底层依赖。第三Jest 的参数化测试和假时钟在时间窗口类用例里很好用正好命中超时判定和断点续传这两个高频场景。这不是说 JavaScript 一定比其他语言强。Python 写协议脚本也有优势但这个存储库的定位是跟着业务后端走所以选了 Node.js。如果你所在团队的后端是 Java 或 Go把 testcases 目录里的脚本换成对应语言也可以目录结构和用例设计思路是一样的。关键是别为了换成团队更熟的语言而丢掉配置驱动和黄金报文比对这两个核心设计。2.3 仓库结构拆解每个目录对应一个验收域把存储库解压后目录结构大致是这样。我按一个目录解决一个验收域的原则组织避免所有脚本堆在根目录里joint-tester/ ├── config/ # 环境配置与验收阈值 │ ├── default.json │ └── acceptance-prod.json ├── protocols/ # 报文编解码与协议适配 │ ├── iec104.js │ ├── modbus-tcp.js │ └── timestamps.js ├── simulators/ # 设备与电网侧模拟器 │ ├── inverter-sim.js │ └── gateway-sim.js ├── testcases/ # Jest 用例 │ ├── report.spec.js │ ├── control.spec.js │ └── complement.spec.js ├── fixtures/ # 黄金报文与 JSON Schema │ ├── schemas/ │ └── golden/ ├── reports/ # 测试报告输出 └── scripts/ ├── smoke.sh └── verify-golden.jsconfig 目录放环境参数protocols 目录处理规约编解码simulators 里是模拟器fixtures 里的 golden 文件是从 DREAMS 规范里摘出来的样例报文后面做回归基线时主要靠它。testcases 目录里每个 spec 文件对应一个数据域report 对应实时上报control 对应功率控制complement 对应断点补报。用例编号规范也要从第一天就建立。我在 testcases 里用的是 TC-RPT-3.1.2 这种格式前缀表示数据域后面的数字直接映射验收规范的章节号。验收评审时专家看到用例编号就能定位到对应规范条款比解释一堆文件名省事得多。这个习惯是某次验收评审被问这条用例对应规范哪一条之后养成的从那以后所有联测仓库都强制带规范章节号。3. 搭联测脚手架Node.js Jest 跑通第一条逆变器上报用例这一章直接进入可执行的部分。目标很明确初始化一个能跑、能出报告的最小仓库然后跑通第一条逆变器实时数据上报用例。3.1 初始化仓库依赖、Node 版本、锁定文件新建目录后先写 package.json。依赖控制在四个以内太多会引入版本漂移问题{ name: dreams-cloud-joint-tester, version: 0.1.0, private: true, engines: { node: 20.0.0 }, scripts: { test: jest --runInBand, test:report: jest --runInBand --reportersdefault --reportersjest-junit, verify:golden: node scripts/verify-golden.js }, devDependencies: { jest: ^29.7.0, jest-junit: ^16.0.0 }, dependencies: { ajv: ^8.12.0, axios: ^1.7.0 } }逻辑说明jest 负责用例执行axios 负责从云监控 API 拉数据ajv 负责按 JSON Schema 校验上报字段。jest-junit 只在 test:report 时启用把结果输出成 JUnit XML方便接入 CI 和生成验收材料。engines 字段指定 Node 20 以上因为下面模拟器用到了较新的 Buffer 和流式 API版本太低会在启动时报错。参数说明--runInBand 强制用例串行执行。这个仓库里的用例会启动 TCP 模拟端口并行跑容易互相抢端口串行虽然慢一点但结果稳定。所以 package.json 里所有 test 脚本都带上了 --runInBand这是一个有意的设计不是为了省事。依赖锁定是必须做的一步。package-lock.json 要提交进仓库换环境跑用例时用 npm ci 而不是 npm install能避免本地全绿、CI 环境翻车的版本漂移问题。我在第 5 章会专门讲一条和这个相关的踩坑记录。3.2 配置驱动的分层设计环境、账号、验收阈值分开config/default.json 是仓库的默认配置。这里把环境参数和验收阈值分开存放联调环境、预验收环境、正式验收环境切换时只改环境变量不改用例代码{ cloudApi: { baseUrl: http://localhost:8080, timeoutMs: 10000, clientId: joint-tester, clientSecret: change-me }, dreams: { endpoint: tcp://127.0.0.1:2404, remoteUnitId: 1, commonAddress: 1 }, acceptance: { reportIntervalSec: 300, complementWindowMin: 15, timestampFormat: ISO8601 } }逻辑说明cloudApi 指向被测的云光伏监控系统dreams 指向本地的 DREAMS 网关模拟器acceptance 段落里放验收阈值。这里最值得注意的字段是 complementWindowMin它是断点补报窗口单位是分钟验收规范里如果写的是不小于 15 分钟那配置就应该填 15而不是 10。很多验收退回就是栽在这个默认值上。参数说明remoteUnitId 和 commonAddress 分别是 104 规约里的远动单元地址和公共地址具体值由接入点配置决定不要照抄样例。配置加载我一般写成 loadConfig() 函数先用 default.json再用 process.env 覆盖这样不用改代码就能切换环境。如果你有多个环境还可以再加一个 acceptance-prod.json把正式验收环境的阈值单独放一份避免污染开发环境。3.3 第一条上报断言用例用 AJV 校验字段结构testcases/report.spec.js 是第一批要跑通的用例。它做三件事请求云监控系统自身的 API、拿到一台逆变器的实时数据、按照规范定义的 JSON Schema 做结构校验const axios require(axios); const Ajv require(ajv); const loadConfig require(../config/loadConfig); const inverterReportSchema require(../fixtures/schemas/inverter-report.schema.json); describe(TC-RPT-3.1.2 逆变器实时数据上报, () { const config loadConfig(); test(单台逆变器上报字段满足 DREAMS 数据订阅要求, async () { const resp await axios.get( ${config.cloudApi.baseUrl}/api/v1/inverters/INV-001/realtime, { timeout: config.cloudApi.timeoutMs } ); expect(resp.status).toBe(200); const ajv new Ajv(); const validate ajv.compile(inverterReportSchema); const valid validate(resp.data); expect(valid).toBe(true); if (validate.errors) { console.error(JSON.stringify(validate.errors, null, 2)); } }); });逻辑说明这里拿到的 resp.data 是云监控系统自己接口返回的实时数据还没到 DREAMS 侧。为什么先测这一层因为如果云监控自身的接口字段都不满足规范那后面推给 DREAMS 的报文必然有问题。在这一层拦截联调成本最低也最容易定位问题。参数说明timeoutMs 用的是 config 里的值避免用例之间同步超时配置。schema 文件放在 fixtures/schemas 下从 DREAMS 规范的字段定义表转成 JSON Schema这一步是体力活但转完一次后面所有上报用例都能复用。URL 路径/api/v1/inverters/INV-001/realtime是示例路径真实环境要以云监控系统的接口文档为准建议把路径也放进 config不要在用例代码里到处写死。3.4 执行与报告JUnit XML 和 Allure 的落地配置跑用例的姿势要固定先安装依赖再执行带报告的脚本npm ci npm run test:reportjest.config.js 里把 JUnit reporter 的输出路径指到 reports 目录module.exports { testEnvironment: node, testTimeout: 30000, reporters: [ default, [jest-junit, { outputDirectory: reports/junit, outputName: joint-test.xml, classNameTemplate: {filepath}, titleTemplate: {title} }] ] };逻辑说明testTimeout 设 30000 毫秒是因为里面有用例要模拟断网等待和补报窗口太短会导致用例误报。outputDirectory 和 outputName 指定 JUnit XML 的落盘位置这类文件是整个验收材料里最直接的自动化证据。参数说明classNameTemplate 用 {filepath}titleTemplate 用 {title}这样 XML 里能直接看到用例来源文件和标题评审时不用再翻源码定位。跑完以后看 reports/junit/joint-test.xml用 Allure 或任何能渲染 JUnit 的工具打开。我习惯的检查顺序是先看失败用例属于哪个数据域再对照第 2 章的五个域定位是配置问题、字段映射问题还是模拟器问题不要一上来就改代码。4. 写模拟器与异常注入没有真实逆变器也能压出链路问题云光伏监控系统的联调难点之一是现场没有真实设备时DREAMS 验收没法做。这个存储库用模拟器代替真实逆变器和采集网关把链路先跑起来。下面讲怎么用 Node.js 内置的 net 模块写一个最小可用的 Modbus TCP 逆变器模拟器。4.1 手写一个 Modbus TCP 逆变器模拟器Modbus TCP 帧由 MBAP 头加 PDU 组成读取保持寄存器的功能码是 0x03。模拟器只需要监听一个端口收到读请求后按寄存器地址返回对应的有功、无功、发电量数值const net require(net); const registers { 0: 5000, // 有功功率0.1kW 单位实际值 500.0kW 1: 200, // 无功功率0.1kVar 2: 125000, // 日发电量0.1kWh 3: 9800 // 功率因数0.0001实际 0.98 }; const server net.createServer((socket) { socket.on(data, (buf) { if (buf.length 8) return; const transactionId buf.readUInt16BE(0); const protocolId buf.readUInt16BE(2); const unitId buf.readUInt8(6); const functionCode buf.readUInt8(7); if (protocolId ! 0 || functionCode ! 0x03) return; const startAddress buf.readUInt16BE(8); const quantity buf.readUInt16BE(10); const byteCount quantity * 2; const response Buffer.alloc(9 byteCount); response.writeUInt16BE(transactionId, 0); response.writeUInt16BE(protocolId, 2); response.writeUInt16BE(byteCount 3, 4); response.writeUInt8(unitId, 6); response.writeUInt8(functionCode, 7); response.writeUInt8(byteCount, 8); for (let i 0; i quantity; i) { const value registers[startAddress i] || 0; response.writeUInt16BE(value, 9 i * 2); } socket.write(response); }); }); server.listen(5020, 127.0.0.1, () { console.log(inverter simulator listening on 5020); });逻辑说明这段代码的核心是构造 Modbus TCP 响应帧。transactionId 必须原样带回客户端靠它匹配请求和响应很多联调问题就出在这个字段被模拟器改了。长度字段 byteCount 3 表示 unitId、functionCode、byteCount 加上寄存器数据的总字节数写错会导致客户端解析错位这是手写协议栈最容易翻车的地方。参数说明registers 对象的地址映射是典型的逆变器保持寄存器布局具体厂商可能用不同的地址表。常见做法是把这个地址表放到配置文件里模拟器启动时读取换设备型号不用改代码。如果你要模拟多台逆变器就让模拟器监听多个端口每个端口对应一台设备的地址表。启动脚本可以写成这样把模拟器进程和测试串起来#!/usr/bin/env bash set -euo pipefail node simulators/inverter-sim.js --port 5020 SIM_PID$! sleep 1 npm run test:report kill $SIM_PIDset -euo pipefail防止脚本中途静默失败sleep 1 是等端口监听就绪端口如果被占用模拟器会直接抛异常退出测试也不会继续。kill 放在测试结束之后保证端口不残留。4.2 异常注入时间戳漂移、负功率和乱序重复帧模拟器能跑正常链路后下一步是让它产出坏数据验证云监控系统能否识别和规避。我一般把异常注入做成独立的 mutator 函数测试时传入帧数据返回篡改后的帧function mutateFrame(frame, mutationType) { const copy Buffer.from(frame); switch (mutationType) { case negative_power: copy.writeUInt16BE(0xFFFF, 9); // 补码表示 -1 break; case reversed_order: return Buffer.concat([copy.slice(6), copy.slice(0, 6)]); case duplicate_frame: return Buffer.concat([copy, copy]); default: return copy; } }逻辑说明negative_power 用例把有功寄存器写到 0xFFFF在补码表示里就是 -1云监控侧应该把这个值判定为无效或触发告警reversed_order 把 MBAP 头和 PDU 对调测试协议解析器的容错能力duplicate_frame 直接拼两帧同样的数据测试云端会不会重复入库。参数说明timestamp_drift 在 Modbus 链路里改不了因为 Modbus 本身没有时间戳。真正要测时间戳漂移应该在应用层上报接口做注入比如云监控的 REST API 或消息队列里把 timestamp 字段偏移几分钟。这个用例更适合放在第 3 章的上报断言用例里配合 mock 数据源来跑。4.3 用 test.each 把异常用例参数化Jest 的 test.each 很适合把正常帧加多种异常帧放进一张参数表。每个用例只描述期望行为输入数据和期望值分开维护describe(异常帧容错, () { test.each([ [negative_power, 应用层应判定为无效功率], [reversed_order, 协议层应丢弃错序帧] ])(%s%s, async (mutationType) { const client await connectToSimulator(); const normalFrame createReadRequestFrame(0, 4); const mutated mutateFrame(normalFrame, mutationType); client.write(mutated); const response await waitForResponse(client, 3000); if (mutationType reversed_order) { expect(response.length).toBe(0); } else { expect(response.length).toBeGreaterThan(0); } }); });逻辑说明mutateFrame 根据 mutationType 决定怎么改帧测试用例只描述期望结果。reversed_order 期望协议层丢弃错序帧即响应为空negative_power 期望模拟器正常响应不做底层拦截因为负功率能不能被识别为无效要由云监控的上层逻辑决定这个用例断言的是链路没有被异常帧打挂。参数说明waitForResponse 的 3000 毫秒是超时上限具体值需要根据被测系统的处理链路调整链路长就调大。connectToSimulator 每次用例重新建连避免前一个用例的 socket 状态影响下一个这也是整个测试必须用 --runInBand 串行跑的另一个原因。5. 联测避坑手记五条验收翻车记录与排查顺序联测阶段有些问题看起来像玄学查到最后基本都是配置、字段映射或依赖版本的问题。下面这几条算得上血泪经验每条都按现象、原因、解决三个顺序写方便你对着排查。5.1 数据类避坑超时判定、时区换算、断点补报窗口第一条DREAMS 界面频繁提示数据超时本地看上报日志却一直正常。原因通常是上报周期本身有抖动云监控按固定周期加固定容忍窗口判定一旦某次上报晚了几秒就进入超时状态。解决方式是改成滑动窗口统计在配置里把容忍窗口从 5 秒放宽到上报周期的一半比如 300 秒周期配 150 秒容忍窗口同时增加上报成功率的监控指标别等 DREAMS 侧先报警。第二条跨天之后曲线断档。界面曲线每天零点前后缺一段数据明细里却查得到记录。原因是云监控内部按北京时间生成时间戳上报后按 UTC 存库界面没有再按本地时区回显导致跨天那一小时看起来是空的。解决方式是统一时间戳格式为 ISO8601 并带上时区偏移界面展示层按操作员时区换算存储层一律 UTC不混用。这条排查起来很费时间因为它涉及存储、上报和展示三层建议把时间戳格式直接写进 JSON Schema 的 format 字段从用例层拦住。第三条断线恢复后DREAMS 侧看到的是缺了一截而不是连续数据。原因基本是补报窗口配小了。不少平台默认补报窗口是 10 分钟但验收规范写的是不小于 15 分钟。解决方式是先把 acceptance.complementWindowMin 改成 15 甚至更大然后重启云监控的采集服务观察补报任务的日志确认缓存数据全部按序上送。这条我在第 1 章开头提到的场景里实际踩过当时连续折腾了几个通宵最后只是改一个配置值。5.2 链路类避坑指令回执、依赖锁定、多连接并发窗口第四条功率控制指令在本地模拟环境里响应正常一进验收环境就超时。排查后发现云监控把指令已收到和指令已执行合成一个字段上报DREAMS 侧期望的是两个独立事件先收到回执再等执行结果。解决方式是拆事件流收到指令后立刻上报 receipt 事件执行完成后上报 result 事件两个事件的状态码分开定义。这个坑的隐蔽之处在于本地模拟器没有严格校验事件流验收侧才暴露出来。第五条同一套用例在 CI 环境跑不过本地几乎全绿。这种情况优先怀疑依赖不是业务代码。package-lock.json 没有提交导致 npm install 在不同时间解析出不同版本某个私有依赖升级后改变了报文校验逻辑长度校验失败。解决方式是提交 package-lock.json在 CI 里改用 npm ci 而不是 npm install同时在 .nvmrc 里固定 Node 主版本。从那以后我所有联测仓库都强制提交 lock 文件并在 CI 的第一条检查 Node 版本。排查顺序建议是当 DREAMS 联测失败时先看时间戳格式和补报窗口配置再看指令回执状态拆分最后查依赖版本。前两个是业务侧最容易改错的点最后一个是环境侧最容易背锅的点。按这个顺序排查大多数问题都能在一轮内定位。6. 进阶用法黄金报文比对让每次发布自带并网体检报告联测用例跑通只是第一步更重要的价值是把它变成回归基线。我常用的进阶做法是黄金报文比对把 DREAMS 规范里的样例报文整理成 fixtures/golden 目录下的 JSON 文件每次被测系统上报后把实际报文和 golden 文件做结构化比对。// scripts/verify-golden.js const fs require(fs); const path require(path); const goldenDir path.join(__dirname, ../fixtures/golden); const actualPath path.join(__dirname, ../reports/last-upload.json); const golden JSON.parse(fs.readFileSync(path.join(goldenDir, realtime.json), utf8)); const actual JSON.parse(fs.readFileSync(actualPath, utf8)); function diffKeys(a, b, prefix ) { const problems []; for (const key of Object.keys(a)) { if (JSON.stringify(a[key]) ! JSON.stringify(b[key])) { problems.push(${prefix}${key}); } } return problems; } const problems diffKeys(golden, actual); if (problems.length 0) { console.error(golden mismatch:, problems.join(, )); process.exit(1); } console.log(golden check passed);逻辑说明这个脚本只做一层 key 比对真实场景建议用 deepStrictEqual 或专门的 JSON diff 库。重点是比对基线不是代码 Reviewer 人肉定的而是从规范文档里整理出来的样例这样每次更新字段映射后跑一遍能自动发现不兼容改动。我在 scripts 里还挂了一个 verify:golden 的 npm script和 Jest 用例并行跑。参数说明process.exit(1) 让脚本在 CI 里失败时能阻断发布流程。reports/last-upload.json 是被测系统最近一次上报的原始报文可以来自云监控的调试接口也可以从上报日志里取最近一条。拿到存储库时第一件事是把 fixtures/golden 目录清空换成你自己接入省份规范的样例报文再去改 config 里的阈值。从那以后我每次改完上报逻辑都会强制走一遍 verify:golden 再提测这个习惯帮我挡掉了至少三次字段映射回归。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

【JavaEE】网络原理 - TCP/IP

【JavaEE】网络原理 - TCP/IP

网络原理 - TCP/IP 文章目录网络原理 - TCP/IP前言一、应用层自定义协议流程二、传输层协议TCP核心机制介绍1 确认应答2.超时重传3.连接管理(面试常考4.滑动窗口5.流量控制6.拥塞控制7.延时应答8.捎带应答(配合延时应答)9.面向字节流10.异常情况1.进程崩溃2.主机关机(正常流程关…

2026/10/15 12:01:06 阅读更多 →
Python图像处理首选:Pillow核心用法全解析

Python图像处理首选:Pillow核心用法全解析

1. 为什么直到今天还在用Pillow1.1 轻量级方案中的最优解我最早接触Pillow是在一个给图片做批量预处理的小项目里。当时摆在面前的两个方向,一个是OpenCV,另一个是Pillow。OpenCV确实功能强,可装包重、概念也多,读取图片出来的默认…

2026/10/15 12:01:06 阅读更多 →
从文本引擎内存飙升到享元模式:C++状态拆分与缓存实战

从文本引擎内存飙升到享元模式:C++状态拆分与缓存实战

1. 从一次内存飙升说起:享元模式想解决的问题 事情发生在给一个文本渲染模块做优化的时候。当时模块里有一块非常朴素的功能:把一份上千页的文稿按页渲染成位图。功能跑起来没有任何问题,但一打开任务管理器我就愣住了,进程占用将…

2026/10/15 12:01:06 阅读更多 →

最新新闻

Vue+ThinkPHP-Laravel构建二手车交易平台实战

Vue+ThinkPHP-Laravel构建二手车交易平台实战

1. 项目背景与核心价值 二手汽车交易市场近年来呈现爆发式增长态势,但传统线下交易模式存在信息不对称、交易流程繁琐、信任成本高等痛点。基于VueThinkPHP-Laravel的混合架构方案,恰好能解决行业数字化转型中的三个关键问题: 前端体验优化 …

2026/10/15 12:38:06 阅读更多 →
双端队列deque全解:从底层原理到单调队列与竞赛应用

双端队列deque全解:从底层原理到单调队列与竞赛应用

做算法题的人大概都经历过这样的场景:一道滑动窗口最大值的题,第一反应是priority_queue,塞进去跑一遍O(n log n)也AC了,但看着题解区那个O(n)的写法总觉得自己绕了远路。再过一阵子遇到DP优化,状态转移里带着一个&quo…

2026/10/15 12:38:06 阅读更多 →
【OpenClaw 本地实战 Ep.1】抛弃 Ollama?转向 LM Studio!Windows 下用 NVIDIA 显卡搭建 OpenClaw 本地极速推理服务

【OpenClaw 本地实战 Ep.1】抛弃 Ollama?转向 LM Studio!Windows 下用 NVIDIA 显卡搭建 OpenClaw 本地极速推理服务

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

2026/10/15 12:38:06 阅读更多 →
八数码问题C语言BFS实现:从伪广搜到工业级最短路径求解

八数码问题C语言BFS实现:从伪广搜到工业级最短路径求解

简介:本资源是一份面向计算机专业本科生与算法初学者的八数码问题求解实践材料,聚焦宽度优先搜索(BFS)思想在经典状态空间搜索问题中的C语言实现。资源以详实的DOC文档形式呈现,完整包含算法原理剖析、结构体设计逻辑、…

2026/10/15 12:38:06 阅读更多 →
OV7670+SDRAM+VGA:FPGA实时图像链路设计与避坑指南

OV7670+SDRAM+VGA:FPGA实时图像链路设计与避坑指南

简介:这是一套面向FPGA与数字图像处理学习者的完整工程实践资料,围绕OV7670 CMOS摄像头、SDRAM缓存与VGA显示构建实时视频采集与显示链路,并集成中值滤波算法改善画质。项目覆盖IIC寄存器配置、SDRAM控制器读写、VGA时序驱动以及灰度图像去噪…

2026/10/15 12:38:06 阅读更多 →
从8k到1M上下文的通用化:利用Qwen-Agent的创新实践

从8k到1M上下文的通用化:利用Qwen-Agent的创新实践

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

2026/10/15 12:37:05 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 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/15 0:14:36 阅读更多 →
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/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练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/15 9:49:14 阅读更多 →