-
Notifications
You must be signed in to change notification settings - Fork 1
/
frame_builder.go
executable file
·142 lines (123 loc) · 3.51 KB
/
frame_builder.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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package frame
import (
"errors"
"github.com/function61/hautomo/pkg/ezstack/binstruct"
)
type frameConfiguration struct {
transactionIdProvider func() uint8
frameType FrameType
frameTypeConfigured bool
manufacturerCode uint16
manufacturerCodeConfigured bool
direction Direction
directionConfigured bool
disableDefaultResponse bool
disableDefaultResponseConfigured bool
commandId uint8
commandIdConfigured bool
command interface{}
commandConfigured bool
}
type Builder interface {
FrameType(frameType FrameType) Builder
ManufacturerCode(manufacturerCode uint16) Builder
Direction(direction Direction) Builder
DisableDefaultResponse(disableDefaultResponse bool) Builder
CommandId(commandId uint8) Builder
Command(command interface{}) Builder
Build() (*Frame, error)
}
var (
defaultTransactionIdProvider = MakeDefaultTransactionIdProvider()
)
func New() Builder {
return &frameConfiguration{transactionIdProvider: defaultTransactionIdProvider}
}
func (f *frameConfiguration) IdGenerator(transactionIdProvider func() uint8) Builder {
f.transactionIdProvider = transactionIdProvider
return f
}
func (f *frameConfiguration) FrameType(frameType FrameType) Builder {
f.frameType = frameType
f.frameTypeConfigured = true
return f
}
func (f *frameConfiguration) ManufacturerCode(manufacturerCode uint16) Builder {
f.manufacturerCode = manufacturerCode
f.manufacturerCodeConfigured = true
return f
}
func (f *frameConfiguration) Direction(direction Direction) Builder {
f.direction = direction
f.directionConfigured = true
return f
}
func (f *frameConfiguration) DisableDefaultResponse(disableDefaultResponse bool) Builder {
f.disableDefaultResponse = disableDefaultResponse
f.disableDefaultResponseConfigured = true
return f
}
func (f *frameConfiguration) CommandId(commandId uint8) Builder {
f.commandId = commandId
f.commandIdConfigured = true
return f
}
func (f *frameConfiguration) Command(command interface{}) Builder {
f.command = command
f.commandConfigured = true
return f
}
func (f *frameConfiguration) Build() (*Frame, error) {
if err := f.validateConfiguration(); err != nil {
return nil, err
}
// FIXME: why not []byte ?
payload := func() []uint8 {
if f.commandConfigured {
return binstruct.Encode(f.command)
} else {
return []uint8{} // FIXME: why not nil?
}
}()
return &Frame{
FrameControl: &FrameControl{
FrameType: f.frameType,
ManufacturerSpecific: flag(f.manufacturerCodeConfigured),
Direction: f.direction,
DisableDefaultResponse: flag(f.disableDefaultResponse),
},
ManufacturerCode: f.manufacturerCode,
TransactionSequenceNumber: f.transactionIdProvider(),
CommandIdentifier: f.commandId,
Payload: payload,
}, nil
}
func (f *frameConfiguration) validateConfiguration() error {
if !f.frameTypeConfigured {
return errors.New("frame type must be set")
}
if !f.commandIdConfigured {
return errors.New("command id must be set")
}
if !f.directionConfigured {
return errors.New("direction must be set")
}
return nil
}
func flag(flag bool) uint8 {
if flag {
return 1
} else {
return 0
}
}
func MakeDefaultTransactionIdProvider() func() uint8 {
transactionId := uint8(1)
return func() uint8 {
transactionId = transactionId + 1
if transactionId > 255 {
transactionId = 1
}
return transactionId
}
}