Golang?IOT中的數(shù)據(jù)序列化與解析過程
Golang IOT中的數(shù)據(jù)序列化與解析
Golang中對(duì)于JSON、XML、HTML、RPC、PB、Thrift等現(xiàn)代化協(xié)議都支持的非常好,但是對(duì)于IOT領(lǐng)域,用的多的反而是HEX原始數(shù)據(jù),如果一個(gè)個(gè)解析,會(huì)是非常麻煩的事情。
所以,對(duì)于HEX數(shù)據(jù)是否有方便好用的打包/解包方法?
目前,比較官方和流行的方式有如下幾種:
- Gob: Golang私有協(xié)議,自由度高,不可定制。原理:http://www.dbjr.com.cn/article/211523.htm
- Binary: Golang 官方庫,只支持固定size的struct。使用非常接近HEX原生。
- MsgPack: 第三方流行方案。類似gob但是結(jié)構(gòu)開放。原理:http://www.dbjr.com.cn/jiaoben/284969tii.htm
對(duì)于gob和msgpack在IOT一般比較困難,適用性差,探索一下binary的方案。
Binary結(jié)構(gòu)體與二進(jìn)制
參考: http://www.dbjr.com.cn/jiaoben/284968z11.htm
經(jīng)常有這樣的需求,在底層硬件設(shè)備通過TCP/UART傳輸了一堆數(shù)據(jù)過來,但是都是16進(jìn)制的,每1-4個(gè)字節(jié)表示一個(gè)數(shù)據(jù),然后還有可能有數(shù)組一類的數(shù)據(jù)。從數(shù)據(jù)類型上存在bool/int8/int16/int32/int64/float32,還有對(duì)應(yīng)的數(shù)組。
如果簡單地通過16進(jìn)制操作,當(dāng)然可以完成,但是維護(hù)起來非常費(fèi)力,如果設(shè)備多了就簡直時(shí)災(zāi)難。
所以,是否存在一種類似模板的方案,自動(dòng)根據(jù)某個(gè)字節(jié)進(jìn)行數(shù)據(jù)的解析和轉(zhuǎn)換呢?答案是肯定的!雖然不一定能完全自動(dòng)化,但是能節(jié)約維護(hù)的時(shí)間和BUG。
假設(shè)我們有這樣一個(gè)HEX數(shù)據(jù)
Message: Byte. 假設(shè)N=4 ┌──────┬──────┬────────┬──────────┬──────────┬───────┐ │ Id: 1│Cmd: 1│ Addr: 2│Length: 2 │Data: 2*N │ CRC:2 │ └──────┴──────┴────────┴──────────┴──────────┴───────┘
對(duì)應(yīng)數(shù)據(jù)Data根據(jù)Cmd的值不同,有不同的長度和意義。該如何Design這個(gè)解析處理呢?
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個(gè)字節(jié),高字節(jié)在前。大端字節(jié)序(big endian) Len uint16 // 返回的真實(shí)數(shù)據(jù)長度,以2個(gè)字節(jié)為一個(gè)單位 //Data [N]uint8 // RAW數(shù)據(jù),根據(jù)Cmd和Addr區(qū)分作用。一般作為繼承數(shù)據(jù)使用。固定size。 //CRC [2]uint8 // CRC校驗(yàn) } // 假設(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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
golang實(shí)現(xiàn)文件上傳并轉(zhuǎn)存數(shù)據(jù)庫功能
這篇文章主要為大家詳細(xì)介紹了golang實(shí)現(xiàn)文件上傳并轉(zhuǎn)存數(shù)據(jù)庫功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07小學(xué)生也能看懂的Golang異常處理recover panic
在其他語言里,宕機(jī)往往以異常的形式存在,底層拋出異常,上層邏輯通過 try/catch 機(jī)制捕獲異常,沒有被捕獲的嚴(yán)重異常會(huì)導(dǎo)致宕機(jī),go語言追求簡潔,優(yōu)雅,Go語言不支持傳統(tǒng)的 try…catch…finally 這種異常2021-09-09golang基礎(chǔ)之Gocurrency并發(fā)
這篇文章主要介紹了golang基礎(chǔ)之Gocurrency并發(fā),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-07-07Golang?Gin解析JSON請(qǐng)求數(shù)據(jù)避免出現(xiàn)EOF錯(cuò)誤
這篇文章主要為大家介紹了Golang?Gin?優(yōu)雅地解析JSON請(qǐng)求數(shù)據(jù),避免ShouldBindBodyWith出現(xiàn)EOF錯(cuò)誤的源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04GO中高效的將int轉(zhuǎn)換為string的方法與源碼
本文將從逐步介紹幾種在?Go?中將?int?轉(zhuǎn)換為?string?的常見方法,并重點(diǎn)剖析這幾種方法在性能上的特點(diǎn),另外,還會(huì)重點(diǎn)介紹?FormatInt?高效的算法實(shí)現(xiàn),需要的朋友可以參考下2024-01-01golang設(shè)置http response響應(yīng)頭與填坑記錄
這篇文章主要給大家介紹了關(guān)于golang設(shè)置http response響應(yīng)頭與填坑記錄的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08