
简介《电力需求响应信息模型 第1部分集中式空调系统》为T/CEC 239.1—2019中国电力企业联合会标准面向集中式空调自动需求响应终端、接口设计与开发人员以及参与智能电网负荷调控的设备厂商和研究者用于统一空调系统参与需求响应的信息表达与互操作框架。压缩包共1个PDF文件大小约396KB完整收录标准正文及资料性附录便于检索查阅。目前已有307人学习。文档围绕实用性、便捷性、适用性与扩展性等建模原则明确整型、字符串、浮点、布尔量、日期时间等数据类型并划分通用包与专用包附录给出需求响应能力计算方法可帮助读者理解终端接口建模、数据字段定义、控制指令与节能策略的组织方式为设备接入、软件开发和后续类似负荷信息模型设计提供参考。1. 集中式空调要参与需求响应先得有一份能对话的信息模型某写字楼夏天收到电网侧发来的需求响应邀约物业说“空调能压 30 分钟”调度那边追问三句压多少千瓦、多久能爬到位、什么时候能完全恢复。两边就聊不下去了。类似僵局我遇到过很多次问题从来不在冷水机组能不能降载——能问题在于双方没有共同语言去描述“这台机组此刻能提供多少可调容量、降载要付出什么代价、恢复到什么状态才算结束”。电力需求响应信息模型 第 1 部分把对象锁定在集中式空调系统上要解决的就是这件事把冷站里的冷机、冷冻水泵、冷却水泵、冷却塔、末端机组连同它们的可调能力、响应约束、事件状态整理成一组可交换、可校验、可被第三方复核的数据结构。这套模型适合三类人做楼宇自控想往上接需求响应平台的、做负荷聚合要盘用户侧可调容量的、以及做配电侧集成需要批量对接空调资源的。它不教你怎么调 PID但它决定你报上去的数字能不能被信任。2. 从设备台帐到逻辑节点集中式空调系统怎么拆成可交换的对象集中式空调也就是常说的中央空调是一个典型的“点多、耦合强、边界模糊”的系统。冷水机组、冷冻水泵、冷却水泵、冷却塔、板式换热器、组合式空调机组、风机盘管、电动二通阀任何一台设备的动作都会牵动整个水系统的温度和流量。给这样的系统建模最忌讳按电气一次图去切也忌讳按厂家品牌去切。合理的切法只有一种按“能独立表达可调能力的最小单元”来切。2.1 先定边界一棵从站到末端的对象树我一般把模型分成四层层级关系固定不允许现场随意增减否则不同项目之间的模型无法比对。第一层是站代表一个冷源站或一个独立的空调系统边界它承担需求响应事件的接收、能力汇总和回执第二层是子系统冷源侧、输配侧、末端侧三个用来描述耦合关系第三层是设备冷机、各类水泵、冷却塔、末端机组第四层是能力也就是可调容量、爬坡率、可持续时长这些“数字”它们不挂在设备铭牌上而是挂在设备当前工况下。这样分层的好处是汇总逻辑天然成立站级可调容量 Σ(设备级可调容量) 但要乘一个同时率系数因为水泵降频之后冷机的可用能力也会跟着变。很多项目栽在这里——把设备容量简单相加报出去的数字比实际能拿到的多三成第一次结算就被打回来。所以模型里必须有一个“同时率”或“耦合修正系数”属性挂在子系统层由现场调试时标定默认值我一般取 0.85再按实际响应曲线修正。对象树还要解决一个现实问题现场大量设备根本没有通信接口老冷机只有一块本地显示屏。这类设备不能从模型里排除而要建成“虚拟设备”——保留设备对象和铭牌属性运行数据由人工录入或由电量计量间接推算并打上数据来源标记。模型对数据来源的诚实比数据的精度更重要。2.2 冷站主要设备的属性清单属性清单是整个模型里最容易失控的部分。写多了没人填写少了没法算。我的经验是每类设备控制在“6 个静态属性 8 个动态属性 4 个能力属性”以内再多就是给自己挖坑。下面这张表是冷站核心设备的必备项可以直接当检查清单用。设备类静态属性铭牌/配置动态属性实时上报能力属性响应相关冷水机组额定制冷量、额定功率、最小负荷率、最短运行时间、最短停机时间、允许启停次数/小时启停状态、负载率、冷冻水出水/回水温度、功率、累计运行时长、故障码可下调容量、可上调容量、降载爬坡率、恢复时长冷冻水泵额定流量、额定扬程、额定功率、变频下限频率、台数运行状态、频率、流量、功率、进出口压差可降频幅度、对应节电功率、爬坡率冷却水泵同上另加与冷机的联锁关系运行状态、频率、流量、功率同上受冷机最小冷却水量约束冷却塔风机台数、单台功率、变频下限、出水温度设定风机状态、频率、出水温度、湿球温度可降容量、受出水温度上限约束组合式空调机组额定风量、风机功率、送风温度设定、服务区域风机频率、送风温度、回风温度、阀位、功率可降风量比例、温度越限容忍时长电动调节阀口径、流量特性、行程时间阀位反馈、指令值可关小幅度、动作时间表里最容易被忽略的是“最短运行时间”“最短停机时间”“允许启停次数”这三个。它们看着像运维参数实际上是硬约束一台冷机上报“10 分钟内可削减 200 kW”但如果它刚启动 5 分钟强制停机就要付出代价模型里没有这个约束字段平台就会给出一个物理上不该执行的调度指令。能力属性里“爬坡率”和“恢复时长”最能区分专业和不专业。爬坡率决定调度能在多短时间内把功率压下去恢复时长决定事件结束后多久能回到正常工况、会不会影响第二天的基线。这两个数字不是查手册得来的是现场实测出来的实测方法后面第 6 章会讲。2.3 从现场点表反推模型一次最小盘点的四步流程不要拿着模型规范去现场逐条对照那样一天盘不完一栋楼。实际做法是反过来先拿到现场已有的点表和系统图再往模型上映射。四步走。第一步圈出参与响应的设备清单。判别标准很简单能远程改变功率、且改变后不影响安全的设备。照明、电梯不在这个标题范围内空调系统里末端风机盘管通常也不单独列合并到区域。第二步对每台设备确认三件事——有没有通信接口、能不能远程写、写下去之后有没有反馈。这三件事决定了它在模型里是“可控设备”“可观设备”还是“虚拟设备”。只有可观不可控的设备照样要建模因为它参与基线计算。第三步把点表里的点名逐条对到属性上对不上的先标“待定”不要硬凑。我见过把冷机的“运行时间累计”硬塞进“最短运行时间”字段的结果平台算出来的可调容量全是 0。第四步用一张 Excel 或者配置表把映射关系固化下来作为模型的实例化输入。这张表后面第 4 章会给出 YAML 形态核心是每个模型属性一行写明来源协议、对象地址、缩放系数、品质位来源。固化之后换楼只改表不改代码这是能不能批量复制的分水岭。提示盘点阶段一定要拉上现场运维的人。模型里 60% 的约束条件联锁、防冻、结露、工艺要求只存在于运维师傅的脑子里规范文档上一条都没有。3. 事件、基线、可调容量需求响应侧的数据结构怎么定设备模型解决的是“我有什么”事件模型解决的是“什么时候、要我做多少、怎么算做到”。这两块必须一起设计因为它们共享同一套时间基准和状态定义。很多项目把设备模型做得很细事件侧只留了一个“目标功率”字段结果执行完了没法结算也没法复盘。3.1 事件对象必须写死的字段与取值约束事件对象是整个模型的主键载体字段少了没法算字段多了没人填。下面这 12 个字段是我认为不能省的每一条都有明确的取值约束。字段含义取值约束与常见错法事件标识全局唯一编号必须跨系统唯一不能只用自增整数否则并网后冲突事件类型削峰 / 填谷 / 紧急 / 经济紧急事件通常不参与基线结算类型必须早定通知时间平台下发时刻用 UTC 带时区偏移不要用本地时间字符串提前通知时长通知到开始的间隔单位统一为分钟且必须 ≥ 设备最短启动准备时间开始时间 / 结束时间响应窗口两个字段必须成对出现不能只给时长目标削减量期望削减的功率单位 kW保留一位小数避免精度歧义目标削减比例相对于基线的比例与目标削减量二选一作为主判据另一个作校核爬坡率要求每分钟可接受的变化量缺少这一项慢响应设备会被判违约允许中断次数窗口内可暂停次数冷机频繁启停的容忍度就靠这个字段表达基线类型与基线值结算依据类型枚举化基线值必须带计算方法标识响应等级多档位如 1~3 级等级与容量对应关系要在模型里显式声明状态待确认/已接受/执行中/已完成/已终止/违约枚举固定不允许自定义字符串表里“提前通知时长 ≥ 设备最短启动准备时间”这条约束建议做成模型校验规则而不是靠人看。冷水机组的准备时间、水泵的暖机时间、末端的预冷时间各不相同平台按最短的那个下发通知一定会有设备来不及。另一个容易漏的是“目标削减量”与“目标削减比例”的主判据问题。两者同时给且互相矛盾时现场执行会无所适从。模型里必须声明哪一个优先我的习惯是以绝对量为主判据比例只用于聚合商层面的分摊。3.2 基线算法怎么变成模型里的一个属性基线不是一个数字是一个算法加一组参数。把算法硬编码在平台里换一个地区、换一种建筑类型就得改代码。正确做法是把基线做成模型里的一个对象类型标识 计算窗口 排除规则 修正系数。常见的基线类型有三种。高 N 取平均取事件前若干天中负荷最高的几天做平均抗偶然波动相邻时段法取事件前 2~4 小时的平均功率外推对天气突变敏感回归法用历史负荷对气温、湿度做回归适合季节性变化大的地区。集中式空调的基线我倾向于用“高 N 取平均 当日气温修正”因为空调负荷和气温的相关性太强纯统计法在连续高温天会把基线压低用户白白吃亏。排除规则同样要建模。事件日、节假日、设备检修日、极端天气日要不要从基线窗口剔除必须写成显式规则否则同一份数据换个人算出来就是两个数。修正系数一般用当日最高气温与窗口内平均最高气温的差值乘以一个灵敏度系数这个系数按建筑类型标定办公类通常取 3%~5%/℃。下面这段是我常用的基线计算骨架参数全部从模型对象里读不写死。# baseline.py —— 基线计算参数来自模型中的 BaselineProfile 对象 def compute_baseline(history, profile, event_day): # history: [(date, temp_max, avg_kw), ...] 已剔除排除日 window [h for h in history if h[0] not in profile[exclude_days]] window window[-profile[window_days]:] # 取最近 N 天 top sorted(window, keylambda x: x[2], reverseTrue)[:profile[top_n]] base sum(x[2] for x in top) / len(top) # 高 N 取平均 d_temp event_day[temp_max] - sum(x[1] for x in top) / len(top) return base * (1 profile[temp_sensitivity] * d_temp)window_days一般取 10top_n取 3 到 5temp_sensitivity按建筑类型取 0.03~0.05。这三个参数在模型里是显式属性允许现场调整并留痕。改参数要记录修改人和时间否则事后结算时没人说得清当初为什么是这个基线。3.3 响应状态机与回执时序别让“已执行”变成自说自话状态机是这个模型里最像“协议”、也最容易被轻慢对待的部分。我见过太多系统状态只有“执行中”和“已完成”两个结果事件结束了平台不知道用户到底压下去没有只能靠事后读表中间这段时间全是黑匣子。完整的状态迁移应该是待确认 → 已接受或已拒绝带原因码→ 执行中 → 已恢复 → 已完成或违约。每个迁移都要有一条回执消息回执里带三个东西迁移发生的时刻、迁移时刻的实测功率、迁移的原因码。原因码至少覆盖设备故障、约束越限、人工干预、平台指令终止。“已恢复”这个状态是很多人漏掉的。需求响应事件窗口结束不等于设备立刻回到原工况。冷机重新加载、水温回落、末端温度恢复都需要时间有的要 30 分钟以上。模型里必须有一个独立的“恢复时长”属性并且在状态机里体现否则结算时按事件结束时刻的功率去比对用户明明完成了响应却因为还在恢复过程中被判定“未恢复到基线”。时序上还有一个硬要求回执时间戳一律用 UTC并在模型里声明时钟漂移容限一般要求设备侧与平台侧偏差在 1 秒以内。跨系统对时不准事件窗口就会错位错位几分钟基线比对结果能差出几十千瓦。4. 映射落地信息模型怎么挂到 Modbus / BACnet 的现场点表上模型写得再漂亮落到现场还是要面对一堆 Modbus 寄存器和 BACnet 对象。这一章讲的就是中间那层黏合剂。我的观点很明确映射关系必须是数据不能是代码。4.1 三条落地路径的取舍现场有三种典型做法各有适用边界选错了后期维护成本翻倍。路径做法适用场景主要代价原生建模现场网关直接按信息模型建模设备层就对齐新建项目控制器可编程对集成商要求高调试周期长点表转换现场保持原有协议网关做协议到模型的映射改造项目存量设备多依赖映射配置的准确性旁路计量加装独立计量与控制回路只在响应时段接入老设备无接口、不允许改动数据不完整只能做可调容量估算存量楼宇改造我一般走点表转换因为不可能为了需求响应把整栋楼的控制器换掉。原生建模适合新建一次到位后面不用维护两套语义。旁路计量是最后手段能用但要清楚它的局限拿不到设备级状态只能测总功率可调容量只能靠统计估计不能做精细调度。还有一个常被忽略的中间选项混合路径。冷站主机走点表转换末端走旁路计量站级汇总时按数据来源打标记精度高的权重高。这种做法工程上很务实模型里只要把“数据来源”和“置信度”两个属性加上就能支持。4.2 用一张配置表把模型和点表解耦映射配置的核心结构是“模型属性 ← 现场点”。一条记录描述一个属性的来源、地址、缩放、品质位来源。写成一棵 YAML 树网关启动时加载运行期只读。# model_map.yaml —— 一条记录对应一个模型属性换楼只改这张表 model: Plant01.Chiller01 # 模型实例路径与对象树一致 class: Chiller points: - attr: Availability # 可用性能否参与本次响应 source: bacnet object: AI-1 # 现场对象实例号 property: present-value quality_from: reliability # 品质位从现场对象取不自己造 - attr: CoolingOutput # 当前制冷量 source: modbus unit_id: 3 register: 40021 dtype: uint16 scale: 0.1 # 原始值 × 0.1 得到 kW offset: 0 - attr: MinLoadRatio # 最小负荷率铭牌静态参数 source: const value: 0.3 - attr: RestoreDuration # 恢复时长实测标定值单位分钟 source: const value: 25scale和offset是最容易出错的两列。Modbus 寄存器常以 0.1 为单位存温度、以 0.01 存功率漏乘一次上报的容量就差一个数量级。我的习惯是配置表里所有scale必须写全哪怕是 1.0 也写出来避免后来人以为可以省略。quality_from这一列决定了数据可信度。BACnet 对象自带 reliability 属性直接透传即可Modbus 没有品质位就要靠网关做超时判断连续 N 次读失败就把品质位打成“无效”而不是继续上报最后一次的值。这一条后面还会展开。source: const用于铭牌参数和标定值这类数据不进实时采集但必须在模型里存在。把它们和实时点混在一张表里好处是模型实例化只有一条路径不会出现“静态参数在数据库、动态参数在网关”的分裂。4.3 时间戳与品质位最容易被糊弄的两列绝大多数翻车不是因为主数据错而是因为这两列没做好。时间戳的问题是时区。现场控制器多数用本地时间而且不带时区标识到了跨时区或跨系统对接时事件窗口就对不上。我的做法是网关统一转换成 UTC 毫秒时间戳本地时间只在展示层出现。模型里每个动态属性都带自己的采样时间不是一个设备一个时间因为不同协议的采集周期不同用一个时间会把慢采样的点“变新”。品质位的问题是把“没数据”当成“数据是 0”。冷机通信断了网关读不到功率如果直接填 0平台会认为这台机组当前功率为零可调容量算出来是满的调度下发指令过去必然失败。正确做法是品质位置为“无效”模型汇总时把该设备从可用容量里剔除。品质位的取值我一般只用四个有效、无效、被闭锁、人工置数。“被闭锁”用于检修挂牌、联锁保护动作这类情况它的语义是“设备本身是好的但现在不允许动”和“无效”要区分开因为前者在容量汇总里同样要剔除但在故障统计里不算故障。“人工置数”用于调试和应急必须带有效期过期自动失效防止调试时填的值一直挂着。注意品质位不要自己发明枚举。模型里定义几种就用几种自定义字符串在跨系统交换时一定解析失败。5. 联调避坑五类翻车现象与排查顺序现场联调阶段暴露的问题八成不是模型设计错而是设计和现场之间那层“想当然”。下面五条按我遇到的频率排序每条都给出排查顺序。5.1 容量类与状态类的坑现象一平台显示可调容量 800 kW实际响应只压下去 300 kW。原因通常是把额定功率当成了可调容量。一台 500 kW 的冷机最小负荷率 30%它真正的可下调空间最多是 350 kW还要扣掉当前已经在低负载运行的部分。更隐蔽的是耦合冷机降载之后冷冻水温上升末端阀位开大水泵频率上升输配侧功率反而涨了。 解决方式是模型里强制分离“额定容量”和“当前可调容量”两组属性后者由工况实时计算并且在子系统层乘耦合修正系数。上报前做一次自检设备级可调容量之和 × 同时率 ≤ 站级历史最大功率与当前功率之差。现象二事件下发后一部分设备完全没动作平台却显示“已执行”。原因是可用性判断没串起来。设备状态里其实已经有“检修”“联锁”“故障”这些位但可用性属性是单独算的没读这些位。另一个常见原因是把“通信正常”等同于“可控”其实有些点表只读不写写下去返回成功但设备不动。 解决方式是可用性做成一个复合判断通信品质有效 AND 无故障 AND 未挂牌 AND 该点可写 AND 满足最短运行时间约束。五条全过才算可用。联调时逐个设备人为制造一个不满足条件看可用性有没有正确翻转这是必做的验证动作。5.2 时序类与工程类的坑现象三事件窗口结束平台判定恢复超时用户申诉。原因是把“事件结束时间”和“恢复完成时间”混成一个字段。事件窗口只管到结束时刻恢复是窗口之后的事模型里必须有独立的恢复时长和恢复完成状态。还有一个变种恢复时长填的是设计值不是实测值实测往往长得多。 解决方式是恢复时长按设备类型分别标定并定期复测冷机 20~40 分钟、水泵 5~10 分钟差异很大。状态机里加“已恢复”节点回执带实测功率结算时按恢复完成时刻的功率比对而不是事件结束时刻。现象四事件窗口整体偏移半小时基线比对全乱。原因是时间戳没统一。现场控制器用本地时间且不标时区网关直接透传平台按 UTC 解析刚好差一个时区偏移。夏令时切换那天会更乱。 解决方式是全链路统一 UTC网关做一次转换模型里每个时间戳带时区偏移字段平台入库前做一致性校验事件开始时间必须晚于通知时间结束时间必须晚于开始时间任何一条不满足直接拒收并告警。现象五换一栋楼就要改一次网关代码。原因是映射硬编码。第一栋楼为了赶工期把寄存器地址写进代码第二栋楼地址一变就得重新编译发版。 解决方式是从项目第一天就用配置表驱动代码里只保留“读取配置 → 建实例 → 周期采集”三段逻辑。这件事没有技术难度纯粹是工程纪律问题但决定了这套方案能不能复制到第十栋楼。排查顺序我固定为先查时间戳再查品质位再查可用性最后查容量计算。因为前三类是“硬错”能快速排除容量类是“软错”要对着曲线一点点看。6. 上线前用历史数据回放把模型的可信度验一遍模型和现场对上之后别急着接真实事件。我的习惯是先做一个回放沙盘拿过去 30 天的历史数据人为构造几个需求响应事件让模型走一遍完整流程看申报值和实测值的偏差。这个过程不花钱但能提前暴露大部分逻辑错误。6.1 一个最小回放沙盘怎么做输入三样东西历史功率与温度曲线15 分钟粒度够用、设备状态日志、映射好的模型实例。输出两样模型在事件时刻给出的可调容量申报值以及从历史数据里“真实”能压下去的量。两者一比偏差就出来了。# replay.py —— 用历史数据回放一次事件比对申报容量与可实现容量 def replay(model, hist, event): t0 event[start] declared model.declared_capacity(t0) # 模型申报的可调容量 base model.baseline(t0) # 同一套基线算法 actual base - min(p for t, p in hist if t0 t event[end]) # 实际最低功率 return { declared_kw: declared, achievable_kw: actual, error_ratio: (declared - actual) / max(actual, 1e-6), }declared_capacity直接调模型接口不要另写一套算法否则验的不是线上那套逻辑。回放窗口建议覆盖三种天气连续高温、阴雨、气温骤降因为空调负荷的响应特性和天气强相关只回放晴天数据会高估能力。6.2 三个验收指标与阈值回放跑完看三个数。第一是容量申报偏差率我要求绝对值控制在 20% 以内超过就说明耦合修正系数或最小负荷率标定有问题。第二是事件执行率即可用设备在窗口内实际参与响应的比例低于 90% 要逐台查可用性判断。第三是恢复时长偏差实测恢复时间与模型标定值之差超过 50% 就要重标。这三个数不是一次达标就完了季节切换、设备大修、末端改造之后都要重跑。我吃过一次亏春天标定的耦合系数到七月连续高温时完全不准申报容量虚高四成第一次真实事件就被判了部分违约。从那以后我把回放做成了季度例行动作比任何文档都管用。再往前一步是聚合。单栋楼的模型跑顺了多栋楼往上汇总时会遇到同时率、响应速度差异、基线口径不一致三个新问题。我的建议是先把单体的三个指标稳定住再谈聚合否则聚合层算出来的数字只是把误差放大了。这个方向值得做因为集中式空调是目前用户侧少数几个既有量、又相对可测、还能连续调节的资源类型模型做扎实了后面的调度和结算才有基础。希望帮到你。本文还有配套的精品资源点击获取