├── .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 |  | 
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 | 
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 |  | 
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 | 
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 |
--------------------------------------------------------------------------------