package at import ( "fmt" "io" "log" "time" "go.bug.st/serial" ) // Some constants const ( ReadTimeout = time.Second InputBufSize = 128 ) type atPort struct { logger *log.Logger baudrate int portName string port serial.Port inputBuf []byte } type Port interface { GetName() string GetBaudrate() int GetSerialPort() serial.Port // For extra need Connect() error Disconnect() error IsConnected() bool Send(cmd string) (Resp, error) io.Closer } func New(logger *log.Logger, portName string, baudrate int) Port { return &atPort{ logger: logger, portName: portName, baudrate: baudrate, inputBuf: make([]byte, InputBufSize), } } func (p *atPort) GetName() string { return p.portName } func (p *atPort) GetBaudrate() int { return p.baudrate } func (p *atPort) GetSerialPort() serial.Port { return p.port } func (p *atPort) Connect() error { p.logger.Println("Connecting to", p.portName, "...") s, err := serial.Open(p.portName, &serial.Mode{BaudRate: p.baudrate}) if err != nil { return fmt.Errorf("open port: %w", err) } // s.Close() There is no open f // s.Open() p.port = s p.port.SetReadTimeout(ReadTimeout) p.port.ResetInputBuffer() p.port.ResetOutputBuffer() return nil } func (p *atPort) Disconnect() error { defer func() { p.port = nil }() if err := p.port.Close(); err != nil { return fmt.Errorf("close port: %w", err) } return nil } func (p *atPort) IsConnected() bool { return p.port != nil } // Low level write/read function func (p *atPort) makeReq(msg string) (string, error) { // Write if _, err := p.port.Write([]byte(msg)); err != nil { return "", fmt.Errorf("serial port write: %w", err) } time.Sleep(time.Millisecond) // Read readLen, err := p.port.Read(p.inputBuf) // p.logger.Println(msg, "\x1b[38;2;150;150;150mRAWREAD:", string(p.inputBuf[:readLen]), "\x1b[38;2;255;255;255m") if err != nil { return "", fmt.Errorf("port read: %w", err) } return string(p.inputBuf[:readLen]), nil } func (p *atPort) Send(cmd string) (Resp, error) { cmd += "\r\n" rawResp, err := p.makeReq(cmd) if err != nil { return RespNil, fmt.Errorf("make request: %w", err) } if len(rawResp) <= 4 { return RespNil, fmt.Errorf("read too small msg: %d byte", len(rawResp)) } resp := rawResp[2 : len(rawResp)-2] // Cut \r\n return Resp(resp), nil } func (p *atPort) Close() error { return p.port.Close() }