Potencially working.
This commit is contained in:
154
api/modem/at/at.go
Normal file
154
api/modem/at/at.go
Normal file
@ -0,0 +1,154 @@
|
||||
package at
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"go.bug.st/serial"
|
||||
)
|
||||
|
||||
// Some constants
|
||||
const (
|
||||
ReadTimeout = time.Second
|
||||
InputBufSize = 128
|
||||
)
|
||||
|
||||
// Command types
|
||||
type CmdType byte
|
||||
|
||||
// Command types base on request/answer semantic:
|
||||
const (
|
||||
CmdTest CmdType = iota
|
||||
// AT\r\n
|
||||
// OK
|
||||
CmdCheck
|
||||
// AT+<CMD>\r\n
|
||||
// OK
|
||||
CmdGet
|
||||
// AT+<CMD>\r\n
|
||||
// +<CMD>: <ANS>
|
||||
CmdQuestion
|
||||
// AT+<CMD>?\r\n
|
||||
// +<CMD>: <ANS>
|
||||
)
|
||||
|
||||
type atPort struct {
|
||||
baudrate int
|
||||
portName string
|
||||
port serial.Port
|
||||
inputBuf []byte
|
||||
}
|
||||
|
||||
type Port interface {
|
||||
Connect() error
|
||||
Disconnect() error
|
||||
Request(cmdType CmdType, cmd string) (string, error)
|
||||
GetName() string
|
||||
IsConnected() bool
|
||||
GetSerialPort() serial.Port // For extra need
|
||||
}
|
||||
|
||||
func New(portName string, baudrate int) Port {
|
||||
return &atPort{
|
||||
portName: portName,
|
||||
baudrate: baudrate,
|
||||
inputBuf: make([]byte, InputBufSize),
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// Low level write/read function
|
||||
func (p *atPort) makeReq(msg string) (string, error) {
|
||||
// Write
|
||||
p.port.ResetInputBuffer()
|
||||
log.Println("Write...") // DEBUG
|
||||
if written, err := p.port.Write([]byte(msg)); err != nil {
|
||||
return "", fmt.Errorf("serial port write: %w", err)
|
||||
} else {
|
||||
log.Println("Written:", written) // DEBUG
|
||||
}
|
||||
// Read
|
||||
log.Println("Read...") // DEBUG
|
||||
readLen, err := p.port.Read(p.inputBuf)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("port read: %w", err)
|
||||
}
|
||||
|
||||
log.Println("Read: ", readLen, string(p.inputBuf[:readLen])) // DEBUG
|
||||
return string(p.inputBuf[:readLen]), nil
|
||||
}
|
||||
|
||||
func (p *atPort) Request(cmdType CmdType, cmd string) (string, error) {
|
||||
msg := "AT"
|
||||
// Make command
|
||||
// By default it just will be AT check cmd
|
||||
switch cmdType {
|
||||
case CmdGet, CmdCheck:
|
||||
msg += cmd
|
||||
case CmdQuestion:
|
||||
msg += cmd + "?"
|
||||
}
|
||||
msg += "\r\n"
|
||||
rawResp, err := p.makeReq(msg)
|
||||
log.Println("Got")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("make at request: %w", err)
|
||||
}
|
||||
if len(rawResp) == 0 {
|
||||
return "", fmt.Errorf("read nothing")
|
||||
}
|
||||
resp := strings.Split(rawResp, "\n")
|
||||
switch cmdType {
|
||||
case CmdTest, CmdCheck:
|
||||
// Check and test cmds do not suppose anything but OK
|
||||
if len(resp[1]) >= 2 && resp[1][:2] == "OK" {
|
||||
return "", nil
|
||||
}
|
||||
return "", fmt.Errorf("connection lost")
|
||||
case CmdGet, CmdQuestion:
|
||||
checkL := len(cmd) + 1
|
||||
if len(resp[1]) >= checkL && resp[1][:checkL] != "+"+cmd {
|
||||
return "", fmt.Errorf("connetion lost")
|
||||
}
|
||||
return strings.Split(resp[1], ":")[1], nil
|
||||
}
|
||||
return "", fmt.Errorf("undefined command type")
|
||||
}
|
||||
|
||||
func (p *atPort) GetName() string {
|
||||
return p.portName
|
||||
}
|
||||
|
||||
func (p *atPort) IsConnected() bool {
|
||||
return p.port != nil
|
||||
}
|
||||
|
||||
func (p *atPort) GetSerialPort() serial.Port {
|
||||
return p.port
|
||||
}
|
Reference in New Issue
Block a user