Compare commits

...

47 Commits

Author SHA1 Message Date
04c711f757 esp_modem: Move common C definitions in to separate header
Separate header for C API created.
It can be used by C DTE extensions.
2022-09-30 11:41:34 +02:00
467fec5c9b Merge pull request #141 from gabsuren/examples/asio_examples_integrationn
ASIO: Example tests integration
2022-09-30 10:38:38 +02:00
5193ebc6ea ASIO: Example tests integration 2022-09-27 16:09:50 +04:00
7310a7a0bc Merge pull request #144 from jonathandreyer/feature/modem_cmux_exit_example
esp_modem: Exit CMUX after end of example
2022-09-20 07:37:21 +02:00
accf9244ca Minor formatting fix and spelling 2022-09-19 17:11:57 +02:00
290197c210 feat(esp-modem): Add exit PPP in example 2022-09-19 17:07:49 +02:00
b8d1e58778 Merge pull request #116 from gabsuren/examples/mdns_examples_integration
mdns: Example tests integration
2022-09-15 11:41:58 +02:00
cc4d33d871 Merge pull request #125 from david-cermak/bugfix/modem_command_race
fix(esp_modem): DTE command race of timeout vs reply's signal
2022-09-14 14:46:06 +02:00
ef0e48a678 extended the modem_console example. (#120)
Co-authored-by: Franz Höpfinger <krone-trailer@franzhoepfinger.de>
Co-authored-by: david-cermak <38914379+david-cermak@users.noreply.github.com>
2022-09-14 14:05:25 +02:00
187ef7676e update(esp_modem): Bump component version 2022-09-14 13:52:00 +02:00
a8714730fb fix(esp_modem): DTE command race of timeout vs reply's signal
Race condtion:
* First command timeouted, but the reply came just after evaluation and
set signal variable to GOT_LINE
* Second command should timeout too, but a consistency check validates
that it timeouted and at the same time GOT_LINE (from previous step) and
throws an exception

STR:
* Revert change in esp_modem_dte.cpp
* Run TEST_CASE("DTE command races", "[esp_modem]")

Closes https://github.com/espressif/esp-protocols/issues/110
2022-09-14 13:50:22 +02:00
d2f519f9e5 Merge pull request #139 from david-cermak/bugfix/modem_get_operator_name_with_act
fix(esp_modem): Make get_operator_name() return also ACT value
2022-09-14 13:46:28 +02:00
a045c1c885 mdns: Example tests integration 2022-09-14 10:58:31 +04:00
543521a220 Merge pull request #123 from thorrak/hygiene/TTL
Replace hardcoded TTL values with named defines (IDFGH-8113)
2022-09-09 15:13:22 +02:00
85be67e708 Merge pull request #126 from jonathandreyer/bugfix/ci-partial-disable
CI: Disable some runs on forks (which are not able to access to secrets) (IDFGH-8152)
2022-09-09 15:11:41 +02:00
5b1b2cce75 Disable specific runs..
.. which are not access to secrets
2022-09-09 14:30:37 +02:00
1029078541 fix(esp_modem): Correct timeouts for certain commands
And adds an explicit timeout parameter to the esp_modem_at()

Closes https://github.com/espressif/esp-protocols/issues/129
2022-09-09 11:23:21 +02:00
0015e5411c fix(esp_modem): Make get_operator_name() return also ACT value
Closes https://github.com/espressif/esp-protocols/issues/128
2022-09-09 10:54:55 +02:00
65b64e1fc1 Merge pull request #138 from tore-espressif/fix/idf_version_check
esp_modem: Fix IDF version resolution (IDFGH-8271)
2022-09-09 10:13:40 +02:00
d07237b2ce esp_modem: Fix IDF version resolution 2022-09-09 09:31:26 +02:00
3c65fde2a7 Merge pull request #117 from david-cermak/bugfix/mdns_add_service_fail_if_nohostname
mdns: Fix add_service() to report error if no hostname has been set
2022-09-08 12:59:08 +02:00
35833d2730 Merge pull request #131 from tore-espressif/feature/esp_modem/err_cb
esp_modem: Expose set_error_cb method
2022-09-08 12:54:13 +02:00
bbb4b7e686 Merge pull request #135 from mahavirj/bugfix/fix_broken_ipv4_only_build
mdns: fix IPV4 only build and also update CI configuration
2022-09-07 22:10:18 +05:30
64e31dae48 ci: fix issue with cryptography package installation 2022-09-07 13:58:10 +05:30
63ce3a5d59 protocol_examples_common: fix build for SPI_ETHERNET case with IDF v5.x 2022-09-07 12:52:39 +05:30
5dd138c883 ci: remove sdkconfig before starting new config based build 2022-09-07 12:52:39 +05:30
088f7ac3f8 mdns: bump up the component version 2022-09-07 09:44:33 +05:30
e079f8ba98 mdns: fix IPV4 only build and also update CI configuration
Earlier commit 48c157bc46 had typo
regarding variable name. This was not caught in CI because IPV6
was not really getting disabled due to an indirect dependency
of `CONFIG_EXAMPLE_CONNECT_IPV6`.

This commit fixes both the problems.
2022-09-07 09:43:46 +05:30
ff2b0734ea Merge pull request #132 from mahavirj/bugfix/build_issue_with_ipv6_disabled
mdns: fix build issue with CONFIG_LWIP_IPV6 disabled
2022-09-06 21:28:33 +05:30
330332a0fb mdns: add test configuration for IPV6 disabled build 2022-09-05 13:24:14 +05:30
48c157bc46 mdns: fix build issue with CONFIG_LWIP_IPV6 disabled 2022-09-02 16:13:17 +05:30
98bf3efeb6 esp_modem: Fix format warnings
Closes https://github.com/espressif/esp-protocols/issues/79
2022-09-02 10:02:34 +02:00
ae8479c77e esp_modem: Expose set_error_cb method 2022-09-02 09:17:49 +02:00
444fae9066 Merge pull request #115 from david-cermak/bugfix/cmux_exit_bg96
fix(esp_modem): Correct exit of CMUX mode
2022-08-29 16:13:31 +02:00
bb4c002841 Replace hardcoded TTL values with named defines
- Replaces hardcoded PTR "half-TTL" with `MDNS_ANSWER_PTR_TTL/2` (defined in mdns_private.h)
- Replaces hardcoded TXT "half-TTL" with `MDNS_ANSWER_TXT_TTL/2` (defined in mdns_private.h)
2022-08-23 08:44:36 -04:00
656ab21c9b mdns: Fix add_service() to report error if no-hostname 2022-08-19 18:47:47 +02:00
2099434b3f fix(esp_modem): Correct exit of CMUX mode
* Fix DISC message's control field (0xFF->0xFE) to keep Poll bit cleared
* Accept UIH resp on DISC for both (0xFF, 0xFE) ignoring P/F bit
* Fix timeout processing when handling DISC message

Closes https://github.com/espressif/esp-protocols/issues/103
2022-08-19 11:45:59 +02:00
8f00fc182a Merge pull request #114 from david-cermak/bugfix/dns-header-bit-order
mdns: fix bit order issue in DNS header flags (updated)
2022-08-19 09:03:04 +02:00
d74c296182 fix(mdns): Example makefile to add only mdns as extra comps 2022-08-18 16:41:38 +02:00
c4e85bd099 mdns: fix bit order issue in DNS header flags
The bit field in the header flags does not match its intended order on
little endian machines. The PR removes the bit field and uses bit
operations instead.
2022-08-18 16:39:38 +02:00
85ba60e405 Merge pull request #88 from david-cermak/bugfix/modem_better_exception_report
fix(esp-modem): Add filename/line info to exception message
2022-08-18 15:27:47 +02:00
89e1bd27b3 fix(esp-modem): Add filename/line info to exception message
This is useful if exceptions are enabled, but caught internally on C++ API boundary
2022-08-18 14:52:21 +02:00
341fcb0f40 Merge pull request #112 from gabsuren/bugfix/updated_esp_modem_package
esp_modem: updated package version to 0.1.19 (IDFGH-8032)
2022-08-18 14:47:47 +02:00
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
3456781494 websocket: updated example to show json data transfer 2022-07-21 16:04:58 +04:00
59 changed files with 882 additions and 307 deletions

View File

@ -9,6 +9,8 @@ jobs:
docs_build:
name: Docs-Build-And-Upload
runs-on: ubuntu-latest
# Skip running on forks since it won't have access to secrets
if: github.repository == 'espressif/esp-protocols'
steps:
- name: Checkout esp-protocols

View File

@ -39,8 +39,8 @@ jobs:
strategy:
matrix:
idf_ver: ["latest"]
idf_target: ["esp32", "esp32s2", "esp32c3"]
idf_target: ["esp32", "esp32s2", "esp32c3"]
config: ["eth_custom_netif", "eth_def", "eth_no_ipv6", "eth_socket"]
runs-on: ubuntu-20.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
@ -48,26 +48,41 @@ jobs:
uses: actions/checkout@v3
with:
submodules: recursive
path: esp-protocols
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }} for ${{ matrix.config }}
env:
IDF_TARGET: ${{ matrix.idf_target }}
shell: bash
working-directory: components/mdns/examples/
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/
rm -rf sdkconfig sdkconfig.defaults build build_${{ matrix.config }}
cat sdkconfig.ci.${{ matrix.config }} >> sdkconfig.defaults
idf.py set-target ${{ matrix.idf_target }}
idf.py build
mv build build_${{ matrix.config }}
- name: Merge binaries with IDF-${{ matrix.idf_ver }} for ${{ matrix.config }}
working-directory: components/mdns/examples
env:
IDF_TARGET: ${{ matrix.idf_target }}
shell: bash
run: |
. ${IDF_PATH}/export.sh
cd build_${{ matrix.config }}
esptool.py --chip ${{ matrix.idf_target }} merge_bin --fill-flash-size 4MB -o flash_image.bin @flash_args
cd ../
cat build_${{ matrix.config }}/config/sdkconfig.json
- uses: actions/upload-artifact@v2
with:
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.config }}
path: |
components/mdns/examples/build_${{ matrix.config }}/bootloader/bootloader.bin
components/mdns/examples/build_${{ matrix.config }}/partition_table/partition-table.bin
components/mdns/examples/build_${{ matrix.config }}/*.bin
components/mdns/examples/build_${{ matrix.config }}/*.elf
components/mdns/examples/build_${{ matrix.config }}/flasher_args.json
components/mdns/examples/build_${{ matrix.config }}/config/sdkconfig.h
components/mdns/examples/build_${{ matrix.config }}/config/sdkconfig.json
if-no-files-found: error
build_asio:
strategy:
@ -75,7 +90,6 @@ jobs:
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:
@ -83,23 +97,43 @@ jobs:
uses: actions/checkout@v3
with:
submodules: recursive
path: esp-protocols
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
working-directory: components/asio/examples/${{ matrix.example }}
env:
IDF_TARGET: ${{ matrix.idf_target }}
shell: bash
run: |
. ${IDF_PATH}/export.sh
cd $GITHUB_WORKSPACE/esp-protocols/components/asio/examples/${{ matrix.example }}
test -f sdkconfig.ci && cat sdkconfig.ci >> sdkconfig.defaults || echo "No sdkconfig.ci"
idf.py set-target ${{ matrix.idf_target }}
idf.py build
- name: Merge binaries with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }} for ${{ matrix.example }}
working-directory: components/asio/examples/${{ matrix.example }}/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@v3
with:
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.example }}
path: |
components/asio/examples/${{ matrix.example }}/build/bootloader/bootloader.bin
components/asio/examples/${{ matrix.example }}/build//partition_table/partition-table.bin
components/asio/examples/${{ matrix.example }}/build/*.bin
components/asio/examples/${{ matrix.example }}/build/*.elf
components/asio/examples/${{ matrix.example }}/build/flasher_args.json
components/asio/examples/${{ matrix.example }}/build/config/sdkconfig.h
components/asio/examples/${{ matrix.example }}/build/config/sdkconfig.json
if-no-files-found: error
build_websocket:
strategy:
matrix:
idf_ver: ["latest"]
idf_target: ["esp32"]
runs-on: ubuntu-20.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
@ -127,7 +161,14 @@ jobs:
- uses: actions/upload-artifact@v2
with:
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}
path: components/esp_websocket_client/examples/build/
path: |
components/esp_websocket_client/examples/build/bootloader/bootloader.bin
components/esp_websocket_client/examples/build/partition_table/partition-table.bin
components/esp_websocket_client/examples/build/*.bin
components/esp_websocket_client/examples/build/*.elf
components/esp_websocket_client/examples/build/flasher_args.json
components/esp_websocket_client/examples/build/config/sdkconfig.h
components/esp_websocket_client/examples/build/config/sdkconfig.json
if-no-files-found: error
run-target:
@ -141,6 +182,8 @@ jobs:
runs-on:
- self-hosted
- ESP32-ETHERNET-KIT
# Skip running on forks since it won't have access to secrets
if: github.repository == 'espressif/esp-protocols'
container:
image: python:3.7-buster
options: --privileged # Privileged mode has access to serial ports
@ -154,16 +197,98 @@ jobs:
env:
PIP_EXTRA_INDEX_URL: "https://www.piwheels.org/simple"
run: |
pip install -r $GITHUB_WORKSPACE/components/esp_websocket_client/examples/requirements.txt
pip install --only-binary cryptography --extra-index-url https://dl.espressif.com/pypi/ -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 }}
pytest --log-cli-level DEBUG --junit-xml=./examples_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
path: components/esp_websocket_client/examples/*.xml
run-target-mdns:
strategy:
matrix:
idf_ver: ["latest"]
idf_target: ["esp32"]
config: ["eth_custom_netif", "eth_def", "eth_no_ipv6", "eth_socket"]
name: Run mDNS Example Test on target
needs: build_mdns
runs-on:
- self-hosted
- ESP32-ETHERNET-KIT
# Skip running on forks since it won't have access to secrets
if: github.repository == 'espressif/esp-protocols'
steps:
- name: Clear repository
run: sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE
- uses: actions/checkout@v3
- uses: actions/download-artifact@v2
with:
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.config }}
path: components/mdns/examples/build_${{ matrix.config }}
- name: Install Python packages
env:
PIP_EXTRA_INDEX_URL: "https://www.piwheels.org/simple"
run: |
sudo apt-get install -y dnsutils
- name: Download Example Test to target ${{ matrix.config }}
run: |
python -m esptool --chip ${{ matrix.idf_target }} write_flash 0x0 components/mdns/examples/build_${{ matrix.config }}/flash_image.bin
- name: Run Example Test on target ${{ matrix.config }}
working-directory: components/mdns/examples
run: |
rm -rf build
mv build_${{ matrix.config }} build
cat sdkconfig.ci.${{ matrix.config }} >> sdkconfig.defaults
python -m pytest --log-cli-level DEBUG --junit-xml=./examples_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.config }}.xml --target=${{ matrix.idf_target }}
rm -rf build sdkconfig.defaults
- uses: actions/upload-artifact@v2
if: always()
with:
name: examples_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.config }}
path: components/mdns/examples/*.xml
run-target-asio:
strategy:
matrix:
idf_ver: ["latest"]
idf_target: ["esp32"]
example: ["asio_chat", "tcp_echo_server", "udp_echo_server", "ssl_client_server"]
name: Run ASIO Example Test on target
needs: build_asio
runs-on:
- self-hosted
- ESP32-ETHERNET-KIT
# Skip running on forks since it won't have access to secrets
if: github.repository == 'espressif/esp-protocols'
steps:
- name: Clear repository
run: sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE
- uses: actions/checkout@v3
- uses: actions/download-artifact@v2
with:
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.example }}
path: components/asio/examples/${{ matrix.example }}/build
- name: Install Python packages
env:
PIP_EXTRA_INDEX_URL: "https://www.piwheels.org/simple"
run: |
sudo apt-get install -y dnsutils
- name: Download Example Test to target ${{ matrix.config }}
run: |
python -m esptool --chip ${{ matrix.idf_target }} write_flash 0x0 components/asio/examples/${{ matrix.example }}/build/flash_image.bin
- name: Run Example Test ${{ matrix.example }} on target
working-directory: components/asio/examples/${{ matrix.example }}
run: |
python -m pytest --log-cli-level DEBUG --junit-xml=./examples_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.config }}.xml --target=${{ matrix.idf_target }}
- uses: actions/upload-artifact@v2
if: always()
with:
name: examples_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.example }}
path: components/asio/examples/${{ matrix.example }}/*.xml

View File

@ -396,7 +396,9 @@ static esp_netif_t *eth_start(void)
#endif
#elif CONFIG_EXAMPLE_USE_SPI_ETHERNET
gpio_install_isr_service(0);
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
spi_device_handle_t spi_handle = NULL;
#endif
spi_bus_config_t buscfg = {
.miso_io_num = CONFIG_EXAMPLE_ETH_SPI_MISO_GPIO,
.mosi_io_num = CONFIG_EXAMPLE_ETH_SPI_MOSI_GPIO,
@ -414,9 +416,14 @@ static esp_netif_t *eth_start(void)
.spics_io_num = CONFIG_EXAMPLE_ETH_SPI_CS_GPIO,
.queue_size = 20
};
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle));
/* dm9051 ethernet driver is based on spi driver */
eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle);
#else
eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg);
#endif // ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
dm9051_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
s_mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
s_phy = esp_eth_phy_new_dm9051(&phy_config);
@ -429,9 +436,13 @@ static esp_netif_t *eth_start(void)
.spics_io_num = CONFIG_EXAMPLE_ETH_SPI_CS_GPIO,
.queue_size = 20
};
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle));
/* w5500 ethernet driver is based on spi driver */
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle);
#else
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg);
#endif // ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
w5500_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
s_mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
s_phy = esp_eth_phy_new_w5500(&phy_config);

View File

@ -1,29 +0,0 @@
# This example code is in the Public Domain (or CC0 licensed, at your option.)
# Unless required by applicable law or agreed to in writing, this
# software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied.
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import re
import ttfw_idf
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC')
def test_examples_asio_chat(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None
msg = 'asio-chat: received hi'
dut = env.get_dut('asio_chat', 'examples/protocols/asio/asio_chat')
# start the test and expect the client to receive back it's original data
dut.start_app()
dut.expect(re.compile(r'{}'.format('Waiting for input')), timeout=30)
dut.write(msg)
dut.write('exit')
dut.expect(re.compile(r'{}'.format(msg)), timeout=30)
if __name__ == '__main__':
test_examples_asio_chat()

View File

@ -0,0 +1,24 @@
[pytest]
# only the files with prefix `pytest_` would be recognized as pytest test scripts.
python_files = pytest_*.py
addopts =
-s
--embedded-services esp,idf
-W ignore::_pytest.warning_types.PytestExperimentalApiWarning
--tb short
# ignore DeprecationWarning
filterwarnings =
ignore:Call to deprecated create function (.*)\(\):DeprecationWarning
# log related
log_cli = True
log_cli_level = INFO
log_cli_format = %(asctime)s %(levelname)s %(message)s
log_cli_date_format = %Y-%m-%d %H:%M:%S
log_file = test.log
log_file_level = INFO
log_file_format = %(asctime)s %(levelname)s %(message)s
log_file_date_format = %Y-%m-%d %H:%M:%S

View File

@ -0,0 +1,21 @@
# This example code is in the Public Domain (or CC0 licensed, at your option.)
# Unless required by applicable law or agreed to in writing, this
# software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied.
# -*- coding: utf-8 -*-
import re
import pytest
from pytest_embedded import Dut
def test_examples_asio_chat(dut):
msg = 'asio-chat: received hi'
# start the test and expect the client to receive back it's original data
dut.expect(re.compile(b'Waiting for input'), timeout=30)
dut.write(msg)
dut.write('exit')
msg = bytes(msg, encoding='utf8')
dut.expect(re.compile(msg), timeout=30)

View File

@ -1,16 +0,0 @@
from __future__ import unicode_literals
import ttfw_idf
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32', 'esp32c3'])
def test_examples_asio_ssl(env, extra_data):
dut = env.get_dut('asio_ssl_client_server', 'examples/protocols/asio/ssl_client_server')
dut.start_app()
dut.expect('Reply: GET / HTTP/1.1')
if __name__ == '__main__':
test_examples_asio_ssl()

View File

@ -0,0 +1,24 @@
[pytest]
# only the files with prefix `pytest_` would be recognized as pytest test scripts.
python_files = pytest_*.py
addopts =
-s
--embedded-services esp,idf
-W ignore::_pytest.warning_types.PytestExperimentalApiWarning
--tb short
# ignore DeprecationWarning
filterwarnings =
ignore:Call to deprecated create function (.*)\(\):DeprecationWarning
# log related
log_cli = True
log_cli_level = INFO
log_cli_format = %(asctime)s %(levelname)s %(message)s
log_cli_date_format = %Y-%m-%d %H:%M:%S
log_file = test.log
log_file_level = INFO
log_file_format = %(asctime)s %(levelname)s %(message)s
log_file_date_format = %Y-%m-%d %H:%M:%S

View File

@ -0,0 +1,8 @@
from __future__ import unicode_literals
import pytest
from pytest_embedded import Dut
def test_examples_asio_ssl(dut):
dut.expect('Reply: GET / HTTP/1.1')

View File

@ -0,0 +1,24 @@
[pytest]
# only the files with prefix `pytest_` would be recognized as pytest test scripts.
python_files = pytest_*.py
addopts =
-s
--embedded-services esp,idf
-W ignore::_pytest.warning_types.PytestExperimentalApiWarning
--tb short
# ignore DeprecationWarning
filterwarnings =
ignore:Call to deprecated create function (.*)\(\):DeprecationWarning
# log related
log_cli = True
log_cli_level = INFO
log_cli_format = %(asctime)s %(levelname)s %(message)s
log_cli_date_format = %Y-%m-%d %H:%M:%S
log_file = test.log
log_file_level = INFO
log_file_format = %(asctime)s %(levelname)s %(message)s
log_file_date_format = %Y-%m-%d %H:%M:%S

View File

@ -1,12 +1,10 @@
import os
import re
import socket
import ttfw_idf
from pytest_embedded import Dut
@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols')
def test_examples_protocol_asio_tcp_server(env, extra_data):
def test_examples_protocol_asio_tcp_server(dut):
"""
steps: |
1. join AP
@ -16,20 +14,13 @@ def test_examples_protocol_asio_tcp_server(env, extra_data):
5. Test evaluates received test message on server stdout
"""
test_msg = b'echo message from client to server'
dut1 = env.get_dut('tcp_echo_server', 'examples/protocols/asio/tcp_echo_server', dut_class=ttfw_idf.ESP32DUT)
# check and log bin size
binary_file = os.path.join(dut1.app.binary_path, 'asio_tcp_echo_server.bin')
bin_size = os.path.getsize(binary_file)
ttfw_idf.log_performance('asio_tcp_echo_server_bin_size', '{}KB'.format(bin_size // 1024))
# 1. start test
dut1.start_app()
# 2. get the server IP address
data = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30)
data = dut.expect(re.compile(b' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30).group(1).decode()
# 3. create tcp client and connect to server
dut1.expect('ASIO engine is up and running', timeout=1)
dut.expect('ASIO engine is up and running', timeout=1)
cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
cli.settimeout(30)
cli.connect((data[0], 2222))
cli.connect((data, 2222))
cli.send(test_msg)
data = cli.recv(1024)
# 4. check the message received back from the server
@ -40,8 +31,5 @@ def test_examples_protocol_asio_tcp_server(env, extra_data):
print('Failure!')
raise ValueError('Wrong data received from asi tcp server: {} (expected:{})'.format(data, test_msg))
# 5. check the client message appears also on server terminal
dut1.expect(test_msg.decode())
dut.expect(test_msg.decode())
if __name__ == '__main__':
test_examples_protocol_asio_tcp_server()

View File

@ -0,0 +1,2 @@
CONFIG_EXAMPLE_CONNECT_WIFI=n
CONFIG_EXAMPLE_CONNECT_ETHERNET=y

View File

@ -1,47 +0,0 @@
import os
import re
import socket
import ttfw_idf
@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols')
def test_examples_protocol_asio_udp_server(env, extra_data):
"""
steps: |
1. join AP
2. Start server
3. Test connects to server and sends a test message
4. Test evaluates received test message from server
5. Test evaluates received test message on server stdout
"""
test_msg = b'echo message from client to server'
dut1 = env.get_dut('udp_echo_server', 'examples/protocols/asio/udp_echo_server', dut_class=ttfw_idf.ESP32DUT)
# check and log bin size
binary_file = os.path.join(dut1.app.binary_path, 'asio_udp_echo_server.bin')
bin_size = os.path.getsize(binary_file)
ttfw_idf.log_performance('asio_udp_echo_server_bin_size', '{}KB'.format(bin_size // 1024))
# 1. start test
dut1.start_app()
# 2. get the server IP address
data = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30)
# 3. create tcp client and connect to server
dut1.expect('ASIO engine is up and running', timeout=1)
cli = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
cli.settimeout(30)
cli.connect((data[0], 2222))
cli.send(test_msg)
data = cli.recv(1024)
# 4. check the message received back from the server
if (data == test_msg):
print('PASS: Received correct message')
pass
else:
print('Failure!')
raise ValueError('Wrong data received from asio udp server: {} (expected:{})'.format(data, test_msg))
# 5. check the client message appears also on server terminal
dut1.expect(test_msg.decode())
if __name__ == '__main__':
test_examples_protocol_asio_udp_server()

View File

@ -0,0 +1,24 @@
[pytest]
# only the files with prefix `pytest_` would be recognized as pytest test scripts.
python_files = pytest_*.py
addopts =
-s
--embedded-services esp,idf
-W ignore::_pytest.warning_types.PytestExperimentalApiWarning
--tb short
# ignore DeprecationWarning
filterwarnings =
ignore:Call to deprecated create function (.*)\(\):DeprecationWarning
# log related
log_cli = True
log_cli_level = INFO
log_cli_format = %(asctime)s %(levelname)s %(message)s
log_cli_date_format = %Y-%m-%d %H:%M:%S
log_file = test.log
log_file_level = INFO
log_file_format = %(asctime)s %(levelname)s %(message)s
log_file_date_format = %Y-%m-%d %H:%M:%S

View File

@ -0,0 +1,33 @@
import os
import re
import socket
import pytest
from pytest_embedded import Dut
def test_examples_protocol_asio_udp_server(dut):
"""
steps: |
1. join AP
2. Start server
3. Test connects to server and sends a test message
4. Test evaluates received test message from server
5. Test evaluates received test message on server stdout
"""
test_msg = b'echo message from client to server'
data = dut.expect(re.compile(b' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30).group(1).decode()
dut.expect('ASIO engine is up and running', timeout=1)
cli = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
cli.settimeout(30)
cli.connect((data, 2222))
cli.send(test_msg)
data = cli.recv(1024)
# 4. check the message received back from the server
if (data == test_msg):
print('PASS: Received correct message')
pass
else:
print('Failure!')
raise ValueError('Wrong data received from asio udp server: {} (expected:{})'.format(data, test_msg))
# 5. check the client message appears also on server terminal
dut.expect(test_msg.decode())

View File

@ -0,0 +1,2 @@
CONFIG_EXAMPLE_CONNECT_WIFI=n
CONFIG_EXAMPLE_CONNECT_ETHERNET=y

View File

@ -14,6 +14,7 @@ else()
set(dependencies driver esp_event esp_netif)
endif()
set(srcs ${platform_srcs}
"src/esp_modem_dte.cpp"
"src/esp_modem_dce.cpp"
@ -34,15 +35,15 @@ 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

@ -11,12 +11,13 @@
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_idf_version.h"
#include "nvs_flash.h"
#include "lwip/lwip_napt.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "network_dce.h"
#if ESP_IDF_VERSION_MAJOR >= 5
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
#include "esp_mac.h"
#include "dhcpserver/dhcpserver.h"
#endif

View File

@ -61,7 +61,7 @@ int main()
bool pin_ok = true;
if (dce->read_pin(pin_ok) == command_result::OK && !pin_ok) {
throw_if_false(dce->set_pin(CONFIG_EXAMPLE_SIM_PIN) == command_result::OK, "Cannot set PIN!");
ESP_MODEM_THROW_IF_FALSE(dce->set_pin(CONFIG_EXAMPLE_SIM_PIN) == command_result::OK, "Cannot set PIN!");
usleep(1000000);
}
std::string str;

View File

@ -70,9 +70,9 @@ public:
.skip_phy_setup = false,
.intr_flags = ESP_INTR_FLAG_LEVEL1,
};
throw_if_esp_fail(usb_host_install(&host_config), "USB Host install failed");
ESP_MODEM_THROW_IF_ERROR(usb_host_install(&host_config), "USB Host install failed");
ESP_LOGD(TAG, "USB Host installed");
throw_if_false(pdTRUE == xTaskCreatePinnedToCore(usb_host_task, "usb_host", 4096, NULL, config->task_priority + 1, NULL, usb_config->xCoreID), "USB host task failed");
ESP_MODEM_THROW_IF_FALSE(pdTRUE == xTaskCreatePinnedToCore(usb_host_task, "usb_host", 4096, NULL, config->task_priority + 1, NULL, usb_config->xCoreID), "USB host task failed");
}
// Install CDC-ACM driver
@ -95,11 +95,11 @@ public:
};
if (usb_config->cdc_compliant) {
throw_if_esp_fail(this->CdcAcmDevice::open(usb_config->vid, usb_config->pid,
ESP_MODEM_THROW_IF_ERROR(this->CdcAcmDevice::open(usb_config->vid, usb_config->pid,
usb_config->interface_idx, &esp_modem_cdc_acm_device_config),
"USB Device open failed");
} else {
throw_if_esp_fail(this->CdcAcmDevice::open_vendor_specific(usb_config->vid, usb_config->pid,
ESP_MODEM_THROW_IF_ERROR(this->CdcAcmDevice::open_vendor_specific(usb_config->vid, usb_config->pid,
usb_config->interface_idx, &esp_modem_cdc_acm_device_config),
"USB Device open failed");
}

View File

@ -14,4 +14,163 @@ menu "Example Configuration"
help
Connect to modem via USB (CDC-ACM class). For IDF version >= 4.4.
endchoice
choice EXAMPLE_MODEM_DEVICE
prompt "Choose supported modem device (DCE)"
default EXAMPLE_MODEM_DEVICE_BG96
help
Select modem device connected to the ESP DTE.
config EXAMPLE_MODEM_DEVICE_SHINY
bool "SHINY"
help
SHINY is a GSM/GPRS module.
It supports SHINY.
config EXAMPLE_MODEM_DEVICE_SIM800
bool "SIM800"
help
SIMCom SIM800L is a GSM/GPRS module.
It supports Quad-band 850/900/1800/1900MHz.
config EXAMPLE_MODEM_DEVICE_BG96
bool "BG96"
help
Quectel BG96 is a series of LTE Cat M1/Cat NB1/EGPRS module.
config EXAMPLE_MODEM_DEVICE_SIM7000
bool "SIM7000"
help
SIM7000 is a Multi-Band LTE-FDD and GSM/GPRS/EDGE module.
config EXAMPLE_MODEM_DEVICE_SIM7070
bool "SIM7070"
help
SIM7070 is Multi-Band CAT M and NB IoT module.
config EXAMPLE_MODEM_DEVICE_SIM7600
bool "SIM7600"
help
SIM7600 is a Multi-Band LTE-TDD/LTE-FDD/HSPA+ and GSM/GPRS/EDGE module.
endchoice
config EXAMPLE_MODEM_PPP_APN
string "Set MODEM APN"
default "internet"
help
Set APN (Access Point Name), a logical name to choose data network
config EXAMPLE_MODEM_PPP_AUTH_USERNAME
string "Set username for authentication"
default "espressif"
depends on !EXAMPLE_MODEM_PPP_AUTH_NONE
help
Set username for PPP Authentication.
config EXAMPLE_MODEM_PPP_AUTH_PASSWORD
string "Set password for authentication"
default "esp32"
depends on !EXAMPLE_MODEM_PPP_AUTH_NONE
help
Set password for PPP Authentication.
config EXAMPLE_MODEM_PPP_AUTH_NONE
bool "Skip PPP authentication"
default n
help
Set to true for the PPP client to skip authentication
config EXAMPLE_SEND_MSG
bool "Short message (SMS)"
default n
help
Select this, the modem will send a short message before power off.
if EXAMPLE_SEND_MSG
config EXAMPLE_SEND_MSG_PEER_PHONE_NUMBER
string "Peer Phone Number (with area code)"
default "+8610086"
help
Enter the peer phone number that you want to send message to.
endif
config EXAMPLE_NEED_SIM_PIN
bool "SIM PIN needed"
default n
help
Enable to set SIM PIN before starting the example
config EXAMPLE_SIM_PIN
string "Set SIM PIN"
default "1234"
depends on EXAMPLE_NEED_SIM_PIN
help
Pin to unlock the SIM
menu "UART Configuration"
config EXAMPLE_MODEM_UART_TX_PIN
int "TXD Pin Number"
default 25
range 0 31
help
Pin number of UART TX.
config EXAMPLE_MODEM_UART_RX_PIN
int "RXD Pin Number"
default 26
range 0 31
help
Pin number of UART RX.
config EXAMPLE_MODEM_UART_RTS_PIN
int "RTS Pin Number"
default 27
range 0 31
help
Pin number of UART RTS.
config EXAMPLE_MODEM_UART_CTS_PIN
int "CTS Pin Number"
default 23
range 0 31
help
Pin number of UART CTS.
config EXAMPLE_MODEM_UART_EVENT_TASK_STACK_SIZE
int "UART Event Task Stack Size"
range 2000 6000
default 2048
help
Stack size of UART event task.
config EXAMPLE_MODEM_UART_EVENT_TASK_PRIORITY
int "UART Event Task Priority"
range 3 22
default 5
help
Priority of UART event task.
config EXAMPLE_MODEM_UART_EVENT_QUEUE_SIZE
int "UART Event Queue Size"
range 10 40
default 30
help
Length of UART event queue.
config EXAMPLE_MODEM_UART_PATTERN_QUEUE_SIZE
int "UART Pattern Queue Size"
range 10 40
default 20
help
Length of UART pattern queue.
config EXAMPLE_MODEM_UART_TX_BUFFER_SIZE
int "UART TX Buffer Size"
range 256 2048
default 512
help
Buffer size of UART TX buffer.
config EXAMPLE_MODEM_UART_RX_BUFFER_SIZE
int "UART RX Buffer Size"
range 256 2048
default 1024
help
Buffer size of UART RX buffer.
endmenu
endmenu

View File

@ -64,8 +64,43 @@ extern "C" void app_main(void)
#if defined(CONFIG_EXAMPLE_SERIAL_CONFIG_UART)
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
/* setup UART specific configuration based on kconfig options */
dte_config.uart_config.tx_io_num = CONFIG_EXAMPLE_MODEM_UART_TX_PIN;
dte_config.uart_config.rx_io_num = CONFIG_EXAMPLE_MODEM_UART_RX_PIN;
dte_config.uart_config.rts_io_num = CONFIG_EXAMPLE_MODEM_UART_RTS_PIN;
dte_config.uart_config.cts_io_num = CONFIG_EXAMPLE_MODEM_UART_CTS_PIN;
dte_config.uart_config.flow_control = ESP_MODEM_FLOW_CONTROL_HW;
dte_config.uart_config.rx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE;
dte_config.uart_config.tx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_TX_BUFFER_SIZE;
dte_config.uart_config.event_queue_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_QUEUE_SIZE;
dte_config.task_stack_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_STACK_SIZE;
dte_config.task_priority = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_PRIORITY;
dte_config.dte_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE / 2;
auto uart_dte = create_uart_dte(&dte_config);
#if CONFIG_EXAMPLE_MODEM_DEVICE_SHINY == 1
ESP_LOGI(TAG, "Initializing esp_modem for the SHINY module...");
auto dce = create_shiny_dce(&dce_config, uart_dte, esp_netif);
#elif CONFIG_EXAMPLE_MODEM_DEVICE_BG96 == 1
ESP_LOGI(TAG, "Initializing esp_modem for the BG96 module...");
auto dce = create_BG96_dce(&dce_config, uart_dte, esp_netif);
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM800 == 1
ESP_LOGI(TAG, "Initializing esp_modem for the SIM800 module...");
auto dce = create_SIM800_dce(&dce_config, uart_dte, esp_netif);
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7000 == 1
ESP_LOGI(TAG, "Initializing esp_modem for the SIM7000 module...");
auto dce = create_SIM7000_dce(&dce_config, uart_dte, esp_netif);
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7070 == 1
ESP_LOGI(TAG, "Initializing esp_modem for the SIM7070 module...");
auto dce = create_SIM7070_dce(&dce_config, uart_dte, esp_netif);
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1
ESP_LOGI(TAG, "Initializing esp_modem for the SIM7600 module...");
auto dce = create_SIM7600_dce(&dce_config, uart_dte, esp_netif);
#else
ESP_LOGI(TAG, "Initializing esp_modem for a generic module...");
auto dce = create_generic_dce(&dce_config, uart_dte, esp_netif);
#endif
#elif defined(CONFIG_EXAMPLE_SERIAL_CONFIG_USB)
struct esp_modem_usb_term_config usb_config = ESP_MODEM_DEFAULT_USB_CONFIG(0x2C7C, 0x0296); // VID and PID of BG96 modem
@ -82,6 +117,14 @@ extern "C" void app_main(void)
assert(dce != nullptr);
if(dte_config.uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
if (command_result::OK != dce->set_flow_control(2, 2)) {
ESP_LOGE(TAG, "Failed to set the set_flow_control mode");
return;
}
ESP_LOGI(TAG, "set_flow_control OK");
}
// init console REPL environment
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();

View File

@ -61,4 +61,10 @@ menu "Example Configuration"
help
HTTPS address of the update binary.
config EXAMPLE_CLOSE_CMUX_AT_END
bool "Close multiplexed mode at the end of the example"
default n
help
Close the multiplexed mode at the end of the example and rollback to command mode.
endmenu

View File

@ -82,7 +82,7 @@ extern "C" void app_main(void)
#if CONFIG_EXAMPLE_NEED_SIM_PIN == 1
bool pin_ok = true;
if (dce->read_pin(pin_ok) == command_result::OK && !pin_ok) {
throw_if_false(dce->set_pin(CONFIG_EXAMPLE_SIM_PIN) == command_result::OK, "Cannot set PIN!");
ESP_MODEM_THROW_IF_FALSE(dce->set_pin(CONFIG_EXAMPLE_SIM_PIN) == command_result::OK, "Cannot set PIN!");
vTaskDelay(pdMS_TO_TICKS(1000)); // Need to wait for some time after unlocking the SIM
}
#endif
@ -164,4 +164,14 @@ extern "C" void app_main(void)
return;
}
#endif // CONFIG_EXAMPLE_PERFORM_OTA
/* Close multiplexed command/data mode */
#if CONFIG_EXAMPLE_CLOSE_CMUX_AT_END == 1
if (dce->set_mode(esp_modem::modem_mode::COMMAND_MODE)) {
std::cout << "Modem has correctly entered command mode" << std::endl;
} else {
ESP_LOGE(TAG, "Failed to configure desired mode... exiting");
return;
}
#endif
}

View File

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

View File

@ -69,12 +69,12 @@ class Creator {
public:
Creator(std::shared_ptr<DTE> dte, esp_netif_t *esp_netif): dte(std::move(dte)), device(nullptr), netif(esp_netif)
{
throw_if_false(netif != nullptr, "Null netif");
ESP_MODEM_THROW_IF_FALSE(netif != nullptr, "Null netif");
}
Creator(std::shared_ptr<DTE> dte, esp_netif_t *esp_netif, std::shared_ptr<T_Module> dev): dte(std::move(dte)), device(std::move(dev)), netif(esp_netif)
{
throw_if_false(netif != nullptr, "Null netif");
ESP_MODEM_THROW_IF_FALSE(netif != nullptr, "Null netif");
}
~Creator()

View File

@ -75,6 +75,12 @@ public:
*/
void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f);
/**
* @brief Sets DTE error callback
* @param f Function to be called on DTE error
*/
void set_error_cb(std::function<void(terminal_error err)> f);
/**
* @brief Sets the DTE to desired mode (Command/Data/Cmux)
* @param m Desired operation mode

View File

@ -16,14 +16,21 @@
#include <string>
#include "esp_err.h"
#include "esp_log.h"
#ifndef __FILENAME__
#define __FILENAME__ __FILE__
#endif
#define ESP_MODEM_THROW_IF_FALSE(...) esp_modem::throw_if_false(__FILENAME__, __LINE__, __VA_ARGS__)
#define ESP_MODEM_THROW_IF_ERROR(...) esp_modem::throw_if_error(__FILENAME__, __LINE__, __VA_ARGS__)
namespace esp_modem {
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
#define THROW(exception) throw(exception)
#define ESP_MODEM_THROW(exception) throw(exception)
class esp_err_exception: virtual public std::exception {
public:
explicit esp_err_exception(esp_err_t err): esp_err(err) {}
explicit esp_err_exception(std::string msg): esp_err(ESP_FAIL), message(std::move(msg)) {}
explicit esp_err_exception(std::string msg, esp_err_t err): esp_err(err), message(std::move(msg)) {}
virtual esp_err_t get_err_t()
@ -31,7 +38,7 @@ public:
return esp_err;
}
~esp_err_exception() noexcept override = default;
virtual const char *what() const noexcept
[[nodiscard]] const char *what() const noexcept override
{
return message.c_str();
}
@ -39,28 +46,43 @@ private:
esp_err_t esp_err;
std::string message;
};
#else
#define THROW(exception) abort()
#define ESP_MODEM_THROW(exception) do { exception; abort(); } while(0)
class esp_err_exception {
void print(std::string msg) { ESP_LOGE("ESP_MODEM_THROW", "%s\n", msg.c_str()); }
public:
explicit esp_err_exception(std::string msg) { print(std::move(msg)); }
explicit esp_err_exception(std::string msg, esp_err_t err) { print(std::move(msg)); }
};
#endif
static inline void throw_if_false(bool condition, std::string message)
static inline std::string make_message(const std::string& filename, int line, const std::string& message = "ERROR")
{
std::string text = filename + ":" + std::to_string(line) + " " + message;
return text;
}
static inline void throw_if_false(const std::string& filename, int line, bool condition, const std::string& message)
{
if (!condition) {
THROW(esp_err_exception(std::move(message)));
ESP_MODEM_THROW(esp_err_exception(make_message(filename, line, message)));
}
}
static inline void throw_if_esp_fail(esp_err_t err, std::string message)
static inline void throw_if_error(const std::string& filename, int line, esp_err_t err, const std::string& message)
{
if (err != ESP_OK) {
THROW(esp_err_exception(std::move(message), err));
ESP_MODEM_THROW(esp_err_exception(make_message(filename, line, message), err));
}
}
static inline void throw_if_esp_fail(esp_err_t err)
static inline void throw_if_error(const std::string& filename, int line, esp_err_t err)
{
if (err != ESP_OK) {
THROW(esp_err_exception(err));
ESP_MODEM_THROW(esp_err_exception(make_message(filename, line), err));
}
}

View File

@ -41,6 +41,7 @@ enum class terminal_error {
BUFFER_OVERFLOW,
CHECKSUM_ERROR,
UNEXPECTED_CONTROL_FLOW,
DEVICE_GONE,
};
/**

View File

@ -0,0 +1,45 @@
// Copyright 2022 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "cxx_include/esp_modem_dce_factory.hpp"
#include "esp_modem_c_api_types.h"
using namespace esp_modem;
struct esp_modem_dce_wrap { // need to mimic the polymorphic dispatch as CPP uses templated dispatch
enum class modem_wrap_dte_type { UART, VFS, USB } dte_type;
dce_factory::ModemType modem_type;
DCE *dce;
};
inline dce_factory::ModemType convert_modem_enum(esp_modem_dce_device_t module)
{
switch (module) {
case ESP_MODEM_DCE_SIM7600:
return esp_modem::dce_factory::ModemType::SIM7600;
case ESP_MODEM_DCE_SIM7070:
return esp_modem::dce_factory::ModemType::SIM7070;
case ESP_MODEM_DCE_SIM7000:
return esp_modem::dce_factory::ModemType::SIM7000;
case ESP_MODEM_DCE_BG96:
return esp_modem::dce_factory::ModemType::BG96;
case ESP_MODEM_DCE_SIM800:
return esp_modem::dce_factory::ModemType::SIM800;
default:
case ESP_MODEM_DCE_GENETIC:
return esp_modem::dce_factory::ModemType::GenericModule;
}
}

View File

@ -47,6 +47,7 @@
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(sync, command_result, 0) \
\
/**
* @brief Reads the operator name
* @param[out] operator name
@ -72,9 +73,10 @@ 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
* @param[in] timeout AT command timeout in milliseconds
* @return OK, FAIL or TIMEOUT
*/\
ESP_MODEM_DECLARE_DCE_COMMAND(at, command_result, 2, STRING_IN(p1, cmd), STRING_OUT(p2, out)) \
ESP_MODEM_DECLARE_DCE_COMMAND(at, command_result, 3, STRING_IN(p1, cmd), STRING_OUT(p2, out), INT_IN(p3, timeout)) \
\
/**
* @brief Checks if the SIM needs a PIN
@ -112,7 +114,7 @@ ESP_MODEM_DECLARE_DCE_COMMAND(sms_character_set, command_result, 0) \
ESP_MODEM_DECLARE_DCE_COMMAND(send_sms, command_result, 2, STRING_IN(p1, number), STRING_IN(p2, message)) \
\
/**
* @brief Resumes data mode (Switches back to th data mode, which was temporarily suspended)
* @brief Resumes data mode (Switches back to the data mode, which was temporarily suspended)
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(resume_data_mode, command_result, 0) \

View File

@ -15,6 +15,7 @@
#pragma once
#include "esp_log.h"
#include "esp_idf_version.h"
#include "driver/uart.h"
/**
@ -23,7 +24,7 @@
*/
static inline int uart_write_bytes_compat(uart_port_t uart_num, const void* src, size_t size)
{
#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 0)
const void *data = src;
#else
auto *data = reinterpret_cast<const char*>(src);

View File

@ -21,6 +21,7 @@
#include "esp_modem_c_api_types.h"
#include "esp_modem_config.h"
#include "exception_stub.hpp"
#include "esp_private/c_api_wrapper.hpp"
#include "cstring"
#ifndef ESP_MODEM_C_API_STR_MAX
@ -35,12 +36,6 @@ size_t strlcpy(char *dest, const char *src, size_t len);
// C API definitions
using namespace esp_modem;
struct esp_modem_dce_wrap { // need to mimic the polymorphic dispatch as CPP uses templated dispatch
enum class modem_wrap_dte_type { UART, } dte_type;
dce_factory::ModemType modem_type;
DCE *dce;
};
static inline esp_err_t command_response_to_esp_err(command_result res)
{
switch (res) {
@ -54,25 +49,6 @@ static inline esp_err_t command_response_to_esp_err(command_result res)
return ESP_ERR_INVALID_ARG;
}
static inline dce_factory::ModemType convert_modem_enum(esp_modem_dce_device_t module)
{
switch (module) {
case ESP_MODEM_DCE_SIM7600:
return esp_modem::dce_factory::ModemType::SIM7600;
case ESP_MODEM_DCE_SIM7070:
return esp_modem::dce_factory::ModemType::SIM7070;
case ESP_MODEM_DCE_SIM7000:
return esp_modem::dce_factory::ModemType::SIM7000;
case ESP_MODEM_DCE_BG96:
return esp_modem::dce_factory::ModemType::BG96;
case ESP_MODEM_DCE_SIM800:
return esp_modem::dce_factory::ModemType::SIM800;
default:
case ESP_MODEM_DCE_GENETIC:
return esp_modem::dce_factory::ModemType::GenericModule;
}
}
extern "C" esp_modem_dce_t *esp_modem_new_dev(esp_modem_dce_device_t module, const esp_modem_dte_config_t *dte_config, const esp_modem_dce_config_t *dce_config, esp_netif_t *netif)
{
auto dce_wrap = new (std::nothrow) esp_modem_dce_wrap;
@ -179,14 +155,14 @@ 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)
extern "C" esp_err_t esp_modem_at(esp_modem_dce_t *dce_wrap, const char *at, char *p_out, int timeout)
{
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));
auto ret = command_response_to_esp_err(dce_wrap->dce->at(at_str, out, timeout));
if ((p_out != NULL) && (!out.empty())) {
strlcpy(p_out, out.c_str(), ESP_MODEM_C_API_STR_MAX);
}
@ -243,15 +219,17 @@ extern "C" esp_err_t esp_modem_get_imei(esp_modem_dce_t *dce_wrap, char *p_imei)
return ret;
}
extern "C" esp_err_t esp_modem_get_operator_name(esp_modem_dce_t *dce_wrap, char *p_name)
extern "C" esp_err_t esp_modem_get_operator_name(esp_modem_dce_t *dce_wrap, char *p_name, int *p_act)
{
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
if (dce_wrap == nullptr || dce_wrap->dce == nullptr || p_name == nullptr || p_act == nullptr) {
return ESP_ERR_INVALID_ARG;
}
std::string name;
auto ret = command_response_to_esp_err(dce_wrap->dce->get_operator_name(name));
int act;
auto ret = command_response_to_esp_err(dce_wrap->dce->get_operator_name(name, act));
if (ret == ESP_OK && !name.empty()) {
strlcpy(p_name, name.c_str(), ESP_MODEM_C_API_STR_MAX);
*p_act = act;
}
return ret;
}

View File

@ -82,7 +82,7 @@ void CMux::send_disconnect(size_t i)
{
if (i == 0) { // control terminal
uint8_t frame[] = {
SOF_MARKER, 0x3, 0xFF, 0x5, 0xC3, 0x1, 0xE7, SOF_MARKER };
SOF_MARKER, 0x3, 0xEF, 0x5, 0xC3, 0x1, 0xF2, SOF_MARKER };
term->write(frame, 8);
} else { // separate virtual terminal
uint8_t frame[] = {
@ -142,7 +142,7 @@ void CMux::data_available(uint8_t *data, size_t len)
read_cb[virtual_term](payload_start, total_payload_size);
#endif
}
} else if (type == 0xFF && dlci == 0) { // notify the internal DISC command
} else if ((type&FT_UIH) == FT_UIH && dlci == 0) { // notify the internal DISC command
Scoped<Lock> l(lock);
sabm_ack = dlci;
}
@ -325,11 +325,12 @@ bool CMux::on_cmux_data(uint8_t *data, size_t actual_len)
bool CMux::deinit()
{
int timeout = 0;
int timeout;
sabm_ack = -1;
// First disconnect all (2) virtual terminals
for (size_t i = 1; i < 3; i++) {
send_disconnect(i);
timeout = 0;
while (true) {
usleep(10'000);
Scoped<Lock> l(lock);
@ -345,6 +346,7 @@ bool CMux::deinit()
sabm_ack = -1;
// Then disconnect the control terminal
send_disconnect(0);
timeout = 0;
while (true) {
usleep(10'000);
Scoped<Lock> l(lock);

View File

@ -273,7 +273,7 @@ command_result set_pdp_context(CommandableIf *t, PdpContext &pdp)
ESP_LOGV(TAG, "%s", __func__ );
std::string pdp_command = "AT+CGDCONT=" + std::to_string(pdp.context_id) +
",\"" + pdp.protocol_type + "\",\"" + pdp.apn + "\"\r";
return generic_command_common(t, pdp_command);
return generic_command_common(t, pdp_command, 150000);
}
command_result set_data_mode(CommandableIf *t)
@ -389,11 +389,11 @@ 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)
command_result at(CommandableIf *t, const std::string &cmd, std::string &out, int timeout = 500)
{
ESP_LOGV(TAG, "%s", __func__ );
std::string at_command = cmd + "\r";
return generic_get_string(t, at_command, out);
return generic_get_string(t, at_command, out, timeout);
}
command_result get_signal_quality(CommandableIf *t, int &rssi, int &ber)
@ -458,7 +458,7 @@ command_result get_network_attachment_state(CommandableIf *t, int &state)
command_result set_radio_state(CommandableIf *t, int state)
{
ESP_LOGV(TAG, "%s", __func__ );
return generic_command_common(t, "AT+CFUN=" + std::to_string(state) + "\r");
return generic_command_common(t, "AT+CFUN=" + std::to_string(state) + "\r", 15000);
}
command_result get_radio_state(CommandableIf *t, int &state)

View File

@ -36,6 +36,7 @@ command_result DTE::command(const std::string &command, got_line_cb got_line, ui
{
Scoped<Lock> l(internal_lock);
command_result res = command_result::TIMEOUT;
signal.clear(GOT_LINE);
command_term->set_read_cb([&](uint8_t *data, size_t len) {
if (!data) {
data = buffer.get();
@ -56,7 +57,7 @@ command_result DTE::command(const std::string &command, got_line_cb got_line, ui
command_term->write((uint8_t *)command.c_str(), command.length());
auto got_lf = signal.wait(GOT_LINE, time_ms);
if (got_lf && res == command_result::TIMEOUT) {
throw_if_esp_fail(ESP_ERR_INVALID_STATE);
ESP_MODEM_THROW_IF_ERROR(ESP_ERR_INVALID_STATE);
}
buffer.consumed = 0;
command_term->set_read_cb(nullptr);
@ -155,6 +156,12 @@ void DTE::set_read_cb(std::function<bool(uint8_t *, size_t)> f)
});
}
void DTE::set_error_cb(std::function<void(terminal_error err)> f)
{
data_term->set_error_cb(f);
command_term->set_error_cb(f);
}
int DTE::read(uint8_t **d, size_t len)
{
auto data_to_read = std::min(len, buffer.size);

View File

@ -14,8 +14,10 @@
#include <memory>
#include <utility>
#include <inttypes.h>
#include <esp_log.h>
#include <esp_event.h>
#include "esp_idf_version.h"
#include "cxx_include/esp_modem_netif.hpp"
#include "cxx_include/esp_modem_dte.hpp"
#include "esp_netif_ppp.h"
@ -28,7 +30,7 @@ void Netif::on_ppp_changed(void *arg, esp_event_base_t event_base,
{
auto *ppp = static_cast<Netif *>(arg);
if (event_id < NETIF_PP_PHASE_OFFSET) {
ESP_LOGI("esp_modem_netif", "PPP state changed event %d", event_id);
ESP_LOGI("esp_modem_netif", "PPP state changed event %" PRId32, event_id);
// only notify the modem on state/error events, ignoring phase transitions
ppp->signal.set(PPP_EXIT);
}
@ -58,7 +60,7 @@ esp_err_t Netif::esp_modem_post_attach(esp_netif_t *esp_netif, void *args)
esp_netif_ppp_config_t ppp_config = { .ppp_phase_event_enabled = true, // assuming phase enabled, as earlier IDFs
.ppp_error_event_enabled = false
}; // don't provide cfg getters so we enable both events
#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 4
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
esp_netif_ppp_get_params(esp_netif, &ppp_config);
#endif // ESP-IDF >= v4.4
if (!ppp_config.ppp_error_event_enabled) {
@ -82,11 +84,11 @@ Netif::Netif(std::shared_ptr<DTE> e, esp_netif_t *ppp_netif) :
driver.base.netif = ppp_netif;
driver.ppp = this;
driver.base.post_attach = esp_modem_post_attach;
throw_if_esp_fail(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed, (void *) this));
throw_if_esp_fail(esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_GOT_IP, esp_netif_action_connected, ppp_netif));
throw_if_esp_fail(
ESP_MODEM_THROW_IF_ERROR(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed, (void *) this));
ESP_MODEM_THROW_IF_ERROR(esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_GOT_IP, esp_netif_action_connected, ppp_netif));
ESP_MODEM_THROW_IF_ERROR(
esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_LOST_IP, esp_netif_action_disconnected, ppp_netif));
throw_if_esp_fail(esp_netif_attach(ppp_netif, &driver));
ESP_MODEM_THROW_IF_ERROR(esp_netif_attach(ppp_netif, &driver));
}
void Netif::start()

View File

@ -28,7 +28,7 @@ void Lock::unlock()
Lock::Lock(): m(nullptr)
{
m = xSemaphoreCreateRecursiveMutex();
throw_if_false(m != nullptr, "create signal event group failed");
ESP_MODEM_THROW_IF_FALSE(m != nullptr, "create signal event group failed");
}
Lock::~Lock()
@ -45,7 +45,7 @@ void Lock::lock()
SignalGroup::SignalGroup(): event_group(nullptr)
{
event_group = xEventGroupCreate();
throw_if_false(event_group != nullptr, "create signal event group failed");
ESP_MODEM_THROW_IF_FALSE(event_group != nullptr, "create signal event group failed");
}
void SignalGroup::set(uint32_t bits)
@ -86,7 +86,7 @@ Task::Task(size_t stack_size, size_t priority, void *task_param, TaskFunction_t
: task_handle(nullptr)
{
BaseType_t ret = xTaskCreate(task_function, "vfs_task", stack_size, task_param, priority, &task_handle);
throw_if_false(ret == pdTRUE, "create vfs task failed");
ESP_MODEM_THROW_IF_FALSE(ret == pdTRUE, "create vfs task failed");
}
Task::~Task()

View File

@ -40,7 +40,7 @@ uart_resource::uart_resource(const esp_modem_uart_term_config *config, QueueHand
: UART_HW_FLOWCTRL_DISABLE;
uart_config.source_clk = config->source_clk;
throw_if_esp_fail(uart_param_config(config->port_num, &uart_config), "config uart parameter failed");
ESP_MODEM_THROW_IF_ERROR(uart_param_config(config->port_num, &uart_config), "config uart parameter failed");
if (config->flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
res = uart_set_pin(config->port_num, config->tx_io_num, config->rx_io_num,
@ -49,24 +49,24 @@ uart_resource::uart_resource(const esp_modem_uart_term_config *config, QueueHand
res = uart_set_pin(config->port_num, config->tx_io_num, config->rx_io_num,
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}
throw_if_esp_fail(res, "config uart gpio failed");
ESP_MODEM_THROW_IF_ERROR(res, "config uart gpio failed");
/* Set flow control threshold */
if (config->flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
res = uart_set_hw_flow_ctrl(config->port_num, UART_HW_FLOWCTRL_CTS_RTS, UART_FIFO_LEN - 8);
} else if (config->flow_control == ESP_MODEM_FLOW_CONTROL_SW) {
res = uart_set_sw_flow_ctrl(config->port_num, true, 8, UART_FIFO_LEN - 8);
}
throw_if_esp_fail(res, "config uart flow control failed");
ESP_MODEM_THROW_IF_ERROR(res, "config uart flow control failed");
/* Install UART driver and get event queue used inside driver */
res = uart_driver_install(config->port_num,
config->rx_buffer_size, config->tx_buffer_size,
config->event_queue_size, config->event_queue_size ? event_queue : nullptr,
0);
throw_if_esp_fail(res, "install uart driver failed");
throw_if_esp_fail(uart_set_rx_timeout(config->port_num, 1), "set rx timeout failed");
ESP_MODEM_THROW_IF_ERROR(res, "install uart driver failed");
ESP_MODEM_THROW_IF_ERROR(uart_set_rx_timeout(config->port_num, 1), "set rx timeout failed");
throw_if_esp_fail(uart_set_rx_full_threshold(config->port_num, 64), "config rx full threshold failed");
ESP_MODEM_THROW_IF_ERROR(uart_set_rx_full_threshold(config->port_num, 64), "config rx full threshold failed");
/* mark UART as initialized */
port = config->port_num;

View File

@ -33,7 +33,7 @@ struct uart_task {
task_handle(nullptr)
{
BaseType_t ret = xTaskCreate(task_function, "uart_task", stack_size, task_param, priority, &task_handle);
throw_if_false(ret == pdTRUE, "create uart event task failed");
ESP_MODEM_THROW_IF_FALSE(ret == pdTRUE, "create uart event task failed");
}
~uart_task()

View File

@ -27,7 +27,7 @@ uart_resource::uart_resource(const esp_modem_uart_term_config *config, QueueHand
{
ESP_LOGD(TAG, "Creating uart resource" );
struct termios tty = {};
throw_if_false(tcgetattr(fd, &tty) == 0, "Failed to tcgetattr()");
ESP_MODEM_THROW_IF_FALSE(tcgetattr(fd, &tty) == 0, "Failed to tcgetattr()");
tty.c_cflag &= ~PARENB;
tty.c_cflag &= ~CSTOPB;

View File

@ -91,7 +91,7 @@ bool vfs_create_socket(struct esp_modem_vfs_socket_creator *config, struct esp_m
}
TRY_CATCH_OR_DO(
int fd = -1;
esp_modem::throw_if_esp_fail(hostname_to_fd(config->host_name, config->port, &fd));
ESP_MODEM_THROW_IF_ERROR(hostname_to_fd(config->host_name, config->port, &fd));
// Set the FD to non-blocking mode
int flags = fcntl(fd, F_GETFL, nullptr) | O_NONBLOCK;

View File

@ -48,7 +48,7 @@ bool vfs_create_uart(struct esp_modem_vfs_uart_creator *config, struct esp_modem
}
TRY_CATCH_OR_DO(
int fd = open(config->dev_name, O_RDWR);
esp_modem::throw_if_false(fd >= 0, "Cannot open the fd");
ESP_MODEM_THROW_IF_FALSE(fd >= 0, "Cannot open the fd");
created_config->resource = new esp_modem_vfs_resource(&config->uart, fd);
created_config->fd = fd;

View File

@ -17,6 +17,7 @@ int LoopbackTerm::write(uint8_t *data, size_t len)
{
if (inject_by) { // injection test: ignore what we write, but respond with injected data
auto ret = std::async(&LoopbackTerm::batch_read, this);
async_results.push_back(std::move(ret));
return len;
}
if (len > 2 && (data[len - 1] == '\r' || data[len - 1] == '+') ) { // Simple AT responder
@ -99,7 +100,7 @@ LoopbackTerm::LoopbackTerm(bool is_bg96): loopback_data(), data_len(0), pin_ok(f
LoopbackTerm::LoopbackTerm(): loopback_data(), data_len(0), pin_ok(false), is_bg96(false), inject_by(0) {}
int LoopbackTerm::inject(uint8_t *data, size_t len, size_t injected_by)
int LoopbackTerm::inject(uint8_t *data, size_t len, size_t injected_by, size_t delay_before, size_t delay_after)
{
if (data == nullptr) {
inject_by = 0;
@ -110,14 +111,20 @@ int LoopbackTerm::inject(uint8_t *data, size_t len, size_t injected_by)
memcpy(&loopback_data[0], data, len);
data_len = len;
inject_by = injected_by;
delay_after_inject = delay_after;
delay_before_inject = delay_before;
return len;
}
void LoopbackTerm::batch_read()
{
while (data_len > 0) {
on_read(nullptr, std::min(inject_by, data_len));
Task::Delay(1);
Task::Delay(delay_before_inject);
{
Scoped<Lock> lock(on_read_guard);
on_read(nullptr, std::min(inject_by, data_len));
}
Task::Delay(delay_after_inject);
}
}

View File

@ -17,7 +17,7 @@ public:
* inject_by defines batch sizes: the read callback is called multiple times
* with partial data of `inject_by` size
*/
int inject(uint8_t *data, size_t len, size_t inject_by);
int inject(uint8_t *data, size_t len, size_t inject_by,size_t delay_before=0, size_t delay_after=1);
void start() override;
void stop() override;
@ -26,6 +26,12 @@ public:
int read(uint8_t *data, size_t len) override;
void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f) override
{
Scoped<Lock> lock(on_read_guard);
on_read = std::move(f);
}
private:
enum class status_t {
STARTED,
@ -39,4 +45,9 @@ private:
bool pin_ok;
bool is_bg96;
size_t inject_by;
size_t delay_before_inject;
size_t delay_after_inject;
std::vector<std::future<void>> async_results;
Lock on_read_guard;
};

View File

@ -7,6 +7,28 @@
using namespace esp_modem;
TEST_CASE("DTE command races", "[esp_modem]") {
auto term = std::make_unique<LoopbackTerm>(true);
auto loopback = term.get();
auto dte = std::make_shared<DTE>(std::move(term));
CHECK(term == nullptr);
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("APN");
esp_netif_t netif{};
auto dce = create_BG96_dce(&dce_config, dte, &netif);
CHECK(dce != nullptr);
uint8_t resp[] = {'O', 'K', '\n'};
// run many commands in succession with the timeout set exactly to the timespan of injected reply
// (checks for potential exception, data races, recycled local variables, etc.)
for (int i=0; i<1000; ++i) {
loopback->inject(&resp[0], sizeof(resp), sizeof(resp), /* 1ms before injecting reply */1, 0);
auto ret = dce->command("AT\n", [&](uint8_t *data, size_t len) {
return command_result::OK;
}, 1);
// this command should either timeout or finish successfully
CHECK((ret == command_result::TIMEOUT || ret == command_result::OK));
}
}
TEST_CASE("Test polymorphic delete for custom device/dte", "[esp_modem]")
{
auto term = std::make_unique<LoopbackTerm>(true);

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

@ -2,7 +2,7 @@
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
set(EXTRA_COMPONENT_DIRS "../..")
set(EXTRA_COMPONENT_DIRS "..")
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
list(APPEND EXTRA_COMPONENT_DIRS "../../../common_components/protocol_examples_common")

View File

@ -332,10 +332,15 @@ static void query_mdns_host_with_getaddrinfo(char * host)
if (!getaddrinfo(host, NULL, &hints, &res)) {
while (res) {
ESP_LOGI(TAG, "getaddrinfo: %s resolved to: %s", host,
res->ai_family == AF_INET?
inet_ntoa(((struct sockaddr_in *) res->ai_addr)->sin_addr):
inet_ntoa(((struct sockaddr_in6 *) res->ai_addr)->sin6_addr));
char *resolved_addr;
#if CONFIG_LWIP_IPV6
resolved_addr = res->ai_family == AF_INET ?
inet_ntoa(((struct sockaddr_in *) res->ai_addr)->sin_addr) :
inet_ntoa(((struct sockaddr_in6 *) res->ai_addr)->sin6_addr);
#else
resolved_addr = inet_ntoa(((struct sockaddr_in *) res->ai_addr)->sin_addr);
#endif // CONFIG_LWIP_IPV6
ESP_LOGI(TAG, "getaddrinfo: %s resolved to: %s", host, resolved_addr);
res = res->ai_next;
}
}

View File

@ -0,0 +1,24 @@
[pytest]
# only the files with prefix `pytest_` would be recognized as pytest test scripts.
python_files = pytest_*.py
addopts =
-s
--embedded-services esp,idf
-W ignore::_pytest.warning_types.PytestExperimentalApiWarning
--tb short
# ignore DeprecationWarning
filterwarnings =
ignore:Call to deprecated create function (.*)\(\):DeprecationWarning
# log related
log_cli = True
log_cli_level = INFO
log_cli_format = %(asctime)s %(levelname)s %(message)s
log_cli_date_format = %Y-%m-%d %H:%M:%S
log_file = test.log
log_file_level = INFO
log_file_format = %(asctime)s %(levelname)s %(message)s
log_file_date_format = %Y-%m-%d %H:%M:%S

View File

@ -5,19 +5,19 @@ import socket
import struct
import subprocess
import time
import pytest
from threading import Event, Thread
import dpkt
import dpkt.dns
import ttfw_idf
from tiny_test_fw import DUT
from tiny_test_fw.Utility import console_log
from pytest_embedded import Dut
import subprocess
def get_dns_query_for_esp(esp_host):
dns = dpkt.dns.DNS(b'\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01')
dns.qd[0].name = esp_host + u'.local'
console_log('Created query for esp host: {} '.format(dns.__repr__()))
print('Created query for esp host: {} '.format(dns.__repr__()))
return dns.pack()
@ -31,7 +31,7 @@ def get_dns_answer_to_mdns(tester_host):
arr.name = tester_host
arr.ip = socket.inet_aton('127.0.0.1')
dns.an.append(arr)
console_log('Created answer to mdns query: {} '.format(dns.__repr__()))
print('Created answer to mdns query: {} '.format(dns.__repr__()))
return dns.pack()
@ -80,18 +80,18 @@ def mdns_server(esp_host, events):
dns = dpkt.dns.DNS(data)
if len(dns.qd) > 0 and dns.qd[0].type == dpkt.dns.DNS_A:
if dns.qd[0].name == TESTER_NAME:
console_log('Received query: {} '.format(dns.__repr__()))
print('Received query: {} '.format(dns.__repr__()))
sock.sendto(get_dns_answer_to_mdns(TESTER_NAME), (MCAST_GRP, UDP_PORT))
elif dns.qd[0].name == TESTER_NAME_LWIP:
console_log('Received query: {} '.format(dns.__repr__()))
print('Received query: {} '.format(dns.__repr__()))
sock.sendto(get_dns_answer_to_mdns_lwip(TESTER_NAME_LWIP, dns.id), addr)
if len(dns.an) > 0 and dns.an[0].type == dpkt.dns.DNS_A:
console_log('Received answer from {}'.format(dns.an[0].name))
print('Received answer from {}'.format(dns.an[0].name))
if dns.an[0].name == esp_host + u'.local':
console_log('Received answer to esp32-mdns query: {}'.format(dns.__repr__()))
print('Received answer to esp32-mdns query: {}'.format(dns.__repr__()))
events['esp_answered'].set()
if dns.an[0].name == esp_host + u'-delegated.local':
console_log('Received answer to esp32-mdns-delegate query: {}'.format(dns.__repr__()))
print('Received answer to esp32-mdns-delegate query: {}'.format(dns.__repr__()))
events['esp_delegated_answered'].set()
except socket.timeout:
break
@ -99,7 +99,7 @@ def mdns_server(esp_host, events):
continue
def test_examples_protocol_mdns(env, config):
def test_examples_protocol_mdns(dut):
"""
steps: |
1. obtain IP address + init mdns example
@ -107,60 +107,31 @@ def test_examples_protocol_mdns(env, config):
3. check the mdns name is accessible
4. check DUT output if mdns advertized host is resolved
"""
dut1 = env.get_dut('mdns-test', 'examples/protocols/mdns', dut_class=ttfw_idf.ESP32DUT, app_config_name=config)
# check and log bin size
binary_file = os.path.join(dut1.app.binary_path, 'mdns_test.bin')
bin_size = os.path.getsize(binary_file)
ttfw_idf.log_performance('mdns-test_bin_size', '{}KB'.format(bin_size // 1024))
# 1. start mdns application
dut1.start_app()
# 2. get the dut host name (and IP address)
specific_host = dut1.expect(re.compile(r'mdns hostname set to: \[([^\]]+)\]'), timeout=30)[0]
specific_host = dut.expect(re.compile(b'mdns hostname set to: \[(.*?)\]')).group(1).decode()
mdns_server_events = {'stop': Event(), 'esp_answered': Event(), 'esp_delegated_answered': Event()}
mdns_responder = Thread(target=mdns_server, args=(str(specific_host), mdns_server_events))
ip_address = dut.expect(re.compile(b'IPv4 address:([a-zA-Z0-9]*).*')).group(1).decode()
print('Connected to AP with IP: {}'.format(ip_address))
try:
ip_address = dut1.expect(re.compile(r' eth ip: ([^,]+),'), timeout=30)[0]
console_log('Connected to AP with IP: {}'.format(ip_address))
except DUT.ExpectTimeout:
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP')
try:
# 3. check the mdns name is accessible
# 3. check the mdns name is accessible.
mdns_responder.start()
if not mdns_server_events['esp_answered'].wait(timeout=30):
raise ValueError('Test has failed: did not receive mdns answer within timeout')
if not mdns_server_events['esp_delegated_answered'].wait(timeout=30):
raise ValueError('Test has failed: did not receive mdns answer for delegated host within timeout')
# 4. check DUT output if mdns advertized host is resolved
dut1.expect(re.compile(r'mdns-test: Query A: tinytester.local resolved to: 127.0.0.1'), timeout=30)
dut1.expect(re.compile(r'mdns-test: gethostbyname: tinytester-lwip.local resolved to: 127.0.0.1'), timeout=30)
dut1.expect(re.compile(r'mdns-test: getaddrinfo: tinytester-lwip.local resolved to: 127.0.0.1'), timeout=30)
dut.expect(re.compile(b'mdns-test: Query A: tinytester.local resolved to: 127.0.0.1'), timeout=30)
dut.expect(re.compile(b'mdns-test: gethostbyname: tinytester-lwip.local resolved to: 127.0.0.1'), timeout=30)
dut.expect(re.compile(b'mdns-test: getaddrinfo: tinytester-lwip.local resolved to: 127.0.0.1'), timeout=30)
# 5. check the DUT answers to `dig` command
dig_output = subprocess.check_output(['dig', '+short', '-p', '5353', '@224.0.0.251',
'{}.local'.format(specific_host)])
console_log('Resolving {} using "dig" succeeded with:\n{}'.format(specific_host, dig_output))
print('Resolving {} using "dig" succeeded with:\n{}'.format(specific_host, dig_output))
if not ip_address.encode('utf-8') in dig_output:
raise ValueError('Test has failed: Incorrectly resolved DUT hostname using dig'
"Output should've contained DUT's IP address:{}".format(ip_address))
finally:
mdns_server_events['stop'].set()
mdns_responder.join()
@ttfw_idf.idf_example_test(env_tag='Example_EthKitV1')
def test_examples_protocol_mdns_default(env, _):
test_examples_protocol_mdns(env, 'eth_def')
@ttfw_idf.idf_example_test(env_tag='Example_EthKitV1')
def test_examples_protocol_mdns_socket(env, _):
test_examples_protocol_mdns(env, 'eth_socket')
@ttfw_idf.idf_example_test(env_tag='Example_EthKitV1')
def test_examples_protocol_mdns_custom_netif(env, _):
test_examples_protocol_mdns(env, 'eth_custom_netif')
if __name__ == '__main__':
test_examples_protocol_mdns_default()

View File

@ -0,0 +1,16 @@
CONFIG_IDF_TARGET="esp32"
CONFIG_MDNS_RESOLVE_TEST_SERVICES=y
CONFIG_MDNS_ADD_MAC_TO_HOSTNAME=y
CONFIG_MDNS_PUBLISH_DELEGATE_HOST=y
CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y
CONFIG_LWIP_IPV6=n
CONFIG_EXAMPLE_CONNECT_IPV6=n
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
CONFIG_EXAMPLE_CONNECT_WIFI=n
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
CONFIG_EXAMPLE_ETH_PHY_IP101=y
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
CONFIG_MDNS_BUTTON_GPIO=32

View File

@ -1,4 +1,4 @@
version: "1.0.5"
version: "1.0.7"
description: mDNS
dependencies:
idf:

View File

@ -232,7 +232,7 @@ static char * _mdns_mangle_name(char* in) {
static bool _mdns_service_match(const mdns_service_t * srv, const char * service, const char * proto,
const char * hostname)
{
if (!service || !proto) {
if (!service || !proto || !srv->hostname) {
return false;
}
return !strcasecmp(srv->service, service) && !strcasecmp(srv->proto, proto) &&
@ -1686,7 +1686,7 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_
if (!packet) {
return;
}
packet->flags = MDNS_FLAGS_AUTHORITATIVE;
packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE;
packet->distributed = parsed_packet->distributed;
packet->id = parsed_packet->id;
@ -1935,7 +1935,7 @@ static mdns_tx_packet_t * _mdns_create_announce_packet(mdns_if_t tcpip_if, mdns_
if (!packet) {
return NULL;
}
packet->flags = MDNS_FLAGS_AUTHORITATIVE;
packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE;
uint8_t i;
for (i=0; i<len; i++) {
@ -1965,7 +1965,7 @@ static mdns_tx_packet_t * _mdns_create_announce_from_probe(mdns_tx_packet_t * pr
if (!packet) {
return NULL;
}
packet->flags = MDNS_FLAGS_AUTHORITATIVE;
packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE;
mdns_out_answer_t * s = probe->servers;
while (s) {
@ -2005,7 +2005,7 @@ static void _mdns_pcb_send_bye(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protoco
if (!packet) {
return;
}
packet->flags = MDNS_FLAGS_AUTHORITATIVE;
packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE;
size_t i;
for (i=0; i<len; i++) {
if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, services[i]->service, NULL, true, true)) {
@ -3342,13 +3342,13 @@ void mdns_parse_packet(mdns_rx_packet_t * packet)
memset(name, 0, sizeof(mdns_name_t));
header.id = _mdns_read_u16(data, MDNS_HEAD_ID_OFFSET);
header.flags.value = _mdns_read_u16(data, MDNS_HEAD_FLAGS_OFFSET);
header.flags = _mdns_read_u16(data, MDNS_HEAD_FLAGS_OFFSET);
header.questions = _mdns_read_u16(data, MDNS_HEAD_QUESTIONS_OFFSET);
header.answers = _mdns_read_u16(data, MDNS_HEAD_ANSWERS_OFFSET);
header.servers = _mdns_read_u16(data, MDNS_HEAD_SERVERS_OFFSET);
header.additional = _mdns_read_u16(data, MDNS_HEAD_ADDITIONAL_OFFSET);
if (header.flags.value == MDNS_FLAGS_AUTHORITATIVE && packet->src_port != MDNS_SERVICE_PORT) {
if (header.flags == MDNS_FLAGS_QR_AUTHORITATIVE && packet->src_port != MDNS_SERVICE_PORT) {
free(parsed_packet);
return;
}
@ -3362,8 +3362,8 @@ void mdns_parse_packet(mdns_rx_packet_t * packet)
parsed_packet->tcpip_if = packet->tcpip_if;
parsed_packet->ip_protocol = packet->ip_protocol;
parsed_packet->multicast = packet->multicast;
parsed_packet->authoritative = header.flags.value == MDNS_FLAGS_AUTHORITATIVE;
parsed_packet->distributed = header.flags.value == MDNS_FLAGS_DISTRIBUTED;
parsed_packet->authoritative = (header.flags == MDNS_FLAGS_QR_AUTHORITATIVE);
parsed_packet->distributed = header.flags == MDNS_FLAGS_DISTRIBUTED;
parsed_packet->id = header.id;
esp_netif_ip_addr_copy(&parsed_packet->src, &packet->src);
parsed_packet->src_port = packet->src_port;
@ -3499,7 +3499,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet)
service = _mdns_get_service_item(name->service, name->proto, NULL);
}
} else {
if (!header.flags.qr || record_type == MDNS_NS) {
if ((header.flags & MDNS_FLAGS_QUERY_REPSONSE) == 0 || record_type == MDNS_NS) {
//skip this record
continue;
}
@ -3520,7 +3520,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet)
_mdns_remove_parsed_question(parsed_packet, type, service);
} else if (service) {
//check if TTL is more than half of the full TTL value (4500)
if (ttl > 2250) {
if (ttl > (MDNS_ANSWER_PTR_TTL/2)) {
_mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service);
}
}
@ -3675,7 +3675,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet)
if (col && !_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running && service) {
do_not_reply = true;
_mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, true);
} else if (ttl > 2250 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) {
} else if (ttl > (MDNS_ANSWER_TXT_TTL/2) && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) {
_mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service);
}
}
@ -4558,7 +4558,8 @@ static void _mdns_remap_self_service_hostname(const char * old_hostname, const c
mdns_srv_item_t * service = _mdns_server->services;
while (service) {
if (strcmp(service->service->hostname, old_hostname) == 0) {
if (service->service->hostname &&
strcmp(service->service->hostname, old_hostname) == 0) {
free((char *)service->service->hostname);
service->service->hostname = strdup(new_hostname);
}
@ -5430,7 +5431,7 @@ esp_err_t mdns_instance_name_set(const char * instance)
esp_err_t mdns_service_add_for_host(const char * instance, const char * service, const char * proto, const char * hostname,
uint16_t port, mdns_txt_item_t txt[], size_t num_items)
{
if (!_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto) || !port) {
if (!_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto) || !port || !hostname) {
return ESP_ERR_INVALID_ARG;
}
@ -6075,11 +6076,11 @@ void mdns_debug_packet(const uint8_t * data, size_t len)
header.additional = _mdns_read_u16(data, MDNS_HEAD_ADDITIONAL_OFFSET);
_mdns_dbg_printf("%s",
(header.flags.value == MDNS_FLAGS_AUTHORITATIVE)?"AUTHORITATIVE\n":
(header.flags.value == MDNS_FLAGS_QR_AUTHORITATIVE)?"AUTHORITATIVE\n":
(header.flags.value == MDNS_FLAGS_DISTRIBUTED)?"DISTRIBUTED\n":
(header.flags.value == 0)?"\n":" "
);
if (header.flags.value && header.flags.value != MDNS_FLAGS_AUTHORITATIVE) {
if (header.flags.value && header.flags.value != MDNS_FLAGS_QR_AUTHORITATIVE) {
_mdns_dbg_printf("0x%04X\n", header.flags.value);
}

View File

@ -339,8 +339,12 @@ 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;
#if CONFIG_LWIP_IPV6
ip_add_copy.type = ip->type;
memcpy(&(ip_add_copy.u_addr),&(ip->u_addr),sizeof(ip_add_copy.u_addr));
memcpy(&(ip_add_copy.u_addr), &(ip->u_addr), sizeof(ip_add_copy.u_addr));
#else
memcpy(&(ip_add_copy.addr), &(ip->u_addr), sizeof(ip_add_copy.addr));
#endif // CONFIG_LWIP_IPV6
mdns_api_call_t msg = {
.tcpip_if = tcpip_if,

View File

@ -71,7 +71,9 @@
#define MDNS_ANSWER_A_TTL 120
#define MDNS_ANSWER_AAAA_TTL 120
#define MDNS_FLAGS_AUTHORITATIVE 0x8400
#define MDNS_FLAGS_QUERY_REPSONSE 0x8000
#define MDNS_FLAGS_AUTHORITATIVE 0x0400
#define MDNS_FLAGS_QR_AUTHORITATIVE (MDNS_FLAGS_QUERY_REPSONSE | MDNS_FLAGS_AUTHORITATIVE)
#define MDNS_FLAGS_DISTRIBUTED 0x0200
#define MDNS_NAME_REF 0xC000
@ -211,21 +213,7 @@ typedef enum {
typedef struct {
uint16_t id;
union {
struct {
uint16_t qr :1;
uint16_t opCode :4;
uint16_t aa :1;
uint16_t tc :1;
uint16_t rd :1;
uint16_t ra :1;
uint16_t z :1;
uint16_t ad :1;
uint16_t cd :1;
uint16_t rCode :4;//response/error code
};
uint16_t value;
} flags;
uint16_t flags;
uint16_t questions; //QDCOUNT
uint16_t answers; //ANCOUNT
uint16_t servers; //NSCOUNT

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")