Repository navigation
Integration Guide: iOS & iPadOS
All Bad Elf GNSS/GPS receivers are certified via Apple's Made for iOS (MFi) program, so any location-based app can use our position data via the iOS CoreLocation framework without any additional work. If your app works with the internal GPS, it works with our receivers as well.
| Model Name | SKU | EA Modern ( com.bad-elf.gnss) |
EA Legacy ( com.bad-elf.gps) |
Configuration & FW Updates |
|---|---|---|---|---|
| Bad Elf Flex Mini (Standard) | BE-GPS-2500 | NMEA (out) | DNU | Flex app, USB-C to PC/Mac |
| Bad Elf Flex Mini (Extreme) | BE-GPS-3500 | NMEA (out) RTCM (in) |
DNU | Flex app, USB-C to PC/Mac |
| Bad Elf Flex (Standard) | BE-GPS-5500 | NMEA (out) | DNU | Flex app, USB key w/ OTG adapter |
| Bad Elf Flex (Extreme) | BE-GPS-6500 | NMEA (out) RTCM (in) |
DNU | Flex app, USB key w/ OTG adapter |
| Legacy/EOL Models: | ||||
| Bad Elf GNSS Surveyor | BE-GPS-3300 | --- | NMEA (out) | USB FAT drive mode Bad Elf GPS app (iOS) |
| Bad Elf Pro+ | BE-GPS-2300 | --- | NMEA (out) | USB FAT drive mode Bad Elf GPS app (iOS) |
| Bad Elf Pro | BE-GPS-2200 | --- | NMEA (out) | Bad Elf GPS app (iOS) |
| Bad Elf GPS Lightning | BE-GPS-1008 | --- | NMEA (out) via Lightning port | Bad Elf GPS app (iOS) |
- DNU - Do not use, only for legacy apps and may be disabled in future FW updates
For iOS/iPadOS app developers wanting to enable direct communications with our current or legacy GPS/GNSS receivers, follow the steps below:
- Send us your app bundle ID(s) via this form. We'll get your app whitelisted with Apple, and respond back to you within 1-2 days with a PPID blurb to include in your app review notes. This is required by Apple when reviewing your TestFlight and/or App Store submissions.
- Update your app's
Info.plistto include one or both of our supported EAAccessory protocol strings. This list controls the accessories your app can access viaEAAccessory.framework. - Modify your app to use the
EAAccessory.frameworkto query connected accessories and be notified when they connect/disconnect via Bluetooth. TheEAAccessoryobject includes basic metadata including the protocol strings supported by the receiver, model name, serial number, etc. Use these values dynamically for any in-app GNSS status panels, alerts, logging, etc -- don't hardcode them in your app! - When you have an
EAAccessoryyou'd like to use, open anEASessionwith your desired protocol string to start communications with the hardware. When theEASessionis open and ready for writing, you'll need to send a configuration message ($PBEJS or binary packet) to the hardware to get NMEA data flowing. These are documented below. - Optionally, parse the
$PELFIDsentence sent by our receivers. This message includes some additional metadata such as the accessory nickname and a few other status flags you can't get via theEASessionobject. - Be ready to parse whatever NMEA or other protocols are being sent by the hardware, with flexibility for different talker IDs (
GPandGN), unknown/partial/corrupt NMEA messages, and unknown binary packets. Always validate checksums, confirm the NMEA timestamps match, and use$/CR/LFbytes for synchronization as needed. - Handle normal lifecycle events such as the accessory appearing and disappearing, reconnects, the data stream being starved or flooded, and the GNSS lock status changing. It's a crazy place out there!
- If you'd like us to do some sanity testing, shoot a TestFlight invite and quick note to ios@bad-elf.com.
- Let us know when your app goes live and we'll be happy to promote it, add it our list of recommended apps, etc.
Our Bad Elf Flex and Flex Mini receivers support the com.bad-elf.gnss protocol string, which will also be supported by all future Bad Elf receivers. If available on the EAAccessory object, always use this protocol first.
Add the following to your app's Info.plist file:
<key>UISupportedExternalAccessoryProtocols</key>
<array>
<string>com.bad-elf.gnss</string>
</array>When the EASession is open and ready for writing, you must send a PBEJS session configuration message to the accessory, containing your app's name, bundle ID, and version. This will get NMEA sentences flowing:
$PBEJS,{"method":"session","params":{"appName":"BadElfSampleGnssApp","appId":"com.bad-elf.BadElfSampleGnssApp","appVersion":"1.0","msgs":"NMEA"}}"*6A<CR><LF>By default our receivers send the GGA, RMC, and GST sentences. Combined, these include all of the necessary position and metadata you need for a single moment in time (epoch).
$GNGGA,174132.000,3337.813638,N,11153.327844,W,1,45,0.54,469.200,M,-26.096,M,,*47
$GNRMC,174132.000,A,3337.813638,N,11153.327844,W,0.14,247.58,111225,,,A,V*1D
$GNGST,174132.000,,,,,3.974,5.220,16.077*40To calculate horizontal accuracy in meters, use the Pythagorean theorem on fields 6 and 7 in the GST sentence. You can use field 8 as-is for vertical accuracy in meters. These values will match what you see on the Flex LCD screen or in the Bad Elf Flex app.
If your app needs to support our legacy (end-of-life) receivers, you can add support for the legacy com.bad-elf.gps protocol string as well:
<key>UISupportedExternalAccessoryProtocols</key>
<array>
<string>com.bad-elf.gnss</string>
<string>com.bad-elf.gps</string>
</array>When the EASession is open, your app will need to send a binary configuration packet to the hardware to enable NMEA flow. To enable the GGA and RMC sentences, send the following bytes:
24be001105010205310132043301640d0a24be000a0100080b0d0aThe GGA and RMC sentences include everything you need for a single epoch with the exception of accuracy metadata in meters.
$GPGGA,011449.00,3337.45759,N,11154.86471,W,1,03,6.70,445.3,M,-27.5,M,,*6C
$GPRMC,011449.00,A,3337.45759,N,11154.86471,W,0.254,,111225,,,A*6EYour app can calculate the estimated horizontal accuracy by multiplying the GGA.HDOP value (field 8) by 3.9 meters. For vertical accuracy, just double the horizontal accuracy. These values will match what is displayed on the LCD screen and in the Bad Elf GPS app.
The legacy protocol is no longer being actively maintained or supported, so your app should always use the newer
com.bad-elf.gnssprotocol if it's available on the detectedEAAccessory. We are only whitelisting new integrations for the legacy protocol on a case-by-base basis. Please get in touch!
There are two common patterns:
-
Model #1: Auto-connect to the first external Bad Elf GNSS receiver detected, and automatically override the CoreLocation position anytime that receiver is providing a good GPS lock. This is the most user-friendly approach, and is commonly used for EFB or other consumer apps. If your app detects multiple connected receivers via
EAAccessory.framework, it should pick one (and only one) and use that receiver until it disconnects. Then your app can restart the "auto-reconnect to the first receiver found" logic. - Model #2: Let the user pick the exact Bad Elf receiver (by serial number) they want to override CoreLocation, and only auto-connect/use that specific receiver when it's available. This approach is commonly used by GIS/survey apps where the specific receiver configuration is important, or several receivers are being used within range of each other. It also prevents the accidental usage of lower-accuracy location sources that might be coming from CoreLocation.
With both approaches, your app UI should indicate to the user which specific location source is being used (ie: Internal GPS, Bad Elf #123456, etc), and the horizontal accuracy being reported by that source.
For Model #1, your app must support a global setting for the "auto-connect via Bad Elf SDK" logic. It can be enabled by default and can be buried deep in your app settings. This setting is handy for troubleshooting, preventing conflicts with other SDK apps, and working around potential firmware, app, and iOS bugs.
Email us at support@bad-elf.com and we'll get back to you promptly!