sim-modem/api/modem/at/at.go
2024-07-23 19:02:28 +03:00

113 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 {
logger *log.Logger
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(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) 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
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)
p.logger.Println(msg, "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
}