-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathdecoder.go
95 lines (72 loc) · 2.24 KB
/
decoder.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package jt808
import (
"fmt"
"sort"
"github.com/francistm/jt808-golang/internal/bytes"
"github.com/francistm/jt808-golang/internal/decode"
"github.com/francistm/jt808-golang/message"
)
//go:generate go run github.com/francistm/jt808-golang/tools/generator/decoder
// Unmarshal 由二进制解析一个完整的消息包
func Unmarshal[T message.MesgBody](data []byte, mesgPack *message.MessagePack[T]) error {
return mesgPack.UnmarshalBinary(data)
}
// ConcatUnmarshal 拼接多个分段消息并解析
func ConcatUnmarshal[T message.MesgBody](packs []*message.MessagePack[*message.PartialPackBody], pack *message.MessagePack[T]) error {
if len(packs) < 2 {
return ErrIncompletedPkgMesg
}
if packs[0].PackHeader.Package == nil {
return ErrNotPkgMesg
}
var (
mesgBodyBuf = bytes.NewBuffer()
mesgBodyReader *bytes.Reader
mesgId = packs[0].PackHeader.MessageID
)
if len(packs) != int(packs[0].PackHeader.Package.Total) {
return ErrIncompletedPkgMesg
}
sort.Slice(packs, func(i, j int) bool {
var (
packsLeft = packs[i]
packsRight = packs[j]
)
if packsLeft.PackHeader.Package == nil {
return false
}
return packsLeft.PackHeader.Package.Index < packsRight.PackHeader.Package.Index
})
for i, pack := range packs {
if pack.PackHeader.Package == nil {
return ErrNotPkgMesg
}
if pack.PackHeader.MessageID != mesgId {
return fmt.Errorf("message at %d is not type of %.4X", i+1, mesgId)
}
if pack.PackHeader.Package.Index != uint16(i+1) {
return fmt.Errorf("message at %d is not the %dth message", i+1, i+1)
}
mesgId = pack.PackHeader.MessageID
mesgBodyBuf.Write(pack.PackBody.RawBody)
}
pack.PackHeader = packs[0].PackHeader
pack.PackHeader.Package = nil
pack.PackHeader.Property.IsMultiplePackage = false
pack.PackHeader.Property.BodyByteLength = uint16(mesgBodyBuf.Len())
packBody, err := pack.NewPackBodyFromMesgId()
if err != nil {
return err
}
typedPackBody, ok := packBody.(T)
if !ok {
return fmt.Errorf("can't convert body from %T to %T", packBody, pack.PackBody)
}
pack.Checksum = 0
pack.PackBody = typedPackBody
mesgBodyReader = bytes.NewReader(mesgBodyBuf.Bytes())
if err := decode.UnmarshalStruct(mesgBodyReader, packBody); err != nil {
return err
}
return nil
}