nRF Cloud device provisioning
The nRF Device provisioning library enables a device to connect to nRF Cloud Provisioning Service, part of nRF Cloud Security Services. It abstracts and hides the details of the transport and encoding scheme that are used for the payload. The current implementation supports the following technologies:
AT-command based provisioning commands
Writing key-value pair based settings to the Settings storage
TLS-secured HTTP as the communication protocol
DTLS-secured CoAP as the communication protocol
Client authentication with JWT token
CBOR as the data format
Configuration
To enable the library, set the CONFIG_NRF_PROVISIONING
Kconfig option to y
.
CONFIG_NRF_PROVISIONING_AUTO_INIT
- Initializes the client in the system initialization phaseCONFIG_NRF_PROVISIONING_ROOT_CA_SEC_TAG
- Root CA security tag for the Provisioning ServiceCONFIG_NRF_PROVISIONING_INTERVAL_S
- Maximum provisioning interval, in secondsCONFIG_NRF_PROVISIONING_WITH_CERT
- Provisions the root CA certificate to the security tag if the tag is emptyCONFIG_NRF_PROVISIONING_RX_BUF_SZ
- Response buffer sizeCONFIG_NRF_PROVISIONING_TX_BUF_SZ
- Request buffer sizeCONFIG_NRF_PROVISIONING_SHELL
- Enables shell module, which allows you to control the client over UARTCONFIG_NRF_PROVISIONING_SETTINGS_STORAGE_PATH
- Sets the path for provisioning settings storage
Configuration options for HTTP
CONFIG_NRF_PROVISIONING_HTTP_HOSTNAME
- HTTP API hostname for the Provisioning Service, defaultprovisioning-http.nrfcloud.com
CONFIG_NRF_PROVISIONING_HTTP_PORT
- Port number for the Provisioning ServiceCONFIG_NRF_PROVISIONING_HTTP_TIMEOUT_MS
- Timeout in milliseconds for HTTP connection of the Provisioning Service
Configuration options for CoAP
CONFIG_NRF_PROVISIONING_COAP_HOSTNAME
- CoAP API hostname for the Provisioning Service, defaultcoap.nrfcloud.com
CONFIG_NRF_PROVISIONING_COAP_PORT
- Port number for the Provisioning ServiceCONFIG_NRF_PROVISIONING_COAP_DTLS_SESSION_CACHE
- Chooses DTLS session cache
Usage
The usage of the nRF Device provisioning library is described in the following sections.
Initialization
Once initialized, the provisioning client runs on its own in the background. The provisioning client can be initialized in one of the following ways:
The application calls
nrf_provisioning_init()
, which starts the client.Set the client to initialize during Zephyr’s system initialization phase. In this case, it is assumed that a network connection has been established in the same phase.
The function uses the following arguments:
A pointer to a
nrf_provisioning_mm_change
structure that holds a callback function to be called when the modem state changes.A pointer to a
nrf_provisioning_dm_change
structure that holds a callback function to be called when the provisioning state changes.
If you provide null
as a callback function address argument, a corresponding default callback is used.
Subsequent calls to the initialization function will only change the callback functions.
This behavior is beneficial when the client has been initialized during the system initialization phase, but the application wants to register its own callback functions afterwards.
Provisioning
By default, when provisioning is done after receiving the FINISHED
command, the device is rebooted.
The behavior can be overwritten by providing a unique callback function for the initialization function.
If anything is written to the modem’s non-volatile memory, the modem needs to be set in offline mode.
This is because the modem cannot be connected while any data is being written to its storage area.
Once the memory write is complete, the aforementioned callback function must be called again to set the modem to the desired state.
To use the default implementation, NULL
can be passed as an argument to the nrf_provisioning_init()
function.
Copy and modify the default callback function as necessary.
The library starts provisioning when it initializes, then according to the configured interval. The interval is read from the storage settings and can be updated with a provisioning command like any other key-value pair.
During provisioning, the library first tries to establish the transport for communicating with the service. This procedure involves a (D)TLS handshake where the client establishes the correct server. The server uses the JWT generated by the device to authenticate the client. See Modem JWT for more information on client authentication.
The (D)TLS handshake happens twice:
Before requesting commands.
After the execution of the commands, to report the results.
If you are using AT commands, the library shuts down the modem for writing data to the modem’s non-volatile memory. Once the memory writes are complete, the connection is re-established to report the results back to the server. The results are reported back to the server when either all the commands succeed or when an error occurs. If an error occurs, the results of all the commands that are successfully executed before the error and the erroneous result are reported back to the server. All successfully executed commands will be removed from the server-side queue, but if any errors occur, the erroneous command and all the remaining unexecuted commands are removed from the server-side queue. The log contains more information about the issue.
Immediate provisioning can be requested by calling the nrf_provisioning_trigger_manually()
function.
Otherwise, the library attempts provisioning according to the set interval.
To trigger immediate provisioning, the library must be initialized first.
The following message sequence chart shows a successful provisioning sequence:
The following message sequence chart shows a failing provisioning sequence:
nRF Provisioning shell
To test the client, you can enable Zephyr’s shell and provisioning command, which allow you to control the client over UART.
The feature is enabled by selecting CONFIG_NRF_PROVISIONING_SHELL
.
Note
The shell is meant for testing. Do not enable it in production.
uart:~$ nrf_provisioning
nrf_provisioning - nRF Provisioning commands
Subcommands:
init: Start the client
now: Do provisioning now
token: Get the attestation token
uuid: Get device UUID
interval: Set provisioning interval
Dependencies
This library uses the following nRF Connect SDK libraries:
It uses the following sdk-nrfxlib library:
It uses the following Zephyr libraries:
API documentation
include/net/nrf_provisioning.h
subsys/net/lib/nrf_provisioning/src/
- group nrf_provisioning
Typedefs
-
typedef int (*nrf_provisioning_mmode_cb_t)(enum lte_lc_func_mode new_mode, void *user_data)
Callback to request a modem state change, being it powering off, flight mode etc.
- Param new_mode:
New mode.
- Param user_data:
Application-specific data.
- Return:
<0 on error, previous mode on success.
-
typedef void (*nrf_provisioning_event_cb_t)(enum nrf_provisioning_event event, void *user_data)
Called when provisioning state changes.
- Param event:
nrf_provisioning event code.
- Param user_data:
Application-specific data.
Enums
-
enum nrf_provisioning_event
nrf_provisioning callback events
nrf_provisioning events are passed back to the nrf_provisioning_event_cb_t callback function.
Values:
-
enumerator NRF_PROVISIONING_EVENT_START
Provisioning process started. Client will connect to the provisioning service.
-
enumerator NRF_PROVISIONING_EVENT_STOP
Provisioning process stopped. All provisioning commands (if any) executed.
-
enumerator NRF_PROVISIONING_EVENT_DONE
Provisioning complete. “Finished” command received from the provisioning service.
-
enumerator NRF_PROVISIONING_EVENT_START
Functions
-
int nrf_provisioning_init(struct nrf_provisioning_mm_change *mmode, struct nrf_provisioning_dm_change *dmode)
Initializes the provisioning library and registers callback handlers.
Consequent calls will only change callback functions used. Feeding a null as a callback address means that the corresponding default callback function is taken into use.
- Parameters:
mmode – Modem mode change callback. Used when data is written to modem.
dmode – Device mode callback. Used when provisioning state changes.
- Returns:
<0 on error, 0 on success.
-
int nrf_provisioning_trigger_manually(void)
Starts provisioning immediately.
- Return values:
-EFAULT – if the library is uninitialized.
0 – on success.
-
void nrf_provisioning_set_interval(int interval)
Set provisioning interval.
- Parameters:
interval – Provisioning interval in seconds.
-
struct nrf_provisioning_mm_change
- #include <nrf_provisioning.h>
Holds the callback used for querying permission from the application to proceed when modem’s state changes. Together with data set by the callback provider.
- Param cb:
The callback function.
- Param user_data:
Application-specific data to be fed to the callback once it is called.
-
struct nrf_provisioning_dm_change
- #include <nrf_provisioning.h>
Holds the callback to be called once provisioning state changes together with data set by the callback provider.
- Param cb:
The callback function.
- Param user_data:
Application-specific data to be fed to the callback once it is called.
-
typedef int (*nrf_provisioning_mmode_cb_t)(enum lte_lc_func_mode new_mode, void *user_data)