Refactored gps. Prepared for adding advanced status checks.
This commit is contained in:
		| @@ -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
									
								
							
							
						
						
									
										108
									
								
								api/modem/gps/gps.go
									
									
									
									
									
										Normal 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 | ||||||
|  | } | ||||||
| @@ -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 { | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								main.go
									
									
									
									
									
								
							| @@ -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")) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user