Compare commits

..

26 Commits

Author SHA1 Message Date
57afa38f49 Bump asio/mdns/esp_websocket_client versions
Update components version afrer change d66f9dc158
2022-07-14 20:04:28 +04:00
10e6348e09 Merge pull request #85 from david-cermak/feature/modem_operator_name_add_act
feat(esp_modem): Add optional ACT to operator-name
2022-07-13 16:20:54 +02:00
a286634359 feat(esp_modem): Add optional ACT to operator-name
Closes https://github.com/espressif/esp-protocols/issues/80
2022-07-13 09:56:29 +02:00
4cdfc857ad Merge pull request #68 from gabsuren/refactor/organize_yml_files
CI: Organize GitHub workflow structures
2022-07-12 20:04:01 +02:00
371a32d4ae Merge pull request #72 from david-cermak/bugfix/modem_c_api_pdp_ctx
fix(esp-modem): Add missing set_pdp_context() to C-API
2022-07-12 20:03:03 +02:00
dc4e54e99a Merge pull request #87 from Lapshin/fix/ignore-format-warnings
ignore format warnings
2022-07-12 20:02:30 +02:00
d66f9dc158 ignore format warnings 2022-07-12 18:13:01 +04:00
4980ac85b7 fix(esp-modem): Add missing set_pdp_context() to C-API 2022-07-12 15:52:39 +02:00
626eb52d04 CI: Organize github workflow structure 2022-07-12 17:24:41 +04:00
82b1aa9280 Merge pull request #73 from Lapshin/fix/ignore-format-warnings
esp_modem: Ignore format warnings (IDFGH-7760)
2022-07-12 10:44:26 +02:00
e8145fcede esp_modem: Ignore format warnings 2022-07-12 12:32:15 +04:00
9c3e24b6cf Merge pull request #70 from david-cermak/bugfix/modem_ap2ppp_retry
fix(esp_modem): Update ap2ppp example to recover network on disconnection
2022-07-11 19:11:48 +02:00
b4d85d6aae Merge pull request #84 from Lapshin/fix/asio-exampels-build
asio: fix exampels build (IDFGH-7792)
2022-07-11 19:02:36 +02:00
0b102f6286 mdns: Fix test_app build 2022-07-11 20:39:56 +04:00
06e7baf2c2 CI: Fix ASIO build in CI run 2022-07-11 19:00:06 +04:00
3662c149fb asio: Fix exampels build 2022-07-11 18:01:46 +04:00
a243d7e878 fix(esp_modem): Update ap2ppp example to recover network on disconnection
Closes https://github.com/espressif/esp-protocols/issues/44
2022-07-01 13:52:49 +02:00
ef1bae5cdd Merge pull request #35 from ESP-YJM/pr/optimize_websocket
feat(websocket): Optimize memory size for websocket client init (IDFGH-7357)
2022-06-28 16:04:09 +02:00
4cefcd3606 feat(websocket): Optimize memory size for websocket client init 2022-06-28 21:09:05 +08:00
a177b3d024 Merge pull request #67 from gabsuren/bugfix/websocket_ci_long_run
CI: Fix CI long run on websocket examples
2022-06-28 13:59:56 +02:00
b7e73d25a7 CI: Fix CI long run on websocket examples 2022-06-28 15:25:40 +04:00
9b403d477f Merge pull request #64 from bbinet/custom-source-clk
Allow to customize uart source_clk (IDFGH-7659)
2022-06-24 16:24:00 +02:00
d723fb7a5a Allow to customize uart source_clk
This is for example needed when using an external crystal to select
UART_SCLK_XTAL, which fixes uart comm issue when using PM with light
sleep enabled.
2022-06-24 14:44:15 +02:00
9905fe4cf6 Merge pull request #62 from gabsuren/asio_submodule_migration_with_history
ASIO: Initial version based on IDF 5.0 with history
2022-06-24 14:29:39 +02:00
8dc3e5835c Merge pull request #63 from bbinet/add-raw-command
Add raw command (IDFGH-7658)
2022-06-23 18:00:42 +02:00
0cf08fb676 Add "at" api for custom commands 2022-06-23 17:40:06 +02:00
43 changed files with 579 additions and 311 deletions

View File

@ -1,36 +0,0 @@
name: Build
on: [push, pull_request]
jobs:
build:
strategy:
matrix:
idf_ver: ["latest", "release-v4.1", "release-v4.2", "release-v4.3", "release-v4.4"]
example: ["pppos_client", "modem_console", "ap_to_pppos", "simple_cmux_client"]
idf_target: ["esp32"]
exclude:
- idf_ver: "release-v4.1"
example: modem_console
- idf_ver: "release-v4.1"
example: ap_to_pppos
- idf_ver: "release-v4.1"
example: simple_cmux_client
- idf_ver: "release-v4.2"
example: simple_cmux_client
runs-on: ubuntu-20.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@master
with:
path: esp-protocols
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
env:
IDF_TARGET: ${{ matrix.idf_target }}
shell: bash
run: |
. ${IDF_PATH}/export.sh
cd $GITHUB_WORKSPACE/esp-protocols/components/esp_modem/examples/${{ matrix.example }}
idf.py build

View File

@ -1,38 +0,0 @@
name: Build mDNS
on: [push, pull_request]
jobs:
build:
strategy:
matrix:
idf_ver: ["latest"]
idf_target: ["esp32", "esp32s2", "esp32c3"]
runs-on: ubuntu-20.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v3
with:
submodules: recursive
path: esp-protocols
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
env:
IDF_TARGET: ${{ matrix.idf_target }}
shell: bash
run: |
. ${IDF_PATH}/export.sh
cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/examples/
idf.py set-target ${{ matrix.idf_target }}
cat sdkconfig.ci.eth_def >> sdkconfig.defaults
idf.py build
rm sdkconfig.defaults
cat sdkconfig.ci.eth_custom_netif >> sdkconfig.defaults
idf.py build
rm sdkconfig.defaults
cat sdkconfig.ci.eth_socket >> sdkconfig.defaults
idf.py build
cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/tests/test_apps/
idf.py set-target ${{ matrix.idf_target }}
idf.py build

View File

@ -1,78 +0,0 @@
name: Build Websockets
on: [push, pull_request]
jobs:
build:
strategy:
matrix:
idf_ver: ["latest"]
idf_target: ["esp32"]
runs-on: ubuntu-20.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v3
with:
submodules: recursive
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
env:
IDF_TARGET: ${{ matrix.idf_target }}
shell: bash
working-directory: components/esp_websocket_client/examples/
run: |
. ${IDF_PATH}/export.sh
cat sdkconfig.ci >> sdkconfig.defaults
idf.py build
- name: Merge binaries
working-directory: components/esp_websocket_client/examples/build
env:
IDF_TARGET: ${{ matrix.idf_target }}
shell: bash
run: |
. ${IDF_PATH}/export.sh
esptool.py --chip ${{ matrix.idf_target }} merge_bin --fill-flash-size 4MB -o flash_image.bin @flash_args
- uses: actions/upload-artifact@v2
with:
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}
path: components/esp_websocket_client/examples/build/
if-no-files-found: error
run-target:
name: Run Example Test on target
needs: build
strategy:
fail-fast: false
matrix:
idf_ver: ["latest"]
idf_target: ["esp32"]
runs-on:
- self-hosted
- ESP32-ETHERNET-KIT
container:
image: python:3.7-buster
options: --privileged # Privileged mode has access to serial ports
steps:
- uses: actions/checkout@v3
- uses: actions/download-artifact@v2
with:
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}
path: components/esp_websocket_client/examples/build/
- name: Install Python packages
env:
PIP_EXTRA_INDEX_URL: "https://www.piwheels.org/simple"
run: |
pip install -r $GITHUB_WORKSPACE/components/esp_websocket_client/examples/requirements.txt
- name: Download Example Test to target
run: python -m esptool --chip ${{ matrix.idf_target }} write_flash 0x0 components/esp_websocket_client/examples/build/flash_image.bin
- name: Run Example Test on target
working-directory: components/esp_websocket_client/examples
run: |
cp sdkconfig.ci sdkconfig.defaults
pytest --log-cli-level DEBUG --junit-xml=./test_app_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}.xml --target=${{ matrix.idf_target }}
- uses: actions/upload-artifact@v2
if: always()
with:
name: examples_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}
path: examples/*.xml

View File

@ -1,28 +0,0 @@
name: Build ASIO
on: [push, pull_request]
jobs:
build:
strategy:
matrix:
idf_ver: ["latest"]
idf_target: ["esp32", "esp32s2"]
example: ["asio_chat", "async_request", "socks4", "ssl_client_server", "tcp_echo_server", "udp_echo_server"]
runs-on: ubuntu-20.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v3
with:
path: esp-protocols
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
env:
IDF_TARGET: ${{ matrix.idf_target }}
shell: bash
run: |
. ${IDF_PATH}/export.sh
cd $GITHUB_WORKSPACE/esp-protocols/components/asio/examples/${{ matrix.example }}
idf.py set-target ${{ matrix.idf_target }}
idf.py build

View File

@ -4,7 +4,7 @@ on: [push, pull_request]
jobs:
host_test:
name: Build and test
name: Build and Test on Host
runs-on: ubuntu-20.04
container: espressif/idf:release-v4.3
env:

169
.github/workflows/target-test.yml vendored Normal file
View File

@ -0,0 +1,169 @@
name: Build and Run Target tests
on: [push, pull_request]
jobs:
build_esp_modem:
strategy:
matrix:
idf_ver: ["latest", "release-v4.1", "release-v4.2", "release-v4.3", "release-v4.4"]
example: ["pppos_client", "modem_console", "ap_to_pppos", "simple_cmux_client"]
idf_target: ["esp32"]
exclude:
- idf_ver: "release-v4.1"
example: modem_console
- idf_ver: "release-v4.1"
example: ap_to_pppos
- idf_ver: "release-v4.1"
example: simple_cmux_client
- idf_ver: "release-v4.2"
example: simple_cmux_client
runs-on: ubuntu-20.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@master
with:
path: esp-protocols
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
env:
IDF_TARGET: ${{ matrix.idf_target }}
shell: bash
run: |
. ${IDF_PATH}/export.sh
cd $GITHUB_WORKSPACE/esp-protocols/components/esp_modem/examples/${{ matrix.example }}
idf.py build
build_mdns:
strategy:
matrix:
idf_ver: ["latest"]
idf_target: ["esp32", "esp32s2", "esp32c3"]
runs-on: ubuntu-20.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v3
with:
submodules: recursive
path: esp-protocols
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
env:
IDF_TARGET: ${{ matrix.idf_target }}
shell: bash
run: |
. ${IDF_PATH}/export.sh
cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/examples/
idf.py set-target ${{ matrix.idf_target }}
cat sdkconfig.ci.eth_def >> sdkconfig.defaults
idf.py build
rm sdkconfig.defaults
cat sdkconfig.ci.eth_custom_netif >> sdkconfig.defaults
idf.py build
rm sdkconfig.defaults
cat sdkconfig.ci.eth_socket >> sdkconfig.defaults
idf.py build
cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/tests/test_apps/
idf.py set-target ${{ matrix.idf_target }}
idf.py build
build_asio:
strategy:
matrix:
idf_ver: ["latest"]
idf_target: ["esp32", "esp32s2"]
example: ["asio_chat", "async_request", "socks4", "ssl_client_server", "tcp_echo_server", "udp_echo_server"]
runs-on: ubuntu-20.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v3
with:
submodules: recursive
path: esp-protocols
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
env:
IDF_TARGET: ${{ matrix.idf_target }}
shell: bash
run: |
. ${IDF_PATH}/export.sh
cd $GITHUB_WORKSPACE/esp-protocols/components/asio/examples/${{ matrix.example }}
idf.py set-target ${{ matrix.idf_target }}
idf.py build
build_websocket:
strategy:
matrix:
idf_ver: ["latest"]
idf_target: ["esp32"]
runs-on: ubuntu-20.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v3
with:
submodules: recursive
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
env:
IDF_TARGET: ${{ matrix.idf_target }}
shell: bash
working-directory: components/esp_websocket_client/examples/
run: |
. ${IDF_PATH}/export.sh
cat sdkconfig.ci >> sdkconfig.defaults
idf.py build
- name: Merge binaries
working-directory: components/esp_websocket_client/examples/build
env:
IDF_TARGET: ${{ matrix.idf_target }}
shell: bash
run: |
. ${IDF_PATH}/export.sh
esptool.py --chip ${{ matrix.idf_target }} merge_bin --fill-flash-size 4MB -o flash_image.bin @flash_args
- uses: actions/upload-artifact@v2
with:
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}
path: components/esp_websocket_client/examples/build/
if-no-files-found: error
run-target:
name: Run Websocket Example Test on target
needs: build_websocket
strategy:
fail-fast: false
matrix:
idf_ver: ["latest"]
idf_target: ["esp32"]
runs-on:
- self-hosted
- ESP32-ETHERNET-KIT
container:
image: python:3.7-buster
options: --privileged # Privileged mode has access to serial ports
steps:
- uses: actions/checkout@v3
- uses: actions/download-artifact@v2
with:
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}
path: components/esp_websocket_client/examples/build/
- name: Install Python packages
env:
PIP_EXTRA_INDEX_URL: "https://www.piwheels.org/simple"
run: |
pip install -r $GITHUB_WORKSPACE/components/esp_websocket_client/examples/requirements.txt
- name: Download Example Test to target
run: python -m esptool --chip ${{ matrix.idf_target }} write_flash 0x0 components/esp_websocket_client/examples/build/flash_image.bin
- name: Run Example Test on target
working-directory: components/esp_websocket_client/examples
run: |
cp sdkconfig.ci sdkconfig.defaults
pytest --log-cli-level DEBUG --junit-xml=./test_app_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}.xml --target=${{ matrix.idf_target }}
- uses: actions/upload-artifact@v2
if: always()
with:
name: examples_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}
path: examples/*.xml

View File

@ -27,6 +27,7 @@ idf_component_register(SRCS ${asio_sources}
INCLUDE_DIRS "asio/asio/include" "port/include"
PRIV_INCLUDE_DIRS ${asio_priv_includes}
REQUIRES lwip)
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
if(CONFIG_ASIO_SSL_SUPPORT)
if(CONFIG_ASIO_USE_ESP_WOLFSSL)

View File

@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.16)
# (Not part of the boilerplate)
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
set(EXTRA_COMPONENT_DIRS ../../../../common_components/protocol_examples_common)
set(EXTRA_COMPONENT_DIRS ../.. ../../../../common_components/protocol_examples_common)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(asio_chat)

View File

@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.16)
# (Not part of the boilerplate)
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
set(EXTRA_COMPONENT_DIRS ../../../../common_components/protocol_examples_common)
set(EXTRA_COMPONENT_DIRS ../../ ../../../../common_components/protocol_examples_common)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(async_http_request)

View File

@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.16)
# (Not part of the boilerplate)
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
set(EXTRA_COMPONENT_DIRS ../../../../common_components/protocol_examples_common)
set(EXTRA_COMPONENT_DIRS ../.. ../../../../common_components/protocol_examples_common)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(asio_sock4)

View File

@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.16)
# (Not part of the boilerplate)
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
set(EXTRA_COMPONENT_DIRS ../../../../common_components/protocol_examples_common)
set(EXTRA_COMPONENT_DIRS ../.. ../../../../common_components/protocol_examples_common)
set(EXCLUDE_COMPONENTS openssl)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)

View File

@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.16)
# (Not part of the boilerplate)
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
set(EXTRA_COMPONENT_DIRS ../../../../common_components/protocol_examples_common)
set(EXTRA_COMPONENT_DIRS ../.. ../../../../common_components/protocol_examples_common)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(asio_tcp_echo_server)

View File

@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.16)
# (Not part of the boilerplate)
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
set(EXTRA_COMPONENT_DIRS ../../../../common_components/protocol_examples_common)
set(EXTRA_COMPONENT_DIRS ../../ ../../../../common_components/protocol_examples_common)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(asio_udp_echo_server)

View File

@ -1,4 +1,4 @@
version: "1.0.1"
version: "1.0.2"
description: ASIO
dependencies:
idf:

View File

@ -44,3 +44,5 @@ if(${target} STREQUAL "linux")
# This is needed for ESP_LOGx() macros, as integer formats differ on ESP32(..) and x64
set_target_properties(${COMPONENT_LIB} PROPERTIES COMPILE_FLAGS -Wno-format)
endif()
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")

View File

@ -124,6 +124,38 @@ void wifi_init_softap(void)
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL);
}
void start_network(void)
{
EventBits_t bits = 0;
while ((bits & CONNECT_BIT) == 0) {
if (!modem_check_sync()) {
ESP_LOGE(TAG, "Modem does not respond, maybe in DATA mode? ...exiting network mode");
modem_stop_network();
if (!modem_check_sync()) {
ESP_LOGE(TAG, "Modem does not respond to AT ...restarting");
modem_reset();
ESP_LOGI(TAG, "Restarted");
}
continue;
}
if (!modem_check_signal()) {
ESP_LOGI(TAG, "Poor signal ...will check after 5s");
vTaskDelay(pdMS_TO_TICKS(5000));
continue;
}
if (!modem_start_network()) {
ESP_LOGE(TAG, "Modem could not enter network mode ...will retry after 10s");
vTaskDelay(pdMS_TO_TICKS(10000));
continue;
}
bits = xEventGroupWaitBits(event_group, (DISCONNECT_BIT | CONNECT_BIT), pdTRUE, pdFALSE, pdMS_TO_TICKS(30000));
if (bits & DISCONNECT_BIT) {
ESP_LOGE(TAG, "Modem got disconnected ...retrying");
modem_stop_network();
}
}
}
void app_main(void)
{
// Initialize NVS
@ -149,16 +181,7 @@ void app_main(void)
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, on_ip_event, NULL));
// Start the PPP network and wait for connection
modem_start_network();
EventBits_t bits;
do {
bits = xEventGroupWaitBits(event_group, (CONNECT_BIT | DISCONNECT_BIT), pdTRUE, pdFALSE, portMAX_DELAY);
if (bits & DISCONNECT_BIT) {
ESP_LOGW(TAG, "Modem got disconnected from the PPP server: retrying...");
modem_stop_network();
modem_start_network();
}
} while ((bits & CONNECT_BIT) == 0);
start_network();
// Initialize the AP and setup the NAT
esp_netif_t *ap_netif = esp_netif_create_default_wifi_ap();
@ -172,11 +195,10 @@ void app_main(void)
// Provide a recovery if disconnection of some kind registered
while (true) {
bits = xEventGroupWaitBits(event_group, DISCONNECT_BIT, pdTRUE, pdFALSE, portMAX_DELAY);
EventBits_t bits = xEventGroupWaitBits(event_group, DISCONNECT_BIT, pdTRUE, pdFALSE, portMAX_DELAY);
if (bits & DISCONNECT_BIT) {
ESP_LOGW(TAG, "Modem got disconnected from the PPP server: restarting the network...");
modem_stop_network();
modem_start_network();
start_network();
}
}
}

View File

@ -47,12 +47,31 @@ void modem_deinit_network(void)
}
}
void modem_start_network()
bool modem_start_network()
{
esp_modem_set_mode(dce, ESP_MODEM_MODE_DATA);
return esp_modem_set_mode(dce, ESP_MODEM_MODE_DATA) == ESP_OK;
}
void modem_stop_network()
bool modem_stop_network()
{
esp_modem_set_mode(dce, ESP_MODEM_MODE_COMMAND);
return esp_modem_set_mode(dce, ESP_MODEM_MODE_COMMAND);
}
bool modem_check_sync()
{
return esp_modem_sync(dce) == ESP_OK;
}
void modem_reset()
{
esp_modem_reset(dce);
}
bool modem_check_signal()
{
int rssi, ber;
if (esp_modem_get_signal_quality(dce, &rssi, &ber) == ESP_OK) {
return rssi != 99 && rssi > 5;
}
return false;
}

View File

@ -79,6 +79,24 @@ public:
}
}
bool sync()
{
return dce_commands::sync(dte.get()) == command_result::OK;
}
void reset()
{
dce_commands::reset(dte.get());
}
bool check_signal()
{
int rssi, ber;
if (dce_commands::get_signal_quality(dte.get(), rssi, ber) != command_result::OK)
return false;
return rssi != 99 && rssi > 5;
}
[[maybe_unused]] bool init_sim(const std::string &pin)
{
// switch to command mode (in case we were in PPP mode)
@ -166,14 +184,14 @@ extern "C" esp_err_t modem_init_network(esp_netif_t *netif)
return ESP_OK;
}
extern "C" void modem_start_network()
extern "C" bool modem_start_network()
{
dce->set_mode(esp_modem::modem_mode::DATA_MODE);
return dce->set_mode(esp_modem::modem_mode::DATA_MODE);
}
extern "C" void modem_stop_network()
extern "C" bool modem_stop_network()
{
dce->set_mode(esp_modem::modem_mode::COMMAND_MODE);
return dce->set_mode(esp_modem::modem_mode::COMMAND_MODE);
}
extern "C" void modem_deinit_network()
@ -182,4 +200,19 @@ extern "C" void modem_deinit_network()
dce = nullptr;
}
extern "C" bool modem_check_sync()
{
return dce->get_module()->sync();
}
extern "C" void modem_reset()
{
dce->get_module()->reset();
}
extern "C" bool modem_check_signal()
{
return dce->get_module()->check_signal();
}
}

View File

@ -31,13 +31,18 @@ void modem_deinit_network();
/**
* @brief Starts the PPP network
*/
void modem_start_network();
bool modem_start_network();
/**
* @brief Stops the PPP network
*/
void modem_stop_network();
bool modem_stop_network();
bool modem_check_sync();
void modem_reset();
bool modem_check_signal();
#ifdef __cplusplus
}

View File

@ -4,3 +4,4 @@ idf_component_register(SRCS "modem_console_main.cpp"
"ping_handle.c"
REQUIRES console esp_http_client nvs_flash esp_modem esp_modem_usb_dte
INCLUDE_DIRS ".")
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")

View File

@ -1,2 +1,3 @@
idf_component_register(SRCS "pppos_client_main.c"
INCLUDE_DIRS ".")
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")

View File

@ -1,4 +1,4 @@
version: "0.1.17"
version: "0.1.18"
description: esp modem
url: https://github.com/espressif/esp-protocols/tree/master/components/esp_modem
dependencies:

View File

@ -104,6 +104,15 @@ public:
pdp = std::move(new_pdp);
}
/**
* @brief Simplified version of operator name (without the ACT, which is included in the command library)
*/
command_result get_operator_name(std::string& name)
{
int dummy_act;
return get_operator_name(name, dummy_act);
}
/**
* @brief Common DCE commands generated from the API AT list
*/

View File

@ -15,6 +15,7 @@
#pragma once
#include "esp_modem_config.h"
#include "esp_netif.h"
#ifdef __cplusplus
extern "C" {
@ -22,7 +23,11 @@ extern "C" {
typedef struct esp_modem_dce_wrap esp_modem_dce_t;
struct PdpContext;
typedef struct esp_modem_PdpContext_t {
size_t context_id;
const char *protocol_type;
const char *apn;
} esp_modem_PdpContext_t;
/**
* @defgroup ESP_MODEM_C_API ESP_MODEM C API

View File

@ -50,7 +50,8 @@ struct esp_modem_uart_term_config {
uart_stop_bits_t stop_bits; /*!< Stop bits of UART */
uart_parity_t parity; /*!< Parity type */
esp_modem_flow_ctrl_t flow_control; /*!< Flow control type */
int baud_rate; /*!< Communication baud rate */
uart_sclk_t source_clk; /*!< UART source clock selection */
int baud_rate; /*!< Communication baud rate */
int tx_io_num; /*!< TXD Pin Number */
int rx_io_num; /*!< RXD Pin Number */
int rts_io_num; /*!< RTS Pin Number */
@ -107,6 +108,7 @@ struct esp_modem_dte_config {
.stop_bits = UART_STOP_BITS_1, \
.parity = UART_PARITY_DISABLE, \
.flow_control = ESP_MODEM_FLOW_CONTROL_NONE,\
.source_clk = UART_SCLK_APB, \
.baud_rate = 115200, \
.tx_io_num = 25, \
.rx_io_num = 26, \

View File

@ -38,7 +38,7 @@
#define BOOL_OUT(param, name) bool* _ARG(param, name)
#define INT_OUT(param, name) int* _ARG(param, name)
#define INTEGER_LIST_IN(param, name) const int* _ARG(param, name)
#define STRUCT_OUT(struct_name, p1) struct struct_name* p1
#define STRUCT_OUT(struct_name, p1) esp_modem_ ## struct_name ## _t* p1
#endif
#define DECLARE_ALL_COMMAND_APIS(...) \
@ -50,9 +50,10 @@ ESP_MODEM_DECLARE_DCE_COMMAND(sync, command_result, 0) \
/**
* @brief Reads the operator name
* @param[out] operator name
* @param[out] access technology
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(get_operator_name, command_result, 1, STRING_OUT(p1, name)) \
ESP_MODEM_DECLARE_DCE_COMMAND(get_operator_name, command_result, 2, STRING_OUT(p1, name), INT_OUT(p2, act)) \
\
/**
* @brief Stores current user profile
@ -65,7 +66,15 @@ ESP_MODEM_DECLARE_DCE_COMMAND(store_profile, command_result, 0) \
* @param[in] pin Pin
* @return OK, FAIL or TIMEOUT
*/\
ESP_MODEM_DECLARE_DCE_COMMAND(set_pin, command_result, 1, STRING_IN(p1, pin)) \
ESP_MODEM_DECLARE_DCE_COMMAND(set_pin, command_result, 1, STRING_IN(p1, pin)) \
\
/**
* @brief Execute the supplied AT command
* @param[in] at AT command
* @param[out] out Command output string
* @return OK, FAIL or TIMEOUT
*/\
ESP_MODEM_DECLARE_DCE_COMMAND(at, command_result, 2, STRING_IN(p1, cmd), STRING_OUT(p2, out)) \
\
/**
* @brief Checks if the SIM needs a PIN
@ -89,7 +98,7 @@ ESP_MODEM_DECLARE_DCE_COMMAND(set_echo, command_result, 1, BOOL_IN(p1, echo_on))
ESP_MODEM_DECLARE_DCE_COMMAND(sms_txt_mode, command_result, 1, BOOL_IN(p1, txt)) \
\
/**
* @brief Sets the default (GSM) charater set
* @brief Sets the default (GSM) character set
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(sms_character_set, command_result, 0) \

View File

@ -22,6 +22,7 @@
.stop_bits = UART_STOP_BITS_1, \
.parity = UART_PARITY_DISABLE, \
.flow_control = ESP_MODEM_FLOW_CONTROL_NONE,\
.source_clk = UART_SCLK_APB, \
.baud_rate = 115200, \
.tx_io_num = 25, \
.rx_io_num = 26, \

View File

@ -17,4 +17,5 @@
typedef int uart_port_t;
typedef int uart_word_length_t;
typedef int uart_stop_bits_t;
typedef int uart_parity_t;
typedef int uart_parity_t;
typedef int uart_sclk_t;

View File

@ -122,20 +122,15 @@ extern "C" esp_err_t esp_modem_set_mode(esp_modem_dce_t *dce_wrap, esp_modem_dce
return ESP_ERR_INVALID_ARG;
}
if (mode == ESP_MODEM_MODE_DATA) {
dce_wrap->dce->set_data();
} else if (mode == ESP_MODEM_MODE_COMMAND) {
dce_wrap->dce->exit_data();
} else if (mode == ESP_MODEM_MODE_CMUX) {
if (dce_wrap->dce->set_mode(modem_mode::CMUX_MODE) &&
// automatically switch to data mode for the primary terminal
dce_wrap->dce->set_mode(modem_mode::DATA_MODE)) {
return ESP_OK;
}
return ESP_FAIL;
} else {
return ESP_ERR_NOT_SUPPORTED;
return dce_wrap->dce->set_mode(modem_mode::DATA_MODE) ? ESP_OK : ESP_FAIL;
}
return ESP_OK;
if (mode == ESP_MODEM_MODE_COMMAND) {
return dce_wrap->dce->set_mode(modem_mode::COMMAND_MODE) ? ESP_OK : ESP_FAIL;
}
if (mode == ESP_MODEM_MODE_CMUX) {
return dce_wrap->dce->set_mode(modem_mode::CMUX_MODE) ? ESP_OK : ESP_FAIL;
}
return ESP_ERR_NOT_SUPPORTED;
}
extern "C" esp_err_t esp_modem_read_pin(esp_modem_dce_t *dce_wrap, bool *pin)
@ -184,6 +179,20 @@ extern "C" esp_err_t esp_modem_set_pin(esp_modem_dce_t *dce_wrap, const char *pi
return command_response_to_esp_err(dce_wrap->dce->set_pin(pin_str));
}
extern "C" esp_err_t esp_modem_at(esp_modem_dce_t *dce_wrap, const char *at, char *p_out)
{
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
return ESP_ERR_INVALID_ARG;
}
std::string out;
std::string at_str(at);
auto ret = command_response_to_esp_err(dce_wrap->dce->at(at_str, out));
if ((p_out != NULL) && (!out.empty())) {
strlcpy(p_out, out.c_str(), ESP_MODEM_C_API_STR_MAX);
}
return ret;
}
extern "C" esp_err_t esp_modem_get_signal_quality(esp_modem_dce_t *dce_wrap, int *rssi, int *ber)
{
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
@ -379,3 +388,19 @@ extern "C" esp_err_t esp_modem_set_gnss_power_mode(esp_modem_dce_t *dce_wrap, in
}
return command_response_to_esp_err(dce_wrap->dce->set_gnss_power_mode(mode));
}
extern "C" esp_err_t esp_modem_reset(esp_modem_dce_t *dce_wrap)
{
return command_response_to_esp_err(dce_wrap->dce->reset());
}
extern "C" esp_err_t esp_modem_set_pdp_context(esp_modem_dce_t *dce_wrap, esp_modem_PdpContext_t *c_api_pdp)
{
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
return ESP_ERR_INVALID_ARG;
}
esp_modem::PdpContext pdp{c_api_pdp->apn};
pdp.context_id = c_api_pdp->context_id;
pdp.protocol_type = c_api_pdp->protocol_type;
return command_response_to_esp_err(dce_wrap->dce->set_pdp_context(pdp));
}

View File

@ -228,7 +228,7 @@ command_result set_flow_control(CommandableIf *t, int dce_flow, int dte_flow)
return generic_command_common(t, "AT+IFC=" + std::to_string(dce_flow) + ", " + std::to_string(dte_flow) + "\r");
}
command_result get_operator_name(CommandableIf *t, std::string &operator_name)
command_result get_operator_name(CommandableIf *t, std::string &operator_name, int &act)
{
ESP_LOGV(TAG, "%s", __func__ );
std::string_view out;
@ -239,9 +239,19 @@ command_result get_operator_name(CommandableIf *t, std::string &operator_name)
auto pos = out.find("+COPS");
auto property = 0;
while (pos != std::string::npos) {
// Looking for: +COPS: <mode>[, <format>[, <oper>]]
// Looking for: +COPS: <mode>[, <format>[, <oper>[, <act>]]]
if (property++ == 2) { // operator name is after second comma (as a 3rd property of COPS string)
operator_name = out.substr(++pos);
auto additional_comma = operator_name.find(','); // check for the optional ACT
if (additional_comma != std::string::npos && std::from_chars(operator_name.data() + additional_comma + 1,operator_name.data() + operator_name.length(), act).ec != std::errc::invalid_argument) {
operator_name = operator_name.substr(0, additional_comma);
}
// and strip quotes if present
auto quote1 = operator_name.find('"');
auto quote2 = operator_name.rfind('"');
if (quote1 != std::string::npos && quote2 != std::string::npos) {
operator_name = operator_name.substr(quote1+1, quote2-1);
}
return command_result::OK;
}
pos = out.find(',', ++pos);
@ -379,6 +389,13 @@ command_result set_pin(CommandableIf *t, const std::string &pin)
return generic_command_common(t, set_pin_command);
}
command_result at(CommandableIf *t, const std::string &cmd, std::string &out)
{
ESP_LOGV(TAG, "%s", __func__ );
std::string at_command = cmd + "\r";
return generic_get_string(t, at_command, out);
}
command_result get_signal_quality(CommandableIf *t, int &rssi, int &ber)
{
ESP_LOGV(TAG, "%s", __func__ );
@ -543,4 +560,4 @@ command_result set_gnss_power_mode_sim76xx(CommandableIf *t, int mode)
return generic_command_common(t, "AT+CGPS=" + std::to_string(mode) + "\r");
}
} // esp_modem::dce_commands
} // esp_modem::dce_commands

View File

@ -38,7 +38,7 @@ uart_resource::uart_resource(const esp_modem_uart_term_config *config, QueueHand
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_APB;
uart_config.source_clk = config->source_clk;
throw_if_esp_fail(uart_param_config(config->port_num, &uart_config), "config uart parameter failed");

View File

@ -34,6 +34,8 @@ int LoopbackTerm::write(uint8_t *data, size_t len)
response = "+CSQ: 123,456\n\r\nOK\r\n";
} else if (command.find("AT+CGMM\r") != std::string::npos) {
response = "0G Dummy Model\n\r\nOK\r\n";
} else if (command.find("AT+COPS?\r") != std::string::npos) {
response = "+COPS: 0,0,\"OperatorName\",5\n\r\nOK\r\n";
} else if (command.find("AT+CBC\r") != std::string::npos) {
response = is_bg96 ? "+CBC: 1,20,123456\r\r\n\r\nOK\r\n\n\r\n" :
"+CBC: 123.456V\r\r\n\r\nOK\r\n\n\r\n";

View File

@ -56,6 +56,14 @@ TEST_CASE("DCE AT parser", "[esp_modem]")
std::string model;
CHECK(dce->get_module_name(model) == command_result::OK);
CHECK(model == "0G Dummy Model");
std::string operator_name;
int act = 99;
CHECK(dce->get_operator_name(operator_name) == command_result::OK);
CHECK(operator_name == "OperatorName");
CHECK(dce->get_operator_name(operator_name, act) == command_result::OK);
CHECK(operator_name == "OperatorName");
CHECK(act == 5);
}

View File

@ -87,7 +87,7 @@ esp_err_t modem_init_network(esp_netif_t *netif)
return NetModule::init(netif);
}
void modem_start_network()
esp_err_t modem_start_network()
{
NetModule::start();
}

View File

@ -10,3 +10,4 @@ idf_component_register(SRCS "esp_websocket_client.c"
INCLUDE_DIRS "include"
REQUIRES lwip esp-tls tcp_transport http_parser
PRIV_REQUIRES esp_timer)
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")

View File

@ -0,0 +1,10 @@
menu "ESP WebSocket client"
config ESP_WS_CLIENT_ENABLE_DYNAMIC_BUFFER
bool "Enable websocket client dynamic buffer for send and receive data"
default n
help
Enable this option will reallocated buffer when send or receive data and free them when end of use.
This can save about 2 KB memory when no websocket data send and receive.
endmenu

View File

@ -54,6 +54,9 @@ static const char *TAG = "WEBSOCKET_CLIENT";
action; \
}
#define WS_OVER_TCP_SCHEME "ws"
#define WS_OVER_TLS_SCHEME "wss"
const static int STOPPED_BIT = BIT0;
const static int CLOSE_FRAME_SENT_BIT = BIT1; // Indicates that a close frame was sent by the client
// and we are waiting for the server to continue with clean close
@ -78,6 +81,15 @@ typedef struct {
char *headers;
int pingpong_timeout_sec;
size_t ping_interval_sec;
const char *cert;
size_t cert_len;
const char *client_cert;
size_t client_cert_len;
const char *client_key;
size_t client_key_len;
bool use_global_ca_store;
bool skip_cert_common_name_check;
esp_err_t (*crt_bundle_attach)(void *conf);
} websocket_config_storage_t;
typedef enum {
@ -122,6 +134,45 @@ static uint64_t _tick_get_ms(void)
return esp_timer_get_time()/1000;
}
static esp_err_t esp_websocket_new_buf(esp_websocket_client_handle_t client, bool is_tx)
{
#ifdef CONFIG_ESP_WS_CLIENT_ENABLE_DYNAMIC_BUFFER
if (is_tx) {
if (client->tx_buffer) {
free(client->tx_buffer);
}
client->tx_buffer = calloc(1, client->buffer_size);
ESP_WS_CLIENT_MEM_CHECK(TAG, client->tx_buffer, return ESP_ERR_NO_MEM);
} else {
if (client->rx_buffer) {
free(client->rx_buffer);
}
client->rx_buffer = calloc(1, client->buffer_size);
ESP_WS_CLIENT_MEM_CHECK(TAG, client->rx_buffer, return ESP_ERR_NO_MEM);
}
#endif
return ESP_OK;
}
static void esp_websocket_free_buf(esp_websocket_client_handle_t client, bool is_tx)
{
#ifdef CONFIG_ESP_WS_CLIENT_ENABLE_DYNAMIC_BUFFER
if (is_tx) {
if (client->tx_buffer) {
free(client->tx_buffer);
client->tx_buffer = NULL;
}
} else {
if (client->rx_buffer) {
free(client->rx_buffer);
client->rx_buffer = NULL;
}
}
#endif
}
static esp_err_t esp_websocket_client_dispatch_event(esp_websocket_client_handle_t client,
esp_websocket_event_id_t event,
const char *data,
@ -308,6 +359,93 @@ static esp_err_t set_websocket_transport_optional_settings(esp_websocket_client_
return ESP_ERR_INVALID_ARG;
}
static esp_err_t esp_websocket_client_create_transport(esp_websocket_client_handle_t client)
{
if (!client->config->scheme) {
ESP_LOGE(TAG, "No scheme found");
return ESP_FAIL;
}
if (client->transport_list) {
esp_transport_list_destroy(client->transport_list);
client->transport_list = NULL;
}
client->transport_list = esp_transport_list_init();
ESP_WS_CLIENT_MEM_CHECK(TAG, client->transport_list, return ESP_ERR_NO_MEM);
if (strcasecmp(client->config->scheme, WS_OVER_TCP_SCHEME) == 0) {
esp_transport_handle_t tcp = esp_transport_tcp_init();
ESP_WS_CLIENT_MEM_CHECK(TAG, tcp, return ESP_ERR_NO_MEM);
esp_transport_set_default_port(tcp, WEBSOCKET_TCP_DEFAULT_PORT);
esp_transport_list_add(client->transport_list, tcp, "_tcp"); // need to save to transport list, for cleanup
if (client->keep_alive_cfg.keep_alive_enable) {
esp_transport_tcp_set_keep_alive(tcp, &client->keep_alive_cfg);
}
if (client->if_name) {
esp_transport_tcp_set_interface_name(tcp, client->if_name);
}
esp_transport_handle_t ws = esp_transport_ws_init(tcp);
ESP_WS_CLIENT_MEM_CHECK(TAG, ws, return ESP_ERR_NO_MEM);
esp_transport_set_default_port(ws, WEBSOCKET_TCP_DEFAULT_PORT);
esp_transport_list_add(client->transport_list, ws, WS_OVER_TCP_SCHEME);
ESP_WS_CLIENT_ERR_OK_CHECK(TAG, set_websocket_transport_optional_settings(client, WS_OVER_TCP_SCHEME), return ESP_FAIL;)
} else if (strcasecmp(client->config->scheme, WS_OVER_TLS_SCHEME) == 0) {
esp_transport_handle_t ssl = esp_transport_ssl_init();
ESP_WS_CLIENT_MEM_CHECK(TAG, ssl, return ESP_ERR_NO_MEM);
esp_transport_set_default_port(ssl, WEBSOCKET_SSL_DEFAULT_PORT);
esp_transport_list_add(client->transport_list, ssl, "_ssl"); // need to save to transport list, for cleanup
if (client->config->use_global_ca_store == true) {
esp_transport_ssl_enable_global_ca_store(ssl);
} else if (client->config->cert) {
if (!client->config->cert_len) {
esp_transport_ssl_set_cert_data(ssl, client->config->cert, strlen(client->config->cert));
} else {
esp_transport_ssl_set_cert_data_der(ssl, client->config->cert, client->config->cert_len);
}
}
if (client->config->client_cert) {
if (!client->config->client_cert_len) {
esp_transport_ssl_set_client_cert_data(ssl, client->config->client_cert, strlen(client->config->client_cert));
} else {
esp_transport_ssl_set_client_cert_data_der(ssl, client->config->client_cert, client->config->client_cert_len);
}
}
if (client->config->client_key) {
if (!client->config->client_key_len) {
esp_transport_ssl_set_client_key_data(ssl, client->config->client_key, strlen(client->config->client_key));
} else {
esp_transport_ssl_set_client_key_data_der(ssl, client->config->client_key, client->config->client_key_len);
}
}
if (client->config->crt_bundle_attach) {
#ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
esp_transport_ssl_crt_bundle_attach(ssl, client->config->crt_bundle_attach);
#else //CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
ESP_LOGE(TAG, "crt_bundle_attach configured but not enabled in menuconfig: Please enable MBEDTLS_CERTIFICATE_BUNDLE option");
#endif
}
if (client->config->skip_cert_common_name_check) {
esp_transport_ssl_skip_common_name_check(ssl);
}
esp_transport_handle_t wss = esp_transport_ws_init(ssl);
ESP_WS_CLIENT_MEM_CHECK(TAG, wss, return ESP_ERR_NO_MEM);
esp_transport_set_default_port(wss, WEBSOCKET_SSL_DEFAULT_PORT);
esp_transport_list_add(client->transport_list, wss, WS_OVER_TLS_SCHEME);
ESP_WS_CLIENT_ERR_OK_CHECK(TAG, set_websocket_transport_optional_settings(client, WS_OVER_TLS_SCHEME), return ESP_FAIL;)
} else {
ESP_LOGE(TAG, "Not support this websocket scheme %s, only support %s and %s", client->config->scheme, WS_OVER_TCP_SCHEME, WS_OVER_TLS_SCHEME);
return ESP_FAIL;
}
return ESP_OK;
}
esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_client_config_t *config)
{
esp_websocket_client_handle_t client = calloc(1, sizeof(struct esp_websocket_client));
@ -343,83 +481,31 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie
client->config = calloc(1, sizeof(websocket_config_storage_t));
ESP_WS_CLIENT_MEM_CHECK(TAG, client->config, goto _websocket_init_fail);
client->transport_list = esp_transport_list_init();
ESP_WS_CLIENT_MEM_CHECK(TAG, client->transport_list, goto _websocket_init_fail);
esp_transport_handle_t tcp = esp_transport_tcp_init();
ESP_WS_CLIENT_MEM_CHECK(TAG, tcp, goto _websocket_init_fail);
esp_transport_set_default_port(tcp, WEBSOCKET_TCP_DEFAULT_PORT);
esp_transport_list_add(client->transport_list, tcp, "_tcp"); // need to save to transport list, for cleanup
esp_transport_tcp_set_keep_alive(tcp, &client->keep_alive_cfg);
esp_transport_tcp_set_interface_name(tcp, client->if_name);
esp_transport_handle_t ws = esp_transport_ws_init(tcp);
ESP_WS_CLIENT_MEM_CHECK(TAG, ws, goto _websocket_init_fail);
esp_transport_set_default_port(ws, WEBSOCKET_TCP_DEFAULT_PORT);
esp_transport_list_add(client->transport_list, ws, "ws");
if (config->transport == WEBSOCKET_TRANSPORT_OVER_TCP) {
asprintf(&client->config->scheme, "ws");
asprintf(&client->config->scheme, WS_OVER_TCP_SCHEME);
ESP_WS_CLIENT_MEM_CHECK(TAG, client->config->scheme, goto _websocket_init_fail);
} else if (config->transport == WEBSOCKET_TRANSPORT_OVER_SSL) {
asprintf(&client->config->scheme, WS_OVER_TLS_SCHEME);
ESP_WS_CLIENT_MEM_CHECK(TAG, client->config->scheme, goto _websocket_init_fail);
}
esp_transport_handle_t ssl = esp_transport_ssl_init();
ESP_WS_CLIENT_MEM_CHECK(TAG, ssl, goto _websocket_init_fail);
esp_transport_set_default_port(ssl, WEBSOCKET_SSL_DEFAULT_PORT);
esp_transport_list_add(client->transport_list, ssl, "_ssl"); // need to save to transport list, for cleanup
if (config->use_global_ca_store == true) {
esp_transport_ssl_enable_global_ca_store(ssl);
} else if (config->cert_pem) {
if (!config->cert_len) {
esp_transport_ssl_set_cert_data(ssl, config->cert_pem, strlen(config->cert_pem));
} else {
esp_transport_ssl_set_cert_data_der(ssl, config->cert_pem, config->cert_len);
}
}
if (config->client_cert) {
if (!config->client_cert_len) {
esp_transport_ssl_set_client_cert_data(ssl, config->client_cert, strlen(config->client_cert));
} else {
esp_transport_ssl_set_client_cert_data_der(ssl, config->client_cert, config->client_cert_len);
}
}
if (config->client_key) {
if (!config->client_key_len) {
esp_transport_ssl_set_client_key_data(ssl, config->client_key, strlen(config->client_key));
} else {
esp_transport_ssl_set_client_key_data_der(ssl, config->client_key, config->client_key_len);
}
}
if (config->crt_bundle_attach) {
#ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
esp_transport_ssl_crt_bundle_attach(ssl, config->crt_bundle_attach);
#else //CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
ESP_LOGE(TAG, "crt_bundle_attach configured but not enabled in menuconfig: Please enable MBEDTLS_CERTIFICATE_BUNDLE option");
#endif
}
if (config->skip_cert_common_name_check) {
esp_transport_ssl_skip_common_name_check(ssl);
}
if (config->reconnect_timeout_ms <= 0) {
client->wait_timeout_ms = WEBSOCKET_RECONNECT_TIMEOUT_MS;
ESP_LOGW(TAG, "`reconnect_timeout_ms` is not set, or it is less than or equal to zero, using default time out %d (milliseconds)", WEBSOCKET_RECONNECT_TIMEOUT_MS);
} else {
client->wait_timeout_ms = config->reconnect_timeout_ms;
}
esp_transport_handle_t wss = esp_transport_ws_init(ssl);
ESP_WS_CLIENT_MEM_CHECK(TAG, wss, goto _websocket_init_fail);
esp_transport_set_default_port(wss, WEBSOCKET_SSL_DEFAULT_PORT);
esp_transport_list_add(client->transport_list, wss, "wss");
if (config->transport == WEBSOCKET_TRANSPORT_OVER_SSL) {
asprintf(&client->config->scheme, "wss");
ESP_WS_CLIENT_MEM_CHECK(TAG, client->config->scheme, goto _websocket_init_fail);
}
// configure ssl related parameters
client->config->use_global_ca_store = config->use_global_ca_store;
client->config->cert = config->cert_pem;
client->config->cert_len = config->cert_len;
client->config->client_cert = config->client_cert;
client->config->client_cert_len = config->client_cert_len;
client->config->client_key = config->client_key;
client->config->client_key_len = config->client_key_len;
client->config->skip_cert_common_name_check = config->skip_cert_common_name_check;
client->config->crt_bundle_attach = config->crt_bundle_attach;
if (config->uri) {
if (esp_websocket_client_set_uri(client, config->uri) != ESP_OK) {
@ -434,13 +520,10 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie
}
if (client->config->scheme == NULL) {
asprintf(&client->config->scheme, "ws");
asprintf(&client->config->scheme, WS_OVER_TCP_SCHEME);
ESP_WS_CLIENT_MEM_CHECK(TAG, client->config->scheme, goto _websocket_init_fail);
}
ESP_WS_CLIENT_ERR_OK_CHECK(TAG, set_websocket_transport_optional_settings(client, "ws"), goto _websocket_init_fail;)
ESP_WS_CLIENT_ERR_OK_CHECK(TAG, set_websocket_transport_optional_settings(client, "wss"), goto _websocket_init_fail;)
client->keepalive_tick_ms = _tick_get_ms();
client->reconnect_tick_ms = _tick_get_ms();
client->ping_tick_ms = _tick_get_ms();
@ -450,6 +533,7 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie
if (buffer_size <= 0) {
buffer_size = WEBSOCKET_BUFFER_SIZE_BYTE;
}
#ifndef CONFIG_ESP_WS_CLIENT_ENABLE_DYNAMIC_BUFFER
client->rx_buffer = malloc(buffer_size);
ESP_WS_CLIENT_MEM_CHECK(TAG, client->rx_buffer, {
goto _websocket_init_fail;
@ -458,6 +542,7 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie
ESP_WS_CLIENT_MEM_CHECK(TAG, client->tx_buffer, {
goto _websocket_init_fail;
});
#endif
client->status_bits = xEventGroupCreate();
ESP_WS_CLIENT_MEM_CHECK(TAG, client->status_bits, {
goto _websocket_init_fail;
@ -566,10 +651,15 @@ static esp_err_t esp_websocket_client_recv(esp_websocket_client_handle_t client)
{
int rlen;
client->payload_offset = 0;
if (esp_websocket_new_buf(client, false) != ESP_OK) {
ESP_LOGE(TAG, "Failed to setup rx buffer");
return ESP_FAIL;
}
do {
rlen = esp_transport_read(client->transport, client->rx_buffer, client->buffer_size, client->config->network_timeout_ms);
if (rlen < 0) {
ESP_LOGE(TAG, "Error read data");
esp_websocket_free_buf(client, false);
return ESP_FAIL;
}
client->payload_len = esp_transport_ws_get_read_payload_len(client->transport);
@ -578,6 +668,7 @@ static esp_err_t esp_websocket_client_recv(esp_websocket_client_handle_t client)
if (rlen == 0 && client->last_opcode == WS_TRANSPORT_OPCODES_NONE ) {
ESP_LOGV(TAG, "esp_transport_read timeouts");
esp_websocket_free_buf(client, false);
return ESP_OK;
}
@ -598,7 +689,7 @@ static esp_err_t esp_websocket_client_recv(esp_websocket_client_handle_t client)
ESP_LOGD(TAG, "Received close frame");
client->state = WEBSOCKET_STATE_CLOSING;
}
esp_websocket_free_buf(client, false);
return ESP_OK;
}
@ -757,6 +848,11 @@ esp_err_t esp_websocket_client_start(esp_websocket_client_handle_t client)
ESP_LOGE(TAG, "The client has started");
return ESP_FAIL;
}
if (esp_websocket_client_create_transport(client) != ESP_OK) {
ESP_LOGE(TAG, "Failed to create websocket transport");
return ESP_FAIL;
}
if (xTaskCreate(esp_websocket_client_task, "websocket_task", client->config->task_stack, client, client->config->task_prio, &client->task_handle) != pdTRUE) {
ESP_LOGE(TAG, "Error create websocket task");
return ESP_FAIL;
@ -890,6 +986,10 @@ static int esp_websocket_client_send_with_opcode(esp_websocket_client_handle_t c
ESP_LOGE(TAG, "Invalid transport");
goto unlock_and_return;
}
if (esp_websocket_new_buf(client, true) != ESP_OK) {
ESP_LOGE(TAG, "Failed to setup tx buffer");
goto unlock_and_return;
}
uint32_t current_opcode = opcode;
while (widx < len || current_opcode) { // allow for sending "current_opcode" only message with len==0
if (need_write > client->buffer_size) {
@ -904,6 +1004,7 @@ static int esp_websocket_client_send_with_opcode(esp_websocket_client_handle_t c
if (wlen < 0 || (wlen == 0 && need_write != 0)) {
ret = wlen;
ESP_LOGE(TAG, "Network error: esp_transport_write() returned %d, errno=%d", ret, errno);
esp_websocket_free_buf(client, true);
esp_websocket_client_abort_connection(client);
goto unlock_and_return;
}
@ -913,6 +1014,7 @@ static int esp_websocket_client_send_with_opcode(esp_websocket_client_handle_t c
}
ret = widx;
esp_websocket_free_buf(client, true);
unlock_and_return:
xSemaphoreGiveRecursive(client->lock);
return ret;

View File

@ -1,2 +1,3 @@
idf_component_register(SRCS "websocket_example.c"
INCLUDE_DIRS ".")
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")

View File

@ -1,4 +1,4 @@
version: "0.0.1"
version: "0.0.2"
description: esp websocket client
dependencies:
idf:

View File

@ -20,6 +20,7 @@ idf_component_register(
PRIV_INCLUDE_DIRS "private_include"
REQUIRES ${dependencies}
PRIV_REQUIRES ${private_dependencies})
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
if(CONFIG_ETH_ENABLED)
idf_component_optional_requires(PRIVATE esp_eth)

View File

@ -1,2 +1,3 @@
idf_component_register(SRCS "mdns_example_main.c"
INCLUDE_DIRS ".")
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")

View File

@ -1,4 +1,4 @@
version: "1.0.3"
version: "1.0.4"
description: mDNS
dependencies:
idf:

View File

@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.5)
# (Not part of the boilerplate)
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
set(EXTRA_COMPONENT_DIRS "../../../../common_components/protocol_examples_common")
set(EXTRA_COMPONENT_DIRS ../../ ../../../../common_components/protocol_examples_common)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)