bugst / go-serial

A cross-platform serial library for go-lang.
BSD 3-Clause "New" or "Revised" License
617 stars 188 forks source link

Always return 1 byte of data #139

Closed ma6254 closed 1 year ago

ma6254 commented 2 years ago

platform: windows 10

image image

package main

import (
    "encoding/binary"
    "encoding/hex"
    "fmt"
    "log"
    "time"

    "go.bug.st/serial"
)

var testCOM = "COM23"
var step uint8

type ReadPkgCallback func([]byte)

func main() {
    var (
        err error
    )

    fmt.Printf("Hello, world.\n")

    mode := &serial.Mode{
        BaudRate: 115200,
        DataBits: 8,
        Parity:   serial.NoParity,
        StopBits: serial.OneStopBit,
    }

    port, err := serial.Open(testCOM, mode)
    if err != nil {
        log.Fatal(err)
    }
    err = port.SetReadTimeout(time.Millisecond * 1000)
    if err != nil {
        log.Fatal(err)
    }

    wch := make(chan int, 1)

    go func(ch chan int) {

        wtick := time.NewTicker(time.Millisecond * 10)
    w_loop:
        for {
            select {
            case <-ch:
                break w_loop
            case <-wtick.C:
                port.Write([]byte{0x7F})
            }
        }
    }(wch)

    r_fn := func(b []byte) {
        log.Printf("recv package: %#v\n", b)
    }

    go func(fn ReadPkgCallback) {
        for {

            var (
                rb       = make([]byte, 1)
                head_cnt = 0
            )

            for {
                _, err = port.Read(rb)
                // fmt.Printf("r: %02X\n", rb[0])

                if head_cnt == 0 {
                    if rb[0] == 0x46 {
                        head_cnt = 1
                    }
                } else {
                    if rb[0] == 0xb9 {
                        // wch <- 1
                        break
                    } else {
                        head_cnt = 0
                    }
                }
            }

            rb = make([]byte, 1)
            _, err := port.Read(rb)
            if err != nil {
                return
            }

            if rb[0] != 0x68 {
                continue
            }

            var len uint16
            binary.Read(port, binary.BigEndian, &len)

            fmt.Printf("len: %#v\n", len)

            rb = make([]byte, len-4)

            n, err := port.Read(rb)
            fmt.Printf("n: %d\n", n)
            fmt.Printf("%s\n", hex.Dump(rb))
            fn(rb)

            // _, err := port.Read(rb)
            // if err != nil {
            // }
        }
    }(r_fn)

    for {
    }
}
cmaglie commented 2 years ago

The reason is that Read waits until at least one byte is received:

// Stores data received from the serial port into the provided byte array
// buffer. The function returns the number of bytes read.
//
// The Read function blocks until (at least) one byte is received from    <-----
// the serial port or an error occurs.
Read(p []byte) (n int, err error)

As soon as the first byte is received the function will unblock and return that byte. If you want to read a fixed-size string you need to cycle and accumulate until you reach the desired size.