chore: Adds pre-commit checks and introduce conventional commits

This commit is contained in:
Euripedes Rocha Filho
2025-09-25 15:49:41 +02:00
parent 5b1f57f690
commit 04f8e3765d
62 changed files with 1902 additions and 873 deletions

31
.ci/astyle-rules.yml Normal file
View File

@@ -0,0 +1,31 @@
DEFAULT:
options: >-
--style=otbs
--indent=spaces=4
--break-blocks
--pad-oper
--pad-comma
--pad-header
--unpad-paren
--delete-empty-lines
--add-braces
--align-pointer=name
--align-reference=name
--max-continuation-indent=120
--keep-one-line-statements
--break-after-logical
include:
- "*.c"
- "*.h"
- "*.cpp"
- "*.hpp"
# Exclude mocked components and generated files
mocks_and_generated:
check: false
include:
- "build*/"
- "components/mocks/"
- "managed_components/"
- "*.pb.h"
- "*.pb.c"

View File

@@ -0,0 +1,46 @@
# don't modify this section!
DEFAULT:
perform_check: yes # should the check be performed?
# Sections setting this to 'no' don't need to include any other options as they are ignored
# When a file is using a section with the option set to 'no', no checks are performed.
# what licenses (or license expressions) are allowed for files in this section
# when setting this option in a section, you need to list all the allowed licenses
allowed_licenses:
- Apache-2.0
license_for_new_files: Apache-2.0 # license to be used when inserting a new copyright notice
new_notice_c: | # notice for new C, CPP, H, HPP and LD files
/*
* SPDX-FileCopyrightText: {years} Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: {license}
*/
new_notice_python: | # notice for new python files
# SPDX-FileCopyrightText: {years} Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: {license}
# comment lines matching:
# SPDX-FileCopyrightText: year[-year] Espressif Systems
# or
# SPDX-FileContributor: year[-year] Espressif Systems
# are replaced with this template prefixed with the correct comment notation (# or // or *) and SPDX- notation
espressif_copyright: "{years} Espressif Systems (Shanghai) CO LTD"
examples_and_unit_tests:
include:
- "examples/"
- "test/**"
- "**/pytest_*.py"
allowed_licenses:
- Apache-2.0
- Unlicense
- CC0-1.0
license_for_new_files: Unlicense OR CC0-1.0
third_party_libs:
include:
- "lib/mqtt_msg.c"
- "lib/include/mqtt_msg.h"
- "test/host/mocks/include/sys/queue.h"
allowed_licenses:
- BSD-3-Clause
- Apache-2.0

View File

@@ -34,4 +34,3 @@ jobs:
# target: ${{inputs.target}}
# app_name: ${{inputs.app_name}}
# app_path: ${{inputs.app_path}}

View File

@@ -49,4 +49,3 @@ jobs:
target: ${{matrix.target}}
app_name: ${{matrix.example.name}}
app_path: $IDF_PATH/examples/protocols/${{matrix.example.path}}

View File

@@ -6,6 +6,7 @@
tags:
- build
- internet
timeout: 1h
script:
- pip install -U 'idf-ci<1'
- idf-ci build run

25
.gitlab/ci/pre-check.yml Normal file
View File

@@ -0,0 +1,25 @@
# Pre-check jobs for ESP-MQTT
.check_pre_commit_template:
stage: pre_check
image: "${CI_DOCKER_REGISTRY}/esp-idf-pre-commit:2"
tags: [build, internet]
variables:
GIT_STRATEGY: fetch
GIT_DEPTH: 1
SUBMODULES_TO_FETCH: "all"
script:
- pre-commit install
- pre-commit run --all-files
cache:
paths:
- .cache/submodule_archives
policy: pull
check_pre_commit:
extends:
- .check_pre_commit_template
rules:
- if: '$CI_COMMIT_REF_NAME == "master" && $CI_PIPELINE_SOURCE == "push"'
when: never
- when: on_success

76
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,76 @@
minimum_pre_commit_version: 4.0.0 # Specifies the minimum version of pre-commit required for this configuration
default_install_hook_types: [pre-commit,commit-msg] # Default hook types to install if not specified in individual hooks
default_stages: [pre-commit]
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace # Removes trailing whitespaces from lines
exclude: &whitespace_excludes |
(?x)^(
.+\.(md|rst|map|bin|drawio|elf)|
.+\.log$|
compile_commands\.json$|
dependencies\.lock$|
build.*/.*|
__pycache__/.*
)$
- id: end-of-file-fixer # Ensures files end with a newline
exclude: *whitespace_excludes
- id: check-executables-have-shebangs # Checks executables have a proper shebang
- id: mixed-line-ending # Detects mixed line endings (CRLF/LF)
args: ['-f=lf'] # Forces files to use LF line endings
- id: double-quote-string-fixer # Converts single quotes to double quotes in strings
- repo: https://github.com/espressif/check-copyright/
rev: v1.1.1
hooks:
- id: check-copyright
args: ['--config', '.ci/check_copyright_config.yaml']
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.11.5
hooks:
- id: ruff # Runs ruff linter (replaces flake8)
args: ['--fix', '--exit-non-zero-on-fix']
files: \.py$
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.15.0
hooks:
- id: mypy # Runs mypy for Python type checking
additional_dependencies: ['PyYAML', 'types-PyYAML']
files: \.py$
exclude: ^docs/.*/conf\.py$
- repo: https://github.com/espressif/conventional-precommit-linter
rev: v1.10.0
hooks:
- id: conventional-precommit-linter # Lints commit messages for conventional format
stages: [commit-msg]
args:
- --types=ci,docs,feat,fix,perf,refactor,chore
- --scopes=mqtt,mqtt5,examples
- --subject-min-length=10
- repo: https://github.com/codespell-project/codespell
rev: v2.4.1
hooks:
- id: codespell # Code spell checker
args: ["--write-changes"]
additional_dependencies: [tomli]
exclude: |
(?x)^(
.+\.(bin|elf|map)|
build.*/.*|
dependencies\.lock$|
compile_commands\.json$|
__pycache__/.*
)$
- repo: https://github.com/espressif/astyle_py.git
rev: v1.1.0
hooks:
- id: astyle_py
args: ['--astyle-version=3.4.7', '--rules=.ci/astyle-rules.yml']

View File

@@ -185,6 +185,6 @@ menu "ESP-MQTT Configurations"
Set to true to have publish topic in all data events. This changes the behaviour
when the message is bigger than the receive buffer size. The first event of the sequence
always have the topic.
Note: This will allocate memory to store the topic only in case of messge bigger than the buffer size.
Note: This will allocate memory to store the topic only in case of message bigger than the buffer size.
endmenu

View File

@@ -1,3 +1,5 @@
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
# -*- coding: utf-8 -*-
#
# Common (non-language-specific) configuration for Sphinx
@@ -6,6 +8,7 @@
# type: ignore
# pylint: disable=wildcard-import
# pylint: disable=undefined-variable
# ruff: noqa: F405
from __future__ import print_function, unicode_literals
@@ -15,7 +18,7 @@ from esp_docs.conf_docs import * # noqa: F403,F401
# Only required when using ESP-IDF extensions that depend on IDF environment
extensions += ['sphinx_copybutton',
extensions += ['sphinx_copybutton', # noqa: F405
# Needed as a trigger for running doxygen
'esp_docs.esp_extensions.dummy_build_system',
'esp_docs.esp_extensions.run_doxygen'
@@ -25,8 +28,8 @@ extensions += ['sphinx_copybutton',
github_repo = 'espressif/esp-mqtt'
# context used by sphinx_idf_theme
html_context['github_user'] = 'espressif'
html_context['github_repo'] = 'esp-mqtt'
html_context['github_user'] = 'espressif' # noqa: F405
html_context['github_repo'] = 'esp-mqtt' # noqa: F405
# Extra options required by sphinx_idf_theme
project_slug = 'esp-mqtt'
@@ -34,6 +37,3 @@ versions_url = './_static/mqtt_docs_versions.js'
idf_targets = [ 'esp32' ]
languages = ['en']

View File

@@ -1,3 +1,5 @@
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
# -*- coding: utf-8 -*-
#
# English Language RTD & Sphinx config file

View File

@@ -1,3 +1,5 @@
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
# -*- coding: utf-8 -*-
#
# English Language RTD & Sphinx config file

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -27,7 +27,6 @@
static const char *TAG = "MQTT_EXAMPLE";
static void log_error_if_nonzero(const char *message, int error_code)
{
if (error_code != 0) {
@@ -51,19 +50,18 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
int msg_id;
switch ((esp_mqtt_event_id_t)event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
msg_id = esp_mqtt_client_publish(client, "/topic/qos1", "data_3", 0, 1, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
@@ -73,27 +71,33 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
printf("DATA=%.*s\r\n", event->data_len, event->data);
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno);
ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
}
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
@@ -111,8 +115,10 @@ static void mqtt_app_start(void)
if (strcmp(mqtt_cfg.broker.address.uri, "FROM_STDIN") == 0) {
int count = 0;
printf("Please enter url of mqtt broker\n");
while (count < 128) {
int c = fgetc(stdin);
if (c == '\n') {
line[count] = '\0';
break;
@@ -120,27 +126,27 @@ static void mqtt_app_start(void)
line[count] = c;
++count;
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
mqtt_cfg.broker.address.uri = line;
printf("Broker url: %s\n", line);
} else {
ESP_LOGE(TAG, "Configuration mismatch: wrong broker url");
abort();
}
#endif /* CONFIG_BROKER_URL_FROM_STDIN */
#endif /* CONFIG_BROKER_URL_FROM_STDIN */
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
/* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
/*Let's enqueue a few messages to the outbox to see the allocations*/
int msg_id;
msg_id = esp_mqtt_client_enqueue(client, "/topic/qos1", "data_3", 0, 1, 0, true);
ESP_LOGI(TAG, "Enqueued msg_id=%d", msg_id);
msg_id = esp_mqtt_client_enqueue(client, "/topic/qos2", "QoS2 message", 0, 2, 0, true);
ESP_LOGI(TAG, "Enqueued msg_id=%d", msg_id);
/* Now we start the client and it's possible to see the memory usage for the operations in the outbox. */
esp_mqtt_client_start(client);
}
@@ -150,7 +156,6 @@ void app_main(void)
ESP_LOGI(TAG, "[APP] Startup..");
ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
esp_log_level_set("*", ESP_LOG_INFO);
esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE);
esp_log_level_set("MQTT_EXAMPLE", ESP_LOG_VERBOSE);
@@ -158,16 +163,13 @@ void app_main(void)
esp_log_level_set("esp-tls", ESP_LOG_VERBOSE);
esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
esp_log_level_set("custom_outbox", ESP_LOG_VERBOSE);
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
* Read "Establishing Wi-Fi or Ethernet Connection" section in
* examples/protocols/README.md for more information about this function.
*/
ESP_ERROR_CHECK(example_connect());
mqtt_app_start();
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -24,9 +24,11 @@ constexpr auto TAG = "custom_outbox";
* The trace resource class is created here as an example on how to build a custom memory resource
* The class is only needed to show where we are allocating from and to track allocations and deallocations.
*/
class trace_resource : public std::pmr::memory_resource {
class trace_resource : public std::pmr::memory_resource
{
public:
explicit trace_resource(std::string resource_name, std::pmr::memory_resource *upstream_resource = std::pmr::get_default_resource()) : upstream{upstream_resource}, name{std::move(resource_name)} {}
explicit trace_resource(std::string resource_name,
std::pmr::memory_resource *upstream_resource = std::pmr::get_default_resource()) : upstream{upstream_resource}, name{std::move(resource_name)} {}
[[nodiscard]] std::string_view get_name() const noexcept
{
return std::string_view(name);
@@ -77,11 +79,14 @@ struct outbox_item {
outbox_tick_t tick,
pending_state_t pending_state,
allocator_type alloc = {}
) : message(std::move(message), alloc), id(msg_id), type(msg_type), qos(msg_qos), tick(tick), pending_state(pending_state) {}
) : message(std::move(message), alloc), id(msg_id), type(msg_type), qos(msg_qos), tick(tick),
pending_state(pending_state) {}
/*Copy and move constructors have an extra allocator parameter, for copy default and allocator aware are the same.*/
outbox_item(const outbox_item &other, allocator_type alloc = {}) : message(other.message, alloc), id(other.id), type(other.type), qos(other.qos), tick(other.tick), pending_state(other.pending_state) {}
outbox_item(outbox_item &&other, allocator_type alloc) noexcept : message(std::move(other.message), alloc), id(other.id), type(other.type), qos(other.qos), tick(other.tick), pending_state(other.pending_state)
outbox_item(const outbox_item &other, allocator_type alloc = {}) : message(other.message, alloc), id(other.id),
type(other.type), qos(other.qos), tick(other.tick), pending_state(other.pending_state) {}
outbox_item(outbox_item &&other, allocator_type alloc) noexcept : message(std::move(other.message), alloc),
id(other.id), type(other.type), qos(other.qos), tick(other.tick), pending_state(other.pending_state)
{}
outbox_item(const outbox_item &) = default;
@@ -175,6 +180,7 @@ struct outbox_t {
total_size -= item.get_size();
return true;
}
return false;
});
}
@@ -228,7 +234,8 @@ struct outbox_t {
QUEUED
);
total_size += item.get_size();
ESP_LOGD(TAG, "ENQUEUE msgid=%d, msg_type=%d, len=%d, size=%" PRIu64, message->msg_id, message->msg_type, message->len + message->remaining_len, outbox_get_size(this));
ESP_LOGD(TAG, "ENQUEUE msgid=%d, msg_type=%d, len=%d, size=%" PRIu64, message->msg_id, message->msg_type,
message->len + message->remaining_len, outbox_get_size(this));
return &item;
} catch (const std::exception &e) {
return nullptr;
@@ -244,6 +251,7 @@ struct outbox_t {
if (tick != nullptr) {
*tick = item->get_tick();
}
return &(*item);
}
return nullptr;
@@ -260,6 +268,7 @@ private:
queue.erase(to_erase);
return ESP_OK;
}
return ESP_FAIL;
}
std::size_t total_size{};
@@ -273,17 +282,17 @@ extern "C" {
/* First we create a fixed size memory buffer to be used. */
static constexpr auto work_memory_size = 16 * 1024;
static std::array<std::byte, work_memory_size> resource_buffer{};
try {
/*
* Since the outbox is managed by a C API we can't rely on C++ automatic cleanup and smart pointers but, on production code it would be better to add the
* memory resources to outbox_t, applying RAII principles, and make only outbox_item allocator aware. For the sake of the example we are keeping them
* separated to explictly show the relations.
* First we create the monotonic buffer and add null_memory_resource as upstream. This way if our working memory is exausted an exception is thrown.
* separated to explicitly show the relations.
* First we create the monotonic buffer and add null_memory_resource as upstream. This way if our working memory is exhausted an exception is thrown.
*/
auto *monotonic_resource = new std::pmr::monotonic_buffer_resource{resource_buffer.data(), resource_buffer.size(), std::pmr::null_memory_resource()};
/*Here we add our custom trace wrapper type to trace allocations and deallocations*/
auto *trace_monotonic = new trace_resource("Monotonic", monotonic_resource);
/* We compose monotonic buffer with pool resource, since the monotonic deallocate is a no-op and we need to remove messages to not go out of memory.*/
auto *pool_resource = new std::pmr::unsynchronized_pool_resource{trace_monotonic};
auto *trace_pool = new trace_resource("Pool", pool_resource);
@@ -293,7 +302,6 @@ extern "C" {
} catch (const std::exception &e) {
ESP_LOGD(TAG, "Not enough memory to construct the outbox, review the resource_buffer size");
return nullptr;
}
}
@@ -318,13 +326,13 @@ uint8_t *outbox_item_get_data(outbox_item_handle_t item, size_t *len, uint16_t
if (item == nullptr) {
return nullptr;
}
return item->get_data(len, msg_id, msg_type, qos);
}
esp_err_t outbox_delete_item(outbox_handle_t outbox, outbox_item_handle_t item_to_delete)
{
return outbox->erase(item_to_delete);
}
esp_err_t outbox_delete(outbox_handle_t outbox, int msg_id, int msg_type)
@@ -356,6 +364,7 @@ pending_state_t outbox_item_get_pending(outbox_item_handle_t item)
if (item != nullptr) {
return item->state();
}
return QUEUED;
}
@@ -384,7 +393,6 @@ void outbox_destroy(outbox_handle_t outbox)
auto *pool_resource = static_cast<std::pmr::unsynchronized_pool_resource *>(trace_pool->upstream_resource());
auto *trace_monotonic = static_cast<trace_resource *>(pool_resource->upstream_resource());
auto *monotonic_resource = static_cast<std::pmr::monotonic_buffer_resource *>(trace_monotonic->upstream_resource());
delete monotonic_resource;
delete trace_monotonic;
delete pool_resource;

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -26,10 +26,10 @@ static void log_error_if_nonzero(const char *message, int error_code)
}
static esp_mqtt5_user_property_item_t user_property_arr[] = {
{"board", "esp32"},
{"u", "user"},
{"p", "password"}
};
{"board", "esp32"},
{"u", "user"},
{"p", "password"}
};
#define USE_PROPERTY_ARR_SIZE sizeof(user_property_arr)/sizeof(esp_mqtt5_user_property_item_t)
@@ -72,8 +72,10 @@ static void print_user_property(mqtt5_user_property_handle_t user_property)
{
if (user_property) {
uint8_t count = esp_mqtt5_client_get_user_property_count(user_property);
if (count) {
esp_mqtt5_user_property_item_t *item = malloc(count * sizeof(esp_mqtt5_user_property_item_t));
if (esp_mqtt5_client_get_user_property(user_property, item, &count) == ESP_OK) {
for (int i = 0; i < count; i ++) {
esp_mqtt5_user_property_item_t *t = &item[i];
@@ -82,6 +84,7 @@ static void print_user_property(mqtt5_user_property_handle_t user_property)
free((char *)t->value);
}
}
free(item);
}
}
@@ -103,8 +106,9 @@ static void mqtt5_event_handler(void *handler_args, esp_event_base_t base, int32
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
int msg_id;
ESP_LOGD(TAG, "free heap size is %" PRIu32 ", minimum %" PRIu32, esp_get_free_heap_size(),
esp_get_minimum_free_heap_size());
ESP_LOGD(TAG, "free heap size is %" PRIu32 ", minimum %" PRIu32, esp_get_free_heap_size(), esp_get_minimum_free_heap_size());
switch ((esp_mqtt_event_id_t)event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
@@ -115,21 +119,18 @@ static void mqtt5_event_handler(void *handler_args, esp_event_base_t base, int32
esp_mqtt5_client_delete_user_property(publish_property.user_property);
publish_property.user_property = NULL;
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
esp_mqtt5_client_set_user_property(&subscribe_property.user_property, user_property_arr, USE_PROPERTY_ARR_SIZE);
esp_mqtt5_client_set_subscribe_property(client, &subscribe_property);
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0);
esp_mqtt5_client_delete_user_property(subscribe_property.user_property);
subscribe_property.user_property = NULL;
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
esp_mqtt5_client_set_user_property(&subscribe1_property.user_property, user_property_arr, USE_PROPERTY_ARR_SIZE);
esp_mqtt5_client_set_subscribe_property(client, &subscribe1_property);
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 2);
esp_mqtt5_client_delete_user_property(subscribe1_property.user_property);
subscribe1_property.user_property = NULL;
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
esp_mqtt5_client_set_user_property(&unsubscribe_property.user_property, user_property_arr, USE_PROPERTY_ARR_SIZE);
esp_mqtt5_client_set_unsubscribe_property(client, &unsubscribe_property);
msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos0");
@@ -137,10 +138,12 @@ static void mqtt5_event_handler(void *handler_args, esp_event_base_t base, int32
esp_mqtt5_client_delete_user_property(unsubscribe_property.user_property);
unsubscribe_property.user_property = NULL;
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
print_user_property(event->property->user_property);
break;
case MQTT_EVENT_SUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d, reason code=0x%02x ", event->msg_id, (uint8_t)*event->data);
print_user_property(event->property->user_property);
@@ -148,6 +151,7 @@ static void mqtt5_event_handler(void *handler_args, esp_event_base_t base, int32
msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
print_user_property(event->property->user_property);
@@ -157,10 +161,12 @@ static void mqtt5_event_handler(void *handler_args, esp_event_base_t base, int32
disconnect_property.user_property = NULL;
esp_mqtt_client_disconnect(client);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
print_user_property(event->property->user_property);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
print_user_property(event->property->user_property);
@@ -171,17 +177,21 @@ static void mqtt5_event_handler(void *handler_args, esp_event_base_t base, int32
ESP_LOGI(TAG, "TOPIC=%.*s", event->topic_len, event->topic);
ESP_LOGI(TAG, "DATA=%.*s", event->data_len, event->data);
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
print_user_property(event->property->user_property);
ESP_LOGI(TAG, "MQTT5 return code is %d", event->error_handle->connect_return_code);
if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno);
ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
}
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
@@ -204,7 +214,6 @@ static void mqtt5_app_start(void)
.correlation_data = "123456",
.correlation_data_len = 6,
};
esp_mqtt_client_config_t mqtt5_cfg = {
.broker.address.uri = CONFIG_BROKER_URL,
.session.protocol_ver = MQTT_PROTOCOL_V_5,
@@ -217,15 +226,16 @@ static void mqtt5_app_start(void)
.session.last_will.qos = 1,
.session.last_will.retain = true,
};
#if CONFIG_BROKER_URL_FROM_STDIN
char line[128];
if (strcmp(mqtt5_cfg.uri, "FROM_STDIN") == 0) {
int count = 0;
printf("Please enter url of mqtt broker\n");
while (count < 128) {
int c = fgetc(stdin);
if (c == '\n') {
line[count] = '\0';
break;
@@ -233,29 +243,28 @@ static void mqtt5_app_start(void)
line[count] = c;
++count;
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
mqtt5_cfg.broker.address.uri = line;
printf("Broker url: %s\n", line);
} else {
ESP_LOGE(TAG, "Configuration mismatch: wrong broker url");
abort();
}
#endif /* CONFIG_BROKER_URL_FROM_STDIN */
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg);
/* Set connection properties and user properties */
esp_mqtt5_client_set_user_property(&connect_property.user_property, user_property_arr, USE_PROPERTY_ARR_SIZE);
esp_mqtt5_client_set_user_property(&connect_property.will_user_property, user_property_arr, USE_PROPERTY_ARR_SIZE);
esp_mqtt5_client_set_connect_property(client, &connect_property);
/* If you call esp_mqtt5_client_set_user_property to set user properties, DO NOT forget to delete them.
* esp_mqtt5_client_set_connect_property will malloc buffer to store the user_property and you can delete it after
*/
esp_mqtt5_client_delete_user_property(connect_property.user_property);
esp_mqtt5_client_delete_user_property(connect_property.will_user_property);
/* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt5_event_handler, NULL);
esp_mqtt_client_start(client);
@@ -263,11 +272,9 @@ static void mqtt5_app_start(void)
void app_main(void)
{
ESP_LOGI(TAG, "[APP] Startup..");
ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
esp_log_level_set("*", ESP_LOG_INFO);
esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE);
esp_log_level_set("mqtt_example", ESP_LOG_VERBOSE);
@@ -275,16 +282,13 @@ void app_main(void)
esp_log_level_set("esp-tls", ESP_LOG_VERBOSE);
esp_log_level_set("transport", ESP_LOG_VERBOSE);
esp_log_level_set("outbox", ESP_LOG_VERBOSE);
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
* Read "Establishing Wi-Fi or Ethernet Connection" section in
* examples/protocols/README.md for more information about this function.
*/
ESP_ERROR_CHECK(example_connect());
mqtt5_app_start();
}

View File

@@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* MQTT over SSL Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
@@ -26,9 +31,9 @@
static const char *TAG = "mqtts_example";
#if CONFIG_BROKER_CERTIFICATE_OVERRIDDEN == 1
static const uint8_t mqtt_eclipseprojects_io_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----";
static const uint8_t mqtt_eclipseprojects_io_pem_start[] = "-----BEGIN CERTIFICATE-----\n"
CONFIG_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----";
#else
extern const uint8_t mqtt_eclipseprojects_io_pem_start[] asm("_binary_mqtt_eclipseprojects_io_pem_start");
#endif
@@ -66,18 +71,18 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
int msg_id;
switch ((esp_mqtt_event_id_t)event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1");
ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
@@ -87,23 +92,30 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
printf("DATA=%.*s\r\n", event->data_len, event->data);
if (strncmp(event->data, "send binary please", event->data_len) == 0) {
ESP_LOGI(TAG, "Sending the binary");
send_binary(client);
}
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
ESP_LOGI(TAG, "Last error code reported from esp-tls: 0x%x", event->error_handle->esp_tls_last_esp_err);
ESP_LOGI(TAG, "Last tls stack error number: 0x%x", event->error_handle->esp_tls_stack_err);
@@ -114,7 +126,9 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
} else {
ESP_LOGW(TAG, "Unknown error type: 0x%x", event->error_handle->error_type);
}
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
@@ -129,7 +143,6 @@ static void mqtt_app_start(void)
.verification.certificate = (const char *)mqtt_eclipseprojects_io_pem_start
},
};
ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
/* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
@@ -142,7 +155,6 @@ void app_main(void)
ESP_LOGI(TAG, "[APP] Startup..");
ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
esp_log_level_set("*", ESP_LOG_INFO);
esp_log_level_set("esp-tls", ESP_LOG_VERBOSE);
esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE);
@@ -150,16 +162,13 @@ void app_main(void)
esp_log_level_set("transport_base", ESP_LOG_VERBOSE);
esp_log_level_set("transport", ESP_LOG_VERBOSE);
esp_log_level_set("outbox", ESP_LOG_VERBOSE);
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
* Read "Establishing Wi-Fi or Ethernet Connection" section in
* examples/protocols/README.md for more information about this function.
*/
ESP_ERROR_CHECK(example_connect());
mqtt_app_start();
}

View File

@@ -11,7 +11,7 @@ from threading import Thread
import paho.mqtt.client as mqtt
import pexpect
import pytest
from pytest_embedded import Dut
from pytest_embedded import Dut # noqa: F401
from pytest_embedded_idf.utils import idf_parametrize
event_client_connected = Event()

View File

@@ -2,14 +2,16 @@
| ----------------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
# ESP-MQTT SSL Mutual Authentication with Digital Signature
(See the README.md file in the upper level 'examples' directory for more information about examples.)
Espressif's ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6, ESP32-H2 and ESP32-P4 MCU have a built-in Digital Signature (DS) Peripheral, which provides hardware acceleration for RSA signature. More details can be found at [Digital Signature with ESP-TLS](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/protocols/esp_tls.html#digital-signature-with-esp-tls).
This example connects to the broker test.mosquitto.org using ssl transport with client certificate(RSA) and as a demonstration subscribes/unsubscribes and sends a message on certain topic.The RSA signature operation required in the ssl connection is performed with help of the Digital Signature (DS) peripheral.
(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)
(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>)
It uses ESP-MQTT library which implements mqtt client to connect to mqtt broker.
## How to use example
### Hardware Required
@@ -21,9 +23,11 @@ This example can be executed on any of the supported ESP32 family board (which h
#### 1) Selecting the target
Please select the supported target with the following command:
```
idf.py set-target /* target */
```
More details can be found at [Selecting the target](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html#selecting-the-target).
#### 2) Generate your client key and certificate
@@ -46,15 +50,18 @@ Paste the generated CSR in the [Mosquitto test certificate signer](https://test.
#### 3) Configure the DS peripheral
* i) Install the [esp_secure_cert configuration utility](https://github.com/espressif/esp_secure_cert_mgr/tree/main/tools#esp_secure_cert-configuration-tool) with following command:
```
pip install esp-secure-cert-tool
```
* ii) The DS peripheral can be configured by executing the following command:
```
configure_esp_secure_cert.py -p /* Serial port */ --device-cert /* Device cert */ --private-key /* RSA priv key */ --target_chip /* target chip */ --configure_ds --skip_flash
```
This command shall generate a partition named `esp_secure_cert.bin` in the `esp_secure_cert_data` directory. This partition would be aumatically detected by the build system and flashed at appropriate offset when `idf.py flash` command is used. For this process, the command must be executed in the current folder only.
This command shall generate a partition named `esp_secure_cert.bin` in the `esp_secure_cert_data` directory. This partition would be automatically detected by the build system and flashed at appropriate offset when `idf.py flash` command is used. For this process, the command must be executed in the current folder only.
In the command USB COM port is nothing but the serial port to which the ESP chip is connected. see
[check serial port](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/establish-serial-connection.html#check-port-on-windows) for more details.
@@ -63,6 +70,7 @@ RSA private key is nothing but the client private key ( RSA ) generated in Step
> Note: More details about the `esp-secure-cert-tool` utility can be found [here](https://github.com/espressif/esp_secure_cert_mgr/tree/main/tools).
#### 4) Connection configuration
* Open the project configuration menu (`idf.py menuconfig`)
* 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.

View File

@@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* MQTT Mutual Authentication Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
@@ -51,19 +56,19 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
int msg_id;
// your_context_t *context = event->context;
switch ((esp_mqtt_event_id_t)event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1");
ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
@@ -73,20 +78,25 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
printf("DATA=%.*s\r\n", event->data_len, event->data);
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
@@ -97,14 +107,17 @@ static void mqtt_app_start(void)
{
/* The context is used by the DS peripheral, should not be freed */
esp_ds_data_ctx_t *ds_data = esp_secure_cert_get_ds_ctx();
if (ds_data == NULL) {
ESP_LOGE(TAG, "Error in reading DS data from NVS");
vTaskDelete(NULL);
}
char *device_cert = NULL;
esp_err_t ret;
uint32_t len;
ret = esp_secure_cert_get_device_cert(&device_cert, &len);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to obtain the device certificate");
vTaskDelete(NULL);
@@ -113,7 +126,7 @@ static void mqtt_app_start(void)
const esp_mqtt_client_config_t mqtt_cfg = {
.broker = {
.address.uri = "mqtts://test.mosquitto.org:8884",
.verification.certificate = (const char *)server_cert_pem_start,
.verification.certificate = (const char *)server_cert_pem_start,
},
.credentials = {
.authentication = {
@@ -123,7 +136,6 @@ static void mqtt_app_start(void)
},
},
};
ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
@@ -135,22 +147,18 @@ void app_main(void)
ESP_LOGI(TAG, "[APP] Startup..");
ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
esp_log_level_set("*", ESP_LOG_INFO);
esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE);
esp_log_level_set("transport_base", ESP_LOG_VERBOSE);
esp_log_level_set("transport", ESP_LOG_VERBOSE);
esp_log_level_set("outbox", ESP_LOG_VERBOSE);
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
* Read "Establishing Wi-Fi or Ethernet Connection" section in
* examples/protocols/README.md for more information about this function.
*/
ESP_ERROR_CHECK(example_connect());
mqtt_app_start();
}

View File

@@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* MQTT Mutual Authentication Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
@@ -61,18 +66,18 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
int msg_id;
switch ((esp_mqtt_event_id_t)event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1");
ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
@@ -82,27 +87,33 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
printf("DATA=%.*s\r\n", event->data_len, event->data);
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno);
ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
}
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
@@ -111,17 +122,16 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
static void mqtt_app_start(void)
{
const esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = "mqtts://test.mosquitto.org:8884",
.broker.verification.certificate = (const char *)server_cert_pem_start,
.credentials = {
.authentication = {
.certificate = (const char *)client_cert_pem_start,
.key = (const char *)client_key_pem_start,
},
}
};
const esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = "mqtts://test.mosquitto.org:8884",
.broker.verification.certificate = (const char *)server_cert_pem_start,
.credentials = {
.authentication = {
.certificate = (const char *)client_cert_pem_start,
.key = (const char *)client_key_pem_start,
},
}
};
ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
/* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
@@ -134,22 +144,18 @@ void app_main(void)
ESP_LOGI(TAG, "[APP] Startup..");
ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
esp_log_level_set("*", ESP_LOG_INFO);
esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE);
esp_log_level_set("transport_base", ESP_LOG_VERBOSE);
esp_log_level_set("transport", ESP_LOG_VERBOSE);
esp_log_level_set("outbox", ESP_LOG_VERBOSE);
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
* Read "Establishing Wi-Fi or Ethernet Connection" section in
* examples/protocols/README.md for more information about this function.
*/
ESP_ERROR_CHECK(example_connect());
mqtt_app_start();
}

View File

@@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* MQTT over SSL Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
@@ -47,10 +52,10 @@ static const char *TAG = "mqtts_example";
static const uint8_t s_key[] = { 0xBA, 0xD1, 0x23 };
static const psk_hint_key_t psk_hint_key = {
.key = s_key,
.key_size = sizeof(s_key),
.hint = "hint"
};
.key = s_key,
.key_size = sizeof(s_key),
.hint = "hint"
};
/*
* @brief Event handler registered to receive MQTT events
@@ -68,55 +73,58 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
int msg_id;
switch ((esp_mqtt_event_id_t)event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1");
ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
break;
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1");
ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
case MQTT_EVENT_SUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d, return code=0x%02x ", event->msg_id, (uint8_t)*event->data);
msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_SUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d, return code=0x%02x ", event->msg_id, (uint8_t)*event->data);
msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
printf("DATA=%.*s\r\n", event->data_len, event->data);
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
printf("DATA=%.*s\r\n", event->data_len, event->data);
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
}
}
static void mqtt_app_start(void)
{
const esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = EXAMPLE_BROKER_URI,
.broker.verification.psk_hint_key = &psk_hint_key,
};
ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
/* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
@@ -129,23 +137,19 @@ void app_main(void)
ESP_LOGI(TAG, "[APP] Startup..");
ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
esp_log_level_set("*", ESP_LOG_INFO);
esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE);
esp_log_level_set("transport_base", ESP_LOG_VERBOSE);
esp_log_level_set("esp-tls", ESP_LOG_VERBOSE);
esp_log_level_set("transport", ESP_LOG_VERBOSE);
esp_log_level_set("outbox", ESP_LOG_VERBOSE);
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
* Read "Establishing Wi-Fi or Ethernet Connection" section in
* examples/protocols/README.md for more information about this function.
*/
ESP_ERROR_CHECK(example_connect());
mqtt_app_start();
}

View File

@@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* MQTT (over TCP) Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
@@ -23,7 +28,6 @@
static const char *TAG = "mqtt_example";
static void log_error_if_nonzero(const char *message, int error_code)
{
if (error_code != 0) {
@@ -47,21 +51,20 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
int msg_id;
switch ((esp_mqtt_event_id_t)event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
msg_id = esp_mqtt_client_publish(client, "/topic/qos1", "data_3", 0, 1, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1");
ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
@@ -71,27 +74,33 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
printf("DATA=%.*s\r\n", event->data_len, event->data);
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno);
ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
}
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
@@ -109,8 +118,10 @@ static void mqtt_app_start(void)
if (strcmp(mqtt_cfg.broker.address.uri, "FROM_STDIN") == 0) {
int count = 0;
printf("Please enter url of mqtt broker\n");
while (count < 128) {
int c = fgetc(stdin);
if (c == '\n') {
line[count] = '\0';
break;
@@ -118,16 +129,18 @@ static void mqtt_app_start(void)
line[count] = c;
++count;
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
mqtt_cfg.broker.address.uri = line;
printf("Broker url: %s\n", line);
} else {
ESP_LOGE(TAG, "Configuration mismatch: wrong broker url");
abort();
}
#endif /* CONFIG_BROKER_URL_FROM_STDIN */
#endif /* CONFIG_BROKER_URL_FROM_STDIN */
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
/* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
@@ -139,7 +152,6 @@ void app_main(void)
ESP_LOGI(TAG, "[APP] Startup..");
ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
esp_log_level_set("*", ESP_LOG_INFO);
esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE);
esp_log_level_set("mqtt_example", ESP_LOG_VERBOSE);
@@ -147,16 +159,13 @@ void app_main(void)
esp_log_level_set("esp-tls", ESP_LOG_VERBOSE);
esp_log_level_set("transport", ESP_LOG_VERBOSE);
esp_log_level_set("outbox", ESP_LOG_VERBOSE);
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
* Read "Establishing Wi-Fi or Ethernet Connection" section in
* examples/protocols/README.md for more information about this function.
*/
ESP_ERROR_CHECK(example_connect());
mqtt_app_start();
}

View File

@@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* MQTT over Websockets Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
@@ -54,6 +59,7 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
int msg_id;
switch ((esp_mqtt_event_id_t)event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
@@ -61,13 +67,12 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1");
ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
@@ -77,27 +82,33 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
printf("DATA=%.*s\r\n", event->data_len, event->data);
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno);
ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
}
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
@@ -109,7 +120,6 @@ static void mqtt_app_start(void)
const esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = CONFIG_BROKER_URI,
};
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
/* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
@@ -121,7 +131,6 @@ void app_main(void)
ESP_LOGI(TAG, "[APP] Startup..");
ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
esp_log_level_set("*", ESP_LOG_INFO);
esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE);
esp_log_level_set("mqtt_example", ESP_LOG_VERBOSE);
@@ -129,16 +138,13 @@ void app_main(void)
esp_log_level_set("transport_ws", ESP_LOG_VERBOSE);
esp_log_level_set("transport", ESP_LOG_VERBOSE);
esp_log_level_set("outbox", ESP_LOG_VERBOSE);
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
* Read "Establishing Wi-Fi or Ethernet Connection" section in
* examples/protocols/README.md for more information about this function.
*/
ESP_ERROR_CHECK(example_connect());
mqtt_app_start();
}

View File

@@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* MQTT over Secure Websockets Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
@@ -31,9 +36,9 @@
static const char *TAG = "mqttwss_example";
#if CONFIG_BROKER_CERTIFICATE_OVERRIDDEN == 1
static const uint8_t mqtt_eclipseprojects_io_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----";
static const uint8_t mqtt_eclipseprojects_io_pem_start[] = "-----BEGIN CERTIFICATE-----\n"
CONFIG_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----";
#else
extern const uint8_t mqtt_eclipseprojects_io_pem_start[] asm("_binary_mqtt_eclipseprojects_io_pem_start");
#endif
@@ -43,19 +48,19 @@ static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
{
esp_mqtt_client_handle_t client = event->client;
int msg_id;
// your_context_t *context = event->context;
switch (event->event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1");
ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
@@ -65,24 +70,30 @@ static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
printf("DATA=%.*s\r\n", event->data_len, event->data);
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
}
return ESP_OK;
}
@@ -99,12 +110,10 @@ static void mqtt_app_start(void)
.broker.address.uri = CONFIG_BROKER_URI,
.broker.verification.certificate = (const char *)mqtt_eclipseprojects_io_pem_start,
};
ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
/* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
esp_mqtt_client_start(client);
}
@@ -113,23 +122,19 @@ void app_main(void)
ESP_LOGI(TAG, "[APP] Startup..");
ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
esp_log_level_set("*", ESP_LOG_INFO);
esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE);
esp_log_level_set("mqtt_example", ESP_LOG_VERBOSE);
esp_log_level_set("transport_base", ESP_LOG_VERBOSE);
esp_log_level_set("transport", ESP_LOG_VERBOSE);
esp_log_level_set("outbox", ESP_LOG_VERBOSE);
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
* Read "Establishing Wi-Fi or Ethernet Connection" section in
* examples/protocols/README.md for more information about this function.
*/
ESP_ERROR_CHECK(example_connect());
mqtt_app_start();
}

View File

@@ -13,7 +13,7 @@ from threading import Thread
import paho.mqtt.client as mqtt
import pexpect
import pytest
from pytest_embedded import Dut
from pytest_embedded import Dut # noqa: F401
from pytest_embedded_idf.utils import idf_parametrize
event_client_connected = Event()
@@ -49,7 +49,7 @@ def on_message(client, userdata, msg): # type: (mqtt.Client, tuple, mqtt.client
@pytest.mark.ethernet
@idf_parametrize('target', ['esp32'], indirect=['target'])
def test_examples_protocol_mqtt_wss(dut): # type: (Dut) -> None
def test_examples_protocol_mqtt_wss(dut): # type: (Dut) -> None # type: ignore
broker_url = ''
broker_port = 0
"""

View File

@@ -19,5 +19,3 @@ tags:
dependencies:
idf:
version: ">=5.3"

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -76,15 +76,18 @@ typedef struct {
uint16_t topic_alias_maximum; /*!< The maximum topic alias that we support */
bool request_resp_info; /*!< This value to request Server to return Response information */
bool request_problem_info; /*!< This value to indicate whether the reason string or user properties are sent in case of failures */
mqtt5_user_property_handle_t user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
mqtt5_user_property_handle_t
user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
uint32_t will_delay_interval; /*!< The time interval that server delays publishing will message */
uint32_t message_expiry_interval; /*!< The time interval that message expiry */
bool payload_format_indicator; /*!< This value is to indicator will message payload format */
const char *content_type; /*!< This value is to indicator will message content type, use a MIME content type string */
const char
*content_type; /*!< This value is to indicator will message content type, use a MIME content type string */
const char *response_topic; /*!< Topic name for a response message */
const char *correlation_data; /*!< Binary data for receiver to match the response message */
uint16_t correlation_data_len; /*!< The length of correlation data */
mqtt5_user_property_handle_t will_user_property; /*!< The handle for will message user property, call function esp_mqtt5_client_set_user_property to set it */
mqtt5_user_property_handle_t
will_user_property; /*!< The handle for will message user property, call function esp_mqtt5_client_set_user_property to set it */
} esp_mqtt5_connection_property_config_t;
/**
@@ -93,12 +96,14 @@ typedef struct {
typedef struct {
bool payload_format_indicator; /*!< This value is to indicator publish message payload format */
uint32_t message_expiry_interval; /*!< The time interval that message expiry */
uint16_t topic_alias; /*!< An interger value to identify the topic instead of using topic name string */
uint16_t topic_alias; /*!< An integer value to identify the topic instead of using topic name string */
const char *response_topic; /*!< Topic name for a response message */
const char *correlation_data; /*!< Binary data for receiver to match the response message */
uint16_t correlation_data_len; /*!< The length of correlation data */
const char *content_type; /*!< This value is to indicator publish message content type, use a MIME content type string */
mqtt5_user_property_handle_t user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
const char
*content_type; /*!< This value is to indicator publish message content type, use a MIME content type string */
mqtt5_user_property_handle_t
user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
} esp_mqtt5_publish_property_config_t;
/**
@@ -110,8 +115,10 @@ typedef struct {
bool retain_as_published_flag; /*!< Subscription Option to keep the retain flag as published option */
uint8_t retain_handle; /*!< Subscription Option to handle retain option */
bool is_share_subscribe; /*!< Whether subscribe is a shared subscription */
const char *share_name; /*!< The name of shared subscription which is a part of $share/{share_name}/{topic} */
mqtt5_user_property_handle_t user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
const char
*share_name; /*!< The name of shared subscription which is a part of $share/{share_name}/{topic} */
mqtt5_user_property_handle_t
user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
} esp_mqtt5_subscribe_property_config_t;
/**
@@ -119,8 +126,10 @@ typedef struct {
*/
typedef struct {
bool is_share_subscribe; /*!< Whether subscribe is a shared subscription */
const char *share_name; /*!< The name of shared subscription which is a part of $share/{share_name}/{topic} */
mqtt5_user_property_handle_t user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
const char
*share_name; /*!< The name of shared subscription which is a part of $share/{share_name}/{topic} */
mqtt5_user_property_handle_t
user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
} esp_mqtt5_unsubscribe_property_config_t;
/**
@@ -128,8 +137,9 @@ typedef struct {
*/
typedef struct {
uint32_t session_expiry_interval; /*!< The interval time of session expiry */
uint8_t disconnect_reason; /*!< The reason that connection disconnet, refer to mqtt5_error_reason_code */
mqtt5_user_property_handle_t user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
uint8_t disconnect_reason; /*!< The reason that connection disconnect, refer to mqtt5_error_reason_code */
mqtt5_user_property_handle_t
user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
} esp_mqtt5_disconnect_property_config_t;
/**
@@ -144,7 +154,8 @@ typedef struct {
char *content_type; /*!< Content type of the message */
int content_type_len; /*!< Content type length of the message */
uint16_t subscribe_id; /*!< Subscription identifier of the message */
mqtt5_user_property_handle_t user_property; /*!< The handle for user property, call function esp_mqtt5_client_delete_user_property to free the memory */
mqtt5_user_property_handle_t
user_property; /*!< The handle for user property, call function esp_mqtt5_client_delete_user_property to free the memory */
} esp_mqtt5_event_property_t;
/**
@@ -166,7 +177,8 @@ typedef struct {
* ESP_FAIL on fail
* ESP_OK on success
*/
esp_err_t esp_mqtt5_client_set_connect_property(esp_mqtt5_client_handle_t client, const esp_mqtt5_connection_property_config_t *connect_property);
esp_err_t esp_mqtt5_client_set_connect_property(esp_mqtt5_client_handle_t client,
const esp_mqtt5_connection_property_config_t *connect_property);
/**
* @brief Set MQTT5 client publish property configuration
@@ -181,7 +193,8 @@ esp_err_t esp_mqtt5_client_set_connect_property(esp_mqtt5_client_handle_t client
* ESP_FAIL on fail
* ESP_OK on success
*/
esp_err_t esp_mqtt5_client_set_publish_property(esp_mqtt5_client_handle_t client, const esp_mqtt5_publish_property_config_t *property);
esp_err_t esp_mqtt5_client_set_publish_property(esp_mqtt5_client_handle_t client,
const esp_mqtt5_publish_property_config_t *property);
/**
* @brief Set MQTT5 client subscribe property configuration
@@ -196,7 +209,8 @@ esp_err_t esp_mqtt5_client_set_publish_property(esp_mqtt5_client_handle_t client
* ESP_FAIL on fail
* ESP_OK on success
*/
esp_err_t esp_mqtt5_client_set_subscribe_property(esp_mqtt5_client_handle_t client, const esp_mqtt5_subscribe_property_config_t *property);
esp_err_t esp_mqtt5_client_set_subscribe_property(esp_mqtt5_client_handle_t client,
const esp_mqtt5_subscribe_property_config_t *property);
/**
* @brief Set MQTT5 client unsubscribe property configuration
@@ -211,7 +225,8 @@ esp_err_t esp_mqtt5_client_set_subscribe_property(esp_mqtt5_client_handle_t clie
* ESP_FAIL on fail
* ESP_OK on success
*/
esp_err_t esp_mqtt5_client_set_unsubscribe_property(esp_mqtt5_client_handle_t client, const esp_mqtt5_unsubscribe_property_config_t *property);
esp_err_t esp_mqtt5_client_set_unsubscribe_property(esp_mqtt5_client_handle_t client,
const esp_mqtt5_unsubscribe_property_config_t *property);
/**
* @brief Set MQTT5 client disconnect property configuration
@@ -227,7 +242,8 @@ esp_err_t esp_mqtt5_client_set_unsubscribe_property(esp_mqtt5_client_handle_t cl
* ESP_FAIL on fail
* ESP_OK on success
*/
esp_err_t esp_mqtt5_client_set_disconnect_property(esp_mqtt5_client_handle_t client, const esp_mqtt5_disconnect_property_config_t *property);
esp_err_t esp_mqtt5_client_set_disconnect_property(esp_mqtt5_client_handle_t client,
const esp_mqtt5_disconnect_property_config_t *property);
/**
* @brief Set MQTT5 client user property configuration
@@ -244,7 +260,8 @@ esp_err_t esp_mqtt5_client_set_disconnect_property(esp_mqtt5_client_handle_t cli
* ESP_FAIL on fail
* ESP_OK on success
*/
esp_err_t esp_mqtt5_client_set_user_property(mqtt5_user_property_handle_t *user_property, esp_mqtt5_user_property_item_t item[], uint8_t item_num);
esp_err_t esp_mqtt5_client_set_user_property(mqtt5_user_property_handle_t *user_property,
esp_mqtt5_user_property_item_t item[], uint8_t item_num);
/**
* @brief Get MQTT5 client user property
@@ -261,7 +278,8 @@ esp_err_t esp_mqtt5_client_set_user_property(mqtt5_user_property_handle_t *user_
* ESP_FAIL on fail
* ESP_OK on success
*/
esp_err_t esp_mqtt5_client_get_user_property(mqtt5_user_property_handle_t user_property, esp_mqtt5_user_property_item_t *item, uint8_t *item_num);
esp_err_t esp_mqtt5_client_get_user_property(mqtt5_user_property_handle_t user_property,
esp_mqtt5_user_property_item_t *item, uint8_t *item_num);
/**
* @brief Get MQTT5 client user property list count

View File

@@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* This file is subject to the terms and conditions defined in
* file 'LICENSE', which is part of this source code package.
@@ -215,7 +220,8 @@ typedef struct esp_mqtt_event_t {
bool retain; /*!< Retained flag of the message associated with this event */
int qos; /*!< QoS of the messages associated with this event */
bool dup; /*!< dup flag of the message associated with this event */
esp_mqtt_protocol_ver_t protocol_ver; /*!< MQTT protocol version used for connection, defaults to value from menuconfig*/
esp_mqtt_protocol_ver_t
protocol_ver; /*!< MQTT protocol version used for connection, defaults to value from menuconfig*/
#ifdef CONFIG_MQTT_PROTOCOL_5
esp_mqtt5_event_property_t *property; /*!< MQTT 5 property associated with this event */
#endif
@@ -260,7 +266,8 @@ typedef struct esp_mqtt_client_config_t {
documentation for details. */
esp_err_t (*crt_bundle_attach)(void *conf); /*!< Pointer to ESP x509 Certificate Bundle attach function for
the usage of certificate bundles. Client only attach the bundle, the clean up must be done by the user. */
const char *certificate; /*!< Certificate data, default is NULL. It's not copied nor freed by the client, user needs to clean up.*/
const char
*certificate; /*!< Certificate data, default is NULL. It's not copied nor freed by the client, user needs to clean up.*/
size_t certificate_len; /*!< Length of the buffer pointed to by certificate. */
const struct psk_key_hint *psk_hint_key; /*!< Pointer to PSK struct defined in esp_tls.h to enable PSK
authentication (as alternative to certificate verification).
@@ -343,7 +350,7 @@ typedef struct esp_mqtt_client_config_t {
* Network related configuration
*/
struct network_t {
int reconnect_timeout_ms; /*!< Reconnect to the broker after this value in miliseconds if auto reconnect is not
int reconnect_timeout_ms; /*!< Reconnect to the broker after this value in milliseconds if auto reconnect is not
disabled (defaults to 10s) */
int timeout_ms; /*!< Abort network operation if it is not completed after this value, in milliseconds
(defaults to 10s). */
@@ -351,8 +358,9 @@ typedef struct esp_mqtt_client_config_t {
bool disable_auto_reconnect; /*!< Client will reconnect to server (when errors/disconnect). Set
`disable_auto_reconnect=true` to disable */
esp_transport_keep_alive_t tcp_keep_alive_cfg; /*!< Transport keep-alive config*/
esp_transport_handle_t transport; /*!< Custom transport handle to use, leave it NULL to allow MQTT client create or recreate its own. Warning: The transport should be valid during the client lifetime and is destroyed when esp_mqtt_client_destroy is called. */
struct ifreq * if_name; /*!< The name of interface for data to go through. Use the default interface without setting */
esp_transport_handle_t
transport; /*!< Custom transport handle to use, leave it NULL to allow MQTT client create or recreate its own. Warning: The transport should be valid during the client lifetime and is destroyed when esp_mqtt_client_destroy is called. */
struct ifreq *if_name; /*!< The name of interface for data to go through. Use the default interface without setting */
} network; /*!< Network configuration */
/**
* Client task configuration
@@ -364,7 +372,7 @@ typedef struct esp_mqtt_client_config_t {
/**
* Client buffer size configuration
*
* Client have two buffers for input and output respectivelly.
* Client have two buffers for input and output respectively.
*/
struct buffer_t {
int size; /*!< size of *MQTT* send/receive buffer*/
@@ -614,7 +622,7 @@ esp_err_t esp_mqtt_client_destroy(esp_mqtt_client_handle_t client);
* (i.e. on "before_connect" event
*
* Notes:
* - When calling this function make sure to have all the intendend configurations
* - When calling this function make sure to have all the intended configurations
* set, otherwise default values are set.
* @param client *MQTT* client handle
*
@@ -655,7 +663,8 @@ esp_err_t esp_mqtt_client_register_event(esp_mqtt_client_handle_t client,
* ESP_ERR_INVALID_ARG on invalid event ID
* ESP_OK on success
*/
esp_err_t esp_mqtt_client_unregister_event(esp_mqtt_client_handle_t client, esp_mqtt_event_id_t event, esp_event_handler_t event_handler);
esp_err_t esp_mqtt_client_unregister_event(esp_mqtt_client_handle_t client, esp_mqtt_event_id_t event,
esp_event_handler_t event_handler);
/**
* @brief Get outbox size

View File

@@ -1,16 +1,8 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _MQTT_SUPPORTED_FEATURES_H_
#define _MQTT_SUPPORTED_FEATURES_H_

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -48,7 +48,8 @@ void esp_mqtt5_client_destory(esp_mqtt5_client_handle_t client);
esp_err_t esp_mqtt5_client_publish_check(esp_mqtt5_client_handle_t client, int qos, int retain);
esp_err_t esp_mqtt5_client_subscribe_check(esp_mqtt5_client_handle_t client, int qos);
esp_err_t esp_mqtt5_create_default_config(esp_mqtt5_client_handle_t client);
esp_err_t esp_mqtt5_get_publish_data(esp_mqtt5_client_handle_t client, uint8_t *msg_buf, size_t msg_read_len, char **msg_topic, size_t *msg_topic_len, char **msg_data, size_t *msg_data_len);
esp_err_t esp_mqtt5_get_publish_data(esp_mqtt5_client_handle_t client, uint8_t *msg_buf, size_t msg_read_len,
char **msg_topic, size_t *msg_topic_len, char **msg_data, size_t *msg_data_len);
#ifdef __cplusplus
}
#endif //__cplusplus

View File

@@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef MQTT5_MSG_H
#define MQTT5_MSG_H
#include <stdint.h>
@@ -119,16 +124,26 @@ typedef struct {
#define mqtt5_get_pubcomp_data mqtt5_get_puback_data
uint16_t mqtt5_get_id(uint8_t *buffer, size_t length);
char *mqtt5_get_publish_property_payload(uint8_t *buffer, size_t buffer_length, char **msg_topic, size_t *msg_topic_len, esp_mqtt5_publish_resp_property_t *resp_property, uint16_t *property_len, size_t *payload_len, mqtt5_user_property_handle_t *user_property);
char *mqtt5_get_publish_property_payload(uint8_t *buffer, size_t buffer_length, char **msg_topic, size_t *msg_topic_len,
esp_mqtt5_publish_resp_property_t *resp_property, uint16_t *property_len, size_t *payload_len,
mqtt5_user_property_handle_t *user_property);
char *mqtt5_get_suback_data(uint8_t *buffer, size_t *length, mqtt5_user_property_handle_t *user_property);
char *mqtt5_get_puback_data(uint8_t *buffer, size_t *length, mqtt5_user_property_handle_t *user_property);
mqtt_message_t *mqtt5_msg_connect(mqtt_connection_t *connection, mqtt_connect_info_t *info, esp_mqtt5_connection_property_storage_t *property, esp_mqtt5_connection_will_property_storage_t *will_property);
mqtt_message_t *mqtt5_msg_publish(mqtt_connection_t *connection, const char *topic, const char *data, int data_length, int qos, int retain, uint16_t *message_id, const esp_mqtt5_publish_property_config_t *property, const char *resp_info);
esp_err_t mqtt5_msg_parse_connack_property(uint8_t *buffer, size_t buffer_len, mqtt_connect_info_t *connection_info, esp_mqtt5_connection_property_storage_t *connection_property, esp_mqtt5_connection_server_resp_property_t *resp_property, int *reason_code, uint8_t *ack_flag, mqtt5_user_property_handle_t *user_property);
mqtt_message_t *mqtt5_msg_connect(mqtt_connection_t *connection, mqtt_connect_info_t *info,
esp_mqtt5_connection_property_storage_t *property, esp_mqtt5_connection_will_property_storage_t *will_property);
mqtt_message_t *mqtt5_msg_publish(mqtt_connection_t *connection, const char *topic, const char *data, int data_length,
int qos, int retain, uint16_t *message_id, const esp_mqtt5_publish_property_config_t *property, const char *resp_info);
esp_err_t mqtt5_msg_parse_connack_property(uint8_t *buffer, size_t buffer_len, mqtt_connect_info_t *connection_info,
esp_mqtt5_connection_property_storage_t *connection_property,
esp_mqtt5_connection_server_resp_property_t *resp_property, int *reason_code, uint8_t *ack_flag,
mqtt5_user_property_handle_t *user_property);
int mqtt5_msg_get_reason_code(uint8_t *buffer, size_t length);
mqtt_message_t *mqtt5_msg_subscribe(mqtt_connection_t *connection, const esp_mqtt_topic_t *topic, int size, uint16_t *message_id, const esp_mqtt5_subscribe_property_config_t *property);
mqtt_message_t *mqtt5_msg_unsubscribe(mqtt_connection_t *connection, const char *topic, uint16_t *message_id, const esp_mqtt5_unsubscribe_property_config_t *property);
mqtt_message_t *mqtt5_msg_disconnect(mqtt_connection_t *connection, esp_mqtt5_disconnect_property_config_t *disconnect_property_info);
mqtt_message_t *mqtt5_msg_subscribe(mqtt_connection_t *connection, const esp_mqtt_topic_t *topic, int size,
uint16_t *message_id, const esp_mqtt5_subscribe_property_config_t *property);
mqtt_message_t *mqtt5_msg_unsubscribe(mqtt_connection_t *connection, const char *topic, uint16_t *message_id,
const esp_mqtt5_unsubscribe_property_config_t *property);
mqtt_message_t *mqtt5_msg_disconnect(mqtt_connection_t *connection,
esp_mqtt5_disconnect_property_config_t *disconnect_property_info);
mqtt_message_t *mqtt5_msg_pubcomp(mqtt_connection_t *connection, uint16_t message_id);
mqtt_message_t *mqtt5_msg_pubrel(mqtt_connection_t *connection, uint16_t message_id);
mqtt_message_t *mqtt5_msg_pubrec(mqtt_connection_t *connection, uint16_t message_id);
@@ -139,4 +154,3 @@ mqtt_message_t *mqtt5_msg_puback(mqtt_connection_t *connection, uint16_t message
#endif
#endif /* MQTT5_MSG_H */

View File

@@ -102,7 +102,7 @@ typedef struct {
int message_retransmit_timeout;
uint64_t outbox_limit;
esp_transport_handle_t transport;
struct ifreq * if_name;
struct ifreq *if_name;
esp_transport_keep_alive_t tcp_keep_alive_cfg;
} mqtt_config_storage_t;

View File

@@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* This file is subject to the terms and conditions defined in
* file 'LICENSE', which is part of this source code package.

View File

@@ -1,3 +1,9 @@
/*
* SPDX-FileCopyrightText: 2014 Stephen Robinson
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MQTT_MSG_H
#define MQTT_MSG_H
#include <stdint.h>
@@ -9,41 +15,10 @@
extern "C" {
#endif
/*
* Copyright (c) 2014, Stephen Robinson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
/* 7 6 5 4 3 2 1 0 */
/*| --- Message Type---- | DUP Flag | QoS Level | Retain | */
/* Remaining Length */
enum mqtt_message_type {
MQTT_MSG_TYPE_CONNECT = 1,
MQTT_MSG_TYPE_CONNACK = 2,
@@ -134,12 +109,14 @@ esp_err_t mqtt_msg_buffer_init(mqtt_connection_t *connection, int buffer_size);
void mqtt_msg_buffer_destroy(mqtt_connection_t *connection);
mqtt_message_t *mqtt_msg_connect(mqtt_connection_t *connection, mqtt_connect_info_t *info);
mqtt_message_t *mqtt_msg_publish(mqtt_connection_t *connection, const char *topic, const char *data, int data_length, int qos, int retain, uint16_t *message_id);
mqtt_message_t *mqtt_msg_publish(mqtt_connection_t *connection, const char *topic, const char *data, int data_length,
int qos, int retain, uint16_t *message_id);
mqtt_message_t *mqtt_msg_puback(mqtt_connection_t *connection, uint16_t message_id);
mqtt_message_t *mqtt_msg_pubrec(mqtt_connection_t *connection, uint16_t message_id);
mqtt_message_t *mqtt_msg_pubrel(mqtt_connection_t *connection, uint16_t message_id);
mqtt_message_t *mqtt_msg_pubcomp(mqtt_connection_t *connection, uint16_t message_id);
mqtt_message_t *mqtt_msg_subscribe(mqtt_connection_t *connection, const esp_mqtt_topic_t topic_list[], int size, uint16_t *message_id) __attribute__((nonnull));
mqtt_message_t *mqtt_msg_subscribe(mqtt_connection_t *connection, const esp_mqtt_topic_t topic_list[], int size,
uint16_t *message_id) __attribute__((nonnull));
mqtt_message_t *mqtt_msg_unsubscribe(mqtt_connection_t *connection, const char *topic, uint16_t *message_id);
mqtt_message_t *mqtt_msg_pingreq(mqtt_connection_t *connection);
mqtt_message_t *mqtt_msg_pingresp(mqtt_connection_t *connection);
@@ -149,4 +126,3 @@ mqtt_message_t *mqtt_msg_disconnect(mqtt_connection_t *connection);
#endif
#endif /* MQTT_MSG_H */

View File

@@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* This file is subject to the terms and conditions defined in
* file 'LICENSE', which is part of this source code package.

View File

@@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* This file is subject to the terms and conditions defined in
* file 'LICENSE', which is part of this source code package.

View File

@@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* This file is subject to the terms and conditions defined in
* file 'LICENSE', which is part of this source code package.

File diff suppressed because it is too large Load Diff

View File

@@ -1,33 +1,8 @@
/*
* Copyright (c) 2014, Stephen Robinson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
* SPDX-FileCopyrightText: 2014 Stephen Robinson
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <string.h>
#include "mqtt_client.h"
#include "mqtt_msg.h"
@@ -56,7 +31,6 @@ static int append_string(mqtt_connection_t *connection, const char *string, int
connection->buffer[connection->outbound_message.length++] = len & 0xff;
memcpy(connection->buffer + connection->outbound_message.length, string, len);
connection->outbound_message.length += len;
return len + 2;
}
@@ -78,7 +52,6 @@ static uint16_t append_message_id(mqtt_connection_t *connection, uint16_t messag
connection->buffer[connection->outbound_message.length++] = message_id >> 8;
connection->buffer[connection->outbound_message.length++] = message_id & 0xff;
return message_id;
}
@@ -101,6 +74,7 @@ static mqtt_message_t *fini_message(mqtt_connection_t *connection, int type, int
int total_length = message_length;
int encoded_length = 0;
uint8_t encoded_lens[4] = {0};
// Check if we have fragmented message and update total_len
if (connection->outbound_message.fragmented_msg_total_length) {
total_length = connection->outbound_message.fragmented_msg_total_length - MQTT_MAX_FIXED_HEADER_SIZE;
@@ -108,12 +82,15 @@ static mqtt_message_t *fini_message(mqtt_connection_t *connection, int type, int
// Encode MQTT message length
int len_bytes = 0; // size of encoded message length
do {
encoded_length = total_length % 128;
total_length /= 128;
if (total_length > 0) {
encoded_length |= 0x80;
}
encoded_lens[len_bytes] = encoded_length;
len_bytes++;
} while (total_length > 0);
@@ -129,7 +106,8 @@ static mqtt_message_t *fini_message(mqtt_connection_t *connection, int type, int
connection->outbound_message.data = connection->buffer + offs;
connection->outbound_message.fragmented_msg_data_offset -= offs;
// type byte
connection->buffer[offs++] = ((type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1);
connection->buffer[offs++] = ((type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1);
// length bytes
for (int j = 0; j < len_bytes; j++) {
connection->buffer[offs++] = encoded_lens[j];
@@ -145,12 +123,15 @@ size_t mqtt_get_total_length(const uint8_t *buffer, size_t length, int *fixed_si
for (i = 1; i < length; ++i) {
totlen += (buffer[i] & 0x7f) << (7 * (i - 1));
if ((buffer[i] & 0x80) == 0) {
++i;
break;
}
}
totlen += i;
if (fixed_size_len) {
*fixed_size_len = i;
}
@@ -167,24 +148,27 @@ bool mqtt_header_complete(uint8_t *buffer, size_t buffer_length)
if (i >= buffer_length) {
return false;
}
if ((buffer[i] & 0x80) == 0) {
++i;
break;
}
}
// i is now the length of the fixed header
if (i + 2 >= buffer_length) {
return false;
}
topiclen = buffer[i++] << 8;
topiclen |= buffer[i++];
i += topiclen;
if (mqtt_get_qos(buffer) > 0) {
i += 2;
}
// i is now the length of the fixed + variable header
return buffer_length >= i;
}
@@ -204,6 +188,7 @@ char *mqtt_get_publish_topic(uint8_t *buffer, size_t *length)
if (i + 2 >= *length) {
return NULL;
}
topiclen = buffer[i++] << 8;
topiclen |= buffer[i++];
@@ -225,16 +210,19 @@ char *mqtt_get_publish_data(uint8_t *buffer, size_t *length)
for (i = 1; i < blength; ++i) {
totlen += (buffer[i] & 0x7f) << (7 * (i - 1));
if ((buffer[i] & 0x80) == 0) {
++i;
break;
}
}
totlen += i;
if (i + 2 >= blength) {
return NULL;
}
topiclen = buffer[i++] << 8;
topiclen |= buffer[i++];
@@ -248,6 +236,7 @@ char *mqtt_get_publish_data(uint8_t *buffer, size_t *length)
if (i + 2 >= blength) {
return NULL;
}
i += 2;
}
@@ -260,6 +249,7 @@ char *mqtt_get_publish_data(uint8_t *buffer, size_t *length)
} else {
*length = blength - i;
}
return (char *)(buffer + i);
}
@@ -271,6 +261,7 @@ char *mqtt_get_suback_data(uint8_t *buffer, size_t *length)
*length -= 4;
return (char *)(buffer + 4);
}
*length = 0;
return NULL;
}
@@ -296,18 +287,21 @@ uint16_t mqtt_get_id(uint8_t *buffer, size_t length)
if (i + 2 >= length) {
return 0;
}
topiclen = buffer[i++] << 8;
topiclen |= buffer[i++];
if (i + topiclen > length) {
return 0;
}
i += topiclen;
if (mqtt_get_qos(buffer) > 0) {
if (i + 2 > length) {
return 0;
}
//i += 2;
} else {
return 0;
@@ -315,6 +309,7 @@ uint16_t mqtt_get_id(uint8_t *buffer, size_t length)
return (buffer[i] << 8) | buffer[i + 1];
}
case MQTT_MSG_TYPE_PUBACK:
case MQTT_MSG_TYPE_PUBREC:
case MQTT_MSG_TYPE_PUBREL:
@@ -339,10 +334,9 @@ uint16_t mqtt_get_id(uint8_t *buffer, size_t length)
mqtt_message_t *mqtt_msg_connect(mqtt_connection_t *connection, mqtt_connect_info_t *info)
{
set_message_header_size(connection);
int header_len;
if (info->protocol_ver == MQTT_PROTOCOL_V_3_1) {
header_len = MQTT_3_1_VARIABLE_HEADER_SIZE;
} else {
@@ -352,9 +346,9 @@ mqtt_message_t *mqtt_msg_connect(mqtt_connection_t *connection, mqtt_connect_inf
if (connection->outbound_message.length + header_len > connection->buffer_length) {
return fail_message(connection);
}
char *variable_header = (char *)(connection->buffer + connection->outbound_message.length);
connection->outbound_message.length += header_len;
int header_idx = 0;
variable_header[header_idx++] = 0; // Variable header length MSB
@@ -400,9 +394,11 @@ mqtt_message_t *mqtt_msg_connect(mqtt_connection_t *connection, mqtt_connect_inf
}
variable_header[flags_offset] |= MQTT_CONNECT_FLAG_WILL;
if (info->will_retain) {
variable_header[flags_offset] |= MQTT_CONNECT_FLAG_WILL_RETAIN;
}
variable_header[flags_offset] |= (info->will_qos & 3) << 3;
}
@@ -436,7 +432,8 @@ mqtt_message_t *mqtt_msg_connect(mqtt_connection_t *connection, mqtt_connect_inf
return fini_message(connection, MQTT_MSG_TYPE_CONNECT, 0, 0, 0);
}
mqtt_message_t *mqtt_msg_publish(mqtt_connection_t *connection, const char *topic, const char *data, int data_length, int qos, int retain, uint16_t *message_id)
mqtt_message_t *mqtt_msg_publish(mqtt_connection_t *connection, const char *topic, const char *data, int data_length,
int qos, int retain, uint16_t *message_id)
{
set_message_header_size(connection);
@@ -464,55 +461,67 @@ mqtt_message_t *mqtt_msg_publish(mqtt_connection_t *connection, const char *topi
if (connection->outbound_message.length + data_length > connection->buffer_length) {
// Not enough size in buffer -> fragment this message
connection->outbound_message.fragmented_msg_data_offset = connection->outbound_message.length;
memcpy(connection->buffer + connection->outbound_message.length, data, connection->buffer_length - connection->outbound_message.length);
memcpy(connection->buffer + connection->outbound_message.length, data,
connection->buffer_length - connection->outbound_message.length);
connection->outbound_message.length = connection->buffer_length;
connection->outbound_message.fragmented_msg_total_length = data_length + connection->outbound_message.fragmented_msg_data_offset;
connection->outbound_message.fragmented_msg_total_length = data_length +
connection->outbound_message.fragmented_msg_data_offset;
} else {
memcpy(connection->buffer + connection->outbound_message.length, data, data_length);
connection->outbound_message.length += data_length;
connection->outbound_message.fragmented_msg_total_length = 0;
}
}
return fini_message(connection, MQTT_MSG_TYPE_PUBLISH, 0, qos, retain);
}
mqtt_message_t *mqtt_msg_puback(mqtt_connection_t *connection, uint16_t message_id)
{
set_message_header_size(connection);
if (append_message_id(connection, message_id) == 0) {
return fail_message(connection);
}
return fini_message(connection, MQTT_MSG_TYPE_PUBACK, 0, 0, 0);
}
mqtt_message_t *mqtt_msg_pubrec(mqtt_connection_t *connection, uint16_t message_id)
{
set_message_header_size(connection);
if (append_message_id(connection, message_id) == 0) {
return fail_message(connection);
}
return fini_message(connection, MQTT_MSG_TYPE_PUBREC, 0, 0, 0);
}
mqtt_message_t *mqtt_msg_pubrel(mqtt_connection_t *connection, uint16_t message_id)
{
set_message_header_size(connection);
if (append_message_id(connection, message_id) == 0) {
return fail_message(connection);
}
return fini_message(connection, MQTT_MSG_TYPE_PUBREL, 0, 1, 0);
}
mqtt_message_t *mqtt_msg_pubcomp(mqtt_connection_t *connection, uint16_t message_id)
{
set_message_header_size(connection);
if (append_message_id(connection, message_id) == 0) {
return fail_message(connection);
}
return fini_message(connection, MQTT_MSG_TYPE_PUBCOMP, 0, 0, 0);
}
mqtt_message_t *mqtt_msg_subscribe(mqtt_connection_t *connection, const esp_mqtt_topic_t topic_list[], int size, uint16_t *message_id)
mqtt_message_t *mqtt_msg_subscribe(mqtt_connection_t *connection, const esp_mqtt_topic_t topic_list[], int size,
uint16_t *message_id)
{
set_message_header_size(connection);
@@ -532,6 +541,7 @@ mqtt_message_t *mqtt_msg_subscribe(mqtt_connection_t *connection, const esp_mqtt
if (connection->outbound_message.length + 1 > connection->buffer_length) {
return fail_message(connection);
}
connection->buffer[connection->outbound_message.length] = topic_list[topic_number].qos;
connection->outbound_message.length ++;
}
@@ -587,6 +597,7 @@ int mqtt_has_valid_msg_hdr(uint8_t *buffer, size_t length)
if (length < 1) {
return 0;
}
switch (mqtt_get_type(buffer)) {
case MQTT_MSG_TYPE_CONNECT:
case MQTT_MSG_TYPE_CONNACK:
@@ -599,10 +610,12 @@ int mqtt_has_valid_msg_hdr(uint8_t *buffer, size_t length)
case MQTT_MSG_TYPE_PINGRESP:
case MQTT_MSG_TYPE_DISCONNECT:
return (buffer[0] & 0x0f) == 0; /* all flag bits are 0 */
case MQTT_MSG_TYPE_PUBREL:
case MQTT_MSG_TYPE_SUBSCRIBE:
case MQTT_MSG_TYPE_UNSUBSCRIBE:
return (buffer[0] & 0x0f) == 0x02; /* only bit 1 is set */
case MQTT_MSG_TYPE_PUBLISH:
qos = mqtt_get_qos(buffer);
dup = mqtt_get_dup(buffer);
@@ -611,6 +624,7 @@ int mqtt_has_valid_msg_hdr(uint8_t *buffer, size_t length)
* dup flag must be set to 0 for all qos=0 messages [MQTT-3.3.1-2]
*/
return (qos < 3) && ((qos > 0) || (dup == 0));
default:
return 0;
}
@@ -620,9 +634,11 @@ esp_err_t mqtt_msg_buffer_init(mqtt_connection_t *connection, int buffer_size)
{
memset(&connection->outbound_message, 0, sizeof(mqtt_message_t));
connection->buffer = (uint8_t *)calloc(buffer_size, sizeof(uint8_t));
if (!connection->buffer) {
return ESP_ERR_NO_MEM;
}
connection->buffer_length = buffer_size;
return ESP_OK;
}
@@ -633,5 +649,3 @@ void mqtt_msg_buffer_destroy(mqtt_connection_t *connection)
free(connection->buffer);
}
}

View File

@@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "mqtt_outbox.h"
#include <stdint.h>
#include <stdlib.h>
@@ -55,12 +60,15 @@ outbox_item_handle_t outbox_enqueue(outbox_handle_t outbox, outbox_message_handl
return NULL;
});
memcpy(item->buffer, message->data, message->len);
if (message->remaining_data) {
memcpy(item->buffer + message->len, message->remaining_data, message->remaining_len);
}
STAILQ_INSERT_TAIL(outbox->list, item, next);
outbox->size += item->len;
ESP_LOGD(TAG, "ENQUEUE msgid=%d, msg_type=%d, len=%d, size=%"PRIu64, message->msg_id, message->msg_type, message->len + message->remaining_len, outbox_get_size(outbox));
ESP_LOGD(TAG, "ENQUEUE msgid=%d, msg_type=%d, len=%d, size=%"PRIu64, message->msg_id, message->msg_type,
message->len + message->remaining_len, outbox_get_size(outbox));
return item;
}
@@ -83,6 +91,7 @@ outbox_item_handle_t outbox_dequeue(outbox_handle_t outbox, pending_state_t pend
if (tick) {
*tick = item->tick;
}
return item;
}
}
@@ -96,7 +105,8 @@ esp_err_t outbox_delete_item(outbox_handle_t outbox, outbox_item_handle_t item_t
if (item == item_to_delete) {
STAILQ_REMOVE(outbox->list, item, outbox_item, next);
outbox->size -= item->len;
ESP_LOGD(TAG, "DELETE_ITEM msgid=%d, msg_type=%d, remain size=%"PRIu64, item_to_delete->msg_id, item_to_delete->msg_type, outbox_get_size(outbox));
ESP_LOGD(TAG, "DELETE_ITEM msgid=%d, msg_type=%d, remain size=%"PRIu64, item_to_delete->msg_id,
item_to_delete->msg_type, outbox_get_size(outbox));
free(item->buffer);
free(item);
return ESP_OK;
@@ -114,6 +124,7 @@ uint8_t *outbox_item_get_data(outbox_item_handle_t item, size_t *len, uint16_t
*qos = item->msg_qos;
return (uint8_t *)item->buffer;
}
return NULL;
}
@@ -129,7 +140,6 @@ esp_err_t outbox_delete(outbox_handle_t outbox, int msg_id, int msg_type)
free(item);
return ESP_OK;
}
}
return ESP_FAIL;
}
@@ -137,10 +147,12 @@ esp_err_t outbox_delete(outbox_handle_t outbox, int msg_id, int msg_type)
esp_err_t outbox_set_pending(outbox_handle_t outbox, int msg_id, pending_state_t pending)
{
outbox_item_handle_t item = outbox_get(outbox, msg_id);
if (item) {
item->pending = pending;
return ESP_OK;
}
return ESP_FAIL;
}
@@ -149,16 +161,19 @@ pending_state_t outbox_item_get_pending(outbox_item_handle_t item)
if (item) {
return item->pending;
}
return QUEUED;
}
esp_err_t outbox_set_tick(outbox_handle_t outbox, int msg_id, outbox_tick_t tick)
{
outbox_item_handle_t item = outbox_get(outbox, msg_id);
if (item) {
item->tick = tick;
return ESP_OK;
}
return ESP_FAIL;
}
@@ -176,7 +191,6 @@ int outbox_delete_single_expired(outbox_handle_t outbox, outbox_tick_t current_t
ESP_LOGD(TAG, "DELETE_SINGLE_EXPIRED msgid=%d, remain size=%"PRIu64, msg_id, outbox_get_size(outbox));
return msg_id;
}
}
return msg_id;
}
@@ -194,7 +208,6 @@ int outbox_delete_expired(outbox_handle_t outbox, outbox_tick_t current_tick, ou
free(item);
deleted_items ++;
}
}
return deleted_items;
}
@@ -210,7 +223,8 @@ void outbox_delete_all_items(outbox_handle_t outbox)
STAILQ_FOREACH_SAFE(item, outbox->list, next, tmp) {
STAILQ_REMOVE(outbox->list, item, outbox_item, next);
outbox->size -= item->len;
ESP_LOGD(TAG, "DELETE_ALL_ITEMS msgid=%d, msg_type=%d, remain size=%"PRIu64, item->msg_id, item->msg_type, outbox_get_size(outbox));
ESP_LOGD(TAG, "DELETE_ALL_ITEMS msgid=%d, msg_type=%d, remain size=%"PRIu64, item->msg_id, item->msg_type,
outbox_get_size(outbox));
free(item->buffer);
free(item);
}

View File

@@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "platform.h"
#ifdef ESP_PLATFORM
@@ -24,14 +29,14 @@ char *platform_create_id_string(void)
{
char *id_string = calloc(1, MAX_ID_STRING);
ESP_MEM_CHECK(TAG, id_string, return NULL);
#ifndef MAC_TYPE
#ifndef MAC_TYPE
ESP_LOGW(TAG, "Soc doesn't provide MAC, client could be disconnected in case of device with same name in the broker.");
sprintf(id_string, "esp_mqtt_client_id");
#else
#else
uint8_t mac[6];
esp_read_mac(mac, MAC_TYPE);
sprintf(id_string, "ESP32_%02x%02X%02X", mac[3], mac[4], mac[5]);
#endif
#endif
return id_string;
}
@@ -42,7 +47,7 @@ int platform_random(int max)
uint64_t platform_tick_get_ms(void)
{
return esp_timer_get_time()/(int64_t)1000;
return esp_timer_get_time() / (int64_t)1000;
}
#endif

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -11,14 +11,18 @@
static const char *TAG = "mqtt5_client";
static void esp_mqtt5_print_error_code(esp_mqtt5_client_handle_t client, int code);
static esp_err_t esp_mqtt5_client_update_topic_alias(mqtt5_topic_alias_handle_t topic_alias_handle, uint16_t topic_alias, char *topic, size_t topic_len);
static char *esp_mqtt5_client_get_topic_alias(mqtt5_topic_alias_handle_t topic_alias_handle, uint16_t topic_alias, size_t *topic_length);
static esp_err_t esp_mqtt5_client_update_topic_alias(mqtt5_topic_alias_handle_t topic_alias_handle,
uint16_t topic_alias, char *topic, size_t topic_len);
static char *esp_mqtt5_client_get_topic_alias(mqtt5_topic_alias_handle_t topic_alias_handle, uint16_t topic_alias,
size_t *topic_length);
static void esp_mqtt5_client_delete_topic_alias(mqtt5_topic_alias_handle_t topic_alias_handle);
static esp_err_t esp_mqtt5_user_property_copy(mqtt5_user_property_handle_t user_property_new, const mqtt5_user_property_handle_t user_property_old);
static esp_err_t esp_mqtt5_user_property_copy(mqtt5_user_property_handle_t user_property_new,
const mqtt5_user_property_handle_t user_property_old);
void esp_mqtt5_increment_packet_counter(esp_mqtt5_client_handle_t client)
{
bool msg_dup = mqtt5_get_dup(client->mqtt_state.connection.outbound_message.data);
if (msg_dup == false) {
client->send_publish_packet_count ++;
ESP_LOGD(TAG, "Sent (%d) qos > 0 publish packet without ack", client->send_publish_packet_count);
@@ -36,9 +40,11 @@ void esp_mqtt5_decrement_packet_counter(esp_mqtt5_client_handle_t client)
void esp_mqtt5_parse_pubcomp(esp_mqtt5_client_handle_t client)
{
if (client->mqtt_state.connection.information.protocol_ver == MQTT_PROTOCOL_V_5) {
ESP_LOGD(TAG, "MQTT_MSG_TYPE_PUBCOMP return code is %d", mqtt5_msg_get_reason_code(client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_read_len));
ESP_LOGD(TAG, "MQTT_MSG_TYPE_PUBCOMP return code is %d", mqtt5_msg_get_reason_code(client->mqtt_state.in_buffer,
client->mqtt_state.in_buffer_read_len));
size_t msg_data_len = client->mqtt_state.in_buffer_read_len;
client->event.data = mqtt5_get_pubcomp_data(client->mqtt_state.in_buffer, &msg_data_len, &client->event.property->user_property);
client->event.data = mqtt5_get_pubcomp_data(client->mqtt_state.in_buffer, &msg_data_len,
&client->event.property->user_property);
client->event.data_len = msg_data_len;
client->event.total_data_len = msg_data_len;
client->event.current_data_offset = 0;
@@ -48,9 +54,11 @@ void esp_mqtt5_parse_pubcomp(esp_mqtt5_client_handle_t client)
void esp_mqtt5_parse_puback(esp_mqtt5_client_handle_t client)
{
if (client->mqtt_state.connection.information.protocol_ver == MQTT_PROTOCOL_V_5) {
ESP_LOGD(TAG, "MQTT_MSG_TYPE_PUBACK return code is %d", mqtt5_msg_get_reason_code(client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_read_len));
ESP_LOGD(TAG, "MQTT_MSG_TYPE_PUBACK return code is %d", mqtt5_msg_get_reason_code(client->mqtt_state.in_buffer,
client->mqtt_state.in_buffer_read_len));
size_t msg_data_len = client->mqtt_state.in_buffer_read_len;
client->event.data = mqtt5_get_puback_data(client->mqtt_state.in_buffer, &msg_data_len, &client->event.property->user_property);
client->event.data = mqtt5_get_puback_data(client->mqtt_state.in_buffer, &msg_data_len,
&client->event.property->user_property);
client->event.data_len = msg_data_len;
client->event.total_data_len = msg_data_len;
client->event.current_data_offset = 0;
@@ -60,9 +68,11 @@ void esp_mqtt5_parse_puback(esp_mqtt5_client_handle_t client)
void esp_mqtt5_parse_unsuback(esp_mqtt5_client_handle_t client)
{
if (client->mqtt_state.connection.information.protocol_ver == MQTT_PROTOCOL_V_5) {
ESP_LOGD(TAG, "MQTT_MSG_TYPE_UNSUBACK return code is %d", mqtt5_msg_get_reason_code(client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_read_len));
ESP_LOGD(TAG, "MQTT_MSG_TYPE_UNSUBACK return code is %d", mqtt5_msg_get_reason_code(client->mqtt_state.in_buffer,
client->mqtt_state.in_buffer_read_len));
size_t msg_data_len = client->mqtt_state.in_buffer_read_len;
client->event.data = mqtt5_get_unsuback_data(client->mqtt_state.in_buffer, &msg_data_len, &client->event.property->user_property);
client->event.data = mqtt5_get_unsuback_data(client->mqtt_state.in_buffer, &msg_data_len,
&client->event.property->user_property);
client->event.data_len = msg_data_len;
client->event.total_data_len = msg_data_len;
client->event.current_data_offset = 0;
@@ -72,7 +82,8 @@ void esp_mqtt5_parse_unsuback(esp_mqtt5_client_handle_t client)
void esp_mqtt5_parse_suback(esp_mqtt5_client_handle_t client)
{
if (client->mqtt_state.connection.information.protocol_ver == MQTT_PROTOCOL_V_5) {
ESP_LOGD(TAG, "MQTT_MSG_TYPE_SUBACK return code is %d", mqtt5_msg_get_reason_code(client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_read_len));
ESP_LOGD(TAG, "MQTT_MSG_TYPE_SUBACK return code is %d", mqtt5_msg_get_reason_code(client->mqtt_state.in_buffer,
client->mqtt_state.in_buffer_read_len));
}
}
@@ -89,45 +100,56 @@ esp_err_t esp_mqtt5_parse_connack(esp_mqtt5_client_handle_t client, int *connect
size_t len = client->mqtt_state.in_buffer_read_len;
client->mqtt_state.in_buffer_read_len = 0;
uint8_t ack_flag = 0;
if (mqtt5_msg_parse_connack_property(client->mqtt_state.in_buffer, len, &client->mqtt_state.
connection.information, &client->mqtt5_config->connect_property_info, &client->mqtt5_config->server_resp_property_info, connect_rsp_code, &ack_flag, &client->event.property->user_property) != ESP_OK) {
connection.information, &client->mqtt5_config->connect_property_info, &client->mqtt5_config->server_resp_property_info,
connect_rsp_code, &ack_flag, &client->event.property->user_property) != ESP_OK) {
ESP_LOGE(TAG, "Failed to parse CONNACK packet");
return ESP_FAIL;
}
if (*connect_rsp_code == MQTT_CONNECTION_ACCEPTED) {
ESP_LOGD(TAG, "Connected");
client->event.session_present = ack_flag & 0x01;
return ESP_OK;
}
esp_mqtt5_print_error_code(client, *connect_rsp_code);
return ESP_FAIL;
}
esp_err_t esp_mqtt5_get_publish_data(esp_mqtt5_client_handle_t client, uint8_t *msg_buf, size_t msg_read_len, char **msg_topic, size_t *msg_topic_len, char **msg_data, size_t *msg_data_len)
esp_err_t esp_mqtt5_get_publish_data(esp_mqtt5_client_handle_t client, uint8_t *msg_buf, size_t msg_read_len,
char **msg_topic, size_t *msg_topic_len, char **msg_data, size_t *msg_data_len)
{
// get property
uint16_t property_len = 0;
esp_mqtt5_publish_resp_property_t property = {0};
*msg_data = mqtt5_get_publish_property_payload(msg_buf, msg_read_len, msg_topic, msg_topic_len, &property, &property_len, msg_data_len, &client->event.property->user_property);
if (*msg_data == NULL) {
*msg_data = mqtt5_get_publish_property_payload(msg_buf, msg_read_len, msg_topic, msg_topic_len, &property,
&property_len, msg_data_len, &client->event.property->user_property);
if (*msg_data == NULL) {
ESP_LOGE(TAG, "%s: mqtt5_get_publish_property_payload() failed", __func__);
return ESP_FAIL;
}
if (property.topic_alias > client->mqtt5_config->connect_property_info.topic_alias_maximum) {
ESP_LOGE(TAG, "%s: Broker response topic alias %d is over the max topic alias %d", __func__, property.topic_alias, client->mqtt5_config->connect_property_info.topic_alias_maximum);
ESP_LOGE(TAG, "%s: Broker response topic alias %d is over the max topic alias %d", __func__, property.topic_alias,
client->mqtt5_config->connect_property_info.topic_alias_maximum);
return ESP_FAIL;
}
if (property.topic_alias) {
if (*msg_topic_len == 0) {
*msg_topic = esp_mqtt5_client_get_topic_alias(client->mqtt5_config->peer_topic_alias, property.topic_alias, msg_topic_len);
*msg_topic = esp_mqtt5_client_get_topic_alias(client->mqtt5_config->peer_topic_alias, property.topic_alias,
msg_topic_len);
if (!*msg_topic) {
ESP_LOGE(TAG, "%s: esp_mqtt5_client_get_topic_alias() failed", __func__);
return ESP_FAIL;
}
} else {
if (esp_mqtt5_client_update_topic_alias(client->mqtt5_config->peer_topic_alias, property.topic_alias, *msg_topic, *msg_topic_len) != ESP_OK) {
if (esp_mqtt5_client_update_topic_alias(client->mqtt5_config->peer_topic_alias, property.topic_alias, *msg_topic,
*msg_topic_len) != ESP_OK) {
ESP_LOGE(TAG, "%s: esp_mqtt5_client_update_topic_alias() failed", __func__);
return ESP_FAIL;
}
@@ -159,6 +181,7 @@ esp_err_t esp_mqtt5_create_default_config(esp_mqtt5_client_handle_t client)
client->mqtt5_config->server_resp_property_info.shared_subscribe_available = true;
client->mqtt5_config->server_resp_property_info.receive_maximum = 65535;
}
return ESP_OK;
}
@@ -168,110 +191,145 @@ static void esp_mqtt5_print_error_code(esp_mqtt5_client_handle_t client, int cod
case MQTT5_UNSPECIFIED_ERROR:
ESP_LOGW(TAG, "Unspecified error");
break;
case MQTT5_MALFORMED_PACKET:
ESP_LOGW(TAG, "Malformed Packet");
break;
case MQTT5_PROTOCOL_ERROR:
ESP_LOGW(TAG, "Protocol Error");
break;
case MQTT5_IMPLEMENT_SPECIFIC_ERROR:
ESP_LOGW(TAG, "Implementation specific error");
break;
case MQTT5_UNSUPPORTED_PROTOCOL_VER:
ESP_LOGW(TAG, "Unsupported Protocol Version");
break;
case MQTT5_INVALID_CLIENT_ID:
ESP_LOGW(TAG, "Client Identifier not valid");
break;
case MQTT5_BAD_USERNAME_OR_PWD:
ESP_LOGW(TAG, "Bad User Name or Password");
break;
case MQTT5_NOT_AUTHORIZED:
ESP_LOGW(TAG, "Not authorized");
break;
case MQTT5_SERVER_UNAVAILABLE:
ESP_LOGW(TAG, "Server unavailable");
break;
case MQTT5_SERVER_BUSY:
ESP_LOGW(TAG, "Server busy");
break;
case MQTT5_BANNED:
ESP_LOGW(TAG, "Banned");
break;
case MQTT5_SERVER_SHUTTING_DOWN:
ESP_LOGW(TAG, "Server shutting down");
break;
case MQTT5_BAD_AUTH_METHOD:
ESP_LOGW(TAG, "Bad authentication method");
break;
case MQTT5_KEEP_ALIVE_TIMEOUT:
ESP_LOGW(TAG, "Keep Alive timeout");
break;
case MQTT5_SESSION_TAKEN_OVER:
ESP_LOGW(TAG, "Session taken over");
break;
case MQTT5_TOPIC_FILTER_INVALID:
ESP_LOGW(TAG, "Topic Filter invalid");
break;
case MQTT5_TOPIC_NAME_INVALID:
ESP_LOGW(TAG, "Topic Name invalid");
break;
case MQTT5_PACKET_IDENTIFIER_IN_USE:
ESP_LOGW(TAG, "Packet Identifier in use");
break;
case MQTT5_PACKET_IDENTIFIER_NOT_FOUND:
ESP_LOGW(TAG, "Packet Identifier not found");
break;
case MQTT5_RECEIVE_MAXIMUM_EXCEEDED:
ESP_LOGW(TAG, "Receive Maximum exceeded");
break;
case MQTT5_TOPIC_ALIAS_INVALID:
ESP_LOGW(TAG, "Topic Alias invalid");
break;
case MQTT5_PACKET_TOO_LARGE:
ESP_LOGW(TAG, "Packet too large");
break;
case MQTT5_MESSAGE_RATE_TOO_HIGH:
ESP_LOGW(TAG, "Message rate too high");
break;
case MQTT5_QUOTA_EXCEEDED:
ESP_LOGW(TAG, "Quota exceeded");
break;
case MQTT5_ADMINISTRATIVE_ACTION:
ESP_LOGW(TAG, "Administrative action");
break;
case MQTT5_PAYLOAD_FORMAT_INVALID:
ESP_LOGW(TAG, "Payload format invalid");
break;
case MQTT5_RETAIN_NOT_SUPPORT:
ESP_LOGW(TAG, "Retain not supported");
break;
case MQTT5_QOS_NOT_SUPPORT:
ESP_LOGW(TAG, "QoS not supported");
break;
case MQTT5_USE_ANOTHER_SERVER:
ESP_LOGW(TAG, "Use another server");
break;
case MQTT5_SERVER_MOVED:
ESP_LOGW(TAG, "Server moved");
break;
case MQTT5_SHARED_SUBSCR_NOT_SUPPORTED:
ESP_LOGW(TAG, "Shared Subscriptions not supported");
break;
case MQTT5_CONNECTION_RATE_EXCEEDED:
ESP_LOGW(TAG, "Connection rate exceeded");
break;
case MQTT5_MAXIMUM_CONNECT_TIME:
ESP_LOGW(TAG, "Maximum connect time");
break;
case MQTT5_SUBSCRIBE_IDENTIFIER_NOT_SUPPORT:
ESP_LOGW(TAG, "Subscription Identifiers not supported");
break;
case MQTT5_WILDCARD_SUBSCRIBE_NOT_SUPPORT:
ESP_LOGW(TAG, "Wildcard Subscriptions not supported");
break;
default:
ESP_LOGW(TAG, "Connection refused, Unknow reason");
ESP_LOGW(TAG, "Connection refused, Unknown reason");
break;
}
}
@@ -303,7 +361,8 @@ esp_err_t esp_mqtt5_client_publish_check(esp_mqtt5_client_handle_t client, int q
/* Flow control to check PUBLISH(No PUBACK or PUBCOMP received) packet sent count(Only record QoS1 and QoS2)*/
if (client->send_publish_packet_count > client->mqtt5_config->server_resp_property_info.receive_maximum) {
ESP_LOGE(TAG, "Client send more than %d QoS1 and QoS2 PUBLISH packet without no ack", client->mqtt5_config->server_resp_property_info.receive_maximum);
ESP_LOGE(TAG, "Client send more than %d QoS1 and QoS2 PUBLISH packet without no ack",
client->mqtt5_config->server_resp_property_info.receive_maximum);
return ESP_FAIL;
}
@@ -324,6 +383,7 @@ void esp_mqtt5_client_destory(esp_mqtt5_client_handle_t client)
esp_mqtt5_client_delete_user_property(client->mqtt5_config->disconnect_property_info.user_property);
free(client->mqtt5_config);
}
free(client->event.property);
}
}
@@ -341,7 +401,8 @@ static void esp_mqtt5_client_delete_topic_alias(mqtt5_topic_alias_handle_t topic
}
}
static esp_err_t esp_mqtt5_client_update_topic_alias(mqtt5_topic_alias_handle_t topic_alias_handle, uint16_t topic_alias, char *topic, size_t topic_len)
static esp_err_t esp_mqtt5_client_update_topic_alias(mqtt5_topic_alias_handle_t topic_alias_handle,
uint16_t topic_alias, char *topic, size_t topic_len)
{
mqtt5_topic_alias_item_t item;
bool found = false;
@@ -351,6 +412,7 @@ static esp_err_t esp_mqtt5_client_update_topic_alias(mqtt5_topic_alias_handle_t
break;
}
}
if (found) {
if ((item->topic_len != topic_len) || strncmp(topic, item->topic, topic_len)) {
free(item->topic);
@@ -372,10 +434,12 @@ static esp_err_t esp_mqtt5_client_update_topic_alias(mqtt5_topic_alias_handle_t
memcpy(item->topic, topic, topic_len);
STAILQ_INSERT_TAIL(topic_alias_handle, item, next);
}
return ESP_OK;
}
static char *esp_mqtt5_client_get_topic_alias(mqtt5_topic_alias_handle_t topic_alias_handle, uint16_t topic_alias, size_t *topic_length)
static char *esp_mqtt5_client_get_topic_alias(mqtt5_topic_alias_handle_t topic_alias_handle, uint16_t topic_alias,
size_t *topic_length)
{
mqtt5_topic_alias_item_t item;
STAILQ_FOREACH(item, topic_alias_handle, next) {
@@ -388,7 +452,8 @@ static char *esp_mqtt5_client_get_topic_alias(mqtt5_topic_alias_handle_t topic_a
return NULL;
}
static esp_err_t esp_mqtt5_user_property_copy(mqtt5_user_property_handle_t user_property_new, const mqtt5_user_property_handle_t user_property_old)
static esp_err_t esp_mqtt5_user_property_copy(mqtt5_user_property_handle_t user_property_new,
const mqtt5_user_property_handle_t user_property_old)
{
if (!user_property_new || !user_property_old) {
ESP_LOGE(TAG, "Input is NULL");
@@ -415,12 +480,14 @@ static esp_err_t esp_mqtt5_user_property_copy(mqtt5_user_property_handle_t user_
return ESP_OK;
}
esp_err_t esp_mqtt5_client_set_publish_property(esp_mqtt5_client_handle_t client, const esp_mqtt5_publish_property_config_t *property)
esp_err_t esp_mqtt5_client_set_publish_property(esp_mqtt5_client_handle_t client,
const esp_mqtt5_publish_property_config_t *property)
{
if (!client) {
ESP_LOGE(TAG, "Client was not initialized");
return ESP_ERR_INVALID_ARG;
}
MQTT_API_LOCK(client);
/* Check protocol version */
@@ -429,27 +496,33 @@ esp_err_t esp_mqtt5_client_set_publish_property(esp_mqtt5_client_handle_t client
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
/* Check topic alias less than server maximum topic alias */
if (property->topic_alias > client->mqtt5_config->server_resp_property_info.topic_alias_maximum) {
ESP_LOGE(TAG, "Topic alias %d is bigger than server support %d", property->topic_alias, client->mqtt5_config->server_resp_property_info.topic_alias_maximum);
ESP_LOGE(TAG, "Topic alias %d is bigger than server support %d", property->topic_alias,
client->mqtt5_config->server_resp_property_info.topic_alias_maximum);
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
client->mqtt5_config->publish_property_info = property;
MQTT_API_UNLOCK(client);
return ESP_OK;
}
esp_err_t esp_mqtt5_client_set_subscribe_property(esp_mqtt5_client_handle_t client, const esp_mqtt5_subscribe_property_config_t *property)
esp_err_t esp_mqtt5_client_set_subscribe_property(esp_mqtt5_client_handle_t client,
const esp_mqtt5_subscribe_property_config_t *property)
{
if (!client) {
ESP_LOGE(TAG, "Client was not initialized");
return ESP_ERR_INVALID_ARG;
}
if (property->retain_handle > 2) {
ESP_LOGE(TAG, "retain_handle only support 0, 1, 2");
return -1;
}
MQTT_API_LOCK(client);
/* Check protocol version */
@@ -458,6 +531,7 @@ esp_err_t esp_mqtt5_client_set_subscribe_property(esp_mqtt5_client_handle_t clie
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
if (property->is_share_subscribe) {
if (property->no_local_flag) {
// MQTT-3.8.3-4 not allow that No Local bit to 1 on a Shared Subscription
@@ -465,28 +539,33 @@ esp_err_t esp_mqtt5_client_set_subscribe_property(esp_mqtt5_client_handle_t clie
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
if (!client->mqtt5_config->server_resp_property_info.shared_subscribe_available) {
ESP_LOGE(TAG, "MQTT broker not support shared subscribe");
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
if (!property->share_name || !strlen(property->share_name)) {
ESP_LOGE(TAG, "Share name can't be empty for shared subscribe");
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
}
client->mqtt5_config->subscribe_property_info = property;
MQTT_API_UNLOCK(client);
return ESP_OK;
}
esp_err_t esp_mqtt5_client_set_unsubscribe_property(esp_mqtt5_client_handle_t client, const esp_mqtt5_unsubscribe_property_config_t *property)
esp_err_t esp_mqtt5_client_set_unsubscribe_property(esp_mqtt5_client_handle_t client,
const esp_mqtt5_unsubscribe_property_config_t *property)
{
if (!client) {
ESP_LOGE(TAG, "Client was not initialized");
return ESP_ERR_INVALID_ARG;
}
MQTT_API_LOCK(client);
/* Check protocol version */
@@ -495,29 +574,34 @@ esp_err_t esp_mqtt5_client_set_unsubscribe_property(esp_mqtt5_client_handle_t cl
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
if (property->is_share_subscribe) {
if (!client->mqtt5_config->server_resp_property_info.shared_subscribe_available) {
ESP_LOGE(TAG, "MQTT broker not support shared subscribe");
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
if (!property->share_name || !strlen(property->share_name)) {
ESP_LOGE(TAG, "Share name can't be empty for shared subscribe");
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
}
client->mqtt5_config->unsubscribe_property_info = property;
MQTT_API_UNLOCK(client);
return ESP_OK;
}
esp_err_t esp_mqtt5_client_set_disconnect_property(esp_mqtt5_client_handle_t client, const esp_mqtt5_disconnect_property_config_t *property)
esp_err_t esp_mqtt5_client_set_disconnect_property(esp_mqtt5_client_handle_t client,
const esp_mqtt5_disconnect_property_config_t *property)
{
if (!client) {
ESP_LOGE(TAG, "Client was not initialized");
return ESP_ERR_INVALID_ARG;
}
MQTT_API_LOCK(client);
/* Check protocol version */
@@ -526,13 +610,16 @@ esp_err_t esp_mqtt5_client_set_disconnect_property(esp_mqtt5_client_handle_t cli
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
if (property) {
if (property->session_expiry_interval) {
client->mqtt5_config->disconnect_property_info.session_expiry_interval = property->session_expiry_interval;
}
if (property->disconnect_reason) {
client->mqtt5_config->disconnect_property_info.disconnect_reason = property->disconnect_reason;
}
if (property->user_property) {
esp_mqtt5_client_delete_user_property(client->mqtt5_config->disconnect_property_info.user_property);
client->mqtt5_config->disconnect_property_info.user_property = calloc(1, sizeof(struct mqtt5_user_property_list_t));
@@ -541,7 +628,9 @@ esp_err_t esp_mqtt5_client_set_disconnect_property(esp_mqtt5_client_handle_t cli
return ESP_ERR_NO_MEM;
});
STAILQ_INIT(client->mqtt5_config->disconnect_property_info.user_property);
if (esp_mqtt5_user_property_copy(client->mqtt5_config->disconnect_property_info.user_property, property->user_property) != ESP_OK) {
if (esp_mqtt5_user_property_copy(client->mqtt5_config->disconnect_property_info.user_property,
property->user_property) != ESP_OK) {
ESP_LOGE(TAG, "esp_mqtt5_user_property_copy fail");
free(client->mqtt5_config->disconnect_property_info.user_property);
client->mqtt5_config->disconnect_property_info.user_property = NULL;
@@ -555,12 +644,14 @@ esp_err_t esp_mqtt5_client_set_disconnect_property(esp_mqtt5_client_handle_t cli
return ESP_OK;
}
esp_err_t esp_mqtt5_client_set_connect_property(esp_mqtt5_client_handle_t client, const esp_mqtt5_connection_property_config_t *connect_property)
esp_err_t esp_mqtt5_client_set_connect_property(esp_mqtt5_client_handle_t client,
const esp_mqtt5_connection_property_config_t *connect_property)
{
if (!client) {
ESP_LOGE(TAG, "Client was not initialized");
return ESP_ERR_INVALID_ARG;
}
MQTT_API_LOCK(client);
/* Check protocol version */
@@ -569,13 +660,16 @@ esp_err_t esp_mqtt5_client_set_connect_property(esp_mqtt5_client_handle_t client
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
if (connect_property) {
if (connect_property->session_expiry_interval) {
client->mqtt5_config->connect_property_info.session_expiry_interval = connect_property->session_expiry_interval;
}
if (connect_property->maximum_packet_size) {
if (connect_property->maximum_packet_size > client->mqtt_state.in_buffer_length) {
ESP_LOGW(TAG, "Connect maximum_packet_size property is over buffer_size(%d), Please first change it", client->mqtt_state.in_buffer_length);
ESP_LOGW(TAG, "Connect maximum_packet_size property is over buffer_size(%d), Please first change it",
client->mqtt_state.in_buffer_length);
MQTT_API_UNLOCK(client);
return ESP_FAIL;
} else {
@@ -584,62 +678,82 @@ esp_err_t esp_mqtt5_client_set_connect_property(esp_mqtt5_client_handle_t client
} else {
client->mqtt5_config->connect_property_info.maximum_packet_size = client->mqtt_state.in_buffer_length;
}
if (connect_property->receive_maximum) {
client->mqtt5_config->connect_property_info.receive_maximum = connect_property->receive_maximum;
}
if (connect_property->topic_alias_maximum) {
client->mqtt5_config->connect_property_info.topic_alias_maximum = connect_property->topic_alias_maximum;
if (!client->mqtt5_config->peer_topic_alias) {
client->mqtt5_config->peer_topic_alias = calloc(1, sizeof(struct mqtt5_topic_alias_list_t));
ESP_MEM_CHECK(TAG, client->mqtt5_config->peer_topic_alias, goto _mqtt_set_config_failed);
STAILQ_INIT(client->mqtt5_config->peer_topic_alias);
}
}
if (connect_property->request_resp_info) {
client->mqtt5_config->connect_property_info.request_resp_info = connect_property->request_resp_info;
}
if (connect_property->request_problem_info) {
client->mqtt5_config->connect_property_info.request_problem_info = connect_property->request_problem_info;
}
if (connect_property->user_property) {
esp_mqtt5_client_delete_user_property(client->mqtt5_config->connect_property_info.user_property);
client->mqtt5_config->connect_property_info.user_property = calloc(1, sizeof(struct mqtt5_user_property_list_t));
ESP_MEM_CHECK(TAG, client->mqtt5_config->connect_property_info.user_property, goto _mqtt_set_config_failed);
STAILQ_INIT(client->mqtt5_config->connect_property_info.user_property);
if (esp_mqtt5_user_property_copy(client->mqtt5_config->connect_property_info.user_property, connect_property->user_property) != ESP_OK) {
if (esp_mqtt5_user_property_copy(client->mqtt5_config->connect_property_info.user_property,
connect_property->user_property) != ESP_OK) {
ESP_LOGE(TAG, "esp_mqtt5_user_property_copy fail");
goto _mqtt_set_config_failed;
}
}
if (connect_property->payload_format_indicator) {
client->mqtt5_config->will_property_info.payload_format_indicator = connect_property->payload_format_indicator;
}
if (connect_property->will_delay_interval) {
client->mqtt5_config->will_property_info.will_delay_interval = connect_property->will_delay_interval;
}
if (connect_property->message_expiry_interval) {
client->mqtt5_config->will_property_info.message_expiry_interval = connect_property->message_expiry_interval;
}
ESP_MEM_CHECK(TAG, esp_mqtt_set_if_config(connect_property->content_type, &client->mqtt5_config->will_property_info.content_type), goto _mqtt_set_config_failed);
ESP_MEM_CHECK(TAG, esp_mqtt_set_if_config(connect_property->response_topic, &client->mqtt5_config->will_property_info.response_topic), goto _mqtt_set_config_failed);
ESP_MEM_CHECK(TAG, esp_mqtt_set_if_config(connect_property->content_type,
&client->mqtt5_config->will_property_info.content_type), goto _mqtt_set_config_failed);
ESP_MEM_CHECK(TAG, esp_mqtt_set_if_config(connect_property->response_topic,
&client->mqtt5_config->will_property_info.response_topic), goto _mqtt_set_config_failed);
if (connect_property->correlation_data && connect_property->correlation_data_len) {
free(client->mqtt5_config->will_property_info.correlation_data);
client->mqtt5_config->will_property_info.correlation_data = malloc(connect_property->correlation_data_len);
ESP_MEM_CHECK(TAG, client->mqtt5_config->will_property_info.correlation_data, goto _mqtt_set_config_failed);
memcpy(client->mqtt5_config->will_property_info.correlation_data, connect_property->correlation_data, connect_property->correlation_data_len);
memcpy(client->mqtt5_config->will_property_info.correlation_data, connect_property->correlation_data,
connect_property->correlation_data_len);
client->mqtt5_config->will_property_info.correlation_data_len = connect_property->correlation_data_len;
}
if (connect_property->will_user_property) {
esp_mqtt5_client_delete_user_property(client->mqtt5_config->will_property_info.user_property);
client->mqtt5_config->will_property_info.user_property = calloc(1, sizeof(struct mqtt5_user_property_list_t));
ESP_MEM_CHECK(TAG, client->mqtt5_config->will_property_info.user_property, goto _mqtt_set_config_failed);
STAILQ_INIT(client->mqtt5_config->will_property_info.user_property);
if (esp_mqtt5_user_property_copy(client->mqtt5_config->will_property_info.user_property, connect_property->will_user_property) != ESP_OK) {
if (esp_mqtt5_user_property_copy(client->mqtt5_config->will_property_info.user_property,
connect_property->will_user_property) != ESP_OK) {
ESP_LOGE(TAG, "esp_mqtt5_user_property_copy fail");
goto _mqtt_set_config_failed;
}
}
}
MQTT_API_UNLOCK(client);
return ESP_OK;
_mqtt_set_config_failed:
@@ -648,7 +762,8 @@ _mqtt_set_config_failed:
return ESP_ERR_NO_MEM;
}
esp_err_t esp_mqtt5_client_set_user_property(mqtt5_user_property_handle_t *user_property, esp_mqtt5_user_property_item_t item[], uint8_t item_num)
esp_err_t esp_mqtt5_client_set_user_property(mqtt5_user_property_handle_t *user_property,
esp_mqtt5_user_property_item_t item[], uint8_t item_num)
{
if (!item_num || !item) {
ESP_LOGE(TAG, "Input value is NULL");
@@ -667,7 +782,6 @@ esp_err_t esp_mqtt5_client_set_user_property(mqtt5_user_property_handle_t *user_
ESP_MEM_CHECK(TAG, user_property_item, goto err);
size_t key_len = strlen(item[i].key);
size_t value_len = strlen(item[i].value);
user_property_item->key = calloc(1, key_len + 1);
ESP_MEM_CHECK(TAG, user_property_item->key, {
free(user_property_item);
@@ -675,7 +789,6 @@ esp_err_t esp_mqtt5_client_set_user_property(mqtt5_user_property_handle_t *user_
});
memcpy(user_property_item->key, item[i].key, key_len);
user_property_item->key[key_len] = '\0';
user_property_item->value = calloc(1, value_len + 1);
ESP_MEM_CHECK(TAG, user_property_item->value, {
free(user_property_item->key);
@@ -684,10 +797,10 @@ esp_err_t esp_mqtt5_client_set_user_property(mqtt5_user_property_handle_t *user_
});
memcpy(user_property_item->value, item[i].value, value_len);
user_property_item->value[value_len] = '\0';
STAILQ_INSERT_TAIL(*user_property, user_property_item, next);
}
}
return ESP_OK;
err:
esp_mqtt5_client_delete_user_property(*user_property);
@@ -695,9 +808,11 @@ err:
return ESP_ERR_NO_MEM;
}
esp_err_t esp_mqtt5_client_get_user_property(mqtt5_user_property_handle_t user_property, esp_mqtt5_user_property_item_t *item, uint8_t *item_num)
esp_err_t esp_mqtt5_client_get_user_property(mqtt5_user_property_handle_t user_property,
esp_mqtt5_user_property_item_t *item, uint8_t *item_num)
{
int i = 0, j = 0;
if (user_property && item && *item_num) {
mqtt5_user_property_item_t user_property_item;
uint8_t num = *item_num;
@@ -729,27 +844,33 @@ esp_err_t esp_mqtt5_client_get_user_property(mqtt5_user_property_handle_t user_p
ESP_LOGE(TAG, "Input value is NULL or item_num is 0");
return ESP_FAIL;
}
err:
for (j = 0; j < i; j ++) {
if (item[j].key) {
free((char *)item[j].key);
}
if (item[j].value) {
free((char *)item[j].value);
}
}
return ESP_ERR_NO_MEM;
}
uint8_t esp_mqtt5_client_get_user_property_count(mqtt5_user_property_handle_t user_property)
{
uint8_t count = 0;
if (user_property) {
mqtt5_user_property_item_t item;
STAILQ_FOREACH(item, user_property, next) {
count ++;
}
}
return count;
}
@@ -764,5 +885,6 @@ void esp_mqtt5_client_delete_user_property(mqtt5_user_property_handle_t user_pro
free(item);
}
}
free(user_property);
}

File diff suppressed because it is too large Load Diff

View File

@@ -25,4 +25,3 @@ log_cli = True
log_cli_level = INFO
log_cli_format = %(asctime)s %(levelname)s %(message)s
log_cli_date_format = %Y-%m-%d %H:%M:%S

View File

@@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* Build only example to check mqtt client API from C++
This example code is in the Public Domain (or CC0 licensed, at your option.)

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -11,7 +11,6 @@
#include "esp_eth.h"
#include "esp_log.h"
#if SOC_EMAC_SUPPORTED
#define ETH_START_BIT BIT(0)
#define ETH_STOP_BIT BIT(1)
@@ -20,7 +19,6 @@
#define ETH_STOP_TIMEOUT_MS (10000)
#define ETH_GET_IP_TIMEOUT_MS (60000)
static const char *TAG = "esp32_eth_test_fixture";
static EventGroupHandle_t s_eth_event_group = NULL;
static esp_netif_t *s_eth_netif = NULL;
@@ -29,30 +27,34 @@ static esp_eth_phy_t *s_phy = NULL;
static esp_eth_handle_t s_eth_handle = NULL;
static esp_eth_netif_glue_handle_t s_eth_glue = NULL;
/** Event handler for Ethernet events */
static void eth_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
EventGroupHandle_t eth_event_group = (EventGroupHandle_t)arg;
switch (event_id) {
case ETHERNET_EVENT_CONNECTED:
xEventGroupSetBits(eth_event_group, ETH_CONNECT_BIT);
ESP_LOGI(TAG, "Ethernet Link Up");
break;
case ETHERNET_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "Ethernet Link Down");
break;
case ETHERNET_EVENT_START:
xEventGroupSetBits(eth_event_group, ETH_START_BIT);
ESP_LOGI(TAG, "Ethernet Started");
break;
case ETHERNET_EVENT_STOP:
xEventGroupSetBits(eth_event_group, ETH_STOP_BIT);
ESP_LOGI(TAG, "Ethernet Stopped");
break;
default:
break;
case ETHERNET_EVENT_CONNECTED:
xEventGroupSetBits(eth_event_group, ETH_CONNECT_BIT);
ESP_LOGI(TAG, "Ethernet Link Up");
break;
case ETHERNET_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "Ethernet Link Down");
break;
case ETHERNET_EVENT_START:
xEventGroupSetBits(eth_event_group, ETH_START_BIT);
ESP_LOGI(TAG, "Ethernet Started");
break;
case ETHERNET_EVENT_STOP:
xEventGroupSetBits(eth_event_group, ETH_STOP_BIT);
ESP_LOGI(TAG, "Ethernet Stopped");
break;
default:
break;
}
}
@@ -76,12 +78,15 @@ static esp_err_t test_uninstall_driver(esp_eth_handle_t eth_hdl, uint32_t ms_to_
{
int i = 0;
ms_to_wait += 100;
for (i = 0; i < ms_to_wait / 100; i++) {
vTaskDelay(pdMS_TO_TICKS(100));
if (esp_eth_driver_uninstall(eth_hdl) == ESP_OK) {
break;
}
}
if (i < ms_to_wait / 10) {
return ESP_OK;
} else {
@@ -89,7 +94,6 @@ static esp_err_t test_uninstall_driver(esp_eth_handle_t eth_hdl, uint32_t ms_to_
}
}
void connect_test_fixture_setup(void)
{
EventBits_t bits;
@@ -99,14 +103,12 @@ void connect_test_fixture_setup(void)
// create TCP/IP netif
esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH();
s_eth_netif = esp_netif_new(&netif_cfg);
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
s_mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
s_phy = esp_eth_phy_new_ip101(&phy_config);
esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(s_mac, s_phy);
// install Ethernet driver
TEST_ESP_OK(esp_eth_driver_install(&eth_config, &s_eth_handle));
// combine driver with netif

View File

@@ -2,4 +2,3 @@ dependencies:
espressif/mqtt:
version: "*"
override_path: "../../../.."

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*
@@ -23,12 +23,14 @@
TEST_GROUP(mqtt);
TEST_SETUP(mqtt){
TEST_SETUP(mqtt)
{
test_utils_record_free_mem();
TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL));
}
TEST_TEAR_DOWN(mqtt){
TEST_TEAR_DOWN(mqtt)
{
test_utils_finish_and_evaluate_leaks(test_utils_get_leak_level(ESP_LEAK_TYPE_WARNING, ESP_COMP_LEAK_ALL),
test_utils_get_leak_level(ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_ALL));
}
@@ -36,87 +38,85 @@ TEST_TEAR_DOWN(mqtt){
TEST(mqtt, init_with_invalid_url)
{
const esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = "INVALID",
.broker.address.uri = "INVALID",
};
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
TEST_ASSERT_EQUAL(NULL, client );
TEST_ASSERT_EQUAL(NULL, client);
}
TEST(mqtt, init_and_deinit)
{
const esp_mqtt_client_config_t mqtt_cfg = {
// no connection takes place, but the uri has to be valid for init() to succeed
.broker.address.uri = "mqtts://localhost:8883",
// no connection takes place, but the uri has to be valid for init() to succeed
.broker.address.uri = "mqtts://localhost:8883",
};
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
TEST_ASSERT_NOT_EQUAL(NULL, client );
TEST_ASSERT_NOT_EQUAL(NULL, client);
esp_mqtt_client_destroy(client);
}
static const char* this_bin_addr(void)
static const char *this_bin_addr(void)
{
esp_partition_mmap_handle_t out_handle;
const void *binary_address;
const esp_partition_t* partition = esp_ota_get_running_partition();
const esp_partition_t *partition = esp_ota_get_running_partition();
esp_partition_mmap(partition, 0, partition->size, ESP_PARTITION_MMAP_DATA, &binary_address, &out_handle);
return binary_address;
}
TEST(mqtt, enqueue_and_destroy_outbox)
{
const char * bin_addr = this_bin_addr();
// Reseting leak detection since this_bin_addr adds to allocated memory.
const char *bin_addr = this_bin_addr();
// Resetting leak detection since this_bin_addr adds to allocated memory.
test_utils_record_free_mem();
TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL));
const int messages = 20;
const int size = 2000;
const esp_mqtt_client_config_t mqtt_cfg = {
// no connection takes place, but the uri has to be valid for init() to succeed
.broker.address.uri = "mqtts://localhost:8883",
// no connection takes place, but the uri has to be valid for init() to succeed
.broker.address.uri = "mqtts://localhost:8883",
};
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
TEST_ASSERT_NOT_EQUAL(NULL, client );
TEST_ASSERT_NOT_EQUAL(NULL, client);
int bytes_before = esp_get_free_heap_size();
for (int i=0; i<messages; ++i) {
for (int i = 0; i < messages; ++i) {
esp_mqtt_client_publish(client, "test", bin_addr, size, 1, 0);
}
int bytes_after = esp_get_free_heap_size();
// check that outbox allocated all messages on heap
TEST_ASSERT_GREATER_OR_EQUAL(messages*size, bytes_before - bytes_after);
TEST_ASSERT_GREATER_OR_EQUAL(messages * size, bytes_before - bytes_after);
esp_mqtt_client_destroy(client);
}
#if SOC_EMAC_SUPPORTED
/**
* This test cases uses ethernet kit, so build and use it only if EMAC supported
* This test cases uses ethernet kit, so build and use it only if EMACS supported
*/
TEST(mqtt, broker_tests)
{
test_case_uses_tcpip();
connect_test_fixture_setup();
RUN_MQTT_BROKER_TEST(mqtt_connect_disconnect);
RUN_MQTT_BROKER_TEST(mqtt_subscribe_publish);
RUN_MQTT_BROKER_TEST(mqtt_lwt_clean_disconnect);
RUN_MQTT_BROKER_TEST(mqtt_subscribe_payload);
connect_test_fixture_teardown();
}
#endif // SOC_EMAC_SUPPORTED
TEST_GROUP_RUNNER(mqtt) {
RUN_TEST_CASE(mqtt, init_with_invalid_url);
RUN_TEST_CASE(mqtt, init_and_deinit);
RUN_TEST_CASE(mqtt, enqueue_and_destroy_outbox);
TEST_GROUP_RUNNER(mqtt)
{
RUN_TEST_CASE(mqtt, init_with_invalid_url);
RUN_TEST_CASE(mqtt, init_and_deinit);
RUN_TEST_CASE(mqtt, enqueue_and_destroy_outbox);
#if SOC_EMAC_SUPPORTED
RUN_TEST_CASE(mqtt, broker_tests);
RUN_TEST_CASE(mqtt, broker_tests);
#endif // SOC_EMAC_SUPPORTED
}
void app_main(void){
UNITY_MAIN(mqtt);
void app_main(void)
{
UNITY_MAIN(mqtt);
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -22,7 +22,6 @@
} \
} while(0)
static const int COMMON_OPERATION_TIMEOUT = 10000;
static const int CONNECT_BIT = BIT0;
static const int DISCONNECT_BIT = BIT1;
@@ -30,7 +29,7 @@ static const int DATA_BIT = BIT2;
static EventGroupHandle_t s_event_group;
static char* append_mac(const char* string)
static char *append_mac(const char *string)
{
uint8_t mac[6];
char *id_string = NULL;
@@ -43,7 +42,7 @@ static void mqtt_data_handler_qos(void *handler_args, esp_event_base_t base, int
{
if (event_id == MQTT_EVENT_DATA) {
esp_mqtt_event_handle_t event = event_data;
int * qos = handler_args;
int *qos = handler_args;
*qos = event->qos;
xEventGroupSetBits(s_event_group, DATA_BIT);
}
@@ -56,12 +55,13 @@ static void mqtt_data_handler_lwt(void *handler_args, esp_event_base_t base, int
ESP_LOGI("mqtt-lwt", "MQTT_EVENT_DATA");
ESP_LOGI("mqtt-lwt", "TOPIC=%.*s", event->topic_len, event->topic);
ESP_LOGI("mqtt-lwt", "DATA=%.*s", event->data_len, event->data);
if (strncmp(event->data, "no-lwt", event->data_len) == 0) {
// no lwt, just to indicate the test has finished
xEventGroupSetBits(s_event_group, DATA_BIT);
} else {
// count up any potential lwt message
int * count = handler_args;
int *count = handler_args;
*count = *count + 1;
ESP_LOGE("mqtt-lwt", "count=%d", *count);
}
@@ -73,40 +73,42 @@ static void mqtt_data_handler_subscribe(void *handler_args, esp_event_base_t bas
if (event_id == MQTT_EVENT_SUBSCRIBED) {
esp_mqtt_event_handle_t event = event_data;
ESP_LOGI("mqtt-subscribe", "MQTT_EVENT_SUBSCRIBED, data size=%d", event->data_len);
int * sub_payload = handler_args;
int *sub_payload = handler_args;
if (event->data_len == 1) {
ESP_LOGI("mqtt-subscribe", "DATA=%d", *(uint8_t*)event->data);
*sub_payload = *(uint8_t*)event->data;
ESP_LOGI("mqtt-subscribe", "DATA=%d", *(uint8_t *)event->data);
*sub_payload = *(uint8_t *)event->data;
}
xEventGroupSetBits(s_event_group, DATA_BIT);
}
}
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
switch ((esp_mqtt_event_id_t)event_id) {
case MQTT_EVENT_CONNECTED:
xEventGroupSetBits(s_event_group, CONNECT_BIT);
break;
case MQTT_EVENT_CONNECTED:
xEventGroupSetBits(s_event_group, CONNECT_BIT);
break;
case MQTT_EVENT_DISCONNECTED:
xEventGroupSetBits(s_event_group, DISCONNECT_BIT);
break;
default:
break;
case MQTT_EVENT_DISCONNECTED:
xEventGroupSetBits(s_event_group, DISCONNECT_BIT);
break;
default:
break;
}
}
bool mqtt_connect_disconnect(void)
{
const esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = CONFIG_MQTT_TEST_BROKER_URI,
.network.disable_auto_reconnect = true,
.broker.address.uri = CONFIG_MQTT_TEST_BROKER_URI,
.network.disable_auto_reconnect = true,
};
s_event_group = xEventGroupCreate();
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
TEST_ASSERT_TRUE(NULL != client );
TEST_ASSERT_TRUE(NULL != client);
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt_client_start(client));
WAIT_FOR_EVENT(CONNECT_BIT);
@@ -122,13 +124,13 @@ bool mqtt_connect_disconnect(void)
bool mqtt_subscribe_publish(void)
{
const esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = CONFIG_MQTT_TEST_BROKER_URI,
.broker.address.uri = CONFIG_MQTT_TEST_BROKER_URI,
};
char* topic = append_mac("topic");
char *topic = append_mac("topic");
TEST_ASSERT_TRUE(NULL != topic);
s_event_group = xEventGroupCreate();
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
TEST_ASSERT_TRUE(NULL != client );
TEST_ASSERT_TRUE(NULL != client);
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt_client_start(client));
WAIT_FOR_EVENT(CONNECT_BIT);
@@ -149,25 +151,24 @@ bool mqtt_subscribe_publish(void)
bool mqtt_lwt_clean_disconnect(void)
{
char* lwt = append_mac("lwt");
char *lwt = append_mac("lwt");
TEST_ASSERT_TRUE(lwt);
const esp_mqtt_client_config_t mqtt_cfg1 = {
.broker.address.uri = CONFIG_MQTT_TEST_BROKER_URI,
.credentials.set_null_client_id = true,
.session.last_will.topic = lwt,
.session.last_will.msg = "lwt_msg"
.broker.address.uri = CONFIG_MQTT_TEST_BROKER_URI,
.credentials.set_null_client_id = true,
.session.last_will.topic = lwt,
.session.last_will.msg = "lwt_msg"
};
const esp_mqtt_client_config_t mqtt_cfg2 = {
.broker.address.uri = CONFIG_MQTT_TEST_BROKER_URI,
.credentials.set_null_client_id = true,
.session.last_will.topic = lwt,
.session.last_will.msg = "lwt_msg"
.broker.address.uri = CONFIG_MQTT_TEST_BROKER_URI,
.credentials.set_null_client_id = true,
.session.last_will.topic = lwt,
.session.last_will.msg = "lwt_msg"
};
s_event_group = xEventGroupCreate();
esp_mqtt_client_handle_t client1 = esp_mqtt_client_init(&mqtt_cfg1);
esp_mqtt_client_handle_t client2 = esp_mqtt_client_init(&mqtt_cfg2);
TEST_ASSERT_TRUE(NULL != client1 && NULL != client2 );
TEST_ASSERT_TRUE(NULL != client1 && NULL != client2);
esp_mqtt_client_register_event(client1, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
esp_mqtt_client_register_event(client2, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
TEST_ASSERT_TRUE(esp_mqtt_client_start(client1) == ESP_OK);
@@ -201,14 +202,14 @@ bool mqtt_lwt_clean_disconnect(void)
bool mqtt_subscribe_payload(void)
{
const esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = CONFIG_MQTT_TEST_BROKER_URI,
.network.disable_auto_reconnect = true,
.broker.address.uri = CONFIG_MQTT_TEST_BROKER_URI,
.network.disable_auto_reconnect = true,
};
char* topic = append_mac("topic");
char *topic = append_mac("topic");
TEST_ASSERT_TRUE(NULL != topic);
s_event_group = xEventGroupCreate();
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
TEST_ASSERT_TRUE(NULL != client );
TEST_ASSERT_TRUE(NULL != client);
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt_client_start(client));
WAIT_FOR_EVENT(CONNECT_BIT);

View File

@@ -19,7 +19,6 @@
ESP_LOGI("mqtt_test", "Test:" #test_name "() passed "); \
} while(0)
/**
* @brief This module contains mqtt test cases interacting the client with a (real) broker
*/

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -15,7 +15,6 @@
#include "test_mqtt_connection.h"
#include "esp_partition.h"
TEST_GROUP(mqtt5);
TEST_SETUP(mqtt5)
@@ -43,7 +42,7 @@ TEST(mqtt5, init_with_invalid_url)
.session.protocol_ver = MQTT_PROTOCOL_V_5,
};
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg);
TEST_ASSERT_EQUAL(NULL, client );
TEST_ASSERT_EQUAL(NULL, client);
}
TEST(mqtt5, init_and_deinit)
@@ -75,14 +74,13 @@ TEST(mqtt5, init_and_deinit)
.correlation_data = "123456",
.correlation_data_len = 6,
};
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg);
esp_mqtt5_client_set_user_property(&connect_property.user_property, user_property_arr, 3);
esp_mqtt5_client_set_user_property(&connect_property.will_user_property, user_property_arr, 3);
esp_mqtt5_client_set_connect_property(client, &connect_property);
esp_mqtt5_client_delete_user_property(connect_property.user_property);
esp_mqtt5_client_delete_user_property(connect_property.will_user_property);
TEST_ASSERT_NOT_EQUAL(NULL, client );
TEST_ASSERT_NOT_EQUAL(NULL, client);
esp_mqtt_client_destroy(client);
}
@@ -98,7 +96,7 @@ static const char *this_bin_addr(void)
TEST(mqtt5, enqueue_and_destroy_outbox)
{
const char *bin_addr = this_bin_addr();
// Reseting leak detection since this_bin_addr adds to allocated memory.
// Resetting leak detection since this_bin_addr adds to allocated memory.
test_utils_record_free_mem();
TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL));
const int messages = 20;
@@ -118,8 +116,9 @@ TEST(mqtt5, enqueue_and_destroy_outbox)
.content_type = "json",
};
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg);
TEST_ASSERT_NOT_EQUAL(NULL, client );
TEST_ASSERT_NOT_EQUAL(NULL, client);
int bytes_before = esp_get_free_heap_size();
for (int i = 0; i < messages; i ++) {
esp_mqtt5_client_set_user_property(&publish_property.user_property, user_property_arr, 3);
esp_mqtt5_client_set_publish_property(client, &publish_property);
@@ -127,27 +126,25 @@ TEST(mqtt5, enqueue_and_destroy_outbox)
esp_mqtt5_client_delete_user_property(publish_property.user_property);
publish_property.user_property = NULL;
}
int bytes_after = esp_get_free_heap_size();
// check that outbox allocated all messages on heap
TEST_ASSERT_GREATER_OR_EQUAL(messages * size, bytes_before - bytes_after);
esp_mqtt_client_destroy(client);
}
#if SOC_EMAC_SUPPORTED
/**
* This test cases uses ethernet kit, so build and use it only if EMAC supported
* This test cases uses ethernet kit, so build and use it only if EMACS supported
*/
TEST(mqtt5, broker_tests)
{
test_case_uses_tcpip();
connect_test_fixture_setup();
RUN_MQTT5_BROKER_TEST(mqtt5_connect_disconnect);
RUN_MQTT5_BROKER_TEST(mqtt5_subscribe_publish);
RUN_MQTT5_BROKER_TEST(mqtt5_lwt_clean_disconnect);
RUN_MQTT5_BROKER_TEST(mqtt5_subscribe_payload);
connect_test_fixture_teardown();
}
#endif // SOC_EMAC_SUPPORTED
@@ -158,14 +155,12 @@ TEST_GROUP_RUNNER(mqtt5)
RUN_TEST_CASE(mqtt5, init_with_invalid_url);
RUN_TEST_CASE(mqtt5, init_and_deinit);
RUN_TEST_CASE(mqtt5, enqueue_and_destroy_outbox);
#if SOC_EMAC_SUPPORTED
RUN_TEST_CASE(mqtt5, broker_tests);
#endif // SOC_EMAC_SUPPORTED
#endif //!DISABLED_FOR_TARGETS(ESP32H2)
}
void app_main(void)
{
UNITY_MAIN(mqtt5);

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -23,7 +23,6 @@
} \
} while(0)
static const int COMMON_OPERATION_TIMEOUT = 10000;
static const int CONNECT_BIT = BIT0;
static const int DISCONNECT_BIT = BIT1;
@@ -37,7 +36,7 @@ static esp_mqtt5_user_property_item_t user_property_arr[3] = {
{"p", "password"}
};
static char* append_mac(const char* string)
static char *append_mac(const char *string)
{
uint8_t mac[6];
char *id_string = NULL;
@@ -50,7 +49,7 @@ static void mqtt5_data_handler_qos(void *handler_args, esp_event_base_t base, in
{
if (event_id == MQTT_EVENT_DATA) {
esp_mqtt_event_handle_t event = event_data;
int * qos = handler_args;
int *qos = handler_args;
*qos = event->qos;
xEventGroupSetBits(s_event_group, DATA_BIT);
}
@@ -63,12 +62,13 @@ static void mqtt5_data_handler_lwt(void *handler_args, esp_event_base_t base, in
ESP_LOGI("mqtt-lwt", "MQTT_EVENT_DATA");
ESP_LOGI("mqtt-lwt", "TOPIC=%.*s", event->topic_len, event->topic);
ESP_LOGI("mqtt-lwt", "DATA=%.*s", event->data_len, event->data);
if (strncmp(event->data, "no-lwt", event->data_len) == 0) {
// no lwt, just to indicate the test has finished
xEventGroupSetBits(s_event_group, DATA_BIT);
} else {
// count up any potential lwt message
int * count = handler_args;
int *count = handler_args;
*count = *count + 1;
ESP_LOGE("mqtt5-lwt", "count=%d", *count);
}
@@ -80,37 +80,39 @@ static void mqtt5_data_handler_subscribe(void *handler_args, esp_event_base_t ba
if (event_id == MQTT_EVENT_SUBSCRIBED) {
esp_mqtt_event_handle_t event = event_data;
ESP_LOGI("mqtt5-subscribe", "MQTT_EVENT_SUBSCRIBED, data size=%d", event->data_len);
int * sub_payload = handler_args;
int *sub_payload = handler_args;
if (event->data_len == 1) {
ESP_LOGI("mqtt5-subscribe", "DATA=%d", *(uint8_t*)event->data);
*sub_payload = *(uint8_t*)event->data;
ESP_LOGI("mqtt5-subscribe", "DATA=%d", *(uint8_t *)event->data);
*sub_payload = *(uint8_t *)event->data;
}
xEventGroupSetBits(s_event_group, DATA_BIT);
}
}
static void mqtt5_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
switch ((esp_mqtt_event_id_t)event_id) {
case MQTT_EVENT_CONNECTED:
xEventGroupSetBits(s_event_group, CONNECT_BIT);
break;
case MQTT_EVENT_CONNECTED:
xEventGroupSetBits(s_event_group, CONNECT_BIT);
break;
case MQTT_EVENT_DISCONNECTED:
xEventGroupSetBits(s_event_group, DISCONNECT_BIT);
break;
default:
break;
case MQTT_EVENT_DISCONNECTED:
xEventGroupSetBits(s_event_group, DISCONNECT_BIT);
break;
default:
break;
}
}
bool mqtt5_connect_disconnect(void)
{
const esp_mqtt_client_config_t mqtt5_cfg = {
.broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI,
.network.disable_auto_reconnect = true,
.session.protocol_ver = MQTT_PROTOCOL_V_5,
.broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI,
.network.disable_auto_reconnect = true,
.session.protocol_ver = MQTT_PROTOCOL_V_5,
};
esp_mqtt5_connection_property_config_t connect_property = {
.session_expiry_interval = 10,
@@ -126,14 +128,15 @@ bool mqtt5_connect_disconnect(void)
};
s_event_group = xEventGroupCreate();
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg);
TEST_ASSERT_TRUE(NULL != client );
TEST_ASSERT_TRUE(NULL != client);
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt5_event_handler, NULL);
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_user_property(&connect_property.user_property, user_property_arr, 3));
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_connect_property(client, &connect_property));
esp_mqtt5_client_delete_user_property(connect_property.user_property);
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt_client_start(client));
WAIT_FOR_EVENT(CONNECT_BIT);
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_user_property(&disconnect_property.user_property, user_property_arr, 3));
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_user_property(&disconnect_property.user_property, user_property_arr,
3));
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_disconnect_property(client, &disconnect_property));
esp_mqtt5_client_delete_user_property(disconnect_property.user_property);
esp_mqtt_client_disconnect(client);
@@ -148,8 +151,8 @@ bool mqtt5_connect_disconnect(void)
bool mqtt5_subscribe_publish(void)
{
const esp_mqtt_client_config_t mqtt5_cfg = {
.broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI,
.session.protocol_ver = MQTT_PROTOCOL_V_5,
.broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI,
.session.protocol_ver = MQTT_PROTOCOL_V_5,
};
esp_mqtt5_publish_property_config_t publish_property = {
.payload_format_indicator = 1,
@@ -166,11 +169,11 @@ bool mqtt5_subscribe_publish(void)
.retain_as_published_flag = true,
.retain_handle = 0,
};
char* topic = append_mac("topic");
char *topic = append_mac("topic");
TEST_ASSERT_TRUE(NULL != topic);
s_event_group = xEventGroupCreate();
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg);
TEST_ASSERT_TRUE(NULL != client );
TEST_ASSERT_TRUE(NULL != client);
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt5_event_handler, NULL);
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt_client_start(client));
WAIT_FOR_EVENT(CONNECT_BIT);
@@ -193,21 +196,21 @@ bool mqtt5_subscribe_publish(void)
bool mqtt5_lwt_clean_disconnect(void)
{
char* lwt = append_mac("lwt");
char *lwt = append_mac("lwt");
TEST_ASSERT_TRUE(lwt);
const esp_mqtt_client_config_t mqtt5_cfg1 = {
.broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI,
.credentials.set_null_client_id = true,
.session.last_will.topic = lwt,
.session.last_will.msg = "lwt_msg",
.session.protocol_ver = MQTT_PROTOCOL_V_5,
.broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI,
.credentials.set_null_client_id = true,
.session.last_will.topic = lwt,
.session.last_will.msg = "lwt_msg",
.session.protocol_ver = MQTT_PROTOCOL_V_5,
};
const esp_mqtt_client_config_t mqtt5_cfg2 = {
.broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI,
.credentials.set_null_client_id = true,
.session.last_will.topic = lwt,
.session.last_will.msg = "lwt_msg",
.session.protocol_ver = MQTT_PROTOCOL_V_5,
.broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI,
.credentials.set_null_client_id = true,
.session.last_will.topic = lwt,
.session.last_will.msg = "lwt_msg",
.session.protocol_ver = MQTT_PROTOCOL_V_5,
};
esp_mqtt5_connection_property_config_t connect_property = {
.will_delay_interval = 10,
@@ -219,10 +222,9 @@ bool mqtt5_lwt_clean_disconnect(void)
.correlation_data_len = 6,
};
s_event_group = xEventGroupCreate();
esp_mqtt_client_handle_t client1 = esp_mqtt_client_init(&mqtt5_cfg1);
esp_mqtt_client_handle_t client2 = esp_mqtt_client_init(&mqtt5_cfg2);
TEST_ASSERT_TRUE(NULL != client1 && NULL != client2 );
TEST_ASSERT_TRUE(NULL != client1 && NULL != client2);
esp_mqtt_client_register_event(client1, ESP_EVENT_ANY_ID, mqtt5_event_handler, NULL);
esp_mqtt_client_register_event(client2, ESP_EVENT_ANY_ID, mqtt5_event_handler, NULL);
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_connect_property(client1, &connect_property));
@@ -258,15 +260,15 @@ bool mqtt5_lwt_clean_disconnect(void)
bool mqtt5_subscribe_payload(void)
{
const esp_mqtt_client_config_t mqtt5_cfg = {
.broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI,
.network.disable_auto_reconnect = true,
.session.protocol_ver = MQTT_PROTOCOL_V_5,
.broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI,
.network.disable_auto_reconnect = true,
.session.protocol_ver = MQTT_PROTOCOL_V_5,
};
char* topic = append_mac("topic");
char *topic = append_mac("topic");
TEST_ASSERT_TRUE(NULL != topic);
s_event_group = xEventGroupCreate();
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg);
TEST_ASSERT_TRUE(NULL != client );
TEST_ASSERT_TRUE(NULL != client);
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt5_event_handler, NULL);
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt_client_start(client));
WAIT_FOR_EVENT(CONNECT_BIT);

View File

@@ -20,7 +20,6 @@
ESP_LOGI("mqtt5_test", "Test:" #test_name "() passed "); \
} while(0)
/**
* @brief This module contains mqtt5 test cases interacting the client with a (real) broker
*/

View File

@@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* MQTT connect test
This example code is in the Public Domain (or CC0 licensed, at your option.)
@@ -43,16 +48,21 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
(void)event_id;
esp_mqtt_event_handle_t event = event_data;
ESP_LOGD(TAG, "Event: %d, Test case: %d", event->event_id, running_test_case);
switch (event->event_id) {
case MQTT_EVENT_BEFORE_CONNECT:
break;
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED: Test=%d", running_test_case);
break;
case MQTT_EVENT_DISCONNECTED:
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR: Test=%d", running_test_case);
if (event->error_handle->error_type == MQTT_ERROR_TYPE_ESP_TLS) {
ESP_LOGI(TAG, "ESP-TLS ERROR: %s", esp_err_to_name(event->error_handle->esp_tls_last_esp_err));
} else if (event->error_handle->error_type == MQTT_ERROR_TYPE_CONNECTION_REFUSED) {
@@ -60,7 +70,9 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
} else {
ESP_LOGW(TAG, "Unknown error type: 0x%x", event->error_handle->error_type);
}
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
@@ -69,7 +81,7 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
static void connect_no_certs(esp_mqtt_client_handle_t client, const char *uri)
{
ESP_LOGI(TAG, "Runnning :CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT");
ESP_LOGI(TAG, "Running :CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT");
const esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = uri
};
@@ -81,10 +93,10 @@ static void connect_with_client_key_password(esp_mqtt_client_handle_t client, co
const esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = uri,
.broker.verification.certificate = (const char *)ca_local_crt,
.credentials.authentication.certificate = (const char *)client_pwd_crt,
.credentials.authentication.key = (const char *)client_pwd_key,
.credentials.authentication.key_password = "esp32",
.credentials.authentication.key_password_len = 5
.credentials.authentication.certificate = (const char *)client_pwd_crt,
.credentials.authentication.key = (const char *)client_pwd_key,
.credentials.authentication.key_password = "esp32",
.credentials.authentication.key_password_len = 5
};
esp_mqtt_set_config(client, &mqtt_cfg);
}
@@ -94,9 +106,9 @@ static void connect_with_server_der_cert(esp_mqtt_client_handle_t client, const
const esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = uri,
.broker.verification.certificate = (const char *)ca_der_start,
.broker.verification.certificate_len = ca_der_end - ca_der_start,
.credentials.authentication.certificate = "NULL",
.credentials.authentication.key = "NULL"
.broker.verification.certificate_len = ca_der_end - ca_der_start,
.credentials.authentication.certificate = "NULL",
.credentials.authentication.key = "NULL"
};
esp_mqtt_set_config(client, &mqtt_cfg);
}
@@ -106,8 +118,8 @@ static void connect_with_wrong_server_cert(esp_mqtt_client_handle_t client, cons
const esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = uri,
.broker.verification.certificate = (const char *)client_pwd_crt,
.credentials.authentication.certificate = "NULL",
.credentials.authentication.key = "NULL"
.credentials.authentication.certificate = "NULL",
.credentials.authentication.key = "NULL"
};
esp_mqtt_set_config(client, &mqtt_cfg);
}
@@ -126,8 +138,8 @@ static void connect_with_server_client_certs(esp_mqtt_client_handle_t client, co
const esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = uri,
.broker.verification.certificate = (const char *)ca_local_crt,
.credentials.authentication.certificate = (const char *)client_pwd_crt,
.credentials.authentication.key = (const char *)client_no_pwd_key
.credentials.authentication.certificate = (const char *)client_pwd_crt,
.credentials.authentication.key = (const char *)client_no_pwd_key
};
esp_mqtt_set_config(client, &mqtt_cfg);
}
@@ -137,8 +149,8 @@ static void connect_with_invalid_client_certs(esp_mqtt_client_handle_t client, c
const esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = uri,
.broker.verification.certificate = (const char *)ca_local_crt,
.credentials.authentication.certificate = (const char *)client_inv_crt,
.credentials.authentication.key = (const char *)client_no_pwd_key
.credentials.authentication.certificate = (const char *)client_inv_crt,
.credentials.authentication.key = (const char *)client_no_pwd_key
};
esp_mqtt_set_config(client, &mqtt_cfg);
}
@@ -153,45 +165,57 @@ static void connect_with_alpn(esp_mqtt_client_handle_t client, const char *uri)
esp_mqtt_set_config(client, &mqtt_cfg);
}
void connect_setup(command_context_t * ctx) {
void connect_setup(command_context_t *ctx)
{
esp_mqtt_client_register_event(ctx->mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler, ctx->data);
}
void connect_teardown(command_context_t * ctx) {
void connect_teardown(command_context_t *ctx)
{
esp_mqtt_client_unregister_event(ctx->mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler);
}
void connection_test(command_context_t * ctx, const char *uri, int test_case)
void connection_test(command_context_t *ctx, const char *uri, int test_case)
{
ESP_LOGI(TAG, "CASE:%d, connecting to %s", test_case, uri);
running_test_case = test_case;
switch (test_case) {
case CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT:
connect_no_certs(ctx->mqtt_client, uri);
break;
case CONFIG_EXAMPLE_CONNECT_CASE_SERVER_CERT:
connect_with_server_cert(ctx->mqtt_client, uri);
break;
case CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH:
connect_with_server_client_certs(ctx->mqtt_client, uri);
break;
case CONFIG_EXAMPLE_CONNECT_CASE_INVALID_SERVER_CERT:
connect_with_wrong_server_cert(ctx->mqtt_client, uri);
break;
case CONFIG_EXAMPLE_CONNECT_CASE_SERVER_DER_CERT:
connect_with_server_der_cert(ctx->mqtt_client, uri);
break;
case CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_KEY_PWD:
connect_with_client_key_password(ctx->mqtt_client, uri);
break;
case CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_BAD_CRT:
connect_with_invalid_client_certs(ctx->mqtt_client, uri);
break;
case CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT_ALPN:
connect_with_alpn(ctx->mqtt_client, uri);
break;
default:
ESP_LOGE(TAG, "Unknown test case %d ", test_case);
break;
}
ESP_LOGI(TAG, "Test case:%d started", test_case);
}

View File

@@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* MQTT publish-connect test
This example code is in the Public Domain (or CC0 licensed, at your option.)
@@ -36,15 +41,16 @@ publish_args_t publish_args;
return 1; \
}} while(0)
static int do_free_heap(int argc, char **argv) {
static int do_free_heap(int argc, char **argv)
{
(void)argc;
(void)argv;
ESP_LOGI(TAG, "Note free memory: %d bytes", esp_get_free_heap_size());
return 0;
}
static int do_init(int argc, char **argv) {
static int do_init(int argc, char **argv)
{
(void)argc;
(void)argv;
const esp_mqtt_client_config_t mqtt_cfg = {
@@ -52,75 +58,92 @@ static int do_init(int argc, char **argv) {
.network.disable_auto_reconnect = true
};
command_context.mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
if(!command_context.mqtt_client) {
if (!command_context.mqtt_client) {
ESP_LOGE(TAG, "Failed to initialize client");
return 1;
}
publish_init_flags();
ESP_LOGI(TAG, "Mqtt client initialized");
return 0;
}
static int do_start(int argc, char **argv) {
static int do_start(int argc, char **argv)
{
(void)argc;
(void)argv;
if(esp_mqtt_client_start(command_context.mqtt_client) != ESP_OK) {
if (esp_mqtt_client_start(command_context.mqtt_client) != ESP_OK) {
ESP_LOGE(TAG, "Failed to start mqtt client task");
return 1;
}
ESP_LOGI(TAG, "Mqtt client started");
return 0;
}
static int do_stop(int argc, char **argv) {
static int do_stop(int argc, char **argv)
{
(void)argc;
(void)argv;
if(esp_mqtt_client_stop(command_context.mqtt_client) != ESP_OK) {
if (esp_mqtt_client_stop(command_context.mqtt_client) != ESP_OK) {
ESP_LOGE(TAG, "Failed to stop mqtt client task");
return 1;
}
ESP_LOGI(TAG, "Mqtt client stopped");
return 0;
}
static int do_disconnect(int argc, char **argv) {
static int do_disconnect(int argc, char **argv)
{
(void)argc;
(void)argv;
if(esp_mqtt_client_disconnect(command_context.mqtt_client) != ESP_OK) {
if (esp_mqtt_client_disconnect(command_context.mqtt_client) != ESP_OK) {
ESP_LOGE(TAG, "Failed to request disconnection");
return 1;
}
ESP_LOGI(TAG, "Mqtt client disconnected");
return 0;
}
static int do_connect_setup(int argc, char **argv) {
static int do_connect_setup(int argc, char **argv)
{
(void)argc;
(void)argv;
connect_setup(&command_context);
return 0;
}
static int do_connect_teardown(int argc, char **argv) {
static int do_connect_teardown(int argc, char **argv)
{
(void)argc;
(void)argv;
connect_teardown(&command_context);
return 0;
}
static int do_reconnect(int argc, char **argv) {
static int do_reconnect(int argc, char **argv)
{
(void)argc;
(void)argv;
if(esp_mqtt_client_reconnect(command_context.mqtt_client) != ESP_OK) {
if (esp_mqtt_client_reconnect(command_context.mqtt_client) != ESP_OK) {
ESP_LOGE(TAG, "Failed to request reconnection");
return 1;
}
ESP_LOGI(TAG, "Mqtt client will reconnect");
return 0;
;
}
static int do_destroy(int argc, char **argv) {
static int do_destroy(int argc, char **argv)
{
(void)argc;
(void)argv;
esp_mqtt_client_destroy(command_context.mqtt_client);
@@ -132,54 +155,62 @@ static int do_destroy(int argc, char **argv) {
static int do_connect(int argc, char **argv)
{
int nerrors = arg_parse(argc, argv, (void **) &connection_args);
if (nerrors != 0) {
arg_print_errors(stderr, connection_args.end, argv[0]);
return 1;
}
if(!command_context.mqtt_client) {
if (!command_context.mqtt_client) {
ESP_LOGE(TAG, "MQTT client not initialized, call init first");
return 1;
}
connection_test(&command_context, *connection_args.uri->sval, *connection_args.test_case->ival);
return 0;
}
static int do_publish_setup(int argc, char **argv) {
static int do_publish_setup(int argc, char **argv)
{
RETURN_ON_PARSE_ERROR(publish_setup_args);
if(command_context.data) {
if (command_context.data) {
free(command_context.data);
}
command_context.data = calloc(1, sizeof(publish_context_t));
((publish_context_t*)command_context.data)->pattern = strdup(*publish_setup_args.pattern->sval);
((publish_context_t*)command_context.data)->pattern_repetitions = *publish_setup_args.pattern_repetitions->ival;
((publish_context_t*)command_context.data)->subscribe_to = strdup(*publish_setup_args.subscribe_to->sval);
((publish_context_t*)command_context.data)->publish_to = strdup(*publish_setup_args.publish_to->sval);
((publish_context_t *)command_context.data)->pattern = strdup(*publish_setup_args.pattern->sval);
((publish_context_t *)command_context.data)->pattern_repetitions = *publish_setup_args.pattern_repetitions->ival;
((publish_context_t *)command_context.data)->subscribe_to = strdup(*publish_setup_args.subscribe_to->sval);
((publish_context_t *)command_context.data)->publish_to = strdup(*publish_setup_args.publish_to->sval);
publish_setup(&command_context, *publish_setup_args.transport->sval);
return 0;
}
static int do_publish(int argc, char **argv) {
static int do_publish(int argc, char **argv)
{
RETURN_ON_PARSE_ERROR(publish_args);
publish_test(&command_context, publish_args.expected_to_publish->ival[0], publish_args.qos->ival[0], publish_args.enqueue->ival[0]);
publish_test(&command_context, publish_args.expected_to_publish->ival[0], publish_args.qos->ival[0],
publish_args.enqueue->ival[0]);
return 0;
}
static int do_publish_report(int argc, char **argv) {
static int do_publish_report(int argc, char **argv)
{
(void)argc;
(void)argv;
publish_context_t * ctx = command_context.data;
ESP_LOGI(TAG,"Test Report : Messages received %d, %d expected", ctx->nr_of_msg_received, ctx->nr_of_msg_expected);
publish_context_t *ctx = command_context.data;
ESP_LOGI(TAG, "Test Report : Messages received %d, %d expected", ctx->nr_of_msg_received, ctx->nr_of_msg_expected);
return 0;
}
void register_common_commands(void) {
void register_common_commands(void)
{
const esp_console_cmd_t init = {
.command = "init",
.help = "Run inition test\n",
.hint = NULL,
.func = &do_init,
};
const esp_console_cmd_t start = {
.command = "start",
.help = "Run startion test\n",
@@ -210,17 +241,19 @@ void register_common_commands(void) {
ESP_ERROR_CHECK(esp_console_cmd_register(&destroy));
ESP_ERROR_CHECK(esp_console_cmd_register(&free_heap));
}
void register_publish_commands(void) {
publish_setup_args.transport = arg_str1(NULL,NULL,"<transport>", "Selected transport to test");
publish_setup_args.publish_to = arg_str1(NULL,NULL,"<transport>", "Selected publish_to to publish");
publish_setup_args.subscribe_to = arg_str1(NULL,NULL,"<transport>", "Selected subscribe_to to publish");
publish_setup_args.pattern = arg_str1(NULL,NULL,"<pattern>", "Message pattern repeated to build big messages");
publish_setup_args.pattern_repetitions = arg_int1(NULL,NULL,"<pattern repetitions>", "How many times the pattern is repeated");
void register_publish_commands(void)
{
publish_setup_args.transport = arg_str1(NULL, NULL, "<transport>", "Selected transport to test");
publish_setup_args.publish_to = arg_str1(NULL, NULL, "<transport>", "Selected publish_to to publish");
publish_setup_args.subscribe_to = arg_str1(NULL, NULL, "<transport>", "Selected subscribe_to to publish");
publish_setup_args.pattern = arg_str1(NULL, NULL, "<pattern>", "Message pattern repeated to build big messages");
publish_setup_args.pattern_repetitions = arg_int1(NULL, NULL, "<pattern repetitions>",
"How many times the pattern is repeated");
publish_setup_args.end = arg_end(1);
publish_args.expected_to_publish = arg_int1(NULL,NULL,"<number of messages>", "How many times the pattern is repeated");
publish_args.qos = arg_int1(NULL,NULL,"<qos>", "How many times the pattern is repeated");
publish_args.enqueue = arg_int1(NULL,NULL,"<enqueue>", "How many times the pattern is repeated");
publish_args.expected_to_publish = arg_int1(NULL, NULL, "<number of messages>",
"How many times the pattern is repeated");
publish_args.qos = arg_int1(NULL, NULL, "<qos>", "How many times the pattern is repeated");
publish_args.enqueue = arg_int1(NULL, NULL, "<enqueue>", "How many times the pattern is repeated");
publish_args.end = arg_end(1);
const esp_console_cmd_t publish_setup = {
.command = "publish_setup",
@@ -229,7 +262,6 @@ void register_publish_commands(void) {
.func = &do_publish_setup,
.argtable = &publish_setup_args
};
const esp_console_cmd_t publish = {
.command = "publish",
.help = "Run publish test\n",
@@ -247,11 +279,11 @@ void register_publish_commands(void) {
ESP_ERROR_CHECK(esp_console_cmd_register(&publish));
ESP_ERROR_CHECK(esp_console_cmd_register(&publish_report));
}
void register_connect_commands(void){
connection_args.uri = arg_str1(NULL,NULL,"<broker uri>", "Broker address");
connection_args.test_case = arg_int1(NULL, NULL, "<test case>","Selected test case");
void register_connect_commands(void)
{
connection_args.uri = arg_str1(NULL, NULL, "<broker uri>", "Broker address");
connection_args.test_case = arg_int1(NULL, NULL, "<test case>", "Selected test case");
connection_args.end = arg_end(1);
const esp_console_cmd_t connect = {
.command = "connect",
.help = "Run connection test\n",
@@ -259,7 +291,6 @@ void register_connect_commands(void){
.func = &do_connect,
.argtable = &connection_args
};
const esp_console_cmd_t reconnect = {
.command = "reconnect",
.help = "Run reconnection test\n",
@@ -292,7 +323,7 @@ void register_connect_commands(void){
}
#ifdef CONFIG_EXAMPLE_RUN_LOCAL_BROKER
static void broker_task(void* ctx)
static void broker_task(void *ctx)
{
// broker continues to run in this task
struct mosq_broker_config config = { .host = CONFIG_EXAMPLE_BROKER_HOST, .port = CONFIG_EXAMPLE_BROKER_PORT };
@@ -303,15 +334,12 @@ static void broker_task(void* ctx)
void app_main(void)
{
static const size_t max_line = 256;
ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
esp_log_level_set("*", ESP_LOG_INFO);
esp_log_level_set("wifi", ESP_LOG_ERROR);
esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE);
esp_log_level_set("outbox", ESP_LOG_VERBOSE);
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
@@ -327,7 +355,6 @@ void app_main(void)
register_common_commands();
register_connect_commands();
register_publish_commands();
esp_console_dev_uart_config_t hw_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_console_new_repl_uart(&hw_config, &repl_config, &repl));
ESP_ERROR_CHECK(esp_console_start_repl(repl));

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -11,7 +11,7 @@ typedef enum {NONE, TCP, SSL, WS, WSS} transport_t;
typedef struct {
esp_mqtt_client_handle_t mqtt_client;
void * data;
void *data;
} command_context_t;
typedef struct {
@@ -25,7 +25,7 @@ typedef struct {
size_t expected_size;
size_t nr_of_msg_received;
size_t nr_of_msg_expected;
char * received_data;
char *received_data;
} publish_context_t ;
typedef struct {
@@ -51,9 +51,9 @@ typedef struct {
} publish_setup_args_t;
void publish_init_flags(void);
void publish_setup(command_context_t * ctx, char const * transport);
void publish_teardown(command_context_t * ctx);
void publish_test(command_context_t * ctx, int expect_to_publish, int qos, bool enqueue);
void connection_test(command_context_t * ctx, const char *uri, int test_case);
void connect_setup(command_context_t * ctx);
void connect_teardown(command_context_t * ctx);
void publish_setup(command_context_t *ctx, char const *transport);
void publish_teardown(command_context_t *ctx);
void publish_test(command_context_t *ctx, int expect_to_publish, int qos, bool enqueue);
void connection_test(command_context_t *ctx, const char *uri, int test_case);
void connect_setup(command_context_t *ctx);
void connect_teardown(command_context_t *ctx);

View File

@@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* MQTT publish test
This example code is in the Public Domain (or CC0 licensed, at your option.)
@@ -27,7 +32,8 @@ static EventGroupHandle_t mqtt_event_group;
const static int CONNECTED_BIT = BIT0;
#define CLIENT_ID_SUFFIX_SIZE 12
#if CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDDEN == 1
static const uint8_t mqtt_eclipseprojects_io_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----";
static const uint8_t mqtt_eclipseprojects_io_pem_start[] = "-----BEGIN CERTIFICATE-----\n"
CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----";
#else
extern const uint8_t mqtt_eclipseprojects_io_pem_start[] asm("_binary_mqtt_eclipseprojects_io_pem_start");
#endif
@@ -35,21 +41,23 @@ extern const uint8_t mqtt_eclipseprojects_io_pem_end[] asm("_binary_mqtt_eclip
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
publish_context_t * test_data = handler_args;
publish_context_t *test_data = handler_args;
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
static int msg_id = 0;
static int actual_len = 0;
switch (event->event_id) {
case MQTT_EVENT_BEFORE_CONNECT:
break;
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
xEventGroupSetBits(mqtt_event_group, CONNECTED_BIT);
msg_id = esp_mqtt_client_subscribe(client, test_data->subscribe_to, test_data->qos);
ESP_LOGI(TAG, "sent subscribe successful %s , msg_id=%d", test_data->subscribe_to, msg_id);
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
@@ -57,58 +65,74 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
case MQTT_EVENT_SUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGD(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
ESP_LOGI(TAG, "TOPIC=%.*s", event->topic_len, event->topic);
ESP_LOGI(TAG, "ID=%d, total_len=%d, data_len=%d, current_data_offset=%d", event->msg_id, event->total_data_len, event->data_len, event->current_data_offset);
if (event->current_data_offset == 0) {
actual_len = event->data_len;
msg_id = event->msg_id;
if (event->total_data_len != test_data->expected_size) {
ESP_LOGE(TAG, "Incorrect message size: %d != %d", event->total_data_len, test_data->expected_size);
abort();
}
} else {
actual_len += event->data_len;
// check consistency with msg_id across multiple data events for single msg
if (msg_id != event->msg_id) {
ESP_LOGE(TAG, "Wrong msg_id in chunked message %d != %d", msg_id, event->msg_id);
abort();
}
}
if (event->current_data_offset + event->data_len > test_data->expected_size) {
ESP_LOGE(TAG, "Buffer overflow detected: offset %d + data_len %d > buffer size %d", event->current_data_offset, event->data_len, test_data->expected_size);
abort();
}
if (memcmp(test_data->expected + event->current_data_offset, event->data, event->data_len) != 0) {
ESP_LOGE(TAG, "Data mismatch at offset %d: \n expected %.*s, \n got %.*s", event->current_data_offset, event->data_len, test_data->expected + event->current_data_offset, event->data_len, event->data);
abort();
}
ESP_LOGI(TAG, "ID=%d, total_len=%d, data_len=%d, current_data_offset=%d", event->msg_id, event->total_data_len,
event->data_len, event->current_data_offset);
if (event->current_data_offset == 0) {
actual_len = event->data_len;
msg_id = event->msg_id;
if (event->total_data_len != test_data->expected_size) {
ESP_LOGE(TAG, "Incorrect message size: %d != %d", event->total_data_len, test_data->expected_size);
abort();
}
} else {
actual_len += event->data_len;
// check consistency with msg_id across multiple data events for single msg
if (msg_id != event->msg_id) {
ESP_LOGE(TAG, "Wrong msg_id in chunked message %d != %d", msg_id, event->msg_id);
abort();
}
}
if (event->current_data_offset + event->data_len > test_data->expected_size) {
ESP_LOGE(TAG, "Buffer overflow detected: offset %d + data_len %d > buffer size %d", event->current_data_offset,
event->data_len, test_data->expected_size);
abort();
}
if (memcmp(test_data->expected + event->current_data_offset, event->data, event->data_len) != 0) {
ESP_LOGE(TAG, "Data mismatch at offset %d: \n expected %.*s, \n got %.*s", event->current_data_offset, event->data_len,
test_data->expected + event->current_data_offset, event->data_len, event->data);
abort();
}
memcpy(test_data->received_data + event->current_data_offset, event->data, event->data_len);
if (actual_len == event->total_data_len) {
if (0 == memcmp(test_data->received_data, test_data->expected, test_data->expected_size)) {
memset(test_data->received_data, 0, test_data->expected_size);
test_data->nr_of_msg_received++;
if (test_data->nr_of_msg_received == test_data->nr_of_msg_expected) {
ESP_LOGI(TAG, "Correct pattern received exactly x times");
ESP_LOGI(TAG, "Test finished correctly!");
}
} else {
ESP_LOGE(TAG, "FAILED!");
abort();
}
}
memcpy(test_data->received_data + event->current_data_offset, event->data, event->data_len);
if (actual_len == event->total_data_len) {
if (0 == memcmp(test_data->received_data, test_data->expected, test_data->expected_size)) {
memset(test_data->received_data, 0, test_data->expected_size);
test_data->nr_of_msg_received++;
if (test_data->nr_of_msg_received == test_data->nr_of_msg_expected) {
ESP_LOGI(TAG, "Correct pattern received exactly x times");
ESP_LOGI(TAG, "Test finished correctly!");
}
} else {
ESP_LOGE(TAG, "FAILED!");
abort();
}
}
break;
case MQTT_EVENT_ERROR:
ESP_LOGE(TAG, "MQTT_EVENT_ERROR");
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
@@ -120,7 +144,7 @@ void test_init(void)
ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
}
void pattern_setup(publish_context_t * test_data)
void pattern_setup(publish_context_t *test_data)
{
int pattern_size = strlen(test_data->pattern);
free(test_data->expected);
@@ -129,17 +153,20 @@ void pattern_setup(publish_context_t * test_data)
test_data->expected_size = (size_t)(pattern_size) * test_data->pattern_repetitions;
test_data->expected = malloc(test_data->expected_size);
test_data->received_data = malloc(test_data->expected_size);
for (int i = 0; i < test_data->pattern_repetitions; i++) {
memcpy(test_data->expected + (ptrdiff_t)(i * pattern_size), test_data->pattern, pattern_size);
}
ESP_LOGI(TAG, "EXPECTED STRING %.*s, SIZE:%d", test_data->expected_size, test_data->expected, test_data->expected_size);
}
static void configure_client(command_context_t * ctx, const char *transport)
static void configure_client(command_context_t *ctx, const char *transport)
{
publish_context_t * test_data = ctx->data;
publish_context_t *test_data = ctx->data;
ESP_LOGI(TAG, "Configuration");
transport_t selected_transport;
if (0 == strcmp(transport, "tcp")) {
selected_transport = TCP;
} else if (0 == strcmp(transport, "ssl")) {
@@ -153,34 +180,40 @@ static void configure_client(command_context_t * ctx, const char *transport)
abort();
}
if (selected_transport != test_data->selected_transport) {
test_data->selected_transport = selected_transport;
esp_mqtt_client_config_t config = {0};
switch (selected_transport) {
case NONE:
break;
case TCP:
ESP_LOGI(TAG, "[TCP transport] Startup..");
config.broker.address.uri = CONFIG_EXAMPLE_BROKER_TCP_URI;
break;
case SSL:
ESP_LOGI(TAG, "[SSL transport] Startup..");
config.broker.address.uri = CONFIG_EXAMPLE_BROKER_SSL_URI;
break;
case WS:
ESP_LOGI(TAG, "[WS transport] Startup..");
config.broker.address.uri = CONFIG_EXAMPLE_BROKER_WS_URI;
break;
case WSS:
ESP_LOGI(TAG, "[WSS transport] Startup..");
config.broker.address.uri = CONFIG_EXAMPLE_BROKER_WSS_URI;
break;
}
if (selected_transport == SSL || selected_transport == WSS) {
ESP_LOGI(TAG, "Set certificate");
config.broker.verification.certificate = (const char *)mqtt_eclipseprojects_io_pem_start;
}
// Generate a random client id for each iteration
char client_id[CLIENT_ID_SUFFIX_SIZE] = {0};
snprintf(client_id, sizeof(client_id), "esp32-%08X", esp_random());
@@ -189,41 +222,47 @@ static void configure_client(command_context_t * ctx, const char *transport)
}
}
void publish_init_flags(void) {
void publish_init_flags(void)
{
mqtt_event_group = xEventGroupCreate();
}
void publish_setup(command_context_t * ctx, char const * const transport) {
void publish_setup(command_context_t *ctx, char const *const transport)
{
xEventGroupClearBits(mqtt_event_group, CONNECTED_BIT);
publish_context_t * data = (publish_context_t*)ctx->data;
publish_context_t *data = (publish_context_t *)ctx->data;
pattern_setup(data);
configure_client(ctx, transport);
esp_mqtt_client_register_event(ctx->mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler, data);
}
void publish_teardown(command_context_t * ctx)
void publish_teardown(command_context_t *ctx)
{
esp_mqtt_client_unregister_event(ctx->mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler);
}
void publish_test(command_context_t * ctx, int expect_to_publish, int qos, bool enqueue)
void publish_test(command_context_t *ctx, int expect_to_publish, int qos, bool enqueue)
{
publish_context_t * data = (publish_context_t*)ctx->data;
publish_context_t *data = (publish_context_t *)ctx->data;
data->nr_of_msg_expected = expect_to_publish;
ESP_LOGI(TAG, "PATTERN:%s REPEATED:%d PUBLISHED:%d", data->pattern, data->pattern_repetitions, data->nr_of_msg_expected);
ESP_LOGI(TAG, "PATTERN:%s REPEATED:%d PUBLISHED:%d", data->pattern, data->pattern_repetitions,
data->nr_of_msg_expected);
xEventGroupWaitBits(mqtt_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
for (int i = 0; i < data->nr_of_msg_expected; i++) {
int msg_id;
if (enqueue) {
msg_id = esp_mqtt_client_enqueue(ctx->mqtt_client, data->publish_to, data->expected, data->expected_size, qos, 0, true);
} else {
msg_id = esp_mqtt_client_publish(ctx->mqtt_client, data->publish_to, data->expected, data->expected_size, qos, 0);
if(msg_id < 0) {
if (msg_id < 0) {
ESP_LOGE(TAG, "Failed to publish");
break;
}
}
ESP_LOGD(TAG, "Publishing msg_id=%d", msg_id);
}
}

View File

@@ -181,8 +181,8 @@ def connect_dut(dut: Dut, uri: str, case_id: int) -> Any:
def run_cases(dut: Dut, uri: str, cases: Dict[str, int]) -> None:
try:
dut.write('init')
dut.write(f'start')
dut.write(f'disconnect')
dut.write('start')
dut.write('disconnect')
for case in [
'EXAMPLE_CONNECT_CASE_NO_CERT',
'EXAMPLE_CONNECT_CASE_SERVER_CERT',

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -25,7 +25,7 @@ extern "C" {
#include "Mockqueue.h"
#include "Mocktask.h"
#if __has_include ("Mockidf_additions.h")
/* Some functions were moved from "task.h" to "idf_additions.h" */
/* Some functions were moved from "task.h" to "idf_additions.h" */
#include "Mockidf_additions.h"
#endif
#include "Mockesp_timer.h"
@@ -49,7 +49,8 @@ auto random_string(std::size_t n)
return str;
}
using unique_mqtt_client = std::unique_ptr < std::remove_pointer_t<esp_mqtt_client_handle_t>, decltype([](esp_mqtt_client_handle_t client)
using unique_mqtt_client = std::unique_ptr < std::remove_pointer_t<esp_mqtt_client_handle_t>,
decltype([](esp_mqtt_client_handle_t client)
{
esp_mqtt_client_destroy(client);
}) >;
@@ -118,15 +119,15 @@ SCENARIO("MQTT Client Operation")
REQUIRE(res == ESP_FAIL);
}
}
SECTION("User set interface to use"){
SECTION("User set interface to use") {
http_parser_parse_url_ExpectAnyArgsAndReturn(0);
http_parser_parse_url_ReturnThruPtr_u(&ret_uri);
struct ifreq if_name = {};
strncpy(if_name.ifr_name, "custom", IFNAMSIZ - 1);
if_name.ifr_name[IFNAMSIZ - 1] = '\0';;
config.network.if_name = &if_name;
SECTION("Client is not started"){
REQUIRE(esp_mqtt_set_config(client.get(), &config)== ESP_OK);
SECTION("Client is not started") {
REQUIRE(esp_mqtt_set_config(client.get(), &config) == ESP_OK);
}
}
SECTION("After Start Client Is Cleanly destroyed") {
@@ -143,15 +144,14 @@ SCENARIO("MQTT Client Operation")
auto password = random_string(10);
auto lw_topic = random_string(10);
auto lw_msg = random_string(10);
config.broker = {.address = {
.hostname = host.data(),
.path = path.data()
.path = path.data()
}
};
config.credentials = {
.username = username.data(),
.client_id = client_id.data(),
.client_id = client_id.data(),
.authentication = {
.password = password.data()
}
@@ -159,13 +159,11 @@ SCENARIO("MQTT Client Operation")
config.session = {
.last_will {
.topic = lw_topic.data(),
.msg = lw_msg.data()
.msg = lw_msg.data()
}
};
auto client = unique_mqtt_client{esp_mqtt_client_init(&config)};
REQUIRE(client != nullptr);
}
}
}