]> granicus.if.org Git - esp-idf/blob - examples/protocols/aws_iot/subscribe_publish/main/subscribe_publish_sample.c
aws_iot: fix aws_iot examples without NVS initialization
[esp-idf] / examples / protocols / aws_iot / subscribe_publish / main / subscribe_publish_sample.c
1 /*
2  * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  * Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License").
6  * You may not use this file except in compliance with the License.
7  * A copy of the License is located at
8  *
9  *  http://aws.amazon.com/apache2.0
10  *
11  * or in the "license" file accompanying this file. This file is distributed
12  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied. See the License for the specific language governing
14  * permissions and limitations under the License.
15  */
16 /**
17  * @file subscribe_publish_sample.c
18  * @brief simple MQTT publish and subscribe on the same topic
19  *
20  * This example takes the parameters from the build configuration and establishes a connection to the AWS IoT MQTT Platform.
21  * It subscribes and publishes to the same topic - "test_topic/esp32"
22  *
23  * Some setup is required. See example README for details.
24  *
25  */
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <ctype.h>
29 #include <unistd.h>
30 #include <limits.h>
31 #include <string.h>
32
33 #include "freertos/FreeRTOS.h"
34 #include "freertos/task.h"
35 #include "freertos/event_groups.h"
36 #include "esp_system.h"
37 #include "esp_wifi.h"
38 #include "esp_event_loop.h"
39 #include "esp_log.h"
40 #include "esp_vfs_fat.h"
41 #include "driver/sdmmc_host.h"
42
43 #include "nvs.h"
44 #include "nvs_flash.h"
45
46 #include "aws_iot_config.h"
47 #include "aws_iot_log.h"
48 #include "aws_iot_version.h"
49 #include "aws_iot_mqtt_client_interface.h"
50
51 static const char *TAG = "subpub";
52
53 /* The examples use simple WiFi configuration that you can set via
54    'make menuconfig'.
55
56    If you'd rather not, just change the below entries to strings with
57    the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
58 */
59 #define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID
60 #define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD
61
62 /* FreeRTOS event group to signal when we are connected & ready to make a request */
63 static EventGroupHandle_t wifi_event_group;
64
65 /* The event group allows multiple bits for each event,
66    but we only care about one event - are we connected
67    to the AP with an IP? */
68 const int CONNECTED_BIT = BIT0;
69
70
71 /* CA Root certificate, device ("Thing") certificate and device
72  * ("Thing") key.
73
74    Example can be configured one of two ways:
75
76    "Embedded Certs" are loaded from files in "certs/" and embedded into the app binary.
77
78    "Filesystem Certs" are loaded from the filesystem (SD card, etc.)
79
80    See example README for more details.
81 */
82 #if defined(CONFIG_EXAMPLE_EMBEDDED_CERTS)
83
84 extern const uint8_t aws_root_ca_pem_start[] asm("_binary_aws_root_ca_pem_start");
85 extern const uint8_t aws_root_ca_pem_end[] asm("_binary_aws_root_ca_pem_end");
86 extern const uint8_t certificate_pem_crt_start[] asm("_binary_certificate_pem_crt_start");
87 extern const uint8_t certificate_pem_crt_end[] asm("_binary_certificate_pem_crt_end");
88 extern const uint8_t private_pem_key_start[] asm("_binary_private_pem_key_start");
89 extern const uint8_t private_pem_key_end[] asm("_binary_private_pem_key_end");
90
91 #elif defined(CONFIG_EXAMPLE_FILESYSTEM_CERTS)
92
93 static const char * DEVICE_CERTIFICATE_PATH = CONFIG_EXAMPLE_CERTIFICATE_PATH;
94 static const char * DEVICE_PRIVATE_KEY_PATH = CONFIG_EXAMPLE_PRIVATE_KEY_PATH;
95 static const char * ROOT_CA_PATH = CONFIG_EXAMPLE_ROOT_CA_PATH;
96
97 #else
98 #error "Invalid method for loading certs"
99 #endif
100
101 /**
102  * @brief Default MQTT HOST URL is pulled from the aws_iot_config.h
103  */
104 char HostAddress[255] = AWS_IOT_MQTT_HOST;
105
106 /**
107  * @brief Default MQTT port is pulled from the aws_iot_config.h
108  */
109 uint32_t port = AWS_IOT_MQTT_PORT;
110
111
112 static esp_err_t event_handler(void *ctx, system_event_t *event)
113 {
114     switch(event->event_id) {
115     case SYSTEM_EVENT_STA_START:
116         esp_wifi_connect();
117         break;
118     case SYSTEM_EVENT_STA_GOT_IP:
119         xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
120         break;
121     case SYSTEM_EVENT_STA_DISCONNECTED:
122         /* This is a workaround as ESP32 WiFi libs don't currently
123            auto-reassociate. */
124         esp_wifi_connect();
125         xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
126         break;
127     default:
128         break;
129     }
130     return ESP_OK;
131 }
132
133 void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen,
134                                     IoT_Publish_Message_Params *params, void *pData) {
135     ESP_LOGI(TAG, "Subscribe callback");
136     ESP_LOGI(TAG, "%.*s\t%.*s", topicNameLen, topicName, (int) params->payloadLen, (char *)params->payload);
137 }
138
139 void disconnectCallbackHandler(AWS_IoT_Client *pClient, void *data) {
140     ESP_LOGW(TAG, "MQTT Disconnect");
141     IoT_Error_t rc = FAILURE;
142
143     if(NULL == pClient) {
144         return;
145     }
146
147     if(aws_iot_is_autoreconnect_enabled(pClient)) {
148         ESP_LOGI(TAG, "Auto Reconnect is enabled, Reconnecting attempt will start now");
149     } else {
150         ESP_LOGW(TAG, "Auto Reconnect not enabled. Starting manual reconnect...");
151         rc = aws_iot_mqtt_attempt_reconnect(pClient);
152         if(NETWORK_RECONNECTED == rc) {
153             ESP_LOGW(TAG, "Manual Reconnect Successful");
154         } else {
155             ESP_LOGW(TAG, "Manual Reconnect Failed - %d", rc);
156         }
157     }
158 }
159
160 void aws_iot_task(void *param) {
161     char cPayload[100];
162
163     int32_t i = 0;
164
165     IoT_Error_t rc = FAILURE;
166
167     AWS_IoT_Client client;
168     IoT_Client_Init_Params mqttInitParams = iotClientInitParamsDefault;
169     IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault;
170
171     IoT_Publish_Message_Params paramsQOS0;
172     IoT_Publish_Message_Params paramsQOS1;
173
174     ESP_LOGI(TAG, "AWS IoT SDK Version %d.%d.%d-%s", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG);
175
176     mqttInitParams.enableAutoReconnect = false; // We enable this later below
177     mqttInitParams.pHostURL = HostAddress;
178     mqttInitParams.port = port;
179
180 #if defined(CONFIG_EXAMPLE_EMBEDDED_CERTS)
181     mqttInitParams.pRootCALocation = (const char *)aws_root_ca_pem_start;
182     mqttInitParams.pDeviceCertLocation = (const char *)certificate_pem_crt_start;
183     mqttInitParams.pDevicePrivateKeyLocation = (const char *)private_pem_key_start;
184
185 #elif defined(CONFIG_EXAMPLE_FILESYSTEM_CERTS)
186     mqttInitParams.pRootCALocation = ROOT_CA_PATH;
187     mqttInitParams.pDeviceCertLocation = DEVICE_CERTIFICATE_PATH;
188     mqttInitParams.pDevicePrivateKeyLocation = DEVICE_PRIVATE_KEY_PATH;
189 #endif
190
191     mqttInitParams.mqttCommandTimeout_ms = 20000;
192     mqttInitParams.tlsHandshakeTimeout_ms = 5000;
193     mqttInitParams.isSSLHostnameVerify = true;
194     mqttInitParams.disconnectHandler = disconnectCallbackHandler;
195     mqttInitParams.disconnectHandlerData = NULL;
196
197 #ifdef CONFIG_EXAMPLE_SDCARD_CERTS
198     ESP_LOGI(TAG, "Mounting SD card...");
199     sdmmc_host_t host = SDMMC_HOST_DEFAULT();
200     sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
201     esp_vfs_fat_sdmmc_mount_config_t mount_config = {
202         .format_if_mount_failed = false,
203         .max_files = 3,
204     };
205     sdmmc_card_t* card;
206     esp_err_t ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card);
207     if (ret != ESP_OK) {
208         ESP_LOGE(TAG, "Failed to mount SD card VFAT filesystem.");
209         abort();
210     }
211 #endif
212
213     rc = aws_iot_mqtt_init(&client, &mqttInitParams);
214     if(SUCCESS != rc) {
215         ESP_LOGE(TAG, "aws_iot_mqtt_init returned error : %d ", rc);
216         abort();
217     }
218
219     /* Wait for WiFI to show as connected */
220     xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
221                         false, true, portMAX_DELAY);
222
223     connectParams.keepAliveIntervalInSec = 10;
224     connectParams.isCleanSession = true;
225     connectParams.MQTTVersion = MQTT_3_1_1;
226     /* Client ID is set in the menuconfig of the example */
227     connectParams.pClientID = CONFIG_AWS_EXAMPLE_CLIENT_ID;
228     connectParams.clientIDLen = (uint16_t) strlen(CONFIG_AWS_EXAMPLE_CLIENT_ID);
229     connectParams.isWillMsgPresent = false;
230
231     ESP_LOGI(TAG, "Connecting to AWS...");
232     do {
233         rc = aws_iot_mqtt_connect(&client, &connectParams);
234         if(SUCCESS != rc) {
235             ESP_LOGE(TAG, "Error(%d) connecting to %s:%d", rc, mqttInitParams.pHostURL, mqttInitParams.port);
236             vTaskDelay(1000 / portTICK_RATE_MS);
237         }
238     } while(SUCCESS != rc);
239
240     /*
241      * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h
242      *  #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL
243      *  #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL
244      */
245     rc = aws_iot_mqtt_autoreconnect_set_status(&client, true);
246     if(SUCCESS != rc) {
247         ESP_LOGE(TAG, "Unable to set Auto Reconnect to true - %d", rc);
248         abort();
249     }
250
251     const char *TOPIC = "test_topic/esp32";
252     const int TOPIC_LEN = strlen(TOPIC);
253
254     ESP_LOGI(TAG, "Subscribing...");
255     rc = aws_iot_mqtt_subscribe(&client, TOPIC, TOPIC_LEN, QOS0, iot_subscribe_callback_handler, NULL);
256     if(SUCCESS != rc) {
257         ESP_LOGE(TAG, "Error subscribing : %d ", rc);
258         abort();
259     }
260
261     sprintf(cPayload, "%s : %d ", "hello from SDK", i);
262
263     paramsQOS0.qos = QOS0;
264     paramsQOS0.payload = (void *) cPayload;
265     paramsQOS0.isRetained = 0;
266
267     paramsQOS1.qos = QOS1;
268     paramsQOS1.payload = (void *) cPayload;
269     paramsQOS1.isRetained = 0;
270
271     while((NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc)) {
272
273         //Max time the yield function will wait for read messages
274         rc = aws_iot_mqtt_yield(&client, 100);
275         if(NETWORK_ATTEMPTING_RECONNECT == rc) {
276             // If the client is attempting to reconnect we will skip the rest of the loop.
277             continue;
278         }
279
280         ESP_LOGI(TAG, "-->sleep");
281         vTaskDelay(1000 / portTICK_RATE_MS);
282         sprintf(cPayload, "%s : %d ", "hello from ESP32 (QOS0)", i++);
283         paramsQOS0.payloadLen = strlen(cPayload);
284         rc = aws_iot_mqtt_publish(&client, TOPIC, TOPIC_LEN, &paramsQOS0);
285
286         sprintf(cPayload, "%s : %d ", "hello from ESP32 (QOS1)", i++);
287         paramsQOS1.payloadLen = strlen(cPayload);
288         rc = aws_iot_mqtt_publish(&client, TOPIC, TOPIC_LEN, &paramsQOS1);
289         if (rc == MQTT_REQUEST_TIMEOUT_ERROR) {
290             ESP_LOGW(TAG, "QOS1 publish ack not received.");
291             rc = SUCCESS;
292         }
293     }
294
295     ESP_LOGE(TAG, "An error occurred in the main loop.");
296     abort();
297 }
298
299 static void initialise_wifi(void)
300 {
301     tcpip_adapter_init();
302     wifi_event_group = xEventGroupCreate();
303     ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
304     wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
305     ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
306     ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
307     wifi_config_t wifi_config = {
308         .sta = {
309             .ssid = EXAMPLE_WIFI_SSID,
310             .password = EXAMPLE_WIFI_PASS,
311         },
312     };
313     ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid);
314     ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
315     ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
316     ESP_ERROR_CHECK( esp_wifi_start() );
317 }
318
319
320 void app_main()
321 {
322     // Initialize NVS.
323     esp_err_t err = nvs_flash_init();
324     if (err == ESP_ERR_NVS_NO_FREE_PAGES) {
325         ESP_ERROR_CHECK(nvs_flash_erase());
326         err = nvs_flash_init();
327     }
328     ESP_ERROR_CHECK( err );
329
330     initialise_wifi();
331 #ifdef CONFIG_MBEDTLS_DEBUG
332     const size_t stack_size = 36*1024;
333 #else
334     const size_t stack_size = 36*1024;
335 #endif
336     xTaskCreatePinnedToCore(&aws_iot_task, "aws_iot_task", stack_size, NULL, 5, NULL, 1);
337 }