Cypress WICED MQTT¶
Prerequisites¶
- Download and install WICED studio from Cypress: https://community.cypress.com/community/wiced-wifi/wiced-wifi-documentation
- For this walkthrough we are using the WICED Studio 6.2.1 for Linux \([https://community.cypress.com/docs/DOC-15209](https://community.cypress.com/docs/DOC-15209)\)
- Once installed, remember to restart the system in order for drivers and udev security rules to be loaded.
- By default the WICED studio is installed to $HOME/WICED-Studio-6.2 and SDK + Source code at
$HOME/Documents/WICED-Studio-6.2/43xxx_Wi-Fi
.
Creating a new Murano MQTT product¶
First we'll Create a new Murano Product.
Choose Product Solution and "Start from Scratch".
Next we'll go to settings in our new product and change protocol to MQTT with the default port 8883. We'll also keep the default token authentication method.
After this we'll go to the "Resource" page and add a new string resource called wiced_resource
.
![Add wiced_resource](assets/Add_new_wiced_resource{: .screenshot}
We'll add a new device to our product.
![Add One Device](assets/Add_One_Device{: .screenshot}
After we've created the new device we can manually set the credentials. Save the generated token as we'll later need to use it for the #define PASSWORD
field in our example code.
We'll also need to get the IoT Connector FQDN to use as our mqtt broker domain.
Creating a new WICED application¶
Launch WICED Studio by executing the provided eclipse binary $HOME/WICED-Studio-6.2/eclipse
. Once launched you'll be asked wich project to use, then select 43xxx_Wi-Fi
.
WICED Studio organizes board applications under the apps/
directory. apps/demo/
more complete demo applications and apps/snip/
contains smaller example code snippets. More details on the folder strucutre is provided in the included README.txt
provided in the 43xxx_Wi-Fi
SDK directory.
We will use the provided apps/snip/secure_mqtt
example and modify it for connecting to murano.
Copy apps/snip/secure_mqtt
to a new project at apps/demo/secure_mqtt_exosite
. Rename secure_mqtt.c
-> secure_mqtt_exosite.c
and secure_mqtt.mk
-> secure_mqtt_exosite.mk
.
Setup WIFI¶
In order to get WIFI working on our device we'll also add a wifi configuration that's missing from the secure_mqtt snip. Copy include/default_wifi_config_dct.h
to apps/demo/secure_mqtt_exosite/wifi_config_dct.h
.
Modify wifi_config_dct.h
to add your wifi configuration:
-#define CLIENT_AP_SSID "YOUR_AP_SSID"
-#define CLIENT_AP_PASSPHRASE "YOUR_AP_PASSPHRASE"
+#define CLIENT_AP_SSID "YOUR_REAL_AP_SSID"
+#define CLIENT_AP_PASSPHRASE "YOUR_REAL_AP_PASSPHRASE"
Add Murano TLS Certificate¶
The secure_mqtt example uses TLS to connect to the MQTT broker. In order to connect to Murano we need to replace the provided root certificate with the one used by Murano. The root certificate need to be stored as a resource under the resources/apps/<project>
directory.
Download the Murano Service Certificate which can be found in (../device-connectivity/device-api-encryption-requirements.md) and save it under resources/apps/secure_mqtt_exosite/murano_root.cer
.
Note: You can choose between the public certificate issued by Digicert or the long-lived Exosite certificate which has a much longer expiration time.
We can now update our demo application make file \(apps/demo/secure_mqtt_exosite/secure_mqtt_exosite.mk
\) with the following changes:
-NAME := App_Secure_MQTT
+NAME := App_Secure_MQTT_Exosite
-$(NAME)_SOURCES := secure_mqtt.c \
+$(NAME)_SOURCES := secure_mqtt_exosite.c \
$(NAME)_COMPONENTS := protocols/MQTT
-$(NAME)_RESOURCES := apps/secure_mqtt/secure_mqtt_root_cacert.cer
+WIFI_CONFIG_DCT_H := wifi_config_dct.h
+
+$(NAME)_RESOURCES := apps/secure_mqtt_exosite/murano_root.cer
Enable SNI¶
In order to successfully and reliably connect Murano with the provided MQTT library \(libraries/protocosl/MQTT/
\) we will need to make two adjustments. First we need to add support for the SNI TLS extension which is required to connect to murano. We also need to fix a bug in how the MQTT library handles multiple MQTT messages in a single TCP frame.
/libraries/protocols/MQTT/mqtt_common.h
@@ -132,12 +132,13 @@ typedef struct wiced_mqtt_pkt_connect_s
typedef struct wiced_mqtt_security_s
{
- char* ca_cert; /* CA certificate, common between client and MQTT Broker */
- uint32_t ca_cert_len; /* CA certificate length */
- char* cert; /* Client certificate in PEM format */
- uint32_t cert_len; /* Client certificate length */
- char* key; /* Client private key */
- uint32_t key_len; /* Client private key length */
+ char* ca_cert; /* CA certificate, common between client and MQTT Broker */
+ uint32_t ca_cert_len; /* CA certificate length */
+ char* cert; /* Client certificate in PEM format */
+ uint32_t cert_len; /* Client certificate length */
+ char* key; /* Client private key */
+ uint32_t key_len; /* Client private key length */
+ wiced_tls_extension_t* tls_extension; /* Optional TLS extension for connecting to the MQTT Broker */
} wiced_mqtt_security_t;
/libraries/protocols/MQTT/mqtt_network.c
@@ -148,6 +148,11 @@ wiced_result_t mqtt_network_init( const wiced_ip_address_t *server_ip_address, u
wiced_tls_init_context( &socket->tls_context, NULL, (const char*) conn->peer_cn );
}
+ if ( security->tls_extension )
+ {
+ wiced_tls_set_extension(&socket->tls_context, security->tls_extension);
+ }
+
wiced_tcp_enable_tls( &socket->socket, &socket->tls_context );
}
@@ -298,11 +303,10 @@ static wiced_result_t mqtt_consume_tcp_packet( mqtt_connection_t* conn, mqtt_fra
/* Decrease the 'remaining' counter of the packet */
pkt->remaining_bytes = pkt->remaining_bytes - bytes_to_consume;
- /* If Packet is not exhausted yet and we've consumed the fragment of the packet completely;
- Move the data-pointer counter to next-fragment of the packet */
- if( bytes_to_consume == pkt->frag_length && pkt->remaining_bytes > 0 )
+ /* If Packet is not exhausted, fetch more messages from the same packet */
+ if( pkt->remaining_bytes > 0 )
{
- wiced_packet_get_data(pkt->packet, (uint16_t)bytes_to_consume, &pkt->data_start, (uint16_t*)&pkt->frag_length, &available_packet );
+ wiced_packet_get_data(pkt->packet, (uint16_t)pkt->consumed_bytes, &pkt->data_start, (uint16_t*)&pkt->frag_length, &available_packet );
}
return ret;
}
Configure for Murano¶
With these fixes in place now work on updating apps/demo/secure_mqtt_exosite/secure_mqtt_exosite.c
.
First we'll change some of the constants to match our Murano product, replace i24zq5fqdcylc0000
with your product ID.
@@ -118,13 +118,17 @@
* Constants
******************************************************/
/* Change the Broker domain address to match the server address */
-#define MQTT_BROKER_ADDRESS "test.mosquitto.org"
+#define MQTT_BROKER_ADDRESS "i24zq5fqdcylc0000.m2.exosite.io"
/* Name of topic name */
-#define WICED_TOPIC "MQTT/WICED/TOPIC"
+#define WICED_TOPIC "$resource/wiced_resource"
/* MQTT message content */
#define WICED_MESSAGE_STR "HELLO WICED"
/* MQTT client ID */
-#define CLIENT_ID "wiced"
+#define CLIENT_ID "" // Leave empty for connecting to Murano
+
+#define USER_NAME "" // Token authentication: leave empty, Password authentication: set device id
+
+#define PASSWORD "" // Token authentication: set token, Password authentication: set password
#define WICED_MQTT_TIMEOUT (5000)
Next we'll add the TLS extension object and change the resource path to our root certificate.
@@ -175,10 +179,11 @@ void application_start( void )
static wiced_mqtt_object_t mqtt_object;
wiced_result_t ret = WICED_SUCCESS;
uint32_t size_out;
+ wiced_tls_extension_t extension;
wiced_init( );
/* Read root CA certificate (self certified) from resources*/
- resource_get_readonly_buffer( &resources_apps_DIR_secure_mqtt_DIR_secure_mqtt_root_cacert_cer, 0, MQTT_MAX_RESOURCE_SIZE, &size_out, (const void **) &security.ca_cert );
+ resource_get_readonly_buffer( &resources_apps_DIR_secure_mqtt_exosite_DIR_digicert_global_root_cer, 0, MQTT_MAX_RESOURCE_SIZE, &size_out, (const void **) &security.ca_cert );
security.ca_cert_len = size_out;
/* Memory allocated for mqtt object*/
@@ -203,6 +208,13 @@ void application_start( void )
return;
}
+
+
+ // Enable SNI support to connect to Murano
+ extension.type = TLS_EXTENSION_TYPE_SERVER_NAME;
+ extension.extension_data.server_name = (uint8_t *)MQTT_BROKER_ADDRESS;
+ security.tls_extension = &extension;
+
wiced_mqtt_init( mqtt_object );
In Murano MQTT subscriptions are managed centrally from the cloud. There is no need for a device to subscribe/unsibscribe from topics so we should remove them from our application code. We also need to update the resource_free_readonly_buffer
call to point to our new resource.
wiced_rtos_init_semaphore( &semaphore );
while ( ret == WICED_SUCCESS )
@@ -211,18 +223,12 @@ void application_start( void )
WPRINT_APP_INFO(("[MQTT] Opening connection..."));
RUN_COMMAND_PRINT_STATUS_AND_BREAK_ON_ERROR( mqtt_conn_open( mqtt_object,&broker_address, WICED_STA_INTERFACE, callbacks, &security ), NULL, "Did you configure you broker IP address?\n" );
- WPRINT_APP_INFO(("[MQTT] Subscribing..."));
- RUN_COMMAND_PRINT_STATUS_AND_BREAK_ON_ERROR( mqtt_app_subscribe( mqtt_object, WICED_TOPIC , WICED_MQTT_QOS_DELIVER_EXACTLY_ONCE ), NULL, NULL );
-
WPRINT_APP_INFO(("[MQTT] Publishing..."));
- RUN_COMMAND_PRINT_STATUS_AND_BREAK_ON_ERROR( mqtt_app_publish( mqtt_object, WICED_MQTT_QOS_DELIVER_EXACTLY_ONCE, WICED_TOPIC, (uint8_t*)WICED_MESSAGE_STR ,sizeof(WICED_MESSAGE_STR) ), NULL, NULL );
+ RUN_COMMAND_PRINT_STATUS_AND_BREAK_ON_ERROR( mqtt_app_publish( mqtt_object, WICED_MQTT_QOS_DELIVER_AT_LEAST_ONCE, WICED_TOPIC, (uint8_t*)WICED_MESSAGE_STR ,sizeof(WICED_MESSAGE_STR) ), NULL, NULL );
WPRINT_APP_INFO(("[MQTT] Waiting some time for ping exchange...\n\n"));
wiced_rtos_delay_milliseconds( WICED_MQTT_DELAY_IN_MILLISECONDS * 10 );
- WPRINT_APP_INFO(("[MQTT] Unsubscribing..."));
- RUN_COMMAND_PRINT_STATUS_AND_BREAK_ON_ERROR( mqtt_app_unsubscribe( mqtt_object, WICED_TOPIC ), NULL, NULL );
-
WPRINT_APP_INFO(("[MQTT] Closing connection..."));
RUN_COMMAND_PRINT_STATUS_AND_BREAK_ON_ERROR( mqtt_conn_close( mqtt_object ), NULL, NULL );
@@ -236,7 +242,7 @@ void application_start( void )
free( mqtt_object );
mqtt_object = NULL;
/* Free security resources, only needed at initialization */
- resource_free_readonly_buffer( &resources_apps_DIR_secure_mqtt_DIR_secure_mqtt_root_cacert_cer, security.ca_cert );
+ resource_free_readonly_buffer( &resources_apps_DIR_secure_mqtt_exosite_DIR_digicert_global_root_cer, security.ca_cert );
}
Finally we need to update the MQTT conninfo
to reference our USER_NAME
and PASSWORD
constants.
@@ -353,8 +359,8 @@ static wiced_result_t mqtt_conn_open( wiced_mqtt_object_t mqtt_obj, wiced_ip_add
conninfo.clean_session = 1;
conninfo.client_id = (uint8_t*) CLIENT_ID;
conninfo.keep_alive = 10;
- conninfo.password = NULL;
- conninfo.username = NULL;
+ conninfo.password = (uint8_t*) PASSWORD;
+ conninfo.username = (uint8_t*) USER_NAME;
conninfo.peer_cn = NULL;
ret = wiced_mqtt_connect( mqtt_obj, address, interface, callback, security, &conninfo );
Deploy to the board¶
Now we can compile and deploy our application to the board. From the 43xxx_Wi-Fi/
directory we can execute the following
./make demo.secure_mqtt_exosite-AP72438V01
The make target is the directory path under apps/
but with directory slashes replaced with .
. apps/demo/secure_mqtt_exosite
-> demo.secure_mqtt_exosite
. -AP72438V01
refers our platform \(board\). All avaliable boards can be found under platforms/
. If your board is not avaliable you might need to contact your board provider to see if they have an WICED SDK platform configuration avaliable.
./make demo.secure_mqtt_exosite-AP72438V01 download run
MAKEFILE MAKECMDGOALS=demo.secure_mqtt_exosite-AP72438V01 download run OTA2_SUPPORT is disabled
Building Bootloader
Finished Building Bootloader
demo.secure_mqtt_exosite-AP72438V01
----------------------------------|---------|---------|
| | Static |
Module | Flash | RAM |
----------------------------------+---------+---------|
App | 1066 | 85 |
crc | 1060 | 0 |
DHCP_Server | 1408 | 132 |
DNS | 1972 | 44 |
Host MCU-family library | 15549 | 2692 |
Interrupt Vectors | 388 | 0 |
libc | 25865 | 3372 |
Linked_List | 434 | 0 |
mbedTLS | 113430 | 88 |
MQTT_Client | 7606 | 816 |
Networking | 4736 | 13912 |
NetX-Duo - Interfaces & Stacks | 0 | 16 |
Other | 47207 | 677 |
Packet Buffers | 0 | 22470 |
platform | 1480 | 256 |
RAM Initialisation | 2820 | 0 |
resources | 391721 | 0 |
Ring_Buffer | 112 | 0 |
SPI_Flash_Library_AP72438V01 | 510 | 0 |
Startup Stack & Link Script fill | 65 | 12 |
Supplicant - BESL | 4244 | 812 |
ThreadX | 8748 | 400 |
WICED | 4305 | 1040 |
Wiced_RO_FS | 566 | 0 |
WWD | 16178 | 3196 |
----------------------------------+---------+---------|
TOTAL (bytes) | 648650 | 50020 |
----------------------------------|---------|---------|
Downloading Bootloader ...
No changes detected
Download complete
Downloading DCT ...
No changes detected
Download complete
Downloading Application ...
No changes detected
Download complete
Resetting target
Target running
Build complete
Making .gdbinit
You should now be able to connect to your boards serial port to see the log output \(refer to the documentation for your board on how to do this for your device\).
ls /dev/ttyUSB*
\(find uart console\)
screen /dev/ttyUSB1 115200
\(might need sudo if your user is not part of the _dialout_ group\)
Please refer to the WICED SDK documentation for more details on how to connect to your specific device.
Starting WICED vWiced_006.002.001.0002
Platform AP72438V01 initialised
Started ThreadX v5.8
Initialising NetX_Duo v5.10_sp3
Creating Packet pools
WLAN MAC Address : B0:F1:EC:55:8C:8A
WLAN Firmware : wl0: Apr 30 2018 04:14:19 version 7.45.98.50 (r688715 CY) FWID 01-283fcdb9
WLAN CLM : API: 12.2 Data: 9.10.39 Compiler: 1.29.4 ClmImport: 1.36.3 Creation: 2018-04-11 22:31:21
Joining : exosite_taipei_03
Successfully joined : exosite_taipei_03
Obtaining IPv4 address via DHCP
DHCP CLIENT hostname WICED IP
IPv4 network ready IP: 172.16.10.14
Setting IPv6 link-local address
IPv6 network ready IP: FE80:0000:0000:0000:B2F1:ECFF:FE55:8C8A
Resolving IP address of MQTT broker...
Resolved Broker IP: 52.9.165.84
[MQTT] Opening connection...OK.
[MQTT] Publishing...OK.
[MQTT] Waiting some time for ping exchange...
[MQTT] Closing connection...OK.
[MQTT] Opening connection...OK.
[MQTT] Publishing...OK.
[MQTT] Waiting some time for ping exchange...