Compare commits

..

42 Commits

Author SHA1 Message Date
469f953b28 esp_modem: updated package version to 0.1.19 2022-08-18 15:59:48 +04:00
381eb314dc Merge pull request #93 from gabsuren/feature/websocket_json_example
websocket: updated example to show how to transfer json data
2022-08-15 14:50:48 +02:00
1ffc20c8e3 Merge pull request #105 from gabsuren/websocket/version_change_03
esp_websocket_client: upgraded package version to 0.0.3 (IDFGH-7986)
2022-08-05 12:37:40 +02:00
5c245dbdb5 esp_websocket_client: Upgraded version to 0.0.3 2022-08-05 10:21:41 +04:00
134a9a9eee Revert "bugfix: mdns IPv6 address convert error"
This reverts commit 238ee96783.
2022-08-04 15:52:40 +04:00
010f98ca80 Merge pull request #99 from gabsuren/bugfix/fix_ci_build
CI: Fix build issues
2022-07-29 11:10:11 +02:00
6e4e4fab1d CI: Fix build issues 2022-07-28 22:47:53 +04:00
b6852a0588 Merge pull request #96 from gjc13/bugfix/aa-bit-receive
fix(mdns): ignore authoritative flag on reception (IDFGH-7891)
2022-07-25 08:26:10 +02:00
415e04a55f fix(mdns): ignore authoritative flag on reception 2022-07-22 22:25:08 +08:00
3456781494 websocket: updated example to show json data transfer 2022-07-21 16:04:58 +04:00
d1129f3d19 esp_err_to_name (IDFGH-7793) (#78)
fix(esp-modem): Use err_to_name to log error message on error
2022-07-18 17:08:15 +02:00
973837dd66 Merge pull request #92 from david-cermak/feat/mdns_explicit_deps
feat(mdns): Define explicit dependencies on esp-wifi
2022-07-18 17:05:44 +02:00
36de9afe0c feat(mdns): Define explicit dependencies on esp-wifi 2022-07-18 09:49:03 +02:00
0d5081b841 Merge pull request #81 from lcj446068124/bugfix/mdns_ipv6_convert_error
bugfix: mdns IPv6 address convert error (IDFGH-7772)
2022-07-15 08:13:06 +02:00
85c7282641 Merge pull request #91 from Lapshin/feature/bump-versions
Bump asio/mdns/esp_websocket_client versions
2022-07-15 07:13:35 +02:00
57afa38f49 Bump asio/mdns/esp_websocket_client versions
Update components version afrer change d66f9dc158
2022-07-14 20:04:28 +04:00
238ee96783 bugfix: mdns IPv6 address convert error
In this fix, we manually convert esp_ip_addr_t to ip_addr_t.
2022-07-14 23:40:08 +08: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
56 changed files with 678 additions and 323 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@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/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

@ -1,4 +1,4 @@
idf_component_register(SRCS "connect.c" "stdin_out.c" "addr_from_stdin.c"
INCLUDE_DIRS "include"
PRIV_REQUIRES esp_netif driver esp_eth
PRIV_REQUIRES esp_netif driver esp_eth esp_wifi vfs
)

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

@ -11,9 +11,10 @@ else()
src/esp_modem_uart.cpp
src/esp_modem_term_uart.cpp
src/esp_modem_netif.cpp)
set(dependencies driver)
set(dependencies driver esp_event esp_netif)
endif()
set(srcs ${platform_srcs}
"src/esp_modem_dte.cpp"
"src/esp_modem_dce.cpp"
@ -34,13 +35,17 @@ idf_component_register(SRCS "${srcs}"
PRIV_INCLUDE_DIRS private_include
REQUIRES ${dependencies})
set_target_properties(${COMPONENT_LIB} PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS ON
)
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

@ -7,3 +7,4 @@ endif()
idf_component_register(SRCS "ap_to_pppos.c"
${NETWORK_DCE}
INCLUDE_DIRS ".")
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

@ -22,11 +22,13 @@ static EventGroupHandle_t event_group = NULL;
static const int CONNECT_BIT = BIT0;
static const int GOT_DATA_BIT = BIT2;
static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id);
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
int msg_id;
switch (event->event_id) {
switch ((esp_mqtt_event_id_t)event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
msg_id = esp_mqtt_client_subscribe(client, "/topic/esp-pppos", 0);
@ -59,7 +61,6 @@ static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
ESP_LOGI(TAG, "MQTT other event id: %d", event->event_id);
break;
}
return ESP_OK;
}
static void on_ppp_changed(void *arg, esp_event_base_t event_base,
@ -200,11 +201,17 @@ void app_main(void)
/* Wait for IP address */
xEventGroupWaitBits(event_group, CONNECT_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
/* Config MQTT */
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
esp_mqtt_client_config_t mqtt_config = {
.broker.address.uri = BROKER_URL,
};
#else
esp_mqtt_client_config_t mqtt_config = {
.uri = BROKER_URL,
.event_handle = mqtt_event_handler,
};
#endif
esp_mqtt_client_handle_t mqtt_client = esp_mqtt_client_init(&mqtt_config);
esp_mqtt_client_register_event(mqtt_client, ESP_EVENT_ANY_ID, 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);

View File

@ -26,7 +26,11 @@ struct MqttClientHandle {
explicit MqttClientHandle(const std::string &uri)
{
esp_mqtt_client_config_t config = { };
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
config.broker.address.uri = uri.c_str();
#else
config.uri = uri.c_str();
#endif
client = esp_mqtt_client_init(&config);
esp_mqtt_client_register_event(client, MQTT_EVENT_ANY, mqtt_event_handler, this);
}

View File

@ -1,4 +1,4 @@
version: "0.1.17"
version: "0.1.19"
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

@ -1,2 +1,3 @@
idf_component_register(INCLUDE_DIRS include
idf_component_register(SRCS "esp_err_to_name.c"
INCLUDE_DIRS include
REQUIRES esp_netif_linux esp_event_mock)

View File

@ -0,0 +1,14 @@
/*
* SPDX-FileCopyrightText: Franz Hoepfinger
*
* SPDX-License-Identifier: Apache-2.0
*/
static const char esp_unknown_msg[] = "ERROR";
const char *esp_err_to_name(int code)
{
return esp_unknown_msg;
}

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

@ -25,3 +25,11 @@ typedef int esp_err_t;
#define ESP_ERR_NOT_FOUND 0x105
#define ESP_ERR_NOT_SUPPORTED 0x106
#define ESP_ERR_TIMEOUT 0x107
#ifdef __cplusplus
extern "C" {
#endif
const char *esp_err_to_name(int code);
#ifdef __cplusplus
}
#endif

View File

@ -22,7 +22,7 @@
action; \
} catch (::esp_modem::esp_err_exception& e) { \
esp_err_t err = e.get_err_t(); \
ESP_LOGE(TAG, "%s: Exception caught with ESP err_code=%d", __func__, err); \
ESP_LOGE(TAG, "%s: Exception caught with ESP err_code=%d %s", __func__, err, esp_err_to_name(err)); \
ESP_LOGE(TAG, "%s", e.what()); \
action; \
}

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

@ -9,4 +9,5 @@ endif()
idf_component_register(SRCS "esp_websocket_client.c"
INCLUDE_DIRS "include"
REQUIRES lwip esp-tls tcp_transport http_parser
PRIV_REQUIRES esp_timer)
PRIV_REQUIRES esp_timer esp_event)
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

@ -23,6 +23,7 @@
#include "esp_log.h"
#include "esp_websocket_client.h"
#include "esp_event.h"
#include <cJSON.h>
#define NO_DATA_TIMEOUT_SEC 5
@ -74,6 +75,19 @@ static void websocket_event_handler(void *handler_args, esp_event_base_t base, i
} else {
ESP_LOGW(TAG, "Received=%.*s", data->data_len, (char *)data->data_ptr);
}
// If received data contains json structure it succeed to parse
cJSON *root = cJSON_Parse(data->data_ptr);
if (root) {
for (int i = 0 ; i < cJSON_GetArraySize(root) ; i++) {
cJSON *elem = cJSON_GetArrayItem(root, i);
cJSON *id = cJSON_GetObjectItem(elem, "id");
cJSON *name = cJSON_GetObjectItem(elem, "name");
ESP_LOGW(TAG, "Json={'id': '%s', 'name': '%s'}", id->valuestring, name->valuestring);
}
cJSON_Delete(root);
}
ESP_LOGW(TAG, "Total payload length=%d, data_len=%d, current payload offset=%d\r\n", data->payload_len, data->data_len, data->payload_offset);
xTimerReset(shutdown_signal_timer, portMAX_DELAY);

View File

@ -6,6 +6,8 @@ import string
from threading import Event, Thread
import pytest
import sys
import json
import time
from SimpleWebSocketServer import SimpleWebSocketServer, WebSocket
from pytest_embedded import Dut
@ -81,8 +83,33 @@ def test_examples_protocol_websocket(dut):
def test_close(dut):
code = dut.expect(re.compile(b'WEBSOCKET: Received closed message with code=(\\d*)'))[0]
print('Received close frame with code {}'.format(code))
def test_json(dut, websocket):
json_string = """
[
{
"id":"1",
"name":"user1"
},
{
"id":"2",
"name":"user2"
}
]
"""
websocket.send_data(json_string)
data = json.loads(json_string)
match = dut.expect(re.compile(b'Json=([a-zA-Z0-9]*).*')).group(0).decode()[5:]
if match == str(data[0]):
print('Sent message and received message are equal')
else:
raise ValueError('DUT received string do not match sent string, \nexpected: {}\nwith length {}\
\nreceived: {}\nwith length {}'.format(data[0], len(data[0]), match, len(match)))
def test_recv_long_msg(dut, websocket, msg_len, repeats):
send_msg = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(msg_len))
for _ in range(repeats):
@ -121,6 +148,7 @@ def test_examples_protocol_websocket(dut):
test_echo(dut)
# Message length should exceed DUT's buffer size to test fragmentation, default is 1024 byte
test_recv_long_msg(dut, ws, 2000, 3)
test_json(dut, ws)
test_close(dut)
else:
print('DUT connecting to {}'.format(uri))

View File

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

View File

@ -10,7 +10,7 @@ if(${target} STREQUAL "linux")
set(srcs "mdns.c" ${MDNS_NETWORKING})
else()
set(dependencies lwip console esp_netif)
set(private_dependencies esp_timer)
set(private_dependencies esp_timer esp_wifi)
set(srcs "mdns.c" ${MDNS_NETWORKING} "mdns_console.c")
endif()
@ -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.5"
description: mDNS
dependencies:
idf:

View File

@ -20,6 +20,8 @@
#if CONFIG_ETH_ENABLED
#include "esp_eth.h"
#endif
#include "esp_wifi.h"
#ifdef MDNS_ENABLE_DEBUG
void mdns_debug_packet(const uint8_t * data, size_t len);
@ -3497,7 +3499,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet)
service = _mdns_get_service_item(name->service, name->proto, NULL);
}
} else {
if (!parsed_packet->authoritative || record_type == MDNS_NS) {
if (!header.flags.qr || record_type == MDNS_NS) {
//skip this record
continue;
}

View File

@ -338,11 +338,15 @@ size_t _mdns_udp_pcb_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, c
}
memcpy((uint8_t *)pbt->payload, data, len);
ip_addr_t ip_add_copy;
ip_add_copy.type = ip->type;
memcpy(&(ip_add_copy.u_addr),&(ip->u_addr),sizeof(ip_add_copy.u_addr));
mdns_api_call_t msg = {
.tcpip_if = tcpip_if,
.ip_protocol = ip_protocol,
.pbt = pbt,
.ip = (ip_addr_t *)ip,
.ip = &ip_add_copy,
.port = port
};
tcpip_api_call(_mdns_udp_pcb_write_api, &msg.call);

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)

View File

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