简介:这是一套面向云端光伏监控系统测试人员的DREAMS对接验证工具包,围绕台电DREAMS规范,通过DNP 3.0协议完成发电数据回传与变流器控制指令下发,覆盖实功/虚功调节、功率因数上限及VPset设定等关键验证点,适合需要将自研监控平台对接台电系统的开发与测试工程师参考。资源包共147个文件,压缩后仅351KB,包含62个JavaScript主程序、18个JSON配置、8个HPP与7个CPP的C++源码,Dockerfile与shell脚本便于在Ubuntu环境快速部署,证书、SSL配置、SQL、YAML等文件支撑完整联调场景。目前已有141人学习下载。压缩包体型小巧却覆盖完整联调链路,适合本地快速搭建测试环境。内容预览可见域名证书、默认站点配置、DNP3消息发送器、SOE事件处理与主测试入口等实现,目录结构紧凑,可直接作为对接联调的代码级样例,帮助理解DNP3协议交互和台电侧接口要求。 第一次在内部仓库里看到 dreams-cloud-joint-tester 这个名字时,我以为是哪个游戏的联调项目。点进去看了 README 才发现,这是测试人员自己维护的一套存储库,目标很直接:验证云光伏监控系统能不能满足 DREAMS 系统的接入要求,把数据正确、稳定地送到电网调度侧。干过光伏监控测试的同行应该都有体会,这类对接验证最磨人的不是功能逻辑本身,而是规约、点表、时序、性能、安全这些“电网侧视角”的硬性指标。今天把仓库背后的设计思路和实操细节拆开聊聊,希望给正在做并网对接测试的朋友一点参考。
1. 项目定位与验证思路拆解
1.1 这个存储库到底解决什么问题
光伏电站的监控系统,核心工作之一是把逆变器、电表、箱变、气象站等设备的数据采集上来,再按照调度侧要求上报。DREAMS 这类系统在电网侧承担分布式能源的监视与管理,它对数据格式、点表、上传频率、告警延迟、安全认证都有明确约定。问题在于,这些约定往往分散在不同文档、不同负责人手里,测一次换一次环境,很多验证工作全靠现场“手搓”。
dreams-cloud-joint-tester 本质上就是把这类验证工作资产化。它把点表比对工具、报文字节解析脚本、模拟数据生成器、告警场景剧本、回归报告模板全部沉淀到同一个仓库里。每次新电站接入、新版本发布、新环境部署,不用把之前踩过的坑再踩一遍,直接跑仓库里的用例就能完成基本验证。适合谁用?不只是测试人员,还包括做接入开发的工程师、做售前交付验证的同学,甚至现场运维排查问题时,也能靠仓库里的抓包脚本和报文样例快速定位大概范围。
这个仓库解决的痛点,用一句话概括就是:让“能不能接入 DREAMS”不再靠人肉确认,而是靠可重复、可追溯的自动化测试结果说话。
1.2 为什么把协议可靠性和数据质量放在第一位
对接 DREAMS 这类系统的验证,第一原则是:调度侧看的不是界面,是数据。监控界面再漂亮,曲线显示再顺畅,一旦上方用的核心数据算错、传错,后果比 UI 偶发刷新慢严重得多。所以测试策略必须分清楚主次。
我一般会把测试设计分成三层来做:
- 通讯层:连接建立、心跳保活、断线重连、消息帧格式是否正确;
- 数据层:点号映射、数据类型、缩放因子、时标精度、数据和告警是否完整;
- 业务层:告警联动、状态切换、曲线统计、报表生成。
这样做排序是有原因的。通讯层都不稳定,业务层的告警测试根本没有可信度;数据层格式不对,性能测试的结果再好看也是无效的。分层之后,每一层都有明确的准入标准,上一层的验证通过才进入下一层,排查问题时也方便快速定位是链路断了、解析错了、还是业务逻辑不对。可以类比寄快递:先保证包裹没破(通讯),再保证东西没放错(数据),最后才谈得上时效不时效(性能)。
2. 核心验证维度与技术要点
2.1 通信规约与点表一致性校验
DREAMS 对接中常见的通信方式有 IEC 60870-5-104、Modbus TCP、MQTT,也有一些项目走私有 JSON 或 REST 接口。无论哪种方式,最底层的工作都是确认规约实现符合规范。比如 104 规约里的 U 帧、S 帧、I 帧交互流程,总召唤、时钟同步、遥测/遥信传输格式,任何一个细节对不上,后面全白搭。
更关键的是点表比对。调度侧下发的点表定义了每个数据点的地址、上报周期、数据类型、缩放因子,平台侧必须严格按点表来组织数据。实际项目里最常见的错误就是缩放因子不一致:同一个电压量,点表要求一个小数位,平台按两位小数上报,数值就差出十倍;或者点号偏移一位,把 A 相电压当成 B 相电压传上去。
点表比对靠人眼看 Excel 很容易漏,我习惯写成脚本。下面是一个简化版思路:
def check_point_value(raw_value, point_config, tolerance=0.01): # point_config 包含缩放因子、数据类型、合理上下限 scaled = raw_value * point_config["scale"] assert point_config["min"] <= scaled <= point_config["max"], \ f"点号 {point_config['id']} 数据越界: {scaled}" assert abs(scaled - point_config["expected"]) < tolerance, \ f"点号 {point_config['id']} 数值偏差超限"这里的核心价值不是脚本多复杂,而是把点表核对变成一个可重复执行的“标准动作”。每当调度侧更新点表,只要替换 Excel 文件,重新跑一遍比对,就能快速识别平台侧映射是否需要调整。
2.2 数据完整性与时序校验
DREAMS 类系统对数据连续性有明确要求。以常见的五分钟采集周期为例,一天应该有 288 个数据点;十五分钟周期则是 96 个点。平台可能数据入库了,但中间缺了一段,或者时间戳出现了倒挂和重复,这都会直接影响上方的曲线和统计分析。
完整性校验的逻辑比较直接:查记录数、查时间戳是否单调递增、查相邻点间隔是否超过设定阈值。我常用的一段脚本是:
def check_time_series(timestamps, interval_minutes=15): diffs = [ (timestamps[i + 1] - timestamps[i]).total_seconds() / 60 for i in range(len(timestamps) - 1) ] max_gap = max(diffs) assert max_gap <= interval_minutes * 1.5, \ f"检测到长时间数据中断: {max_gap} 分钟"这里有一个容易忽略的点:时区。上报数据的时标到底用 UTC 还是本地时间,平台落库时是否做了转换,必须提前确认清楚。我遇到过平台曲线整体偏移 8 小时的情况,排查到最后发现是平台写库时又做了一次本地时区转换,导致时间重复加了一遍。这类时序问题建议在测试数据构造时就混入跨日的边界数据,专门验证切日、切月、跨时区的场景。
2.3 性能、稳定性与告警处理
数据正确之外,调度侧还很看重性能与稳定性。性能方面,主要关注并发上送时延、断线重连恢复时间、补传能力、以及长时间运行后的资源占用。稳定性方面,实际项目里最常见的开关是长时间跑 7×24 小时,观察平台内存是否持续增长、连接数是否异常增加、重连风暴会不会打挂服务。
告警处理在 DREAMS 接入测试里经常被低估。别小看告警,调度侧很多操作动作都依赖告警及时上送。我建议在存储库里放一套“告警场景剧本”,比如:
- 模拟逆变器通讯中断;
- 模拟电压越限并恢复;
- 模拟箱变跳闸;
- 模拟多设备同时掉线形成告警风暴。
每个场景要验证告警上送延迟、去抖时间、恢复确认、重复上送是否被拦截。实测里告警风暴是最容易出问题的点:一百台逆变器同时断线,短时间产生海量告警消息,消息队列处理不过来,轻则告警延迟,重则直接把平台打崩。性能压测脚本可以先从 100 个模拟点开始逐步加压,观察平台在哪个量级出现瓶颈,这个数据对上线容量规划也很有参考价值。
2.4 安全与权限校验
安全这块在监控系统对接测试里经常被忽略,但它恰恰是 DREAMS 这类系统验收时不太能让步的项目。常见检查项包括:
- 连接时证书过期或无效,连接是否被正确拒绝;
- 使用错误密钥握手失败时,系统是否有清晰日志;
- 平台侧账号权限是否按角色划分,普通账号能否访问配置修改接口;
- 关键配置变更是否留痕,能否追溯操作人、操作时间和操作内容。
之前有个项目联调到一半,平台突然连不上调度侧了。查了一圈发现是证书到期,但平台的错误日志只写了一句“连接失败”,完全没有提示证书相关原因,导致排查耗费了大半天。后来我把“证书过期场景”直接加进测试用例列表里,专测系统在证书异常情况下的日志和提示是否足够明确。安全验证不需要很复杂的工具,关键是覆盖面要全,把证书、账号、权限、审计这四类场景都覆盖到。
3. 存储库的组织结构与实操建议
3.1 一个可以直接参考的目录结构
存储库好不好用,目录结构很重要。我推荐按“文档、用例、脚本、数据、报告”五块来组织,结构清晰,新同事上手也不迷糊:
dreams-cloud-joint-tester/ ├── README.md ├── docs/ │ ├── DREAMS_interface_requirements.md │ └── point_table_template.xlsx ├── testcases/ │ ├── protocol/ │ │ └── test_104_link.py │ ├── data/ │ │ └── test_data_quality.py │ └── alarm/ │ └── test_alarm_dedup.py ├── scripts/ │ ├── load_point_table.py │ ├── mock_plant_data_gen.py │ └── capture_parse.py ├── testdata/ │ ├── normal_snapshot.json │ └── anomaly/ │ └── missing_points.csv ├── reports/ │ └── 2025-XX-XX_regression/ └── requirements.txttestcases 按协议、数据、告警分目录,scripts 放辅助脚本,testdata 固化各类正常和异常数据样本,reports 按日期保存回归结果。重点说一下 testdata 为什么值得单独放:测试数据如果不固定,每次执行结果就无法复现;数据一旦固定好,返工排查时环境条件和输入完全一致,问题还原会容易很多。
3.2 测试数据构造的要点
造测试数据是这活儿的重头戏。我的方法是以点表为基准生成一份“基础数据快照”,再在这个快照上做异常注入。注入方式很灵活,比如:
- 删掉中间连续一段数据点,模拟采集中断;
- 把某个时间戳复制一份,模拟重复上报;
- 给时间戳加随机抖动,模拟时钟漂移;
- 把某几个点的值改成远超合理范围的异常值;
- 让状态量在短时间内频繁翻转,模拟告警抖动。
造数据本身用脚本生成,不要手工整理,效率低且容易漏。一天 96 个点、1000 个测点,生成量也就是九万多条记录,CSV 完全能装得下。建议在造数脚本里固定随机种子,保证同样参数跑出来的结果一致。
3.3 一条遥测用例从设计到执行
拿一条最简单的“15 分钟遥测数据完整性”用例来说,完整流程大概是:
- 从点表读取被测点号清单;
- 启动模拟采集器,按 15 分钟间隔生成 24 小时数据;
- 平台入库后,通过接口或数据库查询对应时段的记录数;
- 断言记录数等于 96,且时间戳单调递增、无缺失;
- 执行结束后输出报告,记录测试数据和平台版本信息。
用 pytest 写起来也不复杂:
def test_telemetry_continuity(): plant = FakePlant("./testdata/normal_snapshot.json") plant.run(hours=24) records = query_telemetry(plant.device_id) assert len(records) == 96, "15分钟间隔应上送96条记录" assert check_time_series([r.timestamp for r in records], interval_minutes=15)执行命令就是常规的 pytest 方式:
pytest testcases/data/test_data_quality.py -s这条用例看似简单,但它能拦截掉一群基础问题:数据漏传、时标错乱、周期配置错误、电量统计差数。真正有用的回归用例,往往就是这类“基础但关键”的用例。
3.4 自动化集成与报告输出
存储库只停在手动跑脚本的层面,价值会打不少折扣。建议纳入 CI 流水线,每天晚上定时跑一轮回归,哪怕是测试环境不稳定、部分用例会失败,也不怕——关键是自动化能发现“昨天还好好的、今天突然挂了”这类回归问题。
报告建议直接用 Allure 或者 JUnit XML,方便在 CI 页面里直观查看哪些用例失败、失败在哪个断言。CI 环境跑 DREAMS 对接测试有个难点:平台和数据库环境不容易在临时容器里完整复现。我的做法是让 CI 触发远程测试服务器上的脚本执行,测试结束后再把报告和日志拉回来,既保证了环境一致性,又不需要为测试单独维护一套庞大容器编排。这一步配置起来不复杂,但收益非常大,值得花时间做。
4. 常见问题与排查技巧实录
4.1 高频踩坑点
做了小半年的对接测试,我把高频踩坑点按“出现频率”和“坑人程度”排了个序:
- 时间戳不统一:采集端用本地时间,平台落库用 UTC,两边各加了偏移,数据对不上;
- 点表更新不同步:调度侧加了新测点,平台侧点表配置文件没更新,新数据直接丢弃;
- 缩放因子错误:电压、电流、功率的缩放因子差一位小数,上送数据和实际值对不上;
- 断线重连补传顺序乱:平台重连后开始补传历史数据,但补传的数据顺序错乱,覆盖了本地新数据;
- 告警重复上报:告警没有做好去抖,一个电压越限能连发十几条告警,直接把调度侧刷屏。
每个坑背后都是实际业务场景的代码逻辑问题,光靠读代码不容易发现,靠测试用例却能快速暴露。比如补传顺序问题,只要测试脚本里模拟断线 10 分钟再恢复,然后检查恢复后的数据是否按时间戳严格排序,问题一秒现形。
4.2 排查流程与速查表
排查这类问题,我习惯遵循一条主线:从链路到数据、从数据到业务、从业务到配置。下面这张表是我实际排查时经常对照的,直接贴出来供参考:
| 问题现象 | 可能原因 | 排查步骤 |
|---|---|---|
| 数据入库了但曲线缺失 | 时区偏移/时间戳错乱 | 对比原始报文时间戳与数据库时间,检查是否跨时区重复转换 |
| 告警重复上报 | 缺去抖或持续时长判断 | 查看告警确认报文,检查阈值和去抖配置 |
| 断线重连后历史数据丢失 | 补传机制未覆盖该场景 | 抓包确认重连后是否发起补传请求,检查队列是否溢出 |
| 连接被拒绝且日志不明确 | 证书过期或密钥不匹配 | 检查证书有效期,抓包确认握手阶段错误码 |
| 长时间运行内存增长 | 长连接或消息队列未释放 | 在压测环境抓取堆栈,重点看连接池和队列线程 |
| 平台收不到遥信变位 | 点表映射错误或状态量类型不匹配 | 核对点表遥信定义与平台侧字段类型,做变位报文回放 |
这张表的价值不在表本身,而在提示你用“结构化方式”逐层缩小问题范围。真到了现场联调,着急没用,一步一步打日志、抓包、对比配置,往往比凭感觉改参数更快。
4.3 独家技巧:报文录制与回放
最后分享一个我比较得意的小技巧:报文录制与回放。很多现场问题之所以难复现,是因为现场接线、设备型号、报文节奏都很特殊。我的做法是在联调现场保存一份原始报文日志,回到测试环境后用脚本按相同时间间隔和顺序回放,让平台和处理流程重新走一遍。
回放时需要注意两点:一是时间戳要处理,不能原样用录制时刻的时间,最好设置一个基准时间做偏移,让平台认为数据是实时到达的;二是序列号要重置,避免平台认为报文是重复的旧帧直接丢弃。有了这套回放能力,复现现场问题会轻松很多,研发定位也能直接在测试环境操作,不用反复跑现场。
5. 一点实际体会
做这个存储库的过程中,我的最大体会是:这类测试资产的价值不在于脚本写得有多高级,而在于把“现场经验”变成“可复现用例”的能力。真正维护起来,会发现它不是一个一次性的交付物,更像是一个越用越厚的知识库。每踩一个新坑,就往 testcases 里补一个用例,往 docs 里记一段背景知识,往 reporting 里留一份汇总报告。仓库越来越厚,人却越来越轻松。
还有个小建议:把点表和测试数据基线一起纳入版本管理。点表一变,脚本和测试数据也需要同步更新,保存好历史版本能让你随时复原“上一次联调现场”的环境。后续如果时间允许,可以把 Mock 上报服务抽成独立组件,支持更多规约和更复杂的异常注入,再把新电站接入变成一个半自动化的流程。对我个人来说,这类存储库的长期价值比绝大多数“一次性联调工具”高得多,越早沉淀越省事。
本文还有配套的精品资源,点击获取