Serial port read with while-loop

I wrote a short program in Go to communicate with the sensor via the serial port:

package main import ( "fmt" "github.com/tarm/goserial" "time" ) func main() { c := &serial.Config{Name: "/dev/ttyUSB0", Baud: 9600} s, err := serial.OpenPort(c) if err != nil { fmt.Println(err) } _, err = s.Write([]byte("\x16\x02N0C0 GA\x03\x0d\x0a")) if err != nil { fmt.Println(err) } time.Sleep(time.Second/2) buf := make([]byte, 40) n, err := s.Read(buf) if err != nil { fmt.Println(err) } fmt.Println(string(buf[:n])) s.Close() } 

It works fine, but after writing to the port, I need to wait about a second and a half before I start reading from it. I would like to use a while-loop instead of time.Sleep to read all incoming data. My attempt does not work:

 buf := make([]byte, 40) n := 0 for { n, _ := s.Read(buf) if n > 0 { break } } fmt.Println(string(buf[:n])) 

I think buf gets a rewrite after each loop iteration. Any suggestions?

+6
source share
2 answers

Your problem is that Read() will be returned whenever it has some data - it will not wait for all the data. See the io.Reader specification for more information.

What you want to do is read until you reach a separator. I don’t know exactly what format you are trying to use, but it looks like \x0a is the trailing delimiter.

In this case, you would use bufio.Reader like this

 reader := bufio.NewReader(s) reply, err := reader.ReadBytes('\x0a') if err != nil { panic(err) } fmt.Println(reply) 

Which will read data before the first \x0a .

+9
source

I think buf gets a rewrite after each loop iteration. Any suggestions?

Yes, buf will be overwritten every time Read() called.

A file descriptor timeout would be the approach I would use.

 s, _ := os.OpenFile("/dev/ttyS0", syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0666) t := syscall.Termios{ Iflag: syscall.IGNPAR, Cflag: syscall.CS8 | syscall.CREAD | syscall.CLOCAL | syscall.B115200, Cc: [32]uint8{syscall.VMIN: 0, syscall.VTIME: uint8(20)}, //2.0s timeout Ispeed: syscall.B115200, Ospeed: syscall.B115200, } // syscall syscall.Syscall6(syscall.SYS_IOCTL, uintptr(s.Fd()), uintptr(syscall.TCSETS), uintptr(unsafe.Pointer(&t)), 0, 0, 0) // Send message n, _ := s.Write([]byte("Test message")) // Receive reply for { buf := make([]byte, 128) n, err = s.Read(buf) if err != nil { // err will equal io.EOF break } fmt.Printf("%v\n", string(buf)) } 

Also note: if there is no more data reading and no error, os.File.Read () will return an io.EOF error, as you can see here.

+1
source

Source: https://habr.com/ru/post/949249/


All Articles