├── .gitignore ├── .gitlab-ci.yml ├── .gitmodules ├── CMakeLists.txt ├── Kconfig ├── README.md ├── component.mk ├── examples ├── tls_basic │ ├── CMakeLists.txt │ ├── Makefile │ ├── README.md │ ├── main │ │ ├── CMakeLists.txt │ │ ├── Kconfig.projbuild │ │ ├── component.mk │ │ ├── mqtt_eclipse_org.pem │ │ ├── tls_basic_main.c │ │ └── utilities │ │ │ ├── BasicTLSMQTTExample.c │ │ │ └── demo_config.h │ └── sdkconfig.defaults └── tls_mutual_auth │ ├── CMakeLists.txt │ ├── Makefile │ ├── README.md │ ├── aws-readme │ ├── esp32-c3.md │ └── esp32-s2.md │ ├── main │ ├── CMakeLists.txt │ ├── Kconfig.projbuild │ ├── client.crt │ ├── client.key │ ├── component.mk │ ├── root_cert_auth.pem │ ├── tls_mutual_auth.c │ └── utilities │ │ ├── MutualAuthMQTTExample.c │ │ └── demo_config.h │ └── sdkconfig.defaults └── port ├── exponential_backoff ├── exponential_backoff.c └── exponential_backoff.h ├── include └── core_mqtt_config.h ├── logging ├── logging_levels.h └── logging_stack.h ├── network_transport ├── tls_freertos.c └── tls_freertos.h └── platform ├── platform.c └── platform.h /.gitignore: -------------------------------------------------------------------------------- 1 | .settings 2 | .project 3 | .cproject 4 | .vscode/ 5 | 6 | build 7 | sdkconfig 8 | sdkconfig.old 9 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | stages: 2 | - build 3 | - deploy 4 | 5 | variables: 6 | BATCH_BUILD: "1" 7 | V: "0" 8 | MAKEFLAGS: "-j5 --no-keep-going" 9 | IDF_CI_BUILD: "1" 10 | 11 | build_esp8266_demo: 12 | stage: build 13 | image: $CI_DOCKER_REGISTRY/ae-esp8266-ci-env:latest-029382ce 14 | tags: 15 | - build 16 | script: 17 | - git submodule update --init --recursive 18 | - export IDF_PATH=~/.espressif/rtos/ESP8266_RTOS_SDK 19 | - cd examples/tls_basic 20 | - rm -rf build/ sdkconfig sdkconfig.old 21 | - make defconfig 22 | - make 23 | - cd ../../ 24 | - cd examples/tls_mutual_auth 25 | - rm -rf build/ sdkconfig sdkconfig.old 26 | - make defconfig 27 | - make 28 | 29 | build_esp32_demo_cmake_v4.2: 30 | stage: build 31 | image: $CI_DOCKER_REGISTRY/ae-esp32-ci-env:latest-3cf42c4c 32 | tags: 33 | - build 34 | script: 35 | - git submodule update --init --recursive 36 | - export IDF_PATH=~/.espressif/idf/esp-idf-v4.2 37 | - . $IDF_PATH/export.sh 38 | - cd examples/tls_basic 39 | - rm -rf build/ sdkconfig sdkconfig.old 40 | - idf.py build 41 | - cd ../../ 42 | - cd examples/tls_mutual_auth 43 | - rm -rf build/ sdkconfig sdkconfig.old 44 | - idf.py build 45 | 46 | build_esp32s2_demo_cmake_master: 47 | stage: build 48 | image: $CI_DOCKER_REGISTRY/ae-esp32-ci-env:latest-3cf42c4c 49 | tags: 50 | - build 51 | script: 52 | - git submodule update --init --recursive 53 | - export IDF_PATH=~/.espressif/idf/esp-idf-v4.2 54 | - . $IDF_PATH/export.sh 55 | - cd examples/tls_basic 56 | - rm -rf build/ sdkconfig sdkconfig.old 57 | - idf.py set-target esp32s2 58 | - idf.py build 59 | - cd ../../ 60 | - cd examples/tls_mutual_auth 61 | - rm -rf build/ sdkconfig sdkconfig.old 62 | - idf.py set-target esp32s2 63 | - idf.py build 64 | 65 | push_to_github: 66 | stage: deploy 67 | only: 68 | - master 69 | - /^release\/v/ 70 | # when: on_success 71 | image: espressif/esp32-ci-env 72 | variables: 73 | GIT_STRATEGY: clone 74 | GITHUB_PUSH_REFS: refs/remotes/origin/release refs/remotes/origin/master 75 | script: 76 | - mkdir -p ~/.ssh 77 | - chmod 700 ~/.ssh 78 | - echo -n $GH_PUSH_KEY >> ~/.ssh/id_rsa_base64 79 | - base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa 80 | - chmod 600 ~/.ssh/id_rsa 81 | - echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config 82 | - git remote add github git@github.com:espressif/esp-ali-smartliving.git 83 | # What the next line of script does: goes through the list of refs for all branches we push to github, 84 | # generates a snippet of shell which is evaluated. The snippet checks CI_BUILD_REF against the SHA 85 | # (aka objectname) at tip of each branch, and if any SHAs match then it checks out the local branch 86 | # and then pushes that ref to a corresponding github branch 87 | # 88 | # NB: In gitlab 9.x, CI_BUILD_REF was deprecated. New name is CI_COMMIT_REF. If below command suddenly 89 | # generates bash syntax errors, this is probably why. 90 | - eval $(git for-each-ref --shell bash --format 'if [ $CI_BUILD_REF == %(objectname) ]; then git checkout -B %(refname:strip=3); git push --follow-tags github %(refname:strip=3); fi;' $GITHUB_PUSH_REFS) 91 | 92 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "coreMQTT"] 2 | path = coreMQTT 3 | url = https://github.com/FreeRTOS/coreMQTT.git 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Component Makefile 3 | # 4 | 5 | set (includes) 6 | set (srcs) 7 | set (priv_includes) 8 | 9 | list(APPEND includes 10 | "coreMQTT/source/include" 11 | "coreMQTT/source/interface" 12 | "port/include" 13 | "port/exponential_backoff" 14 | "port/logging" 15 | "port/network_transport" 16 | "port/platform" 17 | ) 18 | 19 | list(APPEND srcs 20 | "coreMQTT/source/core_mqtt_serializer.c" 21 | "coreMQTT/source/core_mqtt_state.c" 22 | "coreMQTT/source/core_mqtt.c" 23 | "port/exponential_backoff/exponential_backoff.c" 24 | "port/network_transport/tls_freertos.c" 25 | "port/platform/platform.c" 26 | ) 27 | 28 | idf_component_register(SRCS "${srcs}" 29 | INCLUDE_DIRS ${includes} 30 | PRIV_INCLUDE_DIRS ${priv_includes} 31 | REQUIRES lwip nghttp mbedtls tcp_transport) 32 | -------------------------------------------------------------------------------- /Kconfig: -------------------------------------------------------------------------------- 1 | menu "FreeRTOS coreMQTT" 2 | 3 | config MQTT_STATE_ARRAY_MAX_COUNT 4 | int "Determines the maximum number of MQTT PUBLISH messages, pending acknowledgement at a time" 5 | range 1 16 6 | default 10 7 | help 8 | Determines the maximum number of MQTT PUBLISH messages, pending 9 | acknowledgement at a time, that are supported for incoming and outgoing 10 | direction of messages, separately. 11 | 12 | config MQTT_MAX_CONNACK_RECEIVE_RETRY_COUNT 13 | int "Retry count for reading CONNACK from network" 14 | range 1 16 15 | default 2 16 | help 17 | It will be used only when the timeoutMs parameter of MQTT_Connect() is passed as 0 . 18 | The transport receive for CONNACK will be retried MQTT_MAX_CONNACK_RECEIVE_RETRY_COUNT 19 | times before timing out. A value of 0 for this config will cause the transport receive 20 | for CONNACK to be invoked only once. 21 | 22 | config MQTT_PINGRESP_TIMEOUT_MS 23 | int "Number of milliseconds to wait for a ping response to a ping request as part of the keep-alive mechanism." 24 | default 500 25 | help 26 | If a ping response is not received before this timeout, then MQTT_ProcessLoop will 27 | return MQTTKeepAliveTimeout. 28 | 29 | endmenu 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP FreeRTOS CoreMQTT 2 | 3 | ## Table of Contents 4 | 5 | - [Introduction](#introduction) 6 | - [Getting Started](#get-started) 7 | - [Monitoring Results](#monitoring) 8 | - [Troubleshooting](#troubleshooting) 9 | 10 | ## Introduction 11 | 12 | 13 | 14 | The ESP FreeRTOS CoreMQTT is based on [coreMQTT](https://github.com/FreeRTOS/coreMQTT) and enables users to connect their ESP32 based devices to any MQTT broker. It provides some examples which can help understand most common use cases. 15 | 16 | ## Getting Started 17 | 18 | 19 | 20 | ### Hardware 21 | 22 | You will basically just need a development host and an [ESP32 development board](https://www.espressif.com/en/products/hardware/development-boards) to get started. 23 | 24 | ### Development Host Setup 25 | 26 | This project is to be used with Espressif's IoT Development Framework, [ESP IDF](https://github.com/espressif/esp-idf). Follow these steps to get started: 27 | 28 | - Setup ESP IDF development environment by following the steps [here](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html). 29 | - In a separate folder, clone the esp-freertos-coremqtt project as follows (please note the --recursive option, which is required to clone the various git submodules required by esp-freertos-coremqtt) 30 | 31 | ``` bash 32 | $ git clone --recursive https://github.com/espressif/esp-freertos-coremqtt.git 33 | ``` 34 | 35 | > Note that if you ever change the branch or the git head of either esp-idf or esp-freertos-coremqtt, ensure that all the submodules of the git repo are in sync by executing `git submodule update --init --recursive` 36 | 37 | ## Monitoring Results 38 | 39 | 40 | 41 | To monitor activity on your ESP device, run: 42 | 43 | `$ make monitor` 44 | 45 | ## Troubleshooting 46 | 47 | 48 | 1. Some common problems can be fixed by disabling the firewall. 49 | 50 | 2. You can try with the followings, if your build fails: 51 | - `$ git submodule update --init --recursive` 52 | - Check the compiler version and verify that it is the correct one for your ESP IDF version. 53 | - Check if the IDF_PATH is set correctly 54 | - Clean the project with `make clean` and if required, using `rm -rf build sdkconfig sdkconfig.old` 55 | -------------------------------------------------------------------------------- /component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Component Makefile 3 | # 4 | 5 | COMPONENT_ADD_INCLUDEDIRS := coreMQTT/source/include 6 | COMPONENT_ADD_INCLUDEDIRS += coreMQTT/source/interface 7 | COMPONENT_ADD_INCLUDEDIRS += port/include 8 | COMPONENT_ADD_INCLUDEDIRS += port/exponential_backoff 9 | COMPONENT_ADD_INCLUDEDIRS += port/logging 10 | COMPONENT_ADD_INCLUDEDIRS += port/network_transport 11 | COMPONENT_ADD_INCLUDEDIRS += port/platform 12 | COMPONENT_SRCDIRS := coreMQTT/source port/exponential_backoff port/network_transport port/platform 13 | -------------------------------------------------------------------------------- /examples/tls_basic/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following five lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common 6 | ../../) 7 | 8 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 9 | project(tls_basic) 10 | 11 | target_add_binary_data(tls_basic.elf "main/mqtt_eclipse_org.pem" TEXT) 12 | -------------------------------------------------------------------------------- /examples/tls_basic/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a 3 | # project subdirectory. 4 | # 5 | 6 | PROJECT_NAME := tls_basic 7 | 8 | EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common 9 | EXTRA_COMPONENT_DIRS += $(PROJECT_PATH)/../../../ 10 | 11 | include $(IDF_PATH)/make/project.mk 12 | -------------------------------------------------------------------------------- /examples/tls_basic/README.md: -------------------------------------------------------------------------------- 1 | # TLS Basic Sample application 2 | 3 | (See the README.md file in the upper level 'examples' directory for more information about examples.) 4 | 5 | This example connects to the broker `mqtt.eclipse.org` using ssl transport and as a demonstration subscribes/unsubscribes and send a message on certain topic. 6 | (Please note that the public broker is maintained by the community so may not be always available, for details please see this [disclaimer](https://iot.eclipse.org/getting-started/#sandboxes)) 7 | 8 | It uses FreeRTOS coreMQTT library which implements mqtt client to connect to mqtt broker. 9 | 10 | ## How to use example 11 | 12 | ### Hardware Required 13 | 14 | This example can be executed on any ESP32 board, the only required interface is WiFi and connection to internet. 15 | 16 | ### Configure the project 17 | 18 | * Open the project configuration menu (`idf.py menuconfig`) 19 | * Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. 20 | * When using Make build system, set `Default serial port` under `Serial flasher config`. 21 | 22 | PEM certificate for this example could be extracted from an openssl `s_client` command connecting to mqtt.eclipse.org. 23 | In case a host operating system has `openssl` and `sed` packages installed, one could execute the following command to download and save the root certificate to a file (Note for Windows users: Both Linux like environment or Windows native packages may be used). 24 | ``` 25 | echo "" | openssl s_client -showcerts -connect mqtt.eclipse.org:8883 | sed -n "1,/Root/d; /BEGIN/,/END/p" | openssl x509 -outform PEM >mqtt_eclipse_org.pem 26 | ``` 27 | Please note that this is not a general command for downloading a root certificate for an arbitrary host; 28 | this command works with mqtt.eclipse.org as the site provides root certificate in the chain, which then could be extracted 29 | with text operation. 30 | 31 | ### Build and Flash 32 | 33 | Build the project and flash it to the board, then run monitor tool to view serial output: 34 | 35 | ``` 36 | idf.py -p PORT flash monitor 37 | ``` 38 | 39 | (To exit the serial monitor, type ``Ctrl-]``.) 40 | 41 | See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. 42 | 43 | ## Example Output 44 | 45 | ``` 46 | I (2621) example_connect: Got IPv6 event: Interface "example_connect: sta" address: fe80:0000:0000:0000:260a:c4ff:fed8:f7f8, type: ESP_IP6_ADDR_IS_LINK_LOCAL 47 | I (6621) esp_netif_handlers: example_connect: sta ip: 172.168.30.217, mask: 255.255.255.0, gw: 172.168.30.1 48 | I (6621) example_connect: Got IPv4 event: Interface "example_connect: sta" address: 172.168.30.217 49 | I (6631) example_connect: Connected to example_connect: sta 50 | I (6631) example_connect: - IPv4 address: 172.168.30.217 51 | I (6641) example_connect: - IPv6 address: fe80:0000:0000:0000:260a:c4ff:fed8:f7f8, type: ESP_IP6_ADDR_IS_LINK_LOCAL 52 | [INFO] [MQTTDemo] [prvConnectToServerWithBackoffRetries:508] Creating a TLS connection to mqtt.eclipse.org:8883. 53 | 54 | I (8671) tls_freertos: (Network connection 0x3ffc6d70) Connection to mqtt.eclipse.org established. 55 | [INFO] [MQTTDemo] [prvMQTTDemoTask:407] Creating an MQTT connection to mqtt.eclipse.org. 56 | 57 | [INFO] [MQTTDemo] [prvCreateMQTTConnectionWithBroker:585] An MQTT connection is established with mqtt.eclipse.org. 58 | [INFO] [MQTTDemo] [prvMQTTSubscribeWithBackoffRetries:643] Attempt to subscribe to the MQTT topic testClient/example/topic. 59 | 60 | [INFO] [MQTTDemo] [prvMQTTSubscribeWithBackoffRetries:650] SUBSCRIBE sent for topic testClient/example/topic to broker. 61 | 62 | 63 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:770] Subscribed to the topic testClient/example/topic with maximum QoS 2. 64 | 65 | [INFO] [MQTTDemo] [prvMQTTDemoTask:431] Publish to the MQTT topic testClient/example/topic. 66 | 67 | [INFO] [MQTTDemo] [prvMQTTDemoTask:437] Attempt to receive publish message from broker. 68 | 69 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:794] PUBREC received for packet id 2. 70 | 71 | 72 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:810] PUBCOMP received for packet id 2. 73 | 74 | 75 | [INFO] [MQTTDemo] [prvEventCallback:860] PUBLISH received for packet id 1. 76 | 77 | 78 | [INFO] [MQTTDemo] [prvMQTTProcessIncomingPublish:827] Incoming QoS : 2 79 | 80 | [INFO] [MQTTDemo] [prvMQTTProcessIncomingPublish:838] 81 | Incoming Publish Topic Name: testClient/example/topic matches subscribed topic. 82 | Incoming Publish Message : Hello World! 83 | 84 | [INFO] [MQTTDemo] [prvMQTTDemoTask:442] Keeping Connection Idle... 85 | 86 | 87 | [INFO] [MQTTDemo] [prvMQTTDemoTask:431] Publish to the MQTT topic testClient/example/topic. 88 | 89 | [INFO] [MQTTDemo] [prvMQTTDemoTask:437] Attempt to receive publish message from broker. 90 | 91 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:802] PUBREL received for packet id 1. 92 | 93 | 94 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:794] PUBREC received for packet id 3. 95 | 96 | 97 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:810] PUBCOMP received for packet id 3. 98 | 99 | 100 | [INFO] [MQTTDemo] [prvEventCallback:860] PUBLISH received for packet id 2. 101 | 102 | 103 | [INFO] [MQTTDemo] [prvMQTTProcessIncomingPublish:827] Incoming QoS : 2 104 | 105 | [INFO] [MQTTDemo] [prvMQTTProcessIncomingPublish:838] 106 | Incoming Publish Topic Name: testClient/example/topic matches subscribed topic. 107 | Incoming Publish Message : Hello World! 108 | 109 | [INFO] [MQTTDemo] [prvMQTTDemoTask:442] Keeping Connection Idle... 110 | 111 | 112 | [INFO] [MQTTDemo] [prvMQTTDemoTask:431] Publish to the MQTT topic testClient/example/topic. 113 | 114 | [INFO] [MQTTDemo] [prvMQTTDemoTask:437] Attempt to receive publish message from broker. 115 | 116 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:802] PUBREL received for packet id 2. 117 | 118 | 119 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:794] PUBREC received for packet id 4. 120 | 121 | 122 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:810] PUBCOMP received for packet id 4. 123 | 124 | 125 | [INFO] [MQTTDemo] [prvEventCallback:860] PUBLISH received for packet id 3. 126 | 127 | 128 | [INFO] [MQTTDemo] [prvMQTTProcessIncomingPublish:827] Incoming QoS : 2 129 | 130 | [INFO] [MQTTDemo] [prvMQTTProcessIncomingPublish:838] 131 | Incoming Publish Topic Name: testClient/example/topic matches subscribed topic. 132 | Incoming Publish Message : Hello World! 133 | 134 | [INFO] [MQTTDemo] [prvMQTTDemoTask:442] Keeping Connection Idle... 135 | 136 | 137 | [INFO] [MQTTDemo] [prvMQTTDemoTask:431] Publish to the MQTT topic testClient/example/topic. 138 | 139 | [INFO] [MQTTDemo] [prvMQTTDemoTask:437] Attempt to receive publish message from broker. 140 | 141 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:802] PUBREL received for packet id 3. 142 | 143 | 144 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:794] PUBREC received for packet id 5. 145 | 146 | 147 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:810] PUBCOMP received for packet id 5. 148 | 149 | 150 | [INFO] [MQTTDemo] [prvEventCallback:860] PUBLISH received for packet id 4. 151 | 152 | 153 | [INFO] [MQTTDemo] [prvMQTTProcessIncomingPublish:827] Incoming QoS : 2 154 | 155 | [INFO] [MQTTDemo] [prvMQTTProcessIncomingPublish:838] 156 | Incoming Publish Topic Name: testClient/example/topic matches subscribed topic. 157 | Incoming Publish Message : Hello World! 158 | 159 | [INFO] [MQTTDemo] [prvMQTTDemoTask:442] Keeping Connection Idle... 160 | 161 | 162 | [INFO] [MQTTDemo] [prvMQTTDemoTask:431] Publish to the MQTT topic testClient/example/topic. 163 | 164 | [INFO] [MQTTDemo] [prvMQTTDemoTask:437] Attempt to receive publish message from broker. 165 | 166 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:802] PUBREL received for packet id 4. 167 | 168 | 169 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:794] PUBREC received for packet id 6. 170 | 171 | 172 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:810] PUBCOMP received for packet id 6. 173 | 174 | 175 | [INFO] [MQTTDemo] [prvEventCallback:860] PUBLISH received for packet id 5. 176 | 177 | 178 | [INFO] [MQTTDemo] [prvMQTTProcessIncomingPublish:827] Incoming QoS : 2 179 | 180 | [INFO] [MQTTDemo] [prvMQTTProcessIncomingPublish:838] 181 | Incoming Publish Topic Name: testClient/example/topic matches subscribed topic. 182 | Incoming Publish Message : Hello World! 183 | 184 | [INFO] [MQTTDemo] [prvMQTTDemoTask:442] Keeping Connection Idle... 185 | 186 | 187 | [INFO] [MQTTDemo] [prvMQTTDemoTask:447] Unsubscribe from the MQTT topic testClient/example/topic. 188 | 189 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:802] PUBREL received for packet id 5. 190 | 191 | 192 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:779] Unsubscribed from the topic testClient/example/topic. 193 | 194 | [INFO] [MQTTDemo] [prvMQTTDemoTask:459] Disconnecting the MQTT connection with mqtt.eclipse.org. 195 | 196 | [INFO] [MQTTDemo] [prvMQTTDemoTask:474] prvMQTTDemoTask() completed an iteration successfully. Total free heap is 231128. 197 | 198 | [INFO] [MQTTDemo] [prvMQTTDemoTask:475] Demo completed successfully. 199 | 200 | [INFO] [MQTTDemo] [prvMQTTDemoTask:476] Short delay before starting the next iteration.... 201 | ``` 202 | 203 | ## Size Information on ESP-IDF v4.3 204 | 205 | ``` 206 | Total sizes: 207 | DRAM .data size: 17356 bytes 208 | DRAM .bss size: 16824 bytes 209 | Used static DRAM: 34180 bytes ( 146556 available, 18.9% used) 210 | Used static IRAM: 87734 bytes ( 43338 available, 66.9% used) 211 | Flash code: 579803 bytes 212 | Flash rodata: 120888 bytes 213 | Total image size:~ 805781 bytes (.bin may be padded larger) 214 | ``` -------------------------------------------------------------------------------- /examples/tls_basic/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_SRCS "tls_basic_main.c" "utilities/BasicTLSMQTTExample.c") 2 | set(COMPONENT_ADD_INCLUDEDIRS "." "utilities") 3 | 4 | register_component() 5 | -------------------------------------------------------------------------------- /examples/tls_basic/main/Kconfig.projbuild: -------------------------------------------------------------------------------- 1 | menu "Example Configuration" 2 | 3 | config MQTT_CLIENT_IDENTIFIER 4 | string "The MQTT client identifier used in this example" 5 | default "testClient" 6 | help 7 | The MQTT client identifier used in this example. Each client identifier must be unique. 8 | so edit as required to ensure that no two clients connecting to the same broker use the same client identifier. 9 | 10 | config MQTT_BROKER_ENDPOINT 11 | string "Endpoint of the MQTT broker to connect to" 12 | default "mqtt.eclipse.org" 13 | help 14 | This example can be run with any MQTT broker, that supports server authentication. 15 | 16 | config MQTT_BROKER_PORT 17 | int "Port of the MQTT broker use" 18 | default 8883 19 | help 20 | In general, port 8883 is for secured MQTT connections. 21 | Port 443 requires use of the ALPN TLS extension with the ALPN protocol name. 22 | When using port 8883, ALPN is not required. 23 | 24 | config MQTT_OPTION_SNI 25 | int "An option to disable Server Name Indication" 26 | range 0 1 27 | default 0 28 | help 29 | When using a local Mosquitto server setup, SNI needs to be disabled 30 | for an MQTT broker that only has an IP address but no hostname. However, 31 | SNI should be enabled whenever possible. 32 | 33 | config MQTT_EXAMPLE_STACKSIZE 34 | int "Set the stack size of the example task" 35 | range 5120 8192 36 | default 5120 37 | help 38 | The actual stack is created by an operating system thread. 39 | 40 | config MQTT_NETWORK_BUFFER_SIZE 41 | int "Size of the network buffer for MQTT packets" 42 | range 1024 2048 43 | default 1024 44 | help 45 | Size of the network buffer for MQTT packets. 46 | 47 | endmenu 48 | -------------------------------------------------------------------------------- /examples/tls_basic/main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | COMPONENT_EMBED_TXTFILES := mqtt_eclipse_org.pem 7 | 8 | COMPONENT_ADD_INCLUDEDIRS += utilities 9 | COMPONENT_SRCDIRS += utilities -------------------------------------------------------------------------------- /examples/tls_basic/main/mqtt_eclipse_org.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/ 3 | MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT 4 | DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow 5 | SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT 6 | GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC 7 | AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF 8 | q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8 9 | SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0 10 | Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA 11 | a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj 12 | /PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T 13 | AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG 14 | CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv 15 | bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k 16 | c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw 17 | VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC 18 | ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz 19 | MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu 20 | Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF 21 | AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo 22 | uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/ 23 | wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu 24 | X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG 25 | PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 26 | KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== 27 | -----END CERTIFICATE----- 28 | -------------------------------------------------------------------------------- /examples/tls_basic/main/tls_basic_main.c: -------------------------------------------------------------------------------- 1 | /* tls-basic example 2 | 3 | This example code is in the Public Domain (or CC0 licensed, at your option.) 4 | 5 | Unless required by applicable law or agreed to in writing, this 6 | software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 7 | CONDITIONS OF ANY KIND, either express or implied. 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "esp_system.h" 14 | #include "nvs_flash.h" 15 | #include "esp_event.h" 16 | #include "esp_netif.h" 17 | #include "protocol_examples_common.h" 18 | 19 | #include "esp_log.h" 20 | 21 | static const char *TAG = "MQTTS_EXAMPLE"; 22 | 23 | /* 24 | * Prototypes for the demos that can be started from this project. Note the 25 | * MQTT demo is not actually started until the network is already. 26 | */ 27 | extern void vStartSimpleMQTTDemo( void ); 28 | 29 | void app_main() 30 | { 31 | ESP_LOGI(TAG, "[APP] Startup.."); 32 | ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); 33 | ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); 34 | 35 | esp_log_level_set("*", ESP_LOG_INFO); 36 | esp_log_level_set("esp-tls", ESP_LOG_VERBOSE); 37 | 38 | ESP_ERROR_CHECK(nvs_flash_init()); 39 | ESP_ERROR_CHECK(esp_netif_init()); 40 | ESP_ERROR_CHECK(esp_event_loop_create_default()); 41 | 42 | /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. 43 | * Read "Establishing Wi-Fi or Ethernet Connection" section in 44 | * examples/protocols/README.md for more information about this function. 45 | */ 46 | ESP_ERROR_CHECK(example_connect()); 47 | 48 | vStartSimpleMQTTDemo(); 49 | } 50 | -------------------------------------------------------------------------------- /examples/tls_basic/main/utilities/BasicTLSMQTTExample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * FreeRTOS Kernel V10.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | * this software and associated documentation files (the "Software"), to deal in 7 | * the Software without restriction, including without limitation the rights to 8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | * the Software, and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | * 22 | * http://www.FreeRTOS.org 23 | * http://aws.amazon.com/freertos 24 | * 25 | */ 26 | 27 | /* 28 | * Demo for showing the use of the MQTT API using a server-authenticated 29 | * network connection. 30 | * 31 | * The example shown below uses MQTT APIs to create MQTT messages and send them 32 | * over the server-authenticated network connection established with the 33 | * MQTT broker. This example is single-threaded and uses statically allocated 34 | * memory. It uses QoS2 for sending and receiving messages from the broker. 35 | * 36 | * A server-authenticated TLS connection is used to connect to the MQTT message 37 | * broker in this example. Define democonfigMQTT_BROKER_ENDPOINT and 38 | * democonfigROOT_CA_PEM in demo_config.h to establish a server-authenticated 39 | * connection. 40 | */ 41 | 42 | /* Standard includes. */ 43 | #include 44 | #include 45 | 46 | /* Kernel includes. */ 47 | #include "freertos/FreeRTOS.h" 48 | #include "freertos/task.h" 49 | 50 | /* Demo Specific configs. */ 51 | #include "demo_config.h" 52 | 53 | /* MQTT library includes. */ 54 | #include "core_mqtt.h" 55 | 56 | /* Exponential backoff retry include. */ 57 | #include "exponential_backoff.h" 58 | 59 | /* Transport interface implementation include header for TLS. */ 60 | #include "tls_freertos.h" 61 | 62 | /*-----------------------------------------------------------*/ 63 | 64 | /* Compile time error for undefined configs. */ 65 | #ifndef democonfigMQTT_BROKER_ENDPOINT 66 | #error "Define the config democonfigMQTT_BROKER_ENDPOINT by following the instructions in file demo_config.h." 67 | #endif 68 | 69 | /*-----------------------------------------------------------*/ 70 | 71 | /* Default values for configs. */ 72 | #ifndef democonfigCLIENT_IDENTIFIER 73 | 74 | /** 75 | * @brief The MQTT client identifier used in this example. Each client identifier 76 | * must be unique so edit as required to ensure no two clients connecting to the 77 | * same broker use the same client identifier. 78 | * 79 | * @note Appending __TIME__ to the client id string will help to create a unique 80 | * client id every time an application binary is built. Only a single instance of 81 | * this application's compiled binary may be used at a time, since the client ID 82 | * will always be the same. 83 | */ 84 | #define democonfigCLIENT_IDENTIFIER "testClient"__TIME__ 85 | #endif 86 | 87 | #ifndef democonfigMQTT_BROKER_PORT 88 | 89 | /** 90 | * @brief The port to use for the demo. 91 | */ 92 | #define democonfigMQTT_BROKER_PORT ( 8883 ) 93 | #endif 94 | 95 | /*-----------------------------------------------------------*/ 96 | 97 | /** 98 | * @brief Timeout for receiving CONNACK packet in milliseconds. 99 | */ 100 | #define mqttexampleCONNACK_RECV_TIMEOUT_MS ( 1000U ) 101 | 102 | /** 103 | * @brief The topic to subscribe and publish to in the example. 104 | * 105 | * The topic name starts with the client identifier to ensure that each demo 106 | * interacts with a unique topic name. 107 | */ 108 | #define mqttexampleTOPIC democonfigCLIENT_IDENTIFIER "/example/topic" 109 | 110 | /** 111 | * @brief The number of topic filters to subscribe. 112 | */ 113 | #define mqttexampleTOPIC_COUNT ( 1 ) 114 | 115 | /** 116 | * @brief The MQTT message published in this example. 117 | */ 118 | #define mqttexampleMESSAGE "Hello World!" 119 | 120 | /** 121 | * @brief Time in ticks to wait between each cycle of the demo implemented 122 | * by prvMQTTDemoTask(). 123 | */ 124 | #define mqttexampleDELAY_BETWEEN_DEMO_ITERATIONS_TICKS ( pdMS_TO_TICKS( 5000U ) ) 125 | 126 | /** 127 | * @brief Timeout for MQTT_ProcessLoop in milliseconds. 128 | */ 129 | #define mqttexamplePROCESS_LOOP_TIMEOUT_MS ( 500U ) 130 | 131 | /** 132 | * @brief The keep-alive timeout period reported to the broker while establishing 133 | * an MQTT connection. 134 | * 135 | * It is the responsibility of the client to ensure that the interval between 136 | * control packets being sent does not exceed this keep-alive value. In the 137 | * absence of sending any other control packets, the client MUST send a 138 | * PINGREQ packet. 139 | */ 140 | #define mqttexampleKEEP_ALIVE_TIMEOUT_SECONDS ( 60U ) 141 | 142 | /** 143 | * @brief Delay (in ticks) between consecutive cycles of MQTT publish operations in a 144 | * demo iteration. 145 | * 146 | * Note that the process loop also has a timeout, so the total time between 147 | * publishes is the sum of the two delays. 148 | */ 149 | #define mqttexampleDELAY_BETWEEN_PUBLISHES_TICKS ( pdMS_TO_TICKS( 2000U ) ) 150 | 151 | /** 152 | * @brief Transport timeout in milliseconds for transport send and receive. 153 | */ 154 | #define mqttexampleTRANSPORT_SEND_RECV_TIMEOUT_MS ( 20000U ) 155 | 156 | /** 157 | * @brief Milliseconds per second. 158 | */ 159 | #define MILLISECONDS_PER_SECOND ( 1000U ) 160 | 161 | /** 162 | * @brief Milliseconds per FreeRTOS tick. 163 | */ 164 | #define MILLISECONDS_PER_TICK ( MILLISECONDS_PER_SECOND / configTICK_RATE_HZ ) 165 | 166 | /*-----------------------------------------------------------*/ 167 | 168 | /** 169 | * @brief The task used to demonstrate the MQTT API. 170 | * 171 | * @param[in] pvParameters Parameters as passed at the time of task creation. Not 172 | * used in this example. 173 | */ 174 | static void prvMQTTDemoTask( void * pvParameters ); 175 | 176 | /** 177 | * @brief Connect to MQTT broker with reconnection retries. 178 | * 179 | * If connection fails, retry is attempted after a timeout. 180 | * Timeout value will exponentially increase until the maximum 181 | * timeout value is reached or the number of attempts are exhausted. 182 | * 183 | * @param[out] pxNetworkContext The output parameter to return the created network context. 184 | * 185 | * @return The status of the final connection attempt. 186 | */ 187 | static TlsTransportStatus_t prvConnectToServerWithBackoffRetries( NetworkCredentials_t * pxNetworkCredentials, 188 | NetworkContext_t * pNetworkContext ); 189 | 190 | /** 191 | * @brief Sends an MQTT Connect packet over the already connected TLS over TCP connection. 192 | * 193 | * @param[in, out] pxMQTTContext MQTT context pointer. 194 | * @param[in] xNetworkContext network context. 195 | */ 196 | static void prvCreateMQTTConnectionWithBroker( MQTTContext_t * pxMQTTContext, 197 | NetworkContext_t * pxNetworkContext ); 198 | 199 | /** 200 | * @brief Function to update variable #xTopicFilterContext with status 201 | * information from Subscribe ACK. Called by the event callback after processing 202 | * an incoming SUBACK packet. 203 | * 204 | * @param[in] Server response to the subscription request. 205 | */ 206 | static void prvUpdateSubAckStatus( MQTTPacketInfo_t * pxPacketInfo ); 207 | 208 | /** 209 | * @brief Subscribes to the topic as specified in mqttexampleTOPIC at the top of 210 | * this file. In the case of a Subscribe ACK failure, then subscription is 211 | * retried using an exponential backoff strategy with jitter. 212 | * 213 | * @param[in] pxMQTTContext MQTT context pointer. 214 | */ 215 | static void prvMQTTSubscribeWithBackoffRetries( MQTTContext_t * pxMQTTContext ); 216 | 217 | /** 218 | * @brief Publishes a message mqttexampleMESSAGE on mqttexampleTOPIC topic. 219 | * 220 | * @param[in] pxMQTTContext MQTT context pointer. 221 | */ 222 | static void prvMQTTPublishToTopic( MQTTContext_t * pxMQTTContext ); 223 | 224 | /** 225 | * @brief Unsubscribes from the previously subscribed topic as specified 226 | * in mqttexampleTOPIC. 227 | * 228 | * @param[in] pxMQTTContext MQTT context pointer. 229 | */ 230 | static void prvMQTTUnsubscribeFromTopic( MQTTContext_t * pxMQTTContext ); 231 | 232 | /** 233 | * @brief The timer query function provided to the MQTT context. 234 | * 235 | * @return Time in milliseconds. 236 | */ 237 | static uint32_t prvGetTimeMs( void ); 238 | 239 | /** 240 | * @brief Process a response or ack to an MQTT request (PING, PUBLISH, 241 | * SUBSCRIBE or UNSUBSCRIBE). This function processes PINGRESP, PUBACK, 242 | * PUBREC, PUBREL, PUBCOMP, SUBACK, and UNSUBACK. 243 | * 244 | * @param[in] pxIncomingPacket is a pointer to structure containing deserialized 245 | * MQTT response. 246 | * @param[in] usPacketId is the packet identifier from the ack received. 247 | */ 248 | static void prvMQTTProcessResponse( MQTTPacketInfo_t * pxIncomingPacket, 249 | uint16_t usPacketId ); 250 | 251 | /** 252 | * @brief Process incoming Publish message. 253 | * 254 | * @param[in] pxPublishInfo is a pointer to structure containing deserialized 255 | * Publish message. 256 | */ 257 | static void prvMQTTProcessIncomingPublish( MQTTPublishInfo_t * pxPublishInfo ); 258 | 259 | /** 260 | * @brief The application callback function for getting the incoming publishes, 261 | * incoming acks, and ping responses reported from the MQTT library. 262 | * 263 | * @param[in] pxMQTTContext MQTT context pointer. 264 | * @param[in] pxPacketInfo Packet Info pointer for the incoming packet. 265 | * @param[in] pxDeserializedInfo Deserialized information from the incoming packet. 266 | */ 267 | static void prvEventCallback( MQTTContext_t * pxMQTTContext, 268 | MQTTPacketInfo_t * pxPacketInfo, 269 | MQTTDeserializedInfo_t * pxDeserializedInfo ); 270 | 271 | /*-----------------------------------------------------------*/ 272 | 273 | /** 274 | * @brief Static buffer used to hold MQTT messages being sent and received. 275 | */ 276 | static uint8_t ucSharedBuffer[ democonfigNETWORK_BUFFER_SIZE ]; 277 | 278 | /** 279 | * @brief Global entry time into the application to use as a reference timestamp 280 | * in the #prvGetTimeMs function. #prvGetTimeMs will always return the difference 281 | * between the current time and the global entry time. This will reduce the chances 282 | * of overflow for the 32 bit unsigned integer used for holding the timestamp. 283 | */ 284 | static uint32_t ulGlobalEntryTimeMs; 285 | 286 | /** 287 | * @brief Packet Identifier generated when Publish request was sent to the broker; 288 | * it is used to match received Publish ACK to the transmitted Publish packet. 289 | */ 290 | static uint16_t usPublishPacketIdentifier; 291 | 292 | /** 293 | * @brief Packet Identifier generated when Subscribe request was sent to the broker; 294 | * it is used to match received Subscribe ACK to the transmitted Subscribe packet. 295 | */ 296 | static uint16_t usSubscribePacketIdentifier; 297 | 298 | /** 299 | * @brief Packet Identifier generated when Unsubscribe request was sent to the broker; 300 | * it is used to match received Unsubscribe response to the transmitted Unsubscribe 301 | * request. 302 | */ 303 | static uint16_t usUnsubscribePacketIdentifier; 304 | 305 | /** 306 | * @brief A pair containing a topic filter and its SUBACK status. 307 | */ 308 | typedef struct topicFilterContext 309 | { 310 | const char * pcTopicFilter; 311 | MQTTSubAckStatus_t xSubAckStatus; 312 | } topicFilterContext_t; 313 | 314 | /** 315 | * @brief An array containing the context of a SUBACK; the SUBACK status 316 | * of a filter is updated when the event callback processes a SUBACK. 317 | */ 318 | static topicFilterContext_t xTopicFilterContext[ mqttexampleTOPIC_COUNT ] = 319 | { 320 | { mqttexampleTOPIC, MQTTSubAckFailure } 321 | }; 322 | 323 | 324 | /** @brief Static buffer used to hold MQTT messages being sent and received. */ 325 | static MQTTFixedBuffer_t xBuffer = 326 | { 327 | ucSharedBuffer, 328 | democonfigNETWORK_BUFFER_SIZE 329 | }; 330 | 331 | #if CONFIG_BROKER_CERTIFICATE_OVERRIDDEN == 1 332 | static const uint8_t mqtt_eclipse_org_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----"; 333 | #else 334 | extern const uint8_t mqtt_eclipse_org_pem_start[] asm("_binary_mqtt_eclipse_org_pem_start"); 335 | #endif 336 | extern const uint8_t mqtt_eclipse_org_pem_end[] asm("_binary_mqtt_eclipse_org_pem_end"); 337 | 338 | /*-----------------------------------------------------------*/ 339 | 340 | /* 341 | * @brief Create the task that demonstrates the MQTT API Demo over a 342 | * server-authenticated network connection with MQTT broker. 343 | */ 344 | void vStartSimpleMQTTDemo( void ) 345 | { 346 | /* This example uses a single application task, which in turn is used to 347 | * connect, subscribe, publish, unsubscribe, and disconnect from the MQTT 348 | * broker. */ 349 | xTaskCreate( prvMQTTDemoTask, /* Function that implements the task. */ 350 | "DemoTask", /* Text name for the task - only used for debugging. */ 351 | democonfigDEMO_STACKSIZE, /* Size of stack (in words, not bytes) to allocate for the task. */ 352 | NULL, /* Task parameter - not used in this case. */ 353 | tskIDLE_PRIORITY, /* Task priority, must be between 0 and configMAX_PRIORITIES - 1. */ 354 | NULL ); /* Used to pass out a handle to the created task - not used in this case. */ 355 | } 356 | /*-----------------------------------------------------------*/ 357 | 358 | /* 359 | * @brief The Example shown below uses MQTT APIs to create MQTT messages and 360 | * send them over the server-authenticated network connection established with the 361 | * MQTT broker. This example is single-threaded and uses statically allocated 362 | * memory. It uses QoS2 for sending and receiving messages from the broker. 363 | * 364 | * This MQTT client subscribes to the topic as specified in mqttexampleTOPIC at the 365 | * top of this file by sending a subscribe packet and waiting for a subscribe 366 | * acknowledgment (SUBACK) from the broker. The client will then publish to the 367 | * same topic it subscribed to, therefore expecting that all outgoing messages will be 368 | * sent back from the broker. 369 | */ 370 | static void prvMQTTDemoTask( void * pvParameters ) 371 | { 372 | uint32_t ulPublishCount = 0U, ulTopicCount = 0U; 373 | const uint32_t ulMaxPublishCount = 5UL; 374 | NetworkContext_t xNetworkContext = { 0 }; 375 | NetworkCredentials_t xNetworkCredentials = { 0 }; 376 | MQTTContext_t xMQTTContext = { 0 }; 377 | MQTTStatus_t xMQTTStatus; 378 | TlsTransportStatus_t xNetworkStatus; 379 | 380 | /* Remove compiler warnings about unused parameters. */ 381 | ( void ) pvParameters; 382 | 383 | /* Set the entry time of the demo application. This entry time will be used 384 | * to calculate relative time elapsed in the execution of the demo application, 385 | * by the timer utility function that is provided to the MQTT library. 386 | */ 387 | ulGlobalEntryTimeMs = prvGetTimeMs(); 388 | 389 | for( ; ; ) 390 | { 391 | /****************************** Connect. ******************************/ 392 | 393 | /* Attempt to establish a TLS connection with the MQTT broker. This example 394 | * connects to the MQTT broker specified in democonfigMQTT_BROKER_ENDPOINT, using 395 | * the port number specified in democonfigMQTT_BROKER_PORT (these macros are defined 396 | * in file demo_config.h). If the connection fails, attempt to re-connect after a timeout. 397 | * The timeout value will be exponentially increased until either the maximum timeout value 398 | * is reached, or the maximum number of attempts are exhausted. The function returns a failure status 399 | * if the TCP connection cannot be established with the broker after a configured number 400 | * of attempts. */ 401 | xNetworkStatus = prvConnectToServerWithBackoffRetries( &xNetworkCredentials, 402 | &xNetworkContext ); 403 | configASSERT( xNetworkStatus == TLS_TRANSPORT_SUCCESS ); 404 | 405 | /* Send an MQTT CONNECT packet over the established TLS connection, 406 | * and wait for the connection acknowledgment (CONNACK) packet. */ 407 | LogInfo( ( "Creating an MQTT connection to %s.\r\n", democonfigMQTT_BROKER_ENDPOINT ) ); 408 | prvCreateMQTTConnectionWithBroker( &xMQTTContext, &xNetworkContext ); 409 | 410 | /**************************** Subscribe. ******************************/ 411 | 412 | /* If the server rejected the subscription request, attempt to resubscribe to the 413 | * topic. Attempts are made according to the exponential backoff retry strategy 414 | * implemented in retryUtils. */ 415 | prvMQTTSubscribeWithBackoffRetries( &xMQTTContext ); 416 | 417 | /* Process incoming packet from the broker. After sending a subscribe packet, the 418 | * client may receive a publish before it receives a subscribe ack. Therefore, 419 | * call the generic incoming packet processing function. Since this demo is 420 | * subscribing to a topic to which no one is publishing, the probability of 421 | * receiving a publish message before a subscribe ack is zero. Regardless, the 422 | * application must be prepared to receive any packet. This demo uses the generic packet 423 | * processing function everywhere to highlight this fact. */ 424 | xMQTTStatus = MQTT_ProcessLoop( &xMQTTContext, mqttexamplePROCESS_LOOP_TIMEOUT_MS ); 425 | configASSERT( xMQTTStatus == MQTTSuccess ); 426 | 427 | /**************************** Publish and Keep-Alive Loop. ******************************/ 428 | /* Publish messages with QoS2, and send and process keep-alive messages. */ 429 | for( ulPublishCount = 0; ulPublishCount < ulMaxPublishCount; ulPublishCount++ ) 430 | { 431 | LogInfo( ( "Publish to the MQTT topic %s.\r\n", mqttexampleTOPIC ) ); 432 | prvMQTTPublishToTopic( &xMQTTContext ); 433 | 434 | /* Process incoming publish echo. Since the application subscribed and published 435 | * to the same topic, the broker will send the incoming publish message back 436 | * to the application. */ 437 | LogInfo( ( "Attempt to receive publish message from broker.\r\n" ) ); 438 | xMQTTStatus = MQTT_ProcessLoop( &xMQTTContext, mqttexamplePROCESS_LOOP_TIMEOUT_MS ); 439 | configASSERT( xMQTTStatus == MQTTSuccess ); 440 | 441 | /* Leave connection idle for some time. */ 442 | LogInfo( ( "Keeping Connection Idle...\r\n\r\n" ) ); 443 | vTaskDelay( mqttexampleDELAY_BETWEEN_PUBLISHES_TICKS ); 444 | } 445 | 446 | /************************ Unsubscribe from the topic. **************************/ 447 | LogInfo( ( "Unsubscribe from the MQTT topic %s.\r\n", mqttexampleTOPIC ) ); 448 | prvMQTTUnsubscribeFromTopic( &xMQTTContext ); 449 | 450 | /* Process incoming UNSUBACK packet from the broker. */ 451 | xMQTTStatus = MQTT_ProcessLoop( &xMQTTContext, mqttexamplePROCESS_LOOP_TIMEOUT_MS ); 452 | configASSERT( xMQTTStatus == MQTTSuccess ); 453 | 454 | /**************************** Disconnect. ******************************/ 455 | 456 | /* Send an MQTT DISCONNECT packet over the already-connected TLS over TCP connection. 457 | * There is no corresponding response expected from the broker. After sending the 458 | * disconnect request, the client must close the network connection. */ 459 | LogInfo( ( "Disconnecting the MQTT connection with %s.\r\n", democonfigMQTT_BROKER_ENDPOINT ) ); 460 | xMQTTStatus = MQTT_Disconnect( &xMQTTContext ); 461 | configASSERT( xMQTTStatus == MQTTSuccess ); 462 | 463 | /* Close the network connection. */ 464 | TLS_FreeRTOS_Disconnect( &xNetworkContext ); 465 | 466 | /* Reset SUBACK status for each topic filter after completion of the subscription request cycle. */ 467 | for( ulTopicCount = 0; ulTopicCount < mqttexampleTOPIC_COUNT; ulTopicCount++ ) 468 | { 469 | xTopicFilterContext[ ulTopicCount ].xSubAckStatus = MQTTSubAckFailure; 470 | } 471 | 472 | /* Wait for some time between two iterations to ensure that we do not 473 | * bombard the broker. */ 474 | LogInfo( ( "prvMQTTDemoTask() completed an iteration successfully. Total free heap is %u.\r\n", xPortGetFreeHeapSize() ) ); 475 | LogInfo( ( "Demo completed successfully.\r\n" ) ); 476 | LogInfo( ( "Short delay before starting the next iteration.... \r\n\r\n" ) ); 477 | vTaskDelay( mqttexampleDELAY_BETWEEN_DEMO_ITERATIONS_TICKS ); 478 | } 479 | } 480 | /*-----------------------------------------------------------*/ 481 | 482 | static TlsTransportStatus_t prvConnectToServerWithBackoffRetries( NetworkCredentials_t * pxNetworkCredentials, 483 | NetworkContext_t * pxNetworkContext ) 484 | { 485 | TlsTransportStatus_t xNetworkStatus; 486 | RetryUtilsStatus_t xRetryUtilsStatus = RetryUtilsSuccess; 487 | RetryUtilsParams_t xReconnectParams; 488 | 489 | /* Set the credentials for establishing a TLS connection. */ 490 | pxNetworkCredentials->pRootCa = ( const unsigned char * ) mqtt_eclipse_org_pem_start; 491 | pxNetworkCredentials->rootCaSize = mqtt_eclipse_org_pem_end - mqtt_eclipse_org_pem_start; 492 | pxNetworkCredentials->disableSni = democonfigDISABLE_SNI; 493 | /* Initialize reconnect attempts and interval. */ 494 | RetryUtils_ParamsReset( &xReconnectParams ); 495 | xReconnectParams.maxRetryAttempts = MAX_RETRY_ATTEMPTS; 496 | 497 | /* Attempt to connect to the MQTT broker. If connection fails, retry after 498 | * a timeout. Timeout value will exponentially increase until maximum 499 | * attempts are reached. 500 | */ 501 | do 502 | { 503 | /* Establish a TLS session with the MQTT broker. This example connects to 504 | * the MQTT broker as specified in democonfigMQTT_BROKER_ENDPOINT and 505 | * democonfigMQTT_BROKER_PORT at the top of this file. */ 506 | LogInfo( ( "Creating a TLS connection to %s:%u.\r\n", 507 | democonfigMQTT_BROKER_ENDPOINT, 508 | democonfigMQTT_BROKER_PORT ) ); 509 | /* Attempt to create a server-authenticated TLS connection. */ 510 | xNetworkStatus = TLS_FreeRTOS_Connect( pxNetworkContext, 511 | democonfigMQTT_BROKER_ENDPOINT, 512 | democonfigMQTT_BROKER_PORT, 513 | pxNetworkCredentials, 514 | mqttexampleTRANSPORT_SEND_RECV_TIMEOUT_MS, 515 | mqttexampleTRANSPORT_SEND_RECV_TIMEOUT_MS ); 516 | 517 | if( xNetworkStatus != TLS_TRANSPORT_SUCCESS ) 518 | { 519 | LogWarn( ( "Connection to the broker failed. Retrying connection with backoff and jitter." ) ); 520 | xRetryUtilsStatus = RetryUtils_BackoffAndSleep( &xReconnectParams ); 521 | } 522 | 523 | if( xRetryUtilsStatus == RetryUtilsRetriesExhausted ) 524 | { 525 | LogError( ( "Connection to the broker failed, all attempts exhausted." ) ); 526 | xNetworkStatus = TLS_TRANSPORT_CONNECT_FAILURE; 527 | } 528 | } while( ( xNetworkStatus != TLS_TRANSPORT_SUCCESS ) && ( xRetryUtilsStatus == RetryUtilsSuccess ) ); 529 | 530 | return xNetworkStatus; 531 | } 532 | /*-----------------------------------------------------------*/ 533 | 534 | static void prvCreateMQTTConnectionWithBroker( MQTTContext_t * pxMQTTContext, 535 | NetworkContext_t * pxNetworkContext ) 536 | { 537 | MQTTStatus_t xResult; 538 | MQTTConnectInfo_t xConnectInfo; 539 | bool xSessionPresent; 540 | TransportInterface_t xTransport; 541 | 542 | /*** 543 | * For readability, error handling in this function is restricted to the use of 544 | * asserts(). 545 | ***/ 546 | 547 | /* Fill in Transport Interface send and receive function pointers. */ 548 | xTransport.pNetworkContext = pxNetworkContext; 549 | xTransport.send = TLS_FreeRTOS_send; 550 | xTransport.recv = TLS_FreeRTOS_recv; 551 | 552 | /* Initialize MQTT library. */ 553 | xResult = MQTT_Init( pxMQTTContext, &xTransport, prvGetTimeMs, prvEventCallback, &xBuffer ); 554 | configASSERT( xResult == MQTTSuccess ); 555 | 556 | /* Some fields are not used in this demo so start with everything at 0. */ 557 | ( void ) memset( ( void * ) &xConnectInfo, 0x00, sizeof( xConnectInfo ) ); 558 | 559 | /* Start with a clean session i.e. direct the MQTT broker to discard any 560 | * previous session data. Also, establishing a connection with clean session 561 | * will ensure that the broker does not store any data when this client 562 | * gets disconnected. */ 563 | xConnectInfo.cleanSession = true; 564 | 565 | /* The client identifier is used to uniquely identify this MQTT client to 566 | * the MQTT broker. In a production device the identifier can be something 567 | * unique, such as a device serial number. */ 568 | xConnectInfo.pClientIdentifier = democonfigCLIENT_IDENTIFIER; 569 | xConnectInfo.clientIdentifierLength = ( uint16_t ) strlen( democonfigCLIENT_IDENTIFIER ); 570 | 571 | /* Set MQTT keep-alive period. If the application does not send packets at an interval less than 572 | * the keep-alive period, the MQTT library will send PINGREQ packets. */ 573 | xConnectInfo.keepAliveSeconds = mqttexampleKEEP_ALIVE_TIMEOUT_SECONDS; 574 | 575 | /* Send MQTT CONNECT packet to broker. LWT is not used in this demo, so it 576 | * is passed as NULL. */ 577 | xResult = MQTT_Connect( pxMQTTContext, 578 | &xConnectInfo, 579 | NULL, 580 | mqttexampleCONNACK_RECV_TIMEOUT_MS, 581 | &xSessionPresent ); 582 | configASSERT( xResult == MQTTSuccess ); 583 | 584 | /* Successfully established and MQTT connection with the broker. */ 585 | LogInfo( ( "An MQTT connection is established with %s.", democonfigMQTT_BROKER_ENDPOINT ) ); 586 | } 587 | /*-----------------------------------------------------------*/ 588 | 589 | static void prvUpdateSubAckStatus( MQTTPacketInfo_t * pxPacketInfo ) 590 | { 591 | MQTTStatus_t xResult = MQTTSuccess; 592 | uint8_t * pucPayload = NULL; 593 | size_t ulSize = 0; 594 | uint32_t ulTopicCount = 0U; 595 | 596 | xResult = MQTT_GetSubAckStatusCodes( pxPacketInfo, &pucPayload, &ulSize ); 597 | 598 | /* MQTT_GetSubAckStatusCodes always returns success if called with packet info 599 | * from the event callback and non-NULL parameters. */ 600 | configASSERT( xResult == MQTTSuccess ); 601 | 602 | for( ulTopicCount = 0; ulTopicCount < ulSize; ulTopicCount++ ) 603 | { 604 | xTopicFilterContext[ ulTopicCount ].xSubAckStatus = pucPayload[ ulTopicCount ]; 605 | } 606 | } 607 | /*-----------------------------------------------------------*/ 608 | 609 | static void prvMQTTSubscribeWithBackoffRetries( MQTTContext_t * pxMQTTContext ) 610 | { 611 | MQTTStatus_t xResult = MQTTSuccess; 612 | RetryUtilsStatus_t xRetryUtilsStatus = RetryUtilsSuccess; 613 | RetryUtilsParams_t xRetryParams; 614 | MQTTSubscribeInfo_t xMQTTSubscription[ mqttexampleTOPIC_COUNT ]; 615 | bool xFailedSubscribeToTopic = false; 616 | uint32_t ulTopicCount = 0U; 617 | 618 | /* Some fields not used by this demo so start with everything at 0. */ 619 | ( void ) memset( ( void * ) &xMQTTSubscription, 0x00, sizeof( xMQTTSubscription ) ); 620 | 621 | /* Get a unique packet id. */ 622 | usSubscribePacketIdentifier = MQTT_GetPacketId( pxMQTTContext ); 623 | 624 | /* Subscribe to the mqttexampleTOPIC topic filter. This example subscribes to 625 | * only one topic and uses QoS2. */ 626 | xMQTTSubscription[ 0 ].qos = MQTTQoS2; 627 | xMQTTSubscription[ 0 ].pTopicFilter = mqttexampleTOPIC; 628 | xMQTTSubscription[ 0 ].topicFilterLength = ( uint16_t ) strlen( mqttexampleTOPIC ); 629 | 630 | /* Initialize retry attempts and interval. */ 631 | RetryUtils_ParamsReset( &xRetryParams ); 632 | xRetryParams.maxRetryAttempts = MAX_RETRY_ATTEMPTS; 633 | 634 | do 635 | { 636 | /* The client is now connected to the broker. Subscribe to the topic 637 | * as specified in mqttexampleTOPIC at the top of this file by sending a 638 | * subscribe packet then waiting for a subscribe acknowledgment (SUBACK). 639 | * This client will then publish to the same topic it subscribed to, so it 640 | * will expect all the messages it sends to the broker to be sent back to it 641 | * from the broker. This demo uses QOS2 in Subscribe, therefore, the Publish 642 | * messages received from the broker will have QOS2. */ 643 | LogInfo( ( "Attempt to subscribe to the MQTT topic %s.\r\n", mqttexampleTOPIC ) ); 644 | xResult = MQTT_Subscribe( pxMQTTContext, 645 | xMQTTSubscription, 646 | sizeof( xMQTTSubscription ) / sizeof( MQTTSubscribeInfo_t ), 647 | usSubscribePacketIdentifier ); 648 | configASSERT( xResult == MQTTSuccess ); 649 | 650 | LogInfo( ( "SUBSCRIBE sent for topic %s to broker.\n\n", mqttexampleTOPIC ) ); 651 | 652 | /* Process incoming packet from the broker. After sending the subscribe, the 653 | * client may receive a publish before it receives a subscribe ack. Therefore, 654 | * call generic incoming packet processing function. Since this demo is 655 | * subscribing to the topic to which no one is publishing, probability of 656 | * receiving Publish message before subscribe ack is zero; but application 657 | * must be ready to receive any packet. This demo uses the generic packet 658 | * processing function everywhere to highlight this fact. */ 659 | xResult = MQTT_ProcessLoop( pxMQTTContext, mqttexamplePROCESS_LOOP_TIMEOUT_MS ); 660 | configASSERT( xResult == MQTTSuccess ); 661 | 662 | /* Reset flag before checking suback responses. */ 663 | xFailedSubscribeToTopic = false; 664 | 665 | /* Check if recent subscription request has been rejected. #xTopicFilterContext is updated 666 | * in the event callback to reflect the status of the SUBACK sent by the broker. It represents 667 | * either the QoS level granted by the server upon subscription, or acknowledgement of 668 | * server rejection of the subscription request. */ 669 | for( ulTopicCount = 0; ulTopicCount < mqttexampleTOPIC_COUNT; ulTopicCount++ ) 670 | { 671 | if( xTopicFilterContext[ ulTopicCount ].xSubAckStatus == MQTTSubAckFailure ) 672 | { 673 | LogWarn( ( "Server rejected subscription request. Attempting to re-subscribe to topic %s.", 674 | xTopicFilterContext[ ulTopicCount ].pcTopicFilter ) ); 675 | xFailedSubscribeToTopic = true; 676 | xRetryUtilsStatus = RetryUtils_BackoffAndSleep( &xRetryParams ); 677 | break; 678 | } 679 | } 680 | 681 | configASSERT( xRetryUtilsStatus != RetryUtilsRetriesExhausted ); 682 | } while( ( xFailedSubscribeToTopic == true ) && ( xRetryUtilsStatus == RetryUtilsSuccess ) ); 683 | } 684 | /*-----------------------------------------------------------*/ 685 | 686 | static void prvMQTTPublishToTopic( MQTTContext_t * pxMQTTContext ) 687 | { 688 | MQTTStatus_t xResult; 689 | MQTTPublishInfo_t xMQTTPublishInfo; 690 | 691 | /*** 692 | * For readability, error handling in this function is restricted to the use of 693 | * asserts(). 694 | ***/ 695 | 696 | /* Some fields are not used by this demo so start with everything at 0. */ 697 | ( void ) memset( ( void * ) &xMQTTPublishInfo, 0x00, sizeof( xMQTTPublishInfo ) ); 698 | 699 | /* This demo uses QoS2 */ 700 | xMQTTPublishInfo.qos = MQTTQoS2; 701 | xMQTTPublishInfo.retain = false; 702 | xMQTTPublishInfo.pTopicName = mqttexampleTOPIC; 703 | xMQTTPublishInfo.topicNameLength = ( uint16_t ) strlen( mqttexampleTOPIC ); 704 | xMQTTPublishInfo.pPayload = mqttexampleMESSAGE; 705 | xMQTTPublishInfo.payloadLength = strlen( mqttexampleMESSAGE ); 706 | 707 | /* Get a unique packet id. */ 708 | usPublishPacketIdentifier = MQTT_GetPacketId( pxMQTTContext ); 709 | 710 | /* Send PUBLISH packet. */ 711 | xResult = MQTT_Publish( pxMQTTContext, &xMQTTPublishInfo, usPublishPacketIdentifier ); 712 | 713 | configASSERT( xResult == MQTTSuccess ); 714 | } 715 | /*-----------------------------------------------------------*/ 716 | 717 | static void prvMQTTUnsubscribeFromTopic( MQTTContext_t * pxMQTTContext ) 718 | { 719 | MQTTStatus_t xResult; 720 | MQTTSubscribeInfo_t xMQTTSubscription[ mqttexampleTOPIC_COUNT ]; 721 | 722 | /* Some fields are not used by this demo so start with everything at 0. */ 723 | memset( ( void * ) &xMQTTSubscription, 0x00, sizeof( xMQTTSubscription ) ); 724 | 725 | /* Unsubscribe from the mqttexampleTOPIC topic filter. */ 726 | xMQTTSubscription[ 0 ].qos = MQTTQoS2; 727 | xMQTTSubscription[ 0 ].pTopicFilter = mqttexampleTOPIC; 728 | xMQTTSubscription[ 0 ].topicFilterLength = ( uint16_t ) strlen( mqttexampleTOPIC ); 729 | 730 | /* Get next unique packet identifier. */ 731 | usUnsubscribePacketIdentifier = MQTT_GetPacketId( pxMQTTContext ); 732 | /* Make sure the packet id obtained is valid. */ 733 | configASSERT( usUnsubscribePacketIdentifier != 0 ); 734 | 735 | /* Send UNSUBSCRIBE packet. */ 736 | xResult = MQTT_Unsubscribe( pxMQTTContext, 737 | xMQTTSubscription, 738 | sizeof( xMQTTSubscription ) / sizeof( MQTTSubscribeInfo_t ), 739 | usUnsubscribePacketIdentifier ); 740 | 741 | configASSERT( xResult == MQTTSuccess ); 742 | } 743 | /*-----------------------------------------------------------*/ 744 | 745 | static void prvMQTTProcessResponse( MQTTPacketInfo_t * pxIncomingPacket, 746 | uint16_t usPacketId ) 747 | { 748 | uint32_t ulTopicCount = 0U; 749 | 750 | switch( pxIncomingPacket->type ) 751 | { 752 | case MQTT_PACKET_TYPE_PUBACK: 753 | LogInfo( ( "PUBACK received for packet Id %u.\r\n", usPacketId ) ); 754 | break; 755 | 756 | case MQTT_PACKET_TYPE_SUBACK: 757 | 758 | /* A SUBACK from the broker, containing the server response to our subscription request, has been received. 759 | * It contains the status code indicating server approval/rejection for the subscription to the single topic 760 | * requested. The SUBACK will be parsed to obtain the status code, and this status code will be stored in global 761 | * variable #xTopicFilterContext. */ 762 | prvUpdateSubAckStatus( pxIncomingPacket ); 763 | 764 | for( ulTopicCount = 0; ulTopicCount < mqttexampleTOPIC_COUNT; ulTopicCount++ ) 765 | { 766 | if( xTopicFilterContext[ ulTopicCount ].xSubAckStatus != MQTTSubAckFailure ) 767 | { 768 | LogInfo( ( "Subscribed to the topic %s with maximum QoS %u.\r\n", 769 | xTopicFilterContext[ ulTopicCount ].pcTopicFilter, 770 | xTopicFilterContext[ ulTopicCount ].xSubAckStatus ) ); 771 | } 772 | } 773 | 774 | /* Make sure ACK packet identifier matches with Request packet identifier. */ 775 | configASSERT( usSubscribePacketIdentifier == usPacketId ); 776 | break; 777 | 778 | case MQTT_PACKET_TYPE_UNSUBACK: 779 | LogInfo( ( "Unsubscribed from the topic %s.\r\n", mqttexampleTOPIC ) ); 780 | /* Make sure ACK packet identifier matches with Request packet identifier. */ 781 | configASSERT( usUnsubscribePacketIdentifier == usPacketId ); 782 | break; 783 | 784 | case MQTT_PACKET_TYPE_PINGRESP: 785 | 786 | /* Nothing to be done from application as library handles 787 | * PINGRESP with the use of MQTT_ProcessLoop API function. */ 788 | LogWarn( ( "PINGRESP should not be handled by the application " 789 | "callback when using MQTT_ProcessLoop.\n" ) ); 790 | break; 791 | 792 | case MQTT_PACKET_TYPE_PUBREC: 793 | LogInfo( ( "PUBREC received for packet id %u.\n\n", 794 | usPacketId ) ); 795 | break; 796 | 797 | case MQTT_PACKET_TYPE_PUBREL: 798 | 799 | /* Nothing to be done from application as library handles 800 | * PUBREL. */ 801 | LogInfo( ( "PUBREL received for packet id %u.\n\n", 802 | usPacketId ) ); 803 | break; 804 | 805 | case MQTT_PACKET_TYPE_PUBCOMP: 806 | 807 | /* Nothing to be done from application as library handles 808 | * PUBCOMP. */ 809 | LogInfo( ( "PUBCOMP received for packet id %u.\n\n", 810 | usPacketId ) ); 811 | break; 812 | 813 | /* Any other packet type is invalid. */ 814 | default: 815 | LogWarn( ( "prvMQTTProcessResponse() called with unknown packet type:(%02X).\r\n", 816 | pxIncomingPacket->type ) ); 817 | } 818 | } 819 | 820 | /*-----------------------------------------------------------*/ 821 | 822 | static void prvMQTTProcessIncomingPublish( MQTTPublishInfo_t * pxPublishInfo ) 823 | { 824 | configASSERT( pxPublishInfo != NULL ); 825 | 826 | /* Process incoming Publish. */ 827 | LogInfo( ( "Incoming QoS : %d\n", pxPublishInfo->qos ) ); 828 | 829 | /* Verify the received publish is for the we have subscribed to. */ 830 | if( ( pxPublishInfo->topicNameLength == strlen( mqttexampleTOPIC ) ) && 831 | ( 0 == strncmp( mqttexampleTOPIC, pxPublishInfo->pTopicName, pxPublishInfo->topicNameLength ) ) ) 832 | { 833 | LogInfo( ( "\r\nIncoming Publish Topic Name: %.*s matches subscribed topic.\r\n" 834 | "Incoming Publish Message : %.*s\r\n", 835 | pxPublishInfo->topicNameLength, 836 | pxPublishInfo->pTopicName, 837 | pxPublishInfo->payloadLength, 838 | (char *)pxPublishInfo->pPayload ) ); 839 | } 840 | else 841 | { 842 | LogInfo( ( "Incoming Publish Topic Name: %.*s does not match subscribed topic.\r\n", 843 | pxPublishInfo->topicNameLength, 844 | pxPublishInfo->pTopicName ) ); 845 | } 846 | } 847 | 848 | /*-----------------------------------------------------------*/ 849 | 850 | static void prvEventCallback( MQTTContext_t * pxMQTTContext, 851 | MQTTPacketInfo_t * pxPacketInfo, 852 | MQTTDeserializedInfo_t * pxDeserializedInfo ) 853 | { 854 | /* The MQTT context is not used in this function. */ 855 | ( void ) pxMQTTContext; 856 | 857 | if( ( pxPacketInfo->type & 0xF0U ) == MQTT_PACKET_TYPE_PUBLISH ) 858 | { 859 | LogInfo( ( "PUBLISH received for packet id %u.\n\n", 860 | pxDeserializedInfo->packetIdentifier ) ); 861 | prvMQTTProcessIncomingPublish( pxDeserializedInfo->pPublishInfo ); 862 | } 863 | else 864 | { 865 | prvMQTTProcessResponse( pxPacketInfo, pxDeserializedInfo->packetIdentifier ); 866 | } 867 | } 868 | 869 | /*-----------------------------------------------------------*/ 870 | 871 | static uint32_t prvGetTimeMs( void ) 872 | { 873 | TickType_t xTickCount = 0; 874 | uint32_t ulTimeMs = 0UL; 875 | 876 | /* Get the current tick count. */ 877 | xTickCount = xTaskGetTickCount(); 878 | 879 | /* Convert the ticks to milliseconds. */ 880 | ulTimeMs = ( uint32_t ) xTickCount * MILLISECONDS_PER_TICK; 881 | 882 | /* Reduce ulGlobalEntryTimeMs from obtained time so as to always return the 883 | * elapsed time in the application. */ 884 | ulTimeMs = ( uint32_t ) ( ulTimeMs - ulGlobalEntryTimeMs ); 885 | 886 | return ulTimeMs; 887 | } 888 | 889 | /*-----------------------------------------------------------*/ 890 | -------------------------------------------------------------------------------- /examples/tls_basic/main/utilities/demo_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FreeRTOS Kernel V10.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | * this software and associated documentation files (the "Software"), to deal in 7 | * the Software without restriction, including without limitation the rights to 8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | * the Software, and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | * 22 | * http://www.FreeRTOS.org 23 | * http://aws.amazon.com/freertos 24 | * 25 | */ 26 | 27 | #ifndef DEMO_CONFIG_H 28 | #define DEMO_CONFIG_H 29 | 30 | /* FreeRTOS config include. */ 31 | #include "freertos/FreeRTOSConfig.h" 32 | 33 | /**************************************************/ 34 | /******* DO NOT CHANGE the following order ********/ 35 | /**************************************************/ 36 | 37 | /* Include logging header files and define logging macros in the following order: 38 | * 1. Include the header file "logging_levels.h". 39 | * 2. Define the LIBRARY_LOG_NAME and LIBRARY_LOG_LEVEL macros depending on 40 | * the logging configuration for DEMO. 41 | * 3. Include the header file "logging_stack.h", if logging is enabled for DEMO. 42 | */ 43 | 44 | #include "logging_levels.h" 45 | 46 | /* Logging configuration for the Demo. */ 47 | #ifndef LIBRARY_LOG_NAME 48 | #define LIBRARY_LOG_NAME "MQTTDemo" 49 | #endif 50 | 51 | #ifndef LIBRARY_LOG_LEVEL 52 | #define LIBRARY_LOG_LEVEL LOG_INFO 53 | #endif 54 | 55 | /* Map the SdkLog macro to the logging function to enable logging 56 | * on Windows simulator. */ 57 | #define SdkLog( message ) printf message 58 | 59 | #include "logging_stack.h" 60 | #include "platform.h" 61 | 62 | /************ End of logging configuration ****************/ 63 | 64 | /** 65 | * @brief The MQTT client identifier used in this example. Each client identifier 66 | * must be unique; so edit as required to ensure that no two clients connecting to 67 | * the same broker use the same client identifier. 68 | * 69 | *!!! Please note a #defined constant is used for convenience of demonstration 70 | *!!! only. Production devices can use something unique to the device that can 71 | *!!! be read by software, such as a production serial number, instead of a 72 | *!!! hard coded constant. 73 | * 74 | * #define democonfigCLIENT_IDENTIFIER "insert here." 75 | */ 76 | #define democonfigCLIENT_IDENTIFIER CONFIG_MQTT_CLIENT_IDENTIFIER 77 | 78 | /** 79 | * @brief Endpoint of the MQTT broker to connect to. 80 | * 81 | * This demo application can be run with any MQTT broker, that supports server 82 | * authentication. 83 | * 84 | * @note If you would like to setup an MQTT broker for running this demo, 85 | * please see `mqtt_broker_setup.txt`. 86 | * 87 | * #define democonfigMQTT_BROKER_ENDPOINT "...insert here..." 88 | */ 89 | #define democonfigMQTT_BROKER_ENDPOINT CONFIG_MQTT_BROKER_ENDPOINT 90 | 91 | /** 92 | * @brief The port to use for the demo. 93 | * 94 | * In general, port 8883 is for secured MQTT connections. 95 | * 96 | * @note Port 443 requires use of the ALPN TLS extension with the ALPN protocol 97 | * name. When using port 8883, ALPN is not required. 98 | * 99 | * #define democonfigMQTT_BROKER_PORT ( insert here ) 100 | */ 101 | #define democonfigMQTT_BROKER_PORT CONFIG_MQTT_BROKER_PORT 102 | 103 | /** 104 | * @brief An option to disable Server Name Indication. 105 | * 106 | * @note When using a local Mosquitto server setup, SNI needs to be disabled 107 | * for an MQTT broker that only has an IP address but no hostname. However, 108 | * SNI should be enabled whenever possible. 109 | */ 110 | #define democonfigDISABLE_SNI CONFIG_MQTT_OPTION_SNI 111 | 112 | /** 113 | * @brief Set the stack size of the main demo task. 114 | * 115 | * In the Windows port, this stack only holds a structure. The actual 116 | * stack is created by an operating system thread. 117 | */ 118 | #define democonfigDEMO_STACKSIZE CONFIG_MQTT_EXAMPLE_STACKSIZE 119 | 120 | /** 121 | * @brief Size of the network buffer for MQTT packets. 122 | */ 123 | #define democonfigNETWORK_BUFFER_SIZE CONFIG_MQTT_NETWORK_BUFFER_SIZE 124 | 125 | #endif /* DEMO_CONFIG_H */ 126 | -------------------------------------------------------------------------------- /examples/tls_basic/sdkconfig.defaults: -------------------------------------------------------------------------------- 1 | # newlib for ESP32 and ESP8266 platform 2 | 3 | CONFIG_NEWLIB_ENABLE=y 4 | CONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL=y 5 | CONFIG_NEWLIB_NANO_FORMAT= 6 | CONFIG_SSL_USING_MBEDTLS=y 7 | CONFIG_LWIP_IPV6=y 8 | 9 | -------------------------------------------------------------------------------- /examples/tls_mutual_auth/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following five lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common 6 | ../../) 7 | 8 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 9 | project(tls_mutual_auth) 10 | 11 | target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "main/root_cert_auth.pem" TEXT) 12 | target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "main/client.crt" TEXT) 13 | target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "main/client.key" TEXT) 14 | -------------------------------------------------------------------------------- /examples/tls_mutual_auth/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a 3 | # project subdirectory. 4 | # 5 | 6 | PROJECT_NAME := tls_mutual_auth 7 | 8 | EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common 9 | EXTRA_COMPONENT_DIRS += $(PROJECT_PATH)/../../../ 10 | 11 | include $(IDF_PATH)/make/project.mk 12 | -------------------------------------------------------------------------------- /examples/tls_mutual_auth/README.md: -------------------------------------------------------------------------------- 1 | # TLS Mutual Auth Sample application (mutual authentication) 2 | 3 | (See the README.md file in the upper level 'examples' directory for more information about examples.) 4 | 5 | For connecting to AWS IoT using this example, follow the README for your chip instead. 6 | [ESP32-C3](aws-readme/esp32-c3.md) 7 | [ESP32-S2](aws-readme/esp32-s2.md) 8 | 9 | This guide is for using the example to connect to the broker test.mosquitto.org using ssl transport with client certificate and as a demonstration subscribes/unsubscribes and send a message on certain topic. 10 | (Please note that the public broker is maintained by the community so may not be always available, for details please visit http://test.mosquitto.org) 11 | 12 | It uses FreeRTOS coreMQTT library which implements mqtt client to connect to mqtt broker. 13 | 14 | ## How to use example 15 | 16 | ### Hardware Required 17 | 18 | This example can be executed on any ESP board, the only required interface is WiFi and connection to internet. 19 | 20 | ### Set the target chip 21 | 22 | ``` 23 | idf.py set-target 24 | # choose between esp32|esp32s2|esp32c3|esp32s3|linux 25 | ``` 26 | 27 | ### Configure the project 28 | 29 | * Open the project configuration menu (`idf.py menuconfig`) 30 | * Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. 31 | * Configure MQTT client identifier, broker endpoint and port under "Example Configuration" menu. 32 | * When using Make build system, set `Default serial port` under `Serial flasher config`. 33 | 34 | * Generate your client keys and certificate 35 | 36 | Navigate to the main directory 37 | 38 | ``` 39 | cd main 40 | ``` 41 | 42 | Generate a client key and a CSR. When you are generating the CSR, do not use the default values. At a minimum, the CSR must include the Country, Organisation and Common Name fields. 43 | 44 | ``` 45 | openssl genrsa -out client.key 46 | openssl req -out client.csr -key client.key -new 47 | ``` 48 | 49 | Paste the generated CSR in the [Mosquitto test certificate signer](https://test.mosquitto.org/ssl/index.php), click Submit and copy the downloaded `client.crt` in the `main` directory. 50 | 51 | Please paste the contents of your root certificate auth in PEM format in the `root_cert_auth.pem` file. 52 | 53 | Please note, that the supplied files `client.crt`, `client.key` and `root_cert_auth.pem` in the `main` directory are only placeholders for your client certificate, key and root certificate (i.e. the example "as is" would compile but would not connect to the broker) 54 | 55 | ### Build and Flash 56 | 57 | Build the project and flash it to the board, then run monitor tool to view serial output: 58 | 59 | ``` 60 | idf.py -p PORT flash monitor 61 | ``` 62 | 63 | (To exit the serial monitor, type ``Ctrl-]``.) 64 | 65 | See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. 66 | 67 | ## Example Output 68 | 69 | ``` 70 | I (11130) example_connect: - IPv4 address: 172.168.30.217 71 | I (11140) example_connect: - IPv6 address: fe80:0000:0000:0000:260a:c4ff:fed8:f7f8, type: ESP_IP6_ADDR_IS_LINK_LOCAL 72 | [INFO] [MQTTDemo] [prvConnectToServerWithBackoffRetries:613] Creating a TLS connection to test.mosquitto.org:8884. 73 | 74 | I (13740) tls_freertos: (Network connection 0x3ffc6d70) Connection to test.mosquitto.org established. 75 | [INFO] [MQTTDemo] [prvMQTTDemoTask:497] Creating an MQTT connection to test.mosquitto.org. 76 | 77 | [INFO] [MQTTDemo] [prvCreateMQTTConnectionWithBroker:713] An MQTT connection is established with test.mosquitto.org. 78 | [INFO] [MQTTDemo] [prvMQTTSubscribeWithBackoffRetries:771] Attempt to subscribe to the MQTT topic testClient/example/topic. 79 | 80 | [INFO] [MQTTDemo] [prvMQTTSubscribeWithBackoffRetries:778] SUBSCRIBE sent for topic testClient/example/topic to broker. 81 | 82 | 83 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:902] Subscribed to the topic testClient/example/topic with maximum QoS 1. 84 | 85 | [INFO] [MQTTDemo] [prvMQTTDemoTask:511] Publish to the MQTT topic testClient/example/topic. 86 | 87 | [INFO] [MQTTDemo] [prvMQTTDemoTask:517] Attempt to receive publish message from broker. 88 | 89 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:883] PUBACK received for packet Id 2. 90 | 91 | [INFO] [MQTTDemo] [prvMQTTProcessIncomingPublish:938] Incoming QoS : 1 92 | 93 | [INFO] [MQTTDemo] [prvMQTTProcessIncomingPublish:949] 94 | Incoming Publish Topic Name: testClient/example/topic matches subscribed topic. 95 | Incoming Publish Message : Hello World! 96 | 97 | [INFO] [MQTTDemo] [prvMQTTDemoTask:522] Keeping Connection Idle... 98 | 99 | 100 | [INFO] [MQTTDemo] [prvMQTTDemoTask:511] Publish to the MQTT topic testClient/example/topic. 101 | 102 | [INFO] [MQTTDemo] [prvMQTTDemoTask:517] Attempt to receive publish message from broker. 103 | 104 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:883] PUBACK received for packet Id 3. 105 | 106 | [INFO] [MQTTDemo] [prvMQTTProcessIncomingPublish:938] Incoming QoS : 1 107 | 108 | [INFO] [MQTTDemo] [prvMQTTProcessIncomingPublish:949] 109 | Incoming Publish Topic Name: testClient/example/topic matches subscribed topic. 110 | Incoming Publish Message : Hello World! 111 | 112 | [INFO] [MQTTDemo] [prvMQTTDemoTask:522] Keeping Connection Idle... 113 | 114 | 115 | [INFO] [MQTTDemo] [prvMQTTDemoTask:511] Publish to the MQTT topic testClient/example/topic. 116 | 117 | [INFO] [MQTTDemo] [prvMQTTDemoTask:517] Attempt to receive publish message from broker. 118 | 119 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:883] PUBACK received for packet Id 4. 120 | 121 | [INFO] [MQTTDemo] [prvMQTTProcessIncomingPublish:938] Incoming QoS : 1 122 | 123 | [INFO] [MQTTDemo] [prvMQTTProcessIncomingPublish:949] 124 | Incoming Publish Topic Name: testClient/example/topic matches subscribed topic. 125 | Incoming Publish Message : Hello World! 126 | 127 | [INFO] [MQTTDemo] [prvMQTTDemoTask:522] Keeping Connection Idle... 128 | 129 | 130 | [INFO] [MQTTDemo] [prvMQTTDemoTask:511] Publish to the MQTT topic testClient/example/topic. 131 | 132 | [INFO] [MQTTDemo] [prvMQTTDemoTask:517] Attempt to receive publish message from broker. 133 | 134 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:883] PUBACK received for packet Id 5. 135 | 136 | [INFO] [MQTTDemo] [prvMQTTProcessIncomingPublish:938] Incoming QoS : 1 137 | 138 | [INFO] [MQTTDemo] [prvMQTTProcessIncomingPublish:949] 139 | Incoming Publish Topic Name: testClient/example/topic matches subscribed topic. 140 | Incoming Publish Message : Hello World! 141 | 142 | [INFO] [MQTTDemo] [prvMQTTDemoTask:522] Keeping Connection Idle... 143 | 144 | 145 | [INFO] [MQTTDemo] [prvMQTTDemoTask:511] Publish to the MQTT topic testClient/example/topic. 146 | 147 | [INFO] [MQTTDemo] [prvMQTTDemoTask:517] Attempt to receive publish message from broker. 148 | 149 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:883] PUBACK received for packet Id 6. 150 | 151 | [INFO] [MQTTDemo] [prvMQTTProcessIncomingPublish:938] Incoming QoS : 1 152 | 153 | [INFO] [MQTTDemo] [prvMQTTProcessIncomingPublish:949] 154 | Incoming Publish Topic Name: testClient/example/topic matches subscribed topic. 155 | Incoming Publish Message : Hello World! 156 | 157 | [INFO] [MQTTDemo] [prvMQTTDemoTask:522] Keeping Connection Idle... 158 | 159 | 160 | [INFO] [MQTTDemo] [prvMQTTDemoTask:527] Unsubscribe from the MQTT topic testClient/example/topic. 161 | 162 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:911] Unsubscribed from the topic testClient/example/topic. 163 | 164 | [INFO] [MQTTDemo] [prvMQTTDemoTask:541] Disconnecting the MQTT connection with test.mosquitto.org. 165 | 166 | [INFO] [MQTTDemo] [prvMQTTDemoTask:559] prvMQTTDemoTask() completed an iteration successfully. Total free heap is 232832. 167 | 168 | [INFO] [MQTTDemo] [prvMQTTDemoTask:560] Demo completed successfully. 169 | 170 | [INFO] [MQTTDemo] [prvMQTTDemoTask:561] Short delay before starting the next iteration.... 171 | ``` 172 | 173 | ## Size Information on ESP-IDF v4.3 174 | 175 | ``` 176 | Total sizes: 177 | DRAM .data size: 16040 bytes 178 | DRAM .bss size: 19416 bytes 179 | Used static DRAM: 0 bytes ( 0 available, nan% used) 180 | Used static IRAM: 0 bytes ( 0 available, nan% used) 181 | Used stat D/IRAM: 118395 bytes ( 258437 available, 31.4% used) 182 | Flash code: 553107 bytes 183 | Flash rodata: 121148 bytes 184 | Total image size:~ 773234 bytes (.bin may be padded larger) 185 | ``` -------------------------------------------------------------------------------- /examples/tls_mutual_auth/aws-readme/esp32-c3.md: -------------------------------------------------------------------------------- 1 | # ESP32-C3 Getting Started Guide for AWS IoT Core 2 | 3 | ## Table of Contents 4 | 5 | 1. [Document Information](#1-document-information) 6 | 2. [Overview](#2-overview) 7 | 3. [Hardware Description](#3-hardware-description) 8 | 4. [Set up your Development Environment](#4-set-up-your-development-environment) 9 | 5. [Set up your hardware](#5-set-up-your-hardware) 10 | 6. [Setup your AWS account and Permissions](#6-setup-your-aws-account-and-permissions) 11 | 7. [Create Resources in AWS IoT](#7-create-resources-in-aws-iot) 12 | 8. [Provision the Device with credentials](#8-provision-the-device-with-credentials) 13 | 9. [Build your first project](#9-build-your-first-project) 14 | 10. [Run the demo](#10-run-the-demo) 15 | 11. [Debugging](#11-debugging) 16 | 12. [Troubleshooting](#12-troubleshooting) 17 | 18 | # 1. Document Information 19 | ## 1.1 Naming Conventions 20 | None 21 | ## 1.2 Glossary 22 | None 23 | ## 1.3 Revision History (Version, Date, Description of change) 24 | 0.1 25-Feb-2021 Initial Draft 25 | # 2. Overview 26 | ESP32-C3 is a single-core, 32-bit, RISC-V-based MCU with 400KB of SRAM, which is capable of running at 160MHz. It has integrated 2.4 GHz Wi-Fi and Bluetooth 5 (LE) with a long-range support. It has 22 programmable GPIOs with support for ADC, SPI, UART, I2C, I2S, RMT, TWAI, and PWM. 27 | 28 | This user guide will help you get started with ESP32-C3 DevKit and AWS IoT. 29 | 30 | ESP32-C3-DevKitM-1 | ESP32-C3-DevKitC-02 31 | :-------------------------:|:-------------------------: 32 | ![](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/_images/esp32-c3-devkitm-1-v1-isometric.png) | ![](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/_images/esp32-c3-devkitc-02-v1-isometric.png) 33 | 34 | This guide works for the ESP32-C3 DevKits: ESP32-C3-DevKitM-1 and ESP32-C3-DevKitC-02. 35 | The ESP32-C3-DevKitM-1 DevKit supports following modules: ESP32-C3-MINI-1 36 | The ESP32-C3-DevKitC-02 DevKit supports following modules: ESP32-C3-WROOM-02 37 | 38 | Refer to the Product Overview section in the [product data sheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf). 39 | 40 | # 3. Hardware Description 41 | ## 3.1 DataSheet 42 | The product data sheet is available [here](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf). 43 | ## 3.2 Standard Kit Contents 44 | Refer to the section Contents and Packaging in the [User Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitm-1.html) 45 | ## 3.3 User Provided items 46 | USB 2.0 cable (Standard A to Micro-B) 47 | Computer running Windows, Linux or mac OS 48 | ## 3.4 3rd Party purchasable items 49 | None 50 | ## 3.5 Additional Hardware References 51 | Refer to the [User Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitm-1.html). 52 | 53 | # 4. Set up your Development Environment 54 | ## 4.1 Tools Installation (IDEs, Toolchains, SDKs) 55 | You have a choice to either download and install the following software manually 56 | - **Toolchain** to compile code for ESP32-C3 57 | - **Build tools** - CMake and Ninja to build a full **Application** for ESP32-C3 58 | - **ESP-IDF** that essentially contains API (software libraries and source code) for ESP32-C3 and scripts to operate the **Toolchain** 59 | **or** get through the onboarding process using the following official plugins for integrated development environments (IDE) described in separate documents 60 | - [Eclipse Plugin](https://github.com/espressif/idf-eclipse-plugin) ([installation link](https://github.com/espressif/idf-eclipse-plugin#installing-idf-plugin-using-update-site-url)) 61 | - [VS Code Extension](https://github.com/espressif/vscode-esp-idf-extension) ([onboarding](https://github.com/espressif/vscode-esp-idf-extension/blob/master/docs/ONBOARDING.md)) 62 | 63 | ![Development of applications for ESP32-C3](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/_images/what-you-need.png) 64 | 65 | For further instructions, refer to [Step-by-step installation.](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/index.html#installation-step-by-step) 66 | ## 4.2 Other software required to develop and debug applications for the device 67 | Please use *install.sh* (for Linux and macOS) or *install.bat* (for Windows)* scripts provided with ESP-IDF to install required software on the development host. 68 | ## 4.3 Other pre-requisites 69 | None. 70 | ## 4.4 Additional Software References 71 | - [Establish Serial Connection with ESP32-C3](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/establish-serial-connection.html) 72 | - [Build and Flash with Eclipse IDE](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/eclipse-setup.html) 73 | - [Getting Started with VS Code IDE](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/vscode-setup.html) 74 | - [IDF Monitor](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-guides/tools/idf-monitor.html) 75 | - [Customized Setup of Toolchain](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/toolchain-setup-scratch.html) 76 | 77 | # 5. Set up your hardware 78 | [Hardware reference](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitm-1.html#hardware-reference) 79 | 80 | [Block diagram](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitm-1.html#block-diagram) 81 | 82 | [Description of Components](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitm-1.html#description-of-components) 83 | 84 | Please refer to above links for the hardware setup. ESP32-C3-DevKit-M1 requires only a USB connection to the development host computer. The same USB connection is used for supplying the power, programming the board and getting serial console access. 85 | 86 | The Red power LED will glow indicating the power supply to the development board. 87 | 88 | Generally no special key-press is required to put the development board in the UART boot mode for programming. In case the Windows driver fails to put the development board, please press "BOOT" and "RST" button together and release only “RST" button first. 89 | 90 | # 6. Setup your AWS account and Permissions 91 | Refer to the instructions at [Set up your AWS Account](https://docs.aws.amazon.com/iot/latest/developerguide/setting-up.html). Follow the steps outlined in these sections to create your account and a user and get started: 92 | 93 | - Sign up for an AWS account and 94 | - Create a user and grant permissions. 95 | - Open the AWS IoT console 96 | 97 | Pay special attention to the Notes. 98 | 99 | # 7. Create Resources in AWS IoT 100 | Refer to the instructions at [Create AWS IoT Resources](https://docs.aws.amazon.com/iot/latest/developerguide/create-iot-resources.html). Follow the steps outlined in these sections to provision resources for your device: 101 | 102 | - Create an AWS IoT Policy 103 | - Create a thing object and certificate 104 | - Download each of the certificate and key files and save them for later. 105 | This will be needed in the next step. 106 | 107 | Pay special attention to the Notes. 108 | 109 | # 8. Provision the Device with credentials 110 | 111 | Ensure that you have downloaded the device certificate and key files in the previous step. 112 | 113 | - In order to load the Device certificate, copy the contents of the Device certificate file to the file named `client.crt` in the main folder. 114 | - In order to load the Private key, copy the contents of the private key file to the file named `client.key` in the main folder. 115 | - In order to load the Root CA certificate, copy the contents of the file `AmazonRootCA1.pem` obtained from [here](https://docs.aws.amazon.com/iot/latest/developerguide/server-authentication.html#server-authentication-certs) to the file named `root_cert_auth.pem` in the main folder. 116 | 117 | 118 | # 9. Build your first project 119 | Refer to the instructions [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/index.html#creating-your-first-project) to: 120 | 121 | - Start a Project 122 | - Connect Your Device 123 | - Configure 124 | - Build the Project 125 | - Flash onto the device 126 | 127 | # 10. Run the demo 128 | 129 | ## 10.1 Set the target chip to your chip 130 | 131 | ``` 132 | idf.py set-target esp32c3 133 | ``` 134 | 135 | ## 10.2 Configuring the demo example 136 | 137 | * Open the project configuration menu (`idf.py menuconfig`) 138 | * Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. 139 | * Configure MQTT client identifier, broker endpoint and port under "Example Configuration" menu. 140 | * When using Make build system, set `Default serial port` under `Serial flasher config`. 141 | 142 | ## 10.3 Running the application 143 | 144 | Build the project and flash it to the board, then run monitor tool to view serial output: 145 | 146 | ``` 147 | idf.py -p PORT flash monitor 148 | ``` 149 | 150 | (To exit the serial monitor, type ``Ctrl-]``.) 151 | 152 | To ensure your application is running correctly, refer to the instructions [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/index.html#step-10-monitor). 153 | 154 | # 11. Debugging 155 | 156 | ## 11.1 View device console output 157 | Refer to the instructions [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/index.html#step-10-monitor). 158 | 159 | ## 11.2 Debugging Examples 160 | 161 | Refer to the examples given [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-guides/jtag-debugging/index.html#jtag-debugging-examples) for [Using the debugger](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-guides/jtag-debugging/using-debugger.html). 162 | 163 | ## 11.3 Example Output 164 | ``` 165 | I (2447) example_connect: Got IPv6 event: Interface "example_connect: sta" address: fe80:0000:0000:0000:7edf:a1ff:fe40:2018, type: ESP_IP6_ADDR_IS_LINK_LOCAL 166 | I (6447) esp_netif_handlers: example_connect: sta ip: 192.168.1.41, mask: 255.255.255.0, gw: 192.168.1.1 167 | I (6447) example_connect: Got IPv4 event: Interface "example_connect: sta" address: 192.168.1.41 168 | I (6457) example_connect: Connected to example_connect: sta 169 | I (6457) example_connect: - IPv4 address: 192.168.1.41 170 | I (6467) example_connect: - IPv6 address: fe80:0000:0000:0000:7edf:a1ff:fe40:2018, type: ESP_IP6_ADDR_IS_LINK_LOCAL 171 | [INFO] [MQTTDemo] [prvConnectToServerWithBackoffRetries:614] Creating a TLS connection to t37g78e7jrczce.deviceadvisor.iot.us-east-1.amazonaws.com:8883. 172 | 173 | W (6507) wifi:idx:0 (ifx:0, 7c:a9:6b:4f:6a:15), tid:0, ssn:5, winSize:64 174 | I (9507) tls_freertos: (Network connection 0x3fca6a84) Connection to t37g78e7jrczce.deviceadvisor.iot.us-east-1.amazonaws.com established. 175 | [INFO] [MQTTDemo] [prvMQTTDemoTask:498] Creating an MQTT connection to t37g78e7jrczce.deviceadvisor.iot.us-east-1.amazonaws.com. 176 | 177 | [INFO] [MQTTDemo] [prvCreateMQTTConnectionWithBroker:714] An MQTT connection is established with t37g78e7jrczce.deviceadvisor.iot.us-east-1.amazonaws.com. 178 | [INFO] [MQTTDemo] [prvMQTTSubscribeWithBackoffRetries:772] Attempt to subscribe to the MQTT topic testClient/example/topic. 179 | 180 | [INFO] [MQTTDemo] [prvMQTTSubscribeWithBackoffRetries:779] SUBSCRIBE sent for topic testClient/example/topic to broker. 181 | 182 | 183 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:903] Subscribed to the topic testClient/example/topic with maximum QoS 1. 184 | 185 | [INFO] [MQTTDemo] [prvMQTTDemoTask:512] Publish to the MQTT topic testClient/example/topic. 186 | 187 | [INFO] [MQTTDemo] [prvMQTTDemoTask:518] Attempt to receive publish message from broker. 188 | ``` 189 | 190 | ## 11.4 Logging with different Debug Levels and Interpreting Errors 191 | Please refer to following pages for: 192 | - [Logging library](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/system/log.html) 193 | - [Error Code Reference](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/error-codes.html#error-codes-reference) 194 | 195 | ## 11.5 Debugging using Software and Hardware debuggers 196 | Please follow the steps mentioned [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-guides/jtag-debugging/index.html). 197 | 198 | # 12 Troubleshooting 199 | Refer to [Flashing Issues](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/index.html#encountered-issues-while-flashing). 200 | -------------------------------------------------------------------------------- /examples/tls_mutual_auth/aws-readme/esp32-s2.md: -------------------------------------------------------------------------------- 1 | # ESP32-S2 Getting Started Guide for AWS IoT Core 2 | 3 | ## Table of Contents 4 | 5 | 1. [Document Information](#1-document-information) 6 | 2. [Overview](#2-overview) 7 | 3. [Hardware Description](#3-hardware-description) 8 | 4. [Set up your Development Environment](#4-set-up-your-development-environment) 9 | 5. [Set up your hardware](#5-set-up-your-hardware) 10 | 6. [Setup your AWS account and Permissions](#6-setup-your-aws-account-and-permissions) 11 | 7. [Create Resources in AWS IoT](#7-create-resources-in-aws-iot) 12 | 8. [Provision the Device with credentials](#8-provision-the-device-with-credentials) 13 | 9. [Build your first project](#9-build-your-first-project) 14 | 10. [Run the demo](#10-run-the-demo) 15 | 11. [Debugging](#11-debugging) 16 | 12. [Troubleshooting](#12-troubleshooting) 17 | 18 | # 1. Document Information 19 | ## 1.1 Naming Conventions 20 | None 21 | ## 1.2 Glossary 22 | None 23 | ## 1.3 Revision History (Version, Date, Description of change) 24 | 0.1 25-Feb-2021 Initial Draft 25 | # 2. Overview 26 | ESP32-S2 is a truly secure, highly integrated, low-power, 2.4 GHz Wi-Fi Microcontroller SoC supporting Wi-Fi HT40 and having 43 GPIOs. Based on an Xtensa® single-core 32-bit LX7 processor, it can be clocked at up to 240 MHz. 27 | 28 | This user guide will help you get started with ESP32-S2 DevKit and AWS IoT. 29 | 30 | ESP32-S2-Saola-1 | ESP32-S2-DevKitM-1 31 | :-------------------------:|:-------------------------: 32 | ![](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/_images/esp32-s2-saola-1-v1.2-isometric.png) | ![](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/_images/esp32-s2-devkitm-1-v1-isometric.png) 33 | 34 | This guide works for the ESP32-S2 DevKits: ESP32-S2-Saola-1 and ESP32-S2-DevKitM-1. 35 | The ESP32-S2-Saola-1 DevKit supports following modules: ESP32-S2-WROOM, ESP32-S2-WROOM-I, ESP32-S2-WROVER, ESP32-S2-WROVER-I 36 | The ESP32-S2-DevKitM-1 DevKit supports following modules: ESP32-S2-MINI-1, ESP32-S2-MINI-1U 37 | 38 | Refer to the Product Overview section in the [product data sheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf). 39 | 40 | # 3. Hardware Description 41 | ## 3.1 DataSheet 42 | The product data sheet is available [here](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf). 43 | ## 3.2 Standard Kit Contents 44 | Refer to the section Contents and Packaging in the [User Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-saola-1-v1.2.html) 45 | ## 3.3 User Provided items 46 | USB 2.0 cable (Standard A to Micro-B) 47 | Computer running Windows, Linux or mac OS 48 | 49 | ## 3.4 3rd Party purchasable items 50 | None 51 | ## 3.5 Additional Hardware References 52 | Refer to the [User Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-saola-1-v1.2.html). 53 | 54 | # 4. Set up your Development Environment 55 | ## 4.1 Tools Installation (IDEs, Toolchains, SDKs) 56 | You have a choice to either download and install the following software manually 57 | - **Toolchain** to compile code for ESP32-S2 58 | - **Build tools** - CMake and Ninja to build a full **Application** for ESP32-S2 59 | - **ESP-IDF** that essentially contains API (software libraries and source code) for ESP32-S2 and scripts to operate the **Toolchain** 60 | **or** get through the onboarding process using the following official plugins for integrated development environments (IDE) described in separate documents 61 | - [Eclipse Plugin](https://github.com/espressif/idf-eclipse-plugin) ([installation link](https://github.com/espressif/idf-eclipse-plugin#installing-idf-plugin-using-update-site-url)) 62 | - [VS Code Extension](https://github.com/espressif/vscode-esp-idf-extension) ([onboarding](https://github.com/espressif/vscode-esp-idf-extension/blob/master/docs/ONBOARDING.md)) 63 | 64 | ![Development of applications for ESP32-S2](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/_images/what-you-need.png) 65 | 66 | For further instructions, refer to [Step-by-step installation.](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/get-started/index.html#installation-step-by-step) 67 | ## 4.2 Other software required to develop and debug applications for the device 68 | Please use *install.sh* (for Linux and macOS) or *install.bat* (for Windows)* scripts provided with ESP-IDF to install required software on the development host. 69 | ## 4.3 Other pre-requisites 70 | None. 71 | ## 4.4 Additional Software References 72 | - [Establish Serial Connection with ESP32-S2](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/get-started/establish-serial-connection.html) 73 | - [Build and Flash with Eclipse IDE](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/get-started/eclipse-setup.html) 74 | - [Getting Started with VS Code IDE](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/get-started/vscode-setup.html) 75 | - [IDF Monitor](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-guides/tools/idf-monitor.html) 76 | - [Customized Setup of Toolchain](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/get-started/toolchain-setup-scratch.html) 77 | 78 | # 5. Set up your hardware 79 | [Hardware reference](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-saola-1-v1.2.html#hardware-reference) 80 | 81 | [Block diagram](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-saola-1-v1.2.html#block-diagram) 82 | 83 | [Description of Components](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-saola-1-v1.2.html#description-of-components) 84 | 85 | Please refer to above links for the hardware setup. The ESP32-S2 DevKit requires only a USB connection to the development host computer. The same USB connection is used for supplying the power, programming the board and getting serial console access. 86 | 87 | The Red power LED will glow indicating the power supply to the development board. 88 | 89 | Generally no special key-press is required to put the development board in the UART boot mode for programming. In case the Windows driver fails to put the development board, please press "BOOT" and "RST" button together and release only “RST" button first. 90 | 91 | # 6. Setup your AWS account and Permissions 92 | Refer to the instructions at [Set up your AWS Account](https://docs.aws.amazon.com/iot/latest/developerguide/setting-up.html). Follow the steps outlined in these sections to create your account and a user and get started: 93 | 94 | - Sign up for an AWS account and 95 | - Create a user and grant permissions. 96 | - Open the AWS IoT console 97 | 98 | Pay special attention to the Notes. 99 | 100 | # 7. Create Resources in AWS IoT 101 | Refer to the instructions at [Create AWS IoT Resources](https://docs.aws.amazon.com/iot/latest/developerguide/create-iot-resources.html). Follow the steps outlined in these sections to provision resources for your device: 102 | 103 | - Create an AWS IoT Policy 104 | - Create a thing object and certificate 105 | - Download each of the certificate and key files and save them for later. 106 | This will be needed in the next step. 107 | 108 | Pay special attention to the Notes. 109 | 110 | # 8. Provision the Device with credentials 111 | 112 | Ensure that you have downloaded the device certificate and key files in the previous step. 113 | 114 | - In order to load the Device certificate, copy the contents of the Device certificate file to the file named `client.crt` in the main folder. 115 | - In order to load the Private key, copy the contents of the private key file to the file named `client.key` in the main folder. 116 | - In order to load the Root CA certificate, copy the contents of the file `AmazonRootCA1.pem` obtained from [here](https://docs.aws.amazon.com/iot/latest/developerguide/server-authentication.html#server-authentication-certs) to the file named `root_cert_auth.pem` in the main folder. 117 | 118 | 119 | # 9. Build your first project 120 | Refer to the instructions [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/get-started/index.html#creating-your-first-project) to: 121 | 122 | - Start a Project 123 | - Connect Your Device 124 | - Configure 125 | - Build the Project 126 | - Flash onto the device 127 | 128 | # 10. Run the demo 129 | 130 | ## 10.1 Set the target chip to your chip 131 | 132 | ``` 133 | idf.py set-target esp32s2 134 | ``` 135 | 136 | ## 10.2 Configuring the demo example 137 | 138 | * Open the project configuration menu (`idf.py menuconfig`) 139 | * Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. 140 | * Configure MQTT client identifier, broker endpoint and port under "Example Configuration" menu. 141 | * When using Make build system, set `Default serial port` under `Serial flasher config`. 142 | 143 | ## 10.3 Running the application 144 | 145 | Build the project and flash it to the board, then run monitor tool to view serial output: 146 | 147 | ``` 148 | idf.py -p PORT flash monitor 149 | ``` 150 | 151 | (To exit the serial monitor, type ``Ctrl-]``.) 152 | 153 | To ensure your application is running correctly, refer to the instructions [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/get-started/index.html#step-10-monitor). 154 | 155 | # 11. Debugging 156 | 157 | ## 11.1 View device console output 158 | Refer to the instructions [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/get-started/index.html#step-10-monitor). 159 | 160 | ## 11.2 Debugging Examples 161 | 162 | Refer to the examples given [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-guides/jtag-debugging/index.html#jtag-debugging-examples) for [Using the debugger](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-guides/jtag-debugging/using-debugger.html). 163 | 164 | ## 11.3 Example Output 165 | ``` 166 | I (2447) example_connect: Got IPv6 event: Interface "example_connect: sta" address: fe80:0000:0000:0000:7edf:a1ff:fe40:2018, type: ESP_IP6_ADDR_IS_LINK_LOCAL 167 | I (6447) esp_netif_handlers: example_connect: sta ip: 192.168.1.41, mask: 255.255.255.0, gw: 192.168.1.1 168 | I (6447) example_connect: Got IPv4 event: Interface "example_connect: sta" address: 192.168.1.41 169 | I (6457) example_connect: Connected to example_connect: sta 170 | I (6457) example_connect: - IPv4 address: 192.168.1.41 171 | I (6467) example_connect: - IPv6 address: fe80:0000:0000:0000:7edf:a1ff:fe40:2018, type: ESP_IP6_ADDR_IS_LINK_LOCAL 172 | [INFO] [MQTTDemo] [prvConnectToServerWithBackoffRetries:614] Creating a TLS connection to t37g78e7jrczce.deviceadvisor.iot.us-east-1.amazonaws.com:8883. 173 | 174 | W (6507) wifi:idx:0 (ifx:0, 7c:a9:6b:4f:6a:15), tid:0, ssn:5, winSize:64 175 | I (9507) tls_freertos: (Network connection 0x3fca6a84) Connection to t37g78e7jrczce.deviceadvisor.iot.us-east-1.amazonaws.com established. 176 | [INFO] [MQTTDemo] [prvMQTTDemoTask:498] Creating an MQTT connection to t37g78e7jrczce.deviceadvisor.iot.us-east-1.amazonaws.com. 177 | 178 | [INFO] [MQTTDemo] [prvCreateMQTTConnectionWithBroker:714] An MQTT connection is established with t37g78e7jrczce.deviceadvisor.iot.us-east-1.amazonaws.com. 179 | [INFO] [MQTTDemo] [prvMQTTSubscribeWithBackoffRetries:772] Attempt to subscribe to the MQTT topic testClient/example/topic. 180 | 181 | [INFO] [MQTTDemo] [prvMQTTSubscribeWithBackoffRetries:779] SUBSCRIBE sent for topic testClient/example/topic to broker. 182 | 183 | 184 | [INFO] [MQTTDemo] [prvMQTTProcessResponse:903] Subscribed to the topic testClient/example/topic with maximum QoS 1. 185 | 186 | [INFO] [MQTTDemo] [prvMQTTDemoTask:512] Publish to the MQTT topic testClient/example/topic. 187 | 188 | [INFO] [MQTTDemo] [prvMQTTDemoTask:518] Attempt to receive publish message from broker. 189 | ``` 190 | 191 | ## 11.4 Logging with different Debug Levels and Interpreting Errors 192 | Please refer to following pages for: 193 | - [Logging library](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/system/log.html) 194 | - [Error Code Reference](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/error-codes.html#error-codes-reference) 195 | 196 | ## 11.5 Debugging using Software and Hardware debuggers 197 | Please follow the steps mentioned [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-guides/jtag-debugging/index.html). 198 | 199 | # 12 Troubleshooting 200 | Refer to [Flashing Issues](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/get-started/index.html#encountered-issues-while-flashing). 201 | -------------------------------------------------------------------------------- /examples/tls_mutual_auth/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_SRCS "tls_mutual_auth.c" "utilities/MutualAuthMQTTExample.c") 2 | set(COMPONENT_ADD_INCLUDEDIRS "." "utilities") 3 | 4 | register_component() 5 | -------------------------------------------------------------------------------- /examples/tls_mutual_auth/main/Kconfig.projbuild: -------------------------------------------------------------------------------- 1 | menu "Example Configuration" 2 | 3 | config MQTT_CLIENT_IDENTIFIER 4 | string "The MQTT client identifier used in this example" 5 | default "testClient" 6 | help 7 | The MQTT client identifier used in this example. Each client identifier must be unique. 8 | so edit as required to ensure that no two clients connecting to the same broker use the same client identifier. 9 | 10 | config MQTT_BROKER_ENDPOINT 11 | string "Endpoint of the MQTT broker to connect to" 12 | default "test.mosquitto.org" 13 | help 14 | This example can be run with any MQTT broker, that supports server authentication. 15 | 16 | config MQTT_BROKER_PORT 17 | int "Port of the MQTT broker use" 18 | default 8884 19 | help 20 | In general, port 8883 is for secured MQTT connections. 21 | Port 443 requires use of the ALPN TLS extension with the ALPN protocol name. 22 | When using port 8883, ALPN is not required. 23 | 24 | config MQTT_OPTION_SNI 25 | int "An option to disable Server Name Indication" 26 | range 0 1 27 | default 0 28 | help 29 | When using a local Mosquitto server setup, SNI needs to be disabled 30 | for an MQTT broker that only has an IP address but no hostname. However, 31 | SNI should be enabled whenever possible. 32 | 33 | config HARDWARE_PLATFORM_NAME 34 | string "The hardware platform" 35 | default "ESP32" 36 | help 37 | The name of the hardware platform the application is running on. 38 | 39 | config MQTT_EXAMPLE_STACKSIZE 40 | int "Set the stack size of the example task" 41 | range 5120 8192 42 | default 5120 43 | help 44 | The actual stack is created by an operating system thread. 45 | 46 | config MQTT_NETWORK_BUFFER_SIZE 47 | int "Size of the network buffer for MQTT packets" 48 | range 1024 2048 49 | default 1024 50 | help 51 | Size of the network buffer for MQTT packets. 52 | 53 | endmenu 54 | -------------------------------------------------------------------------------- /examples/tls_mutual_auth/main/client.crt: -------------------------------------------------------------------------------- 1 | Please paste your client certificate here (follow instructions in README.md) 2 | -------------------------------------------------------------------------------- /examples/tls_mutual_auth/main/client.key: -------------------------------------------------------------------------------- 1 | Please paste here your client key (follow instructions in README.md) 2 | -------------------------------------------------------------------------------- /examples/tls_mutual_auth/main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | COMPONENT_EMBED_TXTFILES := client.crt client.key root_cert_auth.pem 7 | 8 | COMPONENT_ADD_INCLUDEDIRS += utilities 9 | COMPONENT_SRCDIRS += utilities -------------------------------------------------------------------------------- /examples/tls_mutual_auth/main/root_cert_auth.pem: -------------------------------------------------------------------------------- 1 | Please paste your root certificate auth here (follow instructions in README.md) 2 | -------------------------------------------------------------------------------- /examples/tls_mutual_auth/main/tls_mutual_auth.c: -------------------------------------------------------------------------------- 1 | /* tls-basic example 2 | 3 | This example code is in the Public Domain (or CC0 licensed, at your option.) 4 | 5 | Unless required by applicable law or agreed to in writing, this 6 | software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 7 | CONDITIONS OF ANY KIND, either express or implied. 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "esp_system.h" 14 | #include "nvs_flash.h" 15 | #include "esp_event.h" 16 | #include "esp_netif.h" 17 | #include "protocol_examples_common.h" 18 | 19 | #include "esp_log.h" 20 | 21 | static const char *TAG = "MQTTS_EXAMPLE"; 22 | 23 | /* 24 | * Prototypes for the demos that can be started from this project. Note the 25 | * MQTT demo is not actually started until the network is already. 26 | */ 27 | extern void vStartSimpleMQTTDemo( void ); 28 | 29 | void app_main() 30 | { 31 | ESP_LOGI(TAG, "[APP] Startup.."); 32 | ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); 33 | ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); 34 | 35 | esp_log_level_set("*", ESP_LOG_INFO); 36 | esp_log_level_set("esp-tls", ESP_LOG_VERBOSE); 37 | 38 | ESP_ERROR_CHECK(nvs_flash_init()); 39 | ESP_ERROR_CHECK(esp_netif_init()); 40 | ESP_ERROR_CHECK(esp_event_loop_create_default()); 41 | 42 | /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. 43 | * Read "Establishing Wi-Fi or Ethernet Connection" section in 44 | * examples/protocols/README.md for more information about this function. 45 | */ 46 | ESP_ERROR_CHECK(example_connect()); 47 | 48 | vStartSimpleMQTTDemo(); 49 | } 50 | -------------------------------------------------------------------------------- /examples/tls_mutual_auth/main/utilities/MutualAuthMQTTExample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * FreeRTOS Kernel V10.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | * this software and associated documentation files (the "Software"), to deal in 7 | * the Software without restriction, including without limitation the rights to 8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | * the Software, and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | * 22 | * http://www.FreeRTOS.org 23 | * http://aws.amazon.com/freertos 24 | * 25 | */ 26 | 27 | /* 28 | * Demo for showing use of the MQTT API using a mutually authenticated 29 | * network connection. 30 | * 31 | * The Example shown below uses MQTT APIs to create MQTT messages and send them 32 | * over the mutually authenticated network connection established with the 33 | * MQTT broker. This example is single threaded and uses statically allocated 34 | * memory. It uses QoS1 for sending to and receiving messages from the broker. 35 | * 36 | * A mutually authenticated TLS connection is used to connect to the 37 | * MQTT message broker in this example. Define democonfigMQTT_BROKER_ENDPOINT, 38 | * democonfigROOT_CA_PEM, democonfigCLIENT_CERTIFICATE_PEM, 39 | * and democonfigCLIENT_PRIVATE_KEY_PEM in demo_config.h to establish a 40 | * mutually authenticated connection. 41 | */ 42 | 43 | /* Standard includes. */ 44 | #include 45 | #include 46 | 47 | /* Kernel includes. */ 48 | #include "freertos/FreeRTOS.h" 49 | #include "freertos/task.h" 50 | 51 | /* Demo Specific configs. */ 52 | #include "demo_config.h" 53 | 54 | /* MQTT library includes. */ 55 | #include "core_mqtt.h" 56 | 57 | /* Exponential backoff retry include. */ 58 | #include "exponential_backoff.h" 59 | 60 | /* Transport interface implementation include header for TLS. */ 61 | #include "tls_freertos.h" 62 | 63 | /*-----------------------------------------------------------*/ 64 | 65 | /* Compile time error for undefined configs. */ 66 | #ifndef democonfigMQTT_BROKER_ENDPOINT 67 | #error "Define the config democonfigMQTT_BROKER_ENDPOINT by following the instructions in file demo_config.h." 68 | #endif 69 | #ifndef democonfigROOT_CA_PEM 70 | #if CONFIG_BROKER_CERTIFICATE_OVERRIDDEN == 1 71 | static const uint8_t root_cert_auth_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----"; 72 | #else 73 | extern const uint8_t root_cert_auth_pem_start[] asm("_binary_root_cert_auth_pem_start"); 74 | #endif 75 | extern const uint8_t root_cert_auth_pem_end[] asm("_binary_root_cert_auth_pem_end"); 76 | #endif 77 | 78 | /* If no username is defined, then a client certificate/key is required. */ 79 | #ifndef democonfigCLIENT_USERNAME 80 | 81 | /* 82 | *!!! Please note democonfigCLIENT_PRIVATE_KEY_PEM in used for 83 | *!!! convenience of demonstration only. Production devices should 84 | *!!! store keys securely, such as within a secure element. 85 | */ 86 | 87 | #ifndef democonfigCLIENT_CERTIFICATE_PEM 88 | extern const uint8_t client_cert_pem_start[] asm("_binary_client_crt_start"); 89 | extern const uint8_t client_cert_pem_end[] asm("_binary_client_crt_end"); 90 | #endif 91 | #ifndef democonfigCLIENT_PRIVATE_KEY_PEM 92 | extern const uint8_t client_key_pem_start[] asm("_binary_client_key_start"); 93 | extern const uint8_t client_key_pem_end[] asm("_binary_client_key_end"); 94 | #endif 95 | #else 96 | 97 | /* If a username is defined, a client password also would need to be defined for 98 | * client authentication. */ 99 | #ifndef democonfigCLIENT_PASSWORD 100 | #error "Please define client password(democonfigCLIENT_PASSWORD) in demo_config.h for client authentication based on username/password." 101 | #endif 102 | 103 | /* AWS IoT MQTT broker port needs to be 443 for client authentication based on 104 | * username/password. */ 105 | #if defined( democonfigUSE_AWS_IOT_CORE_BROKER ) && democonfigMQTT_BROKER_PORT != 443 106 | #error "Broker port(democonfigMQTT_BROKER_PORT) should be defined as 443 in demo_config.h for client authentication based on username/password in AWS IoT Core." 107 | #endif 108 | #endif /* ifndef democonfigCLIENT_USERNAME */ 109 | 110 | /*-----------------------------------------------------------*/ 111 | 112 | /* Default values for configs. */ 113 | #ifndef democonfigCLIENT_IDENTIFIER 114 | 115 | /** 116 | * @brief The MQTT client identifier used in this example. Each client identifier 117 | * must be unique so edit as required to ensure no two clients connecting to the 118 | * same broker use the same client identifier. 119 | * 120 | * @note Appending __TIME__ to the client id string will help to create a unique 121 | * client id every time an application binary is built. Only a single instance of 122 | * this application's compiled binary may be used at a time, since the client ID 123 | * will always be the same. 124 | */ 125 | #define democonfigCLIENT_IDENTIFIER "testClient"__TIME__ 126 | #endif 127 | 128 | #ifndef democonfigMQTT_BROKER_PORT 129 | 130 | /** 131 | * @brief The port to use for the demo. 132 | */ 133 | #define democonfigMQTT_BROKER_PORT ( 8883 ) 134 | #endif 135 | 136 | /*-----------------------------------------------------------*/ 137 | 138 | /** 139 | * @brief Timeout for receiving CONNACK packet in milliseconds. 140 | */ 141 | #define mqttexampleCONNACK_RECV_TIMEOUT_MS ( 1000U ) 142 | 143 | /** 144 | * @brief The topic to subscribe and publish to in the example. 145 | * 146 | * The topic name starts with the client identifier to ensure that each demo 147 | * interacts with a unique topic name. 148 | */ 149 | #define mqttexampleTOPIC democonfigCLIENT_IDENTIFIER "/example/topic" 150 | 151 | /** 152 | * @brief The number of topic filters to subscribe. 153 | */ 154 | #define mqttexampleTOPIC_COUNT ( 1 ) 155 | 156 | /** 157 | * @brief The MQTT message published in this example. 158 | */ 159 | #define mqttexampleMESSAGE "Hello World!" 160 | 161 | /** 162 | * @brief Time in ticks to wait between each cycle of the demo implemented 163 | * by prvMQTTDemoTask(). 164 | */ 165 | #define mqttexampleDELAY_BETWEEN_DEMO_ITERATIONS_TICKS ( pdMS_TO_TICKS( 5000U ) ) 166 | 167 | /** 168 | * @brief Timeout for MQTT_ProcessLoop in milliseconds. 169 | */ 170 | #define mqttexamplePROCESS_LOOP_TIMEOUT_MS ( 500U ) 171 | 172 | /** 173 | * @brief Keep alive time reported to the broker while establishing 174 | * an MQTT connection. 175 | * 176 | * It is the responsibility of the Client to ensure that the interval between 177 | * Control Packets being sent does not exceed the this Keep Alive value. In the 178 | * absence of sending any other Control Packets, the Client MUST send a 179 | * PINGREQ Packet. 180 | */ 181 | #define mqttexampleKEEP_ALIVE_TIMEOUT_SECONDS ( 60U ) 182 | 183 | /** 184 | * @brief Delay (in ticks) between consecutive cycles of MQTT publish operations in a 185 | * demo iteration. 186 | * 187 | * Note that the process loop also has a timeout, so the total time between 188 | * publishes is the sum of the two delays. 189 | */ 190 | #define mqttexampleDELAY_BETWEEN_PUBLISHES_TICKS ( pdMS_TO_TICKS( 2000U ) ) 191 | 192 | /** 193 | * @brief Transport timeout in milliseconds for transport send and receive. 194 | */ 195 | #define mqttexampleTRANSPORT_SEND_RECV_TIMEOUT_MS ( 20000U ) 196 | 197 | /** 198 | * @brief ALPN (Application-Layer Protocol Negotiation) protocol name for AWS IoT MQTT. 199 | * 200 | * This will be used if democonfigMQTT_BROKER_PORT is configured as 443 for the AWS IoT MQTT broker. 201 | * Please see more details about the ALPN protocol for AWS IoT MQTT endpoint 202 | * in the link below. 203 | * https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/ 204 | */ 205 | #define AWS_IOT_MQTT_ALPN "\x0ex-amzn-mqtt-ca" 206 | 207 | /** 208 | * @brief This is the ALPN (Application-Layer Protocol Negotiation) string 209 | * required by AWS IoT for password-based authentication using TCP port 443. 210 | */ 211 | #define AWS_IOT_CUSTOM_AUTH_ALPN "\x04mqtt" 212 | 213 | /** 214 | * Provide default values for undefined configuration settings. 215 | */ 216 | #ifndef democonfigOS_NAME 217 | #define democonfigOS_NAME "FreeRTOS" 218 | #endif 219 | 220 | #ifndef democonfigOS_VERSION 221 | #define democonfigOS_VERSION tskKERNEL_VERSION_NUMBER 222 | #endif 223 | 224 | #ifndef democonfigHARDWARE_PLATFORM_NAME 225 | #define democonfigHARDWARE_PLATFORM_NAME "WinSim" 226 | #endif 227 | 228 | #ifndef democonfigMQTT_LIB 229 | #define democonfigMQTT_LIB "core-mqtt@1.0.0" 230 | #endif 231 | 232 | /** 233 | * @brief The MQTT metrics string expected by AWS IoT. 234 | */ 235 | #define AWS_IOT_METRICS_STRING \ 236 | "?SDK=" democonfigOS_NAME "&Version=" democonfigOS_VERSION \ 237 | "&Platform=" democonfigHARDWARE_PLATFORM_NAME "&MQTTLib=" democonfigMQTT_LIB 238 | 239 | /** 240 | * @brief The length of the MQTT metrics string expected by AWS IoT. 241 | */ 242 | #define AWS_IOT_METRICS_STRING_LENGTH ( ( uint16_t ) ( sizeof( AWS_IOT_METRICS_STRING ) - 1 ) ) 243 | 244 | #ifdef democonfigCLIENT_USERNAME 245 | 246 | /** 247 | * @brief Append the username with the metrics string if #democonfigCLIENT_USERNAME is defined. 248 | * 249 | * This is to support both metrics reporting and username/password based client 250 | * authentication by AWS IoT. 251 | */ 252 | #define CLIENT_USERNAME_WITH_METRICS democonfigCLIENT_USERNAME AWS_IOT_METRICS_STRING 253 | #endif 254 | 255 | /** 256 | * @brief Milliseconds per second. 257 | */ 258 | #define MILLISECONDS_PER_SECOND ( 1000U ) 259 | 260 | /** 261 | * @brief Milliseconds per FreeRTOS tick. 262 | */ 263 | #define MILLISECONDS_PER_TICK ( MILLISECONDS_PER_SECOND / configTICK_RATE_HZ ) 264 | 265 | /*-----------------------------------------------------------*/ 266 | 267 | /** 268 | * @brief The task used to demonstrate the MQTT API. 269 | * 270 | * @param[in] pvParameters Parameters as passed at the time of task creation. Not 271 | * used in this example. 272 | */ 273 | static void prvMQTTDemoTask( void * pvParameters ); 274 | 275 | /** 276 | * @brief Connect to MQTT broker with reconnection retries. 277 | * 278 | * If connection fails, retry is attempted after a timeout. 279 | * Timeout value will exponentially increase until maximum 280 | * timeout value is reached or the number of attempts are exhausted. 281 | * 282 | * @param[out] pxNetworkContext The parameter to return the created network context. 283 | * 284 | * @return The status of the final connection attempt. 285 | */ 286 | static TlsTransportStatus_t prvConnectToServerWithBackoffRetries( NetworkCredentials_t * pxNetworkCredentials, 287 | NetworkContext_t * pNetworkContext ); 288 | 289 | /** 290 | * @brief Sends an MQTT Connect packet over the already connected TLS over TCP connection. 291 | * 292 | * @param[in, out] pxMQTTContext MQTT context pointer. 293 | * @param[in] xNetworkContext Network context. 294 | */ 295 | static void prvCreateMQTTConnectionWithBroker( MQTTContext_t * pxMQTTContext, 296 | NetworkContext_t * pxNetworkContext ); 297 | 298 | /** 299 | * @brief Function to update variable #xTopicFilterContext with status 300 | * information from Subscribe ACK. Called by the event callback after processing 301 | * an incoming SUBACK packet. 302 | * 303 | * @param[in] Server response to the subscription request. 304 | */ 305 | static void prvUpdateSubAckStatus( MQTTPacketInfo_t * pxPacketInfo ); 306 | 307 | /** 308 | * @brief Subscribes to the topic as specified in mqttexampleTOPIC at the top of 309 | * this file. In the case of a Subscribe ACK failure, then subscription is 310 | * retried using an exponential backoff strategy with jitter. 311 | * 312 | * @param[in] pxMQTTContext MQTT context pointer. 313 | */ 314 | static void prvMQTTSubscribeWithBackoffRetries( MQTTContext_t * pxMQTTContext ); 315 | 316 | /** 317 | * @brief Publishes a message mqttexampleMESSAGE on mqttexampleTOPIC topic. 318 | * 319 | * @param[in] pxMQTTContext MQTT context pointer. 320 | */ 321 | static void prvMQTTPublishToTopic( MQTTContext_t * pxMQTTContext ); 322 | 323 | /** 324 | * @brief Unsubscribes from the previously subscribed topic as specified 325 | * in mqttexampleTOPIC. 326 | * 327 | * @param[in] pxMQTTContext MQTT context pointer. 328 | */ 329 | static void prvMQTTUnsubscribeFromTopic( MQTTContext_t * pxMQTTContext ); 330 | 331 | /** 332 | * @brief The timer query function provided to the MQTT context. 333 | * 334 | * @return Time in milliseconds. 335 | */ 336 | static uint32_t prvGetTimeMs( void ); 337 | 338 | /** 339 | * @brief Process a response or ack to an MQTT request (PING, PUBLISH, 340 | * SUBSCRIBE or UNSUBSCRIBE). This function processes PINGRESP, PUBACK, 341 | * SUBACK, and UNSUBACK. 342 | * 343 | * @param[in] pxIncomingPacket is a pointer to structure containing deserialized 344 | * MQTT response. 345 | * @param[in] usPacketId is the packet identifier from the ack received. 346 | */ 347 | static void prvMQTTProcessResponse( MQTTPacketInfo_t * pxIncomingPacket, 348 | uint16_t usPacketId ); 349 | 350 | /** 351 | * @brief Process incoming Publish message. 352 | * 353 | * @param[in] pxPublishInfo is a pointer to structure containing deserialized 354 | * Publish message. 355 | */ 356 | static void prvMQTTProcessIncomingPublish( MQTTPublishInfo_t * pxPublishInfo ); 357 | 358 | /** 359 | * @brief The application callback function for getting the incoming publishes, 360 | * incoming acks, and ping responses reported from the MQTT library. 361 | * 362 | * @param[in] pxMQTTContext MQTT context pointer. 363 | * @param[in] pxPacketInfo Packet Info pointer for the incoming packet. 364 | * @param[in] pxDeserializedInfo Deserialized information from the incoming packet. 365 | */ 366 | static void prvEventCallback( MQTTContext_t * pxMQTTContext, 367 | MQTTPacketInfo_t * pxPacketInfo, 368 | MQTTDeserializedInfo_t * pxDeserializedInfo ); 369 | 370 | /*-----------------------------------------------------------*/ 371 | 372 | /** 373 | * @brief Static buffer used to hold MQTT messages being sent and received. 374 | */ 375 | static uint8_t ucSharedBuffer[ democonfigNETWORK_BUFFER_SIZE ]; 376 | 377 | /** 378 | * @brief Global entry time into the application to use as a reference timestamp 379 | * in the #prvGetTimeMs function. #prvGetTimeMs will always return the difference 380 | * between the current time and the global entry time. This will reduce the chances 381 | * of overflow for the 32 bit unsigned integer used for holding the timestamp. 382 | */ 383 | static uint32_t ulGlobalEntryTimeMs; 384 | 385 | /** 386 | * @brief Packet Identifier generated when Publish request was sent to the broker; 387 | * it is used to match received Publish ACK to the transmitted Publish packet. 388 | */ 389 | static uint16_t usPublishPacketIdentifier; 390 | 391 | /** 392 | * @brief Packet Identifier generated when Subscribe request was sent to the broker; 393 | * it is used to match received Subscribe ACK to the transmitted Subscribe packet. 394 | */ 395 | static uint16_t usSubscribePacketIdentifier; 396 | 397 | /** 398 | * @brief Packet Identifier generated when Unsubscribe request was sent to the broker; 399 | * it is used to match received Unsubscribe response to the transmitted Unsubscribe 400 | * request. 401 | */ 402 | static uint16_t usUnsubscribePacketIdentifier; 403 | 404 | /** 405 | * @brief A pair containing a topic filter and its SUBACK status. 406 | */ 407 | typedef struct topicFilterContext 408 | { 409 | const char * pcTopicFilter; 410 | MQTTSubAckStatus_t xSubAckStatus; 411 | } topicFilterContext_t; 412 | 413 | /** 414 | * @brief An array containing the context of a SUBACK; the SUBACK status 415 | * of a filter is updated when the event callback processes a SUBACK. 416 | */ 417 | static topicFilterContext_t xTopicFilterContext[ mqttexampleTOPIC_COUNT ] = 418 | { 419 | { mqttexampleTOPIC, MQTTSubAckFailure } 420 | }; 421 | 422 | 423 | /** @brief Static buffer used to hold MQTT messages being sent and received. */ 424 | static MQTTFixedBuffer_t xBuffer = 425 | { 426 | ucSharedBuffer, 427 | democonfigNETWORK_BUFFER_SIZE 428 | }; 429 | 430 | /*-----------------------------------------------------------*/ 431 | 432 | /* 433 | * @brief Create the task that demonstrates the MQTT API Demo over a 434 | * mutually authenticated network connection with MQTT broker. 435 | */ 436 | void vStartSimpleMQTTDemo( void ) 437 | { 438 | /* This example uses a single application task, which in turn is used to 439 | * connect, subscribe, publish, unsubscribe and disconnect from the MQTT 440 | * broker. */ 441 | xTaskCreate( prvMQTTDemoTask, /* Function that implements the task. */ 442 | "DemoTask", /* Text name for the task - only used for debugging. */ 443 | democonfigDEMO_STACKSIZE, /* Size of stack (in words, not bytes) to allocate for the task. */ 444 | NULL, /* Task parameter - not used in this case. */ 445 | tskIDLE_PRIORITY, /* Task priority, must be between 0 and configMAX_PRIORITIES - 1. */ 446 | NULL ); /* Used to pass out a handle to the created task - not used in this case. */ 447 | } 448 | /*-----------------------------------------------------------*/ 449 | 450 | /* 451 | * @brief The Example shown below uses MQTT APIs to create MQTT messages and 452 | * send them over the mutually authenticated network connection established with the 453 | * MQTT broker. This example is single threaded and uses statically allocated 454 | * memory. It uses QoS1 for sending to and receiving messages from the broker. 455 | * 456 | * This MQTT client subscribes to the topic as specified in mqttexampleTOPIC at the 457 | * top of this file by sending a subscribe packet and then waiting for a subscribe 458 | * acknowledgment (SUBACK).This client will then publish to the same topic it 459 | * subscribed to, so it will expect all the messages it sends to the broker to be 460 | * sent back to it from the broker. 461 | */ 462 | static void prvMQTTDemoTask( void * pvParameters ) 463 | { 464 | uint32_t ulPublishCount = 0U, ulTopicCount = 0U; 465 | const uint32_t ulMaxPublishCount = 5UL; 466 | NetworkContext_t xNetworkContext = { 0 }; 467 | NetworkCredentials_t xNetworkCredentials = { 0 }; 468 | MQTTContext_t xMQTTContext = { 0 }; 469 | MQTTStatus_t xMQTTStatus; 470 | TlsTransportStatus_t xNetworkStatus; 471 | 472 | /* Remove compiler warnings about unused parameters. */ 473 | ( void ) pvParameters; 474 | 475 | /* Set the entry time of the demo application. This entry time will be used 476 | * to calculate relative time elapsed in the execution of the demo application, 477 | * by the timer utility function that is provided to the MQTT library. 478 | */ 479 | ulGlobalEntryTimeMs = prvGetTimeMs(); 480 | 481 | for( ; ; ) 482 | { 483 | /****************************** Connect. ******************************/ 484 | 485 | /* Attempt to establish TLS session with MQTT broker. If connection fails, 486 | * retry after a timeout. Timeout value will be exponentially increased 487 | * until the maximum number of attempts are reached or the maximum timeout 488 | * value is reached. The function returns a failure status if the TCP 489 | * connection cannot be established to the broker after the configured 490 | * number of attempts. */ 491 | xNetworkStatus = prvConnectToServerWithBackoffRetries( &xNetworkCredentials, 492 | &xNetworkContext ); 493 | configASSERT( xNetworkStatus == TLS_TRANSPORT_SUCCESS ); 494 | 495 | /* Sends an MQTT Connect packet over the already established TLS connection, 496 | * and waits for connection acknowledgment (CONNACK) packet. */ 497 | LogInfo( ( "Creating an MQTT connection to %s.\r\n", democonfigMQTT_BROKER_ENDPOINT ) ); 498 | prvCreateMQTTConnectionWithBroker( &xMQTTContext, &xNetworkContext ); 499 | 500 | /**************************** Subscribe. ******************************/ 501 | 502 | /* If server rejected the subscription request, attempt to resubscribe to 503 | * topic. Attempts are made according to the exponential backoff retry 504 | * strategy implemented in retryUtils. */ 505 | prvMQTTSubscribeWithBackoffRetries( &xMQTTContext ); 506 | 507 | /****************** Publish and Keep Alive Loop. **********************/ 508 | /* Publish messages with QoS1, send and process Keep alive messages. */ 509 | for( ulPublishCount = 0; ulPublishCount < ulMaxPublishCount; ulPublishCount++ ) 510 | { 511 | LogInfo( ( "Publish to the MQTT topic %s.\r\n", mqttexampleTOPIC ) ); 512 | prvMQTTPublishToTopic( &xMQTTContext ); 513 | 514 | /* Process incoming publish echo, since application subscribed to the 515 | * same topic, the broker will send publish message back to the 516 | * application. */ 517 | LogInfo( ( "Attempt to receive publish message from broker.\r\n" ) ); 518 | xMQTTStatus = MQTT_ProcessLoop( &xMQTTContext, mqttexamplePROCESS_LOOP_TIMEOUT_MS ); 519 | configASSERT( xMQTTStatus == MQTTSuccess ); 520 | 521 | /* Leave Connection Idle for some time. */ 522 | LogInfo( ( "Keeping Connection Idle...\r\n\r\n" ) ); 523 | vTaskDelay( mqttexampleDELAY_BETWEEN_PUBLISHES_TICKS ); 524 | } 525 | 526 | /******************** Unsubscribe from the topic. *********************/ 527 | LogInfo( ( "Unsubscribe from the MQTT topic %s.\r\n", mqttexampleTOPIC ) ); 528 | prvMQTTUnsubscribeFromTopic( &xMQTTContext ); 529 | 530 | /* Process incoming UNSUBACK packet from the broker. */ 531 | xMQTTStatus = MQTT_ProcessLoop( &xMQTTContext, mqttexamplePROCESS_LOOP_TIMEOUT_MS ); 532 | configASSERT( xMQTTStatus == MQTTSuccess ); 533 | 534 | /**************************** Disconnect. *****************************/ 535 | 536 | /* Send an MQTT Disconnect packet over the already connected TLS over 537 | * TCP connection. There is no corresponding response for the disconnect 538 | * packet. After sending disconnect, client must close the network 539 | * connection. */ 540 | LogInfo( ( "Disconnecting the MQTT connection with %s.\r\n", 541 | democonfigMQTT_BROKER_ENDPOINT ) ); 542 | xMQTTStatus = MQTT_Disconnect( &xMQTTContext ); 543 | configASSERT( xMQTTStatus == MQTTSuccess ); 544 | 545 | /* Close the network connection. */ 546 | TLS_FreeRTOS_Disconnect( &xNetworkContext ); 547 | 548 | /* Reset SUBACK status for each topic filter after completion of 549 | * subscription request cycle. */ 550 | for( ulTopicCount = 0; ulTopicCount < mqttexampleTOPIC_COUNT; ulTopicCount++ ) 551 | { 552 | xTopicFilterContext[ ulTopicCount ].xSubAckStatus = MQTTSubAckFailure; 553 | } 554 | 555 | /* Wait for some time between two iterations to ensure that we do not 556 | * bombard the broker. */ 557 | LogInfo( ( "prvMQTTDemoTask() completed an iteration successfully. " 558 | "Total free heap is %u.\r\n", 559 | xPortGetFreeHeapSize() ) ); 560 | LogInfo( ( "Demo completed successfully.\r\n" ) ); 561 | LogInfo( ( "Short delay before starting the next iteration.... \r\n\r\n" ) ); 562 | vTaskDelay( mqttexampleDELAY_BETWEEN_DEMO_ITERATIONS_TICKS ); 563 | } 564 | } 565 | /*-----------------------------------------------------------*/ 566 | 567 | static TlsTransportStatus_t prvConnectToServerWithBackoffRetries( NetworkCredentials_t * pxNetworkCredentials, 568 | NetworkContext_t * pxNetworkContext ) 569 | { 570 | TlsTransportStatus_t xNetworkStatus; 571 | RetryUtilsStatus_t xRetryUtilsStatus = RetryUtilsSuccess; 572 | RetryUtilsParams_t xReconnectParams; 573 | 574 | #ifdef democonfigUSE_AWS_IOT_CORE_BROKER 575 | 576 | /* ALPN protocols must be a NULL-terminated list of strings. Therefore, 577 | * the first entry will contain the actual ALPN protocol string while the 578 | * second entry must remain NULL. */ 579 | char * pcAlpnProtocols[] = { NULL, NULL }; 580 | 581 | /* The ALPN string changes depending on whether username/password authentication is used. */ 582 | #ifdef democonfigCLIENT_USERNAME 583 | pcAlpnProtocols[ 0 ] = AWS_IOT_CUSTOM_AUTH_ALPN; 584 | #else 585 | pcAlpnProtocols[ 0 ] = AWS_IOT_MQTT_ALPN; 586 | #endif 587 | pxNetworkCredentials->pAlpnProtos = pcAlpnProtocols; 588 | #endif /* ifdef democonfigUSE_AWS_IOT_CORE_BROKER */ 589 | 590 | pxNetworkCredentials->disableSni = democonfigDISABLE_SNI; 591 | /* Set the credentials for establishing a TLS connection. */ 592 | pxNetworkCredentials->pRootCa = ( const unsigned char * ) root_cert_auth_pem_start; 593 | pxNetworkCredentials->rootCaSize = root_cert_auth_pem_end - root_cert_auth_pem_start; 594 | pxNetworkCredentials->pClientCert = ( const unsigned char * ) client_cert_pem_start; 595 | pxNetworkCredentials->clientCertSize = client_cert_pem_end - client_cert_pem_start; 596 | pxNetworkCredentials->pPrivateKey = ( const unsigned char * ) client_key_pem_start; 597 | pxNetworkCredentials->privateKeySize = client_key_pem_end - client_key_pem_start; 598 | /* Initialize reconnect attempts and interval. */ 599 | RetryUtils_ParamsReset( &xReconnectParams ); 600 | xReconnectParams.maxRetryAttempts = MAX_RETRY_ATTEMPTS; 601 | 602 | /* Attempt to connect to MQTT broker. If connection fails, retry after 603 | * a timeout. Timeout value will exponentially increase till maximum 604 | * attempts are reached. 605 | */ 606 | do 607 | { 608 | /* Establish a TLS session with the MQTT broker. This example connects to 609 | * the MQTT broker as specified in democonfigMQTT_BROKER_ENDPOINT and 610 | * democonfigMQTT_BROKER_PORT at the top of this file. */ 611 | LogInfo( ( "Creating a TLS connection to %s:%u.\r\n", 612 | democonfigMQTT_BROKER_ENDPOINT, 613 | democonfigMQTT_BROKER_PORT ) ); 614 | /* Attempt to create a mutually authenticated TLS connection. */ 615 | xNetworkStatus = TLS_FreeRTOS_Connect( pxNetworkContext, 616 | democonfigMQTT_BROKER_ENDPOINT, 617 | democonfigMQTT_BROKER_PORT, 618 | pxNetworkCredentials, 619 | mqttexampleTRANSPORT_SEND_RECV_TIMEOUT_MS, 620 | mqttexampleTRANSPORT_SEND_RECV_TIMEOUT_MS ); 621 | 622 | if( xNetworkStatus != TLS_TRANSPORT_SUCCESS ) 623 | { 624 | LogWarn( ( "Connection to the broker failed. Retrying connection with backoff and jitter." ) ); 625 | xRetryUtilsStatus = RetryUtils_BackoffAndSleep( &xReconnectParams ); 626 | } 627 | 628 | if( xRetryUtilsStatus == RetryUtilsRetriesExhausted ) 629 | { 630 | LogError( ( "Connection to the broker failed, all attempts exhausted." ) ); 631 | xNetworkStatus = TLS_TRANSPORT_CONNECT_FAILURE; 632 | } 633 | } while( ( xNetworkStatus != TLS_TRANSPORT_SUCCESS ) && ( xRetryUtilsStatus == RetryUtilsSuccess ) ); 634 | 635 | return xNetworkStatus; 636 | } 637 | /*-----------------------------------------------------------*/ 638 | 639 | static void prvCreateMQTTConnectionWithBroker( MQTTContext_t * pxMQTTContext, 640 | NetworkContext_t * pxNetworkContext ) 641 | { 642 | MQTTStatus_t xResult; 643 | MQTTConnectInfo_t xConnectInfo; 644 | bool xSessionPresent; 645 | TransportInterface_t xTransport; 646 | 647 | /*** 648 | * For readability, error handling in this function is restricted to the use of 649 | * asserts(). 650 | ***/ 651 | 652 | /* Fill in Transport Interface send and receive function pointers. */ 653 | xTransport.pNetworkContext = pxNetworkContext; 654 | xTransport.send = TLS_FreeRTOS_send; 655 | xTransport.recv = TLS_FreeRTOS_recv; 656 | 657 | /* Initialize MQTT library. */ 658 | xResult = MQTT_Init( pxMQTTContext, &xTransport, prvGetTimeMs, prvEventCallback, &xBuffer ); 659 | configASSERT( xResult == MQTTSuccess ); 660 | 661 | /* Some fields are not used in this demo so start with everything at 0. */ 662 | ( void ) memset( ( void * ) &xConnectInfo, 0x00, sizeof( xConnectInfo ) ); 663 | 664 | /* Start with a clean session i.e. direct the MQTT broker to discard any 665 | * previous session data. Also, establishing a connection with clean session 666 | * will ensure that the broker does not store any data when this client 667 | * gets disconnected. */ 668 | xConnectInfo.cleanSession = true; 669 | 670 | /* The client identifier is used to uniquely identify this MQTT client to 671 | * the MQTT broker. In a production device the identifier can be something 672 | * unique, such as a device serial number. */ 673 | xConnectInfo.pClientIdentifier = democonfigCLIENT_IDENTIFIER; 674 | xConnectInfo.clientIdentifierLength = ( uint16_t ) strlen( democonfigCLIENT_IDENTIFIER ); 675 | 676 | /* Set MQTT keep-alive period. If the application does not send packets at an interval less than 677 | * the keep-alive period, the MQTT library will send PINGREQ packets. */ 678 | xConnectInfo.keepAliveSeconds = mqttexampleKEEP_ALIVE_TIMEOUT_SECONDS; 679 | 680 | /* Append metrics when connecting to the AWS IoT Core broker. */ 681 | #ifdef democonfigUSE_AWS_IOT_CORE_BROKER 682 | #ifdef democonfigCLIENT_USERNAME 683 | xConnectInfo.pUserName = CLIENT_USERNAME_WITH_METRICS; 684 | xConnectInfo.userNameLength = ( uint16_t ) strlen( CLIENT_USERNAME_WITH_METRICS ); 685 | xConnectInfo.pPassword = democonfigCLIENT_PASSWORD; 686 | xConnectInfo.passwordLength = ( uint16_t ) strlen( democonfigCLIENT_PASSWORD ); 687 | #else 688 | xConnectInfo.pUserName = AWS_IOT_METRICS_STRING; 689 | xConnectInfo.userNameLength = AWS_IOT_METRICS_STRING_LENGTH; 690 | /* Password for authentication is not used. */ 691 | xConnectInfo.pPassword = NULL; 692 | xConnectInfo.passwordLength = 0U; 693 | #endif 694 | #else /* ifdef democonfigUSE_AWS_IOT_CORE_BROKER */ 695 | #ifdef democonfigCLIENT_USERNAME 696 | xConnectInfo.pUserName = democonfigCLIENT_USERNAME; 697 | xConnectInfo.userNameLength = ( uint16_t ) strlen( democonfigCLIENT_USERNAME ); 698 | xConnectInfo.pPassword = democonfigCLIENT_PASSWORD; 699 | xConnectInfo.passwordLength = ( uint16_t ) strlen( democonfigCLIENT_PASSWORD ); 700 | #endif /* ifdef democonfigCLIENT_USERNAME */ 701 | #endif /* ifdef democonfigUSE_AWS_IOT_CORE_BROKER */ 702 | 703 | /* Send MQTT CONNECT packet to broker. LWT is not used in this demo, so it 704 | * is passed as NULL. */ 705 | xResult = MQTT_Connect( pxMQTTContext, 706 | &xConnectInfo, 707 | NULL, 708 | mqttexampleCONNACK_RECV_TIMEOUT_MS, 709 | &xSessionPresent ); 710 | configASSERT( xResult == MQTTSuccess ); 711 | 712 | /* Successfully established and MQTT connection with the broker. */ 713 | LogInfo( ( "An MQTT connection is established with %s.", democonfigMQTT_BROKER_ENDPOINT ) ); 714 | } 715 | /*-----------------------------------------------------------*/ 716 | 717 | static void prvUpdateSubAckStatus( MQTTPacketInfo_t * pxPacketInfo ) 718 | { 719 | MQTTStatus_t xResult = MQTTSuccess; 720 | uint8_t * pucPayload = NULL; 721 | size_t ulSize = 0; 722 | uint32_t ulTopicCount = 0U; 723 | 724 | xResult = MQTT_GetSubAckStatusCodes( pxPacketInfo, &pucPayload, &ulSize ); 725 | 726 | /* MQTT_GetSubAckStatusCodes always returns success if called with packet info 727 | * from the event callback and non-NULL parameters. */ 728 | configASSERT( xResult == MQTTSuccess ); 729 | 730 | for( ulTopicCount = 0; ulTopicCount < ulSize; ulTopicCount++ ) 731 | { 732 | xTopicFilterContext[ ulTopicCount ].xSubAckStatus = pucPayload[ ulTopicCount ]; 733 | } 734 | } 735 | /*-----------------------------------------------------------*/ 736 | 737 | static void prvMQTTSubscribeWithBackoffRetries( MQTTContext_t * pxMQTTContext ) 738 | { 739 | MQTTStatus_t xResult = MQTTSuccess; 740 | RetryUtilsStatus_t xRetryUtilsStatus = RetryUtilsSuccess; 741 | RetryUtilsParams_t xRetryParams; 742 | MQTTSubscribeInfo_t xMQTTSubscription[ mqttexampleTOPIC_COUNT ]; 743 | bool xFailedSubscribeToTopic = false; 744 | uint32_t ulTopicCount = 0U; 745 | 746 | /* Some fields not used by this demo so start with everything at 0. */ 747 | ( void ) memset( ( void * ) &xMQTTSubscription, 0x00, sizeof( xMQTTSubscription ) ); 748 | 749 | /* Get a unique packet id. */ 750 | usSubscribePacketIdentifier = MQTT_GetPacketId( pxMQTTContext ); 751 | 752 | /* Subscribe to the mqttexampleTOPIC topic filter. This example subscribes to 753 | * only one topic and uses QoS1. */ 754 | xMQTTSubscription[ 0 ].qos = MQTTQoS1; 755 | xMQTTSubscription[ 0 ].pTopicFilter = mqttexampleTOPIC; 756 | xMQTTSubscription[ 0 ].topicFilterLength = ( uint16_t ) strlen( mqttexampleTOPIC ); 757 | 758 | /* Initialize retry attempts and interval. */ 759 | RetryUtils_ParamsReset( &xRetryParams ); 760 | xRetryParams.maxRetryAttempts = MAX_RETRY_ATTEMPTS; 761 | 762 | do 763 | { 764 | /* The client is now connected to the broker. Subscribe to the topic 765 | * as specified in mqttexampleTOPIC at the top of this file by sending a 766 | * subscribe packet then waiting for a subscribe acknowledgment (SUBACK). 767 | * This client will then publish to the same topic it subscribed to, so it 768 | * will expect all the messages it sends to the broker to be sent back to it 769 | * from the broker. This demo uses QOS0 in Subscribe, therefore, the Publish 770 | * messages received from the broker will have QOS0. */ 771 | LogInfo( ( "Attempt to subscribe to the MQTT topic %s.\r\n", mqttexampleTOPIC ) ); 772 | xResult = MQTT_Subscribe( pxMQTTContext, 773 | xMQTTSubscription, 774 | sizeof( xMQTTSubscription ) / sizeof( MQTTSubscribeInfo_t ), 775 | usSubscribePacketIdentifier ); 776 | configASSERT( xResult == MQTTSuccess ); 777 | 778 | LogInfo( ( "SUBSCRIBE sent for topic %s to broker.\n\n", mqttexampleTOPIC ) ); 779 | 780 | /* Process incoming packet from the broker. After sending the subscribe, the 781 | * client may receive a publish before it receives a subscribe ack. Therefore, 782 | * call generic incoming packet processing function. Since this demo is 783 | * subscribing to the topic to which no one is publishing, probability of 784 | * receiving Publish message before subscribe ack is zero; but application 785 | * must be ready to receive any packet. This demo uses the generic packet 786 | * processing function everywhere to highlight this fact. */ 787 | xResult = MQTT_ProcessLoop( pxMQTTContext, mqttexamplePROCESS_LOOP_TIMEOUT_MS ); 788 | configASSERT( xResult == MQTTSuccess ); 789 | 790 | /* Reset flag before checking suback responses. */ 791 | xFailedSubscribeToTopic = false; 792 | 793 | /* Check if recent subscription request has been rejected. #xTopicFilterContext is updated 794 | * in the event callback to reflect the status of the SUBACK sent by the broker. It represents 795 | * either the QoS level granted by the server upon subscription, or acknowledgement of 796 | * server rejection of the subscription request. */ 797 | for( ulTopicCount = 0; ulTopicCount < mqttexampleTOPIC_COUNT; ulTopicCount++ ) 798 | { 799 | if( xTopicFilterContext[ ulTopicCount ].xSubAckStatus == MQTTSubAckFailure ) 800 | { 801 | LogWarn( ( "Server rejected subscription request. Attempting to re-subscribe to topic %s.", 802 | xTopicFilterContext[ ulTopicCount ].pcTopicFilter ) ); 803 | xFailedSubscribeToTopic = true; 804 | xRetryUtilsStatus = RetryUtils_BackoffAndSleep( &xRetryParams ); 805 | break; 806 | } 807 | } 808 | 809 | configASSERT( xRetryUtilsStatus != RetryUtilsRetriesExhausted ); 810 | } while( ( xFailedSubscribeToTopic == true ) && ( xRetryUtilsStatus == RetryUtilsSuccess ) ); 811 | } 812 | /*-----------------------------------------------------------*/ 813 | 814 | static void prvMQTTPublishToTopic( MQTTContext_t * pxMQTTContext ) 815 | { 816 | MQTTStatus_t xResult; 817 | MQTTPublishInfo_t xMQTTPublishInfo; 818 | 819 | /*** 820 | * For readability, error handling in this function is restricted to the use of 821 | * asserts(). 822 | ***/ 823 | 824 | /* Some fields are not used by this demo so start with everything at 0. */ 825 | ( void ) memset( ( void * ) &xMQTTPublishInfo, 0x00, sizeof( xMQTTPublishInfo ) ); 826 | 827 | /* This demo uses QoS1. */ 828 | xMQTTPublishInfo.qos = MQTTQoS1; 829 | xMQTTPublishInfo.retain = false; 830 | xMQTTPublishInfo.pTopicName = mqttexampleTOPIC; 831 | xMQTTPublishInfo.topicNameLength = ( uint16_t ) strlen( mqttexampleTOPIC ); 832 | xMQTTPublishInfo.pPayload = mqttexampleMESSAGE; 833 | xMQTTPublishInfo.payloadLength = strlen( mqttexampleMESSAGE ); 834 | 835 | /* Get a unique packet id. */ 836 | usPublishPacketIdentifier = MQTT_GetPacketId( pxMQTTContext ); 837 | 838 | /* Send PUBLISH packet. Packet ID is not used for a QoS1 publish. */ 839 | xResult = MQTT_Publish( pxMQTTContext, &xMQTTPublishInfo, usPublishPacketIdentifier ); 840 | 841 | configASSERT( xResult == MQTTSuccess ); 842 | } 843 | /*-----------------------------------------------------------*/ 844 | 845 | static void prvMQTTUnsubscribeFromTopic( MQTTContext_t * pxMQTTContext ) 846 | { 847 | MQTTStatus_t xResult; 848 | MQTTSubscribeInfo_t xMQTTSubscription[ mqttexampleTOPIC_COUNT ]; 849 | 850 | /* Some fields not used by this demo so start with everything at 0. */ 851 | ( void ) memset( ( void * ) &xMQTTSubscription, 0x00, sizeof( xMQTTSubscription ) ); 852 | 853 | /* Get a unique packet id. */ 854 | usSubscribePacketIdentifier = MQTT_GetPacketId( pxMQTTContext ); 855 | 856 | /* Subscribe to the mqttexampleTOPIC topic filter. This example subscribes to 857 | * only one topic and uses QoS1. */ 858 | xMQTTSubscription[ 0 ].qos = MQTTQoS1; 859 | xMQTTSubscription[ 0 ].pTopicFilter = mqttexampleTOPIC; 860 | xMQTTSubscription[ 0 ].topicFilterLength = ( uint16_t ) strlen( mqttexampleTOPIC ); 861 | 862 | /* Get next unique packet identifier. */ 863 | usUnsubscribePacketIdentifier = MQTT_GetPacketId( pxMQTTContext ); 864 | 865 | /* Send UNSUBSCRIBE packet. */ 866 | xResult = MQTT_Unsubscribe( pxMQTTContext, 867 | xMQTTSubscription, 868 | sizeof( xMQTTSubscription ) / sizeof( MQTTSubscribeInfo_t ), 869 | usUnsubscribePacketIdentifier ); 870 | 871 | configASSERT( xResult == MQTTSuccess ); 872 | } 873 | /*-----------------------------------------------------------*/ 874 | 875 | static void prvMQTTProcessResponse( MQTTPacketInfo_t * pxIncomingPacket, 876 | uint16_t usPacketId ) 877 | { 878 | uint32_t ulTopicCount = 0U; 879 | 880 | switch( pxIncomingPacket->type ) 881 | { 882 | case MQTT_PACKET_TYPE_PUBACK: 883 | LogInfo( ( "PUBACK received for packet Id %u.\r\n", usPacketId ) ); 884 | /* Make sure ACK packet identifier matches with Request packet identifier. */ 885 | configASSERT( usPublishPacketIdentifier == usPacketId ); 886 | break; 887 | 888 | case MQTT_PACKET_TYPE_SUBACK: 889 | 890 | /* A SUBACK from the broker, containing the server response to our subscription request, has been received. 891 | * It contains the status code indicating server approval/rejection for the subscription to the single topic 892 | * requested. The SUBACK will be parsed to obtain the status code, and this status code will be stored in global 893 | * variable #xTopicFilterContext. */ 894 | prvUpdateSubAckStatus( pxIncomingPacket ); 895 | 896 | for( ulTopicCount = 0; ulTopicCount < mqttexampleTOPIC_COUNT; ulTopicCount++ ) 897 | { 898 | if( xTopicFilterContext[ ulTopicCount ].xSubAckStatus != MQTTSubAckFailure ) 899 | { 900 | LogInfo( ( "Subscribed to the topic %s with maximum QoS %u.\r\n", 901 | xTopicFilterContext[ ulTopicCount ].pcTopicFilter, 902 | xTopicFilterContext[ ulTopicCount ].xSubAckStatus ) ); 903 | } 904 | } 905 | 906 | /* Make sure ACK packet identifier matches with Request packet identifier. */ 907 | configASSERT( usSubscribePacketIdentifier == usPacketId ); 908 | break; 909 | 910 | case MQTT_PACKET_TYPE_UNSUBACK: 911 | LogInfo( ( "Unsubscribed from the topic %s.\r\n", mqttexampleTOPIC ) ); 912 | /* Make sure ACK packet identifier matches with Request packet identifier. */ 913 | configASSERT( usUnsubscribePacketIdentifier == usPacketId ); 914 | break; 915 | 916 | case MQTT_PACKET_TYPE_PINGRESP: 917 | 918 | /* Nothing to be done from application as library handles 919 | * PINGRESP with the use of MQTT_ProcessLoop API function. */ 920 | LogWarn( ( "PINGRESP should not be handled by the application " 921 | "callback when using MQTT_ProcessLoop.\n" ) ); 922 | break; 923 | 924 | /* Any other packet type is invalid. */ 925 | default: 926 | LogWarn( ( "prvMQTTProcessResponse() called with unknown packet type:(%02X).\r\n", 927 | pxIncomingPacket->type ) ); 928 | } 929 | } 930 | 931 | /*-----------------------------------------------------------*/ 932 | 933 | static void prvMQTTProcessIncomingPublish( MQTTPublishInfo_t * pxPublishInfo ) 934 | { 935 | configASSERT( pxPublishInfo != NULL ); 936 | 937 | /* Process incoming Publish. */ 938 | LogInfo( ( "Incoming QoS : %d\n", pxPublishInfo->qos ) ); 939 | 940 | /* Verify the received publish is for the we have subscribed to. */ 941 | if( ( pxPublishInfo->topicNameLength == strlen( mqttexampleTOPIC ) ) && 942 | ( 0 == strncmp( mqttexampleTOPIC, pxPublishInfo->pTopicName, pxPublishInfo->topicNameLength ) ) ) 943 | { 944 | LogInfo( ( "\r\nIncoming Publish Topic Name: %.*s matches subscribed topic.\r\n" 945 | "Incoming Publish Message : %.*s\r\n", 946 | pxPublishInfo->topicNameLength, 947 | pxPublishInfo->pTopicName, 948 | pxPublishInfo->payloadLength, 949 | (char *)pxPublishInfo->pPayload ) ); 950 | } 951 | else 952 | { 953 | LogInfo( ( "Incoming Publish Topic Name: %.*s does not match subscribed topic.\r\n", 954 | pxPublishInfo->topicNameLength, 955 | pxPublishInfo->pTopicName ) ); 956 | } 957 | } 958 | 959 | /*-----------------------------------------------------------*/ 960 | 961 | static void prvEventCallback( MQTTContext_t * pxMQTTContext, 962 | MQTTPacketInfo_t * pxPacketInfo, 963 | MQTTDeserializedInfo_t * pxDeserializedInfo ) 964 | { 965 | /* The MQTT context is not used for this demo. */ 966 | ( void ) pxMQTTContext; 967 | 968 | if( ( pxPacketInfo->type & 0xF0U ) == MQTT_PACKET_TYPE_PUBLISH ) 969 | { 970 | prvMQTTProcessIncomingPublish( pxDeserializedInfo->pPublishInfo ); 971 | } 972 | else 973 | { 974 | prvMQTTProcessResponse( pxPacketInfo, pxDeserializedInfo->packetIdentifier ); 975 | } 976 | } 977 | 978 | /*-----------------------------------------------------------*/ 979 | 980 | static uint32_t prvGetTimeMs( void ) 981 | { 982 | TickType_t xTickCount = 0; 983 | uint32_t ulTimeMs = 0UL; 984 | 985 | /* Get the current tick count. */ 986 | xTickCount = xTaskGetTickCount(); 987 | 988 | /* Convert the ticks to milliseconds. */ 989 | ulTimeMs = ( uint32_t ) xTickCount * MILLISECONDS_PER_TICK; 990 | 991 | /* Reduce ulGlobalEntryTimeMs from obtained time so as to always return the 992 | * elapsed time in the application. */ 993 | ulTimeMs = ( uint32_t ) ( ulTimeMs - ulGlobalEntryTimeMs ); 994 | 995 | return ulTimeMs; 996 | } 997 | 998 | /*-----------------------------------------------------------*/ 999 | -------------------------------------------------------------------------------- /examples/tls_mutual_auth/main/utilities/demo_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FreeRTOS Kernel V10.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | * this software and associated documentation files (the "Software"), to deal in 7 | * the Software without restriction, including without limitation the rights to 8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | * the Software, and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | * 22 | * http://www.FreeRTOS.org 23 | * http://aws.amazon.com/freertos 24 | * 25 | */ 26 | 27 | #ifndef DEMO_CONFIG_H 28 | #define DEMO_CONFIG_H 29 | 30 | /* FreeRTOS config include. */ 31 | #include "freertos/FreeRTOSConfig.h" 32 | 33 | /**************************************************/ 34 | /******* DO NOT CHANGE the following order ********/ 35 | /**************************************************/ 36 | 37 | /* Include logging header files and define logging macros in the following order: 38 | * 1. Include the header file "logging_levels.h". 39 | * 2. Define the LIBRARY_LOG_NAME and LIBRARY_LOG_LEVEL macros depending on 40 | * the logging configuration for DEMO. 41 | * 3. Include the header file "logging_stack.h", if logging is enabled for DEMO. 42 | */ 43 | 44 | #include "logging_levels.h" 45 | 46 | /* Logging configuration for the Demo. */ 47 | #ifndef LIBRARY_LOG_NAME 48 | #define LIBRARY_LOG_NAME "MQTTDemo" 49 | #endif 50 | 51 | #ifndef LIBRARY_LOG_LEVEL 52 | #define LIBRARY_LOG_LEVEL LOG_INFO 53 | #endif 54 | 55 | /* Map the SdkLog macro to the logging function to enable logging 56 | * on Windows simulator. */ 57 | #define SdkLog( message ) printf message 58 | 59 | #include "logging_stack.h" 60 | #include "platform.h" 61 | 62 | /************ End of logging configuration ****************/ 63 | 64 | /** 65 | * @brief The MQTT client identifier used in this example. Each client identifier 66 | * must be unique; so edit as required to ensure that no two clients connecting to 67 | * the same broker use the same client identifier. 68 | * 69 | *!!! Please note a #defined constant is used for convenience of demonstration 70 | *!!! only. Production devices can use something unique to the device that can 71 | *!!! be read by software, such as a production serial number, instead of a 72 | *!!! hard coded constant. 73 | * 74 | * #define democonfigCLIENT_IDENTIFIER "insert here." 75 | */ 76 | #define democonfigCLIENT_IDENTIFIER CONFIG_MQTT_CLIENT_IDENTIFIER 77 | 78 | /** 79 | * @brief Endpoint of the MQTT broker to connect to. 80 | * 81 | * This demo application can be run with any MQTT broker, that supports server 82 | * authentication. 83 | * 84 | * @note If you would like to setup an MQTT broker for running this demo, 85 | * please see `mqtt_broker_setup.txt`. 86 | * 87 | * #define democonfigMQTT_BROKER_ENDPOINT "...insert here..." 88 | */ 89 | #define democonfigMQTT_BROKER_ENDPOINT CONFIG_MQTT_BROKER_ENDPOINT 90 | 91 | /** 92 | * @brief The port to use for the demo. 93 | * 94 | * In general, port 8883 is for secured MQTT connections. 95 | * 96 | * @note Port 443 requires use of the ALPN TLS extension with the ALPN protocol 97 | * name. When using port 8883, ALPN is not required. 98 | * 99 | * #define democonfigMQTT_BROKER_PORT ( insert here ) 100 | */ 101 | #define democonfigMQTT_BROKER_PORT CONFIG_MQTT_BROKER_PORT 102 | 103 | /** 104 | * @brief Server's root CA certificate. 105 | * 106 | * For AWS IoT MQTT broker, this certificate is used to identify the AWS IoT 107 | * server and is publicly available. Refer to the AWS documentation available 108 | * in the link below. 109 | * https://docs.aws.amazon.com/iot/latest/developerguide/server-authentication.html#server-authentication-certs 110 | * 111 | * @note This certificate should be PEM-encoded. 112 | * 113 | * Must include the PEM header and footer: 114 | * "-----BEGIN CERTIFICATE-----\n"\ 115 | * "...base64 data...\n"\ 116 | * "-----END CERTIFICATE-----\n" 117 | * 118 | * #define democonfigROOT_CA_PEM "...insert here..." 119 | */ 120 | 121 | /** 122 | * @brief Client certificate. 123 | * 124 | * For AWS IoT MQTT broker, refer to the AWS documentation below for details 125 | * regarding client authentication. 126 | * https://docs.aws.amazon.com/iot/latest/developerguide/client-authentication.html 127 | * 128 | * @note This certificate should be PEM-encoded. 129 | * 130 | * Must include the PEM header and footer: 131 | * "-----BEGIN CERTIFICATE-----\n"\ 132 | * "...base64 data...\n"\ 133 | * "-----END CERTIFICATE-----\n" 134 | * 135 | * #define democonfigCLIENT_CERTIFICATE_PEM "...insert here..." 136 | */ 137 | 138 | /** 139 | * @brief Client's private key. 140 | * 141 | *!!! Please note pasting a key into the header file in this manner is for 142 | *!!! convenience of demonstration only and should not be done in production. 143 | *!!! Never paste a production private key here!. Production devices should 144 | *!!! store keys securely, such as within a secure element. Additionally, 145 | *!!! we provide the corePKCS library that further enhances security by 146 | *!!! enabling securely stored keys to be used without exposing them to 147 | *!!! software. 148 | * 149 | * For AWS IoT MQTT broker, refer to the AWS documentation below for details 150 | * regarding clientauthentication. 151 | * https://docs.aws.amazon.com/iot/latest/developerguide/client-authentication.html 152 | * 153 | * @note This private key should be PEM-encoded. 154 | * 155 | * Must include the PEM header and footer: 156 | * "-----BEGIN RSA PRIVATE KEY-----\n"\ 157 | * "...base64 data...\n"\ 158 | * "-----END RSA PRIVATE KEY-----\n" 159 | * 160 | * #define democonfigCLIENT_PRIVATE_KEY_PEM "...insert here..." 161 | */ 162 | 163 | /** 164 | * @brief An option to disable Server Name Indication. 165 | * 166 | * @note When using a local Mosquitto server setup, SNI needs to be disabled 167 | * for an MQTT broker that only has an IP address but no hostname. However, 168 | * SNI should be enabled whenever possible. 169 | */ 170 | #define democonfigDISABLE_SNI CONFIG_MQTT_OPTION_SNI 171 | 172 | /** 173 | * @brief Configuration that indicates if the demo connection is made to the AWS IoT Core MQTT broker. 174 | * 175 | * If username/password based authentication is used, the demo will use appropriate TLS ALPN and 176 | * SNI configurations as required for the Custom Authentication feature of AWS IoT. 177 | * For more information, refer to the following documentation: 178 | * https://docs.aws.amazon.com/iot/latest/developerguide/custom-auth.html#custom-auth-mqtt 179 | * 180 | * #define democonfigUSE_AWS_IOT_CORE_BROKER ( 1 ) 181 | */ 182 | 183 | /** 184 | * @brief The username value for authenticating client to the MQTT broker when 185 | * username/password based client authentication is used. 186 | * 187 | * For AWS IoT MQTT broker, refer to the AWS IoT documentation below for 188 | * details regarding client authentication with a username and password. 189 | * https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html 190 | * An authorizer setup needs to be done, as mentioned in the above link, to use 191 | * username/password based client authentication. 192 | * 193 | * #define democonfigCLIENT_USERNAME "...insert here..." 194 | */ 195 | 196 | /** 197 | * @brief The password value for authenticating client to the MQTT broker when 198 | * username/password based client authentication is used. 199 | * 200 | * For AWS IoT MQTT broker, refer to the AWS IoT documentation below for 201 | * details regarding client authentication with a username and password. 202 | * https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html 203 | * An authorizer setup needs to be done, as mentioned in the above link, to use 204 | * username/password based client authentication. 205 | * 206 | * #define democonfigCLIENT_PASSWORD "...insert here..." 207 | */ 208 | 209 | /** 210 | * @brief The name of the operating system that the application is running on. 211 | * The current value is given as an example. Please update for your specific 212 | * operating system. 213 | */ 214 | #define democonfigOS_NAME "FreeRTOS" 215 | 216 | /** 217 | * @brief The version of the operating system that the application is running 218 | * on. The current value is given as an example. Please update for your specific 219 | * operating system version. 220 | */ 221 | #define democonfigOS_VERSION tskKERNEL_VERSION_NUMBER 222 | 223 | /** 224 | * @brief The name of the hardware platform the application is running on. The 225 | * current value is given as an example. Please update for your specific 226 | * hardware platform. 227 | */ 228 | #define democonfigHARDWARE_PLATFORM_NAME CONFIG_HARDWARE_PLATFORM_NAME 229 | 230 | /** 231 | * @brief The name of the MQTT library used and its version, following an "@" 232 | * symbol. 233 | */ 234 | #define democonfigMQTT_LIB "core-mqtt@1.0.0" 235 | 236 | /** 237 | * @brief Set the stack size of the main demo task. 238 | * 239 | * In the Windows port, this stack only holds a structure. The actual 240 | * stack is created by an operating system thread. 241 | */ 242 | #define democonfigDEMO_STACKSIZE CONFIG_MQTT_EXAMPLE_STACKSIZE 243 | 244 | /** 245 | * @brief Size of the network buffer for MQTT packets. 246 | */ 247 | #define democonfigNETWORK_BUFFER_SIZE CONFIG_MQTT_NETWORK_BUFFER_SIZE 248 | 249 | #endif /* DEMO_CONFIG_H */ 250 | -------------------------------------------------------------------------------- /examples/tls_mutual_auth/sdkconfig.defaults: -------------------------------------------------------------------------------- 1 | # newlib for ESP32 and ESP8266 platform 2 | 3 | CONFIG_NEWLIB_ENABLE=y 4 | CONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL=y 5 | CONFIG_NEWLIB_NANO_FORMAT= 6 | CONFIG_SSL_USING_MBEDTLS=y 7 | CONFIG_LWIP_IPV6=y 8 | 9 | -------------------------------------------------------------------------------- /port/exponential_backoff/exponential_backoff.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | * this software and associated documentation files (the "Software"), to deal in 6 | * the Software without restriction, including without limitation the rights to 7 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | * the Software, and to permit persons to whom the Software is furnished to do so, 9 | * subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | /** 23 | * @file exponential_backoff.c 24 | * @brief Utility implementation of backoff logic, used for attempting retries of failed processes. 25 | */ 26 | 27 | /* Standard includes. */ 28 | #include 29 | 30 | /* Kernel includes. */ 31 | #include "freertos/FreeRTOS.h" 32 | #include "freertos/task.h" 33 | 34 | #include "exponential_backoff.h" 35 | 36 | #define MILLISECONDS_PER_SECOND ( 1000U ) /**< @brief Milliseconds per second. */ 37 | 38 | extern UBaseType_t uxRand( void ); 39 | 40 | /*-----------------------------------------------------------*/ 41 | 42 | RetryUtilsStatus_t RetryUtils_BackoffAndSleep( RetryUtilsParams_t * pRetryParams ) 43 | { 44 | RetryUtilsStatus_t status = RetryUtilsRetriesExhausted; 45 | uint32_t backOffDelayMs = 0; 46 | 47 | /* If pRetryParams->maxRetryAttempts is set to 0, try forever. */ 48 | if( ( pRetryParams->attemptsDone < pRetryParams->maxRetryAttempts ) || 49 | ( 0U == pRetryParams->maxRetryAttempts ) ) 50 | { 51 | /* Choose a random value for back-off time between 0 and the max jitter value. */ 52 | backOffDelayMs = uxRand() % pRetryParams->nextJitterMax; 53 | 54 | /* Wait for backoff time to expire for the next retry. */ 55 | vTaskDelay( pdMS_TO_TICKS( backOffDelayMs * MILLISECONDS_PER_SECOND ) ); 56 | 57 | /* Increment backoff counts. */ 58 | pRetryParams->attemptsDone++; 59 | 60 | /* Double the max jitter value for the next retry attempt, only 61 | * if the new value will be less than the max backoff time value. */ 62 | if( pRetryParams->nextJitterMax < ( MAX_RETRY_BACKOFF_SECONDS / 2U ) ) 63 | { 64 | pRetryParams->nextJitterMax += pRetryParams->nextJitterMax; 65 | } 66 | else 67 | { 68 | pRetryParams->nextJitterMax = MAX_RETRY_BACKOFF_SECONDS; 69 | } 70 | 71 | status = RetryUtilsSuccess; 72 | } 73 | else 74 | { 75 | /* When max retry attempts are exhausted, let application know by 76 | * returning RetryUtilsRetriesExhausted. Application may choose to 77 | * restart the retry process after calling RetryUtils_ParamsReset(). */ 78 | status = RetryUtilsRetriesExhausted; 79 | RetryUtils_ParamsReset( pRetryParams ); 80 | } 81 | 82 | return status; 83 | } 84 | 85 | /*-----------------------------------------------------------*/ 86 | 87 | void RetryUtils_ParamsReset( RetryUtilsParams_t * pRetryParams ) 88 | { 89 | uint32_t jitter = 0; 90 | 91 | /* Reset attempts done to zero so that the next retry cycle can start. */ 92 | pRetryParams->attemptsDone = 0; 93 | 94 | /* Calculate jitter value using picking a random number. */ 95 | jitter = ( uxRand() % MAX_JITTER_VALUE_SECONDS ); 96 | 97 | /* Reset the backoff value to the initial time out value plus jitter. */ 98 | pRetryParams->nextJitterMax = INITIAL_RETRY_BACKOFF_SECONDS + jitter; 99 | } 100 | 101 | /*-----------------------------------------------------------*/ 102 | -------------------------------------------------------------------------------- /port/exponential_backoff/exponential_backoff.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | * this software and associated documentation files (the "Software"), to deal in 6 | * the Software without restriction, including without limitation the rights to 7 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | * the Software, and to permit persons to whom the Software is furnished to do so, 9 | * subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | /** 23 | * @file exponential_backoff.h 24 | * @brief Declaration of the exponential backoff retry logic utility functions 25 | * and constants. 26 | */ 27 | 28 | #ifndef EXPONENTIAL_BACKOFF_H 29 | #define EXPONENTIAL_BACKOFF_H 30 | 31 | /* Standard include. */ 32 | #include 33 | 34 | /** 35 | * @page retryutils_page Retry Utilities 36 | * @brief An abstraction of utilities for retrying with exponential back off and 37 | * jitter. 38 | * 39 | * @section retryutils_overview Overview 40 | * The retry utilities are a set of APIs that aid in retrying with exponential 41 | * backoff and jitter. Exponential backoff with jitter is strongly recommended 42 | * for retrying failed actions over the network with servers. Please see 43 | * https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/ for 44 | * more information about the benefits with AWS. 45 | * 46 | * Exponential backoff with jitter is typically used when retrying a failed 47 | * connection to the server. In an environment with poor connectivity, a client 48 | * can get disconnected at any time. A backoff strategy helps the client to 49 | * conserve battery by not repeatedly attempting reconnections when they are 50 | * unlikely to succeed. 51 | * 52 | * Before retrying the failed communication to the server there is a quiet period. 53 | * In this quiet period, the task that is retrying must sleep for some random 54 | * amount of seconds between 0 and the lesser of a base value and a predefined 55 | * maximum. The base is doubled with each retry attempt until the maximum is 56 | * reached.
57 | * 58 | * > sleep_seconds = random_between( 0, min( 2attempts_count * base_seconds, maximum_seconds ) ) 59 | * 60 | * @section retryutils_implementation Implementing Retry Utils 61 | * 62 | * The functions that must be implemented are:
63 | * - @ref RetryUtils_ParamsReset 64 | * - @ref RetryUtils_BackoffAndSleep 65 | * 66 | * The functions are used as shown in the diagram below. This is the exponential 67 | * backoff with jitter loop: 68 | * 69 | * @image html exponential_backoff_flow.png width=25% 70 | * 71 | * The following steps give guidance on implementing the Retry Utils. An example 72 | * implementation of the Retry Utils for the FreeRTOS platform can be found in file 73 | * @ref exponential_backoff.c. 74 | * 75 | * -# Implementing @ref RetryUtils_ParamsReset 76 | * @snippet this define_retryutils_paramsreset 77 | *
78 | * This function initializes @ref RetryUtilsParams_t. It is expected to set 79 | * @ref RetryUtilsParams_t.attemptsDone to zero. It is also expected to set 80 | * @ref RetryUtilsParams_t.nextJitterMax to @ref INITIAL_RETRY_BACKOFF_SECONDS 81 | * plus some random amount of seconds, jitter. This jitter is a random number 82 | * between 0 and @ref MAX_JITTER_VALUE_SECONDS. This function must be called 83 | * before entering the exponential backoff with jitter loop using 84 | * @ref RetryUtils_BackoffAndSleep.

85 | * Please follow the example below to implement your own @ref RetryUtils_ParamsReset. 86 | * The lines with FIXME comments should be updated. 87 | * @code{c} 88 | * void RetryUtils_ParamsReset( RetryUtilsParams_t * pRetryParams ) 89 | * { 90 | * uint32_t jitter = 0; 91 | * 92 | * // Reset attempts done to zero so that the next retry cycle can start. 93 | * pRetryParams->attemptsDone = 0; 94 | * 95 | * // Seed pseudo random number generator with the current time. FIXME: Your 96 | * // system may have another method to retrieve the current time to seed the 97 | * // pseudo random number generator. 98 | * srand( time( NULL ) ); 99 | * 100 | * // Calculate jitter value using picking a random number. 101 | * jitter = ( rand() % MAX_JITTER_VALUE_SECONDS ); 102 | * 103 | * // Reset the backoff value to the initial time out value plus jitter. 104 | * pRetryParams->nextJitterMax = INITIAL_RETRY_BACKOFF_SECONDS + jitter; 105 | * } 106 | * @endcode
107 | * 108 | * -# Implementing @ref RetryUtils_BackoffAndSleep 109 | * @snippet this define_retryutils_backoffandsleep 110 | *
111 | * When this function is invoked, the calling task is expected to sleep a random 112 | * number of seconds between 0 and @ref RetryUtilsParams_t.nextJitterMax. After 113 | * sleeping this function must double @ref RetryUtilsParams_t.nextJitterMax, but 114 | * not exceeding @ref MAX_RETRY_BACKOFF_SECONDS. When @ref RetryUtilsParams_t.maxRetryAttempts 115 | * are reached this function should return @ref RetryUtilsRetriesExhausted, unless 116 | * @ref RetryUtilsParams_t.maxRetryAttempts is set to zero. 117 | * When @ref RetryUtilsRetriesExhausted is returned the calling application can 118 | * stop trying with a failure, or it can call @ref RetryUtils_ParamsReset again 119 | * and restart the exponential back off with jitter loop.

120 | * Please follow the example below to implement your own @ref RetryUtils_BackoffAndSleep. 121 | * The lines with FIXME comments should be updated. 122 | * @code{c} 123 | * RetryUtilsStatus_t RetryUtils_BackoffAndSleep( RetryUtilsParams_t * pRetryParams ) 124 | * { 125 | * RetryUtilsStatus_t status = RetryUtilsRetriesExhausted; 126 | * // The quiet period delay in seconds. 127 | * int backOffDelay = 0; 128 | * 129 | * // If pRetryParams->maxRetryAttempts is set to 0, try forever. 130 | * if( ( pRetryParams->attemptsDone < pRetryParams->maxRetryAttempts ) || 131 | * ( 0U == pRetryParams->maxRetryAttempts ) ) 132 | * { 133 | * // Choose a random value for back-off time between 0 and the max jitter value. 134 | * backOffDelay = rand() % pRetryParams->nextJitterMax; 135 | * 136 | * // Wait for backoff time to expire for the next retry. 137 | * ( void ) myThreadSleepFunction( backOffDelay ); // FIXME: Replace with your system's thread sleep function. 138 | * 139 | * // Increment backoff counts. 140 | * pRetryParams->attemptsDone++; 141 | * 142 | * // Double the max jitter value for the next retry attempt, only 143 | * // if the new value will be less than the max backoff time value. 144 | * if( pRetryParams->nextJitterMax < ( MAX_RETRY_BACKOFF_SECONDS / 2U ) ) 145 | * { 146 | * pRetryParams->nextJitterMax += pRetryParams->nextJitterMax; 147 | * } 148 | * else 149 | * { 150 | * pRetryParams->nextJitterMax = MAX_RETRY_BACKOFF_SECONDS; 151 | * } 152 | * 153 | * status = RetryUtilsSuccess; 154 | * } 155 | * else 156 | * { 157 | * // When max retry attempts are exhausted, let application know by 158 | * // returning RetryUtilsRetriesExhausted. Application may choose to 159 | * // restart the retry process after calling RetryUtils_ParamsReset(). 160 | * status = RetryUtilsRetriesExhausted; 161 | * RetryUtils_ParamsReset( pRetryParams ); 162 | * } 163 | * 164 | * return status; 165 | * } 166 | * @endcode 167 | */ 168 | 169 | /** 170 | * @brief Max number of retry attempts. Set this value to 0 if the client must 171 | * retry forever. 172 | */ 173 | #define MAX_RETRY_ATTEMPTS 4U 174 | 175 | /** 176 | * @brief Initial fixed backoff value in seconds between two successive 177 | * retries. A random jitter value is added to every backoff value. 178 | */ 179 | #define INITIAL_RETRY_BACKOFF_SECONDS 1U 180 | 181 | /** 182 | * @brief Max backoff value in seconds. 183 | */ 184 | #define MAX_RETRY_BACKOFF_SECONDS 128U 185 | 186 | /** 187 | * @brief Max jitter value in seconds. 188 | */ 189 | #define MAX_JITTER_VALUE_SECONDS 5U 190 | 191 | /** 192 | * @brief Status for @ref RetryUtils_BackoffAndSleep. 193 | */ 194 | typedef enum RetryUtilsStatus 195 | { 196 | RetryUtilsSuccess = 0, /**< @brief The function returned successfully after sleeping. */ 197 | RetryUtilsRetriesExhausted /**< @brief The function exhausted all retry attempts. */ 198 | } RetryUtilsStatus_t; 199 | 200 | /** 201 | * @brief Represents parameters required for retry logic. 202 | */ 203 | typedef struct RetryUtilsParams 204 | { 205 | /** 206 | * @brief Max number of retry attempts. Set this value to 0 if the client must 207 | * retry forever. 208 | */ 209 | uint32_t maxRetryAttempts; 210 | 211 | /** 212 | * @brief The cumulative count of backoff delay cycles completed 213 | * for retries. 214 | */ 215 | uint32_t attemptsDone; 216 | 217 | /** 218 | * @brief The max jitter value for backoff time in retry attempt. 219 | */ 220 | uint32_t nextJitterMax; 221 | } RetryUtilsParams_t; 222 | 223 | 224 | /** 225 | * @brief Resets the retry timeout value and number of attempts. 226 | * This function must be called by the application before a new retry attempt. 227 | * 228 | * @param[in, out] pRetryParams Structure containing attempts done and timeout 229 | * value. 230 | */ 231 | void RetryUtils_ParamsReset( RetryUtilsParams_t * pRetryParams ); 232 | 233 | /** 234 | * @brief Simple platform specific exponential backoff function. The application 235 | * must use this function between retry failures to add exponential delay. 236 | * This function will block the calling task for the current timeout value. 237 | * 238 | * @param[in, out] pRetryParams Structure containing retry parameters. 239 | * 240 | * @return #RetryUtilsSuccess after a successful sleep, #RetryUtilsRetriesExhausted 241 | * when all attempts are exhausted. 242 | */ 243 | RetryUtilsStatus_t RetryUtils_BackoffAndSleep( RetryUtilsParams_t * pRetryParams ); 244 | 245 | #endif /* ifndef EXPONENTIAL_BACKOFF_H */ 246 | -------------------------------------------------------------------------------- /port/include/core_mqtt_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * coreMQTT v1.0.1 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | * this software and associated documentation files (the "Software"), to deal in 7 | * the Software without restriction, including without limitation the rights to 8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | * the Software, and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file core_mqtt_config.h 25 | * @brief This header sets configuration macros for the MQTT library. 26 | */ 27 | #ifndef CORE_MQTT_CONFIG_H_ 28 | #define CORE_MQTT_CONFIG_H_ 29 | 30 | #include "platform.h" 31 | 32 | /** 33 | * @brief Determines the maximum number of MQTT PUBLISH messages, pending 34 | * acknowledgement at a time, that are supported for incoming and outgoing 35 | * direction of messages, separately. 36 | * 37 | * QoS 1 and 2 MQTT PUBLISHes require acknowledgement from the server before 38 | * they can be completed. While they are awaiting the acknowledgement, the 39 | * client must maintain information about their state. The value of this 40 | * macro sets the limit on how many simultaneous PUBLISH states an MQTT 41 | * context maintains, separately, for both incoming and outgoing direction of 42 | * PUBLISHes. 43 | * 44 | * @note This definition must exist in order to compile. 10U is a typical value 45 | * used in the MQTT demos. 46 | */ 47 | #define MQTT_STATE_ARRAY_MAX_COUNT CONFIG_MQTT_STATE_ARRAY_MAX_COUNT 48 | 49 | /** 50 | * @brief Retry count for reading CONNACK from network. 51 | * 52 | * The MQTT_MAX_CONNACK_RECEIVE_RETRY_COUNT will be used only when the 53 | * timeoutMs parameter of #MQTT_Connect() is passed as 0 . The transport 54 | * receive for CONNACK will be retried MQTT_MAX_CONNACK_RECEIVE_RETRY_COUNT 55 | * times before timing out. A value of 0 for this config will cause the 56 | * transport receive for CONNACK to be invoked only once. 57 | */ 58 | #define MQTT_MAX_CONNACK_RECEIVE_RETRY_COUNT CONFIG_MQTT_MAX_CONNACK_RECEIVE_RETRY_COUNT 59 | 60 | /** 61 | * @brief Number of milliseconds to wait for a ping response to a ping 62 | * request as part of the keep-alive mechanism. 63 | * 64 | * If a ping response is not received before this timeout, then 65 | * #MQTT_ProcessLoop will return #MQTTKeepAliveTimeout. 66 | */ 67 | #define MQTT_PINGRESP_TIMEOUT_MS CONFIG_MQTT_PINGRESP_TIMEOUT_MS 68 | 69 | #endif /* ifndef CORE_MQTT_CONFIG_H_ */ 70 | -------------------------------------------------------------------------------- /port/logging/logging_levels.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FreeRTOS Kernel V10.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | * this software and associated documentation files (the "Software"), to deal in 7 | * the Software without restriction, including without limitation the rights to 8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | * the Software, and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | * 22 | * http://www.FreeRTOS.org 23 | * http://aws.amazon.com/freertos 24 | * 25 | * 1 tab == 4 spaces! 26 | */ 27 | 28 | /** 29 | * @file logging_levels.h 30 | * @brief Defines the configuration constants for all logging verbosity levels. 31 | */ 32 | 33 | #ifndef LOGGING_LEVELS_H 34 | #define LOGGING_LEVELS_H 35 | 36 | /** 37 | * @constantspage{logging,logging library} 38 | * 39 | * @section logging_constants_levels Log levels 40 | * @brief Log levels for the libraries in this SDK. 41 | * 42 | * Each library should specify a log level by setting @ref LIBRARY_LOG_LEVEL. 43 | * All log messages with a level at or below the specified level will be printed 44 | * for that library. 45 | * 46 | * Currently, there are 4 log levels. In the order of lowest to highest, they are: 47 | * - #LOG_NONE
48 | * @copybrief LOG_NONE 49 | * - #LOG_ERROR
50 | * @copybrief LOG_ERROR 51 | * - #LOG_WARN
52 | * @copybrief LOG_WARN 53 | * - #LOG_INFO
54 | * @copybrief LOG_INFO 55 | * - #LOG_DEBUG
56 | * @copybrief LOG_DEBUG 57 | */ 58 | 59 | /** 60 | * @brief No log messages. 61 | * 62 | * When @ref LIBRARY_LOG_LEVEL is #LOG_NONE, logging is disabled and no 63 | * logging messages are printed. 64 | */ 65 | #define LOG_NONE 0 66 | 67 | /** 68 | * @brief Represents erroneous application state or event. 69 | * 70 | * These messages describe the situations when a library encounters an error from 71 | * which it cannot recover. 72 | * 73 | * These messages are printed when @ref LIBRARY_LOG_LEVEL is defined as either 74 | * of #LOG_ERROR, #LOG_WARN, #LOG_INFO or #LOG_DEBUG. 75 | */ 76 | #define LOG_ERROR 1 77 | 78 | /** 79 | * @brief Message about an abnormal event. 80 | * 81 | * These messages describe the situations when a library encounters 82 | * abnormal event that may be indicative of an error. Libraries continue 83 | * execution after logging a warning. 84 | * 85 | * These messages are printed when @ref LIBRARY_LOG_LEVEL is defined as either 86 | * of #LOG_WARN, #LOG_INFO or #LOG_DEBUG. 87 | */ 88 | #define LOG_WARN 2 89 | 90 | /** 91 | * @brief A helpful, informational message. 92 | * 93 | * These messages describe normal execution of a library. They provide 94 | * the progress of the program at a coarse-grained level. 95 | * 96 | * These messages are printed when @ref LIBRARY_LOG_LEVEL is defined as either 97 | * of #LOG_INFO or #LOG_DEBUG. 98 | */ 99 | #define LOG_INFO 3 100 | 101 | /** 102 | * @brief Detailed and excessive debug information. 103 | * 104 | * Debug log messages are used to provide the 105 | * progress of the program at a fine-grained level. These are mostly used 106 | * for debugging and may contain excessive information such as internal 107 | * variables, buffers, or other specific information. 108 | * 109 | * These messages are only printed when @ref LIBRARY_LOG_LEVEL is defined as 110 | * #LOG_DEBUG. 111 | */ 112 | #define LOG_DEBUG 4 113 | 114 | #endif /* ifndef LOGGING_LEVELS_H */ 115 | -------------------------------------------------------------------------------- /port/logging/logging_stack.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FreeRTOS Kernel V10.3.0 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | * this software and associated documentation files (the "Software"), to deal in 7 | * the Software without restriction, including without limitation the rights to 8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | * the Software, and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | * 22 | * http://www.FreeRTOS.org 23 | * http://aws.amazon.com/freertos 24 | * 25 | * 1 tab == 4 spaces! 26 | */ 27 | 28 | /** 29 | * @file logging_stack.h 30 | * @brief Utility header file that exposes macros for configuring logging implementation of logging macros (LogError, LogWarn, LogInfo, LogDebug). 31 | */ 32 | 33 | #ifndef LOGGING_STACK_H 34 | #define LOGGING_STACK_H 35 | 36 | /* Include header for logging level macros. */ 37 | #include "logging_levels.h" 38 | 39 | /* Standard Include. */ 40 | #include 41 | #include 42 | 43 | /** 44 | * @brief The name of the library or demo to add as metadata in log messages 45 | * from the library or demo. 46 | * 47 | * This metadata aids in identifying the module source of log messages. 48 | * The metadata is logged in the format `[ ]` as a prefix to the 49 | * log messages. 50 | * Refer to #LOG_METADATA_FORMAT for the complete format of the metadata prefix in 51 | * log messages. 52 | */ 53 | /* Check if LIBRARY_LOG_NAME macro has been defined. */ 54 | #if !defined( LIBRARY_LOG_NAME ) 55 | #error "Please define LIBRARY_LOG_NAME for the library." 56 | #endif 57 | 58 | /* Metadata information to prepend to every log message. */ 59 | #ifndef LOG_METADATA_FORMAT 60 | #define LOG_METADATA_FORMAT "[%s:%d] " /**< @brief Format of metadata prefix in log messages. */ 61 | #endif 62 | 63 | #ifndef LOG_METADATA_ARGS 64 | #define LOG_METADATA_ARGS __FUNCTION__, __LINE__ /**< @brief Arguments into the metadata logging prefix format. */ 65 | #endif 66 | 67 | /** 68 | * @brief Common macro that maps all the logging interfaces, 69 | * (#LogDebug, #LogInfo, #LogWarn, #LogError) to the platform-specific logging 70 | * function. 71 | * 72 | * @note The default definition of the macro is an empty definition that does not 73 | * generate any logging. 74 | */ 75 | #ifndef SdkLog 76 | #define SdkLog( string ) 77 | #endif 78 | 79 | /** 80 | * Disable definition of logging interface macros when generating doxygen output, 81 | * to avoid conflict with documentation of macros at the end of the file. 82 | */ 83 | /* Check that LIBRARY_LOG_LEVEL is defined and has a valid value. */ 84 | #if !defined( LIBRARY_LOG_LEVEL ) || \ 85 | ( ( LIBRARY_LOG_LEVEL != LOG_NONE ) && \ 86 | ( LIBRARY_LOG_LEVEL != LOG_ERROR ) && \ 87 | ( LIBRARY_LOG_LEVEL != LOG_WARN ) && \ 88 | ( LIBRARY_LOG_LEVEL != LOG_INFO ) && \ 89 | ( LIBRARY_LOG_LEVEL != LOG_DEBUG ) ) 90 | #error "Please define LIBRARY_LOG_LEVEL as either LOG_NONE, LOG_ERROR, LOG_WARN, LOG_INFO, or LOG_DEBUG." 91 | #else 92 | #if LIBRARY_LOG_LEVEL == LOG_DEBUG 93 | /* All log level messages will logged. */ 94 | #define LogError( message ) SdkLog( ( "[ERROR] [%s] "LOG_METADATA_FORMAT, LIBRARY_LOG_NAME, LOG_METADATA_ARGS ) ); SdkLog( message ); SdkLog( ( "\r\n" ) ) 95 | #define LogWarn( message ) SdkLog( ( "[WARN] [%s] "LOG_METADATA_FORMAT, LIBRARY_LOG_NAME, LOG_METADATA_ARGS ) ); SdkLog( message ); SdkLog( ( "\r\n" ) ) 96 | #define LogInfo( message ) SdkLog( ( "[INFO] [%s] "LOG_METADATA_FORMAT, LIBRARY_LOG_NAME, LOG_METADATA_ARGS ) ); SdkLog( message ); SdkLog( ( "\r\n" ) ) 97 | #define LogDebug( message ) SdkLog( ( "[DEBUG] [%s] "LOG_METADATA_FORMAT, LIBRARY_LOG_NAME, LOG_METADATA_ARGS ) ); SdkLog( message ); SdkLog( ( "\r\n" ) ) 98 | 99 | #elif LIBRARY_LOG_LEVEL == LOG_INFO 100 | /* Only INFO, WARNING and ERROR messages will be logged. */ 101 | #define LogError( message ) SdkLog( ( "[ERROR] [%s] "LOG_METADATA_FORMAT, LIBRARY_LOG_NAME, LOG_METADATA_ARGS ) ); SdkLog( message ); SdkLog( ( "\r\n" ) ) 102 | #define LogWarn( message ) SdkLog( ( "[WARN] [%s] "LOG_METADATA_FORMAT, LIBRARY_LOG_NAME, LOG_METADATA_ARGS ) ); SdkLog( message ); SdkLog( ( "\r\n" ) ) 103 | #define LogInfo( message ) SdkLog( ( "[INFO] [%s] "LOG_METADATA_FORMAT, LIBRARY_LOG_NAME, LOG_METADATA_ARGS ) ); SdkLog( message ); SdkLog( ( "\r\n" ) ) 104 | #define LogDebug( message ) 105 | 106 | #elif LIBRARY_LOG_LEVEL == LOG_WARN 107 | /* Only WARNING and ERROR messages will be logged.*/ 108 | #define LogError( message ) SdkLog( ( "[ERROR] [%s] "LOG_METADATA_FORMAT, LIBRARY_LOG_NAME, LOG_METADATA_ARGS ) ); SdkLog( message ); SdkLog( ( "\r\n" ) ) 109 | #define LogWarn( message ) SdkLog( ( "[WARN] [%s] "LOG_METADATA_FORMAT, LIBRARY_LOG_NAME, LOG_METADATA_ARGS ) ); SdkLog( message ); SdkLog( ( "\r\n" ) ) 110 | #define LogInfo( message ) 111 | #define LogDebug( message ) 112 | 113 | #elif LIBRARY_LOG_LEVEL == LOG_ERROR 114 | /* Only ERROR messages will be logged. */ 115 | #define LogError( message ) SdkLog( ( "[ERROR] [%s] "LOG_METADATA_FORMAT, LIBRARY_LOG_NAME, LOG_METADATA_ARGS ) ); SdkLog( message ); SdkLog( ( "\r\n" ) ) 116 | #define LogWarn( message ) 117 | #define LogInfo( message ) 118 | #define LogDebug( message ) 119 | 120 | #else /* if LIBRARY_LOG_LEVEL == LOG_ERROR */ 121 | 122 | #define LogError( message ) 123 | #define LogWarn( message ) 124 | #define LogInfo( message ) 125 | #define LogDebug( message ) 126 | 127 | #endif /* if LIBRARY_LOG_LEVEL == LOG_ERROR */ 128 | #endif /* if !defined( LIBRARY_LOG_LEVEL ) || ( ( LIBRARY_LOG_LEVEL != LOG_NONE ) && ( LIBRARY_LOG_LEVEL != LOG_ERROR ) && ( LIBRARY_LOG_LEVEL != LOG_WARN ) && ( LIBRARY_LOG_LEVEL != LOG_INFO ) && ( LIBRARY_LOG_LEVEL != LOG_DEBUG ) ) */ 129 | 130 | #endif /* ifndef LOGGING_STACK_H */ 131 | -------------------------------------------------------------------------------- /port/network_transport/tls_freertos.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | * this software and associated documentation files (the "Software"), to deal in 6 | * the Software without restriction, including without limitation the rights to 7 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | * the Software, and to permit persons to whom the Software is furnished to do so, 9 | * subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | /** 23 | * @file tls_freertos.c 24 | * @brief TLS transport interface implementations. This implementation uses 25 | * mbedTLS. 26 | */ 27 | 28 | /* Standard includes. */ 29 | #include 30 | 31 | /* FreeRTOS includes. */ 32 | #include "freertos/FreeRTOS.h" 33 | 34 | /* TLS transport header. */ 35 | #include "tls_freertos.h" 36 | 37 | #include "esp_log.h" 38 | 39 | static const char *TAG = "tls_freertos"; 40 | /*-----------------------------------------------------------*/ 41 | 42 | TlsTransportStatus_t TLS_FreeRTOS_Connect( NetworkContext_t * pNetworkContext, 43 | const char * pHostName, 44 | uint16_t port, 45 | const NetworkCredentials_t * pNetworkCredentials, 46 | uint32_t receiveTimeoutMs, 47 | uint32_t sendTimeoutMs ) 48 | { 49 | TlsTransportStatus_t returnStatus = TLS_TRANSPORT_SUCCESS; 50 | 51 | if( ( pNetworkContext == NULL ) || 52 | ( pHostName == NULL ) || 53 | ( pNetworkCredentials == NULL ) ) 54 | { 55 | ESP_LOGE(TAG, "Invalid input parameter(s): Arguments cannot be NULL. pNetworkContext=%p, " 56 | "pHostName=%p, pNetworkCredentials=%p.", 57 | pNetworkContext, 58 | pHostName, 59 | pNetworkCredentials); 60 | return TLS_TRANSPORT_INVALID_PARAMETER; 61 | } 62 | 63 | pNetworkContext->transport = esp_transport_ssl_init(); 64 | pNetworkContext->receiveTimeoutMs = receiveTimeoutMs; 65 | pNetworkContext->sendTimeoutMs = sendTimeoutMs; 66 | if (pNetworkCredentials->pAlpnProtos) { 67 | esp_transport_ssl_set_alpn_protocol(pNetworkContext->transport, pNetworkCredentials->pAlpnProtos); 68 | } 69 | 70 | if (pNetworkCredentials->disableSni) { 71 | esp_transport_ssl_skip_common_name_check(pNetworkContext->transport); 72 | } 73 | 74 | if (pNetworkCredentials->pRootCa) { 75 | esp_transport_ssl_set_cert_data_der(pNetworkContext->transport, (const char *)pNetworkCredentials->pRootCa, pNetworkCredentials->rootCaSize); 76 | } 77 | 78 | if (pNetworkCredentials->pClientCert) { 79 | esp_transport_ssl_set_client_cert_data_der(pNetworkContext->transport, (const char *)pNetworkCredentials->pClientCert, pNetworkCredentials->clientCertSize); 80 | } 81 | 82 | if (pNetworkCredentials->pPrivateKey) { 83 | esp_transport_ssl_set_client_key_data_der(pNetworkContext->transport, (const char *)pNetworkCredentials->pPrivateKey, pNetworkCredentials->privateKeySize); 84 | } 85 | 86 | if (esp_transport_connect(pNetworkContext->transport, pHostName, port, receiveTimeoutMs) < 0) { 87 | returnStatus = TLS_TRANSPORT_CONNECT_FAILURE; 88 | } else { 89 | returnStatus = TLS_TRANSPORT_SUCCESS; 90 | } 91 | 92 | /* Clean up on failure. */ 93 | if( returnStatus != TLS_TRANSPORT_SUCCESS ) 94 | { 95 | if( pNetworkContext != NULL ) 96 | { 97 | esp_transport_close( pNetworkContext->transport ); 98 | esp_transport_destroy( pNetworkContext->transport ); 99 | } 100 | } 101 | else 102 | { 103 | ESP_LOGI(TAG, "(Network connection %p) Connection to %s established.", 104 | pNetworkContext, 105 | pHostName); 106 | } 107 | 108 | return returnStatus; 109 | } 110 | /*-----------------------------------------------------------*/ 111 | 112 | void TLS_FreeRTOS_Disconnect( NetworkContext_t * pNetworkContext ) 113 | { 114 | if (( pNetworkContext == NULL ) ) { 115 | ESP_LOGE(TAG, "Invalid input parameter(s): Arguments cannot be NULL. pNetworkContext=%p.", pNetworkContext); 116 | return; 117 | } 118 | 119 | /* Attempting to terminate TLS connection. */ 120 | esp_transport_close( pNetworkContext->transport ); 121 | 122 | /* Free TLS contexts. */ 123 | esp_transport_destroy( pNetworkContext->transport ); 124 | } 125 | /*-----------------------------------------------------------*/ 126 | 127 | int32_t TLS_FreeRTOS_recv( NetworkContext_t * pNetworkContext, 128 | void * pBuffer, 129 | size_t bytesToRecv ) 130 | { 131 | int32_t tlsStatus = 0; 132 | 133 | if (( pNetworkContext == NULL ) || 134 | ( pBuffer == NULL) || 135 | ( bytesToRecv == 0) ) { 136 | ESP_LOGE(TAG, "Invalid input parameter(s): Arguments cannot be NULL. pNetworkContext=%p, " 137 | "pBuffer=%p, bytesToRecv=%d.", pNetworkContext, pBuffer, bytesToRecv ); 138 | return TLS_TRANSPORT_INVALID_PARAMETER; 139 | } 140 | 141 | tlsStatus = esp_transport_read(pNetworkContext->transport, pBuffer, bytesToRecv, pNetworkContext->receiveTimeoutMs); 142 | if (tlsStatus < 0) { 143 | ESP_LOGE(TAG, "Reading failed, errno= %d", errno); 144 | return ESP_FAIL; 145 | } 146 | 147 | return tlsStatus; 148 | } 149 | /*-----------------------------------------------------------*/ 150 | 151 | int32_t TLS_FreeRTOS_send( NetworkContext_t * pNetworkContext, 152 | const void * pBuffer, 153 | size_t bytesToSend ) 154 | { 155 | int32_t tlsStatus = 0; 156 | 157 | if (( pNetworkContext == NULL ) || 158 | ( pBuffer == NULL) || 159 | ( bytesToSend == 0) ) { 160 | ESP_LOGE(TAG, "Invalid input parameter(s): Arguments cannot be NULL. pNetworkContext=%p, " 161 | "pBuffer=%p, bytesToSend=%d.", pNetworkContext, pBuffer, bytesToSend ); 162 | return TLS_TRANSPORT_INVALID_PARAMETER; 163 | } 164 | 165 | tlsStatus = esp_transport_write(pNetworkContext->transport, pBuffer, bytesToSend, pNetworkContext->sendTimeoutMs); 166 | if (tlsStatus < 0) { 167 | ESP_LOGE(TAG, "Writing failed, errno= %d", errno); 168 | return ESP_FAIL; 169 | } 170 | 171 | return tlsStatus; 172 | } 173 | /*-----------------------------------------------------------*/ 174 | -------------------------------------------------------------------------------- /port/network_transport/tls_freertos.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | * this software and associated documentation files (the "Software"), to deal in 6 | * the Software without restriction, including without limitation the rights to 7 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | * the Software, and to permit persons to whom the Software is furnished to do so, 9 | * subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | /** 23 | * @file tls_freertos.h 24 | * @brief TLS transport interface header. 25 | */ 26 | 27 | #ifndef TLS_FREERTOS 28 | #define TLS_FREERTOS 29 | 30 | /**************************************************/ 31 | /******* DO NOT CHANGE the following order ********/ 32 | /**************************************************/ 33 | 34 | /* Logging related header files are required to be included in the following order: 35 | * 1. Include the header file "logging_levels.h". 36 | * 2. Define LIBRARY_LOG_NAME and LIBRARY_LOG_LEVEL. 37 | * 3. Include the header file "logging_stack.h". 38 | */ 39 | 40 | /* Include header that defines log levels. */ 41 | #include "logging_levels.h" 42 | 43 | /* Logging configuration for the Sockets. */ 44 | #ifndef LIBRARY_LOG_NAME 45 | #define LIBRARY_LOG_NAME "TlsTransport" 46 | #endif 47 | #ifndef LIBRARY_LOG_LEVEL 48 | #define LIBRARY_LOG_LEVEL LOG_ERROR 49 | #endif 50 | 51 | /* Map the SdkLog macro to the logging function to enable logging 52 | * on Windows simulator. */ 53 | #define SdkLog( message ) printf message 54 | 55 | #include "logging_stack.h" 56 | 57 | /************ End of logging configuration ****************/ 58 | 59 | /* Transport include. */ 60 | #include "esp_transport.h" 61 | #include "esp_transport_tcp.h" 62 | 63 | /* Transport interface include. */ 64 | #include "transport_interface.h" 65 | 66 | /* TLS includes. */ 67 | #include "esp_transport_ssl.h" 68 | 69 | /** 70 | * @brief Definition of the network context for the transport interface 71 | * implementation that uses mbedTLS and FreeRTOS+TLS sockets. 72 | */ 73 | struct NetworkContext 74 | { 75 | esp_transport_handle_t transport; 76 | uint32_t receiveTimeoutMs; 77 | uint32_t sendTimeoutMs; 78 | }; 79 | 80 | /** 81 | * @brief Contains the credentials necessary for tls connection setup. 82 | */ 83 | typedef struct NetworkCredentials 84 | { 85 | /** 86 | * @brief To use ALPN, set this to a NULL-terminated list of supported 87 | * protocols in decreasing order of preference. 88 | * 89 | * See [this link] 90 | * (https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/) 91 | * for more information. 92 | */ 93 | const char ** pAlpnProtos; 94 | 95 | /** 96 | * @brief Disable server name indication (SNI) for a TLS session. 97 | */ 98 | BaseType_t disableSni; 99 | 100 | const uint8_t * pRootCa; /**< @brief String representing a trusted server root certificate. */ 101 | size_t rootCaSize; /**< @brief Size associated with #NetworkCredentials.pRootCa. */ 102 | const uint8_t * pClientCert; /**< @brief String representing the client certificate. */ 103 | size_t clientCertSize; /**< @brief Size associated with #NetworkCredentials.pClientCert. */ 104 | const uint8_t * pPrivateKey; /**< @brief String representing the client certificate's private key. */ 105 | size_t privateKeySize; /**< @brief Size associated with #NetworkCredentials.pPrivateKey. */ 106 | } NetworkCredentials_t; 107 | 108 | /** 109 | * @brief TLS Connect / Disconnect return status. 110 | */ 111 | typedef enum TlsTransportStatus 112 | { 113 | TLS_TRANSPORT_SUCCESS = 0, /**< Function successfully completed. */ 114 | TLS_TRANSPORT_INVALID_PARAMETER, /**< At least one parameter was invalid. */ 115 | TLS_TRANSPORT_INSUFFICIENT_MEMORY, /**< Insufficient memory required to establish connection. */ 116 | TLS_TRANSPORT_INVALID_CREDENTIALS, /**< Provided credentials were invalid. */ 117 | TLS_TRANSPORT_HANDSHAKE_FAILED, /**< Performing TLS handshake with server failed. */ 118 | TLS_TRANSPORT_INTERNAL_ERROR, /**< A call to a system API resulted in an internal error. */ 119 | TLS_TRANSPORT_CONNECT_FAILURE /**< Initial connection to the server failed. */ 120 | } TlsTransportStatus_t; 121 | 122 | /** 123 | * @brief Create a TLS connection with FreeRTOS sockets. 124 | * 125 | * @param[out] pNetworkContext Pointer to a network context to contain the 126 | * initialized socket handle. 127 | * @param[in] pHostName The hostname of the remote endpoint. 128 | * @param[in] port The destination port. 129 | * @param[in] pNetworkCredentials Credentials for the TLS connection. 130 | * @param[in] receiveTimeoutMs Receive socket timeout. 131 | * @param[in] sendTimeoutMs Send socket timeout. 132 | * 133 | * @return #TLS_TRANSPORT_SUCCESS, #TLS_TRANSPORT_INSUFFICIENT_MEMORY, #TLS_TRANSPORT_INVALID_CREDENTIALS, 134 | * #TLS_TRANSPORT_HANDSHAKE_FAILED, #TLS_TRANSPORT_INTERNAL_ERROR, or #TLS_TRANSPORT_CONNECT_FAILURE. 135 | */ 136 | TlsTransportStatus_t TLS_FreeRTOS_Connect( NetworkContext_t * pNetworkContext, 137 | const char * pHostName, 138 | uint16_t port, 139 | const NetworkCredentials_t * pNetworkCredentials, 140 | uint32_t receiveTimeoutMs, 141 | uint32_t sendTimeoutMs ); 142 | 143 | /** 144 | * @brief Gracefully disconnect an established TLS connection. 145 | * 146 | * @param[in] pNetworkContext Network context. 147 | */ 148 | void TLS_FreeRTOS_Disconnect( NetworkContext_t * pNetworkContext ); 149 | 150 | /** 151 | * @brief Receives data from an established TLS connection. 152 | * 153 | * This is the TLS version of the transport interface's 154 | * #TransportRecv_t function. 155 | * 156 | * @param[in] pNetworkContext The Network context. 157 | * @param[out] pBuffer Buffer to receive bytes into. 158 | * @param[in] bytesToRecv Number of bytes to receive from the network. 159 | * 160 | * @return Number of bytes (> 0) received if successful; 161 | * 0 if the socket times out without reading any bytes; 162 | * negative value on error. 163 | */ 164 | int32_t TLS_FreeRTOS_recv( NetworkContext_t * pNetworkContext, 165 | void * pBuffer, 166 | size_t bytesToRecv ); 167 | 168 | /** 169 | * @brief Sends data over an established TLS connection. 170 | * 171 | * This is the TLS version of the transport interface's 172 | * #TransportSend_t function. 173 | * 174 | * @param[in] pNetworkContext The network context. 175 | * @param[in] pBuffer Buffer containing the bytes to send. 176 | * @param[in] bytesToSend Number of bytes to send from the buffer. 177 | * 178 | * @return Number of bytes (> 0) sent on success; 179 | * 0 if the socket times out without sending any bytes; 180 | * else a negative value to represent error. 181 | */ 182 | int32_t TLS_FreeRTOS_send( NetworkContext_t * pNetworkContext, 183 | const void * pBuffer, 184 | size_t bytesToSend ); 185 | 186 | #endif /* ifndef TLS_FREERTOS */ 187 | -------------------------------------------------------------------------------- /port/platform/platform.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "platform.h" 16 | 17 | #ifdef ESP_PLATFORM 18 | #include "esp_system.h" 19 | #include "esp_log.h" 20 | #include "freertos/FreeRTOS.h" 21 | 22 | static const char *TAG = "PLATFORM"; 23 | 24 | UBaseType_t uxRand( void ) 25 | { 26 | return esp_random(); 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /port/platform/platform.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #include 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * @brief Size of the network buffer for MQTT packets. 25 | */ 26 | #if CONFIG_IDF_TARGET_ESP8266 27 | #define xPortGetFreeHeapSize() esp_get_free_heap_size() 28 | #endif 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | --------------------------------------------------------------------------------