110 lines
2.1 KiB
Go
110 lines
2.1 KiB
Go
package at
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"time"
|
|
|
|
"go.bug.st/serial"
|
|
)
|
|
|
|
// Some constants
|
|
const (
|
|
ReadTimeout = time.Second
|
|
InputBufSize = 128
|
|
)
|
|
|
|
type atPort struct {
|
|
baudrate int
|
|
portName string
|
|
port serial.Port
|
|
inputBuf []byte
|
|
}
|
|
|
|
type Port interface {
|
|
GetName() string
|
|
GetSerialPort() serial.Port // For extra need
|
|
|
|
Connect() error
|
|
Disconnect() error
|
|
IsConnected() bool
|
|
|
|
Send(cmd string) (Resp, error)
|
|
}
|
|
|
|
func New(portName string, baudrate int) Port {
|
|
return &atPort{
|
|
portName: portName,
|
|
baudrate: baudrate,
|
|
inputBuf: make([]byte, InputBufSize),
|
|
}
|
|
}
|
|
|
|
func (p *atPort) GetName() string {
|
|
return p.portName
|
|
}
|
|
|
|
func (p *atPort) GetSerialPort() serial.Port {
|
|
return p.port
|
|
}
|
|
|
|
func (p *atPort) Connect() error {
|
|
log.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
|
|
p.port.ResetInputBuffer()
|
|
if _, err := p.port.Write([]byte(msg)); err != nil {
|
|
return "", fmt.Errorf("serial port write: %w", err)
|
|
}
|
|
// Read
|
|
readLen, err := p.port.Read(p.inputBuf)
|
|
log.Println("RAWREAD:", string(p.inputBuf[:readLen]))
|
|
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
|
|
}
|