DLMS/COSEM协议编解码杂谈

DLMS/COSEM协议编解码杂谈

DLMS协议编解码论述

DLMS/COSEM(Device Language Message Specification/Companion Specification for Energy Metering)是一种用于远程读取电力、燃气、水和热能表的通信协议。在DLMS/COSEM协议中,数据被编码为一系列的数据类型,每种数据类型都由一个标签(Tag)和一个长度(Length)字段组成。

  • 标签(tag)是一个字节,用于表示数据的类型。
    例如,八位字节字符串(octet-string)的标签是0x09,数组(array)的标签是0x01,结构(structure)的标签是0x02,等等。

  • 长度字段表示数据的长度。
    在DLMS/COSEM协议中,长度字段可以是一个或多个字节具体取决于数据的长度。如果数据的长度小于或等于127字节,那么长度字段就是一个字节,其值就是数据的长度。如果数据的长度大于127字节,那么长度字段就是多个字节,第一个字节的最高位是1,其余位表示长度字段的字节数,后续的字节表示数据的长度。

  • 数据本身紧跟在长度字段之后。
    对于八位字节字符串,数据就是字符串的内容。对于数组和结构,数据是一个或多个编码为DLMS/COSEM数据类型的元素。

例如,一个包含三个字节(0x01, 0x02, 0x03)的八位字节字符串在DLMS/COSEM协议中会被编码为:0x09 0x03 0x01 0x02 0x03。其中,0x09是标签,表示这是一个八位字节字符串;0x03是长度字段,表示字符串的长度是3字节;0x01, 0x02, 0x03是数据,即字符串的内容。

解码DLMS/COSEM数据类型的过程就是编码过程的逆过程。

  • 首先,读取标签来确定数据的类型;
  • 然后,读取长度字段来确定数据的长度;
  • 最后,读取数据本身。

DLMS/COSEM协议中,数据类型的标签(tag)是一个字节,用于表示数据的类型。以下是一些常见的数据类型和对应的标签:

- Null :0x00
- Array:0x01
- Structure:0x02
- Boolean:0x03
- Bit-string:0x04

- int32:0x05
- uint32:0x06
- Octet-string:0x09
- Visible-string:0x0A
- UTF8-string:0x0B

- BCD:0x0D
- int8:0x0F
- int16:0x10
- uint8:0x11
- uint16:0x12

- Compact array:0x13
- int64:0x14
- uint64:0x15
- enum:0x16
- float32:0x17

- float64:0x18
- DateTime:0x19
- Date:0x1A
- Time:0x1B

编码过程如下:

  1. 首先,将数据类型的标签(Tag)添加到编码结果中。

  2. 然后,根据数据的长度(Length),将长度编码为一个或多个字节,并添加到编码结果中。

  3. 最后,将数据本身添加到编码结果中。

例如,如果我们要编码一个长度为3的八位字节字符串"ABC",过程如下:

  1. 八位字节字符串(Octet-string)的标签是0x09,所以我们首先添加0x09到编码结果中。

  2. 字符串的长度是3,所以我们添加0x03到编码结果中。

  3. 最后,我们将字符串"ABC"的ASCII值0x41, 0x42, 0x43添加到编码结果中。

所以,编码结果是:0x09 0x03 0x41 0x42 0x43

注意,对于一些数据类型(如数组和结构),数据本身可能包含多个子元素,每个子元素都需要按照上述过程进行编码。

在DLMS/COSEM协议中,数组和结构体的编码方式与其他数据类型类似,但是它们的数据部分包含多个元素,每个元素都是一个DLMS/COSEM数据类型。

对于数组和结构体长度字段表示元素的数量,而不是字节的数量。

以下是一个数组的编码示例:

假设我们有一个数组,包含两个元素一个INT8值3和一个八位字节字符串"AB"

  1. 首先,我们添加数组的标签0x01到编码结果中。

  2. 然后,我们添加元素的数量2到编码结果中。

  3. 接下来,我们将每个元素编码为DLMS/COSEM数据类型,并添加到编码结果中。
    3.1. 首先,我们添加INT8值3的编码结果:0x0F 0x03
    3.2. 然后,我们添加**八位字节字符串"AB"**的编码结果:0x09 0x02 0x41 0x42

所以,整个数组的编码结果是:0x01 0x02 0x0F 0x03 0x09 0x02 0x41 0x42。

结构体的编码方式与数组类似,只是标签不同(结构体的标签是0x02)。

解码数组和结构体的过程与编码过程相反
首先,读取标签来确定数据类型是数组还是结构体。然后,读取长度字段来确定元素的数量。最后,依次解码每个元素。

ToTLVString()和TLVtoEntity(std::string s_string)这两个函数的主要作用是实现TLV(Tag-Length-Value)格式的编码和解码。

  1. ToTLVString()函数的作用是将实体的各个属性编码为TLV格式的字符串。TLV格式是一种编码格式,其中T代表标签(Tag),L代表长度(Length),V代表值(Value)。在这个函数中,每个属性都被编码为一个TLV元素,然后所有的TLV元素被连接在一起,形成一个字符串。

  2. TLVtoEntity(std::string s_string)函数的作用是将一个TLV格式的字符串解码为实体的各个属性。这个函数的参数s_string是一个TLV格式的字符串。在这个函数中,首先从字符串中提取出一个TLV元素,然后根据这个元素的标签(Tag)确定它代表哪个属性,然后根据这个元素的长度(Length)和值(Value)来解码这个属性的值。

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nerd Nirvana

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值