package gps import ( "fmt" "strconv" "strings" ) type Status struct { GotResponses bool `json:"gotResponses"` IsValidData bool `json:"isValidData"` FoundSatelitesCount int `json:"foundSatelitesCount"` ActiveSatelitesCount int `json:"activeSatelitesCount"` } var StatusNil = Status{ GotResponses: false, IsValidData: false, FoundSatelitesCount: 0, ActiveSatelitesCount: 0, } func (g *gps) GetStatus() (Status, error) { // Provides more information about signal and possible problems using NMEA reports // Collect reports reports, err := g.collectNmeaReports(nmeaFlagsAll) // Now minimum if err != nil { return StatusNil, fmt.Errorf("collect nmea reports: %w", err) } // Annalise st := Status{} checkLoop: for _, s := range reports { // Check for NMEA format if len(s) < 1 || s[0] != '$' { continue checkLoop } st.GotResponses = true g.logger.Println("NMEA check:", s) values := strings.Split(s, ",") if len(values[0]) != 6 { return StatusNil, fmt.Errorf("nmea invalid sentence: %s", s) } switch values[0][3:] { // Switch by content case "GSV": g.logger.Println("check GSV") // Check len if len(values) < 17 { g.logger.Println("GSV too small values") continue checkLoop } // 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 } st.FoundSatelitesCount = satCount case "GSA": g.logger.Println("check GSA") // 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) case "RMC": g.logger.Println("check RMC") // 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 // Msg index if values[2] == "A" { st.IsValidData = true } } } return st, nil }