ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

DLMS/COSEM 蓝皮书解读(三):Register 类(class_id = 3)—— 给数值装上“量纲“

DLMS/COSEM 蓝皮书解读(三):Register 类(class_id = 3)—— 给数值装上“量纲“ DLMS/COSEM 蓝皮书解读三Register 类class_id 3—— 给数值装上量纲系列说明本系列基于 DLMS User Association《Blue Book蓝皮书第 16 版 · 第 2 部分 —— COSEM interface classes》按一个接口类一篇的节奏展开。第 1 篇建立协议与文档框架第 2 篇讲了最简单的Dataclass_id 1。从本篇起进入真正干活的类。上篇回顾Data只有两个属性 ——logical_namevalue它能装任何东西但不知道自己装的是什么单位。本篇的Register就是要解决这件事它多了一个scaler_unit属性让一个数字变成1 234,5 Wh这样有明确物理含义的量。0. 为什么必须要有 Register光用 Data 不行吗先把问题想清楚。假设主站从表里读到一个数12345。它是多少度电1.2345 kWh12.345 kWh还是 12345 Wh它是什么量电能功率电压Data类回答不了这两个问题 —— 它没有地方放单位和小数点位置。所以工程上会出现非常尴尬的局面主站必须在代码里硬编码这块表的 1-0:1.8.0 是小数值 2 位换一款表、换一家厂商就得改一次代码。Register的设计就是把这个隐含约定显式化蓝皮书原文Register, Overview“This IC allows modelling a process or a status value with its associated scaler and unit. ‘Register’ objects know the nature of the process or status value.”翻译过来就是Register 对象知道自己装的值是什么性质—— 因为量纲unit和缩放scaler就写在对象里主站读出来即可自行换算不需要外部约定。一句话定位Register带量纲的数值容器。凡是要表示多少 kWh / 多少 W / 多少 V / 多少 m³的地方基本都是它。1. 类蓝图Register 0...n class_id 3, version 00...n是基数cardinality意思是一台设备里可以有任意多个Register实例正向有功、反向有功、费率 1、费率 2…也可以是 0 个。属性静态/动态数据类型Short namelogical_name(static)octet-stringxvalue原文未标 static即动态CHOICEx 0x08scaler_unit(static)scal_unit_typex 0x10方法必选/可选(m/o)Short namereset (data)o可选x 0x28注原文中value行没有标(static)按蓝皮书惯例未标 static 的属性即为动态dyn.属性 —— 电能值当然会变。reset标o optional不是所有表都实现主站调用前应先确认这也是很多复位失败工单的根源。2. 属性逐条解读2.1logical_namestatic, octet-string对象的身份证6 字节OBIS编码。上篇已讲过格式A-B:C.D.E。Register最典型的几个 OBIS这些都是行业惯例值OBIS含义典型 unit1-0:1.8.0正向有功总电能AWh301-0:2.8.0反向有功总电能−AWh301-0:1.8.1费率 1 正向有功电能Wh301-0:1.8.2费率 2 正向有功电能Wh301-0:15.7.0总有功功率瞬时W272.2valueCHOICE—— 一张数据类型母表蓝皮书给value的是一个CHOICE也就是可以是下列任意一种类型。原文列出的完整清单CHOICE { -- simple data types null-data [0], bit-string [4], double-long [5], double-long-unsigned [6], octet-string [9], visible-string [10], utf8-string [12], integer [15], long [16], unsigned [17], long-unsigned [18], long64 [20], long64-unsigned [21], enum [22], float32 [23], float64 [24], }方括号里是A-XDR 编码时的 tag。工程上最常见的三种long-unsigned [18]/double-long-unsigned [6]累计电量最常用integer [15]/long [16]可正可负的量如功率方向、需量enum [22]状态类数值蓝皮书特别强调了一句选择原则“The data type of the value depends on the instantiation defined by logical_name and possibly on the choice of the manufacturer. It has to be chosen so that, together with the logical_name, an unambiguous interpretation of the value is possible.”解读value的类型由logical_name这个对象是什么决定厂商有一定自由度但必须保证类型 logical_name能唯一定值含义。这也解释了为什么主站不能假设所有 Register 的 value 都是 long-unsigned—— 得按对象来。2.3scaler_unitstatic, scal_unit_type—— 本篇的核心scal_unit_type :: structure { scaler, -- integer unit -- enum }一个两元素的 structure两个字段分工明确scalerinteger有符号“This is the exponent (to the base of 10) of the multiplication factor.”即真值 value × 10^scaler。scaler 0→ 原值scaler 3→ ×1000scaler -2→ ÷100还有一条容易漏的约束“REMARK: If the value is not numerical, then the scaler shall be set to 0.”如果 value 不是数值比如字符串scaler 必须设 0。unitenum蓝皮书给了一张很长的物理单位枚举表Table — Enumerated values for physical units从 1 到 255。常用的一段unit符号物理量SI 定义5htime / hour60*60 s7stime / seconds9°CtemperatureK−273.1513m³volumem³27Wactive power §W Js⁻¹28VAapparent power (S)volt-ampere29varreactive power (Q)var30Whactive energyWs*(60*60)31VAhapparent energyVAs*(60*60)32varhreactive energyvar s*(60*60)33Acurrent (I)ampere35Vvoltage (U)volt44Hzfrequencys⁻¹253—extended table of units—254otherother unit—255countno unit, unitless, count—表中unit 255 (count)非常重要 —— 它表示无单位 / 计数是Register退化成Data的钥匙见示例 3。另外单位 16 与 18corrected volume已被弃用deprecated因为 OBIS 码本身已经指明了是否为修正体积避免与 OBIS 矛盾。3. 方法reset (data)reset (data) data :: integer (0)“Forces a reset of the object. By invoking this method, the value is set to the default value. The default value is an instance specific constant.”要点调用后value被置为默认值这个默认值是实例特定的常量instance specific constant不是 0也不是由这个方法传入的。data固定是integer (0)—— 只是占位参数没有实际语义。它是o可选方法且通常需要较高的安全级别写权限实操中常被拒绝。4. 【实战举例】示例 1读正向有功总电能的完整动作假设要读1-0:1.8.0的当前值。正确做法是先读量纲再读值顺序很重要# 第 1 步读 scaler_unitattribute 3 GET (class_id3, logical_name1-0:1.8.0, attribute_index3) → 返回 structure { scaler -1, unit 30 } # unit 30 Wh # 第 2 步读 valueattribute 2 GET (class_id3, logical_name1-0:1.8.0, attribute_index2) → 返回 12345 # long-unsigned # 第 3 步主站换算 真值 12345 × 10^(-1) 1234.5 Wh 1.2345 kWh如果跳过第 1 步、直接假定 scaler 0就会得到 12345 Wh 12.345 kWh ——差了 10 倍。这是 DLMS 集成里最经典的事故之一。实践建议scaler_unit是(static)属性一次会话内读一次即可缓存不必每次读值都重读。示例 2蓝皮书官方给的换算示例直接抄作业蓝皮书Table — Examples for scaler_unit给了 5 个例子我原样搬过来ValueScalerUnit实际数据263788−3m³263,788 m³5933Wh593 kWh3467−1V346,7 V34670V3467 V34671V34 670 V注意第 2 行value 593、scaler 3、unit Wh→ 593 × 10³ 593 000 Wh 593 kWh。也就是说表里存的整数很小靠 scaler 撑起量级—— 这是为了在寄存器位宽有限时仍能表示大电量。示例 3什么时候 Register 可以当 Data 用蓝皮书明确给了口子“When a ‘Register’ object is used instead of a ‘Data’ object, (with the scaler_unit attribute not used or with scaler 0, unit 255) then the data types allowed for the value attribute of the ‘Data’ IC are allowed.”即当scaler 0且unit 255 (count)时Register就等价于一个无量纲容器此时value可以用Data类允许的全部数据类型。什么时候这么干比如某厂商为了保证整表对象模型统一全是 Register把仪表常数脉冲常数这类无量纲参数也做成Register实例此时就会看到scaler_unit {0, 255}。主站看到unit 255就应该不做任何换算。示例 4用 SN短名寻址时SN 方式下不看属性名而是用基名 偏移。Register的三个属性偏移是属性Short namelogical_namexvaluex 0x08scaler_unitx 0x10方法resetx 0x28所以读值就是读x 0x08这个 13 位短名。对比Data类value也是x 0x08—— 两者前两个属性偏移完全一致区别只在Register多出来的x 0x10scaler_unit。示例 5电压 / 电流 / 功率各用什么 unit一个三相表常见的一组Register实例量纲配置大致是OBIS量value 类型scaler_unit1-0:32.7.0电压 L1瞬时long-unsigned{0, 35}→ V或{-1, 35}→ 346,7 V1-0:31.7.0电流 L1瞬时long-unsigned{-1, 33}→ A1-0:15.7.0总有功功率integer{0, 27}→ W1-0:1.8.0正向有功总电能double-long-unsigned{-1, 30}→ Wh提示电压用{-1, 35}表示一位小数346,7 V是很多表的实际做法 —— 这正是 scaler 存在的意义用整数传输小数。具体 scaler 取值由厂商决定主站必须读scaler_unit而不能猜。5. 工程上容易踩的坑硬编码 scaler最大的坑。换表、换固件后 scaler 可能变化必须每次从scaler_unit读。unit与 OBIS 冲突蓝皮书已把 corrected volume16/18标为 deprecated就是为了防止 OBIS 说修正体积、unit 又说工况体积这种自相矛盾。建模时要让 unit 与 OBIS 语义一致。以为reset一定可用它是o可选。而且默认值是实例特定的未必是 0 —— 不能假设复位后读到的就是 0。非数值 value 忘了把 scaler 置 0违反 REMARK 约束会让主站误做量纲换算。把Register和Data混用导致模型不统一判断标准很简单 ——这个量有没有物理单位有 →Register没有序列号、固件版本、开关标志→Data。6. 小结 下期预告本篇要点Registerclass_id 3是带量纲的数值容器靠scaler_unit {scaler, unit}把一个裸整数变成1 234,5 Wh真值 value × 10^scaler换算必须读scaler_unit不能硬编码value是 CHOICE16 种类型可选类型由logical_name决定scaler 0unit 255 (count)时Register可当作Data用reset是可选方法复位到实例特定的默认值不是 0。下一篇第 4 篇Extended registerclass_id 4。它在Register基础上又加了两个属性 ——status数据状态和capture_time这个值是什么时刻采下来的。如果你遇到过读到的电量到底是哪一时刻的这条数据有没有被篡改/溢出这类问题下一篇就是答案。我们还会把Data / Register / Extended register / Demand register四个寄存器兄弟放在一起做一次横向对比。参考资料DLMS UA《Blue Book Ed.16 Part 2 – COSEM interface classes》Register (class_id 3, version 0) 章节含 Table “Enumerated values for physical units” 与 Table “Examples for scaler_unit”。文中所有属性、数据类型、Short name 偏移、方法与示例数值均与该章节原文一致。
返回列表