This library implements the port layer for the Azure SDK for Embedded C to work on PSoC™ 6 MCU connectivity-enabled platforms. This library automatically pulls the Azure SDK for Embedded C library; the port layer functions implemented by this library are used by the Azure SDK for Embedded C library.
Features
API Flow for HTTP Request
The Azure C SDK library provides various C APIs to connect with Azure Cloud and use the services offered. The Azure C SDK library also provide APIs to form and send an HTTP request to the server. This section provides the API call sequence to issue a secure or non-secure HTTP request to the server.
HTTP Client send request
+-----------------------+
| cy_http_client_init() |
+-----------------------+
|
v
+----------------------------+
| cy_http_client_create() |
+----------------------------+
|
v
+--------------------------+
| cy_http_client_connect() |
+--------------------------+
|
v
+------------------------+
| az_http_response_init()|
+------------------------+
|
v
+-------------------------------+
| az_http_client_send_request() |
+-------------------------------+
|
v
+-----------------------------+
| cy_http_client_disconnect() |
+-----------------------------+
|
v
+-------------------------+
| cy_http_client_delete() |
+-------------------------+
|
v
+-------------------------+
| cy_http_client_deinit() |
+-------------------------+
Supported Platform
Supported Frameworks
This middleware library is supported on the ModusToolbox™ environment:
- This environment uses the abstraction-rtos library for RTOS abstraction APIs, the http-client library for sending HTTP client requests and receiving server responses, and the mqtt library for Azure-supported IoT hub services.
Dependencies
Azure C SDK Port library depends on the following libraries:
Quick Start
This library is supported only on the ModusToolbox™ environment. The following section provides steps to build the library on the ModusToolbox™.
- Review and make the required changes to the pre-defined configuration files.
- The configuration files are bundled with the wifi-mw-core library for FreeRTOS, lwIP, and Mbed TLS. See README.md for more details.
- If the application is using bundle library then the configuration files are in the bundle library. For example if the application is using Wi-Fi core freertos lwip mbedtls bundle library, the configuration files are in
wifi-core-freertos-lwip-mbedtls/configs
folder. Similarly if the application is using Ethernet Core FreeRTOS lwIP mbedtls library, the configuration files are in ethernet-core-freertos-lwip-mbedtls/configs
folder.
- Define the following COMPONENTS in the application's Makefile for the HTTP client library. For additional information, see the "Quick Start" section in README.md.
COMPONENTS=FREERTOS MBEDTLS LWIP SECURE_SOCKETS
- The Azure C SDK Port library disables all the debug log messages by default. To enable log messages, the application must perform the following:
- Add the
ENABLE_AZ_PORT_LOGS
macro to the DEFINES in the code example's Makefile. The Makefile entry would look as follows: DEFINES+=ENABLE_AZ_PORT_LOGS
- Call the
cy_log_init()
function provided by the cy-log module. cy-log is part of the connectivity-utilities library. See connectivity-utilities library API documentation for cy-log details.
- Define the following macro in the application's Makefile for HTTP client configuration:
- This is an optional configuration to change the HTTP response header maximum length to 'N'. By default, this value will be set to 2048:
DEFINES+=HTTP_MAX_RESPONSE_HEADERS_SIZE_BYTES=<N>
- To configure the user agent name in all HTTP request headers. By default, this component will be added to the request header. Update this for user-defined agent values:
DEFINES += HTTP_USER_AGENT_VALUE="\"anycloud-http-client\""
- Define the following macros in the application's Makefile to mandatorily disable custom configuration header files that are not needed for the build:
DEFINES += HTTP_DO_NOT_USE_CUSTOM_CONFIG
DEFINES += MQTT_DO_NOT_USE_CUSTOM_CONFIG
- If the user application doesn't use MQTT client features, add the following path in the .cyignore file of the application to exclude the coreMQTT source files from the build:
$(SEARCH_aws-iot-device-sdk-embedded-C)/libraries/standard/coreMQTT
libs/aws-iot-device-sdk-embedded-C/libraries/standard/coreMQTT
- Sample applications for Azure IoT hub, and Azure DPS features are located in folder
./sample_app/
. For running the sample applications on PSoC™ 6 MCU connectivity-enabled platforms, Refer README.md located in *./sample_app/README.md*.
Addtional Information
Code Snippets
This section provides code snippets for this library on the ModusToolbox™ environment. The code snippets given under this section uses C APIs. In general, the library features are tested on ModusToolbox™ using C APIs.
The code snippets given in this section demonstrates how Azure APIs can be used for issuing a secure and non-secure HTTP request to the server.
Code Snippet 1: Send a non-secure HTTP GET request to the server
Send a HTTP GET request (header + body) to the server and receive response
#define MAKE_IPV4_ADDRESS(a, b, c, d) ((((uint32_t) d) << 24) | \
(((uint32_t) c) << 16) | \
(((uint32_t) b) << 8) |\
((uint32_t) a))
#define SERVER_IP_ADDRESS MAKE_IPV4_ADDRESS(192, 168, 18, 9)
#define SERVER_HOST "httpbin.org"
#define SERVER_PORT 80
#define TRANSPORT_SEND_RECV_TIMEOUT_MS ( 5000 )
#define GET_PATH "/get"
#define USER_BUFFER_LENGTH ( 2048 )
#define REQUEST_BODY "Hello, world!"
#define REQUEST_BODY_LENGTH ( sizeof( REQUEST_BODY ) - 1 )
static uint8_t userBuffer[ USER_BUFFER_LENGTH ];
static cy_awsport_server_info_t server_info;
static cy_http_client_t handle;
static az_http_request az_request;
static _az_http_request_header az_header;
static az_http_response az_response;
void snippet_non_secure_http_client_send(void)
{
cy_rslt_t result = CY_RSLT_SUCCESS;
az_result returnStatus;
cy_http_disconnect_callback_t http_cb;
( void ) memset( &server_info, 0, sizeof( server_info ) );
server_info.host_name = SERVER_HOST;
server_info.port = SERVER_PORT;
result = cy_http_client_init();
if( result != CY_RSLT_SUCCESS )
{
}
http_cb = disconnect_callback;
result = cy_http_client_create( NULL, &server_info, http_cb, NULL, &handle );
if( result != CY_RSLT_SUCCESS )
{
}
result = cy_http_client_connect( handle, TRANSPORT_SEND_RECV_TIMEOUT_MS, TRANSPORT_SEND_RECV_TIMEOUT_MS );
if( result != CY_RSLT_SUCCESS )
{
}
az_span az_buffer = az_span_create( ( uint8_t* )userBuffer, ( int32_t )USER_BUFFER_LENGTH );
returnStatus = az_http_response_init( &az_response, az_buffer );
if( returnStatus != AZ_OK )
{
}
az_request._internal.context = handle;
az_request._internal.method = az_http_method_get();
az_request._internal.url._internal.ptr = ( uint8_t * )GET_PATH;
az_request._internal.url_length = strlen( GET_PATH );
az_request._internal.headers_length = 1;
az_header.name._internal.ptr = ( uint8_t * )"Connection";
az_header.name._internal.size = sizeof( "Connection" ) - 1;
az_header.value._internal.ptr = ( uint8_t * )"keep-alive";
az_header.value._internal.size = sizeof( "keep-alive" ) - 1;
az_request._internal.headers._internal.ptr = ( uint8_t * )&az_header;
az_request._internal.headers._internal.size = sizeof ( az_header ) * az_request._internal.headers_length;
az_request._internal.body._internal.ptr = ( uint8_t * )REQUEST_BODY;
az_request._internal.body._internal.size = REQUEST_BODY_LENGTH;
returnStatus = az_http_client_send_request( &az_request, &az_response );
if( returnStatus != AZ_OK )
{
}
result = cy_http_client_disconnect(handle);
if( result != CY_RSLT_SUCCESS )
{
}
result = cy_http_client_delete(handle);
if( result != CY_RSLT_SUCCESS )
{
}
result = cy_http_client_deinit();
if( result != CY_RSLT_SUCCESS )
{
}
}
Code Snippet 2: Send a secure HTTP GET request to the server
Send a HTTP GET request (header + body) to the server and receive the response
#define MAKE_IPV4_ADDRESS(a, b, c, d) ((((uint32_t) d) << 24) | \
(((uint32_t) c) << 16) | \
(((uint32_t) b) << 8) |\
((uint32_t) a))
#define SERVER_IP_ADDRESS MAKE_IPV4_ADDRESS(192, 168, 18, 9)
#define SERVER_HOST "httpbin.org"
#define SERVER_PORT 80
#define TRANSPORT_SEND_RECV_TIMEOUT_MS ( 5000 )
#define GET_PATH "/get"
#define USER_BUFFER_LENGTH ( 2048 )
#define REQUEST_BODY "Hello, world!"
#define REQUEST_BODY_LENGTH ( sizeof( REQUEST_BODY ) - 1 )
static uint8_t userBuffer[ USER_BUFFER_LENGTH ];
static cy_awsport_ssl_credentials_t credentials;
static cy_awsport_server_info_t server_info;
static cy_http_client_t handle;
static az_http_request az_request;
static _az_http_request_header az_header;
static az_http_response az_response;
#define SSL_SERVERCERT_PEM \
"-----BEGIN CERTIFICATE-----\n" \
"........base64 data........\n" \
"-----END CERTIFICATE-----"
#define SSL_SERVERKEY_PEM \
"-----BEGIN RSA PRIVATE KEY-----\n" \
"..........base64 data..........\n" \
"-----END RSA PRIVATE KEY-----"
#define SSL_ROOTCA_PEM \
"-----BEGIN CERTIFICATE-----\n" \
"........base64 data........\n" \
"-----END CERTIFICATE-----"
void snippet_secure_http_client_send(void)
{
cy_rslt_t result = CY_RSLT_SUCCESS;
az_result returnStatus;
cy_http_disconnect_callback_t http_cb;
( void ) memset( &credentials, 0, sizeof( credentials ) );
( void ) memset( &server_info, 0, sizeof( server_info ) );
credentials.client_cert = ( const char * ) &SSL_SERVERCERT_PEM;
credentials.client_cert_size = sizeof( SSL_SERVERCERT_PEM );
credentials.private_key = ( const char * ) &SSL_SERVERKEY_PEM;
credentials.private_key_size = sizeof( SSL_SERVERKEY_PEM );
credentials.root_ca = ( const char * ) &SSL_ROOTCA_PEM;
credentials.root_ca_size = sizeof( SSL_ROOTCA_PEM );
server_info.host_name = SERVER_HOST;
server_info.port = SERVER_PORT;
result = cy_http_client_init();
if( result != CY_RSLT_SUCCESS )
{
}
http_cb = disconnect_callback;
result = cy_http_client_create( &credentials, &server_info, http_cb, NULL, &handle );
if( result != CY_RSLT_SUCCESS )
{
}
result = cy_http_client_connect( handle, TRANSPORT_SEND_RECV_TIMEOUT_MS, TRANSPORT_SEND_RECV_TIMEOUT_MS );
if( result != CY_RSLT_SUCCESS )
{
}
az_span az_buffer = az_span_create( ( uint8_t* )userBuffer, ( int32_t )USER_BUFFER_LENGTH );
returnStatus = az_http_response_init( &az_response, az_buffer );
if( returnStatus != AZ_OK )
{
}
az_request._internal.context = handle;
az_request._internal.method = az_http_method_get();
az_request._internal.url._internal.ptr = ( uint8_t * )GET_PATH;
az_request._internal.url_length = strlen( GET_PATH );
az_request._internal.headers_length = 1;
az_header.name._internal.ptr = ( uint8_t * )"Connection";
az_header.name._internal.size = sizeof( "Connection" ) - 1;
az_header.value._internal.ptr = ( uint8_t * )"keep-alive";
az_header.value._internal.size = sizeof( "keep-alive" ) - 1;
az_request._internal.headers._internal.ptr = ( uint8_t * )&az_header;
az_request._internal.headers._internal.size = sizeof ( az_header ) * az_request._internal.headers_length;
az_request._internal.body._internal.ptr = ( uint8_t * )REQUEST_BODY;
az_request._internal.body._internal.size = REQUEST_BODY_LENGTH;
returnStatus = az_http_client_send_request( &az_request, &az_response );
if( returnStatus != AZ_OK )
{
}
result = cy_http_client_disconnect(handle);
if( result != CY_RSLT_SUCCESS )
{
}
result = cy_http_client_delete(handle);
if( result != CY_RSLT_SUCCESS )
{
}
result = cy_http_client_deinit();
if( result != CY_RSLT_SUCCESS )
{
}
}