Skip to content

Commit

Permalink
net: lib: nrf_cloud: Add new CoAP library
Browse files Browse the repository at this point in the history
Uses the Zephyr coap_client library. Sends and receives
data with nRF Cloud using CBOR and sometimes JSON.

Supports most nRF Cloud services - FOTA, data messaging,
location services (cellular, Wi-Fi, A-GPS, P-GPS).

Signed-off-by: Pete Skeggs <peter.skeggs@nordicsemi.no>
  • Loading branch information
plskeggs committed Jul 18, 2023
1 parent acd755c commit 8c62307
Show file tree
Hide file tree
Showing 43 changed files with 4,638 additions and 79 deletions.
23 changes: 22 additions & 1 deletion include/net/nrf_cloud.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,20 @@ enum nrf_cloud_sensor {
NRF_CLOUD_SENSOR_LIGHT,
};

/** @brief Data types for nrf_cloud_sensor_data. */
enum nrf_cloud_data_type {
/** The struct nrf_cloud_data structure points to the data and indicates its length.
* The contents of the block are identified with the enum nrf_cloud_sensor type.
*/
NRF_CLOUD_DATA_TYPE_BLOCK,
/** The const char *str_val field points to a NULL-terminated string. */
NRF_CLOUD_DATA_TYPE_STR,
/** The double double_val field contains the data. */
NRF_CLOUD_DATA_TYPE_DOUBLE,
/** The int int_val field contains the data. */
NRF_CLOUD_DATA_TYPE_INT
};

/** @brief Topic types supported by nRF Cloud. */
enum nrf_cloud_topic_type {
/** Endpoint used to update the cloud-side device shadow state . */
Expand Down Expand Up @@ -373,8 +387,15 @@ struct nrf_cloud_topic {
struct nrf_cloud_sensor_data {
/** The sensor that is the source of the data. */
enum nrf_cloud_sensor type;
/** The data type to encode. */
enum nrf_cloud_data_type data_type;
/** Sensor data to be transmitted. */
struct nrf_cloud_data data;
union {
struct nrf_cloud_data data;
const char *str_val;
double double_val;
int int_val;
};
/** Unique tag to identify the sent data. Can be used to match
* acknowledgment on the NRF_CLOUD_EVT_SENSOR_DATA_ACK event.
* Valid range: NCT_MSG_ID_USER_TAG_BEGIN to NCT_MSG_ID_USER_TAG_END.
Expand Down
254 changes: 254 additions & 0 deletions include/net/nrf_cloud_coap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#ifndef NRF_CLOUD_COAP_H_
#define NRF_CLOUD_COAP_H_

/** @file nrf_cloud_coap.h
* @brief Module to provide nRF Cloud CoAP API
*/

#ifdef __cplusplus
extern "C" {
#endif

#include <net/nrf_cloud_rest.h>
#include <net/nrf_cloud_agps.h>
#include <net/nrf_cloud_pgps.h>
#include <zephyr/net/coap_client.h>

/**
* @defgroup nrf_cloud_coap nRF CoAP API
* @{
*/

/* Transport functions */
/** @brief Initialize nRF Cloud CoAP library.
*
* @return 0 if initialization was successful, otherwise, a negative error number.
*/
int nrf_cloud_coap_init(void);

/**
* @brief Connect to and obtain authorization to access the nRF Cloud CoAP server.
*
* This function must return 0 indicating success so that the other functions below,
* other than nrf_cloud_coap_disconnect(), will not immediately return an error when called.
*
* @return 0 if authorized successfully, otherwise, a negative error number.
*/
int nrf_cloud_coap_connect(void);

/**
* @brief Pause CoAP connection.
*
* This function temporarily pauses the nRF Cloud CoAP connection so that
* another DTLS socket can be opened and used. Once the new socket is no longer needed,
* close that one, then use nrf_cloud_coap_resume() to resume using CoAP.
* Do not call nrf_cloud_coap_disconnect() nor shut down the LTE connection,
* or else the requisite data for the socket will be discarded in the modem,
* and the connection cannot be resumed. In that case, call nrf_cloud_coap_connect(),
* which results in a full DTLS handshake.
*
* @retval -EACCES if DTLS CID was not active or the connection was not authenticated.
* @retval -EAGAIN if an error occurred while saving the connection; it is still usable.
* @retval -EINVAL if the operation could not be performed.
* @retval -ENOMEM if too many connections are already saved (four).
* @retval 0 If successful.
*/
int nrf_cloud_coap_pause(void);

/**
* @brief Resume CoAP connection.
*
* This function restores a previous connection for use.
*
* @retval -EACCES if the connection was not previously paused.
* @retval -EAGAIN if an error occurred while loading the connection.
* @retval -EINVAL if the operation could not be performed.
* @retval 0 If successful.
*/
int nrf_cloud_coap_resume(void);

/**
* @brief Disconnect the nRF Cloud CoAP connection.
*
* This does not teardown the thread in coap_client, as there is no way to do so.
* The thread's call to poll(sock) will fail, resulting in an error message.
* This is expected. Call nrf_cloud_coap_connect() to re-establish the connection, and
* the thread in coap_client will resume.
*
* @return 0 if the socket was closed successfully, or a negative error number.
*/
int nrf_cloud_coap_disconnect(void);

/* nRF Cloud service functions */

/**
* @brief Request nRF Cloud CoAP Assisted GPS (A-GPS) data.
*
* @param[in] request Data to be provided in API call.
* @param[in,out] result Structure pointing to caller-provided buffer in which to store A-GPS data.
*
* @retval -EINVAL will be returned, and an error message printed, if invalid parameters
* are given.
* @retval -ENOENT will be returned if there was no A-GPS data requested for the specified
* request type.
* @retval -ENOBUFS will be returned, and an error message printed, if there is not enough
* buffer space to store retrieved AGPS data.
* @retval 0 If successful.
*/
int nrf_cloud_coap_agps_data_get(struct nrf_cloud_rest_agps_request const *const request,
struct nrf_cloud_rest_agps_result *result);

/**
* @brief Request URL for nRF Cloud Predicted GPS (P-GPS) data.
*
* After a successful call to this function, pass the file_location to
* nrf_cloud_pgps_update(), which then downloads and processes the file's binary P-GPS data.
*
* @param[in] request Data to be provided in API call.
* @param[in,out] file_location Structure that will contain the host and path to
* the prediction file.
*
* @retval 0 If successful.
* Otherwise, a (negative) error code is returned.
*/
int nrf_cloud_coap_pgps_url_get(struct nrf_cloud_rest_pgps_request const *const request,
struct nrf_cloud_pgps_result *file_location);

/**
* @brief Send a sensor value to nRF Cloud.
*
* The CoAP message is sent as a non-confirmable CoAP message.
*
* @param[in] app_id The app_id identifying the type of data. See the values in nrf_cloud_defs.h
* that begin with NRF_CLOUD_JSON_APPID_. You may also use custom names.
* @param[in] value Sensor reading.
* @param[in] ts_ms Timestamp the data was measured, or NRF_CLOUD_NO_TIMESTAMP.
*
* @retval 0 If successful.
* Otherwise, a (negative) error code is returned.
*/
int nrf_cloud_coap_sensor_send(const char *app_id, double value, int64_t ts_ms);

/**
* @brief Send the device location in the @ref nrf_cloud_gnss_data PVT field to nRF Cloud.
*
* The CoAP message is sent as a non-confirmable CoAP message. Only
* @ref NRF_CLOUD_GNSS_TYPE_PVT is supported.
*
* @param[in] gnss A pointer to an @ref nrf_cloud_gnss_data struct indicating the device
* location, usually as determined by the GNSS unit.
*
* @retval 0 If successful.
* Otherwise, a (negative) error code is returned.
*/
int nrf_cloud_coap_location_send(const struct nrf_cloud_gnss_data * const gnss);

/**
* @brief Request device location from nRF Cloud.
*
* At least one of cell_info or wifi_info must be provided within the request.
*
* @param[in] request Data to be provided in API call.
* @param[in,out] result Location information.
*
* @return 0 if the request succeeded, a positive value indicating a CoAP result code,
* or a negative error number.
*/
int nrf_cloud_coap_location_get(struct nrf_cloud_rest_location_request const *const request,
struct nrf_cloud_location_result *const result);

/**
* @brief Request current nRF Cloud FOTA job info for the specified device.
*
* @param[out] job Parsed job info. If no job exists, type will
* be set to invalid. If a job exists, user must call
* @ref nrf_cloud_rest_fota_job_free to free the memory
* allocated by this function.
*
* @return 0 if the request succeeded, a positive value indicating a CoAP result code,
* or a negative error number.
*/
int nrf_cloud_coap_fota_job_get(struct nrf_cloud_fota_job_info *const job);

/**
* @brief Free memory allocated by nrf_cloud_coap_current_fota_job_get().
*
* @param[in,out] job Job info to be freed.
*
*/
void nrf_cloud_coap_fota_job_free(struct nrf_cloud_fota_job_info *const job);

/**
* @brief Update the status of the specified nRF Cloud FOTA job.
*
* @param[in] job_id Null-terminated FOTA job identifier.
* @param[in] status Status of the FOTA job.
* @param[in] details Null-terminated string containing details of the
* job, such as an error description.
*
* @return 0 if the request succeeded, a positive value indicating a CoAP result code,
* or a negative error number.
*/
int nrf_cloud_coap_fota_job_update(const char *const job_id,
const enum nrf_cloud_fota_status status, const char * const details);

/**
* @brief Query the device's shadow delta.
*
* If there is no delta, the return value will be 0 and the length of the string stored
* in buf will be 0.
*
* @param[in,out] buf Pointer to memory in which to receive the delta.
* @param[in] buf_len Size of buffer.
* @param[in] delta True to request only changes in the shadow, if any; otherwise,
* all of desired part.
*
* @return 0 if the request succeeded, a positive value indicating a CoAP result code,
* or a negative error number.
*/
int nrf_cloud_coap_shadow_get(char *buf, size_t buf_len, bool delta);

/**
* @brief Update the device's "state" in the shadow via the UpdateDeviceState endpoint.
*
* @param[in] shadow_json Null-terminated JSON string to be written to the device's shadow.
*
* @return 0 if the request succeeded, a positive value indicating a CoAP result code,
* or a negative error number.
*/
int nrf_cloud_coap_shadow_state_update(const char * const shadow_json);

/**
* @brief Update the device status in the shadow.
*
* @param[in] dev_status Device status to be encoded.
*
* @return 0 if the request succeeded, a positive value indicating a CoAP result code,
* or a negative error number.
*/
int nrf_cloud_coap_shadow_device_status_update(const struct nrf_cloud_device_status
*const dev_status);

/**
* @brief Update the device's "serviceInfo" in the shadow.
*
* @param[in] svc_inf Service info items to be updated in the shadow.
*
* @return 0 if the request succeeded, a positive value indicating a CoAP result code,
* or a negative error number.
*/
int nrf_cloud_coap_shadow_service_info_update(const struct nrf_cloud_svc_info * const svc_inf);

/** @} */

#ifdef __cplusplus
}
#endif

#endif /* NRF_CLOUD_COAP_H_ */
1 change: 1 addition & 0 deletions subsys/net/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ if (DEFINED CONFIG_NRF_CLOUD_MQTT OR
DEFINED CONFIG_NRF_CLOUD_PGPS OR
DEFINED CONFIG_NRF_CLOUD_REST OR
DEFINED CONFIG_NRF_CLOUD_FOTA OR
DEFINED CONFIG_NRF_CLOUD_COAP OR
DEFINED CONFIG_NRF_CLOUD_LOCATION)
add_subdirectory(nrf_cloud)
endif()
Expand Down
18 changes: 18 additions & 0 deletions subsys/net/lib/nrf_cloud/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,22 @@ zephyr_library_sources_ifdef(
zephyr_library_sources_ifdef(
CONFIG_NRF_CLOUD_REST
src/nrf_cloud_rest.c)
zephyr_compile_definitions_ifdef(
CONFIG_NRF_CLOUD_COAP
nrf_cloud_coap CDDL_CBOR_CANONICAL)
zephyr_library_sources_ifdef(
CONFIG_NRF_CLOUD_COAP
coap/src/agps_encode.c
coap/src/nrf_cloud_coap_transport.c
coap/src/coap_codec.c
coap/src/nrfc_dtls.c
coap/src/ground_fix_encode.c
coap/src/ground_fix_decode.c
coap/src/msg_encode.c
coap/src/nrf_cloud_coap.c
coap/src/pgps_decode.c
coap/src/pgps_encode.c)
zephyr_include_directories_ifdef(
CONFIG_NRF_CLOUD_COAP
coap/include)
zephyr_include_directories(./include)
4 changes: 3 additions & 1 deletion subsys/net/lib/nrf_cloud/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ rsource "Kconfig.nrf_cloud_alert"

rsource "Kconfig.nrf_cloud_log"

rsource "Kconfig.nrf_cloud_coap"

config NRF_CLOUD_GATEWAY
bool "nRF Cloud Gateway"
help
Enables functionality in this device to be compatible with
nRF Cloud LTE gateway support.

if NRF_CLOUD_MQTT || NRF_CLOUD_REST || NRF_CLOUD_PGPS || MODEM_JWT
if NRF_CLOUD_MQTT || NRF_CLOUD_REST || NRF_CLOUD_PGPS || MODEM_JWT || NRF_CLOUD_COAP

config NRF_CLOUD_HOST_NAME
string "nRF Cloud server hostname"
Expand Down
56 changes: 56 additions & 0 deletions subsys/net/lib/nrf_cloud/Kconfig.nrf_cloud_coap
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Copyright (c) 2023 Nordic Semiconductor
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

menuconfig NRF_CLOUD_COAP
bool "nRF Cloud COAP"
select CJSON_LIB
select ZCBOR
select COAP
select COAP_EXTENDED_OPTIONS_LEN
select COAP_CLIENT
select EXPERIMENTAL

if NRF_CLOUD_COAP

config NRF_CLOUD_COAP_SERVER_HOSTNAME
string "CoAP server hostname"
default "coap.dev.nrfcloud.com"

config NRF_CLOUD_COAP_SEC_TAG
int "Security tag for credentials"
default NRF_CLOUD_SEC_TAG

config NRF_CLOUD_COAP_SERVER_PORT
int "CoAP server port"
default 5684

config NON_RESP_RETRIES
int "Number of times to retry waiting for a response to a NON request"
default 0
help
Non confirmable requests are usually used to send data to the cloud
for which it is OK if it is sometimes lost. A value of 0 means it is
acceptable if no response is received from the cloud. Non-zero values
result in up to this number of retransmissions of the request followed
by waits for a response.

if WIFI

config NRF_CLOUD_COAP_SEND_SSIDS
bool "Include access point SSIDs with scan results"
default n
help
The nRF Cloud Wi-Fi location service does not require the human-
readable SSIDs in order to determine the device location. It does
require the access point MAC addresses. By not including SSIDs
the amount of data sent to the cloud is greatly reduced.

endif

module = NRF_CLOUD_COAP
module-str = nRF Cloud COAP
source "subsys/logging/Kconfig.template.log_config"

endif # NRF_CLOUD_COAP
Loading

0 comments on commit 8c62307

Please sign in to comment.