package uart import ( "bytes" "io" "strings" "time" "github.com/tarm/serial" ) const ( BUFFERSIZE = 4096 READTIMEOUT = 50 * time.Millisecond IDLE = 200 * time.Millisecond ) type UART struct { port *serial.Port } func New(device string, baud int) (*UART, error) { c := &serial.Config{ Name: device, Baud: baud, ReadTimeout: READTIMEOUT, } p, err := serial.OpenPort(c) if err != nil { return nil, err } return &UART{port: p}, nil } func (u *UART) Write(cmd string) error { _, err := u.port.Write([]byte(strings.TrimSpace(cmd) + "\r")) return err } func (u *UART) ReadResponse() (string, error) { buf := make([]byte, BUFFERSIZE) var out bytes.Buffer received := false lastData := time.Now() for { n, err := u.port.Read(buf) if err != nil && err != io.EOF && !errorsIsTimeout(err) { return "", err } if n > 0 { received = true lastData = time.Now() out.Write(buf[:n]) } if received && time.Since(lastData) >= IDLE { return strings.TrimSpace(out.String()), nil } } } func errorsIsTimeout(err error) bool { return strings.Contains(strings.ToLower(err.Error()), "timeout") } func (u *UART) Exec(cmd string) (string, error) { if err := u.Write(cmd); err != nil { return "", err } return u.ReadResponse() } func (u *UART) Close() error { return u.port.Close() }