From b831d44294957e805e8274f407bf737ab821271a Mon Sep 17 00:00:00 2001 From: yotia Date: Wed, 31 Jul 2024 14:51:29 +0300 Subject: [PATCH] Refactored gps. Prepared for adding advanced status checks. --- api/modem/{gps.go => gps/data.go} | 74 +++----------------- api/modem/gps/gps.go | 108 ++++++++++++++++++++++++++++++ api/modem/modem.go | 74 +++++++++----------- main.go | 2 +- 4 files changed, 147 insertions(+), 111 deletions(-) rename api/modem/{gps.go => gps/data.go} (53%) create mode 100644 api/modem/gps/gps.go diff --git a/api/modem/gps.go b/api/modem/gps/data.go similarity index 53% rename from api/modem/gps.go rename to api/modem/gps/data.go index 86934f6..15df608 100644 --- a/api/modem/gps.go +++ b/api/modem/gps/data.go @@ -1,4 +1,4 @@ -package modem +package gps import ( "fmt" @@ -6,11 +6,9 @@ import ( "strconv" "strings" "time" - - "github.com/CGSG-2021-AE4/modem-test/api/modem/at" ) -type GpsData struct { +type Data struct { Latitude float64 `json:"Latitude"` Longitude float64 `json:"Longitude"` LatitudeIndicator string `json:"Latitude_indicator"` // North/South @@ -22,13 +20,13 @@ type GpsData struct { Time string `json:"-"` } -var GpsInfoNil = GpsData{} +var GpsInfoNil = Data{} func deg2rad(deg float64) float64 { return deg * (math.Pi / 180) } -func (gps *GpsData) calculateSpeed(newLatitude, newLongitude float64, lastUpdateTime time.Time) { +func (gps *Data) CalculateSpeed(newLatitude, newLongitude float64, lastUpdateTime time.Time) { earthRad := 6371.0 // TODO ? dLat := deg2rad(math.Abs(newLatitude - gps.Latitude)) dLon := deg2rad(math.Abs(newLongitude - gps.Longitude)) @@ -39,10 +37,12 @@ func (gps *GpsData) calculateSpeed(newLatitude, newLongitude float64, lastUpdate gps.Speed = earthRad * c / (math.Abs(float64(time.Since(lastUpdateTime)))) } +// To remove warning + // Parse string from AT command that contains gps data -func (gps *GpsData) decode(str string) error { +func (gps *Data) decode(str string) error { var err error - newGpsInfo := GpsData{} + newGpsInfo := Data{} strs := strings.Split(strings.Split(strings.Replace(str, " ", "", -1), "\n")[0], ",") newGpsInfo.Latitude, err = strconv.ParseFloat(strs[0], 64) @@ -77,61 +77,3 @@ func (gps *GpsData) decode(str string) error { *gps = newGpsInfo return nil } - -func (gps *GpsData) Update(port at.Port) error { - if err := switchGpsMode(port, true); err != nil { - return fmt.Errorf("try to GPS mode: %w", err) - } - defer switchGpsMode(port, false) - - resp, err := port.Send("AT+CGPSINFO") - if err != nil { - return fmt.Errorf("receive GPS data: %w", err) - } - if !resp.Check() { - return fmt.Errorf("error response") - } - if err := gps.decode(strings.Split(strings.Replace(resp.RmFront("+CGPSINFO:").String(), "\r", "", -1), "\n")[0]); err != nil { - return fmt.Errorf("decode: %w", err) - } - return nil -} - -func switchGpsMode(port at.Port, on bool) error { - onStr := "0" - if on { - onStr = "1" - } - - // Reset input - if err := port.GetSerialPort().ResetInputBuffer(); err != nil { - return fmt.Errorf("reset input buffer: %w", err) - } - // Reset output - if err := port.GetSerialPort().ResetOutputBuffer(); err != nil { - return fmt.Errorf("reset output buffer: %w", err) - } - - // Check gps mode status - resp, err := 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.Replace(strings.Split(strings.Split(resp.RmFront("+CGPS:").String(), "\n")[0], ",")[0], " ", "", -1) - if ans == onStr { - return nil - } - - // Modem is not in GPS mode - resp, err = port.Send("AT+CGPS=" + onStr) - if err != nil { - return fmt.Errorf("try to switch to gps: %w", err) - } - if !resp.Check() { - return fmt.Errorf("switch tp GPS failed") - } - return nil -} diff --git a/api/modem/gps/gps.go b/api/modem/gps/gps.go new file mode 100644 index 0000000..7d5ae6f --- /dev/null +++ b/api/modem/gps/gps.go @@ -0,0 +1,108 @@ +package gps + +import ( + "fmt" + "io" + "log" + "strings" + + "github.com/CGSG-2021-AE4/modem-test/api/modem/at" +) + +type gps struct { + logger *log.Logger + port at.Port + data Data +} + +type Gps interface { + Init() error + Update() error + GetData() Data + CheckStatus() error + io.Closer +} + +func New(logger *log.Logger, port at.Port) Gps { + return &gps{ + logger: logger, + port: port, + } +} + +func (g *gps) Init() error { + if g.port.IsConnected() { + return fmt.Errorf("at port is not connected") + } + return nil +} + +func (g *gps) Update() error { + if err := g.switchGpsMode(true); err != nil { + return fmt.Errorf("try to GPS mode: %w", err) + } + defer g.switchGpsMode(false) + + resp, err := g.port.Send("AT+CGPSINFO") + if err != nil { + return fmt.Errorf("receive GPS data: %w", err) + } + if !resp.Check() { + return fmt.Errorf("error response") + } + if err := g.data.decode(strings.Split(strings.Replace(resp.RmFront("+CGPSINFO:").String(), "\r", "", -1), "\n")[0]); err != nil { + return fmt.Errorf("decode: %w", err) + } + return nil +} + +func (g *gps) switchGpsMode(on bool) error { + onStr := "0" + if on { + onStr = "1" + } + + // Reset input + if err := g.port.GetSerialPort().ResetInputBuffer(); err != nil { + return fmt.Errorf("reset input buffer: %w", err) + } + // Reset output + if err := g.port.GetSerialPort().ResetOutputBuffer(); err != nil { + return fmt.Errorf("reset output buffer: %w", err) + } + + // Check gps mode status + resp, err := g.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.Replace(strings.Split(strings.Split(resp.RmFront("+CGPS:").String(), "\n")[0], ",")[0], " ", "", -1) + if ans == onStr { + return nil + } + + // Modem is not in GPS mode + resp, err = g.port.Send("AT+CGPS=" + onStr) + if err != nil { + return fmt.Errorf("try to switch to gps: %w", err) + } + if !resp.Check() { + return fmt.Errorf("switch tp GPS failed") + } + return nil +} + +func (g *gps) GetData() Data { + return g.data +} + +func (g *gps) CheckStatus() error { + return fmt.Errorf("not impemented yet") +} + +func (g *gps) Close() error { + return nil +} diff --git a/api/modem/modem.go b/api/modem/modem.go index bfc5db2..e07005b 100644 --- a/api/modem/modem.go +++ b/api/modem/modem.go @@ -11,13 +11,14 @@ import ( "github.com/CGSG-2021-AE4/modem-test/api/modem/at" "github.com/CGSG-2021-AE4/modem-test/api/modem/gpio" + "github.com/CGSG-2021-AE4/modem-test/api/modem/gps" "github.com/CGSG-2021-AE4/modem-test/api/modem/internet" "github.com/CGSG-2021-AE4/modem-test/api/modem/sms" ) type ModemData struct { Port string `json:"Port"` - GpsData + gps.Data } type modem struct { @@ -37,7 +38,7 @@ type modem struct { lastUpdateTime time.Time // GPS - gpsInfo GpsData + gps gps.Gps // Internet connection ic internet.Conn @@ -50,20 +51,22 @@ type Modem interface { Init() error Validate() bool Update() error - GetInfo() ModemData + GetData() ModemData - // Temp access to SMS and AT interface - Sms() sms.Dialer + // Temp access to SMS, GPS, AT interfaces mostly for debug At() at.Port + Gps() gps.Gps + Sms() sms.Dialer io.Closer } func New(logger *log.Logger) Modem { return &modem{ - logger: logger, - baudrate: 115200, - onOffPin: gpio.New(log.New(logger.Writer(), "gpio", log.LstdFlags), 6), + logger: logger, + baudrate: 115200, + onOffPin: gpio.New(log.New(logger.Writer(), "gpio", log.LstdFlags), 6), + lastUpdateTime: time.Now(), } } @@ -111,11 +114,17 @@ func (m *modem) Init() error { // return fmt.Errorf("internet connection init: %w", err) // } - // Init sms dialer - m.sms = sms.New(log.New(m.logger.Writer(), "sms", log.LstdFlags), m.port) + // Init submodules + m.sms = sms.New(log.New(m.logger.Writer(), "modem-sms", log.LstdFlags), m.port) if err := m.sms.Init(); err != nil { return fmt.Errorf("sms dialer init %w", err) } + + m.gps = gps.New(log.New(m.logger.Writer(), "modem-gps", log.LstdFlags), m.port) + if err := m.gps.Init(); err != nil { + return fmt.Errorf("gps init %w", err) + } + return nil } @@ -129,44 +138,16 @@ func (m *modem) Update() error { return nil } m.logger.Println("Update") - // 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) - // } - // m.logger.Println("switched to GPS mode") - // } else { - // m.logger.Println("mode in right GPS mode") - // } - - // Update - m.logger.Println("Receiving GPS data...") - resp, err := m.port.Send("AT+CGPSINFO") - if err != nil { - return fmt.Errorf("receive GPS data: %w", err) + if err := m.gps.Update(); err != nil { + return fmt.Errorf("gps update: %w", err) } - if !resp.Check() { - return fmt.Errorf("error response") - } - m.logger.Println("Decoding data...") - - if err := m.gpsInfo.decode(strings.Split(strings.Replace(resp.RmFront("+CGPSINFO:").String(), "\r", "", -1), "\n")[0]); err != nil { - m.logger.Println("Gps info decode error:", err.Error()) - return nil - } - m.logger.Println("Decoded successfully") return nil } -func (m *modem) GetInfo() ModemData { +func (m *modem) GetData() ModemData { return ModemData{ - Port: m.port.GetName(), - GpsData: m.gpsInfo, + Port: m.port.GetName(), + Data: m.gps.GetData(), } } @@ -174,6 +155,10 @@ func (m *modem) Sms() sms.Dialer { return m.sms } +func (m *modem) Gps() gps.Gps { + return m.gps +} + func (m *modem) At() at.Port { return m.port } @@ -231,7 +216,8 @@ func (m *modem) testGPS() error { // Difference: I do not set \n at the end of string func (m *modem) getShortInfo() string { - return fmt.Sprintf("%f,%s,%f,%s", m.gpsInfo.Latitude, m.gpsInfo.LatitudeIndicator, m.gpsInfo.Longitude, m.gpsInfo.LongitudeIndicator) + d := m.gps.GetData() + return fmt.Sprintf("%f,%s,%f,%s", d.Latitude, d.LatitudeIndicator, d.Longitude, d.LongitudeIndicator) } func (m *modem) saveGPS(path string) error { diff --git a/main.go b/main.go index 182cd5d..d05db01 100644 --- a/main.go +++ b/main.go @@ -26,7 +26,7 @@ func mainE() error { return nil } log.Println("||||||||||||||||| GET INFO |||||||||||||||||") - log.Println(m.GetInfo()) + log.Println(m.GetData()) log.Println("||||||||||||||||| SEND SMS |||||||||||||||||") log.Println(m.At().Send("AT+CNUM"))