Skip to content
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

Add serial binary communication #653

Merged
merged 37 commits into from
Aug 18, 2021
Merged

Add serial binary communication #653

merged 37 commits into from
Aug 18, 2021

Conversation

umbynos
Copy link
Contributor

@umbynos umbynos commented Jul 30, 2021

Please check if the PR fulfills these requirements

  • The PR has no duplicates (please search among the Pull Requests
    before creating one)
  • Tests for the changes have been added (for bug fixes / features)
  • What kind of change does this PR introduce?

feature

  • What is the current behavior?

no serial binary communication

  • What is the new behavior?

serial binary communication have been added back: now you can open a serial with this buffer type by using open <port> <baud> timedraw command, once the socketio connection has been established.
To send binary data you have to base64 encode yourself and use sendraw <port> base64_encoded_binary
Tests have been added:

  • test_ws_connection and test_list should work even on the CI

  • other tests aim to verify if the communication through the serial works correctly, so you have to run them locally (poetry run pytest test/test_ws.py) with a board connected and the sketch present in test/testdata/SerialEcho/SerialEcho.ino already flashed

  • Does this PR introduce a breaking change?

it should not

  • Other information:

@umbynos umbynos added type: enhancement Proposed improvement topic: code Related to content of the project itself go labels Jul 30, 2021
@umbynos umbynos requested a review from a team July 30, 2021 14:15
@umbynos umbynos self-assigned this Jul 30, 2021
@umbynos
Copy link
Contributor Author

umbynos commented Jul 30, 2021

I still have to produce some docs

serialport.go Outdated Show resolved Hide resolved
@umbynos umbynos changed the title Umbynos/serial binary Add serial binary communication Jul 30, 2021
serialport.go Outdated Show resolved Hide resolved
serialport.go Outdated Show resolved Hide resolved
test/test_ws.py Outdated Show resolved Hide resolved
test/test_ws.py Outdated Show resolved Hide resolved
test/test_ws.py Outdated Show resolved Hide resolved
umbynos and others added 2 commits August 2, 2021 10:53
Co-authored-by: per1234 <accounts@perglass.com>
@umbynos umbynos requested a review from silvanocerza August 2, 2021 09:10
test/common.py Outdated Show resolved Hide resolved
hub.go Outdated Show resolved Hide resolved
bufferflow.go Outdated Show resolved Hide resolved
bufferflow_timedbinary.go Outdated Show resolved Hide resolved
bufferflow_timedbinary.go Outdated Show resolved Hide resolved
bufferflow_timedbinary.go Outdated Show resolved Hide resolved
@umbynos umbynos requested a review from silvanocerza August 4, 2021 16:07
bufferflow.go Outdated Show resolved Hide resolved
bufferflow_timedraw.go Outdated Show resolved Hide resolved
hub.go Outdated Show resolved Hide resolved
Copy link
Contributor

@silvanocerza silvanocerza left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comments.

@umbynos
Copy link
Contributor Author

umbynos commented Aug 5, 2021

This is the diff I'm taking about, the only difference is the location of the casting. Apart from it they are the same. Removing timedbinary

--- /home/umberto/Nextcloud/8tb/Lavoro/arduino-create-agent/bufferflow_timedraw.go
+++ /home/umberto/Nextcloud/8tb/Lavoro/arduino-create-agent/bufferflow_timedbinary.go
@@ -7,50 +7,50 @@
 	log "github.com/sirupsen/logrus"
 )
 
-type BufferflowTimedRaw struct {
-	port              string
-	output            chan<- []byte
-	input             chan string
-	done              chan bool
-	ticker            *time.Ticker
-	bufferedOutputRaw []byte
-	sPortRaw          string
+type BufferflowTimedBinary struct {
+	port                 string
+	output               chan<- []byte
+	input                chan []byte
+	done                 chan bool
+	ticker               *time.Ticker
+	bufferedOutputBinary []byte
+	sPortBinary          string
 }
 
-func NewBufferflowTimedRaw(port string, output chan<- []byte) *BufferflowTimedRaw {
-	return &BufferflowTimedRaw{
-		port:              port,
-		output:            output,
-		input:             make(chan string),
-		done:              make(chan bool),
-		ticker:            time.NewTicker(16 * time.Millisecond),
-		bufferedOutputRaw: nil,
-		sPortRaw:          "",
+func NewBufferflowTimedBinary(port string, output chan<- []byte) *BufferflowTimedBinary {
+	return &BufferflowTimedBinary{
+		port:                 port,
+		output:               output,
+		input:                make(chan []byte),
+		done:                 make(chan bool),
+		ticker:               time.NewTicker(16 * time.Millisecond),
+		bufferedOutputBinary: nil,
+		sPortBinary:          "",
 	}
 }
 
-func (b *BufferflowTimedRaw) Init() {
-	log.Println("Initting timed buffer raw flow (output once every 16ms)")
+func (b *BufferflowTimedBinary) Init() {
+	log.Println("Initting timed buffer binary flow (output once every 16ms)")
 	go b.consumeInput()
 }
 
-func (b *BufferflowTimedRaw) consumeInput() {
+func (b *BufferflowTimedBinary) consumeInput() {
 Loop:
 	for {
 		select {
 		case data := <-b.input: // use the buffer and append data to it
-			b.bufferedOutputRaw = append(b.bufferedOutputRaw, []byte(data)...)
-			b.sPortRaw = b.port
+			b.bufferedOutputBinary = append(b.bufferedOutputBinary, data...)
+			b.sPortBinary = b.port
 		case <-b.ticker.C: // after 16ms send the buffered output message
-			if b.bufferedOutputRaw != nil {
-				m := SpPortMessageRaw{b.sPortRaw, b.bufferedOutputRaw}
+			if b.bufferedOutputBinary != nil {
+				m := SpPortMessageRaw{b.sPortBinary, b.bufferedOutputBinary}
 				buf, _ := json.Marshal(m)
 				// data is now encoded in base64 format
 				// need a decoder on the other side
 				b.output <- buf
 				// reset the buffer and the port
-				b.bufferedOutputRaw = nil
-				b.sPortRaw = ""
+				b.bufferedOutputBinary = nil
+				b.sPortBinary = ""
 			}
 		case <-b.done:
 			break Loop //this is required, a simple break statement would only exit the innermost switch statement
@@ -59,16 +59,16 @@
 	close(b.input)
 }
 
-func (b *BufferflowTimedRaw) BlockUntilReady(cmd string, id string) (bool, bool) {
+func (b *BufferflowTimedBinary) BlockUntilReady(cmd string, id string) (bool, bool) {
 	//log.Printf("BlockUntilReady() start\n")
 	return true, false
 }
 
-func (b *BufferflowTimedRaw) OnIncomingData(data string) {
-	b.input <- data
+func (b *BufferflowTimedBinary) OnIncomingData(data string) {
+	b.input <- []byte(data)
 }
 
-func (b *BufferflowTimedRaw) Close() {
+func (b *BufferflowTimedBinary) Close() {
 	b.ticker.Stop()
 	b.done <- true
 	close(b.done)

@umbynos
Copy link
Contributor Author

umbynos commented Aug 5, 2021

I prepared a Release Candidate to test the functionality out.

@umbynos umbynos requested a review from silvanocerza August 12, 2021 11:03
@umbynos
Copy link
Contributor Author

umbynos commented Aug 12, 2021

@umbynos umbynos requested a review from cmaglie August 13, 2021 07:31
Copy link
Member

@cmaglie cmaglie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good, if you have tested it, it's ok to merge IMHO.

buffered_ch.Reset()
for i, w := 0, 0; i < n; i += w {
runeValue, width := utf8.DecodeRune(bufferPart[i:n]) // try to decode the first i bytes in the buffer (UTF8 runes do not have a fixed length)
if runeValue == utf8.RuneError {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As it is, this loop won't go over a malformed UTF8 sequence. If the UTF8 rune is incomplete it will be completed over multiple iterations, but if the UTF8 rune is corrupted the loop won't go past it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW I see that it's the same loop as before, so it may be fixed in another PR if needed.

serialport.go Outdated Show resolved Hide resolved
@umbynos umbynos merged commit 250b17c into main Aug 18, 2021
@umbynos umbynos deleted the umbynos/serial_binary branch August 18, 2021 08:32
umbynos added a commit that referenced this pull request Aug 18, 2021
* 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 <accounts@perglass.com>

* 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 <accounts@perglass.com>
Co-authored-by: Silvano Cerza <silvanocerza@gmail.com>
@umbynos umbynos mentioned this pull request Sep 15, 2021
2 tasks
@rsora rsora added the go label Sep 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: code Related to content of the project itself type: enhancement Proposed improvement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants