您现在的位置是:首页 >技术杂谈 >Golang IOT中的数据序列化与解析网站首页技术杂谈
Golang IOT中的数据序列化与解析
简介Golang IOT中的数据序列化与解析
Golang IOT中的数据序列化与解析
Golang中对于JSON、XML、HTML、RPC、PB、Thrift等现代化协议都支持的非常好,但是对于IOT领域,用的多的反而是HEX原始数据,如果一个个解析,会是非常麻烦的事情。
所以,对于HEX数据是否有方便好用的打包/解包方法?
目前,比较官方和流行的方式有如下几种:
- Gob: Golang私有协议,自由度高,不可定制。原理:https://blog.csdn.net/ma2595162349/article/details/112437636
- Binary: Golang 官方库,只支持固定size的struct。使用非常接近HEX原生。
- MsgPack: 第三方流行方案。类似gob但是结构开放。原理:https://blog.csdn.net/weixin_41112414/article/details/108683577
对于gob和msgpack在IOT一般比较困难,适用性差,探索一下binary的方案。
Binary结构体与二进制
参考: https://blog.csdn.net/Peerless__/article/details/121443159
经常有这样的需求,在底层硬件设备通过TCP/UART传输了一堆数据过来,但是都是16进制的,每1-4个字节表示一个数据,然后还有可能有数组一类的数据。从数据类型上存在bool/int8/int16/int32/int64/float32,还有对应的数组。
如果简单地通过16进制操作,当然可以完成,但是维护起来非常费力,如果设备多了就简直时灾难。
所以,是否存在一种类似模板的方案,自动根据某个字节进行数据的解析和转换呢?答案是肯定的!虽然不一定能完全自动化,但是能节约维护的时间和BUG。
假设我们有这样一个HEX数据
Message: Byte. 假设N=4
┌──────┬──────┬────────┬──────────┬──────────┬───────┐
│ Id: 1│Cmd: 1│ Addr: 2│Length: 2 │Data: 2*N │ CRC:2 │
└──────┴──────┴────────┴──────────┴──────────┴───────┘
对应数据Data根据Cmd的值不同,有不同的长度和意义。该如何Design这个解析处理呢?
package main
import (
"bytes"
"encoding/binary"
"fmt"
)
// message的基础结构,继承后使用
// size = 6
type CmdMsgBaseHeader struct {
Idx uint8 // 设备模块的唯一ID,从1-254,255表示广播
Cmd uint8 // 命令值,表示不同类型的消息
Addr uint16 // 数据地址,2个字节,高字节在前。大端字节序(big endian)
Len uint16 // 返回的真实数据长度,以2个字节为一个单位
//Data [N]uint8 // RAW数据,根据Cmd和Addr区分作用。一般作为继承数据使用。固定size。
//CRC [2]uint8 // CRC校验
}
// 假设的 数据1
// size = 2 + 2*Len = 10
type CmdMsg_IO_Status struct {
CmdMsgBaseHeader
Data [4]uint16
CRC [2]uint8
}
func main() {
a := CmdMsg_IO_Status{}
b := []uint8{0x01, 0x09, 0x02, 0x01, 0x00, 0x04 /*Data*/, 0x01, 0x02, 0x01, 0x03, 0x01, 0x04, 0x01, 0x05 /*CRC*/, 0xAC, 0xAC}
buff := bytes.NewBuffer(b)
// buff size = 6+10 = 16
err := binary.Read(buff, binary.BigEndian, &a)
if err != nil {
fmt.Println("read error:", err)
return
}
// decode ok
fmt.Printf("decode: %+v
", a) // {CmdMsgBaseHeader:{Idx:1 Cmd:9 Addr:513 Len:4} Data:[258 259 260 261] CRC:[172 172]}
}
这样,通过不断定制CmdMsg_IO_Status
就可以按照需求解析HEX数据。
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。