nRF Cloud P-GPS

The nRF Cloud P-GPS library enables applications to request and process Predicted GPS (P-GPS) data from nRF Cloud to be used with the nRF9160 SiP. This library is an enhancement to the nRF Cloud library. It can be used with or without Assisted GNSS (A-GNSS) data from nRF Cloud.

Overview

To get a position fix, a Global Navigation Satellite System (GNSS) module needs information such as the satellite orbital data broadcasted by the satellites.

Predicted GPS (P-GPS) is a form of assistance that reduces the Time to First Fix (TTFF), the time needed by a GNSS module to estimate its position. It is provided through nRF Cloud services. In P-GPS, nRF Cloud provides data containing information about the estimated orbits (Ephemerides) of the 32 GPS satellites for up to two weeks. Each set of ephemerides predictions is valid for a specific four-hour period within the set of all provided predictions. A device using P-GPS downloads the ephemeris predictions from the cloud, stores them in its flash memory, and later injects them into the GNSS module when needed.

P-GPS is designed for devices that are frequently disconnected from the cloud but need periodic GNSS fixes as quickly as possible to save power. This is possible because a device does not need to download ephemerides from the satellite broadcast. However, P-GPS should not be used for general use cases that already work with Assisted GNSS (A-GNSS) only.

Note

When using two-week ephemeris prediction sets, the TTFF towards the end of the second week increases due to the accumulated errors in the predictions and the decreases in the number of satellite ephemerides in the later prediction periods.

P-GPS requires a cloud connection approximately once a week to download new predictions, depending on the configuration settings. With A-GNSS, new ephemerides are needed on average every two hours, or if the fix interval is longer, whenever GNSS is started.

Note

To use the nRF Cloud P-GPS service, you need an nRF Cloud account, and the device needs to be associated with the account.

Configuration

Configure the CONFIG_NRF_CLOUD_PGPS Kconfig option to enable or disable the use of this library.

Configure one of the following options to control the network transport for P-GPS requests and responses:

Configure one of the following options to control the network transport for downloading P-GPS predictions:

Configure these additional options to refine the behavior of P-GPS:

Configure the CONFIG_NRF_CLOUD_AGNSS option if you need your application to also use A-GNSS, for time and coarse position data and to get the fastest TTFF. Using A-GNSS also improves the accuracy because of ionospheric corrections.

Note

Disable this option if you do not want to use A-GNSS (due to data costs or expected frequent loss of cloud connectivity).

You must also configure the following options for storing settings, for having accurate clock time, and for having a location to store predictions:

The P-GPS library requires a storage location in the flash memory for storing the P-GPS prediction data. There are three ways to define this storage location:

  • To use a dedicated partition, enable the CONFIG_NRF_CLOUD_PGPS_STORAGE_PARTITION option.

    By default, this partition is stored in the main SoC flash. This partition can optionally be located in external flash for the nRF9160 development kit version 0.14.0 and later. This conserves space in the main flash for storing code or other data.

    To use an external flash partition, enable the following options in your project’s configuration file or place them in a configuration overlay file (for example samples/cellular/nrf_cloud_mqtt_multi_service/overlay_pgps_ext_flash.conf):

    If you are using the P-GPS external flash partition and full modem FOTA, ensure the FMFU partition is also enabled:

    Also, specify your development kit version by appending it to the board name. For example, if your development kit version is 1.0.1, use the board name nrf9160dk_nrf9160_ns@1_0_1 in your build command.

    Note

    If you fail to specify the version, the build system selects a baseline board version which does not include external flash. This results in a build failure:

    devicetree error: /chosen: undefined node label 'mx25r64'
    

    Finally, add the following to a device tree overlay for your board.

    / {
      chosen {
        nordic,pm-ext-flash = &mx25r64;
      };
    };
    
    /* Enable high drive mode for the SPI3 pins to get a square signal at 8 MHz */
    &spi3_default {
      group1 {
        nordic,drive-mode = <NRF_DRIVE_H0H1>;
      };
    };
    

    This is typically placed in a file within your application’s source folder in a boards subfolder. See an example provided in the file samples/cellular/nrf_cloud_mqtt_multi_service/boards/nrf9160dk_nrf9160_ns_0_14_0.overlay.

  • To use the MCUboot secondary partition as storage, enable the CONFIG_NRF_CLOUD_PGPS_STORAGE_MCUBOOT_SECONDARY option.

    Use this option if the flash memory for your application is too full to use a dedicated partition, and the application uses MCUboot for FOTA updates but not for MCUboot itself.

    Do not use this option if you are using MCUboot as a second-stage upgradable bootloader and also have FOTA updates enabled for MCUboot itself, not just the application (using CONFIG_SECURE_BOOT and CONFIG_BUILD_S1_VARIANT). Otherwise, the P-GPS library prevents the full completion of MCUboot update, and the first-stage immutable bootloader reverts MCUboot to its previous image.

  • To use an application-specific storage, enable the CONFIG_NRF_CLOUD_PGPS_STORAGE_CUSTOM option.

    You must also pass the address and the size of your custom location in the flash memory to the nrf_cloud_pgps_init() function.

    Note

    The address must be aligned to a flash page boundary, and the size must be equal to or greater than 2048 bytes times the CONFIG_NRF_CLOUD_PGPS_NUM_PREDICTIONS option.

    Use this option if you do not use MCUboot and you want complete control over the storing location of P-GPS data in the flash memory.

See Configuring your application for information on how to change configuration options.

Usage

A device can use P-GPS together with A-GNSS. This provides the following advantages:

  • It shortens TTFF compared to using only P-GPS.

  • A-GNSS provides ionospheric correction data, which improves accuracy.

In particular, A-GNSS is beneficial when the device is powered on. Getting GPS system time and coarse location using A-GNSS can significantly shorten the time needed for the first fix. As long as the modem remains powered on, GNSS “knows” the previous location and the current time with sufficient accuracy.

To improve accuracy, ionospheric correction data can also be downloaded periodically using A-GNSS. If used, the ionospheric correction data should be updated at least every 24 hours.

There should be no need to download almanacs with A-GNSS, because it is assumed that the device has valid ephemerides (predictions) for all satellites available at all times. Because ephemerides and almanacs do not need to be downloaded with A-GNSS, the amount of data is very small, less than 200 bytes.

Initialization

Ideally, once the device has connected to the cloud, the application must call the P-GPS initialization function. If a connection is not available, initialization must still be called. If the CONFIG_NRF_CLOUD_PGPS_REQUEST_UPON_INIT option is disabled, the initialization function does not automatically download missing P-GPS data. In these cases, predictions might be unavailable until a connection is established to the cloud.

Note

Each prediction requires 2 kB of flash. For prediction period of 240 minutes (four hours), and with 42 predictions in a week, the flash requirement adds up to 84 kB.

The P-GPS subsystem’s nrf_cloud_pgps_init() function takes a pointer to a nrf_cloud_pgps_init_param structure. If the CONFIG_NRF_CLOUD_PGPS_STORAGE_CUSTOM option is enabled, the structure must specify the storage base address and the storage size in the flash memory where the P-GPS subsystem stores predictions. It can optionally pass a pointer to a pgps_event_handler_t() callback function.

Note

The storage base address must be aligned to the flash memory page boundary.

Time

The proper operation of the P-GPS subsystem depends on an accurate sense of time. For use cases where a cloud connection can be established easily, use the Date-Time library with NTP enabled. Otherwise, use a battery-backed real-time clock calendar chip so that accurate time is available regardless of cloud availability after reset.

Transport mechanisms

Complete these three steps to request and store P-GPS data in the device:

  1. Send the request to nRF Cloud.

  2. Receive a URL from nRF Cloud pointing to the prediction set.

  3. Download the predictions from the URL.

The first two steps use the network transport defined by the CONFIG_NRF_CLOUD_PGPS_TRANSPORT option.

The default configuration selects the CONFIG_NRF_CLOUD_PGPS_TRANSPORT_MQTT option if the CONFIG_NRF_CLOUD_MQTT option is active. MQTT use is built into the P-GPS library.

The library uses REST or other transports by means of the CONFIG_NRF_CLOUD_PGPS_TRANSPORT_NONE option. REST support is not built into the P-GPS library and must be provided by the application. The Cellular: GNSS sample is one example of using REST.

The third step uses the network transport defined by the CONFIG_NRF_CLOUD_PGPS_DOWNLOAD_TRANSPORT option.

The P-GPS library uses the CONFIG_NRF_CLOUD_PGPS_DOWNLOAD_TRANSPORT_HTTP option when using MQTT for the main transport. Applications that use REST for the main transport usually use the HTTP option for the download transport. This download transport is built into the P-GPS library.

Alternatively, use the CONFIG_NRF_CLOUD_PGPS_DOWNLOAD_TRANSPORT_CUSTOM with CONFIG_NRF_CLOUD_PGPS_TRANSPORT_NONE to manage the full flow of data outside of the P-GPS library. Call the following functions when using this configuration:

  1. nrf_cloud_pgps_begin_update()

  2. nrf_cloud_pgps_process_update()

  3. nrf_cloud_pgps_finish_update()

Requesting and processing P-GPS data

The library offers two different ways to control the timing of P-GPS cloud requests:

The indirect methods are used in the Asset Tracker v2 and the Serial LTE modem applications. They are simpler to use than the direct methods. The direct method is used in the Cellular: GNSS sample.

When nRF Cloud responds with the requested P-GPS data, the library sends the CLOUD_EVT_DATA_RECEIVED event. The application’s cloud_evt_handler_t() function receives this event. The handler calls the nrf_cloud_pgps_process() function that parses the data and stores it.

Finding a prediction and injecting to modem

A P-GPS prediction for the current date and time can be retrieved using one of the following methods:

The indirect method is used in the Cellular: GNSS sample and in the Asset Tracker v2 and Serial LTE modem applications.

The application can inject the data contained in the prediction to the GNSS module in the modem by calling the nrf_cloud_pgps_inject() function. This must be done when event NRF_MODEM_GNSS_EVT_AGNSS_REQ is received from the GNSS interface. After injecting the prediction, call the nrf_cloud_pgps_preemptive_updates() function to update the prediction set as needed.

A prediction is also automatically injected to the modem every four hours whenever the current prediction expires and the next one begins (if the next one is available in flash).

Interaction with the GNSS interface

The P-GPS subsystem, like several other nRF Cloud subsystems, is event driven.

Following are the two GNSS events relating to P-GPS that an application receives through the GNSS interface:

  • NRF_MODEM_GNSS_EVT_AGNSS_REQ - Occurs when the GNSS module requires assistance data.

  • NRF_MODEM_GNSS_EVT_FIX - Occurs once a fix is attained.

When the application receives the NRF_MODEM_GNSS_EVT_AGNSS_REQ event, it must call the nrf_cloud_pgps_notify_prediction() function. This event results in the callback of the application’s pgps_event_handler_t() function when a valid P-GPS prediction set is available. It passes the PGPS_EVT_AVAILABLE event and a pointer to the nrf_cloud_pgps_prediction structure to the handler.

The application must pass this prediction to the nrf_cloud_pgps_inject() function, along with either the nrf_modem_gnss_agnss_data_frame structure read from the GNSS interface after the NRF_MODEM_GNSS_EVT_AGNSS_REQ event or NULL.

If the device does not move distances longer than a few dozen kilometers before it gets a new GNSS fix, it can pass the latitude and longitude read after the NRF_MODEM_GNSS_EVT_FIX event to the nrf_cloud_pgps_set_location() function. The P-GPS subsystem uses this stored location for the next GNSS request for position assistance when A-GNSS assistance is not enabled or is unavailable. If the device moves further between fix attempts, such a mechanism can be detrimental to short TTFF, as the saved position might be too inaccurate to be useful.

The application can also call the nrf_cloud_pgps_preemptive_updates() function to discard expired predictions and replace them with newer ones, before the expiration of the entire set of predictions. This can be useful in use cases where cloud connections are available infrequently. The CONFIG_NRF_CLOUD_PGPS_REPLACEMENT_THRESHOLD option sets the minimum number of valid predictions remaining before such an update occurs.

For best performance, applications can call the P-GPS functions mentioned in this section from workqueue handlers rather than directly from various callback functions.

The P-GPS subsystem itself generates events that can be passed to a registered callback function. See nrf_cloud_pgps_event_type.

Dependencies

This library uses the following nRF Connect SDK libraries:

It uses the following sdk-nrfxlib library:

It uses the following Zephyr subsystem:

API documentation

Header file: include/net/nrf_cloud_pgps.h
Source files: subsys/net/lib/nrf_cloud/src/
group nrf_cloud_pgps

Defines

NRF_CLOUD_PGPS_NUM_SV
NRF_CLOUD_PGPS_REQ_NO_COUNT

Omit the prediction count from P-GPS request

NRF_CLOUD_PGPS_REQ_NO_INTERVAL

Omit the prediction validity period from P-GPS request

NRF_CLOUD_PGPS_REQ_NO_GPS_DAY

Omit the GPS day from P-GPS request

NRF_CLOUD_PGPS_REQ_NO_GPS_TOD

Omit the GPS time of day from P-GPS request

ETIMEUNKNOWN

P-GPS error code: current time unknown.

ELOADING

P-GPS error code: not found but loading in progress.

NRF_CLOUD_PGPS_EMPTY_EPHEM_HEALTH

Value to mark the ephemeris as unavailable for satellites for which no predictions are available from the cloud.

Typedefs

typedef void (*pgps_event_handler_t)(struct nrf_cloud_pgps_event *event)

Event handler registered with the module to handle asynchronous events from the module.

Param event:

[in] The event that just occurred.

Enums

enum nrf_cloud_pgps_event_type

P-GPS event passed to the registered pgps_event_handler.

Values:

enumerator PGPS_EVT_INIT

P-GPS initialization beginning.

enumerator PGPS_EVT_UNAVAILABLE

There are currently no P-GPS predictions available.

enumerator PGPS_EVT_LOADING

P-GPS predictions are being loaded from the cloud.

enumerator PGPS_EVT_AVAILABLE

A P-GPS prediction is available now for the current date and time. The prediction pointer in the associated nrf_cloud_pgps_event structure points to the prediction.

enumerator PGPS_EVT_READY

All P-GPS predictions are available.

enumerator PGPS_EVT_REQUEST

A P-GPS request has been created for missing predictions. The event has payload in the form of gps_pgps_request. The event is intended to be used when CONFIG_NRF_CLOUD_PGPS_TRANSPORT_MQTT is disabled to let the application decide when and how to use the request information. This event type is not received if CONFIG_NRF_CLOUD_PGPS_TRANSPORT_MQTT is enabled.

Functions

void nrf_cloud_pgps_set_location_normalized(int32_t latitude, int32_t longitude)

Update storage of the most recent known location, in modem-specific normalized format (int32_t). Current time is also stored. Normalization: (latitude / 90.0) * (1 << 23) (longitude / 360.0) * (1 << 24)

Parameters:
  • latitude – Current latitude normalized.

  • longitude – Current longitude in normalized.

void nrf_cloud_pgps_set_location(double latitude, double longitude)

Update the storage of the most recent known location in degrees. This will be injected along with the current time and relevant predicted ephemerides to the GPS unit in order to get the fastest possible fix, when the P-GPS subsystem is built with A-GNSS disabled, or when A-GNSS data is unavailable due to lack of a cloud connection. Current time is also stored.

Parameters:
  • latitude – Current latitude in degrees.

  • longitude – Current longitude in degrees.

void nrf_cloud_pgps_clear_location(void)

If location has previously been set, clear it. The application should do this if significant distances might have been travelled since the previous location was saved.

void nrf_cloud_pgps_set_leap_seconds(int leap_seconds)

Update the storage of the leap second offset between GPS time and UTC. This called automatically by the A-GNSS subsystem (if enabled) when it receives a UTC assistance element, setting leap_seconds to the delta_tls field.

Parameters:
  • leap_seconds – Offset in seconds.

int nrf_cloud_pgps_notify_prediction(void)

Schedule a callback when prediction for current time is available. Callback could be immediate, if data already stored in Flash, or later, after loading from the cloud.

Returns:

0 if scheduled successfully, or negative error code if could not send request to cloud.

int nrf_cloud_pgps_find_prediction(struct nrf_cloud_pgps_prediction **prediction)

Tries to find an appropriate GPS prediction for the current time.

Parameters:
  • prediction – Pointer to a pointer to a prediction; the pointer at this pointer will be modified to point to the prediction if the return value is 0. Will be set to NULL on failure.

Returns:

0..NumPredictions-1 if successful; -ETIMEUNKNOWN if current date and time not known; -ETIMEDOUT if all predictions stored are expired; -EINVAL if prediction for the current time is invalid.

int nrf_cloud_pgps_request(const struct gps_pgps_request *request)

Requests specified P-GPS data from nRF Cloud via MQTT. Not used for other transports.

Parameters:
  • request – Pointer to structure specifying what P-GPS data is desired. The request may fail if there no cloud connection; if the specified GPS day and GPS time of day is in the past or more than 2 weeks in the future; if the GPS time of day is larger than 86339; or if the prediction_period_min field is not within the range 120 to 480.

Return values:
  • 0 – Request sent successfully.

  • -EACCES – Cloud connection is not established; wait for NRF_CLOUD_EVT_READY.

Returns:

A negative value indicates an error.

int nrf_cloud_pgps_request_all(void)

Requests all available P-GPS data from nRF Cloud via MQTT. Not used for other transports.

Returns:

0 if successful, otherwise a (negative) error code.

int nrf_cloud_pgps_begin_update(void)

Use this function when you use a custom transport mechanism for downloading prediction data. When your pgps_event_handler_t receives a PGPS_EVT_REQUEST event, send the P-GPS request to the cloud over your transport, then call this function. This function resets the internal state of the library and prepares the flash storage to receive incoming data.

The library calls this automatically for HTTP(S) transports.

Return values:
  • 0 – Ready for updating.

  • -ENOMEM – No free space in P-GPS flash storage area.

  • -EBUSY – P-GPS download already in progress.

  • -ENODEV – Flash device is not ready.

  • -EFAULT – Error accessing flash stream.

Returns:

a negative value indicates an error.

int nrf_cloud_pgps_process_update(uint8_t *buf, size_t len)

Call this function when your transport receives a block of prediction data. Prediction data must be received in file order.

The library calls this automatically for HTTP(S) transports.

Parameters:
  • buf – Pointer to P-GPS data received from transport.

  • len – Size of P-GPS data chunk received from transport.

Return values:
  • 0 – Buffer processed.

  • -EINVAL – Invalid parameter to function or invalid header in P-GPS data received.

  • -ENODATA – Unable to determine current date and time.

  • -ENOMEM – No free flash in P-GPS storage area.

  • -EFAULT – Error writing to flash stream.

Returns:

a negative value indicates an error.

int nrf_cloud_pgps_finish_update(void)

Call this function regardless of whether the download succeeded or failed.

The library calls this automatically for HTTP(S) transports.

For custom transports, the application must call this for transport error, error from a call to nrf_cloud_pgps_process_update(), as well as successful completion. Further, when an error occurs, the application must terminate the transfer.

Return values:

0 – No failure.

Returns:

a negative value indicates an error.

void nrf_cloud_pgps_request_reset(void)

If previous request for P-GPS data failed, re-enable future retries. This should be called by the application after it attempts to handle PGPS_EVT_REQUEST, but is unable to complete it successfully. For example, it should be called if the cloud connection being used to transmit the request is temporarily unavailable.

No need to call when using the MQTT transport.

int nrf_cloud_pgps_process(const char *buf, size_t buf_len)

Processes binary P-GPS data received from nRF Cloud over MQTT or REST.

Parameters:
  • buf – Pointer to data received from nRF Cloud.

  • buf_len – Buffer size of data to be processed.

Return values:
  • 0 – P-GPS data successfully processed.

  • -EFAULT – An nRF Cloud P-GPS error code was processed.

Returns:

A negative value indicates an error.

int nrf_cloud_pgps_update(struct nrf_cloud_pgps_result *file_location)

Processes binary P-GPS data using URL received from nRF Cloud.

Parameters:
  • file_location – Pointer to structure holding the hostname and filename.

Return values:
  • 0 – P-GPS data successfully processed.

  • -EFAULT – An nRF Cloud P-GPS error code was processed.

Returns:

A negative value indicates an error.

int nrf_cloud_pgps_inject(struct nrf_cloud_pgps_prediction *p, const struct nrf_modem_gnss_agnss_data_frame *request)

Injects binary P-GPS data to the modem. If request is NULL, it is assumed that only ephemerides assistance should be injected.

Parameters:
  • p – Pointer to a prediction.

  • request – Which assistance elements the modem needs. May be NULL.

Returns:

0 if successful, otherwise a (negative) error code.

bool nrf_cloud_pgps_loading(void)

Find out if P-GPS update is in progress.

Returns:

True if request sent but loading not yet completed.

int nrf_cloud_pgps_preemptive_updates(void)

Download more predictions if less than CONFIG_NRF_CLOUD_PGPS_REPLACEMENT_THRESHOLD predictions remain which are still valid.

Returns:

0 if successful, otherwise a (negative) error code.

int nrf_cloud_pgps_init(struct nrf_cloud_pgps_init_param *param)

Initialize P-GPS subsystem. Validates what is stored, then requests any missing predictions, or full set if expired or missing. When successful, it is ready to provide valid ephemeris predictions.

Note

It must return successfully before using P-GPS services.

Parameters:
  • param[in] Initialization parameters.

Returns:

0 if valid or request begun; nonzero on error.

struct nrf_cloud_pgps_system_time
#include <nrf_cloud_pgps.h>

nrf_cloud_pgps_system_time is a special version of nrf_cloud_agnss_system_time that does not include the full array of sv_tow values; this is transferred from the cloud as part of each prediction, to indicate the date_day and time_full_s for the center of each prediction’s validity period.

Public Members

uint16_t date_day

Number of days since GPS time began on 6 Jan 1980 for the center of a prediction’s validity period.

uint32_t time_full_s

Seconds into GPS day for center of validity period.

uint16_t time_frac_ms

Will be 0.

uint32_t sv_mask

Will be 0.

uint32_t pad

Placeholder where sv_tow[32] is for A-GNSS.

struct nrf_cloud_pgps_prediction
#include <nrf_cloud_pgps.h>

P-GPS prediction Flash storage format.

Public Members

uint8_t time_type

Set to NRF_CLOUD_AGNSS_GPS_SYSTEM_CLOCK.

uint16_t time_count

Will be 1.

struct nrf_cloud_pgps_system_time time

Information about when this prediction is applicable.

uint8_t schema_version

Not from cloud; inserted during storage to ease reusing A-GNSS code.

uint8_t ephemeris_type

Set to NRF_CLOUD_AGNSS_EPHEMERIDES.

uint16_t ephemeris_count

Usually will be NRF_CLOUD_PGPS_NUM_SV.

struct nrf_cloud_agnss_ephemeris ephemerii[(32U)]

Array of satellite orbital equation coefficients.

uint32_t sentinel

Not from cloud; appended during storage to verify integrity on retrieval.

struct gps_pgps_request
#include <nrf_cloud_pgps.h>

P-GPS request type.

Public Members

uint16_t prediction_count

Number of predictions desired.

uint16_t prediction_period_min

Validity time per prediction, in minutes. Valid range 120 to 480.

uint16_t gps_day

Number of days since GPS time began on 6 Jan 1980 for the center of the first prediction desired.

uint32_t gps_time_of_day

Number of seconds since the start of this GPS day for the center of the first prediction desired. Valid range 0 to 86399.

struct nrf_cloud_pgps_result
#include <nrf_cloud_pgps.h>

nRF Cloud Predicted GPS (P-GPS) result; the location of the P-GPS data file which is to be downloaded and provided to nrf_cloud_pgps_process().

Public Members

char *host

User-provided buffer to hold download host name

size_t host_sz

Size of user-provided host buffer

char *path

User-provided buffer to hold download path/file name

size_t path_sz

Size of user-provided path buffer

struct nrf_cloud_pgps_event
#include <nrf_cloud_pgps.h>
struct nrf_cloud_pgps_init_param
#include <nrf_cloud_pgps.h>

Initialization parameters for the module.

Public Members

pgps_event_handler_t event_handler

Event handler that is registered with the module.

uint32_t storage_base

Flash storage address. Must be on a Flash page boundary.

uint32_t storage_size

Flash storage size. Must be a multiple of a Flash page in size, in bytes.