Skip to content

Commit

Permalink
demo(esp_modem): console uses DCE commandable to handle URC
Browse files Browse the repository at this point in the history
  • Loading branch information
david-cermak committed Dec 19, 2022
1 parent a299192 commit c61fe1f
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 7 deletions.
@@ -1,5 +1,6 @@
idf_component_register(SRCS "modem_console_main.cpp"
"console_helper.cpp"
"my_module_dce.cpp"
"httpget_handle.c"
"ping_handle.c"
REQUIRES console esp_http_client nvs_flash
Expand Down
Expand Up @@ -59,6 +59,12 @@ using namespace esp_modem;
static SignalGroup exit_signal;


command_result handle_urc(uint8_t *data, size_t len)
{
ESP_LOG_BUFFER_HEXDUMP("on_read", data, len, ESP_LOG_INFO);
return command_result::TIMEOUT;
}

extern "C" void app_main(void)
{
ESP_ERROR_CHECK(nvs_flash_init());
Expand Down Expand Up @@ -216,8 +222,9 @@ extern "C" void app_main(void)

const ConsoleCommand GetOperatorName("get_operator_name", "reads the operator name", no_args, [&](ConsoleCommand * c) {
std::string operator_name;
int act;
ESP_LOGI(TAG, "Reading operator name...");
CHECK_ERR(dce->get_operator_name(operator_name), ESP_LOGI(TAG, "OK. Operator name: %s", operator_name.c_str()));
CHECK_ERR(dce->get_operator_name(operator_name, act), ESP_LOGI(TAG, "OK. Operator name: %s", operator_name.c_str()));
});

const struct GenericCommandArgs {
Expand Down Expand Up @@ -269,6 +276,18 @@ extern "C" void app_main(void)
ESP_LOGI(TAG, "Resetting the module...");
CHECK_ERR(dce->reset(), ESP_LOGI(TAG, "OK"));
});
const ConsoleCommand HandleURC("urc", "toggle urc handling", no_args, [&](ConsoleCommand * c) {
static int cnt = 0;
if (++cnt % 2) {
ESP_LOGI(TAG, "Adding URC handler");
dce->set_on_read(handle_urc);
} else {
ESP_LOGI(TAG, "URC removed");
dce->set_on_read(nullptr);
}
return 0;
});

const struct SetApn {
SetApn(): apn(STR1, nullptr, nullptr, "<apn>", "APN (Access Point Name)") {}
CommandArgs apn;
Expand Down
90 changes: 90 additions & 0 deletions components/esp_modem/examples/modem_console/main/my_module_dce.cpp
@@ -0,0 +1,90 @@
/* Modem console example: Custom DCE
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/

#include <cstring>
#include "cxx_include/esp_modem_api.hpp"
#include "cxx_include/esp_modem_dce_module.hpp"
#include "generate/esp_modem_command_declare.inc"
#include "my_module_dce.hpp"

using namespace esp_modem;

//
// Define preprocessor's forwarding to dce_commands definitions
//

// Helper macros to handle multiple arguments of declared API
#define ARGS0
#define ARGS1 , p1
#define ARGS2 , p1 , p2
#define ARGS3 , p1 , p2 , p3
#define ARGS4 , p1 , p2 , p3, p4
#define ARGS5 , p1 , p2 , p3, p4, p5
#define ARGS6 , p1 , p2 , p3, p4, p5, p6

#define _ARGS(x) ARGS ## x
#define ARGS(x) _ARGS(x)

//
// Repeat all declarations and forward to the AT commands defined in esp_modem::dce_commands:: namespace
//
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, arg_nr, ...) \
return_type Shiny::DCE::name(__VA_ARGS__) { return esp_modem::dce_commands::name(this ARGS(arg_nr) ); }

DECLARE_ALL_COMMAND_APIS(return_type name(...) )

#undef ESP_MODEM_DECLARE_DCE_COMMAND

std::unique_ptr<Shiny::DCE> create_shiny_dce(const esp_modem::dce_config *config,
std::shared_ptr<esp_modem::DTE> dte,
esp_netif_t *netif)
{
return Shiny::Factory::create(config, std::move(dte), netif);
}

command_result Shiny::DCE::command(const std::string &cmd, got_line_cb got_line, uint32_t time_ms, const char separator)
{
if (!handling_urc) {
return dte->command(cmd, got_line, time_ms, separator);
}
handle_cmd = got_line;
signal.clear(3);
dte->write_cmd((uint8_t *)cmd.c_str(), cmd.length());
signal.wait_any(3, time_ms);
handle_cmd = nullptr;
if (signal.is_any(1)) {
return esp_modem::command_result::OK;
}
if (signal.is_any(2)) {
return esp_modem::command_result::FAIL;
}
return esp_modem::command_result::TIMEOUT;
}

command_result Shiny::DCE::handle_data(uint8_t *data, size_t len)
{
if (std::memchr(data, '\n', len)) {
if (handle_urc) {
handle_urc(data, len);
}
if (handle_cmd) {
auto ret = handle_cmd(data, len);
if (ret == esp_modem::command_result::TIMEOUT) {
return command_result::TIMEOUT;
}
if (ret == esp_modem::command_result::OK) {
signal.set(1);
}
if (ret == esp_modem::command_result::FAIL) {
signal.set(2);
}
}
}
return command_result::TIMEOUT;
}
77 changes: 71 additions & 6 deletions components/esp_modem/examples/modem_console/main/my_module_dce.hpp
Expand Up @@ -10,6 +10,8 @@
#pragma once


#include <utility>

#include "cxx_include/esp_modem_dce_factory.hpp"
#include "cxx_include/esp_modem_dce_module.hpp"

Expand All @@ -27,13 +29,76 @@ class MyShinyModem: public esp_modem::GenericModule {
}
};

namespace Shiny {

using namespace esp_modem;

class DCE : public esp_modem::DCE_T<MyShinyModem>, public CommandableIf {
public:
using DCE_T<MyShinyModem>::DCE_T;

command_result
command(const std::string &cmd, got_line_cb got_line, uint32_t time_ms) override {
return command(cmd, got_line, time_ms, '\n');
}

command_result
command(const std::string &cmd, got_line_cb got_line, uint32_t time_ms, const char separator) override;

int write(uint8_t *data, size_t len) override { return dte->write(data, len); }

void on_read(got_line_cb on_data) override { return dte->on_read(on_data); }

#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, num, ...) \
esp_modem::return_type name(__VA_ARGS__);

DECLARE_ALL_COMMAND_APIS(forwards name(...))

#undef ESP_MODEM_DECLARE_DCE_COMMAND

void set_on_read(esp_modem::got_line_cb on_read_cb) {
if (on_read_cb == nullptr) {
handling_urc = false;
handle_urc = nullptr;
dte->on_read(nullptr);
return;
}
handle_urc = std::move(on_read_cb);
dte->on_read([this](uint8_t *data, size_t len) {
this->handle_data(data, len);
return command_result::TIMEOUT;
});
handling_urc = true;
}

private:
got_line_cb handle_urc{nullptr};
got_line_cb handle_cmd{nullptr};
SignalGroup signal;
bool handling_urc {false};

command_result handle_data(uint8_t *data, size_t len);

};

class Factory: public ::esp_modem::dce_factory::Factory{
public:

static std::unique_ptr<DCE> create(const esp_modem::dce_config *config,
std::shared_ptr<esp_modem::DTE> dte,
esp_netif_t *netif)
{
return build_generic_DCE<MyShinyModem, DCE, std::unique_ptr<DCE>>(config, std::move(dte), netif);
}

};

} // namespace Shiny

/**
* @brief Helper create method which employs the DCE factory for creating DCE objects templated by a custom module
* @return unique pointer of the resultant DCE
*/
std::unique_ptr<esp_modem::DCE> create_shiny_dce(const esp_modem::dce_config *config,
std::shared_ptr<esp_modem::DTE> dte,
esp_netif_t *netif)
{
return esp_modem::dce_factory::Factory::build_unique<MyShinyModem>(config, std::move(dte), netif);
}
std::unique_ptr<Shiny::DCE> create_shiny_dce(const esp_modem::dce_config *config,
std::shared_ptr<esp_modem::DTE> dte,
esp_netif_t *netif);
2 changes: 2 additions & 0 deletions components/esp_modem/include/cxx_include/esp_modem_dte.hpp
Expand Up @@ -61,6 +61,8 @@ class DTE : public CommandableIf {
*/
int write(uint8_t *data, size_t len) override;

int write_cmd(uint8_t *data, size_t len);

/**
* @brief Reading from the underlying terminal
* @param d Returning the data pointer of the received payload
Expand Down
5 changes: 5 additions & 0 deletions components/esp_modem/src/esp_modem_dte.cpp
Expand Up @@ -176,6 +176,11 @@ int DTE::write(uint8_t *data, size_t len)
return data_term->write(data, len);
}

int DTE::write_cmd(uint8_t *data, size_t len)
{
return command_term->write(data, len);
}

void DTE::on_read(got_line_cb on_read_cb)
{
if (on_read_cb == nullptr) {
Expand Down

0 comments on commit c61fe1f

Please sign in to comment.