2024-07-31 19:18:44 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2024-08-04 12:59:58 +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-04 12:59:58 +00:00
|
|
|
}
|
2024-08-02 16:43:15 +00:00
|
|
|
|
2024-08-06 17:37:20 +00:00
|
|
|
func (g *gps) GetStatus() (Status, error) {
|
2024-07-31 19:18:44 +00:00
|
|
|
// 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
|
2024-07-31 19:18:44 +00:00
|
|
|
if err != nil {
|
2024-08-02 16:43:15 +00:00
|
|
|
return StatusNil, fmt.Errorf("collect nmea reports: %w", err)
|
2024-07-31 19:18:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Annalise
|
2024-08-02 16:43:15 +00:00
|
|
|
st := Status{}
|
|
|
|
|
2024-07-31 19:18:44 +00:00
|
|
|
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
|
|
|
|
2024-08-12 16:24:31 +00:00
|
|
|
// g.logger.Println("NMEA check:", s)
|
2024-07-31 19:18:44 +00:00
|
|
|
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)
|
2024-07-31 19:18:44 +00:00
|
|
|
}
|
|
|
|
switch values[0][3:] { // Switch by content
|
2024-08-07 14:34:56 +00:00
|
|
|
case "GSV": // Any satelites
|
2024-08-12 16:24:31 +00:00
|
|
|
// g.logger.Println("check GSV")
|
2024-08-07 08:35:06 +00:00
|
|
|
// Check len
|
2024-07-31 19:18:44 +00:00
|
|
|
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])
|
2024-07-31 19:18:44 +00:00
|
|
|
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
|
2024-08-12 16:24:31 +00:00
|
|
|
// 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
|
2024-08-12 16:24:31 +00:00
|
|
|
// 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":
|
2024-08-12 16:24:31 +00:00
|
|
|
// 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-07-31 19:18:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-02 16:43:15 +00:00
|
|
|
return st, nil
|
2024-07-31 19:18:44 +00:00
|
|
|
}
|