Skip to content

Commit 315c993

Browse files
committed
fix(modem): Add support for ESP-AT based tcp-client example
fix(modem): Fixup tcp-client example with esp-at fix(modem): Use nicer way to override modules fix(modem): Make tcp-client example support multiple connections fix(modem): Add link id to tcp API fix(modem): Use link-id from responder class fix(modem): WIP for multiple conn fix(modem): Support for TCP-TRANSPORT mode fix(modem): Cleanup CI fix(modem): Fix build step fix(modem): Make ssl connection working with esp-at fix(modem): Add support for BG96 and SIM7600
1 parent 39e2333 commit 315c993

File tree

8 files changed

+392
-135
lines changed

8 files changed

+392
-135
lines changed

components/esp_modem/examples/modem_tcp_client/main/command/sock_dce.cpp

Lines changed: 68 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7+
#include <algorithm>
78
#include <charconv>
89
#include <sys/socket.h>
910
#include "esp_vfs.h"
@@ -15,6 +16,28 @@ namespace sock_dce {
1516

1617
constexpr auto const *TAG = "sock_dce";
1718

19+
// Definition of the static member variables
20+
std::vector<DCE *> DCE::dce_list{};
21+
bool DCE::network_init = false;
22+
int Responder::s_link_id = 0;
23+
SemaphoreHandle_t Responder::s_dte_mutex{};
24+
25+
// Constructor - add this DCE instance to the static list
26+
DCE::DCE(std::shared_ptr<esp_modem::DTE> dte_arg, const esp_modem_dce_config *config)
27+
: Module(std::move(dte_arg), config)
28+
{
29+
dce_list.push_back(this);
30+
}
31+
32+
// Destructor - remove this DCE instance from the static list
33+
DCE::~DCE()
34+
{
35+
auto it = std::find(dce_list.begin(), dce_list.end(), this);
36+
if (it != dce_list.end()) {
37+
dce_list.erase(it);
38+
}
39+
}
40+
1841

1942
bool DCE::perform_sock()
2043
{
@@ -61,13 +84,24 @@ bool DCE::perform_sock()
6184

6285
void DCE::perform_at(uint8_t *data, size_t len)
6386
{
64-
ESP_LOG_BUFFER_HEXDUMP(TAG, data, len, ESP_LOG_VERBOSE);
87+
if (state != status::RECEIVING) {
88+
std::string_view resp_sv((char *)data, len);
89+
at.check_urc(state, resp_sv);
90+
if (state == status::IDLE) {
91+
return;
92+
}
93+
}
94+
ESP_LOG_BUFFER_HEXDUMP(TAG, data, len, ESP_LOG_INFO);
6595
switch (at.process_data(state, data, len)) {
6696
case Responder::ret::OK:
97+
ESP_LOGW(TAG, "GIVE data %d", at.link_id);
98+
xSemaphoreGive(at.s_dte_mutex);
6799
state = status::IDLE;
68100
signal.set(IDLE);
69101
return;
70102
case Responder::ret::FAIL:
103+
ESP_LOGW(TAG, "GIVE data %d", at.link_id);
104+
xSemaphoreGive(at.s_dte_mutex);
71105
state = status::FAILED;
72106
signal.set(IDLE);
73107
return;
@@ -82,10 +116,14 @@ void DCE::perform_at(uint8_t *data, size_t len)
82116
std::string_view response((char *)data, len);
83117
switch (at.check_async_replies(state, response)) {
84118
case Responder::ret::OK:
119+
ESP_LOGW(TAG, "GIVE command %d", at.link_id);
120+
xSemaphoreGive(at.s_dte_mutex);
85121
state = status::IDLE;
86122
signal.set(IDLE);
87123
return;
88124
case Responder::ret::FAIL:
125+
ESP_LOGW(TAG, "GIVE command %d", at.link_id);
126+
xSemaphoreGive(at.s_dte_mutex);
89127
state = status::FAILED;
90128
signal.set(IDLE);
91129
return;
@@ -131,6 +169,9 @@ bool DCE::at_to_sock()
131169
close_sock();
132170
return false;
133171
}
172+
ESP_LOGI(TAG, "TAKE RECV %d", at.link_id);
173+
xSemaphoreTake(at.s_dte_mutex, portMAX_DELAY);
174+
ESP_LOGE(TAG, "TAKE RECV %d", at.link_id);
134175
state = status::RECEIVING;
135176
at.start_receiving(at.get_buf_len());
136177
return true;
@@ -139,8 +180,8 @@ bool DCE::at_to_sock()
139180
bool DCE::sock_to_at()
140181
{
141182
ESP_LOGD(TAG, "socket read: data available");
142-
if (!signal.wait(IDLE, 1000)) {
143-
ESP_LOGE(TAG, "Failed to get idle");
183+
if (!signal.wait(IDLE, 5000)) {
184+
ESP_LOGE(TAG, "Failed to get idle 2");
144185
close_sock();
145186
return false;
146187
}
@@ -149,6 +190,9 @@ bool DCE::sock_to_at()
149190
close_sock();
150191
return false;
151192
}
193+
ESP_LOGI(TAG, "TAKE SEND %d", at.link_id);
194+
xSemaphoreTake(at.s_dte_mutex, portMAX_DELAY);
195+
ESP_LOGE(TAG, "TAKE SEND %d", at.link_id);
152196
state = status::SENDING;
153197
int len = ::recv(sock, at.get_buf(), at.get_buf_len(), 0);
154198
if (len < 0) {
@@ -224,12 +268,17 @@ void DCE::start_listening(int port)
224268

225269
bool DCE::connect(std::string host, int port)
226270
{
227-
dte->on_read(nullptr);
228-
tcp_close();
229-
dte->on_read([this](uint8_t *data, size_t len) {
230-
this->perform_at(data, len);
231-
return esp_modem::command_result::TIMEOUT;
232-
});
271+
data_ready_fd = eventfd(0, EFD_SUPPORT_ISR);
272+
assert(data_ready_fd > 0);
273+
// dte->on_read(nullptr);
274+
// tcp_close();
275+
// dte->on_read([](uint8_t *data, size_t len) {
276+
// read_callback(data, len);
277+
// return esp_modem::command_result::TIMEOUT;
278+
// });
279+
ESP_LOGI(TAG, "TAKE CONNECT %d", at.link_id);
280+
xSemaphoreTake(at.s_dte_mutex, portMAX_DELAY);
281+
ESP_LOGE(TAG, "TAKE CONNECT %d", at.link_id);
233282
if (!at.start_connecting(host, port)) {
234283
ESP_LOGE(TAG, "Unable to start connecting");
235284
dte->on_read(nullptr);
@@ -241,12 +290,15 @@ bool DCE::connect(std::string host, int port)
241290

242291
bool DCE::init()
243292
{
293+
if (network_init) {
294+
return true;
295+
}
296+
network_init = true;
297+
Responder::s_dte_mutex = xSemaphoreCreateBinary();
298+
xSemaphoreGive(at.s_dte_mutex);
244299
esp_vfs_eventfd_config_t config = ESP_VFS_EVENTD_CONFIG_DEFAULT();
245300
esp_vfs_eventfd_register(&config);
246301

247-
data_ready_fd = eventfd(0, EFD_SUPPORT_ISR);
248-
assert(data_ready_fd > 0);
249-
250302
dte->on_read(nullptr);
251303
const int retries = 5;
252304
int i = 0;
@@ -287,6 +339,10 @@ bool DCE::init()
287339
esp_modem::Task::Delay(5000);
288340
}
289341
ESP_LOGI(TAG, "Got IP %s", ip_addr.c_str());
342+
dte->on_read([](uint8_t *data, size_t len) {
343+
read_callback(data, len);
344+
return esp_modem::command_result::TIMEOUT;
345+
});
290346
return true;
291347
}
292348

components/esp_modem/examples/modem_tcp_client/main/command/sock_dce.hpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class Responder {
3434
sock(s), data_ready_fd(ready_fd), dte(dte_arg) {}
3535
ret process_data(status state, uint8_t *data, size_t len);
3636
ret check_async_replies(status state, std::string_view &response);
37+
ret check_urc(status state, std::string_view &response);
3738

3839
void start_sending(size_t len);
3940
void start_receiving(size_t len);
@@ -63,13 +64,17 @@ class Responder {
6364
return total_len;
6465
}
6566

67+
int link_id{s_link_id++};
68+
static SemaphoreHandle_t s_dte_mutex;
6669
private:
70+
static int s_link_id;
6771
static constexpr size_t buffer_size = 512;
6872

6973
bool on_read(char *data, size_t len)
7074
{
7175
#ifndef CONFIG_EXAMPLE_CUSTOM_TCP_TRANSPORT
7276
::send(sock, data, len, 0);
77+
printf("sending %d\n", len);
7378
#else
7479
::memcpy(&buffer[actual_read], data, len);
7580
actual_read += len;
@@ -101,6 +106,8 @@ class Responder {
101106
class DCE : public Module {
102107
using Module::Module;
103108
public:
109+
DCE(std::shared_ptr<esp_modem::DTE> dte_arg, const esp_modem_dce_config *config);
110+
~DCE();
104111

105112
/**
106113
* @brief Opens network in AT command mode
@@ -163,6 +170,9 @@ class DCE : public Module {
163170
return 0;
164171
}
165172
at.clear_offsets();
173+
ESP_LOGI("TAG", "TAKE RECV %d", at.link_id);
174+
xSemaphoreTake(at.s_dte_mutex, portMAX_DELAY);
175+
ESP_LOGE("TAG", "TAKE RECV %d", at.link_id);
166176
state = status::RECEIVING;
167177
uint64_t data;
168178
read(data_ready_fd, &data, sizeof(data));
@@ -184,6 +194,9 @@ class DCE : public Module {
184194
if (!wait_to_idle(timeout_ms)) {
185195
return -1;
186196
}
197+
ESP_LOGI("TAG", "TAKE SEND %d", at.link_id);
198+
xSemaphoreTake(at.s_dte_mutex, portMAX_DELAY);
199+
ESP_LOGE("TAG", "TAKE SEND %d", at.link_id);
187200
state = status::SENDING;
188201
memcpy(at.get_buf(), buffer, len_to_send);
189202
ESP_LOG_BUFFER_HEXDUMP("dce", at.get_buf(), len, ESP_LOG_VERBOSE);
@@ -224,6 +237,14 @@ class DCE : public Module {
224237
}
225238
return -1;
226239
}
240+
static std::vector<DCE *> dce_list;
241+
static bool network_init;
242+
static void read_callback(uint8_t *data, size_t len)
243+
{
244+
for (auto dce : dce_list) {
245+
dce->perform_at(data, len);
246+
}
247+
}
227248
private:
228249
esp_modem::SignalGroup signal;
229250
void close_sock();

components/esp_modem/examples/modem_tcp_client/main/generate/sock_dce.cpp

Lines changed: 68 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7+
#include <algorithm>
78
#include <charconv>
89
#include <sys/socket.h>
910
#include "esp_vfs.h"
@@ -15,6 +16,28 @@ namespace sock_dce {
1516

1617
constexpr auto const *TAG = "sock_dce";
1718

19+
// Definition of the static member variables
20+
std::vector<DCE*> DCE::dce_list{};
21+
bool DCE::network_init = false;
22+
int Responder::s_link_id = 0;
23+
SemaphoreHandle_t Responder::s_dte_mutex{};
24+
25+
// Constructor - add this DCE instance to the static list
26+
DCE::DCE(std::shared_ptr<esp_modem::DTE> dte_arg, const esp_modem_dce_config *config)
27+
: Module(std::move(dte_arg), config)
28+
{
29+
dce_list.push_back(this);
30+
}
31+
32+
// Destructor - remove this DCE instance from the static list
33+
DCE::~DCE()
34+
{
35+
auto it = std::find(dce_list.begin(), dce_list.end(), this);
36+
if (it != dce_list.end()) {
37+
dce_list.erase(it);
38+
}
39+
}
40+
1841

1942
bool DCE::perform_sock()
2043
{
@@ -61,13 +84,24 @@ bool DCE::perform_sock()
6184

6285
void DCE::perform_at(uint8_t *data, size_t len)
6386
{
64-
ESP_LOG_BUFFER_HEXDUMP(TAG, data, len, ESP_LOG_VERBOSE);
87+
if (state != status::RECEIVING) {
88+
std::string_view resp_sv((char *)data, len);
89+
at.check_urc(state, resp_sv);
90+
if (state == status::IDLE) {
91+
return;
92+
}
93+
}
94+
ESP_LOG_BUFFER_HEXDUMP(TAG, data, len, ESP_LOG_INFO);
6595
switch (at.process_data(state, data, len)) {
6696
case Responder::ret::OK:
97+
ESP_LOGW(TAG, "GIVE data %d", at.link_id);
98+
xSemaphoreGive(at.s_dte_mutex);
6799
state = status::IDLE;
68100
signal.set(IDLE);
69101
return;
70102
case Responder::ret::FAIL:
103+
ESP_LOGW(TAG, "GIVE data %d", at.link_id);
104+
xSemaphoreGive(at.s_dte_mutex);
71105
state = status::FAILED;
72106
signal.set(IDLE);
73107
return;
@@ -82,10 +116,14 @@ void DCE::perform_at(uint8_t *data, size_t len)
82116
std::string_view response((char *)data, len);
83117
switch (at.check_async_replies(state, response)) {
84118
case Responder::ret::OK:
119+
ESP_LOGW(TAG, "GIVE command %d", at.link_id);
120+
xSemaphoreGive(at.s_dte_mutex);
85121
state = status::IDLE;
86122
signal.set(IDLE);
87123
return;
88124
case Responder::ret::FAIL:
125+
ESP_LOGW(TAG, "GIVE command %d", at.link_id);
126+
xSemaphoreGive(at.s_dte_mutex);
89127
state = status::FAILED;
90128
signal.set(IDLE);
91129
return;
@@ -131,6 +169,9 @@ bool DCE::at_to_sock()
131169
close_sock();
132170
return false;
133171
}
172+
ESP_LOGI(TAG, "TAKE RECV %d", at.link_id);
173+
xSemaphoreTake(at.s_dte_mutex, portMAX_DELAY);
174+
ESP_LOGE(TAG, "TAKE RECV %d", at.link_id);
134175
state = status::RECEIVING;
135176
at.start_receiving(at.get_buf_len());
136177
return true;
@@ -139,8 +180,8 @@ bool DCE::at_to_sock()
139180
bool DCE::sock_to_at()
140181
{
141182
ESP_LOGD(TAG, "socket read: data available");
142-
if (!signal.wait(IDLE, 1000)) {
143-
ESP_LOGE(TAG, "Failed to get idle");
183+
if (!signal.wait(IDLE, 5000)) {
184+
ESP_LOGE(TAG, "Failed to get idle 2");
144185
close_sock();
145186
return false;
146187
}
@@ -149,6 +190,9 @@ bool DCE::sock_to_at()
149190
close_sock();
150191
return false;
151192
}
193+
ESP_LOGI(TAG, "TAKE SEND %d", at.link_id);
194+
xSemaphoreTake(at.s_dte_mutex, portMAX_DELAY);
195+
ESP_LOGE(TAG, "TAKE SEND %d", at.link_id);
152196
state = status::SENDING;
153197
int len = ::recv(sock, at.get_buf(), at.get_buf_len(), 0);
154198
if (len < 0) {
@@ -224,12 +268,17 @@ void DCE::start_listening(int port)
224268

225269
bool DCE::connect(std::string host, int port)
226270
{
227-
dte->on_read(nullptr);
228-
tcp_close();
229-
dte->on_read([this](uint8_t *data, size_t len) {
230-
this->perform_at(data, len);
231-
return esp_modem::command_result::TIMEOUT;
232-
});
271+
data_ready_fd = eventfd(0, EFD_SUPPORT_ISR);
272+
assert(data_ready_fd > 0);
273+
// dte->on_read(nullptr);
274+
// tcp_close();
275+
// dte->on_read([](uint8_t *data, size_t len) {
276+
// read_callback(data, len);
277+
// return esp_modem::command_result::TIMEOUT;
278+
// });
279+
ESP_LOGI(TAG, "TAKE CONNECT %d", at.link_id);
280+
xSemaphoreTake(at.s_dte_mutex, portMAX_DELAY);
281+
ESP_LOGE(TAG, "TAKE CONNECT %d", at.link_id);
233282
if (!at.start_connecting(host, port)) {
234283
ESP_LOGE(TAG, "Unable to start connecting");
235284
dte->on_read(nullptr);
@@ -241,12 +290,15 @@ bool DCE::connect(std::string host, int port)
241290

242291
bool DCE::init()
243292
{
293+
if (network_init) {
294+
return true;
295+
}
296+
network_init = true;
297+
Responder::s_dte_mutex = xSemaphoreCreateBinary();
298+
xSemaphoreGive(at.s_dte_mutex);
244299
esp_vfs_eventfd_config_t config = ESP_VFS_EVENTD_CONFIG_DEFAULT();
245300
esp_vfs_eventfd_register(&config);
246301

247-
data_ready_fd = eventfd(0, EFD_SUPPORT_ISR);
248-
assert(data_ready_fd > 0);
249-
250302
dte->on_read(nullptr);
251303
const int retries = 5;
252304
int i = 0;
@@ -287,6 +339,10 @@ bool DCE::init()
287339
esp_modem::Task::Delay(5000);
288340
}
289341
ESP_LOGI(TAG, "Got IP %s", ip_addr.c_str());
342+
dte->on_read([](uint8_t *data, size_t len) {
343+
read_callback(data, len);
344+
return esp_modem::command_result::TIMEOUT;
345+
});
290346
return true;
291347
}
292348

0 commit comments

Comments
 (0)