Skip to content

Commit 250b17c

Browse files
umbynosper1234silvanocerza
authored
Add serial binary communication (#653)
* update bufferflow_timedraw as bufferflow_timed * remove old commands * remove utf8 decoding with timedraw buffer type * binary support (WIP) * use switch case * fixed test deps * socketio test connection is working 🎉 (with the correct python-socketio version) * add callback to capture returned message, add new test for serial * fix tests: "socketio.exceptions.ConnectionError: Connection refused by the server" * minor optimizations: data and buf are already an array of bytes * enhanced a bit how the logic of the serial works * enhance a lot test on serial communication (with different buffer types) The tests should be skipped on the CI (no board connected) * update and enhance commands output (the space in front of `<` and `>` is required) 🤷‍♂️ * increased sleeptime, remove harcoded message[i]: should work on different systems * generalize the tests * Apply suggestions from code review Co-authored-by: per1234 <[email protected]> * add sketch used for testing * Fix panic closing closed channel * apply suggestions * Partially revert #e80400b7ddbbc2e8f34f1e6701b55102c3a99289 * 🧹(cleanup) and 🛠️(refactoring) of bufferflow stuff * extract code in helper function and uniform the code reintroduce the closing of input channel (it's required) * optimize the handling of data coming from the serial port * uniform default bufferflow and 🧹 * forgot to fix this in #621 * apply suggestions from code review ✨ * remove timedbinary: it's the same as timedraw except for the casting * Escape html commands string * forgot to remove timed_binary * remove useless id field (was unused) * remove useless channel done & other stuff * make sendNoBuf more general: will be used later 😏 * add `sendraw` command to send base64 encoded bytes, add tests (for send raw and for open/close port) * forgot to skip test_sendraw_serial on CI * update comments * refactor tests * remove BlockUntilReady because it was unused Co-authored-by: per1234 <[email protected]> Co-authored-by: Silvano Cerza <[email protected]>
1 parent 3bdd07d commit 250b17c

14 files changed

+644
-482
lines changed

bufferflow.go

+2-44
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,7 @@
11
package main
22

3-
import (
4-
//"log"
5-
//"time"
6-
)
7-
8-
var availableBufferAlgorithms = []string{"default", "timed", "timedraw"}
9-
10-
type BufferMsg struct {
11-
Cmd string
12-
Port string
13-
TriggeringResponse string
14-
//Desc string
15-
//Desc string
16-
}
17-
183
type Bufferflow interface {
194
Init()
20-
BlockUntilReady(cmd string, id string) (bool, bool) // implement this method
21-
//JustQueue(cmd string, id string) bool // implement this method
22-
OnIncomingData(data string) // implement this method
23-
ClearOutSemaphore() // implement this method
24-
BreakApartCommands(cmd string) []string // implement this method
25-
Pause() // implement this method
26-
Unpause() // implement this method
27-
SeeIfSpecificCommandsShouldSkipBuffer(cmd string) bool // implement this method
28-
SeeIfSpecificCommandsShouldPauseBuffer(cmd string) bool // implement this method
29-
SeeIfSpecificCommandsShouldUnpauseBuffer(cmd string) bool // implement this method
30-
SeeIfSpecificCommandsShouldWipeBuffer(cmd string) bool // implement this method
31-
SeeIfSpecificCommandsReturnNoResponse(cmd string) bool // implement this method
32-
ReleaseLock() // implement this method
33-
IsBufferGloballySendingBackIncomingData() bool // implement this method
34-
Close() // implement this method
35-
}
36-
37-
/*data packets returned to client*/
38-
type DataCmdComplete struct {
39-
Cmd string
40-
Id string
41-
P string
42-
BufSize int `json:"-"`
43-
D string `json:"-"`
44-
}
45-
46-
type DataPerLine struct {
47-
P string
48-
D string
5+
OnIncomingData(data string) // implement this method
6+
Close() // implement this method
497
}

bufferflow_default.go

+31-50
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,52 @@
11
package main
22

33
import (
4+
"encoding/json"
5+
46
log "github.com/sirupsen/logrus"
57
)
68

79
type BufferflowDefault struct {
8-
Name string
9-
Port string
10+
port string
11+
output chan<- []byte
12+
input chan string
13+
done chan bool
1014
}
1115

12-
var ()
16+
func NewBufferflowDefault(port string, output chan<- []byte) *BufferflowDefault {
17+
return &BufferflowDefault{
18+
port: port,
19+
output: output,
20+
input: make(chan string),
21+
done: make(chan bool),
22+
}
23+
}
1324

1425
func (b *BufferflowDefault) Init() {
1526
log.Println("Initting default buffer flow (which means no buffering)")
27+
go b.consumeInput()
1628
}
1729

18-
func (b *BufferflowDefault) BlockUntilReady(cmd string, id string) (bool, bool) {
19-
//log.Printf("BlockUntilReady() start\n")
20-
return true, false
30+
func (b *BufferflowDefault) consumeInput() {
31+
Loop:
32+
for {
33+
select {
34+
case data := <-b.input:
35+
m := SpPortMessage{b.port, data}
36+
message, _ := json.Marshal(m)
37+
b.output <- message
38+
case <-b.done:
39+
break Loop //this is required, a simple break statement would only exit the innermost switch statement
40+
}
41+
}
42+
close(b.input) // close the input channel at the end of the computation
2143
}
2244

2345
func (b *BufferflowDefault) OnIncomingData(data string) {
24-
//log.Printf("OnIncomingData() start. data:%v\n", data)
25-
}
26-
27-
// Clean out b.sem so it can truly block
28-
func (b *BufferflowDefault) ClearOutSemaphore() {
29-
}
30-
31-
func (b *BufferflowDefault) BreakApartCommands(cmd string) []string {
32-
return []string{cmd}
33-
}
34-
35-
func (b *BufferflowDefault) Pause() {
36-
return
37-
}
38-
39-
func (b *BufferflowDefault) Unpause() {
40-
return
41-
}
42-
43-
func (b *BufferflowDefault) SeeIfSpecificCommandsShouldSkipBuffer(cmd string) bool {
44-
return false
45-
}
46-
47-
func (b *BufferflowDefault) SeeIfSpecificCommandsShouldPauseBuffer(cmd string) bool {
48-
return false
49-
}
50-
51-
func (b *BufferflowDefault) SeeIfSpecificCommandsShouldUnpauseBuffer(cmd string) bool {
52-
return false
53-
}
54-
55-
func (b *BufferflowDefault) SeeIfSpecificCommandsShouldWipeBuffer(cmd string) bool {
56-
return false
57-
}
58-
59-
func (b *BufferflowDefault) SeeIfSpecificCommandsReturnNoResponse(cmd string) bool {
60-
return false
61-
}
62-
63-
func (b *BufferflowDefault) ReleaseLock() {
64-
}
65-
66-
func (b *BufferflowDefault) IsBufferGloballySendingBackIncomingData() bool {
67-
return false
46+
b.input <- data
6847
}
6948

7049
func (b *BufferflowDefault) Close() {
50+
b.done <- true
51+
close(b.done)
7152
}

bufferflow_timed.go

+41-88
Original file line numberDiff line numberDiff line change
@@ -8,104 +8,57 @@ import (
88
)
99

1010
type BufferflowTimed struct {
11-
Name string
12-
Port string
13-
Output chan []byte
14-
Input chan string
15-
done chan bool
16-
ticker *time.Ticker
11+
port string
12+
output chan<- []byte
13+
input chan string
14+
done chan bool
15+
ticker *time.Ticker
16+
sPort string
17+
bufferedOutput string
1718
}
1819

19-
var (
20-
bufferedOutput string
21-
sPort string
22-
)
20+
func NewBufferflowTimed(port string, output chan<- []byte) *BufferflowTimed {
21+
return &BufferflowTimed{
22+
port: port,
23+
output: output,
24+
input: make(chan string),
25+
done: make(chan bool),
26+
ticker: time.NewTicker(16 * time.Millisecond),
27+
sPort: "",
28+
bufferedOutput: "",
29+
}
30+
}
2331

2432
func (b *BufferflowTimed) Init() {
2533
log.Println("Initting timed buffer flow (output once every 16ms)")
26-
bufferedOutput = ""
27-
sPort = ""
28-
29-
go func() {
30-
b.ticker = time.NewTicker(16 * time.Millisecond)
31-
b.done = make(chan bool)
32-
Loop:
33-
for {
34-
select {
35-
case data := <-b.Input:
36-
bufferedOutput = bufferedOutput + data
37-
sPort = b.Port
38-
case <-b.ticker.C:
39-
if bufferedOutput != "" {
40-
m := SpPortMessage{sPort, bufferedOutput}
41-
buf, _ := json.Marshal(m)
42-
// data is now encoded in base64 format
43-
// need a decoder on the other side
44-
b.Output <- []byte(buf)
45-
bufferedOutput = ""
46-
sPort = ""
47-
}
48-
case <-b.done:
49-
break Loop
34+
go b.consumeInput()
35+
}
36+
37+
func (b *BufferflowTimed) consumeInput() {
38+
Loop:
39+
for {
40+
select {
41+
case data := <-b.input: // use the buffer and append data to it
42+
b.bufferedOutput = b.bufferedOutput + data
43+
b.sPort = b.port
44+
case <-b.ticker.C: // after 16ms send the buffered output message
45+
if b.bufferedOutput != "" {
46+
m := SpPortMessage{b.sPort, b.bufferedOutput}
47+
buf, _ := json.Marshal(m)
48+
b.output <- buf
49+
// reset the buffer and the port
50+
b.bufferedOutput = ""
51+
b.sPort = ""
5052
}
53+
case <-b.done:
54+
break Loop //this is required, a simple break statement would only exit the innermost switch statement
5155
}
52-
53-
close(b.Input)
54-
55-
}()
56-
57-
}
58-
59-
func (b *BufferflowTimed) BlockUntilReady(cmd string, id string) (bool, bool) {
60-
//log.Printf("BlockUntilReady() start\n")
61-
return true, false
56+
}
57+
close(b.input)
6258
}
6359

6460
func (b *BufferflowTimed) OnIncomingData(data string) {
65-
b.Input <- data
66-
}
67-
68-
// Clean out b.sem so it can truly block
69-
func (b *BufferflowTimed) ClearOutSemaphore() {
70-
}
71-
72-
func (b *BufferflowTimed) BreakApartCommands(cmd string) []string {
73-
return []string{cmd}
74-
}
75-
76-
func (b *BufferflowTimed) Pause() {
77-
return
78-
}
79-
80-
func (b *BufferflowTimed) Unpause() {
81-
return
82-
}
83-
84-
func (b *BufferflowTimed) SeeIfSpecificCommandsShouldSkipBuffer(cmd string) bool {
85-
return false
86-
}
87-
88-
func (b *BufferflowTimed) SeeIfSpecificCommandsShouldPauseBuffer(cmd string) bool {
89-
return false
90-
}
91-
92-
func (b *BufferflowTimed) SeeIfSpecificCommandsShouldUnpauseBuffer(cmd string) bool {
93-
return false
94-
}
95-
96-
func (b *BufferflowTimed) SeeIfSpecificCommandsShouldWipeBuffer(cmd string) bool {
97-
return false
98-
}
99-
100-
func (b *BufferflowTimed) SeeIfSpecificCommandsReturnNoResponse(cmd string) bool {
101-
return false
102-
}
103-
104-
func (b *BufferflowTimed) ReleaseLock() {
105-
}
106-
107-
func (b *BufferflowTimed) IsBufferGloballySendingBackIncomingData() bool {
108-
return true
61+
b.input <- data
10962
}
11063

11164
func (b *BufferflowTimed) Close() {

0 commit comments

Comments
 (0)