Refactored gps. Prepared for adding advanced status checks.

This commit is contained in:
yotia 2024-07-31 14:51:29 +03:00
parent fd9e999b5a
commit b831d44294
4 changed files with 147 additions and 111 deletions

View File

@ -1,4 +1,4 @@
package modem package gps
import ( import (
"fmt" "fmt"
@ -6,11 +6,9 @@ import (
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/CGSG-2021-AE4/modem-test/api/modem/at"
) )
type GpsData struct { type Data struct {
Latitude float64 `json:"Latitude"` Latitude float64 `json:"Latitude"`
Longitude float64 `json:"Longitude"` Longitude float64 `json:"Longitude"`
LatitudeIndicator string `json:"Latitude_indicator"` // North/South LatitudeIndicator string `json:"Latitude_indicator"` // North/South
@ -22,13 +20,13 @@ type GpsData struct {
Time string `json:"-"` Time string `json:"-"`
} }
var GpsInfoNil = GpsData{} var GpsInfoNil = Data{}
func deg2rad(deg float64) float64 { func deg2rad(deg float64) float64 {
return deg * (math.Pi / 180) 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 ? earthRad := 6371.0 // TODO ?
dLat := deg2rad(math.Abs(newLatitude - gps.Latitude)) dLat := deg2rad(math.Abs(newLatitude - gps.Latitude))
dLon := deg2rad(math.Abs(newLongitude - gps.Longitude)) 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)))) gps.Speed = earthRad * c / (math.Abs(float64(time.Since(lastUpdateTime))))
} }
// To remove warning
// Parse string from AT command that contains gps data // 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 var err error
newGpsInfo := GpsData{} newGpsInfo := Data{}
strs := strings.Split(strings.Split(strings.Replace(str, " ", "", -1), "\n")[0], ",") strs := strings.Split(strings.Split(strings.Replace(str, " ", "", -1), "\n")[0], ",")
newGpsInfo.Latitude, err = strconv.ParseFloat(strs[0], 64) newGpsInfo.Latitude, err = strconv.ParseFloat(strs[0], 64)
@ -77,61 +77,3 @@ func (gps *GpsData) decode(str string) error {
*gps = newGpsInfo *gps = newGpsInfo
return nil 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
}

108
api/modem/gps/gps.go Normal file
View File

@ -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
}

View File

@ -11,13 +11,14 @@ import (
"github.com/CGSG-2021-AE4/modem-test/api/modem/at" "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/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/internet"
"github.com/CGSG-2021-AE4/modem-test/api/modem/sms" "github.com/CGSG-2021-AE4/modem-test/api/modem/sms"
) )
type ModemData struct { type ModemData struct {
Port string `json:"Port"` Port string `json:"Port"`
GpsData gps.Data
} }
type modem struct { type modem struct {
@ -37,7 +38,7 @@ type modem struct {
lastUpdateTime time.Time lastUpdateTime time.Time
// GPS // GPS
gpsInfo GpsData gps gps.Gps
// Internet connection // Internet connection
ic internet.Conn ic internet.Conn
@ -50,20 +51,22 @@ type Modem interface {
Init() error Init() error
Validate() bool Validate() bool
Update() error Update() error
GetInfo() ModemData GetData() ModemData
// Temp access to SMS and AT interface // Temp access to SMS, GPS, AT interfaces mostly for debug
Sms() sms.Dialer
At() at.Port At() at.Port
Gps() gps.Gps
Sms() sms.Dialer
io.Closer io.Closer
} }
func New(logger *log.Logger) Modem { func New(logger *log.Logger) Modem {
return &modem{ return &modem{
logger: logger, logger: logger,
baudrate: 115200, baudrate: 115200,
onOffPin: gpio.New(log.New(logger.Writer(), "gpio", log.LstdFlags), 6), onOffPin: gpio.New(log.New(logger.Writer(), "gpio", log.LstdFlags), 6),
lastUpdateTime: time.Now(), lastUpdateTime: time.Now(),
} }
} }
@ -111,11 +114,17 @@ func (m *modem) Init() error {
// return fmt.Errorf("internet connection init: %w", err) // return fmt.Errorf("internet connection init: %w", err)
// } // }
// Init sms dialer // Init submodules
m.sms = sms.New(log.New(m.logger.Writer(), "sms", log.LstdFlags), m.port) m.sms = sms.New(log.New(m.logger.Writer(), "modem-sms", log.LstdFlags), m.port)
if err := m.sms.Init(); err != nil { if err := m.sms.Init(); err != nil {
return fmt.Errorf("sms dialer init %w", err) 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 return nil
} }
@ -129,44 +138,16 @@ func (m *modem) Update() error {
return nil return nil
} }
m.logger.Println("Update") m.logger.Println("Update")
// ans, err := m.port.Request(at.CmdQuestion, "CGPSINFO") if err := m.gps.Update(); err != nil {
// if err != nil { return fmt.Errorf("gps update: %w", err)
// 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 !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 return nil
} }
func (m *modem) GetInfo() ModemData { func (m *modem) GetData() ModemData {
return ModemData{ return ModemData{
Port: m.port.GetName(), Port: m.port.GetName(),
GpsData: m.gpsInfo, Data: m.gps.GetData(),
} }
} }
@ -174,6 +155,10 @@ func (m *modem) Sms() sms.Dialer {
return m.sms return m.sms
} }
func (m *modem) Gps() gps.Gps {
return m.gps
}
func (m *modem) At() at.Port { func (m *modem) At() at.Port {
return m.port return m.port
} }
@ -231,7 +216,8 @@ func (m *modem) testGPS() error {
// Difference: I do not set \n at the end of string // Difference: I do not set \n at the end of string
func (m *modem) getShortInfo() 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 { func (m *modem) saveGPS(path string) error {

View File

@ -26,7 +26,7 @@ func mainE() error {
return nil return nil
} }
log.Println("||||||||||||||||| GET INFO |||||||||||||||||") log.Println("||||||||||||||||| GET INFO |||||||||||||||||")
log.Println(m.GetInfo()) log.Println(m.GetData())
log.Println("||||||||||||||||| SEND SMS |||||||||||||||||") log.Println("||||||||||||||||| SEND SMS |||||||||||||||||")
log.Println(m.At().Send("AT+CNUM")) log.Println(m.At().Send("AT+CNUM"))