您现在的位置是:首页 >技术杂谈 >Golang IOT中的数据序列化与解析网站首页技术杂谈

Golang IOT中的数据序列化与解析

笨笨D幸福 2024-06-17 10:47:00
简介Golang IOT中的数据序列化与解析

Golang IOT中的数据序列化与解析

Golang中对于JSON、XML、HTML、RPC、PB、Thrift等现代化协议都支持的非常好,但是对于IOT领域,用的多的反而是HEX原始数据,如果一个个解析,会是非常麻烦的事情。
所以,对于HEX数据是否有方便好用的打包/解包方法?

目前,比较官方和流行的方式有如下几种:

  1. Gob: Golang私有协议,自由度高,不可定制。原理:https://blog.csdn.net/ma2595162349/article/details/112437636
  2. Binary: Golang 官方库,只支持固定size的struct。使用非常接近HEX原生。
  3. 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数据。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。