I 'm looking for a way to obtain the GPRMC info from device GPS.
Is it even possible in any way?
I 'm looking for a way to obtain the GPRMC info from device GPS.
Is it even possible in any way?
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:
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)
}