Skip to content

Commit 8aac217

Browse files
committed
Fix sdo_writer not detecting emergency messages by skipping wrong arbitration ids
1 parent e308e4a commit 8aac217

File tree

7 files changed

+402
-75
lines changed

7 files changed

+402
-75
lines changed

.devcontainer/devcontainer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
2-
"name": "CANOPENREST",
2+
"name": "GoCanOpen",
33
"image": "devcontainer-go-dev:latest",
44
"runArgs": [
5-
"--name=CANOPENREST_Devcontainer"
5+
"--name=GoCanOpen_Devcontainer"
66
],
77
"customizations": {
88
// Configure properties specific to VS Code.

interfaces.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package canopen
2+
3+
import (
4+
"time"
5+
6+
"github.com/angelodlfrtr/go-can"
7+
)
8+
9+
type ISDOClient interface {
10+
FindName(name string) DicObject
11+
Read(index uint16, subIndex uint8) ([]byte, error)
12+
Send(req []byte, expectFunc networkFramesChanFilterFunc, timeout *time.Duration, retryCount *int) (*can.Frame, error)
13+
SendRequest(req []byte) error
14+
Write(index uint16, subIndex uint8, forceSegment bool, data []byte) error
15+
}
16+
17+
type INode interface {
18+
GetId() int
19+
FindName(name string) DicObject
20+
Send(arbID uint32, data []byte) error
21+
AcquireFramesChanFromNetwork(filterFunc networkFramesChanFilterFunc) *NetworkFramesChan
22+
ReleaseFramesChanFromNetwork(id string)
23+
}

node.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package canopen
22

3+
import "errors"
4+
35
// Node is a canopen node
46
type Node struct {
57
// Each node has an id, which is ArbitrationID & 0x7F
@@ -23,6 +25,42 @@ func NewNode(id int, network *Network, objectDic *DicObjectDic) *Node {
2325
return node
2426
}
2527

28+
// GetId returns Node ID
29+
func (node *Node) GetId() int {
30+
return node.ID
31+
}
32+
33+
// FindName gets DicObject from ObjectDic
34+
func (node *Node) FindName(name string) DicObject {
35+
if node.ObjectDic == nil {
36+
return nil
37+
}
38+
return node.ObjectDic.FindName(name)
39+
}
40+
41+
// Send sends Frame with arbitration ID by connected network
42+
func (node *Node) Send(arbID uint32, data []byte) error {
43+
if node.Network == nil {
44+
return errors.New("Network not defined")
45+
}
46+
return node.Network.Send(arbID, data)
47+
}
48+
49+
// AcquireFramesChanFromNetwork gets new Channel for given FilterFunc
50+
func (node *Node) AcquireFramesChanFromNetwork(filterFunc networkFramesChanFilterFunc) *NetworkFramesChan {
51+
if node.Network == nil {
52+
return nil
53+
}
54+
return node.Network.AcquireFramesChan(filterFunc)
55+
}
56+
57+
// ReleaseFramesChanFromNetwork free channel with given id from network
58+
func (node *Node) ReleaseFramesChanFromNetwork(id string) {
59+
if node.Network != nil {
60+
node.Network.ReleaseFramesChan(id)
61+
}
62+
}
63+
2664
// SetNetwork set node.Network to the desired network
2765
func (node *Node) SetNetwork(network *Network) {
2866
node.Network = network

sdo.go

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -26,29 +26,29 @@ const (
2626

2727
// SDOClient represent an SDO client
2828
type SDOClient struct {
29-
Node *Node
29+
Node INode
3030
RXCobID uint32
3131
TXCobID uint32
3232
SendQueue []string
3333
}
3434

35-
func NewSDOClient(node *Node) *SDOClient {
35+
func NewSDOClient(node INode) *SDOClient {
3636
return &SDOClient{
3737
Node: node,
38-
RXCobID: uint32(0x600 + node.ID),
39-
TXCobID: uint32(0x580 + node.ID),
38+
RXCobID: uint32(0x600 + node.GetId()),
39+
TXCobID: uint32(0x580 + node.GetId()),
4040
SendQueue: []string{},
4141
}
4242
}
4343

4444
// SendRequest to network bus
4545
func (sdoClient *SDOClient) SendRequest(req []byte) error {
46-
return sdoClient.Node.Network.Send(sdoClient.RXCobID, req)
46+
return sdoClient.Node.Send(sdoClient.RXCobID, req)
4747
}
4848

4949
// FindName find an sdo object from object dictionary by name
5050
func (sdoClient *SDOClient) FindName(name string) DicObject {
51-
if ob := sdoClient.Node.ObjectDic.FindName(name); ob != nil {
51+
if ob := sdoClient.Node.FindName(name); ob != nil {
5252
ob.SetSDO(sdoClient)
5353
return ob
5454
}
@@ -83,12 +83,22 @@ func (sdoClient *SDOClient) Send(
8383
retryCount = &rtc
8484
}
8585

86-
framesChan := sdoClient.Node.Network.AcquireFramesChan(expectFunc)
86+
var expectSdoFunc networkFramesChanFilterFunc
87+
if expectFunc != nil {
88+
expectSdoFilterFunc := func(frm *can.Frame) bool {
89+
arbitrationId := frm.ArbitrationID
90+
if arbitrationId != sdoClient.TXCobID {
91+
return false
92+
}
93+
return (*expectFunc)(frm)
94+
}
95+
expectSdoFunc = &expectSdoFilterFunc
96+
}
97+
framesChan := sdoClient.Node.AcquireFramesChanFromNetwork(expectSdoFunc)
98+
defer sdoClient.Node.ReleaseFramesChanFromNetwork(framesChan.ID)
8799

88100
// Retry loop
89101
remainingCount := *retryCount
90-
var frm *can.Frame
91-
92102
for {
93103
if remainingCount == 0 {
94104
break
@@ -100,32 +110,27 @@ func (sdoClient *SDOClient) Send(
100110

101111
timer := time.NewTimer(*timeout)
102112

103-
select {
104-
case <-timer.C:
105-
// Double timeout for each retry
106-
newTimeout := *timeout * 2
107-
timeout = &newTimeout
108-
case fr := <-framesChan.C:
109-
frm = fr
113+
loop := true
114+
for {
115+
if !loop {
116+
break
117+
}
118+
select {
119+
case <-timer.C:
120+
// Double timeout for each retry
121+
newTimeout := *timeout * 2
122+
timeout = &newTimeout
123+
loop = false
124+
case fr := <-framesChan.C:
125+
return fr, nil
126+
}
110127
}
111128

112129
timer.Stop()
113130
remainingCount--
114-
115-
if frm != nil {
116-
break
117-
}
118-
}
119-
120-
// Release data chan
121-
sdoClient.Node.Network.ReleaseFramesChan(framesChan.ID)
122-
123-
// If no frm, timeout execeded
124-
if frm == nil {
125-
return nil, errors.New("timeout execeded")
126131
}
127132

128-
return frm, nil
133+
return nil, errors.New("timeout execeded")
129134
}
130135

131136
// Read sdo

0 commit comments

Comments
 (0)