mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-30 02:37:31 +02:00
Corrections on fragmenting/buffering for vfs/cmux
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
idf_component_register(SRCS "test_modem.cpp"
|
||||
idf_component_register(SRCS "test_modem.cpp" "LoopbackTerm.cpp"
|
||||
INCLUDE_DIRS "$ENV{IDF_PATH}/tools/catch"
|
||||
REQUIRES esp_modem)
|
||||
|
||||
|
82
esp_modem/test/host_test/main/LoopbackTerm.cpp
Normal file
82
esp_modem/test/host_test/main/LoopbackTerm.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
#include <memory>
|
||||
#include <future>
|
||||
#include <cstring>
|
||||
#include "LoopbackTerm.h"
|
||||
|
||||
void LoopbackTerm::start()
|
||||
{
|
||||
status = status_t::STARTED;
|
||||
}
|
||||
|
||||
void LoopbackTerm::stop()
|
||||
{
|
||||
status = status_t::STOPPED;
|
||||
}
|
||||
|
||||
int LoopbackTerm::write(uint8_t *data, size_t len)
|
||||
{
|
||||
if (len > 2 && (data[len-1] == '\r' || data[len-1] == '+') ) { // Simple AT responder
|
||||
std::string command((char*)data, len);
|
||||
std::string response;
|
||||
if (command == "+++") {
|
||||
response = "NO CARRIER\r\n";
|
||||
} else if (command == "ATE1\r" || command == "ATE0\r") {
|
||||
response = "OK\r\n";
|
||||
} else if (command == "ATO\r") {
|
||||
response = "ERROR\r\n";
|
||||
} else if (command.find("ATD") != std::string::npos) {
|
||||
response = "CONNECT\r\n";
|
||||
} else if (command.find("AT+CSQ\r") != std::string::npos) {
|
||||
response = "+CSQ: 123,456\n\r\nOK\r\n";
|
||||
} else if (command.find("AT+CBC\r") != std::string::npos) {
|
||||
response = is_bg96 ? "+CBC: 1,2,123456V\r\r\n\r\nOK\r\n\n\r\n":
|
||||
"+CBC: 123.456V\r\r\n\r\nOK\r\n\n\r\n";
|
||||
} else if (command.find("AT+CPIN=1234\r") != std::string::npos) {
|
||||
response = "OK\r\n";
|
||||
pin_ok = true;
|
||||
} else if (command.find("AT+CPIN?\r") != std::string::npos) {
|
||||
response = pin_ok?"+CPIN: READY\r\nOK\r\n":"+CPIN: SIM PIN\r\nOK\r\n";
|
||||
} else if (command.find("AT") != std::string::npos) {
|
||||
response = "OK\r\n";
|
||||
}
|
||||
if (!response.empty()) {
|
||||
data_len = response.length();
|
||||
loopback_data.resize(data_len);
|
||||
memcpy(&loopback_data[0], &response[0], data_len);
|
||||
auto ret = std::async(on_data, nullptr, data_len);
|
||||
return len;
|
||||
}
|
||||
}
|
||||
if (len > 2 && data[0] == 0xf9) { // Simple CMUX responder
|
||||
// turn the request into a reply -> implements CMUX loopback
|
||||
if (data[2] == 0x3f) // SABM command
|
||||
data[2] = 0x73;
|
||||
else if (data[2] == 0xef) { // Generic request
|
||||
data[2] = 0xff; // generic reply
|
||||
}
|
||||
}
|
||||
loopback_data.resize(data_len + len);
|
||||
memcpy(&loopback_data[data_len], data, len);
|
||||
data_len += len;
|
||||
auto ret = std::async(on_data, nullptr, data_len);
|
||||
return len;
|
||||
}
|
||||
|
||||
int LoopbackTerm::read(uint8_t *data, size_t len)
|
||||
{
|
||||
size_t read_len = std::min(data_len, len);
|
||||
if (read_len) {
|
||||
if (loopback_data.capacity() < len)
|
||||
loopback_data.reserve(len);
|
||||
memcpy(data, &loopback_data[0], read_len);
|
||||
loopback_data.erase(loopback_data.begin(), loopback_data.begin() + read_len);
|
||||
data_len -= read_len;
|
||||
}
|
||||
return read_len;
|
||||
}
|
||||
|
||||
LoopbackTerm::LoopbackTerm(bool is_bg96): loopback_data(), data_len(0), pin_ok(false), is_bg96(is_bg96) {}
|
||||
|
||||
LoopbackTerm::LoopbackTerm(): loopback_data(), data_len(0), pin_ok(false), is_bg96(false) {}
|
||||
|
||||
LoopbackTerm::~LoopbackTerm() = default;
|
36
esp_modem/test/host_test/main/LoopbackTerm.h
Normal file
36
esp_modem/test/host_test/main/LoopbackTerm.h
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef _LOOPBACKTERM_H_
|
||||
#define _LOOPBACKTERM_H_
|
||||
|
||||
#include "cxx_include/esp_modem_api.hpp"
|
||||
#include "cxx_include/esp_modem_terminal.hpp"
|
||||
|
||||
using namespace esp_modem;
|
||||
|
||||
class LoopbackTerm : public Terminal {
|
||||
public:
|
||||
explicit LoopbackTerm(bool is_bg96);
|
||||
explicit LoopbackTerm();
|
||||
|
||||
~LoopbackTerm() override;
|
||||
|
||||
void start() override;
|
||||
void stop() override;
|
||||
|
||||
int write(uint8_t *data, size_t len) override;
|
||||
|
||||
int read(uint8_t *data, size_t len) override;
|
||||
|
||||
private:
|
||||
enum class status_t {
|
||||
STARTED,
|
||||
STOPPED
|
||||
};
|
||||
status_t status;
|
||||
SignalGroup signal;
|
||||
std::vector<uint8_t> loopback_data;
|
||||
size_t data_len;
|
||||
bool pin_ok;
|
||||
bool is_bg96;
|
||||
};
|
||||
|
||||
#endif //_LOOPBACKTERM_H_
|
@ -2,82 +2,44 @@
|
||||
#include <memory>
|
||||
#include <future>
|
||||
#include "catch.hpp"
|
||||
#include "cxx_include/esp_modem_terminal.hpp"
|
||||
#include "cxx_include/esp_modem_api.hpp"
|
||||
#include "LoopbackTerm.h"
|
||||
|
||||
using namespace esp_modem;
|
||||
|
||||
class LoopbackTerm : public Terminal {
|
||||
public:
|
||||
explicit LoopbackTerm(): loopback_data(), data_len(0) {}
|
||||
TEST_CASE("DCE AT parser", "[esp_modem]")
|
||||
{
|
||||
auto term = std::make_unique<LoopbackTerm>(true);
|
||||
auto dte = std::make_shared<DTE>(std::move(term));
|
||||
CHECK(term == nullptr);
|
||||
|
||||
~LoopbackTerm() override = default;
|
||||
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("APN");
|
||||
esp_netif_t netif{};
|
||||
auto dce = create_BG96_dce(&dce_config, dte, &netif);
|
||||
CHECK(dce != nullptr);
|
||||
|
||||
void start() override {
|
||||
status = status_t::STARTED;
|
||||
}
|
||||
CHECK(dce->set_command_mode() == command_result::OK);
|
||||
|
||||
void stop() override {
|
||||
status = status_t::STOPPED;
|
||||
}
|
||||
int milli_volt, bcl, bcs;
|
||||
CHECK(dce->get_battery_status(milli_volt, bcl, bcs) == command_result::OK);
|
||||
CHECK(milli_volt == 123456);
|
||||
CHECK(bcl == 1);
|
||||
CHECK(bcs == 2);
|
||||
|
||||
int write(uint8_t *data, size_t len) override {
|
||||
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 == "+++") {
|
||||
response = "OK\r\n";
|
||||
} else if (command == "ATO\r") {
|
||||
response = "ERROR\r\n";
|
||||
} else if (command.find("ATD") != std::string::npos) {
|
||||
response = "CONNECT\r\n";
|
||||
} else if (command.find("AT") != std::string::npos) {
|
||||
response = "OK\r\n";
|
||||
}
|
||||
if (!response.empty()) {
|
||||
data_len = response.length();
|
||||
loopback_data.resize(data_len);
|
||||
memcpy(&loopback_data[0], &response[0], data_len);
|
||||
auto ret = std::async(on_data, nullptr, data_len);
|
||||
return len;
|
||||
}
|
||||
}
|
||||
if (len > 2 && data[0] == 0xf9) { // Simple CMUX responder
|
||||
// turn the request into a reply -> implements CMUX loopback
|
||||
if (data[2] == 0x3f) // SABM command
|
||||
data[2] = 0x73;
|
||||
else if (data[2] == 0xef) // Generic request
|
||||
data[2] = 0xff; // generic reply
|
||||
}
|
||||
loopback_data.resize(data_len + len);
|
||||
memcpy(&loopback_data[data_len], data, len);
|
||||
data_len += len;
|
||||
auto ret = std::async(on_data, nullptr, data_len);
|
||||
return len;
|
||||
}
|
||||
int rssi, ber;
|
||||
CHECK(dce->get_signal_quality(rssi, ber) == command_result::OK);
|
||||
CHECK(rssi == 123);
|
||||
CHECK(ber == 456);
|
||||
|
||||
int read(uint8_t *data, size_t len) override {
|
||||
size_t read_len = std::min(data_len, len);
|
||||
if (read_len) {
|
||||
memcpy(data, &loopback_data[0], len);
|
||||
loopback_data.erase(loopback_data.begin(), loopback_data.begin() + read_len);
|
||||
data_len -= len;
|
||||
}
|
||||
return read_len;
|
||||
}
|
||||
bool pin_ok;
|
||||
CHECK(dce->read_pin(pin_ok) == command_result::OK);
|
||||
CHECK(pin_ok == false);
|
||||
CHECK(dce->set_pin("1234") == command_result::OK);
|
||||
CHECK(dce->read_pin(pin_ok) == command_result::OK);
|
||||
CHECK(pin_ok == true);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
enum class status_t {
|
||||
STARTED,
|
||||
STOPPED
|
||||
};
|
||||
status_t status;
|
||||
signal_group signal;
|
||||
std::vector<uint8_t> loopback_data;
|
||||
size_t data_len;
|
||||
};
|
||||
|
||||
TEST_CASE("DTE send/receive command", "[esp_modem]")
|
||||
{
|
||||
auto term = std::make_unique<LoopbackTerm>();
|
||||
@ -127,11 +89,15 @@ TEST_CASE("DCE AT commands", "[esp_modem]")
|
||||
auto dce = create_SIM7600_dce(&dce_config, dte, &netif);
|
||||
CHECK(dce != nullptr);
|
||||
|
||||
int milli_volt, bcl, bcs;
|
||||
CHECK(dce->set_echo(false) == command_result::OK);
|
||||
CHECK(dce->set_echo(true) == command_result::OK);
|
||||
CHECK(dce->get_battery_status(milli_volt, bcl, bcs) == command_result::OK);
|
||||
CHECK(milli_volt == 123456);
|
||||
CHECK(dce->resume_data_mode() == command_result::FAIL);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("DCE modes", "[esp_modem]")
|
||||
{
|
||||
auto term = std::make_unique<LoopbackTerm>();
|
||||
@ -162,8 +128,9 @@ TEST_CASE("DCE CMUX test", "[esp_modem]") {
|
||||
const auto test_command = "Test\n";
|
||||
auto ret = dce->command(test_command, [&](uint8_t *data, size_t len) {
|
||||
std::string response((char *) data, len);
|
||||
std::cout << "Response:" << response << std::endl;
|
||||
CHECK(response == test_command);
|
||||
return command_result::OK;
|
||||
}, 1000);
|
||||
CHECK(ret == command_result::OK);
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +0,0 @@
|
||||
-- Found Git: /usr/bin/git (found version "2.30.2")
|
||||
-- Component directory /home/david/esp/idf/components/aws_iot does not contain a CMakeLists.txt file. No component will be added
|
||||
-- Component directory /home/david/esp/idf/components/micro-ecc does not contain a CMakeLists.txt file. No component will be added
|
||||
-- Component directory /home/david/esp/idf/components/nimble does not contain a CMakeLists.txt file. No component will be added
|
||||
-- ccache will be used for faster recompilation
|
||||
-- The C compiler identification is GNU 10.2.1
|
||||
-- The CXX compiler identification is GNU 10.2.1
|
||||
-- The ASM compiler identification is GNU
|
||||
-- Found assembler: /usr/lib64/ccache/cc
|
||||
-- Detecting C compiler ABI info
|
||||
-- Detecting C compiler ABI info - done
|
||||
-- Check for working C compiler: /usr/lib64/ccache/cc - skipped
|
||||
-- Detecting C compile features
|
||||
-- Detecting C compile features - done
|
||||
-- Detecting CXX compiler ABI info
|
||||
-- Detecting CXX compiler ABI info - done
|
||||
-- Check for working CXX compiler: /usr/lib64/ccache/c++ - skipped
|
||||
-- Detecting CXX compile features
|
||||
-- Detecting CXX compile features - done
|
||||
-- Building ESP-IDF components for target linux
|
||||
-- adding linux stuff...
|
||||
-- Found Git: /usr/bin/git (found version "2.30.2")
|
||||
-- Configuring incomplete, errors occurred!
|
||||
See also "/home/david/repos/esp-idf-contrib/esp_modem/test/host_test/build/CMakeFiles/CMakeOutput.log".
|
||||
Adding "set-target"'s dependency "fullclean" to list of commands with default set of options.
|
||||
Executing action: fullclean
|
||||
Build directory '/home/david/repos/esp-idf-contrib/esp_modem/test/host_test/build' not found. Nothing to clean.
|
||||
Executing action: set-target
|
||||
Set Target to: linux, new sdkconfig created. Existing sdkconfig renamed to sdkconfig.old.
|
||||
Running cmake in directory /home/david/repos/esp-idf-contrib/esp_modem/test/host_test/build
|
||||
Executing "cmake -G Ninja -DPYTHON_DEPS_CHECKED=1 -DESP_PLATFORM=1 -DIDF_TARGET=linux -DIDF_TARGET=linux -DCCACHE_ENABLE=1 /home/david/repos/esp-idf-contrib/esp_modem/test/host_test"...
|
@ -54,10 +54,23 @@ public:
|
||||
{
|
||||
// configure
|
||||
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
||||
esp_modem_dte_config_t dte_config2 = {
|
||||
.dte_buffer_size = 512,
|
||||
.vfs_config = {.port_num = UART_NUM_1,
|
||||
.dev_name = "/dev/uart/1",
|
||||
.rx_buffer_size = 1024,
|
||||
.tx_buffer_size = 1024,
|
||||
.baud_rate = 115200,
|
||||
.tx_io_num = 25,
|
||||
.rx_io_num = 26,
|
||||
.task_stack_size = 4096,
|
||||
.task_prio = 5}
|
||||
};
|
||||
esp_modem_dce_config dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("");
|
||||
|
||||
// create DTE and minimal network DCE
|
||||
auto uart_dte = create_uart_dte(&dte_config);
|
||||
auto uart_dte = create_vfs_dte(&dte_config2);
|
||||
// auto uart_dte = create_uart_dte(&dte_config);
|
||||
dce = NetDCE_Factory::create<NetModule>(&dce_config, uart_dte, netif);
|
||||
return dce == nullptr ? ESP_FAIL : ESP_OK;
|
||||
}
|
||||
|
Reference in New Issue
Block a user