fix(modem): Replace MQTT client with simple ping command

This commit is contained in:
David Cermak
2025-11-24 09:07:19 +01:00
parent 9b2b1f680d
commit 0ccaf2c0bb
6 changed files with 30 additions and 251 deletions

View File

@@ -1,2 +1,2 @@
idf_component_register(SRCS "simple_cmux_client_main.cpp" "simple_mqtt_client.cpp"
idf_component_register(SRCS "simple_cmux_client_main.cpp"
INCLUDE_DIRS ".")

View File

@@ -2,7 +2,5 @@ dependencies:
espressif/esp_modem:
version: "^1.0.1"
override_path: "../../../"
espressif/mqtt:
rules:
- if: idf_version >=6.0
version: ^1.0.0
console_cmd_ping:
version: '*'

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: Unlicense OR CC0-1.0
*/
@@ -21,11 +21,13 @@
#include "cxx_include/esp_modem_dte.hpp"
#include "esp_modem_config.h"
#include "cxx_include/esp_modem_api.hpp"
#include "simple_mqtt_client.hpp"
#include "esp_vfs_dev.h" // For optional VFS support
#include "esp_https_ota.h" // For potential OTA configuration
#include "vfs_resource/vfs_create.hpp"
#include "SIM7070_gnss.hpp"
#include "esp_console.h"
#include "console_ping.h"
#include "esp_event.h"
#if defined(CONFIG_EXAMPLE_FLOW_CONTROL_NONE)
#define EXAMPLE_FLOW_CONTROL ESP_MODEM_FLOW_CONTROL_NONE
@@ -35,9 +37,6 @@
#define EXAMPLE_FLOW_CONTROL ESP_MODEM_FLOW_CONTROL_HW
#endif
#define BROKER_URL CONFIG_BROKER_URI
using namespace esp_modem;
static const char *TAG = "cmux_example";
@@ -45,8 +44,6 @@ static const char *TAG = "cmux_example";
class StatusHandler {
public:
static constexpr auto IP_Event = SignalGroup::bit0;
static constexpr auto MQTT_Connect = SignalGroup::bit1;
static constexpr auto MQTT_Data = SignalGroup::bit2;
StatusHandler()
{
@@ -58,12 +55,6 @@ public:
esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, on_event);
}
void handle_mqtt(MqttClient *client)
{
mqtt_client = client;
client->register_handler(ESP_EVENT_ANY_ID, on_event, this);
}
esp_err_t wait_for(decltype(IP_Event) event, int milliseconds)
{
return signal.wait_any(event, milliseconds);
@@ -80,8 +71,6 @@ private:
auto *handler = static_cast<StatusHandler *>(arg);
if (base == IP_EVENT) {
handler->ip_event(event, data);
} else {
handler->mqtt_event(event, data);
}
}
@@ -92,27 +81,16 @@ private:
ESP_LOGI(TAG, "IP : " IPSTR, IP2STR(&event->ip_info.ip));
ESP_LOGI(TAG, "Netmask : " IPSTR, IP2STR(&event->ip_info.netmask));
ESP_LOGI(TAG, "Gateway : " IPSTR, IP2STR(&event->ip_info.gw));
ip_event_type = static_cast<ip_event_t>(id);
signal.set(IP_Event);
} else if (id == IP_EVENT_PPP_LOST_IP) {
signal.set(IP_Event);
}
ip_event_type = static_cast<ip_event_t>(id);
}
void mqtt_event(int32_t event, void *data)
{
if (mqtt_client && event == mqtt_client->get_event(MqttClient::Event::CONNECT)) {
signal.set(MQTT_Connect);
} else if (mqtt_client && event == mqtt_client->get_event(MqttClient::Event::DATA)) {
ESP_LOGI(TAG, " TOPIC: %s", mqtt_client->get_topic(data).c_str());
ESP_LOGI(TAG, " DATA: %s", mqtt_client->get_data(data).c_str());
signal.set(MQTT_Data);
signal.set(IP_Event);
}
}
esp_modem::SignalGroup signal{};
MqttClient *mqtt_client{nullptr};
ip_event_t ip_event_type;
ip_event_t ip_event_type{};
};
@@ -122,6 +100,11 @@ extern "C" void app_main(void)
ESP_ERROR_CHECK(esp_event_loop_create_default());
ESP_ERROR_CHECK(esp_netif_init());
// Initialize console REPL, register ping and start it
ESP_ERROR_CHECK(console_cmd_init());
ESP_ERROR_CHECK(console_cmd_ping_register());
ESP_ERROR_CHECK(console_cmd_start());
/* Configure and create the DTE */
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
/* setup UART specific configuration based on kconfig options */
@@ -175,7 +158,7 @@ extern "C" void app_main(void)
#endif
assert(dce);
/* Try to connect to the network and publish an mqtt topic */
/* Try to connect to the network */
StatusHandler handler;
if (dte_config.uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
@@ -224,24 +207,14 @@ extern "C" void app_main(void)
} else if (handler.get_ip_event_type() == IP_EVENT_PPP_GOT_IP) {
std::cout << "Got IP address" << std::endl;
/* When connected to network, subscribe and publish some MQTT data */
MqttClient mqtt(BROKER_URL);
handler.handle_mqtt(&mqtt);
mqtt.connect();
if (!handler.wait_for(StatusHandler::MQTT_Connect, 60000)) {
ESP_LOGE(TAG, "Cannot connect to %s within specified timeout... exiting", BROKER_URL);
/* When connected to network, we can ping the internet */
int ping_ret_val;
ESP_ERROR_CHECK(esp_console_run("ping www.espressif.com", &ping_ret_val));
ESP_LOGI(TAG, "Ping command finished with return value: %d", ping_ret_val);
if (ping_ret_val != 0) {
ESP_LOGE(TAG, "Ping command failed with return value: %d", ping_ret_val);
return;
}
std::cout << "Connected" << std::endl;
mqtt.subscribe(CONFIG_EXAMPLE_MQTT_TEST_TOPIC);
mqtt.publish(CONFIG_EXAMPLE_MQTT_TEST_TOPIC, CONFIG_EXAMPLE_MQTT_TEST_DATA);
if (!handler.wait_for(StatusHandler::MQTT_Data, 60000)) {
ESP_LOGE(TAG, "Didn't receive published data within specified timeout... exiting");
return;
}
std::cout << "Received MQTT data" << std::endl;
} else if (handler.get_ip_event_type() == IP_EVENT_PPP_LOST_IP) {
ESP_LOGE(TAG, "PPP client has lost connection... exiting");
return;

View File

@@ -1,100 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/*
* PPPoS Client Example
*/
#include <memory>
#include "mqtt_client.h"
#include "simple_mqtt_client.hpp"
/**
* Reference to the MQTT event base
*/
ESP_EVENT_DECLARE_BASE(MQTT_EVENTS);
/**
* Thin wrapper around C mqtt_client
*/
struct MqttClientHandle {
explicit MqttClientHandle(const std::string &uri)
{
esp_mqtt_client_config_t config = { };
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
config.broker.address.uri = uri.c_str();
#else
config.uri = uri.c_str();
#endif
client = esp_mqtt_client_init(&config);
}
~MqttClientHandle()
{
esp_mqtt_client_destroy(client);
}
esp_mqtt_client_handle_t client;
};
/**
* @brief Definitions of MqttClient methods
*/
MqttClient::MqttClient(const std::string &uri):
h(std::unique_ptr<MqttClientHandle>(new MqttClientHandle(uri)))
{}
void MqttClient::connect()
{
esp_mqtt_client_start(h->client);
}
int32_t MqttClient::get_event(MqttClient::Event ev)
{
switch (ev) {
case Event::CONNECT: {
return MQTT_EVENT_CONNECTED;
}
case Event::DATA:
return MQTT_EVENT_DATA;
}
return -1;
}
int MqttClient::publish(const std::string &topic, const std::string &data, int qos)
{
return esp_mqtt_client_publish(h->client, topic.c_str(), data.c_str(), 0, qos, 0);
}
int MqttClient::subscribe(const std::string &topic, int qos)
{
return esp_mqtt_client_subscribe(h->client, topic.c_str(), qos);
}
std::string MqttClient::get_topic(void *event_data)
{
auto event = (esp_mqtt_event_handle_t)event_data;
if (event == nullptr || event->client != h->client)
return {};
return std::string(event->topic, event->topic_len);
}
std::string MqttClient::get_data(void *event_data)
{
auto event = (esp_mqtt_event_handle_t)event_data;
if (event == nullptr || event->client != h->client)
return {};
return std::string(event->data, event->data_len);
}
void MqttClient::register_handler(int32_t event_id, esp_event_handler_t event_handler, void *arg)
{
ESP_ERROR_CHECK(esp_mqtt_client_register_event(h->client, MQTT_EVENT_ANY, event_handler, arg));
}
MqttClient::~MqttClient() = default;

View File

@@ -1,81 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/*
* PPPoS Client Example
*/
#pragma once
#include <string>
#include <memory>
struct MqttClientHandle;
/**
* @brief Simple MQTT client wrapper
*/
class MqttClient {
public:
enum class Event {
CONNECT,
DATA,
};
explicit MqttClient(const std::string &uri);
~MqttClient();
/**
* @brief Start the mqtt-client
*/
void connect();
/**
* @brief Publish to topic
* @param topic Topic to publish
* @param data Data to publish
* @param qos QoS (0 by default)
* @return message id
*/
int publish(const std::string &topic, const std::string &data, int qos = 0);
/**
* @brief Subscribe to a topic
* @param topic Topic to subscribe
* @param qos QoS (0 by default)
* @return message id
*/
int subscribe(const std::string &topic, int qos = 0);
/**
* @brief Get topic from event data
* @return String topic
*/
std::string get_topic(void *);
/**
* @brief Get published data from event
* @return String representation of the data
*/
std::string get_data(void *);
/**
* @brief Register MQTT event
* @param id Event id
* @param event_handler Event handler
* @param event_handler_arg Event handler parameters
*/
void register_handler(int32_t id, esp_event_handler_t event_handler, void *event_handler_arg);
/**
* @brief Convert internal MQTT event to standard ESPEvent
* @param ev internal mqtt event
* @return corresponding esp_event id
*/
static int32_t get_event(Event ev);
private:
std::unique_ptr<MqttClientHandle> h;
};

View File

@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Unlicense OR CC0-1.0
from __future__ import print_function, unicode_literals
@@ -6,21 +6,10 @@ from __future__ import print_function, unicode_literals
def test_cmux_connection(dut):
"""
steps:
1. initializes connection with SIM800
2. checks we get an IP
3. checks for the MQTT events
1. checks we're in CMUX mode and get an IP
2. checks for ping command
"""
# Get topic and data from Kconfig
topic = ''
data = ''
try:
topic = dut.app.sdkconfig.get('EXAMPLE_MQTT_TEST_TOPIC')
data = dut.app.sdkconfig.get('EXAMPLE_MQTT_TEST_DATA')
except Exception:
print('ENV_TEST_FAILURE: Cannot find broker url in sdkconfig')
raise
# Check the sequence of connecting, publishing, disconnecting
dut.expect('Modem has correctly entered multiplexed')
# Check for MQTT connection and the data event
dut.expect(f'TOPIC: {topic}')
dut.expect(f'DATA: {data}')
# Check we're in CMUX mode and get an IP
dut.expect('Modem has correctly entered multiplexed command/data mode', timeout=60)
# Check for ping command
dut.expect('Ping command finished with return value: 0', timeout=30)