简介:T/CEC 239.1—2019《电力需求响应信息模型 第1部分:集中式空调系统》是中国电力企业联合会发布的行业标准,面向集中式空调自动需求响应终端与接口的设计开发人员,以及参与电网负荷调度的科研与工程技术人员。标准规定了建模原则、数据类型、通用包与专用包,并附需求响应能力计算方法,为大型建筑空调系统参与削峰填谷提供统一的信息模型框架。资源包共1个PDF文件,约396KB,内容涵盖范围、规范性引用文件、术语定义、建模原则、数据类型、通用包、专用包及资料性附录,目录结构完整,便于按章节查阅。已有306人学习下载。读者可据此理解空调负荷可调度数据的组织方式,掌握终端与接口建模的通用与专用模块划分,并借助附录方法评估需求响应潜力,对分散式空调、电热水器等同类负荷建模亦有参考价值。
1. 集中式空调凭什么能当“虚拟电厂”:一份信息模型标准真正解决的是什么
一栋写字楼里的集中式空调,主机、冷冻泵、冷却泵、冷却塔风机加起来动辄几百千瓦,占整栋楼用电负荷的四成以上。电网调度员盯着这条曲线会想:如果高峰时段能让它少用一点,是不是就等于多建了一座小电厂?但真去调的时候,问题立刻冒出来——不同品牌的主机、不同厂家的水泵、不同年代的楼控系统,各自说各自的话,功率、温度、状态这些量连单位都不统一,调度主站根本没法“看懂”一台空调现在能不能降、能降多少、降多久。T/CEC 239.1—2019 这份《电力需求响应信息模型 第1部分:集中式空调系统》要解决的,正是这个“看不懂”的问题:它不规定空调怎么造,而是规定一台集中式空调在参与需求响应时,应该用什么样的信息类、属性和数据类型把自己描述清楚,让自动需求响应终端和接口能按同一套语义去读、去控、去算。搞懂这套建模逻辑,你才能明白为什么需求响应不是“发个指令关设备”这么简单,而是一场关于语义对齐的工程。
2. 建模原则:为什么先定“怎么描述”而不是“怎么控制”
2.1 四条原则背后的取舍:实用性压过完备性
标准第4章只给了四条原则——实用性、便捷性、适用性、扩展性。看起来像套话,但每一条都在约束后面的建模动作。实用性要求模型能直接支撑自动需求响应终端和接口的设计开发,意思是模型不能是学术本体论,必须能落到报文和字段上;便捷性要求建模所需参数便于获得,这解释了为什么大量属性被标成“可选项”——现场拿不到的量就不强制填,否则终端厂商会因为缺一个出厂编号而无法通过一致性检查;适用性要求覆盖主流品牌集中式空调的技术参数,所以模型里出现了水冷、风冷、多联机三种机型枚举,而不是只按某一家主机的私有协议建模;扩展性则体现在几乎每个枚举类型都留了x-{ User-defined }这个口子。
这四条原则合在一起,其实做了一个很现实的取舍:宁可少描述一点,也要保证描述出来的东西现场能采到、主站能解析。常见的实现思路是,把“必须有的”压到最小集合(设备ID、用户编号、额定功率、实时功率、可削减功率),把“锦上添花”的全部设为可选,这样不同自动化水平的楼宇都能接入,而不是只有新建的高端楼宇才能玩需求响应。
2.2 信息类、包、类间关系:三个词撑起整个模型骨架
标准第3章给了几个定义,值得逐字读。信息模型是“描述需求响应业务涉及的对象,由描述对象的信息类及其关联关系构成”;信息类是“由一组描述对象特性的属性构成”;包是“由一组相同类型的信息类及信息类的关联关系构成”。这三层是递进的:属性组成类,类加关系组成包,包组成模型。
为什么要有“包”这一层?因为集中式空调系统涉及的对象太多——设备本身、设备所属用户、用户签的合约、设备的自动化能力、实时运行数据、温湿度参数、需求响应能力。如果全部平铺成几十个类,终端开发者很难判断哪些是通用能力、哪些是空调专有。标准用“通用包”和“专用包”做了切分:通用包里的设备出厂信息、用户信息、自动化能力、合约信息,理论上电热水器、电动汽车也能复用;专用包才是集中式空调特有的工作模式、机型、部件额定参数、实时信息和需求响应能力。这种切分方式在工程上很实用,做终端固件时通用包可以做成公共库,专用包按设备类型插拔。
类间关系在标准里出现得不多,但有一处很关键:UserDRContract和DRProgramme之间的关联,起始端[1..1]、目标端[0..n],意思是“一份合约对应零到多个需求响应项目类型”。这个基数约束直接决定了主站侧的数据结构——一个用户可能同时签了分时电价和可中断响应,终端上报合约信息时项目类型是个列表而不是单值。如果实现时按单值处理,遇到多项目用户就会丢数据,这是后面避坑章节要展开的一个典型翻车点。
3. 数据类型层:为什么功率要带 unit 和 multiplier 两个字段
3.1 基本型与量测型的分离:Float 不够用
标准第5章列了整型、字符串、浮点、布尔、日期时间、持续时间六个基本型,然后从 5.8 开始一口气定义了电压、电流、频率、视在功率、有功功率、有功电能、无功功率、温度、比热容、热阻、压力、容积、密度、流量、风速、光照强度、热值、转速共十八个量测型。每个量测型的结构几乎一模一样:value是 Float,unit是带常量约束的 UnitSymbol,multiplier是 UnitMultiplier。
为什么不直接用 Float 加一个字符串单位?因为字符串单位没法做机器校验。unit=V(const)这个写法表示该字段的取值被常量约束为伏特,解析方看到 Voltage 类型就知道 value 一定是伏特数,不需要再猜。multiplier则解决量纲缩放:同样是有功功率,主机额定功率可能是 350 kW,末端风机可能是 0.75 kW,如果统一用瓦特,前者是 350000,后者是 0.75,数值跨度大且容易在整型转换时溢出。用multiplier=k表示千,value 填 350,既保留精度又压缩数值范围。
# 按标准第5章构造一个带乘数的有功功率值 # ActivePower: value(Float) + unit=W(const) + multiplier(UnitMultiplier) def make_active_power(value_watt: float) -> dict: # 大于等于 1000 W 时切换到千瓦,避免大数值 if abs(value_watt) >= 1000: return { "value": value_watt / 1000.0, "unit": "W", # 单位常量仍是瓦特 "multiplier": "k" # 乘数表示千 } return { "value": value_watt, "unit": "W", "multiplier": None # 无乘数,按原值解释 }这段代码的关键不在除法,而在语义:unit永远是 W,multiplier才是缩放因子,解析方必须做value × multiplier系数才能还原真实瓦特数。如果实现时把multiplier当成单位的一部分拼字符串(比如拼成 “kW” 再解析),遇到m(毫)和M(兆)这种大小写敏感的字面量就会解析错。标准表20 里m是千分之一、M是兆,一个字母大小写差九个数量级,这是量测型设计里最容易被忽视的细节。
3.2 枚举型的扩展位:x-{ User-defined } 是逃生舱不是垃圾桶
标准里几乎每个枚举都带x-{ User-defined },包括用户类型、通信方式、需求响应协议、底层通信协议、需求响应项目、控制方式、故障状态、工作模式、运行状态、机型、部件类型。这个设计动机很直白:标准制定时不可能穷举所有厂商的私有能力,留一个自定义前缀让厂商扩展,同时保证标准枚举值不被污染。
但扩展位在工程上有个隐含契约:自定义值必须以x-开头,且接收方遇到不认识的x-值不能直接报错丢弃,而应该降级处理。比如某主机上报工作模式为x-DryMode(除湿),主站不认识这个值,正确做法是把它归入“未知工作模式”继续处理其他字段,而不是整条报文拒收。常见的实现思路是在解析层做白名单加前缀判断:标准值走严格校验,x-开头走宽松透传。如果实现时把枚举当封闭集合做 switch 且没有 default 分支,新机型一接入就会触发解析异常,这是互操作性测试里高频出现的故障。
4. 通用包与专用包:设备能力怎么被拆成可查询的字段
4.1 EQAutoAbilityInfo:一台空调“能不能被调”的四个布尔量
通用包里的设备自动化能力信息类(EQAutoAbilityInfo)是整个需求响应可行性的第一道筛子。它用四个布尔量加三个枚举回答一个问题:这台设备具备什么样的被控能力。ComAbility表示能否与外界通信;On-OffAbility表示是否支持刚性控制(开/关);Flexability表示是否支持柔性调节(功率连续可调);ThirdPartyPlatform表示是否已连第三方主站平台。通信方式和协议则分别由ComMode、DRProtocol、UnderlyingProtocol描述。
这四个布尔量的组合直接决定调度策略。只有On-OffAbility为 true 的设备,需求响应时只能整机启停,可削减功率是阶跃的;Flexability为 true 的设备才能做功率跟随,按主站下发的目标功率连续调节。ThirdPartyPlatform为 true 则意味着存在中间层,主站指令可能要经过第三方平台转发,时延和可靠性都要打折。建模时把这四个能力拆成独立字段而不是一个综合等级,好处是主站可以按位组合筛选——比如“找所有支持柔性调节且不经过第三方平台的设备”就是一次布尔与运算,不需要理解厂商私有的能力编码。
4.2 RatedParameter 与 ACComponentRatedParameter:整机参数和部件参数为什么分开
专用包里有两个容易混淆的类。RatedParameter描述整机层面:机型(水冷/风冷/多联机)、制冷采暖面积、平均层高、制热能效比 COP、制冷能效比 EER、建筑物能量损失系数。ACComponentRatedParameter描述部件层面:部件类型(主机、冷冻泵、冷却泵)、数量、额定电流、额定电压、额定功率、额定频率、主机负荷率限定值。
分开的理由在附录A 的计算公式里能看出来。可削减功率的计算用的是整机参数——面积 S、层高 H、COP/EER、室内外温差,这些是建筑和主机级别的量;而实际执行削减时,调度要落到具体部件上,比如停一台冷却泵、把主机负荷率压到限定值以下,这就需要部件级的额定功率和负荷率限定值。如果只建整机参数,主站知道“这栋楼能削 200 kW”,但不知道怎么削;如果只建部件参数,主站知道“每台泵 30 kW”,但算不出建筑热惯性允许削多久。两个类配合,才能既算得出能力又落得到执行。
提示:
ACComponentRatedParameter里的LoadRateLimit是可选字段,但它往往是柔性调节的安全边界。实现时如果该字段缺失,不要默认按 100% 处理,而应按厂商文档或现场调试值保守设定,否则功率下调指令可能触发主机保护停机。
4.3 RealTimeInfo 与 TRHParameter:实时电气量和热工量为什么要分两个类
RealTimeInfo装的是电气量:实时电压、电流、频率、总有功功率、总无功功率、主机负载率。TRHParameter装的是热工量:目标温度、室内平均温度、室内相对湿度、室外平均温度、室外相对湿度,以及冷凝器、蒸发器、采暖水的进出口温度。分两个类的设计动机是采样频率和来源不同——电气量来自电表或终端采集,秒级刷新;热工量来自楼控或温湿度传感器,分钟级刷新,且部分点位(如冷凝器进出口温度)只有部分机型提供,所以标了可选。
这个切分对终端实现的直接影响是数据缓存策略:电气量需要环形缓冲区支撑功率曲线和需求响应基线计算,热工量只需要保留最新值和少量历史用于趋势判断。如果把两类混在一个结构里按同一频率轮询,要么电气量采样不足,要么热工量通道被无效刷新拖垮。常见的实现思路是两条独立采集任务,通过时间戳对齐后组装成完整信息类再上报。
5. 需求响应能力计算:附录A 的公式为什么长这样
5.1 从热平衡出发:可削减功率的本质是“允许室温漂移多少”
附录A 给的公式看起来复杂,拆开看就是一个热平衡等式。以制冷工况 A.3 为例:
P_DR,decreased × t_DR = (ρ × c × S × H × (T_limit − T_set)) / EER左边是“少用的电能”,右边是“建筑物允许吸收的热量除以能效比”。ρ 是空气密度 1.177 kg/m³,c 是定压比热容 1.005 kJ/(kg·K),S 是制冷面积,H 是平均层高,三者相乘得到室内空气的总热容;再乘以允许温升(T_limit − T_set),得到建筑物在不超温前提下能“存”多少热量;除以 EER 换算成电功率。等式隐含的假设是:需求响应期间空调制冷量降为零或降低,室内温度从设定值缓慢漂移到用户可承受的上限,漂移过程吸收的热量正好等于少制的冷量。
这个公式的价值在于它把“能削多少”和“能削多久”绑成了一个乘积关系。持续时间 t_DR 确定时,最大可削减功率就能反解出来;反过来,削减功率确定时,持续时间也有上限。主站下发指令时如果只给功率不给时长,终端就没法判断这个功率是否可持续,可能削了五分钟就触顶反弹。所以DRAbility类里IncreasedPower、DecreasedPower、TimeDuration三个属性必须一起看,单独一个数没有工程意义。
5.2 制热与制冷的符号差异:为什么 A.1 和 A.3 的温差方向相反
制热工况 A.1 的温差是(T_set − T_limit),T_limit 是用户允许的最低室温,低于设定值;制冷工况 A.3 的温差是(T_limit − T_set),T_limit 是允许的最高室温,高于设定值。两式都保证温差为正,但物理含义相反:制热时室温允许往下漂,制冷时允许往上漂。A.2 计算可增加功率时,制热工况用(T_limit − T_set),T_limit 是允许的最高室温,对应“多制热把室温往上顶”的能力。
实现时最容易翻车的地方是温度单位。公式里 c 和 ρ 取的是 300K 附近的物性值,但 T_set 和 T_limit 在TRHParameter里是摄氏度(unit=degC)。温差用摄氏度差值计算时数值上等于开尔文差值,所以不需要转换;但如果实现时先把摄氏度转成开尔文再相减,结果一样,只是多了一步无意义运算。真正要小心的是LossFactor(建筑物能量损失系数,单位 KJ/min)在公式里没有出现——它描述的是稳态漏热,而附录A 的假设是响应前系统已处于平稳运行、制热量与建筑物热耗匹配,所以漏热已经被稳态运行抵消掉了。如果现场建筑保温极差,这个假设不成立,公式算出的可削减功率会偏乐观,需要按 LossFactor 做修正。标准把它列为整机参数而不是公式项,是留给实现方按实际工况决定是否引入修正。
6. 避坑与排查:信息模型落地时的五个高频翻车点
6.1 枚举扩展值被当成非法值拒收
现象:新接入一批支持除湿模式的主机,主站日志里大量报文解析失败,其他字段正常的设备也掉线。原因:终端或主站把WorkModeType当封闭枚举做严格校验,遇到x-DryMode直接抛异常并丢弃整条报文。解决:解析层对x-前缀值走透传分支,未知枚举值映射为“未知/其他”继续处理其余字段,同时在日志里记录原始字面量供后续扩展。
6.2 multiplier 大小写混淆导致功率差三个数量级
现象:某台设备上报有功功率 350,主站显示 350 W,实际应为 350 kW,需求响应能力计算完全失真。原因:实现方把multiplier的k和M当成不区分大小写处理,或者把m(毫)误读为M(兆)。解决:UnitMultiplier严格按表20 字面量做大小写敏感匹配,解析函数里对m/c/d/k/M/G建显式映射表,禁止用lower()归一化。
6.3 UserDRContract 按单项目类型建模丢数据
现象:同时签了分时电价和可中断响应的用户,主站只看到一种项目类型,另一种合约信息丢失。原因:UserDRContract与DRProgramme的关联是[1..1]到[0..n],实现时把项目类型字段做成了单值枚举而不是列表。解决:合约信息类里项目类型用数组承载,序列化时即使只有一个元素也输出数组结构,避免后续扩展时改协议。
6.4 可削减功率脱离持续时间单独下发
现象:主站按DecreasedPower下发削减指令,空调运行几分钟后室温触顶,主机保护性停机,削减量骤降为零。原因:DRAbility的三个属性被拆开使用,调度侧只取了功率值,没有按附录A 的乘积关系校验持续时间。解决:能力上报和指令下发都把功率与时长作为二元组处理,终端侧在本地按热平衡公式做可持续性预判,超出能力范围时回执拒绝而不是硬执行。
6.5 部件额定参数缺失时默认满负荷
现象:柔性调节指令把主机负荷率压到很低,主机频繁启停,能效反而下降。原因:ACComponentRatedParameter的LoadRateLimit是可选字段,实现时缺失就按 100% 处理,没有考虑主机最低负荷限制。解决:该字段缺失时按机型查厂商默认下限(常见水冷主机最低负荷率在 30% 左右),并在终端配置里留人工覆盖入口,调试时用实测数据校准。
7. 从这份模型看标准建模的边界感:描述能力不等于控制能力
把这份标准读完,最值得琢磨的不是它定义了多少个类,而是它刻意没定义什么。它定义了DRAbility里的可增加/可削减功率和持续时间,但没有定义主站怎么下发指令、终端怎么执行、执行失败怎么回滚——那些属于 DL/T 1867-2018 信息交换规范和具体终端协议的事。它定义了EQAutoAbilityInfo里的能力布尔量,但没有定义能力等级评分,因为评分是调度策略,不是设备属性。这种“只描述对象、不规定行为”的边界感,是信息模型类标准能跨厂商复用的前提:一旦把控制逻辑写进模型,模型就绑定了某一种调度算法,扩展性立刻消失。
但边界感也带来代价。附录A 的计算公式是资料性附录而非规范性条款,意味着不同实现方对“平稳运行状态”的判定、对 LossFactor 是否引入修正、对 T_limit 取用户设定还是建筑规范上限,都可能做出不同选择,算出来的可削减功率不具备严格可比性。这在需求响应聚合场景下是个真实问题:同一栋楼,不同终端厂商上报的能力值可能差一截,聚合商做容量申报时只能取保守值。我一般会这么理解:这份模型解决的是“语义互通”,不是“数值一致”,后者要靠一致性测试和现场校准来补。
如果要验证一个实现是否符合这份模型的精神,我会做三件事:拿一台支持柔性调节的主机,检查EQAutoAbilityInfo的四个布尔量是否与实测能力一致;构造一个多项目合约用户,看UserDRContract序列化后项目类型是不是列表;按附录A 公式手算一遍可削减功率,再和终端上报的DRAbility对比,偏差超过 20% 就回去查multiplier和温度单位。这套检查做完,基本能筛掉大部分“字段填了但语义错了”的实现。从那以后我每次对接新的需求响应终端,都强制先跑一遍这三个验证再谈联调,省下来的排查时间远比写验证脚本多。希望帮到你。
本文还有配套的精品资源,点击获取