diff options
26 files changed, 4946 insertions, 2995 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 68d3c8be..3f74c006 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,7 @@ endif() if(NXD_ENABLE_AZURE_IOT) message(STATUS "NXD_ENABLE_AZURE_IOT - defined") - target_link_libraries(${PROJECT_NAME} PUBLIC az_iot_hub az_iot_provisioning) + target_link_libraries(${PROJECT_NAME} PUBLIC az_iot_pnp az_iot_hub az_iot_provisioning) if(NOT NX_AZURE_DISABLE_IOT_SECURITY_MODULE) target_link_libraries(${PROJECT_NAME} PUBLIC iot_security_module) endif() diff --git a/addons/CMakeLists.txt b/addons/CMakeLists.txt index cfe60389..941cb38a 100644 --- a/addons/CMakeLists.txt +++ b/addons/CMakeLists.txt @@ -52,6 +52,8 @@ if(NXD_ENABLE_AZURE_IOT) ${CMAKE_CURRENT_LIST_DIR}/azure_iot/nx_azure_iot_json_reader.c ${CMAKE_CURRENT_LIST_DIR}/azure_iot/nx_azure_iot_json_writer.c ${CMAKE_CURRENT_LIST_DIR}/azure_iot/nx_azure_iot_provisioning_client.c + ${CMAKE_CURRENT_LIST_DIR}/azure_iot/nx_azure_iot_pnp_client.c + ${CMAKE_CURRENT_LIST_DIR}/azure_iot/nx_azure_iot_hub_transport.c ) set(ENV{AZ_SDK_C_NO_SAMPLES} TRUE) set(NX_AZURE_DISABLE_IOT_SECURITY_MODULE OFF CACHE BOOL "Disable Azure IoT Security Module (default is OFF)") diff --git a/addons/azure_iot/azure-sdk-for-c b/addons/azure_iot/azure-sdk-for-c -Subproject 5e9d7b96dbd98ce7125e4beed385959a32b4c6c +Subproject c305408ce67e98e1417bb7518ae2743b8c397ec diff --git a/addons/azure_iot/azure_iot_security_module/nx_azure_iot_security_module.c b/addons/azure_iot/azure_iot_security_module/nx_azure_iot_security_module.c index 9e44ac83..c71225d7 100644 --- a/addons/azure_iot/azure_iot_security_module/nx_azure_iot_security_module.c +++ b/addons/azure_iot/azure_iot_security_module/nx_azure_iot_security_module.c @@ -346,7 +346,7 @@ NX_AZURE_IOT_RESOURCE *resource_ptr; NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)resource_ptr->resource_data_ptr; /* Filter only connected IoT Hubs. */ - if (hub_client_ptr->nx_azure_iot_hub_client_state == NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED) + if (hub_client_ptr->nx_azure_iot_hub_client_transport.nx_azure_iot_hub_transport_state == NX_AZURE_IOT_HUB_TRANSPORT_STATUS_CONNECTED) { exists_connected_iot_hub = true; @@ -583,7 +583,7 @@ NX_AZURE_IOT_RESOURCE *resource_ptr; NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)resource_ptr->resource_data_ptr; /* Check IoT Hub client connectivity. */ - if (hub_client_ptr->nx_azure_iot_hub_client_state == NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED) + if (hub_client_ptr->nx_azure_iot_hub_client_transport.nx_azure_iot_hub_transport_state == NX_AZURE_IOT_HUB_TRANSPORT_STATUS_CONNECTED) { return true; } diff --git a/addons/azure_iot/nx_azure_iot.c b/addons/azure_iot/nx_azure_iot.c index 698ed5b0..677d4ed7 100644 --- a/addons/azure_iot/nx_azure_iot.c +++ b/addons/azure_iot/nx_azure_iot.c @@ -9,7 +9,7 @@ /* */ /**************************************************************************/ -/* Version: 6.1 */ +/* Version: 6.1 PnP Preview 1 */ #include "nx_azure_iot.h" #ifndef NX_AZURE_DISABLE_IOT_SECURITY_MODULE @@ -170,14 +170,6 @@ static VOID nx_azure_iot_log_listener(az_log_classification classification, az_s VOID nx_azure_iot_log_init(VOID(*log_callback)(az_log_classification classification, UCHAR *msg, UINT msg_len)) { -static az_log_classification const classifications[] = {AZ_LOG_IOT_AZURERTOS, - AZ_LOG_MQTT_RECEIVED_TOPIC, - AZ_LOG_MQTT_RECEIVED_PAYLOAD, - AZ_LOG_IOT_RETRY, - AZ_LOG_IOT_SAS_TOKEN, - _az_LOG_END_OF_LIST}; - - _az_log_set_classifications(classifications); _nx_azure_iot_log_callback = log_callback; az_log_set_message_callback(nx_azure_iot_log_listener); } @@ -1026,3 +1018,58 @@ UINT binary_key_buf_size; return(NX_AZURE_IOT_SUCCESS); } + +UINT nx_azure_iot_topic_property_append(NX_PACKET *packet_ptr, + const UCHAR *property_name, USHORT property_name_length, + const UCHAR *property_value, USHORT property_value_length, + UINT wait_option) +{ +UINT status; + + if ((packet_ptr == NX_NULL) || + (property_name == NX_NULL) || + (property_value == NX_NULL)) + { + LogError(LogLiteralArgs("Property append failed: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + if (*(packet_ptr -> nx_packet_append_ptr - 1) != '/') + { + status = nx_packet_data_append(packet_ptr, "&", 1, + packet_ptr -> nx_packet_pool_owner, + wait_option); + if (status) + { + LogError(LogLiteralArgs("Property append of & failed")); + return(status); + } + } + + status = nx_packet_data_append(packet_ptr, (VOID *)property_name, (UINT)property_name_length, + packet_ptr -> nx_packet_pool_owner, wait_option); + if (status) + { + LogError(LogLiteralArgs("Property name append failed")); + return(status); + } + + status = nx_packet_data_append(packet_ptr, "=", 1, + packet_ptr -> nx_packet_pool_owner, + wait_option); + if (status) + { + LogError(LogLiteralArgs("Property append of = failed")); + return(status); + } + + status = nx_packet_data_append(packet_ptr, (VOID *)property_value, (UINT)property_value_length, + packet_ptr -> nx_packet_pool_owner, wait_option); + if (status) + { + LogError(LogLiteralArgs("Property value append failed")); + return(status); + } + + return(NX_AZURE_IOT_SUCCESS); +} diff --git a/addons/azure_iot/nx_azure_iot.h b/addons/azure_iot/nx_azure_iot.h index d4229d2f..fa0a00a6 100644 --- a/addons/azure_iot/nx_azure_iot.h +++ b/addons/azure_iot/nx_azure_iot.h @@ -9,7 +9,7 @@ /* */ /**************************************************************************/ -/* Version: 6.1 */ +/* Version: 6.1 PnP Preview 1 */ /** * @file nx_azure_iot.h @@ -128,9 +128,12 @@ UINT nx_azure_iot_log(UCHAR *type_ptr, UINT type_len, UCHAR *msg_ptr, UINT msg_l #define NX_AZURE_IOT_NO_SUBSCRIBE_ACK 0x20014 #define NX_AZURE_IOT_THROTTLED 0x20015 +#define NX_AZURE_IOT_EMPTY_JSON 0x20016 + /* Resource type managed by AZ_IOT. */ #define NX_AZURE_IOT_RESOURCE_IOT_HUB 0x1 #define NX_AZURE_IOT_RESOURCE_IOT_PROVISIONING 0x2 +#define NX_AZURE_IOT_RESOURCE_IOT_PNP 0x3 /* Define the packet buffer for THREADX TLS. */ #ifndef NX_AZURE_IOT_TLS_PACKET_BUFFER_SIZE @@ -198,6 +201,15 @@ typedef struct NX_AZURE_IOT_STRUCT UINT (*nx_azure_iot_unix_time_get)(ULONG *unix_time); } NX_AZURE_IOT; +typedef struct NX_AZURE_IOT_THREAD_STRUCT +{ + TX_THREAD *thread_ptr; + struct NX_AZURE_IOT_THREAD_STRUCT *thread_next; + UINT thread_message_type; + UINT thread_expected_id; /* Used by device twin. */ + NX_PACKET *thread_received_message; +} NX_AZURE_IOT_THREAD; + /** * @brief Create the Azure IoT subsystem * @@ -297,7 +309,10 @@ UINT nx_azure_iot_base64_hmac_sha256_calculate(NX_AZURE_IOT_RESOURCE *resource_p const UCHAR *message_ptr, UINT message_size, UCHAR *buffer_ptr, UINT buffer_len, UCHAR **output_ptr, UINT *output_len_ptr); - +UINT nx_azure_iot_topic_property_append(NX_PACKET *packet_ptr, + const UCHAR *property_name, USHORT property_name_length, + const UCHAR *property_value, USHORT property_value_length, + UINT wait_option); #ifdef __cplusplus } diff --git a/addons/azure_iot/nx_azure_iot_hub_client.c b/addons/azure_iot/nx_azure_iot_hub_client.c index 3cdff666..752c2626 100644 --- a/addons/azure_iot/nx_azure_iot_hub_client.c +++ b/addons/azure_iot/nx_azure_iot_hub_client.c @@ -9,7 +9,7 @@ /* */ /**************************************************************************/ -/* Version: 6.1 */ +/* Version: 6.1 PnP Preview 1 */ #include "nx_azure_iot_hub_client.h" @@ -32,36 +32,23 @@ NX_AZURE_IOT_HUB_CLIENT_TO_STR(THREADX_MINOR_VERSION) "%29" #endif /* NX_AZURE_IOT_HUB_CLIENT_USER_AGENT */ -static VOID nx_azure_iot_hub_client_received_message_cleanup(NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE *message); -static UINT nx_azure_iot_hub_client_cloud_message_sub_unsub(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - UINT is_subscribe); -static UINT nx_azure_iot_hub_client_process_publish_packet(UCHAR *start_ptr, - ULONG *topic_offset_ptr, - USHORT *topic_length_ptr); -static VOID nx_azure_iot_hub_client_mqtt_receive_callback(NXD_MQTT_CLIENT* client_ptr, - UINT number_of_messages); -static UINT nx_azure_iot_hub_client_c2d_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - NX_PACKET *packet_ptr, - ULONG topic_offset, - USHORT topic_length); -static UINT nx_azure_iot_hub_client_device_twin_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - NX_PACKET *packet_ptr, - ULONG topic_offset, - USHORT topic_length); +/* Queue index used in transport to receive the messages */ +#define NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_QUEUE_INDEX 0 +#define NX_AZURE_IOT_HUB_DIRECT_METHOD_QUEUE_INDEX 1 +#define NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES_QUEUE_INDEX 2 +#define NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES_QUEUE_INDEX 3 +#define NX_AZURE_IOT_HUB_DEVICE_TWIN_REPORTED_PROPERTIES_RESPONSE_QUEUE_INDEX 4 + extern UINT _nxd_mqtt_process_publish_packet(NX_PACKET *packet_ptr, ULONG *topic_offset_ptr, USHORT *topic_length_ptr, ULONG *message_offset_ptr, ULONG *message_length_ptr); -static VOID nx_azure_iot_hub_client_mqtt_connect_notify(struct NXD_MQTT_CLIENT_STRUCT *client_ptr, - UINT status, VOID *context); -static VOID nx_azure_iot_hub_client_mqtt_disconnect_notify(NXD_MQTT_CLIENT *client_ptr); -static VOID nx_azure_iot_hub_client_thread_dequeue(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - NX_AZURE_IOT_THREAD *thread_list_ptr); -static UINT nx_azure_iot_hub_client_sas_token_get(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - ULONG expiry_time_secs, const UCHAR *key, UINT key_len, - UCHAR *sas_buffer, UINT sas_buffer_len, UINT *sas_length); -static UINT nx_azure_iot_hub_client_messages_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr); -static VOID nx_azure_iot_hub_client_device_twin_ack_notify(NXD_MQTT_CLIENT *client_ptr, UINT type, - USHORT packet_id, NX_PACKET *transmit_packet_ptr, VOID *context); + +static UINT nx_azure_iot_hub_client_c2d_process(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + NX_PACKET *packet_ptr, ULONG topic_offset, + USHORT topic_length); +static UINT nx_azure_iot_hub_client_device_twin_process(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + NX_PACKET *packet_ptr, ULONG topic_offset, + USHORT topic_length); static UINT nx_azure_iot_hub_client_device_twin_parse(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, NX_PACKET *packet_ptr, ULONG topic_offset, USHORT topic_length, UINT *request_id_ptr, @@ -106,7 +93,7 @@ UINT status = NX_AZURE_IOT_SUCCESS; if (hub_client_ptr -> nx_azure_iot_hub_client_throttle_count != 0) { - if ((status = nx_azure_iot_unix_time_get(hub_client_ptr -> nx_azure_iot_ptr, ¤t_time))) + if ((status = nx_azure_iot_unix_time_get(hub_client_ptr -> nx_azure_iot_hub_client_transport.nx_azure_iot_ptr, ¤t_time))) { LogError(LogLiteralArgs("IoTHub client fail to get unix time: %d"), status); return(status); @@ -121,624 +108,303 @@ UINT status = NX_AZURE_IOT_SUCCESS; return(status); } -UINT nx_azure_iot_hub_client_initialize(NX_AZURE_IOT_HUB_CLIENT* hub_client_ptr, - NX_AZURE_IOT *nx_azure_iot_ptr, - const UCHAR *host_name, UINT host_name_length, - const UCHAR *device_id, UINT device_id_length, - const UCHAR *module_id, UINT module_id_length, - const NX_CRYPTO_METHOD **crypto_array, UINT crypto_array_size, - const NX_CRYPTO_CIPHERSUITE **cipher_map, UINT cipher_map_size, - UCHAR * metadata_memory, UINT memory_size, - NX_SECURE_X509_CERT *trusted_certificate) +static UINT nx_azure_iot_hub_client_mesg_type_to_queue_index(UINT message_type) { +UINT queue_index; -UINT status; -NX_AZURE_IOT_RESOURCE *resource_ptr; -az_span hostname_span = az_span_create((UCHAR *)host_name, (INT)host_name_length); -az_span device_id_span = az_span_create((UCHAR *)device_id, (INT)device_id_length); -az_iot_hub_client_options options = az_iot_hub_client_options_default(); -az_result core_result; - - if ((nx_azure_iot_ptr == NX_NULL) || (hub_client_ptr == NX_NULL) || (host_name == NX_NULL) || - (device_id == NX_NULL) || (host_name_length == 0) || (device_id_length == 0)) + switch (message_type) { - LogError(LogLiteralArgs("IoTHub client initialization fail: INVALID POINTER")); - return(NX_AZURE_IOT_INVALID_PARAMETER); - } + case NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_MESSAGE : + { + queue_index = NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_QUEUE_INDEX; + } + break; - memset(hub_client_ptr, 0, sizeof(NX_AZURE_IOT_HUB_CLIENT)); + case NX_AZURE_IOT_HUB_DIRECT_METHOD : + { + queue_index = NX_AZURE_IOT_HUB_DIRECT_METHOD_QUEUE_INDEX; + } + break; - hub_client_ptr -> nx_azure_iot_ptr = nx_azure_iot_ptr; - hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_crypto_array = crypto_array; - hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_crypto_array_size = crypto_array_size; - hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_cipher_map = cipher_map; - hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_cipher_map_size = cipher_map_size; - hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_metadata_ptr = metadata_memory; - hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_metadata_size = memory_size; - hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_trusted_certificate = trusted_certificate; - hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_hostname = host_name; - hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_hostname_length = host_name_length; - options.module_id = az_span_create((UCHAR *)module_id, (INT)module_id_length); - options.user_agent = AZ_SPAN_FROM_STR(NX_AZURE_IOT_HUB_CLIENT_USER_AGENT); + case NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES : + { + queue_index = NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES_QUEUE_INDEX; + } + break; - core_result = az_iot_hub_client_init(&hub_client_ptr -> iot_hub_client_core, - hostname_span, device_id_span, &options); - if (az_result_failed(core_result)) - { - LogError(LogLiteralArgs("IoTHub client failed initialization with error status: %d"), core_result); - return(NX_AZURE_IOT_SDK_CORE_ERROR); - } + case NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES : + { + queue_index = NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES_QUEUE_INDEX; + } + break; - /* Set resource pointer. */ - resource_ptr = &(hub_client_ptr -> nx_azure_iot_hub_client_resource); + case NX_AZURE_IOT_HUB_DEVICE_TWIN_REPORTED_PROPERTIES_RESPONSE : + { + queue_index = NX_AZURE_IOT_HUB_DEVICE_TWIN_REPORTED_PROPERTIES_RESPONSE_QUEUE_INDEX; + } + break; - /* Create MQTT client. */ - status = _nxd_mqtt_client_cloud_create(&(resource_ptr -> resource_mqtt), - (CHAR *)nx_azure_iot_ptr -> nx_azure_iot_name, - "", 0, - nx_azure_iot_ptr -> nx_azure_iot_ip_ptr, - nx_azure_iot_ptr -> nx_azure_iot_pool_ptr, - &nx_azure_iot_ptr -> nx_azure_iot_cloud); - if (status) - { - LogError(LogLiteralArgs("IoTHub client initialization fail: MQTT CLIENT CREATE FAIL status: %d"), status); - return(status); + default : + { + /* no queue */ + queue_index = NX_AZURE_IOT_HUB_TRANSPORT_MAX_NUM_RECEIVE_QUEUE; + } + break; } - /* Set mqtt receive notify. */ - status = nxd_mqtt_client_receive_notify_set(&(resource_ptr -> resource_mqtt), - nx_azure_iot_hub_client_mqtt_receive_callback); - if (status) - { - LogError(LogLiteralArgs("IoTHub client set message callback status: %d"), status); - nxd_mqtt_client_delete(&(resource_ptr -> resource_mqtt)); - return(status); - } + return(queue_index); +} - /* Obtain the mutex. */ - tx_mutex_get(nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); +static az_result nx_azure_iot_hub_client_client_id_get(struct NX_AZURE_IOT_HUB_TRANSPORT_STRUCT *hub_trans_ptr, + UCHAR *buffer, UINT buffer_len, UINT *bytes_copied) +{ +NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)hub_trans_ptr -> nx_azure_iot_hub_transport_client_context; - /* Link the resource. */ - resource_ptr -> resource_data_ptr = (VOID *)hub_client_ptr; - resource_ptr -> resource_type = NX_AZURE_IOT_RESOURCE_IOT_HUB; - nx_azure_iot_resource_add(nx_azure_iot_ptr, resource_ptr); + return(az_iot_hub_client_get_client_id(&(hub_client_ptr -> iot_hub_client_core), + (CHAR *)buffer, buffer_len, bytes_copied)); +} - /* Release the mutex. */ - tx_mutex_put(nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); +static az_result nx_azure_iot_hub_client_username_get(struct NX_AZURE_IOT_HUB_TRANSPORT_STRUCT *hub_trans_ptr, + UCHAR *buffer, UINT buffer_len, UINT *bytes_copied) +{ +NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)hub_trans_ptr -> nx_azure_iot_hub_transport_client_context; - return(NX_AZURE_IOT_SUCCESS); + return(az_iot_hub_client_get_user_name(&hub_client_ptr -> iot_hub_client_core, + (CHAR *)buffer, buffer_len, bytes_copied)); } -UINT nx_azure_iot_hub_client_connection_status_callback_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - VOID (*connection_status_cb)( - struct NX_AZURE_IOT_HUB_CLIENT_STRUCT *client_ptr, - UINT status)) +static az_result nx_azure_iot_hub_client_signature_get(struct NX_AZURE_IOT_HUB_TRANSPORT_STRUCT *hub_trans_ptr, + ULONG expiry_time_secs, az_span buffer, az_span *out_buffer) { +NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)hub_trans_ptr -> nx_azure_iot_hub_transport_client_context; - /* Check for invalid input pointers. */ - if ((hub_client_ptr == NX_NULL) || (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL)) - { - LogError(LogLiteralArgs("IoTHub client connect callback fail: INVALID POINTER")); - return(NX_AZURE_IOT_INVALID_PARAMETER); - } + return(az_iot_hub_client_sas_get_signature(&(hub_client_ptr -> iot_hub_client_core), + expiry_time_secs, buffer, out_buffer)); +} - /* Set callback function for disconnection. */ - nxd_mqtt_client_disconnect_notify_set(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), - nx_azure_iot_hub_client_mqtt_disconnect_notify); +static az_result nx_azure_iot_hub_client_password_get(struct NX_AZURE_IOT_HUB_TRANSPORT_STRUCT *hub_trans_ptr, + ULONG expiry_time_secs, az_span hash_buffer, az_span key_name, + UCHAR *out_buffer, UINT out_buffer_len, UINT *bytes_copied) +{ +NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)hub_trans_ptr -> nx_azure_iot_hub_transport_client_context; - /* Obtain the mutex. */ - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + return(az_iot_hub_client_sas_get_password(&(hub_client_ptr -> iot_hub_client_core), + expiry_time_secs, hash_buffer, key_name, + (CHAR *)out_buffer, out_buffer_len, bytes_copied)); +} - /* Set connection status callback. */ - hub_client_ptr -> nx_azure_iot_hub_client_connection_status_callback = connection_status_cb; +static VOID nx_azure_iot_hub_client_receive_callback(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN arg1, + VOID *arg2) +{ +NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)hub_trans_ptr -> nx_azure_iot_hub_transport_client_context; - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + ((VOID (*)(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, VOID *args))arg1)(hub_client_ptr, arg2); +} - /* Return success. */ - return(NX_AZURE_IOT_SUCCESS); +static VOID nx_azure_iot_hub_client_connection_status_callback(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + UINT status, NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN arg) +{ +NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)hub_trans_ptr -> nx_azure_iot_hub_transport_client_context; + ((VOID (*)(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT status))arg)(hub_client_ptr, status); } -UINT nx_azure_iot_hub_client_connect(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - UINT clean_session, UINT wait_option) +static VOID nx_azure_iot_hub_client_reported_property_receive_callback(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN arg1, + VOID *arg2) { -UINT status; -NXD_ADDRESS server_address; -NX_AZURE_IOT_RESOURCE *resource_ptr; -NXD_MQTT_CLIENT *mqtt_client_ptr; -UCHAR *buffer_ptr; -UINT buffer_size; -VOID *buffer_context; -UINT buffer_length; -ULONG expiry_time_secs; -az_result core_result; +NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)hub_trans_ptr -> nx_azure_iot_hub_transport_client_context; +UINT status; +NX_PACKET *packet_ptr; +ULONG topic_offset; +USHORT topic_length; +UINT request_id; +UINT response_status; +ULONG version = 0; - /* Check for invalid input pointers. */ - if ((hub_client_ptr == NX_NULL) || (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL)) + if ((status = nx_azure_iot_hub_transport_message_receive(hub_trans_ptr, + NX_AZURE_IOT_HUB_DEVICE_TWIN_REPORTED_PROPERTIES_RESPONSE_QUEUE_INDEX, 0, + &packet_ptr, NX_NO_WAIT))) { - LogError(LogLiteralArgs("IoTHub client connect fail: INVALID POINTER")); - return(NX_AZURE_IOT_INVALID_PARAMETER); + LogError(LogLiteralArgs("IoTHub failed to find reported property: %d"), status); + return; } - /* Check for status. */ - if (hub_client_ptr -> nx_azure_iot_hub_client_state == NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED) + if (nx_azure_iot_hub_transport_process_publish_packet(packet_ptr -> nx_packet_prepend_ptr, &topic_offset, + &topic_length)) { - LogError(LogLiteralArgs("IoTHub client already connected")); - return(NX_AZURE_IOT_ALREADY_CONNECTED); - } - else if (hub_client_ptr -> nx_azure_iot_hub_client_state == NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTING) - { - LogError(LogLiteralArgs("IoTHub client is connecting")); - return(NX_AZURE_IOT_CONNECTING); - } - /* Resolve the host name. */ - /* Note: always using default dns timeout. */ - status = nxd_dns_host_by_name_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_dns_ptr, - (UCHAR *)hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_hostname, - &server_address, NX_AZURE_IOT_HUB_CLIENT_DNS_TIMEOUT, NX_IP_VERSION_V4); - if (status) - { - LogError(LogLiteralArgs("IoTHub client connect fail: DNS RESOLVE FAIL status: %d"), status); - return(status); + /* Message not supported. It will be released. */ + nx_packet_release(packet_ptr); + return; } - /* Allocate buffer for client id, username and sas token. */ - status = nx_azure_iot_buffer_allocate(hub_client_ptr -> nx_azure_iot_ptr, - &buffer_ptr, &buffer_size, &buffer_context); - if (status) + if ((status = nx_azure_iot_hub_client_device_twin_parse(hub_client_ptr, packet_ptr, + topic_offset, topic_length, + &request_id, &version, + NX_NULL, &response_status))) { - LogError(LogLiteralArgs("IoTHub client failed initialization: BUFFER ALLOCATE FAIL")); - return(status); + nx_packet_release(packet_ptr); + return; } - /* Obtain the mutex. */ - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - - /* Set resource pointer and buffer context. */ - resource_ptr = &(hub_client_ptr -> nx_azure_iot_hub_client_resource); - - /* Build client id. */ - buffer_length = buffer_size; - core_result = az_iot_hub_client_get_client_id(&(hub_client_ptr -> iot_hub_client_core), - (CHAR *)buffer_ptr, buffer_length, &buffer_length); - if (az_result_failed(core_result)) - { + ((VOID (*)(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + UINT request_id, UINT response_status, + ULONG version, VOID *arg))arg1)(hub_client_ptr, + request_id, + response_status, + version, + arg2); + nx_packet_release(packet_ptr); +} - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - nx_azure_iot_buffer_free(buffer_context); - LogError(LogLiteralArgs("IoTHub client failed to get clientId with error status: "), core_result); - return(NX_AZURE_IOT_SDK_CORE_ERROR); - } - resource_ptr -> resource_mqtt_client_id = buffer_ptr; - resource_ptr -> resource_mqtt_client_id_length = buffer_length; +UINT nx_azure_iot_hub_client_initialize(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT *nx_azure_iot_ptr, + const UCHAR *host_name, UINT host_name_length, + const UCHAR *device_id, UINT device_id_length, + const UCHAR *module_id, UINT module_id_length, + const NX_CRYPTO_METHOD **crypto_array, UINT crypto_array_size, + const NX_CRYPTO_CIPHERSUITE **cipher_map, UINT cipher_map_size, + UCHAR * metadata_memory, UINT memory_size, + NX_SECURE_X509_CERT *trusted_certificate) +{ - /* Update buffer for user name. */ - buffer_ptr += resource_ptr -> resource_mqtt_client_id_length; - buffer_size -= resource_ptr -> resource_mqtt_client_id_length; +UINT status; +az_span hostname_span = az_span_create((UCHAR *)host_name, (INT)host_name_length); +az_span device_id_span = az_span_create((UCHAR *)device_id, (INT)device_id_length); +az_iot_hub_client_options options = az_iot_hub_client_options_default(); +az_result core_result; - /* Build user name. */ - buffer_length = buffer_size; - core_result = az_iot_hub_client_get_user_name(&hub_client_ptr -> iot_hub_client_core, - (CHAR *)buffer_ptr, buffer_length, &buffer_length); - if (az_result_failed(core_result)) + if ((nx_azure_iot_ptr == NX_NULL) || (hub_client_ptr == NX_NULL) || (host_name == NX_NULL) || + (device_id == NX_NULL) || (host_name_length == 0) || (device_id_length == 0)) { - - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - nx_azure_iot_buffer_free(buffer_context); - LogError(LogLiteralArgs("IoTHub client connect fail, with error status: %d"), core_result); - return(NX_AZURE_IOT_SDK_CORE_ERROR); + LogError(LogLiteralArgs("IoTHub client initialization fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); } - resource_ptr -> resource_mqtt_user_name = buffer_ptr; - resource_ptr -> resource_mqtt_user_name_length = buffer_length; - /* Build sas token. */ - resource_ptr -> resource_mqtt_sas_token = buffer_ptr + buffer_length; - resource_ptr -> resource_mqtt_sas_token_length = buffer_size - buffer_length; - - /* Check if token refersh is setup. */ - if (hub_client_ptr -> nx_azure_iot_hub_client_token_refresh) - { - status = nx_azure_iot_unix_time_get(hub_client_ptr -> nx_azure_iot_ptr, &expiry_time_secs); - if (status) - { - - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - nx_azure_iot_buffer_free(buffer_context); - LogError(LogLiteralArgs("IoTHub client connect fail: unixtime get failed status: %d"), status); - return(status); - } + memset(hub_client_ptr, 0, sizeof(NX_AZURE_IOT_HUB_CLIENT)); - expiry_time_secs += NX_AZURE_IOT_HUB_CLIENT_TOKEN_EXPIRY; - status = hub_client_ptr -> nx_azure_iot_hub_client_token_refresh(hub_client_ptr, - expiry_time_secs, - hub_client_ptr -> nx_azure_iot_hub_client_symmetric_key, - hub_client_ptr -> nx_azure_iot_hub_client_symmetric_key_length, - resource_ptr -> resource_mqtt_sas_token, - resource_ptr -> resource_mqtt_sas_token_length, - &(resource_ptr -> resource_mqtt_sas_token_length)); - if (status) - { + options.module_id = az_span_create((UCHAR *)module_id, (INT)module_id_length); + options.user_agent = AZ_SPAN_FROM_STR(NX_AZURE_IOT_HUB_CLIENT_USER_AGENT); - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - nx_azure_iot_buffer_free(buffer_context); - LogError(LogLiteralArgs("IoTHub client connect fail: Token generation failed status: %d"), status); - return(status); - } - } - else + core_result = az_iot_hub_client_init(&hub_client_ptr -> iot_hub_client_core, + hostname_span, device_id_span, &options); + if (az_result_failed(core_result)) { - resource_ptr -> resource_mqtt_sas_token_length = 0; + LogError(LogLiteralArgs("IoTHub client failed initialization with error status: %d"), core_result); + return(NX_AZURE_IOT_SDK_CORE_ERROR); } - /* Set azure IoT and MQTT client. */ - mqtt_client_ptr = &(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt); - - /* Update client id. */ - mqtt_client_ptr -> nxd_mqtt_client_id = (CHAR *)resource_ptr -> resource_mqtt_client_id; - mqtt_client_ptr -> nxd_mqtt_client_id_length = resource_ptr -> resource_mqtt_client_id_length; - - /* Set login info. */ - status = nxd_mqtt_client_login_set(&(resource_ptr -> resource_mqtt), - (CHAR *)resource_ptr -> resource_mqtt_user_name, - resource_ptr -> resource_mqtt_user_name_length, - (CHAR *)resource_ptr -> resource_mqtt_sas_token, - resource_ptr -> resource_mqtt_sas_token_length); + status = nx_azure_iot_hub_transport_initialize(&(hub_client_ptr -> nx_azure_iot_hub_client_transport), + nx_azure_iot_ptr, host_name, host_name_length, + nx_azure_iot_hub_client_client_id_get, + nx_azure_iot_hub_client_username_get, + crypto_array, crypto_array_size, + cipher_map, cipher_map_size, + metadata_memory, memory_size, + trusted_certificate, (VOID *)hub_client_ptr); if (status) { - - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - nx_azure_iot_buffer_free(buffer_context); - LogError(LogLiteralArgs("IoTHub client connect fail: MQTT CLIENT LOGIN SET FAIL status: %d"), status); + LogError(LogLiteralArgs("IoTHub client failed to initialization transport with error status: %d"), core_result); return(status); } - /* Set connect notify for non-blocking mode. */ - if (wait_option == 0) - { - mqtt_client_ptr -> nxd_mqtt_connect_notify = nx_azure_iot_hub_client_mqtt_connect_notify; - mqtt_client_ptr -> nxd_mqtt_connect_context = hub_client_ptr; - } - - /* Save the resource buffer. */ - resource_ptr -> resource_mqtt_buffer_context = buffer_context; - resource_ptr -> resource_mqtt_buffer_size = buffer_size; - - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - - /* Start MQTT connection. */ - status = nxd_mqtt_client_secure_connect(mqtt_client_ptr, &server_address, NXD_MQTT_TLS_PORT, - nx_azure_iot_mqtt_tls_setup, NX_AZURE_IOT_MQTT_KEEP_ALIVE, - clean_session, wait_option); - - /* Obtain the mutex. */ - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - - /* Check status for non-blocking mode. */ - if ((wait_option == 0) && (status == NX_IN_PROGRESS)) - { - hub_client_ptr -> nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTING; - - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - - /* Return in-progress completion status. */ - return(NX_AZURE_IOT_CONNECTING); - } - - /* Release the mqtt connection resource. */ - if (resource_ptr -> resource_mqtt_buffer_context) - { - nx_azure_iot_buffer_free(resource_ptr -> resource_mqtt_buffer_context); - resource_ptr -> resource_mqtt_buffer_context = NX_NULL; - } - - /* Check status. */ - if (status != NX_AZURE_IOT_SUCCESS) - { - hub_client_ptr -> nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_NOT_CONNECTED; - LogError(LogLiteralArgs("IoTHub client connect fail: MQTT CONNECT FAIL status: %d"), status); - } - else - { - - /* Connected to IoT Hub. */ - hub_client_ptr -> nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED; - } - - if (status == NX_AZURE_IOT_SUCCESS) - { - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - - status = nx_azure_iot_hub_client_messages_enable(hub_client_ptr); - - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - - if (status) - { - hub_client_ptr -> nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_NOT_CONNECTED; - LogError(LogLiteralArgs("IoTHub client connect fail: MQTT SUBSCRIBE FAIL status: %d"), status); - } - } - - /* Call connection notify if it is set. */ - if (hub_client_ptr -> nx_azure_iot_hub_client_connection_status_callback) - { - hub_client_ptr -> nx_azure_iot_hub_client_connection_status_callback(hub_client_ptr, status); - } - - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - - return(status); + return(NX_AZURE_IOT_SUCCESS); } -static VOID nx_azure_iot_hub_client_mqtt_connect_notify(struct NXD_MQTT_CLIENT_STRUCT *client_ptr, - UINT status, VOID *context) +UINT nx_azure_iot_hub_client_connection_status_callback_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + VOID (*connection_status_cb)( + struct NX_AZURE_IOT_HUB_CLIENT_STRUCT *client_ptr, + UINT status)) { -NX_AZURE_IOT_HUB_CLIENT *iot_hub_client = (NX_AZURE_IOT_HUB_CLIENT*)context; - - - NX_PARAMETER_NOT_USED(client_ptr); - - /* Obtain the mutex. */ - tx_mutex_get(iot_hub_client -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - - /* Release the mqtt connection resource. */ - if (iot_hub_client -> nx_azure_iot_hub_client_resource.resource_mqtt_buffer_context) - { - nx_azure_iot_buffer_free(iot_hub_client -> nx_azure_iot_hub_client_resource.resource_mqtt_buffer_context); - iot_hub_client -> nx_azure_iot_hub_client_resource.resource_mqtt_buffer_context = NX_NULL; - } - - /* Update hub client status. */ - if (status == NXD_MQTT_SUCCESS) - { - iot_hub_client -> nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED; - } - else - { - iot_hub_client -> nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_NOT_CONNECTED; - } - - if (status == NXD_MQTT_SUCCESS) - { - tx_mutex_put(iot_hub_client -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - - status = nx_azure_iot_hub_client_messages_enable(iot_hub_client); - - tx_mutex_get(iot_hub_client -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - - if (status) - { - iot_hub_client -> nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_NOT_CONNECTED; - LogError(LogLiteralArgs("IoTHub client connect fail: MQTT SUBSCRIBE FAIL status: %d"), status); - } - } - - /* Call connection notify if it is set. */ - if (iot_hub_client -> nx_azure_iot_hub_client_connection_status_callback) + /* Check for invalid input pointers. */ + if (hub_client_ptr == NX_NULL) { - iot_hub_client -> nx_azure_iot_hub_client_connection_status_callback(iot_hub_client, status); + LogError(LogLiteralArgs("IoTHub client connect callback fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); } - /* Release the mutex. */ - tx_mutex_put(iot_hub_client -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + return(nx_azure_iot_hub_transport_connection_callback_set(&(hub_client_ptr -> nx_azure_iot_hub_client_transport), + nx_azure_iot_hub_client_connection_status_callback, + (NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN)connection_status_cb)); } -static VOID nx_azure_iot_hub_client_mqtt_disconnect_notify(NXD_MQTT_CLIENT *client_ptr) +UINT nx_azure_iot_hub_client_connect(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + UINT clean_session, UINT wait_option) { -NX_AZURE_IOT_RESOURCE *resource = nx_azure_iot_resource_search(client_ptr); -NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = NX_NULL; -NX_AZURE_IOT_THREAD *thread_list_ptr; - - /* This function is protected by MQTT mutex. */ - - if (resource && (resource -> resource_type == NX_AZURE_IOT_RESOURCE_IOT_HUB)) - { - hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)resource -> resource_data_ptr; - } - else - { - return; - } - - NX_ASSERT(hub_client_ptr != NX_NULL); - /* Wake up all threads. */ - for (thread_list_ptr = hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended; - thread_list_ptr; - thread_list_ptr = thread_list_ptr -> thread_next) + /* Check for invalid input pointers. */ + if (hub_client_ptr == NX_NULL) { - tx_thread_wait_abort(thread_list_ptr -> thread_ptr); + LogError(LogLiteralArgs("IoTHub client connect fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); } - /* Do not call callback if not connected, as at our layer connected means : mqtt connect + subscribe messages topic. */ - if (hub_client_ptr -> nx_azure_iot_hub_client_state == NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED) - { - hub_client_ptr -> nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_NOT_CONNECTED; - - /* Call connection notify if it is set. */ - if (hub_client_ptr && hub_client_ptr -> nx_azure_iot_hub_client_connection_status_callback) - { - hub_client_ptr -> nx_azure_iot_hub_client_connection_status_callback(hub_client_ptr, - NX_AZURE_IOT_DISCONNECTED); - } - } + return(nx_azure_iot_hub_transport_connect(&(hub_client_ptr -> nx_azure_iot_hub_client_transport), + clean_session, wait_option)); } UINT nx_azure_iot_hub_client_disconnect(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { -UINT status; -NX_AZURE_IOT_THREAD *thread_list_ptr; - /* Check for invalid input pointers. */ - if ((hub_client_ptr == NX_NULL) || (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL)) + if (hub_client_ptr == NX_NULL) { LogError(LogLiteralArgs("IoTHub client disconnect fail: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); } - /* Disconnect. */ - status = nxd_mqtt_client_disconnect(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt)); - if (status) - { - LogError(LogLiteralArgs("IoTHub client disconnect fail status: %d"), status); - return(status); - } - - /* Obtain the mutex. */ - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - - /* Release the mqtt connection resource. */ - if (hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt_buffer_context) - { - nx_azure_iot_buffer_free(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt_buffer_context); - hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt_buffer_context = NX_NULL; - } - - /* Wakeup all suspend threads. */ - for (thread_list_ptr = hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended; - thread_list_ptr; - thread_list_ptr = thread_list_ptr -> thread_next) - { - tx_thread_wait_abort(thread_list_ptr -> thread_ptr); - } - - /* Cleanup received messages. */ - nx_azure_iot_hub_client_received_message_cleanup(&(hub_client_ptr -> nx_azure_iot_hub_client_c2d_message)); - nx_azure_iot_hub_client_received_message_cleanup(&(hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message)); - nx_azure_iot_hub_client_received_message_cleanup(&(hub_client_ptr -> nx_azure_iot_hub_client_device_twin_desired_properties_message)); - nx_azure_iot_hub_client_received_message_cleanup(&(hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message)); - - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - - return(NX_AZURE_IOT_SUCCESS); -} - -static VOID nx_azure_iot_hub_client_received_message_cleanup(NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE *message) -{ -NX_PACKET *current_ptr; -NX_PACKET *next_ptr; - - for (current_ptr = message -> message_head; current_ptr; current_ptr = next_ptr) - { - - /* Get next packet in queue. */ - next_ptr = current_ptr -> nx_packet_queue_next; - - /* Release current packet. */ - current_ptr -> nx_packet_queue_next = NX_NULL; - nx_packet_release(current_ptr); - } - - /* Reset received messages. */ - message -> message_head = NX_NULL; - message -> message_tail = NX_NULL; + return(nx_azure_iot_hub_transport_disconnect(&(hub_client_ptr -> nx_azure_iot_hub_client_transport))); } UINT nx_azure_iot_hub_client_deinitialize(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { -UINT status; /* Check for invalid input pointers. */ - if ((hub_client_ptr == NX_NULL) || (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL)) + if (hub_client_ptr == NX_NULL) { LogError(LogLiteralArgs("IoTHub client deinitialize fail: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); } - nx_azure_iot_hub_client_disconnect(hub_client_ptr); - - status = nxd_mqtt_client_delete(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt)); - if (status) - { - LogError(LogLiteralArgs("IoTHub client delete fail status: %d"), status); - return(status); - } - - /* Obtain the mutex. */ - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - - /* Remove resource from list. */ - status = nx_azure_iot_resource_remove(hub_client_ptr -> nx_azure_iot_ptr, - &(hub_client_ptr -> nx_azure_iot_hub_client_resource)); - if (status) - { - - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - LogError(LogLiteralArgs("IoTHub client handle not found")); - return(status); - } - - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - - return(NX_AZURE_IOT_SUCCESS); + return(nx_azure_iot_hub_transport_deinitialize(&(hub_client_ptr -> nx_azure_iot_hub_client_transport))); } UINT nx_azure_iot_hub_client_device_cert_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, NX_SECURE_X509_CERT *device_certificate) { - - if ((hub_client_ptr == NX_NULL) || - (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL) || - (device_certificate == NX_NULL)) + if (hub_client_ptr == NX_NULL) { LogError(LogLiteralArgs("IoTHub device certificate set fail: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); } - /* Obtain the mutex. */ - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - - hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_device_certificate = device_certificate; - - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - - return(NX_AZURE_IOT_SUCCESS); + return(nx_azure_iot_hub_transport_device_cert_set(&(hub_client_ptr -> nx_azure_iot_hub_client_transport), + device_certificate)); } UINT nx_azure_iot_hub_client_symmetric_key_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, const UCHAR *symmetric_key, UINT symmetric_key_length) { - if ((hub_client_ptr == NX_NULL) || (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL) || - (symmetric_key == NX_NULL) || (symmetric_key_length == 0)) + if (hub_client_ptr == NX_NULL) { LogError(LogLiteralArgs("IoTHub client symmetric key fail: Invalid argument")); return(NX_AZURE_IOT_INVALID_PARAMETER); } - /* Obtain the mutex. */ - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - - hub_client_ptr -> nx_azure_iot_hub_client_symmetric_key = symmetric_key; - hub_client_ptr -> nx_azure_iot_hub_client_symmetric_key_length = symmetric_key_length; - - hub_client_ptr -> nx_azure_iot_hub_client_token_refresh = nx_azure_iot_hub_client_sas_token_get; - - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - - return(NX_AZURE_IOT_SUCCESS); + return(nx_azure_iot_hub_transport_symmetric_key_auth_set(&(hub_client_ptr -> nx_azure_iot_hub_client_transport), + nx_azure_iot_hub_client_signature_get, + nx_azure_iot_hub_client_password_get, + symmetric_key, symmetric_key_length)); } UINT nx_azure_iot_hub_client_model_id_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, const UCHAR *model_id_ptr, UINT model_id_length) { - if ((hub_client_ptr == NX_NULL) || (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL) || + if ((hub_client_ptr == NX_NULL) || + (hub_client_ptr -> nx_azure_iot_hub_client_transport.nx_azure_iot_ptr == NX_NULL) || (model_id_ptr == NX_NULL) || (model_id_length == 0)) { LogError(LogLiteralArgs("IoTHub client model Id fail: Invalid argument")); @@ -746,14 +412,14 @@ UINT nx_azure_iot_hub_client_model_id_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_pt } /* Obtain the mutex. */ - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + tx_mutex_get(hub_client_ptr -> nx_azure_iot_hub_client_transport.nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); /* Had no way to update option, so had to access the internal fields of iot_hub_client_core. */ hub_client_ptr -> iot_hub_client_core._internal.options.model_id = az_span_create((UCHAR *)model_id_ptr, (INT)model_id_length); /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + tx_mutex_put(hub_client_ptr -> nx_azure_iot_hub_client_transport.nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); return(NX_AZURE_IOT_SUCCESS); } @@ -767,16 +433,14 @@ UINT status; az_result core_result; if ((hub_client_ptr == NX_NULL) || - (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL) || (packet_pptr == NX_NULL)) { LogError(LogLiteralArgs("IoTHub telemetry message create fail: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); } - status = nx_azure_iot_publish_packet_get(hub_client_ptr -> nx_azure_iot_ptr, - &(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), - &packet_ptr, wait_option); + status = nx_azure_iot_hub_transport_publish_packet_get(&(hub_client_ptr -> nx_azure_iot_hub_client_transport), + &packet_ptr, wait_option); if (status) { LogError(LogLiteralArgs("Create telemetry data fail")); @@ -784,7 +448,7 @@ az_result core_result; } topic_length = (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr); - core_result = az_iot_hub_client_telemetry_get_publish_topic(&hub_client_ptr -> iot_hub_client_core, + core_result = az_iot_hub_client_telemetry_get_publish_topic(&(hub_client_ptr -> iot_hub_client_core), NULL, (CHAR *)packet_ptr -> nx_packet_prepend_ptr, topic_length, &topic_length); if (az_result_failed(core_result)) @@ -810,114 +474,22 @@ UINT nx_azure_iot_hub_client_telemetry_property_add(NX_PACKET *packet_ptr, const UCHAR *property_value, USHORT property_value_length, UINT wait_option) { -UINT status; - - if ((packet_ptr == NX_NULL) || - (property_name == NX_NULL) || - (property_value == NX_NULL)) - { - LogError(LogLiteralArgs("IoTHub telemetry property add fail: INVALID POINTER")); - return(NX_AZURE_IOT_INVALID_PARAMETER); - } - - if (*(packet_ptr -> nx_packet_append_ptr - 1) != '/') - { - status = nx_packet_data_append(packet_ptr, "&", 1, - packet_ptr -> nx_packet_pool_owner, - wait_option); - if (status) - { - LogError(LogLiteralArgs("Telemetry data append fail")); - return(status); - } - } - - status = nx_packet_data_append(packet_ptr, (VOID *)property_name, (UINT)property_name_length, - packet_ptr -> nx_packet_pool_owner, wait_option); - if (status) - { - LogError(LogLiteralArgs("Telemetry data append fail")); - return(status); - } - - status = nx_packet_data_append(packet_ptr, "=", 1, - packet_ptr -> nx_packet_pool_owner, - wait_option); - if (status) - { - LogError(LogLiteralArgs("Telemetry data append fail")); - return(status); - } - - status = nx_packet_data_append(packet_ptr, (VOID *)property_value, (UINT)property_value_length, - packet_ptr -> nx_packet_pool_owner, wait_option); - if (status) - { - LogError(LogLiteralArgs("Telemetry data append fail")); - return(status); - } - - return(NX_AZURE_IOT_SUCCESS); + return(nx_azure_iot_topic_property_append(packet_ptr, property_name, property_name_length, + property_value, property_value_length, wait_option)); } UINT nx_azure_iot_hub_client_telemetry_send(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, NX_PACKET *packet_ptr, const UCHAR *telemetry_data, UINT data_size, UINT wait_option) { -UINT status; -UINT topic_len; -UCHAR packet_id[2]; - - if ((hub_client_ptr == NX_NULL) || (packet_ptr == NX_NULL)) + if ((hub_client_ptr == NX_NULL)) { LogError(LogLiteralArgs("IoTHub telemetry send fail: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); } - topic_len = packet_ptr -> nx_packet_length; - - status = nx_azure_iot_mqtt_packet_id_get(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), - packet_id, wait_option); - if (status) - { - LogError(LogLiteralArgs("Failed to get packet id")); - return(status); - } - - /* Append packet identifier. */ - status = nx_packet_data_append(packet_ptr, packet_id, sizeof(packet_id), - packet_ptr -> nx_packet_pool_owner, - wait_option); - if (status) - { - LogError(LogLiteralArgs("Telemetry append fail")); - return(status); - } - - if (telemetry_data && (data_size != 0)) - { - - /* Append payload. */ - status = nx_packet_data_append(packet_ptr, (VOID *)telemetry_data, data_size, - packet_ptr -> nx_packet_pool_owner, - wait_option); - if (status) - { - LogError(LogLiteralArgs("Telemetry data append fail")); - return(status); - } - } - - status = nx_azure_iot_publish_mqtt_packet(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), - packet_ptr, topic_len, packet_id, NX_AZURE_IOT_HUB_CLIENT_TELEMETRY_QOS, - wait_option); - if (status) - { - LogError(LogLiteralArgs("IoTHub client send fail: PUBLISH FAIL status: %d"), status); - return(status); - } - - return(NX_AZURE_IOT_SUCCESS); + return(nx_azure_iot_hub_transport_publish(&(hub_client_ptr -> nx_azure_iot_hub_client_transport), packet_ptr, + telemetry_data, data_size, NX_AZURE_IOT_HUB_CLIENT_TELEMETRY_QOS, wait_option)); } UINT nx_azure_iot_hub_client_receive_callback_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, @@ -927,241 +499,69 @@ UINT nx_azure_iot_hub_client_receive_callback_set(NX_AZURE_IOT_HUB_CLIENT *hub_c VOID *args), VOID *callback_args) { - if ((hub_client_ptr == NX_NULL) || (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL)) +UINT message_queue_index; + + if ((hub_client_ptr == NX_NULL)) { LogError(LogLiteralArgs("IoTHub receive callback set fail: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); } - /* Obtain the mutex. */ - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - - if (message_type == NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_MESSAGE) - { - hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_callback = callback_ptr; - hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_callback_args = callback_args; - } - else if (message_type == NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES) - { - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message.message_callback = callback_ptr; - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message.message_callback_args = callback_args; - } - else if (message_type == NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES) - { - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_desired_properties_message.message_callback = callback_ptr; - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_desired_properties_message.message_callback_args = callback_args; - } - else if (message_type == NX_AZURE_IOT_HUB_DIRECT_METHOD) - { - hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message.message_callback = callback_ptr; - hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message.message_callback_args = callback_args; - } - else - { - - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - return(NX_AZURE_IOT_NOT_SUPPORTED); - } - - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + message_queue_index = nx_azure_iot_hub_client_mesg_type_to_queue_index(message_type); - return(NX_AZURE_IOT_SUCCESS); + return(nx_azure_iot_hub_transport_receive_message_callback_set(&(hub_client_ptr ->nx_azure_iot_hub_client_transport), + message_queue_index, + callback_ptr != NX_NULL ? nx_azure_iot_hub_client_receive_callback : NX_NULL, + (NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN)callback_ptr, callback_args)); } UINT nx_azure_iot_hub_client_cloud_message_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { - return(nx_azure_iot_hub_client_cloud_message_sub_unsub(hub_client_ptr, NX_TRUE)); -} - -UINT nx_azure_iot_hub_client_cloud_message_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) -{ - return(nx_azure_iot_hub_client_cloud_message_sub_unsub(hub_client_ptr, NX_FALSE)); -} - -static UINT nx_azure_iot_hub_client_process_publish_packet(UCHAR *start_ptr, - ULONG *topic_offset_ptr, - USHORT *topic_length_ptr) -{ -UCHAR *byte = start_ptr; -UINT byte_count = 0; -UINT multiplier = 1; -UINT remaining_length = 0; -UINT topic_length; - - /* Validate packet start contains fixed header. */ - do - { - if (byte_count >= 4) - { - LogError(LogLiteralArgs("Invalid mqtt packet start position")); - return(NX_AZURE_IOT_INVALID_PACKET); - } - - byte++; - remaining_length += (((*byte) & 0x7F) * multiplier); - multiplier = multiplier << 7; - byte_count++; - } while ((*byte) & 0x80); - - if (remaining_length < 2) - { - return(NX_AZURE_IOT_INVALID_PACKET); - } - - /* Retrieve topic length. */ - byte++; - topic_length = (UINT)(*(byte) << 8) | (*(byte + 1)); - - if (topic_length > remaining_length - 2u) + if (hub_client_ptr == NX_NULL) { - return(NX_AZURE_IOT_INVALID_PACKET); + LogError(LogLiteralArgs("IoTHub cloud message enable fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); } - *topic_offset_ptr = (ULONG)((byte + 2) - start_ptr); - *topic_length_ptr = (USHORT)topic_length; - - /* Return. */ - return(NX_AZURE_IOT_SUCCESS); + return(nx_azure_iot_hub_transport_receive_message_enable(&(hub_client_ptr ->nx_azure_iot_hub_client_transport), + NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_QUEUE_INDEX, + (const UCHAR *)AZ_IOT_HUB_CLIENT_C2D_SUBSCRIBE_TOPIC, + sizeof(AZ_IOT_HUB_CLIENT_C2D_SUBSCRIBE_TOPIC) - 1, + nx_azure_iot_hub_client_c2d_process)); } -static UINT nx_azure_iot_hub_client_message_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT message_type, - NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE *receive_message, - NX_PACKET **packet_pptr, UINT wait_option) +UINT nx_azure_iot_hub_client_cloud_message_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { -NX_PACKET *packet_ptr = NX_NULL; -UINT old_threshold; -NX_AZURE_IOT_THREAD thread_list; - - if ((hub_client_ptr == NX_NULL) || - (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL) || - (packet_pptr == NX_NULL)) + if (hub_client_ptr == NX_NULL) { - LogError(LogLiteralArgs("IoTHub message receive fail: INVALID POINTER")); + LogError(LogLiteralArgs("IoTHub cloud message disable fail: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); } - if (receive_message -> message_process == NX_NULL) - { - LogError(LogLiteralArgs("IoTHub message receive fail: NOT ENABLED")); - return(NX_AZURE_IOT_NOT_ENABLED); - } - - /* Obtain the mutex. */ - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - - if (receive_message -> message_head) - { - packet_ptr = receive_message -> message_head; - if (receive_message -> message_tail == packet_ptr) - { - receive_message -> message_tail = NX_NULL; - } - receive_message -> message_head = packet_ptr -> nx_packet_queue_next; - } - else if (wait_option) - { - thread_list.thread_message_type = message_type; - thread_list.thread_ptr = tx_thread_identify(); - thread_list.thread_received_message = NX_NULL; - thread_list.thread_expected_id = 0; - thread_list.thread_next = hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended; - hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended = &thread_list; - - /* Disable preemption. */ - tx_thread_preemption_change(tx_thread_identify(), 0, &old_threshold); - - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - - tx_thread_sleep(wait_option); - - /* Obtain the mutex. */ - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - - nx_azure_iot_hub_client_thread_dequeue(hub_client_ptr, &thread_list); - - /* Restore preemption. */ - tx_thread_preemption_change(tx_thread_identify(), old_threshold, &old_threshold); - packet_ptr = thread_list.thread_received_message; - } - - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - - if (packet_ptr == NX_NULL) - { - if (hub_client_ptr -> nx_azure_iot_hub_client_state != NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED) - { - LogError(LogLiteralArgs("IoTHub message receive fail: IoTHub client not connected")); - return(NX_AZURE_IOT_DISCONNECTED); - } - - return(NX_AZURE_IOT_NO_PACKET); - } - - *packet_pptr = packet_ptr; - - return(NX_AZURE_IOT_SUCCESS); + return(nx_azure_iot_hub_transport_receive_message_disable(&(hub_client_ptr ->nx_azure_iot_hub_client_transport), + NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_QUEUE_INDEX)); } -static UINT nx_azure_iot_hub_client_adjust_payload(NX_PACKET *packet_ptr) +UINT nx_azure_iot_hub_client_cloud_message_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET **packet_pptr, UINT wait_option) { UINT status; -ULONG topic_offset; -USHORT topic_length; -ULONG message_offset; -ULONG message_length; - - status = _nxd_mqtt_process_publish_packet(packet_ptr, &topic_offset, - &topic_length, &message_offset, - &message_length); - if (status) - { - nx_packet_release(packet_ptr); - return(status); - } - - packet_ptr -> nx_packet_length = message_length; - /* Adjust packet to pointer to message payload. */ - while (packet_ptr) + if (hub_client_ptr == NX_NULL) { - if ((ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) > message_offset) - { - - /* This packet contains message payload. */ - packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + message_offset; - break; - } - - message_offset -= (ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr); - - /* Set current packet to empty. */ - packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_append_ptr; - - /* Move to next packet. */ - packet_ptr = packet_ptr -> nx_packet_next; + LogError(LogLiteralArgs("IoTHub cloud message receive fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); } - return(NX_AZURE_IOT_SUCCESS); -} - -UINT nx_azure_iot_hub_client_cloud_message_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - NX_PACKET **packet_pptr, UINT wait_option) -{ -UINT status; - - status = nx_azure_iot_hub_client_message_receive(hub_client_ptr, NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_MESSAGE, - &(hub_client_ptr -> nx_azure_iot_hub_client_c2d_message), - packet_pptr, wait_option); + status = nx_azure_iot_hub_transport_message_receive(&(hub_client_ptr -> nx_azure_iot_hub_client_transport), + NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_QUEUE_INDEX, 0, + packet_pptr, wait_option); if (status) { return(status); } - return(nx_azure_iot_hub_client_adjust_payload(*packet_pptr)); + return(nx_azure_iot_hub_transport_adjust_payload(*packet_pptr)); } UINT nx_azure_iot_hub_client_cloud_message_property_get(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, @@ -1187,8 +587,8 @@ az_span span; return(NX_AZURE_IOT_INVALID_PARAMETER); } - status = nx_azure_iot_hub_client_process_publish_packet(packet_ptr -> nx_packet_data_start, - &topic_offset, &topic_size); + status = nx_azure_iot_hub_transport_process_publish_packet(packet_ptr -> nx_packet_data_start, + &topic_offset, &topic_size); if (status) { return(status); @@ -1235,45 +635,9 @@ az_span span; return(NX_AZURE_IOT_SUCCESS); } -static VOID nx_azure_iot_hub_client_device_twin_ack_notify(NXD_MQTT_CLIENT *client_ptr, UINT type, - USHORT packet_id, NX_PACKET *transmit_packet_ptr, VOID *context) -{ - -NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)context; -UCHAR buffer[sizeof(AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_SUBSCRIBE_TOPIC) - 1]; -ULONG bytes_copied; - - - NX_PARAMETER_NOT_USED(client_ptr); - NX_PARAMETER_NOT_USED(packet_id); - NX_PARAMETER_NOT_USED(context); - - /* Mointor subscribe ack. */ - if (type == MQTT_CONTROL_PACKET_TYPE_SUBACK) - { - - /* Get the topic. */ - if (nx_packet_data_extract_offset(transmit_packet_ptr, - NX_AZURE_IOT_MQTT_SUBSCRIBE_TOPIC_OFFSET, - buffer, sizeof(buffer), &bytes_copied)) - { - return; - } - - /* Compare the topic. */ - if ((bytes_copied == sizeof(AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_SUBSCRIBE_TOPIC) - 1) && - (!memcmp(AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_SUBSCRIBE_TOPIC, - buffer, sizeof(AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_SUBSCRIBE_TOPIC) - 1))) - { - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_response_subscribe_ack = NX_TRUE; - } - } -} - UINT nx_azure_iot_hub_client_device_twin_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { UINT status; -NXD_MQTT_CLIENT *client_ptr; if (hub_client_ptr == NX_NULL) { @@ -1281,57 +645,33 @@ NXD_MQTT_CLIENT *client_ptr; return(NX_AZURE_IOT_INVALID_PARAMETER); } - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - - /* Atomically update the handler as we need to serialize the handler with incoming messages. */ - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message.message_process = - nx_azure_iot_hub_client_device_twin_process; - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_desired_properties_message.message_process = - nx_azure_iot_hub_client_device_twin_process; - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message.message_enable = - nx_azure_iot_hub_client_device_twin_enable; - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_desired_properties_message.message_enable = - nx_azure_iot_hub_client_device_twin_enable; - - /* Register callbacks even if not connect and when connect complete subscribe for topics. */ - if (hub_client_ptr -> nx_azure_iot_hub_client_state != NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED) + status = nx_azure_iot_hub_transport_receive_message_enable(&(hub_client_ptr ->nx_azure_iot_hub_client_transport), + NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES_QUEUE_INDEX, + (const UCHAR *)AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_SUBSCRIBE_TOPIC, + sizeof(AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_SUBSCRIBE_TOPIC) - 1, + nx_azure_iot_hub_client_device_twin_process); + if (status) { - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - return(NX_AZURE_IOT_SUCCESS); + LogError(LogLiteralArgs("IoTHub client device twin subscribe fail status: %d"), status); + return(status); } - /* Initialize variables. */ - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_response_subscribe_ack = NX_FALSE; - - /* Set ack receive notify for subscribe ack. */ - client_ptr = &(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt); - client_ptr -> nxd_mqtt_ack_receive_notify = nx_azure_iot_hub_client_device_twin_ack_notify; - client_ptr -> nxd_mqtt_ack_receive_context = hub_client_ptr; - - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - - status = nxd_mqtt_client_subscribe(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), - AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_SUBSCRIBE_TOPIC, - sizeof(AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_SUBSCRIBE_TOPIC) - 1, - NX_AZURE_IOT_MQTT_QOS_0); + status = nx_azure_iot_hub_transport_receive_message_enable(&(hub_client_ptr ->nx_azure_iot_hub_client_transport), + NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES_QUEUE_INDEX, + (const UCHAR *)AZ_IOT_HUB_CLIENT_TWIN_PATCH_SUBSCRIBE_TOPIC, + sizeof(AZ_IOT_HUB_CLIENT_TWIN_PATCH_SUBSCRIBE_TOPIC) - 1, + NX_NULL); if (status) { - - /* Clean ack receive notify. */ - client_ptr -> nxd_mqtt_ack_receive_notify = NX_NULL; LogError(LogLiteralArgs("IoTHub client device twin subscribe fail status: %d"), status); return(status); } - status = nxd_mqtt_client_subscribe(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), - AZ_IOT_HUB_CLIENT_TWIN_PATCH_SUBSCRIBE_TOPIC, - sizeof(AZ_IOT_HUB_CLIENT_TWIN_PATCH_SUBSCRIBE_TOPIC) - 1, - NX_AZURE_IOT_MQTT_QOS_0); + status = nx_azure_iot_hub_transport_receive_message_enable(&(hub_client_ptr ->nx_azure_iot_hub_client_transport), + NX_AZURE_IOT_HUB_DEVICE_TWIN_REPORTED_PROPERTIES_RESPONSE_QUEUE_INDEX, + NX_NULL, 0, NX_NULL); if (status) { - - /* Clean ack receive notify. */ - client_ptr -> nxd_mqtt_ack_receive_notify = NX_NULL; LogError(LogLiteralArgs("IoTHub client device twin subscribe fail status: %d"), status); return(status); } @@ -1349,27 +689,22 @@ UINT status; return(NX_AZURE_IOT_INVALID_PARAMETER); } - status = nxd_mqtt_client_unsubscribe(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), - AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_SUBSCRIBE_TOPIC, - sizeof(AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_SUBSCRIBE_TOPIC) - 1); + status = nx_azure_iot_hub_transport_receive_message_disable(&(hub_client_ptr ->nx_azure_iot_hub_client_transport), + NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES_QUEUE_INDEX); if (status) { LogError(LogLiteralArgs("IoTHub client device twin unsubscribe fail status: %d"), status); return(status); } - status = nxd_mqtt_client_unsubscribe(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), - AZ_IOT_HUB_CLIENT_TWIN_PATCH_SUBSCRIBE_TOPIC, - sizeof(AZ_IOT_HUB_CLIENT_TWIN_PATCH_SUBSCRIBE_TOPIC) - 1); + status = nx_azure_iot_hub_transport_receive_message_disable(&(hub_client_ptr ->nx_azure_iot_hub_client_transport), + NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES_QUEUE_INDEX); if (status) { LogError(LogLiteralArgs("IoTHub client device twin unsubscribe fail status: %d"), status); return(status); } - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message.message_process = NX_NULL; - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_desired_properties_message.message_process = NX_NULL; - return(NX_AZURE_IOT_SUCCESS); } @@ -1388,10 +723,10 @@ UINT nx_azure_iot_hub_client_report_properties_response_callback_set(NX_AZURE_IO return(NX_AZURE_IOT_INVALID_PARAMETER); } - hub_client_ptr -> nx_azure_iot_hub_client_report_properties_response_callback = callback_ptr; - hub_client_ptr -> nx_azure_iot_hub_client_report_properties_response_callback_args = callback_args; - - return(NX_AZURE_IOT_SUCCESS); + return(nx_azure_iot_hub_transport_receive_message_callback_set(&(hub_client_ptr ->nx_azure_iot_hub_client_transport), + NX_AZURE_IOT_HUB_DEVICE_TWIN_REPORTED_PROPERTIES_RESPONSE_QUEUE_INDEX, + callback_ptr != NX_NULL ? nx_azure_iot_hub_client_reported_property_receive_callback : NX_NULL, + (NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN)callback_ptr, callback_args)); } static UINT nx_azure_iot_hub_client_twin_request_id_get(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, @@ -1402,7 +737,7 @@ static UINT nx_azure_iot_hub_client_twin_request_id_get(NX_AZURE_IOT_HUB_CLIENT az_span span; /* Obtain the mutex. */ - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + tx_mutex_get(hub_client_ptr -> nx_azure_iot_hub_client_transport.nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); /* Check if current request_id is even and new requested is also even or current request_id is odd and new requested is also odd. */ @@ -1426,7 +761,7 @@ az_span span; { /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + tx_mutex_put(hub_client_ptr -> nx_azure_iot_hub_client_transport.nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); LogError(LogLiteralArgs("IoTHub client device failed to u32toa")); return(NX_AZURE_IOT_SDK_CORE_ERROR); } @@ -1434,56 +769,7 @@ az_span span; *request_id_span_ptr = az_span_create(buffer_ptr, (INT)(buffer_len - (UINT)az_span_size(span))); /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - - return(NX_AZURE_IOT_SUCCESS); -} - -static UINT nx_azure_iot_hub_client_device_twin_reponse_topic_status(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT wait_option) -{ - - /* Wait for subscribe ack of topic "$iothub/twin/res/#". */ - while (1) - { - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - - /* Check if it is still in connected status. */ - if (hub_client_ptr -> nx_azure_iot_hub_client_state != NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED) - { - - /* Clean ack receive notify. */ - hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt.nxd_mqtt_ack_receive_notify = NX_NULL; - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - return(NX_AZURE_IOT_DISCONNECTED); - } - - /* Check if receive the subscribe ack. */ - if (hub_client_ptr -> nx_azure_iot_hub_client_device_twin_response_subscribe_ack == NX_TRUE) - { - - /* Clean ack receive notify. */ - hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt.nxd_mqtt_ack_receive_notify = NX_NULL; - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - break; - } - - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - - /* Update wait time. */ - if (wait_option != NX_WAIT_FOREVER) - { - if (wait_option > 0) - { - wait_option--; - } - else - { - return(NX_AZURE_IOT_NO_SUBSCRIBE_ACK); - } - } - - tx_thread_sleep(1); - } + tx_mutex_put(hub_client_ptr -> nx_azure_iot_hub_client_transport.nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); return(NX_AZURE_IOT_SUCCESS); } @@ -1499,10 +785,10 @@ NX_PACKET *packet_ptr; UINT topic_length; UINT request_id; az_span request_id_span; -NX_AZURE_IOT_THREAD thread_list; az_result core_result; ULONG topic_offset; USHORT length; +NX_PACKET *response_packet_ptr; if (hub_client_ptr == NX_NULL) { @@ -1510,7 +796,10 @@ USHORT length; return(NX_AZURE_IOT_INVALID_PARAMETER); } - if ((status = nx_azure_iot_hub_client_device_twin_reponse_topic_status(hub_client_ptr, wait_option))) + /* Check if twin response is subscribed */ + if ((status = nx_azure_iot_hub_transport_receive_message_is_subscribed(&(hub_client_ptr -> nx_azure_iot_hub_client_transport), + NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES_QUEUE_INDEX, + wait_option))) { LogError(LogLiteralArgs("IoTHub client reported state send fail with error %d"), status); return(status); @@ -1528,15 +817,8 @@ USHORT length; * 2. Wait for the response if required. * 3. Return result if present. * */ - if (hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message.message_process == NX_NULL) - { - LogError(LogLiteralArgs("IoTHub client reported state send fail: NOT ENABLED")); - return(NX_AZURE_IOT_NOT_ENABLED); - } - - status = nx_azure_iot_publish_packet_get(hub_client_ptr -> nx_azure_iot_ptr, - &(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), - &packet_ptr, wait_option); + status = nx_azure_iot_hub_transport_publish_packet_get(&(hub_client_ptr -> nx_azure_iot_hub_client_transport), + &packet_ptr, wait_option); if (status) { LogError(LogLiteralArgs("IoTHub client reported state send fail: BUFFER ALLOCATE FAIL")); @@ -1580,10 +862,10 @@ USHORT length; packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + topic_length; packet_ptr -> nx_packet_length = topic_length; - /* Append payload. */ - status = nx_packet_data_append(packet_ptr, (VOID *)message_buffer, message_length, - packet_ptr -> nx_packet_pool_owner, - wait_option); + status = nx_azure_iot_hub_transport_request_response(&(hub_client_ptr -> nx_azure_iot_hub_client_transport), + request_id, packet_ptr, topic_length, message_buffer, message_length, + NX_AZURE_IOT_HUB_DEVICE_TWIN_REPORTED_PROPERTIES_RESPONSE_QUEUE_INDEX, + &response_packet_ptr, wait_option); if (status) { LogError(LogLiteralArgs("IoTHub client reported state send fail: append failed")); @@ -1591,60 +873,16 @@ USHORT length; return(status); } - /* Obtain the mutex. */ - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - - thread_list.thread_message_type = NX_AZURE_IOT_HUB_DEVICE_TWIN_REPORTED_PROPERTIES_RESPONSE; - thread_list.thread_ptr = tx_thread_identify(); - thread_list.thread_expected_id = request_id; - thread_list.thread_received_message = NX_NULL; - thread_list.thread_next = hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended; - hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended = &thread_list; - - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - - status = nx_azure_iot_publish_mqtt_packet(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), - packet_ptr, topic_length, NX_NULL, NX_AZURE_IOT_MQTT_QOS_0, - wait_option); - - if (status) - { - nx_packet_release(packet_ptr); - - /* remove thread from waiting suspend queue. */ - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - nx_azure_iot_hub_client_thread_dequeue(hub_client_ptr, &thread_list); - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - - LogError(LogLiteralArgs("IoTHub client reported state send: PUBLISH FAIL status: %d"), status); - return(status); - } - LogDebug(LogLiteralArgs("request_id: %d"), request_id); - - if ((thread_list.thread_received_message) == NX_NULL && wait_option) - { - tx_thread_sleep(wait_option); - } - - /* Obtain the mutex. */ - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - - nx_azure_iot_hub_client_thread_dequeue(hub_client_ptr, &thread_list); - packet_ptr = thread_list.thread_received_message; - - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - if (request_id_ptr) { *request_id_ptr = request_id; } - if (packet_ptr == NX_NULL) + if (response_packet_ptr == NX_NULL) { LogError(LogLiteralArgs("IoTHub client reported state not responded")); - if (hub_client_ptr -> nx_azure_iot_hub_client_state != NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED) + if (hub_client_ptr -> nx_azure_iot_hub_client_transport.nx_azure_iot_hub_transport_state != + NX_AZURE_IOT_HUB_TRANSPORT_STATUS_CONNECTED) { return(NX_AZURE_IOT_DISCONNECTED); } @@ -1652,24 +890,24 @@ USHORT length; return(NX_AZURE_IOT_NO_PACKET); } - if ((status = nx_azure_iot_hub_client_process_publish_packet(packet_ptr -> nx_packet_prepend_ptr, - &topic_offset, &length))) + if ((status = nx_azure_iot_hub_transport_process_publish_packet(response_packet_ptr -> nx_packet_prepend_ptr, + &topic_offset, &length))) { - nx_packet_release(packet_ptr); + nx_packet_release(response_packet_ptr); return(status); } if ((status = nx_azure_iot_hub_client_device_twin_parse(hub_client_ptr, - packet_ptr, topic_offset, length, + response_packet_ptr, topic_offset, length, NX_NULL, version_ptr, NX_NULL, response_status_ptr))) { - nx_packet_release(packet_ptr); + nx_packet_release(response_packet_ptr); return(status); } /* Release message block. */ - nx_packet_release(packet_ptr); + nx_packet_release(response_packet_ptr); return(NX_AZURE_IOT_SUCCESS); } @@ -1691,7 +929,9 @@ az_result core_result; return(NX_AZURE_IOT_INVALID_PARAMETER); } - if ((status = nx_azure_iot_hub_client_device_twin_reponse_topic_status(hub_client_ptr, wait_option))) + if ((status = nx_azure_iot_hub_transport_receive_message_is_subscribed(&(hub_client_ptr -> nx_azure_iot_hub_client_transport), + NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES_QUEUE_INDEX, + wait_option))) { LogError(LogLiteralArgs("IoTHub client device twin publish fail with error %d"), status); return(status); @@ -1707,9 +947,8 @@ az_result core_result; /* Steps. * 1. Publish message to topic "$iothub/twin/GET/?$rid={request id}" * */ - status = nx_azure_iot_publish_packet_get(hub_client_ptr -> nx_azure_iot_ptr, - &(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), - &packet_ptr, wait_option); + status = nx_azure_iot_hub_transport_publish_packet_get(&(hub_client_ptr -> nx_azure_iot_hub_client_transport), + &packet_ptr, wait_option); if (status) { LogError(LogLiteralArgs("IoTHub client device twin publish fail: BUFFER ALLOCATE FAIL")); @@ -1752,9 +991,8 @@ az_result core_result; packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + topic_length; packet_ptr -> nx_packet_length = topic_length; - status = nx_azure_iot_publish_mqtt_packet(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), - packet_ptr, topic_length, NX_NULL, NX_AZURE_IOT_MQTT_QOS_0, - wait_option); + status = nx_azure_iot_hub_transport_publish(&(hub_client_ptr -> nx_azure_iot_hub_client_transport), packet_ptr, + NX_NULL, 0, NX_AZURE_IOT_MQTT_QOS_0, wait_option); if (status) { LogError(LogLiteralArgs("IoTHub client device twin: PUBLISH FAIL status: %d"), status); @@ -1776,7 +1014,8 @@ az_span topic_span; az_iot_hub_client_twin_response out_twin_response; NX_PACKET *packet_ptr; - if (hub_client_ptr == NX_NULL || packet_pptr == NX_NULL) + if ((hub_client_ptr == NX_NULL) || + (packet_pptr == NX_NULL)) { LogError(LogLiteralArgs("IoTHub client device twin receive failed: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); @@ -1787,17 +1026,17 @@ NX_PACKET *packet_ptr; * 2. If present check the response. * 3. Return the payload of the response. * */ - status = nx_azure_iot_hub_client_message_receive(hub_client_ptr, NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES, - &(hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message), - &packet_ptr, wait_option); + status = nx_azure_iot_hub_transport_message_receive(&(hub_client_ptr -> nx_azure_iot_hub_client_transport), + NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES_QUEUE_INDEX, 0, + &packet_ptr, wait_option); if (status) { LogError(LogLiteralArgs("IoTHub client device twin receive failed status: %d"), status); return(status); } - if (nx_azure_iot_hub_client_process_publish_packet(packet_ptr -> nx_packet_prepend_ptr, &topic_offset, - &topic_length)) + if (nx_azure_iot_hub_transport_process_publish_packet(packet_ptr -> nx_packet_prepend_ptr, &topic_offset, + &topic_length)) { /* Message not supported. It will be released. */ @@ -1824,7 +1063,7 @@ NX_PACKET *packet_ptr; *packet_pptr = packet_ptr; - return(nx_azure_iot_hub_client_adjust_payload(*packet_pptr)); + return(nx_azure_iot_hub_transport_adjust_payload(*packet_pptr)); } UINT nx_azure_iot_hub_client_device_twin_desired_properties_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, @@ -1832,7 +1071,8 @@ UINT nx_azure_iot_hub_client_device_twin_desired_properties_receive(NX_AZURE_IOT { UINT status; - if (hub_client_ptr == NX_NULL || packet_pptr == NX_NULL) + if ((hub_client_ptr == NX_NULL) || + (packet_pptr == NX_NULL)) { LogError(LogLiteralArgs("IoTHub client device twin receive properties failed: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); @@ -1842,228 +1082,26 @@ UINT status; * 1. Check if the desired properties document is available to receive from linklist. * 2. Return result if present. * */ - status = nx_azure_iot_hub_client_message_receive(hub_client_ptr, NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES, - &(hub_client_ptr -> nx_azure_iot_hub_client_device_twin_desired_properties_message), - packet_pptr, wait_option); + status = nx_azure_iot_hub_transport_message_receive(&(hub_client_ptr -> nx_azure_iot_hub_client_transport), + NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES_QUEUE_INDEX, 0, + packet_pptr, wait_option); if (status) { return(status); } - return(nx_azure_iot_hub_client_adjust_payload(*packet_pptr)); -} - -static UINT nx_azure_iot_hub_client_cloud_message_sub_unsub(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT is_subscribe) -{ -UINT status; - - if (hub_client_ptr == NX_NULL) - { - LogError(LogLiteralArgs("IoTHub cloud message subscribe fail: INVALID POINTER")); - return(NX_AZURE_IOT_INVALID_PARAMETER); - } - - if (is_subscribe) - { - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - - /* Atomically update the handler as we need to serialize the handler with incoming messages. */ - hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_process = nx_azure_iot_hub_client_c2d_process; - hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_enable = nx_azure_iot_hub_client_cloud_message_enable; - - /* Register callbacks even if not connect and when connect complete subscribe for topics. */ - if (hub_client_ptr -> nx_azure_iot_hub_client_state != NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED) - { - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - return(NX_AZURE_IOT_SUCCESS); - } - - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - - status = nxd_mqtt_client_subscribe(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), - AZ_IOT_HUB_CLIENT_C2D_SUBSCRIBE_TOPIC, sizeof(AZ_IOT_HUB_CLIENT_C2D_SUBSCRIBE_TOPIC) - 1, - NX_AZURE_IOT_MQTT_QOS_1); - if (status) - { - LogError(LogLiteralArgs("IoTHub cloud message subscribe fail: status: %d"), status); - return(status); - } - } - else - { - status = nxd_mqtt_client_unsubscribe(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), - AZ_IOT_HUB_CLIENT_C2D_SUBSCRIBE_TOPIC, sizeof(AZ_IOT_HUB_CLIENT_C2D_SUBSCRIBE_TOPIC) - 1); - if (status) - { - LogError(LogLiteralArgs("IoTHub cloud message subscribe fail: status: %d"), status); - return(status); - } - - hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_process = NX_NULL; - } - - return(NX_AZURE_IOT_SUCCESS); -} - -static VOID nx_azure_iot_hub_client_mqtt_receive_callback(NXD_MQTT_CLIENT* client_ptr, - UINT number_of_messages) -{ -NX_AZURE_IOT_RESOURCE *resource = nx_azure_iot_resource_search(client_ptr); -NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = NX_NULL; -NX_PACKET *packet_ptr; -NX_PACKET *packet_next_ptr; -ULONG topic_offset; -USHORT topic_length; - - /* This function is protected by MQTT mutex. */ - - NX_PARAMETER_NOT_USED(number_of_messages); - - if (resource && (resource -> resource_type == NX_AZURE_IOT_RESOURCE_IOT_HUB)) - { - hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)resource -> resource_data_ptr; - } - - if (hub_client_ptr) - { - for (packet_ptr = client_ptr -> message_receive_queue_head; - packet_ptr; - packet_ptr = packet_next_ptr) - { - - /* Store next packet in case current packet is consumed. */ - packet_next_ptr = packet_ptr -> nx_packet_queue_next; - - /* Adjust packet to simply process logic. */ - nx_azure_iot_mqtt_packet_adjust(packet_ptr); - - if (nx_azure_iot_hub_client_process_publish_packet(packet_ptr -> nx_packet_prepend_ptr, &topic_offset, - &topic_length)) - { - - /* Message not supported. It will be released. */ - nx_packet_release(packet_ptr); - continue; - } - - if ((topic_offset + topic_length) > - (ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr)) - { - - /* Only process topic in the first packet since the fixed topic is short enough to fit into one packet. */ - topic_length = (USHORT)(((ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) - - topic_offset) & 0xFFFF); - } - - if (hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message.message_process && - (hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message.message_process(hub_client_ptr, packet_ptr, - topic_offset, - topic_length) == NX_AZURE_IOT_SUCCESS)) - { - - /* Direct method message is processed. */ - continue; - } - - if (hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_process && - (hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_process(hub_client_ptr, packet_ptr, - topic_offset, - topic_length) == NX_AZURE_IOT_SUCCESS)) - { - - /* Could to Device message is processed. */ - continue; - } - - if ((hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message.message_process) && - (hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message.message_process(hub_client_ptr, - packet_ptr, topic_offset, - topic_length) == NX_AZURE_IOT_SUCCESS)) - { - - /* Device Twin message is processed. */ - continue; - } - - /* Message not supported. It will be released. */ - nx_packet_release(packet_ptr); - } - - /* Clear all message from MQTT receive queue. */ - client_ptr -> message_receive_queue_head = NX_NULL; - client_ptr -> message_receive_queue_tail = NX_NULL; - client_ptr -> message_receive_queue_depth = 0; - } -} - -static VOID nx_azure_iot_hub_client_message_notify(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE *receive_message, - NX_PACKET *packet_ptr) -{ - if (receive_message -> message_tail) - { - receive_message -> message_tail -> nx_packet_queue_next = packet_ptr; - } - else - { - receive_message -> message_head = packet_ptr; - } - receive_message -> message_tail = packet_ptr; - - /* Check for user callback function. */ - if (receive_message -> message_callback) - { - receive_message -> message_callback(hub_client_ptr, receive_message -> message_callback_args); - } + return(nx_azure_iot_hub_transport_adjust_payload(*packet_pptr)); } -static UINT nx_azure_iot_hub_client_receive_thread_find(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - NX_PACKET *packet_ptr, UINT message_type, - UINT request_id, NX_AZURE_IOT_THREAD **thread_list_pptr) -{ -NX_AZURE_IOT_THREAD *thread_list_prev = NX_NULL; -NX_AZURE_IOT_THREAD *thread_list_ptr; - - /* Search thread waiting for message type. */ - for (thread_list_ptr = hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended; - thread_list_ptr; - thread_list_ptr = thread_list_ptr -> thread_next) - { - if ((thread_list_ptr -> thread_message_type == message_type) && - (request_id == thread_list_ptr -> thread_expected_id)) - { - - /* Found a thread waiting for message type. */ - if (thread_list_prev == NX_NULL) - { - hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended = thread_list_ptr -> thread_next; - } - else - { - thread_list_prev -> thread_next = thread_list_ptr -> thread_next; - } - thread_list_ptr -> thread_received_message = packet_ptr; - *thread_list_pptr = thread_list_ptr; - return(NX_AZURE_IOT_SUCCESS); - } - - thread_list_prev = thread_list_ptr; - } - - return(NX_AZURE_IOT_NOT_FOUND); -} - -static UINT nx_azure_iot_hub_client_c2d_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - NX_PACKET *packet_ptr, - ULONG topic_offset, +static UINT nx_azure_iot_hub_client_c2d_process(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + NX_PACKET *packet_ptr, ULONG topic_offset, USHORT topic_length) { UCHAR *topic_name; az_iot_hub_client_c2d_request request; az_span receive_topic; az_result core_result; -UINT status; -NX_AZURE_IOT_THREAD *thread_list_ptr; +NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)hub_trans_ptr -> nx_azure_iot_hub_transport_client_context; /* This function is protected by MQTT mutex. */ @@ -2087,35 +1125,19 @@ NX_AZURE_IOT_THREAD *thread_list_ptr; return(NX_AZURE_IOT_NOT_FOUND); } - status = nx_azure_iot_hub_client_receive_thread_find(hub_client_ptr, - packet_ptr, - NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_MESSAGE, - 0, &thread_list_ptr); - if (status == NX_AZURE_IOT_SUCCESS) - { - tx_thread_wait_abort(thread_list_ptr -> thread_ptr); - return(NX_AZURE_IOT_SUCCESS); - } - - /* No thread is waiting for C2D message yet. */ - nx_azure_iot_hub_client_message_notify(hub_client_ptr, - &(hub_client_ptr -> nx_azure_iot_hub_client_c2d_message), - packet_ptr); - - return(NX_AZURE_IOT_SUCCESS); + return(nx_azure_iot_hub_transport_receive_notify(hub_trans_ptr, packet_ptr, + NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_QUEUE_INDEX, 0)); } -static UINT nx_azure_iot_hub_client_direct_method_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - NX_PACKET *packet_ptr, - ULONG topic_offset, +static UINT nx_azure_iot_hub_client_direct_method_process(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + NX_PACKET *packet_ptr, ULONG topic_offset, USHORT topic_length) { UCHAR *topic_name; az_iot_hub_client_method_request request; az_span receive_topic; az_result core_result; -UINT status; -NX_AZURE_IOT_THREAD *thread_list_ptr; +NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)hub_trans_ptr -> nx_azure_iot_hub_transport_client_context; /* This function is protected by MQTT mutex. */ @@ -2139,27 +1161,14 @@ NX_AZURE_IOT_THREAD *thread_list_ptr; return(NX_AZURE_IOT_NOT_FOUND); } - status = nx_azure_iot_hub_client_receive_thread_find(hub_client_ptr, - packet_ptr, - NX_AZURE_IOT_HUB_DIRECT_METHOD, - 0, &thread_list_ptr); - if (status == NX_AZURE_IOT_SUCCESS) - { - tx_thread_wait_abort(thread_list_ptr -> thread_ptr); - return(NX_AZURE_IOT_SUCCESS); - } - - /* No thread is waiting for direct method message yet. */ - nx_azure_iot_hub_client_message_notify(hub_client_ptr, - &(hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message), - packet_ptr); - return(NX_AZURE_IOT_SUCCESS); + return(nx_azure_iot_hub_transport_receive_notify(hub_trans_ptr, packet_ptr, + NX_AZURE_IOT_HUB_DIRECT_METHOD_QUEUE_INDEX, 0)); } static UINT nx_azure_iot_hub_client_device_twin_message_type_get(az_iot_hub_client_twin_response *out_twin_response_ptr, UINT request_id) { -UINT mesg_type; +UINT message_type; switch (out_twin_response_ptr -> response_type) { @@ -2171,24 +1180,24 @@ UINT mesg_type; { /* Odd requests are of reported properties and even of twin properties. */ - mesg_type = request_id % 2 == 0 ? NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES : - NX_AZURE_IOT_HUB_DEVICE_TWIN_REPORTED_PROPERTIES_RESPONSE; + message_type = request_id % 2 == 0 ? NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES : + NX_AZURE_IOT_HUB_DEVICE_TWIN_REPORTED_PROPERTIES_RESPONSE; } break; case AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_TYPE_DESIRED_PROPERTIES : { - mesg_type = NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES; + message_type = NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES; } break; default : { - mesg_type = NX_AZURE_IOT_HUB_NONE; + message_type = NX_AZURE_IOT_HUB_NONE; } } - return mesg_type; + return message_type; } static UINT nx_azure_iot_hub_client_device_twin_parse(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, @@ -2250,12 +1259,10 @@ uint32_t version; return(NX_AZURE_IOT_SUCCESS); } -static UINT nx_azure_iot_hub_client_device_twin_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - NX_PACKET *packet_ptr, - ULONG topic_offset, +static UINT nx_azure_iot_hub_client_device_twin_process(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + NX_PACKET *packet_ptr, ULONG topic_offset, USHORT topic_length) { -NX_AZURE_IOT_THREAD *thread_list_ptr; UINT message_type; UINT response_status; UINT request_id = 0; @@ -2263,6 +1270,8 @@ ULONG version = 0; UINT correlation_id; UINT status; ULONG current_time; +NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)hub_trans_ptr -> nx_azure_iot_hub_transport_client_context; +UINT message_queue_index; /* This function is protected by MQTT mutex. */ if ((status = nx_azure_iot_hub_client_device_twin_parse(hub_client_ptr, packet_ptr, @@ -2275,7 +1284,7 @@ ULONG current_time; if (response_status == NX_AZURE_IOT_HUB_CLIENT_THROTTLE_STATUS_CODE) { - if ((status = nx_azure_iot_unix_time_get(hub_client_ptr -> nx_azure_iot_ptr, ¤t_time))) + if ((status = nx_azure_iot_unix_time_get(hub_client_ptr -> nx_azure_iot_hub_client_transport.nx_azure_iot_ptr, ¤t_time))) { LogError(LogLiteralArgs("IoTHub client fail to get unix time: %d"), status); return(status); @@ -2303,206 +1312,38 @@ ULONG current_time; correlation_id = 0; } - status = nx_azure_iot_hub_client_receive_thread_find(hub_client_ptr, - packet_ptr, - message_type, - correlation_id, &thread_list_ptr); - if (status == NX_AZURE_IOT_SUCCESS) - { - tx_thread_wait_abort(thread_list_ptr -> thread_ptr); - return(NX_AZURE_IOT_SUCCESS); - } + message_queue_index = nx_azure_iot_hub_client_mesg_type_to_queue_index(message_type); + status = nx_azure_iot_hub_transport_receive_notify(hub_trans_ptr, packet_ptr, + message_queue_index, correlation_id); - switch(message_type) - { - case NX_AZURE_IOT_HUB_DEVICE_TWIN_REPORTED_PROPERTIES_RESPONSE : - { - if (hub_client_ptr -> nx_azure_iot_hub_client_report_properties_response_callback) - { - hub_client_ptr -> nx_azure_iot_hub_client_report_properties_response_callback(hub_client_ptr, - request_id, - response_status, - version, - hub_client_ptr -> nx_azure_iot_hub_client_report_properties_response_callback_args); - } - - nx_packet_release(packet_ptr); - } - break; - - case NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES : - { - - /* No thread is waiting for device twin message yet. */ - nx_azure_iot_hub_client_message_notify(hub_client_ptr, - &(hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message), - packet_ptr); - } - break; - - case NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES : - { - - /* No thread is waiting for device twin message yet. */ - nx_azure_iot_hub_client_message_notify(hub_client_ptr, - &(hub_client_ptr -> nx_azure_iot_hub_client_device_twin_desired_properties_message), - packet_ptr); - } - break; - - default : - nx_packet_release(packet_ptr); - } - - return(NX_AZURE_IOT_SUCCESS); -} - -static VOID nx_azure_iot_hub_client_thread_dequeue(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - NX_AZURE_IOT_THREAD *thread_list_ptr) -{ -NX_AZURE_IOT_THREAD *thread_list_prev = NX_NULL; -NX_AZURE_IOT_THREAD *thread_list_current; - - for (thread_list_current = hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended; - thread_list_current; - thread_list_current = thread_list_current -> thread_next) - { - if (thread_list_current == thread_list_ptr) - { - - /* Found the thread to dequeue. */ - if (thread_list_prev == NX_NULL) - { - hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended = thread_list_current -> thread_next; - } - else - { - thread_list_prev -> thread_next = thread_list_current -> thread_next; - } - break; - } - - thread_list_prev = thread_list_current; - } -} - -static UINT nx_azure_iot_hub_client_sas_token_get(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - ULONG expiry_time_secs, const UCHAR *key, UINT key_len, - UCHAR *sas_buffer, UINT sas_buffer_len, UINT *sas_length) -{ -UCHAR *buffer_ptr; -UINT buffer_size; -VOID *buffer_context; -az_span span = az_span_create(sas_buffer, (INT)sas_buffer_len); -az_span buffer_span; -UINT status; -UCHAR *output_ptr; -UINT output_len; -az_result core_result; - - status = nx_azure_iot_buffer_allocate(hub_client_ptr -> nx_azure_iot_ptr, &buffer_ptr, &buffer_size, &buffer_context); - if (status) - { - LogError(LogLiteralArgs("IoTHub client sas token fail: BUFFER ALLOCATE FAIL")); - return(status); - } - - core_result = az_iot_hub_client_sas_get_signature(&(hub_client_ptr -> iot_hub_client_core), - expiry_time_secs, span, &span); - if (az_result_failed(core_result)) - { - LogError(LogLiteralArgs("IoTHub failed failed to get signature with error status: %d"), core_result); - nx_azure_iot_buffer_free(buffer_context); - return(NX_AZURE_IOT_SDK_CORE_ERROR); - } - - status = nx_azure_iot_base64_hmac_sha256_calculate(&(hub_client_ptr -> nx_azure_iot_hub_client_resource), - key, key_len, az_span_ptr(span), (UINT)az_span_size(span), - buffer_ptr, buffer_size, &output_ptr, &output_len); - if (status) - { - LogError(LogLiteralArgs("IoTHub failed to encoded hash")); - nx_azure_iot_buffer_free(buffer_context); - return(status); - } - - buffer_span = az_span_create(output_ptr, (INT)output_len); - core_result= az_iot_hub_client_sas_get_password(&(hub_client_ptr -> iot_hub_client_core), - expiry_time_secs, buffer_span, AZ_SPAN_EMPTY, - (CHAR *)sas_buffer, sas_buffer_len, &sas_buffer_len); - if (az_result_failed(core_result)) - { - LogError(LogLiteralArgs("IoTHub failed to generate token with error status: %d"), core_result); - nx_azure_iot_buffer_free(buffer_context); - return(NX_AZURE_IOT_SDK_CORE_ERROR); - } - - *sas_length = sas_buffer_len; - nx_azure_iot_buffer_free(buffer_context); - - return(NX_AZURE_IOT_SUCCESS); + return(status); } UINT nx_azure_iot_hub_client_direct_method_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { -UINT status; - if (hub_client_ptr == NX_NULL) { LogError(LogLiteralArgs("IoTHub client direct method subscribe fail: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); } - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - - /* Atomically update the handler as we need to serialize the handler with incoming messages. */ - hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message.message_process = nx_azure_iot_hub_client_direct_method_process; - hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message.message_enable = nx_azure_iot_hub_client_direct_method_enable; - - /* Register callbacks even if not connect and when connect complete subscribe for topics. */ - if (hub_client_ptr -> nx_azure_iot_hub_client_state != NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED) - { - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - return(NX_AZURE_IOT_SUCCESS); - } - - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - - status = nxd_mqtt_client_subscribe(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), - AZ_IOT_HUB_CLIENT_METHODS_SUBSCRIBE_TOPIC, - sizeof(AZ_IOT_HUB_CLIENT_METHODS_SUBSCRIBE_TOPIC) - 1, - NX_AZURE_IOT_MQTT_QOS_0); - if (status) - { - LogError(LogLiteralArgs("IoTHub client direct method subscribe fail %d"), status); - return(status); - } - - return(NX_AZURE_IOT_SUCCESS); + return(nx_azure_iot_hub_transport_receive_message_enable(&(hub_client_ptr ->nx_azure_iot_hub_client_transport), + NX_AZURE_IOT_HUB_DIRECT_METHOD_QUEUE_INDEX, + (const UCHAR *)AZ_IOT_HUB_CLIENT_METHODS_SUBSCRIBE_TOPIC, + sizeof(AZ_IOT_HUB_CLIENT_METHODS_SUBSCRIBE_TOPIC) - 1, + nx_azure_iot_hub_client_direct_method_process)); } UINT nx_azure_iot_hub_client_direct_method_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { -UINT status; - if (hub_client_ptr == NX_NULL) { LogError(LogLiteralArgs("IoTHub client direct method unsubscribe fail: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); } - status = nxd_mqtt_client_unsubscribe(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), - AZ_IOT_HUB_CLIENT_METHODS_SUBSCRIBE_TOPIC, - sizeof(AZ_IOT_HUB_CLIENT_METHODS_SUBSCRIBE_TOPIC) - 1); - if (status) - { - LogError(LogLiteralArgs("IoTHub client direct method unsubscribe fail status: %d"), status); - return(status); - } - - hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message.message_process = NX_NULL; - - return(NX_AZURE_IOT_SUCCESS); + return(nx_azure_iot_hub_transport_receive_message_disable(&(hub_client_ptr ->nx_azure_iot_hub_client_transport), + NX_AZURE_IOT_HUB_DIRECT_METHOD_QUEUE_INDEX)); } UINT nx_azure_iot_hub_client_direct_method_message_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, @@ -2531,9 +1372,9 @@ az_iot_hub_client_method_request request; return(NX_AZURE_IOT_INVALID_PARAMETER); } - status = nx_azure_iot_hub_client_message_receive(hub_client_ptr, NX_AZURE_IOT_HUB_DIRECT_METHOD, - &(hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message), - packet_pptr, wait_option); + status = nx_azure_iot_hub_transport_message_receive(&(hub_client_ptr -> nx_azure_iot_hub_client_transport), + NX_AZURE_IOT_HUB_DIRECT_METHOD_QUEUE_INDEX, 0, + packet_pptr, wait_option); if (status) { return(status); @@ -2599,7 +1440,6 @@ UINT status; az_result core_result; if ((hub_client_ptr == NX_NULL) || - (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL) || (context_ptr == NX_NULL) || (context_length == 0)) { @@ -2608,9 +1448,8 @@ az_result core_result; } /* Prepare response packet. */ - status = nx_azure_iot_publish_packet_get(hub_client_ptr -> nx_azure_iot_ptr, - &(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), - &packet_ptr, wait_option); + status = nx_azure_iot_hub_transport_publish_packet_get(&(hub_client_ptr -> nx_azure_iot_hub_client_transport), + &packet_ptr, wait_option); if (status) { LogError(LogLiteralArgs("Create response data fail")); @@ -2630,43 +1469,17 @@ az_result core_result; return(NX_AZURE_IOT_SDK_CORE_ERROR); } - packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + topic_length; packet_ptr -> nx_packet_length = topic_length; - if (payload && (payload_length != 0)) + if ((payload == NX_NULL) || (payload_length == 0)) { - - /* Append payload. */ - status = nx_packet_data_append(packet_ptr, (VOID *)payload, payload_length, - packet_ptr -> nx_packet_pool_owner, - wait_option); - if (status) - { - LogError(LogLiteralArgs("Method reponse data append fail")); - nx_packet_release(packet_ptr); - return(status); - } - } - else - { - - /* Append payload. */ - status = nx_packet_data_append(packet_ptr, NX_AZURE_IOT_HUB_CLIENT_EMPTY_JSON, - sizeof(NX_AZURE_IOT_HUB_CLIENT_EMPTY_JSON) - 1, - packet_ptr -> nx_packet_pool_owner, - wait_option); - if (status) - { - LogError(LogLiteralArgs("Adding empty json failed.")); - nx_packet_release(packet_ptr); - return(status); - } + payload = (const UCHAR *)NX_AZURE_IOT_HUB_CLIENT_EMPTY_JSON; + payload_length = sizeof(NX_AZURE_IOT_HUB_CLIENT_EMPTY_JSON) - 1; } - status = nx_azure_iot_publish_mqtt_packet(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), - packet_ptr, topic_length, NX_NULL, NX_AZURE_IOT_MQTT_QOS_0, - wait_option); + status = nx_azure_iot_hub_transport_publish(&(hub_client_ptr -> nx_azure_iot_hub_client_transport), packet_ptr, + payload, payload_length, NX_AZURE_IOT_MQTT_QOS_0, wait_option); if (status) { LogError(LogLiteralArgs("IoTHub client method response fail: PUBLISH FAIL status: %d"), status); @@ -2676,28 +1489,3 @@ az_result core_result; return(NX_AZURE_IOT_SUCCESS); } - -static UINT nx_azure_iot_hub_client_messages_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) -{ -UINT status = NX_AZURE_IOT_SUCCESS; - - if (status == NX_AZURE_IOT_SUCCESS && - (hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_process != NX_NULL)) - { - status = hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_enable(hub_client_ptr); - } - - if (status == NX_AZURE_IOT_SUCCESS && - (hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message.message_process != NX_NULL)) - { - status = hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message.message_enable(hub_client_ptr); - } - - if (status == NX_AZURE_IOT_SUCCESS && - (hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message.message_process != NX_NULL)) - { - status = hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message.message_enable(hub_client_ptr); - } - - return(status); -}
\ No newline at end of file diff --git a/addons/azure_iot/nx_azure_iot_hub_client.h b/addons/azure_iot/nx_azure_iot_hub_client.h index a510bb81..dcbce16a 100644 --- a/addons/azure_iot/nx_azure_iot_hub_client.h +++ b/addons/azure_iot/nx_azure_iot_hub_client.h @@ -9,7 +9,7 @@ /* */ /**************************************************************************/ -/* Version: 6.1 */ +/* Version: 6.1 PnP Preview 1 */ /** * @file nx_azure_iot_hub_client.h @@ -28,11 +28,10 @@ extern "C" { #endif #include "azure/iot/az_iot_hub_client.h" +#include "nx_azure_iot_hub_transport.h" #include "nx_azure_iot.h" #include "nx_api.h" #include "nx_cloud.h" -#include "nxd_dns.h" -#include "nxd_mqtt_client.h" /**< Value denoting a message is of "None" type */ #define NX_AZURE_IOT_HUB_NONE 0x00000000 @@ -55,16 +54,6 @@ extern "C" { /**< Value denoting a message is a device reported properties response */ #define NX_AZURE_IOT_HUB_DEVICE_TWIN_REPORTED_PROPERTIES_RESPONSE 0x00000010 -/* Set the default timeout for DNS query. */ -#ifndef NX_AZURE_IOT_HUB_CLIENT_DNS_TIMEOUT -#define NX_AZURE_IOT_HUB_CLIENT_DNS_TIMEOUT (5 * NX_IP_PERIODIC_RATE) -#endif /* NX_AZURE_IOT_HUB_CLIENT_DNS_TIMEOUT */ - -/* Set the default token expiry in secs. */ -#ifndef NX_AZURE_IOT_HUB_CLIENT_TOKEN_EXPIRY -#define NX_AZURE_IOT_HUB_CLIENT_TOKEN_EXPIRY (3600) -#endif /* NX_AZURE_IOT_HUB_CLIENT_TOKEN_EXPIRY */ - #ifndef NX_AZURE_IOT_HUB_CLIENT_MAX_BACKOFF_IN_SEC #define NX_AZURE_IOT_HUB_CLIENT_MAX_BACKOFF_IN_SEC (10 * 60) #endif /* NX_AZURE_IOT_HUB_CLIENT_MAX_BACKOFF_IN_SEC */ @@ -79,80 +68,32 @@ extern "C" { /* Define AZ IoT Hub Client state. */ /**< The client is not connected */ -#define NX_AZURE_IOT_HUB_CLIENT_STATUS_NOT_CONNECTED 0 +#define NX_AZURE_IOT_HUB_CLIENT_STATUS_NOT_CONNECTED NX_AZURE_IOT_HUB_TRANSPORT_STATUS_NOT_CONNECTED /**< The client is connecting */ -#define NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTING 1 +#define NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTING NX_AZURE_IOT_HUB_TRANSPORT_STATUS_CONNECTING /**< The client is connected */ -#define NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED 2 +#define NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED NX_AZURE_IOT_HUB_TRANSPORT_STATUS_CONNECTED /* Default TELEMETRY QoS is QoS1 */ #ifndef NX_AZURE_IOT_HUB_CLIENT_TELEMETRY_QOS #define NX_AZURE_IOT_HUB_CLIENT_TELEMETRY_QOS NX_AZURE_IOT_MQTT_QOS_1 #endif /* NX_AZURE_IOT_HUB_CLIENT_TELEMETRY_QOS */ -typedef struct NX_AZURE_IOT_THREAD_STRUCT -{ - TX_THREAD *thread_ptr; - struct NX_AZURE_IOT_THREAD_STRUCT *thread_next; - UINT thread_message_type; - UINT thread_expected_id; /* Used by device twin. */ - NX_PACKET *thread_received_message; -} NX_AZURE_IOT_THREAD; - -/* Forward declration*/ -struct NX_AZURE_IOT_HUB_CLIENT_STRUCT; - -typedef struct NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE_STRUCT -{ - NX_PACKET *message_head; - NX_PACKET *message_tail; - VOID (*message_callback)(struct NX_AZURE_IOT_HUB_CLIENT_STRUCT *hub_client_ptr, VOID *args); - VOID *message_callback_args; - UINT (*message_process)(struct NX_AZURE_IOT_HUB_CLIENT_STRUCT *hub_client_ptr, - NX_PACKET *packet_ptr, ULONG topic_offset, USHORT topic_length); - UINT (*message_enable)(struct NX_AZURE_IOT_HUB_CLIENT_STRUCT *hub_client_ptr); -} NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE; - /** * @brief Azure IoT Hub Client struct * */ typedef struct NX_AZURE_IOT_HUB_CLIENT_STRUCT { - NX_AZURE_IOT *nx_azure_iot_ptr; - - UINT nx_azure_iot_hub_client_state; - NX_AZURE_IOT_THREAD *nx_azure_iot_hub_client_thread_suspended; - NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE nx_azure_iot_hub_client_c2d_message; - NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE nx_azure_iot_hub_client_device_twin_message; - NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE nx_azure_iot_hub_client_device_twin_desired_properties_message; - NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE nx_azure_iot_hub_client_direct_method_message; - VOID (*nx_azure_iot_hub_client_report_properties_response_callback)( - struct NX_AZURE_IOT_HUB_CLIENT_STRUCT *hub_client_ptr, - UINT request_id, UINT response_status, ULONG version, VOID *args); - VOID *nx_azure_iot_hub_client_report_properties_response_callback_args; - - VOID (*nx_azure_iot_hub_client_connection_status_callback)( - struct NX_AZURE_IOT_HUB_CLIENT_STRUCT *hub_client_ptr, - UINT status); - UINT (*nx_azure_iot_hub_client_token_refresh)( - struct NX_AZURE_IOT_HUB_CLIENT_STRUCT *hub_client_ptr, - ULONG expiry_time_secs, const UCHAR *key, UINT key_len, - UCHAR *sas_buffer, UINT sas_buffer_len, UINT *sas_length); - - UINT nx_azure_iot_hub_client_request_id; - const UCHAR *nx_azure_iot_hub_client_symmetric_key; - UINT nx_azure_iot_hub_client_symmetric_key_length; - NX_AZURE_IOT_RESOURCE nx_azure_iot_hub_client_resource; + NX_AZURE_IOT_HUB_TRANSPORT nx_azure_iot_hub_client_transport; - volatile UCHAR nx_azure_iot_hub_client_device_twin_response_subscribe_ack; - UCHAR reserved[3]; + UINT nx_azure_iot_hub_client_request_id; - az_iot_hub_client iot_hub_client_core; - UINT nx_azure_iot_hub_client_throttle_count; - ULONG nx_azure_iot_hub_client_throttle_end_time; + az_iot_hub_client iot_hub_client_core; + UINT nx_azure_iot_hub_client_throttle_count; + ULONG nx_azure_iot_hub_client_throttle_end_time; } NX_AZURE_IOT_HUB_CLIENT; diff --git a/addons/azure_iot/nx_azure_iot_hub_transport.c b/addons/azure_iot/nx_azure_iot_hub_transport.c new file mode 100644 index 00000000..26238971 --- /dev/null +++ b/addons/azure_iot/nx_azure_iot_hub_transport.c @@ -0,0 +1,1439 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/* Version: 6.1 PnP Preview 1 */ + +#include "nx_azure_iot_hub_transport.h" + +#include "azure/core/az_version.h" + + +#define NX_AZURE_IOT_HUB_U32_MAX_BUFFER_SIZE 10 +#define NX_AZURE_IOT_HUB_EMPTY_JSON "{}" +#define NX_AZURE_IOT_HUB_THROTTLE_STATUS_CODE 429 + + +extern UINT _nxd_mqtt_process_publish_packet(NX_PACKET *packet_ptr, ULONG *topic_offset_ptr, + USHORT *topic_length_ptr, ULONG *message_offset_ptr, + ULONG *message_length_ptr); +extern UINT _nxd_mqtt_client_sub_unsub(NXD_MQTT_CLIENT *client_ptr, UINT op, + CHAR *topic_name, UINT topic_name_length, + USHORT *packet_id_ptr, UINT QoS); + +static VOID nx_azure_iot_hub_transport_sub_ack_notify(NXD_MQTT_CLIENT *client_ptr, UINT type, + USHORT packet_id, NX_PACKET *transmit_packet_ptr, VOID *context) +{ +NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr = (NX_AZURE_IOT_HUB_TRANSPORT *)context; +UINT pending_subscribe_ack = hub_transport_ptr -> nx_azure_iot_hub_transport_message_pending_subscribe_ack; + + NX_PARAMETER_NOT_USED(client_ptr); + NX_PARAMETER_NOT_USED(transmit_packet_ptr); + + /* Mointor subscribe ack. */ + if (type == MQTT_CONTROL_PACKET_TYPE_SUBACK) + { + + if (pending_subscribe_ack == 0) + { + return; + } + + /* Compare the topic. */ + for (UINT index = 0; index < NX_AZURE_IOT_HUB_TRANSPORT_MAX_NUM_RECEIVE_QUEUE; index++) + { + if ((pending_subscribe_ack & (UINT)(0x1 << index)) && + (hub_transport_ptr -> nx_azure_iot_hub_transport_message[index].message_sub_packet_id == packet_id)) + { + pending_subscribe_ack &= ~((UINT)(0x1 << index)); + break; + } + } + + hub_transport_ptr -> nx_azure_iot_hub_transport_message_pending_subscribe_ack = pending_subscribe_ack; + } +} + +static UINT nx_azure_iot_hub_transport_message_subscribe(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr, UINT queue_index) +{ +UINT status; + + if ((hub_transport_ptr -> nx_azure_iot_hub_transport_message[queue_index].message_topic_ptr == NX_NULL) || + (hub_transport_ptr -> nx_azure_iot_hub_transport_message[queue_index].message_topic_length == 0)) + { + /* Nothing to subscribe */ + return(NX_AZURE_IOT_SUCCESS); + } + + /* Obtain the mutex. */ + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + hub_transport_ptr -> nx_azure_iot_hub_transport_message_pending_subscribe_ack |= (UINT)(0x1 << queue_index); + hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_mqtt.nxd_mqtt_ack_receive_notify = nx_azure_iot_hub_transport_sub_ack_notify; + hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_mqtt.nxd_mqtt_ack_receive_context = hub_transport_ptr; + + /* Release the mutex. */ + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + status = _nxd_mqtt_client_sub_unsub(&(hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_mqtt), + (MQTT_CONTROL_PACKET_TYPE_SUBSCRIBE << 4) | 0x02, + (CHAR *)hub_transport_ptr -> nx_azure_iot_hub_transport_message[queue_index].message_topic_ptr, + hub_transport_ptr -> nx_azure_iot_hub_transport_message[queue_index].message_topic_length, + &(hub_transport_ptr -> nx_azure_iot_hub_transport_message[queue_index].message_sub_packet_id), + NX_AZURE_IOT_MQTT_QOS_0); + + if (status) + { + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + /* Reset the pending subscribe */ + hub_transport_ptr -> nx_azure_iot_hub_transport_message_pending_subscribe_ack &= ~(UINT)(0x1 << queue_index); + + /* Release the mutex. */ + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + } + + return(status); +} + +static UINT nx_azure_iot_hub_transport_messages_enable(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr) +{ +UINT status = NX_AZURE_IOT_SUCCESS; +UINT index = 0; + + for (index = 0; index < NX_AZURE_IOT_HUB_TRANSPORT_MAX_NUM_RECEIVE_QUEUE; index++) + { + if (hub_transport_ptr -> nx_azure_iot_hub_transport_message[index].message_topic_ptr != NX_NULL) + { + status = nx_azure_iot_hub_transport_message_subscribe(hub_transport_ptr, index); + if (status) + { + LogError(LogLiteralArgs("Failed to enable message type: %d"), index); + LogError(LogLiteralArgs("Enable status: %d"), status); + break; + } + } + } + + return(status); +} + +static VOID nx_azure_iot_hub_transport_mqtt_receive_callback(NXD_MQTT_CLIENT* client_ptr, + UINT number_of_messages) +{ +NX_AZURE_IOT_RESOURCE *resource = nx_azure_iot_resource_search(client_ptr); +NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr = NX_NULL; +NX_PACKET *packet_ptr; +NX_PACKET *packet_next_ptr; +ULONG topic_offset; +USHORT topic_length; +UINT index = 0; + + /* This function is protected by MQTT mutex. */ + + NX_PARAMETER_NOT_USED(number_of_messages); + + if (resource && (resource -> resource_type == NX_AZURE_IOT_RESOURCE_IOT_HUB)) + { + hub_transport_ptr = (NX_AZURE_IOT_HUB_TRANSPORT *)resource -> resource_data_ptr; + } + + if (hub_transport_ptr) + { + for (packet_ptr = client_ptr -> message_receive_queue_head; + packet_ptr; + packet_ptr = packet_next_ptr) + { + + /* Store next packet in case current packet is consumed. */ + packet_next_ptr = packet_ptr -> nx_packet_queue_next; + + /* Adjust packet to simply process logic. */ + nx_azure_iot_mqtt_packet_adjust(packet_ptr); + + if (nx_azure_iot_hub_transport_process_publish_packet(packet_ptr -> nx_packet_prepend_ptr, &topic_offset, + &topic_length)) + { + + /* Message not supported. It will be released. */ + nx_packet_release(packet_ptr); + continue; + } + + if ((topic_offset + topic_length) > + (ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr)) + { + + /* Message with topic spaning multiple packet is not supported. It will be released. */ + LogDebug(LogLiteralArgs("IoTHub packet receive fail as topic span multiple packet")); + nx_packet_release(packet_ptr); + continue; + } + + for (index = 0; index < NX_AZURE_IOT_HUB_TRANSPORT_MAX_NUM_RECEIVE_QUEUE; index++) + { + if ((hub_transport_ptr -> nx_azure_iot_hub_transport_message[index].message_process != NX_NULL) && + (hub_transport_ptr -> nx_azure_iot_hub_transport_message[index].message_process(hub_transport_ptr, + packet_ptr, topic_offset, + topic_length) == NX_AZURE_IOT_SUCCESS)) + { + break; + } + } + + if (index >= NX_AZURE_IOT_HUB_TRANSPORT_MAX_NUM_RECEIVE_QUEUE) + { + /* Message not supported. It will be released. */ + nx_packet_release(packet_ptr); + } + } + + /* Clear all message from MQTT receive queue. */ + client_ptr -> message_receive_queue_head = NX_NULL; + client_ptr -> message_receive_queue_tail = NX_NULL; + client_ptr -> message_receive_queue_depth = 0; + } +} + +static VOID nx_azure_iot_hub_transport_mqtt_connect_notify(struct NXD_MQTT_CLIENT_STRUCT *client_ptr, + UINT status, VOID *context) +{ +NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr = (NX_AZURE_IOT_HUB_TRANSPORT *)context; + + + NX_PARAMETER_NOT_USED(client_ptr); + + /* Obtain the mutex. */ + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + /* Release the mqtt connection resource. */ + if (hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_mqtt_buffer_context) + { + nx_azure_iot_buffer_free(hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_mqtt_buffer_context); + hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_mqtt_buffer_context = NX_NULL; + } + + /* Update hub client status. */ + if (status == NXD_MQTT_SUCCESS) + { + hub_transport_ptr -> nx_azure_iot_hub_transport_state = NX_AZURE_IOT_HUB_TRANSPORT_STATUS_CONNECTED; + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + status = nx_azure_iot_hub_transport_messages_enable(hub_transport_ptr); + + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + if (status) + { + hub_transport_ptr -> nx_azure_iot_hub_transport_state = NX_AZURE_IOT_HUB_TRANSPORT_STATUS_NOT_CONNECTED; + LogError(LogLiteralArgs("IoTHub connect fail: MQTT SUBSCRIBE FAIL status: %d"), status); + } + } + else + { + hub_transport_ptr -> nx_azure_iot_hub_transport_state = NX_AZURE_IOT_HUB_TRANSPORT_STATUS_NOT_CONNECTED; + } + + /* Call connection notify if it is set. */ + if (hub_transport_ptr -> nx_azure_iot_hub_transport_connection_status_callback) + { + hub_transport_ptr -> nx_azure_iot_hub_transport_connection_status_callback(hub_transport_ptr, status, + hub_transport_ptr -> nx_azure_iot_hub_transport_connection_status_callback_arg); + } + + /* Release the mutex. */ + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); +} + +static VOID nx_azure_iot_hub_transport_mqtt_disconnect_notify(NXD_MQTT_CLIENT *client_ptr) +{ +NX_AZURE_IOT_RESOURCE *resource = nx_azure_iot_resource_search(client_ptr); +NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr = NX_NULL; +NX_AZURE_IOT_THREAD *thread_list_ptr; + + /* This function is protected by MQTT mutex. */ + + if (resource && (resource -> resource_type == NX_AZURE_IOT_RESOURCE_IOT_HUB)) + { + hub_transport_ptr = (NX_AZURE_IOT_HUB_TRANSPORT *)resource -> resource_data_ptr; + } + + if (hub_transport_ptr == NX_NULL) + { + return; + } + + /* Wake up all threads. */ + for (thread_list_ptr = hub_transport_ptr -> nx_azure_iot_hub_transport_thread_suspended; + thread_list_ptr; + thread_list_ptr = thread_list_ptr -> thread_next) + { + tx_thread_wait_abort(thread_list_ptr -> thread_ptr); + } + + /* Do not call callback if not connected, as at our layer connected means : mqtt connect + subscribe messages topic. */ + if (hub_transport_ptr -> nx_azure_iot_hub_transport_state == NX_AZURE_IOT_HUB_TRANSPORT_STATUS_CONNECTED) + { + hub_transport_ptr -> nx_azure_iot_hub_transport_state = NX_AZURE_IOT_HUB_TRANSPORT_STATUS_NOT_CONNECTED; + + /* Call connection notify if it is set. */ + if (hub_transport_ptr -> nx_azure_iot_hub_transport_connection_status_callback) + { + hub_transport_ptr -> nx_azure_iot_hub_transport_connection_status_callback(hub_transport_ptr, + NX_AZURE_IOT_DISCONNECTED, + hub_transport_ptr -> nx_azure_iot_hub_transport_connection_status_callback_arg); + } + } +} + +static UINT nx_azure_iot_hub_transport_sas_token_get(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr, + ULONG expiry_time_secs, const UCHAR *key, UINT key_len, + UCHAR *sas_buffer, UINT sas_buffer_len, UINT *sas_length) +{ +UCHAR *buffer_ptr; +UINT buffer_size; +VOID *buffer_context; +UINT bytes_used; +UINT status; +UCHAR *output_ptr; +UINT output_len; +az_span span; +az_result core_result; + + status = nx_azure_iot_buffer_allocate(hub_transport_ptr -> nx_azure_iot_ptr, &buffer_ptr, &buffer_size, &buffer_context); + if (status) + { + LogError(LogLiteralArgs("IoTHub sas token fail: BUFFER ALLOCATE FAIL")); + return(status); + } + + span = az_span_create(sas_buffer, (INT)sas_buffer_len); + core_result = hub_transport_ptr -> nx_azure_iot_hub_transport_sas_signature(hub_transport_ptr, + expiry_time_secs, span, &span); + if (az_result_failed(core_result)) + { + LogError(LogLiteralArgs("IoTHub failed failed to get signature with error status: %d"), status); + nx_azure_iot_buffer_free(buffer_context); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + bytes_used = (UINT)az_span_size(span); + status = nx_azure_iot_base64_hmac_sha256_calculate(&(hub_transport_ptr -> nx_azure_iot_hub_transport_resource), + key, key_len, sas_buffer, bytes_used, + buffer_ptr, buffer_size, &output_ptr, &output_len); + if (status) + { + LogError(LogLiteralArgs("IoTHub failed to encoded hash")); + nx_azure_iot_buffer_free(buffer_context); + return(status); + } + + span = az_span_create(output_ptr, (INT)output_len); + core_result = hub_transport_ptr -> nx_azure_iot_hub_transport_sas_password(hub_transport_ptr, + expiry_time_secs, span, + AZ_SPAN_EMPTY, + sas_buffer, sas_buffer_len, + &bytes_used); + if (az_result_failed(core_result)) + { + LogError(LogLiteralArgs("IoTHub failed to generate token with error status: %d"), core_result); + nx_azure_iot_buffer_free(buffer_context); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + *sas_length = bytes_used; + nx_azure_iot_buffer_free(buffer_context); + + return(NX_AZURE_IOT_SUCCESS); +} + +static VOID nx_azure_iot_hub_transport_thread_dequeue(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr, + NX_AZURE_IOT_THREAD *thread_list_ptr) +{ +NX_AZURE_IOT_THREAD *thread_list_prev = NX_NULL; +NX_AZURE_IOT_THREAD *thread_list_current; + + for (thread_list_current = hub_transport_ptr -> nx_azure_iot_hub_transport_thread_suspended; + thread_list_current; + thread_list_current = thread_list_current -> thread_next) + { + if (thread_list_current == thread_list_ptr) + { + + /* Found the thread to dequeue. */ + if (thread_list_prev == NX_NULL) + { + hub_transport_ptr -> nx_azure_iot_hub_transport_thread_suspended = thread_list_current -> thread_next; + } + else + { + thread_list_prev -> thread_next = thread_list_current -> thread_next; + } + break; + } + + thread_list_prev = thread_list_current; + } +} + +static UINT nx_azure_iot_hub_transport_message_receive_internal(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr, + UINT message_queue_index, UINT expected_id, + NX_AZURE_IOT_HUB_TRANSPORT_RECEIVE_MESSAGE *receive_message, + NX_PACKET **packet_pptr, UINT wait_option) +{ +NX_PACKET *packet_ptr = NX_NULL; +UINT old_threshold; +NX_AZURE_IOT_THREAD thread_list; + + /* Obtain the mutex. */ + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + if (receive_message -> message_head) + { + packet_ptr = receive_message -> message_head; + if (receive_message -> message_tail == packet_ptr) + { + receive_message -> message_tail = NX_NULL; + } + + receive_message -> message_head = packet_ptr -> nx_packet_queue_next; + packet_ptr -> nx_packet_queue_next = NX_NULL; + } + else if (wait_option) + { + thread_list.thread_message_type = message_queue_index; + thread_list.thread_ptr = tx_thread_identify(); + thread_list.thread_received_message = NX_NULL; + thread_list.thread_expected_id = expected_id; + thread_list.thread_next = hub_transport_ptr -> nx_azure_iot_hub_transport_thread_suspended; + hub_transport_ptr -> nx_azure_iot_hub_transport_thread_suspended = &thread_list; + + /* Disable preemption. */ + tx_thread_preemption_change(tx_thread_identify(), 0, &old_threshold); + + /* Release the mutex. */ + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + tx_thread_sleep(wait_option); + + /* Obtain the mutex. */ + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + nx_azure_iot_hub_transport_thread_dequeue(hub_transport_ptr, &thread_list); + + /* Restore preemption. */ + tx_thread_preemption_change(tx_thread_identify(), old_threshold, &old_threshold); + packet_ptr = thread_list.thread_received_message; + } + + /* Release the mutex. */ + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + if (packet_ptr == NX_NULL) + { + if (hub_transport_ptr -> nx_azure_iot_hub_transport_state != NX_AZURE_IOT_HUB_TRANSPORT_STATUS_CONNECTED) + { + LogError(LogLiteralArgs("IoTHub transport message receive fail: IoTHub client not connected")); + return(NX_AZURE_IOT_DISCONNECTED); + } + + return(NX_AZURE_IOT_NO_PACKET); + } + + *packet_pptr = packet_ptr; + + return(NX_AZURE_IOT_SUCCESS); +} + +static VOID nx_azure_iot_hub_transport_received_message_cleanup(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr) +{ +NX_PACKET *current_ptr; +NX_PACKET *next_ptr; +NX_AZURE_IOT_HUB_TRANSPORT_RECEIVE_MESSAGE *message_queue_ptr; + + for (UINT index = 0; index < NX_AZURE_IOT_HUB_TRANSPORT_MAX_NUM_RECEIVE_QUEUE; index++) + { + message_queue_ptr = &(hub_transport_ptr -> nx_azure_iot_hub_transport_message[index]); + for (current_ptr = message_queue_ptr -> message_head; current_ptr; current_ptr = next_ptr) + { + + /* Get next packet in queue. */ + next_ptr = current_ptr -> nx_packet_queue_next; + + /* Release current packet. */ + current_ptr -> nx_packet_queue_next = NX_NULL; + nx_packet_release(current_ptr); + } + + /* Reset received messages. */ + message_queue_ptr -> message_head = NX_NULL; + message_queue_ptr -> message_tail = NX_NULL; + } + +} + +UINT nx_azure_iot_hub_transport_initialize(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr, + NX_AZURE_IOT *nx_azure_iot_ptr, + const UCHAR *host_name, UINT host_name_length, + const NX_AZURE_IOT_HUB_TRANSPORT_CLIENT_ID_GET_FN client_id_get, + const NX_AZURE_IOT_HUB_TRANSPORT_USERNAME_GET_FN username_get, + const NX_CRYPTO_METHOD **crypto_array, UINT crypto_array_size, + const NX_CRYPTO_CIPHERSUITE **cipher_map, UINT cipher_map_size, + UCHAR *metadata_memory, UINT memory_size, + NX_SECURE_X509_CERT *trusted_certificate, + VOID *client_context) +{ +UINT status; +NX_AZURE_IOT_RESOURCE *resource_ptr; + + if ((nx_azure_iot_ptr == NX_NULL) || (hub_transport_ptr == NX_NULL) || (host_name == NX_NULL)) + { + LogError(LogLiteralArgs("IoTHub initialization fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + memset(hub_transport_ptr, 0, sizeof(NX_AZURE_IOT_HUB_TRANSPORT)); + + hub_transport_ptr -> nx_azure_iot_ptr = nx_azure_iot_ptr; + hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_crypto_array = crypto_array; + hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_crypto_array_size = crypto_array_size; + hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_cipher_map = cipher_map; + hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_cipher_map_size = cipher_map_size; + hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_metadata_ptr = metadata_memory; + hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_metadata_size = memory_size; + hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_trusted_certificate = trusted_certificate; + hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_hostname = host_name; + hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_hostname_length = host_name_length; + hub_transport_ptr -> nx_azure_iot_hub_transport_client_context = client_context; + hub_transport_ptr -> nx_azure_iot_hub_transport_client_id_get = client_id_get; + hub_transport_ptr -> nx_azure_iot_hub_transport_username_get = username_get; + + /* Set resource pointer. */ + resource_ptr = &(hub_transport_ptr -> nx_azure_iot_hub_transport_resource); + + /* Create MQTT client. */ + status = _nxd_mqtt_client_cloud_create(&(resource_ptr -> resource_mqtt), + (CHAR *)nx_azure_iot_ptr -> nx_azure_iot_name, + "", 0, + nx_azure_iot_ptr -> nx_azure_iot_ip_ptr, + nx_azure_iot_ptr -> nx_azure_iot_pool_ptr, + &nx_azure_iot_ptr -> nx_azure_iot_cloud); + if (status) + { + LogError(LogLiteralArgs("IoTHub initialization fail: MQTT CLIENT CREATE FAIL status: %d"), status); + return(status); + } + + /* Set mqtt receive notify. */ + status = nxd_mqtt_client_receive_notify_set(&(resource_ptr -> resource_mqtt), + nx_azure_iot_hub_transport_mqtt_receive_callback); + if (status) + { + LogError(LogLiteralArgs("IoTHub set message callback status: %d"), status); + nxd_mqtt_client_delete(&(resource_ptr -> resource_mqtt)); + return(status); + } + + /* Obtain the mutex. */ + tx_mutex_get(nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + /* Link the resource. */ + resource_ptr -> resource_data_ptr = (VOID *)hub_transport_ptr; + resource_ptr -> resource_type = NX_AZURE_IOT_RESOURCE_IOT_HUB; + nx_azure_iot_resource_add(nx_azure_iot_ptr, resource_ptr); + + /* Release the mutex. */ + tx_mutex_put(nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_hub_transport_deinitialize(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr) +{ +UINT status; + + /* Check for invalid input pointers. */ + if ((hub_transport_ptr == NX_NULL) || (hub_transport_ptr -> nx_azure_iot_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoTHub deinitialize fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + nx_azure_iot_hub_transport_disconnect(hub_transport_ptr); + + status = nxd_mqtt_client_delete(&(hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_mqtt)); + if (status) + { + LogError(LogLiteralArgs("IoTHub client delete fail status: %d"), status); + return(status); + } + + /* Obtain the mutex. */ + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + /* Remove resource from list. */ + status = nx_azure_iot_resource_remove(hub_transport_ptr -> nx_azure_iot_ptr, + &(hub_transport_ptr -> nx_azure_iot_hub_transport_resource)); + if (status) + { + + /* Release the mutex. */ + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + LogError(LogLiteralArgs("IoTHub client handle not found")); + return(status); + } + + /* Release the mutex. */ + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_hub_transport_device_cert_set(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr, + NX_SECURE_X509_CERT *device_certificate) +{ + if ((hub_transport_ptr == NX_NULL) || + (hub_transport_ptr -> nx_azure_iot_ptr == NX_NULL) || + (device_certificate == NX_NULL)) + { + LogError(LogLiteralArgs("IoTHub device certificate set fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Obtain the mutex. */ + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_device_certificate = device_certificate; + + /* Release the mutex. */ + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_hub_transport_symmetric_key_auth_set(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr, + const NX_AZURE_IOT_HUB_TRANSPORT_SIGNATURE_GET_FN sas_signature_get, + const NX_AZURE_IOT_HUB_TRANSPORT_PASSWORD_GET_FN sas_password_get, + const UCHAR *symmetric_key, UINT symmetric_key_length) +{ + if ((hub_transport_ptr == NX_NULL) || (hub_transport_ptr -> nx_azure_iot_ptr == NX_NULL) || + (symmetric_key == NX_NULL) || (symmetric_key_length == 0)) + { + LogError(LogLiteralArgs("IoTHub symmetric key fail: Invalid argument")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Obtain the mutex. */ + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + hub_transport_ptr -> nx_azure_iot_hub_transport_symmetric_key = symmetric_key; + hub_transport_ptr -> nx_azure_iot_hub_transport_symmetric_key_length = symmetric_key_length; + hub_transport_ptr -> nx_azure_iot_hub_transport_sas_signature = sas_signature_get; + hub_transport_ptr -> nx_azure_iot_hub_transport_sas_password = sas_password_get; + hub_transport_ptr -> nx_azure_iot_hub_transport_token_refresh = nx_azure_iot_hub_transport_sas_token_get; + + /* Release the mutex. */ + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_hub_transport_connection_callback_set(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr, + NX_AZURE_IOT_HUB_TRANSPORT_CONNECTION_STATUS_CB connection_cb, + NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN arg) +{ + if ((hub_transport_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoTHub set connection cb fail: Invalid argument")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Set callback function for disconnection. */ + nxd_mqtt_client_disconnect_notify_set(&(hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_mqtt), + nx_azure_iot_hub_transport_mqtt_disconnect_notify); + + /* Obtain the mutex. */ + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + hub_transport_ptr -> nx_azure_iot_hub_transport_connection_status_callback = connection_cb; + hub_transport_ptr -> nx_azure_iot_hub_transport_connection_status_callback_arg = arg; + + /* Release the mutex. */ + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_hub_transport_connect(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr, + UINT clean_session, UINT wait_option) +{ +UINT status; +NXD_ADDRESS server_address; +NX_AZURE_IOT_RESOURCE *resource_ptr; +NXD_MQTT_CLIENT *mqtt_client_ptr; +UCHAR *buffer_ptr; +UINT buffer_size; +VOID *buffer_context; +UINT buffer_length; +ULONG expiry_time_secs; +az_result core_result; + + /* Check for invalid input pointers. */ + if ((hub_transport_ptr == NX_NULL) || (hub_transport_ptr -> nx_azure_iot_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoTHub connect fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Check for status. */ + if (hub_transport_ptr -> nx_azure_iot_hub_transport_state == NX_AZURE_IOT_HUB_TRANSPORT_STATUS_CONNECTED) + { + LogError(LogLiteralArgs("IoTHub already connected")); + return(NX_AZURE_IOT_ALREADY_CONNECTED); + } + else if (hub_transport_ptr -> nx_azure_iot_hub_transport_state == NX_AZURE_IOT_HUB_TRANSPORT_STATUS_CONNECTING) + { + LogError(LogLiteralArgs("IoTHub is connecting")); + return(NX_AZURE_IOT_CONNECTING); + } + + /* Resolve the host name. */ + /* Note: always using default dns timeout. */ + status = nxd_dns_host_by_name_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_dns_ptr, + (UCHAR *)hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_hostname, + &server_address, NX_AZURE_IOT_HUB_TRANSPORT_DNS_TIMEOUT, NX_IP_VERSION_V4); + if (status) + { + LogError(LogLiteralArgs("IoTHub connect fail: DNS RESOLVE FAIL status: %d"), status); + return(status); + } + + /* Allocate buffer for client id, username and sas token. */ + status = nx_azure_iot_buffer_allocate(hub_transport_ptr -> nx_azure_iot_ptr, + &buffer_ptr, &buffer_size, &buffer_context); + if (status) + { + LogError(LogLiteralArgs("IoTHub failed initialization: BUFFER ALLOCATE FAIL")); + return(status); + } + + /* Obtain the mutex. */ + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + /* Set resource pointer and buffer context. */ + resource_ptr = &(hub_transport_ptr -> nx_azure_iot_hub_transport_resource); + + /* Build client id. */ + buffer_length = buffer_size; + core_result = hub_transport_ptr -> nx_azure_iot_hub_transport_client_id_get(hub_transport_ptr, + buffer_ptr, buffer_length, + &buffer_length); + if (az_result_failed(core_result)) + { + /* Release the mutex. */ + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + nx_azure_iot_buffer_free(buffer_context); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + resource_ptr -> resource_mqtt_client_id = buffer_ptr; + resource_ptr -> resource_mqtt_client_id_length = buffer_length; + + /* Update buffer for user name. */ + buffer_ptr += resource_ptr -> resource_mqtt_client_id_length; + buffer_size -= resource_ptr -> resource_mqtt_client_id_length; + + /* Build user name. */ + buffer_length = buffer_size; + core_result = hub_transport_ptr -> nx_azure_iot_hub_transport_username_get(hub_transport_ptr, + buffer_ptr, buffer_length, + &buffer_length); + if (az_result_failed(core_result)) + { + + /* Release the mutex. */ + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + nx_azure_iot_buffer_free(buffer_context); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + resource_ptr -> resource_mqtt_user_name = buffer_ptr; + resource_ptr -> resource_mqtt_user_name_length = buffer_length; + + /* Build sas token. */ + resource_ptr -> resource_mqtt_sas_token = buffer_ptr + buffer_length; + resource_ptr -> resource_mqtt_sas_token_length = buffer_size - buffer_length; + + /* Check if token refersh is setup. */ + if (hub_transport_ptr -> nx_azure_iot_hub_transport_token_refresh) + { + status = nx_azure_iot_unix_time_get(hub_transport_ptr -> nx_azure_iot_ptr, &expiry_time_secs); + if (status) + { + + /* Release the mutex. */ + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + nx_azure_iot_buffer_free(buffer_context); + LogError(LogLiteralArgs("IoTHub connect fail: unixtime get failed status: %d"), status); + return(status); + } + + expiry_time_secs += NX_AZURE_IOT_HUB_TRANSPORT_TOKEN_EXPIRY; + if ((status = hub_transport_ptr -> nx_azure_iot_hub_transport_token_refresh(hub_transport_ptr, + expiry_time_secs, + hub_transport_ptr -> nx_azure_iot_hub_transport_symmetric_key, + hub_transport_ptr -> nx_azure_iot_hub_transport_symmetric_key_length, + resource_ptr -> resource_mqtt_sas_token, + resource_ptr -> resource_mqtt_sas_token_length, + &(resource_ptr -> resource_mqtt_sas_token_length)))) + { + + /* Release the mutex. */ + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + nx_azure_iot_buffer_free(buffer_context); + LogError(LogLiteralArgs("IoTHub connect fail: Token generation failed status: %d"), status); + return(status); + } + } + else + { + resource_ptr -> resource_mqtt_sas_token_length = 0; + } + + mqtt_client_ptr = &(hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_mqtt); + + /* Update client id. */ + mqtt_client_ptr -> nxd_mqtt_client_id = (CHAR *)resource_ptr -> resource_mqtt_client_id; + mqtt_client_ptr -> nxd_mqtt_client_id_length = resource_ptr -> resource_mqtt_client_id_length; + + /* Set login info. */ + status = nxd_mqtt_client_login_set(&(resource_ptr -> resource_mqtt), + (CHAR *)resource_ptr -> resource_mqtt_user_name, + resource_ptr -> resource_mqtt_user_name_length, + (CHAR *)resource_ptr -> resource_mqtt_sas_token, + resource_ptr -> resource_mqtt_sas_token_length); + if (status) + { + + /* Release the mutex. */ + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + nx_azure_iot_buffer_free(buffer_context); + LogError(LogLiteralArgs("IoTHub connect fail: MQTT CLIENT LOGIN SET FAIL status: %d"), status); + return(status); + } + + /* Set connect notify for non-blocking mode. */ + if (wait_option == 0) + { + mqtt_client_ptr -> nxd_mqtt_connect_notify = nx_azure_iot_hub_transport_mqtt_connect_notify; + mqtt_client_ptr -> nxd_mqtt_connect_context = hub_transport_ptr; + } + + /* Save the resource buffer. */ + resource_ptr -> resource_mqtt_buffer_context = buffer_context; + resource_ptr -> resource_mqtt_buffer_size = buffer_size; + + /* Release the mutex. */ + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + /* Start MQTT connection. */ + status = nxd_mqtt_client_secure_connect(mqtt_client_ptr, &server_address, NXD_MQTT_TLS_PORT, + nx_azure_iot_mqtt_tls_setup, NX_AZURE_IOT_MQTT_KEEP_ALIVE, + clean_session, wait_option); + + /* Check status for non-blocking mode. */ + if ((wait_option == 0) && (status == NX_IN_PROGRESS)) + { + + /* Obtain the mutex. */ + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + hub_transport_ptr -> nx_azure_iot_hub_transport_state = NX_AZURE_IOT_HUB_TRANSPORT_STATUS_CONNECTING; + + /* Release the mutex. */ + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + /* Return in-progress completion status. */ + return(NX_AZURE_IOT_CONNECTING); + } + + /* Call notify in synchronous way */ + nx_azure_iot_hub_transport_mqtt_connect_notify(mqtt_client_ptr, status, (VOID *)hub_transport_ptr); + + return(status); +} + +UINT nx_azure_iot_hub_transport_disconnect(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr) +{ +UINT status; +NX_AZURE_IOT_THREAD *thread_list_ptr; + + /* Check for invalid input pointers. */ + if ((hub_transport_ptr == NX_NULL) || (hub_transport_ptr -> nx_azure_iot_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoTHub client disconnect fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Disconnect. */ + status = nxd_mqtt_client_disconnect(&(hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_mqtt)); + if (status) + { + LogError(LogLiteralArgs("IoTHub disconnect fail status: %d"), status); + } + + /* Obtain the mutex. */ + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + /* Release the mqtt connection resource. */ + if (hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_mqtt_buffer_context) + { + nx_azure_iot_buffer_free(hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_mqtt_buffer_context); + hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_mqtt_buffer_context = NX_NULL; + } + + /* Wakeup all suspend threads. */ + for (thread_list_ptr = hub_transport_ptr -> nx_azure_iot_hub_transport_thread_suspended; + thread_list_ptr; + thread_list_ptr = thread_list_ptr -> thread_next) + { + tx_thread_wait_abort(thread_list_ptr -> thread_ptr); + } + + hub_transport_ptr -> nx_azure_iot_hub_transport_state = NX_AZURE_IOT_HUB_TRANSPORT_STATUS_NOT_CONNECTED; + + /* cleanup all the queues */ + nx_azure_iot_hub_transport_received_message_cleanup(hub_transport_ptr); + + /* Release the mutex. */ + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + return(status); +} + +UINT nx_azure_iot_hub_transport_receive_message_enable(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr, UINT message_queue_index, + const UCHAR *message_topic_ptr, UINT message_topic_length, + NX_AZURE_IOT_HUB_TRANSPORT_MESSAGE_PROCESS_FN message_process) +{ +UINT status; + + if ((hub_transport_ptr == NX_NULL) || + (message_queue_index >= NX_AZURE_IOT_HUB_TRANSPORT_MAX_NUM_RECEIVE_QUEUE)) + { + LogError(LogLiteralArgs("IoTHub transport receive message process fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + hub_transport_ptr -> nx_azure_iot_hub_transport_message[message_queue_index].message_topic_ptr = message_topic_ptr; + hub_transport_ptr -> nx_azure_iot_hub_transport_message[message_queue_index].message_topic_length = message_topic_length; + hub_transport_ptr -> nx_azure_iot_hub_transport_message[message_queue_index].message_process = message_process; + hub_transport_ptr -> nx_azure_iot_hub_transport_message[message_queue_index].message_control_flag |= NZ_AZURE_IOT_HUB_TRANSPORT_MESSAGE_ENABLE; + + /* Register callbacks even if not connect and when connect complete subscribe for topics. */ + if (hub_transport_ptr -> nx_azure_iot_hub_transport_state != NX_AZURE_IOT_HUB_TRANSPORT_STATUS_CONNECTED) + { + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + return(NX_AZURE_IOT_SUCCESS); + } + + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + status = nx_azure_iot_hub_transport_message_subscribe(hub_transport_ptr, message_queue_index); + if (status) + { + LogError(LogLiteralArgs("IoTHub transport receive subscribe fail: %d"), status); + return(status); + } + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_hub_transport_receive_message_disable(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr, + UINT message_queue_index) +{ +UINT status; + + if ((hub_transport_ptr == NX_NULL) || + (message_queue_index >= NX_AZURE_IOT_HUB_TRANSPORT_MAX_NUM_RECEIVE_QUEUE)) + { + LogError(LogLiteralArgs("IoTHub transport receive message process fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + if (hub_transport_ptr -> nx_azure_iot_hub_transport_message[message_queue_index].message_topic_ptr == NX_NULL) + { + return(NX_AZURE_IOT_SUCCESS); + } + + status = nxd_mqtt_client_unsubscribe(&(hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_mqtt), + (CHAR *)hub_transport_ptr -> nx_azure_iot_hub_transport_message[message_queue_index].message_topic_ptr, + hub_transport_ptr -> nx_azure_iot_hub_transport_message[message_queue_index].message_topic_length); + if (status) + { + LogError(LogLiteralArgs("IoTHub transport receive topic unsubscribe fail status: %d"), status); + return(status); + } + + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + hub_transport_ptr -> nx_azure_iot_hub_transport_message[message_queue_index].message_sub_packet_id = 0; + hub_transport_ptr -> nx_azure_iot_hub_transport_message_pending_subscribe_ack &= ~(UINT)(0x1 << message_queue_index); + hub_transport_ptr -> nx_azure_iot_hub_transport_message[message_queue_index].message_topic_ptr = NX_NULL; + hub_transport_ptr -> nx_azure_iot_hub_transport_message[message_queue_index].message_topic_length = 0; + hub_transport_ptr -> nx_azure_iot_hub_transport_message[message_queue_index].message_process = NX_NULL; + hub_transport_ptr -> nx_azure_iot_hub_transport_message[message_queue_index].message_control_flag &= (USHORT)(~NZ_AZURE_IOT_HUB_TRANSPORT_MESSAGE_ENABLE); + + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_hub_transport_receive_message_callback_set(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr, UINT message_queue_index, + NX_AZURE_IOT_HUB_TRANSPORT_MESSAGE_CB_FN message_callback, + NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN arg1, VOID *arg2) +{ + if ((hub_transport_ptr == NX_NULL) || + (message_queue_index >= NX_AZURE_IOT_HUB_TRANSPORT_MAX_NUM_RECEIVE_QUEUE) || + (hub_transport_ptr -> nx_azure_iot_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoTHub transport receive message set callback fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + hub_transport_ptr -> nx_azure_iot_hub_transport_message[message_queue_index].message_callback = message_callback; + hub_transport_ptr -> nx_azure_iot_hub_transport_message[message_queue_index].message_callback_arg1 = arg1; + hub_transport_ptr -> nx_azure_iot_hub_transport_message[message_queue_index].message_callback_arg2 = arg2; + + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_hub_transport_receive_message_is_subscribed(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr, + UINT message_queue_index, UINT wait_option) +{ + if ((hub_transport_ptr == NX_NULL) || + (message_queue_index >= NX_AZURE_IOT_HUB_TRANSPORT_MAX_NUM_RECEIVE_QUEUE)) + { + LogError(LogLiteralArgs("IoTHub transport receive message is subscribed fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Wait for subscribe ack. */ + while (1) + { + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + if (!(hub_transport_ptr -> nx_azure_iot_hub_transport_message[message_queue_index].message_control_flag & + NZ_AZURE_IOT_HUB_TRANSPORT_MESSAGE_ENABLE)) + { + LogError(LogLiteralArgs("IoTHub transport receive message is subscribed fail: not enabled")); + return(NX_AZURE_IOT_NOT_ENABLED); + } + + /* Check if it is still in connected status. */ + if (hub_transport_ptr -> nx_azure_iot_hub_transport_state != NX_AZURE_IOT_HUB_TRANSPORT_STATUS_CONNECTED) + { + + /* Clean ack receive notify. */ + hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_mqtt.nxd_mqtt_ack_receive_notify = NX_NULL; + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + return(NX_AZURE_IOT_DISCONNECTED); + } + + if (hub_transport_ptr -> nx_azure_iot_hub_transport_message_pending_subscribe_ack == 0) + { + /* Clean ack receive notify. */ + hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_mqtt.nxd_mqtt_ack_receive_notify = NX_NULL; + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + break; + } + + /* Check if receive the subscribe ack. */ + if ((hub_transport_ptr -> nx_azure_iot_hub_transport_message_pending_subscribe_ack & (UINT)(0x1 << message_queue_index)) == 0) + { + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + break; + } + + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + /* Update wait time. */ + if (wait_option != NX_WAIT_FOREVER) + { + if (wait_option > 0) + { + wait_option--; + } + else + { + return(NX_AZURE_IOT_NO_SUBSCRIBE_ACK); + } + } + + tx_thread_sleep(1); + } + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_hub_transport_message_receive(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr, + UINT message_queue_index, UINT expected_id, + NX_PACKET **packet_pptr, UINT wait_option) +{ +UINT status; + + if ((hub_transport_ptr == NX_NULL) || + (packet_pptr == NX_NULL) || + (message_queue_index >= NX_AZURE_IOT_HUB_TRANSPORT_MAX_NUM_RECEIVE_QUEUE)) + { + LogError(LogLiteralArgs("IoTHub transport argument: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + if ((hub_transport_ptr -> nx_azure_iot_hub_transport_message[message_queue_index].message_control_flag & + NZ_AZURE_IOT_HUB_TRANSPORT_MESSAGE_ENABLE)) + { + status = nx_azure_iot_hub_transport_message_receive_internal(hub_transport_ptr, message_queue_index, expected_id, + &(hub_transport_ptr -> nx_azure_iot_hub_transport_message[message_queue_index]), + packet_pptr, wait_option); + } + else + { + LogError(LogLiteralArgs("IoTHub transport receive queue not enabled for message_queue_index : %d"), message_queue_index); + status = NX_AZURE_IOT_NOT_ENABLED; + } + + return(status); +} + +UINT nx_azure_iot_hub_transport_receive_notify(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr, + NX_PACKET *packet_ptr, UINT message_queue_index, + UINT correlation_id) +{ +NX_AZURE_IOT_THREAD *thread_list_prev = NX_NULL; +NX_AZURE_IOT_THREAD *thread_list_ptr; +NX_AZURE_IOT_HUB_TRANSPORT_RECEIVE_MESSAGE *receive_message = NX_NULL; + + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + /* Search thread waiting for message type. */ + for (thread_list_ptr = hub_transport_ptr -> nx_azure_iot_hub_transport_thread_suspended; + thread_list_ptr; + thread_list_ptr = thread_list_ptr -> thread_next) + { + + /* Each queue point to messages of particular type */ + if ((thread_list_ptr -> thread_message_type == message_queue_index) && + (correlation_id == thread_list_ptr -> thread_expected_id)) + { + + /* Found a thread waiting for message type. */ + if (thread_list_prev == NX_NULL) + { + hub_transport_ptr -> nx_azure_iot_hub_transport_thread_suspended = thread_list_ptr -> thread_next; + } + else + { + thread_list_prev -> thread_next = thread_list_ptr -> thread_next; + } + + thread_list_ptr -> thread_received_message = packet_ptr; + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + tx_thread_wait_abort(thread_list_ptr -> thread_ptr); + + return(NX_AZURE_IOT_SUCCESS); + } + + thread_list_prev = thread_list_ptr; + } + + /* Check if queue exist for this message type and then notify using callback if present */ + if (message_queue_index < NX_AZURE_IOT_HUB_TRANSPORT_MAX_NUM_RECEIVE_QUEUE) + { + receive_message = &(hub_transport_ptr -> nx_azure_iot_hub_transport_message[message_queue_index]); + + if (receive_message -> message_tail) + { + receive_message -> message_tail -> nx_packet_queue_next = packet_ptr; + } + else + { + receive_message -> message_head = packet_ptr; + } + receive_message -> message_tail = packet_ptr; + + /* Check for user callback function. */ + if (receive_message -> message_callback) + { + receive_message -> message_callback(hub_transport_ptr, + receive_message -> message_callback_arg1, + receive_message -> message_callback_arg2); + } + + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + return(NX_AZURE_IOT_SUCCESS); + } + + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + return(NX_AZURE_IOT_NOT_FOUND); +} + +UINT nx_azure_iot_hub_transport_request_response(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr, + UINT request_id, NX_PACKET *packet_ptr, ULONG topic_length, + const UCHAR *message_buffer, UINT message_length, UINT response_queue_index, + NX_PACKET **response_packet_pptr, UINT wait_option) +{ +NX_AZURE_IOT_THREAD thread_list; +UINT status; + + if ((hub_transport_ptr == NX_NULL) || + (response_queue_index >= NX_AZURE_IOT_HUB_TRANSPORT_MAX_NUM_RECEIVE_QUEUE)) + { + LogError(LogLiteralArgs("IoTHub transport request response argument: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + if (!(hub_transport_ptr -> nx_azure_iot_hub_transport_message[response_queue_index].message_control_flag & + NZ_AZURE_IOT_HUB_TRANSPORT_MESSAGE_ENABLE)) + { + LogError(LogLiteralArgs("IoTHub transport receive queue not enabled for response_queue_index : %d"), response_queue_index); + return(NX_AZURE_IOT_NOT_ENABLED); + } + + if ((message_buffer != NX_NULL) && (message_length != 0)) + { + + /* Append payload. */ + status = nx_packet_data_append(packet_ptr, (VOID *)message_buffer, message_length, + packet_ptr -> nx_packet_pool_owner, + wait_option); + if (status) + { + LogError(LogLiteralArgs("IoTHub client reported state send fail: append failed")); + return(status); + } + } + + + /* Obtain the mutex. */ + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + thread_list.thread_message_type = response_queue_index; + thread_list.thread_ptr = tx_thread_identify(); + thread_list.thread_expected_id = request_id; + thread_list.thread_received_message = NX_NULL; + thread_list.thread_next = hub_transport_ptr -> nx_azure_iot_hub_transport_thread_suspended; + hub_transport_ptr -> nx_azure_iot_hub_transport_thread_suspended = &thread_list; + + /* Release the mutex. */ + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + status = nx_azure_iot_publish_mqtt_packet(&(hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_mqtt), + packet_ptr, topic_length, NX_NULL, NX_AZURE_IOT_MQTT_QOS_0, + wait_option); + + if (status) + { + /* remove thread from waiting suspend queue. */ + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + nx_azure_iot_hub_transport_thread_dequeue(hub_transport_ptr, &thread_list); + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + LogError(LogLiteralArgs("IoTHub transport send: PUBLISH FAIL status: %d"), status); + return(status); + } + + if ((thread_list.thread_received_message) == NX_NULL && wait_option) + { + tx_thread_sleep(wait_option); + } + + /* Obtain the mutex. */ + tx_mutex_get(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + nx_azure_iot_hub_transport_thread_dequeue(hub_transport_ptr, &thread_list); + *response_packet_pptr = thread_list.thread_received_message; + + /* Release the mutex. */ + tx_mutex_put(hub_transport_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_hub_transport_publish(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr, NX_PACKET *packet_ptr, + const UCHAR *data, UINT data_size, UINT qos, UINT wait_option) +{ +UINT status; +UINT topic_len; +UCHAR packet_id[2]; + + if ((hub_transport_ptr == NX_NULL) || (packet_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoTHub transport publish fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + topic_len = packet_ptr -> nx_packet_length; + + if (qos != 0) + { + status = nx_azure_iot_mqtt_packet_id_get(&(hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_mqtt), + packet_id, wait_option); + + if (status) + { + LogError(LogLiteralArgs("Failed to get packet id")); + return(status); + } + + /* Append packet identifier. */ + status = nx_packet_data_append(packet_ptr, packet_id, sizeof(packet_id), + packet_ptr -> nx_packet_pool_owner, + wait_option); + if (status) + { + LogError(LogLiteralArgs("packet id append fail")); + return(status); + } + } + + if (data && (data_size != 0)) + { + + /* Append payload. */ + status = nx_packet_data_append(packet_ptr, (VOID *)data, data_size, + packet_ptr -> nx_packet_pool_owner, + wait_option); + if (status) + { + LogError(LogLiteralArgs("data append fail")); + return(status); + } + } + + status = nx_azure_iot_publish_mqtt_packet(&(hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_mqtt), + packet_ptr, topic_len, packet_id, qos, wait_option); + if (status) + { + LogError(LogLiteralArgs("IoTHub transport send fail: PUBLISH FAIL status: %d"), status); + return(status); + } + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_hub_transport_process_publish_packet(UCHAR *start_ptr, ULONG *topic_offset_ptr, + USHORT *topic_length_ptr) +{ +UCHAR *byte = start_ptr; +UINT byte_count = 0; +UINT multiplier = 1; +UINT remaining_length = 0; +UINT topic_length; + + /* Validate packet start contains fixed header. */ + do + { + if (byte_count >= 4) + { + LogError(LogLiteralArgs("Invalid mqtt packet start position")); + return(NX_AZURE_IOT_INVALID_PACKET); + } + + byte++; + remaining_length += (((*byte) & 0x7F) * multiplier); + multiplier = multiplier << 7; + byte_count++; + } while ((*byte) & 0x80); + + if (remaining_length < 2) + { + return(NX_AZURE_IOT_INVALID_PACKET); + } + + /* Retrieve topic length. */ + byte++; + topic_length = (UINT)(*(byte) << 8) | (*(byte + 1)); + + if (topic_length > remaining_length - 2u) + { + return(NX_AZURE_IOT_INVALID_PACKET); + } + + *topic_offset_ptr = (ULONG)((byte + 2) - start_ptr); + *topic_length_ptr = (USHORT)topic_length; + + /* Return. */ + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_hub_transport_adjust_payload(NX_PACKET *packet_ptr) +{ +UINT status; +ULONG topic_offset; +USHORT topic_length; +ULONG message_offset; +ULONG message_length; + + status = _nxd_mqtt_process_publish_packet(packet_ptr, &topic_offset, + &topic_length, &message_offset, + &message_length); + if (status) + { + nx_packet_release(packet_ptr); + return(status); + } + + packet_ptr -> nx_packet_length = message_length; + + /* Adjust packet to pointer to message payload. */ + while (packet_ptr) + { + if ((ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) > message_offset) + { + + /* This packet contains message payload. */ + packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + message_offset; + break; + } + + message_offset -= (ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr); + + /* Set current packet to empty. */ + packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_append_ptr; + + /* Move to next packet. */ + packet_ptr = packet_ptr -> nx_packet_next; + } + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_hub_transport_publish_packet_get(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr, + NX_PACKET **packet_pptr, UINT wait_option) +{ + if ((hub_transport_ptr == NX_NULL) || + (hub_transport_ptr -> nx_azure_iot_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoTHub transport publish packet get: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + return(nx_azure_iot_publish_packet_get(hub_transport_ptr -> nx_azure_iot_ptr, + &(hub_transport_ptr -> nx_azure_iot_hub_transport_resource.resource_mqtt), + packet_pptr, wait_option)); +} diff --git a/addons/azure_iot/nx_azure_iot_hub_transport.h b/addons/azure_iot/nx_azure_iot_hub_transport.h new file mode 100644 index 00000000..685e3399 --- /dev/null +++ b/addons/azure_iot/nx_azure_iot_hub_transport.h @@ -0,0 +1,216 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/* Version: 6.1 PnP Preview 1 */ + +/** + * @file nx_azure_iot_hub_transport.h + * + * + */ + +#ifndef NX_AZURE_IOT_HUB_TRANSPORT_H +#define NX_AZURE_IOT_HUB_TRANSPORT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "azure/core/az_result.h" +#include "azure/core/az_span.h" +#include "nx_azure_iot.h" +#include "nx_api.h" +#include "nx_cloud.h" +#include "nxd_dns.h" +#include "nxd_mqtt_client.h" + +#define NX_AZURE_IOT_HUB_TRANSPORT_MAX_NUM_RECEIVE_QUEUE 5 + +/* Set the default timeout for DNS query. */ +#ifndef NX_AZURE_IOT_HUB_TRANSPORT_DNS_TIMEOUT +#ifndef NX_AZURE_IOT_HUB_CLIENT_DNS_TIMEOUT +#define NX_AZURE_IOT_HUB_TRANSPORT_DNS_TIMEOUT (5 * NX_IP_PERIODIC_RATE) +#else +#define NX_AZURE_IOT_HUB_TRANSPORT_DNS_TIMEOUT NX_AZURE_IOT_HUB_CLIENT_DNS_TIMEOUT +#endif /* NX_AZURE_IOT_HUB_CLIENT_DNS_TIMEOUT */ +#endif /* NX_AZURE_IOT_HUB_TRANSPORT_DNS_TIMEOUT */ + + +/* Set the default token expiry in secs. */ +#ifndef NX_AZURE_IOT_HUB_TRANSPORT_TOKEN_EXPIRY +#ifndef NX_AZURE_IOT_HUB_CLIENT_TOKEN_EXPIRY +#define NX_AZURE_IOT_HUB_TRANSPORT_TOKEN_EXPIRY (3600) +#else +#define NX_AZURE_IOT_HUB_TRANSPORT_TOKEN_EXPIRY NX_AZURE_IOT_HUB_CLIENT_TOKEN_EXPIRY +#endif /* NX_AZURE_IOT_HUB_CLIENT_TOKEN_EXPIRY */ +#endif /* NX_AZURE_IOT_HUB_TRANSPORT_TOKEN_EXPIRY */ + +/* Define AZ IoT Hub Client state. */ +/**< The client is not connected */ +#define NX_AZURE_IOT_HUB_TRANSPORT_STATUS_NOT_CONNECTED 0 + +/**< The client is connecting */ +#define NX_AZURE_IOT_HUB_TRANSPORT_STATUS_CONNECTING 1 + +/**< The client is connected */ +#define NX_AZURE_IOT_HUB_TRANSPORT_STATUS_CONNECTED 2 + +/* Default TELEMETRY QoS is QoS1 */ +#ifndef NX_AZURE_IOT_HUB_TRANSPORT_TELEMETRY_QOS +#define NX_AZURE_IOT_HUB_TRANSPORT_TELEMETRY_QOS NX_AZURE_IOT_MQTT_QOS_1 +#endif /* NX_AZURE_IOT_HUB_TRANSPORT_TELEMETRY_QOS */ + +#define NZ_AZURE_IOT_HUB_TRANSPORT_MESSAGE_ENABLE (0x0001) + +/* Forward declaration */ +struct NX_AZURE_IOT_HUB_TRANSPORT_STRUCT; + +typedef VOID (*NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN)(VOID); +typedef VOID (*NX_AZURE_IOT_HUB_TRANSPORT_CONNECTION_STATUS_CB)(struct NX_AZURE_IOT_HUB_TRANSPORT_STRUCT *hub_trans_ptr, + UINT status, NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN arg); +typedef az_result (*NX_AZURE_IOT_HUB_TRANSPORT_CLIENT_ID_GET_FN)(struct NX_AZURE_IOT_HUB_TRANSPORT_STRUCT *hub_trans_ptr, + UCHAR *buffer, UINT buffer_len, UINT *bytes_copied); +typedef az_result (*NX_AZURE_IOT_HUB_TRANSPORT_USERNAME_GET_FN)(struct NX_AZURE_IOT_HUB_TRANSPORT_STRUCT *hub_trans_ptr, + UCHAR *buffer, UINT buffer_len, UINT *bytes_copied); +typedef az_result (*NX_AZURE_IOT_HUB_TRANSPORT_SIGNATURE_GET_FN)(struct NX_AZURE_IOT_HUB_TRANSPORT_STRUCT *hub_trans_ptr, + ULONG expiry_time_secs, az_span buffer, az_span *out_buffer); +typedef az_result (*NX_AZURE_IOT_HUB_TRANSPORT_PASSWORD_GET_FN)(struct NX_AZURE_IOT_HUB_TRANSPORT_STRUCT *hub_trans_ptr, + ULONG expiry_time_secs, az_span hash_buffer, az_span key_name, + UCHAR *out_buffer, UINT out_buffer_len, UINT *bytes_copied); + +typedef VOID (*NX_AZURE_IOT_HUB_TRANSPORT_MESSAGE_CB_FN)(struct NX_AZURE_IOT_HUB_TRANSPORT_STRUCT *hub_trans_ptr, + NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN arg1, + VOID *arg2); +typedef UINT (*NX_AZURE_IOT_HUB_TRANSPORT_MESSAGE_PROCESS_FN)(struct NX_AZURE_IOT_HUB_TRANSPORT_STRUCT *hub_trans_ptr, + NX_PACKET *packet_ptr, ULONG topic_offset, USHORT topic_length); +typedef UINT (*NX_AZURE_IOT_HUB_TRANSPORT_MESSAGE_ENABLE_FN)(struct NX_AZURE_IOT_HUB_TRANSPORT_STRUCT *hub_trans_ptr); + +typedef struct NX_AZURE_IOT_HUB_TRANSPORT_RECEIVE_MESSAGE_STRUCT +{ + NX_PACKET *message_head; + NX_PACKET *message_tail; + NX_AZURE_IOT_HUB_TRANSPORT_MESSAGE_CB_FN message_callback; + NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN message_callback_arg1; + VOID *message_callback_arg2; + const UCHAR *message_topic_ptr; + UINT message_topic_length; + NX_AZURE_IOT_HUB_TRANSPORT_MESSAGE_PROCESS_FN message_process; + USHORT message_sub_packet_id; + USHORT message_control_flag; +} NX_AZURE_IOT_HUB_TRANSPORT_RECEIVE_MESSAGE; + +/** + * @brief Azure IoT Hub transport struct + * + */ +typedef struct NX_AZURE_IOT_HUB_TRANSPORT_STRUCT +{ + NX_AZURE_IOT *nx_azure_iot_ptr; + + UINT nx_azure_iot_hub_transport_state; + + UINT nx_azure_iot_hub_transport_request_id; + const UCHAR *nx_azure_iot_hub_transport_symmetric_key; + UINT nx_azure_iot_hub_transport_symmetric_key_length; + NX_AZURE_IOT_RESOURCE nx_azure_iot_hub_transport_resource; + + VOID *nx_azure_iot_hub_transport_client_context; + + NX_AZURE_IOT_HUB_TRANSPORT_CONNECTION_STATUS_CB nx_azure_iot_hub_transport_connection_status_callback; + NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN nx_azure_iot_hub_transport_connection_status_callback_arg; + UINT (*nx_azure_iot_hub_transport_token_refresh)( + struct NX_AZURE_IOT_HUB_TRANSPORT_STRUCT *hub_trans_ptr, + ULONG expiry_time_secs, const UCHAR *key, UINT key_len, + UCHAR *sas_buffer, UINT sas_buffer_len, UINT *sas_length); + + NX_AZURE_IOT_HUB_TRANSPORT_CLIENT_ID_GET_FN nx_azure_iot_hub_transport_client_id_get; + NX_AZURE_IOT_HUB_TRANSPORT_USERNAME_GET_FN nx_azure_iot_hub_transport_username_get; + NX_AZURE_IOT_HUB_TRANSPORT_SIGNATURE_GET_FN nx_azure_iot_hub_transport_sas_signature; + NX_AZURE_IOT_HUB_TRANSPORT_PASSWORD_GET_FN nx_azure_iot_hub_transport_sas_password; + + + NX_AZURE_IOT_THREAD *nx_azure_iot_hub_transport_thread_suspended; + NX_AZURE_IOT_HUB_TRANSPORT_RECEIVE_MESSAGE nx_azure_iot_hub_transport_message[NX_AZURE_IOT_HUB_TRANSPORT_MAX_NUM_RECEIVE_QUEUE]; + volatile UINT nx_azure_iot_hub_transport_message_pending_subscribe_ack; +} NX_AZURE_IOT_HUB_TRANSPORT; + + +UINT nx_azure_iot_hub_transport_initialize(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + NX_AZURE_IOT *nx_azure_iot_ptr, + const UCHAR *host_name, UINT host_name_length, + const NX_AZURE_IOT_HUB_TRANSPORT_CLIENT_ID_GET_FN client_id_get, + const NX_AZURE_IOT_HUB_TRANSPORT_USERNAME_GET_FN username_get, + const NX_CRYPTO_METHOD **crypto_array, UINT crypto_array_size, + const NX_CRYPTO_CIPHERSUITE **cipher_map, UINT cipher_map_size, + UCHAR *metadata_memory, UINT memory_size, + NX_SECURE_X509_CERT *trusted_certificate, + VOID *client_context); + +UINT nx_azure_iot_hub_transport_deinitialize(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr); + +UINT nx_azure_iot_hub_transport_device_cert_set(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + NX_SECURE_X509_CERT *device_certificate); + +UINT nx_azure_iot_hub_transport_symmetric_key_auth_set(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + const NX_AZURE_IOT_HUB_TRANSPORT_SIGNATURE_GET_FN sas_signature_get, + const NX_AZURE_IOT_HUB_TRANSPORT_PASSWORD_GET_FN sas_password_get, + const UCHAR *symmetric_key, UINT symmetric_key_length); + +UINT nx_azure_iot_hub_transport_connection_callback_set(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + NX_AZURE_IOT_HUB_TRANSPORT_CONNECTION_STATUS_CB connection_cb, + NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN arg); + +UINT nx_azure_iot_hub_transport_connect(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + UINT clean_session, UINT wait_option); + +UINT nx_azure_iot_hub_transport_disconnect(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr); + +UINT nx_azure_iot_hub_transport_receive_message_enable(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, UINT message_queue_index, + const UCHAR *message_topic_ptr, UINT message_topic_length, + NX_AZURE_IOT_HUB_TRANSPORT_MESSAGE_PROCESS_FN message_process); + +UINT nx_azure_iot_hub_transport_receive_message_disable(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + UINT message_queue_index); + +UINT nx_azure_iot_hub_transport_receive_message_callback_set(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, UINT message_queue_index, + NX_AZURE_IOT_HUB_TRANSPORT_MESSAGE_CB_FN message_callback, + NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN arg1, VOID *arg2); + +UINT nx_azure_iot_hub_transport_receive_message_is_subscribed(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + UINT message_queue_index, UINT wait_option); + +UINT nx_azure_iot_hub_transport_message_receive(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + UINT message_queue_index, UINT expected_id, + NX_PACKET **packet_pptr, UINT wait_option); + +UINT nx_azure_iot_hub_transport_receive_notify(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + NX_PACKET *packet_ptr, UINT message_queue_index, + UINT correlation_id); + +UINT nx_azure_iot_hub_transport_request_response(NX_AZURE_IOT_HUB_TRANSPORT *hub_transport_ptr, + UINT request_id, NX_PACKET *packet_ptr, ULONG topic_length, + const UCHAR *message_buffer, UINT message_length, UINT response_queue_index, + NX_PACKET **response_packet_pptr, UINT wait_option); + +UINT nx_azure_iot_hub_transport_publish(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, NX_PACKET *packet_ptr, + const UCHAR *data, UINT data_size, UINT qos, UINT wait_option); + +UINT nx_azure_iot_hub_transport_process_publish_packet(UCHAR *start_ptr, ULONG *topic_offset_ptr, + USHORT *topic_length_ptr); + +UINT nx_azure_iot_hub_transport_adjust_payload(NX_PACKET *packet_ptr); + +UINT nx_azure_iot_hub_transport_publish_packet_get(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + NX_PACKET **packet_pptr, UINT wait_option); +#ifdef __cplusplus +} +#endif +#endif /* NX_AZURE_IOT_HUB_TRANSPORT_H */ diff --git a/addons/azure_iot/nx_azure_iot_json_reader.c b/addons/azure_iot/nx_azure_iot_json_reader.c index cd480db3..0e5713c8 100644 --- a/addons/azure_iot/nx_azure_iot_json_reader.c +++ b/addons/azure_iot/nx_azure_iot_json_reader.c @@ -9,25 +9,56 @@ /* */ /**************************************************************************/ -/* Version: 6.1 */ +/* Version: 6.1 PnP Preview 1 */ #include "nx_azure_iot_json_reader.h" #include "nx_azure_iot.h" +static UINT nx_azure_iot_json_reader_translate_error_code(NX_AZURE_IOT_JSON_READER *reader_ptr, + az_result core_result) +{ + if (az_result_failed(core_result)) + { + if (core_result == AZ_ERROR_JSON_READER_DONE) + { + return(NX_AZURE_IOT_NOT_FOUND); + } + + if (reader_ptr -> json_length == 0) + { + return(NX_AZURE_IOT_EMPTY_JSON); + } + + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + return(NX_AZURE_IOT_SUCCESS); +} + UINT nx_azure_iot_json_reader_with_buffer_init(NX_AZURE_IOT_JSON_READER *reader_ptr, const UCHAR *buffer_ptr, UINT buffer_len) { az_span span = az_span_create((UCHAR *)buffer_ptr, (INT)buffer_len); if ((reader_ptr == NX_NULL) || - (buffer_ptr == NX_NULL) || (buffer_len == 0)) + (buffer_ptr == NX_NULL)) { return(NX_AZURE_IOT_INVALID_PARAMETER); } memset(reader_ptr, 0, sizeof(NX_AZURE_IOT_JSON_READER)); + /* Allow initializing with zero size buffer, as any futher call will fail for empty JSON */ + if (buffer_len == 0) + { + reader_ptr -> json_reader.token.kind = AZ_JSON_TOKEN_NONE; + + return(NX_AZURE_IOT_SUCCESS); + } + + reader_ptr -> json_length = (ULONG)buffer_len; + if (az_result_failed(az_json_reader_init(&(reader_ptr -> json_reader), span, NX_NULL))) { @@ -43,8 +74,7 @@ UINT nx_azure_iot_json_reader_init(NX_AZURE_IOT_JSON_READER *reader_ptr, UINT count = 0; if ((reader_ptr == NX_NULL) || - (packet_ptr == NX_NULL) || - (packet_ptr -> nx_packet_length == 0)) + (packet_ptr == NX_NULL)) { return(NX_AZURE_IOT_INVALID_PARAMETER); } @@ -53,6 +83,16 @@ UINT count = 0; reader_ptr -> packet_ptr = packet_ptr; + /* Allow initializing with zero size packet, as any futher call will fail for empty JSON */ + if (packet_ptr -> nx_packet_length == 0) + { + reader_ptr -> json_reader.token.kind = AZ_JSON_TOKEN_NONE; + + return(NX_AZURE_IOT_SUCCESS); + } + + reader_ptr -> json_length = packet_ptr -> nx_packet_length; + while (packet_ptr != NX_NULL) { if (count >= NX_AZURE_IOT_READER_MAX_LIST) @@ -110,32 +150,30 @@ az_span span = az_span_create(value_ptr, (INT)value_len); UINT nx_azure_iot_json_reader_next_token(NX_AZURE_IOT_JSON_READER *reader_ptr) { +az_result core_result; + if ((reader_ptr == NX_NULL)) { return(NX_AZURE_IOT_INVALID_PARAMETER); } - if (az_result_failed(az_json_reader_next_token(&(reader_ptr -> json_reader)))) - { - return(NX_AZURE_IOT_SDK_CORE_ERROR); - } - - return(NX_AZURE_IOT_SUCCESS); + core_result = az_json_reader_next_token(&(reader_ptr -> json_reader)); + + return(nx_azure_iot_json_reader_translate_error_code(reader_ptr, core_result)); } UINT nx_azure_iot_json_reader_skip_children(NX_AZURE_IOT_JSON_READER *reader_ptr) { +az_result core_result; + if ((reader_ptr == NX_NULL)) { return(NX_AZURE_IOT_INVALID_PARAMETER); } - if (az_result_failed(az_json_reader_skip_children(&(reader_ptr -> json_reader)))) - { - return(NX_AZURE_IOT_SDK_CORE_ERROR); - } + core_result = az_json_reader_skip_children(&(reader_ptr -> json_reader)); - return(NX_AZURE_IOT_SUCCESS); + return(nx_azure_iot_json_reader_translate_error_code(reader_ptr, core_result)); } UINT nx_azure_iot_json_reader_token_bool_get(NX_AZURE_IOT_JSON_READER *reader_ptr, diff --git a/addons/azure_iot/nx_azure_iot_json_reader.h b/addons/azure_iot/nx_azure_iot_json_reader.h index 7fefa51d..dbb1ecaa 100644 --- a/addons/azure_iot/nx_azure_iot_json_reader.h +++ b/addons/azure_iot/nx_azure_iot_json_reader.h @@ -9,7 +9,7 @@ /* */ /**************************************************************************/ -/* Version: 6.1 */ +/* Version: 6.1 PnP Preview 1 */ /** * @file nx_azure_iot_json_reader.h @@ -54,6 +54,7 @@ typedef struct NX_AZURE_IOT_READER_STRUCT NX_PACKET *packet_ptr; az_json_reader json_reader; az_span span_list[NX_AZURE_IOT_READER_MAX_LIST]; + ULONG json_length; } NX_AZURE_IOT_JSON_READER; /** @@ -68,7 +69,6 @@ typedef struct NX_AZURE_IOT_READER_STRUCT * @retval #NX_AZURE_IOT_SUCCESS The #NX_AZURE_IOT_JSON_READER is initialized successfully. * @retval other Initialization failed. * - * @remarks The provided json buffer must not be empty, as that is invalid JSON. */ UINT nx_azure_iot_json_reader_with_buffer_init(NX_AZURE_IOT_JSON_READER *reader_ptr, const UCHAR *buffer_ptr, UINT buffer_len); @@ -83,8 +83,6 @@ UINT nx_azure_iot_json_reader_with_buffer_init(NX_AZURE_IOT_JSON_READER *reader_ * @retval #NX_AZURE_IOT_SUCCESS The #NX_AZURE_IOT_JSON_READER is initialized successfully. * @retval other Initialization failed. * - * @remarks The provided json buffer must not be empty, as that is invalid JSON. - * * @remarks Ownership of #NX_PACKET is taken by the reader. */ UINT nx_azure_iot_json_reader_init(NX_AZURE_IOT_JSON_READER *reader_ptr, diff --git a/addons/azure_iot/nx_azure_iot_json_writer.c b/addons/azure_iot/nx_azure_iot_json_writer.c index eb4e3c43..4b3f3be3 100644 --- a/addons/azure_iot/nx_azure_iot_json_writer.c +++ b/addons/azure_iot/nx_azure_iot_json_writer.c @@ -9,7 +9,7 @@ /* */ /**************************************************************************/ -/* Version: 6.1 */ +/* Version: 6.1 PnP Preview 1 */ #include "nx_azure_iot_json_writer.h" @@ -344,8 +344,6 @@ UINT nx_azure_iot_json_writer_append_begin_object(NX_AZURE_IOT_JSON_WRITER *json return(NX_AZURE_IOT_SDK_CORE_ERROR); } - json_writer_ptr -> object_depth++; - nx_azure_iot_json_writer_packet_update(json_writer_ptr); return(NX_AZURE_IOT_SUCCESS); @@ -382,8 +380,6 @@ UINT nx_azure_iot_json_writer_append_end_object(NX_AZURE_IOT_JSON_WRITER *json_w return(NX_AZURE_IOT_SDK_CORE_ERROR); } - json_writer_ptr -> object_depth--; - nx_azure_iot_json_writer_packet_update(json_writer_ptr); return(NX_AZURE_IOT_SUCCESS); diff --git a/addons/azure_iot/nx_azure_iot_json_writer.h b/addons/azure_iot/nx_azure_iot_json_writer.h index e40b999f..0228f0b1 100644 --- a/addons/azure_iot/nx_azure_iot_json_writer.h +++ b/addons/azure_iot/nx_azure_iot_json_writer.h @@ -9,7 +9,7 @@ /* */ /**************************************************************************/ -/* Version: 6.1 */ +/* Version: 6.1 PnP Preview 1 */ /** * @file nx_azure_iot_json_writer.h @@ -38,7 +38,6 @@ typedef struct NX_AZURE_IOT_JSON_WRITER_STRUCT { NX_PACKET *packet_ptr; az_json_writer json_writer; - UINT object_depth; UINT wait_option; ULONG nx_tail_packet_offset; ULONG nx_packet_init_length; diff --git a/addons/azure_iot/nx_azure_iot_pnp_client.c b/addons/azure_iot/nx_azure_iot_pnp_client.c new file mode 100644 index 00000000..66f9fbab --- /dev/null +++ b/addons/azure_iot/nx_azure_iot_pnp_client.c @@ -0,0 +1,1588 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/* Version: 6.1 PnP Preview 1 */ + +#include "nx_azure_iot_pnp_client.h" + +#include "azure/core/az_version.h" + +#define NX_AZURE_IOT_PNP_CLIENT_U32_MAX_BUFFER_SIZE 10 +#define NX_AZURE_IOT_PNP_CLIENT_EMPTY_JSON "{}" +#define NX_AZURE_IOT_PNP_CLIENT_THROTTLE_STATUS_CODE 429 + +#ifndef NX_AZURE_IOT_PNP_CLIENT_USER_AGENT + +/* Useragent e.g: DeviceClientType=c%2F1.0.0-preview.1%20%28nx%206.0%3Bazrtos%206.0%29 */ +#define NX_AZURE_IOT_PNP_CLIENT_STR(C) #C +#define NX_AZURE_IOT_PNP_CLIENT_TO_STR(x) NX_AZURE_IOT_PNP_CLIENT_STR(x) +#define NX_AZURE_IOT_PNP_CLIENT_USER_AGENT "DeviceClientType=c%2F" AZ_SDK_VERSION_STRING "%20%28nx%20" \ + NX_AZURE_IOT_PNP_CLIENT_TO_STR(NETXDUO_MAJOR_VERSION) "." \ + NX_AZURE_IOT_PNP_CLIENT_TO_STR(NETXDUO_MINOR_VERSION) "%3Bazrtos%20"\ + NX_AZURE_IOT_PNP_CLIENT_TO_STR(THREADX_MAJOR_VERSION) "." \ + NX_AZURE_IOT_PNP_CLIENT_TO_STR(THREADX_MINOR_VERSION) "%29" +#endif /* NX_AZURE_IOT_PNP_CLIENT_USER_AGENT */ + +/* Queue index used in transport to receive the messages */ +#define NX_AZURE_IOT_PNP_COMMAND_QUEUE_INDEX 0 +#define NX_AZURE_IOT_PNP_PROPERTIES_QUEUE_INDEX 1 +#define NX_AZURE_IOT_PNP_DESIRED_PROPERTIES_QUEUE_INDEX 2 +#define NX_AZURE_IOT_PNP_REPORTED_PROPERTIES_RESPONSE_QUEUE_INDEX 3 + +extern UINT _nxd_mqtt_process_publish_packet(NX_PACKET *packet_ptr, ULONG *topic_offset_ptr, + USHORT *topic_length_ptr, ULONG *message_offset_ptr, + ULONG *message_length_ptr); + +static UINT nx_azure_iot_pnp_client_mesg_type_to_queue_index(UINT message_type) +{ +UINT queue_index; + + switch (message_type) + { + case NX_AZURE_IOT_PNP_COMMAND : + { + queue_index = NX_AZURE_IOT_PNP_COMMAND_QUEUE_INDEX; + } + break; + + case NX_AZURE_IOT_PNP_PROPERTIES : + { + queue_index = NX_AZURE_IOT_PNP_PROPERTIES_QUEUE_INDEX; + } + break; + + case NX_AZURE_IOT_PNP_DESIRED_PROPERTIES : + { + queue_index = NX_AZURE_IOT_PNP_DESIRED_PROPERTIES_QUEUE_INDEX; + } + break; + + case NX_AZURE_IOT_PNP_REPORTED_PROPERTIES_RESPONSE : + { + queue_index = NX_AZURE_IOT_PNP_REPORTED_PROPERTIES_RESPONSE_QUEUE_INDEX; + } + break; + + default : + { + /* no queue */ + queue_index = NX_AZURE_IOT_HUB_TRANSPORT_MAX_NUM_RECEIVE_QUEUE; + } + break; + } + + return(queue_index); +} + +static UINT nx_azure_iot_pnp_client_command_process(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + NX_PACKET *packet_ptr, + ULONG topic_offset, + USHORT topic_length) +{ +UCHAR *topic_name; +az_iot_pnp_client_command_request request; +az_span receive_topic; +az_result core_result; +NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr = (NX_AZURE_IOT_PNP_CLIENT *)hub_trans_ptr -> nx_azure_iot_hub_transport_client_context; + + /* This function is protected by MQTT mutex. */ + + /* Check message type first. */ + topic_name = &(packet_ptr -> nx_packet_prepend_ptr[topic_offset]); + + /* NOTE: Current implementation does not support topic to span multiple packets. */ + if ((ULONG)(packet_ptr -> nx_packet_append_ptr - topic_name) < topic_length) + { + LogError(LogLiteralArgs("topic out of boundaries of single packet")); + return(NX_AZURE_IOT_TOPIC_TOO_LONG); + } + + receive_topic = az_span_create(topic_name, topic_length); + core_result = az_iot_pnp_client_commands_parse_received_topic(&(pnp_client_ptr -> iot_pnp_client_core), + receive_topic, &request); + if (az_result_failed(core_result)) + { + + /* Topic name does not match command format. */ + return(NX_AZURE_IOT_NOT_FOUND); + } + + return(nx_azure_iot_hub_transport_receive_notify(hub_trans_ptr, packet_ptr, + NX_AZURE_IOT_PNP_COMMAND_QUEUE_INDEX, 0)); +} + +static UINT nx_azure_iot_pnp_client_twin_request_id_get(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + UCHAR *buffer_ptr, UINT buffer_len, + az_span *request_id_span_ptr, + UINT *request_id_ptr, UINT odd_seq) +{ +az_span span; + + /* Obtain the mutex. */ + tx_mutex_get(pnp_client_ptr -> nx_azure_iot_pnp_client_transport.nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + /* Check if current request_id is even and new requested is also even or + current request_id is odd and new requested is also odd. */ + if ((pnp_client_ptr -> nx_azure_iot_pnp_client_request_id & 0x1) == odd_seq) + { + pnp_client_ptr -> nx_azure_iot_pnp_client_request_id += 2; + } + else + { + pnp_client_ptr -> nx_azure_iot_pnp_client_request_id += 1; + } + + if (pnp_client_ptr -> nx_azure_iot_pnp_client_request_id == 0) + { + pnp_client_ptr -> nx_azure_iot_pnp_client_request_id = 2; + } + + *request_id_ptr = pnp_client_ptr -> nx_azure_iot_pnp_client_request_id; + span = az_span_create(buffer_ptr, (INT)buffer_len); + if (az_result_failed(az_span_u32toa(span, *request_id_ptr, &span))) + { + + /* Release the mutex. */ + tx_mutex_put(pnp_client_ptr -> nx_azure_iot_pnp_client_transport.nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + LogError(LogLiteralArgs("IoT PnP client device failed to u32toa")); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + *request_id_span_ptr = az_span_create(buffer_ptr, (INT)(buffer_len - (UINT)az_span_size(span))); + + /* Release the mutex. */ + tx_mutex_put(pnp_client_ptr -> nx_azure_iot_pnp_client_transport.nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + return(NX_AZURE_IOT_SUCCESS); +} + +static UINT nx_azure_iot_pnp_client_device_twin_message_type_get(az_iot_pnp_client_property_response *out_twin_response_ptr, + UINT request_id) +{ +UINT message_type; + + switch (out_twin_response_ptr -> response_type) + { + case AZ_IOT_PNP_CLIENT_PROPERTY_RESPONSE_TYPE_GET : + + /* Fall through. */ + + case AZ_IOT_PNP_CLIENT_PROPERTY_RESPONSE_TYPE_REPORTED_PROPERTIES : + { + + /* Odd requests are of reported properties and even of twin properties. */ + message_type = request_id % 2 == 0 ? NX_AZURE_IOT_PNP_PROPERTIES : + NX_AZURE_IOT_PNP_REPORTED_PROPERTIES_RESPONSE; + } + break; + + case AZ_IOT_PNP_CLIENT_PROPERTY_RESPONSE_TYPE_DESIRED_PROPERTIES : + { + message_type = NX_AZURE_IOT_PNP_DESIRED_PROPERTIES; + } + break; + + default : + { + message_type = NX_AZURE_IOT_PNP_NONE; + } + } + + return message_type; +} + +static UINT nx_azure_iot_pnp_client_device_twin_parse(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_PACKET *packet_ptr, ULONG topic_offset, + USHORT topic_length, UINT *request_id_ptr, + ULONG *version_ptr, UINT *message_type_ptr, + UINT *status_ptr) +{ +az_result core_result; +az_span topic_span; +az_iot_pnp_client_property_response out_twin_response; +uint32_t request_id = 0; +uint32_t version; + + topic_span = az_span_create(&(packet_ptr -> nx_packet_prepend_ptr[topic_offset]), (INT)topic_length); + core_result = az_iot_pnp_client_property_parse_received_topic(&(pnp_client_ptr -> iot_pnp_client_core), + topic_span, &out_twin_response); + if (az_result_failed(core_result)) + { + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + if (version_ptr != NX_NULL && az_span_ptr(out_twin_response.version)) + { + core_result = az_span_atou32(out_twin_response.version, &version); + if (az_result_failed(core_result)) + { + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + *version_ptr = (ULONG)version; + } + + if (az_span_ptr(out_twin_response.request_id)) + { + core_result = az_span_atou32(out_twin_response.request_id, &request_id); + if (az_result_failed(core_result)) + { + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + } + + if (request_id_ptr) + { + *request_id_ptr = (UINT)request_id; + } + + if (message_type_ptr) + { + *message_type_ptr = nx_azure_iot_pnp_client_device_twin_message_type_get(&out_twin_response, + (UINT)request_id); + } + + if (status_ptr) + { + *status_ptr = (UINT)out_twin_response.status; + } + + return(NX_AZURE_IOT_SUCCESS); +} + +static UINT nx_azure_iot_pnp_client_throttle_with_jitter(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr) +{ +UINT jitter; +UINT base_delay = NX_AZURE_IOT_PNP_CLIENT_MAX_BACKOFF_IN_SEC; +UINT retry_count = pnp_client_ptr -> nx_azure_iot_pnp_client_throttle_count; +uint64_t delay; + + if (retry_count < (sizeof(UINT) * 8 - 1)) + { + retry_count++; + delay = (uint64_t)((1 << retry_count) * NX_AZURE_IOT_PNP_CLIENT_INITIAL_BACKOFF_IN_SEC); + + if (delay <= (UINT)(-1)) + { + base_delay = (UINT)delay; + } + } + + if (base_delay > NX_AZURE_IOT_PNP_CLIENT_MAX_BACKOFF_IN_SEC) + { + base_delay = NX_AZURE_IOT_PNP_CLIENT_MAX_BACKOFF_IN_SEC; + } + else + { + pnp_client_ptr -> nx_azure_iot_pnp_client_throttle_count = retry_count; + } + + jitter = base_delay * NX_AZURE_IOT_PNP_CLIENT_MAX_BACKOFF_JITTER_PERCENT * (NX_RAND() & 0xFF) / 25600; + return((UINT)(base_delay + jitter)); +} + +static UINT nx_azure_iot_pnp_client_throttled_check(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr) +{ +ULONG current_time; +UINT status = NX_AZURE_IOT_SUCCESS; + + if (pnp_client_ptr -> nx_azure_iot_pnp_client_throttle_count != 0) + { + if ((status = nx_azure_iot_unix_time_get(pnp_client_ptr -> nx_azure_iot_pnp_client_transport.nx_azure_iot_ptr, ¤t_time))) + { + LogError(LogLiteralArgs("IoT PnP client fail to get unix time: %d"), status); + return(status); + } + + if (current_time < pnp_client_ptr -> nx_azure_iot_pnp_client_throttle_end_time) + { + return(NX_AZURE_IOT_THROTTLED); + } + } + + return(status); +} + +static UINT nx_azure_iot_pnp_client_device_twin_process(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + NX_PACKET *packet_ptr, + ULONG topic_offset, + USHORT topic_length) +{ +UINT message_type; +UINT response_status; +UINT request_id = 0; +ULONG version = 0; +UINT correlation_id; +UINT status; +ULONG current_time; +UINT message_queue_index; +NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr = (NX_AZURE_IOT_PNP_CLIENT *)hub_trans_ptr -> nx_azure_iot_hub_transport_client_context ; + + /* This function is protected by MQTT mutex. */ + if ((status = nx_azure_iot_pnp_client_device_twin_parse(pnp_client_ptr, packet_ptr, + topic_offset, topic_length, + &request_id, &version, + &message_type, &response_status))) + { + return(status); + } + + if (response_status == NX_AZURE_IOT_PNP_CLIENT_THROTTLE_STATUS_CODE) + { + if ((status = nx_azure_iot_unix_time_get(pnp_client_ptr -> nx_azure_iot_pnp_client_transport.nx_azure_iot_ptr, ¤t_time))) + { + LogError(LogLiteralArgs("IoT PnP client fail to get unix time: %d"), status); + return(status); + } + + pnp_client_ptr -> nx_azure_iot_pnp_client_throttle_end_time = + current_time + nx_azure_iot_pnp_client_throttle_with_jitter(pnp_client_ptr); + } + else + { + pnp_client_ptr -> nx_azure_iot_pnp_client_throttle_count = 0; + pnp_client_ptr -> nx_azure_iot_pnp_client_throttle_end_time = 0; + } + + if (message_type == NX_AZURE_IOT_PNP_REPORTED_PROPERTIES_RESPONSE) + { + + /* Only requested thread should be woken. */ + correlation_id = request_id; + } + else + { + + /* Any thread can be woken. */ + correlation_id = 0; + } + + message_queue_index = nx_azure_iot_pnp_client_mesg_type_to_queue_index(message_type); + status = nx_azure_iot_hub_transport_receive_notify(hub_trans_ptr, packet_ptr, + message_queue_index, correlation_id); + + return(status); +} + +static az_result nx_azure_iot_pnp_client_client_id_get(struct NX_AZURE_IOT_HUB_TRANSPORT_STRUCT *hub_trans_ptr, + UCHAR *buffer, UINT buffer_len, UINT *bytes_copied) +{ +NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr = (NX_AZURE_IOT_PNP_CLIENT *)hub_trans_ptr -> nx_azure_iot_hub_transport_client_context; + + return(az_iot_pnp_client_get_client_id(&(pnp_client_ptr -> iot_pnp_client_core), + (CHAR *)buffer, buffer_len, bytes_copied)); +} + +static az_result nx_azure_iot_pnp_client_username_get(struct NX_AZURE_IOT_HUB_TRANSPORT_STRUCT *hub_trans_ptr, + UCHAR *buffer, UINT buffer_len, UINT *bytes_copied) +{ +NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr = (NX_AZURE_IOT_PNP_CLIENT *)hub_trans_ptr -> nx_azure_iot_hub_transport_client_context; + + return(az_iot_pnp_client_get_user_name(&pnp_client_ptr -> iot_pnp_client_core, + (CHAR *)buffer, buffer_len, bytes_copied)); +} + +static az_result nx_azure_iot_pnp_client_signature_get(struct NX_AZURE_IOT_HUB_TRANSPORT_STRUCT *hub_trans_ptr, + ULONG expiry_time_secs, az_span buffer, az_span *out_buffer) +{ +NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr = (NX_AZURE_IOT_PNP_CLIENT *)hub_trans_ptr -> nx_azure_iot_hub_transport_client_context; + + return(az_iot_pnp_client_sas_get_signature(&(pnp_client_ptr -> iot_pnp_client_core), + expiry_time_secs, buffer, out_buffer)); +} + +static az_result nx_azure_iot_pnp_client_password_get(struct NX_AZURE_IOT_HUB_TRANSPORT_STRUCT *hub_trans_ptr, + ULONG expiry_time_secs, az_span hash_buffer, az_span key_name, + UCHAR *out_buffer, UINT out_buffer_len, UINT *bytes_copied) +{ +NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr = (NX_AZURE_IOT_PNP_CLIENT *)hub_trans_ptr -> nx_azure_iot_hub_transport_client_context; + + return(az_iot_pnp_client_sas_get_password(&(pnp_client_ptr -> iot_pnp_client_core), + expiry_time_secs, hash_buffer, key_name, + (CHAR *)out_buffer, out_buffer_len, bytes_copied)); +} + +static VOID nx_azure_iot_pnp_client_receive_callback(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN arg1, + VOID *arg2) +{ +NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr = (NX_AZURE_IOT_PNP_CLIENT *)hub_trans_ptr -> nx_azure_iot_hub_transport_client_context; + + ((VOID (*)(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, VOID *args))arg1)(pnp_client_ptr, arg2); +} + +static VOID nx_azure_iot_pnp_client_connection_status_callback(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + UINT status, NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN arg) +{ +NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr = (NX_AZURE_IOT_PNP_CLIENT *)hub_trans_ptr -> nx_azure_iot_hub_transport_client_context; + + ((VOID (*)(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, UINT status))arg)(pnp_client_ptr, status); +} + +static VOID nx_azure_iot_pnp_client_reported_property_receive_callback(NX_AZURE_IOT_HUB_TRANSPORT *hub_trans_ptr, + NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN arg1, + VOID *arg2) +{ +NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr = (NX_AZURE_IOT_PNP_CLIENT *)hub_trans_ptr -> nx_azure_iot_hub_transport_client_context; +UINT status; +NX_PACKET *packet_ptr; +ULONG topic_offset; +USHORT topic_length; +UINT request_id; +UINT response_status; +ULONG version = 0; + + if ((status = nx_azure_iot_hub_transport_message_receive(hub_trans_ptr, + NX_AZURE_IOT_PNP_REPORTED_PROPERTIES_RESPONSE_QUEUE_INDEX, 0, + &packet_ptr, NX_NO_WAIT))) + { + LogError(LogLiteralArgs("IoTHub failed to find reported property: %d"), status); + return; + } + + if (nx_azure_iot_hub_transport_process_publish_packet(packet_ptr -> nx_packet_prepend_ptr, &topic_offset, + &topic_length)) + { + + /* Message not supported. It will be released. */ + nx_packet_release(packet_ptr); + return; + } + + if ((status = nx_azure_iot_pnp_client_device_twin_parse(pnp_client_ptr, packet_ptr, + topic_offset, topic_length, + &request_id, &version, + NX_NULL, &response_status))) + { + nx_packet_release(packet_ptr); + return; + } + + ((VOID (*)(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + UINT request_id, UINT response_status, + ULONG version, VOID *arg))arg1)(pnp_client_ptr, + request_id, + response_status, + version, + arg2); + nx_packet_release(packet_ptr); +} + +UINT nx_azure_iot_pnp_client_initialize(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT *nx_azure_iot_ptr, + const UCHAR *host_name, UINT host_name_length, + const UCHAR *device_id, UINT device_id_length, + const UCHAR *module_id, UINT module_id_length, + const UCHAR *model_id, UINT model_id_length, + const NX_CRYPTO_METHOD **crypto_array, UINT crypto_array_size, + const NX_CRYPTO_CIPHERSUITE **cipher_map, UINT cipher_map_size, + UCHAR *metadata_memory, UINT memory_size, + NX_SECURE_X509_CERT *trusted_certificate) +{ + +UINT status; +az_span hostname_span = az_span_create((UCHAR *)host_name, (INT)host_name_length); +az_span device_id_span = az_span_create((UCHAR *)device_id, (INT)device_id_length); +az_span model_id_span = az_span_create((UCHAR *)model_id, (INT)model_id_length); +az_iot_pnp_client_options options = az_iot_pnp_client_options_default(); +az_result core_result; + + if ((nx_azure_iot_ptr == NX_NULL) || (pnp_client_ptr == NX_NULL) || (host_name == NX_NULL) || + (device_id == NX_NULL) || (host_name_length == 0) || (device_id_length == 0) || + (model_id == NX_NULL) || (model_id_length == 0)) + { + LogError(LogLiteralArgs("IoT PnP client initialization fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + memset(pnp_client_ptr, 0, sizeof(NX_AZURE_IOT_PNP_CLIENT)); + + options.module_id = az_span_create((UCHAR *)module_id, (INT)module_id_length); + options.user_agent = AZ_SPAN_FROM_STR(NX_AZURE_IOT_PNP_CLIENT_USER_AGENT); + options.component_names = pnp_client_ptr -> nx_azure_iot_pnp_client_component_list; + options.component_names_length = 0; + + core_result = az_iot_pnp_client_init(&pnp_client_ptr -> iot_pnp_client_core, + hostname_span, device_id_span, model_id_span, &options); + if (az_result_failed(core_result)) + { + LogError(LogLiteralArgs("IoT PnP client failed initialization with error status: %d"), core_result); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + status = nx_azure_iot_hub_transport_initialize(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport), + nx_azure_iot_ptr, host_name, host_name_length, + nx_azure_iot_pnp_client_client_id_get, + nx_azure_iot_pnp_client_username_get, + crypto_array, crypto_array_size, + cipher_map, cipher_map_size, + metadata_memory, memory_size, + trusted_certificate, (VOID *)pnp_client_ptr); + if (status) + { + LogError(LogLiteralArgs("IoTPnP client failed to initialization transport with error status: %d"), core_result); + return(status); + } + + /* Enable all the features */ + if ((status = nx_azure_iot_hub_transport_receive_message_enable(&(pnp_client_ptr ->nx_azure_iot_pnp_client_transport), + NX_AZURE_IOT_PNP_COMMAND_QUEUE_INDEX, + (const UCHAR *)AZ_IOT_PNP_CLIENT_COMMANDS_SUBSCRIBE_TOPIC, + sizeof(AZ_IOT_PNP_CLIENT_COMMANDS_SUBSCRIBE_TOPIC) - 1, + nx_azure_iot_pnp_client_command_process)) || + (status = nx_azure_iot_hub_transport_receive_message_enable(&(pnp_client_ptr ->nx_azure_iot_pnp_client_transport), + NX_AZURE_IOT_PNP_PROPERTIES_QUEUE_INDEX, + (const UCHAR *)AZ_IOT_PNP_CLIENT_PROPERTY_RESPONSE_SUBSCRIBE_TOPIC, + sizeof(AZ_IOT_PNP_CLIENT_PROPERTY_RESPONSE_SUBSCRIBE_TOPIC) - 1, + nx_azure_iot_pnp_client_device_twin_process)) || + (status = nx_azure_iot_hub_transport_receive_message_enable(&(pnp_client_ptr ->nx_azure_iot_pnp_client_transport), + NX_AZURE_IOT_PNP_DESIRED_PROPERTIES_QUEUE_INDEX, + (const UCHAR *)AZ_IOT_PNP_CLIENT_PROPERTY_PATCH_SUBSCRIBE_TOPIC, + sizeof(AZ_IOT_PNP_CLIENT_PROPERTY_PATCH_SUBSCRIBE_TOPIC) - 1, + NX_NULL)) || + (status = nx_azure_iot_hub_transport_receive_message_enable(&(pnp_client_ptr ->nx_azure_iot_pnp_client_transport), + NX_AZURE_IOT_PNP_REPORTED_PROPERTIES_RESPONSE_QUEUE_INDEX, + NX_NULL, 0, + NX_NULL))) + { + LogError(LogLiteralArgs("IoTPnP client failed to enable pnp features : %d"), status); + nx_azure_iot_hub_transport_deinitialize(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport)); + return(status); + } + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_pnp_client_deinitialize(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr) +{ + + /* Check for invalid input pointers. */ + if (pnp_client_ptr == NX_NULL) + { + LogError(LogLiteralArgs("IoTPnP client deinitialize fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + return(nx_azure_iot_hub_transport_deinitialize(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport))); +} + +UINT nx_azure_iot_pnp_client_component_add(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + const UCHAR *component_name_ptr, + UINT component_name_length) +{ +UINT length_of_componet_list; + + if ((pnp_client_ptr == NX_NULL) || + (component_name_ptr == NX_NULL) || + (component_name_length == NX_NULL)) + { + LogError(LogLiteralArgs("IoT PnP add component fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + tx_mutex_get(pnp_client_ptr -> nx_azure_iot_pnp_client_transport.nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + length_of_componet_list = + (UINT)pnp_client_ptr -> iot_pnp_client_core._internal.options.component_names_length; + + if (length_of_componet_list >= NX_AZURE_IOT_PNP_CLIENT_MAX_PNP_COMPONENT_LIST) + { + LogError(LogLiteralArgs("IoT PnP fail due to buffer insufficient")); + tx_mutex_put(pnp_client_ptr -> nx_azure_iot_pnp_client_transport.nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE); + } + + /* Using internal fields for faster update */ + pnp_client_ptr -> nx_azure_iot_pnp_client_component_list[length_of_componet_list] = + az_span_create((UCHAR *)component_name_ptr, (INT)component_name_length); + pnp_client_ptr -> iot_pnp_client_core._internal.options.component_names_length++; + + tx_mutex_put(pnp_client_ptr -> nx_azure_iot_pnp_client_transport.nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_pnp_client_device_cert_set(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_SECURE_X509_CERT *device_certificate) +{ + if (pnp_client_ptr == NX_NULL) + { + LogError(LogLiteralArgs("IoTPnP device certificate set fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + return(nx_azure_iot_hub_transport_device_cert_set(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport), + device_certificate)); +} + +UINT nx_azure_iot_pnp_client_symmetric_key_set(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + const UCHAR *symmetric_key, UINT symmetric_key_length) +{ + if (pnp_client_ptr == NX_NULL) + { + LogError(LogLiteralArgs("IoTPnP client symmetric key fail: Invalid argument")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + return(nx_azure_iot_hub_transport_symmetric_key_auth_set(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport), + nx_azure_iot_pnp_client_signature_get, + nx_azure_iot_pnp_client_password_get, + symmetric_key, symmetric_key_length)); +} + +UINT nx_azure_iot_pnp_client_connect(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + UINT clean_session, UINT wait_option) +{ + + /* Check for invalid input pointers. */ + if (pnp_client_ptr == NX_NULL) + { + LogError(LogLiteralArgs("IoTPnP client connect fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + return(nx_azure_iot_hub_transport_connect(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport), + clean_session, wait_option)); +} + +UINT nx_azure_iot_pnp_client_disconnect(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr) +{ + + /* Check for invalid input pointers. */ + if (pnp_client_ptr == NX_NULL) + { + LogError(LogLiteralArgs("IoTPnP client disconnect fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + return(nx_azure_iot_hub_transport_disconnect(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport))); +} + +UINT nx_azure_iot_pnp_client_connection_status_callback_set(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + VOID (*connection_status_cb)( + struct NX_AZURE_IOT_PNP_CLIENT_STRUCT *client_ptr, + UINT status)) +{ + + /* Check for invalid input pointers. */ + if (pnp_client_ptr == NX_NULL) + { + LogError(LogLiteralArgs("IoTPnP client connect callback fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + return(nx_azure_iot_hub_transport_connection_callback_set(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport), + nx_azure_iot_pnp_client_connection_status_callback, + (NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN)connection_status_cb)); +} + +UINT nx_azure_iot_pnp_client_receive_callback_set(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + UINT message_type, + VOID (*callback_ptr)( + NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + VOID *args), + VOID *callback_args) +{ +UINT message_queue_index; + + if ((pnp_client_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoTPnP receive callback set fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + message_queue_index = nx_azure_iot_pnp_client_mesg_type_to_queue_index(message_type); + + return(nx_azure_iot_hub_transport_receive_message_callback_set(&(pnp_client_ptr ->nx_azure_iot_pnp_client_transport), + message_queue_index, + callback_ptr != NX_NULL ? nx_azure_iot_pnp_client_receive_callback : NX_NULL, + (NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN)callback_ptr, callback_args)); +} + +UINT nx_azure_iot_pnp_client_telemetry_message_create(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + const UCHAR *component_name_ptr, + UINT component_name_length, + NX_PACKET **packet_pptr, + UINT wait_option) +{ +NX_PACKET *packet_ptr; +UINT topic_length; +UINT status; +az_result core_result; +az_span component_name = az_span_create((UCHAR *)component_name_ptr, (INT)component_name_length); + + if ((pnp_client_ptr == NX_NULL) || + (packet_pptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoT PnP telemetry message create fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + status = nx_azure_iot_hub_transport_publish_packet_get(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport), + &packet_ptr, wait_option); + if (status) + { + LogError(LogLiteralArgs("Create telemetry data fail")); + return(status); + } + + topic_length = (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr); + core_result = az_iot_pnp_client_telemetry_get_publish_topic(&(pnp_client_ptr -> iot_pnp_client_core), + component_name, NULL, + (CHAR *)packet_ptr -> nx_packet_prepend_ptr, + topic_length, &topic_length); + if (az_result_failed(core_result)) + { + LogError(LogLiteralArgs("IoT PnP client telemetry message create fail with error status: %d"), core_result); + nx_packet_release(packet_ptr); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + topic_length; + packet_ptr -> nx_packet_length = topic_length; + *packet_pptr = packet_ptr; + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_pnp_client_telemetry_message_delete(NX_PACKET *packet_ptr) +{ + return(nx_packet_release(packet_ptr)); +} + +UINT nx_azure_iot_pnp_client_telemetry_property_add(NX_PACKET *packet_ptr, + const UCHAR *property_name, + USHORT property_name_length, + const UCHAR *property_value, + USHORT property_value_length, + UINT wait_option) +{ + return(nx_azure_iot_topic_property_append(packet_ptr, property_name, property_name_length, + property_value, property_value_length, wait_option)); +} + +UINT nx_azure_iot_pnp_client_telemetry_send(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_PACKET *packet_ptr, + const UCHAR *telemetry_data, + UINT data_size, UINT wait_option) +{ + if ((pnp_client_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoTPnP telemetry send fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + return(nx_azure_iot_hub_transport_publish(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport), packet_ptr, + telemetry_data, data_size, NX_AZURE_IOT_PNP_CLIENT_TELEMETRY_QOS, wait_option)); +} + +UINT nx_azure_iot_pnp_client_command_receive(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + const UCHAR **component_name_pptr, UINT *component_name_length_ptr, + const UCHAR **pnp_command_name_pptr, UINT *pnp_command_name_length_ptr, + VOID **context_pptr, USHORT *context_length_ptr, + NX_AZURE_IOT_JSON_READER *reader_ptr, UINT wait_option) +{ +UINT status; +ULONG topic_offset; +USHORT topic_length; +az_span topic_span; +ULONG message_offset; +ULONG message_length; +NX_PACKET *start_packet_ptr; +NX_PACKET *packet_ptr; +az_result core_result; +az_iot_pnp_client_command_request request; + + if ((pnp_client_ptr == NX_NULL) || + (component_name_pptr == NX_NULL) || + (component_name_length_ptr == NX_NULL) || + (pnp_command_name_pptr == NX_NULL) || + (pnp_command_name_length_ptr == NX_NULL) || + (context_pptr == NX_NULL) || + (context_length_ptr == NX_NULL) || + (reader_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoT PnP client command receive fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + status = nx_azure_iot_hub_transport_message_receive(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport), + NX_AZURE_IOT_PNP_COMMAND_QUEUE_INDEX, 0, + &packet_ptr, wait_option); + if (status) + { + return(status); + } + + status = _nxd_mqtt_process_publish_packet(packet_ptr, &topic_offset, &topic_length, &message_offset, &message_length); + if (status) + { + nx_packet_release(packet_ptr); + return(status); + } + + topic_span = az_span_create(&(packet_ptr -> nx_packet_prepend_ptr[topic_offset]), topic_length); + core_result = az_iot_pnp_client_commands_parse_received_topic(&(pnp_client_ptr -> iot_pnp_client_core), + topic_span, &request); + if (az_result_failed(core_result)) + { + nx_packet_release(packet_ptr); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + packet_ptr -> nx_packet_length = message_length; + start_packet_ptr = packet_ptr; + + /* Adjust packet to pointer to message payload. */ + while (packet_ptr) + { + if ((ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) > message_offset) + { + + /* This packet contains message payload. */ + packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + message_offset; + break; + } + + message_offset -= (ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr); + + /* Set current packet to empty. */ + packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_append_ptr; + + /* Move to next packet. */ + packet_ptr = packet_ptr -> nx_packet_next; + } + + if ((status = nx_azure_iot_json_reader_init(reader_ptr, start_packet_ptr))) + { + nx_packet_release(start_packet_ptr); + return(status); + } + + *component_name_pptr = (const UCHAR *)az_span_ptr(request.component_name); + *component_name_length_ptr = (UINT)az_span_size(request.component_name); + *pnp_command_name_pptr = (const UCHAR *)az_span_ptr(request.command_name); + *pnp_command_name_length_ptr = (UINT)az_span_size(request.command_name); + *context_pptr = (VOID*)az_span_ptr(request.request_id); + *context_length_ptr = (USHORT)az_span_size(request.request_id); + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_pnp_client_command_message_response(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + UINT status_code, VOID *context_ptr, + USHORT context_length, const UCHAR *payload_ptr, + UINT payload_length, UINT wait_option) +{ +NX_PACKET *packet_ptr; +UINT topic_length; +az_span request_id_span; +UINT status; +az_result core_result; + + if ((pnp_client_ptr == NX_NULL) || + (context_ptr == NX_NULL) || + (context_length == 0)) + { + LogError(LogLiteralArgs("IoT PnP command response fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Prepare response packet. */ + status = nx_azure_iot_hub_transport_publish_packet_get(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport), + &packet_ptr, wait_option); + if (status) + { + LogError(LogLiteralArgs("Create response data fail")); + return(status); + } + + topic_length = (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr); + request_id_span = az_span_create((UCHAR*)context_ptr, (INT)context_length); + core_result = az_iot_pnp_client_commands_response_get_publish_topic(&(pnp_client_ptr -> iot_pnp_client_core), + request_id_span, (USHORT)status_code, + (CHAR *)packet_ptr -> nx_packet_prepend_ptr, + topic_length, &topic_length); + if (az_result_failed(core_result)) + { + LogError(LogLiteralArgs("Failed to create the command response topic")); + nx_packet_release(packet_ptr); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + topic_length; + packet_ptr -> nx_packet_length = topic_length; + + if ((payload_ptr == NX_NULL) || (payload_length == 0)) + { + payload_ptr = (const UCHAR *)NX_AZURE_IOT_PNP_CLIENT_EMPTY_JSON; + payload_length = sizeof(NX_AZURE_IOT_PNP_CLIENT_EMPTY_JSON) - 1; + } + + status = nx_azure_iot_hub_transport_publish(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport), packet_ptr, + payload_ptr, payload_length, NX_AZURE_IOT_MQTT_QOS_0, wait_option); + if (status) + { + LogError(LogLiteralArgs("IoTPnP client command response fail: PUBLISH FAIL status: %d"), status); + nx_packet_release(packet_ptr); + return(status); + } + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_pnp_client_reported_properties_create(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr, + UINT wait_option) +{ +UINT status; +NX_PACKET *packet_ptr; +UINT request_id; +UCHAR *buffer_ptr; +ULONG buffer_size; +az_span request_id_span; +az_result core_result; +UINT topic_length; + + if ((pnp_client_ptr == NX_NULL) || + (writer_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoT PnP reported property create fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + status = nx_azure_iot_hub_transport_publish_packet_get(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport), + &packet_ptr, wait_option); + if (status) + { + LogError(LogLiteralArgs("IoT PnP client reported state send fail: BUFFER ALLOCATE FAIL")); + return(status); + } + + buffer_size = (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr); + if (buffer_size <= NX_AZURE_IOT_PNP_CLIENT_U32_MAX_BUFFER_SIZE) + { + LogError(LogLiteralArgs("IoT PnP client reported state send fail: BUFFER INSUFFICENT")); + nx_packet_release(packet_ptr); + return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE); + } + + buffer_size -= NX_AZURE_IOT_PNP_CLIENT_U32_MAX_BUFFER_SIZE; + + /* Generate odd request id for reported properties send */ + status = nx_azure_iot_pnp_client_twin_request_id_get(pnp_client_ptr, + (UCHAR *)(packet_ptr -> nx_packet_data_end - + NX_AZURE_IOT_PNP_CLIENT_U32_MAX_BUFFER_SIZE), + NX_AZURE_IOT_PNP_CLIENT_U32_MAX_BUFFER_SIZE, + &request_id_span, &request_id, NX_TRUE); + + if (status) + { + LogError(LogLiteralArgs("IoT PnP client reported state send failed to get request id")); + nx_packet_release(packet_ptr); + return(status); + } + + core_result = az_iot_pnp_client_property_patch_get_publish_topic(&(pnp_client_ptr -> iot_pnp_client_core), + request_id_span, + (CHAR *)packet_ptr -> nx_packet_prepend_ptr, + buffer_size, &topic_length); + if (az_result_failed(core_result)) + { + LogError(LogLiteralArgs("IoT PnP client reported state send fail: NX_AZURE_IOT_PNP_CLIENT_TOPIC_SIZE is too small.")); + nx_packet_release(packet_ptr); + return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE); + } + + packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + topic_length; + packet_ptr -> nx_packet_length = topic_length; + + /* todo: use the macro for this magic number, possibly share it with nx_azure_iot.h */ + buffer_ptr = packet_ptr -> nx_packet_prepend_ptr - 7; + + /* encode topic length */ + buffer_ptr[5] = (UCHAR)(packet_ptr -> nx_packet_length >> 8); + buffer_ptr[6] = (UCHAR)(packet_ptr -> nx_packet_length & 0xFF); + + /* encode request id */ + buffer_ptr[4] = (UCHAR)((request_id & 0xFF)); + request_id >>= 8; + buffer_ptr[3] = (UCHAR)((request_id & 0xFF)); + request_id >>= 8; + buffer_ptr[2] = (UCHAR)((request_id & 0xFF)); + request_id >>= 8; + buffer_ptr[1] = (UCHAR)(request_id & 0xFF); + + if ((status = nx_azure_iot_json_writer_init(writer_ptr, packet_ptr, wait_option)) || + (status = nx_azure_iot_json_writer_append_begin_object(writer_ptr))) + { + nx_packet_release(packet_ptr); + return(status); + } + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_pnp_client_reported_property_component_begin(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr, + const UCHAR *component_name_ptr, + UINT component_name_length) +{ +az_result core_result; +az_span component_name = az_span_create((UCHAR *)component_name_ptr, (INT)component_name_length); + + if ((pnp_client_ptr == NX_NULL) || + (writer_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoT PnP reported property begin fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + core_result = az_iot_pnp_client_property_builder_begin_component(&(pnp_client_ptr -> iot_pnp_client_core), + &(writer_ptr -> json_writer), component_name); + if (az_result_failed(core_result)) + { + LogError(LogLiteralArgs("IoT PnP failed to append component, core error : %d"), core_result); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_pnp_client_reported_property_component_end(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr) +{ +az_result core_result; + + if ((pnp_client_ptr == NX_NULL) || + (writer_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoT PnP reported property end fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + core_result = az_iot_pnp_client_property_builder_end_component(&(pnp_client_ptr -> iot_pnp_client_core), + &(writer_ptr -> json_writer)); + if (az_result_failed(core_result)) + { + LogError(LogLiteralArgs("IoT PnP failed to append component, core error : %d"), core_result); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_pnp_client_reported_property_status_begin(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr, + const UCHAR *property_name_ptr, UINT property_name_length, + UINT ack_code, ULONG ack_version, + const UCHAR *ack_description_ptr, UINT ack_description_length) +{ +az_span property_name; +az_span description; +az_result core_result; + + if ((pnp_client_ptr == NX_NULL) || + (writer_ptr == NX_NULL) || + (property_name_ptr == NX_NULL) || + (property_name_length == 0) ) + { + LogError(LogLiteralArgs("IoT PnP client begin reported status failed: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + property_name = az_span_create((UCHAR *)property_name_ptr, (INT)property_name_length); + description = az_span_create((UCHAR *)ack_description_ptr, (INT)ack_description_length); + + core_result = az_iot_pnp_client_property_builder_begin_reported_status(&(pnp_client_ptr -> iot_pnp_client_core), + &(writer_ptr -> json_writer), + property_name, (int32_t)ack_code, + (int32_t)ack_version, description); + if (az_result_failed(core_result)) + { + LogError(LogLiteralArgs("Failed to prefix data with core error : %d"), core_result); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_pnp_client_reported_property_status_end(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr) +{ +az_result core_result; + + if ((pnp_client_ptr == NX_NULL) || + (writer_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoT PnP client end reported status failed: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + core_result = az_iot_pnp_client_property_builder_end_reported_status(&(pnp_client_ptr -> iot_pnp_client_core), + &(writer_ptr -> json_writer)); + if (az_result_failed(core_result)) + { + LogError(LogLiteralArgs("Failed to suffix data with core error : %d"), core_result); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_pnp_client_report_properties_response_callback_set(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + VOID (*callback_ptr)( + NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + UINT request_id, + UINT response_status, + ULONG version, + VOID *args), + VOID *callback_args) +{ + if (pnp_client_ptr == NX_NULL) + { + LogError(LogLiteralArgs("IoTPnP client device twin set callback fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + return(nx_azure_iot_hub_transport_receive_message_callback_set(&(pnp_client_ptr ->nx_azure_iot_pnp_client_transport), + NX_AZURE_IOT_PNP_REPORTED_PROPERTIES_RESPONSE_QUEUE_INDEX, + callback_ptr != NX_NULL ? nx_azure_iot_pnp_client_reported_property_receive_callback : NX_NULL, + (NX_AZURE_IOT_HUB_TRANSPORT_GENERIC_FN)callback_ptr, callback_args)); +} + +UINT nx_azure_iot_pnp_client_reported_properties_send(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr, + UINT *request_id_ptr, UINT *response_status_ptr, + ULONG *version_ptr, UINT wait_option) +{ +NX_PACKET *packet_ptr; +NX_PACKET *response_packet_ptr; +UINT topic_length; +UINT request_id = 0; +ULONG topic_offset; +USHORT length; +UCHAR *buffer_ptr; +UINT status; + + if ((pnp_client_ptr == NX_NULL) || + (writer_ptr == NX_NULL) || + (writer_ptr -> packet_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoT PnP client reported state send fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Check if twin response is subscribed */ + if ((status = nx_azure_iot_hub_transport_receive_message_is_subscribed(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport), + NX_AZURE_IOT_PNP_PROPERTIES_QUEUE_INDEX, + wait_option))) + { + LogError(LogLiteralArgs("IoTPnP client reported state send fail with error %d"), status); + return(status); + } + + /* Check if the last request was throttled and if the next need to be throttled. */ + if ((status = nx_azure_iot_pnp_client_throttled_check(pnp_client_ptr))) + { + LogError(LogLiteralArgs("IoT PnP client reported state send fail with error %d"), status); + return(status); + } + + if (writer_ptr -> json_writer._internal.bit_stack._internal.current_depth > 1) + { + LogError(LogLiteralArgs("IoT PnP client reported state send fail with JSON wrong state")); + return(NX_AZURE_IOT_WRONG_STATE); + } + + /* TODO: Need public api to get object depth */ + if (writer_ptr -> json_writer._internal.bit_stack._internal.current_depth > 0) + { + if ((status = nx_azure_iot_json_writer_append_end_object(writer_ptr))) + { + LogError(LogLiteralArgs("IoT PnP client reported state send fail to close object with error %d"), status); + return(status); + } + } + + /* Steps. + * 1. Publish message to topic "$iothub/twin/PATCH/properties/reported/?$rid={request id}" + * 2. Wait for the response if required. + * 3. Return result if present. + * */ + + packet_ptr = writer_ptr -> packet_ptr; + buffer_ptr = packet_ptr -> nx_packet_prepend_ptr - 7; + + topic_length = (UINT)((buffer_ptr[5] << 8) | buffer_ptr[6]); + + request_id += (buffer_ptr[1] & 0xFF); + request_id <<= 8; + request_id += (buffer_ptr[2] & 0xFF); + request_id <<= 8; + request_id += (buffer_ptr[3] & 0xFF); + request_id <<= 8; + request_id += (buffer_ptr[4] & 0xFF); + + status = nx_azure_iot_hub_transport_request_response(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport), + request_id, packet_ptr, topic_length, NX_NULL, 0, + NX_AZURE_IOT_PNP_REPORTED_PROPERTIES_RESPONSE_QUEUE_INDEX, + &response_packet_ptr, wait_option); + if (status) + { + LogError(LogLiteralArgs("IoTPnP client reported state send fail: append failed")); + return(status); + } + + /* Ownership of packet is taken by MQTT stack */ + writer_ptr -> packet_ptr = NX_NULL; + + if (request_id_ptr) + { + *request_id_ptr = request_id; + } + + if (response_packet_ptr == NX_NULL) + { + LogError(LogLiteralArgs("IoT PnP client reported state not responded")); + if (pnp_client_ptr -> nx_azure_iot_pnp_client_transport.nx_azure_iot_hub_transport_state != + NX_AZURE_IOT_HUB_TRANSPORT_STATUS_CONNECTED) + { + return(NX_AZURE_IOT_DISCONNECTED); + } + + return(NX_AZURE_IOT_NO_PACKET); + } + + if ((status = nx_azure_iot_hub_transport_process_publish_packet(response_packet_ptr -> nx_packet_prepend_ptr, + &topic_offset, &length))) + { + nx_packet_release(response_packet_ptr); + return(status); + } + + if ((status = nx_azure_iot_pnp_client_device_twin_parse(pnp_client_ptr, + response_packet_ptr, topic_offset, length, + NX_NULL, version_ptr, NX_NULL, + response_status_ptr))) + { + nx_packet_release(response_packet_ptr); + return(status); + } + + /* Release message block. */ + nx_packet_release(response_packet_ptr); + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_pnp_client_properties_request(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + UINT wait_option) +{ +UINT status; +UINT topic_length; +UINT buffer_size; +NX_PACKET *packet_ptr; +az_span request_id_span; +UINT request_id; +az_result core_result; + + if (pnp_client_ptr == NX_NULL) + { + LogError(LogLiteralArgs("IoT PnP client device twin get request fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + if ((status = nx_azure_iot_hub_transport_receive_message_is_subscribed(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport), + NX_AZURE_IOT_PNP_PROPERTIES_QUEUE_INDEX, + wait_option))) + { + LogError(LogLiteralArgs("IoTPnP client device twin publish fail with error %d"), status); + return(status); + } + + /* Check if the last request was throttled and if the next need to be throttled. */ + if ((status = nx_azure_iot_pnp_client_throttled_check(pnp_client_ptr))) + { + LogError(LogLiteralArgs("IoT PnP client device twin get request failed with error %d"), status); + return(status); + } + + /* Steps. + * 1. Publish message to topic "$iothub/twin/GET/?$rid={request id}" + * */ + status = nx_azure_iot_hub_transport_publish_packet_get(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport), + &packet_ptr, wait_option); + if (status) + { + LogError(LogLiteralArgs("IoT PnP client device twin get request fail: BUFFER ALLOCATE FAIL")); + return(status); + } + + buffer_size = (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr); + if (buffer_size <= NX_AZURE_IOT_PNP_CLIENT_U32_MAX_BUFFER_SIZE) + { + LogError(LogLiteralArgs("IoT PnP client device twin get request fail: BUFFER ALLOCATE FAIL")); + nx_packet_release(packet_ptr); + return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE); + } + + buffer_size -= NX_AZURE_IOT_PNP_CLIENT_U32_MAX_BUFFER_SIZE; + + /* Generate even request id for twin properties request. */ + status = nx_azure_iot_pnp_client_twin_request_id_get(pnp_client_ptr, + (UCHAR *)(packet_ptr -> nx_packet_data_end - + NX_AZURE_IOT_PNP_CLIENT_U32_MAX_BUFFER_SIZE), + NX_AZURE_IOT_PNP_CLIENT_U32_MAX_BUFFER_SIZE, + &request_id_span, &request_id, NX_FALSE); + if (status) + { + LogError(LogLiteralArgs("IoT PnP client device twin failed to get request id")); + nx_packet_release(packet_ptr); + return(status); + } + + core_result = az_iot_pnp_client_property_document_get_publish_topic(&(pnp_client_ptr -> iot_pnp_client_core), + request_id_span, (CHAR *)packet_ptr -> nx_packet_prepend_ptr, + buffer_size, &topic_length); + if (az_result_failed(core_result)) + { + LogError(LogLiteralArgs("IoT PnP client device twin get topic fail.")); + nx_packet_release(packet_ptr); + return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE); + } + + packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + topic_length; + packet_ptr -> nx_packet_length = topic_length; + + status = nx_azure_iot_hub_transport_publish(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport), packet_ptr, + NX_NULL, 0, NX_AZURE_IOT_MQTT_QOS_0, wait_option); + if (status) + { + LogError(LogLiteralArgs("IoTPnP client device twin: PUBLISH FAIL status: %d"), status); + nx_packet_release(packet_ptr); + return(status); + } + + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_pnp_client_properties_receive(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT_JSON_READER *reader_ptr, + ULONG *desired_properties_version_ptr, + UINT wait_option) +{ +UINT status; +ULONG topic_offset; +USHORT topic_length; +az_result core_result; +az_span topic_span; +az_iot_pnp_client_property_response out_twin_response; +NX_PACKET *packet_ptr; +int32_t version; + + if ((pnp_client_ptr == NX_NULL) || (reader_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoT PnP client device twin receive failed: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Steps. + * 1. Check if the twin document is available to receive from linklist. + * 2. If present check the response. + * 3. Return the payload of the response. + * */ + status = nx_azure_iot_hub_transport_message_receive(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport), + NX_AZURE_IOT_PNP_PROPERTIES_QUEUE_INDEX, 0, + &packet_ptr, wait_option); + if (status) + { + LogError(LogLiteralArgs("IoT PnP client device twin receive failed status: %d"), status); + return(status); + } + + if (nx_azure_iot_hub_transport_process_publish_packet(packet_ptr -> nx_packet_prepend_ptr, &topic_offset, + &topic_length)) + { + + /* Message not supported. It will be released. */ + nx_packet_release(packet_ptr); + return(NX_AZURE_IOT_INVALID_PACKET); + } + + topic_span = az_span_create(&(packet_ptr -> nx_packet_prepend_ptr[topic_offset]), (INT)topic_length); + core_result = az_iot_pnp_client_property_parse_received_topic(&(pnp_client_ptr -> iot_pnp_client_core), + topic_span, &out_twin_response); + if (az_result_failed(core_result)) + { + + /* Topic name does not match device twin format. */ + nx_packet_release(packet_ptr); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + if ((out_twin_response.status < 200) || (out_twin_response.status >= 300)) + { + nx_packet_release(packet_ptr); + return(NX_AZURE_IOT_SERVER_RESPONSE_ERROR); + } + + if ((status = nx_azure_iot_hub_transport_adjust_payload(packet_ptr))) + { + nx_packet_release(packet_ptr); + return(status); + } + + if ((status = nx_azure_iot_json_reader_init(reader_ptr, packet_ptr))) + { + nx_packet_release(packet_ptr); + return(status); + } + + if (desired_properties_version_ptr) + { + core_result = az_iot_pnp_client_property_get_property_version(&(pnp_client_ptr -> iot_pnp_client_core), + &(reader_ptr -> json_reader), + AZ_IOT_PNP_CLIENT_PROPERTY_RESPONSE_TYPE_GET, + &version); + if (az_result_failed(core_result)) + { + nx_azure_iot_json_reader_deinit(reader_ptr); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + /* Re-initialize the JSON reader state */ + if ((status = nx_azure_iot_json_reader_init(reader_ptr, packet_ptr))) + { + nx_packet_release(packet_ptr); + return(status); + } + + *desired_properties_version_ptr = (ULONG)version; + } + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_pnp_client_desired_properties_receive(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT_JSON_READER *reader_ptr, + ULONG *properties_version_ptr, + UINT wait_option) +{ +UINT status; +NX_PACKET *packet_ptr; +ULONG topic_offset; +USHORT topic_length; + + if ((pnp_client_ptr == NX_NULL) || + (reader_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoT PnP client device twin receive properties failed: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Steps. + * 1. Check if the desired properties document is available to receive from linklist. + * 2. Parse result if present. + * 3. Return parse result. + * */ + status = nx_azure_iot_hub_transport_message_receive(&(pnp_client_ptr -> nx_azure_iot_pnp_client_transport), + NX_AZURE_IOT_PNP_DESIRED_PROPERTIES_QUEUE_INDEX, 0, + &packet_ptr, wait_option); + if (status) + { + return(status); + } + + if (nx_azure_iot_hub_transport_process_publish_packet(packet_ptr -> nx_packet_prepend_ptr, &topic_offset, + &topic_length)) + { + + /* Message not supported. It will be released. */ + nx_packet_release(packet_ptr); + return(NX_AZURE_IOT_INVALID_PACKET); + } + + if ((status = nx_azure_iot_pnp_client_device_twin_parse(pnp_client_ptr, packet_ptr, + topic_offset, topic_length, + NX_NULL, properties_version_ptr, + NX_NULL, NX_NULL))) + { + nx_packet_release(packet_ptr); + return(status); + } + + if ((status = nx_azure_iot_hub_transport_adjust_payload(packet_ptr))) + { + nx_packet_release(packet_ptr); + return(status); + } + + if ((status = nx_azure_iot_json_reader_init(reader_ptr, packet_ptr))) + { + nx_packet_release(packet_ptr); + return(status); + } + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_pnp_client_desired_component_property_value_next(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT_JSON_READER *reader_ptr, UINT message_type, + const UCHAR **component_pptr, UINT *component_len_ptr, + NX_AZURE_IOT_JSON_READER *name_value_reader_ptr) +{ +az_span component_name; +az_iot_pnp_client_property_response_type type; +az_result core_result; + + if ((pnp_client_ptr == NX_NULL) || + (reader_ptr == NX_NULL) || + (component_pptr == NX_NULL) || + (component_len_ptr == NX_NULL) ) + { + LogError(LogLiteralArgs("IoT PnP client desired component next property failed: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + if ((message_type != NX_AZURE_IOT_PNP_DESIRED_PROPERTIES) && + (message_type != NX_AZURE_IOT_PNP_PROPERTIES)) + { + LogError(LogLiteralArgs("Invalid message type passed")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Copy reader control block but do not give NX_PACKET ownership */ + *name_value_reader_ptr = *reader_ptr; + name_value_reader_ptr -> packet_ptr = NX_NULL; + type = (message_type == NX_AZURE_IOT_PNP_DESIRED_PROPERTIES) ? AZ_IOT_PNP_CLIENT_PROPERTY_RESPONSE_TYPE_DESIRED_PROPERTIES : + AZ_IOT_PNP_CLIENT_PROPERTY_RESPONSE_TYPE_GET; + + core_result = az_iot_pnp_client_property_get_next_component_property(&(pnp_client_ptr -> iot_pnp_client_core), + &(reader_ptr -> json_reader), + type, &component_name, + &(name_value_reader_ptr -> json_reader)); + if (core_result == AZ_ERROR_IOT_END_OF_PROPERTIES) + { + return(NX_AZURE_IOT_NOT_FOUND); + } + else if (az_result_failed(core_result)) + { + LogError(LogLiteralArgs("Failed to parse document with core error : %d"), core_result); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + *component_pptr = az_span_ptr(component_name); + *component_len_ptr = (UINT)az_span_size(component_name); + + return(NX_AZURE_IOT_SUCCESS); +} diff --git a/addons/azure_iot/nx_azure_iot_pnp_client.h b/addons/azure_iot/nx_azure_iot_pnp_client.h new file mode 100644 index 00000000..dfe8e341 --- /dev/null +++ b/addons/azure_iot/nx_azure_iot_pnp_client.h @@ -0,0 +1,677 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/* Version: 6.1 PnP Preview 1 */ + +/** + * @file nx_azure_iot_pnp_client.h + * + * @brief Definition for the Azure IoT PnP client. + * + */ + +#ifndef NX_AZURE_IOT_PNP_CLIENT_H +#define NX_AZURE_IOT_PNP_CLIENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "azure/iot/az_iot_pnp_client.h" +#include "nx_azure_iot_hub_transport.h" +#include "nx_azure_iot.h" +#include "nx_azure_iot_json_reader.h" +#include "nx_azure_iot_json_writer.h" +#include "nx_api.h" +#include "nx_cloud.h" + +/**< Value denoting a message is of "None" type */ +#define NX_AZURE_IOT_PNP_NONE 0x00000000 + +/**< Value denoting a message is of "all" type */ +#define NX_AZURE_IOT_PNP_ALL_MESSAGE 0xFFFFFFFF + +/**< Value denoting a message is a command */ +#define NX_AZURE_IOT_PNP_COMMAND 0x00000002 + +/**< Value denoting a message is a all properties message */ +#define NX_AZURE_IOT_PNP_PROPERTIES 0x00000004 + +/**< Value denoting a message is a desired properties message */ +#define NX_AZURE_IOT_PNP_DESIRED_PROPERTIES 0x00000008 + +/**< Value denoting a message is a reported properties response */ +#define NX_AZURE_IOT_PNP_REPORTED_PROPERTIES_RESPONSE 0x00000010 + +#ifndef NX_AZURE_IOT_PNP_CLIENT_MAX_BACKOFF_IN_SEC +#define NX_AZURE_IOT_PNP_CLIENT_MAX_BACKOFF_IN_SEC (10 * 60) +#endif /* NX_AZURE_IOT_PNP_CLIENT_MAX_BACKOFF_IN_SEC */ + +#ifndef NX_AZURE_IOT_PNP_CLIENT_INITIAL_BACKOFF_IN_SEC +#define NX_AZURE_IOT_PNP_CLIENT_INITIAL_BACKOFF_IN_SEC (3) +#endif /* NX_AZURE_IOT_PNP_CLIENT_INITIAL_BACKOFF_IN_SEC */ + +#ifndef NX_AZURE_IOT_PNP_CLIENT_MAX_BACKOFF_JITTER_PERCENT +#define NX_AZURE_IOT_PNP_CLIENT_MAX_BACKOFF_JITTER_PERCENT (60) +#endif /* NX_AZURE_IOT_PNP_CLIENT_MAX_BACKOFF_JITTER_PERCENT */ + +#ifndef NX_AZURE_IOT_PNP_CLIENT_MAX_PNP_COMPONENT_LIST +#define NX_AZURE_IOT_PNP_CLIENT_MAX_PNP_COMPONENT_LIST (4) +#endif /* NX_AZURE_IOT_PNP_CLIENT_MAX_PNP_COMPONENT_LIST */ + +/* Default TELEMETRY QoS is QoS1 */ +#ifndef NX_AZURE_IOT_PNP_CLIENT_TELEMETRY_QOS +#define NX_AZURE_IOT_PNP_CLIENT_TELEMETRY_QOS NX_AZURE_IOT_MQTT_QOS_1 +#endif /* NX_AZURE_IOT_PNP_CLIENT_TELEMETRY_QOS */ + +/** + * @brief Azure IoT PnP Client struct + * + */ +typedef struct NX_AZURE_IOT_PNP_CLIENT_STRUCT +{ + NX_AZURE_IOT_HUB_TRANSPORT nx_azure_iot_pnp_client_transport; + + UINT nx_azure_iot_pnp_client_request_id; + + az_iot_pnp_client iot_pnp_client_core; + az_span nx_azure_iot_pnp_client_component_list[NX_AZURE_IOT_PNP_CLIENT_MAX_PNP_COMPONENT_LIST]; + UINT nx_azure_iot_pnp_client_throttle_count; + ULONG nx_azure_iot_pnp_client_throttle_end_time; +} NX_AZURE_IOT_PNP_CLIENT; + +/** + * @brief Initialize Azure IoT PnP instance + * + * @param pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @param nx_azure_iot_ptr A pointer to a #NX_AZURE_IOT. + * @param host_name A `UCHAR` pointer to IoTHub hostname. Must be `NULL` terminated. + * @param[in] host_name_length Length of `host_name`. Does not include the `NULL` terminator. + * @param[in] device_id A `UCHAR` pointer to the device ID. + * @param[in] device_id_length Length of the `device_id`. Does not include the `NULL` terminator. + * @param[in] module_id A `UCHAR` pointer to the module ID. + * @param[in] module_id_length Length of the `module_id`. Does not include the `NULL` terminator. + * @param[in] model_id A `UCHAR` pointer to the model ID. + * @param[in] model_id_length Length of the `model_id`. Does not include the `NULL` terminator. + * @param[in] crypto_array A pointer to an array of `NX_CRYPTO_METHOD`. + * @param[in] crypto_array_size Size of `crypto_array`. + * @param[in] cipher_map A pointer to an array of `NX_CRYPTO_CIPHERSUITE`. + * @param[in] cipher_map_size Size of `cipher_map`. + * @param[in] metadata_memory A `UCHAR` pointer to metadata memory buffer. + * @param[in] memory_size Size of `metadata_memory`. + * @param[in] trusted_certificate A pointer to `NX_SECURE_X509_CERT`, which are the server side certs. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successfully initialized the Azure IoT PnP client. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to initialize the Azure IoT PnP client due to invalid parameter. + * @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to initialize the Azure IoT PnP client due to SDK core error. + */ +UINT nx_azure_iot_pnp_client_initialize(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT *nx_azure_iot_ptr, + const UCHAR *host_name, UINT host_name_length, + const UCHAR *device_id, UINT device_id_length, + const UCHAR *module_id, UINT module_id_length, + const UCHAR *model_id, UINT model_id_length, + const NX_CRYPTO_METHOD **crypto_array, UINT crypto_array_size, + const NX_CRYPTO_CIPHERSUITE **cipher_map, UINT cipher_map_size, + UCHAR *metadata_memory, UINT memory_size, + NX_SECURE_X509_CERT *trusted_certificate); + +/** + * @brief Deinitialize the Azure IoT PnP instance. + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successfully de-initialized the Azure IoT PnP client. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to deinitialize the Azure IoT PnP client due to invalid parameter. + */ +UINT nx_azure_iot_pnp_client_deinitialize(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr); + + +/** + * @brief Add component name to IoT PnP client. + * @note This routine should be called for all the component in the PnP model. + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @param[in] component_name_ptr A pointer to component, that is part of PnP model. + * @param[in] component_name_length Length of the `component_name_ptr`. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successfully add the component name to the PnP client. + * @retval #NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to add the component name due to out of memory. + */ +UINT nx_azure_iot_pnp_client_component_add(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + const UCHAR *component_name_ptr, + UINT component_name_length); + +/** + * @brief Set the client certificate in the IoT PnP client. + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @param[in] device_certificate A pointer to a `NX_SECURE_X509_CERT`, which is the device certificate. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successfully set device certificate to AZ IoT PnP Instance. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to set device certificate to AZ IoT PnP Instance due to invalid parameter. + */ +UINT nx_azure_iot_pnp_client_device_cert_set(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_SECURE_X509_CERT *device_certificate); + +/** + * @brief Set symmetric key in the IoT PnP client. + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @param[in] symmetric_key A pointer to a symmetric key. + * @param[in] symmetric_key_length Length of `symmetric_key`. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successfully set symmetric key to IoT PnP client. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to set symmetric key to IoT PnP client due to invalid parameter. + */ +UINT nx_azure_iot_pnp_client_symmetric_key_set(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + const UCHAR *symmetric_key, UINT symmetric_key_length); + +/** + * @brief Connect to IoT Hub. + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @param[in] clean_session Can be set to `0` to re-use current session, or `1` to start new session + * @param[in] wait_option Number of ticks to wait for internal resources to be available. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if connected to Azure IoT Hub. + * @retval #NX_AZURE_IOT_CONNECTING Successfully started connection but not yet completed. + * @retval #NX_AZURE_IOT_ALREADY_CONNECTED Already connected to Azure IoT Hub. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to connect to Azure IoT Hub due to invalid parameter. + * @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to connect to Azure IoT Hub due to SDK core error. + * @retval #NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to connect to Azure IoT Hub due to buffer size is too small. + * @retval NX_DNS_QUERY_FAILED Fail to connect to Azure IoT Hub due to hostname can not be resolved. + * @retval NX_NO_PACKET Fail to connect to Azure IoT Hub due to no available packet in pool. + * @retval NX_INVALID_PARAMETERS Fail to connect to Azure IoT Hub due to invalid parameters. + * @retval NX_SECURE_TLS_INSUFFICIENT_METADATA_SPACE Fail to connect to Azure IoT Hub due to insufficient metadata space. + * @retval NX_SECURE_TLS_UNSUPPORTED_CIPHER Fail to connect to Azure IoT Hub due to unsupported cipher. + * @retval NXD_MQTT_ALREADY_CONNECTED Fail to connect to Azure IoT Hub due to MQTT session is not disconnected. + * @retval NXD_MQTT_CONNECT_FAILURE Fail to connect to Azure IoT Hub due to TCP/TLS connect error. + * @retval NXD_MQTT_COMMUNICATION_FAILURE Fail to connect to Azure IoT Hub due to MQTT connect error. + * @retval NXD_MQTT_ERROR_SERVER_UNAVAILABLE Fail to connect to Azure IoT Hub due to server unavailable. + * @retval NXD_MQTT_ERROR_NOT_AUTHORIZED Fail to connect to Azure IoT Hub due to authentication error. + */ +UINT nx_azure_iot_pnp_client_connect(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + UINT clean_session, UINT wait_option); + +/** + * @brief Disconnect from IoT Hub. + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if client disconnects. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to disconnect due to invalid parameter. + */ +UINT nx_azure_iot_pnp_client_disconnect(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr); + +/** + * @brief Sets connection status callback function + * @details This routine sets the connection status callback. This callback function is + * invoked when PnP client status is changed, such as when the client is connected to IoT Hub. + * The different statuses include: + * + * - #NX_AZURE_IOT_SUCCESS + * - NX_SECURE_TLS_ALERT_RECEIVED + * - NX_SECURE_TLS_NO_SUPPORTED_CIPHERS + * - NX_SECURE_X509_CHAIN_VERIFY_FAILURE + * - NXD_MQTT_CONNECT_FAILURE + * - NXD_MQTT_ERROR_SERVER_UNAVAILABLE + * - NXD_MQTT_ERROR_NOT_AUTHORIZED + * - NX_AZURE_IOT_DISCONNECTED + * + * Setting the callback function to `NULL` disables the callback function. + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @param[in] connection_status_cb Pointer to a callback function invoked on connection status is changed. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if connection status callback is set. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to set connection status callback due to invalid parameter. + */ +UINT nx_azure_iot_pnp_client_connection_status_callback_set(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + VOID (*connection_status_cb)( + struct NX_AZURE_IOT_PNP_CLIENT_STRUCT *pnp_client_ptr, + UINT status)); + +/** + * @brief Sets receive callback function + * @details This routine sets the IoT PnP receive callback function. This callback + * function is invoked when a message is received from Azure IoT hub. Setting the + * callback function to `NULL` disables the callback function. Message types can be: + * + * - #NX_AZURE_IOT_PNP_COMMAND + * - #NX_AZURE_IOT_PNP_PROPERTIES + * - #NX_AZURE_IOT_PNP_DESIRED_PROPERTIES + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @param[in] message_type Message type of callback function. + * @param[in] callback_ptr Pointer to a callback function invoked if the specified message type is received. + * @param[in] callback_args Pointer to an argument passed to callback function. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if callback function is set. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to set receive callback due to invalid parameter. + * @retval #NX_AZURE_IOT_NOT_SUPPORTED Fail to set receive callback due to message_type not supported. + */ +UINT nx_azure_iot_pnp_client_receive_callback_set(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + UINT message_type, + VOID (*callback_ptr)( + NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + VOID *args), + VOID *callback_args); + +/** + * @brief Creates PnP telemetry message. + * @details This routine prepares a packet for sending telemetry data. After the packet is properly created, + * application owns the `NX_PACKET` and can add additional user-defined properties before sending out. + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @param[in] component_name_ptr A pointer to a component name. + * @param[in] component_name_length Length of `component_name_ptr`. Does not include the `NULL` terminator. + * @param[out] packet_pptr Returned allocated `NX_PACKET` on success. Caller owns the `NX_PACKET` memory. + * @param[in] wait_option Ticks to wait if no packet is available. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if a packet is allocated. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to allocate telemetry message due to invalid parameter. + * @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to allocate telemetry message due to SDK core error. + * @retval NX_NO_PACKET Fail to allocate telemetry message due to no available packet in pool. + */ +UINT nx_azure_iot_pnp_client_telemetry_message_create(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + const UCHAR *component_name_ptr, + UINT component_name_length, + NX_PACKET **packet_pptr, + UINT wait_option); + +/** + * @brief Deletes PnP telemetry message + * + * @param[in] packet_ptr The `NX_PACKET` to release. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if a packet is deallocated. + */ +UINT nx_azure_iot_pnp_client_telemetry_message_delete(NX_PACKET *packet_ptr); + +/** + * @brief Add property to telemetry message + * @details This routine allows an application to add user-defined properties to a telemetry message + * before it is being sent. This routine can be called multiple times to add all the properties to + * the message. The properties are stored in the sequence which the routine is being called. + * The property must be added after a telemetry packet is created, and before the telemetry + * message is being sent. + * + * @param[in] packet_ptr A pointer to telemetry property packet. + * @param[in] property_name Pointer to property name. + * @param[in] property_name_length Length of property name. + * @param[in] property_value Pointer to property value. + * @param[in] property_value_length Length of property value. + * @param[in] wait_option Ticks to wait if packet needs to be expanded. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if property is added. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to add property due to invalid parameter. + * @retval NX_NO_PACKET Fail to add property due to no available packet in pool. + */ +UINT nx_azure_iot_pnp_client_telemetry_property_add(NX_PACKET *packet_ptr, + const UCHAR *property_name, + USHORT property_name_length, + const UCHAR *property_value, + USHORT property_value_length, + UINT wait_option); + +/** + * @brief Sends PnP telemetry message to IoTHub. + * @details This routine sends PnP telemetry to IoTHub, with `packet_ptr` containing all the properties. + * On successful return of this function, ownership of `NX_PACKET` is released. + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @param[in] packet_ptr A pointer to telemetry property packet. + * @param[in] telemetry_data Pointer to telemetry data. + * @param[in] data_size Size of telemetry data. + * @param[in] wait_option Ticks to wait for message to be sent. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if telemetry message is sent out. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to send telemetry message due to invalid parameter. + * @retval #NX_AZURE_IOT_INVALID_PACKET Fail to send telemetry message due to packet is invalid. + * @retval NXD_MQTT_PACKET_POOL_FAILURE Fail to send telemetry message due to no available packet in pool. + * @retval NXD_MQTT_COMMUNICATION_FAILURE Fail to send telemetry message due to TCP/TLS error. + * @retval NX_NO_PACKET Fail to send telemetry message due to no available packet in pool. + */ +UINT nx_azure_iot_pnp_client_telemetry_send(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_PACKET *packet_ptr, + const UCHAR *telemetry_data, + UINT data_size, UINT wait_option); + +/** + * @brief Receives receiving PnP command message from IoTHub + * @details This routine receives PnP command message from IoT Hub. If there are no + * messages in the receive queue, this routine can block. The amount of time it waits for a + * message is determined by the `wait_option` parameter. + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @param[out] component_name_pptr Return a pointer to PnP component name on success. + * @param[out] component_name_length_ptr Return length of `*component_name_pptr` on success. + * @param[out] pnp_command_name_pptr Return a pointer to PnP command name on success. + * @param[out] pnp_command_name_length_ptr Return length of `*pnp_command_name_pptr` on success. + * @param[out] context_pptr Return a pointer to the context pointer on success. + * @param[out] context_length_ptr Return length of `context` on success. + * @param[out] reader_ptr Return `NX_AZURE_IOT_JSON_READER` containing the method payload on success. + * @param[in] wait_option Ticks to wait for message to arrive. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if PnP command message is received. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to receive PnP command message due to invalid parameter. + * @retval #NX_AZURE_IOT_NOT_ENABLED Fail to receive PnP command message due to it is not enabled. + * @retval #NX_AZURE_IOT_NO_PACKET Fail to receive PnP command message due to timeout. + * @retval #NX_AZURE_IOT_INVALID_PACKET Fail to receive PnP command message due to invalid packet. + * @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to receive PnP command message due to SDK core error. + * @retval #NX_AZURE_IOT_DISCONNECTED Fail to receive PnP command message due to disconnect. + */ +UINT nx_azure_iot_pnp_client_command_receive(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + const UCHAR **component_name_pptr, UINT *component_name_length_ptr, + const UCHAR **pnp_command_name_pptr, UINT *pnp_command_name_length_ptr, + VOID **context_pptr, USHORT *context_length_ptr, + NX_AZURE_IOT_JSON_READER *reader_ptr, UINT wait_option); + +/** + * @brief Return response to PnP command message from IoTHub + * @details This routine returns response to the PnP command message from IoT Hub. + * @note request_id ties the correlation between PnP command message receive and response. + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @param[in] status_code Status code for PnP command. + * @param[in] context_ptr Pointer to context return from nx_azure_iot_pnp_client_command_receive(). + * @param[in] context_length Length of context. + * @param[in] payload Pointer to `UCHAR` containing the payload for the PnP command response. Payload is in JSON format. + * @param[in] payload_length Length of `payload` + * @param[in] wait_option Ticks to wait for message to send. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if PnP command response is send. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to send PnP command response due to invalid parameter. + * @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to send PnP command response due to SDK core error. + * @retval NX_NO_PACKET Fail send PnP command response due to no available packet in pool. + */ +UINT nx_azure_iot_pnp_client_command_message_response(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + UINT status_code, VOID *context_ptr, + USHORT context_length, const UCHAR *payload_ptr, + UINT payload_length, UINT wait_option); + +/** + * @brief Creates PnP reported property message writer. + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT + * @param[out] writer_ptr A pointer to a #NX_AZURE_IOT_JSON_WRITER + * @param[in] wait_option Ticks to wait for writer creation + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if a message writer is created. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to create message writer due to invalid parameter. + * @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to create message writer due to SDK core error. + * @retval NX_NO_PACKET Fail to create message writer due to no available packet in pool. + */ +UINT nx_azure_iot_pnp_client_reported_properties_create(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr, + UINT wait_option); + +/** + * @brief Append the necessary characters to a reported property JSON payload belonging to a + * subcomponent. + * + * The payload will be of the form: + * + * @code + * "reported": { + * "<component_name>": { + * "__t": "c", + * "temperature": 23 + * } + * } + * @endcode + * + * @note This API should be used in conjunction with + * nx_azure_iot_pnp_client_reported_property_component_end(). + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT + * @param[in] writer_ptr A pointer to a #NX_AZURE_IOT_JSON_WRITER + * @param[in] component_name_ptr A pointer to a component name + * @param[in] component_name_length Length of `component_name_ptr` + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if JSON payload was prefixed successfully. + */ +UINT nx_azure_iot_pnp_client_reported_property_component_begin(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr, + const UCHAR *component_name_ptr, + UINT component_name_length); + +/** + * @brief Append the necessary characters to end a reported property JSON payload belonging to a + * subcomponent. + * + * @note This API should be used in conjunction with + * nx_azure_iot_pnp_client_reported_property_component_begin(). + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT + * @param[in] writer_ptr A pointer to a #NX_AZURE_IOT_JSON_WRITER + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS The JSON payload was suffixed successfully. + */ +UINT nx_azure_iot_pnp_client_reported_property_component_end(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr); + +/** + * @brief Begin a property response payload with confirmation status. + * + * This API should be used in response to an incoming desired property. More details can be found + * here: + * + * https://docs.microsoft.com/en-us/azure/iot-pnp/concepts-convention#writable-properties + * + * The payload will be of the form: + * + * **Without component** + * @code + * //{ + * // "<property_name>":{ + * // "ac": <ack_code>, + * // "av": <ack_version>, + * // "ad": "<ack_description>", + * // "value": <user_value> + * // } + * //} + * @endcode + * + * To send a status for a property belonging to a component, first call the + * nx_azure_iot_pnp_client_reported_property_status_begin() API to prefix the payload with the + * necessary identification. The API call flow would look like the following with the listed JSON + * payload being generated. + * + * **With component** + * @code + * + * nx_azure_iot_pnp_client_reported_property_component_begin() + * nx_azure_iot_pnp_client_reported_property_status_begin() + * // Append user value here (<user_value>) + * nx_azure_iot_pnp_client_reported_property_status_end() + * nx_azure_iot_pnp_client_reported_property_component_end() + * + * //{ + * // "<component_name>": { + * // "__t": "c", + * // "<property_name>": { + * // "ac": <ack_code>, + * // "av": <ack_version>, + * // "ad": "<ack_description>", + * // "value": <user_value> + * // } + * // } + * //} + * @endcode + * + * @note This API should be used in conjunction with + * nx_azure_iot_pnp_client_reported_property_status_end(). + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @param[in] writer_ptr A pointer to a #NX_AZURE_IOT_JSON_WRITER + * @param[in] property_name_ptr A pointer to property name. + * @param[in] property_name_length Length of `property_name_ptr`. + * @param[in] ack_code The HTTP-like status code to respond with. + * @param[in] ack_version The version of the property the application is acknowledging. + * @param[in] ack_description_ptr An optional pointer to description detailing the context or any details about + * the acknowledgement. This can be empty string. + * @param[in] ack_description_length Length of ack_description_ptr + * + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful appended JSON prefix. + */ +UINT nx_azure_iot_pnp_client_reported_property_status_begin(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr, + const UCHAR *property_name_ptr, UINT property_name_length, + UINT ack_code, ULONG ack_version, + const UCHAR *ack_description_ptr, UINT ack_description_length); + +/** + * @brief End a property response payload with confirmation status. + * + * @note This API should be used in conjunction with + * nx_azure_iot_pnp_client_reported_property_status_begin(). + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @param[in] writer_ptr A pointer to a #NX_AZURE_IOT_JSON_WRITER + * + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful appended JSON suffix. + */ +UINT nx_azure_iot_pnp_client_reported_property_status_end(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr); + +/** + * @brief Sets reported properties response callback function + * @details This routine sets the reponse receive callback function for reported properties. This callback + * function is invoked when a response is received from Azure IoT hub for reported properties and no + * thread is waiting for response. Setting the callback function to `NULL` disables the callback + * function. + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @param[in] callback_ptr Pointer to a callback function invoked. + * @param[in] callback_args Pointer to an argument passed to callback function. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if callback function is set. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to set callback due to invalid parameter. + */ +UINT nx_azure_iot_pnp_client_report_properties_response_callback_set(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + VOID (*callback_ptr)( + NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + UINT request_id, + UINT response_status, + ULONG version, + VOID *args), + VOID *callback_args); + +/** + * @brief Sends PnP reported properties message to IoTHub. + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @param[in] writer_ptr A pointer to a #NX_AZURE_IOT_JSON_WRITER + * @param[out] request_id_ptr Request Id assigned to the request. + * @param[out] response_status_ptr Status return for successful send of reported properties. + * @param[out] version_ptr Version return for successful send of reported properties. + * @param[in] wait_option Ticks to wait for message to send. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if reported properties is sent. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to send reported properties due to invalid parameter. + * @retval #NX_AZURE_IOT_NOT_ENABLED Fail to send reported properties due to device twin is not enabled. + * @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to send reported properties due to SDK core error. + * @retval #NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to send reported properties due to buffer size is too small. + * @retval #NX_AZURE_IOT_NO_PACKET Fail to send reported properties due to no packet available. + * @retval NX_NO_PACKET Fail to send reported properties due to no packet available. + * @retval #NX_AZURE_IOT_DISCONNECTED Fail to send reported properties due to disconnect. + */ +UINT nx_azure_iot_pnp_client_reported_properties_send(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT_JSON_WRITER *reported_property_message, + UINT *request_id_ptr, UINT *response_status_ptr, + ULONG *version_ptr, UINT wait_option); + +/** + * @brief Request complete to get all properties + * @details This routine requests all properties. + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @param[in] wait_option Ticks to wait for request to send. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if request get all properties is sent. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to request get all properties due to invalid parameter. + * @retval #NX_AZURE_IOT_NO_SUBSCRIBE_ACK Fail to request get all properties due to no subscribe ack. + * @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to request get all properties due to SDK core error. + * @retval #NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to request get all properties due to buffer size is too small. + * @retval #NX_AZURE_IOT_NO_PACKET Fail to request get all properties due to no packet available. + * @retval NX_NO_PACKET Fail to request get all properties due to no packet available. + */ +UINT nx_azure_iot_pnp_client_properties_request(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + UINT wait_option); + +/** + * @brief Receive all the properties + * @details This routine receives all the properties. + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @param[out] reader_ptr A pointer to a #NX_AZURE_IOT_JSON_READER containing all the properties + * @param[out] desired_properties_version_ptr A pointer to `ULONG`, containing version of desired properties + * @param[in] wait_option Ticks to wait for message to receive. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if all properties is received. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to receive all properties due to invalid parameter. + * @retval #NX_AZURE_IOT_NOT_ENABLED Fail to receive all properties due to it is not enabled. + * @retval #NX_AZURE_IOT_NO_PACKET Fail to receive all properties due to timeout. + * @retval #NX_AZURE_IOT_INVALID_PACKET Fail to receive all properties due to invalid packet. + * @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to receive all properties due to SDK core error. + * @retval #NX_AZURE_IOT_SERVER_RESPONSE_ERROR Response code from server is not 2xx. + * @retval #NX_AZURE_IOT_DISCONNECTED Fail to receive all properties due to disconnect. + */ +UINT nx_azure_iot_pnp_client_properties_receive(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT_JSON_READER *reader_ptr, + ULONG *desired_properties_version_ptr, + UINT wait_option); + +/** + * @brief Receive desired properties form IoTHub + * @details This routine receives desired properties from IoTHub. + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @param[out] reader_ptr A pointer to a #NX_AZURE_IOT_JSON_READER containing desired properties + * @param[out] desired_properties_version_ptr A pointer to `ULONG`, containing version of properties + * @param[in] wait_option Ticks to wait for message to receive. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if desired properties is received. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to receive desired properties due to invalid parameter. + * @retval #NX_AZURE_IOT_NOT_ENABLED Fail to receive desired properties due to it is not enabled. + * @retval #NX_AZURE_IOT_NO_PACKET Fail to receive desired properties due to timeout. + * @retval #NX_AZURE_IOT_INVALID_PACKET Fail to receive desired properties due to invalid packet. + * @retval #NX_AZURE_IOT_DISCONNECTED Fail to receive desired properties due to disconnect. + */ +UINT nx_azure_iot_pnp_client_desired_properties_receive(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT_JSON_READER *reader_ptr, + ULONG *properties_version_ptr, + UINT wait_option); + +/** + * @brief Return the next desired property in the property document passed. + * + * @param[in] pnp_client_ptr A pointer to a #NX_AZURE_IOT_PNP_CLIENT. + * @param[in] reader_ptr A pointer to a #NX_AZURE_IOT_JSON_READER containing properties document + * @param[in] message_type Type of document, only valid value are NX_AZURE_IOT_PNP_DESIRED_PROPERTIES or NX_AZURE_IOT_PNP_PROPERTIES + * @param[out] component_pptr A pointer to component name for the property returned using name_value_reader_ptr + * @param[out] component_len_ptr Length of the component name + * @param[out] name_value_reader_ptr A pointer to a #NX_AZURE_IOT_JSON_READER containing property name and value + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if next desired property is found. + */ +UINT nx_azure_iot_pnp_client_desired_component_property_value_next(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT_JSON_READER *reader_ptr, UINT message_type, + const UCHAR **component_pptr, UINT *component_len_ptr, + NX_AZURE_IOT_JSON_READER *name_value_reader_ptr); +#ifdef __cplusplus +} +#endif +#endif /* NX_AZURE_IOT_PNP_CLIENT_H */ diff --git a/addons/azure_iot/nx_azure_iot_provisioning_client.c b/addons/azure_iot/nx_azure_iot_provisioning_client.c index 78a4d014..134d7f6c 100644 --- a/addons/azure_iot/nx_azure_iot_provisioning_client.c +++ b/addons/azure_iot/nx_azure_iot_provisioning_client.c @@ -9,7 +9,7 @@ /* */ /**************************************************************************/ -/* Version: 6.1 */ +/* Version: 6.1 PnP Preview 1 */ #include "nx_azure_iot_provisioning_client.h" diff --git a/addons/azure_iot/nx_azure_iot_provisioning_client.h b/addons/azure_iot/nx_azure_iot_provisioning_client.h index cba71332..6b552413 100644 --- a/addons/azure_iot/nx_azure_iot_provisioning_client.h +++ b/addons/azure_iot/nx_azure_iot_provisioning_client.h @@ -9,7 +9,7 @@ /* */ /**************************************************************************/ -/* Version: 6.1 */ +/* Version: 6.1 PnP Preview 1 */ /** * @file nx_azure_iot_provisioning_client.h diff --git a/addons/azure_iot/samples/common/nx_azure_iot_pnp_helpers.c b/addons/azure_iot/samples/common/nx_azure_iot_pnp_helpers.c deleted file mode 100644 index 167195ef..00000000 --- a/addons/azure_iot/samples/common/nx_azure_iot_pnp_helpers.c +++ /dev/null @@ -1,443 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#include "nx_azure_iot_pnp_helpers.h" - -#include <stdio.h> - -#include "azure/core/az_json.h" -#include "nx_api.h" - -/* Telemetry message property used to indicate the message's component. */ -static const CHAR sample_pnp_telemetry_component_property[] = "$.sub"; - -/* Reported property response property keys. */ -static const CHAR sample_pnp_component_type_property_name[] = "__t"; -static const CHAR reported_component_type_value[] = "c"; -static const CHAR reported_value_property_name[] = "value"; -static const CHAR reported_status_property_name[] = "ac"; -static const CHAR reported_version_property_name[] = "av"; -static const CHAR reported_description_property_name[] = "ad"; - -/* PnP command seperator. */ -static const az_span command_separator = AZ_SPAN_LITERAL_FROM_STR("*"); - -/* Device twin keys */ -static const CHAR sample_iot_hub_twin_desired_version[] = "$version"; -static const CHAR sample_iot_hub_twin_desired[] = "desired"; - -/* Move reader to the value of property name. */ -static UINT sample_json_child_token_move(NX_AZURE_IOT_JSON_READER *json_reader_ptr, - UCHAR *property_name_ptr, UINT property_name_len) -{ - while (nx_azure_iot_json_reader_next_token(json_reader_ptr) == NX_AZURE_IOT_SUCCESS) - { - if ((nx_azure_iot_json_reader_token_type(json_reader_ptr) == - NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME) && - nx_azure_iot_json_reader_token_is_text_equal(json_reader_ptr, - property_name_ptr, - property_name_len)) - { - if (nx_azure_iot_json_reader_next_token(json_reader_ptr)) - { - printf("Failed to read next token\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - return(NX_AZURE_IOT_SUCCESS); - } - else if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == - NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) - { - if (nx_azure_iot_json_reader_skip_children(json_reader_ptr)) - { - printf("Failed to skip child of complex object\r\n"); - return(NX_NOT_SUCCESSFUL); - } - } - else if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == - NX_AZURE_IOT_READER_TOKEN_END_OBJECT) - { - return(NX_AZURE_IOT_NOT_FOUND); - } - } - - return(NX_AZURE_IOT_NOT_FOUND); -} - -/* Visit component property Object and call callback on each property of that component. */ -static UINT visit_component_properties(UCHAR *component_name_ptr, UINT component_name_len, - NX_AZURE_IOT_JSON_READER *json_reader_ptr, UINT version, - UCHAR *scratch_buf, UINT scratch_buf_len, - VOID (*sample_desired_property_callback)(UCHAR *component_name_ptr, - UINT component_name_len, - UCHAR *property_name_ptr, UINT property_name_len, - NX_AZURE_IOT_JSON_READER property_value_reader, UINT version, - VOID *userContextCallback), VOID *context_ptr) -{ -UINT len; - - while (nx_azure_iot_json_reader_next_token(json_reader_ptr) == NX_AZURE_IOT_SUCCESS) - { - if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME) - { - if (nx_azure_iot_json_reader_token_string_get(json_reader_ptr, scratch_buf, scratch_buf_len, &len)) - { - printf("Failed to get string property value\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - if (nx_azure_iot_json_reader_next_token(json_reader_ptr)) - { - printf("Failed to get next token\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - if ((len == sizeof(sample_pnp_component_type_property_name) - 1) && - (memcmp((VOID *)scratch_buf, (VOID *)sample_pnp_component_type_property_name, len) == 0)) - { - continue; - } - - if ((len == sizeof(sample_iot_hub_twin_desired_version) - 1) && - (memcmp((VOID *)scratch_buf, (VOID *)sample_iot_hub_twin_desired_version, len) == 0)) - { - continue; - } - - sample_desired_property_callback(component_name_ptr, component_name_len, - scratch_buf, len, *json_reader_ptr, version, context_ptr); - - } - - if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) - { - if (nx_azure_iot_json_reader_skip_children(json_reader_ptr)) - { - printf("Failed to skip children of object\r\n"); - return(NX_NOT_SUCCESSFUL); - } - } - else if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == NX_AZURE_IOT_READER_TOKEN_END_OBJECT) - { - break; - } - } - - return(NX_AZURE_IOT_SUCCESS); -} - -/* Check if component is part of component list. */ -static UINT is_component_in_model(UCHAR *component_name_ptr, UINT component_name_len, - CHAR **sample_components_ptr, UINT sample_components_num, - UINT *out_index) -{ -UINT index = 0; - - if (component_name_ptr == NX_NULL || component_name_len == 0) - { - return(NX_NOT_SUCCESSFUL); - } - - while (index < sample_components_num) - { - if ((component_name_len == strlen(sample_components_ptr[index])) && - (memcmp((VOID *)component_name_ptr, (VOID *)sample_components_ptr[index], component_name_len) == 0)) - { - *out_index = index; - return(NX_AZURE_IOT_SUCCESS); - } - - index++; - } - - return(NX_AZURE_IOT_NOT_FOUND); -} - -/* Parse PnP command names. */ -UINT nx_azure_iot_pnp_helper_command_name_parse(const UCHAR *method_name_ptr, UINT method_name_length, - const UCHAR **component_name_pptr, UINT *component_name_length_ptr, - const UCHAR **pnp_command_name_pptr, UINT *pnp_command_name_length_ptr) -{ -INT index; -az_span method_name = az_span_create((UCHAR *)method_name_ptr, (INT)method_name_length); - - if ((index = az_span_find(method_name, command_separator)) != -1) - { - /* If a separator character is present in the device method name, then a command on a subcomponent of - the model is being targeted (e.g. thermostat1*getMaxMinReport). */ - *component_name_pptr = method_name_ptr; - *component_name_length_ptr = (UINT)index; - *pnp_command_name_pptr = method_name_ptr + index + 1; - *pnp_command_name_length_ptr = method_name_length - (UINT)index - 1; - } - else - { - /* The separator character is optional. If it is not present, it indicates a command of the root - component and not a subcomponent (e.g. "reboot"). */ - *component_name_pptr = NULL; - *component_name_length_ptr = 0; - *pnp_command_name_pptr = method_name_ptr; - *pnp_command_name_length_ptr = method_name_length; - } - - return(NX_AZURE_IOT_SUCCESS); -} - -/* Parse twin data and call callback on each desired property. */ -UINT nx_azure_iot_pnp_helper_twin_data_parse(NX_AZURE_IOT_JSON_READER *json_reader_ptr, UINT is_partial, - CHAR **sample_components_ptr, UINT sample_components_num, - UCHAR *scratch_buf, UINT scratch_buf_len, - VOID (*sample_desired_property_callback)(UCHAR *component_name_ptr, - UINT component_name_len, UCHAR *property_name_ptr, - UINT property_name_len, - NX_AZURE_IOT_JSON_READER property_value_reader, UINT version, - VOID *userContextCallback), - VOID *context_ptr) -{ -NX_AZURE_IOT_JSON_READER copy_json_reader; -UINT version; -UINT len; -UINT index; -UINT status; - - if ((status = nx_azure_iot_json_reader_next_token(json_reader_ptr))) - { - printf("Failed to initialize json reader: error %d\r\n", status); - return(status); - } - - if (!is_partial && sample_json_child_token_move(json_reader_ptr, - (UCHAR *)sample_iot_hub_twin_desired, - sizeof(sample_iot_hub_twin_desired) - 1)) - { - printf("Failed to get desired property\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - copy_json_reader = *json_reader_ptr; - if (sample_json_child_token_move(©_json_reader, - (UCHAR *)sample_iot_hub_twin_desired_version, - sizeof(sample_iot_hub_twin_desired_version) - 1) || - nx_azure_iot_json_reader_token_int32_get(©_json_reader, (int32_t *)&version)) - { - printf("Failed to get version\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - while (nx_azure_iot_json_reader_next_token(json_reader_ptr) == NX_AZURE_IOT_SUCCESS) - { - if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == - NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME) - { - if (nx_azure_iot_json_reader_token_string_get(json_reader_ptr, scratch_buf, - scratch_buf_len, &len)) - { - printf("Failed to string value for property name\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - if (nx_azure_iot_json_reader_next_token(json_reader_ptr)) - { - printf("Failed to next token\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - if ((len == sizeof(sample_iot_hub_twin_desired_version) - 1) && - (memcmp((VOID *)sample_iot_hub_twin_desired_version, (VOID *)scratch_buf, len) == 0)) - { - continue; - } - - if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT && - sample_components_ptr != NX_NULL && - (is_component_in_model(scratch_buf, len, - sample_components_ptr, sample_components_num, - &index) == NX_AZURE_IOT_SUCCESS)) - { - if (visit_component_properties((UCHAR *)sample_components_ptr[index], - strlen(sample_components_ptr[index]), - json_reader_ptr, version, scratch_buf, scratch_buf_len, - sample_desired_property_callback, context_ptr)) - { - printf("Failed to visit component properties\r\n"); - return(NX_NOT_SUCCESSFUL); - } - } - else - { - sample_desired_property_callback(NX_NULL, 0, scratch_buf, len, - *json_reader_ptr, version, context_ptr); - - if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == - NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) - { - if (nx_azure_iot_json_reader_skip_children(json_reader_ptr)) - { - printf("Failed to skip children of object\r\n"); - return(NX_NOT_SUCCESSFUL); - } - } - } - } - else if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == - NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) - { - if (nx_azure_iot_json_reader_skip_children(json_reader_ptr)) - { - printf("Failed to skip children of object\r\n"); - return(NX_NOT_SUCCESSFUL); - } - } - else if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == - NX_AZURE_IOT_READER_TOKEN_END_OBJECT) - { - break; - } - } - - return(NX_AZURE_IOT_SUCCESS); -} - -/* Create PnP telemetry message. */ -UINT nx_azure_iot_pnp_helper_telemetry_message_create(NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr, - UCHAR *component_name, UINT component_name_len, - NX_PACKET **packet_pptr, UINT wait_option) -{ -UINT status; - - /* Create a telemetry message packet. */ - if ((status = nx_azure_iot_hub_client_telemetry_message_create(iothub_client_ptr, packet_pptr, wait_option))) - { - printf("Telemetry message create failed!: error code = 0x%08x\r\n", status); - } - - /* If the component will be used, then specify this as a property of the message. */ - else if ((component_name != NULL) && - (status = nx_azure_iot_hub_client_telemetry_property_add(*packet_pptr, - (UCHAR *)sample_pnp_telemetry_component_property, - (USHORT)sizeof(sample_pnp_telemetry_component_property) - 1, - component_name, (USHORT)component_name_len, - NX_WAIT_FOREVER)) != NX_AZURE_IOT_SUCCESS) - { - printf("nx_azure_iot_hub_client_telemetry_property_add=%s failed, error=%d", - sample_pnp_telemetry_component_property, status); - nx_azure_iot_hub_client_telemetry_message_delete(*packet_pptr); - } - else - { - status = NX_AZURE_IOT_SUCCESS; - } - - return(status); -} - -/* Build PnP reported property into user provided buffer. */ -UINT nx_azure_iot_pnp_helper_build_reported_property(UCHAR *component_name_ptr, UINT component_name_len, - UINT (*append_reported_property)(NX_AZURE_IOT_JSON_WRITER *json_builder_ptr, - VOID *context), - VOID *context, NX_AZURE_IOT_JSON_WRITER *json_builder_ptr) -{ -UINT status; - - if (nx_azure_iot_json_writer_append_begin_object(json_builder_ptr) || - (component_name_ptr != NX_NULL && - (nx_azure_iot_json_writer_append_property_name(json_builder_ptr, - component_name_ptr, - component_name_len) || - nx_azure_iot_json_writer_append_begin_object(json_builder_ptr) || - nx_azure_iot_json_writer_append_property_with_string_value(json_builder_ptr, - (UCHAR *)sample_pnp_component_type_property_name, - sizeof(sample_pnp_component_type_property_name) - 1, - (UCHAR *)reported_component_type_value, - sizeof(reported_component_type_value) - 1))) || - (append_reported_property(json_builder_ptr, context) != NX_AZURE_IOT_SUCCESS) || - (component_name_ptr != NX_NULL && nx_azure_iot_json_writer_append_end_object(json_builder_ptr)) || - nx_azure_iot_json_writer_append_end_object(json_builder_ptr)) - { - printf("Failed to build reported property\r\n"); - status = NX_NOT_SUCCESSFUL; - } - else - { - status = NX_AZURE_IOT_SUCCESS; - } - - return(status); -} - -/* Build reported property with status. */ -UINT nx_azure_iot_pnp_helper_build_reported_property_with_status(UCHAR *component_name_ptr, UINT component_name_len, - UCHAR *property_name_ptr, UINT property_name_len, - UINT (*append_value)(NX_AZURE_IOT_JSON_WRITER *builder, - VOID *context), - VOID *context, - INT result, UCHAR *description_ptr, - UINT description_len, - UINT ack_version, - NX_AZURE_IOT_JSON_WRITER *json_builder_ptr) -{ - if (nx_azure_iot_json_writer_append_begin_object(json_builder_ptr)) - { - printf("Failed initializing json writer \r\n"); - return(NX_NOT_SUCCESSFUL); - } - - if (component_name_ptr != NX_NULL && - (nx_azure_iot_json_writer_append_property_name(json_builder_ptr, - component_name_ptr, - component_name_len) || - nx_azure_iot_json_writer_append_begin_object(json_builder_ptr) || - nx_azure_iot_json_writer_append_property_with_string_value(json_builder_ptr, - (UCHAR *)sample_pnp_component_type_property_name, - sizeof(sample_pnp_component_type_property_name) - 1, - (UCHAR *)reported_component_type_value, - sizeof(reported_component_type_value) - 1))) - { - printf("Failed build reported property with status message \r\n"); - return(NX_NOT_SUCCESSFUL); - } - - if (nx_azure_iot_json_writer_append_property_name(json_builder_ptr, - property_name_ptr, property_name_len) || - nx_azure_iot_json_writer_append_begin_object(json_builder_ptr) || - nx_azure_iot_json_writer_append_property_name(json_builder_ptr, - (UCHAR *)reported_value_property_name, - sizeof(reported_value_property_name) - 1) || - (append_value(json_builder_ptr, context) != NX_AZURE_IOT_SUCCESS) || - nx_azure_iot_json_writer_append_property_with_int32_value(json_builder_ptr, - (UCHAR *)reported_status_property_name, - sizeof(reported_status_property_name) - 1, - result) || - nx_azure_iot_json_writer_append_property_with_string_value(json_builder_ptr, - (UCHAR *)reported_description_property_name, - sizeof(reported_description_property_name) - 1, - description_ptr, description_len) || - nx_azure_iot_json_writer_append_property_with_int32_value(json_builder_ptr, - (UCHAR *)reported_version_property_name, - sizeof(reported_version_property_name) - 1, - (INT)ack_version) || - nx_azure_iot_json_writer_append_end_object(json_builder_ptr) || - nx_azure_iot_json_writer_append_end_object(json_builder_ptr)) - { - printf("Failed build reported property with status message\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - if (component_name_ptr != NX_NULL && - nx_azure_iot_json_writer_append_end_object(json_builder_ptr)) - { - printf("Failed build reported property with status message\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - return(NX_AZURE_IOT_SUCCESS); -} diff --git a/addons/azure_iot/samples/common/nx_azure_iot_pnp_helpers.h b/addons/azure_iot/samples/common/nx_azure_iot_pnp_helpers.h deleted file mode 100644 index ba6ffb7e..00000000 --- a/addons/azure_iot/samples/common/nx_azure_iot_pnp_helpers.h +++ /dev/null @@ -1,125 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#ifndef NX_AZURE_IOT_PNP_HELPERS_H -#define NX_AZURE_IOT_PNP_HELPERS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "nx_azure_iot_json_reader.h" -#include "nx_azure_iot_json_writer.h" -#include "nx_azure_iot_hub_client.h" -#include "nx_api.h" - -/** - * @brief Parse PnP command name - * - * @param[in] method_name_ptr Pointer to method name - * @param[in] method_name_length Length of method name - * @param[out] component_name_pptr Pointer to component pointer - * @param[out] component_name_length_ptr Pointer to length of component name length - * @param[out] pnp_command_name_pptr Pointer to command name pointer - * @param[out] pnp_command_name_length_ptr Pointer to length of command name - * @return A `UINT` with the result of the API. - * @retval #NX_AZURE_IOT_SUCCESS Successful if successful parsed command name. - */ -UINT nx_azure_iot_pnp_helper_command_name_parse(const UCHAR *method_name_ptr, UINT method_name_length, - const UCHAR **component_name_pptr, UINT *component_name_length_ptr, - const UCHAR **pnp_command_name_pptr, UINT *pnp_command_name_length_ptr); - -/** - * @brief Parse twin data and call callback on each desired property - * - * @param[in] json_reader_ptr `NX_AZURE_IOT_JSON_READER` pointer containing the twin data - * @param[in] is_partial 1 if twin data is patch else 0 if full twin document - * @param[in] sample_components_ptr Pointer to list of all components name pointers - * @param[in] sample_components_num Size of component list - * @param[in] scratch_buf Temporary buffer used for staging property names out of the JSON document - * @param[in] scratch_buf_len Temporary buffer length size - * @param[in] sample_desired_property_callback Callback called with each desired property - * @param[in] context_ptr Context passed to the callback - * @return A `UINT` with the result of the API. - * @retval #NX_AZURE_IOT_SUCCESS Successful if successful parsed twin data. - */ -UINT nx_azure_iot_pnp_helper_twin_data_parse(NX_AZURE_IOT_JSON_READER *json_reader_ptr, UINT is_partial, - CHAR **sample_components_ptr, UINT sample_components_num, - UCHAR *scratch_buf, UINT scratch_buf_len, - VOID (*sample_desired_property_callback)(UCHAR *component_name_ptr, - UINT component_name_len, UCHAR *property_name_ptr, - UINT property_name_len, - NX_AZURE_IOT_JSON_READER property_value_reader, UINT version, - VOID *userContextCallback), - VOID *context_ptr); - -/** - * @brief Create PnP telemetry message - * - * @param[in] iothub_client_ptr Pointer to `NX_AZURE_IOT_HUB_CLIENT` - * @param[in] component_name Pointer to component name - * @param[in] component_name_len Length of component name - * @param[out] packet_pptr `NX_PACKET` return via the API. - * @param[in] wait_option Ticks to wait if no packet is available. - * @return A `UINT` with the result of the API. - * @retval #NX_AZURE_IOT_SUCCESS Successful if successful created NX_PACKET. - */ -UINT nx_azure_iot_pnp_helper_telemetry_message_create(NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr, - UCHAR *component_name, UINT component_name_len, - NX_PACKET **packet_pptr, UINT wait_option); - -/** - * @brief Build PnP reported property into user provided buffer - * - * @param[in] component_name_ptr Pointer to component name - * @param[in] component_name_len Length of component name - * @param[in] append_reported_property Callback to add reported property - * @param[in] context Context pass to callback - * @param[out] json_builder_ptr Pointer to `NX_AZURE_IOT_JSON_WRITER`, containing the json reported property - * @return A `UINT` with the result of the API. - * @retval #NX_AZURE_IOT_SUCCESS Successful if successful created reported property message. - */ -UINT nx_azure_iot_pnp_helper_build_reported_property(UCHAR *component_name_ptr, UINT component_name_len, - UINT (*append_reported_property)(NX_AZURE_IOT_JSON_WRITER *json_builder_ptr, - VOID *context), - VOID *context, NX_AZURE_IOT_JSON_WRITER *json_builder_ptr); - -/** - * @brief Build reported property with status - * - * @param[in] component_name_ptr Pointer to component name - * @param[in] component_name_len Length of component name - * @param[in] property_name_ptr Pointer to property name - * @param[in] property_name_len Length of property name - * @param[in] append_value Callback to add property value - * @param[in] context Context pass to callback - * @param[in] result Status for reported property - * @param[in] description Pointer to description - * @param[in] description_len Length of description - * @param[in] ack_version ack version - * @param[out] json_builder_ptr Pointer to `NX_AZURE_IOT_JSON_WRITER`, containing the json reported property - * @return A `UINT` with the result of the API. - * @retval #NX_AZURE_IOT_SUCCESS Successful if successful created reported property message. - */ -UINT nx_azure_iot_pnp_helper_build_reported_property_with_status(UCHAR *component_name_ptr, UINT component_name_len, - UCHAR *property_name_ptr, UINT property_name_len, - UINT (*append_value)(NX_AZURE_IOT_JSON_WRITER *builder, - VOID *context), - VOID *context, - INT result, UCHAR *description_ptr, - UINT description_len, - UINT ack_version, - NX_AZURE_IOT_JSON_WRITER *json_builder_ptr); - -#ifdef __cplusplus -} -#endif -#endif /* NX_AZURE_IOT_PNP_HELPERS_H */
\ No newline at end of file diff --git a/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_pnp.c b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_pnp.c index 7b4faac4..908287a0 100644 --- a/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_pnp.c +++ b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_pnp.c @@ -12,7 +12,7 @@ #include <stdio.h> #include "nx_api.h" -#include "nx_azure_iot_hub_client.h" +#include "nx_azure_iot_pnp_client.h" #include "nx_azure_iot_json_reader.h" #include "nx_azure_iot_json_writer.h" #include "nx_azure_iot_provisioning_client.h" @@ -42,11 +42,11 @@ #define SAMPLE_ALL_EVENTS ((ULONG)0xFFFFFFFF) #define SAMPLE_CONNECT_EVENT ((ULONG)0x00000001) #define SAMPLE_INITIALIZATION_EVENT ((ULONG)0x00000002) -#define SAMPLE_METHOD_MESSAGE_EVENT ((ULONG)0x00000004) -#define SAMPLE_DEVICE_TWIN_GET_EVENT ((ULONG)0x00000008) -#define SAMPLE_DEVICE_TWIN_DESIRED_PROPERTY_EVENT ((ULONG)0x00000010) +#define SAMPLE_COMMAND_MESSAGE_EVENT ((ULONG)0x00000004) +#define SAMPLE_DEVICE_PROPERTIES_GET_EVENT ((ULONG)0x00000008) +#define SAMPLE_DEVICE_DESIRED_PROPERTIES_EVENT ((ULONG)0x00000010) #define SAMPLE_TELEMETRY_SEND_EVENT ((ULONG)0x00000020) -#define SAMPLE_DEVICE_TWIN_REPORTED_PROPERTY_EVENT ((ULONG)0x00000040) +#define SAMPLE_DEVICE_REPORTED_PROPERTIES_EVENT ((ULONG)0x00000040) #define SAMPLE_DISCONNECT_EVENT ((ULONG)0x00000080) #define SAMPLE_RECONNECT_EVENT ((ULONG)0x00000100) #define SAMPLE_CONNECTED_EVENT ((ULONG)0x00000200) @@ -83,13 +83,13 @@ typedef struct SAMPLE_CONTEXT_STRUCT NOTE: If user can not make sure sharing memory is safe, IoTHub Client and DPS Client must be defined seperately. */ union SAMPLE_CLIENT_UNION { - NX_AZURE_IOT_HUB_CLIENT iothub_client; + NX_AZURE_IOT_PNP_CLIENT iotpnp_client; #ifdef ENABLE_DPS_SAMPLE NX_AZURE_IOT_PROVISIONING_CLIENT prov_client; #endif /* ENABLE_DPS_SAMPLE */ } client; -#define iothub_client client.iothub_client +#define iotpnp_client client.iotpnp_client #ifdef ENABLE_DPS_SAMPLE #define prov_client client.prov_client #endif /* ENABLE_DPS_SAMPLE */ @@ -136,12 +136,10 @@ static UINT exponential_retry_count; static const CHAR telemetry_name[] = "temperature"; /* Device command. */ -static const CHAR report_method_name[] = "getMaxMinReport"; +static const CHAR report_command_name[] = "getMaxMinReport"; -/* Twin properties. */ +/* Device properties. */ static const CHAR desired_temp_property_name[] = "targetTemperature"; -static const CHAR desired_property_name[] = "desired"; -static const CHAR desired_version_property_name[] = "$version"; static const CHAR reported_max_temp_since_last_reboot[] = "maxTempSinceLastReboot"; static const CHAR report_max_temp_name[] = "maxTemp"; static const CHAR report_min_temp_name[] = "minTemp"; @@ -149,10 +147,6 @@ static const CHAR report_avg_temp_name[] = "avgTemp"; static const CHAR report_start_time_name[] = "startTime"; static const CHAR report_end_time_name[] = "endTime"; static const CHAR reported_temp_property_name[] = "targetTemperature"; -static const CHAR reported_value_property_name[] = "value"; -static const CHAR reported_status_property_name[] = "ac"; -static const CHAR reported_version_property_name[] = "av"; -static const CHAR reported_description_property_name[] = "ad"; static const CHAR temp_response_description[] = "success"; /* Fake device data. */ @@ -167,163 +161,83 @@ static double device_min_temp = SAMPLE_DEAFULT_START_TEMP_CELSIUS; static double device_avg_temp = SAMPLE_DEAFULT_START_TEMP_CELSIUS; static UCHAR scratch_buffer[256]; -/* Move reader to the value of property name. */ -static UINT sample_json_child_token_move(NX_AZURE_IOT_JSON_READER *json_reader, - UCHAR *property_name_ptr, UINT property_name_len) -{ - while (nx_azure_iot_json_reader_next_token(json_reader) == NX_AZURE_IOT_SUCCESS) - { - if ((nx_azure_iot_json_reader_token_type(json_reader) == NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME) && - nx_azure_iot_json_reader_token_is_text_equal(json_reader, - property_name_ptr, - property_name_len)) - { - if (nx_azure_iot_json_reader_next_token(json_reader)) - { - printf("Failed to read next token\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - return(NX_AZURE_IOT_SUCCESS); - } - else if (nx_azure_iot_json_reader_token_type(json_reader) == NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) - { - if (nx_azure_iot_json_reader_skip_children(json_reader)) - { - printf("Failed to skip child of complex object\r\n"); - return(NX_NOT_SUCCESSFUL); - } - } - else if (nx_azure_iot_json_reader_token_type(json_reader) == NX_AZURE_IOT_READER_TOKEN_END_OBJECT) - { - return(NX_AZURE_IOT_NOT_FOUND); - } - } - - return(NX_AZURE_IOT_NOT_FOUND); -} - -/* Build reported property JSON. */ -static UINT sample_build_reported_property(NX_AZURE_IOT_JSON_WRITER *json_builder_ptr, double temp) -{ -UINT ret; - - if (nx_azure_iot_json_writer_append_begin_object(json_builder_ptr) || - nx_azure_iot_json_writer_append_property_with_double_value(json_builder_ptr, - (UCHAR *)reported_max_temp_since_last_reboot, - sizeof(reported_max_temp_since_last_reboot) - 1, - temp, DOUBLE_DECIMAL_PLACE_DIGITS) || - nx_azure_iot_json_writer_append_end_object(json_builder_ptr)) - { - ret = 1; - printf("Failed to build reported property\r\n"); - } - else - { - ret = 0; - } - - return(ret); -} - /* Send desired property response as reported property. */ static VOID sample_send_target_temperature_report(SAMPLE_CONTEXT *context, double current_device_temp_value, - UINT status, UINT version, UCHAR *description_ptr, + UINT status, ULONG version, UCHAR *description_ptr, UINT description_len) { NX_AZURE_IOT_JSON_WRITER json_builder; -UINT bytes_copied; UINT response_status; UINT request_id; -ULONG reported_property_version; - if (nx_azure_iot_json_writer_with_buffer_init(&json_builder, scratch_buffer, sizeof(scratch_buffer))) + if (nx_azure_iot_pnp_client_reported_properties_create(&(context -> iotpnp_client), + &json_builder, NX_WAIT_FOREVER)) { printf("Failed to build reported response\r\n"); return; } - if (nx_azure_iot_json_writer_append_begin_object(&json_builder) || - nx_azure_iot_json_writer_append_property_name(&json_builder, - (UCHAR *)reported_temp_property_name, - sizeof(reported_temp_property_name) - 1) || - nx_azure_iot_json_writer_append_begin_object(&json_builder) || - nx_azure_iot_json_writer_append_property_with_double_value(&json_builder, - (UCHAR *)reported_value_property_name, - sizeof(reported_value_property_name) - 1, - current_device_temp_value, DOUBLE_DECIMAL_PLACE_DIGITS) || - nx_azure_iot_json_writer_append_property_with_int32_value(&json_builder, - (UCHAR *)reported_status_property_name, - sizeof(reported_status_property_name) - 1, - (int32_t)status) || - nx_azure_iot_json_writer_append_property_with_int32_value(&json_builder, - (UCHAR *)reported_version_property_name, - sizeof(reported_version_property_name) - 1, - (int32_t)version) || - nx_azure_iot_json_writer_append_property_with_string_value(&json_builder, - (UCHAR *)reported_description_property_name, - sizeof(reported_description_property_name) - 1, - description_ptr, description_len) || - nx_azure_iot_json_writer_append_end_object(&json_builder) || - nx_azure_iot_json_writer_append_end_object(&json_builder)) + if (nx_azure_iot_pnp_client_reported_property_status_begin(&(context -> iotpnp_client), + &json_builder, (const UCHAR *)reported_temp_property_name, + sizeof(reported_temp_property_name) - 1, + status, version, + description_ptr, description_len) || + nx_azure_iot_json_writer_append_double(&json_builder, + current_device_temp_value, + DOUBLE_DECIMAL_PLACE_DIGITS) || + nx_azure_iot_pnp_client_reported_property_status_end(&(context -> iotpnp_client), &json_builder)) { nx_azure_iot_json_writer_deinit(&json_builder); printf("Failed to build reported response\r\n"); } else { - bytes_copied = nx_azure_iot_json_writer_get_bytes_used(&json_builder); - if (nx_azure_iot_hub_client_device_twin_reported_properties_send(&(context -> iothub_client), - scratch_buffer, bytes_copied, - &request_id, &response_status, - &reported_property_version, - (5 * NX_IP_PERIODIC_RATE))) + if (nx_azure_iot_pnp_client_reported_properties_send(&(context -> iotpnp_client), + &json_builder, &request_id, + &response_status, NX_NULL, + (5 * NX_IP_PERIODIC_RATE))) { printf("Failed to send reported response\r\n"); } + nx_azure_iot_json_writer_deinit(&json_builder); } } -/* Parses device twin document. */ +/* Parses device properties document. */ static UINT sample_parse_desired_temp_property(SAMPLE_CONTEXT *context, NX_AZURE_IOT_JSON_READER *json_reader_ptr, - UINT is_partial) + UINT message_type, ULONG version) { double parsed_value; -UINT version; -NX_AZURE_IOT_JSON_READER copy_json_reader; - - if (nx_azure_iot_json_reader_next_token(json_reader_ptr)) - { - printf("Failed to move to next token\r\n"); - return(NX_NOT_SUCCESSFUL); - } +UINT status; +const UCHAR *component_ptr; +UINT component_len; +NX_AZURE_IOT_JSON_READER name_value_reader; - if (!is_partial && sample_json_child_token_move(json_reader_ptr, - (UCHAR *)desired_property_name, - sizeof(desired_property_name) - 1)) + while ((status = nx_azure_iot_pnp_client_desired_component_property_value_next(&(context -> iotpnp_client), + json_reader_ptr, + message_type, + &component_ptr, &component_len, + &name_value_reader)) == NX_AZURE_IOT_SUCCESS) { - printf("Failed to get desired property\r\n"); - return(NX_NOT_SUCCESSFUL); - } + if (nx_azure_iot_json_reader_token_is_text_equal(&name_value_reader, + (UCHAR *)desired_temp_property_name, + sizeof(desired_temp_property_name) - 1)) + { + if ((status = nx_azure_iot_json_reader_next_token(&name_value_reader)) || + (status = nx_azure_iot_json_reader_token_double_get(&name_value_reader, &parsed_value))) + { + return(status); + } - copy_json_reader = *json_reader_ptr; - if (sample_json_child_token_move(©_json_reader, - (UCHAR *)desired_version_property_name, - sizeof(desired_version_property_name) - 1) || - nx_azure_iot_json_reader_token_int32_get(©_json_reader, (int32_t *)&version)) - { - printf("Failed to get version\r\n"); - return(NX_NOT_SUCCESSFUL); + break; + } } - if (sample_json_child_token_move(json_reader_ptr, - (UCHAR *)desired_temp_property_name, - sizeof(desired_temp_property_name) - 1) || - nx_azure_iot_json_reader_token_double_get(json_reader_ptr, &parsed_value)) + if (status) { - return(NX_NOT_SUCCESSFUL); + return(status); } current_device_temp = parsed_value; @@ -343,13 +257,13 @@ NX_AZURE_IOT_JSON_READER copy_json_reader; device_avg_temp = device_temperature_avg_total / device_temperature_avg_count; sample_send_target_temperature_report(context, current_device_temp, 200, - (UINT)version, (UCHAR *)temp_response_description, + version, (UCHAR *)temp_response_description, sizeof(temp_response_description) - 1); return(NX_AZURE_IOT_SUCCESS); } -/* sample direct method implementation. */ +/* sample direct command implementation. */ static UINT sample_get_maxmin_report(NX_AZURE_IOT_JSON_READER *json_reader_ptr, NX_AZURE_IOT_JSON_WRITER *out_json_builder_ptr) { @@ -358,10 +272,10 @@ UCHAR *start_time = (UCHAR *)fake_start_report_time; UINT start_time_len = sizeof(fake_start_report_time) - 1; UCHAR time_buf[32]; - if (json_reader_ptr != NX_NULL) + /* Check for start time if present */ + if ((status = nx_azure_iot_json_reader_next_token(json_reader_ptr)) == NX_AZURE_IOT_SUCCESS) { - if (nx_azure_iot_json_reader_next_token(json_reader_ptr) || - nx_azure_iot_json_reader_token_string_get(json_reader_ptr, time_buf, + if (nx_azure_iot_json_reader_token_string_get(json_reader_ptr, time_buf, sizeof(time_buf), &start_time_len)) { return(NX_NOT_SUCCESSFUL); @@ -369,7 +283,14 @@ UCHAR time_buf[32]; start_time = time_buf; } - + else + { + if (status != NX_AZURE_IOT_EMPTY_JSON) + { + return(NX_NOT_SUCCESSFUL); + } + } + if (nx_azure_iot_json_writer_append_begin_object(out_json_builder_ptr) || nx_azure_iot_json_writer_append_property_with_double_value(out_json_builder_ptr, (UCHAR *)report_max_temp_name, @@ -405,16 +326,6 @@ UCHAR time_buf[32]; return(status); } -static VOID printf_packet(NX_PACKET *packet_ptr) -{ - while (packet_ptr != NX_NULL) - { - printf("%.*s", (INT)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr), - (CHAR *)packet_ptr -> nx_packet_prepend_ptr); - packet_ptr = packet_ptr -> nx_packet_next; - } -} - static UINT exponential_backoff_with_jitter() { double jitter_percent = (SAMPLE_MAX_EXPONENTIAL_BACKOFF_JITTER_PERCENT / 100.0) * (rand() / ((double)RAND_MAX)); @@ -447,7 +358,7 @@ static VOID exponential_backoff_reset() exponential_retry_count = 0; } -static VOID connection_status_callback(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT status) +static VOID connection_status_callback(NX_AZURE_IOT_PNP_CLIENT *hub_client_ptr, UINT status) { NX_PARAMETER_NOT_USED(hub_client_ptr); @@ -466,31 +377,31 @@ static VOID connection_status_callback(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, } } -static VOID message_receive_callback_twin(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, VOID *context) +static VOID message_receive_callback_properties(NX_AZURE_IOT_PNP_CLIENT *hub_client_ptr, VOID *context) { SAMPLE_CONTEXT *sample_ctx = (SAMPLE_CONTEXT *)context; NX_PARAMETER_NOT_USED(hub_client_ptr); tx_event_flags_set(&(sample_ctx -> sample_events), - SAMPLE_DEVICE_TWIN_GET_EVENT, TX_OR); + SAMPLE_DEVICE_PROPERTIES_GET_EVENT, TX_OR); } -static VOID message_receive_callback_method(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, VOID *context) +static VOID message_receive_callback_command(NX_AZURE_IOT_PNP_CLIENT *hub_client_ptr, VOID *context) { SAMPLE_CONTEXT *sample_ctx = (SAMPLE_CONTEXT *)context; NX_PARAMETER_NOT_USED(hub_client_ptr); tx_event_flags_set(&(sample_ctx -> sample_events), - SAMPLE_METHOD_MESSAGE_EVENT, TX_OR); + SAMPLE_COMMAND_MESSAGE_EVENT, TX_OR); } -static VOID message_receive_callback_desire_property(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, VOID *context) +static VOID message_receive_callback_desire_property(NX_AZURE_IOT_PNP_CLIENT *hub_client_ptr, VOID *context) { SAMPLE_CONTEXT *sample_ctx = (SAMPLE_CONTEXT *)context; NX_PARAMETER_NOT_USED(hub_client_ptr); tx_event_flags_set(&(sample_ctx -> sample_events), - SAMPLE_DEVICE_TWIN_DESIRED_PROPERTY_EVENT, TX_OR); + SAMPLE_DEVICE_DESIRED_PROPERTIES_EVENT, TX_OR); } static VOID sample_connect_action(SAMPLE_CONTEXT *context) @@ -500,7 +411,8 @@ static VOID sample_connect_action(SAMPLE_CONTEXT *context) return; } - context -> action_result = nx_azure_iot_hub_client_connect(&(context -> iothub_client), NX_FALSE, SAMPLE_WAIT_OPTION); + context -> action_result = nx_azure_iot_pnp_client_connect(&(context -> iotpnp_client), + NX_FALSE, SAMPLE_WAIT_OPTION); if (context -> action_result == NX_AZURE_IOT_CONNECTING) { @@ -516,7 +428,8 @@ static VOID sample_connect_action(SAMPLE_CONTEXT *context) context -> state = SAMPLE_STATE_CONNECTED; context -> action_result = - nx_azure_iot_hub_client_device_twin_properties_request(&(context -> iothub_client), NX_WAIT_FOREVER); + nx_azure_iot_pnp_client_properties_request(&(context -> iotpnp_client), + NX_WAIT_FOREVER); } } @@ -528,7 +441,7 @@ static VOID sample_disconnect_action(SAMPLE_CONTEXT *context) return; } - context -> action_result = nx_azure_iot_hub_client_disconnect(&(context -> iothub_client)); + context -> action_result = nx_azure_iot_pnp_client_disconnect(&(context -> iotpnp_client)); context -> state = SAMPLE_STATE_DISCONNECTED; } @@ -542,7 +455,7 @@ static VOID sample_connected_action(SAMPLE_CONTEXT *context) context -> state = SAMPLE_STATE_CONNECTED; context -> action_result = - nx_azure_iot_hub_client_device_twin_properties_request(&(context -> iothub_client), NX_WAIT_FOREVER); + nx_azure_iot_pnp_client_properties_request(&(context -> iotpnp_client), NX_WAIT_FOREVER); } static VOID sample_initialize_iothub(SAMPLE_CONTEXT *context) @@ -559,7 +472,7 @@ UCHAR *iothub_device_id = (UCHAR *)DEVICE_ID; UINT iothub_hostname_length = sizeof(HOST_NAME) - 1; UINT iothub_device_id_length = sizeof(DEVICE_ID) - 1; #endif /* ENABLE_DPS_SAMPLE */ -NX_AZURE_IOT_HUB_CLIENT* iothub_client_ptr = &(context -> iothub_client); +NX_AZURE_IOT_PNP_CLIENT* iotpnp_client_ptr = &(context -> iotpnp_client); if (context -> state != SAMPLE_STATE_INIT) { @@ -582,10 +495,11 @@ NX_AZURE_IOT_HUB_CLIENT* iothub_client_ptr = &(context -> iothub_client); iothub_hostname_length, iothub_hostname, iothub_device_id_length, iothub_device_id); /* Initialize IoTHub client. */ - if ((status = nx_azure_iot_hub_client_initialize(iothub_client_ptr, &nx_azure_iot, + if ((status = nx_azure_iot_pnp_client_initialize(iotpnp_client_ptr, &nx_azure_iot, iothub_hostname, iothub_hostname_length, iothub_device_id, iothub_device_id_length, - (UCHAR *)MODULE_ID, sizeof(MODULE_ID) - 1, + (const UCHAR *)MODULE_ID, sizeof(MODULE_ID) - 1, + (const UCHAR *)SAMPLE_PNP_MODEL_ID, sizeof(SAMPLE_PNP_MODEL_ID) - 1, _nx_azure_iot_tls_supported_crypto, _nx_azure_iot_tls_supported_crypto_size, _nx_azure_iot_tls_ciphersuite_map, @@ -594,7 +508,7 @@ NX_AZURE_IOT_HUB_CLIENT* iothub_client_ptr = &(context -> iothub_client); sizeof(nx_azure_iot_tls_metadata_buffer), &root_ca_cert))) { - printf("Failed on nx_azure_iot_hub_client_initialize!: error code = 0x%08x\r\n", status); + printf("Failed on nx_azure_iot_pnp_client_initialize!: error code = 0x%08x\r\n", status); context -> action_result = status; return; } @@ -612,64 +526,52 @@ NX_AZURE_IOT_HUB_CLIENT* iothub_client_ptr = &(context -> iothub_client); } /* Set device certificate. */ - else if ((status = nx_azure_iot_hub_client_device_cert_set(iothub_client_ptr, &device_certificate))) + else if ((status = nx_azure_iot_pnp_client_device_cert_set(iotpnp_client_ptr, &device_certificate))) { - printf("Failed on nx_azure_iot_hub_client_device_cert_set!: error code = 0x%08x\r\n", status); + printf("Failed on nx_azure_iot_pnp_client_device_cert_set!: error code = 0x%08x\r\n", status); } #else /* Set symmetric key. */ - if ((status = nx_azure_iot_hub_client_symmetric_key_set(iothub_client_ptr, + if ((status = nx_azure_iot_pnp_client_symmetric_key_set(iotpnp_client_ptr, (UCHAR *)DEVICE_SYMMETRIC_KEY, sizeof(DEVICE_SYMMETRIC_KEY) - 1))) { - printf("Failed on nx_azure_iot_hub_client_symmetric_key_set!\r\n"); + printf("Failed on nx_azure_iot_pnp_client_symmetric_key_set!\r\n"); } #endif /* USE_DEVICE_CERTIFICATE */ /* Set connection status callback. */ - else if ((status = nx_azure_iot_hub_client_connection_status_callback_set(iothub_client_ptr, + else if ((status = nx_azure_iot_pnp_client_connection_status_callback_set(iotpnp_client_ptr, connection_status_callback))) { printf("Failed on connection_status_callback!\r\n"); } - else if ((status = nx_azure_iot_hub_client_direct_method_enable(iothub_client_ptr))) - { - printf("Direct method receive enable failed!: error code = 0x%08x\r\n", status); - } - else if ((status = nx_azure_iot_hub_client_device_twin_enable(iothub_client_ptr))) - { - printf("device twin enabled failed!: error code = 0x%08x\r\n", status); - } - else if ((status = nx_azure_iot_hub_client_receive_callback_set(iothub_client_ptr, - NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES, - message_receive_callback_twin, + else if ((status = nx_azure_iot_pnp_client_receive_callback_set(iotpnp_client_ptr, + NX_AZURE_IOT_PNP_PROPERTIES, + message_receive_callback_properties, (VOID *)context))) { - printf("device twin callback set!: error code = 0x%08x\r\n", status); + printf("device properties callback set!: error code = 0x%08x\r\n", status); } - else if ((status = nx_azure_iot_hub_client_receive_callback_set(iothub_client_ptr, - NX_AZURE_IOT_HUB_DIRECT_METHOD, - message_receive_callback_method, + else if ((status = nx_azure_iot_pnp_client_receive_callback_set(iotpnp_client_ptr, + NX_AZURE_IOT_PNP_COMMAND, + message_receive_callback_command, (VOID *)context))) { - printf("device method callback set!: error code = 0x%08x\r\n", status); + printf("device command callback set!: error code = 0x%08x\r\n", status); } - else if ((status = nx_azure_iot_hub_client_receive_callback_set(iothub_client_ptr, - NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES, + else if ((status = nx_azure_iot_pnp_client_receive_callback_set(iotpnp_client_ptr, + NX_AZURE_IOT_PNP_DESIRED_PROPERTIES, message_receive_callback_desire_property, (VOID *)context))) { - printf("device twin desired property callback set!: error code = 0x%08x\r\n", status); - } - else if ((status = nx_azure_iot_hub_client_model_id_set(iothub_client_ptr, (UCHAR *)SAMPLE_PNP_MODEL_ID, sizeof(SAMPLE_PNP_MODEL_ID) - 1))) - { - printf("digital twin modelId set!: error code = 0x%08x\r\n", status); + printf("device desired property callback set!: error code = 0x%08x\r\n", status); } if (status) { - nx_azure_iot_hub_client_deinitialize(iothub_client_ptr); + nx_azure_iot_pnp_client_deinitialize(iotpnp_client_ptr); } context -> action_result = status; @@ -703,7 +605,7 @@ static VOID sample_connection_error_recover(SAMPLE_CONTEXT *context) printf("re-initializing iothub connection, after backoff\r\n"); tx_thread_sleep(exponential_backoff_with_jitter()); - nx_azure_iot_hub_client_deinitialize(&(context -> iothub_client)); + nx_azure_iot_pnp_client_deinitialize(&(context -> iotpnp_client)); context -> state = SAMPLE_STATE_INIT; } break; @@ -741,7 +643,7 @@ static VOID sample_trigger_action(SAMPLE_CONTEXT *context) { context -> last_periodic_action_tick = tx_time_get(); tx_event_flags_set(&(context -> sample_events), SAMPLE_TELEMETRY_SEND_EVENT, TX_OR); - tx_event_flags_set(&(context -> sample_events), SAMPLE_DEVICE_TWIN_REPORTED_PROPERTY_EVENT, TX_OR); + tx_event_flags_set(&(context -> sample_events), SAMPLE_DEVICE_REPORTED_PROPERTIES_EVENT, TX_OR); } } break; @@ -754,18 +656,18 @@ static VOID sample_trigger_action(SAMPLE_CONTEXT *context) } } -static void sample_direct_method_action(SAMPLE_CONTEXT *sample_context_ptr) +static void sample_command_action(SAMPLE_CONTEXT *sample_context_ptr) { -NX_PACKET *packet_ptr; UINT status = 0; -USHORT method_name_length; -const UCHAR *method_name_ptr; +const UCHAR *component_name_ptr; +UINT component_name_length; +const UCHAR *command_name_ptr; +UINT command_name_length; USHORT context_length; VOID *context_ptr; UINT dm_status = 404; UINT response_payload = 0; NX_AZURE_IOT_JSON_READER json_reader; -NX_AZURE_IOT_JSON_READER *json_reader_ptr = NX_NULL; NX_AZURE_IOT_JSON_WRITER json_builder; if (sample_context_ptr -> state != SAMPLE_STATE_CONNECTED) @@ -773,54 +675,33 @@ NX_AZURE_IOT_JSON_WRITER json_builder; return; } - if ((status = nx_azure_iot_hub_client_direct_method_message_receive(&(sample_context_ptr -> iothub_client), - &method_name_ptr, &method_name_length, - &context_ptr, &context_length, - &packet_ptr, NX_WAIT_FOREVER))) + if ((status = nx_azure_iot_pnp_client_command_receive(&(sample_context_ptr -> iotpnp_client), + &component_name_ptr, &component_name_length, + &command_name_ptr, &command_name_length, + &context_ptr, &context_length, + &json_reader, NX_WAIT_FOREVER))) { - printf("Direct method receive failed!: error code = 0x%08x\r\n", status); + printf("Command receive failed!: error code = 0x%08x\r\n", status); return; } - printf("Receive method call: %.*s, with payload:", (INT)method_name_length, (CHAR *)method_name_ptr); - printf_packet(packet_ptr); + printf("Received command: %.*s", (INT)command_name_length, (CHAR *)command_name_ptr); printf("\r\n"); - if ((method_name_length == (sizeof(report_method_name) - 1)) && - (memcmp((VOID *)method_name_ptr, (VOID *)report_method_name, sizeof(report_method_name) - 1) == 0)) + if ((status = nx_azure_iot_json_writer_with_buffer_init(&json_builder, + scratch_buffer, + sizeof(scratch_buffer)))) { - if ((status = nx_azure_iot_json_writer_with_buffer_init(&json_builder, - scratch_buffer, - sizeof(scratch_buffer)))) - { - printf("Failed to initalize json builder response \r\n"); - nx_packet_release(packet_ptr); - return; - } - - if (packet_ptr ->nx_packet_length != 0) - { - if ((status = nx_azure_iot_json_reader_init(&json_reader, packet_ptr))) - { - printf("Failed to init json reader!: error code = 0x%08x\r\n", status); - nx_packet_release(packet_ptr); - } - else - { - json_reader_ptr = &json_reader; - } - } - else - { - nx_packet_release(packet_ptr); - status = NX_AZURE_IOT_SUCCESS; - } + printf("Failed to initialize json builder response \r\n"); + nx_azure_iot_json_reader_deinit(&json_reader); + return; + } - if (status != NX_AZURE_IOT_SUCCESS) - { - dm_status = SAMPLE_COMMAND_ERROR_STATUS; - } - else if (sample_get_maxmin_report(json_reader_ptr, &json_builder) != NX_AZURE_IOT_SUCCESS) + if ((command_name_length == (sizeof(report_command_name) - 1)) && + (memcmp((VOID *)command_name_ptr, (VOID *)report_command_name, + sizeof(report_command_name) - 1) == 0)) + { + if (sample_get_maxmin_report(&json_reader, &json_builder) != NX_AZURE_IOT_SUCCESS) { dm_status = SAMPLE_COMMAND_ERROR_STATUS; } @@ -829,57 +710,45 @@ NX_AZURE_IOT_JSON_WRITER json_builder; dm_status = SAMPLE_COMMAND_SUCCESS_STATUS; response_payload = nx_azure_iot_json_writer_get_bytes_used(&json_builder); } + } - if (json_reader_ptr) - { - nx_azure_iot_json_reader_deinit(json_reader_ptr); - } + nx_azure_iot_json_reader_deinit(&json_reader); - nx_azure_iot_json_writer_deinit(&json_builder); - } - else + if ((status = nx_azure_iot_pnp_client_command_message_response(&(sample_context_ptr -> iotpnp_client), dm_status, + context_ptr, context_length, scratch_buffer, + response_payload, NX_WAIT_FOREVER))) { - nx_packet_release(packet_ptr); + printf("Command response failed!: error code = 0x%08x\r\n", status); } - if ((status = nx_azure_iot_hub_client_direct_method_message_response(&(sample_context_ptr -> iothub_client), dm_status, - context_ptr, context_length, scratch_buffer, - response_payload, NX_WAIT_FOREVER))) - { - printf("Direct method response failed!: error code = 0x%08x\r\n", status); - } + nx_azure_iot_json_writer_deinit(&json_builder); } -static void sample_device_twin_desired_property_action(SAMPLE_CONTEXT *context) +static void sample_device_desired_property_action(SAMPLE_CONTEXT *context) { -NX_PACKET *packet_ptr; UINT status = 0; NX_AZURE_IOT_JSON_READER json_reader; +ULONG properties_version; if (context -> state != SAMPLE_STATE_CONNECTED) { return; } - if ((status = nx_azure_iot_hub_client_device_twin_desired_properties_receive(&(context -> iothub_client), &packet_ptr, - NX_WAIT_FOREVER))) + if ((status = nx_azure_iot_pnp_client_desired_properties_receive(&(context -> iotpnp_client), + &json_reader, &properties_version, + NX_WAIT_FOREVER))) { printf("Receive desired property receive failed!: error code = 0x%08x\r\n", status); return; } - printf("Receive desired property: "); - printf_packet(packet_ptr); + printf("Received desired property"); printf("\r\n"); - if (nx_azure_iot_json_reader_init(&json_reader, packet_ptr)) - { - printf("Failed to initialize json reader\r\n"); - nx_packet_release(packet_ptr); - return; - } - - if (sample_parse_desired_temp_property(context, &json_reader, NX_TRUE) != NX_AZURE_IOT_SUCCESS) + status = sample_parse_desired_temp_property(context, &json_reader, + NX_AZURE_IOT_PNP_DESIRED_PROPERTIES, properties_version); + if (status && (status != NX_AZURE_IOT_NOT_FOUND)) { printf("Failed to parse value\r\n"); } @@ -887,12 +756,11 @@ NX_AZURE_IOT_JSON_READER json_reader; nx_azure_iot_json_reader_deinit(&json_reader); } -static void sample_device_twin_reported_property_action(SAMPLE_CONTEXT *context) +static void sample_device_reported_property_action(SAMPLE_CONTEXT *context) { UINT status = 0; UINT response_status; UINT request_id; -UINT reported_properties_length; NX_AZURE_IOT_JSON_WRITER json_builder; ULONG reported_property_version; @@ -907,28 +775,30 @@ ULONG reported_property_version; return; } - if (nx_azure_iot_json_writer_with_buffer_init(&json_builder, scratch_buffer, sizeof(scratch_buffer))) + if ((status = nx_azure_iot_pnp_client_reported_properties_create(&(context -> iotpnp_client), + &json_builder, NX_WAIT_FOREVER))) { - printf("Failed to init json writer \r\n"); + printf("Failed create reported properties: error code = 0x%08x\r\n", status); return; } - if ((status = sample_build_reported_property(&json_builder, device_max_temp))) + if ((status = nx_azure_iot_json_writer_append_property_with_double_value(&json_builder, + (const UCHAR *)reported_max_temp_since_last_reboot, + sizeof(reported_max_temp_since_last_reboot) - 1, + device_max_temp, DOUBLE_DECIMAL_PLACE_DIGITS))) { printf("Build reported property failed: error code = 0x%08x\r\n", status); nx_azure_iot_json_writer_deinit(&json_builder); return; } - reported_properties_length = nx_azure_iot_json_writer_get_bytes_used(&json_builder); - if ((status = nx_azure_iot_hub_client_device_twin_reported_properties_send(&(context -> iothub_client), - scratch_buffer, - reported_properties_length, - &request_id, &response_status, - &reported_property_version, - (5 * NX_IP_PERIODIC_RATE)))) + if ((status = nx_azure_iot_pnp_client_reported_properties_send(&(context -> iotpnp_client), + &json_builder, + &request_id, &response_status, + &reported_property_version, + (5 * NX_IP_PERIODIC_RATE)))) { - printf("Device twin reported properties failed!: error code = 0x%08x\r\n", status); + printf("Reported properties failed!: error code = 0x%08x\r\n", status); nx_azure_iot_json_writer_deinit(&json_builder); return; } @@ -937,43 +807,39 @@ ULONG reported_property_version; if ((response_status < 200) || (response_status >= 300)) { - printf("device twin report properties failed with code : %d\r\n", response_status); + printf("Reported properties failed with code : %d\r\n", response_status); return; } last_device_max_tem_reported = device_max_temp; } -static void sample_device_twin_get_action(SAMPLE_CONTEXT *context) +static void sample_device_properties_get_action(SAMPLE_CONTEXT *context) { UINT status = 0; -NX_PACKET *packet_ptr; NX_AZURE_IOT_JSON_READER json_reader; +ULONG desired_properties_version; if (context -> state != SAMPLE_STATE_CONNECTED) { return; } - if ((status = nx_azure_iot_hub_client_device_twin_properties_receive(&(context -> iothub_client), &packet_ptr, - NX_WAIT_FOREVER))) + if ((status = nx_azure_iot_pnp_client_properties_receive(&(context -> iotpnp_client), + &json_reader, + &desired_properties_version, + NX_WAIT_FOREVER))) { - printf("Twin receive failed!: error code = 0x%08x\r\n", status); + printf("Get all properties receive failed!: error code = 0x%08x\r\n", status); return; } - printf("Receive twin properties: "); - printf_packet(packet_ptr); + printf("Received all properties"); printf("\r\n"); - if (nx_azure_iot_json_reader_init(&json_reader, packet_ptr)) - { - printf("Failed to initialize json reader\r\n"); - nx_packet_release(packet_ptr); - return; - } - - if (sample_parse_desired_temp_property(context, &json_reader, NX_FALSE) != NX_AZURE_IOT_SUCCESS) + status = sample_parse_desired_temp_property(context, &json_reader, + NX_AZURE_IOT_PNP_PROPERTIES, desired_properties_version); + if (status && (status != NX_AZURE_IOT_NOT_FOUND)) { printf("Failed to parse value\r\n"); } @@ -994,7 +860,9 @@ UINT buffer_length; } /* Create a telemetry message packet. */ - if ((status = nx_azure_iot_hub_client_telemetry_message_create(&(context -> iothub_client), &packet_ptr, NX_WAIT_FOREVER))) + if ((status = nx_azure_iot_pnp_client_telemetry_message_create(&(context -> iotpnp_client), + NX_NULL, 0, &packet_ptr, + NX_WAIT_FOREVER))) { printf("Telemetry message create failed!: error code = 0x%08x\r\n", status); return; @@ -1004,7 +872,7 @@ UINT buffer_length; if(nx_azure_iot_json_writer_with_buffer_init(&json_builder, scratch_buffer, sizeof(scratch_buffer))) { printf("Telemetry message failed to build message\r\n"); - nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); + nx_azure_iot_pnp_client_telemetry_message_delete(packet_ptr); return; } @@ -1018,17 +886,18 @@ UINT buffer_length; { printf("Telemetry message failed to build message\r\n"); nx_azure_iot_json_writer_deinit(&json_builder); - nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); + nx_azure_iot_pnp_client_telemetry_message_delete(packet_ptr); return; } buffer_length = nx_azure_iot_json_writer_get_bytes_used(&json_builder); nx_azure_iot_json_writer_deinit(&json_builder); - if ((status = nx_azure_iot_hub_client_telemetry_send(&(context -> iothub_client), packet_ptr, - (UCHAR *)scratch_buffer, buffer_length, SAMPLE_WAIT_OPTION))) + if ((status = nx_azure_iot_pnp_client_telemetry_send(&(context -> iotpnp_client), packet_ptr, + (UCHAR *)scratch_buffer, buffer_length, + SAMPLE_WAIT_OPTION))) { printf("Telemetry message send failed!: error code = 0x%08x\r\n", status); - nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); + nx_azure_iot_pnp_client_telemetry_message_delete(packet_ptr); return; } @@ -1085,7 +954,7 @@ UINT status; if ((status = nx_azure_iot_provisioning_client_symmetric_key_set(prov_client_ptr, (UCHAR *)DEVICE_SYMMETRIC_KEY, sizeof(DEVICE_SYMMETRIC_KEY) - 1))) { - printf("Failed on nx_azure_iot_hub_client_symmetric_key_set!: error code = 0x%08x\r\n", status); + printf("Failed on nx_azure_iot_pnp_client_symmetric_key_set!: error code = 0x%08x\r\n", status); } #endif /* USE_DEVICE_CERTIFICATE */ else if ((status = nx_azure_iot_provisioning_client_registration_payload_set(prov_client_ptr, (UCHAR *)SAMPLE_PNP_DPS_PAYLOAD, @@ -1129,8 +998,8 @@ UINT status; * | | INIT | | | | | | * | | SUCCESS | | | | | +--------+ * | INIT | | CONNECT | | CONNECTING | | CONNECTED | | (TELEMETRY | - * | +-----------> +----->+ +-------> | | METHOD | - * | | | | | | | <--------+ DEVICETWIN) + * | +-----------> +----->+ +-------> | | COMMAND | + * | | | | | | | <--------+ PROPERTIES) * | | | | | | | | * +-----+--------+ +----+---+-----+ +------+-------+ +--------+-----+ * ^ ^ | | | @@ -1181,19 +1050,19 @@ UINT loop = NX_TRUE; sample_initialize_iothub(context); } - if (app_events & SAMPLE_DEVICE_TWIN_GET_EVENT) + if (app_events & SAMPLE_DEVICE_PROPERTIES_GET_EVENT) { - sample_device_twin_get_action(context); + sample_device_properties_get_action(context); } - if (app_events & SAMPLE_METHOD_MESSAGE_EVENT) + if (app_events & SAMPLE_COMMAND_MESSAGE_EVENT) { - sample_direct_method_action(context); + sample_command_action(context); } - if (app_events & SAMPLE_DEVICE_TWIN_DESIRED_PROPERTY_EVENT) + if (app_events & SAMPLE_DEVICE_DESIRED_PROPERTIES_EVENT) { - sample_device_twin_desired_property_action(context); + sample_device_desired_property_action(context); } if (app_events & SAMPLE_TELEMETRY_SEND_EVENT) @@ -1201,9 +1070,9 @@ UINT loop = NX_TRUE; sample_telemetry_action(context); } - if (app_events & SAMPLE_DEVICE_TWIN_REPORTED_PROPERTY_EVENT) + if (app_events & SAMPLE_DEVICE_REPORTED_PROPERTIES_EVENT) { - sample_device_twin_reported_property_action(context); + sample_device_reported_property_action(context); } if (app_events & SAMPLE_DISCONNECT_EVENT) diff --git a/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_deviceinfo_component.c b/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_deviceinfo_component.c index bb53737a..26208459 100644 --- a/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_deviceinfo_component.c +++ b/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_deviceinfo_component.c @@ -11,8 +11,6 @@ #include "sample_pnp_deviceinfo_component.h" -#include "nx_azure_iot_pnp_helpers.h" - #define DOUBLE_DECIMAL_PLACE_DIGITS (2) /* Reported property keys and values. */ @@ -33,14 +31,10 @@ static const double sample_pnp_device_info_total_storage_property_value = 1024.0 static const CHAR sample_pnp_device_info_total_memory_property_name[] = "totalMemory"; static const double sample_pnp_device_info_total_memory_property_value = 128; -static UCHAR scratch_buffer[512]; - -static UINT append_properties(NX_AZURE_IOT_JSON_WRITER *json_writer, VOID *context) +static UINT append_properties(NX_AZURE_IOT_JSON_WRITER *json_writer) { UINT status; - NX_PARAMETER_NOT_USED(context); - if (nx_azure_iot_json_writer_append_property_with_string_value(json_writer, (UCHAR *)sample_pnp_device_info_manufacturer_property_name, sizeof(sample_pnp_device_info_manufacturer_property_name) - 1, @@ -92,50 +86,48 @@ UINT status; } UINT sample_pnp_deviceinfo_report_all_properties(UCHAR *component_name_ptr, UINT component_name_len, - NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr) + NX_AZURE_IOT_PNP_CLIENT *iotpnp_client_ptr) { -UINT reported_properties_length; UINT status; -UINT response_status; -UINT request_id; -NX_AZURE_IOT_JSON_WRITER json_builder; -ULONG reported_property_version; +UINT response_status = 0; +NX_AZURE_IOT_JSON_WRITER json_writer; - if ((status = nx_azure_iot_json_writer_with_buffer_init(&json_builder, - scratch_buffer, - sizeof(scratch_buffer)))) + if ((status = nx_azure_iot_pnp_client_reported_properties_create(iotpnp_client_ptr, + &json_writer, NX_WAIT_FOREVER))) { - printf("Failed to initialize json writer\r\n"); - return(NX_NOT_SUCCESSFUL); + printf("Failed create reported properties: error code = 0x%08x\r\n", status); + return(status); } - if ((status = nx_azure_iot_pnp_helper_build_reported_property(component_name_ptr, component_name_len, - append_properties, NX_NULL, - &json_builder))) + if ((status = nx_azure_iot_pnp_client_reported_property_component_begin(iotpnp_client_ptr, + &json_writer, + component_name_ptr, + component_name_len)) || + (status = append_properties(&json_writer)) || + (status = nx_azure_iot_pnp_client_reported_property_component_end(iotpnp_client_ptr, + &json_writer))) { printf("Failed to build reported property!: error code = 0x%08x\r\n", status); - nx_azure_iot_json_writer_deinit(&json_builder); + nx_azure_iot_json_writer_deinit(&json_writer); return(status); } - reported_properties_length = nx_azure_iot_json_writer_get_bytes_used(&json_builder); - if ((status = nx_azure_iot_hub_client_device_twin_reported_properties_send(iothub_client_ptr, - scratch_buffer, - reported_properties_length, - &request_id, &response_status, - &reported_property_version, - (5 * NX_IP_PERIODIC_RATE)))) + if ((status = nx_azure_iot_pnp_client_reported_properties_send(iotpnp_client_ptr, + &json_writer, + NX_NULL, &response_status, + NX_NULL, + (5 * NX_IP_PERIODIC_RATE)))) { - printf("Device twin reported properties failed!: error code = 0x%08x\r\n", status); - nx_azure_iot_json_writer_deinit(&json_builder); + printf("Reported properties send failed!: error code = 0x%08x\r\n", status); + nx_azure_iot_json_writer_deinit(&json_writer); return(status); } - nx_azure_iot_json_writer_deinit(&json_builder); + nx_azure_iot_json_writer_deinit(&json_writer); if ((response_status < 200) || (response_status >= 300)) { - printf("device twin report properties failed with code : %d\r\n", response_status); + printf("Reported properties send failed with code : %d\r\n", response_status); return(NX_NOT_SUCCESSFUL); } diff --git a/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_deviceinfo_component.h b/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_deviceinfo_component.h index 2de2bbe5..539811f8 100644 --- a/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_deviceinfo_component.h +++ b/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_deviceinfo_component.h @@ -16,11 +16,11 @@ extern "C" { #endif -#include "nx_azure_iot_hub_client.h" +#include "nx_azure_iot_pnp_client.h" #include "nx_api.h" UINT sample_pnp_deviceinfo_report_all_properties(UCHAR *component_name_ptr, UINT component_name_len, - NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr); + NX_AZURE_IOT_PNP_CLIENT *iotpnp_client_ptr); #ifdef __cplusplus } diff --git a/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_temperature_controller.c b/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_temperature_controller.c index 54d245e8..e2caf044 100644 --- a/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_temperature_controller.c +++ b/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_temperature_controller.c @@ -12,7 +12,7 @@ #include <stdio.h> #include "nx_api.h" -#include "nx_azure_iot_hub_client.h" +#include "nx_azure_iot_pnp_client.h" #include "nx_azure_iot_provisioning_client.h" /* These are sample files, user can build their own certificate and ciphersuites. */ @@ -20,7 +20,6 @@ #include "nx_azure_iot_ciphersuites.h" #include "sample_config.h" #include "sample_pnp_deviceinfo_component.h" -#include "nx_azure_iot_pnp_helpers.h" #include "sample_pnp_thermostat_component.h" #ifndef SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC @@ -43,11 +42,11 @@ #define SAMPLE_ALL_EVENTS ((ULONG)0xFFFFFFFF) #define SAMPLE_CONNECT_EVENT ((ULONG)0x00000001) #define SAMPLE_INITIALIZATION_EVENT ((ULONG)0x00000002) -#define SAMPLE_METHOD_MESSAGE_EVENT ((ULONG)0x00000004) -#define SAMPLE_DEVICE_TWIN_GET_EVENT ((ULONG)0x00000008) -#define SAMPLE_DEVICE_TWIN_DESIRED_PROPERTY_EVENT ((ULONG)0x00000010) +#define SAMPLE_COMMAND_MESSAGE_EVENT ((ULONG)0x00000004) +#define SAMPLE_DEVICE_PROPERTIES_GET_EVENT ((ULONG)0x00000008) +#define SAMPLE_DEVICE_DESIRED_PROPERTIES_EVENT ((ULONG)0x00000010) #define SAMPLE_TELEMETRY_SEND_EVENT ((ULONG)0x00000020) -#define SAMPLE_DEVICE_TWIN_REPORTED_PROPERTY_EVENT ((ULONG)0x00000040) +#define SAMPLE_DEVICE_REPORTED_PROPERTIES_EVENT ((ULONG)0x00000040) #define SAMPLE_DISCONNECT_EVENT ((ULONG)0x00000080) #define SAMPLE_RECONNECT_EVENT ((ULONG)0x00000100) #define SAMPLE_CONNECTED_EVENT ((ULONG)0x00000200) @@ -84,13 +83,13 @@ typedef struct SAMPLE_CONTEXT_STRUCT NOTE: If user can not make sure sharing memory is safe, IoTHub Client and DPS Client must be defined seperately. */ union SAMPLE_CLIENT_UNION { - NX_AZURE_IOT_HUB_CLIENT iothub_client; + NX_AZURE_IOT_PNP_CLIENT iotpnp_client; #ifdef ENABLE_DPS_SAMPLE NX_AZURE_IOT_PROVISIONING_CLIENT prov_client; #endif /* ENABLE_DPS_SAMPLE */ } client; -#define iothub_client client.iothub_client +#define iotpnp_client client.iotpnp_client #ifdef ENABLE_DPS_SAMPLE #define prov_client client.prov_client #endif /* ENABLE_DPS_SAMPLE */ @@ -143,10 +142,6 @@ static double sample_thermostat_2_last_device_max_tem_reported; static const CHAR sample_device_info_component[] = "deviceInformation"; static UINT sample_device_info_sent; static UINT sample_device_serial_info_sent; -static const CHAR *sample_components[] = { sample_thermostat_1_component, - sample_thermostat_2_component, - sample_device_info_component }; -static UINT sample_components_num = sizeof(sample_components) / sizeof(sample_components[0]); /* Name of the serial number property as defined in this component's DTML. */ static const CHAR sample_serial_number_property_name[] = "serialNumber"; @@ -162,7 +157,7 @@ static const CHAR rebootCommand[] = "reboot"; static const INT working_set_minimum = 1000; static const INT working_set_random_modulo = 500; -static UCHAR scratch_buffer[512]; +static UCHAR scratch_buffer[256]; static UINT sample_pnp_temp_controller_reboot_command(NX_AZURE_IOT_JSON_READER *json_reader_ptr, NX_AZURE_IOT_JSON_WRITER *out_json_builder_ptr) @@ -171,24 +166,16 @@ INT delay; NX_PARAMETER_NOT_USED(out_json_builder_ptr); - if (json_reader_ptr == NX_NULL) + if (nx_azure_iot_json_reader_next_token(json_reader_ptr) || + nx_azure_iot_json_reader_token_int32_get(json_reader_ptr, (int32_t *)&delay)) { - printf("Payload found to be null for reboot command\r\n"); return(NX_NOT_SUCCESSFUL); } - else - { - if (nx_azure_iot_json_reader_next_token(json_reader_ptr) || - nx_azure_iot_json_reader_token_int32_get(json_reader_ptr, (int32_t *)&delay)) - { - return(NX_NOT_SUCCESSFUL); - } - } return(NX_AZURE_IOT_SUCCESS); } -static UINT sample_pnp_temp_controller_telemetry_send(NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr) +static UINT sample_pnp_temp_controller_telemetry_send(NX_AZURE_IOT_PNP_CLIENT *iotpnp_client_ptr) { UINT status; NX_PACKET *packet_ptr; @@ -199,7 +186,7 @@ INT working_set_value; working_set_value = working_set_minimum + (rand() % working_set_random_modulo); /* Create a telemetry message packet. */ - if ((status = nx_azure_iot_pnp_helper_telemetry_message_create(iothub_client_ptr, NX_NULL, 0, + if ((status = nx_azure_iot_pnp_client_telemetry_message_create(iotpnp_client_ptr, NX_NULL, 0, &packet_ptr, NX_WAIT_FOREVER))) { printf("Telemetry message create failed!: error code = 0x%08x\r\n", status); @@ -210,7 +197,7 @@ INT working_set_value; if (nx_azure_iot_json_writer_with_buffer_init(&json_writer, scratch_buffer, sizeof(scratch_buffer))) { printf("Telemetry message failed to build message\r\n"); - nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); + nx_azure_iot_pnp_client_telemetry_message_delete(packet_ptr); return(NX_NOT_SUCCESSFUL); } @@ -223,17 +210,17 @@ INT working_set_value; { printf("Telemetry message failed to build message\r\n"); nx_azure_iot_json_writer_deinit(&json_writer); - nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); + nx_azure_iot_pnp_client_telemetry_message_delete(packet_ptr); return(NX_NOT_SUCCESSFUL); } buffer_length = nx_azure_iot_json_writer_get_bytes_used(&json_writer); - if ((status = nx_azure_iot_hub_client_telemetry_send(iothub_client_ptr, packet_ptr, + if ((status = nx_azure_iot_pnp_client_telemetry_send(iotpnp_client_ptr, packet_ptr, (UCHAR *)scratch_buffer, buffer_length, NX_WAIT_FOREVER))) { printf("Telemetry message send failed!: error code = 0x%08x\r\n", status); nx_azure_iot_json_writer_deinit(&json_writer); - nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); + nx_azure_iot_pnp_client_telemetry_message_delete(packet_ptr); return(status); } @@ -258,7 +245,8 @@ UINT dm_status; if (pnp_command_name_length != (sizeof(rebootCommand) - 1) || strncmp((CHAR *)pnp_command_name_ptr, (CHAR *)rebootCommand, pnp_command_name_length) != 0) { - printf("PnP command=%.*s is not supported on thermostat component", pnp_command_name_length, pnp_command_name_ptr); + printf("PnP command=%.*s is not supported on thermostat component", + pnp_command_name_length, pnp_command_name_ptr); dm_status = SAMPLE_COMMAND_NOT_FOUND_STATUS; } else @@ -278,76 +266,52 @@ UINT dm_status; return(NX_AZURE_IOT_SUCCESS); } -static UINT append_serial_number(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr, VOID *context) +static UINT sample_pnp_temp_controller_report_serial_number_property(NX_AZURE_IOT_PNP_CLIENT *iotpnp_client_ptr) { - NX_PARAMETER_NOT_USED(context); - - return(nx_azure_iot_json_writer_append_property_with_string_value(json_writer_ptr, - (UCHAR *)sample_serial_number_property_name, - sizeof(sample_serial_number_property_name) - 1, - (UCHAR *)sample_serial_number_property_value, - sizeof(sample_serial_number_property_value) - 1)); -} - -static UINT sample_pnp_temp_controller_report_serial_number_property(NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr) -{ -UINT reported_properties_length; UINT status; -UINT response_status; -UINT request_id; -NX_AZURE_IOT_JSON_WRITER json_builder; -ULONG reported_property_version; +UINT response_status = 0; +NX_AZURE_IOT_JSON_WRITER json_writer; - if ((status = nx_azure_iot_json_writer_with_buffer_init(&json_builder, - scratch_buffer, - sizeof(scratch_buffer)))) + if ((status = nx_azure_iot_pnp_client_reported_properties_create(iotpnp_client_ptr, + &json_writer, NX_WAIT_FOREVER))) { - printf("Failed to initialize json writer\r\n"); - return(NX_NOT_SUCCESSFUL); + printf("Failed create reported properties: error code = 0x%08x\r\n", status); + return(status); } - if ((status = nx_azure_iot_pnp_helper_build_reported_property(NX_NULL, 0, append_serial_number, NX_NULL, - &json_builder))) + if ((status = nx_azure_iot_json_writer_append_property_with_string_value(&json_writer, + (UCHAR *)sample_serial_number_property_name, + sizeof(sample_serial_number_property_name) - 1, + (UCHAR *)sample_serial_number_property_value, + sizeof(sample_serial_number_property_value) - 1))) { printf("Failed to build reported property!: error code = 0x%08x\r\n", status); - nx_azure_iot_json_writer_deinit(&json_builder); + nx_azure_iot_json_writer_deinit(&json_writer); return(status); } - reported_properties_length = nx_azure_iot_json_writer_get_bytes_used(&json_builder); - if ((status = nx_azure_iot_hub_client_device_twin_reported_properties_send(iothub_client_ptr, - scratch_buffer, - reported_properties_length, - &request_id, &response_status, - &reported_property_version, - (5 * NX_IP_PERIODIC_RATE)))) + if ((status = nx_azure_iot_pnp_client_reported_properties_send(iotpnp_client_ptr, + &json_writer, + NX_NULL, &response_status, + NX_NULL, + (5 * NX_IP_PERIODIC_RATE)))) { - printf("Device twin reported properties failed!: error code = 0x%08x\r\n", status); - nx_azure_iot_json_writer_deinit(&json_builder); + printf("Reported properties send failed!: error code = 0x%08x\r\n", status); + nx_azure_iot_json_writer_deinit(&json_writer); return(status); } - nx_azure_iot_json_writer_deinit(&json_builder); + nx_azure_iot_json_writer_deinit(&json_writer); if ((response_status < 200) || (response_status >= 300)) { - printf("device twin report properties failed with code : %d\r\n", response_status); + printf("Reported properties send failed with code : %d\r\n", response_status); return(NX_NOT_SUCCESSFUL); } return(status); } -static VOID printf_packet(NX_PACKET *packet_ptr) -{ - while (packet_ptr != NX_NULL) - { - printf("%.*s", (INT)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr), - (CHAR *)packet_ptr -> nx_packet_prepend_ptr); - packet_ptr = packet_ptr -> nx_packet_next; - } -} - static UINT exponential_backoff_with_jitter() { double jitter_percent = (SAMPLE_MAX_EXPONENTIAL_BACKOFF_JITTER_PERCENT / 100.0) * (rand() / ((double)RAND_MAX)); @@ -380,7 +344,7 @@ static VOID exponential_backoff_reset() exponential_retry_count = 0; } -static VOID connection_status_callback(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT status) +static VOID connection_status_callback(NX_AZURE_IOT_PNP_CLIENT *hub_client_ptr, UINT status) { NX_PARAMETER_NOT_USED(hub_client_ptr); @@ -399,31 +363,31 @@ static VOID connection_status_callback(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, } } -static VOID message_receive_callback_twin(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, VOID *context) +static VOID message_receive_callback_properties(NX_AZURE_IOT_PNP_CLIENT *hub_client_ptr, VOID *context) { SAMPLE_CONTEXT *sample_ctx = (SAMPLE_CONTEXT *)context; NX_PARAMETER_NOT_USED(hub_client_ptr); tx_event_flags_set(&(sample_ctx -> sample_events), - SAMPLE_DEVICE_TWIN_GET_EVENT, TX_OR); + SAMPLE_DEVICE_PROPERTIES_GET_EVENT, TX_OR); } -static VOID message_receive_callback_method(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, VOID *context) +static VOID message_receive_callback_command(NX_AZURE_IOT_PNP_CLIENT *hub_client_ptr, VOID *context) { SAMPLE_CONTEXT *sample_ctx = (SAMPLE_CONTEXT *)context; NX_PARAMETER_NOT_USED(hub_client_ptr); tx_event_flags_set(&(sample_ctx -> sample_events), - SAMPLE_METHOD_MESSAGE_EVENT, TX_OR); + SAMPLE_COMMAND_MESSAGE_EVENT, TX_OR); } -static VOID message_receive_callback_desired_property(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, VOID *context) +static VOID message_receive_callback_desired_property(NX_AZURE_IOT_PNP_CLIENT *hub_client_ptr, VOID *context) { SAMPLE_CONTEXT *sample_ctx = (SAMPLE_CONTEXT *)context; NX_PARAMETER_NOT_USED(hub_client_ptr); tx_event_flags_set(&(sample_ctx -> sample_events), - SAMPLE_DEVICE_TWIN_DESIRED_PROPERTY_EVENT, TX_OR); + SAMPLE_DEVICE_DESIRED_PROPERTIES_EVENT, TX_OR); } static VOID sample_connect_action(SAMPLE_CONTEXT *context) @@ -433,7 +397,8 @@ static VOID sample_connect_action(SAMPLE_CONTEXT *context) return; } - context -> action_result = nx_azure_iot_hub_client_connect(&(context -> iothub_client), NX_FALSE, SAMPLE_WAIT_OPTION); + context -> action_result = nx_azure_iot_pnp_client_connect(&(context -> iotpnp_client), + NX_FALSE, SAMPLE_WAIT_OPTION); if (context -> action_result == NX_AZURE_IOT_CONNECTING) { @@ -449,7 +414,7 @@ static VOID sample_connect_action(SAMPLE_CONTEXT *context) context -> state = SAMPLE_STATE_CONNECTED; context -> action_result = - nx_azure_iot_hub_client_device_twin_properties_request(&(context -> iothub_client), NX_WAIT_FOREVER); + nx_azure_iot_pnp_client_properties_request(&(context -> iotpnp_client), NX_WAIT_FOREVER); } } @@ -461,7 +426,7 @@ static VOID sample_disconnect_action(SAMPLE_CONTEXT *context) return; } - context -> action_result = nx_azure_iot_hub_client_disconnect(&(context -> iothub_client)); + context -> action_result = nx_azure_iot_pnp_client_disconnect(&(context -> iotpnp_client)); context -> state = SAMPLE_STATE_DISCONNECTED; } @@ -475,7 +440,7 @@ static VOID sample_connected_action(SAMPLE_CONTEXT *context) context -> state = SAMPLE_STATE_CONNECTED; context -> action_result = - nx_azure_iot_hub_client_device_twin_properties_request(&(context -> iothub_client), NX_WAIT_FOREVER); + nx_azure_iot_pnp_client_properties_request(&(context -> iotpnp_client), NX_WAIT_FOREVER); } static VOID sample_initialize_iothub(SAMPLE_CONTEXT *context) @@ -492,7 +457,7 @@ UCHAR *iothub_device_id = (UCHAR *)DEVICE_ID; UINT iothub_hostname_length = sizeof(HOST_NAME) - 1; UINT iothub_device_id_length = sizeof(DEVICE_ID) - 1; #endif /* ENABLE_DPS_SAMPLE */ -NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr = &(context -> iothub_client); +NX_AZURE_IOT_PNP_CLIENT *iotpnp_client_ptr = &(context -> iotpnp_client); if (context -> state != SAMPLE_STATE_INIT) { @@ -515,10 +480,11 @@ NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr = &(context -> iothub_client); iothub_hostname_length, iothub_hostname, iothub_device_id_length, iothub_device_id); /* Initialize IoTHub client. */ - if ((status = nx_azure_iot_hub_client_initialize(iothub_client_ptr, &nx_azure_iot, + if ((status = nx_azure_iot_pnp_client_initialize(iotpnp_client_ptr, &nx_azure_iot, iothub_hostname, iothub_hostname_length, iothub_device_id, iothub_device_id_length, - (UCHAR *)MODULE_ID, sizeof(MODULE_ID) - 1, + (const UCHAR *)MODULE_ID, sizeof(MODULE_ID) - 1, + (const UCHAR *)SAMPLE_PNP_MODEL_ID, sizeof(SAMPLE_PNP_MODEL_ID) - 1, _nx_azure_iot_tls_supported_crypto, _nx_azure_iot_tls_supported_crypto_size, _nx_azure_iot_tls_ciphersuite_map, @@ -527,7 +493,7 @@ NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr = &(context -> iothub_client); sizeof(nx_azure_iot_tls_metadata_buffer), &root_ca_cert))) { - printf("Failed on nx_azure_iot_hub_client_initialize!: error code = 0x%08x\r\n", status); + printf("Failed on nx_azure_iot_pnp_client_initialize!: error code = 0x%08x\r\n", status); context -> action_result = status; return; } @@ -545,64 +511,64 @@ NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr = &(context -> iothub_client); } /* Set device certificate. */ - else if ((status = nx_azure_iot_hub_client_device_cert_set(iothub_client_ptr, &device_certificate))) + else if ((status = nx_azure_iot_pnp_client_device_cert_set(iotpnp_client_ptr, &device_certificate))) { - printf("Failed on nx_azure_iot_hub_client_device_cert_set!: error code = 0x%08x\r\n", status); + printf("Failed on nx_azure_iot_pnp_client_device_cert_set!: error code = 0x%08x\r\n", status); } #else /* Set symmetric key. */ - if ((status = nx_azure_iot_hub_client_symmetric_key_set(iothub_client_ptr, + if ((status = nx_azure_iot_pnp_client_symmetric_key_set(iotpnp_client_ptr, (UCHAR *)DEVICE_SYMMETRIC_KEY, sizeof(DEVICE_SYMMETRIC_KEY) - 1))) { - printf("Failed on nx_azure_iot_hub_client_symmetric_key_set! error: 0x%08x\r\n", status); + printf("Failed on nx_azure_iot_pnp_client_symmetric_key_set! error: 0x%08x\r\n", status); } #endif /* USE_DEVICE_CERTIFICATE */ /* Set connection status callback. */ - else if ((status = nx_azure_iot_hub_client_connection_status_callback_set(iothub_client_ptr, + else if ((status = nx_azure_iot_pnp_client_connection_status_callback_set(iotpnp_client_ptr, connection_status_callback))) { printf("Failed on connection_status_callback!\r\n"); } - else if ((status = nx_azure_iot_hub_client_direct_method_enable(iothub_client_ptr))) - { - printf("Direct method receive enable failed!: error code = 0x%08x\r\n", status); - } - else if ((status = nx_azure_iot_hub_client_device_twin_enable(iothub_client_ptr))) - { - printf("device twin enabled failed!: error code = 0x%08x\r\n", status); - } - else if ((status = nx_azure_iot_hub_client_receive_callback_set(iothub_client_ptr, - NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES, - message_receive_callback_twin, + else if ((status = nx_azure_iot_pnp_client_receive_callback_set(iotpnp_client_ptr, + NX_AZURE_IOT_PNP_PROPERTIES, + message_receive_callback_properties, (VOID *)context))) { - printf("device twin callback set!: error code = 0x%08x\r\n", status); + printf("device properties callback set!: error code = 0x%08x\r\n", status); } - else if ((status = nx_azure_iot_hub_client_receive_callback_set(iothub_client_ptr, - NX_AZURE_IOT_HUB_DIRECT_METHOD, - message_receive_callback_method, + else if ((status = nx_azure_iot_pnp_client_receive_callback_set(iotpnp_client_ptr, + NX_AZURE_IOT_PNP_COMMAND, + message_receive_callback_command, (VOID *)context))) { - printf("device method callback set!: error code = 0x%08x\r\n", status); + printf("device command callback set!: error code = 0x%08x\r\n", status); } - else if ((status = nx_azure_iot_hub_client_receive_callback_set(iothub_client_ptr, - NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES, + else if ((status = nx_azure_iot_pnp_client_receive_callback_set(iotpnp_client_ptr, + NX_AZURE_IOT_PNP_DESIRED_PROPERTIES, message_receive_callback_desired_property, (VOID *)context))) { - printf("device twin desired property callback set!: error code = 0x%08x\r\n", status); + printf("device desired property callback set!: error code = 0x%08x\r\n", status); } - else if ((status = nx_azure_iot_hub_client_model_id_set(iothub_client_ptr, (UCHAR *)SAMPLE_PNP_MODEL_ID, sizeof(SAMPLE_PNP_MODEL_ID) - 1))) + else if ((status = nx_azure_iot_pnp_client_component_add(iotpnp_client_ptr, + (const UCHAR *)sample_thermostat_1_component, + sizeof(sample_thermostat_1_component) - 1)) || + (status = nx_azure_iot_pnp_client_component_add(iotpnp_client_ptr, + (const UCHAR *)sample_thermostat_2_component, + sizeof(sample_thermostat_2_component) - 1)) || + (status = nx_azure_iot_pnp_client_component_add(iotpnp_client_ptr, + (const UCHAR *)sample_device_info_component, + sizeof(sample_device_info_component) - 1))) { - printf("digital twin modelId set!: error code = 0x%08x\r\n", status); + printf("Failed to add component to pnp client!: error code = 0x%08x\r\n", status); } if (status) { - nx_azure_iot_hub_client_deinitialize(iothub_client_ptr); + nx_azure_iot_pnp_client_deinitialize(iotpnp_client_ptr); } context -> action_result = status; @@ -636,7 +602,7 @@ static VOID sample_connection_error_recover(SAMPLE_CONTEXT *context) printf("re-initializing iothub connection, after backoff\r\n"); tx_thread_sleep(exponential_backoff_with_jitter()); - nx_azure_iot_hub_client_deinitialize(&(context -> iothub_client)); + nx_azure_iot_pnp_client_deinitialize(&(context -> iotpnp_client)); context -> state = SAMPLE_STATE_INIT; } break; @@ -674,7 +640,7 @@ static VOID sample_trigger_action(SAMPLE_CONTEXT *context) { context -> last_periodic_action_tick = tx_time_get(); tx_event_flags_set(&(context -> sample_events), SAMPLE_TELEMETRY_SEND_EVENT, TX_OR); - tx_event_flags_set(&(context -> sample_events), SAMPLE_DEVICE_TWIN_REPORTED_PROPERTY_EVENT, TX_OR); + tx_event_flags_set(&(context -> sample_events), SAMPLE_DEVICE_REPORTED_PROPERTIES_EVENT, TX_OR); } } break; @@ -687,12 +653,9 @@ static VOID sample_trigger_action(SAMPLE_CONTEXT *context) } } -static VOID sample_direct_method_action(SAMPLE_CONTEXT *sample_context_ptr) +static VOID sample_command_action(SAMPLE_CONTEXT *sample_context_ptr) { -NX_PACKET *packet_ptr; UINT status; -USHORT method_name_length; -const UCHAR *method_name_ptr; USHORT context_length; VOID *context_ptr; UINT component_name_length; @@ -701,7 +664,6 @@ UINT pnp_command_name_length; const UCHAR *pnp_command_name_ptr; NX_AZURE_IOT_JSON_WRITER json_writer; NX_AZURE_IOT_JSON_READER json_reader; -NX_AZURE_IOT_JSON_READER *json_reader_ptr; UINT status_code; UINT response_length; @@ -710,179 +672,153 @@ UINT response_length; return; } - if ((status = nx_azure_iot_hub_client_direct_method_message_receive(&(sample_context_ptr -> iothub_client), - &method_name_ptr, &method_name_length, - &context_ptr, &context_length, - &packet_ptr, NX_WAIT_FOREVER))) + if ((status = nx_azure_iot_pnp_client_command_receive(&(sample_context_ptr -> iotpnp_client), + &component_name_ptr, &component_name_length, + &pnp_command_name_ptr, &pnp_command_name_length, + &context_ptr, &context_length, + &json_reader, NX_WAIT_FOREVER))) { - printf("Direct method receive failed!: error code = 0x%08x\r\n", status); + printf("Command receive failed!: error code = 0x%08x\r\n", status); return; } - printf("Receive method call: %.*s, with payload:", (INT)method_name_length, (CHAR *)method_name_ptr); - printf_packet(packet_ptr); + if (component_name_ptr != NX_NULL) + { + printf("Received component: %.*s ", component_name_length, component_name_ptr); + } + else + { + printf("Received component: root component "); + } + + printf("command: %.*s", pnp_command_name_length, (CHAR *)pnp_command_name_ptr); printf("\r\n"); - if ((status = nx_azure_iot_pnp_helper_command_name_parse(method_name_ptr, method_name_length, - &component_name_ptr, &component_name_length, - &pnp_command_name_ptr, - &pnp_command_name_length)) != NX_AZURE_IOT_SUCCESS) + if ((status = nx_azure_iot_json_writer_with_buffer_init(&json_writer, + scratch_buffer, + sizeof(scratch_buffer)))) + { + printf("Failed to initialize json builder response \r\n"); + nx_azure_iot_json_reader_deinit(&json_reader); + return; + } + + if ((status = sample_pnp_thermostat_process_command(&sample_thermostat_1, component_name_ptr, + component_name_length, pnp_command_name_ptr, + pnp_command_name_length, &json_reader, + &json_writer, &status_code)) == NX_AZURE_IOT_SUCCESS) { - printf("Failed to parse command name: error code = 0x%08x\r\n", status); - nx_packet_release(packet_ptr); + printf("Successfully executed command %.*s on thermostat 1\r\n", pnp_command_name_length, pnp_command_name_ptr); + response_length = nx_azure_iot_json_writer_get_bytes_used(&json_writer); } - else if ((status = nx_azure_iot_json_writer_with_buffer_init(&json_writer, - scratch_buffer, - sizeof(scratch_buffer)))) + else if ((status = sample_pnp_thermostat_process_command(&sample_thermostat_2, component_name_ptr, + component_name_length, pnp_command_name_ptr, + pnp_command_name_length, &json_reader, + &json_writer, &status_code)) == NX_AZURE_IOT_SUCCESS) { - printf("Failed to initialize json writer: error code = 0x%08x\r\n", status); - nx_packet_release(packet_ptr); + printf("Successfully executed command %.*s on thermostat 2\r\n", pnp_command_name_length, pnp_command_name_ptr); + response_length = nx_azure_iot_json_writer_get_bytes_used(&json_writer); } - else if ((packet_ptr ->nx_packet_length != 0) && - (status = nx_azure_iot_json_reader_init(&json_reader, packet_ptr))) + else if((status = sample_pnp_temp_controller_process_command(component_name_ptr, component_name_length, + pnp_command_name_ptr, pnp_command_name_length, + &json_reader, &json_writer, + &status_code)) == NX_AZURE_IOT_SUCCESS) { - printf("Failed to initialize json reader: error code = 0x%08x\r\n", status); - nx_packet_release(packet_ptr); + printf("Successfully executed command %.*s controller \r\n", pnp_command_name_length, pnp_command_name_ptr); + response_length = nx_azure_iot_json_writer_get_bytes_used(&json_writer); } else { - if (packet_ptr ->nx_packet_length == 0) - { - nx_packet_release(packet_ptr); - json_reader_ptr = NX_NULL; - } - else - { - json_reader_ptr = &json_reader; - } + printf("Failed to find any handler for command %.*s\r\n", pnp_command_name_length, pnp_command_name_ptr); + status_code = SAMPLE_COMMAND_NOT_FOUND_STATUS; + response_length = 0; + } - if ((status = sample_pnp_thermostat_process_command(&sample_thermostat_1, component_name_ptr, - component_name_length, pnp_command_name_ptr, - pnp_command_name_length, json_reader_ptr, - &json_writer, &status_code)) == NX_AZURE_IOT_SUCCESS) - { - printf("Successfully executed command %.*s on thermostat 1\r\n", method_name_length, method_name_ptr); - response_length = nx_azure_iot_json_writer_get_bytes_used(&json_writer); - } - else if ((status = sample_pnp_thermostat_process_command(&sample_thermostat_2, component_name_ptr, - component_name_length, pnp_command_name_ptr, - pnp_command_name_length, json_reader_ptr, - &json_writer, &status_code)) == NX_AZURE_IOT_SUCCESS) + nx_azure_iot_json_reader_deinit(&json_reader); + + if ((status = nx_azure_iot_pnp_client_command_message_response(&(sample_context_ptr -> iotpnp_client), status_code, + context_ptr, context_length, scratch_buffer, + response_length, NX_WAIT_FOREVER))) + { + printf("Command response failed!: error code = 0x%08x\r\n", status); + } + + nx_azure_iot_json_writer_deinit(&json_writer); +} + +static VOID sample_desired_properties_parse(NX_AZURE_IOT_PNP_CLIENT *pnp_client_ptr, + NX_AZURE_IOT_JSON_READER *json_reader_ptr, + UINT message_type, ULONG version) +{ +const UCHAR *component_ptr = NX_NULL; +UINT component_len = 0; +NX_AZURE_IOT_JSON_READER name_value_reader; + + while (nx_azure_iot_pnp_client_desired_component_property_value_next(pnp_client_ptr, + json_reader_ptr, message_type, + &component_ptr, &component_len, + &name_value_reader) == NX_AZURE_IOT_SUCCESS) + { + if (sample_pnp_thermostat_process_property_update(&sample_thermostat_1, + pnp_client_ptr, + component_ptr, component_len, + &name_value_reader, version) == NX_AZURE_IOT_SUCCESS) { - printf("Successfully executed command %.*s on thermostat 2\r\n", method_name_length, method_name_ptr); - response_length = nx_azure_iot_json_writer_get_bytes_used(&json_writer); + printf("property updated of thermostat 1\r\n"); } - else if((status = sample_pnp_temp_controller_process_command(component_name_ptr, component_name_length, - pnp_command_name_ptr, pnp_command_name_length, - json_reader_ptr, &json_writer, - &status_code)) == NX_AZURE_IOT_SUCCESS) + else if (sample_pnp_thermostat_process_property_update(&sample_thermostat_2, + pnp_client_ptr, + component_ptr, component_len, + &name_value_reader, version) == NX_AZURE_IOT_SUCCESS) { - printf("Successfully executed command %.*s controller \r\n", method_name_length, method_name_ptr); - response_length = nx_azure_iot_json_writer_get_bytes_used(&json_writer); + printf("property updated of thermostat 2\r\n"); } else { - printf("Failed to find any handler for method %.*s\r\n", method_name_length, method_name_ptr); - status_code = SAMPLE_COMMAND_NOT_FOUND_STATUS; - response_length = 0; - } - - if (json_reader_ptr) - { - nx_azure_iot_json_reader_deinit(json_reader_ptr); - } - - if ((status = nx_azure_iot_hub_client_direct_method_message_response(&(sample_context_ptr -> iothub_client), - status_code, context_ptr, context_length, - scratch_buffer, response_length, NX_WAIT_FOREVER))) - { - printf("Direct method response failed!: error code = 0x%08x\r\n", status); + if (component_ptr) + { + printf("Component=%.*s is not implemented by the Controller\r\n", component_len, component_ptr); + } + else + { + printf("Root component is not implemented by the Controller\r\n"); + } } - - nx_azure_iot_json_writer_deinit(&json_writer); } } -static VOID sample_desired_property_callback(UCHAR *component_name_ptr, UINT component_name_len, - UCHAR *property_name_ptr, UINT property_name_len, - NX_AZURE_IOT_JSON_READER property_value_reader, UINT version, - VOID *userContextCallback) +static VOID sample_device_desired_property_action(SAMPLE_CONTEXT *context) { - if (component_name_ptr == NULL || component_name_len == 0) - { - /* The PnP protocol does not define a mechanism to report errors such as this to IoTHub, so - the best we can do here is to log for diagnostics purposes. */ - printf("Property=%.*s arrived for Control component itself. This does not support\ - writeable properties on it (all properties are on subcomponents)", property_name_len, property_name_ptr); - } - else if (sample_pnp_thermostat_process_property_update(&sample_thermostat_1, - (NX_AZURE_IOT_HUB_CLIENT *)userContextCallback, - component_name_ptr, component_name_len, - property_name_ptr, property_name_len, - &property_value_reader, version) == NX_AZURE_IOT_SUCCESS) - { - printf("property updated of thermostat 1\r\n"); - } - else if (sample_pnp_thermostat_process_property_update(&sample_thermostat_2, - (NX_AZURE_IOT_HUB_CLIENT *)userContextCallback, - component_name_ptr, component_name_len, - property_name_ptr, property_name_len, - &property_value_reader, version) == NX_AZURE_IOT_SUCCESS) - { - printf("property updated of thermostat 2\r\n"); - } - else - { - printf("Component=%.*s is not implemented by the Controller\r\n", component_name_len, component_name_ptr); - } -} - -static VOID sample_device_twin_desired_property_action(SAMPLE_CONTEXT *context) -{ -NX_PACKET *packet_ptr; -UINT status; +UINT status = 0; NX_AZURE_IOT_JSON_READER json_reader; +ULONG desired_properties_version; if (context -> state != SAMPLE_STATE_CONNECTED) { return; } - if ((status = nx_azure_iot_hub_client_device_twin_desired_properties_receive(&(context -> iothub_client), - &packet_ptr, - NX_WAIT_FOREVER))) + if ((status = nx_azure_iot_pnp_client_desired_properties_receive(&(context -> iotpnp_client), + &json_reader, + &desired_properties_version, + NX_WAIT_FOREVER))) { - printf("Receive desired property receive failed!: error code = 0x%08x\r\n", status); + printf("desired properties receive failed!: error code = 0x%08x\r\n", status); return; } - printf("Receive desired property: "); - printf_packet(packet_ptr); + printf("Received desired property"); printf("\r\n"); - if ((status = nx_azure_iot_json_reader_init(&json_reader, packet_ptr))) - { - printf("Failed to initialize json reader: error code = 0x%08x\r\n", status); - nx_packet_release(packet_ptr); - } - else - { - if ((status = nx_azure_iot_pnp_helper_twin_data_parse(&json_reader, NX_TRUE, - (CHAR **)sample_components, - sample_components_num, - scratch_buffer, sizeof(scratch_buffer), - sample_desired_property_callback, - (VOID *)&(context -> iothub_client)))) - { - printf("Failed to parse twin data!: error code = 0x%08x\r\n", status); - } + sample_desired_properties_parse(&(context -> iotpnp_client), &json_reader, + NX_AZURE_IOT_PNP_DESIRED_PROPERTIES, + desired_properties_version); - nx_azure_iot_json_reader_deinit(&json_reader); - } + nx_azure_iot_json_reader_deinit(&json_reader); } -static VOID sample_device_twin_reported_property_action(SAMPLE_CONTEXT *context) +static VOID sample_device_reported_property_action(SAMPLE_CONTEXT *context) { UINT status; @@ -894,7 +830,7 @@ UINT status; /* Only report once. */ if (sample_device_serial_info_sent == 0) { - if ((status = sample_pnp_temp_controller_report_serial_number_property(&(context -> iothub_client)))) + if ((status = sample_pnp_temp_controller_report_serial_number_property(&(context -> iotpnp_client)))) { printf("Failed sample_pnp_temp_controller_report_serial_number_property: error code = 0x%08x\r\n", status); } @@ -904,13 +840,12 @@ UINT status; } } - /* Only report once. */ if (sample_device_info_sent == 0) { if ((status = sample_pnp_deviceinfo_report_all_properties((UCHAR *)sample_device_info_component, sizeof(sample_device_info_component) - 1, - &(context -> iothub_client)))) + &(context -> iotpnp_client)))) { printf("Failed sample_pnp_deviceinfo_report_all_properties: error code = 0x%08x\r\n", status); } @@ -925,7 +860,7 @@ UINT status; ((sample_thermostat_1_last_device_max_temp_reported + 0.01) > sample_thermostat_1.maxTemperature))) { if ((status = sample_pnp_thermostat_report_max_temp_since_last_reboot_property(&sample_thermostat_1, - &(context -> iothub_client)))) + &(context -> iotpnp_client)))) { printf("Failed sample_pnp_thermostat_report_max_temp_since_last_reboot_property: error code = 0x%08x\r\n", status); } @@ -940,7 +875,7 @@ UINT status; ((sample_thermostat_2_last_device_max_tem_reported + 0.01) > sample_thermostat_2.maxTemperature))) { if ((status = sample_pnp_thermostat_report_max_temp_since_last_reboot_property(&sample_thermostat_2, - &(context -> iothub_client)))) + &(context -> iotpnp_client)))) { printf("Failed sample_pnp_thermostat_report_max_temp_since_last_reboot_property: error code = 0x%08x\r\n", status); } @@ -951,46 +886,34 @@ UINT status; } } -static VOID sample_device_twin_get_action(SAMPLE_CONTEXT *context) +static VOID sample_device_properties_get_action(SAMPLE_CONTEXT *context) { -NX_PACKET *packet_ptr; -UINT status; +UINT status = 0; NX_AZURE_IOT_JSON_READER json_reader; +ULONG desired_properties_version; if (context -> state != SAMPLE_STATE_CONNECTED) { return; } - if ((status = nx_azure_iot_hub_client_device_twin_properties_receive(&(context -> iothub_client), &packet_ptr, - NX_WAIT_FOREVER))) + if ((status = nx_azure_iot_pnp_client_properties_receive(&(context -> iotpnp_client), + &json_reader, + &desired_properties_version, + NX_WAIT_FOREVER))) { - printf("Twin receive failed!: error code = 0x%08x\r\n", status); + printf("Get all properties receive failed!: error code = 0x%08x\r\n", status); return; } - printf("Received twin properties: "); - printf_packet(packet_ptr); + printf("Received all properties"); printf("\r\n"); - if ((status = nx_azure_iot_json_reader_init(&json_reader, packet_ptr))) - { - printf("Failed to initialize json reader: error code = 0x%08x\r\n", status); - nx_packet_release(packet_ptr); - } - else - { - if ((status = nx_azure_iot_pnp_helper_twin_data_parse(&json_reader, NX_FALSE, - (CHAR **)sample_components, sample_components_num, - scratch_buffer, sizeof(scratch_buffer), - sample_desired_property_callback, - (VOID *)&(context -> iothub_client)))) - { - printf("Failed to parse twin data!: error code = 0x%08x\r\n", status); - } + sample_desired_properties_parse(&(context -> iotpnp_client), &json_reader, + NX_AZURE_IOT_PNP_PROPERTIES, + desired_properties_version); - nx_azure_iot_json_reader_deinit(&json_reader); - } + nx_azure_iot_json_reader_deinit(&json_reader); } static VOID sample_telemetry_action(SAMPLE_CONTEXT *context) @@ -1002,19 +925,19 @@ UINT status; return; } - if ((status = sample_pnp_temp_controller_telemetry_send(&(context -> iothub_client))) != NX_AZURE_IOT_SUCCESS) + if ((status = sample_pnp_temp_controller_telemetry_send(&(context -> iotpnp_client))) != NX_AZURE_IOT_SUCCESS) { printf("Failed to send sample_pnp__telemetry_send, error: %d", status); } if ((status = sample_pnp_thermostat_telemetry_send(&sample_thermostat_1, - &(context -> iothub_client))) != NX_AZURE_IOT_SUCCESS) + &(context -> iotpnp_client))) != NX_AZURE_IOT_SUCCESS) { printf("Failed to send sample_pnp_thermostat_telemetry_send, error: %d", status); } if ((status = sample_pnp_thermostat_telemetry_send(&sample_thermostat_2, - &(context -> iothub_client))) != NX_AZURE_IOT_SUCCESS) + &(context -> iotpnp_client))) != NX_AZURE_IOT_SUCCESS) { printf("Failed to send sample_pnp_thermostat_telemetry_send, error: %d", status); } @@ -1070,7 +993,7 @@ UINT status; if ((status = nx_azure_iot_provisioning_client_symmetric_key_set(prov_client_ptr, (UCHAR *)DEVICE_SYMMETRIC_KEY, sizeof(DEVICE_SYMMETRIC_KEY) - 1))) { - printf("Failed on nx_azure_iot_hub_client_symmetric_key_set!: error code = 0x%08x\r\n", status); + printf("Failed on nx_azure_iot_pnp_client_symmetric_key_set!: error code = 0x%08x\r\n", status); } #endif /* USE_DEVICE_CERTIFICATE */ else if ((status = nx_azure_iot_provisioning_client_registration_payload_set(prov_client_ptr, (UCHAR *)SAMPLE_PNP_DPS_PAYLOAD, @@ -1115,8 +1038,8 @@ UINT status; * | | INIT | | | | | | * | | SUCCESS | | | | | +--------+ * | INIT | | CONNECT | | CONNECTING | | CONNECTED | | (TELEMETRY | - * | +-----------> +----->+ +-------> | | METHOD | - * | | | | | | | <--------+ DEVICETWIN) + * | +-----------> +----->+ +-------> | | COMMAND | + * | | | | | | | <--------+ PROPERTIES) * | | | | | | | | * +-----+--------+ +----+---+-----+ +------+-------+ +--------+-----+ * ^ ^ | | | @@ -1167,19 +1090,19 @@ UINT loop = NX_TRUE; sample_initialize_iothub(context); } - if (app_events & SAMPLE_DEVICE_TWIN_GET_EVENT) + if (app_events & SAMPLE_DEVICE_PROPERTIES_GET_EVENT) { - sample_device_twin_get_action(context); + sample_device_properties_get_action(context); } - if (app_events & SAMPLE_METHOD_MESSAGE_EVENT) + if (app_events & SAMPLE_COMMAND_MESSAGE_EVENT) { - sample_direct_method_action(context); + sample_command_action(context); } - if (app_events & SAMPLE_DEVICE_TWIN_DESIRED_PROPERTY_EVENT) + if (app_events & SAMPLE_DEVICE_DESIRED_PROPERTIES_EVENT) { - sample_device_twin_desired_property_action(context); + sample_device_desired_property_action(context); } if (app_events & SAMPLE_TELEMETRY_SEND_EVENT) @@ -1187,9 +1110,9 @@ UINT loop = NX_TRUE; sample_telemetry_action(context); } - if (app_events & SAMPLE_DEVICE_TWIN_REPORTED_PROPERTY_EVENT) + if (app_events & SAMPLE_DEVICE_REPORTED_PROPERTIES_EVENT) { - sample_device_twin_reported_property_action(context); + sample_device_reported_property_action(context); } if (app_events & SAMPLE_DISCONNECT_EVENT) diff --git a/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_thermostat_component.c b/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_thermostat_component.c index 79ce96d6..004ffa70 100644 --- a/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_thermostat_component.c +++ b/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_thermostat_component.c @@ -11,8 +11,6 @@ #include "sample_pnp_thermostat_component.h" -#include "nx_azure_iot_pnp_helpers.h" - #define SAMPLE_DEAFULT_START_TEMP_CELSIUS (22) #define DOUBLE_DECIMAL_PLACE_DIGITS (2) #define SAMPLE_COMMAND_SUCCESS_STATUS (200) @@ -44,17 +42,17 @@ static UCHAR scratch_buffer[256]; /* sample direct method implementation */ static UINT sample_get_maxmin_report(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, NX_AZURE_IOT_JSON_READER *json_reader_ptr, - NX_AZURE_IOT_JSON_WRITER *out_json_builder_ptr) + NX_AZURE_IOT_JSON_WRITER *out_json_writer_ptr) { UINT status; UCHAR *start_time = (UCHAR *)fake_start_report_time; UINT start_time_len = sizeof(fake_start_report_time) - 1; UCHAR time_buf[32]; - if (json_reader_ptr != NX_NULL) + /* Check for start time if present */ + if ((status = nx_azure_iot_json_reader_next_token(json_reader_ptr)) == NX_AZURE_IOT_SUCCESS) { - if (nx_azure_iot_json_reader_next_token(json_reader_ptr) || - nx_azure_iot_json_reader_token_string_get(json_reader_ptr, time_buf, + if (nx_azure_iot_json_reader_token_string_get(json_reader_ptr, time_buf, sizeof(time_buf), &start_time_len)) { return(NX_NOT_SUCCESSFUL); @@ -62,34 +60,41 @@ UCHAR time_buf[32]; start_time = time_buf; } + else + { + if (status != NX_AZURE_IOT_EMPTY_JSON) + { + return(NX_NOT_SUCCESSFUL); + } + } /* Build the method response payload */ - if (nx_azure_iot_json_writer_append_begin_object(out_json_builder_ptr) || - nx_azure_iot_json_writer_append_property_with_double_value(out_json_builder_ptr, + if (nx_azure_iot_json_writer_append_begin_object(out_json_writer_ptr) || + nx_azure_iot_json_writer_append_property_with_double_value(out_json_writer_ptr, (UCHAR *)report_max_temp_name, sizeof(report_max_temp_name) - 1, handle -> maxTemperature, DOUBLE_DECIMAL_PLACE_DIGITS) || - nx_azure_iot_json_writer_append_property_with_double_value(out_json_builder_ptr, + nx_azure_iot_json_writer_append_property_with_double_value(out_json_writer_ptr, (UCHAR *)report_min_temp_name, sizeof(report_min_temp_name) - 1, handle -> minTemperature, DOUBLE_DECIMAL_PLACE_DIGITS) || - nx_azure_iot_json_writer_append_property_with_double_value(out_json_builder_ptr, + nx_azure_iot_json_writer_append_property_with_double_value(out_json_writer_ptr, (UCHAR *)report_avg_temp_name, sizeof(report_avg_temp_name) - 1, handle -> avgTemperature, DOUBLE_DECIMAL_PLACE_DIGITS) || - nx_azure_iot_json_writer_append_property_with_string_value(out_json_builder_ptr, + nx_azure_iot_json_writer_append_property_with_string_value(out_json_writer_ptr, (UCHAR *)report_start_time_name, sizeof(report_start_time_name) - 1, (UCHAR *)start_time, start_time_len) || - nx_azure_iot_json_writer_append_property_with_string_value(out_json_builder_ptr, + nx_azure_iot_json_writer_append_property_with_string_value(out_json_writer_ptr, (UCHAR *)report_end_time_name, sizeof(report_end_time_name) - 1, (UCHAR *)fake_end_report_time, sizeof(fake_end_report_time) - 1) || - nx_azure_iot_json_writer_append_end_object(out_json_builder_ptr)) + nx_azure_iot_json_writer_append_end_object(out_json_writer_ptr)) { status = NX_NOT_SUCCESSFUL; } @@ -101,64 +106,48 @@ UCHAR time_buf[32]; return(status); } -static UINT append_temp(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr, VOID *context) -{ - return(nx_azure_iot_json_writer_append_double(json_writer_ptr, - *(double *)context, - DOUBLE_DECIMAL_PLACE_DIGITS)); -} - -static UINT append_max_temp(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr, VOID *context) -{ -SAMPLE_PNP_THERMOSTAT_COMPONENT *handle = (SAMPLE_PNP_THERMOSTAT_COMPONENT *)context; - - return(nx_azure_iot_json_writer_append_property_with_double_value(json_writer_ptr, - (UCHAR *)reported_max_temp_since_last_reboot, - sizeof(reported_max_temp_since_last_reboot) - 1, - handle -> maxTemperature, - DOUBLE_DECIMAL_PLACE_DIGITS)); -} - static VOID sample_send_target_temperature_report(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, - NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr, double temp, - INT status_code, UINT version, const CHAR *description) + NX_AZURE_IOT_PNP_CLIENT *iotpnp_client_ptr, double temp, + UINT status_code, ULONG version, const CHAR *description) { -UINT bytes_copied; UINT response_status; -UINT request_id; NX_AZURE_IOT_JSON_WRITER json_writer; -ULONG reported_property_version; - /* Build telemetry JSON payload */ - if (nx_azure_iot_json_writer_with_buffer_init(&json_writer, scratch_buffer, sizeof(scratch_buffer))) + if (nx_azure_iot_pnp_client_reported_properties_create(iotpnp_client_ptr, + &json_writer, NX_WAIT_FOREVER)) { - printf("Failed to create json writer\r\n"); + printf("Failed to build reported response\r\n"); return; } - if (nx_azure_iot_pnp_helper_build_reported_property_with_status(handle -> component_name_ptr, handle -> component_name_length, - (UCHAR *)target_temp_property_name, - sizeof(target_temp_property_name) - 1, - append_temp, (VOID *)&temp, status_code, - (UCHAR *)description, - strlen(description), version, &json_writer)) + if (nx_azure_iot_pnp_client_reported_property_component_begin(iotpnp_client_ptr, &json_writer, + handle ->component_name_ptr, + handle -> component_name_length) || + nx_azure_iot_pnp_client_reported_property_status_begin(iotpnp_client_ptr, + &json_writer, (UCHAR *)target_temp_property_name, + sizeof(target_temp_property_name) - 1, + status_code, version, + (const UCHAR *)description, strlen(description)) || + nx_azure_iot_json_writer_append_double(&json_writer, + temp, DOUBLE_DECIMAL_PLACE_DIGITS) || + nx_azure_iot_pnp_client_reported_property_status_end(iotpnp_client_ptr, &json_writer) || + nx_azure_iot_pnp_client_reported_property_component_end(iotpnp_client_ptr, &json_writer)) { - printf("Failed to create reported response\r\n"); + nx_azure_iot_json_writer_deinit(&json_writer); + printf("Failed to build reported response\r\n"); } else { - bytes_copied = nx_azure_iot_json_writer_get_bytes_used(&json_writer); - if (nx_azure_iot_hub_client_device_twin_reported_properties_send(iothub_client_ptr, - scratch_buffer, bytes_copied, - &request_id, &response_status, - &reported_property_version, - (5 * NX_IP_PERIODIC_RATE))) + if (nx_azure_iot_pnp_client_reported_properties_send(iotpnp_client_ptr, + &json_writer, NX_NULL, + &response_status, NX_NULL, + (5 * NX_IP_PERIODIC_RATE))) { printf("Failed to send reported response\r\n"); } - } - nx_azure_iot_json_writer_deinit(&json_writer); + nx_azure_iot_json_writer_deinit(&json_writer); + } } UINT sample_pnp_thermostat_init(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, @@ -224,7 +213,8 @@ UINT dm_status; return(NX_AZURE_IOT_SUCCESS); } -UINT sample_pnp_thermostat_telemetry_send(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr) +UINT sample_pnp_thermostat_telemetry_send(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, + NX_AZURE_IOT_PNP_CLIENT *iotpnp_client_ptr) { UINT status; NX_PACKET *packet_ptr; @@ -237,7 +227,7 @@ UINT buffer_length; } /* Create a telemetry message packet. */ - if ((status = nx_azure_iot_pnp_helper_telemetry_message_create(iothub_client_ptr, handle -> component_name_ptr, + if ((status = nx_azure_iot_pnp_client_telemetry_message_create(iotpnp_client_ptr, handle -> component_name_ptr, handle -> component_name_length, &packet_ptr, NX_WAIT_FOREVER))) { @@ -249,7 +239,7 @@ UINT buffer_length; if (nx_azure_iot_json_writer_with_buffer_init(&json_writer, scratch_buffer, sizeof(scratch_buffer))) { printf("Telemetry message failed to build message\r\n"); - nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); + nx_azure_iot_pnp_client_telemetry_message_delete(packet_ptr); return(NX_NOT_SUCCESSFUL); } @@ -263,17 +253,17 @@ UINT buffer_length; { printf("Telemetry message failed to build message\r\n"); nx_azure_iot_json_writer_deinit(&json_writer); - nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); + nx_azure_iot_pnp_client_telemetry_message_delete(packet_ptr); return(NX_NOT_SUCCESSFUL); } buffer_length = nx_azure_iot_json_writer_get_bytes_used(&json_writer); - if ((status = nx_azure_iot_hub_client_telemetry_send(iothub_client_ptr, packet_ptr, + if ((status = nx_azure_iot_pnp_client_telemetry_send(iotpnp_client_ptr, packet_ptr, (UCHAR *)scratch_buffer, buffer_length, NX_WAIT_FOREVER))) { printf("Telemetry message send failed!: error code = 0x%08x\r\n", status); nx_azure_iot_json_writer_deinit(&json_writer); - nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); + nx_azure_iot_pnp_client_telemetry_message_delete(packet_ptr); return(status); } @@ -285,47 +275,48 @@ UINT buffer_length; } UINT sample_pnp_thermostat_report_max_temp_since_last_reboot_property(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, - NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr) + NX_AZURE_IOT_PNP_CLIENT *iotpnp_client_ptr) { -UINT reported_properties_length; UINT status; -UINT response_status; -UINT request_id; -NX_AZURE_IOT_JSON_WRITER json_builder; -ULONG reported_property_version; +UINT response_status = 0; +NX_AZURE_IOT_JSON_WRITER json_writer; - if ((status = nx_azure_iot_json_writer_with_buffer_init(&json_builder, - scratch_buffer, - sizeof(scratch_buffer)))) + if ((status = nx_azure_iot_pnp_client_reported_properties_create(iotpnp_client_ptr, + &json_writer, NX_WAIT_FOREVER))) { - printf("Failed to initialize json writer\r\n"); - return(NX_NOT_SUCCESSFUL); + printf("Failed create reported properties: error code = 0x%08x\r\n", status); + return(status); } - if ((status = nx_azure_iot_pnp_helper_build_reported_property(handle -> component_name_ptr, - handle -> component_name_length, - append_max_temp, (VOID *)handle, - &json_builder))) + if ((status = nx_azure_iot_pnp_client_reported_property_component_begin(iotpnp_client_ptr, + &json_writer, + handle -> component_name_ptr, + handle -> component_name_length)) || + (status = nx_azure_iot_json_writer_append_property_with_double_value(&json_writer, + (const UCHAR *)reported_max_temp_since_last_reboot, + sizeof(reported_max_temp_since_last_reboot) - 1, + handle -> maxTemperature, + DOUBLE_DECIMAL_PLACE_DIGITS)) || + (status = nx_azure_iot_pnp_client_reported_property_component_end(iotpnp_client_ptr, + &json_writer))) { printf("Failed to build reported property!: error code = 0x%08x\r\n", status); - nx_azure_iot_json_writer_deinit(&json_builder); + nx_azure_iot_json_writer_deinit(&json_writer); return(status); } - reported_properties_length = nx_azure_iot_json_writer_get_bytes_used(&json_builder); - if ((status = nx_azure_iot_hub_client_device_twin_reported_properties_send(iothub_client_ptr, - scratch_buffer, - reported_properties_length, - &request_id, &response_status, - &reported_property_version, - (5 * NX_IP_PERIODIC_RATE)))) + if ((status = nx_azure_iot_pnp_client_reported_properties_send(iotpnp_client_ptr, + &json_writer, + NX_NULL, &response_status, + NX_NULL, + (5 * NX_IP_PERIODIC_RATE)))) { printf("Device twin reported properties failed!: error code = 0x%08x\r\n", status); - nx_azure_iot_json_writer_deinit(&json_builder); + nx_azure_iot_json_writer_deinit(&json_writer); return(status); } - nx_azure_iot_json_writer_deinit(&json_builder); + nx_azure_iot_json_writer_deinit(&json_writer); if ((response_status < 200) || (response_status >= 300)) { @@ -337,13 +328,12 @@ ULONG reported_property_version; } UINT sample_pnp_thermostat_process_property_update(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, - NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr, - UCHAR *component_name_ptr, UINT component_name_length, - UCHAR *property_name_ptr, UINT property_name_length, - NX_AZURE_IOT_JSON_READER *property_value_reader_ptr, UINT version) + NX_AZURE_IOT_PNP_CLIENT *iotpnp_client_ptr, + const UCHAR *component_name_ptr, UINT component_name_length, + NX_AZURE_IOT_JSON_READER *name_value_reader_ptr, UINT version) { double parsed_value = 0; -INT status_code; +UINT status_code; const CHAR *description; if (handle == NX_NULL) @@ -357,15 +347,16 @@ const CHAR *description; return(NX_NOT_SUCCESSFUL); } - if (property_name_length != (sizeof(target_temp_property_name) - 1) || - strncmp((CHAR *)property_name_ptr, (CHAR *)target_temp_property_name, property_name_length) != 0) + if (nx_azure_iot_json_reader_token_is_text_equal(name_value_reader_ptr, + (UCHAR *)target_temp_property_name, + sizeof(target_temp_property_name) - 1) == NX_FALSE) { - printf("PnP property=%.*s is not supported on thermostat component\r\n", - property_name_length, property_name_ptr); + printf("Unknown property for component %.*s received\r\n", component_name_length, component_name_ptr); status_code = 404; description = temp_response_description_failed; } - else if (nx_azure_iot_json_reader_token_double_get(property_value_reader_ptr, &parsed_value)) + else if (nx_azure_iot_json_reader_next_token(name_value_reader_ptr) || + nx_azure_iot_json_reader_token_double_get(name_value_reader_ptr, &parsed_value)) { status_code = 401; description = temp_response_description_failed; @@ -392,7 +383,7 @@ const CHAR *description; handle -> avgTemperature = handle -> allTemperatures / handle -> numTemperatureUpdates; } - sample_send_target_temperature_report(handle, iothub_client_ptr, parsed_value, + sample_send_target_temperature_report(handle, iotpnp_client_ptr, parsed_value, status_code, version, description); return(NX_AZURE_IOT_SUCCESS); diff --git a/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_thermostat_component.h b/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_thermostat_component.h index ffa2906f..37f73e2d 100644 --- a/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_thermostat_component.h +++ b/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_thermostat_component.h @@ -16,7 +16,7 @@ extern "C" { #endif -#include "nx_azure_iot_hub_client.h" +#include "nx_azure_iot_pnp_client.h" #include "nx_azure_iot_json_reader.h" #include "nx_azure_iot_json_writer.h" #include "nx_api.h" @@ -56,17 +56,17 @@ UINT sample_pnp_thermostat_process_command(SAMPLE_PNP_THERMOSTAT_COMPONENT *hand NX_AZURE_IOT_JSON_READER *json_reader_ptr, NX_AZURE_IOT_JSON_WRITER *json_response_ptr, UINT *status_code); -UINT sample_pnp_thermostat_telemetry_send(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr); +UINT sample_pnp_thermostat_telemetry_send(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, + NX_AZURE_IOT_PNP_CLIENT *iotpnp_client_ptr); UINT sample_pnp_thermostat_report_max_temp_since_last_reboot_property(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, - NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr); + NX_AZURE_IOT_PNP_CLIENT *iotpnp_client_ptr); UINT sample_pnp_thermostat_process_property_update(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, - NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr, - UCHAR *component_name_ptr, UINT component_name_length, - UCHAR *property_name_ptr, UINT property_name_length, - NX_AZURE_IOT_JSON_READER *property_value_reader_ptr, UINT version); + NX_AZURE_IOT_PNP_CLIENT *iotpnp_client_ptr, + const UCHAR *component_name_ptr, UINT component_name_length, + NX_AZURE_IOT_JSON_READER *name_value_reader_ptr, UINT version); #ifdef __cplusplus } |
