From 8b7df5b8c99825b809b009e39822c071b4358237 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 7 Apr 2021 09:51:41 +0200 Subject: [PATCH] CMUX: Implement cmux test Cleanup example code, fix write err length --- .../simple_cxx_client/main/simple_client.cpp | 170 ++++-------------- esp_modem/src/esp_modem_cmux.cpp | 18 +- esp_modem/test/host_test/main/test_modem.cpp | 32 +++- esp_modem/test/host_test/sdkconfig | 82 --------- 4 files changed, 73 insertions(+), 229 deletions(-) delete mode 100644 esp_modem/test/host_test/sdkconfig diff --git a/esp_modem/examples/simple_cxx_client/main/simple_client.cpp b/esp_modem/examples/simple_cxx_client/main/simple_client.cpp index d34124d22..d16b7b5ac 100644 --- a/esp_modem/examples/simple_cxx_client/main/simple_client.cpp +++ b/esp_modem/examples/simple_cxx_client/main/simple_client.cpp @@ -22,7 +22,8 @@ using namespace esp_modem; -static const char *TAG = "pppos_example"; +static const char *TAG = "cmux_example"; + static EventGroupHandle_t event_group = NULL; static const int CONNECT_BIT = BIT0; static const int STOP_BIT = BIT1; @@ -35,11 +36,9 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_ int msg_id; switch (event->event_id) { case MQTT_EVENT_CONNECTED: - ESP_LOGE(TAG, "MQTT_EVENT_CONNECTED"); - xEventGroupSetBits(event_group, GOT_DATA_BIT); -// -// msg_id = esp_mqtt_client_subscribe(client, "/topic/esp-pppos", 0); -// ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); + ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); + msg_id = esp_mqtt_client_subscribe(client, "/topic/esp-pppos", 0); + ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); break; case MQTT_EVENT_DISCONNECTED: ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED"); @@ -119,7 +118,6 @@ static void on_ip_event(void *arg, esp_event_base_t event_base, extern "C" void app_main(void) { - /* Init and register system/core components */ ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); @@ -137,151 +135,51 @@ extern "C" void app_main(void) /* Configure the PPP netif */ esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP(); - uint8_t data[32] = {}; - int actual_len = 0; auto uart_dte = create_uart_dte(&dte_config); - uart_dte->set_mode(modem_mode::UNDEF); - uart_dte->command("+++", [&](uint8_t *data, size_t len) { - std::string response((char*)data, len); - ESP_LOGI("in the lambda", "len=%d data %s", len, (char*)data); - std::cout << response << std::endl; - return command_result::OK; - }, 500); -// uart_dte->command("AT+CPIN?\r", [&](uint8_t *data, size_t len) { -// std::string response((char*)data, len); -// ESP_LOGI("in the lambda", "len=%d data %s", len, (char*)data); -// std::cout << response << std::endl; -// return command_result::OK; -// }, 1000); -// -// uart_dte->command("AT+CPIN=1234\r", [&](uint8_t *data, size_t len) { -// std::string response((char*)data, len); -// ESP_LOGI("in the lambda", "len=%d data %s", len, (char*)data); -// std::cout << response << std::endl; -// return command_result::OK; -// }, 1000); -// -// return; esp_netif_t *esp_netif = esp_netif_new(&netif_ppp_config); assert(esp_netif); - std::string apn = "internet"; -// auto device = create_generic_module(uart_dte, apn); -// auto device = create_SIM7600_module(uart_dte, apn); -// bool pin_ok = true; -// if (device->read_pin(pin_ok) == command_result::OK && !pin_ok) { -// throw_if_false(device->set_pin("1234") == command_result::OK, "Cannot set PIN!"); -// } + auto dce = create_SIM7600_dce(&dce_config, uart_dte, esp_netif); + dce->set_command_mode(); -// - std::string number; -// std::cout << "----" << std::endl; -// device->get_imsi(number); -// std::cout << "----" << std::endl; -// std::cout << "|" << number << "|" << std::endl; -// ESP_LOG_BUFFER_HEXDUMP("TEST", number.c_str(), number.length(), ESP_LOG_INFO); -// std::cout << "----" << std::endl; -// device->get_imei(number); -// std::cout << "|" << number << "|" << std::endl; -// device->get_module_name(number); -// std::cout << "|" << number << "|" << std::endl; -// std::cout << "----" << std::endl; -// auto my_dce = create_generic_module_dce(uart_dte, device, esp_netif); - auto my_dce = create_SIM7600_dce(&dce_config, uart_dte, esp_netif); - my_dce->set_command_mode(); - my_dce->get_module_name(number); - std::cout << "|" << number << "|" << std::endl; + std::string str; + dce->get_module_name(str); + std::cout << "Module name:" << str << std::endl; bool pin_ok = true; - if (my_dce->read_pin(pin_ok) == command_result::OK && !pin_ok) { - throw_if_false(my_dce->set_pin("1234") == command_result::OK, "Cannot set PIN!"); + if (dce->read_pin(pin_ok) == command_result::OK && !pin_ok) { + throw_if_false(dce->set_pin("1234") == command_result::OK, "Cannot set PIN!"); } vTaskDelay(pdMS_TO_TICKS(1000)); -// return; -// my_dce->set_cmux(); - my_dce->set_mode(esp_modem::modem_mode::CMUX_MODE); - my_dce->get_imsi(number); - std::cout << "|" << number << "|" << std::endl; + dce->set_mode(esp_modem::modem_mode::CMUX_MODE); + dce->get_imsi(str); + std::cout << "Modem IMSI number:" << str << "|" << std::endl; -// while (1) { -// vTaskDelay(pdMS_TO_TICKS(1000)); -// my_dce->get_imsi(number); -// std::cout << "|" << number << "|" << std::endl; -// -// } -// uart_dte->send_cmux_command(2, "AT+CPIN?"); -// return; + dce->set_data(); -// my_dce->get_module_name(number); -// my_dce->set_data_mode(); -// -// my_dce->command("AT+CPIN?\r", [&](uint8_t *data, size_t len) { -// std::string response((char*)data, len); -// ESP_LOGI("in the lambda", "len=%d data %s", len, (char*)data); -// std::cout << response << std::endl; -// return command_result::OK; -// }, 1000); + // MQTT connection + xEventGroupWaitBits(event_group, CONNECT_BIT, pdTRUE, pdTRUE, portMAX_DELAY); + esp_mqtt_client_config_t mqtt_config = { }; + mqtt_config.uri = BROKER_URL; + esp_mqtt_client_handle_t mqtt_client = esp_mqtt_client_init(&mqtt_config); + esp_mqtt_client_register_event(mqtt_client, MQTT_EVENT_ANY, mqtt_event_handler, NULL); + esp_mqtt_client_start(mqtt_client); + EventBits_t got_data = 0; + while (got_data == 0) { // reading IMSI number until we get published data from MQTT + dce->get_imsi(str); + std::cout << "Modem IMSI number:" << str << "|" << std::endl; + got_data = xEventGroupWaitBits(event_group, GOT_DATA_BIT, pdTRUE, pdTRUE, pdMS_TO_TICKS(500)); + } + esp_mqtt_client_destroy(mqtt_client); - -// while (1) - { - - my_dce->set_data(); - /* Config MQTT */ - xEventGroupWaitBits(event_group, CONNECT_BIT, pdTRUE, pdTRUE, portMAX_DELAY); - esp_mqtt_client_config_t mqtt_config = { }; - mqtt_config.uri = BROKER_URL; - esp_mqtt_client_handle_t mqtt_client = esp_mqtt_client_init(&mqtt_config); - esp_mqtt_client_register_event(mqtt_client, MQTT_EVENT_ANY, mqtt_event_handler, NULL); - esp_mqtt_client_start(mqtt_client); - xEventGroupWaitBits(event_group, GOT_DATA_BIT, pdTRUE, pdTRUE, portMAX_DELAY); - esp_mqtt_client_destroy(mqtt_client); - - while (1) { - vTaskDelay(pdMS_TO_TICKS(2000)); - my_dce->get_imsi(number); - std::cout << "|" << number << "|" << std::endl; - } - -// vTaskDelay(pdMS_TO_TICKS(20000)); -// my_dce->exit_data(); -// uart_dte->command("AT+CPIN?\r", [&](uint8_t *data, size_t len) { -// std::string response((char*)data, len); -//// ESP_LOGI("in the lambda", "len=%d data %s", len, (char*)data); -// std::cout << response << std::endl; -// return command_result::OK; -// }, 1000); + while (true) { // reading IMSI number after + dce->get_imsi(str); + std::cout << "Modem IMSI number:" << str << "|" << std::endl; + vTaskDelay(pdMS_TO_TICKS(1000)); } -// ddd->send_command("AT+COPS=?\r", [&](uint8_t *data, size_t len) { -// std::string response((char*)data, len); -// ESP_LOGI("in the lambda", "len=%d data %s", len, (char*)data); -// std::cout << response << std::endl; -// return true; -// }, 60000); - -// auto uart = create_uart_terminal(dte_config); -// uart->set_data_cb([&](size_t len){ -// actual_len = uart->read(data, 32); -// ESP_LOGI("in the lambda", "len=%d data %s", len, (char*)data); -// }); -// uart->write((uint8_t*)"AT\r",3); - - vTaskDelay(pdMS_TO_TICKS(1000)); -// int len = uart->read(data, 32); -// ESP_LOGI(TAG, "len=%d data %s", len, (char*)data); -// vTaskDelay(pdMS_TO_TICKS(1000)); -// len = uart->read(data, 32); - ESP_LOGI(TAG, "len=%d data %s", actual_len, (char*)data); - - uart_dte->command("AT+CPIN?\r", [&](uint8_t *data, size_t len) { - std::string response((char*)data, len); - ESP_LOGI("in the lambda", "len=%d data %s", len, (char*)data); - std::cout << response << std::endl; - return command_result::OK; - }, 1000); } diff --git a/esp_modem/src/esp_modem_cmux.cpp b/esp_modem/src/esp_modem_cmux.cpp index 53804997e..52984d33a 100644 --- a/esp_modem/src/esp_modem_cmux.cpp +++ b/esp_modem/src/esp_modem_cmux.cpp @@ -101,7 +101,7 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len) data = buffer.get(); actual_len = term->read(data, data_to_read); } - ESP_LOG_BUFFER_HEXDUMP("Received", data, actual_len, ESP_LOG_VERBOSE); + ESP_LOG_BUFFER_HEXDUMP("Received", data, actual_len, ESP_LOG_DEBUG); uint8_t* frame = data; auto available_len = actual_len; size_t payload_offset = 0; @@ -116,6 +116,13 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len) ESP_LOGW("CMUX", "TODO: Recover!"); return true; } + if (available_len > 1 && frame[1] == SOF_MARKER) { + ESP_LOGI("CMUX", "Empty frame"); + // empty frame + available_len -= 2; + frame += 2; + break; + } state = cmux_state::HEADER; available_len--; frame_header_offset = 1; @@ -133,7 +140,7 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len) dlci = frame_header[1] >> 2; type = frame_header[2]; payload_len = (frame_header[3] >> 1); - ESP_LOGW("CMUX", "CMUX FR: A:%02x T:%02x L:%d consumed:%d", dlci, type, payload_len, 0); + ESP_LOGI("CMUX", "CMUX FR: A:%02x T:%02x L:%d", dlci, type, payload_len); frame += payload_offset; available_len -= payload_offset; state = cmux_state::PAYLOAD; @@ -194,8 +201,9 @@ void CMux::init() } } -int CMux::write(int virtual_term, uint8_t *data, size_t len) { - +int CMux::write(int virtual_term, uint8_t *data, size_t len) +{ + Scoped l(lock); int i = virtual_term + 1; uint8_t frame[6]; frame[0] = SOF_MARKER; @@ -211,7 +219,7 @@ int CMux::write(int virtual_term, uint8_t *data, size_t len) { ESP_LOG_BUFFER_HEXDUMP("Send", frame, 4, ESP_LOG_VERBOSE); ESP_LOG_BUFFER_HEXDUMP("Send", data, len, ESP_LOG_VERBOSE); ESP_LOG_BUFFER_HEXDUMP("Send", frame+4, 2, ESP_LOG_VERBOSE); - return 0; + return len; } void CMux::set_read_cb(int inst, std::function f) { diff --git a/esp_modem/test/host_test/main/test_modem.cpp b/esp_modem/test/host_test/main/test_modem.cpp index fdea59c9f..387e635ee 100644 --- a/esp_modem/test/host_test/main/test_modem.cpp +++ b/esp_modem/test/host_test/main/test_modem.cpp @@ -22,7 +22,7 @@ public: } int write(uint8_t *data, size_t len) override { - if (len > 2 && (data[len-1] == '\r' || data[len-1] == '+') ) { + if (len > 2 && (data[len-1] == '\r' || data[len-1] == '+') ) { // Simple AT responder std::string command((char*)data, len); std::string response; if (command == "ATE1\r" || command == "ATE0\r" || command == "+++") { @@ -38,14 +38,17 @@ public: data_len = response.length(); loopback_data.resize(data_len); memcpy(&loopback_data[0], &response[0], data_len); - auto ret = std::async(on_data, data_len); + auto ret = std::async(on_data, nullptr, data_len); return len; } } + if (len > 2 && data[0] == 0xf9 && data[2] == 0xef) { // Simple CMUX responder + data[2] = 0xff; // turn the request into a reply -> implements CMUX loopback + } loopback_data.resize(data_len + len); memcpy(&loopback_data[data_len], data, len); data_len += len; - auto ret = std::async(on_data, data_len); + auto ret = std::async(on_data, nullptr, data_len); return len; } @@ -59,9 +62,6 @@ public: return read_len; } - void set_data_cb(std::function f) override { - on_data = std::move(f); - } private: enum class status_t { @@ -143,3 +143,23 @@ TEST_CASE("DCE modes", "[esp_modem]") CHECK(dce->set_mode(esp_modem::modem_mode::DATA_MODE) == true); CHECK(dce->set_mode(esp_modem::modem_mode::COMMAND_MODE) == true); } + +TEST_CASE("DCE CMUX test", "[esp_modem]") { + auto term = std::make_unique(); + auto dte = std::make_shared(std::move(term)); + CHECK(term == nullptr); + + esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("APN"); + esp_netif_t netif{}; + auto dce = create_SIM7600_dce(&dce_config, dte, &netif); + CHECK(dce != nullptr); + + CHECK(dce->set_mode(esp_modem::modem_mode::CMUX_MODE) == true); + const auto test_command = "Test\n"; + auto ret = dce->command(test_command, [&](uint8_t *data, size_t len) { + std::string response((char *) data, len); + CHECK(response == test_command); + return command_result::OK; + }, 1000); + CHECK(ret == command_result::OK); +} \ No newline at end of file diff --git a/esp_modem/test/host_test/sdkconfig b/esp_modem/test/host_test/sdkconfig deleted file mode 100644 index cf88b8d21..000000000 --- a/esp_modem/test/host_test/sdkconfig +++ /dev/null @@ -1,82 +0,0 @@ -# -# Automatically generated file. DO NOT EDIT. -# Espressif IoT Development Framework (ESP-IDF) Project Configuration -# -CONFIG_IDF_CMAKE=y -CONFIG_IDF_TARGET="linux" -CONFIG_IDF_FIRMWARE_CHIP_ID=0xFFFF - -# -# SDK tool configuration -# -CONFIG_SDK_TOOLPREFIX="" -# CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS is not set -# end of SDK tool configuration - -# -# Build type -# -CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y -# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set -CONFIG_APP_BUILD_GENERATE_BINARIES=y -CONFIG_APP_BUILD_BOOTLOADER=y -CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y -# end of Build type - -# -# Compiler options -# -CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y -# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set -# CONFIG_COMPILER_OPTIMIZATION_PERF is not set -# CONFIG_COMPILER_OPTIMIZATION_NONE is not set -CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y -# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set -# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set -CONFIG_COMPILER_HIDE_PATHS_MACROS=y -CONFIG_COMPILER_CXX_EXCEPTIONS=y -CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 -CONFIG_COMPILER_CXX_RTTI=y -CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y -# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set -# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set -# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set -# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set -# CONFIG_COMPILER_DISABLE_GCC8_WARNINGS is not set -# CONFIG_COMPILER_DUMP_RTL_FILES is not set -# end of Compiler options - -# -# Component config -# - -# -# ESP-MODEM -# -CONFIG_MODEM_LEGACY_API=y -CONFIG_MODEM_PPP_APN="internet" -# end of ESP-MODEM -# end of Component config - -# -# Compatibility options -# -# CONFIG_LEGACY_INCLUDE_COMMON_HEADERS is not set -# end of Compatibility options - -# Deprecated options for backward compatibility -CONFIG_TOOLPREFIX="" -CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y -# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set -CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y -# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set -# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set -CONFIG_CXX_EXCEPTIONS=y -CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 -CONFIG_STACK_CHECK_NONE=y -# CONFIG_STACK_CHECK_NORM is not set -# CONFIG_STACK_CHECK_STRONG is not set -# CONFIG_STACK_CHECK_ALL is not set -# CONFIG_WARN_WRITE_STRINGS is not set -# CONFIG_DISABLE_GCC8_WARNINGS is not set -# End of deprecated options