Added signal check.
This commit is contained in:
parent
75d05f197c
commit
d21ad0ce00
@ -37,8 +37,9 @@ type Port interface {
|
||||
Disconnect() error
|
||||
IsConnected() bool
|
||||
|
||||
RawSend(msg string) (string, error)
|
||||
RawSend(msg string, timeout time.Duration) (string, error)
|
||||
Send(cmd string) (Resp, error)
|
||||
SendWithTimeout(cmd string, timeout time.Duration) (Resp, error)
|
||||
|
||||
io.Closer
|
||||
}
|
||||
@ -106,7 +107,7 @@ func (p *atPort) IsConnected() bool {
|
||||
}
|
||||
|
||||
// Low level write/read function
|
||||
func (p *atPort) RawSend(msg string) (string, error) {
|
||||
func (p *atPort) RawSend(msg string, timeout time.Duration) (string, error) {
|
||||
p.mutex.Lock()
|
||||
defer p.mutex.Unlock()
|
||||
|
||||
@ -114,7 +115,7 @@ func (p *atPort) RawSend(msg string) (string, error) {
|
||||
if _, err := p.port.Write([]byte(msg)); err != nil {
|
||||
return "", fmt.Errorf("serial port write: %w", err)
|
||||
}
|
||||
// time.Sleep(time.Millisecond)
|
||||
time.Sleep(timeout)
|
||||
// Read
|
||||
outBuf := make([]byte, 0)
|
||||
readLoop:
|
||||
@ -131,13 +132,26 @@ readLoop:
|
||||
break readLoop
|
||||
}
|
||||
}
|
||||
// p.logger.Println(msg, "\x1b[38;2;150;150;150mRAWREAD:", string(p.inputBuf[:readLen]), "\x1b[38;2;255;255;255m")
|
||||
// p.logger.Println(msg, "\x1b[38;2;150;150;150mRAWREAD:", string(outBuf), "\x1b[38;2;255;255;255m")
|
||||
|
||||
return string(outBuf), nil
|
||||
}
|
||||
|
||||
func (p *atPort) Send(cmd string) (Resp, error) {
|
||||
rawResp, err := p.RawSend(cmd + "\r\n")
|
||||
rawResp, err := p.RawSend(cmd+"\r\n", time.Microsecond)
|
||||
if err != nil {
|
||||
return RespNil, fmt.Errorf("%s request: %w", cmd, err)
|
||||
}
|
||||
if len(rawResp) <= 4 {
|
||||
return RespNil, fmt.Errorf("%s request: read too small msg: %d byte - %s", cmd, len(rawResp), string(rawResp))
|
||||
}
|
||||
resp := rawResp[2 : len(rawResp)-2] // Cut \r\n
|
||||
|
||||
return Resp(resp), nil
|
||||
}
|
||||
|
||||
func (p *atPort) SendWithTimeout(cmd string, timeout time.Duration) (Resp, error) {
|
||||
rawResp, err := p.RawSend(cmd+"\r\n", timeout)
|
||||
if err != nil {
|
||||
return RespNil, fmt.Errorf("%s request: %w", cmd, err)
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
"gitea.unprism.ru/KRBL/sim-modem/api/modem/gps"
|
||||
"gitea.unprism.ru/KRBL/sim-modem/api/modem/internet"
|
||||
"gitea.unprism.ru/KRBL/sim-modem/api/modem/sms"
|
||||
"gitea.unprism.ru/KRBL/sim-modem/api/modem/utils"
|
||||
)
|
||||
|
||||
type ModemData struct {
|
||||
@ -53,6 +54,7 @@ type Modem interface {
|
||||
IsConnected() bool
|
||||
Update() error
|
||||
GetData() ModemData
|
||||
CheckSignal() error
|
||||
|
||||
PowerOn() error
|
||||
PowerOff() error
|
||||
@ -170,6 +172,10 @@ func (m *modem) GetData() ModemData {
|
||||
}
|
||||
}
|
||||
|
||||
func (m *modem) CheckSignal() error {
|
||||
return utils.CheckSignal(m.port, m.logger)
|
||||
}
|
||||
|
||||
func (m *modem) PowerOn() error {
|
||||
m.onOffPin.PowerOn() // DEBUG do not want to wait 30 seconds
|
||||
return nil
|
||||
@ -276,10 +282,10 @@ func (m *modem) saveGPS(path string) error {
|
||||
// Short way to send command
|
||||
func (m *modem) printCmd(cmd string) {
|
||||
if resp, err := m.port.Send(cmd); err != nil {
|
||||
m.logger.Println("FAILED TO SEND REQ", cmd, ":", err.Error())
|
||||
m.logger.Println("FAILED TO SEND REQ", cmd, "===>", err.Error())
|
||||
} else {
|
||||
_ = resp
|
||||
m.logger.Println("CMD", cmd, ":", resp)
|
||||
// m.logger.Println("CMD", cmd, "===>", resp)
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,6 +310,16 @@ func (m *modem) setupPort() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *modem) checkCurPortDead() error {
|
||||
if resp, err := m.port.RawSend("AT\r\n", 20*time.Millisecond); err != nil || len(resp) == 0 {
|
||||
if err != nil {
|
||||
return fmt.Errorf("raw send: %w", err)
|
||||
}
|
||||
return fmt.Errorf("read 0")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *modem) checkPort(portName string) (outErr error) {
|
||||
defer func() {
|
||||
if outErr != nil { // Clear port if there is error
|
||||
@ -327,8 +343,9 @@ func (m *modem) checkPort(portName string) (outErr error) {
|
||||
// m.restart()
|
||||
|
||||
// To filter dead ports
|
||||
if str, err := m.port.RawSend("AT"); err != nil || len(str) == 0 {
|
||||
return fmt.Errorf("ping error: %w", err)
|
||||
|
||||
if err := m.checkCurPortDead(); err != nil {
|
||||
return fmt.Errorf("echo: %w", err)
|
||||
}
|
||||
|
||||
if err := m.setupPort(); err != nil {
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"io"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gitea.unprism.ru/KRBL/sim-modem/api/modem/at"
|
||||
)
|
||||
@ -40,7 +41,7 @@ func (d *dialer) Init() error {
|
||||
}
|
||||
// Setup prefered message storage
|
||||
if err := d.setupMsgSt(); err != nil {
|
||||
return fmt.Errorf("setup msg storage: %w", err)
|
||||
d.logger.Printf("ERROR setup msg storage: %s\n", err.Error())
|
||||
}
|
||||
// Check number
|
||||
if resp, err := d.port.Send("AT+CNUM"); err != nil || !resp.Check() {
|
||||
@ -57,7 +58,7 @@ func (d *dialer) Send(number, msg string) error {
|
||||
return err
|
||||
}
|
||||
d.logger.Println(sresp)
|
||||
resp, err := d.port.RawSend(fmt.Sprintf("%s\x1A", msg)) // Add additional \r\n because there is not supposed to be
|
||||
resp, err := d.port.RawSend(fmt.Sprintf("%s\x1A", msg), time.Millisecond) // Add additional \r\n because there is not supposed to be
|
||||
if err != nil {
|
||||
return fmt.Errorf("message request: %w", err)
|
||||
}
|
||||
|
108
api/modem/utils/signal.go
Normal file
108
api/modem/utils/signal.go
Normal file
@ -0,0 +1,108 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gitea.unprism.ru/KRBL/sim-modem/api/modem/at"
|
||||
)
|
||||
|
||||
func CheckSignal(port at.Port, logger *log.Logger) error {
|
||||
rssi, ber, err := getSignalQuality(port)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get signal quality: %w", err)
|
||||
}
|
||||
logger.Printf("check signal: rssi=%d ber=%d\n", rssi, ber)
|
||||
if err := checkRssi(rssi); err != nil {
|
||||
return fmt.Errorf("rssi: %w", err)
|
||||
}
|
||||
if err := checkBer(ber); err != nil {
|
||||
logger.Printf("bad ber(not critical): %s", err.Error()) // Happened not to be critical
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkRssi(rssi int) error {
|
||||
// rssi - Received signal strenght indicator
|
||||
// 0 -113 dBm or less
|
||||
// 1 -111 dBm
|
||||
// 2...30 -109... - 53 dBm
|
||||
// 31 -51 dBm or greater
|
||||
// 99 not known or not detectable
|
||||
// 100 -116 dBm or less
|
||||
// 101 -115 dBm
|
||||
// 102…191 -114... - 26dBm
|
||||
// 191 -25 dBm or greater
|
||||
// 199 not known or not detectable
|
||||
// 100…199 expand to TDSCDMA, indicate RSCPreceived
|
||||
|
||||
if rssi <= 2 { // Too poor
|
||||
return fmt.Errorf("too poor <= -109dBm")
|
||||
}
|
||||
if rssi > 2 && rssi <= 31 {
|
||||
return nil // Can live
|
||||
}
|
||||
if rssi == 99 {
|
||||
return fmt.Errorf("not known or not detectable")
|
||||
}
|
||||
if rssi >= 100 && rssi <= 102 {
|
||||
return fmt.Errorf("too poor <= -114dBm")
|
||||
}
|
||||
if rssi > 102 && rssi <= 191 {
|
||||
return nil // Can live
|
||||
}
|
||||
if rssi == 199 {
|
||||
return fmt.Errorf("not known or not detectable")
|
||||
}
|
||||
return fmt.Errorf("invalid code %d", rssi)
|
||||
}
|
||||
|
||||
func checkBer(ber int) error {
|
||||
// ber - Bit error rate
|
||||
// 0 <0.01%
|
||||
// 1 0.01% --- 0.1%
|
||||
// 2 0.1% --- 0.5%
|
||||
// 3 0.5% --- 1.0%
|
||||
// 4 1.0% --- 2.0%
|
||||
// 5 2.0% --- 4.0%
|
||||
// 6 4.0% --- 8.0%
|
||||
// 7 >=8.0%
|
||||
// 99 not known or not detectable
|
||||
if ber >= 0 && ber <= 3 {
|
||||
// ber -> [0%;1%)
|
||||
// Ok, can live
|
||||
return nil
|
||||
}
|
||||
if ber >= 4 && ber <= 7 {
|
||||
return fmt.Errorf("too high: %d code", ber)
|
||||
}
|
||||
if ber == 99 {
|
||||
return fmt.Errorf("not known or not detectable")
|
||||
}
|
||||
return fmt.Errorf("invalid code %d", ber)
|
||||
}
|
||||
|
||||
func getSignalQuality(port at.Port) (int, int, error) {
|
||||
resp, err := port.Send("AT+CSQ")
|
||||
if err != nil {
|
||||
return 99, 99, err
|
||||
}
|
||||
if !resp.Check() || !resp.CheckFront("+CSQ: ") {
|
||||
return 99, 99, fmt.Errorf("error response: %s", resp)
|
||||
}
|
||||
values := strings.Split(strings.ReplaceAll(strings.Split(resp.RmFront("+CSQ: ").String(), "\n")[0], "\r", ""), ",")
|
||||
if len(values) != 2 {
|
||||
return 99, 99, fmt.Errorf("invalid values(len): [% s]", values)
|
||||
}
|
||||
rssi, err := strconv.Atoi(values[0])
|
||||
if err != nil {
|
||||
return 99, 99, fmt.Errorf("parse rssi: %w", err)
|
||||
}
|
||||
ber, err := strconv.Atoi(values[1])
|
||||
if err != nil {
|
||||
return 99, 99, fmt.Errorf("parse ber: %w", err)
|
||||
}
|
||||
return rssi, ber, nil
|
||||
}
|
35
main.go
35
main.go
@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"gitea.unprism.ru/KRBL/sim-modem/api/modem"
|
||||
"gitea.unprism.ru/KRBL/sim-modem/api/modem/at"
|
||||
@ -42,19 +43,8 @@ func mainE() error {
|
||||
// logger.Printf("DATA: %+v\n", m.GetData())
|
||||
|
||||
logger.Println("||||||||||||||||| SMS |||||||||||||||||")
|
||||
// resp, err := m.At().Send("AT+CNUM")
|
||||
// logger.Println("CNUM:", resp, err)
|
||||
// // if err := m.Sms().Send("+79218937173", "CGSG forever"); err != nil {
|
||||
// // return err
|
||||
// // }
|
||||
// if ms, err := m.Sms().ReadNew(); err != nil {
|
||||
// return err
|
||||
// } else {
|
||||
// logger.Println("NEW:", ms)
|
||||
// }
|
||||
|
||||
Cmd := func(cmd string) {
|
||||
resp, err := m.At().Send(cmd)
|
||||
resp, err := m.At().SendWithTimeout(cmd, 50*time.Millisecond)
|
||||
logger.Println(cmd, "===>", resp, err)
|
||||
}
|
||||
_ = Cmd
|
||||
@ -67,16 +57,27 @@ func mainE() error {
|
||||
_ = buf
|
||||
|
||||
// Select ME PMS
|
||||
// resp, err = m.At().Send("AT+CPMS=?")
|
||||
// logger.Println("Possible mem storages:", resp, err)
|
||||
// resp, err = m.At().Send("AT+CPMS?")
|
||||
// logger.Println("Prefered mem storage:", resp, err)
|
||||
// Cmd("AT")
|
||||
// logger.Println("SEND SMS")
|
||||
// logger.Println(m.Sms().Send("+79218937173", "CGSG forever!!!"))
|
||||
// m.At().RawSend("\r\n\x1A\r\n")
|
||||
|
||||
Cmd("AT+CREG?")
|
||||
Cmd("AT+CNMI?")
|
||||
Cmd("AT+CSQ")
|
||||
Cmd("AT+CSCA?")
|
||||
Cmd("AT+CPOL?")
|
||||
Cmd("AT+COPS?")
|
||||
// Cmd("AT+COPS=?")
|
||||
Cmd("AT+CPSI?")
|
||||
resp, err = m.At().Send("AT+CNMI=2,2")
|
||||
for {
|
||||
|
||||
// if err := m.CheckSignal(); err != nil {
|
||||
// logger.Println(err)
|
||||
// } else {
|
||||
// logger.Println("AAAAAAAAAAA THERE IS SIGNAL")
|
||||
// }
|
||||
// time.Sleep(250 * time.Millisecond)
|
||||
readLen, err := m.At().SerialPort().Read(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
|
Loading…
Reference in New Issue
Block a user