Golang?IOT中的數(shù)據(jù)序列化與解析過程
Golang IOT中的數(shù)據(jù)序列化與解析
Golang中對于JSON、XML、HTML、RPC、PB、Thrift等現(xiàn)代化協(xié)議都支持的非常好,但是對于IOT領(lǐng)域,用的多的反而是HEX原始數(shù)據(jù),如果一個個解析,會是非常麻煩的事情。
所以,對于HEX數(shù)據(jù)是否有方便好用的打包/解包方法?
目前,比較官方和流行的方式有如下幾種:
- Gob: Golang私有協(xié)議,自由度高,不可定制。原理:http://m.fzitv.net/article/211523.htm
- Binary: Golang 官方庫,只支持固定size的struct。使用非常接近HEX原生。
- MsgPack: 第三方流行方案。類似gob但是結(jié)構(gòu)開放。原理:http://m.fzitv.net/jiaoben/284969tii.htm
對于gob和msgpack在IOT一般比較困難,適用性差,探索一下binary的方案。
Binary結(jié)構(gòu)體與二進(jìn)制
參考: http://m.fzitv.net/jiaoben/284968z11.htm
經(jīng)常有這樣的需求,在底層硬件設(shè)備通過TCP/UART傳輸了一堆數(shù)據(jù)過來,但是都是16進(jìn)制的,每1-4個字節(jié)表示一個數(shù)據(jù),然后還有可能有數(shù)組一類的數(shù)據(jù)。從數(shù)據(jù)類型上存在bool/int8/int16/int32/int64/float32,還有對應(yīng)的數(shù)組。
如果簡單地通過16進(jìn)制操作,當(dāng)然可以完成,但是維護(hù)起來非常費力,如果設(shè)備多了就簡直時災(zāi)難。
所以,是否存在一種類似模板的方案,自動根據(jù)某個字節(jié)進(jìn)行數(shù)據(jù)的解析和轉(zhuǎn)換呢?答案是肯定的!雖然不一定能完全自動化,但是能節(jié)約維護(hù)的時間和BUG。
假設(shè)我們有這樣一個HEX數(shù)據(jù)
Message: Byte. 假設(shè)N=4 ┌──────┬──────┬────────┬──────────┬──────────┬───────┐ │ Id: 1│Cmd: 1│ Addr: 2│Length: 2 │Data: 2*N │ CRC:2 │ └──────┴──────┴────────┴──────────┴──────────┴───────┘
對應(yīng)數(shù)據(jù)Data根據(jù)Cmd的值不同,有不同的長度和意義。該如何Design這個解析處理呢?
package main
import (
"bytes"
"encoding/binary"
"fmt"
)
// message的基礎(chǔ)結(jié)構(gòu),繼承后使用
// size = 6
type CmdMsgBaseHeader struct {
Idx uint8 // 設(shè)備模塊的唯一ID,從1-254,255表示廣播
Cmd uint8 // 命令值,表示不同類型的消息
Addr uint16 // 數(shù)據(jù)地址,2個字節(jié),高字節(jié)在前。大端字節(jié)序(big endian)
Len uint16 // 返回的真實數(shù)據(jù)長度,以2個字節(jié)為一個單位
//Data [N]uint8 // RAW數(shù)據(jù),根據(jù)Cmd和Addr區(qū)分作用。一般作為繼承數(shù)據(jù)使用。固定size。
//CRC [2]uint8 // CRC校驗
}
// 假設(shè)的 數(shù)據(jù)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\n", a) // {CmdMsgBaseHeader:{Idx:1 Cmd:9 Addr:513 Len:4} Data:[258 259 260 261] CRC:[172 172]}
}這樣,通過不斷定制CmdMsg_IO_Status就可以按照需求解析HEX數(shù)據(jù)。
到此這篇關(guān)于Golang IOT中的數(shù)據(jù)序列化與解析的文章就介紹到這了,更多相關(guān)go數(shù)據(jù)序列化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
GoLang調(diào)用鏈可視化go-callvis使用介紹
與鏈路追蹤(Tracing)不同,Tracing關(guān)注復(fù)雜的分布式環(huán)境中各個服務(wù)節(jié)點間的調(diào)用關(guān)系,主要用于服務(wù)治理。而我們本次探索的代碼調(diào)用鏈路則是代碼方法級別的調(diào)用關(guān)系,主要用于代碼設(shè)計2023-02-02
解析Go 標(biāo)準(zhǔn)庫 http.FileServer 實現(xiàn)靜態(tài)文件服務(wù)
http.FileServer 方法屬于標(biāo)準(zhǔn)庫 net/http,返回一個使用 FileSystem 接口 root 提供文件訪問服務(wù)的 HTTP 處理器。下面通過本文給大家介紹Go 標(biāo)準(zhǔn)庫 http.FileServer 實現(xiàn)靜態(tài)文件服務(wù)的相關(guān)知識,感興趣的朋友一起看看吧2018-08-08
Golang實現(xiàn)優(yōu)雅的將struct轉(zhuǎn)換為map
在項目實踐中,有時候我們需要將struct結(jié)構(gòu)體轉(zhuǎn)為map映射表,然后基于map做數(shù)據(jù)裁剪或操作。那么下面我來介紹下常用的兩種轉(zhuǎn)換方式,希望對大家有所幫助2023-01-01
一文帶你了解Golang中interface的設(shè)計與實現(xiàn)
本文就來詳細(xì)說說為什么說?接口本質(zhì)是一種自定義類型,以及這種自定義類型是如何構(gòu)建起?go?的?interface?系統(tǒng)的,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-01-01
Go語言同步與異步執(zhí)行多個任務(wù)封裝詳解(Runner和RunnerAsync)
這篇文章主要給大家介紹了關(guān)于Go語言同步與異步執(zhí)行多個任務(wù)封裝(Runner和RunnerAsync)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01

