Skip to content

Add serial binary communication #653

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 37 commits into from
Aug 18, 2021
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
895cc03
update bufferflow_timedraw as bufferflow_timed
umbynos Jul 15, 2021
05ee6f5
remove old commands
umbynos Jul 15, 2021
6a50f87
remove utf8 decoding with timedraw buffer type
umbynos Jul 19, 2021
e80400b
binary support (WIP)
umbynos Jul 19, 2021
eb2b3f3
use switch case
umbynos Jul 20, 2021
1cd174a
fixed test deps
umbynos Mar 1, 2021
48cc695
socketio test connection is working 🎉 (with the correct python-socket…
umbynos Mar 4, 2021
fc1222e
add callback to capture returned message, add new test for serial
umbynos Jul 21, 2021
9c7d3f8
fix tests: "socketio.exceptions.ConnectionError: Connection refused b…
umbynos Jul 21, 2021
dfcc14e
minor optimizations: data and buf are already an array of bytes
umbynos Jul 23, 2021
b7f70f1
enhanced a bit how the logic of the serial works
umbynos Jul 23, 2021
c86bb4f
enhance a lot test on serial communication (with different buffer types)
umbynos Jul 23, 2021
099a575
update and enhance commands output (the space in front of `<` and `>`…
umbynos Jul 23, 2021
b41d0cc
increased sleeptime, remove harcoded message[i]: should work on diffe…
umbynos Jul 29, 2021
fcaa53c
generalize the tests
umbynos Jul 29, 2021
43451a3
Apply suggestions from code review
umbynos Aug 2, 2021
15af2e4
add sketch used for testing
umbynos Aug 2, 2021
575efa1
Fix panic closing closed channel
silvanocerza Aug 3, 2021
2d78733
apply suggestions
umbynos Aug 3, 2021
8f9ff20
Partially revert #e80400b7ddbbc2e8f34f1e6701b55102c3a99289
umbynos Aug 3, 2021
0bbb45b
🧹(cleanup) and 🛠️(refactoring) of bufferflow stuff
umbynos Aug 4, 2021
5e2ad37
extract code in helper function and uniform the code
umbynos Aug 4, 2021
5d0bd27
optimize the handling of data coming from the serial port
umbynos Aug 4, 2021
f3d5dca
uniform default bufferflow and 🧹
umbynos Aug 4, 2021
5db1975
forgot to fix this in #621
umbynos Aug 4, 2021
37cf997
apply suggestions from code review ✨
umbynos Aug 5, 2021
724de59
remove timedbinary: it's the same as timedraw except for the casting
umbynos Aug 5, 2021
402a848
Escape html commands string
silvanocerza Aug 6, 2021
d5228ec
forgot to remove timed_binary
umbynos Aug 6, 2021
bcf0023
remove useless id field (was unused)
umbynos Aug 9, 2021
d077ded
remove useless channel done & other stuff
umbynos Aug 9, 2021
d704dd2
make sendNoBuf more general: will be used later 😏
umbynos Aug 10, 2021
791b03e
add `sendraw` command to send base64 encoded bytes, add tests (for se…
umbynos Aug 11, 2021
8dadd0c
forgot to skip test_sendraw_serial on CI
umbynos Aug 11, 2021
500a1ee
update comments
umbynos Aug 12, 2021
a86a61a
refactor tests
umbynos Aug 12, 2021
a21ae9e
remove BlockUntilReady because it was unused
umbynos Aug 16, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion bufferflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
//"time"
)

var availableBufferAlgorithms = []string{"default", "timed", "timedraw"}
var availableBufferAlgorithms = []string{"default", "timed", "timedraw", "timedbinary"}

type BufferMsg struct {
Cmd string
Expand All @@ -19,6 +19,7 @@ type Bufferflow interface {
Init()
BlockUntilReady(cmd string, id string) (bool, bool) // implement this method
//JustQueue(cmd string, id string) bool // implement this method
OnIncomingDataBinary(data []byte)
OnIncomingData(data string) // implement this method
ClearOutSemaphore() // implement this method
BreakApartCommands(cmd string) []string // implement this method
Expand Down
4 changes: 4 additions & 0 deletions bufferflow_default.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ func (b *BufferflowDefault) BlockUntilReady(cmd string, id string) (bool, bool)
return true, false
}

// not implemented, we are gonna use OnIncomingData
func (b *BufferflowDefault) OnIncomingDataBinary(data []byte) {
}

func (b *BufferflowDefault) OnIncomingData(data string) {
//log.Printf("OnIncomingData() start. data:%v\n", data)
}
Expand Down
6 changes: 5 additions & 1 deletion bufferflow_timed.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type BufferflowTimed struct {

var (
bufferedOutput string
sPort string
sPort string
)

func (b *BufferflowTimed) Init() {
Expand Down Expand Up @@ -61,6 +61,10 @@ func (b *BufferflowTimed) BlockUntilReady(cmd string, id string) (bool, bool) {
return true, false
}

// not implemented, we are gonna use OnIncomingData
func (b *BufferflowTimed) OnIncomingDataBinary(data []byte) {
}

func (b *BufferflowTimed) OnIncomingData(data string) {
b.Input <- data
}
Expand Down
114 changes: 114 additions & 0 deletions bufferflow_timedbinary.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package main

import (
"encoding/json"
"time"

log "github.com/sirupsen/logrus"
)

type BufferflowTimedBinary struct {
Name string
Port string
Output chan []byte
Input chan []byte
done chan bool
ticker *time.Ticker
}

var (
bufferedOutputBinary []byte
sPortBinary string
)

func (b *BufferflowTimedBinary) Init() {
log.Println("Initting timed buffer binary flow (output once every 16ms)")
bufferedOutputBinary = nil
sPortBinary = ""

go func() {
b.ticker = time.NewTicker(16 * time.Millisecond)
b.done = make(chan bool)
Loop:
for {
select {
case data := <-b.Input:
bufferedOutputBinary = append(bufferedOutputBinary, data...)
sPortBinary = b.Port
case <-b.ticker.C:
if bufferedOutputBinary != nil {
m := SpPortMessageRaw{sPortBinary, bufferedOutputBinary}
buf, _ := json.Marshal(m)
b.Output <- buf
bufferedOutputBinary = nil
sPortBinary = ""
}
case <-b.done:
break Loop
}
}

close(b.Input)
}()
}

func (b *BufferflowTimedBinary) BlockUntilReady(cmd string, id string) (bool, bool) {
//log.Printf("BlockUntilReady() start\n")
return true, false
}

func (b *BufferflowTimedBinary) OnIncomingDataBinary(data []byte) {
b.Input <- data
}

// not implemented, we are gonna use OnIncomingDataBinary
func (b *BufferflowTimedBinary) OnIncomingData(data string) {
}

// Clean out b.sem so it can truly block
func (b *BufferflowTimedBinary) ClearOutSemaphore() {
}

func (b *BufferflowTimedBinary) BreakApartCommands(cmd string) []string {
return []string{cmd}
}

func (b *BufferflowTimedBinary) Pause() {
return
}

func (b *BufferflowTimedBinary) Unpause() {
return
}

func (b *BufferflowTimedBinary) SeeIfSpecificCommandsShouldSkipBuffer(cmd string) bool {
return false
}

func (b *BufferflowTimedBinary) SeeIfSpecificCommandsShouldPauseBuffer(cmd string) bool {
return false
}

func (b *BufferflowTimedBinary) SeeIfSpecificCommandsShouldUnpauseBuffer(cmd string) bool {
return false
}

func (b *BufferflowTimedBinary) SeeIfSpecificCommandsShouldWipeBuffer(cmd string) bool {
return false
}

func (b *BufferflowTimedBinary) SeeIfSpecificCommandsReturnNoResponse(cmd string) bool {
return false
}

func (b *BufferflowTimedBinary) ReleaseLock() {
}

func (b *BufferflowTimedBinary) IsBufferGloballySendingBackIncomingData() bool {
return true
}

func (b *BufferflowTimedBinary) Close() {
b.ticker.Stop()
close(b.Input)
}
46 changes: 30 additions & 16 deletions bufferflow_timedraw.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,43 +12,57 @@ type BufferflowTimedRaw struct {
Port string
Output chan []byte
Input chan string
done chan bool
ticker *time.Ticker
}

var (
bufferedOutputRaw []byte
sPortRaw string
)

func (b *BufferflowTimedRaw) Init() {
log.Println("Initting timed buffer flow (output once every 16ms)")

go func() {
for data := range b.Input {
bufferedOutputRaw = append(bufferedOutputRaw, []byte(data)...)
}
}()
log.Println("Initting timed buffer raw flow (output once every 16ms)")
bufferedOutputRaw = nil
sPortRaw = ""

go func() {
b.ticker = time.NewTicker(16 * time.Millisecond)
for _ = range b.ticker.C {
if len(bufferedOutputRaw) != 0 {
m := SpPortMessageRaw{b.Port, bufferedOutputRaw}
buf, _ := json.Marshal(m)
// data is now encoded in base64 format
// need a decoder on the other side
b.Output <- []byte(buf)
bufferedOutputRaw = nil
b.done = make(chan bool)
Loop:
for {
select {
case data := <-b.Input:
bufferedOutputRaw = append(bufferedOutputRaw, []byte(data)...)
sPortRaw = b.Port
case <-b.ticker.C:
if bufferedOutputRaw != nil {
m := SpPortMessageRaw{sPortRaw, bufferedOutputRaw}
buf, _ := json.Marshal(m)
// data is now encoded in base64 format
// need a decoder on the other side
b.Output <- []byte(buf)
bufferedOutputRaw = nil
sPortRaw = ""
}
case <-b.done:
break Loop
}
}
}()

close(b.Input)
}()
}

func (b *BufferflowTimedRaw) BlockUntilReady(cmd string, id string) (bool, bool) {
//log.Printf("BlockUntilReady() start\n")
return true, false
}

// not implemented, we are gonna use OnIncomingData
func (b *BufferflowTimedRaw) OnIncomingDataBinary(data []byte) {
}

func (b *BufferflowTimedRaw) OnIncomingData(data string) {
b.Input <- data
}
Expand Down
20 changes: 18 additions & 2 deletions hub.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,30 @@ var h = hub{
connections: make(map[*connection]bool),
}

const commands = "{\"Commands\": [" +
"\"list\", " +
"\"open < portName > < baud > [bufferAlgorithm: ({default}, timed, timedraw, timedbinary)]\", " +
"\"send < portName > < cmd >\", " +
"\"sendnobuf < portName > < cmd >\", " +
"\"close < portName >\", " +
"\"restart\", " +
"\"exit\", " +
"\"killupload\", " +
"\"downloadtool < tool > < toolVersion: {latest} > < pack: {arduino} > < behaviour: {keep} >\", " +
"\"log\", " +
"\"memorystats\", " +
"\"gc\", " +
"\"hostname\", " +
"\"version\"]} "

func (h *hub) run() {
for {
select {
case c := <-h.register:
h.connections[c] = true
// send supported commands
c.send <- []byte("{\"Version\" : \"" + version + "\"} ")
c.send <- []byte("{\"Commands\" : [\"list\", \"open [portName] [baud] [bufferAlgorithm (optional)]\", \"send [portName] [cmd]\", \"sendnobuf [portName] [cmd]\", \"close [portName]\", \"bufferalgorithms\", \"baudrates\", \"restart\", \"exit\", \"program [portName] [board:name] [$path/to/filename/without/extension]\", \"programfromurl [portName] [board:name] [urlToHexFile]\"]} ")
c.send <- []byte(commands)
c.send <- []byte("{\"Hostname\" : \"" + *hostname + "\"} ")
c.send <- []byte("{\"OS\" : \"" + runtime.GOOS + "\"} ")
case c := <-h.unregister:
Expand Down Expand Up @@ -127,7 +143,7 @@ func checkCmd(m []byte) {
}
// pass in buffer type now as string. if user does not
// ask for a buffer type pass in empty string
bufferAlgorithm := ""
bufferAlgorithm := "default" // use the default buffer if none is specified
if len(args) > 3 {
// cool. we got a buffer type request
buftype := strings.Replace(args[3], "\n", "", -1)
Expand Down
Loading