Is it possible to retrieve the GPRMC from device G

2020-04-21 07:26发布

I 'm looking for a way to obtain the GPRMC info from device GPS.

Is it even possible in any way?

2条回答
男人必须洒脱
2楼-- · 2020-04-21 08:03

There's no public API to retrieve the GPRMC from the device's GPS chip. The closest you can get to that is to build the GPRMC sentences from what the Location API provides you.

The following code builds the GPRMC and GPGGA sentences from CLLocation, in Swift. It's based on this question and on the NMEA specification for those sentences. Some data is hard-coded because we don't have access to that on iOS.

On your CLLocationManagerDelegate:

let timestampFormatter = NSDateFormatter()
let nmeaDateFormatter = NSDateFormatter()

init () {
    timestampFormatter.timeZone = NSTimeZone(name: "UTC")
    timestampFormatter.dateFormat = "HHmmss.SSS"

    nmeaDateFormatter.timeZone = NSTimeZone(name: "UTC")
    nmeaDateFormatter.dateFormat = "ddMMyy"
}

func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    for location in locations {
        let latitude = convertCLLocationDegreesToNmea(location.coordinate.latitude)
        let longitude = convertCLLocationDegreesToNmea(location.coordinate.longitude)

        // GPGGA
        // http://www.gpsinformation.org/dale/nmea.htm#GGA
        var nmea0183GPGGA = "GPGGA," + timestampFormatter.stringFromDate(location.timestamp)
        nmea0183GPGGA += String(format: ",%08.4f,", arguments: [abs(latitude)])
        nmea0183GPGGA += latitude > 0.0 ? "N" : "S"
        nmea0183GPGGA += String(format: ",%08.4f,", arguments: [abs(longitude)])
        nmea0183GPGGA += longitude > 0.0 ? "E" : "W"
        nmea0183GPGGA += ",1,08,1.0,"
        nmea0183GPGGA += String(format: "%1.1f,M,%1.1f,M,,,", arguments: [location.altitude, location.altitude])
        nmea0183GPGGA += String(format: "*%02lX", arguments: [nmeaSentenceChecksum(nmea0183GPGGA)])
        nmea0183GPGGA = "$" + nmea0183GPGGA

        // GPRMC
        // http://www.gpsinformation.org/dale/nmea.htm#RMC
        var nmea0183GPRMC = "GPRMC," + timestampFormatter.stringFromDate(location.timestamp) + ",A,"
        nmea0183GPRMC += String(format: "%08.4f,", arguments: [abs(latitude)])
        nmea0183GPRMC += latitude > 0.0 ? "N" : "S"
        nmea0183GPRMC += String(format: ",%08.4f,", arguments: [abs(longitude)])
        nmea0183GPRMC += longitude > 0.0 ? "E" : "W"
        nmea0183GPRMC += String(format: ",%04.1f,", arguments: [(location.course > 0.0 ? location.speed * 3600.0 / 1000.0 * 0.54 : 0.0)])
        nmea0183GPRMC += String(format: "%04.1f,", arguments: [(location.course > 0.0 ? location.course : 0.0)])
        nmea0183GPRMC += nmeaDateFormatter.stringFromDate(location.timestamp)
        nmea0183GPRMC += ",,,A"
        nmea0183GPRMC += String(format: "*%02lX", arguments: [nmeaSentenceChecksum(nmea0183GPRMC)])
        nmea0183GPRMC = "$" + nmea0183GPRMC

        // Log
        debugPrint(nmea0183GPGGA)
        debugPrint(nmea0183GPRMC)
    }
}

func convertCLLocationDegreesToNmea(degrees: CLLocationDegrees) -> Double {
    let degreeSign = ((degrees > 0.0) ? 1.0 : ((degrees < 0.0) ? -1.0 : 0));
    let degree = abs(degrees);
    let degreeDecimal = floor(degree);
    let degreeFraction = degree - degreeDecimal;
    let minutes = degreeFraction * 60.0;
    let nmea = degreeSign * (degreeDecimal * 100.0 + minutes);
    return nmea;
}

func nmeaSentenceChecksum(sentence: String) -> CLong {
    var checksum: unichar = 0;
    var stringUInt16 = [UInt16]()
    stringUInt16 += sentence.utf16
    for char in stringUInt16 {
        checksum ^= char
    }
    checksum &= 0x0ff
    return CLong(checksum)
}
查看更多
乱世女痞
3楼-- · 2020-04-21 08:18

No, it is not possible.
First GPRMC is a message from the text based NMEA protocoll, which is a not well defined protocoll, each chip manufacturer interprets it differently.
Therfore most professional devices, use the binary protocoll from the Chip manufacturer. And even when Apple woud internally use the NMEA Protokoll to communicate with the chip, you would not have any access to that messages.

However the data of the GPRMC message is available in CLLocation delivered by CLLocationManager.

Lets look at the attributes of RMC:

  • time: no not really, apple may correct the time by local time, or by a user correction offset offset.
  • validFlag: yes in CLLocation
  • latitude: yes
  • longitude: yes
  • speed: yes
  • course: yes (CLLocation.course)
  • Magnetic Variation: yes possible, but needs an API call.
查看更多
登录 后发表回答