☰
DLMS/COSEM 蓝皮书解读(十五):Image transfer 类(class_id = 18)—— 远程升级(OTA)在 COSEM 里的完整建模:分块传输 → 校验 → 激活
2026/10/2 8:22:04 网站建设 项目流程

DLMS/COSEM 蓝皮书解读(十五):Image transfer 类(class_id = 18)—— 远程升级(OTA)在 COSEM 里的完整建模:分块传输 → 校验 → 激活

系列说明:本系列基于 DLMS UA《Blue Book(蓝皮书)第 16 版 · 第 2 部分 —— COSEM interface classes》,一个接口类一篇。第 14 篇讲了SAP assignment(class_id = 17),它解决的是"一台物理设备里的多个逻辑设备分别挂在哪个 SAP 上"——本质上还是"数据在哪"。本篇的Image transfer(class_id = 18)解决的是一件性质完全不同的事:固件 / 二进制文件(Image)如何远程传到表计里,也就是"远程升级"在 COSEM 里怎么建模。这也是本系列到目前为止第一个带完整业务流程的类:前 14 篇讲的都是"读一个数、写一张表、建一次连接",而Image transfer第一次把"分块传输 → 校验 → 激活"这样一条有状态、有顺序、有失败分支的多步流程塞进了一个接口类里。

上篇回顾:SAP assignment只有 2 个 attribute + 1 个o(可选)method,是典型的静态配置表——读一次就知道全局。本篇的Image transfer气质完全相反:7 个 attribute、4 个全部为m(mandatory)的 method,且属性之间强时序耦合——image_transfer_status是一个 8 态enum,image_transferred_blocks_status是一张会随传输进度动态增长的bit-string位图。从本篇起,我们要读的不再是"一张表",而是"一台状态机"。


0. 为什么需要 Image transfer:远程升级到底难在哪

一块表装到现场十几年不换,但固件要改:修 bug、换费率算法、补安全漏洞、适配新规约。派人拆表刷固件的成本在多数项目里不可接受,所以必须有 OTA。那为什么不能直接"把文件SET进去"?

困难具体表现
内存不够表计 RAM 常只有几十 KB,固件 Image 动辄几百 KB,服务器无法整包缓冲
链路不可靠HDLC 帧长有限、PLC 丢包、GPRS 断线。传大文件必然中途失败
帧长受限一次ACTION能带的数据受ServerMaxReceivePduSize约束,超了直接被拒
失败代价极高写坏就是"变砖",现场只能换表。升级失败成本远高于抄表失败
批量一次升级常是几万、几十万台,逐个点对点传带宽不够(所以有 broadcast)
要可确认主站必须知道"传完没"“哪块没到”“校验过没”“激活成功没”

这六条直接决定了本类的建模方式:

蓝皮书原文(Image transfer, General):
“Instances of the Image transfer IC model the process of transferring binary files, called Images to COSEM servers.”

蓝皮书原文(Image transfer, Overview):
“This IC allows provides the attributes and methods with which to model the image transfer process.”

注意措辞:model theprocess(建模"过程"),不是 model the file。这是全篇的钥匙——这个类建模的是一条流程,不是一个文件容器(第二条引文原文语法作 “allows provides”,照录未改)。

0.1 为什么必须分块:三个硬约束

  1. 内存约束:Step 2 要求服务器预留空间——“The server shall make sufficient memory space available to accommodate the Image.”但"预留"不等于能整包缓冲;分块让服务器边收边写。
  2. PDU 约束:“ImageBlockSize shall not exceed the ServerMaxReceivePduSize negotiated.”块大小不能超过 AA 阶段协商的 PDU 上限。
  3. 断点续传:只有分块,"哪块到了、哪块没到"才能被精确表达——这正是image_transferred_blocks_status(位图)与image_first_not_transferred_block_number(首个缺口)存在的理由。整包传输中断一次就得从 0 开始,几百 KB 在 PLC 上可能永远传不完。

一句话定位:>Image transfer=带状态机的固件传输管道——把"传文件"拆成initiate → block_transfer ×N → verify → activate,用一张位图记进度、一个 8 态enum记状态,让不可靠链路上的大文件传输变得可中断、可续传、可校验、可确认。


1. 类蓝图

Image transfer 0…n class_id = 18, version = 0

0…n是基数(cardinality):一台设备里可有任意多个实例(表计本体固件、通信模块固件、M-Bus 从设备各一个),也可以是 0 个(不支持远程升级的表没有)。

属性静态/动态数据类型Min.Max.Def.Short name
logical_name(static)octet-stringx
image_block_size(static)double-long-unsignedx + 0x08
image_transferred_blocks_status(dyn.)bit-stringx + 0x10
image_first_not_transferred_block_number(dyn.)double-long-unsignedx + 0x18
image_transfer_enabled(static)booleanx + 0x20
image_transfer_status(dyn.)enumx + 0x28
image_to_activate_info(dyn.)arrayx + 0x30
方法必选/可选(m/o)Short name
image_transfer_initiate (data)mx + 0x40
image_block_transfer (data)mx + 0x48
image_verify (data)mx + 0x50
image_activate (data)mx + 0x58

三点必读:

  1. 四个方法全部m(mandatory)——与本系列前面绝大多数类(方法多为o)形成鲜明对比。若某台表只实现image_block_transfer而没有image_verify,即为不合规实现,应作为风险点上报。
  2. Min. / Max. / Def. 三列原文全为空;特别地image_transfer_enabled没有 Def.,主站不能假设出厂是 TRUE(见踩坑 1)。
  3. Short name 偏移比前面的类"宽":属性x~x + 0x30(步长0x08),方法从x + 0x40起(步长0x08)。SN 寻址时不要沿用Register那样"方法在x + 0x28"的习惯。

2. 属性逐条解读

2.1logical_name(static,octet-string,x)

蓝皮书原文:“Identifies the ‘Image transfer’ object instance. See .”

6 字节OBIS,原文未规定必须是什么码(示例:管理类码段0-0:44.0.0.255一类)。因为基数0…n,OBIS 是区分"升级哪个目标"的唯一依据——主站不能只按class_id = 18找对象。

2.2image_block_size(static,double-long-unsigned,x + 0x08)

蓝皮书原文:“Holds the ImageBlockSize, expressed in octets, which can be handled by the server. ImageBlockSize shall not exceed the ServerMaxReceivePduSize negotiated.”

“NOTE – image_block_size is a property of the server.”

单位是octets;类型double-long-unsigned远大于实际需要(标准给未来留余量)。它是服务器的属性,不是"本次传输的参数"——主站只能读、只能适配(且原文标(static))。

2.3image_transferred_blocks_status(dyn.,bit-string,x + 0x10)

蓝皮书原文:“Provides information about the transfer status of each ImageBlock. Each bit in the bit-string provides information about one individual ImageBlock: 0 = Not transferred, 1 = Transferred.”

“NOTE – The size of the attribute may be dynamic, i.e. it may grow upon reception of new ImageBlocks.”

断点续传的核心:一位一块的位图,第 N 位对应ImageBlockNumber = N。长度动态增长,主站解析不能写死。

2.4image_first_not_transferred_block_number(dyn.,double-long-unsigned,x + 0x18)

蓝皮书原文:“Provides the ImageBlockNumber of the first ImageBlock not transferred. Once the Image is complete, the value returned should be equal to or above the number of blocks calculated from the Image size and the ImageBlockSize.”

位图的廉价替代品:只给"第一个缺口",4 字节,适合窄带轮询。注意原文是should be equal to or above(“等于或大于”),不是"等于"——不能当"传输完成"的判据(见踩坑 5)。

2.5image_transfer_enabled(static,boolean,x + 0x20)

蓝皮书原文:“Controls the enabling of the Image transfer process. boolean: FALSE = Disabled, TRUE = Enabled. The image transfer methods can be invoked successfully only if the value of this attribute is TRUE. Setting the value of this this attribute to FALSE disables all methods (invoking them fails).”

一道总闸:FALSE 时四个方法全部调用失败。它标(static)却可被 SET,原文未解释持久性(重启后是否保持),以设备手册为准。Precondition 一节还补了一句:“…The value of the status attributes is not defined.”——中途关闸后状态属性的值不可信,必须重新image_transfer_initiate从头开始。

2.6image_transfer_status(dyn.,enum,x + 0x28)

蓝皮书原文:“Holds the status of the Image transfer process.”

值含义值含义
(0)Image transfer not initiated(4)Image verification failed
(1)Image transfer initiated(5)Image activation initiated
(2)Image verification initiated(6)Image activation successful
(3)Image verification successful(7)Image activation failed

主站的主状态机镜像。务必分清:(2)(3)(4) 是校验,(5)(6)(7) 是激活——把 (2) 当成 (5) 是高频 bug。

2.7image_to_activate_info(dyn.,array,x + 0x30)

蓝皮书原文:“Provides information on the Image(s) ready for activation. It is generated as the result of the Image verification process. The client may check this information before activating the Images.”

array image_to_activate_info_element image_to_activate_info_element ::= structure { image_to_activate_size: double-long-unsigned, image_to_activate_identification: octet-string, image_to_activate_signature: octet-string }
元素类型原文释义
image_to_activate_sizedouble-long-unsigned“is the size of the Image to be activated, expressed in octets”
image_to_activate_identificationoctet-string“… may contain information like manufacturer, device type, version information, etc.”
image_to_activate_signatureoctet-string“is the signature of the Image to be activated.”

两个易错点:① 它是array——一个 Image容器里可含多个待激活 Image(例如表计固件 + 通信模块固件),按"只有一个"解析会漏(见示例 4);② signature 算法不在本规范内——“NOTE – The algorithm to generate the signature is out of the Scope of this specification.”原文未定义,不要假设是 SHA-256 或 CRC32。


3. 方法:四个m

3.1image_transfer_initiate (data)(m,x + 0x40)

蓝皮书原文:“Initializes the Image transfer process.”

data ::= structure { image_identifier: octet-string, image_size: double-long-unsigned -- ImageSize, expressed in octets }

一条极重要、极易误读的 NOTE:

蓝皮书原文:“The image_identifier identifies the Image to be transferred (container) but it is not necessarily linked to its content, i.e. the Images which will be activated. That information can be retrieved from the image_to_activate attribute after verification of the Image transferred.”

image_identifier标识的是"容器",不保证与里面真正要激活的内容一致——这就是"外面写 A 版本、里面装 B 版本"的标准出处,也是 Step 6 存在的理由。

蓝皮书原文:“After a successful invocation of the method the image_transfer_status attribute is set to (1) and the image_first_not_transferred_block_number is set to 0. Any subsequent invocation of the method resets the whole Image transfer process and all ImageBlocks need to be transferred again.”

重复调用 = 全部重传(踩坑 3)。

3.2image_block_transfer (data)(m,x + 0x48)

蓝皮书原文:“Transfers one block of the Image to the server.”

data ::= structure { image_block_number: double-long-unsigned, image_block_value: octet-string }

蓝皮书原文:“After a successful invocation of the method the corresponding bit in the image_transferred_blocks_status attribute is set to 1 and the image_first_not_transferred_block_number attribute is updated.”

一次调用只传一块,块号由主站显式指定——意味着可以乱序传(先传第 500 块再传第 0 块,位图照样记)。

3.3image_verify (data)(m,x + 0x50)

蓝皮书原文:“Verifies the integrity of the Image before activation.”data ::= integer (0)(占位参数,无语义)

蓝皮书原文:“The result of the invocation of this method may be success, temporary_failure or other_reason. If it is not success, then the result of the verification can be found by retrieving the value of the image_transfer_status attribute.”

“In the case of success, the image_to_activate_info attribute holds the information about the images to activate.”

三态结果:success / temporary-failure / other-reason,后两者必须回读image_transfer_status才能区分。至于"校验什么",原文(Step 5)明说“NOTE – The conditions of verifying the Image are out of the scope of this document.”——原文未定义校验条件,具体定义见蓝皮书其他章节。

3.4image_activate (data)(m,x + 0x58)

蓝皮书原文:“Activates the Image.”data ::= integer (0)

蓝皮书原文:“If the Image transferred has not been verified before, then this is done as part of the Image activation.”

未校验就激活 → 隐式校验。功能可行,但你失去了激活前检查image_to_activate_info的机会——这是变砖风险的主要来源之一。

蓝皮书原文(Step 7):“In the case of success, the server performs the activation of the new Image(s).During this process, it is not accessible.After the Image(s) has (have) been activated, the result of may be checked by the client by retrieving the value of the image_transfer_status attribute or by reading the contents of the appropriate COSEM objects holding the identifier, version and digital signature of the active firmware.”

激活期间服务器不可访问,主站必须有"静默期"设计。结果两种确认方式:回读image_transfer_status,或读存放在用固件identifier / version / signature 的 COSEM 对象。

3.5 附:M-Bus 设备的 Image transfer(原文同章)

流程仍是七步,两处差异。其一,Step 2 的image_identifier有专门结构(原文照录):

MAN M-Bus DEV M-Bus PREPARE MAN: Manufacturer (three letter) code according to FLAG, ASCII encoded M-Bus DEV M-Bus DEV code (letters "MBUS"), ASCII encoded M-Bus PREPARE M-Bus Prepare Command Structure (as specified in EN13757-3:2018, I.2.4)

其二,Step 5 变强制——原文:“This is when the image is transferred to the M-Bus device and hence is mandatory.”因为这一步才是把 Image 从 DLMS server 转发到 M-Bus 从设备的时刻。

M-Bus 从设备的State映射到image_transfer_status(原文 Table 节选):

M-Bus “State”Attributeimage_transfer_status
0 Synchronization activated / 2 Transfer initiated / 3 Transfer activeNot affected
5 Transfer successful / 6 Transfer failedNot affected
7 Validation initiated(2) Image verification initiated
9 Validation successful(3) Image verification successful
10 Validation failed(4) Image verification failed
11 Activation initiated(5) Image activation initiated
12 Activation successful(6) Image activation successful
13 Activation failed(7) Image activation failed
14 Image Transfer Terminated / 15 IdleNot affected

读法:M-Bus 侧的传输阶段(0/2/3/5/6)完全不反映到image_transfer_status——主站在这段轮询会看到它一直停在 (1),不代表没在动;只有进入 Validation / Activation(7 以后)才跳变。


4. 【实战举例】

示例 1:先算清楚要传多少块(Step 1)

# AA 协商出 ServerMaxReceivePduSize = 640 GET (class_id=18, logical_name=0-0:44.0.0.255, attribute_index=2) # image_block_size → 512 # double-long-unsigned,单位 octets;512 ≤ 640 ✔ 合规 image_size = 524 288 octets (512 KiB) 块数 = ceil(524288 / 512) = 1024 ;位图 = 1024 bits = 128 octets

若image_size = 524 300(不整除):块数 =ceil(524300/512) = 1025,最后一块只有 12 octets。所以image_block_value长度不能假设都等于image_block_size。另外(非规格提示)一次ACTION报文还要占 APDU 头、structure头、image_block_number与安全开销,实际可承载的块大小小于理论值,开销因安全套件而异,本文不臆造数值。

示例 2:块状态位图怎么读(Step 4,机制一)

前 12 块中第 3、7 块失败:

bit: 0 1 2 3 4 5 6 7 8 9 10 11 val: 1 1 1 0 1 1 1 0 1 1 1 1 └─缺─┘ └─缺─┘ A-XDR 编码(示例): 0x04 0xEE 0xF0 0x04 = 最后一个字节中未使用的 bit 数;0xEE = blocks 0..7 = 1110 1110 0xF0 = blocks 8..11 = 1111 + 4 bit 补 0

主站得到缺失集合{3, 7},只补这两块:ACTION image_block_transfer { 3, <512 octets> }、ACTION image_block_transfer { 7, <512 octets> }。

注意“may grow upon reception of new ImageBlocks”:传输初期GET回来可能只有几字节,后期才到 128 字节,必须按实际长度动态解析。

示例 3:断点续传(Step 4,机制二)

PLC 链路,传到第 300 块时中断 20 分钟:

重连后先查总闸:GET image_transfer_enabled → TRUE ✔ GET image_transfer_status → (1) Image transfer initiated ✔ 进程还活着 机制二(4 字节):GET image_first_not_transferred_block_number → 300 从 300 续传:ACTION image_block_transfer { 300, ... } 、{ 301, ... } …

绝不能重调image_transfer_initiate——“resets the whole Image transfer process”,前 300 块全废。原文还给了两机制合并许可:

蓝皮书原文(Step 4):“NOTE – The two mechanisms can be freely combined.”

实践:宽带用位图(一次GET拿全貌,批量补洞);窄带/按字节计费链路用image_first_not_transferred_block_number(4 字节),传一块读一次循环推进。

示例 4:完整七步时序(含耗时估算)

T+00:00 GET image_transfer_enabled → TRUE T+00:01 GET image_block_size → 512 (Step 1) T+00:02 ACTION image_transfer_initiate { image_identifier = "FW-3.2.1", image_size = 524288 } → success (Step 2) # 服务器预留空间;status→(1);位图复位;first_not_transferred→0; # image_to_activate_info 复位 T+00:03 ACTION image_block_transfer {0..1023} (Step 3) # 示例估算:HDLC 9600 bit/s,每块 512 B + 开销 ≈ 0.5 s # 1024 × 0.5 s ≈ 8 分 32 秒 T+08:35 GET image_transferred_blocks_status → 全 1 (Step 4) T+08:36 GET image_first_not_transferred_block_number → 1024 (≥1024 ✔) T+08:37 ACTION image_verify (0) → success (Step 5) # status → (3) Image verification successful T+08:45 GET image_to_activate_info → array[1] (Step 6) # { size = 524288, identification = "FW-3.2.1 / MeterType-X", # signature = <32 octets> } → 版本/厂商/大小均对得上,继续 T+08:46 ACTION image_activate (0) → success (Step 7) # status → (5);★ 此后服务器 NOT ACCESSIBLE,主站停止一切请求 T+09:46 (静默 60 s 后重连) T+09:50 GET image_transfer_status → (6) activation successful ✔

Step 6 是最后一道防线。原文:“If the image transferred contains images with attributes that match those expected, the Server goes to step 7 and activates the image(s). However if the attributes do not match then the client can restart transferring the image.”——发现不匹配,正确动作是"重新传",不是"硬着头皮激活"。

还要注意image_to_activate_info是array,一个容器里常常不止一个待激活 Image:

GET image_to_activate_info → array [0] { size = 524288, identification = "METER-FW 3.2.1", signature = <32 octets> } [1] { size = 65536, identification = "MODEM-FW 1.4.0", signature = <32 octets> }

一次传输、一次激活,两个固件都升(原文 Step 7 用的是 “the new Image(s)”)。主站若按"只有一个"解析就会漏掉 modem 固件,后果是"以为是单升级,实际升了两个"。

示例 5:广播升级一批表(块大小必须一致)

蓝皮书原文(Step 1):“If ImageBlocks are sent using broadcast to a group of COSEM servers the ImageBlockSize shall be the same in each member of the group.”

一批 500 台表:480 台image_block_size = 512,20 台老批次 = 256。

错误做法:按 512 广播 → 那 20 台收不下,传输失败 正确做法:image_block_size_broadcast = min(全组) = 256 块数 = ceil(524288/256) = 2048 # 块数翻倍,总时长变长

代价是块数翻倍——用传输时间换"广播可行";另一种做法是分两组单播,用管理成本换时间。

蓝皮书原文(Step 3):“ImageBlocks are accepted only by those COSEM servers, in which the Image transfer process has been successfully initiated. Other servers silently discard any ImageBlocks received.”

“silently discard”(静默丢弃):没initiate过的服务器收到块不报错、不回应。主站不能靠"没收到错误"判定成功,必须回到 Step 4 逐台核对位图。

示例 6:激活失败与"回退"——原文到底给了什么

ACTION image_activate (0) → other-reason GET image_transfer_status → (7) Image activation failed

原文给了什么:只有状态值 (7),以及"可回读image_transfer_status或读存放在用固件identifier / version / signature 的 COSEM 对象确认结果"。

原文没有给的(如实说明):①没有"回退 / rollback"方法(4 个 method 里没有image_rollback之类);②没有定义激活失败后服务器应处于什么状态(是否自动回滚、A/B 双区如何切换)——属实现与厂商策略,不在本类规格内;③没有定义 signature 算法与校验条件(原文明确 out of scope)。

原文提供的唯一"重来"手段只有两条:① 重新image_transfer_initiate→“resets the whole Image transfer process”,推倒重传;② Step 6 发现不匹配时 →“the client can restart transferring the image”。

所以工程上的A/B 双区自动回退是厂商实现层面的保障,不是 COSEM 协议能力;主站侧唯一能做的就是"激活前把image_to_activate_info看清楚"——这正是 Step 6 被写进流程的意义。


5. 工程上容易踩的坑

  1. 以为image_transfer_enabled默认 TRUE:原文未给 Def.,且明说四个方法只有它为 TRUE 时才能成功调用。第一步就GET它;FALSE 则先 SET(需写权限),失败应报"设备未开启远程升级"而非"方法不存在"。
  2. 把image_block_size当成本次传输参数去 SET,或让它超过 PDU 上限:“is a property of the server”且标(static),主站只能读、只能适配;同时必须满足“shall not exceed the ServerMaxReceivePduSize negotiated”。另注意最后一块长度 ≠image_block_size,写死长度会截断或补错。
  3. 断点续传时手贱重调image_transfer_initiate:“all ImageBlocks need to be transferred again”。续传的正确动作是只读image_first_not_transferred_block_number(或位图)后直接image_block_transfer。这是 OTA 项目里最浪费流量的 bug。
  4. bit-string解析写死长度 / 漏掉首字节:长度“may be dynamic”;A-XDR 编码首字节是未使用 bit 数,漏掉会整体错位一字节。位序(第 N 位 ↔ 第 N 块)也要与厂商确认。
  5. 拿image_first_not_transferred_block_number当"完成"判据:原文是“equal to or above”,只说明没有更靠前的缺口,不代表位图全 1(后面仍可能有孤立缺口)。判完成应看位图,或两者结合。
  6. 没验明正身就激活:一是把image_identifier当固件版本——原文 NOTE 明确它标识容器,“not necessarily linked to its content”,版本/厂商/大小只能从image_to_activate_info拿;二是跳过 Step 6 直接image_activate——会触发隐式校验,把"传错包"的发现时机从激活前推迟到激活后,代价从"重传"变成"变砖"。
  7. 校验/激活返回非 success 时不去回读image_transfer_status:temporary-failure(仍在 (2))需等待并轮询,other-reason((4)/(7))才是真失败。把两者混为一律重传,会在慢设备上陷入死循环。
  8. 把"没动静"误判为故障:激活期间“it is not accessible”,主站若按常规超时判定掉线并触发重连/告警,会在激活窗口期制造大量误报——应预留"设备重启 + 应用初始化"的静默窗口;同理,M-Bus 传输阶段(State 0/2/3/5/6)完全不影响image_transfer_status,主站看到它停在 (1) 也不是故障。

6. 小结 & 下期预告

本篇要点:

  1. Image transfer(class_id = 18, version = 0)建模的是"过程"而非"文件"——本系列第一个带完整业务流程的类;
  2. 必须分块的三条硬理由:内存小、“shall not exceed the ServerMaxReceivePduSize negotiated”、只有分块才能断点续传;
  3. 断点续传靠两条互补机制:image_transferred_blocks_status(动态bit-string位图)与image_first_not_transferred_block_number(首个缺口,4 字节),原文允许“can be freely combined”;
  4. image_transfer_enabled是总闸,FALSE 时四个方法全失败且状态属性*“not defined”*;image_transfer_status是 8 态enum,务必分清(2)(3)(4) 校验与(5)(6)(7) 激活;
  5. image_to_activate_info是array,一个容器可含多个待激活 Image;signature 算法与校验条件原文未定义(out of scope);
  6. 原文没有回退方法——失败后唯一标准动作是重新image_transfer_initiate重传;A/B 双区回退属厂商实现而非 COSEM 能力,因此Step 6 的image_to_activate_info比对是主站最后一道防线。

下一篇(第 16 篇):IEC local port setup(class_id = 19)—— 从"远程"回到"本地":表计那个光口(本地口)的通信参数怎么配置(波特率、协议模式、响应时间等)。它也是本系列里少见的**带两个 version(version = 0 与 version = 1)**的类,我们会按版本对比讲清 v1 新增了什么、现场抄表掌机插上去为什么有时连不上。如果说本篇解决的是"固件怎么进来",下一篇解决的就是"人拿着设备走到表前面,怎么接进去"。


参考资料:DLMS UA《Blue Book Ed.16 Part 2 – COSEM interface classes》,Image transfer (class_id = 18, version = 0) 章节,含 General / Overview / Attribute description / Method description / “Example for a standard image transfer process”(Step 1–7)/ “Image transfer for M-Bus devices”(含 M-Bus State → image_transfer_status 映射表)。文中属性名与顺序、数据类型、static/dyn 标注、Short name 偏移、方法名与 m/o、enum 取值与英文引文均与该章节原文一致;signature 生成算法与 Image 校验条件原文明确声明 out of scope,本篇未作推演。示例中的 OBIS、块大小、报文编码、时序与耗时估算均为帮助理解而构造(实际以设备对象列表与厂商手册为准)。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询