mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-06-25 17:31:33 +02:00
Compare commits
173 Commits
test_clang
...
console_cm
Author | SHA1 | Date | |
---|---|---|---|
c5b49de2db | |||
2e9bb6ee45 | |||
1fcc5b1d56 | |||
849fe7b6cb | |||
5eadf1edee | |||
428fdbbd80 | |||
433a033fcc | |||
090b1ff845 | |||
295d99df96 | |||
b65cff3a0b | |||
e711f26670 | |||
4a1cb65c67 | |||
6c61dd39cf | |||
8821ea3a99 | |||
062b8dcacc | |||
7de57bb412 | |||
67191f3bb5 | |||
6d94ad646d | |||
685d47cd2f | |||
31f57ad067 | |||
32ac21b03c | |||
5b06a3b319 | |||
cc2741d4ad | |||
c5653ff204 | |||
77731c9b36 | |||
2442f6b553 | |||
0b5e362a7b | |||
5219c39d09 | |||
1a9eaf3e98 | |||
52598e5f03 | |||
542547d38b | |||
2bcfa45d30 | |||
a453ca1f38 | |||
72f4f7c7a3 | |||
a353702e04 | |||
991ac40d75 | |||
fbd296f8dd | |||
a5b0b9d6ea | |||
2d9759265b | |||
8f1f935858 | |||
3f48f9ea7e | |||
8520245657 | |||
185247d220 | |||
73b3293b86 | |||
f613c70e00 | |||
c2c4bf835a | |||
1af4bbe1ab | |||
f5dc07fdcc | |||
e992787bcd | |||
8c4f392f93 | |||
8d8f2bf130 | |||
30f121e6a9 | |||
29810f4139 | |||
2abe55c173 | |||
eb7ea3450e | |||
1b62adbdf1 | |||
d6347a9d5f | |||
c454ec09e6 | |||
ff5dac70b7 | |||
50c113e412 | |||
bde97203ed | |||
8795d16466 | |||
e9ac41e1d7 | |||
7ca5ed1d3e | |||
345c457711 | |||
2e53b81f64 | |||
1a57a878be | |||
010a404a04 | |||
8475adf1d1 | |||
29e5fbdf93 | |||
554f022cbf | |||
cfd6d6ad90 | |||
6f90d85933 | |||
0e0cbd6b17 | |||
e926a2c4e6 | |||
b6792c527c | |||
492a6a0029 | |||
22ec03b3e6 | |||
6705bcae5e | |||
2208e76e04 | |||
c348076849 | |||
1b6a3b3b75 | |||
e2392c36fe | |||
a20c0c9d2c | |||
5c850cdad3 | |||
de4531e8c7 | |||
d2880418e5 | |||
8e4d43e00d | |||
fb7b0c201d | |||
f5c13b927f | |||
571a741b56 | |||
1790989242 | |||
f8ae7defd6 | |||
25b3d5fd7b | |||
11846c7d00 | |||
73c48307a3 | |||
b9357b31b5 | |||
788f0513fa | |||
bcab28c1b8 | |||
60817dd384 | |||
2c1b16617e | |||
169405b534 | |||
0d8f2a6d53 | |||
643dc6d43b | |||
f9f234c440 | |||
3f97a8228b | |||
c62b920bb9 | |||
a927bf3a8d | |||
99d5fb27e9 | |||
8a690503ed | |||
7e5ac87d09 | |||
d4da9cb079 | |||
0660ece128 | |||
d7fa24bc20 | |||
9cf4163663 | |||
a8f13bc861 | |||
aecf6f80bf | |||
34d7c1b23b | |||
6766be6955 | |||
234f579bd8 | |||
1e8ede3396 | |||
f107dcd118 | |||
ee00e97b2b | |||
07b79abf62 | |||
c9a58d7350 | |||
6b9a6ce65b | |||
43de7e5c4d | |||
ce7f326af0 | |||
a91ead8ef5 | |||
e425a3c504 | |||
50d059af07 | |||
f198967c98 | |||
c41e8891ca | |||
b80c19d72c | |||
5964eadbf5 | |||
e583848695 | |||
cb1bc41386 | |||
8d91f5fd62 | |||
5ccc018a98 | |||
9d4d5d2d49 | |||
e2f0477a00 | |||
906e447193 | |||
15ae280bbe | |||
e6f9fe2385 | |||
3a6720ded6 | |||
333a68936a | |||
25d8423e6d | |||
bd9f062709 | |||
9152cfcf82 | |||
8195fc4b8f | |||
68da69e4d8 | |||
c6e2eb2dac | |||
a9dd78ffad | |||
eb09e42638 | |||
adafeae5cf | |||
d7eaa77b89 | |||
5fe3870494 | |||
402176c9e0 | |||
085dd79079 | |||
a05fbc7ed9 | |||
ba35d14e43 | |||
83ea2876fc | |||
c714d24d75 | |||
2b64e80acd | |||
ac9972aa48 | |||
1c5a149b14 | |||
8d0152f612 | |||
b2272b410d | |||
5d43f9660f | |||
bdbf16c113 | |||
7f248bd03f | |||
dabd4bfd0e | |||
70fa3af771 |
4
.github/workflows/clang-tidy.yml
vendored
4
.github/workflows/clang-tidy.yml
vendored
@ -35,14 +35,14 @@ jobs:
|
||||
working-directory: test_app
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
idf.py clang-check --include-paths $GITHUB_WORKSPACE --exclude-paths $PWD --run-clang-tidy-py run-clang-tidy
|
||||
idf.py clang-check --include-paths $GITHUB_WORKSPACE --exclude-paths $PWD --run-clang-tidy-py run-clang-tidy --run-clang-tidy-options "-checks=-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling"
|
||||
cp warnings.txt ../
|
||||
- name: Convert clang-tidy results into SARIF output
|
||||
run: |
|
||||
export PATH=$PWD:$PATH
|
||||
./clang-tidy-sarif -o results.sarif.raw warnings.txt
|
||||
python3 filter_sarif.py -o results.sarif --include-prefix ${GITHUB_WORKSPACE}/ results.sarif.raw
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: |
|
||||
warnings.txt
|
||||
|
32
.github/workflows/console_cmd_mqtt__build.yml
vendored
Normal file
32
.github/workflows/console_cmd_mqtt__build.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
name: "console_cmd_mqtt: build-tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, labeled]
|
||||
|
||||
jobs:
|
||||
build_console_cmd_mqtt:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'console') || github.event_name == 'push'
|
||||
name: Build
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3"]
|
||||
idf_target: ["esp32"]
|
||||
test: [ { app: mqtt_ssl_auth_console, path: "components/console_cmd_mqtt/examples" }]
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
working-directory: ${{matrix.test.path}}
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
python ../../../ci/build_apps.py ./${{ matrix.test.app }} --target ${{ matrix.idf_target }} -vv --preserve-all --pytest-app
|
@ -14,12 +14,17 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.1", "release-v5.2", "release-v5.3"]
|
||||
include:
|
||||
- idf_ver: "latest"
|
||||
warning: "Warning: The smallest app partition is nearly full"
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v4
|
||||
- name: Build with IDF-${{ matrix.idf_ver }}
|
||||
env:
|
||||
EXPECTED_WARNING: ${{ matrix.warning }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
|
23
.github/workflows/mdns__host-tests.yml
vendored
23
.github/workflows/mdns__host-tests.yml
vendored
@ -10,27 +10,30 @@ on:
|
||||
jobs:
|
||||
host_test_mdns:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'mdns') || github.event_name == 'push'
|
||||
name: Host test
|
||||
name: Host test build
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:release-v5.1
|
||||
container: espressif/idf:release-v5.3
|
||||
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: esp-protocols
|
||||
path: protocols
|
||||
|
||||
- name: Build and Test
|
||||
shell: bash
|
||||
run: |
|
||||
apt-get update && apt-get install -y dnsutils gcc g++
|
||||
. ${IDF_PATH}/export.sh
|
||||
cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/tests/host_test
|
||||
idf.py build
|
||||
./build/mdns_host.elf &
|
||||
dig +short -p 5353 @224.0.0.251 myesp.local > ip.txt
|
||||
cat ip.txt | xargs dig +short -p 5353 @224.0.0.251 -x
|
||||
cat ip.txt
|
||||
python -m pip install idf-build-apps dnspython pytest pytest-embedded pytest-embedded-serial-esp pytest-embedded-idf
|
||||
cd $GITHUB_WORKSPACE/protocols
|
||||
# Build host tests app (with all configs and targets supported)
|
||||
python ./ci/build_apps.py components/mdns/tests/host_test/
|
||||
cd components/mdns/tests/host_test
|
||||
# First run the linux_app and send a quick A query and a reverse query
|
||||
./build_linux_app/mdns_host.elf &
|
||||
python dnsfixture.py A myesp.local --ip_only | xargs python dnsfixture.py X
|
||||
# Next we run the pytest (using the console app)
|
||||
pytest
|
||||
|
||||
build_afl_host_test_mdns:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'mdns') || github.event_name == 'push'
|
||||
|
15
.github/workflows/modem__build-host-tests.yml
vendored
15
.github/workflows/modem__build-host-tests.yml
vendored
@ -13,11 +13,8 @@ jobs:
|
||||
name: Build examples
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v4.4", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3"]
|
||||
idf_ver: ["latest", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3", "release-v5.4"]
|
||||
example: ["pppos_client", "modem_console", "modem_tcp_client", "ap_to_pppos", "simple_cmux_client"]
|
||||
exclude:
|
||||
- idf_ver: "release-v4.4"
|
||||
example: modem_tcp_client
|
||||
include:
|
||||
- idf_ver: "release-v5.0"
|
||||
example: "simple_cmux_client"
|
||||
@ -26,13 +23,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Check out code (v3) # @v4 failed due to Node 20's requirement, incompatible with older IDF versions
|
||||
if: matrix.idf_ver != 'latest' && matrix.idf_ver < 'release-v5.0'
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: protocols
|
||||
- name: Check out code (v4)
|
||||
if: matrix.idf_ver == 'latest' || matrix.idf_ver >= 'release-v5.0'
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: protocols
|
||||
@ -53,7 +44,7 @@ jobs:
|
||||
name: Build tests
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3", "latest"]
|
||||
idf_ver: ["release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3", "release-v5.4", "latest"]
|
||||
test: ["target", "target_ota", "target_iperf"]
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
|
8
.github/workflows/modem__target-test.yml
vendored
8
.github/workflows/modem__target-test.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
idf_target: ["esp32c3"]
|
||||
test: [ { app: pppd, path: test/target }, { app: sim800_c3, path: examples/pppos_client }, { app: sim800_cmux, path: examples/simple_cmux_client } ]
|
||||
test: [ { app: pppd, path: test/target }, { app: pppd_chap_auth, path: test/target }, { app: sim800_c3, path: examples/pppos_client }, { app: sim800_cmux, path: examples/simple_cmux_client } ]
|
||||
include:
|
||||
- idf_ver: "latest"
|
||||
idf_target: "esp32s2"
|
||||
@ -58,7 +58,7 @@ jobs:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
idf_target: ["esp32c3"]
|
||||
test: [ { app: pppd, path: test/target }, { app: sim800_c3, path: examples/pppos_client }, { app: sim800_cmux, path: examples/simple_cmux_client } ]
|
||||
test: [ { app: pppd, path: test/target }, { app: pppd_chap_auth, path: test/target }, { app: sim800_c3, path: examples/pppos_client }, { app: sim800_cmux, path: examples/simple_cmux_client } ]
|
||||
include:
|
||||
- idf_ver: "latest"
|
||||
idf_target: "esp32s2"
|
||||
@ -69,9 +69,11 @@ jobs:
|
||||
- modem
|
||||
env:
|
||||
TEST_DIR: components/esp_modem/${{ matrix.test.path }}
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
steps:
|
||||
- name: Clear repository
|
||||
run: sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE
|
||||
run: |
|
||||
sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
|
73
.github/workflows/mosq__build.yml
vendored
Normal file
73
.github/workflows/mosq__build.yml
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
name: "mosq: build-tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, labeled]
|
||||
|
||||
jobs:
|
||||
build_mosq:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'mosquitto') || github.event_name == 'push'
|
||||
name: Mosquitto build
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.3"]
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
env:
|
||||
TEST_DIR: components/mosquitto/examples/broker
|
||||
TARGET_TEST_DIR: build_esp32_default
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build with IDF-${{ matrix.idf_ver }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
python ci/build_apps.py ${TEST_DIR}
|
||||
cd ${TEST_DIR}
|
||||
${GITHUB_WORKSPACE}/ci/clean_build_artifacts.sh `pwd`/${TARGET_TEST_DIR}
|
||||
zip -qur artifacts.zip ${TARGET_TEST_DIR}
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: mosq_target_esp32_${{ matrix.idf_ver }}
|
||||
path: ${{ env.TEST_DIR }}/artifacts.zip
|
||||
if-no-files-found: error
|
||||
|
||||
test_mosq:
|
||||
# Skip running on forks since it won't have access to secrets
|
||||
if: |
|
||||
github.repository == 'espressif/esp-protocols' &&
|
||||
( contains(github.event.pull_request.labels.*.name, 'mosquitto') || github.event_name == 'push' )
|
||||
name: Mosquitto target test
|
||||
needs: build_mosq
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.3"]
|
||||
runs-on:
|
||||
- self-hosted
|
||||
- ESP32-ETHERNET-KIT
|
||||
env:
|
||||
TEST_DIR: components/mosquitto/examples/broker
|
||||
TARGET_TEST_DIR: build_esp32_default
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: mosq_target_esp32_${{ matrix.idf_ver }}
|
||||
path: ${{ env.TEST_DIR }}/ci/
|
||||
- name: Run Test
|
||||
working-directory: ${{ env.TEST_DIR }}
|
||||
run: |
|
||||
python -m pip install pytest-embedded-serial-esp pytest-embedded-idf pytest-rerunfailures pytest-timeout pytest-ignore-test-results
|
||||
unzip ci/artifacts.zip -d ci
|
||||
for dir in `ls -d ci/build_*`; do
|
||||
rm -rf build sdkconfig.defaults
|
||||
mv $dir build
|
||||
python -m pytest --log-cli-level DEBUG --junit-xml=./results_esp32_${{ matrix.idf_ver }}_${dir#"ci/build_"}.xml --target=esp32
|
||||
done
|
2
.github/workflows/pre_commit_check.yml
vendored
2
.github/workflows/pre_commit_check.yml
vendored
@ -26,7 +26,7 @@ jobs:
|
||||
- name: Set up Python environment
|
||||
uses: actions/setup-python@master
|
||||
with:
|
||||
python-version: v3.7
|
||||
python-version: v3.8
|
||||
- name: Install python packages
|
||||
run: |
|
||||
pip install pre-commit
|
||||
|
4
.github/workflows/publish-docs-component.yml
vendored
4
.github/workflows/publish-docs-component.yml
vendored
@ -98,7 +98,9 @@ jobs:
|
||||
components/console_cmd_ping;
|
||||
components/console_cmd_ifconfig;
|
||||
components/console_cmd_wifi;
|
||||
components/esp_wifi_remote;
|
||||
components/console_cmd_mqtt;
|
||||
components/mbedtls_cxx;
|
||||
components/mosquitto;
|
||||
components/sock_utils;
|
||||
namespace: "espressif"
|
||||
api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }}
|
||||
|
6
.github/workflows/run-host-tests.yml
vendored
6
.github/workflows/run-host-tests.yml
vendored
@ -87,8 +87,10 @@ jobs:
|
||||
shell: bash
|
||||
if: ${{ inputs.run_coverage }}
|
||||
run: |
|
||||
apt-get update && apt-get install -y python3-pip rsync
|
||||
python -m pip install gcovr
|
||||
apt-get update && apt-get install -y rsync
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
python3 -m pip install gcovr
|
||||
cd $GITHUB_WORKSPACE/${{inputs.component_path}}
|
||||
component=$(basename ${{ inputs.component_path }})
|
||||
gcov `find . -name "$component*gcda"`
|
||||
|
95
.github/workflows/sockutls_build.yml
vendored
Normal file
95
.github/workflows/sockutls_build.yml
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
name: "sock_utils: build-tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, labeled]
|
||||
|
||||
jobs:
|
||||
build_sock_utils:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'sock_utils') || github.event_name == 'push'
|
||||
name: Socket helpers build
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.3"]
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
env:
|
||||
TEST_DIR: components/sock_utils/examples/simple
|
||||
TARGET_TEST_DIR: build_esp32_default
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build with IDF-${{ matrix.idf_ver }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
python ci/build_apps.py ${TEST_DIR}
|
||||
cd ${TEST_DIR}
|
||||
${GITHUB_WORKSPACE}/ci/clean_build_artifacts.sh `pwd`/${TARGET_TEST_DIR}
|
||||
zip -qur artifacts.zip ${TARGET_TEST_DIR}
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sock_utils_target_esp32_${{ matrix.idf_ver }}
|
||||
path: ${{ env.TEST_DIR }}/artifacts.zip
|
||||
if-no-files-found: error
|
||||
host_test_sock_utils:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'sock_utils') || github.event_name == 'push'
|
||||
name: Socket helpers host test
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.3"]
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
env:
|
||||
TEST_DIR: components/sock_utils/test/host
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build with IDF-${{ matrix.idf_ver }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
cd ${TEST_DIR}
|
||||
idf.py build
|
||||
./build/sock_utils_host_test.elf
|
||||
|
||||
test_sock_utils:
|
||||
# Skip running on forks since it won't have access to secrets
|
||||
if: |
|
||||
github.repository == 'espressif/esp-protocols' &&
|
||||
( contains(github.event.pull_request.labels.*.name, 'sock_utils') || github.event_name == 'push' )
|
||||
name: Socket helpers target test
|
||||
needs: build_sock_utils
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.3"]
|
||||
runs-on:
|
||||
- self-hosted
|
||||
- ESP32-ETHERNET-KIT
|
||||
env:
|
||||
TEST_DIR: components/sock_utils/examples/simple
|
||||
TARGET_TEST_DIR: build_esp32_default
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: sock_utils_target_esp32_${{ matrix.idf_ver }}
|
||||
path: ${{ env.TEST_DIR }}/ci/
|
||||
- name: Run Test
|
||||
working-directory: ${{ env.TEST_DIR }}
|
||||
run: |
|
||||
unzip ci/artifacts.zip -d ci
|
||||
for dir in `ls -d ci/build_*`; do
|
||||
rm -rf build sdkconfig.defaults
|
||||
mv $dir build
|
||||
python -m pytest --log-cli-level DEBUG --junit-xml=./results_esp32_${{ matrix.idf_ver }}_${dir#"ci/build_"}.xml --target=esp32
|
||||
done
|
77
.github/workflows/wifi_remote__build.yml
vendored
77
.github/workflows/wifi_remote__build.yml
vendored
@ -1,77 +0,0 @@
|
||||
name: "esp_wifi_remote: build-tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, labeled]
|
||||
|
||||
jobs:
|
||||
wifi_remote_api_compat:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'wifi_remote') || github.event_name == 'push'
|
||||
name: Check API compatibility of WiFi Remote
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
- name: Check that headers are the same as generated
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
cd ./components/esp_wifi_remote/scripts
|
||||
python generate_and_check.py
|
||||
|
||||
build_wifi_remote:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'wifi_remote') || github.event_name == 'push'
|
||||
name: Build WiFi Remote Test
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
test: [ { app: smoke_test, path: "test/smoke_test" }]
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: ${{ matrix.idf_ver }}
|
||||
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
python ./ci/build_apps.py ./components/esp_wifi_remote/${{matrix.test.path}} -vv --preserve-all
|
||||
|
||||
build_wifi_remote_example:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'wifi_remote') || github.event_name == 'push'
|
||||
name: Build WiFi Remote Example
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
example: [ { app: host, path: "examples/mqtt" }, { app: slave, path: "examples/server" }]
|
||||
include:
|
||||
- idf_ver: "latest"
|
||||
example: { app: slave, path: "examples/server" }
|
||||
warning: "Warning: The smallest app partition is nearly full"
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
- name: Build ${{ matrix.example.app }} with IDF-${{ matrix.idf_ver }}
|
||||
env:
|
||||
EXPECTED_WARNING: ${{ matrix.warning }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
python ./ci/build_apps.py ./components/esp_wifi_remote/${{matrix.example.path}} -vv --preserve-all
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +1,6 @@
|
||||
[submodule "components/asio/asio"]
|
||||
path = components/asio/asio
|
||||
url = https://github.com/espressif/asio
|
||||
[submodule "components/mosquitto/mosquitto"]
|
||||
path = components/mosquitto/mosquitto
|
||||
url = https://github.com/eclipse/mosquitto
|
||||
|
@ -48,7 +48,7 @@ repos:
|
||||
- id: check-copyright
|
||||
args: ['--ignore', 'ci/check_copyright_ignore.txt', '--config', 'ci/check_copyright_config.yaml']
|
||||
- repo: https://github.com/igrr/astyle_py.git
|
||||
rev: c0013808882a15a0c0c2c1a9b5c903866c53a653
|
||||
rev: v1.0.5
|
||||
hooks:
|
||||
- id: astyle_py
|
||||
args: ['--style=otbs', '--attach-namespaces', '--attach-classes', '--indent=spaces=4', '--convert-tabs', '--align-pointer=name', '--align-reference=name', '--keep-one-line-statements', '--pad-header', '--pad-oper', '--exclude-list=ci/ignore_astyle.txt']
|
||||
@ -61,8 +61,8 @@ repos:
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: commit message scopes
|
||||
name: "commit message must be scoped with: mdns, modem, websocket, asio, mqtt_cxx, console, common, eppp, wifi_remote, tls_cxx"
|
||||
entry: '\A(?!(feat|fix|ci|bump|test|docs)\((mdns|modem|common|console|websocket|asio|mqtt_cxx|examples|eppp|wifi_remote|tls_cxx)\)\:)'
|
||||
name: "commit message must be scoped with: mdns, modem, websocket, asio, mqtt_cxx, console, common, eppp, tls_cxx, mosq, sockutls"
|
||||
entry: '\A(?!(feat|fix|ci|bump|test|docs|chore)\((mdns|modem|common|console|websocket|asio|mqtt_cxx|examples|eppp|tls_cxx|mosq|sockutls)\)\:)'
|
||||
language: pygrep
|
||||
args: [--multiline]
|
||||
stages: [commit-msg]
|
||||
|
13
README.md
13
README.md
@ -54,10 +54,15 @@ Please refer to instructions in [ESP-IDF](https://github.com/espressif/esp-idf)
|
||||
|
||||
* Brief introduction [README](components/eppp_link/README.md)
|
||||
|
||||
### esp_wifi_remote
|
||||
|
||||
* Brief introduction [README](components/esp_wifi_remote/README.md)
|
||||
|
||||
### mbedtls_cxx
|
||||
|
||||
* Brief introduction [README](components/mbedtls_cxx/README.md)
|
||||
|
||||
### mosquitto
|
||||
|
||||
* Brief introduction [README](components/mosquitto/README.md)
|
||||
* API documentation [api.md](components/mosquitto/api.md)
|
||||
|
||||
### Socket helpers (sock-utils)
|
||||
|
||||
* Brief introduction [README](components/sock_utils/README.md)
|
||||
|
@ -1,4 +1,4 @@
|
||||
# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
"""
|
||||
This file is used in CI for esp-protocols build tests
|
||||
@ -10,8 +10,6 @@ import sys
|
||||
|
||||
from idf_build_apps import build_apps, find_apps, setup_logging
|
||||
from idf_build_apps.constants import SUPPORTED_TARGETS
|
||||
from packaging import version
|
||||
from pkg_resources import get_distribution
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(
|
||||
@ -51,43 +49,24 @@ if __name__ == '__main__':
|
||||
SUPPORTED_TARGETS.append('linux')
|
||||
ignore_warning = 'warning: ' # Ignore all common warnings on linux builds
|
||||
setup_logging(2)
|
||||
if version.parse(get_distribution('idf_build_apps').version) >= version.parse('2.0.0'):
|
||||
apps = find_apps(
|
||||
args.paths,
|
||||
recursive=args.recursive,
|
||||
target=args.target,
|
||||
build_dir='build_@t_@w',
|
||||
config_rules_str=args.rules,
|
||||
build_log_filename='build_log.txt',
|
||||
size_json_filename='size.json' if not args.linux else None,
|
||||
check_warnings=True,
|
||||
preserve=not args.delete,
|
||||
manifest_files=args.manifests,
|
||||
default_build_targets=SUPPORTED_TARGETS,
|
||||
manifest_rootpath='.',
|
||||
)
|
||||
else:
|
||||
apps = find_apps(
|
||||
args.paths,
|
||||
recursive=args.recursive,
|
||||
target=args.target,
|
||||
build_dir='build_@t_@w',
|
||||
config_rules_str=args.rules,
|
||||
build_log_path='build_log.txt',
|
||||
size_json_path='size.json' if not args.linux else None,
|
||||
check_warnings=True,
|
||||
preserve=not args.delete,
|
||||
manifest_files=args.manifests,
|
||||
default_build_targets=SUPPORTED_TARGETS,
|
||||
manifest_rootpath='.',
|
||||
)
|
||||
|
||||
for app in apps:
|
||||
print(app)
|
||||
apps = find_apps(
|
||||
args.paths,
|
||||
recursive=args.recursive,
|
||||
target=args.target,
|
||||
build_dir='build_@t_@w',
|
||||
config_rules_str=args.rules,
|
||||
build_log_filename='build_log.txt',
|
||||
size_json_filename='size.json' if not args.linux else None,
|
||||
check_warnings=True,
|
||||
manifest_files=args.manifests,
|
||||
default_build_targets=SUPPORTED_TARGETS,
|
||||
manifest_rootpath='.',
|
||||
)
|
||||
|
||||
sys.exit(
|
||||
build_apps(apps,
|
||||
dry_run=False,
|
||||
keep_going=False,
|
||||
no_preserve=args.delete,
|
||||
ignore_warning_strs=ignore_warning)
|
||||
)
|
||||
|
@ -47,6 +47,14 @@ asio_component:
|
||||
- Apache-2.0
|
||||
- BSL-1.0
|
||||
|
||||
mosquitto_component:
|
||||
include:
|
||||
- 'components/mosquitto/port/**'
|
||||
allowed_licenses:
|
||||
- EPL-2.0
|
||||
- Apache-2.0
|
||||
- BSD-3-Clause
|
||||
|
||||
slim_modem_examples:
|
||||
include:
|
||||
- 'examples/esp_netif/slip_custom_netif/**'
|
||||
|
@ -22,7 +22,11 @@ if git log -1 -m --name-only --pretty="" | grep -q components/${comp}/idf_compon
|
||||
if [ $(git tag -l "$tag") ]; then
|
||||
echo "${comp}: version (${tag}) already exits"
|
||||
else
|
||||
# skip components that do not have changelog
|
||||
[ -f components/${comp}/CHANGELOG.md ] || continue
|
||||
|
||||
echo "${comp}: Component version has been updated to ${version}"
|
||||
|
||||
# creates release notes from the last entry (between first two "## sections")
|
||||
awk '/^## \[/{a++};{if(a==1){print}}' components/${comp}/CHANGELOG.md > release_notes.md
|
||||
|
||||
|
@ -1,2 +0,0 @@
|
||||
# The below file is generated from esp_wifi_types_native.h in IDF, which doesn't follow atyle
|
||||
components/esp_wifi_remote/include/esp_wifi_types_native.h
|
||||
|
@ -0,0 +1 @@
|
||||
idf_component_register()
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -12,8 +12,24 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "osal/osal_api.h"
|
||||
#include <semaphore.h>
|
||||
|
||||
typedef struct task_notifiers {
|
||||
sem_t sem;
|
||||
TaskHandle_t id;
|
||||
} task_notifiers_t;
|
||||
|
||||
typedef struct pthread_params {
|
||||
void *const param;
|
||||
TaskFunction_t task;
|
||||
bool started;
|
||||
TaskHandle_t handle;
|
||||
} pthread_params_t;
|
||||
|
||||
static uint64_t s_semaphore_data = 0;
|
||||
static task_notifiers_t *s_notifiers;
|
||||
static int s_threads = 0;
|
||||
pthread_mutex_t s_mutex;
|
||||
|
||||
typedef enum queue_type_tag {
|
||||
MUTEX_REC,
|
||||
@ -89,6 +105,7 @@ BaseType_t xSemaphoreGiveRecursive( QueueHandle_t xQueue)
|
||||
}
|
||||
return pdFALSE;
|
||||
}
|
||||
|
||||
BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask )
|
||||
{
|
||||
struct generic_queue_handle *h = xQueue;
|
||||
@ -99,7 +116,6 @@ BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask )
|
||||
return xQueueReceive(xQueue, &s_semaphore_data, portMAX_DELAY);
|
||||
}
|
||||
|
||||
|
||||
BaseType_t xSemaphoreTakeRecursive( QueueHandle_t xQueue, TickType_t pvTask )
|
||||
{
|
||||
struct generic_queue_handle *h = xQueue;
|
||||
@ -110,9 +126,6 @@ BaseType_t xSemaphoreTakeRecursive( QueueHandle_t xQueue, TickType_t pvTask )
|
||||
return pdFALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void vQueueDelete( QueueHandle_t xQueue )
|
||||
{
|
||||
struct generic_queue_handle *h = xQueue;
|
||||
@ -128,8 +141,7 @@ void vQueueDelete( QueueHandle_t xQueue )
|
||||
|
||||
QueueHandle_t xSemaphoreCreateBinary(void)
|
||||
{
|
||||
QueueHandle_t sempaphore = xQueueCreate(1, 1);
|
||||
return sempaphore;
|
||||
return xQueueCreate(1, 1);
|
||||
}
|
||||
|
||||
QueueHandle_t xSemaphoreCreateMutex(void)
|
||||
@ -145,6 +157,13 @@ QueueHandle_t xSemaphoreCreateRecursiveMutex(void)
|
||||
|
||||
void vTaskDelete(TaskHandle_t *task)
|
||||
{
|
||||
for (int i = 0; i < s_threads; ++i) {
|
||||
if (task == s_notifiers[i].id) {
|
||||
sem_destroy(&s_notifiers[i].sem);
|
||||
s_notifiers[i].id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (task == NULL) {
|
||||
pthread_exit(0);
|
||||
}
|
||||
@ -171,14 +190,21 @@ void vTaskDelay( const TickType_t xTicksToDelay )
|
||||
|
||||
void *pthread_task(void *params)
|
||||
{
|
||||
struct {
|
||||
void *const param;
|
||||
TaskFunction_t task;
|
||||
bool started;
|
||||
} *pthread_params = params;
|
||||
pthread_params_t *pthread_params = params;
|
||||
|
||||
void *const param = pthread_params->param;
|
||||
TaskFunction_t task = pthread_params->task;
|
||||
|
||||
pthread_params->handle = xTaskGetCurrentTaskHandle();
|
||||
if (s_threads == 0) {
|
||||
pthread_mutex_init(&s_mutex, NULL);
|
||||
}
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
s_notifiers = realloc(s_notifiers, sizeof(struct task_notifiers) * (++s_threads));
|
||||
assert(s_notifiers);
|
||||
s_notifiers[s_threads - 1].id = pthread_params->handle;
|
||||
sem_init(&s_notifiers[s_threads - 1].sem, 0, 0);
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
pthread_params->started = true;
|
||||
|
||||
task(param);
|
||||
@ -198,16 +224,12 @@ BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode,
|
||||
return pdTRUE;
|
||||
}
|
||||
|
||||
|
||||
BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char *const pcName, const uint32_t usStackDepth, void *const pvParameters, UBaseType_t uxPriority, TaskHandle_t *const pvCreatedTask)
|
||||
{
|
||||
pthread_t new_thread = (pthread_t)NULL;
|
||||
pthread_attr_t attr;
|
||||
struct {
|
||||
void *const param;
|
||||
TaskFunction_t task;
|
||||
bool started;
|
||||
} pthread_params = { .param = pvParameters, .task = pvTaskCode};
|
||||
pthread_params_t pthread_params = { .param = pvParameters, .task = pvTaskCode};
|
||||
|
||||
int res = pthread_attr_init(&attr);
|
||||
assert(res == 0);
|
||||
res = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
||||
@ -215,20 +237,33 @@ BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char *const pcName, cons
|
||||
res = pthread_create(&new_thread, &attr, pthread_task, &pthread_params);
|
||||
assert(res == 0);
|
||||
|
||||
if (pvCreatedTask) {
|
||||
*pvCreatedTask = (void *)new_thread;
|
||||
}
|
||||
|
||||
// just wait till the task started so we can unwind params from the stack
|
||||
while (pthread_params.started == false) {
|
||||
usleep(1000);
|
||||
}
|
||||
if (pvCreatedTask) {
|
||||
*pvCreatedTask = pthread_params.handle;
|
||||
}
|
||||
|
||||
return pdTRUE;
|
||||
}
|
||||
|
||||
void xTaskNotifyGive(TaskHandle_t task)
|
||||
{
|
||||
|
||||
int i = 0;
|
||||
while (true) {
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
if (task == s_notifiers[i].id) {
|
||||
sem_post(&s_notifiers[i].sem);
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
return;
|
||||
}
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
if (++i == s_threads) {
|
||||
i = 0;
|
||||
}
|
||||
usleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time )
|
||||
@ -238,7 +273,7 @@ BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear,
|
||||
|
||||
TaskHandle_t xTaskGetCurrentTaskHandle(void)
|
||||
{
|
||||
return NULL;
|
||||
return (TaskHandle_t)pthread_self();
|
||||
}
|
||||
|
||||
EventGroupHandle_t xEventGroupCreate( void )
|
||||
@ -270,3 +305,22 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits
|
||||
{
|
||||
return osal_signal_wait(xEventGroup, uxBitsToWaitFor, xWaitForAllBits, xTicksToWait);
|
||||
}
|
||||
|
||||
void ulTaskNotifyTake(bool clear_on_exit, uint32_t xTicksToWait)
|
||||
{
|
||||
TaskHandle_t task = xTaskGetCurrentTaskHandle();
|
||||
int i = 0;
|
||||
while (true) {
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
if (task == s_notifiers[i].id) {
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
sem_wait(&s_notifiers[i].sem);
|
||||
return;
|
||||
}
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
if (++i == s_threads) {
|
||||
i = 0;
|
||||
}
|
||||
usleep(1000);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
@ -4,5 +4,3 @@
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#pragma once
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_hosted_api.h"
|
@ -11,6 +11,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define tskNO_AFFINITY ( ( BaseType_t ) 0x7FFFFFFF )
|
||||
#define TaskHandle_t TaskHandle_t
|
||||
#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) )
|
||||
|
||||
@ -18,6 +19,8 @@ void vTaskDelay( const TickType_t xTicksToDelay );
|
||||
|
||||
void xTaskNotifyGive(TaskHandle_t task);
|
||||
|
||||
void ulTaskNotifyTake(bool stuff, uint32_t timeout);
|
||||
|
||||
TaskHandle_t xTaskGetCurrentTaskHandle(void);
|
||||
|
||||
BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time );
|
||||
|
8
components/console_cmd_mqtt/.cz.yaml
Normal file
8
components/console_cmd_mqtt/.cz.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
commitizen:
|
||||
bump_message: 'bump(console): $current_version -> $new_version'
|
||||
pre_bump_hooks: python ../../ci/changelog.py console_cmd_mqtt
|
||||
tag_format: console_cmd_mqtt-v$version
|
||||
version: 1.0.0
|
||||
version_files:
|
||||
- idf_component.yml
|
7
components/console_cmd_mqtt/CHANGELOG.md
Normal file
7
components/console_cmd_mqtt/CHANGELOG.md
Normal file
@ -0,0 +1,7 @@
|
||||
# Changelog
|
||||
|
||||
## [1.0.0](https://github.com/espressif/esp-protocols/commits/console_cmd_mqtt-v1.0.0)
|
||||
|
||||
### Features
|
||||
|
||||
- Added component with mqtt command ([1fcc5b1d](https://github.com/espressif/esp-protocols/commit/1fcc5b1d))
|
7
components/console_cmd_mqtt/CMakeLists.txt
Normal file
7
components/console_cmd_mqtt/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
idf_component_register(SRCS "console_mqtt.c"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES esp_netif console mqtt)
|
||||
|
||||
if(CONFIG_MQTT_CMD_AUTO_REGISTRATION)
|
||||
target_link_libraries(${COMPONENT_LIB} PRIVATE "-u console_cmd_mqtt_register")
|
||||
endif()
|
15
components/console_cmd_mqtt/Kconfig.projbuild
Normal file
15
components/console_cmd_mqtt/Kconfig.projbuild
Normal file
@ -0,0 +1,15 @@
|
||||
menu "MQTT Configuration"
|
||||
|
||||
config MQTT_CMD_AUTO_REGISTRATION
|
||||
bool "Enable Console command mqtt Auto-registration"
|
||||
default y
|
||||
help
|
||||
Enabling this allows for the autoregistration of the wifi command.
|
||||
|
||||
config MQTT_BROKER_URL
|
||||
string "Broker URL or IP address"
|
||||
default "mqtt://mqtt.eclipseprojects.io"
|
||||
help
|
||||
URL or IP address of the broker to connect to
|
||||
|
||||
endmenu
|
87
components/console_cmd_mqtt/README.md
Normal file
87
components/console_cmd_mqtt/README.md
Normal file
@ -0,0 +1,87 @@
|
||||
# Console command mqtt
|
||||
The component provides a console where mqtt commands can be executed.
|
||||
|
||||
|
||||
## MQTT Configuration:
|
||||
1. Broker: Use menuconfig **"MQTT Configuration"** to configure the broker url.
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### Steps to enable console in an example code:
|
||||
1. Add this component to your project using ```idf.py add-dependency``` command.
|
||||
2. In the main file of the example, add the following line:
|
||||
```c
|
||||
#include "console_mqtt.h"
|
||||
```
|
||||
3. Ensure esp-netif is initialized and default event loop is created in your app_main():
|
||||
```c
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
```
|
||||
4. In your app_main() function, add the following line as the last line:
|
||||
```c
|
||||
ESP_ERROR_CHECK(console_cmd_init()); // Initialize console
|
||||
|
||||
// Register all plugin command added to your project
|
||||
ESP_ERROR_CHECK(console_cmd_all_register());
|
||||
|
||||
// To register only mqtt command skip calling console_cmd_all_register()
|
||||
ESP_ERROR_CHECK(console_cmd_mqtt_register());
|
||||
|
||||
ESP_ERROR_CHECK(console_cmd_start()); // Start console
|
||||
```
|
||||
|
||||
Note: Auto-registration of a specific plugin command can be disabled from menuconfig.
|
||||
|
||||
### Certificate Integration for Mutual Authentication
|
||||
To enhance security and enable secure communication over MQTT, three functions have been added to the API, allowing users to set client certificates, client keys, and broker certificates separately.
|
||||
|
||||
Setting the client certificate:
|
||||
```c
|
||||
set_mqtt_client_cert(client_cert_pem_start, client_cert_pem_end);
|
||||
```
|
||||
Setting the client key:
|
||||
```c
|
||||
set_mqtt_client_key(client_key_pem_start, client_key_pem_end);
|
||||
```
|
||||
Setting the broker certificate:
|
||||
```c
|
||||
set_mqtt_broker_certs(broker_cert_pem_start, broker_cert_pem_end);
|
||||
```
|
||||
Each function takes pointers to the start and end of the respective PEM-encoded data, allowing users to specify the necessary certificate and key information independently. For a complete secure MQTT setup, users should call all three functions in their application code.
|
||||
|
||||
To utilize these certificates, users need to include additional arguments when establishing MQTT connections using the library. Specifically, users should provide the `--cert`, `--key`, and `--cafile` options along with the MQTT connection command.
|
||||
|
||||
### Adding a plugin command or component:
|
||||
To add a plugin command or any component from IDF component manager into your project, simply include an entry within the `idf_component.yml` file.
|
||||
|
||||
For more details refer [IDF Component Manager](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-component-manager.html)
|
||||
|
||||
## Suported command:
|
||||
|
||||
### mqtt:
|
||||
```
|
||||
mqtt [-CsD] [-h <host>] [-u <username>] [-P <password>] [--cert] [--key] [--cafile]
|
||||
mqtt command
|
||||
-C, --connect Connect to a broker (flag, no argument)
|
||||
-h, --host=<host> Specify the host uri to connect to
|
||||
-s, --status Displays the status of the mqtt client (flag, no argument)
|
||||
-u, --username=<username> Provide a username to be used for authenticating with the broker
|
||||
-P, --password=<password> Provide a password to be used for authenticating with the broker
|
||||
--cert Define the PEM encoded certificate for this client, if required by the broker (flag, no argument)
|
||||
--key Define the PEM encoded private key for this client, if required by the broker (flag, no argument)
|
||||
--cafile Define the PEM encoded CA certificates that are trusted (flag, no argument)
|
||||
--use-internal-bundle Use the internal certificate bundle for TLS (flag, no argument)
|
||||
-D, --disconnect Disconnect from the broker (flag, no argument)
|
||||
|
||||
mqtt_pub [-t <topic>] [-m <message>]
|
||||
mqtt publish command
|
||||
-t, --topic=<topic> Topic to Subscribe/Publish
|
||||
-m, --message=<message> Message to Publish
|
||||
|
||||
mqtt_sub [-U] [-t <topic>]
|
||||
mqtt subscribe command
|
||||
-t, --topic=<topic> Topic to Subscribe/Publish
|
||||
-U, --unsubscribe Unsubscribe from a topic
|
||||
```
|
475
components/console_cmd_mqtt/console_mqtt.c
Normal file
475
components/console_cmd_mqtt/console_mqtt.c
Normal file
@ -0,0 +1,475 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "console_mqtt.h"
|
||||
#include "mqtt_client.h"
|
||||
#if defined(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE)
|
||||
#include "esp_crt_bundle.h"
|
||||
#endif
|
||||
|
||||
static const char *TAG = "console_mqtt";
|
||||
|
||||
#define CONNECT_HELP_MSG "mqtt -C -h <host uri> -u <username> -P <password> --cert --key --cafile\n"
|
||||
#define PUBLISH_HELP_MSG "Usage: mqtt -P -t <topic> -d <data>\n"
|
||||
#define SUBSCRIBE_HELP_MSG "Usage: mqtt -S -t <topic>\n"
|
||||
#define UNSUBSCRIBE_HELP_MSG "Usage: mqtt -U\n"
|
||||
#define DISCONNECT_HELP_MSG "Usage: mqtt -D\n"
|
||||
|
||||
#if CONFIG_MQTT_CMD_AUTO_REGISTRATION
|
||||
/**
|
||||
* Static registration of this plugin is achieved by defining the plugin description
|
||||
* structure and placing it into .console_cmd_desc section.
|
||||
* The name of the section and its placement is determined by linker.lf file in 'plugins' component.
|
||||
*/
|
||||
static const console_cmd_plugin_desc_t __attribute__((section(".console_cmd_desc"), used)) PLUGIN = {
|
||||
.name = "console_cmd_mqtt",
|
||||
.plugin_regd_fn = &console_cmd_mqtt_register
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct {
|
||||
struct arg_lit *connect;
|
||||
struct arg_str *uri;
|
||||
struct arg_lit *status;
|
||||
struct arg_str *username;
|
||||
struct arg_str *password;
|
||||
struct arg_lit *cert;
|
||||
struct arg_lit *key;
|
||||
struct arg_lit *cafile;
|
||||
#if defined(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE)
|
||||
struct arg_lit *use_internal_bundle;
|
||||
#endif
|
||||
struct arg_lit *disconnect;
|
||||
|
||||
struct arg_end *end;
|
||||
} mqtt_args;
|
||||
|
||||
static struct {
|
||||
struct arg_str *topic;
|
||||
struct arg_lit *unsubscribe;
|
||||
|
||||
struct arg_end *end;
|
||||
} mqtt_sub_args;
|
||||
|
||||
static struct {
|
||||
struct arg_str *topic;
|
||||
struct arg_str *message;
|
||||
|
||||
struct arg_end *end;
|
||||
} mqtt_pub_args;
|
||||
|
||||
typedef enum {
|
||||
MQTT_STATE_INIT = 0,
|
||||
MQTT_STATE_DISCONNECTED,
|
||||
MQTT_STATE_CONNECTED,
|
||||
MQTT_STATE_ERROR,
|
||||
MQTT_STATE_STOPPED,
|
||||
} mqtt_client_state_t;
|
||||
|
||||
mqtt_client_state_t client_status = MQTT_STATE_INIT;
|
||||
|
||||
static esp_mqtt_client_handle_t client_handle = NULL;
|
||||
|
||||
static const uint8_t *s_own_cert_pem_start = NULL;
|
||||
static const uint8_t *s_own_cert_pem_end = NULL;
|
||||
static const uint8_t *s_own_key_pem_start = NULL;
|
||||
static const uint8_t *s_own_key_pem_end = NULL;
|
||||
static const uint8_t *s_ca_cert_pem_start = NULL;
|
||||
static const uint8_t *s_ca_cert_pem_end = NULL;
|
||||
|
||||
static void log_error_if_nonzero(const char *message, int error_code)
|
||||
{
|
||||
if (error_code != 0) {
|
||||
ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Event handler registered to receive MQTT events
|
||||
*
|
||||
* This function is called by the MQTT client event loop.
|
||||
*
|
||||
* @param handler_args user data registered to the event.
|
||||
* @param base Event base for the handler(always MQTT Base in this example).
|
||||
* @param event_id The id for the received event.
|
||||
* @param event_data The data for the event, esp_mqtt_event_handle_t.
|
||||
*/
|
||||
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=%" PRIi32, base, event_id);
|
||||
esp_mqtt_event_handle_t event = event_data;
|
||||
switch ((esp_mqtt_event_id_t)event_id) {
|
||||
case MQTT_EVENT_BEFORE_CONNECT:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_BEFORE_CONNECT");
|
||||
break;
|
||||
case MQTT_EVENT_CONNECTED:
|
||||
client_status = MQTT_STATE_CONNECTED;
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
|
||||
break;
|
||||
case MQTT_EVENT_DISCONNECTED:
|
||||
client_status = MQTT_STATE_DISCONNECTED;
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
|
||||
break;
|
||||
case MQTT_EVENT_SUBSCRIBED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_UNSUBSCRIBED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_PUBLISHED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_DATA:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
|
||||
ESP_LOGI(TAG, "TOPIC=%.*s\r\n", event->topic_len, event->topic);
|
||||
ESP_LOGI(TAG, "DATA=%.*s\r\n", event->data_len, event->data);
|
||||
break;
|
||||
case MQTT_EVENT_ERROR:
|
||||
client_status = MQTT_STATE_ERROR;
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
|
||||
if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
|
||||
log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
|
||||
log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
|
||||
log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno);
|
||||
ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const char *mqtt_state_to_string(mqtt_client_state_t state)
|
||||
{
|
||||
switch (state) {
|
||||
case MQTT_STATE_INIT:
|
||||
return "Initializing";
|
||||
case MQTT_STATE_DISCONNECTED:
|
||||
return "Disconnected";
|
||||
case MQTT_STATE_CONNECTED:
|
||||
return "Connected";
|
||||
case MQTT_STATE_ERROR:
|
||||
return "Error";
|
||||
case MQTT_STATE_STOPPED:
|
||||
return "Disconnected and Stopped";
|
||||
default:
|
||||
return "Unknown State";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int do_mqtt_cmd(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **)&mqtt_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, mqtt_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mqtt_args.status->count > 0) {
|
||||
ESP_LOGI(TAG, "MQTT Client Status: %s\n", mqtt_state_to_string(client_status));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mqtt_args.connect->count > 0) {
|
||||
|
||||
if (client_handle != NULL) {
|
||||
ESP_LOGW(TAG, "mqtt client already connected");
|
||||
ESP_LOGI(TAG, "Try: %s", DISCONNECT_HELP_MSG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *uri = CONFIG_MQTT_BROKER_URL;
|
||||
if (mqtt_args.uri->count > 0) {
|
||||
uri = (char *)mqtt_args.uri->sval[0];
|
||||
}
|
||||
|
||||
esp_mqtt_client_config_t mqtt_cfg = {
|
||||
.broker.address.uri = uri,
|
||||
};
|
||||
|
||||
if ((mqtt_args.username->count > 0) && (mqtt_args.password->count > 0)) {
|
||||
mqtt_cfg.credentials.username = mqtt_args.username->sval[0];
|
||||
mqtt_cfg.credentials.authentication.password = mqtt_args.password->sval[0];
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "broker: %s", mqtt_cfg.broker.address.uri);
|
||||
|
||||
#if defined(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE)
|
||||
/* Ensure --use_internal_bundle and --cafile are mutually exclusive */
|
||||
if ((mqtt_args.use_internal_bundle->count > 0) && (mqtt_args.cafile->count > 0)) {
|
||||
ESP_LOGE(TAG, "Error: Options can't be used together. Use either --use-internal-bundle or --cafile. \n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mqtt_args.use_internal_bundle->count > 0) {
|
||||
mqtt_cfg.broker.verification.crt_bundle_attach = esp_crt_bundle_attach;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mqtt_args.cafile->count > 0) {
|
||||
if (s_ca_cert_pem_start && s_ca_cert_pem_end) {
|
||||
mqtt_cfg.broker.verification.certificate = (const char *)s_ca_cert_pem_start;
|
||||
} else {
|
||||
ESP_LOGW(TAG, "cafile not provided");
|
||||
}
|
||||
}
|
||||
|
||||
if (mqtt_args.cert->count > 0) {
|
||||
if (s_own_cert_pem_start && s_own_cert_pem_end) {
|
||||
mqtt_cfg.credentials.authentication.certificate = (const char *)s_own_cert_pem_start;
|
||||
} else {
|
||||
ESP_LOGW(TAG, "cert not provided");
|
||||
}
|
||||
|
||||
if (mqtt_args.key->count > 0) {
|
||||
if (s_own_key_pem_start && s_own_key_pem_end) {
|
||||
mqtt_cfg.credentials.authentication.key = (const char *)s_own_key_pem_start;
|
||||
} else {
|
||||
ESP_LOGW(TAG, "key not provided");
|
||||
}
|
||||
} else {
|
||||
mqtt_cfg.credentials.authentication.key = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
client_handle = esp_mqtt_client_init(&mqtt_cfg);
|
||||
if (client_handle == NULL) {
|
||||
ESP_LOGE(TAG, "ERROR: Client init");
|
||||
ESP_LOGI(TAG, "Try: %s", DISCONNECT_HELP_MSG);
|
||||
ESP_LOGE(TAG, CONNECT_HELP_MSG);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
|
||||
esp_mqtt_client_register_event(client_handle, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
|
||||
esp_mqtt_client_start(client_handle);
|
||||
|
||||
} else if (mqtt_args.disconnect->count > 0) {
|
||||
ESP_LOGD(TAG, "Disconnect command received:");
|
||||
|
||||
if (client_handle == NULL) {
|
||||
ESP_LOGE(TAG, "mqtt client not connected");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (esp_mqtt_client_stop(client_handle) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to stop mqtt client task");
|
||||
return 1;
|
||||
}
|
||||
|
||||
client_handle = NULL;
|
||||
client_status = MQTT_STATE_STOPPED;
|
||||
ESP_LOGI(TAG, "mqtt client disconnected and stopped");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t set_mqtt_client_cert(const uint8_t *client_cert_pem_start_i, const uint8_t *client_cert_pem_end_i)
|
||||
{
|
||||
if (!client_cert_pem_start_i || !client_cert_pem_end_i ||
|
||||
(client_cert_pem_start_i > client_cert_pem_end_i)) {
|
||||
ESP_LOGE(TAG, "Invalid mqtt Client certs(%d)\n", __LINE__);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
s_own_cert_pem_start = client_cert_pem_start_i;
|
||||
s_own_cert_pem_end = client_cert_pem_end_i;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t set_mqtt_client_key(const uint8_t *client_key_pem_start_i, const uint8_t *client_key_pem_end_i)
|
||||
{
|
||||
if (client_key_pem_start_i && client_key_pem_end_i &&
|
||||
(client_key_pem_start_i >= client_key_pem_end_i)) {
|
||||
ESP_LOGE(TAG, "Invalid mqtt Client key(%d)\n", __LINE__);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
s_own_key_pem_start = client_key_pem_start_i;
|
||||
s_own_key_pem_end = client_key_pem_end_i;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t set_mqtt_broker_certs(const uint8_t *ca_cert_pem_start_i, const uint8_t *ca_cert_pem_end_i)
|
||||
{
|
||||
if (!ca_cert_pem_start_i || !ca_cert_pem_end_i ||
|
||||
(ca_cert_pem_start_i > ca_cert_pem_end_i)) {
|
||||
ESP_LOGE(TAG, "Invalid mqtt ca cert(%d)\n", __LINE__);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
s_ca_cert_pem_start = ca_cert_pem_start_i;
|
||||
s_ca_cert_pem_end = ca_cert_pem_end_i;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
static int do_mqtt_sub_cmd(int argc, char **argv)
|
||||
{
|
||||
int msg_id;
|
||||
int nerrors = arg_parse(argc, argv, (void **)&mqtt_sub_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, mqtt_sub_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (client_handle == NULL) {
|
||||
ESP_LOGE(TAG, "mqtt client not connected");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mqtt_sub_args.unsubscribe->count > 0) {
|
||||
if (mqtt_sub_args.topic->count <= 0) {
|
||||
ESP_LOGE(TAG, UNSUBSCRIBE_HELP_MSG);
|
||||
return 0;
|
||||
}
|
||||
char *topic = (char *)mqtt_sub_args.topic->sval[0];
|
||||
|
||||
msg_id = esp_mqtt_client_unsubscribe(client_handle, mqtt_sub_args.topic->sval[0]);
|
||||
ESP_LOGI(TAG, "Unsubscribe successful, msg_id=%d, topic=%s", msg_id, topic);
|
||||
|
||||
} else {
|
||||
if (mqtt_sub_args.topic->count <= 0) {
|
||||
ESP_LOGE(TAG, SUBSCRIBE_HELP_MSG);
|
||||
return 0;
|
||||
}
|
||||
char *topic = (char *)mqtt_sub_args.topic->sval[0];
|
||||
|
||||
msg_id = esp_mqtt_client_subscribe(client_handle, topic, 0);
|
||||
ESP_LOGI(TAG, "Subscribe successful, msg_id=%d, topic=%s", msg_id, topic);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int do_mqtt_pub_cmd(int argc, char **argv)
|
||||
{
|
||||
int msg_id;
|
||||
int nerrors = arg_parse(argc, argv, (void **)&mqtt_pub_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, mqtt_pub_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (client_handle == NULL) {
|
||||
ESP_LOGE(TAG, "mqtt client not connected");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((mqtt_pub_args.topic->count <= 0) || (mqtt_pub_args.message->count <= 0)) {
|
||||
ESP_LOGE(TAG, PUBLISH_HELP_MSG);
|
||||
}
|
||||
|
||||
msg_id = esp_mqtt_client_publish(client_handle,
|
||||
mqtt_pub_args.topic->sval[0],
|
||||
mqtt_pub_args.message->sval[0],
|
||||
0, 1, 0);
|
||||
if (msg_id == -1) {
|
||||
ESP_LOGE(TAG, "mqtt client not connected");
|
||||
return 0;
|
||||
}
|
||||
ESP_LOGI(TAG, "Publish successful, msg_id=%d, topic=%s, data=%s",
|
||||
msg_id, mqtt_pub_args.topic->sval[0], mqtt_pub_args.message->sval[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Registers the mqtt commands.
|
||||
*
|
||||
* @return
|
||||
* - esp_err_t
|
||||
*/
|
||||
esp_err_t console_cmd_mqtt_register(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
/* Register mqtt */
|
||||
mqtt_args.connect = arg_lit0("C", "connect", "Connect to a broker (flag, no argument)");
|
||||
mqtt_args.uri = arg_str0("h", "host", "<host>", "Specify the host uri to connect to");
|
||||
mqtt_args.status = arg_lit0("s", "status", "Displays the status of the mqtt client (flag, no argument)");
|
||||
mqtt_args.username = arg_str0("u", "username", "<username>", "Provide a username to be used for authenticating with the broker");
|
||||
mqtt_args.password = arg_str0("P", "password", "<password>", "Provide a password to be used for authenticating with the broker");
|
||||
mqtt_args.cert = arg_lit0(NULL, "cert", "Define the PEM encoded certificate for this client, if required by the broker (flag, no argument)");
|
||||
mqtt_args.key = arg_lit0(NULL, "key", "Define the PEM encoded private key for this client, if required by the broker (flag, no argument)");
|
||||
mqtt_args.cafile = arg_lit0(NULL, "cafile", "Define the PEM encoded CA certificates that are trusted (flag, no argument)");
|
||||
#if defined(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE)
|
||||
mqtt_args.use_internal_bundle = arg_lit0(NULL, "use-internal-bundle", "Use the internal certificate bundle for TLS (flag, no argument)");
|
||||
#endif
|
||||
mqtt_args.disconnect = arg_lit0("D", "disconnect", "Disconnect from the broker (flag, no argument)");
|
||||
mqtt_args.end = arg_end(1);
|
||||
|
||||
const esp_console_cmd_t mqtt_cmd = {
|
||||
.command = "mqtt",
|
||||
.help = "mqtt command",
|
||||
.hint = NULL,
|
||||
.func = &do_mqtt_cmd,
|
||||
.argtable = &mqtt_args
|
||||
};
|
||||
|
||||
ret = esp_console_cmd_register(&mqtt_cmd);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Unable to register mqtt");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Register mqtt_pub */
|
||||
mqtt_pub_args.topic = arg_str0("t", "topic", "<topic>", "Topic to Subscribe/Publish");
|
||||
mqtt_pub_args.message = arg_str0("m", "message", "<message>", "Message to Publish");
|
||||
mqtt_pub_args.end = arg_end(1);
|
||||
|
||||
const esp_console_cmd_t mqtt_pub_cmd = {
|
||||
.command = "mqtt_pub",
|
||||
.help = "mqtt publish command",
|
||||
.hint = NULL,
|
||||
.func = &do_mqtt_pub_cmd,
|
||||
.argtable = &mqtt_pub_args
|
||||
};
|
||||
|
||||
ret = esp_console_cmd_register(&mqtt_pub_cmd);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Unable to register mqtt_pub");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Register mqtt_sub */
|
||||
mqtt_sub_args.topic = arg_str0("t", "topic", "<topic>", "Topic to Subscribe/Publish");
|
||||
mqtt_sub_args.unsubscribe = arg_lit0("U", "unsubscribe", "Unsubscribe from a topic");
|
||||
mqtt_sub_args.end = arg_end(1);
|
||||
|
||||
const esp_console_cmd_t mqtt_sub_cmd = {
|
||||
.command = "mqtt_sub",
|
||||
.help = "mqtt subscribe command",
|
||||
.hint = NULL,
|
||||
.func = &do_mqtt_sub_cmd,
|
||||
.argtable = &mqtt_sub_args
|
||||
};
|
||||
|
||||
ret = esp_console_cmd_register(&mqtt_sub_cmd);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Unable to register mqtt_sub");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
73
components/console_cmd_mqtt/console_mqtt.h
Normal file
73
components/console_cmd_mqtt/console_mqtt.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "console_simple_init.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Registers the mqtt command.
|
||||
*
|
||||
* @return
|
||||
* - esp_err_t
|
||||
*/
|
||||
esp_err_t console_cmd_mqtt_register(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set MQTT client certificate
|
||||
*
|
||||
* This function sets the MQTT client certificate for secure communication.
|
||||
* The function takes the PEM(Privacy Enhanced Mail) encoded certificate arguments.
|
||||
*
|
||||
* @param client_cert_pem_start_i Pointer to the beginning of the client certificate PEM data.
|
||||
* @param client_cert_pem_end_i Pointer to the end of the client certificate PEM data.
|
||||
*
|
||||
* @return
|
||||
* ESP_OK on success
|
||||
* ESP_ERR_INVALID_ARG on invalid arguments
|
||||
*/
|
||||
esp_err_t set_mqtt_client_cert(const uint8_t *client_cert_pem_start_i, const uint8_t *client_cert_pem_end_i);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set MQTT client key
|
||||
*
|
||||
* This function sets the MQTT client key for secure communication.
|
||||
* The function takes the PEM(Privacy Enhanced Mail) encoded key arguments.
|
||||
*
|
||||
* @param client_key_pem_start_i Pointer to the beginning of the client key PEM data.
|
||||
* @param client_key_pem_end_i Pointer to the end of the client key PEM data.
|
||||
*
|
||||
* @return
|
||||
* ESP_OK on success
|
||||
* ESP_ERR_INVALID_ARG on invalid arguments
|
||||
*/
|
||||
esp_err_t set_mqtt_client_key(const uint8_t *client_key_pem_start_i, const uint8_t *client_key_pem_end_i);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set MQTT broker certificate
|
||||
*
|
||||
* This function sets the MQTT broker certificate for secure communication.
|
||||
* The function takes the PEM(Privacy Enhanced Mail) encoded broker certificate arguments.
|
||||
*
|
||||
* @param broker_cert_pem_start_i Pointer to the beginning of the broker certificate PEM data.
|
||||
* @param broker_cert_pem_end_i Pointer to the end of the broker certificate PEM data.
|
||||
*
|
||||
* @return
|
||||
* ESP_OK on success
|
||||
* ESP_ERR_INVALID_ARG on invalid arguments
|
||||
*/
|
||||
esp_err_t set_mqtt_broker_certs(const uint8_t *broker_cert_pem_start_i, const uint8_t *broker_cert_pem_end_i);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,11 @@
|
||||
# The following five lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(mqtt_ssl_auth_console)
|
||||
|
||||
# Certs for mqtts://test.mosquitto.org:8884
|
||||
target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "certs/client.crt" TEXT)
|
||||
target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "certs/client.key" TEXT)
|
||||
target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "certs/mosquitto.org.pem" TEXT)
|
@ -0,0 +1,174 @@
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||
|
||||
# ESP-MQTT SSL Authentication Console
|
||||
|
||||
This example demonstrates the use of the MQTT command-line component to connect to both secured and unsecured MQTT brokers. It provides multiple modes of connection, including:
|
||||
|
||||
* Unsecured transport: Connect to a broker without encryption.
|
||||
* SSL/TLS transport: Securely connect using SSL/TLS with options for:
|
||||
* Validating the broker using a provided CA certificate.
|
||||
* Validating the broker using the internal certificate bundle.
|
||||
* Performing SSL mutual authentication using client and broker certificates.
|
||||
|
||||
Additionally, the example allows subscribing to topics, unsubscribing from topics, and publishing messages to a specified topic through commands. Connections to the broker at test.mosquitto.org are used to demonstrate these features.
|
||||
(Please note that the public broker is maintained by the community so may not be always available, for details please visit http://test.mosquitto.org)
|
||||
|
||||
It uses ESP-MQTT library which implements mqtt client to connect to mqtt broker.
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
This example can be executed on any ESP32 board, the only required interface is WiFi and connection to internet.
|
||||
|
||||
### Configure the project
|
||||
|
||||
* Open the project configuration menu (`idf.py menuconfig`)
|
||||
* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details.
|
||||
|
||||
* Generate your client keys and certificate (specific to testing with Mosquitto broker)
|
||||
|
||||
Note: The following steps are for testing with the Mosquitto broker. If you're using a different broker, you may need to adapt the steps to meet your broker's certificate and key requirements.
|
||||
|
||||
#### Steps for SSL Mutual authentication:
|
||||
Navigate to the certs directory
|
||||
|
||||
```
|
||||
cd certs
|
||||
```
|
||||
|
||||
Generate a client key and a CSR. When you are generating the CSR, do not use the default values. At a minimum, the CSR must include the Country, Organisation and Common Name fields.
|
||||
|
||||
```
|
||||
openssl genrsa -out client.key
|
||||
openssl req -out client.csr -key client.key -new
|
||||
```
|
||||
|
||||
Paste the generated CSR in the [Mosquitto test certificate signer](https://test.mosquitto.org/ssl/index.php), click Submit and copy the downloaded `client.crt` in the `main` directory.
|
||||
|
||||
Please note, that the supplied files `client.crt` and `client.key` in the `main` directory are only placeholders for your client certificate and key (i.e. the example "as is" would compile but would not connect to the broker)
|
||||
|
||||
The broker certificate `mosquitto.org.pem` can be downloaded in pem format from [mosquitto.org.crt](https://test.mosquitto.org/ssl/mosquitto.org.crt). Convert it to `mosquitto.org.pem` simply by renaming it.
|
||||
|
||||
Note: If your certificate and key file names differ, update the root `CMakeLists.txt` file and main/`mqtt_ssl_auth_console.c` accordingly.
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||
|
||||
```
|
||||
idf.py -p PORT flash monitor
|
||||
```
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
Warning: This example might need a bigger app partition size if you're compiling it for debug. To ensere this issue doesn't happen "optimize for size is enabled in menuconfig.
|
||||
|
||||
### Command Usage:
|
||||
```
|
||||
esp> help
|
||||
help [<string>]
|
||||
Print the summary of all registered commands if no arguments are given,
|
||||
otherwise print summary of given command.
|
||||
<string> Name of command
|
||||
|
||||
mqtt [-CsD] [-h <host>] [-u <username>] [-P <password>] [--cert] [--key] [--cafile]
|
||||
mqtt command
|
||||
-C, --connect Connect to a broker (flag, no argument)
|
||||
-h, --host=<host> Specify the host uri to connect to
|
||||
-s, --status Displays the status of the mqtt client (flag, no argument)
|
||||
-u, --username=<username> Provide a username to be used for authenticating with the broker
|
||||
-P, --password=<password> Provide a password to be used for authenticating with the broker
|
||||
--cert Define the PEM encoded certificate for this client, if required by the broker (flag, no argument)
|
||||
--key Define the PEM encoded private key for this client, if required by the broker (flag, no argument)
|
||||
--cafile Define the PEM encoded CA certificates that are trusted (flag, no argument)
|
||||
--use-internal-bundle Use the internal certificate bundle for TLS (flag, no argument)
|
||||
-D, --disconnect Disconnect from the broker (flag, no argument)
|
||||
|
||||
mqtt_pub [-t <topic>] [-m <message>]
|
||||
mqtt publish command
|
||||
-t, --topic=<topic> Topic to Subscribe/Publish
|
||||
-m, --message=<message> Message to Publish
|
||||
|
||||
mqtt_sub [-U] [-t <topic>]
|
||||
mqtt subscribe command
|
||||
-t, --topic=<topic> Topic to Subscribe/Publish
|
||||
-U, --unsubscribe Unsubscribe from a topic
|
||||
```
|
||||
|
||||
### Connection:
|
||||
|
||||
#### Connect without Validating the Broker:
|
||||
This option connects to the broker without validating its certificate. It is not secure.
|
||||
```
|
||||
mqtt -h mqtts://test.mosquitto.org -C
|
||||
```
|
||||
or
|
||||
```
|
||||
mqtt -h mqtts://mqtt.eclipseprojects.io -C
|
||||
```
|
||||
|
||||
#### Validate the Broker using the Internal Certificate Bundle:
|
||||
This option uses the ESP-IDF's built-in certificate bundle to verify the broker's identity.
|
||||
```
|
||||
mqtt -h mqtts://mqtt.eclipseprojects.io -C --use-internal-bundle
|
||||
```
|
||||
or
|
||||
```
|
||||
mqtt -h mqtts://test.mosquitto.org -C --use-internal-bundle
|
||||
```
|
||||
|
||||
#### Validate the Broker using a Provided CA Certificate:
|
||||
This option requires you to provide the broker's CA certificate for validation.
|
||||
```
|
||||
mqtt -h mqtts://test.mosquitto.org -C --cafile
|
||||
```
|
||||
|
||||
|
||||
#### SSL Mutual Authentication(encrypted, client certificate required):
|
||||
This option performs client authentication in addition to broker validation. It requires the client certificate, private key, and broker CA certificate.
|
||||
```
|
||||
mqtt -h mqtts://test.mosquitto.org:8884 -C --cert --key --cafile
|
||||
```
|
||||
or
|
||||
```
|
||||
mqtt -h mqtts://test.mosquitto.org:8884 -C --cert --key --use-internal-bundle
|
||||
```
|
||||
|
||||
Note: In this example, the broker's certificate is included in the certificate bundle (refer to sdkconfig.default).
|
||||
|
||||
### Disconnect:
|
||||
```
|
||||
esp> mqtt -D
|
||||
I (1189949) console_mqtt: mqtt client disconnected
|
||||
```
|
||||
|
||||
### Subscribe/Unsubscribe:
|
||||
```
|
||||
esp> mqtt_sub -t test0
|
||||
I (897289) console_mqtt: Subscribe successful, msg_id=57425, topic=test0
|
||||
esp> I (897799) console_mqtt: MQTT_EVENT_SUBSCRIBED, msg_id=57425
|
||||
esp>
|
||||
esp> mqtt_sub -U -t test0
|
||||
I (902009) console_mqtt: Unsubscribe successful, msg_id=27663, topic=test0
|
||||
esp> I (902509) console_mqtt: MQTT_EVENT_UNSUBSCRIBED, msg_id=27663
|
||||
```
|
||||
|
||||
### Publish:
|
||||
```
|
||||
esp> mqtt_pub -t test0 -m "Hello, Testing 123"
|
||||
I (999469) console_mqtt: Publish successful, msg_id=55776, topic=test0, data=Hello, Testing 123
|
||||
I (1000009) console_mqtt: MQTT_EVENT_PUBLISHED, msg_id=55776
|
||||
esp>
|
||||
```
|
||||
|
||||
### Receiving data event:
|
||||
```
|
||||
esp> I (999999) console_mqtt: MQTT_EVENT_DATA
|
||||
I (999999) console_mqtt: TOPIC=test0
|
||||
|
||||
I (999999) console_mqtt: DATA=Hello, Testing 123
|
||||
```
|
@ -0,0 +1,24 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEAzCCAuugAwIBAgIUBY1hlCGvdj4NhBXkZ/uLUZNILAwwDQYJKoZIhvcNAQEL
|
||||
BQAwgZAxCzAJBgNVBAYTAkdCMRcwFQYDVQQIDA5Vbml0ZWQgS2luZ2RvbTEOMAwG
|
||||
A1UEBwwFRGVyYnkxEjAQBgNVBAoMCU1vc3F1aXR0bzELMAkGA1UECwwCQ0ExFjAU
|
||||
BgNVBAMMDW1vc3F1aXR0by5vcmcxHzAdBgkqhkiG9w0BCQEWEHJvZ2VyQGF0Y2hv
|
||||
by5vcmcwHhcNMjAwNjA5MTEwNjM5WhcNMzAwNjA3MTEwNjM5WjCBkDELMAkGA1UE
|
||||
BhMCR0IxFzAVBgNVBAgMDlVuaXRlZCBLaW5nZG9tMQ4wDAYDVQQHDAVEZXJieTES
|
||||
MBAGA1UECgwJTW9zcXVpdHRvMQswCQYDVQQLDAJDQTEWMBQGA1UEAwwNbW9zcXVp
|
||||
dHRvLm9yZzEfMB0GCSqGSIb3DQEJARYQcm9nZXJAYXRjaG9vLm9yZzCCASIwDQYJ
|
||||
KoZIhvcNAQEBBQADggEPADCCAQoCggEBAME0HKmIzfTOwkKLT3THHe+ObdizamPg
|
||||
UZmD64Tf3zJdNeYGYn4CEXbyP6fy3tWc8S2boW6dzrH8SdFf9uo320GJA9B7U1FW
|
||||
Te3xda/Lm3JFfaHjkWw7jBwcauQZjpGINHapHRlpiCZsquAthOgxW9SgDgYlGzEA
|
||||
s06pkEFiMw+qDfLo/sxFKB6vQlFekMeCymjLCbNwPJyqyhFmPWwio/PDMruBTzPH
|
||||
3cioBnrJWKXc3OjXdLGFJOfj7pP0j/dr2LH72eSvv3PQQFl90CZPFhrCUcRHSSxo
|
||||
E6yjGOdnz7f6PveLIB574kQORwt8ePn0yidrTC1ictikED3nHYhMUOUCAwEAAaNT
|
||||
MFEwHQYDVR0OBBYEFPVV6xBUFPiGKDyo5V3+Hbh4N9YSMB8GA1UdIwQYMBaAFPVV
|
||||
6xBUFPiGKDyo5V3+Hbh4N9YSMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
|
||||
BQADggEBAGa9kS21N70ThM6/Hj9D7mbVxKLBjVWe2TPsGfbl3rEDfZ+OKRZ2j6AC
|
||||
6r7jb4TZO3dzF2p6dgbrlU71Y/4K0TdzIjRj3cQ3KSm41JvUQ0hZ/c04iGDg/xWf
|
||||
+pp58nfPAYwuerruPNWmlStWAXf0UTqRtg4hQDWBuUFDJTuWuuBvEXudz74eh/wK
|
||||
sMwfu1HFvjy5Z0iMDU8PUDepjVolOCue9ashlS4EB5IECdSR2TItnAIiIwimx839
|
||||
LdUdRudafMu5T5Xma182OC0/u/xRlEm+tvKGGmfFcN0piqVl8OrSPBgIlb+1IKJE
|
||||
m/XriWr/Cq4h/JfB7NTsezVslgkBaoU=
|
||||
-----END CERTIFICATE-----
|
@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "mqtt_ssl_auth_console.c"
|
||||
INCLUDE_DIRS ".")
|
@ -0,0 +1,8 @@
|
||||
dependencies:
|
||||
idf:
|
||||
version: ">=5.0"
|
||||
protocol_examples_common:
|
||||
path: ${IDF_PATH}/examples/common_components/protocol_examples_common
|
||||
console_cmd_mqtt:
|
||||
version: "*"
|
||||
override_path: '../../../'
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_event.h"
|
||||
#include <netdb.h>
|
||||
#include "console_mqtt.h"
|
||||
#include "protocol_examples_common.h"
|
||||
|
||||
// Certs for mqtts://test.mosquitto.org:8884
|
||||
extern const uint8_t g_client_cert_pem_start[] asm("_binary_client_crt_start");
|
||||
extern const uint8_t g_client_cert_pem_end[] asm("_binary_client_crt_end");
|
||||
extern const uint8_t g_client_key_pem_start[] asm("_binary_client_key_start");
|
||||
extern const uint8_t g_client_key_pem_end[] asm("_binary_client_key_end");
|
||||
extern const uint8_t g_broker_cert_pem_start[] asm("_binary_mosquitto_org_pem_start");
|
||||
extern const uint8_t g_broker_cert_pem_end[] asm("_binary_mosquitto_org_pem_end");
|
||||
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
esp_err_t ret = nvs_flash_init(); //Initialize NVS
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
|
||||
* Read "Establishing Wi-Fi or Ethernet Connection" section in
|
||||
* ${IDF_PATH}/examples/protocols/README.md for more information about this function.
|
||||
*/
|
||||
ESP_ERROR_CHECK(example_connect());
|
||||
|
||||
// Initialize console REPL
|
||||
ESP_ERROR_CHECK(console_cmd_init());
|
||||
ESP_ERROR_CHECK(console_cmd_all_register());
|
||||
|
||||
set_mqtt_client_cert(g_client_cert_pem_start, g_client_cert_pem_end);
|
||||
set_mqtt_client_key(g_client_key_pem_start, g_client_key_pem_end);
|
||||
set_mqtt_broker_certs(g_broker_cert_pem_start, g_broker_cert_pem_end);
|
||||
|
||||
// start console REPL
|
||||
ESP_ERROR_CHECK(console_cmd_start());
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.esp32
|
||||
def test_examples_ifconfig_command(dut):
|
||||
dut.expect('esp>', timeout=30)
|
||||
dut.write('help mqtt')
|
||||
dut.expect(r'mqtt \[-CsD\] \[-h <host>\] \[-u <username>\] \[-P <password>\] \[--cert\] \[--key\] \[--cafile\]', timeout=30)
|
||||
|
||||
dut.write('help mqtt_pub')
|
||||
dut.expect(r'mqtt_pub \[-t <topic>\] \[-m <message>\]', timeout=30)
|
||||
|
||||
dut.write('help mqtt_sub')
|
||||
dut.expect(r'mqtt_sub \[-U\] \[-t <topic>\]', timeout=30)
|
@ -0,0 +1,7 @@
|
||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||
# Espressif IoT Development Framework (ESP-IDF) 5.5.0 Project Minimal Configuration
|
||||
#
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y
|
||||
CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE=y
|
||||
CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="certs/mosquitto.org.pem"
|
11
components/console_cmd_mqtt/idf_component.yml
Normal file
11
components/console_cmd_mqtt/idf_component.yml
Normal file
@ -0,0 +1,11 @@
|
||||
version: 1.0.0
|
||||
url: https://github.com/espressif/esp-protocols/tree/master/components/console_cmd_mqtt
|
||||
description: The component provides a console where the 'mqtt' command can be executed.
|
||||
license: Apache-2.0
|
||||
dependencies:
|
||||
idf:
|
||||
version: '>=5.0'
|
||||
espressif/console_simple_init:
|
||||
version: '>=1.1.0'
|
||||
override_path: '../console_simple_init'
|
||||
public: true
|
@ -3,6 +3,6 @@ commitizen:
|
||||
bump_message: 'bump(console): $current_version -> $new_version'
|
||||
pre_bump_hooks: python ../../ci/changelog.py console_cmd_ping
|
||||
tag_format: console_cmd_ping-v$version
|
||||
version: 1.0.0
|
||||
version: 1.1.0
|
||||
version_files:
|
||||
- idf_component.yml
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Changelog
|
||||
|
||||
## [1.1.0](https://github.com/espressif/esp-protocols/commits/console_cmd_ping-v1.1.0)
|
||||
|
||||
### Features
|
||||
|
||||
- Added command getaddrinfo, set/get dnsserver to console_cmd_ping ([b80c19d7](https://github.com/espressif/esp-protocols/commit/b80c19d7))
|
||||
|
||||
## [1.0.0](https://github.com/espressif/esp-protocols/commits/console_cmd_ping-v1.0.0)
|
||||
|
||||
### Features
|
||||
|
@ -1,4 +1,10 @@
|
||||
idf_component_register(SRCS "console_ping.c"
|
||||
idf_component_register(SRCS "console_ping.c" "console_getaddrinfo.c" "console_getsetdnsserver.c"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES esp_netif console
|
||||
WHOLE_ARCHIVE)
|
||||
PRIV_REQUIRES esp_netif console)
|
||||
|
||||
if(CONFIG_PING_CMD_AUTO_REGISTRATION)
|
||||
target_link_libraries(${COMPONENT_LIB} "-u console_cmd_ping_register")
|
||||
target_link_libraries(${COMPONENT_LIB} "-u console_cmd_getaddrinfo_register")
|
||||
target_link_libraries(${COMPONENT_LIB} "-u console_cmd_setdnsserver_register")
|
||||
target_link_libraries(${COMPONENT_LIB} "-u console_cmd_getdnsserver_register")
|
||||
endif()
|
||||
|
9
components/console_cmd_ping/Kconfig.projbuild
Normal file
9
components/console_cmd_ping/Kconfig.projbuild
Normal file
@ -0,0 +1,9 @@
|
||||
menu "Ping command Configuration"
|
||||
|
||||
config PING_CMD_AUTO_REGISTRATION
|
||||
bool "Enable Console command ping/dns Auto-registration"
|
||||
default y
|
||||
help
|
||||
Enabling this allows for the autoregistration of the ping and dns commands.
|
||||
|
||||
endmenu
|
@ -1,5 +1,5 @@
|
||||
# Console command ping
|
||||
The component provides a console where the 'ping' command can be executed.
|
||||
# Console command ping and DNS server configuration
|
||||
The component provides a console where the 'ping' command, 'getaddrinfo', and DNS server configuration commands can be executed.
|
||||
|
||||
## API
|
||||
|
||||
@ -27,8 +27,11 @@ The component provides a console where the 'ping' command can be executed.
|
||||
// Register all plugin command added to your project
|
||||
ESP_ERROR_CHECK(console_cmd_all_register());
|
||||
|
||||
// To register only ifconfig command skip calling console_cmd_all_register()
|
||||
// To register only ping/dns command skip calling console_cmd_all_register()
|
||||
ESP_ERROR_CHECK(console_cmd_ping_register());
|
||||
ESP_ERROR_CHECK(console_cmd_getaddrinfo_register());
|
||||
ESP_ERROR_CHECK(console_cmd_setdnsserver_register());
|
||||
ESP_ERROR_CHECK(console_cmd_getdnsserver_register());
|
||||
|
||||
ESP_ERROR_CHECK(console_cmd_start()); // Start console
|
||||
```
|
||||
@ -36,6 +39,8 @@ The component provides a console where the 'ping' command can be executed.
|
||||
### Adding a plugin command or component:
|
||||
To add a plugin command or any component from IDF component manager into your project, simply include an entry within the `idf_component.yml` file.
|
||||
|
||||
Note: **Auto-registration** of a specific plugin command can be disabled from menuconfig.
|
||||
|
||||
For more details refer [IDF Component Manager](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-component-manager.html)
|
||||
|
||||
|
||||
@ -52,4 +57,72 @@ ping [-W <t>] [-i <t>] [-s <n>] [-c <n>] [-Q <n>] [-T <n>] <host>
|
||||
-Q, --tos=<n> Set Type of Service related bits in IP datagrams
|
||||
-T, --ttl=<n> Set Time to Live related bits in IP datagrams
|
||||
<host> Host address
|
||||
|
||||
getaddrinfo [-f <AF>] [-F <FLAGS>]... [-p <port>] <hostname>
|
||||
Usage: getaddrinfo [options] <hostname> [service]
|
||||
-f, --family=<AF> Address family (AF_INET, AF_INET6, AF_UNSPEC).
|
||||
-F, --flags=<FLAGS> Special flags (AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST, AI_V4MAPPED, AI_ALL).
|
||||
-p, --port=<port> String containing a numeric port number.
|
||||
<hostname> Host address
|
||||
|
||||
setdnsserver <main> [backup] [fallback]
|
||||
Usage: setdnsserver <main> [backup] [fallback]
|
||||
<main> The main DNS server IP address.
|
||||
backup The secondary DNS server IP address (optional).
|
||||
fallback The fallback DNS server IP address (optional).
|
||||
|
||||
getdnsserver
|
||||
Usage: getdnsserver
|
||||
```
|
||||
These commands allow you to configure and retrieve DNS server settings on your ESP32 device, in addition to the existing ping functionality.
|
||||
|
||||
## Usage
|
||||
### Using the setdnsserver command:
|
||||
1. To set the main DNS server:
|
||||
```
|
||||
setdnsserver 8.8.8.8
|
||||
```
|
||||
|
||||
2. To set the main and backup DNS servers:
|
||||
|
||||
```
|
||||
setdnsserver 8.8.8.8 fe80::b0be:83ff:fe77:dd64
|
||||
```
|
||||
|
||||
3. To set the main, backup, and fallback DNS servers:
|
||||
|
||||
```
|
||||
setdnsserver 8.8.8.8 fe80::b0be:83ff:fe77:dd64 www.xyz.com
|
||||
```
|
||||
|
||||
### Using the getdnsserver command:
|
||||
To get the current DNS server settings:
|
||||
```
|
||||
getdnsserver
|
||||
```
|
||||
|
||||
### Using the getaddrinfo command:
|
||||
1. To get address information for a hostname:
|
||||
|
||||
```
|
||||
getaddrinfo www.example.com
|
||||
```
|
||||
|
||||
2. To specify additional options:
|
||||
|
||||
```
|
||||
getaddrinfo -f AF_INET -F AI_PASSIVE www.example.com
|
||||
```
|
||||
|
||||
### Using the ping command:
|
||||
1. To ping a host:
|
||||
|
||||
```
|
||||
ping www.example.com
|
||||
```
|
||||
|
||||
2. To specify additional options, such as timeout, interval, packet size, etc.:
|
||||
|
||||
```
|
||||
ping -W 5 -i 1 -s 64 -c 4 -Q 0x10 -T 64 www.example.com
|
||||
```
|
||||
|
180
components/console_cmd_ping/console_getaddrinfo.c
Normal file
180
components/console_cmd_ping/console_getaddrinfo.c
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netdb.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_log.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include <netdb.h>
|
||||
#include "console_ping.h"
|
||||
|
||||
|
||||
static const char *TAG = "console_getaddrinfo";
|
||||
|
||||
#if CONFIG_PING_CMD_AUTO_REGISTRATION
|
||||
/**
|
||||
* @brief Static registration of the getaddrinfo command plugin.
|
||||
*
|
||||
* This section registers the plugin description structure and places it into
|
||||
* the .console_cmd_desc section, as determined by the linker.lf file in the
|
||||
* 'plugins' component.
|
||||
*/
|
||||
static const console_cmd_plugin_desc_t __attribute__((section(".console_cmd_desc"), used)) PLUGIN = {
|
||||
.name = "console_cmd_getddrinfo",
|
||||
.plugin_regd_fn = &console_cmd_getaddrinfo_register
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Structure to hold arguments for the getaddrinfo command.
|
||||
*/
|
||||
static struct {
|
||||
struct arg_str *family;
|
||||
struct arg_str *flags;
|
||||
struct arg_str *port_nr;
|
||||
struct arg_str *hostname;
|
||||
struct arg_end *end;
|
||||
} getddrinfo_args;
|
||||
|
||||
/**
|
||||
* @brief Executes the getaddrinfo command.
|
||||
*
|
||||
* This function parses arguments, sets hints for address resolution, and calls
|
||||
* getaddrinfo to resolve the hostname. It then prints the resolved IP addresses
|
||||
* and associated information.
|
||||
*
|
||||
* @param argc Argument count
|
||||
* @param argv Argument vector
|
||||
*
|
||||
* @return int Returns 0 on success, 1 on error.
|
||||
*/
|
||||
static int do_getddrinfo_cmd(int argc, char **argv)
|
||||
{
|
||||
char ip_str[INET6_ADDRSTRLEN];
|
||||
struct addrinfo hint = {0};
|
||||
struct addrinfo *res = NULL, *res_tmp = NULL;
|
||||
const char *port_nr_str = NULL;
|
||||
int ret = 0;
|
||||
|
||||
int nerrors = arg_parse(argc, argv, (void **)&getddrinfo_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, getddrinfo_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Set the address family */
|
||||
if (getddrinfo_args.family->count > 0) {
|
||||
if (strcmp(getddrinfo_args.family->sval[0], "AF_INET") == 0) {
|
||||
hint.ai_family = AF_INET;
|
||||
} else if (strcmp(getddrinfo_args.family->sval[0], "AF_INET6") == 0) {
|
||||
hint.ai_family = AF_INET6;
|
||||
} else if (strcmp(getddrinfo_args.family->sval[0], "AF_UNSPEC") == 0) {
|
||||
hint.ai_family = AF_UNSPEC;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Unknown family");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the flags */
|
||||
if (getddrinfo_args.flags->count > 0) {
|
||||
for (int i = 0; i < getddrinfo_args.flags->count; i++) {
|
||||
if (strcmp(getddrinfo_args.flags->sval[i], "AI_PASSIVE") == 0) {
|
||||
hint.ai_flags |= AI_PASSIVE;
|
||||
} else if (strcmp(getddrinfo_args.flags->sval[i], "AI_CANONNAME") == 0) {
|
||||
hint.ai_flags |= AI_CANONNAME;
|
||||
} else if (strcmp(getddrinfo_args.flags->sval[i], "AI_NUMERICHOST") == 0) {
|
||||
hint.ai_flags |= AI_NUMERICHOST;
|
||||
} else if (strcmp(getddrinfo_args.flags->sval[i], "AI_V4MAPPED") == 0) {
|
||||
hint.ai_flags |= AI_V4MAPPED;
|
||||
} else if (strcmp(getddrinfo_args.flags->sval[i], "AI_ALL") == 0) {
|
||||
hint.ai_flags |= AI_ALL;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Unknown flag: %s", getddrinfo_args.flags->sval[i]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getddrinfo_args.port_nr->count > 0) {
|
||||
port_nr_str = getddrinfo_args.port_nr->sval[0];
|
||||
}
|
||||
|
||||
/* Convert hostname to IP address */
|
||||
if (!strcmp(getddrinfo_args.hostname->sval[0], "NULL")) {
|
||||
ret = getaddrinfo(NULL, port_nr_str, &hint, &res);
|
||||
} else {
|
||||
ret = getaddrinfo(getddrinfo_args.hostname->sval[0], port_nr_str, &hint, &res);
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
printf("getddrinfo: Failure host:%s(ERROR: %d)\n", getddrinfo_args.hostname->sval[0], ret);
|
||||
ESP_LOGE(TAG, "Failure host");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Iterate through the results from getaddrinfo */
|
||||
for (res_tmp = res; res_tmp != NULL; res_tmp = res_tmp->ai_next) {
|
||||
|
||||
if (res_tmp->ai_family == AF_INET) {
|
||||
inet_ntop(AF_INET, &((struct sockaddr_in *)res_tmp->ai_addr)->sin_addr, ip_str, INET_ADDRSTRLEN);
|
||||
printf("\tIP Address: %s\n", ip_str);
|
||||
printf("\tAddress Family: AF_INET\n");
|
||||
} else if (res_tmp->ai_family == AF_INET6) {
|
||||
inet_ntop(AF_INET6, &((struct sockaddr_in6 *)res_tmp->ai_addr)->sin6_addr, ip_str, INET6_ADDRSTRLEN);
|
||||
printf("\tIP Address: %s\n", ip_str);
|
||||
printf("\tAddress Family: AF_INET6\n");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "ai_family Unknown: %d\n", res_tmp->ai_family);
|
||||
}
|
||||
|
||||
/* Print the protocol used */
|
||||
printf("\tProtocol: %d\n", res_tmp->ai_protocol);
|
||||
|
||||
/* Print the canonical name if available */
|
||||
if (res_tmp->ai_canonname) {
|
||||
printf("\tCanonical Name: %s\n", res_tmp->ai_canonname);
|
||||
}
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Registers the getaddrinfo command.
|
||||
*
|
||||
* @return esp_err_t Returns ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t console_cmd_getaddrinfo_register(void)
|
||||
{
|
||||
esp_err_t ret;
|
||||
|
||||
getddrinfo_args.family = arg_str0("f", "family", "<AF>", "Address family (AF_INET, AF_INET6, AF_UNSPEC).");
|
||||
getddrinfo_args.flags = arg_strn("F", "flags", "<FLAGS>", 0, 5, "Special flags (AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST, AI_V4MAPPED, AI_ALL).");
|
||||
getddrinfo_args.port_nr = arg_str0("p", "port", "<port>", "String containing a numeric port number.");
|
||||
getddrinfo_args.hostname = arg_str1(NULL, NULL, "<hostname>", "Host address");
|
||||
getddrinfo_args.end = arg_end(1);
|
||||
const esp_console_cmd_t getddrinfo_cmd = {
|
||||
.command = "getaddrinfo",
|
||||
.help = "Usage: getaddrinfo [options] <hostname> [service]",
|
||||
.hint = NULL,
|
||||
.func = &do_getddrinfo_cmd,
|
||||
.argtable = &getddrinfo_args
|
||||
};
|
||||
|
||||
ret = esp_console_cmd_register(&getddrinfo_cmd);
|
||||
if (ret) {
|
||||
ESP_LOGE(TAG, "Unable to register getddrinfo");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
279
components/console_cmd_ping/console_getsetdnsserver.c
Normal file
279
components/console_cmd_ping/console_getsetdnsserver.c
Normal file
@ -0,0 +1,279 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netdb.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_netif.h"
|
||||
#include "lwip/netdb.h"
|
||||
#include "esp_log.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include <netdb.h>
|
||||
#include "console_ping.h"
|
||||
|
||||
|
||||
static const char *TAG = "console_setdnsserver";
|
||||
|
||||
#if CONFIG_PING_CMD_AUTO_REGISTRATION
|
||||
static esp_err_t console_cmd_dnscmd_register(void);
|
||||
|
||||
/**
|
||||
* @brief Static registration of the getaddrinfo command plugin.
|
||||
*
|
||||
* This section registers the plugin description structure and places it into
|
||||
* the .console_cmd_desc section, as determined by the linker.lf file in the
|
||||
* 'plugins' component.
|
||||
*/
|
||||
static const console_cmd_plugin_desc_t __attribute__((section(".console_cmd_desc"), used)) PLUGIN = {
|
||||
.name = "console_cmd_dnscmd",
|
||||
.plugin_regd_fn = &console_cmd_dnscmd_register
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Registers the DNS commands (setdnsserver and getdnsserver) with the console.
|
||||
*
|
||||
* @return esp_err_t Returns ESP_OK.
|
||||
*/
|
||||
static esp_err_t console_cmd_dnscmd_register(void)
|
||||
{
|
||||
console_cmd_setdnsserver_register();
|
||||
console_cmd_getdnsserver_register();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Structure to hold arguments for the setdnsserver command.
|
||||
*/
|
||||
static struct {
|
||||
struct arg_str *main;
|
||||
struct arg_str *backup;
|
||||
struct arg_str *fallback;
|
||||
struct arg_end *end;
|
||||
} setdnsserver_args;
|
||||
|
||||
/**
|
||||
* @brief Sets the DNS server address for all network interfaces.
|
||||
*
|
||||
* This function iterates over all network interfaces available on the ESP32 device
|
||||
* and sets the DNS server address for the specified DNS type (main, backup, or fallback).
|
||||
* The DNS address is only set if a valid address is provided (non-zero and not equal to IPADDR_NONE).
|
||||
*
|
||||
* @param server IP address of the DNS server.
|
||||
* @param type Type of the DNS server (main, backup, fallback).
|
||||
*
|
||||
* @return esp_err_t Returns ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
static esp_err_t set_dns_server(const char *server, esp_netif_dns_type_t type)
|
||||
{
|
||||
int ret = 0;
|
||||
struct addrinfo hint = {0};
|
||||
struct addrinfo *res = NULL, *res_tmp = NULL;
|
||||
esp_netif_t *esp_netif = NULL;
|
||||
esp_netif_dns_info_t dns;
|
||||
int addr_cnt = 0;
|
||||
|
||||
ret = getaddrinfo(server, NULL, &hint, &res);
|
||||
if (ret != 0) {
|
||||
printf("setdnsserver: Failure host:%s(ERROR: %d)\n", server, ret);
|
||||
ESP_LOGE(TAG, "Failure host");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (res_tmp = res; res_tmp != NULL; res_tmp = res_tmp->ai_next) {
|
||||
|
||||
if (addr_cnt == 0) {
|
||||
if (res_tmp->ai_family == AF_INET) {
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
|
||||
while ((esp_netif = esp_netif_next_unsafe(esp_netif)) != NULL) {
|
||||
#else
|
||||
while ((esp_netif = esp_netif_next(esp_netif)) != NULL) {
|
||||
#endif
|
||||
struct sockaddr_in *ipv4 = (struct sockaddr_in *)res_tmp->ai_addr;
|
||||
dns.ip.u_addr.ip4.addr = ipv4->sin_addr.s_addr;
|
||||
dns.ip.type = IPADDR_TYPE_V4;
|
||||
ESP_ERROR_CHECK(esp_netif_set_dns_info(esp_netif, type, &dns));
|
||||
}
|
||||
} else if (res_tmp->ai_family == AF_INET6) {
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
|
||||
while ((esp_netif = esp_netif_next_unsafe(esp_netif)) != NULL) {
|
||||
#else
|
||||
while ((esp_netif = esp_netif_next(esp_netif)) != NULL) {
|
||||
#endif
|
||||
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)res_tmp->ai_addr;
|
||||
memcpy(dns.ip.u_addr.ip6.addr, &ipv6->sin6_addr, sizeof(dns.ip.u_addr.ip6.addr));
|
||||
dns.ip.type = IPADDR_TYPE_V6;
|
||||
ESP_ERROR_CHECK(esp_netif_set_dns_info(esp_netif, type, &dns));
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "ai_family Unknown: %d\n", res_tmp->ai_family);
|
||||
}
|
||||
}
|
||||
addr_cnt++;
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Command handler for setting DNS server addresses.
|
||||
*
|
||||
* @param argc Argument count.
|
||||
* @param argv Argument values.
|
||||
*
|
||||
* @return int: 0 on success, 1 on error.
|
||||
*/
|
||||
static int do_setdnsserver_cmd(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **)&setdnsserver_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, setdnsserver_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
set_dns_server(setdnsserver_args.main->sval[0], ESP_NETIF_DNS_MAIN);
|
||||
|
||||
if (setdnsserver_args.backup->count > 0) {
|
||||
set_dns_server(setdnsserver_args.backup->sval[0], ESP_NETIF_DNS_BACKUP);
|
||||
}
|
||||
|
||||
if (setdnsserver_args.fallback->count > 0) {
|
||||
set_dns_server(setdnsserver_args.fallback->sval[0], ESP_NETIF_DNS_FALLBACK);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Registers the setdnsserver command.
|
||||
*
|
||||
* @return esp_err_t Returns ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t console_cmd_setdnsserver_register(void)
|
||||
{
|
||||
esp_err_t ret;
|
||||
|
||||
setdnsserver_args.main = arg_str1(NULL, NULL, "<main>", "The main DNS server IP address.");
|
||||
setdnsserver_args.backup = arg_str0(NULL, NULL, "backup", "The secondary DNS server IP address (optional).");
|
||||
setdnsserver_args.fallback = arg_str0(NULL, NULL, "fallback", "The fallback DNS server IP address (optional).");
|
||||
setdnsserver_args.end = arg_end(1);
|
||||
const esp_console_cmd_t setdnsserver_cmd = {
|
||||
.command = "setdnsserver",
|
||||
.help = "Usage: setdnsserver <main> [backup] [fallback]",
|
||||
.hint = NULL,
|
||||
.func = &do_setdnsserver_cmd,
|
||||
.argtable = &setdnsserver_args
|
||||
};
|
||||
|
||||
ret = esp_console_cmd_register(&setdnsserver_cmd);
|
||||
if (ret) {
|
||||
ESP_LOGE(TAG, "Unable to register setdnsserver");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Structure to hold arguments for the getdnsserver command.
|
||||
*/
|
||||
static struct {
|
||||
struct arg_end *end;
|
||||
} getdnsserver_args;
|
||||
|
||||
/**
|
||||
* @brief Command handler for getting DNS server addresses.
|
||||
*
|
||||
* @param argc Argument count.
|
||||
* @param argv Argument values.
|
||||
*
|
||||
* @return int: 0 on success, 1 on error.
|
||||
*/
|
||||
static int do_getdnsserver_cmd(int argc, char **argv)
|
||||
{
|
||||
esp_netif_t *esp_netif = NULL;
|
||||
esp_netif_dns_info_t dns_info;
|
||||
char interface[10];
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
|
||||
int nerrors = arg_parse(argc, argv, (void **)&getdnsserver_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, getdnsserver_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
|
||||
while ((esp_netif = esp_netif_next_unsafe(esp_netif)) != NULL) {
|
||||
#else
|
||||
while ((esp_netif = esp_netif_next(esp_netif)) != NULL) {
|
||||
#endif
|
||||
|
||||
/* Print Interface Name and Number */
|
||||
ret = esp_netif_get_netif_impl_name(esp_netif, interface);
|
||||
if ((ESP_FAIL == ret) || (NULL == esp_netif)) {
|
||||
ESP_LOGE(TAG, "No interface available");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Interface Name: %s\n", interface);
|
||||
ESP_ERROR_CHECK(esp_netif_get_dns_info(esp_netif, ESP_NETIF_DNS_MAIN, &dns_info));
|
||||
if (dns_info.ip.type == ESP_IPADDR_TYPE_V4) {
|
||||
printf("Main DNS server : " IPSTR "\n", IP2STR(&dns_info.ip.u_addr.ip4));
|
||||
} else if (dns_info.ip.type == ESP_IPADDR_TYPE_V6) {
|
||||
printf("Main DNS server : " IPV6STR "\n", IPV62STR(dns_info.ip.u_addr.ip6));
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(esp_netif_get_dns_info(esp_netif, ESP_NETIF_DNS_BACKUP, &dns_info));
|
||||
if (dns_info.ip.type == ESP_IPADDR_TYPE_V4) {
|
||||
printf("Backup DNS server : " IPSTR "\n", IP2STR(&dns_info.ip.u_addr.ip4));
|
||||
} else if (dns_info.ip.type == ESP_IPADDR_TYPE_V6) {
|
||||
printf("Backup DNS server : " IPV6STR "\n", IPV62STR(dns_info.ip.u_addr.ip6));
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(esp_netif_get_dns_info(esp_netif, ESP_NETIF_DNS_FALLBACK, &dns_info));
|
||||
if (dns_info.ip.type == ESP_IPADDR_TYPE_V4) {
|
||||
printf("Fallback DNS server : " IPSTR "\n", IP2STR(&dns_info.ip.u_addr.ip4));
|
||||
} else if (dns_info.ip.type == ESP_IPADDR_TYPE_V6) {
|
||||
printf("Fallback DNS server : " IPV6STR "\n", IPV62STR(dns_info.ip.u_addr.ip6));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Registers the getdnsserver command.
|
||||
*
|
||||
* @return esp_err_t Returns ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t console_cmd_getdnsserver_register(void)
|
||||
{
|
||||
esp_err_t ret;
|
||||
|
||||
getdnsserver_args.end = arg_end(1);
|
||||
const esp_console_cmd_t getdnsserver_cmd = {
|
||||
.command = "getdnsserver",
|
||||
.help = "Usage: getdnsserver",
|
||||
.hint = NULL,
|
||||
.func = &do_getdnsserver_cmd,
|
||||
.argtable = &getdnsserver_args
|
||||
};
|
||||
|
||||
ret = esp_console_cmd_register(&getdnsserver_cmd);
|
||||
if (ret) {
|
||||
ESP_LOGE(TAG, "Unable to register getdnsserver");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -20,7 +20,7 @@
|
||||
static const char *TAG = "console_ping";
|
||||
SemaphoreHandle_t sync_semaphore;
|
||||
|
||||
|
||||
#if CONFIG_PING_CMD_AUTO_REGISTRATION
|
||||
/**
|
||||
* Static registration of this plugin is achieved by defining the plugin description
|
||||
* structure and placing it into .console_cmd_desc section.
|
||||
@ -30,7 +30,7 @@ static const console_cmd_plugin_desc_t __attribute__((section(".console_cmd_desc
|
||||
.name = "console_cmd_ping",
|
||||
.plugin_regd_fn = &console_cmd_ping_register
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static void cmd_ping_on_ping_success(esp_ping_handle_t hdl, void *args)
|
||||
{
|
||||
@ -75,9 +75,13 @@ static void cmd_ping_on_ping_end(esp_ping_handle_t hdl, void *args)
|
||||
loss = 0;
|
||||
}
|
||||
if (IP_IS_V4(&target_addr)) {
|
||||
#if CONFIG_LWIP_IPV4
|
||||
printf("\n--- %s ping statistics ---\n", inet_ntoa(*ip_2_ip4(&target_addr)));
|
||||
#endif
|
||||
} else {
|
||||
#if CONFIG_LWIP_IPV6
|
||||
printf("\n--- %s ping statistics ---\n", inet6_ntoa(*ip_2_ip6(&target_addr)));
|
||||
#endif
|
||||
}
|
||||
printf("%" PRIu32 " packets transmitted, %" PRIu32 " received, %" PRIu32 "%% packet loss, time %" PRIu32 "ms\n",
|
||||
transmitted, received, loss, total_time_ms);
|
||||
@ -150,11 +154,15 @@ static int do_ping_cmd(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
if (res->ai_family == AF_INET) {
|
||||
#if CONFIG_LWIP_IPV4
|
||||
struct in_addr addr4 = ((struct sockaddr_in *) (res->ai_addr))->sin_addr;
|
||||
inet_addr_to_ip4addr(ip_2_ip4(&target_addr), &addr4);
|
||||
#endif
|
||||
} else {
|
||||
#if CONFIG_LWIP_IPV6
|
||||
struct in6_addr addr6 = ((struct sockaddr_in6 *) (res->ai_addr))->sin6_addr;
|
||||
inet6_addr_to_ip6addr(ip_2_ip6(&target_addr), &addr6);
|
||||
#endif
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -20,6 +20,30 @@ extern "C" {
|
||||
*/
|
||||
esp_err_t console_cmd_ping_register(void);
|
||||
|
||||
/**
|
||||
* @brief Registers the getddrinfo command.
|
||||
*
|
||||
* @return
|
||||
* - esp_err_t
|
||||
*/
|
||||
esp_err_t console_cmd_getaddrinfo_register(void);
|
||||
|
||||
/**
|
||||
* @brief Registers the setdnsserver command.
|
||||
*
|
||||
* @return
|
||||
* - esp_err_t
|
||||
*/
|
||||
esp_err_t console_cmd_setdnsserver_register(void);
|
||||
|
||||
/**
|
||||
* @brief Registers the setdnsserver command.
|
||||
*
|
||||
* @return
|
||||
* - esp_err_t
|
||||
*/
|
||||
esp_err_t console_cmd_getdnsserver_register(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: 1.0.0
|
||||
version: 1.1.0
|
||||
url: https://github.com/espressif/esp-protocols/tree/master/components/console_cmd_ping
|
||||
description: The component provides a console where the 'ping' command can be executed.
|
||||
dependencies:
|
||||
|
@ -3,6 +3,6 @@ commitizen:
|
||||
bump_message: 'bump(console): $current_version -> $new_version'
|
||||
pre_bump_hooks: python ../../ci/changelog.py console_cmd_wifi
|
||||
tag_format: console_cmd_wifi-v$version
|
||||
version: 1.0.1
|
||||
version: 1.1.0
|
||||
version_files:
|
||||
- idf_component.yml
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Changelog
|
||||
|
||||
## [1.1.0](https://github.com/espressif/esp-protocols/commits/console_cmd_wifi-v1.1.0)
|
||||
|
||||
### Features
|
||||
|
||||
- Added support to join pre-configured network ([bdbf16c1](https://github.com/espressif/esp-protocols/commit/bdbf16c1))
|
||||
|
||||
## [1.0.1](https://github.com/espressif/esp-protocols/commits/console_cmd_wifi-v1.0.1)
|
||||
|
||||
### Features
|
||||
|
@ -1,4 +1,8 @@
|
||||
idf_component_register(SRCS "console_wifi.c"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES esp_netif console esp_wifi
|
||||
WHOLE_ARCHIVE)
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES lwip
|
||||
PRIV_REQUIRES esp_netif console esp_wifi esp_timer)
|
||||
|
||||
if(CONFIG_WIFI_CMD_AUTO_REGISTRATION)
|
||||
target_link_libraries(${COMPONENT_LIB} "-u console_cmd_wifi_register")
|
||||
endif()
|
||||
|
22
components/console_cmd_wifi/Kconfig.projbuild
Normal file
22
components/console_cmd_wifi/Kconfig.projbuild
Normal file
@ -0,0 +1,22 @@
|
||||
menu "Wifi command Configuration"
|
||||
|
||||
config WIFI_CMD_AUTO_REGISTRATION
|
||||
bool "Enable Console command wifi Auto-registration"
|
||||
default y
|
||||
help
|
||||
Enabling this allows for the autoregistration of the wifi command.
|
||||
|
||||
config WIFI_CMD_NETWORK_SSID
|
||||
string "WiFi SSID"
|
||||
default "myssid"
|
||||
help
|
||||
SSID (network name) to connect to.
|
||||
|
||||
config WIFI_CMD_NETWORK_PASSWORD
|
||||
string "WiFi Password"
|
||||
default "mypassword"
|
||||
help
|
||||
WiFi password (WPA or WPA2) to use.
|
||||
Can be left blank if the network has no security set.
|
||||
|
||||
endmenu
|
@ -33,12 +33,16 @@ The component offers a console with a command that enables runtime wifi configur
|
||||
ESP_ERROR_CHECK(console_cmd_start()); // Start console
|
||||
```
|
||||
|
||||
Note: Auto-registration of a specific plugin command can be disabled from menuconfig.
|
||||
|
||||
## Suported command:
|
||||
|
||||
### wifi:
|
||||
* ```wifi help```: Prints the help text for all wifi commands
|
||||
* ```wifi show network```: Scans and displays upto 10 available wifi networks.
|
||||
* ```wifi show sta```: Shows the details of wifi station.
|
||||
* ```wifi sta join <network ssid> <password>```: Station joins the given wifi network.
|
||||
* ```wifi sta join <network ssid>```: Station joins the given unsecured wifi network.
|
||||
* ```wifi sta leave```: Station leaves the wifi network.
|
||||
```
|
||||
wifi help: Prints the help text for all wifi commands
|
||||
wifi show network/sta: Scans and displays all available wifi APs./ Shows the details of wifi station.
|
||||
wifi sta join <network ssid> <password>: Station joins the given wifi network.
|
||||
wifi sta join <network ssid>: Station joins the given unsecured wifi network.
|
||||
wifi sta join: Station joins the pre-configured wifi network.
|
||||
wifi sta leave: Station leaves the wifi network.
|
||||
```
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#define DEFAULT_SCAN_LIST_SIZE 10
|
||||
|
||||
#if CONFIG_WIFI_CMD_AUTO_REGISTRATION
|
||||
/**
|
||||
* Static registration of this plugin is achieved by defining the plugin description
|
||||
* structure and placing it into .console_cmd_desc section.
|
||||
@ -30,6 +31,7 @@ static const console_cmd_plugin_desc_t __attribute__((section(".console_cmd_desc
|
||||
.name = "console_cmd_wifi",
|
||||
.plugin_regd_fn = &console_cmd_wifi_register
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef struct wifi_op_t {
|
||||
char *name;
|
||||
@ -55,8 +57,9 @@ static const int CONNECTED_BIT = BIT1;
|
||||
static wifi_op_t cmd_list[] = {
|
||||
{.name = "help", .operation = wifi_help_op, .arg_cnt = 2, .start_index = 1, .help = "wifi help: Prints the help text for all wifi commands"},
|
||||
{.name = "show", .operation = wifi_show_op, .arg_cnt = 3, .start_index = 1, .help = "wifi show network/sta: Scans and displays all available wifi APs./ Shows the details of wifi station."},
|
||||
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 4, .start_index = 2, .help = "wifi sta join <network ssid> <password>: Station joins the given wifi network."},
|
||||
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 5, .start_index = 2, .help = "wifi sta join <network ssid>: Station joins the given unsecured wifi network."},
|
||||
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 5, .start_index = 2, .help = "wifi sta join <network ssid> <password>: Station joins the given wifi network."},
|
||||
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 4, .start_index = 2, .help = "wifi sta join <network ssid>: Station joins the given unsecured wifi network."},
|
||||
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 3, .start_index = 2, .help = "wifi sta join: Station joins the pre-configured wifi network."},
|
||||
{.name = "leave", .operation = wifi_sta_leave_op, .arg_cnt = 3, .start_index = 2, .help = "wifi sta leave: Station leaves the wifi network."},
|
||||
};
|
||||
|
||||
@ -162,7 +165,6 @@ static esp_err_t wifi_show_op(wifi_op_t *self, int argc, char *argv[])
|
||||
ESP_LOGI(TAG, "Showing Joind AP details:");
|
||||
ESP_LOGI(TAG, "*************************");
|
||||
ESP_LOGI(TAG, "SSID: %s", wifi_config.sta.ssid);
|
||||
ESP_LOGI(TAG, "Password: %s", wifi_config.sta.password);
|
||||
ESP_LOGI(TAG, "Channel: %d", wifi_config.sta.channel);
|
||||
ESP_LOGI(TAG, "bssid: %02x:%02x:%02x:%02x:%02x:%02x", wifi_config.sta.bssid[0],
|
||||
wifi_config.sta.bssid[1], wifi_config.sta.bssid[2], wifi_config.sta.bssid[3],
|
||||
@ -184,7 +186,13 @@ static esp_err_t wifi_sta_join_op(wifi_op_t *self, int argc, char *argv[])
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
strlcpy((char *) wifi_config.sta.ssid, argv[self->start_index + 1], sizeof(wifi_config.sta.ssid));
|
||||
if (self->arg_cnt == 3) {
|
||||
strlcpy((char *) wifi_config.sta.ssid, CONFIG_WIFI_CMD_NETWORK_SSID, sizeof(wifi_config.sta.ssid));
|
||||
strlcpy((char *) wifi_config.sta.password, CONFIG_WIFI_CMD_NETWORK_PASSWORD, sizeof(wifi_config.sta.password));
|
||||
} else {
|
||||
strlcpy((char *) wifi_config.sta.ssid, argv[self->start_index + 1], sizeof(wifi_config.sta.ssid));
|
||||
}
|
||||
|
||||
if (self->arg_cnt == 5) {
|
||||
strlcpy((char *) wifi_config.sta.password, argv[self->start_index + 2], sizeof(wifi_config.sta.password));
|
||||
}
|
||||
@ -260,7 +268,7 @@ static esp_err_t do_cmd_wifi(int argc, char **argv)
|
||||
*/
|
||||
esp_err_t console_cmd_wifi_register(void)
|
||||
{
|
||||
esp_err_t ret;
|
||||
esp_err_t ret = ESP_OK;
|
||||
esp_console_cmd_t command = {
|
||||
.command = "wifi",
|
||||
.help = "Command for wifi configuration and monitoring\n For more info run 'wifi help'",
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: 1.0.1
|
||||
version: 1.1.0
|
||||
url: https://github.com/espressif/esp-protocols/tree/master/components/console_cmd_wifi
|
||||
description: The component offers a console that enables runtime wifi configuration and monitoring.
|
||||
dependencies:
|
||||
|
@ -3,6 +3,6 @@ commitizen:
|
||||
bump_message: 'bump(eppp): $current_version -> $new_version'
|
||||
pre_bump_hooks: python ../../ci/changelog.py eppp_link
|
||||
tag_format: eppp-v$version
|
||||
version: 0.1.1
|
||||
version: 0.2.0
|
||||
version_files:
|
||||
- idf_component.yml
|
||||
|
@ -1,5 +1,16 @@
|
||||
# Changelog
|
||||
|
||||
## [0.2.0](https://github.com/espressif/esp-protocols/commits/eppp-v0.2.0)
|
||||
|
||||
### Features
|
||||
|
||||
- Add support for SDIO transport ([085dd790](https://github.com/espressif/esp-protocols/commit/085dd790))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fixed strict prototype API decl issue in SDIO ([eb09e426](https://github.com/espressif/esp-protocols/commit/eb09e426))
|
||||
- Fix SIDO host to check/clear interrupts atomically ([402176c9](https://github.com/espressif/esp-protocols/commit/402176c9))
|
||||
|
||||
## [0.1.1](https://github.com/espressif/esp-protocols/commits/eppp-v0.1.1)
|
||||
|
||||
### Bug Fixes
|
||||
|
@ -1,3 +1,3 @@
|
||||
idf_component_register(SRCS "eppp_link.c"
|
||||
idf_component_register(SRCS eppp_link.c eppp_sdio_slave.c eppp_sdio_host.c
|
||||
INCLUDE_DIRS "include"
|
||||
PRIV_REQUIRES esp_netif esp_driver_spi esp_driver_gpio esp_timer driver)
|
||||
|
@ -21,6 +21,13 @@ menu "eppp_link"
|
||||
bool "SPI"
|
||||
help
|
||||
Use SPI.
|
||||
|
||||
config EPPP_LINK_DEVICE_SDIO
|
||||
bool "SDIO"
|
||||
depends on SOC_SDMMC_HOST_SUPPORTED || SOC_SDIO_SLAVE_SUPPORTED
|
||||
help
|
||||
Use SDIO.
|
||||
|
||||
endchoice
|
||||
|
||||
config EPPP_LINK_CONN_MAX_RETRY
|
||||
@ -34,8 +41,30 @@ menu "eppp_link"
|
||||
config EPPP_LINK_PACKET_QUEUE_SIZE
|
||||
int "Packet queue size"
|
||||
default 64
|
||||
depends on EPPP_LINK_DEVICE_SPI
|
||||
help
|
||||
Size of the Tx packet queue.
|
||||
You can decrease the number for slower bit rates.
|
||||
|
||||
choice EPPP_LINK_SDIO_ROLE
|
||||
prompt "Choose SDIO host or slave"
|
||||
depends on EPPP_LINK_DEVICE_SDIO
|
||||
default EPPP_LINK_DEVICE_SDIO_HOST if SOC_SDMMC_HOST_SUPPORTED
|
||||
help
|
||||
Select which either SDIO host or slave
|
||||
|
||||
config EPPP_LINK_DEVICE_SDIO_HOST
|
||||
bool "Host"
|
||||
depends on SOC_SDMMC_HOST_SUPPORTED
|
||||
help
|
||||
Use SDIO host.
|
||||
|
||||
config EPPP_LINK_DEVICE_SDIO_SLAVE
|
||||
bool "SLAVE"
|
||||
depends on SOC_SDIO_SLAVE_SUPPORTED
|
||||
help
|
||||
Use SDIO slave.
|
||||
|
||||
endchoice
|
||||
|
||||
endmenu
|
||||
|
@ -14,7 +14,7 @@ brings in the WiFi connectivity from the "SLAVE" microcontroller.
|
||||
SLAVE micro HOST micro
|
||||
\|/ +----------------+ +----------------+
|
||||
| | | serial line | |
|
||||
+---+ WiFi NAT PPPoS |======== UART / SPI =======| PPPoS client |
|
||||
+---+ WiFi NAT PPPoS |=== UART / SPI / SDIO =====| PPPoS client |
|
||||
| (server)| | |
|
||||
+----------------+ +----------------+
|
||||
```
|
||||
@ -39,14 +39,19 @@ brings in the WiFi connectivity from the "SLAVE" microcontroller.
|
||||
|
||||
## Throughput
|
||||
|
||||
Tested with WiFi-NAPT example, no IRAM optimizations
|
||||
Tested with WiFi-NAPT example
|
||||
|
||||
### UART @ 3Mbauds
|
||||
|
||||
* TCP - 2Mbits/s
|
||||
* UDP - 2Mbits/s
|
||||
|
||||
### SPI @ 20MHz
|
||||
### SPI @ 16MHz
|
||||
|
||||
* TCP - 6Mbits/s
|
||||
* UDP - 10Mbits/s
|
||||
* TCP - 5Mbits/s
|
||||
* UDP - 8Mbits/s
|
||||
|
||||
### SDIO
|
||||
|
||||
* TCP - 9Mbits/s
|
||||
* UDP - 11Mbits/s
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "esp_event.h"
|
||||
#include "esp_netif_ppp.h"
|
||||
#include "eppp_link.h"
|
||||
#include "esp_serial_slave_link/essl_sdio.h"
|
||||
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
#include "driver/spi_master.h"
|
||||
@ -86,7 +87,18 @@ struct eppp_handle {
|
||||
bool netif_stop;
|
||||
};
|
||||
|
||||
typedef esp_err_t (*transmit_t)(void *h, void *buffer, size_t len);
|
||||
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||
esp_err_t eppp_sdio_host_tx(void *h, void *buffer, size_t len);
|
||||
esp_err_t eppp_sdio_host_rx(esp_netif_t *netif);
|
||||
esp_err_t eppp_sdio_slave_rx(esp_netif_t *netif);
|
||||
esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len);
|
||||
esp_err_t eppp_sdio_host_init(struct eppp_config_sdio_s *config);
|
||||
esp_err_t eppp_sdio_slave_init(void);
|
||||
void eppp_sdio_slave_deinit(void);
|
||||
void eppp_sdio_host_deinit(void);
|
||||
#else
|
||||
static esp_err_t transmit(void *h, void *buffer, size_t len)
|
||||
{
|
||||
struct eppp_handle *handle = h;
|
||||
@ -125,9 +137,10 @@ static esp_err_t transmit(void *h, void *buffer, size_t len)
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||
ESP_LOG_BUFFER_HEXDUMP("ppp_uart_send", buffer, len, ESP_LOG_VERBOSE);
|
||||
uart_write_bytes(handle->uart_port, buffer, len);
|
||||
#endif
|
||||
#endif // DEVICE UART or SPI
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void netif_deinit(esp_netif_t *netif)
|
||||
{
|
||||
@ -209,7 +222,11 @@ static esp_netif_t *netif_init(eppp_type_t role, eppp_config_t *eppp_config)
|
||||
|
||||
esp_netif_driver_ifconfig_t driver_cfg = {
|
||||
.handle = h,
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||
.transmit = role == EPPP_CLIENT ? eppp_sdio_host_tx : eppp_sdio_slave_tx,
|
||||
#else
|
||||
.transmit = transmit,
|
||||
#endif
|
||||
};
|
||||
const esp_netif_driver_ifconfig_t *ppp_driver_cfg = &driver_cfg;
|
||||
|
||||
@ -657,6 +674,20 @@ esp_err_t eppp_perform(esp_netif_t *netif)
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||
|
||||
esp_err_t eppp_perform(esp_netif_t *netif)
|
||||
{
|
||||
struct eppp_handle *h = esp_netif_get_io_driver(netif);
|
||||
if (h->stop) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
if (h->role == EPPP_SERVER) {
|
||||
return eppp_sdio_slave_rx(netif);
|
||||
} else {
|
||||
return eppp_sdio_host_rx(netif);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CONFIG_EPPP_LINK_DEVICE_SPI / UART
|
||||
|
||||
@ -700,6 +731,13 @@ void eppp_deinit(esp_netif_t *netif)
|
||||
}
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||
deinit_uart(esp_netif_get_io_driver(netif));
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||
struct eppp_handle *h = esp_netif_get_io_driver(netif);
|
||||
if (h->role == EPPP_CLIENT) {
|
||||
eppp_sdio_host_deinit();
|
||||
} else {
|
||||
eppp_sdio_slave_deinit();
|
||||
}
|
||||
#endif
|
||||
netif_deinit(netif);
|
||||
}
|
||||
@ -714,7 +752,6 @@ esp_netif_t *eppp_init(eppp_type_t role, eppp_config_t *config)
|
||||
esp_netif_t *netif = netif_init(role, config);
|
||||
if (!netif) {
|
||||
ESP_LOGE(TAG, "Failed to initialize PPP netif");
|
||||
remove_handlers();
|
||||
return NULL;
|
||||
}
|
||||
esp_netif_ppp_config_t netif_params;
|
||||
@ -732,6 +769,18 @@ esp_netif_t *eppp_init(eppp_type_t role, eppp_config_t *config)
|
||||
}
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||
init_uart(esp_netif_get_io_driver(netif), config);
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||
esp_err_t ret;
|
||||
if (role == EPPP_SERVER) {
|
||||
ret = eppp_sdio_slave_init();
|
||||
} else {
|
||||
ret = eppp_sdio_host_init(&config->sdio);
|
||||
}
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to initialize SDIO %d", ret);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
return netif;
|
||||
}
|
||||
@ -754,6 +803,12 @@ esp_netif_t *eppp_open(eppp_type_t role, eppp_config_t *config, int connect_time
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||
if (config->transport != EPPP_TRANSPORT_SDIO) {
|
||||
ESP_LOGE(TAG, "Invalid transport: SDIO device must be enabled in Kconfig");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (config->task.run_task == false) {
|
||||
ESP_LOGE(TAG, "task.run_task == false is invalid in this API. Please use eppp_init()");
|
||||
|
19
components/eppp_link/eppp_sdio.h
Normal file
19
components/eppp_link/eppp_sdio.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define MAX_SDIO_PAYLOAD 1500
|
||||
#define SDIO_ALIGN(size) (((size) + 3U) & ~(3U))
|
||||
#define SDIO_PAYLOAD SDIO_ALIGN(MAX_SDIO_PAYLOAD)
|
||||
#define PPP_SOF 0x7E
|
||||
|
||||
// Interrupts and registers
|
||||
#define SLAVE_INTR 0
|
||||
#define SLAVE_REG_REQ 0
|
||||
|
||||
// Requests from host to slave
|
||||
#define REQ_RESET 1
|
||||
#define REQ_INIT 2
|
200
components/eppp_link/eppp_sdio_host.c
Normal file
200
components/eppp_link/eppp_sdio_host.c
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_netif.h"
|
||||
#include "driver/sdio_slave.h"
|
||||
#include "esp_serial_slave_link/essl_sdio.h"
|
||||
#include "eppp_sdio.h"
|
||||
#include "driver/sdmmc_host.h"
|
||||
#include "sdmmc_cmd.h"
|
||||
#include "esp_check.h"
|
||||
#include "eppp_link.h"
|
||||
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SDIO_HOST
|
||||
|
||||
// For blocking operations
|
||||
#define TIMEOUT_MAX UINT32_MAX
|
||||
// Short timeout for sending/receiving ESSL packets
|
||||
#define PACKET_TIMEOUT_MS 50
|
||||
|
||||
static const char *TAG = "eppp_sdio_host";
|
||||
static SemaphoreHandle_t s_essl_mutex = NULL;
|
||||
static essl_handle_t s_essl = NULL;
|
||||
static sdmmc_card_t *s_card = NULL;
|
||||
|
||||
static DRAM_DMA_ALIGNED_ATTR uint8_t send_buffer[SDIO_PAYLOAD];
|
||||
static DMA_ATTR uint8_t rcv_buffer[SDIO_PAYLOAD];
|
||||
|
||||
esp_err_t eppp_sdio_host_tx(void *h, void *buffer, size_t len)
|
||||
{
|
||||
if (s_essl == NULL || s_essl_mutex == NULL) {
|
||||
// silently skip the Tx if the SDIO not fully initialized
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
memcpy(send_buffer, buffer, len);
|
||||
size_t send_len = SDIO_ALIGN(len);
|
||||
if (send_len > len) {
|
||||
// pad with SOF's
|
||||
memset(&send_buffer[len], PPP_SOF, send_len - len);
|
||||
}
|
||||
xSemaphoreTake(s_essl_mutex, portMAX_DELAY);
|
||||
esp_err_t ret = essl_send_packet(s_essl, send_buffer, send_len, PACKET_TIMEOUT_MS);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Slave not ready to receive packet %x", ret);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
ret = ESP_ERR_NO_MEM; // to inform the upper layers
|
||||
}
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, send_buffer, send_len, ESP_LOG_VERBOSE);
|
||||
xSemaphoreGive(s_essl_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t request_slave_reset(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
ESP_LOGI(TAG, "send reset to slave...");
|
||||
ESP_GOTO_ON_ERROR(essl_write_reg(s_essl, SLAVE_REG_REQ, REQ_RESET, NULL, TIMEOUT_MAX), err, TAG, "write-reg failed");
|
||||
ESP_GOTO_ON_ERROR(essl_send_slave_intr(s_essl, BIT(SLAVE_INTR), TIMEOUT_MAX), err, TAG, "send-intr failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(PACKET_TIMEOUT_MS));
|
||||
ESP_GOTO_ON_ERROR(essl_wait_for_ready(s_essl, TIMEOUT_MAX), err, TAG, "wait-for-ready failed");
|
||||
ESP_LOGI(TAG, "slave io ready");
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t eppp_sdio_host_init(struct eppp_config_sdio_s *eppp_config)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
ESP_GOTO_ON_ERROR(sdmmc_host_init(), err, TAG, "sdmmc host init failed");
|
||||
|
||||
// configure SDIO interface and slot
|
||||
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
|
||||
slot_config.width = eppp_config->width;
|
||||
#ifdef CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
|
||||
slot_config.clk = eppp_config->clk;
|
||||
slot_config.cmd = eppp_config->cmd;
|
||||
slot_config.d0 = eppp_config->d0;
|
||||
slot_config.d1 = eppp_config->d1;
|
||||
slot_config.d2 = eppp_config->d2;
|
||||
slot_config.d3 = eppp_config->d3;
|
||||
#endif
|
||||
|
||||
ESP_GOTO_ON_ERROR(sdmmc_host_init_slot(SDMMC_HOST_SLOT_1, &slot_config), err, TAG, "init sdmmc host slot failed");
|
||||
|
||||
sdmmc_host_t config = SDMMC_HOST_DEFAULT();
|
||||
config.flags = SDMMC_HOST_FLAG_4BIT;
|
||||
config.flags |= SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF;
|
||||
config.max_freq_khz = SDMMC_FREQ_HIGHSPEED;
|
||||
|
||||
s_card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t));
|
||||
ESP_GOTO_ON_FALSE(s_card, ESP_ERR_NO_MEM, err, TAG, "card allocation failed");
|
||||
ESP_GOTO_ON_ERROR(sdmmc_card_init(&config, s_card), err, TAG, "sdmmc card init failed");
|
||||
|
||||
essl_sdio_config_t ser_config = {
|
||||
.card = s_card,
|
||||
.recv_buffer_size = SDIO_PAYLOAD,
|
||||
};
|
||||
ESP_GOTO_ON_FALSE(essl_sdio_init_dev(&s_essl, &ser_config) == ESP_OK && s_essl, ESP_FAIL, err, TAG, "essl_sdio_init_dev failed");
|
||||
ESP_GOTO_ON_ERROR(essl_init(s_essl, TIMEOUT_MAX), err, TAG, "essl-init failed");
|
||||
ESP_GOTO_ON_ERROR(request_slave_reset(), err, TAG, "failed to reset the slave");
|
||||
ESP_GOTO_ON_FALSE((s_essl_mutex = xSemaphoreCreateMutex()), ESP_ERR_NO_MEM, err, TAG, "failed to create semaphore");
|
||||
return ret;
|
||||
|
||||
err:
|
||||
essl_sdio_deinit_dev(s_essl);
|
||||
s_essl = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t get_intr(uint32_t *out_raw)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
ESP_GOTO_ON_ERROR(essl_get_intr(s_essl, out_raw, NULL, 0), err, TAG, "essl-get-int failed");
|
||||
ESP_GOTO_ON_ERROR(essl_clear_intr(s_essl, *out_raw, 0), err, TAG, "essl-clear-int failed");
|
||||
ESP_LOGD(TAG, "intr: %08"PRIX32, *out_raw);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t eppp_sdio_host_rx(esp_netif_t *netif)
|
||||
{
|
||||
uint32_t intr;
|
||||
esp_err_t err = essl_wait_int(s_essl, TIMEOUT_MAX);
|
||||
if (err == ESP_ERR_TIMEOUT) {
|
||||
return ESP_OK;
|
||||
}
|
||||
xSemaphoreTake(s_essl_mutex, portMAX_DELAY);
|
||||
err = get_intr(&intr);
|
||||
if (err == ESP_ERR_TIMEOUT) {
|
||||
xSemaphoreGive(s_essl_mutex);
|
||||
return ESP_OK;
|
||||
}
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "failed to check for interrupts %d", err);
|
||||
xSemaphoreGive(s_essl_mutex);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (intr & ESSL_SDIO_DEF_ESP32.new_packet_intr_mask) {
|
||||
esp_err_t ret;
|
||||
do {
|
||||
size_t size_read = SDIO_PAYLOAD;
|
||||
ret = essl_get_packet(s_essl, rcv_buffer, SDIO_PAYLOAD, &size_read, PACKET_TIMEOUT_MS);
|
||||
if (ret == ESP_ERR_NOT_FOUND) {
|
||||
ESP_LOGE(TAG, "interrupt but no data can be read");
|
||||
break;
|
||||
} else if (ret == ESP_OK) {
|
||||
ESP_LOGD(TAG, "receive data, size: %d", size_read);
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, rcv_buffer, size_read, ESP_LOG_VERBOSE);
|
||||
esp_netif_receive(netif, rcv_buffer, size_read, NULL);
|
||||
break;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "rx packet error: %08X", ret);
|
||||
if (request_slave_reset() != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to request slave reset %x", ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (ret == ESP_ERR_NOT_FINISHED);
|
||||
}
|
||||
xSemaphoreGive(s_essl_mutex);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void eppp_sdio_host_deinit(void)
|
||||
{
|
||||
essl_sdio_deinit_dev(s_essl);
|
||||
sdmmc_host_deinit();
|
||||
free(s_card);
|
||||
s_card = NULL;
|
||||
s_essl = NULL;
|
||||
}
|
||||
|
||||
#else // SDMMC_HOST NOT-SUPPORTED
|
||||
|
||||
esp_err_t eppp_sdio_host_tx(void *handle, void *buffer, size_t len)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_err_t eppp_sdio_host_rx(esp_netif_t *netif)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
void eppp_sdio_host_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
esp_err_t eppp_sdio_host_init(struct eppp_config_sdio_s *config)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
#endif // CONFIG_SOC_SDIO_SLAVE_SUPPORTED
|
174
components/eppp_link/eppp_sdio_slave.c
Normal file
174
components/eppp_link/eppp_sdio_slave.c
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_netif.h"
|
||||
#include "driver/sdio_slave.h"
|
||||
#include "eppp_sdio.h"
|
||||
#include "esp_check.h"
|
||||
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SDIO_SLAVE
|
||||
#define BUFFER_NUM 4
|
||||
#define BUFFER_SIZE SDIO_PAYLOAD
|
||||
static const char *TAG = "eppp_sdio_slave";
|
||||
static DMA_ATTR uint8_t sdio_slave_rx_buffer[BUFFER_NUM][BUFFER_SIZE];
|
||||
static DMA_ATTR uint8_t sdio_slave_tx_buffer[SDIO_PAYLOAD];
|
||||
static int s_slave_request = 0;
|
||||
|
||||
esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len)
|
||||
{
|
||||
if (s_slave_request != REQ_INIT) {
|
||||
// silently skip the Tx if the SDIO not fully initialized
|
||||
return ESP_OK;
|
||||
}
|
||||
memcpy(sdio_slave_tx_buffer, buffer, len);
|
||||
size_t send_len = SDIO_ALIGN(len);
|
||||
if (send_len > len) {
|
||||
// pad with SOF's if the size is not 4 bytes aligned
|
||||
memset(&sdio_slave_tx_buffer[len], PPP_SOF, send_len - len);
|
||||
}
|
||||
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, sdio_slave_tx_buffer, send_len, ESP_LOG_VERBOSE);
|
||||
esp_err_t ret = sdio_slave_transmit(sdio_slave_tx_buffer, send_len);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "sdio slave transmit error, ret : 0x%x", ret);
|
||||
// to inform the upper layers
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t slave_reset(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
ESP_LOGI(TAG, "SDIO slave reset");
|
||||
sdio_slave_stop();
|
||||
ESP_GOTO_ON_ERROR(sdio_slave_reset(), err, TAG, "slave reset failed");
|
||||
ESP_GOTO_ON_ERROR(sdio_slave_start(), err, TAG, "slave start failed");
|
||||
|
||||
while (1) {
|
||||
sdio_slave_buf_handle_t handle;
|
||||
ret = sdio_slave_send_get_finished(&handle, 0);
|
||||
if (ret == ESP_ERR_TIMEOUT) {
|
||||
break;
|
||||
}
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "slave-get-finished failed");
|
||||
ESP_GOTO_ON_ERROR(sdio_slave_recv_load_buf(handle), err, TAG, "slave-load-buf failed");
|
||||
}
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t eppp_sdio_slave_rx(esp_netif_t *netif)
|
||||
{
|
||||
if (s_slave_request == REQ_RESET) {
|
||||
ESP_LOGD(TAG, "request: %x", s_slave_request);
|
||||
slave_reset();
|
||||
s_slave_request = REQ_INIT;
|
||||
}
|
||||
sdio_slave_buf_handle_t handle;
|
||||
size_t length;
|
||||
uint8_t *ptr;
|
||||
esp_err_t ret = sdio_slave_recv_packet(&handle, pdMS_TO_TICKS(1000));
|
||||
if (ret == ESP_ERR_TIMEOUT) {
|
||||
return ESP_OK;
|
||||
}
|
||||
if (ret == ESP_ERR_NOT_FINISHED || ret == ESP_OK) {
|
||||
again:
|
||||
ptr = sdio_slave_recv_get_buf(handle, &length);
|
||||
esp_netif_receive(netif, ptr, length, NULL);
|
||||
if (sdio_slave_recv_load_buf(handle) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to recycle packet buffer");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (ret == ESP_ERR_NOT_FINISHED) {
|
||||
ret = sdio_slave_recv_packet(&handle, 0);
|
||||
if (ret == ESP_ERR_NOT_FINISHED || ret == ESP_OK) {
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, ptr, length, ESP_LOG_VERBOSE);
|
||||
return ESP_OK;
|
||||
}
|
||||
ESP_LOGE(TAG, "Error when receiving packet %d", ret);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
|
||||
static void event_cb(uint8_t pos)
|
||||
{
|
||||
ESP_EARLY_LOGI(TAG, "SDIO event: %d", pos);
|
||||
if (pos == SLAVE_INTR) {
|
||||
s_slave_request = sdio_slave_read_reg(SLAVE_REG_REQ);
|
||||
sdio_slave_write_reg(SLAVE_REG_REQ, 0);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t eppp_sdio_slave_init(void)
|
||||
{
|
||||
sdio_slave_config_t config = {
|
||||
.sending_mode = SDIO_SLAVE_SEND_PACKET,
|
||||
.send_queue_size = BUFFER_NUM,
|
||||
.recv_buffer_size = BUFFER_SIZE,
|
||||
.event_cb = event_cb,
|
||||
};
|
||||
esp_err_t ret = sdio_slave_initialize(&config);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (int i = 0; i < BUFFER_NUM; i++) {
|
||||
sdio_slave_buf_handle_t handle = sdio_slave_recv_register_buf(sdio_slave_rx_buffer[i]);
|
||||
if (handle == NULL) {
|
||||
sdio_slave_deinit();
|
||||
return ESP_FAIL;
|
||||
}
|
||||
ret = sdio_slave_recv_load_buf(handle);
|
||||
if (ret != ESP_OK) {
|
||||
sdio_slave_deinit();
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
sdio_slave_set_host_intena(SDIO_SLAVE_HOSTINT_SEND_NEW_PACKET); // only need one interrupt to notify of a new packet
|
||||
|
||||
ret = sdio_slave_start();
|
||||
if (ret != ESP_OK) {
|
||||
sdio_slave_deinit();
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void eppp_sdio_slave_deinit(void)
|
||||
{
|
||||
sdio_slave_stop();
|
||||
sdio_slave_deinit();
|
||||
}
|
||||
|
||||
#else // SOC_SDIO_SLAVE NOT-SUPPORTED
|
||||
|
||||
esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
esp_err_t eppp_sdio_slave_rx(esp_netif_t *netif)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
void eppp_sdio_slave_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
esp_err_t eppp_sdio_slave_init(void)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
#endif // CONFIG_SOC_SDIO_SLAVE_SUPPORTED
|
@ -104,11 +104,13 @@ void app_main(void)
|
||||
eppp_config_t config = EPPP_DEFAULT_CLIENT_CONFIG();
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
config.transport = EPPP_TRANSPORT_SPI;
|
||||
#else
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||
config.transport = EPPP_TRANSPORT_UART;
|
||||
config.uart.tx_io = CONFIG_EXAMPLE_UART_TX_PIN;
|
||||
config.uart.rx_io = CONFIG_EXAMPLE_UART_RX_PIN;
|
||||
config.uart.baud = CONFIG_EXAMPLE_UART_BAUDRATE;
|
||||
#else
|
||||
config.transport = EPPP_TRANSPORT_SDIO;
|
||||
#endif
|
||||
esp_netif_t *eppp_netif = eppp_connect(&config);
|
||||
if (eppp_netif == NULL) {
|
||||
|
@ -128,16 +128,21 @@ void app_main(void)
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
init_network_interface(); // WiFi station if withing SoC capabilities (otherwise a placeholder)
|
||||
// ESP_ERROR_CHECK(esp_netif_init());
|
||||
// ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
eppp_config_t config = EPPP_DEFAULT_SERVER_CONFIG();
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
config.transport = EPPP_TRANSPORT_SPI;
|
||||
#else
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||
config.transport = EPPP_TRANSPORT_UART;
|
||||
config.uart.tx_io = CONFIG_EXAMPLE_UART_TX_PIN;
|
||||
config.uart.rx_io = CONFIG_EXAMPLE_UART_RX_PIN;
|
||||
config.uart.baud = CONFIG_EXAMPLE_UART_BAUDRATE;
|
||||
#endif
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||
config.transport = EPPP_TRANSPORT_SDIO;
|
||||
#endif // transport device
|
||||
|
||||
esp_netif_t *eppp_netif = eppp_listen(&config);
|
||||
if (eppp_netif == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to setup connection");
|
||||
|
@ -1,6 +1,6 @@
|
||||
version: 0.1.1
|
||||
version: 0.2.0
|
||||
url: https://github.com/espressif/esp-protocols/tree/master/components/eppp_link
|
||||
description: The component provides a general purpose PPP connectivity, typically used as WiFi-PPP router
|
||||
dependencies:
|
||||
idf:
|
||||
version: '>=5.2'
|
||||
idf: '>=5.2'
|
||||
espressif/esp_serial_slave_link: "^1.1.0"
|
||||
|
@ -28,7 +28,16 @@
|
||||
.rx_io = 26, \
|
||||
.queue_size = 16, \
|
||||
.rx_buffer_size = 1024, \
|
||||
}, \
|
||||
}, \
|
||||
.sdio = { \
|
||||
.width = 4, \
|
||||
.clk = 18, \
|
||||
.cmd = 19, \
|
||||
.d0 = 49, \
|
||||
.d1 = 50, \
|
||||
.d2 = 16, \
|
||||
.d3 = 17, \
|
||||
}, \
|
||||
. task = { \
|
||||
.run_task = true, \
|
||||
.stack_size = 4096, \
|
||||
@ -53,6 +62,7 @@ typedef enum eppp_type {
|
||||
typedef enum eppp_transport {
|
||||
EPPP_TRANSPORT_UART,
|
||||
EPPP_TRANSPORT_SPI,
|
||||
EPPP_TRANSPORT_SDIO,
|
||||
} eppp_transport_t;
|
||||
|
||||
|
||||
@ -81,6 +91,16 @@ typedef struct eppp_config_t {
|
||||
int rx_buffer_size;
|
||||
} uart;
|
||||
|
||||
struct eppp_config_sdio_s {
|
||||
int width;
|
||||
int clk;
|
||||
int cmd;
|
||||
int d0;
|
||||
int d1;
|
||||
int d2;
|
||||
int d3;
|
||||
} sdio;
|
||||
|
||||
struct eppp_config_task_s {
|
||||
bool run_task;
|
||||
int stack_size;
|
||||
|
@ -3,6 +3,6 @@ commitizen:
|
||||
bump_message: 'bump(modem): $current_version -> $new_version'
|
||||
pre_bump_hooks: python ../../ci/changelog.py esp_modem
|
||||
tag_format: modem-v$version
|
||||
version: 1.1.0
|
||||
version: 1.2.1
|
||||
version_files:
|
||||
- idf_component.yml
|
||||
|
@ -1,5 +1,47 @@
|
||||
# Changelog
|
||||
|
||||
## [1.2.1](https://github.com/espressif/esp-protocols/commits/modem-v1.2.1)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Use higher GPIO range to support new chips ([428fdbbd](https://github.com/espressif/esp-protocols/commit/428fdbbd), [#558](https://github.com/espressif/esp-protocols/issues/558))
|
||||
- Remove tests and support for IDFv4.4, added IDFv5.4 ([433a033f](https://github.com/espressif/esp-protocols/commit/433a033f))
|
||||
- Fix typo GENETIC -> GENERIC in mode types ([090b1ff8](https://github.com/espressif/esp-protocols/commit/090b1ff8), [#667](https://github.com/espressif/esp-protocols/issues/667))
|
||||
- Add support for URC handler into C-API ([295d99df](https://github.com/espressif/esp-protocols/commit/295d99df), [#180](https://github.com/espressif/esp-protocols/issues/180))
|
||||
|
||||
## [1.2.0](https://github.com/espressif/esp-protocols/commits/modem-v1.2.0)
|
||||
|
||||
### Features
|
||||
|
||||
- Add support for guessing mode ([52598e5f](https://github.com/espressif/esp-protocols/commit/52598e5f))
|
||||
- Delete CMUX internal implementation even if terminal exit fails ([0e0cbd6b](https://github.com/espressif/esp-protocols/commit/0e0cbd6b))
|
||||
- Add support for handling URC ([1b6a3b3b](https://github.com/espressif/esp-protocols/commit/1b6a3b3b), [#180](https://github.com/espressif/esp-protocols/issues/180))
|
||||
- add ability to change ESP_MODEM_C_API_STR_MAX from Kconfig ([17909892](https://github.com/espressif/esp-protocols/commit/17909892))
|
||||
- Added target test config with CHAP authentication ([f8ae7def](https://github.com/espressif/esp-protocols/commit/f8ae7def))
|
||||
- example add esp32p4 usb support ([adafeae5](https://github.com/espressif/esp-protocols/commit/adafeae5))
|
||||
- Publish mbedtls component ([0140455f](https://github.com/espressif/esp-protocols/commit/0140455f))
|
||||
- host test support of the latest ESP-IDF release ([3f74b4e8](https://github.com/espressif/esp-protocols/commit/3f74b4e8))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix console example to use urc/detect features ([1a9eaf3e](https://github.com/espressif/esp-protocols/commit/1a9eaf3e))
|
||||
- Update target test builds to use external Catch2 ([554f022c](https://github.com/espressif/esp-protocols/commit/554f022c))
|
||||
- Fix arguments names when spawn esp_modem_xxx declarations ([b6792c52](https://github.com/espressif/esp-protocols/commit/b6792c52))
|
||||
- Remove catch dependency ([c3480768](https://github.com/espressif/esp-protocols/commit/c3480768))
|
||||
- Examples: use local configs for MQTT topic/data ([f5c13b92](https://github.com/espressif/esp-protocols/commit/f5c13b92))
|
||||
- Fixed clang-tidy warnings ([70fa3af7](https://github.com/espressif/esp-protocols/commit/70fa3af7))
|
||||
- Fix CI build per IDFv5.3 ([d0c17ef0](https://github.com/espressif/esp-protocols/commit/d0c17ef0))
|
||||
- Fixed UART task to check for buffered data periodically ([4bdd90cc](https://github.com/espressif/esp-protocols/commit/4bdd90cc), [#536](https://github.com/espressif/esp-protocols/issues/536))
|
||||
- Cleanup unused configs from PPPoS example ([08a62ccc](https://github.com/espressif/esp-protocols/commit/08a62ccc))
|
||||
- Update CMUX example with SIM7070_gnss cleaned-up ([56fe5327](https://github.com/espressif/esp-protocols/commit/56fe5327))
|
||||
- Update console example with SIM7070_gnss format comments ([5baaf542](https://github.com/espressif/esp-protocols/commit/5baaf542))
|
||||
- Fix remaining print format warnings ([3b80181d](https://github.com/espressif/esp-protocols/commit/3b80181d))
|
||||
|
||||
### Updated
|
||||
|
||||
- docs(modem): Fix esp_modem_at_raw() description (C-API) ([492a6a00](https://github.com/espressif/esp-protocols/commit/492a6a00))
|
||||
- ci(common): updated github actions(checkout, upload, download) v3 to 4, Ubuntu 20.04 to v22.04 ([a23a0027](https://github.com/espressif/esp-protocols/commit/a23a0027))
|
||||
|
||||
## [1.1.0](https://github.com/espressif/esp-protocols/commits/modem-v1.1.0)
|
||||
|
||||
### Features
|
||||
|
@ -63,4 +63,17 @@ menu "esp-modem"
|
||||
dce_factory::Factory::create_unique_dce_from<CustomModule, DCE*>(dce_config, std::move(dte), netif)
|
||||
Please refer to the pppos_client example for more details.
|
||||
|
||||
config ESP_MODEM_C_API_STR_MAX
|
||||
int "Size in bytes for response from AT commands returning textual values (C-API)"
|
||||
default 128
|
||||
help
|
||||
Some AT commands returns textual values which C-API copy as c-string to user allocated space,
|
||||
it also truncates the output data to this size. Increase this if some AT answers are truncated.
|
||||
|
||||
config ESP_MODEM_URC_HANDLER
|
||||
bool "Enable support for adding URC handler"
|
||||
default n
|
||||
help
|
||||
If enabled, APIs to add URC handler are available
|
||||
|
||||
endmenu
|
||||
|
@ -15,7 +15,3 @@ By default, this example simply connects to the PPP server using a supported dev
|
||||
This example however, doesn't rely on sending specific AT commands, just the bare minimum to setup the cellular network.
|
||||
Thus, if the `EXAMPLE_USE_MINIMAL_DCE` option is enabled, we directly inherit from the `ModuleIf` and implement only the basic commands.
|
||||
Also, to demonstrate the dce_factory functionality, a new `NetDCE_Factory` is implemented for creating the network module and the DCE.
|
||||
|
||||
### Supported IDF versions
|
||||
|
||||
This example is only supported from `v4.2`, since is uses NAPT feature.
|
||||
|
@ -17,7 +17,3 @@ over PPPoS, i.e. over the modem serial line.
|
||||
* Experiment with the network, after getting the IP from the modem device
|
||||
- directly in the code
|
||||
- in the system (need to set `tun` interface IP, dns servers, and routing the desired traffic over the tun interface)
|
||||
|
||||
### Supported IDF versions
|
||||
|
||||
This example (using the default CMake IDF build system) is only supported from `v4.4`, since is uses `idf.py`'s linux target.
|
||||
|
@ -16,18 +16,12 @@ class.
|
||||
|
||||
### USB DTE support
|
||||
|
||||
For USB enabled targets (ESP32-S2 and ESP32-S3), it is possible to connect to the modem device via USB.
|
||||
For USB enabled targets (ESP32-S2, ESP32-S3, or ESP32-P4), it is possible to connect to the modem device via USB.
|
||||
1. In menuconfig, navigate to `Example Configuration->Type of serial connection to the modem` and choose `USB`.
|
||||
2. Connect the modem USB signals to pin 19 (DATA-) and 20 (DATA+) on your ESP chip.
|
||||
2. Connect the modem USB signals to your ESP chip (pin 19 (DATA-) and 20 (DATA+) for ESP32-S2/S3).
|
||||
|
||||
USB example uses Quactel BG96 modem device. BG96 needs a positive pulse on its PWK pin to boot-up.
|
||||
|
||||
This example supports USB modem hot-plugging and reconnection. There is one limitation coming from esp_console component:
|
||||
When esp_console REPL is being destroyed (after USB mode disconnection or after `exit` command), it will block on UART read.
|
||||
You must send a character to it (via idf.py monitor), so it unblocks and properly exits.
|
||||
|
||||
### Supported IDF versions
|
||||
|
||||
This example is only supported from `v4.2`, due to support of the console repl mode.
|
||||
|
||||
USB example is supported from `v4.4`.
|
||||
|
@ -10,7 +10,7 @@ menu "Example Configuration"
|
||||
Connect to modem via UART.
|
||||
config EXAMPLE_SERIAL_CONFIG_USB
|
||||
bool "USB"
|
||||
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4
|
||||
help
|
||||
Connect to modem via USB (CDC-ACM class). For IDF version >= 4.4.
|
||||
endchoice
|
||||
@ -36,6 +36,11 @@ menu "Example Configuration"
|
||||
bool "BG96"
|
||||
help
|
||||
Quectel BG96 is a series of LTE Cat M1/Cat NB1/EGPRS module.
|
||||
config EXAMPLE_MODEM_DEVICE_EC20
|
||||
depends on EXAMPLE_SERIAL_CONFIG_USB
|
||||
bool "EC20"
|
||||
help
|
||||
Quectel EC20 is a series of LTE Cat M4 module.
|
||||
config EXAMPLE_MODEM_DEVICE_SIM7000
|
||||
depends on EXAMPLE_SERIAL_CONFIG_UART
|
||||
bool "SIM7000"
|
||||
@ -103,28 +108,28 @@ menu "Example Configuration"
|
||||
config EXAMPLE_MODEM_UART_TX_PIN
|
||||
int "TXD Pin Number"
|
||||
default 25
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number of UART TX.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RX_PIN
|
||||
int "RXD Pin Number"
|
||||
default 26
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number of UART RX.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RTS_PIN
|
||||
int "RTS Pin Number"
|
||||
default 27
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number of UART RTS.
|
||||
|
||||
config EXAMPLE_MODEM_UART_CTS_PIN
|
||||
int "CTS Pin Number"
|
||||
default 23
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number of UART CTS.
|
||||
|
||||
@ -174,7 +179,7 @@ menu "Example Configuration"
|
||||
config EXAMPLE_MODEM_PWRKEY_PIN
|
||||
int "PWRKEY Pin Number"
|
||||
default 18
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number connected to modem's power key pin.
|
||||
endmenu
|
||||
|
@ -6,7 +6,7 @@ dependencies:
|
||||
version: "^1.0.0"
|
||||
override_path: "../../../"
|
||||
espressif/esp_modem_usb_dte:
|
||||
version: "^1.1.0"
|
||||
version: "^1.2.0"
|
||||
rules:
|
||||
- if: "idf_version >=4.4"
|
||||
- if: "target in [esp32s2, esp32s3]"
|
||||
- if: "target in [esp32s2, esp32s3, esp32p4]"
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
@ -89,7 +89,7 @@ void wakeup_modem(void)
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_MODEM_DEVICE_SHINY
|
||||
#ifdef CONFIG_ESP_MODEM_URC_HANDLER
|
||||
command_result handle_urc(uint8_t *data, size_t len)
|
||||
{
|
||||
ESP_LOG_BUFFER_HEXDUMP("on_read", data, len, ESP_LOG_INFO);
|
||||
@ -160,6 +160,9 @@ extern "C" void app_main(void)
|
||||
#if CONFIG_EXAMPLE_MODEM_DEVICE_BG96 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the BG96 module...");
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_BG96_USB_CONFIG();
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_EC20 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the EC20 module...");
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_EC20_USB_CONFIG();
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the SIM7600 module...");
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_SIM7600_USB_CONFIG();
|
||||
@ -180,7 +183,7 @@ extern "C" void app_main(void)
|
||||
});
|
||||
#if CONFIG_EXAMPLE_MODEM_DEVICE_BG96 == 1
|
||||
std::unique_ptr<DCE> dce = create_BG96_dce(&dce_config, dte, esp_netif);
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1 || CONFIG_EXAMPLE_MODEM_DEVICE_A7670 == 1
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1 || CONFIG_EXAMPLE_MODEM_DEVICE_A7670 == 1 || CONFIG_EXAMPLE_MODEM_DEVICE_EC20 == 1
|
||||
std::unique_ptr<DCE> dce = create_SIM7600_dce(&dce_config, dte, esp_netif);
|
||||
#else
|
||||
#error USB modem not selected
|
||||
@ -235,7 +238,9 @@ extern "C" void app_main(void)
|
||||
if (c->get_count_of(&SetModeArgs::mode)) {
|
||||
auto mode = c->get_string_of(&SetModeArgs::mode);
|
||||
modem_mode dev_mode;
|
||||
if (mode == "UNDEF") {
|
||||
if (mode == "AUTO") {
|
||||
dev_mode = esp_modem::modem_mode::AUTODETECT;
|
||||
} else if (mode == "UNDEF") {
|
||||
dev_mode = esp_modem::modem_mode::UNDEF;
|
||||
} else if (mode == "CMUX1") {
|
||||
dev_mode = esp_modem::modem_mode::CMUX_MANUAL_MODE;
|
||||
@ -367,15 +372,15 @@ extern "C" void app_main(void)
|
||||
ESP_LOGI(TAG, "Resetting the module...");
|
||||
CHECK_ERR(dce->reset(), ESP_LOGI(TAG, "OK"));
|
||||
});
|
||||
#ifdef CONFIG_EXAMPLE_MODEM_DEVICE_SHINY
|
||||
#ifdef CONFIG_ESP_MODEM_URC_HANDLER
|
||||
const ConsoleCommand HandleURC("urc", "toggle urc handling", no_args, [&](ConsoleCommand * c) {
|
||||
static int cnt = 0;
|
||||
if (++cnt % 2) {
|
||||
ESP_LOGI(TAG, "Adding URC handler");
|
||||
dce->set_on_read(handle_urc);
|
||||
dce->set_urc(handle_urc);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "URC removed");
|
||||
dce->set_on_read(nullptr);
|
||||
dce->set_urc(nullptr);
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
@ -0,0 +1,2 @@
|
||||
CONFIG_IDF_TARGET="esp32p4"
|
||||
CONFIG_EXAMPLE_SERIAL_CONFIG_USB=y
|
@ -20,14 +20,14 @@ menu "Example Configuration"
|
||||
config EXAMPLE_MODEM_UART_TX_PIN
|
||||
int "TXD Pin Number"
|
||||
default 4
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number of UART TX.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RX_PIN
|
||||
int "RXD Pin Number"
|
||||
default 5
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number of UART RX.
|
||||
|
||||
@ -70,14 +70,14 @@ menu "Example Configuration"
|
||||
config EXAMPLE_MODEM_PWRKEY_PIN
|
||||
int "PWRKEY Pin Number"
|
||||
default 18
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number connected to modem's power key pin.
|
||||
|
||||
config EXAMPLE_MODEM_STATUS_PIN
|
||||
int "STATUS Pin Number"
|
||||
default 19
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number connected to modem's status pin.
|
||||
|
||||
|
@ -22,7 +22,3 @@ To enable this mode, please set `EXAMPLE_CUSTOM_TCP_TRANSPORT=y`
|
||||
This configuration could be used with any network library, which is connecting to a localhost endpoint instead of remote one. This example creates a localhost listener which basically mimics the remote endpoint by forwarding the traffic between the library and the TCP/socket layer of the modem (which is already secure if the TLS is used in the network library)
|
||||
|
||||

|
||||
|
||||
### Supported IDF versions
|
||||
|
||||
This example is supported from IDF `v5.0`.
|
||||
|
@ -30,28 +30,28 @@ menu "Example Configuration"
|
||||
config EXAMPLE_MODEM_UART_TX_PIN
|
||||
int "TXD Pin Number"
|
||||
default 25
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number of UART TX.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RX_PIN
|
||||
int "RXD Pin Number"
|
||||
default 26
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number of UART RX.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RTS_PIN
|
||||
int "RTS Pin Number"
|
||||
default 27
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number of UART RTS.
|
||||
|
||||
config EXAMPLE_MODEM_UART_CTS_PIN
|
||||
int "CTS Pin Number"
|
||||
default 23
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number of UART CTS.
|
||||
|
||||
|
@ -11,16 +11,10 @@ See the README.md file in the upper level `pppos` directory for more information
|
||||
|
||||
### USB DTE support
|
||||
|
||||
For USB enabled targets (ESP32-S2 and ESP32-S3), it is possible to connect to the modem device via USB.
|
||||
For USB enabled targets (ESP32-S2, ESP32-S3, or ESP32-P4), it is possible to connect to the modem device via USB.
|
||||
1. In menuconfig, navigate to `Example Configuration->Type of serial connection to the modem` and choose `USB`.
|
||||
2. Connect the modem USB signals to pin 19 (DATA-) and 20 (DATA+) on your ESP chip.
|
||||
2. Connect the modem USB signals to your ESP chip (pin 19 (DATA-) and 20 (DATA+) for ESP32-S2/S3).
|
||||
|
||||
USB example uses Quactel BG96 modem device. BG96 needs a positive pulse on its PWK pin to boot-up.
|
||||
|
||||
This example supports USB modem hot-plugging and reconnection.
|
||||
|
||||
### Supported IDF versions
|
||||
|
||||
This example is only supported from `v4.1`, as this is the default dependency of `esp-modem` component.
|
||||
|
||||
USB example is supported from `v4.4`.
|
||||
|
@ -9,7 +9,7 @@ menu "Example Configuration"
|
||||
Connect to modem via UART.
|
||||
config EXAMPLE_SERIAL_CONFIG_USB
|
||||
bool "USB"
|
||||
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4
|
||||
help
|
||||
Connect to modem via USB (CDC-ACM class). For IDF version >= 4.4.
|
||||
endchoice
|
||||
@ -29,6 +29,11 @@ menu "Example Configuration"
|
||||
bool "BG96"
|
||||
help
|
||||
Quectel BG96 is a series of LTE Cat M1/Cat NB1/EGPRS module.
|
||||
config EXAMPLE_MODEM_DEVICE_EC20
|
||||
depends on EXAMPLE_SERIAL_CONFIG_USB
|
||||
bool "EC20"
|
||||
help
|
||||
Quectel EC20 is a series of LTE Cat M4 module.
|
||||
config EXAMPLE_MODEM_DEVICE_SIM7000
|
||||
depends on EXAMPLE_SERIAL_CONFIG_UART
|
||||
bool "SIM7000"
|
||||
@ -95,28 +100,28 @@ menu "Example Configuration"
|
||||
config EXAMPLE_MODEM_UART_TX_PIN
|
||||
int "TXD Pin Number"
|
||||
default 25
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number of UART TX.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RX_PIN
|
||||
int "RXD Pin Number"
|
||||
default 26
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number of UART RX.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RTS_PIN
|
||||
int "RTS Pin Number"
|
||||
default 27
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number of UART RTS.
|
||||
|
||||
config EXAMPLE_MODEM_UART_CTS_PIN
|
||||
int "CTS Pin Number"
|
||||
default 23
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number of UART CTS.
|
||||
|
||||
|
@ -56,7 +56,7 @@ DCE *esp_modem_create_custom_dce(const esp_modem_dce_config_t *dce_config, std::
|
||||
/**
|
||||
* @brief This API is only needed for extending standard C-API, since we added get_time() method to our CustomModule
|
||||
*
|
||||
* @note This header is included from esp_modem_c_api.cpp, so it could use ESP_MODEM_C_API_STR_MAX macro
|
||||
* @note This header is included from esp_modem_c_api.cpp, so it could use CONFIG_ESP_MODEM_C_API_STR_MAX macro
|
||||
* indicating maximum C-API string size
|
||||
*
|
||||
* @note In order to access the newly added API get_time(), we have to static_cast<> the GenericModule from DCE
|
||||
@ -70,10 +70,10 @@ extern "C" esp_err_t esp_modem_get_time(esp_modem_dce_t *dce_wrap, char *p_time)
|
||||
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
std::string time{ESP_MODEM_C_API_STR_MAX};
|
||||
std::string time{CONFIG_ESP_MODEM_C_API_STR_MAX};
|
||||
auto ret = command_response_to_esp_err(static_cast<SIM7600_WITH_TIME *>(dce_wrap->dce->get_module())->get_time(time));
|
||||
if (ret == ESP_OK && !time.empty()) {
|
||||
strlcpy(p_time, time.c_str(), ESP_MODEM_C_API_STR_MAX);
|
||||
strlcpy(p_time, time.c_str(), CONFIG_ESP_MODEM_C_API_STR_MAX);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ dependencies:
|
||||
version: "^1.0.0"
|
||||
override_path: "../../../"
|
||||
espressif/esp_modem_usb_dte:
|
||||
version: "^1.1.0"
|
||||
version: "^1.2.0"
|
||||
rules:
|
||||
- if: "idf_version >=4.4"
|
||||
- if: "target in [esp32s2, esp32s3]"
|
||||
- if: "target in [esp32s2, esp32s3, esp32p4]"
|
||||
|
@ -219,6 +219,10 @@ void app_main(void)
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the BG96 module...");
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_BG96_USB_CONFIG();
|
||||
esp_modem_dce_device_t usb_dev_type = ESP_MODEM_DCE_BG96;
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_EC20 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the EC20 module...");
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_EC20_USB_CONFIG();
|
||||
esp_modem_dce_device_t usb_dev_type = ESP_MODEM_DCE_EC20;
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the SIM7600 module...");
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_SIM7600_USB_CONFIG();
|
||||
|
@ -0,0 +1,2 @@
|
||||
CONFIG_IDF_TARGET="esp32p4"
|
||||
CONFIG_EXAMPLE_SERIAL_CONFIG_USB=y
|
@ -11,11 +11,3 @@ The example uses the following configuration options to demonstrate basic esp-mo
|
||||
* `EXAMPLE_NEED_SIM_PIN`: To unlock the SIM card with a PIN code if needed
|
||||
* `EXAMPLE_PERFORM_OTA`: To start simple OTA at the end of the example to exercise basic CMUX/modem networking. Please note that the option `CONFIG_UART_ISR_IN_IRAM` is not enabled automatically, so that buffer overflows are expected and CMUX/PPP and networking should recover.
|
||||
* `EXAMPLE_USE_VFS_TERM`: To demonstrate using an abstract file descriptor to talk to the device (instead of the UART driver directly). This option could be used when implementing a custom VFS driver.
|
||||
|
||||
## About the esp_modem
|
||||
|
||||
Please check the component [README](../../README.md)
|
||||
|
||||
### Supported IDF versions
|
||||
|
||||
This example is only supported from `v4.3`, since is uses an experimental `esp_event_cxx` component.
|
||||
|
@ -69,28 +69,28 @@ menu "Example Configuration"
|
||||
config EXAMPLE_MODEM_UART_TX_PIN
|
||||
int "TXD Pin Number"
|
||||
default 25
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number of UART TX.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RX_PIN
|
||||
int "RXD Pin Number"
|
||||
default 26
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number of UART RX.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RTS_PIN
|
||||
int "RTS Pin Number"
|
||||
default 27
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number of UART RTS.
|
||||
|
||||
config EXAMPLE_MODEM_UART_CTS_PIN
|
||||
int "CTS Pin Number"
|
||||
default 23
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number of UART CTS.
|
||||
endmenu
|
||||
@ -129,4 +129,16 @@ menu "Example Configuration"
|
||||
help
|
||||
URL of an mqtt broker which this example connects to.
|
||||
|
||||
config EXAMPLE_MQTT_TEST_TOPIC
|
||||
string "MQTT topic to publish/subscribe"
|
||||
default "/topic/esp-pppos"
|
||||
help
|
||||
MQTT topic, which we subscribe on and publish to.
|
||||
|
||||
config EXAMPLE_MQTT_TEST_DATA
|
||||
string "MQTT data to publish/receive"
|
||||
default "esp32-pppos"
|
||||
help
|
||||
MQTT data message, which we publish and expect to receive.
|
||||
|
||||
endmenu
|
||||
|
@ -234,8 +234,8 @@ extern "C" void app_main(void)
|
||||
}
|
||||
std::cout << "Connected" << std::endl;
|
||||
|
||||
mqtt.subscribe("/topic/esp-modem");
|
||||
mqtt.publish("/topic/esp-modem", "Hello modem");
|
||||
mqtt.subscribe(CONFIG_EXAMPLE_MQTT_TEST_TOPIC);
|
||||
mqtt.publish(CONFIG_EXAMPLE_MQTT_TEST_TOPIC, CONFIG_EXAMPLE_MQTT_TEST_DATA);
|
||||
if (!handler.wait_for(StatusHandler::MQTT_Data, 60000)) {
|
||||
ESP_LOGE(TAG, "Didn't receive published data within specified timeout... exiting");
|
||||
return;
|
||||
|
@ -1,4 +1,4 @@
|
||||
# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
from __future__ import print_function, unicode_literals
|
||||
|
||||
@ -10,8 +10,17 @@ def test_cmux_connection(dut):
|
||||
2. checks we get an IP
|
||||
3. checks for the MQTT events
|
||||
"""
|
||||
# Get topic and data from Kconfig
|
||||
topic = ''
|
||||
data = ''
|
||||
try:
|
||||
topic = dut.app.sdkconfig.get('EXAMPLE_MQTT_TEST_TOPIC')
|
||||
data = dut.app.sdkconfig.get('EXAMPLE_MQTT_TEST_DATA')
|
||||
except Exception:
|
||||
print('ENV_TEST_FAILURE: Cannot find broker url in sdkconfig')
|
||||
raise
|
||||
# Check the sequence of connecting, publishing, disconnecting
|
||||
dut.expect('Modem has correctly entered multiplexed')
|
||||
# Check for MQTT connection and the data event
|
||||
dut.expect('TOPIC: /topic/esp-modem')
|
||||
dut.expect('DATA: Hello modem')
|
||||
dut.expect(f'TOPIC: {topic}')
|
||||
dut.expect(f'DATA: {data}')
|
||||
|
@ -15,3 +15,4 @@ CONFIG_ESP32_PANIC_PRINT_HALT=y
|
||||
CONFIG_COMPILER_CXX_EXCEPTIONS=y
|
||||
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
|
||||
CONFIG_EXAMPLE_CLOSE_CMUX_AT_END=y
|
||||
CONFIG_EXAMPLE_MQTT_TEST_TOPIC="/ci/esp-modem/pppos-client"
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: "1.1.0"
|
||||
version: "1.2.1"
|
||||
description: Library for communicating with cellular modems in command and data modes
|
||||
url: https://github.com/espressif/esp-protocols/tree/master/components/esp_modem
|
||||
issues: https://github.com/espressif/esp-protocols/issues
|
||||
|
@ -142,7 +142,6 @@ private:
|
||||
size_t frame_header_offset;
|
||||
uint8_t *payload_start;
|
||||
size_t total_payload_size;
|
||||
int instance;
|
||||
int sabm_ack;
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -30,9 +30,11 @@ public:
|
||||
~DCE_Mode() = default;
|
||||
bool set(DTE *dte, ModuleIf *module, Netif &netif, modem_mode m);
|
||||
modem_mode get();
|
||||
modem_mode guess(DTE *dte, bool with_cmux = false);
|
||||
|
||||
private:
|
||||
bool set_unsafe(DTE *dte, ModuleIf *module, Netif &netif, modem_mode m);
|
||||
modem_mode guess_unsafe(DTE *dte, bool with_cmux);
|
||||
modem_mode mode;
|
||||
|
||||
};
|
||||
@ -79,6 +81,11 @@ public:
|
||||
return dte->command(command, std::move(got_line), time_ms);
|
||||
}
|
||||
|
||||
modem_mode guess_mode(bool with_cmux = false)
|
||||
{
|
||||
return mode.guess(dte.get(), with_cmux);
|
||||
}
|
||||
|
||||
bool set_mode(modem_mode m)
|
||||
{
|
||||
return mode.set(dte.get(), device.get(), netif, m);
|
||||
@ -89,6 +96,13 @@ public:
|
||||
return dte->recover();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP_MODEM_URC_HANDLER
|
||||
void set_urc(got_line_cb on_read_cb)
|
||||
{
|
||||
dte->set_urc_cb(on_read_cb);
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
std::shared_ptr<DTE> dte;
|
||||
std::shared_ptr<SpecificModule> device;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user