-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbus_manager.go
104 lines (94 loc) · 2.29 KB
/
bus_manager.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
package canopen
import (
"log/slog"
"sync"
)
// Bus manager is a wrapper around the CAN bus interface
// Used by the CANopen stack to control errors, callbacks for specific IDs, etc.
type BusManager struct {
logger *slog.Logger
mu sync.Mutex
bus Bus // Bus interface that can be adapted
frameListeners map[uint32][]FrameListener
canError uint16
}
// Implements the FrameListener interface
// This handles all received CAN frames from Bus
// [listener.Handle] should not be blocking !
func (bm *BusManager) Handle(frame Frame) {
bm.mu.Lock()
defer bm.mu.Unlock()
listeners, ok := bm.frameListeners[frame.ID]
if !ok {
return
}
for _, listener := range listeners {
listener.Handle(frame)
}
}
// Set bus
func (bm *BusManager) SetBus(bus Bus) {
bm.mu.Lock()
defer bm.mu.Unlock()
bm.bus = bus
}
func (bm *BusManager) Bus() Bus {
bm.mu.Lock()
defer bm.mu.Unlock()
return bm.bus
}
// Send a CAN message
// Limited error handling
func (bm *BusManager) Send(frame Frame) error {
err := bm.bus.Send(frame)
if err != nil {
bm.logger.Warn("error sending frame", "err", err)
}
return err
}
// This should be called cyclically to update errors
func (bm *BusManager) Process() error {
bm.mu.Lock()
defer bm.mu.Unlock()
// TODO get bus state error
bm.canError = 0
return nil
}
// Subscribe to a specific CAN ID
func (bm *BusManager) Subscribe(ident uint32, mask uint32, rtr bool, callback FrameListener) error {
bm.mu.Lock()
defer bm.mu.Unlock()
ident = ident & CanSffMask
if rtr {
ident |= CanRtrFlag
}
_, ok := bm.frameListeners[ident]
if !ok {
bm.frameListeners[ident] = []FrameListener{callback}
return nil
}
// Iterate over all callbacks and verify that we are not adding the same one twice
for _, cb := range bm.frameListeners[ident] {
if cb == callback {
bm.logger.Warn("callback for frame already present", "id", ident)
return nil
}
}
bm.frameListeners[ident] = append(bm.frameListeners[ident], callback)
return nil
}
// Get CAN error
func (bm *BusManager) Error() uint16 {
bm.mu.Lock()
defer bm.mu.Unlock()
return bm.canError
}
func NewBusManager(bus Bus) *BusManager {
bm := &BusManager{
bus: bus,
logger: slog.Default(),
frameListeners: make(map[uint32][]FrameListener),
canError: 0,
}
return bm
}