From f71192b87611d56a9f46663c2b3267dbebb80899 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 30 Jan 2023 15:04:44 +0100 Subject: [PATCH] fix(esp_modem): Fix cmux client compilation issue Removed dependency on esp_event_cxx --- .../simple_cmux_client/CMakeLists.txt | 2 +- .../main/simple_cmux_client_main.cpp | 128 +++++++++++++----- .../main/simple_mqtt_client.cpp | 25 ++-- .../main/simple_mqtt_client.hpp | 15 +- 4 files changed, 115 insertions(+), 55 deletions(-) diff --git a/components/esp_modem/examples/simple_cmux_client/CMakeLists.txt b/components/esp_modem/examples/simple_cmux_client/CMakeLists.txt index 6547c1450..4f298cdb6 100644 --- a/components/esp_modem/examples/simple_cmux_client/CMakeLists.txt +++ b/components/esp_modem/examples/simple_cmux_client/CMakeLists.txt @@ -2,7 +2,7 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) -set(EXTRA_COMPONENT_DIRS "../.." $ENV{IDF_PATH}/examples/cxx/experimental/experimental_cpp_component) +set(EXTRA_COMPONENT_DIRS "../..") include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(simple_cmux_client) diff --git a/components/esp_modem/examples/simple_cmux_client/main/simple_cmux_client_main.cpp b/components/esp_modem/examples/simple_cmux_client/main/simple_cmux_client_main.cpp index df9229547..0b840519d 100644 --- a/components/esp_modem/examples/simple_cmux_client/main/simple_cmux_client_main.cpp +++ b/components/esp_modem/examples/simple_cmux_client/main/simple_cmux_client_main.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -17,10 +17,10 @@ #include "freertos/event_groups.h" #include "esp_netif.h" #include "esp_log.h" +#include "esp_event.h" #include "cxx_include/esp_modem_dte.hpp" #include "esp_modem_config.h" #include "cxx_include/esp_modem_api.hpp" -#include "esp_event_cxx.hpp" #include "simple_mqtt_client.hpp" #include "esp_vfs_dev.h" // For optional VFS support #include "esp_https_ota.h" // For potential OTA configuration @@ -39,16 +39,87 @@ using namespace esp_modem; -using namespace idf::event; - 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() + { + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, on_event, this)); + } + + ~StatusHandler() + { + 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); + } + + ip_event_t get_ip_event_type() + { + return ip_event_type; + } + +private: + static void on_event(void *arg, esp_event_base_t base, int32_t event, void *data) + { + auto *handler = static_cast(arg); + if (base == IP_EVENT) { + handler->ip_event(event, data); + } else { + handler->mqtt_event(event, data); + } + } + + void ip_event(int32_t id, void *data) + { + if (id == IP_EVENT_PPP_GOT_IP) { + auto *event = (ip_event_got_ip_t *)data; + 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)); + signal.set(IP_Event); + } else if (id == IP_EVENT_PPP_LOST_IP) { + signal.set(IP_Event); + } + ip_event_type = static_cast(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); + } + } + + esp_modem::SignalGroup signal{}; + MqttClient *mqtt_client{nullptr}; + ip_event_t ip_event_type; +}; + extern "C" void app_main(void) { /* Init and register system/core components */ - auto loop = std::make_shared(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); ESP_ERROR_CHECK(esp_netif_init()); /* Configure and create the DTE */ @@ -145,45 +216,32 @@ extern "C" void app_main(void) #endif /* Try to connect to the network and publish an mqtt topic */ - ESPEventHandlerSync event_handler(loop); - event_handler.listen_to(ESPEvent(IP_EVENT, ESPEventID(ESP_EVENT_ANY_ID))); - auto result = event_handler.wait_event_for(std::chrono::milliseconds(60000)); - if (result.timeout) { + StatusHandler handler; + if (!handler.wait_for(StatusHandler::IP_Event, 60000)) { ESP_LOGE(TAG, "Cannot get IP within specified timeout... exiting"); return; - } else if (result.event.id == ESPEventID(IP_EVENT_PPP_GOT_IP)) { - auto *event = (ip_event_got_ip_t *)result.ev_data; - 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)); + } 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); - event_handler.listen_to(MqttClient::get_event(MqttClient::Event::CONNECT)); - event_handler.listen_to(MqttClient::get_event(MqttClient::Event::DATA)); - - auto reg = loop->register_event(MqttClient::get_event(MqttClient::Event::DATA), - [&mqtt](const ESPEvent & event, void *data) { - std::cout << " TOPIC:" << mqtt.get_topic(data) << std::endl; - std::cout << " DATA:" << mqtt.get_data(data) << std::endl; - }); + handler.handle_mqtt(&mqtt); mqtt.connect(); - while (true) { - result = event_handler.wait_event_for(std::chrono::milliseconds(60000)); - if (result.event == MqttClient::get_event(MqttClient::Event::CONNECT)) { - mqtt.subscribe("/topic/esp-modem"); - mqtt.publish("/topic/esp-modem", "Hello modem"); - continue; - } else if (result.event == MqttClient::get_event(MqttClient::Event::DATA)) { - std::cout << "Data received" << std::endl; - break; /* Continue with CMUX example after getting data from MQTT */ - } else { - break; - } + if (!handler.wait_for(StatusHandler::MQTT_Connect, 60000)) { + ESP_LOGE(TAG, "Cannot connect to %s within specified timeout... exiting", BROKER_URL); + return; } + std::cout << "Connected" << std::endl; - } else if (result.event.id == ESPEventID(IP_EVENT_PPP_LOST_IP)) { + mqtt.subscribe("/topic/esp-modem"); + mqtt.publish("/topic/esp-modem", "Hello modem"); + 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; } diff --git a/components/esp_modem/examples/simple_cmux_client/main/simple_mqtt_client.cpp b/components/esp_modem/examples/simple_cmux_client/main/simple_mqtt_client.cpp index 91b95519c..1f86e5a0a 100644 --- a/components/esp_modem/examples/simple_cmux_client/main/simple_mqtt_client.cpp +++ b/components/esp_modem/examples/simple_cmux_client/main/simple_mqtt_client.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -10,11 +10,8 @@ #include #include "mqtt_client.h" -#include "esp_event_cxx.hpp" #include "simple_mqtt_client.hpp" -using namespace idf::event; - /** * Reference to the MQTT event base */ @@ -33,7 +30,6 @@ struct MqttClientHandle { config.uri = uri.c_str(); #endif client = esp_mqtt_client_init(&config); - esp_mqtt_client_register_event(client, MQTT_EVENT_ANY, mqtt_event_handler, this); } ~MqttClientHandle() @@ -41,12 +37,6 @@ struct MqttClientHandle { esp_mqtt_client_destroy(client); } - static void mqtt_event_handler(void *args, esp_event_base_t base, int32_t id, void *data) - { - // forwards the internal event to the global ESPEvent - esp_event_post(base, id, data, sizeof(esp_mqtt_event_t), portMAX_DELAY); - } - esp_mqtt_client_handle_t client; }; @@ -62,16 +52,16 @@ void MqttClient::connect() esp_mqtt_client_start(h->client); } -idf::event::ESPEvent MqttClient::get_event(MqttClient::Event ev) +int32_t MqttClient::get_event(MqttClient::Event ev) { switch (ev) { case Event::CONNECT: { - return { MQTT_EVENTS, ESPEventID(MQTT_EVENT_CONNECTED) }; + return MQTT_EVENT_CONNECTED; } case Event::DATA: - return { MQTT_EVENTS, ESPEventID(MQTT_EVENT_DATA) }; + return MQTT_EVENT_DATA; } - return { }; + return -1; } int MqttClient::publish(const std::string &topic, const std::string &data, int qos) @@ -102,4 +92,9 @@ std::string MqttClient::get_data(void *event_data) 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; diff --git a/components/esp_modem/examples/simple_cmux_client/main/simple_mqtt_client.hpp b/components/esp_modem/examples/simple_cmux_client/main/simple_mqtt_client.hpp index 971d980b9..f726e4639 100644 --- a/components/esp_modem/examples/simple_cmux_client/main/simple_mqtt_client.hpp +++ b/components/esp_modem/examples/simple_cmux_client/main/simple_mqtt_client.hpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -11,7 +11,6 @@ #include #include -#include "esp_event_cxx.hpp" struct MqttClientHandle; @@ -62,12 +61,20 @@ public: */ 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 ESPEvent + * @return corresponding esp_event id */ - static idf::event::ESPEvent get_event(Event ev); + static int32_t get_event(Event ev); private: std::unique_ptr h;