sim-modem/api/modem/gps/status.go

152 lines
3.3 KiB
Go
Raw Normal View History

package gps
import (
"fmt"
"strconv"
"strings"
)
2024-08-02 16:43:15 +00:00
type Status struct {
2024-08-07 14:34:56 +00:00
GotResponses bool `json:"gotResponses"`
IsValidData bool `json:"isValidData"`
FoundSatelitesCount int `json:"foundSatelitesCount"`
ActiveSatelitesCount int `json:"activeSatelitesCount"`
Rms float32 `json:"rms"` // Root mean square
2024-08-02 16:43:15 +00:00
}
var StatusNil = Status{
2024-08-07 08:35:06 +00:00
GotResponses: false,
IsValidData: false,
FoundSatelitesCount: 0,
ActiveSatelitesCount: 0,
2024-08-07 14:34:56 +00:00
Rms: 0,
}
2024-08-02 16:43:15 +00:00
2024-08-06 17:37:20 +00:00
func (g *gps) GetStatus() (Status, error) {
// Provides more information about signal and possible problems using NMEA reports
// Collect reports
2024-08-01 16:34:58 +00:00
reports, err := g.collectNmeaReports(nmeaFlagsAll) // Now minimum
if err != nil {
2024-08-02 16:43:15 +00:00
return StatusNil, fmt.Errorf("collect nmea reports: %w", err)
}
// Annalise
2024-08-02 16:43:15 +00:00
st := Status{}
checkLoop:
for _, s := range reports {
2024-08-02 16:16:39 +00:00
// Check for NMEA format
if len(s) < 1 || s[0] != '$' {
continue checkLoop
}
2024-08-02 16:43:15 +00:00
st.GotResponses = true
2024-08-02 16:16:39 +00:00
// g.logger.Println("NMEA check:", s)
values := strings.Split(s, ",")
2024-08-02 16:16:39 +00:00
if len(values[0]) != 6 {
2024-08-02 16:43:15 +00:00
return StatusNil, fmt.Errorf("nmea invalid sentence: %s", s)
}
switch values[0][3:] { // Switch by content
2024-08-07 14:34:56 +00:00
case "GSV": // Any satelites
// g.logger.Println("check GSV")
2024-08-07 08:35:06 +00:00
// Check len
if len(values) < 17 {
g.logger.Println("GSV too small values")
continue checkLoop
}
2024-08-07 08:35:06 +00:00
// Decode
// 0 - msg type
// 1 - number of msgs
// 2 - index of this msg
// 3 - number of visible satelites
// 4: - other data
// Msg index
index, err := strconv.Atoi(values[3])
if err != nil {
g.logger.Println("GSV too small values")
continue checkLoop
}
_ = index
// if index != 0 {
// g.logger.Println("discard not first GSV msg")
// continue checkLoop
// }
// Count
satCount, err := strconv.Atoi(values[4])
if err != nil {
g.logger.Println("GSV too small values")
continue checkLoop
}
2024-08-07 08:35:06 +00:00
st.FoundSatelitesCount = satCount
2024-08-07 14:34:56 +00:00
case "GSA": // Active satelites
// g.logger.Println("check GSA")
2024-08-07 08:35:06 +00:00
// Check len
if len(values) < 17 {
g.logger.Println("GSV too small values")
continue checkLoop
}
// Decode
// 0 - msg type
// 1 - mode of selecting format
// 2 - mode of selected format
// 3:15 - IDs of active satelites
// 15: - other data
// Counting active satelites
count := 0
for _, v := range values[3:15] {
if _, err := strconv.Atoi(v); err == nil {
count += 1
}
}
st.ActiveSatelitesCount = max(st.ActiveSatelitesCount, count)
2024-08-07 14:34:56 +00:00
case "RMC": // Minimum GPS data
// g.logger.Println("check RMC")
2024-08-07 08:35:06 +00:00
// Check len
if len(values) < 12 {
g.logger.Println("RMC too small values")
continue checkLoop
}
// Decode
// 0 - msg type
// 1 - time
// 2 - is data valid or not
// 3: - other data
2024-08-07 14:34:56 +00:00
// Is valid value
2024-08-07 08:35:06 +00:00
if values[2] == "A" {
st.IsValidData = true
}
2024-08-07 14:34:56 +00:00
case "GST":
// g.logger.Println("check GST")
2024-08-07 14:34:56 +00:00
// Check len
if len(values) < 8 {
g.logger.Println("GST too small values")
continue checkLoop
}
// Decode
// 0 - msg type
// 1 - time
// 2 - Root Mean Square
// 3: - other data
rms, err := strconv.ParseFloat(values[2], 32)
if err != nil {
g.logger.Println("RMS decode:", err.Error())
continue checkLoop
}
st.Rms = float32(rms)
}
}
2024-08-02 16:43:15 +00:00
return st, nil
}