From 6b8284ee47fb0a135b2979c1314253752d4f47cd Mon Sep 17 00:00:00 2001 From: Andrey Egorov Date: Tue, 23 Jul 2024 12:22:53 +0300 Subject: [PATCH] Changed at requests. --- .gitignore | 1 + Dockerfile | 4 +- api/modem/at/at.go | 97 ++++++++++------------------------------ api/modem/at/response.go | 17 +++++++ api/modem/modem.go | 71 ++++++++++++++++++----------- 5 files changed, 90 insertions(+), 100 deletions(-) create mode 100644 api/modem/at/response.go diff --git a/.gitignore b/.gitignore index 96e6ca0..74750ad 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ out/ +Makefile go.sum .git/ diff --git a/Dockerfile b/Dockerfile index 1ca49aa..0ebf38e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,9 @@ FROM golang:1.22.5 WORKDIR /app -COPY go.mod go.sum ./ +COPY ./ ./ RUN go mod download -COPY *.go ./ + RUN CGO_ENABLED=0 GOOS=linux go build -o /modem-test diff --git a/api/modem/at/at.go b/api/modem/at/at.go index bb3dbad..630f5a1 100644 --- a/api/modem/at/at.go +++ b/api/modem/at/at.go @@ -3,7 +3,6 @@ package at import ( "fmt" "log" - "strings" "time" "go.bug.st/serial" @@ -15,25 +14,6 @@ const ( InputBufSize = 128 ) -// Command types -type CmdType byte - -// Command types base on request/answer semantic: -const ( - CmdTest CmdType = iota - // AT\r\n - // OK - CmdCheck - // AT+\r\n - // OK - CmdGet - // AT+\r\n - // +: - CmdQuestion - // AT+?\r\n - // +: -) - type atPort struct { baudrate int portName string @@ -42,12 +22,14 @@ type atPort struct { } type Port interface { + GetName() string + GetSerialPort() serial.Port // For extra need + Connect() error Disconnect() error - Request(cmdType CmdType, cmd string) (string, error) - GetName() string IsConnected() bool - GetSerialPort() serial.Port // For extra need + + Send(cmd string) (Resp, error) } func New(portName string, baudrate int) Port { @@ -58,6 +40,14 @@ func New(portName string, baudrate int) Port { } } +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}) @@ -83,6 +73,10 @@ func (p *atPort) Disconnect() error { 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 @@ -100,59 +94,16 @@ func (p *atPort) makeReq(msg string) (string, error) { return string(p.inputBuf[:readLen]), nil } -func (p *atPort) Request(cmdType CmdType, cmd string) (outStr string, outErr error) { - defer func() { - if outErr != nil { - return - } - - log.Println("GOT:", outStr, "BYTE:", []byte(outStr)) - }() - - 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") +func (p *atPort) Send(cmd string) (Resp, error) { + cmd += "\r\n" + rawResp, err := p.makeReq(cmd) if err != nil { - return "", fmt.Errorf("make at request: %w", err) + return RespNil, fmt.Errorf("make request: %w", err) } - if len(rawResp) == 0 { - return "", fmt.Errorf("read nothing") + 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 - switch cmdType { - case CmdTest, CmdCheck: - // Check and test cmds do not suppose anything but OK - if len(resp) >= 2 && resp[:2] == "OK" { - return "", nil - } - return "", fmt.Errorf("connection lost") - case CmdGet, CmdQuestion: - checkL := len(cmd) + 1 - if len(resp) >= checkL && resp[:checkL] != "+"+cmd { - return "", fmt.Errorf("connetion lost") - } - return strings.Split(resp, ":")[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 + return Resp(resp), nil } diff --git a/api/modem/at/response.go b/api/modem/at/response.go new file mode 100644 index 0000000..d92a8b5 --- /dev/null +++ b/api/modem/at/response.go @@ -0,0 +1,17 @@ +package at + +type Resp string + +const RespNil = Resp("") + +func (resp Resp) Check() bool { + return len(resp) >= 2 && resp[len(resp)-2:] == "OK" +} + +func (resp Resp) RmFront(str string) Resp { + return Resp(string(resp)[len(str):]) +} + +func (resp Resp) Str() string { + return string(resp) +} diff --git a/api/modem/modem.go b/api/modem/modem.go index a0dda20..9d102e9 100644 --- a/api/modem/modem.go +++ b/api/modem/modem.go @@ -76,8 +76,6 @@ func (m *modem) Init() error { return fmt.Errorf("soft port search: %w", err) } - return nil - // Common search if m.port == nil { if err := m.SearchPort(false); err != nil { @@ -121,7 +119,16 @@ func (m *modem) checkPort(portName string) error { } // Check model - model, err := m.port.Request(at.CmdGet, "CGMM") + log.Println("Check model...") + + resp, err := m.port.Send("AT+CGMM") + if err != nil { + return fmt.Errorf("get model: %w", err) + } + if !resp.Check() { + return fmt.Errorf("error response: %s", resp) + } + model := resp.RmFront("+CGMM:").String() if err != nil { return fmt.Errorf("get model: %w", err) } @@ -168,8 +175,14 @@ func (m *modem) Connect() error { } func (m *modem) Ping() error { - _, err := m.port.Request(at.CmdTest, "") - return err + resp, err := m.port.Send("AT") + if err != nil { + return err + } + if resp.Check() { + return fmt.Errorf("connection lost") + } + return nil } func (m *modem) SwitchToGpsMode() error { @@ -180,20 +193,27 @@ func (m *modem) SwitchToGpsMode() error { } // Check gps mode status - ans, err := m.port.Request(at.CmdQuestion, "CGPS") + resp, err := m.port.Send("AT+CGPS?") if err != nil { return fmt.Errorf("make at ask: %w", err) } + if !resp.Check() { + return fmt.Errorf("error response") + } + ans := strings.Split(resp.RmFront("+CGPS:").String(), "\n")[0] if ans == "1" { log.Println("GPS already enabled") return nil } // Modem is not in GPS mode - _, err = m.port.Request(at.CmdCheck, "CGPS=1") + resp, err = m.port.Send("AT+CGPS=1") if err != nil { return fmt.Errorf("try to switch to gps: %w", err) } + if !resp.Check() { + return fmt.Errorf("switch tp GPS failed") + } log.Println("GPS mode enabled") return nil } @@ -220,31 +240,32 @@ func (m *modem) Update() error { log.Println("No connection to module") return nil } - ans, err := m.port.Request(at.CmdQuestion, "CGPSINFO") - if err != nil { - return fmt.Errorf("check GPS info mode: %w", err) - } - ok := ans == "1" - if !ok { - _, err := m.port.Request(at.CmdCheck, "CGPSINFO") - if err != nil { - return fmt.Errorf("switch to GPS info mode: %w", err) - } - log.Println("switched to GPS mode") - } else { - log.Println("mode in right GPS mode") - } + // ans, err := m.port.Request(at.CmdQuestion, "CGPSINFO") + // if err != nil { + // return fmt.Errorf("check GPS info mode: %w", err) + // } + // ok := ans == "1" + // if !ok { + // _, err := m.port.Request(at.CmdCheck, "CGPSINFO") + // if err != nil { + // return fmt.Errorf("switch to GPS info mode: %w", err) + // } + // log.Println("switched to GPS mode") + // } else { + // log.Println("mode in right GPS mode") + // } // Update - log.Println("Receiving GPS data...") - resp, err := m.port.Request(at.CmdGet, "GPSINFO") + resp, err := m.port.Send("AT+GPSINFO") if err != nil { return fmt.Errorf("receive GPS data: %w", err) } - + if !resp.Check() { + return fmt.Errorf("error response") + } log.Println("Decoding data...") - coordinates := strings.Split(resp, ",") + coordinates := strings.Split(strings.Split(resp.RmFront("+CGPSINFO:").String(), "\n")[0], ",") m.gpsInfo.Latitude, err = strconv.ParseFloat(coordinates[0], 64) if err != nil {