mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-16 12:02:11 +02:00
Reworded DCE/DTE modes and switching
This commit is contained in:
@ -10,7 +10,12 @@ set(srcs "src/esp_modem.c"
|
||||
"src/esp_bg96.c"
|
||||
"src/esp_modem_dte.cpp"
|
||||
"src/ppp_netif.cpp"
|
||||
"src/esp_modem_commands.cpp")
|
||||
"src/esp_modem_commands.cpp"
|
||||
"src/esp_modem_api.cpp"
|
||||
"src/esp_modem_dce.cpp"
|
||||
"src/esp_modem_device.cpp"
|
||||
"src/esp_modem_device_factory.cpp"
|
||||
"src/esp_modem_uart.cpp")
|
||||
|
||||
set(include_dirs "include")
|
||||
|
||||
|
@ -17,8 +17,9 @@
|
||||
#include "esp_log.h"
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "cxx_include/uart_terminal.hpp"
|
||||
#include "cxx_include/esp_modem_api.hpp"
|
||||
|
||||
#define BROKER_URL "mqtt://mqtt.eclipse.org"
|
||||
#define BROKER_URL "mqtt://mqtt.eclipseprojects.io"
|
||||
|
||||
static const char *TAG = "pppos_example";
|
||||
static EventGroupHandle_t event_group = NULL;
|
||||
@ -135,9 +136,11 @@ 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_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);
|
||||
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);
|
||||
break;
|
||||
case MQTT_EVENT_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
|
||||
@ -262,36 +265,58 @@ static void modem_test_app(esp_modem_dte_config_t *dte_config, esp_modem_dce_con
|
||||
// dte_config->line_buffer_size = 1000000;
|
||||
uint8_t data[32] = {};
|
||||
int actual_len = 0;
|
||||
auto ddd = create_dte(dte_config);
|
||||
ddd->set_mode(dte_mode::UNDEF);
|
||||
ddd->send_command("AT+CPIN?\r", [&](uint8_t *data, size_t len) {
|
||||
auto uart_dte = create_uart_dte(dte_config);
|
||||
uart_dte->set_mode(dte_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 true;
|
||||
return command_result::OK;
|
||||
}, 1000);
|
||||
|
||||
// ddd->send_command("AT+CPIN=1234\r", [&](uint8_t *data, size_t len) {
|
||||
// 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 true;
|
||||
// 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(ppp_config);
|
||||
assert(esp_netif);
|
||||
|
||||
auto my_dce = create_dce(ddd, esp_netif);
|
||||
std::string apn = "internet";
|
||||
auto device = create_device(uart_dte, apn);
|
||||
auto my_dce = create_dce(uart_dte, device, esp_netif);
|
||||
|
||||
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 true;
|
||||
return command_result::OK;
|
||||
}, 1000);
|
||||
|
||||
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);
|
||||
|
||||
// vTaskDelay(pdMS_TO_TICKS(20000));
|
||||
my_dce->exit_data();
|
||||
|
||||
// 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);
|
||||
@ -312,6 +337,13 @@ static void modem_test_app(esp_modem_dte_config_t *dte_config, esp_modem_dce_con
|
||||
// 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);
|
||||
return;
|
||||
|
||||
/* create dce object */
|
||||
|
14
esp_modem/include/cxx_include/esp_modem_api.hpp
Normal file
14
esp_modem/include/cxx_include/esp_modem_api.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include "cxx_include/esp_modem_dce.hpp"
|
||||
#include "cxx_include/esp_modem_device_factory.hpp"
|
||||
|
||||
class DTE;
|
||||
struct dte_config;
|
||||
typedef struct esp_netif_obj esp_netif_t;
|
||||
|
||||
std::shared_ptr<DTE> create_uart_dte(const dte_config *config);
|
||||
|
||||
std::unique_ptr<DCE> create_dce(const std::shared_ptr<DTE>& dte, const std::shared_ptr<DeviceIf>& dev, esp_netif_t *netif);
|
||||
|
@ -5,12 +5,81 @@
|
||||
#ifndef SIMPLE_CXX_CLIENT_ESP_MODEM_COMMANDS_HPP
|
||||
#define SIMPLE_CXX_CLIENT_ESP_MODEM_COMMANDS_HPP
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_modem_dte.hpp"
|
||||
//#include "esp_modem_dce_commands.hpp"
|
||||
enum class command_result;
|
||||
struct PdpContext {
|
||||
PdpContext(std::string& apn): context_id(1), protocol_type("IP"), apn(apn) {}
|
||||
size_t context_id;
|
||||
std::string protocol_type;
|
||||
std::string apn;
|
||||
};
|
||||
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace esp_modem {
|
||||
namespace dce_commands {
|
||||
|
||||
template <typename T> esp_err_t sync(T t);
|
||||
template <typename T> static inline command_result generic_command(T t, const std::string& command,
|
||||
const std::string& pass_phrase,
|
||||
const std::string& fail_phrase, uint32_t timeout_ms)
|
||||
{
|
||||
std::cout << command << std::endl;
|
||||
return t->command(command.c_str(), [&](uint8_t *data, size_t len) {
|
||||
std::string response((char*)data, len);
|
||||
std::cout << response << std::endl;
|
||||
|
||||
if (response.find(pass_phrase) != std::string::npos) {
|
||||
return command_result::OK;
|
||||
} else if (response.find(fail_phrase) != std::string::npos) {
|
||||
return command_result::FAIL;
|
||||
}
|
||||
return command_result::TIMEOUT;
|
||||
}, timeout_ms);
|
||||
}
|
||||
|
||||
template <typename T> static inline command_result generic_command_common(T t, std::string command)
|
||||
{
|
||||
return generic_command(t, command, "OK", "ERROR", 500);
|
||||
}
|
||||
|
||||
|
||||
template <typename T> command_result sync(T t)
|
||||
{
|
||||
return generic_command_common(t, "AT\r");
|
||||
}
|
||||
|
||||
template <typename T> command_result set_echo(T t, bool on)
|
||||
{
|
||||
if (on)
|
||||
return generic_command_common(t, "ATE1\r");
|
||||
return generic_command_common(t, "ATE0\r");
|
||||
}
|
||||
|
||||
template <typename T> command_result set_pdp_context(T t, PdpContext& pdp)
|
||||
{
|
||||
std::string pdp_command = "AT+CGDCONT=" + std::to_string(pdp.context_id) +
|
||||
",\"" + pdp.protocol_type + "\",\"" + pdp.apn + "\"\r";
|
||||
return generic_command_common(t, pdp_command);
|
||||
}
|
||||
|
||||
template <typename T> command_result set_data_mode(T t)
|
||||
{
|
||||
return generic_command(t, "ATD*99##\r", "CONNECT", "ERROR", 5000);
|
||||
}
|
||||
|
||||
template <typename T> command_result resume_data_mode(T t)
|
||||
{
|
||||
return generic_command(t, "ATO\r", "CONNECT", "ERROR", 5000);
|
||||
}
|
||||
|
||||
template <typename T> command_result set_command_mode(T t)
|
||||
{
|
||||
return generic_command(t, "+++", "OK", "ERROR", 50000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // dce_commands
|
||||
} // esp_modem
|
||||
|
32
esp_modem/include/cxx_include/esp_modem_dce.hpp
Normal file
32
esp_modem/include/cxx_include/esp_modem_dce.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include "cxx_include/esp_modem_dce_commands_if.hpp"
|
||||
|
||||
class DCE {
|
||||
public:
|
||||
explicit DCE(const std::shared_ptr<DTE>& d, std::shared_ptr<DeviceIf> device, esp_netif_t * netif);
|
||||
void set_data() {
|
||||
// command("AT+CGDCONT=1,\"IP\",\"internet\"\r", [&](uint8_t *data, size_t len) {
|
||||
// return command_result::OK;
|
||||
// }, 1000);
|
||||
// command("ATD*99***1#\r", [&](uint8_t *data, size_t len) {
|
||||
// return command_result::OK;
|
||||
// }, 1000);
|
||||
device->setup_data_mode();
|
||||
device->set_mode(dte_mode::DATA_MODE);
|
||||
dce_dte->set_mode(dte_mode::DATA_MODE);
|
||||
ppp_netif.start();
|
||||
}
|
||||
void exit_data() {
|
||||
ppp_netif.stop();
|
||||
device->set_mode(dte_mode::COMMAND_MODE);
|
||||
ppp_netif.wait_until_ppp_exits();
|
||||
dce_dte->set_mode(dte_mode::COMMAND_MODE);
|
||||
}
|
||||
command_result command(const std::string& command, got_line_cb got_line, uint32_t time_ms) {
|
||||
return dce_dte->command(command, got_line, time_ms);
|
||||
}
|
||||
private:
|
||||
std::shared_ptr<DTE> dce_dte;
|
||||
std::shared_ptr<DeviceIf> device;
|
||||
ppp ppp_netif;
|
||||
};
|
28
esp_modem/include/cxx_include/esp_modem_dce_commands.hpp
Normal file
28
esp_modem/include/cxx_include/esp_modem_dce_commands.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include "cxx_include/esp_modem_dce_commands_if.hpp"
|
||||
#include "cxx_include/esp_modem_commands.hpp"
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
enum class command_result;
|
||||
class DTE;
|
||||
|
||||
class Device: public DeviceIf {
|
||||
public:
|
||||
explicit Device(std::shared_ptr<DTE> dte, std::unique_ptr<PdpContext> pdp):
|
||||
dte(std::move(dte)), pdp(std::move(pdp)) {}
|
||||
bool setup_data_mode() override;
|
||||
bool set_mode(dte_mode mode) override;
|
||||
|
||||
command_result set_echo(bool on) { return esp_modem::dce_commands::set_echo(dte, on); }
|
||||
command_result set_data_mode() { return esp_modem::dce_commands::set_data_mode(dte); }
|
||||
command_result resume_data_mode() { return esp_modem::dce_commands::resume_data_mode(dte); }
|
||||
command_result set_pdp_context(PdpContext& pdp_context) { return esp_modem::dce_commands::set_pdp_context(dte.get(), pdp_context); }
|
||||
command_result set_command_mode() { return esp_modem::dce_commands::set_command_mode(dte); }
|
||||
|
||||
private:
|
||||
std::shared_ptr<DTE> dte;
|
||||
std::unique_ptr<PdpContext> pdp;
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
enum class dte_mode;
|
||||
|
||||
class DeviceIf {
|
||||
public:
|
||||
virtual bool setup_data_mode() = 0;
|
||||
virtual bool set_mode(dte_mode mode) = 0;
|
||||
};
|
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
std::shared_ptr<DeviceIf> create_device(const std::shared_ptr<DTE>& dte, std::string &apn);
|
@ -51,19 +51,21 @@ enum class dte_mode {
|
||||
DATA_MODE
|
||||
};
|
||||
|
||||
const int DTE_BUFFER_SIZE = 1024;
|
||||
|
||||
struct dte_data {
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
enum class command_result {
|
||||
OK,
|
||||
FAIL,
|
||||
TIMEOUT
|
||||
};
|
||||
|
||||
typedef std::function<bool(uint8_t *data, size_t len)> got_line_cb;
|
||||
const int DTE_BUFFER_SIZE = 1024;
|
||||
|
||||
class dte {
|
||||
|
||||
typedef std::function<command_result(uint8_t *data, size_t len)> got_line_cb;
|
||||
|
||||
class DTE {
|
||||
public:
|
||||
explicit dte(std::unique_ptr<terminal> t);
|
||||
~dte() = default;
|
||||
explicit DTE(std::unique_ptr<terminal> t);
|
||||
~DTE() = default;
|
||||
// void set_line_cb(got_line f) { on_line_cb = std::move(f); }
|
||||
int write(uint8_t *data, size_t len) { return term->write(data, len); }
|
||||
int read(uint8_t **d, size_t len) {
|
||||
@ -83,7 +85,7 @@ public:
|
||||
term->set_data_cb(on_data);
|
||||
}
|
||||
}
|
||||
bool send_command(const std::string& command, got_line_cb got_line, uint32_t time_ms);
|
||||
command_result command(const std::string& command, got_line_cb got_line, uint32_t time_ms);
|
||||
|
||||
private:
|
||||
const size_t GOT_LINE = BIT0;
|
||||
@ -98,27 +100,7 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class dce {
|
||||
public:
|
||||
explicit dce(std::shared_ptr<dte> d, esp_netif_t * netif);
|
||||
void set_data() {
|
||||
command("AT+CGDCONT=1,\"IP\",\"internet\"\r", [&](uint8_t *data, size_t len) {
|
||||
return true;
|
||||
}, 1000);
|
||||
command("ATD*99***1#\r", [&](uint8_t *data, size_t len) {
|
||||
return true;
|
||||
}, 1000);
|
||||
|
||||
dce_dte->set_mode(dte_mode::DATA_MODE);
|
||||
ppp_netif.start();
|
||||
}
|
||||
bool command(const std::string& command, got_line_cb got_line, uint32_t time_ms) {
|
||||
return dce_dte->send_command(command, got_line, time_ms);
|
||||
}
|
||||
private:
|
||||
std::shared_ptr<dte> dce_dte;
|
||||
ppp ppp_netif;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
10
esp_modem/include/cxx_include/esp_modem_uart_terminal.hpp
Normal file
10
esp_modem/include/cxx_include/esp_modem_uart_terminal.hpp
Normal file
@ -0,0 +1,10 @@
|
||||
//
|
||||
// Created by david on 3/3/21.
|
||||
//
|
||||
|
||||
#ifndef SIMPLE_CXX_CLIENT_ESP_MODEM_UART_TERMINAL_HPP
|
||||
#define SIMPLE_CXX_CLIENT_ESP_MODEM_UART_TERMINAL_HPP
|
||||
|
||||
|
||||
|
||||
#endif //SIMPLE_CXX_CLIENT_ESP_MODEM_UART_TERMINAL_HPP
|
@ -6,26 +6,33 @@
|
||||
#define SIMPLE_CXX_CLIENT_PPP_NETIF_HPP
|
||||
|
||||
#include "esp_netif.h"
|
||||
#include "cxx_include/terminal_objects.hpp"
|
||||
|
||||
class dte;
|
||||
class DTE;
|
||||
|
||||
//struct ppp_netif_driver;
|
||||
struct ppp_netif_driver {
|
||||
esp_netif_driver_base_t base;
|
||||
dte *e;
|
||||
DTE *e;
|
||||
};
|
||||
|
||||
|
||||
class ppp {
|
||||
public:
|
||||
explicit ppp(std::shared_ptr<dte> e, esp_netif_t *netif);
|
||||
explicit ppp(std::shared_ptr<DTE> e, esp_netif_t *netif);
|
||||
|
||||
void start();
|
||||
void notify_ppp_exit() { signal.set(PPP_EXIT); }
|
||||
void wait_until_ppp_exits() { signal.wait(PPP_EXIT, 50000); }
|
||||
void stop();
|
||||
private:
|
||||
void receive(uint8_t *data, size_t len) const;
|
||||
std::shared_ptr<dte> ppp_dte;
|
||||
std::shared_ptr<DTE> ppp_dte;
|
||||
esp_netif_t *netif;
|
||||
struct ppp_netif_driver driver;
|
||||
signal_group signal;
|
||||
const size_t PPP_EXIT = BIT0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -6,15 +6,12 @@
|
||||
#define SIMPLE_CXX_CLIENT_UART_TERMINAL_HPP
|
||||
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "esp_modem_dte_config.h"
|
||||
|
||||
std::unique_ptr<terminal> create_uart_terminal(const struct dte_config *config);
|
||||
|
||||
class dte;
|
||||
struct dte_config;
|
||||
|
||||
std::shared_ptr<dte> create_dte(const struct dte_config *config);
|
||||
std::unique_ptr<terminal> create_uart_terminal(const dte_config *config);
|
||||
|
||||
std::unique_ptr<dce> create_dce(const std::shared_ptr<dte>& e, esp_netif_t *netif);
|
||||
|
||||
|
||||
#endif //SIMPLE_CXX_CLIENT_UART_TERMINAL_HPP
|
||||
|
44
esp_modem/src/esp_modem_api.cpp
Normal file
44
esp_modem/src/esp_modem_api.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
//
|
||||
// Created by david on 3/3/21.
|
||||
//
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "cxx_include/uart_terminal.hpp"
|
||||
#include "esp_log.h"
|
||||
#include "cxx_include/esp_modem_api.hpp"
|
||||
|
||||
static const char *TAG = "dce_factory";
|
||||
struct PdpContext;
|
||||
|
||||
std::shared_ptr<DTE> create_uart_dte(const dte_config *config)
|
||||
{
|
||||
try {
|
||||
// auto term = std::make_unique<dte>(std::make_unique<uart_terminal>(config));
|
||||
auto term = create_uart_terminal(config);
|
||||
return std::make_shared<DTE>(std::move(term));
|
||||
} catch (std::bad_alloc& e) {
|
||||
ESP_LOGE(TAG, "Out of memory");
|
||||
return nullptr;
|
||||
} catch (esp_err_exception& e) {
|
||||
esp_err_t err = e.get_err_t();
|
||||
ESP_LOGE(TAG, "Error occurred during UART term init: %d", err);
|
||||
ESP_LOGE(TAG, "%s", e.what());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::unique_ptr<DCE> create_dce(const std::shared_ptr<DTE>& dte, const std::shared_ptr<DeviceIf>& dev, esp_netif_t *netif)
|
||||
{
|
||||
try {
|
||||
return std::make_unique<DCE>(dte, dev, netif);
|
||||
} catch (std::bad_alloc& e) {
|
||||
ESP_LOGE(TAG, "Out of memory");
|
||||
return nullptr;
|
||||
} catch (esp_err_exception& e) {
|
||||
esp_err_t err = e.get_err_t();
|
||||
ESP_LOGE(TAG, "Error occurred during UART term init: %d", err);
|
||||
ESP_LOGE(TAG, "%s", e.what());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -5,18 +5,61 @@
|
||||
|
||||
namespace esp_modem::dce_commands {
|
||||
|
||||
template <typename T> esp_err_t sync(T t)
|
||||
{
|
||||
return t->send_command("AT\r", [&](uint8_t *data, size_t len) {
|
||||
std::string response((char*)data, len);
|
||||
if (response.find("OK") != std::string::npos) {
|
||||
return ESP_OK;
|
||||
} else if (response.find("ERROR") != std::string::npos) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
|
||||
//template <typename T> static inline command_result generic_command(T t, std::string command,
|
||||
// std::string pass_phrase, std::string fail_phrase, uint32_t timeout_ms)
|
||||
//{
|
||||
// return t->command(command.c_str(), [&](uint8_t *data, size_t len) {
|
||||
// std::string response((char*)data, len);
|
||||
// if (response.find(pass_phrase) != std::string::npos) {
|
||||
// return command_result::OK;
|
||||
// } else if (response.find(fail_phrase) != std::string::npos) {
|
||||
// return command_result::FAIL;
|
||||
// }
|
||||
// return command_result::TIMEOUT;
|
||||
// }, timeout_ms);
|
||||
//}
|
||||
//
|
||||
//template <typename T> static inline command_result generic_command_common(T t, std::string command)
|
||||
//{
|
||||
// return generic_command(t, command, "OK", "ERROR", 500);
|
||||
//}
|
||||
//
|
||||
|
||||
//template <typename T> command_result sync(T t)
|
||||
//{
|
||||
// return t->command("AT\r", [&](uint8_t *data, size_t len) {
|
||||
// std::string response((char*)data, len);
|
||||
// if (response.find("OK") != std::string::npos) {
|
||||
// return command_result::OK;
|
||||
// } else if (response.find("ERROR") != std::string::npos) {
|
||||
// return command_result::FAIL;
|
||||
// }
|
||||
// return command_result::TIMEOUT;
|
||||
// }, 1000);
|
||||
//}
|
||||
|
||||
//template <typename T> command_result set_echo(T t, bool on) { return command_result::OK; }
|
||||
|
||||
|
||||
|
||||
//template <typename T> command_result set_echo(T* t, bool on)
|
||||
//{
|
||||
// if (on)
|
||||
// return generic_command_common(t, "ATE1\r");
|
||||
// return generic_command_common(t, "ATE0\r");
|
||||
//}
|
||||
//
|
||||
//template <typename T> command_result set_data_mode(T t)
|
||||
//{
|
||||
// return generic_command(t, "ATD*99##\r", "CONNECT", "ERROR", 5000);
|
||||
//}
|
||||
//
|
||||
//template <typename T> command_result set_pdp_context(T t, PdpContext& pdp_context)
|
||||
//{
|
||||
// return generic_command(t, "ATD*99##\r", "CONNECT", "ERROR", 5000);
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
@ -25,7 +68,7 @@ namespace esp_modem {
|
||||
template <class T>
|
||||
class generic_dce {
|
||||
public:
|
||||
explicit generic_dce(std::shared_ptr<dte> e) : dce_dte(std::move(e)) {}
|
||||
explicit generic_dce(std::shared_ptr<DTE> e) : dce_dte(std::move(e)) {}
|
||||
|
||||
esp_err_t sync() { return dce_commands::sync(dce_dte); }
|
||||
|
||||
|
11
esp_modem/src/esp_modem_dce.cpp
Normal file
11
esp_modem/src/esp_modem_dce.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "cxx_include/esp_modem_dce.hpp"
|
||||
#include <string.h>
|
||||
|
||||
#include <utility>
|
||||
#include "esp_log.h"
|
||||
|
||||
DCE::DCE(const std::shared_ptr<DTE>& dte, std::shared_ptr<DeviceIf> device, esp_netif_t * netif):
|
||||
dce_dte(dte), device(std::move(device)), ppp_netif(dte, netif)
|
||||
{ }
|
||||
|
30
esp_modem/src/esp_modem_device.cpp
Normal file
30
esp_modem/src/esp_modem_device.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
//
|
||||
// Created by david on 3/3/21.
|
||||
//
|
||||
|
||||
#include "cxx_include/esp_modem_dce_commands.hpp"
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
|
||||
|
||||
|
||||
bool Device::setup_data_mode() {
|
||||
if (set_echo(false) != command_result::OK)
|
||||
return false;
|
||||
if (set_pdp_context(*pdp) != command_result::OK)
|
||||
return false;
|
||||
// if (set_data_mode() != command_result::OK)
|
||||
// return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Device::set_mode(dte_mode mode) {
|
||||
if (mode == dte_mode::DATA_MODE) {
|
||||
if (set_data_mode() != command_result::OK)
|
||||
return resume_data_mode() == command_result::OK;
|
||||
return true;
|
||||
} else if (mode == dte_mode::COMMAND_MODE) {
|
||||
return set_command_mode() == command_result::OK;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
9
esp_modem/src/esp_modem_device_factory.cpp
Normal file
9
esp_modem/src/esp_modem_device_factory.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
#include "cxx_include/esp_modem_dce_commands.hpp"
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
|
||||
std::shared_ptr<DeviceIf> create_device(const std::shared_ptr<DTE>& dte, std::string &apn)
|
||||
{
|
||||
auto pdp = std::make_unique<PdpContext>(apn);
|
||||
return std::make_shared<Device>(dte, std::move(pdp));
|
||||
}
|
||||
|
@ -1,334 +1,16 @@
|
||||
//
|
||||
// Created by david on 2/24/21.
|
||||
//
|
||||
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_modem.h"
|
||||
#include "esp_modem_dce.h"
|
||||
#include "esp_log.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_modem_internal.h"
|
||||
#include "esp_modem_dte_internal.h"
|
||||
#include "esp_modem_dte_config.h"
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#define ESP_MODEM_EVENT_QUEUE_SIZE (16)
|
||||
#define MIN_PATTERN_INTERVAL (9)
|
||||
#define MIN_POST_IDLE (0)
|
||||
#define MIN_PRE_IDLE (0)
|
||||
DTE::DTE(std::unique_ptr<terminal> terminal):
|
||||
buffer_size(DTE_BUFFER_SIZE), consumed(0),
|
||||
buffer(std::make_unique<uint8_t[]>(buffer_size)),
|
||||
term(std::move(terminal)), mode(dte_mode::UNDEF) {}
|
||||
|
||||
|
||||
static const char *TAG = "dte_uart";
|
||||
|
||||
//class uart_terminal;
|
||||
|
||||
//class dte {
|
||||
//public:
|
||||
// esp_err_t init(std::unique_ptr<terminal> t);
|
||||
//
|
||||
//private:
|
||||
// std::unique_ptr<terminal> m_terminal;
|
||||
//
|
||||
//};
|
||||
|
||||
struct uart_task {
|
||||
explicit uart_task(size_t stack_size, size_t priority, void* task_param, TaskFunction_t task_function):
|
||||
task_handle(nullptr)
|
||||
{
|
||||
BaseType_t ret = xTaskCreate(task_function, "uart_task", stack_size, task_param, priority, &task_handle);
|
||||
throw_if_false(ret == pdTRUE, "create uart event task failed");
|
||||
}
|
||||
~uart_task()
|
||||
{
|
||||
if (task_handle) vTaskDelete(task_handle);
|
||||
}
|
||||
|
||||
TaskHandle_t task_handle; /*!< UART event task handle */
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct uart_event_loop {
|
||||
explicit uart_event_loop(): event_loop_hdl(nullptr)
|
||||
{
|
||||
esp_event_loop_args_t loop_args = {};
|
||||
loop_args.queue_size = ESP_MODEM_EVENT_QUEUE_SIZE;
|
||||
loop_args.task_name = nullptr;
|
||||
throw_if_esp_fail(esp_event_loop_create(&loop_args, &event_loop_hdl), "create event loop failed");
|
||||
}
|
||||
void run() { esp_event_loop_run(event_loop_hdl, pdMS_TO_TICKS(0)); }
|
||||
|
||||
~uart_event_loop() { if (event_loop_hdl) esp_event_loop_delete(event_loop_hdl); }
|
||||
|
||||
esp_event_loop_handle_t event_loop_hdl;
|
||||
};
|
||||
|
||||
struct uart_resource {
|
||||
explicit uart_resource(const struct dte_config *config);
|
||||
|
||||
~uart_resource();
|
||||
|
||||
bool get_event(uart_event_t& event, uint32_t time_ms)
|
||||
{
|
||||
return xQueueReceive(event_queue, &event, pdMS_TO_TICKS(time_ms));
|
||||
}
|
||||
void reset_events()
|
||||
{
|
||||
uart_flush_input(port);
|
||||
xQueueReset(event_queue);
|
||||
}
|
||||
|
||||
uart_port_t port; /*!< UART port */
|
||||
QueueHandle_t event_queue; /*!< UART event queue handle */
|
||||
// esp_modem_on_receive receive_cb; /*!< ptr to data reception */
|
||||
// void *receive_cb_ctx; /*!< ptr to rx fn context data */
|
||||
int line_buffer_size; /*!< line buffer size in command mode */
|
||||
int pattern_queue_size; /*!< UART pattern queue size */
|
||||
};
|
||||
|
||||
class uart_terminal: public terminal {
|
||||
public:
|
||||
explicit uart_terminal(const struct dte_config *config):
|
||||
uart(config), event_loop(), signal(),
|
||||
task_handle(config->event_task_stack_size, config->event_task_priority, this, s_task) {}
|
||||
|
||||
~uart_terminal() override = default;
|
||||
void start() override
|
||||
{
|
||||
signal.set(TASK_START);
|
||||
}
|
||||
void stop() override
|
||||
{
|
||||
signal.set(TASK_STOP);
|
||||
}
|
||||
// { ESP_LOGE(TAG, "uart_terminal destruct"); }
|
||||
|
||||
int write(uint8_t *data, size_t len) override;
|
||||
int read(uint8_t *data, size_t len) override;
|
||||
|
||||
private:
|
||||
static void s_task(void * task_param)
|
||||
{
|
||||
auto t = static_cast<uart_terminal*>(task_param);
|
||||
t->task();
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
void task();
|
||||
|
||||
const size_t TASK_INIT = BIT0;
|
||||
const size_t TASK_START = BIT1;
|
||||
const size_t TASK_STOP = BIT2;
|
||||
|
||||
|
||||
uart_resource uart;
|
||||
uart_event_loop event_loop;
|
||||
signal_group signal;
|
||||
uart_task task_handle;
|
||||
|
||||
};
|
||||
|
||||
|
||||
uart_resource::~uart_resource()
|
||||
{
|
||||
if (port >= UART_NUM_0 && port < UART_NUM_MAX) {
|
||||
uart_driver_delete(port);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
uart_resource::uart_resource(const struct dte_config *config):
|
||||
port(-1)
|
||||
// buffer(std::make_unique<uint8_t[]>(config->line_buffer_size))
|
||||
{
|
||||
esp_err_t res;
|
||||
|
||||
line_buffer_size = config->line_buffer_size;
|
||||
|
||||
/* TODO: Bind methods */
|
||||
|
||||
/* Config UART */
|
||||
uart_config_t uart_config = {};
|
||||
uart_config.baud_rate = config->baud_rate;
|
||||
uart_config.data_bits = config->data_bits;
|
||||
uart_config.parity = config->parity;
|
||||
uart_config.stop_bits = config->stop_bits;
|
||||
uart_config.flow_ctrl = (config->flow_control == ESP_MODEM_FLOW_CONTROL_HW) ? UART_HW_FLOWCTRL_CTS_RTS
|
||||
: UART_HW_FLOWCTRL_DISABLE;
|
||||
uart_config.source_clk = UART_SCLK_REF_TICK;
|
||||
|
||||
throw_if_esp_fail(uart_param_config(config->port_num, &uart_config), "config uart parameter failed");
|
||||
|
||||
if (config->flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
|
||||
res = uart_set_pin(config->port_num, config->tx_io_num, config->rx_io_num,
|
||||
config->rts_io_num, config->cts_io_num);
|
||||
} else {
|
||||
res = uart_set_pin(config->port_num, config->tx_io_num, config->rx_io_num,
|
||||
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
||||
}
|
||||
throw_if_esp_fail(res, "config uart gpio failed");
|
||||
/* Set flow control threshold */
|
||||
if (config->flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
|
||||
res = uart_set_hw_flow_ctrl(config->port_num, UART_HW_FLOWCTRL_CTS_RTS, UART_FIFO_LEN - 8);
|
||||
} else if (config->flow_control == ESP_MODEM_FLOW_CONTROL_SW) {
|
||||
res = uart_set_sw_flow_ctrl(config->port_num, true, 8, UART_FIFO_LEN - 8);
|
||||
}
|
||||
throw_if_esp_fail(res, "config uart flow control failed");
|
||||
/* Install UART driver and get event queue used inside driver */
|
||||
res = uart_driver_install(config->port_num, config->rx_buffer_size, config->tx_buffer_size,
|
||||
config->event_queue_size, &(event_queue), 0);
|
||||
throw_if_esp_fail(res, "install uart driver failed");
|
||||
throw_if_esp_fail(uart_set_rx_timeout(config->port_num, 1), "set rx timeout failed");
|
||||
|
||||
/* Set pattern interrupt, used to detect the end of a line. */
|
||||
// res = uart_enable_pattern_det_baud_intr(config->port_num, '\n', 1, MIN_PATTERN_INTERVAL, MIN_POST_IDLE, MIN_PRE_IDLE);
|
||||
/* Set pattern queue size */
|
||||
// pattern_queue_size = config->pattern_queue_size;
|
||||
// res |= uart_pattern_queue_reset(config->port_num, config->pattern_queue_size);
|
||||
/* Starting in command mode -> explicitly disable RX interrupt */
|
||||
// uart_disable_rx_intr(config->port_num);
|
||||
uart_set_rx_full_threshold(config->port_num, 64);
|
||||
throw_if_esp_fail(res, "config uart pattern failed");
|
||||
/* mark UART as initialized */
|
||||
port = config->port_num;
|
||||
}
|
||||
|
||||
std::unique_ptr<terminal> create_uart_terminal(const struct dte_config *config)
|
||||
{
|
||||
try {
|
||||
auto term = std::make_unique<uart_terminal>(config);
|
||||
term->start();
|
||||
return term;
|
||||
} catch (std::bad_alloc& e) {
|
||||
ESP_LOGE(TAG, "Out of memory");
|
||||
return nullptr;
|
||||
} catch (esp_err_exception& e) {
|
||||
esp_err_t err = e.get_err_t();
|
||||
ESP_LOGE(TAG, "Error occurred during UART term init: %d", err);
|
||||
ESP_LOGE(TAG, "%s", e.what());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::shared_ptr<dte> create_dte(const struct dte_config *config)
|
||||
{
|
||||
try {
|
||||
// auto term = std::make_unique<dte>(std::make_unique<uart_terminal>(config));
|
||||
auto term = std::make_shared<dte>(std::make_unique<uart_terminal>(config));
|
||||
return term;
|
||||
} catch (std::bad_alloc& e) {
|
||||
ESP_LOGE(TAG, "Out of memory");
|
||||
return nullptr;
|
||||
} catch (esp_err_exception& e) {
|
||||
esp_err_t err = e.get_err_t();
|
||||
ESP_LOGE(TAG, "Error occurred during UART term init: %d", err);
|
||||
ESP_LOGE(TAG, "%s", e.what());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::unique_ptr<dce> create_dce(const std::shared_ptr<dte>& e, esp_netif_t *netif)
|
||||
{
|
||||
try {
|
||||
return std::make_unique<dce>(e, netif);
|
||||
} catch (std::bad_alloc& e) {
|
||||
ESP_LOGE(TAG, "Out of memory");
|
||||
return nullptr;
|
||||
} catch (esp_err_exception& e) {
|
||||
esp_err_t err = e.get_err_t();
|
||||
ESP_LOGE(TAG, "Error occurred during UART term init: %d", err);
|
||||
ESP_LOGE(TAG, "%s", e.what());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void uart_terminal::task()
|
||||
{
|
||||
uart_event_t event;
|
||||
size_t len;
|
||||
signal.set(TASK_INIT);
|
||||
signal.wait_any(TASK_START | TASK_STOP, portMAX_DELAY);
|
||||
if (signal.is_any(TASK_STOP)) {
|
||||
return; // deletes the static task
|
||||
}
|
||||
while(signal.is_any(TASK_START)) {
|
||||
event_loop.run();
|
||||
if (uart.get_event(event, 100)) {
|
||||
switch (event.type) {
|
||||
case UART_DATA:
|
||||
ESP_LOGI(TAG, "UART_DATA");
|
||||
uart_get_buffered_data_len(uart.port, &len);
|
||||
ESP_LOGI(TAG, "UART_DATA len=%d, on_data=%d", len, (bool)on_data);
|
||||
if (len && on_data) {
|
||||
on_data(len);
|
||||
}
|
||||
break;
|
||||
case UART_FIFO_OVF:
|
||||
ESP_LOGW(TAG, "HW FIFO Overflow");
|
||||
uart.reset_events();
|
||||
break;
|
||||
case UART_BUFFER_FULL:
|
||||
ESP_LOGW(TAG, "Ring Buffer Full");
|
||||
uart.reset_events();
|
||||
break;
|
||||
case UART_BREAK:
|
||||
ESP_LOGW(TAG, "Rx Break");
|
||||
break;
|
||||
case UART_PARITY_ERR:
|
||||
ESP_LOGE(TAG, "Parity Error");
|
||||
break;
|
||||
case UART_FRAME_ERR:
|
||||
ESP_LOGE(TAG, "Frame Error");
|
||||
break;
|
||||
case UART_PATTERN_DET:
|
||||
ESP_LOGI(TAG, "UART_PATTERN_DET");
|
||||
break;
|
||||
default:
|
||||
ESP_LOGW(TAG, "unknown uart event type: %d", event.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ESP_LOGI(TAG, "uart_event_task_entry");
|
||||
// vTaskDelay(pdMS_TO_TICKS(200));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int uart_terminal::read(uint8_t *data, size_t len)
|
||||
{
|
||||
size_t length = 0;
|
||||
uart_get_buffered_data_len(uart.port, &length);
|
||||
if (length > 0) {
|
||||
return uart_read_bytes(uart.port, data, length, portMAX_DELAY);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uart_terminal::write(uint8_t *data, size_t len)
|
||||
{
|
||||
return uart_write_bytes(uart.port, data, len);
|
||||
}
|
||||
|
||||
dte::dte(std::unique_ptr<terminal> terminal):
|
||||
buffer_size(DTE_BUFFER_SIZE), consumed(0),
|
||||
buffer(std::make_unique<uint8_t[]>(buffer_size)),
|
||||
term(std::move(terminal)), mode(dte_mode::UNDEF) {}
|
||||
|
||||
|
||||
bool dte::send_command(const std::string& command, got_line_cb got_line, uint32_t time_ms)
|
||||
command_result DTE::command(const std::string& command, got_line_cb got_line, uint32_t time_ms)
|
||||
{
|
||||
command_result res = command_result::TIMEOUT;
|
||||
term->write((uint8_t *)command.c_str(), command.length());
|
||||
term->set_data_cb([&](size_t len){
|
||||
auto data_to_read = std::min(len, buffer_size - consumed);
|
||||
@ -336,18 +18,17 @@ bool dte::send_command(const std::string& command, got_line_cb got_line, uint32_
|
||||
auto actual_len = term->read(data, data_to_read);
|
||||
consumed += actual_len;
|
||||
if (memchr(data, '\n', actual_len)) {
|
||||
ESP_LOGD("in the lambda", "FOUND");
|
||||
if (got_line(buffer.get(), consumed)) {
|
||||
res = got_line(buffer.get(), consumed);
|
||||
if (res == command_result::OK || res == command_result::FAIL) {
|
||||
signal.set(GOT_LINE);
|
||||
}
|
||||
}
|
||||
});
|
||||
auto res = signal.wait(GOT_LINE, time_ms);
|
||||
auto got_lf = signal.wait(GOT_LINE, time_ms);
|
||||
if (got_lf && res == command_result::TIMEOUT) {
|
||||
throw_if_esp_fail(ESP_ERR_INVALID_STATE);
|
||||
}
|
||||
consumed = 0;
|
||||
term->set_data_cb(nullptr);
|
||||
return res;
|
||||
}
|
||||
|
||||
dce::dce(std::shared_ptr<dte> e, esp_netif_t * netif):
|
||||
dce_dte(e), ppp_netif(e, netif)
|
||||
{ }
|
||||
|
||||
}
|
246
esp_modem/src/esp_modem_uart.cpp
Normal file
246
esp_modem/src/esp_modem_uart.cpp
Normal file
@ -0,0 +1,246 @@
|
||||
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_event.h"
|
||||
#include "driver/uart.h"
|
||||
#include "esp_modem_dte_config.h"
|
||||
|
||||
#define ESP_MODEM_EVENT_QUEUE_SIZE (16)
|
||||
|
||||
static const char *TAG = "uart_terminal";
|
||||
|
||||
struct uart_resource {
|
||||
explicit uart_resource(const struct dte_config *config);
|
||||
|
||||
~uart_resource();
|
||||
|
||||
bool get_event(uart_event_t& event, uint32_t time_ms)
|
||||
{
|
||||
return xQueueReceive(event_queue, &event, pdMS_TO_TICKS(time_ms));
|
||||
}
|
||||
void reset_events()
|
||||
{
|
||||
uart_flush_input(port);
|
||||
xQueueReset(event_queue);
|
||||
}
|
||||
|
||||
uart_port_t port; /*!< UART port */
|
||||
QueueHandle_t event_queue; /*!< UART event queue handle */
|
||||
int line_buffer_size; /*!< line buffer size in command mode */
|
||||
int pattern_queue_size; /*!< UART pattern queue size */
|
||||
};
|
||||
|
||||
struct uart_task {
|
||||
explicit uart_task(size_t stack_size, size_t priority, void* task_param, TaskFunction_t task_function):
|
||||
task_handle(nullptr)
|
||||
{
|
||||
BaseType_t ret = xTaskCreate(task_function, "uart_task", stack_size, task_param, priority, &task_handle);
|
||||
throw_if_false(ret == pdTRUE, "create uart event task failed");
|
||||
}
|
||||
~uart_task()
|
||||
{
|
||||
if (task_handle) vTaskDelete(task_handle);
|
||||
}
|
||||
|
||||
TaskHandle_t task_handle; /*!< UART event task handle */
|
||||
};
|
||||
|
||||
|
||||
struct uart_event_loop {
|
||||
explicit uart_event_loop(): event_loop_hdl(nullptr)
|
||||
{
|
||||
esp_event_loop_args_t loop_args = {};
|
||||
loop_args.queue_size = ESP_MODEM_EVENT_QUEUE_SIZE;
|
||||
loop_args.task_name = nullptr;
|
||||
throw_if_esp_fail(esp_event_loop_create(&loop_args, &event_loop_hdl), "create event loop failed");
|
||||
}
|
||||
void run() { esp_event_loop_run(event_loop_hdl, pdMS_TO_TICKS(0)); }
|
||||
|
||||
~uart_event_loop() { if (event_loop_hdl) esp_event_loop_delete(event_loop_hdl); }
|
||||
|
||||
esp_event_loop_handle_t event_loop_hdl;
|
||||
};
|
||||
|
||||
uart_resource::~uart_resource()
|
||||
{
|
||||
if (port >= UART_NUM_0 && port < UART_NUM_MAX) {
|
||||
uart_driver_delete(port);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uart_resource::uart_resource(const struct dte_config *config):
|
||||
port(-1)
|
||||
{
|
||||
esp_err_t res;
|
||||
line_buffer_size = config->line_buffer_size;
|
||||
|
||||
/* Config UART */
|
||||
uart_config_t uart_config = {};
|
||||
uart_config.baud_rate = config->baud_rate;
|
||||
uart_config.data_bits = config->data_bits;
|
||||
uart_config.parity = config->parity;
|
||||
uart_config.stop_bits = config->stop_bits;
|
||||
uart_config.flow_ctrl = (config->flow_control == ESP_MODEM_FLOW_CONTROL_HW) ? UART_HW_FLOWCTRL_CTS_RTS
|
||||
: UART_HW_FLOWCTRL_DISABLE;
|
||||
uart_config.source_clk = UART_SCLK_REF_TICK;
|
||||
|
||||
throw_if_esp_fail(uart_param_config(config->port_num, &uart_config), "config uart parameter failed");
|
||||
|
||||
if (config->flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
|
||||
res = uart_set_pin(config->port_num, config->tx_io_num, config->rx_io_num,
|
||||
config->rts_io_num, config->cts_io_num);
|
||||
} else {
|
||||
res = uart_set_pin(config->port_num, config->tx_io_num, config->rx_io_num,
|
||||
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
||||
}
|
||||
throw_if_esp_fail(res, "config uart gpio failed");
|
||||
/* Set flow control threshold */
|
||||
if (config->flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
|
||||
res = uart_set_hw_flow_ctrl(config->port_num, UART_HW_FLOWCTRL_CTS_RTS, UART_FIFO_LEN - 8);
|
||||
} else if (config->flow_control == ESP_MODEM_FLOW_CONTROL_SW) {
|
||||
res = uart_set_sw_flow_ctrl(config->port_num, true, 8, UART_FIFO_LEN - 8);
|
||||
}
|
||||
throw_if_esp_fail(res, "config uart flow control failed");
|
||||
/* Install UART driver and get event queue used inside driver */
|
||||
res = uart_driver_install(config->port_num, config->rx_buffer_size, config->tx_buffer_size,
|
||||
config->event_queue_size, &(event_queue), 0);
|
||||
throw_if_esp_fail(res, "install uart driver failed");
|
||||
throw_if_esp_fail(uart_set_rx_timeout(config->port_num, 1), "set rx timeout failed");
|
||||
|
||||
uart_set_rx_full_threshold(config->port_num, 64);
|
||||
throw_if_esp_fail(res, "config uart pattern failed");
|
||||
/* mark UART as initialized */
|
||||
port = config->port_num;
|
||||
}
|
||||
|
||||
class uart_terminal: public terminal {
|
||||
public:
|
||||
explicit uart_terminal(const struct dte_config *config):
|
||||
uart(config), event_loop(), signal(),
|
||||
task_handle(config->event_task_stack_size, config->event_task_priority, this, s_task) {}
|
||||
|
||||
~uart_terminal() override = default;
|
||||
void start() override
|
||||
{
|
||||
signal.set(TASK_START);
|
||||
}
|
||||
void stop() override
|
||||
{
|
||||
signal.set(TASK_STOP);
|
||||
}
|
||||
|
||||
int write(uint8_t *data, size_t len) override;
|
||||
int read(uint8_t *data, size_t len) override;
|
||||
|
||||
private:
|
||||
static void s_task(void * task_param)
|
||||
{
|
||||
auto t = static_cast<uart_terminal*>(task_param);
|
||||
t->task();
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
void task();
|
||||
|
||||
const size_t TASK_INIT = BIT0;
|
||||
const size_t TASK_START = BIT1;
|
||||
const size_t TASK_STOP = BIT2;
|
||||
|
||||
|
||||
uart_resource uart;
|
||||
uart_event_loop event_loop;
|
||||
signal_group signal;
|
||||
uart_task task_handle;
|
||||
|
||||
};
|
||||
|
||||
std::unique_ptr<terminal> create_uart_terminal(const dte_config *config)
|
||||
{
|
||||
try {
|
||||
auto term = std::make_unique<uart_terminal>(config);
|
||||
term->start();
|
||||
return term;
|
||||
} catch (std::bad_alloc& e) {
|
||||
ESP_LOGE(TAG, "Out of memory");
|
||||
return nullptr;
|
||||
} catch (esp_err_exception& e) {
|
||||
esp_err_t err = e.get_err_t();
|
||||
ESP_LOGE(TAG, "Error occurred during UART term init: %d", err);
|
||||
ESP_LOGE(TAG, "%s", e.what());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void uart_terminal::task()
|
||||
{
|
||||
uart_event_t event;
|
||||
size_t len;
|
||||
signal.set(TASK_INIT);
|
||||
signal.wait_any(TASK_START | TASK_STOP, portMAX_DELAY);
|
||||
if (signal.is_any(TASK_STOP)) {
|
||||
return; // exits to the static method where the task gets deleted
|
||||
}
|
||||
while(signal.is_any(TASK_START)) {
|
||||
event_loop.run();
|
||||
if (uart.get_event(event, 100)) {
|
||||
switch (event.type) {
|
||||
case UART_DATA:
|
||||
ESP_LOGI(TAG, "UART_DATA");
|
||||
// ESP_LOG_BUFFER_HEXDUMP("esp-modem-pattern: debug_data", esp_dte->buffer, length, ESP_LOG_DEBUG);
|
||||
uart_get_buffered_data_len(uart.port, &len);
|
||||
ESP_LOGI(TAG, "UART_DATA len=%d, on_data=%d", len, (bool)on_data);
|
||||
if (len && on_data) {
|
||||
on_data(len);
|
||||
}
|
||||
break;
|
||||
case UART_FIFO_OVF:
|
||||
ESP_LOGW(TAG, "HW FIFO Overflow");
|
||||
uart.reset_events();
|
||||
break;
|
||||
case UART_BUFFER_FULL:
|
||||
ESP_LOGW(TAG, "Ring Buffer Full");
|
||||
uart.reset_events();
|
||||
break;
|
||||
case UART_BREAK:
|
||||
ESP_LOGW(TAG, "Rx Break");
|
||||
break;
|
||||
case UART_PARITY_ERR:
|
||||
ESP_LOGE(TAG, "Parity Error");
|
||||
break;
|
||||
case UART_FRAME_ERR:
|
||||
ESP_LOGE(TAG, "Frame Error");
|
||||
break;
|
||||
case UART_PATTERN_DET:
|
||||
ESP_LOGI(TAG, "UART_PATTERN_DET");
|
||||
break;
|
||||
default:
|
||||
ESP_LOGW(TAG, "unknown uart event type: %d", event.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int uart_terminal::read(uint8_t *data, size_t len)
|
||||
{
|
||||
size_t length = 0;
|
||||
uart_get_buffered_data_len(uart.port, &length);
|
||||
if (length > 0) {
|
||||
return uart_read_bytes(uart.port, data, length, portMAX_DELAY);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uart_terminal::write(uint8_t *data, size_t len)
|
||||
{
|
||||
return uart_write_bytes(uart.port, data, len);
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "esp_netif_ppp.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
//struct ppp_netif_driver {
|
||||
// esp_netif_driver_base_t base;
|
||||
@ -17,19 +18,23 @@
|
||||
static void on_ppp_changed(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
dte *e = (dte*)arg;
|
||||
ppp *e = (ppp*)arg;
|
||||
// DTE *e = (DTE*)arg;
|
||||
std::cout << "on_ppp_changed " << std::endl;
|
||||
ESP_LOGW("TAG", "PPP state changed event %d", event_id);
|
||||
if (event_id < NETIF_PP_PHASE_OFFSET) {
|
||||
ESP_LOGI("TAG", "PPP state changed event %d", event_id);
|
||||
// only notify the modem on state/error events, ignoring phase transitions
|
||||
e->data_mode_closed();
|
||||
e->notify_ppp_exit();
|
||||
// e->data_mode_closed();
|
||||
// esp_modem_notify_ppp_netif_closed(dte);
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t esp_modem_dte_transmit(void *h, void *buffer, size_t len)
|
||||
{
|
||||
dte *e = (dte*)h;
|
||||
DTE *e = (DTE*)h;
|
||||
std::cout << "sending data " << len << std::endl;
|
||||
if (e->write((uint8_t*)buffer, len) > 0) {
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -42,28 +47,30 @@ static esp_err_t esp_modem_post_attach(esp_netif_t * esp_netif, void * args)
|
||||
esp_netif_driver_ifconfig_t driver_ifconfig = { };
|
||||
driver_ifconfig.transmit = esp_modem_dte_transmit;
|
||||
driver_ifconfig.handle = (void*)d->e;
|
||||
|
||||
std::cout << "esp_modem_post_attach " << std::endl;
|
||||
d->base.netif = esp_netif;
|
||||
ESP_ERROR_CHECK(esp_netif_set_driver_config(esp_netif, &driver_ifconfig));
|
||||
// check if PPP error events are enabled, if not, do enable the error occurred/state changed
|
||||
// to notify the modem layer when switching modes
|
||||
esp_netif_ppp_config_t ppp_config;
|
||||
esp_netif_ppp_get_params(esp_netif, &ppp_config);
|
||||
if (!ppp_config.ppp_error_event_enabled) {
|
||||
// if (!ppp_config.ppp_error_event_enabled) {
|
||||
ppp_config.ppp_error_event_enabled = true;
|
||||
ppp_config.ppp_phase_event_enabled = true;
|
||||
esp_netif_ppp_set_params(esp_netif, &ppp_config);
|
||||
}
|
||||
// }
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed, (void*)d->e));
|
||||
// ESP_ERROR_CHECK(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed, 0));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void ppp::receive(uint8_t *data, size_t len) const
|
||||
{
|
||||
std::cout << "received data " << len << std::endl;
|
||||
esp_netif_receive(driver.base.netif, data, len, nullptr);
|
||||
}
|
||||
|
||||
ppp::ppp(std::shared_ptr<dte> e, esp_netif_t *ppp_netif):
|
||||
ppp::ppp(std::shared_ptr<DTE> e, esp_netif_t *ppp_netif):
|
||||
ppp_dte(std::move(e)), netif(ppp_netif)
|
||||
{
|
||||
driver.base.netif = ppp_netif;
|
||||
@ -74,10 +81,20 @@ ppp::ppp(std::shared_ptr<dte> e, esp_netif_t *ppp_netif):
|
||||
auto actual_len = ppp_dte->read(&data, len);
|
||||
return receive(data, actual_len);
|
||||
});
|
||||
throw_if_esp_fail(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed, (void*)this));
|
||||
throw_if_esp_fail(esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_GOT_IP, esp_netif_action_connected, ppp_netif));
|
||||
throw_if_esp_fail(esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_LOST_IP, esp_netif_action_disconnected, ppp_netif));
|
||||
throw_if_esp_fail(esp_netif_attach(ppp_netif, &driver));
|
||||
}
|
||||
|
||||
void ppp::start()
|
||||
{
|
||||
esp_netif_action_start(driver.base.netif, 0, 0, 0);
|
||||
}
|
||||
|
||||
void ppp::stop()
|
||||
{
|
||||
std::cout << "esp_netif_action_stop " << std::endl;
|
||||
esp_netif_action_stop(driver.base.netif, nullptr, 0, nullptr);
|
||||
|
||||
}
|
Reference in New Issue
Block a user