mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-12-23 07:12:32 +01:00
Compare commits
180 Commits
mdns-v1.4.
...
modem-v1.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
752ac663a5 | ||
|
|
9cd7b2ad60 | ||
|
|
309ba9e2b2 | ||
|
|
a80a3cbb1e | ||
|
|
2cc7c99664 | ||
|
|
07be98ebc3 | ||
|
|
9719450778 | ||
|
|
aa94e168d8 | ||
|
|
0d17f19f8d | ||
|
|
d65f8f6986 | ||
|
|
8b58f03a2b | ||
|
|
6a8aeb6c9b | ||
|
|
b452066087 | ||
|
|
5179f55202 | ||
|
|
26b3859cfb | ||
|
|
b710dbd2ad | ||
|
|
5eeb29cb94 | ||
|
|
a00117fbdb | ||
|
|
6ed672da7b | ||
|
|
1b4baaed0e | ||
|
|
74b7d85d4a | ||
|
|
317faf89ff | ||
|
|
b97dfc08b8 | ||
|
|
e9d7350219 | ||
|
|
61da30b013 | ||
|
|
8fd2c99f15 | ||
|
|
8560f02191 | ||
|
|
703c49297f | ||
|
|
2fe8345fa5 | ||
|
|
3fc26a5e5c | ||
|
|
5db6be7422 | ||
|
|
8ca45f34fa | ||
|
|
2e28774228 | ||
|
|
e14e21ab32 | ||
|
|
6f00c369fc | ||
|
|
905b84fb97 | ||
|
|
d7f5322a39 | ||
|
|
eb12d05bf3 | ||
|
|
520b8194fc | ||
|
|
40142cdcfd | ||
|
|
c7663cdef2 | ||
|
|
e01e67e7eb | ||
|
|
37f84ee5a4 | ||
|
|
95b56600ed | ||
|
|
a22c3da49e | ||
|
|
5d0fd5c1c5 | ||
|
|
7ea6879a19 | ||
|
|
2db11bbb8c | ||
|
|
cdb7bfd188 | ||
|
|
c679ceed85 | ||
|
|
c009892968 | ||
|
|
5f66f35f5f | ||
|
|
dea5f1c431 | ||
|
|
384d1c23ba | ||
|
|
88162d1f3a | ||
|
|
e65f22ab6c | ||
|
|
7d29b47676 | ||
|
|
f1a72ec42c | ||
|
|
ce160505dc | ||
|
|
87e96b4682 | ||
|
|
5b2077e373 | ||
|
|
b45fe143a4 | ||
|
|
ee2fbbbee7 | ||
|
|
cb061c9c38 | ||
|
|
0690eba3a8 | ||
|
|
eb4ab52487 | ||
|
|
8fcad10ccf | ||
|
|
936e43f9d8 | ||
|
|
64d818b2d3 | ||
|
|
cd07228f81 | ||
|
|
1c6580e22b | ||
|
|
87f835af0f | ||
|
|
85a8dac42d | ||
|
|
39866116f5 | ||
|
|
7740b591b6 | ||
|
|
b57979d967 | ||
|
|
42674b49f9 | ||
|
|
e069ae7762 | ||
|
|
44d476fc50 | ||
|
|
55385ec312 | ||
|
|
a3c2bbed9e | ||
|
|
84c47c37f1 | ||
|
|
e7273c46ec | ||
|
|
2e7d240abd | ||
|
|
d4a004b5b4 | ||
|
|
9046af8f8d | ||
|
|
eeeb9006eb | ||
|
|
b167aa315f | ||
|
|
72ba24470d | ||
|
|
7dc87d28b2 | ||
|
|
ac6a388cdd | ||
|
|
76aaea08d2 | ||
|
|
5db32cce30 | ||
|
|
9bdd429c7c | ||
|
|
6f7c52cc3f | ||
|
|
27435b7f34 | ||
|
|
813331f003 | ||
|
|
bd23c233a4 | ||
|
|
4eda7d472f | ||
|
|
163029c0b6 | ||
|
|
96eae25096 | ||
|
|
ebec8eff63 | ||
|
|
4451a8c5ad | ||
|
|
6d19aabb02 | ||
|
|
9162de1150 | ||
|
|
dbd164dd91 | ||
|
|
90d663ad01 | ||
|
|
a83f1b6787 | ||
|
|
84caca465d | ||
|
|
8f81478fff | ||
|
|
ae5a8ceeda | ||
|
|
774bab22ea | ||
|
|
265e38d684 | ||
|
|
93f772171c | ||
|
|
4ad88e297f | ||
|
|
196198ecc9 | ||
|
|
e838bf03f4 | ||
|
|
99b54ac384 | ||
|
|
f5be2f4115 | ||
|
|
9b74256b51 | ||
|
|
3d8835cfb9 | ||
|
|
24f55ce9b4 | ||
|
|
8f8516cc3f | ||
|
|
75a8e8640a | ||
|
|
907087c09b | ||
|
|
68a9e14898 | ||
|
|
827ea65fd5 | ||
|
|
9537721600 | ||
|
|
4394f845fc | ||
|
|
9b0ba6060f | ||
|
|
7c6a3098af | ||
|
|
f3f3e23bec | ||
|
|
9ed835ba3f | ||
|
|
f12a205657 | ||
|
|
5bd82c01a5 | ||
|
|
b4cb8f8a66 | ||
|
|
0499ed93df | ||
|
|
ade9448c01 | ||
|
|
4745fc8fe1 | ||
|
|
73e523e736 | ||
|
|
3cd0ed377b | ||
|
|
95294f5f89 | ||
|
|
5dcc33300f | ||
|
|
840a561de4 | ||
|
|
e6fb8aa078 | ||
|
|
3b2c614d86 | ||
|
|
cdeab8f517 | ||
|
|
6cce87e465 | ||
|
|
d57b8c5b29 | ||
|
|
9c11003449 | ||
|
|
85a7fc772c | ||
|
|
b090a3cb69 | ||
|
|
42cde46c97 | ||
|
|
beb6e57e5e | ||
|
|
15d3a01e11 | ||
|
|
e12ecb8e89 | ||
|
|
54271a1b96 | ||
|
|
886215032f | ||
|
|
269351f41c | ||
|
|
5e929902c7 | ||
|
|
f7c0b7564a | ||
|
|
c989c6adae | ||
|
|
18f196fa1e | ||
|
|
1db83cd1ca | ||
|
|
247f1681e8 | ||
|
|
32387f7e39 | ||
|
|
dbc3ea6809 | ||
|
|
8b6ea3311a | ||
|
|
8e55b93b59 | ||
|
|
0cb59ff80d | ||
|
|
1284f66d58 | ||
|
|
c5b49de2db | ||
|
|
2e9bb6ee45 | ||
|
|
1fcc5b1d56 | ||
|
|
849fe7b6cb | ||
|
|
5eadf1edee | ||
|
|
428fdbbd80 | ||
|
|
433a033fcc | ||
|
|
090b1ff845 | ||
|
|
295d99df96 |
@@ -13,7 +13,7 @@ jobs:
|
||||
name: Build
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "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"]
|
||||
idf_target: ["esp32", "esp32s2"]
|
||||
example: ["asio_chat", "async_request", "socks4", "ssl_client_server", "tcp_echo_server", "udp_echo_server"]
|
||||
runs-on: ubuntu-22.04
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
name: Target tests
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.0", "release-v5.2", "release-v5.3"]
|
||||
idf_ver: ["latest", "release-v5.1", "release-v5.2", "release-v5.3", "release-v5.4"]
|
||||
idf_target: ["esp32"]
|
||||
example: ["asio_chat", "tcp_echo_server", "udp_echo_server", "ssl_client_server"]
|
||||
needs: build_asio
|
||||
|
||||
7
.github/workflows/clang-tidy.yml
vendored
7
.github/workflows/clang-tidy.yml
vendored
@@ -9,10 +9,10 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
name: Run clang-tidy
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: Install esp-clang
|
||||
@@ -24,6 +24,7 @@ jobs:
|
||||
chmod +x clang-tidy-sarif
|
||||
curl -sSL https://raw.githubusercontent.com/espressif/idf-extra-components/master/.github/filter_sarif.py -o filter_sarif.py
|
||||
- name: Install pyclang
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install pyclang~=0.2.0
|
||||
@@ -49,7 +50,7 @@ jobs:
|
||||
results.sarif
|
||||
results.sarif.raw
|
||||
- name: Upload SARIF file
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
category: clang-tidy
|
||||
|
||||
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
|
||||
2
.github/workflows/eppp__build.yml
vendored
2
.github/workflows/eppp__build.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.3"]
|
||||
test: [ { app: host, path: "examples/host" }, { app: slave, path: "examples/slave" }, { app: test_app, path: "test/test_app" }]
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
|
||||
50
.github/workflows/examples_build-host-test.yml
vendored
50
.github/workflows/examples_build-host-test.yml
vendored
@@ -13,12 +13,15 @@ jobs:
|
||||
name: Build examples
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.1", "release-v5.2", "release-v5.3"]
|
||||
idf_ver: ["latest", "release-v5.1", "release-v5.2", "release-v5.3", "release-v5.4"]
|
||||
include:
|
||||
- idf_ver: "latest"
|
||||
warning: "Warning: The smallest app partition is nearly full"
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
env:
|
||||
TARGET_TEST: examples/esp_netif/slip_custom_netif/
|
||||
TARGET_TEST_DIR: build_esp32c3_target
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v4
|
||||
@@ -31,6 +34,16 @@ jobs:
|
||||
python -m pip install idf-build-apps
|
||||
# Build default configs for all targets
|
||||
python ./ci/build_apps.py examples -m examples/.build-test-rules.yml -d -c
|
||||
# Build target tests
|
||||
python ./ci/build_apps.py ${TARGET_TEST} -r sdkconfig.ci=target
|
||||
cd ${TARGET_TEST}
|
||||
${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: slip_target_${{ matrix.idf_ver }}
|
||||
path: ${{ env.TARGET_TEST }}/artifacts.zip
|
||||
if-no-files-found: error
|
||||
|
||||
build_and_run_on_host:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'examples') || github.event_name == 'push'
|
||||
@@ -51,3 +64,38 @@ jobs:
|
||||
python ./ci/build_apps.py examples/mqtt -l -t linux
|
||||
timeout 5 ./examples/mqtt/build_linux_default/esp_mqtt_demo.elf | tee test.log || true
|
||||
grep 'MQTT_EVENT_DATA' test.log
|
||||
|
||||
run_on_target:
|
||||
# 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, 'examples') || github.event_name == 'push' )
|
||||
name: Slip example target test
|
||||
needs: build_all_examples
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["release-v5.4", "latest"]
|
||||
runs-on:
|
||||
- self-hosted
|
||||
- modem
|
||||
env:
|
||||
TARGET_TEST: examples/esp_netif/slip_custom_netif/
|
||||
TARGET_TEST_DIR: build_esp32c3_target
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: slip_target_${{ matrix.idf_ver }}
|
||||
path: ${{ env.TARGET_TEST }}/ci/
|
||||
- name: Run Test
|
||||
working-directory: ${{ env.TARGET_TEST }}
|
||||
run: |
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install --prefer-binary cryptography pytest-embedded pytest-embedded-serial-esp pytest-embedded-idf pytest-custom_exit_code esptool netifaces
|
||||
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 --target=esp32c3
|
||||
done
|
||||
|
||||
86
.github/workflows/lws_build.yml
vendored
Normal file
86
.github/workflows/lws_build.yml
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
name: "lws: build-tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, labeled]
|
||||
|
||||
jobs:
|
||||
build_lws:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'lws') || github.event_name == 'push'
|
||||
name: Libwebsockets build
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.3", "release-v5.4"]
|
||||
test: [ { app: example, path: "examples/client" }]
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
env:
|
||||
TEST_DIR: components/libwebsockets/${{ matrix.test.path }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
python -m pip install idf-build-apps
|
||||
python ./ci/build_apps.py ${TEST_DIR}
|
||||
cd ${TEST_DIR}
|
||||
for dir in `ls -d build_esp32_*`; do
|
||||
$GITHUB_WORKSPACE/ci/clean_build_artifacts.sh `pwd`/$dir
|
||||
zip -qur artifacts.zip $dir
|
||||
done
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: lws_target_esp32_${{ matrix.idf_ver }}_${{ matrix.test.app }}
|
||||
path: ${{ env.TEST_DIR }}/artifacts.zip
|
||||
if-no-files-found: error
|
||||
|
||||
run-target-lws:
|
||||
# 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, 'lws') || github.event_name == 'push' )
|
||||
name: Target test
|
||||
needs: build_lws
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.3", "release-v5.4"]
|
||||
idf_target: ["esp32"]
|
||||
test: [ { app: example, path: "examples/client" }]
|
||||
runs-on:
|
||||
- self-hosted
|
||||
- ESP32-ETHERNET-KIT
|
||||
env:
|
||||
TEST_DIR: components/libwebsockets/${{ matrix.test.path }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: lws_target_esp32_${{ matrix.idf_ver }}_${{ matrix.test.app }}
|
||||
path: ${{ env.TEST_DIR }}/ci/
|
||||
- name: Install Python packages
|
||||
env:
|
||||
PIP_EXTRA_INDEX_URL: "https://www.piwheels.org/simple"
|
||||
run: |
|
||||
pip install --only-binary cryptography --extra-index-url https://dl.espressif.com/pypi/ -r $GITHUB_WORKSPACE/ci/requirements.txt
|
||||
- name: Run Example Test on target
|
||||
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_${{ matrix.test.app }}_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${dir#"ci/build_"}.xml --target=${{ matrix.idf_target }}
|
||||
done
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: results_${{ matrix.test.app }}_${{ matrix.idf_target }}_${{ matrix.idf_ver }}.xml
|
||||
path: components/libwebsockets/${{ matrix.test.path }}/*.xml
|
||||
24
.github/workflows/mdns__host-tests.yml
vendored
24
.github/workflows/mdns__host-tests.yml
vendored
@@ -35,30 +35,36 @@ jobs:
|
||||
# Next we run the pytest (using the console app)
|
||||
pytest
|
||||
|
||||
build_afl_host_test_mdns:
|
||||
host_compat_checks:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'mdns') || github.event_name == 'push'
|
||||
name: Build AFL host test
|
||||
name: Set of compatibility checks
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
idf_target: ["esp32"]
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: esp-protocols
|
||||
- name: Install Necessary Libs
|
||||
run: |
|
||||
apt-get update -y
|
||||
apt-get install -y libbsd-dev
|
||||
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
env:
|
||||
IDF_TARGET: ${{ matrix.idf_target }}
|
||||
- name: Test AFL compat build
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/tests/test_afl_fuzz_host/
|
||||
cd components/mdns/tests/test_afl_fuzz_host/
|
||||
make INSTR=off
|
||||
- name: Test no malloc functions
|
||||
shell: bash
|
||||
run: |
|
||||
cd components/mdns
|
||||
for file in $(ls *.c); do
|
||||
cp $file /tmp
|
||||
echo -n "Checking that $file does not call any std allocations directly..."
|
||||
python mem_prefix_script.py $file
|
||||
diff -q $file /tmp/$file || exit 1
|
||||
echo "OK"
|
||||
done
|
||||
|
||||
24
.github/workflows/modem__build-host-tests.yml
vendored
24
.github/workflows/modem__build-host-tests.yml
vendored
@@ -13,35 +13,21 @@ 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"
|
||||
warning: "Warning: The smallest app partition is nearly full"
|
||||
|
||||
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
|
||||
- if: ${{ matrix.skip_config }}
|
||||
run: rm -f $GITHUB_WORKSPACE/protocols/components/esp_modem/examples/${{ matrix.example }}/sdkconfig.ci.${{ matrix.skip_config }}*
|
||||
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }}
|
||||
env:
|
||||
EXPECTED_WARNING: ${{ matrix.warning }}
|
||||
shell: bash
|
||||
env:
|
||||
EXPECTED_WARNING: "Warning: The smallest app partition is nearly full\nwarning: unknown kconfig symbol 'ESP32_PANIC_PRINT_HALT'"
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
python -m pip install idf-build-apps
|
||||
@@ -53,7 +39,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
|
||||
|
||||
13
.github/workflows/modem__target-test.yml
vendored
13
.github/workflows/modem__target-test.yml
vendored
@@ -42,7 +42,7 @@ jobs:
|
||||
idf.py set-target ${{ matrix.idf_target }}
|
||||
idf.py build
|
||||
$GITHUB_WORKSPACE/ci/clean_build_artifacts.sh ${GITHUB_WORKSPACE}/${TEST_DIR}/build
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: modem_target_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.test.app }}
|
||||
path: ${{ env.TEST_DIR }}/build
|
||||
@@ -75,12 +75,17 @@ jobs:
|
||||
run: |
|
||||
sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: modem_target_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.test.app }}
|
||||
path: ${{ env.TEST_DIR }}/build
|
||||
- name: Run Example Test on target
|
||||
working-directory: ${{ env.TEST_DIR }}
|
||||
env:
|
||||
PIP_EXTRA_INDEX_URL: "https://dl.espressif.com/pypi/"
|
||||
run: |
|
||||
python -m pip install -r $GITHUB_WORKSPACE/ci/requirements.txt
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install --prefer-binary cryptography pytest-embedded pytest-embedded-serial-esp pytest-embedded-idf pytest-custom_exit_code esptool
|
||||
pip install -r $GITHUB_WORKSPACE/ci/requirements.txt
|
||||
cd ${{ env.TEST_DIR }}
|
||||
python -m pytest --log-cli-level DEBUG --target=${{ matrix.idf_target }}
|
||||
|
||||
115
.github/workflows/mosq__build.yml
vendored
115
.github/workflows/mosq__build.yml
vendored
@@ -17,7 +17,8 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
env:
|
||||
TEST_DIR: components/mosquitto/examples/broker
|
||||
TEST_DIR: components/mosquitto/examples
|
||||
TARGET_TEST: broker
|
||||
TARGET_TEST_DIR: build_esp32_default
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
@@ -29,14 +30,15 @@ jobs:
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
python ci/build_apps.py ${TEST_DIR}
|
||||
cd ${TEST_DIR}
|
||||
python ci/build_apps.py -c ${TEST_DIR} -m components/mosquitto/.build-test-rules.yml
|
||||
# upload only the target test artifacts
|
||||
cd ${TEST_DIR}/${TARGET_TEST}
|
||||
${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
|
||||
path: ${{ env.TEST_DIR }}/${{ env.TARGET_TEST }}/artifacts.zip
|
||||
if-no-files-found: error
|
||||
|
||||
test_mosq:
|
||||
@@ -71,3 +73,108 @@ jobs:
|
||||
mv $dir build
|
||||
python -m pytest --log-cli-level DEBUG --junit-xml=./results_esp32_${{ matrix.idf_ver }}_${dir#"ci/build_"}.xml --target=esp32
|
||||
done
|
||||
|
||||
check_consistency:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'mosquitto') || github.event_name == 'push'
|
||||
name: Checks that API docs and versions are consistent
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Checks API Docs and versions
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install doxygen
|
||||
pip install esp-doxybook
|
||||
cd components/mosquitto
|
||||
cp api.md api_orig.md
|
||||
./generate_api_docs.sh
|
||||
diff -wB api.md api_orig.md
|
||||
# check version consistency
|
||||
CONFIG_VERSION=$(grep -Po '(?<=#define VERSION ")[^"]*' port/priv_include/config.h)
|
||||
CZ_VERSION=$(grep -Po '(?<=version: )[^"]*' .cz.yaml)
|
||||
COMP_VERSION=$(grep -Po '(?<=version: ")[^"]*' idf_component.yml)
|
||||
if [ "$CONFIG_VERSION" != "v$CZ_VERSION" ] || [ "$CONFIG_VERSION" != "v$COMP_VERSION" ]; then
|
||||
echo "Version mismatch detected:"
|
||||
echo "config.h: $CONFIG_VERSION"
|
||||
echo ".cz.yaml: $CZ_VERSION"
|
||||
echo "idf_component.yml: $COMP_VERSION"
|
||||
exit 1
|
||||
fi
|
||||
echo "Versions are consistent: $CONFIG_VERSION"
|
||||
|
||||
build_idf_tests_with_mosq:
|
||||
if: |
|
||||
github.repository == 'espressif/esp-protocols' &&
|
||||
( contains(github.event.pull_request.labels.*.name, 'mosquitto') || github.event_name == 'push' )
|
||||
name: Build IDF tests
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
idf_target: ["esp32"]
|
||||
test: [ { app: publish, path: "tools/test_apps/protocols/mqtt/publish_connect_test" }]
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
env:
|
||||
TARGET_TEST_DIR: build_esp32_local_broker
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
export MOSQUITTO_PATH=`pwd`/components/mosquitto
|
||||
# to use the actual version of mosquitto
|
||||
sed -i '/espressif\/mosquitto:/a \ \ \ \ override_path: "${MOSQUITTO_PATH}"' ${IDF_PATH}/${{matrix.test.path}}/main/idf_component.yml
|
||||
export PEDANTIC_FLAGS="-DIDF_CI_BUILD -Werror -Werror=deprecated-declarations -Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function"
|
||||
export EXTRA_CFLAGS="${PEDANTIC_FLAGS} -Wstrict-prototypes"
|
||||
export EXTRA_CXXFLAGS="${PEDANTIC_FLAGS}"
|
||||
cd ${IDF_PATH}/${{matrix.test.path}}
|
||||
idf-build-apps find --config sdkconfig.ci.local_broker -vv --target ${{ matrix.idf_target }} --build-dir=${TARGET_TEST_DIR}
|
||||
idf-build-apps build --config sdkconfig.ci.local_broker -vv --target ${{ matrix.idf_target }} --build-dir=${TARGET_TEST_DIR}
|
||||
${GITHUB_WORKSPACE}/ci/clean_build_artifacts.sh `pwd`/${TARGET_TEST_DIR}
|
||||
# to replace mqtt test configs with specific mosquitto markers
|
||||
python ${MOSQUITTO_PATH}/test/replace_decorators.py pytest_mqtt_publish_app.py ${TARGET_TEST_DIR}/pytest_mosquitto.py
|
||||
zip -qur ${GITHUB_WORKSPACE}/artifacts.zip ${TARGET_TEST_DIR}
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: mosq_publish_esp32_${{ matrix.idf_ver }}
|
||||
path: artifacts.zip
|
||||
if-no-files-found: error
|
||||
|
||||
test_idf_ci_with_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 IDF target tests
|
||||
needs: build_idf_tests_with_mosq
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
runs-on:
|
||||
- self-hosted
|
||||
- ESP32-ETHERNET-KIT
|
||||
env:
|
||||
TEST_DIR: examples
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: mosq_publish_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 "paho-mqtt<2" --upgrade
|
||||
unzip ci/artifacts.zip -d ci
|
||||
for dir in `ls -d ci/build_*`; do
|
||||
rm -rf build sdkconfig.defaults
|
||||
mv $dir build
|
||||
mv build/*.py .
|
||||
# Run only "test_mosquitto" marked tests
|
||||
python -m pytest --log-cli-level DEBUG --junit-xml=./results_esp32_${{ matrix.idf_ver }}_${dir#"ci/build_"}.xml --target=esp32 -m test_mosquitto
|
||||
done
|
||||
|
||||
45
.github/workflows/pre_commit_check.yml
vendored
45
.github/workflows/pre_commit_check.yml
vendored
@@ -1,45 +0,0 @@
|
||||
name: Check pre-commit rules
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, reopened, synchronize]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
pre_commit_check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.base_ref }}
|
||||
fetch-depth: 20
|
||||
- name: Fetch head and base refs
|
||||
# This is necessary for pre-commit to check the changes in the PR branch (and to set origin/HEAD and HEAD refs)
|
||||
run: |
|
||||
git fetch origin ${{ github.event.pull_request.head.sha }}:pr_ref
|
||||
git checkout pr_ref
|
||||
git remote set-head origin --auto
|
||||
git merge-base origin/HEAD HEAD || ( echo "Your PR is far behind origin/HEAD, please rebase" && exit 1 )
|
||||
- name: Set up Python environment
|
||||
uses: actions/setup-python@master
|
||||
with:
|
||||
python-version: v3.8
|
||||
- name: Install python packages
|
||||
run: |
|
||||
pip install pre-commit
|
||||
pre-commit install-hooks
|
||||
- name: Run pre-commit and check for any changes
|
||||
run: |
|
||||
echo "Commits being checked:"
|
||||
git log --oneline --no-decorate origin/HEAD..HEAD
|
||||
echo ""
|
||||
if ! pre-commit run --from-ref origin/HEAD --to-ref HEAD --hook-stage manual --show-diff-on-failure ; then
|
||||
echo ""
|
||||
echo "::notice::It looks like the commits in this PR have been made without having pre-commit hooks installed."
|
||||
echo "::notice::Please see https://github.com/espressif/esp-protocols/CONTRIBUTING.md for instructions."
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
16
.github/workflows/publish-docs-component.yml
vendored
16
.github/workflows/publish-docs-component.yml
vendored
@@ -4,6 +4,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release-modem-v1.4
|
||||
|
||||
env:
|
||||
DOCS_DEPLOY_URL_BASE: ${{ secrets.DOCS_DEPLOY_URL_BASE }}
|
||||
@@ -55,9 +56,6 @@ jobs:
|
||||
if [[ "${{ env.BUMP_COMPONENT }}" == "${comp}" ]]; then
|
||||
echo "Building specific version of ${comp} (${{ env.BUMP_VERSION }})"
|
||||
./generate_docs ${{ env.BUMP_VERSION }}
|
||||
else
|
||||
echo "Building latest version of ${comp}"
|
||||
./generate_docs
|
||||
fi
|
||||
fi
|
||||
done
|
||||
@@ -67,16 +65,6 @@ jobs:
|
||||
source $GITHUB_WORKSPACE/docs/utils.sh
|
||||
add_doc_server_ssh_keys $DOCS_DEPLOY_KEY $DOCS_DEPLOY_SERVER $DOCS_DEPLOY_SERVER_USER
|
||||
export GIT_VER=$(git describe --always)
|
||||
export GITHUB_REF_NAME=latest
|
||||
for comp in `ls components`; do
|
||||
if [[ -d $GITHUB_WORKSPACE/docs/${comp} ]]; then
|
||||
echo "Deploying latest of ${comp}"
|
||||
export DOCS_BUILD_DIR=$GITHUB_WORKSPACE/docs/${comp}
|
||||
export DOCS_DEPLOY_PATH=$DOCS_DEPLOY_PATH_ORIG/${comp}
|
||||
cd $GITHUB_WORKSPACE/docs/${comp}
|
||||
deploy-docs
|
||||
fi
|
||||
done;
|
||||
# Deploy docs with version path
|
||||
if [[ "${{ env.BUMP_VERSION }}" != "" ]] && [[ -d $GITHUB_WORKSPACE/docs/${{ env.BUMP_COMPONENT }} ]]; then
|
||||
echo "Deploying specific version of ${{ env.BUMP_COMPONENT }} (${{ env.BUMP_VERSION }})"
|
||||
@@ -98,8 +86,10 @@ jobs:
|
||||
components/console_cmd_ping;
|
||||
components/console_cmd_ifconfig;
|
||||
components/console_cmd_wifi;
|
||||
components/console_cmd_mqtt;
|
||||
components/mbedtls_cxx;
|
||||
components/mosquitto;
|
||||
components/sock_utils;
|
||||
components/libwebsockets;
|
||||
namespace: "espressif"
|
||||
api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }}
|
||||
|
||||
2
.github/workflows/tls_cxx__build.yml
vendored
2
.github/workflows/tls_cxx__build.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.3", "release-v5.2", "release-v5.1"]
|
||||
test: [ { app: client, path: "examples/tls_client" }, { app: udp, path: "examples/udp_mutual_auth" }, { app: test, path: "tests/uart_mutual_auth" } ]
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
|
||||
5
.gitmodules
vendored
5
.gitmodules
vendored
@@ -1,6 +1,9 @@
|
||||
[submodule "components/asio/asio"]
|
||||
path = components/asio/asio
|
||||
url = https://github.com/espressif/asio
|
||||
url = https://github.com/chriskohlhoff/asio
|
||||
[submodule "components/mosquitto/mosquitto"]
|
||||
path = components/mosquitto/mosquitto
|
||||
url = https://github.com/eclipse/mosquitto
|
||||
[submodule "components/libwebsockets/libwebsockets"]
|
||||
path = components/libwebsockets/libwebsockets
|
||||
url = https://github.com/warmcat/libwebsockets.git
|
||||
|
||||
@@ -51,7 +51,7 @@ repos:
|
||||
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']
|
||||
args: ['--style=otbs', '--attach-namespaces', '--attach-classes', '--indent=spaces=4', '--convert-tabs', '--align-reference=name', '--keep-one-line-statements', '--pad-header', '--pad-oper', '--unpad-paren', '--max-continuation-indent=120', '--exclude-list=ci/ignore_astyle.txt']
|
||||
- repo: https://github.com/commitizen-tools/commitizen
|
||||
rev: v2.42.1
|
||||
hooks:
|
||||
@@ -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, 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)\)\:)'
|
||||
name: "commit message must be scoped with: mdns, modem, websocket, asio, mqtt_cxx, console, common, eppp, tls_cxx, mosq, sockutls, lws"
|
||||
entry: '\A(?!(feat|fix|ci|bump|test|docs|chore)\((mdns|modem|common|console|websocket|asio|mqtt_cxx|examples|eppp|tls_cxx|mosq|sockutls|lws)\)\:)'
|
||||
language: pygrep
|
||||
args: [--multiline]
|
||||
stages: [commit-msg]
|
||||
|
||||
@@ -66,3 +66,7 @@ Please refer to instructions in [ESP-IDF](https://github.com/espressif/esp-idf)
|
||||
### Socket helpers (sock-utils)
|
||||
|
||||
* Brief introduction [README](components/sock_utils/README.md)
|
||||
|
||||
### libwebsockets
|
||||
|
||||
* Brief introduction [README](components/libwebsockets/README.md)
|
||||
|
||||
@@ -56,7 +56,7 @@ if __name__ == '__main__':
|
||||
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,
|
||||
size_json_filename=None,
|
||||
check_warnings=True,
|
||||
manifest_files=args.manifests,
|
||||
default_build_targets=SUPPORTED_TARGETS,
|
||||
@@ -65,6 +65,7 @@ if __name__ == '__main__':
|
||||
|
||||
sys.exit(
|
||||
build_apps(apps,
|
||||
verbose=2,
|
||||
dry_run=False,
|
||||
keep_going=False,
|
||||
no_preserve=args.delete,
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
components/mosquitto/examples/serverless_mqtt/components/libjuice/port/juice_random.c
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -64,7 +64,7 @@ static struct generic_queue_handle *create_generic_queue(queue_type_t type, uint
|
||||
return h;
|
||||
}
|
||||
|
||||
QueueHandle_t xQueueCreate(uint32_t uxQueueLength, uint32_t uxItemSize )
|
||||
QueueHandle_t xQueueCreate(uint32_t uxQueueLength, uint32_t uxItemSize)
|
||||
{
|
||||
return (QueueHandle_t)create_generic_queue(QUEUE, uxQueueLength, uxItemSize);
|
||||
}
|
||||
@@ -75,7 +75,7 @@ uint32_t xQueueSend(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t
|
||||
return osal_queue_send(h->q, (uint8_t *)pvItemToQueue, h->item_size) ? pdTRUE : pdFAIL;
|
||||
}
|
||||
|
||||
uint32_t xQueueSendToBack(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait )
|
||||
uint32_t xQueueSendToBack(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait)
|
||||
{
|
||||
return xQueueSend(xQueue, pvItemToQueue, xTicksToWait);
|
||||
}
|
||||
@@ -86,7 +86,7 @@ uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksTo
|
||||
return osal_queue_recv(h->q, (uint8_t *)pvBuffer, h->item_size, xTicksToWait) ? pdTRUE : pdFAIL;
|
||||
}
|
||||
|
||||
BaseType_t xSemaphoreGive( QueueHandle_t xQueue)
|
||||
BaseType_t xSemaphoreGive(QueueHandle_t xQueue)
|
||||
{
|
||||
struct generic_queue_handle *h = xQueue;
|
||||
if (h->type == MUTEX) {
|
||||
@@ -96,7 +96,7 @@ BaseType_t xSemaphoreGive( QueueHandle_t xQueue)
|
||||
return xQueueSend(xQueue, &s_semaphore_data, portMAX_DELAY);
|
||||
}
|
||||
|
||||
BaseType_t xSemaphoreGiveRecursive( QueueHandle_t xQueue)
|
||||
BaseType_t xSemaphoreGiveRecursive(QueueHandle_t xQueue)
|
||||
{
|
||||
struct generic_queue_handle *h = xQueue;
|
||||
if (h->type == MUTEX_REC) {
|
||||
@@ -106,7 +106,7 @@ BaseType_t xSemaphoreGiveRecursive( QueueHandle_t xQueue)
|
||||
return pdFALSE;
|
||||
}
|
||||
|
||||
BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask )
|
||||
BaseType_t xSemaphoreTake(QueueHandle_t xQueue, TickType_t pvTask)
|
||||
{
|
||||
struct generic_queue_handle *h = xQueue;
|
||||
if (h->type == MUTEX) {
|
||||
@@ -116,7 +116,7 @@ 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 )
|
||||
BaseType_t xSemaphoreTakeRecursive(QueueHandle_t xQueue, TickType_t pvTask)
|
||||
{
|
||||
struct generic_queue_handle *h = xQueue;
|
||||
if (h->type == MUTEX_REC) {
|
||||
@@ -126,7 +126,7 @@ BaseType_t xSemaphoreTakeRecursive( QueueHandle_t xQueue, TickType_t pvTask )
|
||||
return pdFALSE;
|
||||
}
|
||||
|
||||
void vQueueDelete( QueueHandle_t xQueue )
|
||||
void vQueueDelete(QueueHandle_t xQueue)
|
||||
{
|
||||
struct generic_queue_handle *h = xQueue;
|
||||
if (h->q) {
|
||||
@@ -166,6 +166,8 @@ void vTaskDelete(TaskHandle_t *task)
|
||||
|
||||
if (task == NULL) {
|
||||
pthread_exit(0);
|
||||
} else {
|
||||
pthread_cancel((pthread_t)task);
|
||||
}
|
||||
void *thread_rval = NULL;
|
||||
pthread_join((pthread_t)task, &thread_rval);
|
||||
@@ -176,14 +178,14 @@ void vTaskSuspend(void *task)
|
||||
vTaskDelete(task);
|
||||
}
|
||||
|
||||
TickType_t xTaskGetTickCount( void )
|
||||
TickType_t xTaskGetTickCount(void)
|
||||
{
|
||||
struct timespec spec;
|
||||
clock_gettime(CLOCK_REALTIME, &spec);
|
||||
return spec.tv_nsec / 1000000 + spec.tv_sec * 1000;
|
||||
}
|
||||
|
||||
void vTaskDelay( const TickType_t xTicksToDelay )
|
||||
void vTaskDelay(const TickType_t xTicksToDelay)
|
||||
{
|
||||
usleep(xTicksToDelay * 1000);
|
||||
}
|
||||
@@ -212,13 +214,27 @@ void *pthread_task(void *params)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode,
|
||||
const char *const pcName,
|
||||
const uint32_t usStackDepth,
|
||||
void *const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
TaskHandle_t *const pvCreatedTask,
|
||||
const BaseType_t xCoreID)
|
||||
TaskHandle_t xTaskCreateStaticPinnedToCore(TaskFunction_t pxTaskCode,
|
||||
const char *const pcName,
|
||||
const uint32_t ulStackDepth,
|
||||
void *const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
StackType_t *const puxStackBuffer,
|
||||
StaticTask_t *const pxTaskBuffer,
|
||||
const BaseType_t xCoreID)
|
||||
{
|
||||
static TaskHandle_t pvCreatedTask;
|
||||
xTaskCreate(pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &pvCreatedTask);
|
||||
return pvCreatedTask;
|
||||
}
|
||||
|
||||
BaseType_t xTaskCreatePinnedToCore(TaskFunction_t pvTaskCode,
|
||||
const char *const pcName,
|
||||
const uint32_t usStackDepth,
|
||||
void *const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
TaskHandle_t *const pvCreatedTask,
|
||||
const BaseType_t xCoreID)
|
||||
{
|
||||
xTaskCreate(pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pvCreatedTask);
|
||||
return pdTRUE;
|
||||
@@ -266,7 +282,7 @@ void xTaskNotifyGive(TaskHandle_t task)
|
||||
}
|
||||
}
|
||||
|
||||
BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time )
|
||||
BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -276,32 +292,32 @@ TaskHandle_t xTaskGetCurrentTaskHandle(void)
|
||||
return (TaskHandle_t)pthread_self();
|
||||
}
|
||||
|
||||
EventGroupHandle_t xEventGroupCreate( void )
|
||||
EventGroupHandle_t xEventGroupCreate(void)
|
||||
{
|
||||
return osal_signal_create();
|
||||
}
|
||||
|
||||
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
|
||||
void vEventGroupDelete(EventGroupHandle_t xEventGroup)
|
||||
{
|
||||
osal_signal_delete(xEventGroup);
|
||||
}
|
||||
|
||||
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
|
||||
EventBits_t xEventGroupClearBits(EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear)
|
||||
{
|
||||
return osal_signal_clear(xEventGroup, uxBitsToClear);
|
||||
}
|
||||
|
||||
EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup)
|
||||
EventBits_t xEventGroupGetBits(EventGroupHandle_t xEventGroup)
|
||||
{
|
||||
return osal_signal_get(xEventGroup);
|
||||
}
|
||||
|
||||
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
|
||||
EventBits_t xEventGroupSetBits(EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet)
|
||||
{
|
||||
return osal_signal_set(xEventGroup, uxBitsToSet);
|
||||
}
|
||||
|
||||
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )
|
||||
EventBits_t xEventGroupWaitBits(EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait)
|
||||
{
|
||||
return osal_signal_wait(xEventGroup, uxBitsToWaitFor, xWaitForAllBits, xTicksToWait);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -15,7 +16,10 @@ extern "C" {
|
||||
#define TaskHandle_t TaskHandle_t
|
||||
#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) )
|
||||
|
||||
void vTaskDelay( const TickType_t xTicksToDelay );
|
||||
typedef void *StackType_t;
|
||||
typedef void *StaticTask_t;
|
||||
|
||||
void vTaskDelay(const TickType_t xTicksToDelay);
|
||||
|
||||
void xTaskNotifyGive(TaskHandle_t task);
|
||||
|
||||
@@ -23,39 +27,48 @@ 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 );
|
||||
BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time);
|
||||
|
||||
BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode,
|
||||
const char *const pcName,
|
||||
const uint32_t usStackDepth,
|
||||
void *const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
TaskHandle_t *const pvCreatedTask,
|
||||
const BaseType_t xCoreID);
|
||||
TaskHandle_t xTaskCreateStaticPinnedToCore(TaskFunction_t pxTaskCode,
|
||||
const char *const pcName,
|
||||
const uint32_t ulStackDepth,
|
||||
void *const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
StackType_t *const puxStackBuffer,
|
||||
StaticTask_t *const pxTaskBuffer,
|
||||
const BaseType_t xCoreID);
|
||||
|
||||
BaseType_t xTaskCreatePinnedToCore(TaskFunction_t pvTaskCode,
|
||||
const char *const pcName,
|
||||
const uint32_t usStackDepth,
|
||||
void *const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
TaskHandle_t *const pvCreatedTask,
|
||||
const BaseType_t xCoreID);
|
||||
|
||||
BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char *const pcName, const uint32_t usStackDepth, void *const pvParameters, UBaseType_t uxPriority, TaskHandle_t *const pvCreatedTask);
|
||||
|
||||
TickType_t xTaskGetTickCount( void );
|
||||
TickType_t xTaskGetTickCount(void);
|
||||
|
||||
void vQueueDelete( QueueHandle_t xQueue );
|
||||
void vQueueDelete(QueueHandle_t xQueue);
|
||||
|
||||
QueueHandle_t xSemaphoreCreateBinary(void);
|
||||
|
||||
QueueHandle_t xSemaphoreCreateMutex(void);
|
||||
QueueHandle_t xSemaphoreCreateRecursiveMutex(void);
|
||||
|
||||
BaseType_t xSemaphoreGive( QueueHandle_t xQueue);
|
||||
BaseType_t xSemaphoreGive(QueueHandle_t xQueue);
|
||||
|
||||
BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask );
|
||||
BaseType_t xSemaphoreTake(QueueHandle_t xQueue, TickType_t pvTask);
|
||||
|
||||
BaseType_t xSemaphoreGiveRecursive( QueueHandle_t xQueue);
|
||||
BaseType_t xSemaphoreGiveRecursive(QueueHandle_t xQueue);
|
||||
|
||||
BaseType_t xSemaphoreTakeRecursive( QueueHandle_t xQueue, TickType_t pvTask );
|
||||
BaseType_t xSemaphoreTakeRecursive(QueueHandle_t xQueue, TickType_t pvTask);
|
||||
|
||||
void vTaskDelete(TaskHandle_t *task);
|
||||
|
||||
QueueHandle_t xQueueCreate( uint32_t uxQueueLength,
|
||||
uint32_t uxItemSize );
|
||||
QueueHandle_t xQueueCreate(uint32_t uxQueueLength,
|
||||
uint32_t uxItemSize);
|
||||
|
||||
uint32_t xQueueSend(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait);
|
||||
|
||||
@@ -63,23 +76,26 @@ uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksTo
|
||||
|
||||
void vTaskSuspend(void *task);
|
||||
|
||||
EventGroupHandle_t xEventGroupCreate( void );
|
||||
void vEventGroupDelete( EventGroupHandle_t xEventGroup );
|
||||
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToClear );
|
||||
EventGroupHandle_t xEventGroupCreate(void);
|
||||
void vEventGroupDelete(EventGroupHandle_t xEventGroup);
|
||||
EventBits_t xEventGroupClearBits(EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToClear);
|
||||
|
||||
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToWaitFor,
|
||||
const BaseType_t xClearOnExit,
|
||||
const BaseType_t xWaitForAllBits,
|
||||
TickType_t xTicksToWait );
|
||||
EventBits_t xEventGroupWaitBits(EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToWaitFor,
|
||||
const BaseType_t xClearOnExit,
|
||||
const BaseType_t xWaitForAllBits,
|
||||
TickType_t xTicksToWait);
|
||||
|
||||
EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup);
|
||||
EventBits_t xEventGroupGetBits(EventGroupHandle_t xEventGroup);
|
||||
|
||||
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToSet );
|
||||
EventBits_t xEventGroupSetBits(EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToSet);
|
||||
|
||||
uint32_t xQueueSendToBack(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait );
|
||||
uint32_t xQueueSendToBack(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait);
|
||||
|
||||
void *heap_caps_malloc(size_t size, uint32_t caps);
|
||||
void heap_caps_free(void *ptr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
commitizen:
|
||||
bump_message: 'bump(asio): $current_version -> $new_version'
|
||||
pre_bump_hooks: python ../../ci/changelog.py asio
|
||||
tag_format: asio-v$version
|
||||
version: 1.28.0~0
|
||||
version: 1.32.0
|
||||
version_files:
|
||||
- idf_component.yml
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
# Changelog
|
||||
|
||||
## [1.32.0](https://github.com/espressif/esp-protocols/commits/asio-v1.32.0)
|
||||
|
||||
### Features
|
||||
|
||||
- Upgrade asio to 1.32 ([9bdd429c](https://github.com/espressif/esp-protocols/commit/9bdd429c))
|
||||
- Drop esp/asio patches in favor of sock-utils ([27435b7f](https://github.com/espressif/esp-protocols/commit/27435b7f))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix chat example to print only the message body ([76aaea08](https://github.com/espressif/esp-protocols/commit/76aaea08))
|
||||
- Make asio enable if_nametoindex to fix linking ([5db32cce](https://github.com/espressif/esp-protocols/commit/5db32cce))
|
||||
- Re-applie refs to common comps idf_component.yml ([9fe44a45](https://github.com/espressif/esp-protocols/commit/9fe44a45))
|
||||
- Reference common component from IDF ([74fc228c](https://github.com/espressif/esp-protocols/commit/74fc228c))
|
||||
- Revert referencing protocol_examples_common from IDF ([f9e0281a](https://github.com/espressif/esp-protocols/commit/f9e0281a))
|
||||
- reference protocol_examples_common from IDF ([09abb18b](https://github.com/espressif/esp-protocols/commit/09abb18b))
|
||||
- specify override_path in example manifest files ([1d8923cf](https://github.com/espressif/esp-protocols/commit/1d8923cf))
|
||||
|
||||
### Updated
|
||||
|
||||
- docs(asio): Updates asio docs ([ce9337d3](https://github.com/espressif/esp-protocols/commit/ce9337d3))
|
||||
|
||||
## [1.28.2~0](https://github.com/espressif/esp-protocols/commits/asio-1.28.2_0)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -6,8 +6,8 @@ if(NOT CONFIG_LWIP_IPV6 AND NOT CMAKE_BUILD_EARLY_EXPANSION)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(asio_sources "asio/asio/src/asio.cpp")
|
||||
set(asio_requires lwip)
|
||||
set(asio_sources "asio/asio/src/asio.cpp" "port/src/asio_stub.cpp")
|
||||
set(asio_requires lwip sock_utils)
|
||||
|
||||
if(CONFIG_ASIO_SSL_SUPPORT)
|
||||
list(APPEND asio_sources
|
||||
@@ -18,7 +18,7 @@ if(CONFIG_ASIO_SSL_SUPPORT)
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS ${asio_sources}
|
||||
INCLUDE_DIRS "asio/asio/include" "port/include"
|
||||
INCLUDE_DIRS "port/include" "asio/asio/include"
|
||||
PRIV_INCLUDE_DIRS ${asio_priv_includes}
|
||||
PRIV_REQUIRES ${asio_requires})
|
||||
|
||||
@@ -30,6 +30,7 @@ target_compile_definitions(${COMPONENT_LIB} PUBLIC SA_RESTART=0x01
|
||||
ASIO_STANDALONE
|
||||
ASIO_HAS_PTHREADS
|
||||
OPENSSL_NO_ENGINE
|
||||
ASIO_DETAIL_IMPL_POSIX_EVENT_IPP # this replaces asio's posix_event constructor
|
||||
)
|
||||
|
||||
if(NOT CONFIG_COMPILER_CXX_EXCEPTIONS)
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
menu "ESP-ASIO"
|
||||
visible if LWIP_IPV6
|
||||
|
||||
config ASIO_IS_ENABLED
|
||||
# Invisible option that is enabled if ASIO is added to the IDF components.
|
||||
# This is used to "select" LWIP_NETIF_API option
|
||||
# which enables if_indextoname() and if_nametoindex() functions
|
||||
# (these are optionally used in asio)
|
||||
bool
|
||||
default "y"
|
||||
select LWIP_NETIF_API
|
||||
|
||||
config ASIO_SSL_SUPPORT
|
||||
bool "Enable SSL/TLS support of ASIO"
|
||||
default n
|
||||
|
||||
Submodule components/asio/asio updated: a2e0f70d61...03ae834edb
@@ -120,7 +120,7 @@ private:
|
||||
asio::buffer(read_msg_.body(), read_msg_.body_length()),
|
||||
[this, self](std::error_code ec, std::size_t /*length*/) {
|
||||
if (!ec) {
|
||||
ESP_LOGD("asio-chat:", "%s", read_msg_.body());
|
||||
ESP_LOGD("asio-chat", "%.*s", read_msg_.body_length(), read_msg_.body());
|
||||
room_.deliver(read_msg_);
|
||||
do_read_header();
|
||||
} else {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
version: "1.28.2~0"
|
||||
version: "1.32.0"
|
||||
description: Cross-platform C++ library for network and I/O programming
|
||||
url: https://github.com/espressif/esp-protocols/tree/master/components/asio
|
||||
issues: https://github.com/espressif/esp-protocols/issues
|
||||
@@ -7,3 +7,5 @@ repository: https://github.com/espressif/esp-protocols.git
|
||||
dependencies:
|
||||
idf:
|
||||
version: ">=5.0"
|
||||
espressif/sock_utils:
|
||||
version: "^0.1"
|
||||
|
||||
11
components/asio/port/include/asio/detail/config.hpp
Normal file
11
components/asio/port/include/asio/detail/config.hpp
Normal file
@@ -0,0 +1,11 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "sys/socket.h"
|
||||
#include "socketpair.h"
|
||||
|
||||
#include_next "asio/detail/config.hpp"
|
||||
@@ -1,12 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef _ESP_ASIO_CONFIG_H_
|
||||
#define _ESP_ASIO_CONFIG_H_
|
||||
|
||||
#define ASIO_SSL_DETAIL_OPENSSL_TYPES_HPP
|
||||
#include "openssl_stub.hpp"
|
||||
|
||||
#endif // _ESP_ASIO_CONFIG_H_
|
||||
@@ -8,7 +8,7 @@
|
||||
//
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "openssl_stub.hpp"
|
||||
#include "asio/ssl/detail/openssl_types.hpp"
|
||||
#include <cstring>
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "openssl_stub.hpp"
|
||||
#include "asio/ssl/detail/openssl_types.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/ssl/detail/engine.hpp"
|
||||
|
||||
36
components/asio/port/src/asio_stub.cpp
Normal file
36
components/asio/port/src/asio_stub.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
// SPDX-FileContributor: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
#include "asio/detail/posix_event.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <unistd.h>
|
||||
#include <climits>
|
||||
|
||||
namespace asio::detail {
|
||||
// This replaces asio's posix_event constructor
|
||||
// since the default POSIX version uses pthread_condattr_t operations (init, setclock, destroy),
|
||||
// which are not available on all IDF versions (some are defined in compilers' headers, others in
|
||||
// pthread library, but they typically return `ENOSYS` which causes trouble in the event wrapper)
|
||||
// IMPORTANT: Check implementation of posix_event() when upgrading upstream asio in order not to
|
||||
// miss any initialization step.
|
||||
posix_event::posix_event()
|
||||
: state_(0)
|
||||
{
|
||||
int error = ::pthread_cond_init(&cond_, nullptr);
|
||||
asio::error_code ec(error, asio::error::get_system_category());
|
||||
asio::detail::throw_error(ec, "event");
|
||||
}
|
||||
} // namespace asio::detail
|
||||
|
||||
extern "C" int pause (void)
|
||||
{
|
||||
while (true) {
|
||||
::sleep(UINT_MAX);
|
||||
}
|
||||
}
|
||||
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(modem): $current_version -> $new_version'
|
||||
pre_bump_hooks: python ../../ci/changelog.py esp_modem
|
||||
tag_format: modem-v$version
|
||||
version: 1.2.0
|
||||
version: 1.4.2
|
||||
version_files:
|
||||
- idf_component.yml
|
||||
|
||||
@@ -1,5 +1,60 @@
|
||||
# Changelog
|
||||
|
||||
## [1.4.2](https://github.com/espressif/esp-protocols/commits/modem-v1.4.2)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- CEREG parsing fails due to incorrect state index ([a80a3cbb](https://github.com/espressif/esp-protocols/commit/a80a3cbb))
|
||||
|
||||
## [1.4.1](https://github.com/espressif/esp-protocols/commits/modem-v1.4.1)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Remove unused kconfig ([97194507](https://github.com/espressif/esp-protocols/commit/97194507))
|
||||
- Fix modem console dependencies ([0d17f19f](https://github.com/espressif/esp-protocols/commit/0d17f19f))
|
||||
- Fix CI build issues with IDFv6.0 ([d65f8f69](https://github.com/espressif/esp-protocols/commit/d65f8f69))
|
||||
- Address build issues ([b4520660](https://github.com/espressif/esp-protocols/commit/b4520660))
|
||||
- Fix driver dependency issue on v6.0 ([26b3859c](https://github.com/espressif/esp-protocols/commit/26b3859c))
|
||||
|
||||
## [1.4.0](https://github.com/espressif/esp-protocols/commits/modem-v1.4.0)
|
||||
|
||||
### Features
|
||||
|
||||
- added config_edrx api function ([74b7d85d](https://github.com/espressif/esp-protocols/commit/74b7d85d))
|
||||
- added sqn_gm02s connect function ([b97dfc08](https://github.com/espressif/esp-protocols/commit/b97dfc08))
|
||||
- add support for sequans GM02S modem ([8560f021](https://github.com/espressif/esp-protocols/commit/8560f021))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix cmux log message ([6ed672da](https://github.com/espressif/esp-protocols/commit/6ed672da))
|
||||
- fixed minor code mistakes. ([317faf89](https://github.com/espressif/esp-protocols/commit/317faf89))
|
||||
- handle nullptr in DTE constructors to prevent invalid access ([95b56600](https://github.com/espressif/esp-protocols/commit/95b56600))
|
||||
|
||||
## [1.3.0](https://github.com/espressif/esp-protocols/commits/modem-v1.3.0)
|
||||
|
||||
### Features
|
||||
|
||||
- Add mode detection to the example ([18f196fa](https://github.com/espressif/esp-protocols/commit/18f196fa))
|
||||
- Support for pausing network in C-API ([1db83cd1](https://github.com/espressif/esp-protocols/commit/1db83cd1))
|
||||
- Add support for pausing netif ([247f1681](https://github.com/espressif/esp-protocols/commit/247f1681), [#699](https://github.com/espressif/esp-protocols/issues/699))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Minor cleanup of pppos example ([5e929902](https://github.com/espressif/esp-protocols/commit/5e929902))
|
||||
- Fix PPP mode detection to accept LCP/conf ([c989c6ad](https://github.com/espressif/esp-protocols/commit/c989c6ad))
|
||||
- Refine mode switch data->command ([8b6ea331](https://github.com/espressif/esp-protocols/commit/8b6ea331), [#692](https://github.com/espressif/esp-protocols/issues/692))
|
||||
- Detect serial ports properly ([0cb59ff8](https://github.com/espressif/esp-protocols/commit/0cb59ff8))
|
||||
- Fix CMUX enter to ignore URC before transition ([1284f66d](https://github.com/espressif/esp-protocols/commit/1284f66d), [#669](https://github.com/espressif/esp-protocols/issues/669))
|
||||
|
||||
## [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
|
||||
|
||||
@@ -11,7 +11,12 @@ else()
|
||||
src/esp_modem_uart.cpp
|
||||
src/esp_modem_term_uart.cpp
|
||||
src/esp_modem_netif.cpp)
|
||||
set(dependencies driver esp_event esp_netif)
|
||||
set(dependencies esp_event esp_netif)
|
||||
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER "5.3")
|
||||
list(APPEND dependencies esp_driver_uart)
|
||||
else()
|
||||
list(APPEND dependencies driver)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
@@ -76,4 +76,20 @@ menu "esp-modem"
|
||||
help
|
||||
If enabled, APIs to add URC handler are available
|
||||
|
||||
config ESP_MODEM_PPP_ESCAPE_BEFORE_EXIT
|
||||
bool "Send escape sequence when switching PPP -> CMD"
|
||||
default n
|
||||
help
|
||||
If enabled, the library sends a PPP escape ("+++" command)
|
||||
to switch to command mode. This make switching from PPP to CMD
|
||||
mode more robust for some devices (e.g. Quectel), but might cause
|
||||
trouble for other devices (e.g. SIMCOM).
|
||||
|
||||
config ESP_MODEM_ADD_DEBUG_LOGS
|
||||
bool "Add UART Tx/Rx logs"
|
||||
default n
|
||||
help
|
||||
If enabled, the library dumps all transmitted and received data.
|
||||
This option is only used for debugging.
|
||||
|
||||
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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
@@ -100,10 +100,10 @@ void wifi_init_softap(void)
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
|
||||
ESP_EVENT_ANY_ID,
|
||||
&wifi_event_handler,
|
||||
NULL,
|
||||
NULL));
|
||||
ESP_EVENT_ANY_ID,
|
||||
&wifi_event_handler,
|
||||
NULL,
|
||||
NULL));
|
||||
|
||||
wifi_config_t wifi_config = {
|
||||
.ap = {
|
||||
@@ -120,7 +120,7 @@ void wifi_init_softap(void)
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d",
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -25,9 +25,3 @@ USB example uses Quactel BG96 modem device. BG96 needs a positive pulse on its P
|
||||
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`.
|
||||
|
||||
@@ -3,5 +3,4 @@ idf_component_register(SRCS "modem_console_main.cpp"
|
||||
"my_module_dce.cpp"
|
||||
"httpget_handle.c"
|
||||
"ping_handle.c"
|
||||
REQUIRES console esp_http_client nvs_flash
|
||||
INCLUDE_DIRS ".")
|
||||
|
||||
@@ -108,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.
|
||||
|
||||
@@ -179,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
|
||||
|
||||
@@ -63,13 +63,12 @@ void ConsoleCommand::RegisterCommand(const char *command, const char *help, cons
|
||||
|
||||
arg_type end = { .end = arg_end(1) };
|
||||
arg_table.emplace_back(end);
|
||||
const esp_console_cmd_t command_def = {
|
||||
.command = command,
|
||||
.help = help,
|
||||
.hint = nullptr,
|
||||
.func = command_func_pts[last_command],
|
||||
.argtable = &arg_table[0]
|
||||
};
|
||||
esp_console_cmd_t command_def = { };
|
||||
command_def.command = command;
|
||||
command_def.help = help;
|
||||
command_def.hint = nullptr;
|
||||
command_def.func = command_func_pts[last_command];
|
||||
command_def.argtable = &arg_table[0];
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&command_def));
|
||||
last_command++;
|
||||
console_commands.emplace_back(this);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "esp_modem_config.h"
|
||||
#include "cxx_include/esp_modem_api.hpp"
|
||||
#include "esp_idf_version.h"
|
||||
#if defined(CONFIG_EXAMPLE_SERIAL_CONFIG_USB)
|
||||
#include "esp_modem_usb_config.h"
|
||||
#include "cxx_include/esp_modem_usb_api.hpp"
|
||||
@@ -29,6 +30,12 @@
|
||||
#include "console_helper.hpp"
|
||||
#include "my_module_dce.hpp"
|
||||
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
|
||||
#define GET_WAKEUP_CAUSE() esp_sleep_get_wakeup_causes()
|
||||
#else
|
||||
#define GET_WAKEUP_CAUSE() esp_sleep_get_wakeup_cause()
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_EXAMPLE_FLOW_CONTROL_NONE)
|
||||
#define EXAMPLE_FLOW_CONTROL ESP_MODEM_FLOW_CONTROL_NONE
|
||||
#elif defined(CONFIG_EXAMPLE_FLOW_CONTROL_SW)
|
||||
@@ -208,7 +215,7 @@ extern "C" void app_main(void)
|
||||
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &s_repl));
|
||||
|
||||
switch (esp_sleep_get_wakeup_cause()) {
|
||||
switch (GET_WAKEUP_CAUSE()) {
|
||||
case ESP_SLEEP_WAKEUP_TIMER:
|
||||
if (esp_modem::modem_mode::CMUX_MODE == mode_rtc) {
|
||||
ESP_LOGI(TAG, "Deep sleep reset\n");
|
||||
@@ -385,6 +392,17 @@ extern "C" void app_main(void)
|
||||
return 0;
|
||||
});
|
||||
#endif
|
||||
const ConsoleCommand PauseNetwork("pause_net", "toggle network pause", no_args, [&](ConsoleCommand * c) {
|
||||
static int cnt = 0;
|
||||
if (++cnt % 2) {
|
||||
ESP_LOGI(TAG, "Pausing netif");
|
||||
dce->pause_netif(true);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Unpausing netif");
|
||||
dce->pause_netif(false);
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
const struct SetApn {
|
||||
SetApn(): apn(STR1, nullptr, nullptr, "<apn>", "APN (Access Point Name)") {}
|
||||
@@ -416,7 +434,7 @@ extern "C" void app_main(void)
|
||||
const ConsoleCommand SetDeepSleep("set_deep_sleep", "Put esp32 to deep sleep", &deep_sleep_args, sizeof(deep_sleep_args), [&](ConsoleCommand * c) {
|
||||
int tout = c->get_int_of(&DeepSleepArgs::timeout);
|
||||
ESP_LOGI(TAG, "Entering deep sleep for %d sec", tout);
|
||||
ESP_LOGI(TAG, "Wakeup Cause: %d ", esp_sleep_get_wakeup_cause());
|
||||
ESP_LOGI(TAG, "Wakeup Cause: %d ", GET_WAKEUP_CAUSE());
|
||||
esp_deep_sleep(tout * 1000000);
|
||||
return 0;
|
||||
});
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -18,9 +18,3 @@ For USB enabled targets (ESP32-S2, ESP32-S3, or ESP32-P4), it is possible to con
|
||||
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`.
|
||||
|
||||
@@ -100,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.
|
||||
|
||||
@@ -201,4 +201,23 @@ menu "Example Configuration"
|
||||
help
|
||||
MQTT data message, which we publish and expect to receive.
|
||||
|
||||
config EXAMPLE_PAUSE_NETIF_TO_CHECK_SIGNAL
|
||||
bool "Demonstrate netif pause"
|
||||
default n
|
||||
help
|
||||
Set this to true to demonstrate network pausing.
|
||||
If enabled, the example waits for an MQTT data, then temporarily
|
||||
drops network to check signal quality, resumes networking and
|
||||
publishes another MQTT message.
|
||||
Connection to the MQTT broker should be kept.
|
||||
|
||||
config EXAMPLE_DETECT_MODE_BEFORE_CONNECT
|
||||
bool "Detect mode before connect"
|
||||
default n
|
||||
help
|
||||
Set this to true to demonstrate mode auto-detection.
|
||||
If enabled, the example tries to recognize the actual mode.
|
||||
If mode is detected correctly and it is not a command mode,
|
||||
then the example switches to command mode.
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -34,6 +34,7 @@
|
||||
static const char *TAG = "pppos_example";
|
||||
static EventGroupHandle_t event_group = NULL;
|
||||
static const int CONNECT_BIT = BIT0;
|
||||
static const int DISCONNECT_BIT = BIT1;
|
||||
static const int GOT_DATA_BIT = BIT2;
|
||||
static const int USB_DISCONNECTED_BIT = BIT3; // Used only with USB DTE but we define it unconditionally, to avoid too many #ifdefs in the code
|
||||
|
||||
@@ -55,6 +56,7 @@ static void usb_terminal_error_handler(esp_modem_terminal_error_t err)
|
||||
}
|
||||
#define CHECK_USB_DISCONNECTION(event_group) \
|
||||
if ((xEventGroupGetBits(event_group) & USB_DISCONNECTED_BIT) == USB_DISCONNECTED_BIT) { \
|
||||
ESP_LOGE(TAG, "USB_DISCONNECTED_BIT destroying modem dce"); \
|
||||
esp_modem_destroy(dce); \
|
||||
continue; \
|
||||
}
|
||||
@@ -140,6 +142,7 @@ static void on_ip_event(void *arg, esp_event_base_t event_base,
|
||||
ESP_LOGI(TAG, "GOT ip event!!!");
|
||||
} else if (event_id == IP_EVENT_PPP_LOST_IP) {
|
||||
ESP_LOGI(TAG, "Modem Disconnect from PPP Server");
|
||||
xEventGroupSetBits(event_group, DISCONNECT_BIT);
|
||||
} else if (event_id == IP_EVENT_GOT_IP6) {
|
||||
ESP_LOGI(TAG, "GOT IPv6 event!");
|
||||
|
||||
@@ -158,6 +161,7 @@ void app_main(void)
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed, NULL));
|
||||
|
||||
/* Configure the PPP netif */
|
||||
esp_err_t err;
|
||||
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(CONFIG_EXAMPLE_MODEM_PPP_APN);
|
||||
esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP();
|
||||
esp_netif_t *esp_netif = esp_netif_new(&netif_ppp_config);
|
||||
@@ -205,7 +209,7 @@ void app_main(void)
|
||||
#endif
|
||||
assert(dce);
|
||||
if (dte_config.uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
|
||||
esp_err_t err = esp_modem_set_flow_control(dce, 2, 2); //2/2 means HW Flow Control.
|
||||
err = esp_modem_set_flow_control(dce, 2, 2); //2/2 means HW Flow Control.
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to set the set_flow_control mode");
|
||||
return;
|
||||
@@ -246,7 +250,27 @@ void app_main(void)
|
||||
#error Invalid serial connection to modem.
|
||||
#endif
|
||||
|
||||
xEventGroupClearBits(event_group, CONNECT_BIT | GOT_DATA_BIT | USB_DISCONNECTED_BIT);
|
||||
#if CONFIG_EXAMPLE_DETECT_MODE_BEFORE_CONNECT
|
||||
xEventGroupClearBits(event_group, CONNECT_BIT | GOT_DATA_BIT | USB_DISCONNECTED_BIT | DISCONNECT_BIT);
|
||||
|
||||
err = esp_modem_set_mode(dce, ESP_MODEM_MODE_DETECT);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_modem_set_mode(ESP_MODEM_MODE_DETECT) failed with %d", err);
|
||||
return;
|
||||
}
|
||||
esp_modem_dce_mode_t mode = esp_modem_get_mode(dce);
|
||||
ESP_LOGI(TAG, "Mode detection completed: current mode is: %d", mode);
|
||||
if (mode == ESP_MODEM_MODE_DATA) { // set back to command mode
|
||||
err = esp_modem_set_mode(dce, ESP_MODEM_MODE_COMMAND);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_modem_set_mode(ESP_MODEM_MODE_COMMAND) failed with %d", err);
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(TAG, "Command mode restored");
|
||||
}
|
||||
#endif // CONFIG_EXAMPLE_DETECT_MODE_BEFORE_CONNECT
|
||||
|
||||
xEventGroupClearBits(event_group, CONNECT_BIT | GOT_DATA_BIT | USB_DISCONNECTED_BIT | DISCONNECT_BIT);
|
||||
|
||||
/* Run the modem demo app */
|
||||
#if CONFIG_EXAMPLE_NEED_SIM_PIN == 1
|
||||
@@ -262,7 +286,7 @@ void app_main(void)
|
||||
#endif
|
||||
|
||||
int rssi, ber;
|
||||
esp_err_t err = esp_modem_get_signal_quality(dce, &rssi, &ber);
|
||||
err = esp_modem_get_signal_quality(dce, &rssi, &ber);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_modem_get_signal_quality failed with %d %s", err, esp_err_to_name(err));
|
||||
return;
|
||||
@@ -301,22 +325,41 @@ void app_main(void)
|
||||
}
|
||||
/* Wait for IP address */
|
||||
ESP_LOGI(TAG, "Waiting for IP address");
|
||||
xEventGroupWaitBits(event_group, CONNECT_BIT | USB_DISCONNECTED_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
|
||||
xEventGroupWaitBits(event_group, CONNECT_BIT | USB_DISCONNECTED_BIT | DISCONNECT_BIT, pdFALSE, pdFALSE,
|
||||
pdMS_TO_TICKS(60000));
|
||||
CHECK_USB_DISCONNECTION(event_group);
|
||||
if ((xEventGroupGetBits(event_group) & CONNECT_BIT) != CONNECT_BIT) {
|
||||
ESP_LOGW(TAG, "Modem not connected, switching back to the command mode");
|
||||
err = esp_modem_set_mode(dce, ESP_MODEM_MODE_COMMAND);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_modem_set_mode(ESP_MODEM_MODE_COMMAND) failed with %d", err);
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(TAG, "Command mode restored");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Config MQTT */
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
esp_mqtt_client_config_t mqtt_config = {
|
||||
.broker.address.uri = CONFIG_EXAMPLE_MQTT_BROKER_URI,
|
||||
};
|
||||
#else
|
||||
esp_mqtt_client_config_t mqtt_config = {
|
||||
.uri = CONFIG_EXAMPLE_MQTT_BROKER_URI,
|
||||
};
|
||||
#endif
|
||||
esp_mqtt_client_handle_t mqtt_client = esp_mqtt_client_init(&mqtt_config);
|
||||
esp_mqtt_client_register_event(mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
|
||||
esp_mqtt_client_start(mqtt_client);
|
||||
|
||||
#if CONFIG_EXAMPLE_PAUSE_NETIF_TO_CHECK_SIGNAL
|
||||
xEventGroupWaitBits(event_group, GOT_DATA_BIT, pdTRUE, pdFALSE, portMAX_DELAY);
|
||||
esp_modem_pause_net(dce, true);
|
||||
err = esp_modem_get_signal_quality(dce, &rssi, &ber);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_modem_get_signal_quality failed with %d", err);
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(TAG, "Signal quality: rssi=%d, ber=%d", rssi, ber);
|
||||
esp_modem_pause_net(dce, false);
|
||||
esp_mqtt_client_publish(mqtt_client, CONFIG_EXAMPLE_MQTT_TEST_TOPIC, CONFIG_EXAMPLE_MQTT_TEST_DATA, 0, 0, 0);
|
||||
#endif // CONFIG_EXAMPLE_PAUSE_NETIF_TO_CHECK_SIGNAL
|
||||
|
||||
ESP_LOGI(TAG, "Waiting for MQTT data");
|
||||
xEventGroupWaitBits(event_group, GOT_DATA_BIT | USB_DISCONNECTED_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
|
||||
CHECK_USB_DISCONNECTION(event_group);
|
||||
|
||||
@@ -12,7 +12,7 @@ def test_pppos_connect(dut):
|
||||
4. checks that the client cleanly disconnects
|
||||
"""
|
||||
# Check the sequence of connecting, publishing, disconnecting
|
||||
dut.expect('Modem Connect to PPP Server')
|
||||
dut.expect('Modem Connect to PPP Server', timeout=90)
|
||||
# Check for MQTT connection and the data event
|
||||
dut.expect('MQTT_EVENT_CONNECTED')
|
||||
dut.expect('MQTT_EVENT_DATA')
|
||||
|
||||
@@ -11,5 +11,7 @@ CONFIG_EXAMPLE_MODEM_DEVICE_SIM800=y
|
||||
CONFIG_EXAMPLE_MODEM_DEVICE_BG96=n
|
||||
CONFIG_EXAMPLE_MODEM_PPP_APN="lpwa.vodafone.com"
|
||||
CONFIG_EXAMPLE_MQTT_TEST_TOPIC="/ci/esp-modem/pppos-client"
|
||||
CONFIG_EXAMPLE_PAUSE_NETIF_TO_CHECK_SIGNAL=y
|
||||
CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y
|
||||
CONFIG_ESP32_PANIC_PRINT_HALT=y
|
||||
CONFIG_EXAMPLE_DETECT_MODE_BEFORE_CONNECT=y
|
||||
|
||||
@@ -8,7 +8,6 @@ CONFIG_LWIP_PPP_ENABLE_IPV6=n
|
||||
CONFIG_EXAMPLE_SERIAL_CONFIG_USB=y
|
||||
CONFIG_EXAMPLE_MODEM_DEVICE_A7670=y
|
||||
CONFIG_EXAMPLE_MODEM_PPP_APN="lpwa.vodafone.com"
|
||||
CONFIG_EXAMPLE_MODEM_PPP_AUTH_NONE=y
|
||||
CONFIG_EXAMPLE_MQTT_TEST_TOPIC="/ci/esp-modem/pppos-client"
|
||||
CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y
|
||||
CONFIG_ESP32_PANIC_PRINT_HALT=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
|
||||
|
||||
@@ -16,3 +16,4 @@ 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"
|
||||
CONFIG_BROKER_URI="mqtt://mqtt.eclipseprojects.io"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
version: "1.2.0"
|
||||
version: "1.4.2"
|
||||
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
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include "esp_log.h"
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "cxx_include/esp_modem_dce_module.hpp"
|
||||
|
||||
namespace esp_modem::dce_commands {
|
||||
command_result generic_command(CommandableIf *t, const std::string &command,
|
||||
const std::list<std::string_view> &pass_phrase,
|
||||
const std::list<std::string_view> &fail_phrase,
|
||||
uint32_t timeout_ms);
|
||||
}
|
||||
@@ -84,7 +84,6 @@ std::unique_ptr<DCE> create_SIM7070_dce(const dce_config *config, std::shared_pt
|
||||
*/
|
||||
std::unique_ptr<DCE> create_SIM7000_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create DCE based on SIM800 module
|
||||
*/
|
||||
@@ -95,6 +94,11 @@ std::unique_ptr<DCE> create_SIM800_dce(const dce_config *config, std::shared_ptr
|
||||
*/
|
||||
std::unique_ptr<DCE> create_BG96_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif);
|
||||
|
||||
/**
|
||||
* @brief Create DCE based on Sequans GM02S module
|
||||
*/
|
||||
std::unique_ptr<DCE> create_SQNGM02S_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif);
|
||||
|
||||
/**
|
||||
* @brief Create generic DCE
|
||||
*/
|
||||
|
||||
@@ -91,6 +91,11 @@ public:
|
||||
return mode.set(dte.get(), device.get(), netif, m);
|
||||
}
|
||||
|
||||
modem_mode get_mode()
|
||||
{
|
||||
return mode.get();
|
||||
}
|
||||
|
||||
bool recover()
|
||||
{
|
||||
return dte->recover();
|
||||
@@ -103,6 +108,29 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Pauses/Unpauses network temporarily
|
||||
* @param do_pause true to pause, false to unpause
|
||||
* @param force true to ignore command failures and continue
|
||||
* @return command_result of the underlying commands
|
||||
*/
|
||||
command_result pause_netif(bool do_pause, bool force = false, int delay = 1000)
|
||||
{
|
||||
command_result result;
|
||||
if (do_pause) {
|
||||
netif.pause();
|
||||
Task::Delay(delay); // Mandatory 1s pause before
|
||||
dte->set_command_callbacks();
|
||||
result = device->set_command_mode();
|
||||
} else {
|
||||
result = device->resume_data_mode();
|
||||
if (result == command_result::OK || force) {
|
||||
netif.resume();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::shared_ptr<DTE> dte;
|
||||
std::shared_ptr<SpecificModule> device;
|
||||
|
||||
@@ -118,6 +118,7 @@ enum class ModemType {
|
||||
SIM7000, /*!< Derived from the GenericModule, specifics applied to SIM7000 model */
|
||||
BG96, /*!< Derived from the GenericModule, specifics applied to BG69 model */
|
||||
SIM800, /*!< Derived from the GenericModule with specifics applied to SIM800 model */
|
||||
SQNGM02S, /*!< Derived from the GenericModule, specifics applied to GM02S model */
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -178,6 +179,8 @@ public:
|
||||
return build_shared_module<SIM7000>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::BG96:
|
||||
return build_shared_module<BG96>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::SQNGM02S:
|
||||
return build_shared_module<SQNGM02S>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::GenericModule:
|
||||
return build_shared_module<GenericModule>(cfg, std::forward<Args>(args)...);
|
||||
default:
|
||||
@@ -207,6 +210,8 @@ public:
|
||||
return build_unique<SIM7000>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::BG96:
|
||||
return build_unique<BG96>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::SQNGM02S:
|
||||
return build_unique<SQNGM02S>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::GenericModule:
|
||||
return build_unique<GenericModule>(cfg, std::forward<Args>(args)...);
|
||||
default:
|
||||
@@ -229,6 +234,8 @@ public:
|
||||
return build<SIM7000>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::BG96:
|
||||
return build<BG96>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::SQNGM02S:
|
||||
return build<SQNGM02S>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::GenericModule:
|
||||
return build<GenericModule>(cfg, std::forward<Args>(args)...);
|
||||
default:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -77,7 +77,9 @@ public:
|
||||
if (set_command_mode() == command_result::OK) {
|
||||
return true;
|
||||
}
|
||||
Task::Delay(1000); // Mandatory 1s pause after escape
|
||||
// send a newline to delimit the escape from the upcoming sync command
|
||||
uint8_t delim = '\n';
|
||||
dte->write(&delim, 1);
|
||||
if (sync() == command_result::OK) {
|
||||
return true;
|
||||
}
|
||||
@@ -113,7 +115,7 @@ public:
|
||||
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, num, ...) \
|
||||
virtual return_type name(__VA_ARGS__);
|
||||
|
||||
DECLARE_ALL_COMMAND_APIS(virtual return_type name(...); )
|
||||
DECLARE_ALL_COMMAND_APIS(virtual return_type name(...);)
|
||||
|
||||
#undef ESP_MODEM_DECLARE_DCE_COMMAND
|
||||
|
||||
@@ -175,6 +177,14 @@ public:
|
||||
command_result set_pdp_context(PdpContext &pdp) override;
|
||||
};
|
||||
|
||||
class SQNGM02S : public GenericModule {
|
||||
using GenericModule::GenericModule;
|
||||
|
||||
public:
|
||||
command_result connect(PdpContext &pdp);
|
||||
bool setup_data_mode() override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -145,6 +145,12 @@ public:
|
||||
*/
|
||||
bool recover();
|
||||
|
||||
/**
|
||||
* @brief Set internal command callbacks to the underlying terminal.
|
||||
* Here we capture command replies to be processed by supplied command callbacks in struct command_cb.
|
||||
*/
|
||||
void set_command_callbacks();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Allows for locking the DTE
|
||||
@@ -204,12 +210,6 @@ private:
|
||||
} inflatable;
|
||||
#endif // CONFIG_ESP_MODEM_USE_INFLATABLE_BUFFER_IF_NEEDED
|
||||
|
||||
/**
|
||||
* @brief Set internal command callbacks to the underlying terminal.
|
||||
* Here we capture command replies to be processed by supplied command callbacks in struct command_cb.
|
||||
*/
|
||||
void set_command_callbacks();
|
||||
|
||||
/**
|
||||
* @brief This abstracts command callback processing and implements its locking, signaling of completion and timeouts.
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -54,6 +54,16 @@ public:
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* @brief Pause the network interface
|
||||
*/
|
||||
void pause();
|
||||
|
||||
/**
|
||||
* @brief Resume the network interface
|
||||
*/
|
||||
void resume();
|
||||
|
||||
void receive(uint8_t *data, size_t len);
|
||||
|
||||
private:
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Compatibility macro to be removed in v2.0
|
||||
*/
|
||||
#define ESP_MODEM_DCE_GENETIC ESP_MODEM_DCE_GENERIC
|
||||
|
||||
typedef struct esp_modem_dce_wrap esp_modem_dce_t;
|
||||
|
||||
typedef struct esp_modem_PdpContext_t {
|
||||
@@ -41,19 +45,22 @@ typedef enum esp_modem_dce_mode {
|
||||
ESP_MODEM_MODE_CMUX_MANUAL_SWAP, /**< Swap terminals in CMUX manual mode */
|
||||
ESP_MODEM_MODE_CMUX_MANUAL_DATA, /**< Set DATA mode in CMUX manual mode */
|
||||
ESP_MODEM_MODE_CMUX_MANUAL_COMMAND, /**< Set COMMAND mode in CMUX manual mode */
|
||||
ESP_MODEM_MODE_DETECT, /**< Detect the mode and resume it (if sucessfully detected) */
|
||||
ESP_MODEM_MODE_UNDEF,
|
||||
} esp_modem_dce_mode_t;
|
||||
|
||||
/**
|
||||
* @brief DCE devices: Enum list of supported devices
|
||||
*/
|
||||
typedef enum esp_modem_dce_device {
|
||||
ESP_MODEM_DCE_GENETIC, /**< The most generic device */
|
||||
ESP_MODEM_DCE_GENERIC, /**< The most generic device */
|
||||
ESP_MODEM_DCE_SIM7600,
|
||||
ESP_MODEM_DCE_SIM7070,
|
||||
ESP_MODEM_DCE_SIM7000,
|
||||
ESP_MODEM_DCE_BG96,
|
||||
ESP_MODEM_DCE_EC20,
|
||||
ESP_MODEM_DCE_SIM800,
|
||||
ESP_MODEM_DCE_SQNGM02S,
|
||||
ESP_MODEM_DCE_CUSTOM
|
||||
} esp_modem_dce_device_t;
|
||||
|
||||
@@ -141,6 +148,35 @@ esp_err_t esp_modem_command(esp_modem_dce_t *dce, const char *command, esp_err_t
|
||||
*/
|
||||
esp_err_t esp_modem_set_apn(esp_modem_dce_t *dce, const char *apn);
|
||||
|
||||
#ifdef CONFIG_ESP_MODEM_URC_HANDLER
|
||||
/**
|
||||
* @brief Sets a handler for unsolicited result codes (URCs) from the modem
|
||||
*
|
||||
* This function registers a callback that is triggered whenever an unsolicited
|
||||
* result code (URC) is received from the modem. URCs are typically sent by the
|
||||
* modem without a prior command to notify the host about certain events or status changes.
|
||||
*
|
||||
* @param dce Modem DCE handle
|
||||
* @param got_line_cb Callback function which is called whenever a URC line is received
|
||||
* @return ESP_OK on success, ESP_FAIL on failure
|
||||
*/
|
||||
esp_err_t esp_modem_set_urc(esp_modem_dce_t *dce, esp_err_t(*got_line_cb)(uint8_t *data, size_t len));
|
||||
#endif
|
||||
|
||||
esp_err_t esp_modem_sqn_gm02s_connect(esp_modem_dce_t *dce, const esp_modem_PdpContext_t *pdp_context);
|
||||
|
||||
/**
|
||||
* @brief This API provides support for temporarily pausing networking in order
|
||||
* to send/receive AT commands and resume networking afterwards.
|
||||
* @note This function does not switch modes, the modem is still in data mode.
|
||||
*
|
||||
* @param dce Modem DCE handle
|
||||
* @param pause true to pause the network interface, false to resume networking
|
||||
* @return ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_modem_pause_net(esp_modem_dce_t *dce, bool pause);
|
||||
|
||||
esp_modem_dce_mode_t esp_modem_get_mode(esp_modem_dce_t *dce);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -43,8 +43,10 @@ inline dce_factory::ModemType convert_modem_enum(esp_modem_dce_device_t module)
|
||||
return esp_modem::dce_factory::ModemType::BG96;
|
||||
case ESP_MODEM_DCE_SIM800:
|
||||
return esp_modem::dce_factory::ModemType::SIM800;
|
||||
case ESP_MODEM_DCE_SQNGM02S:
|
||||
return esp_modem::dce_factory::ModemType::SQNGM02S;
|
||||
default:
|
||||
case ESP_MODEM_DCE_GENETIC:
|
||||
case ESP_MODEM_DCE_GENERIC:
|
||||
return esp_modem::dce_factory::ModemType::GenericModule;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,7 +290,69 @@ ESP_MODEM_DECLARE_DCE_COMMAND(set_gnss_power_mode, command_result, 1, INT_IN(p1,
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_gnss_power_mode, command_result, 1, INT_OUT(p1, mode)) \
|
||||
\
|
||||
|
||||
/**
|
||||
* @brief Configure PSM
|
||||
* @param[in] mode psm mode (0 - off, 1 - on, 2 - off & discard stored params)
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(config_psm, command_result, 3, INT_IN(p1, mode), STRING_IN(p2, tau), STRING_IN(p3, active_time)) \
|
||||
\
|
||||
/**
|
||||
* @brief Configure CEREG urc
|
||||
* @param[in] value
|
||||
* value = 0 - Disable network URC
|
||||
* value = 1 - Enable network URC
|
||||
* value = 2 - Enable network URC with location information
|
||||
* value = 3 - Enable network URC with location information and EMM cause
|
||||
* value = 4 - Enable network URC with location information and PSM value
|
||||
* value = 5 - Enable network URC with location information and PSM value, EMM cause
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(config_network_registration_urc, command_result, 1, INT_IN(p1, value)) \
|
||||
\
|
||||
/**
|
||||
* @brief Gets the current network registration state
|
||||
* @param[out] state The current network registration state
|
||||
* state = 0 - Not registered, MT is not currently searching an operator to register to
|
||||
* state = 1 - Registered, home network
|
||||
* state = 2 - Not registered, but MT is currently trying to attach or searching an operator to register to
|
||||
* state = 3 - Registration denied
|
||||
* state = 4 - Unknown
|
||||
* state = 5 - Registered, Roaming
|
||||
* state = 6 - Registered, for SMS only, home network (NB-IoT only)
|
||||
* state = 7 - Registered, for SMS only, roaming (NB-IoT only)
|
||||
* state = 8 - Attached for emergency bearer services only
|
||||
* state = 9 - Registered for CSFB not preferred, home network
|
||||
* state = 10 - Registered for CSFB not preferred, roaming
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_network_registration_state, command_result, 1, INT_OUT(p1,state)) \
|
||||
\
|
||||
/**
|
||||
* @brief Configures the mobile termination error (+CME ERROR)
|
||||
* @param[in] mode The form of the final result code
|
||||
* mode = 0 - Disable, use and send ERROR instead
|
||||
* mode = 1 - Enable, use numeric error values
|
||||
* mode = 2 - Enable, result code and use verbose error values
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(config_mobile_termination_error, command_result, 1, INT_IN(p1, mode)) \
|
||||
\
|
||||
/**
|
||||
* @brief Configure eDRX
|
||||
* @param[in] mode
|
||||
* mode = 0 - Disable
|
||||
* mode = 1 - Enable
|
||||
* mode = 2 - Enable + URC
|
||||
* mode = 3 - Disable + Reset parameter.
|
||||
* @param[in] access_technology
|
||||
* act = 0 - ACT is not using eDRX (used in URC)
|
||||
* act = 1 - EC-GSM-IoT (A/Gb mode)
|
||||
* act = 2 - GSM (A/Gb mode)
|
||||
* act = 3 - UTRAN (Iu mode)
|
||||
* act = 4 - E-UTRAN (WB-S1 mode)
|
||||
* act = 5 - E-UTRAN (NB-S1 mode)
|
||||
* @param[in] edrx_value nible string containing encoded eDRX time
|
||||
* @param[in] ptw_value nible string containing encoded Paging Time Window
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(config_edrx, command_result, 3, INT_IN(p1, mode), INT_IN(p2, access_technology), STRING_IN(p3, edrx_value)) \
|
||||
|
||||
#ifdef GENERATE_DOCS
|
||||
// cat ../include/generate/esp_modem_command_declare.inc | clang++ -E -P -CC -xc++ -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p'
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
|
||||
#define MPPE_SUPPORT 0
|
||||
|
||||
#define PPP_MAXIDLEFLAG 0
|
||||
#define PPP_MAXIDLEFLAG 100
|
||||
|
||||
#define PRINTPKT_SUPPORT 1
|
||||
#define PPP_PROTOCOLNAME 1
|
||||
|
||||
@@ -104,7 +104,7 @@ static void ppp_link_status_cb(ppp_pcb *pcb, int err_code, void *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
static u32_t ppp_output_cb(struct ppp_pcb_s *pcb, const void *data, u32_t len, void *ctx)
|
||||
static u32_t ppp_output_cb(struct ppp_pcb_s *pcb, u8_t *data, u32_t len, void *ctx)
|
||||
{
|
||||
esp_netif_t *netif = (esp_netif_t *)ctx;
|
||||
if (netif->transmit) {
|
||||
|
||||
@@ -66,6 +66,11 @@ std::unique_ptr<DCE> create_BG96_dce(const dce_config *config, std::shared_ptr<D
|
||||
return create_modem_dce(dce_factory::ModemType::BG96, config, std::move(dte), netif);
|
||||
}
|
||||
|
||||
std::unique_ptr<DCE> create_SQNGM02S_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif)
|
||||
{
|
||||
return create_modem_dce(dce_factory::ModemType::SQNGM02S, config, std::move(dte), netif);
|
||||
}
|
||||
|
||||
std::unique_ptr<DCE> create_generic_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif)
|
||||
{
|
||||
return create_modem_dce(dce_factory::ModemType::GenericModule, config, std::move(dte), netif);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -60,7 +60,7 @@ extern "C" esp_modem_dce_t *esp_modem_new_dev(esp_modem_dce_device_t module, con
|
||||
|
||||
extern "C" esp_modem_dce_t *esp_modem_new(const esp_modem_dte_config_t *dte_config, const esp_modem_dce_config_t *dce_config, esp_netif_t *netif)
|
||||
{
|
||||
return esp_modem_new_dev(ESP_MODEM_DCE_GENETIC, dte_config, dce_config, netif);
|
||||
return esp_modem_new_dev(ESP_MODEM_DCE_GENERIC, dte_config, dce_config, netif);
|
||||
}
|
||||
|
||||
extern "C" void esp_modem_destroy(esp_modem_dce_t *dce_wrap)
|
||||
@@ -95,12 +95,43 @@ extern "C" esp_err_t esp_modem_sync(esp_modem_dce_t *dce_wrap)
|
||||
return command_response_to_esp_err(dce_wrap->dce->sync());
|
||||
}
|
||||
|
||||
extern "C" esp_modem_dce_mode_t esp_modem_get_mode(esp_modem_dce_t *dce_wrap)
|
||||
{
|
||||
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
|
||||
return ESP_MODEM_MODE_UNDEF;
|
||||
}
|
||||
auto mode = dce_wrap->dce->get_mode();
|
||||
switch (mode) {
|
||||
default:
|
||||
case modem_mode::UNDEF:
|
||||
return ESP_MODEM_MODE_UNDEF;
|
||||
case modem_mode::COMMAND_MODE:
|
||||
return ESP_MODEM_MODE_COMMAND;
|
||||
case modem_mode::DATA_MODE:
|
||||
return ESP_MODEM_MODE_DATA;
|
||||
case modem_mode::CMUX_MODE:
|
||||
return ESP_MODEM_MODE_CMUX;
|
||||
case modem_mode::CMUX_MANUAL_MODE:
|
||||
return ESP_MODEM_MODE_CMUX_MANUAL;
|
||||
case modem_mode::CMUX_MANUAL_EXIT:
|
||||
return ESP_MODEM_MODE_CMUX_MANUAL_EXIT;
|
||||
case modem_mode::CMUX_MANUAL_DATA:
|
||||
return ESP_MODEM_MODE_CMUX_MANUAL_DATA;
|
||||
case modem_mode::CMUX_MANUAL_COMMAND:
|
||||
return ESP_MODEM_MODE_CMUX_MANUAL_COMMAND;
|
||||
case modem_mode::CMUX_MANUAL_SWAP:
|
||||
return ESP_MODEM_MODE_CMUX_MANUAL_SWAP;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" esp_err_t esp_modem_set_mode(esp_modem_dce_t *dce_wrap, esp_modem_dce_mode_t mode)
|
||||
{
|
||||
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
switch (mode) {
|
||||
case ESP_MODEM_MODE_UNDEF:
|
||||
return dce_wrap->dce->set_mode(modem_mode::UNDEF) ? ESP_OK : ESP_FAIL;
|
||||
case ESP_MODEM_MODE_DATA:
|
||||
return dce_wrap->dce->set_mode(modem_mode::DATA_MODE) ? ESP_OK : ESP_FAIL;
|
||||
case ESP_MODEM_MODE_COMMAND:
|
||||
@@ -117,6 +148,8 @@ extern "C" esp_err_t esp_modem_set_mode(esp_modem_dce_t *dce_wrap, esp_modem_dce
|
||||
return dce_wrap->dce->set_mode(modem_mode::CMUX_MANUAL_DATA) ? ESP_OK : ESP_FAIL;
|
||||
case ESP_MODEM_MODE_CMUX_MANUAL_COMMAND:
|
||||
return dce_wrap->dce->set_mode(modem_mode::CMUX_MANUAL_COMMAND) ? ESP_OK : ESP_FAIL;
|
||||
case ESP_MODEM_MODE_DETECT:
|
||||
return dce_wrap->dce->set_mode(modem_mode::AUTODETECT) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
@@ -406,6 +439,77 @@ extern "C" esp_err_t esp_modem_get_gnss_power_mode(esp_modem_dce_t *dce_wrap, in
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern "C" esp_err_t esp_modem_config_psm(esp_modem_dce_t *dce_wrap, int mode, const char *tau, const char *active_time)
|
||||
{
|
||||
if (dce_wrap == nullptr || dce_wrap->dce == nullptr || mode > 3) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (mode == 1 && (strlen(tau) != 8 || strlen(active_time) != 8)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return command_response_to_esp_err(dce_wrap->dce->config_psm(mode, std::string(tau), std::string(active_time)));
|
||||
}
|
||||
|
||||
extern "C" esp_err_t esp_modem_config_network_registration_urc(esp_modem_dce_t *dce_wrap, int value)
|
||||
{
|
||||
if (dce_wrap == nullptr || dce_wrap->dce == nullptr || value > 5) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return command_response_to_esp_err(dce_wrap->dce->config_network_registration_urc(value));
|
||||
}
|
||||
|
||||
extern "C" esp_err_t esp_modem_get_network_registration_state(esp_modem_dce_t *dce_wrap, int *p_state)
|
||||
{
|
||||
if (dce_wrap == nullptr || dce_wrap->dce == nullptr || p_state == nullptr) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
int state;
|
||||
auto ret = command_response_to_esp_err(dce_wrap->dce->get_network_registration_state(state));
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
*p_state = state;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern "C" esp_err_t esp_modem_config_mobile_termination_error(esp_modem_dce_t *dce_wrap, int mode)
|
||||
{
|
||||
if (dce_wrap == nullptr || dce_wrap->dce == nullptr || mode > 2) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return command_response_to_esp_err(dce_wrap->dce->config_mobile_termination_error(mode));
|
||||
}
|
||||
|
||||
extern "C" esp_err_t esp_modem_config_edrx(esp_modem_dce_t *dce_wrap, int mode, int access_technology, const char *edrx_value)
|
||||
{
|
||||
if (dce_wrap == nullptr || dce_wrap->dce == nullptr || mode > 3 || access_technology > 5) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if ((mode == 1 || mode == 2) && strlen(edrx_value) != 4) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return command_response_to_esp_err(dce_wrap->dce->config_edrx(mode, access_technology, std::string(edrx_value)));
|
||||
}
|
||||
|
||||
extern "C" esp_err_t esp_modem_sqn_gm02s_connect(esp_modem_dce_t *dce_wrap, const esp_modem_PdpContext_t *pdp_context)
|
||||
{
|
||||
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_modem::PdpContext pdp{pdp_context->apn};
|
||||
pdp.context_id = pdp_context->context_id;
|
||||
pdp.protocol_type = pdp_context->protocol_type;
|
||||
return command_response_to_esp_err(static_cast<SQNGM02S *>(dce_wrap->dce->get_module())->connect(pdp));
|
||||
}
|
||||
|
||||
extern "C" esp_err_t esp_modem_reset(esp_modem_dce_t *dce_wrap)
|
||||
{
|
||||
return command_response_to_esp_err(dce_wrap->dce->reset());
|
||||
@@ -451,3 +555,43 @@ extern "C" esp_err_t esp_modem_set_apn(esp_modem_dce_t *dce_wrap, const char *ap
|
||||
dce_wrap->dce->get_module()->configure_pdp_context(std::move(new_pdp));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP_MODEM_URC_HANDLER
|
||||
extern "C" esp_err_t esp_modem_set_urc(esp_modem_dce_t *dce_wrap, esp_err_t(*got_line_fn)(uint8_t *data, size_t len))
|
||||
{
|
||||
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (got_line_fn == nullptr) {
|
||||
dce_wrap->dce->set_urc(nullptr);
|
||||
return ESP_OK;
|
||||
}
|
||||
dce_wrap->dce->set_urc([got_line_fn](uint8_t *data, size_t len) {
|
||||
switch (got_line_fn(data, len)) {
|
||||
case ESP_OK:
|
||||
return command_result::OK;
|
||||
case ESP_FAIL:
|
||||
return command_result::FAIL;
|
||||
default:
|
||||
return command_result::TIMEOUT;
|
||||
}
|
||||
});
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern "C" esp_err_t esp_modem_pause_net(esp_modem_dce_t *dce_wrap, bool pause)
|
||||
{
|
||||
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return command_response_to_esp_err(dce_wrap->dce->pause_netif(pause));
|
||||
}
|
||||
|
||||
extern "C" esp_err_t esp_modem_hang_up(esp_modem_dce_t *dce_wrap)
|
||||
{
|
||||
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return command_response_to_esp_err(dce_wrap->dce->hang_up());
|
||||
}
|
||||
|
||||
@@ -123,7 +123,12 @@ bool CMux::data_available(uint8_t *data, size_t len)
|
||||
{
|
||||
if (data && (type & FT_UIH) == FT_UIH && len > 0 && dlci > 0) { // valid payload on a virtual term
|
||||
int virtual_term = dlci - 1;
|
||||
if (virtual_term < MAX_TERMINALS_NUM && read_cb[virtual_term]) {
|
||||
if (virtual_term < MAX_TERMINALS_NUM) {
|
||||
if (read_cb[virtual_term] == nullptr) {
|
||||
// ignore all virtual terminal's data before we completely establish CMUX
|
||||
ESP_LOG_BUFFER_HEXDUMP("CMUX Rx before init", data, len, ESP_LOG_DEBUG);
|
||||
return true;
|
||||
}
|
||||
// Post partial data (or defragment to post on CMUX footer)
|
||||
#ifdef DEFRAGMENT_CMUX_PAYLOAD
|
||||
if (payload_start == nullptr) {
|
||||
@@ -142,7 +147,11 @@ bool CMux::data_available(uint8_t *data, size_t len)
|
||||
sabm_ack = dlci;
|
||||
} else if (data == nullptr && dlci > 0) {
|
||||
int virtual_term = dlci - 1;
|
||||
if (virtual_term < MAX_TERMINALS_NUM && read_cb[virtual_term]) {
|
||||
if (virtual_term < MAX_TERMINALS_NUM) {
|
||||
if (read_cb[virtual_term] == nullptr) {
|
||||
// silently ignore this CMUX frame (not finished entering CMUX, yet)
|
||||
return true;
|
||||
}
|
||||
#ifdef DEFRAGMENT_CMUX_PAYLOAD
|
||||
read_cb[virtual_term](payload_start, total_payload_size);
|
||||
#endif
|
||||
@@ -239,7 +248,7 @@ bool CMux::on_header(CMuxFrame &frame)
|
||||
// Sanity check for expected values of DLCI and type,
|
||||
// since CRC could be evaluated after the frame payload gets received
|
||||
if (dlci > MAX_TERMINALS_NUM || (frame_header[1] & 0x01) == 0 ||
|
||||
(((type & FT_UIH) != FT_UIH) && type != (FT_UA | PF) ) ) {
|
||||
(((type & FT_UIH) != FT_UIH) && type != (FT_UA | PF))) {
|
||||
recover_protocol(protocol_mismatch_reason::UNEXPECTED_HEADER);
|
||||
return true;
|
||||
}
|
||||
@@ -318,7 +327,7 @@ bool CMux::on_cmux_data(uint8_t *data, size_t actual_len)
|
||||
auto data_end = buffer.get() + buffer.size;
|
||||
data_to_read = payload_len + 2; // 2 -- CMUX protocol footer
|
||||
if (data + data_to_read >= data_end) {
|
||||
ESP_LOGW("CUMX", "Failed to defragment longer payload (payload=%" PRIsize_t ")", payload_len);
|
||||
ESP_LOGW("CMUX", "Failed to defragment longer payload (payload=%" PRIsize_t ")", payload_len);
|
||||
// If you experience this error, your device uses longer payloads while
|
||||
// the configured buffer is too small to defragment the payload properly.
|
||||
// To resolve this issue you can:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -12,14 +12,16 @@
|
||||
#include "cxx_include/esp_modem_command_library.hpp"
|
||||
#include "cxx_include/esp_modem_command_library_utils.hpp"
|
||||
|
||||
#include "cxx17_include/esp_modem_command_library_17.hpp"
|
||||
|
||||
namespace esp_modem::dce_commands {
|
||||
|
||||
static const char *TAG = "command_lib";
|
||||
|
||||
static command_result generic_command(CommandableIf *t, const std::string &command,
|
||||
const std::list<std::string_view> &pass_phrase,
|
||||
const std::list<std::string_view> &fail_phrase,
|
||||
uint32_t timeout_ms)
|
||||
command_result generic_command(CommandableIf *t, const std::string &command,
|
||||
const std::list<std::string_view> &pass_phrase,
|
||||
const std::list<std::string_view> &fail_phrase,
|
||||
uint32_t timeout_ms)
|
||||
{
|
||||
ESP_LOGD(TAG, "%s command %s\n", __func__, command.c_str());
|
||||
return t->command(command, [&](uint8_t *data, size_t len) {
|
||||
@@ -45,7 +47,7 @@ command_result generic_command(CommandableIf *t, const std::string &command,
|
||||
const std::string &pass_phrase,
|
||||
const std::string &fail_phrase, uint32_t timeout_ms)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
const auto pass = std::list<std::string_view>({pass_phrase});
|
||||
const auto fail = std::list<std::string_view>({fail_phrase});
|
||||
return generic_command(t, command, pass, fail, timeout_ms);
|
||||
@@ -81,7 +83,7 @@ bool set(std::span<char> &dest, std::string_view &src)
|
||||
|
||||
template <typename T> command_result generic_get_string(CommandableIf *t, const std::string &command, T &output, uint32_t timeout_ms)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return t->command(command, [&](uint8_t *data, size_t len) {
|
||||
size_t pos = 0;
|
||||
std::string_view response((char *)data, len);
|
||||
@@ -110,67 +112,67 @@ template <typename T> command_result generic_get_string(CommandableIf *t, const
|
||||
|
||||
command_result generic_command_common(CommandableIf *t, const std::string &command, uint32_t timeout_ms)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command(t, command, "OK", "ERROR", timeout_ms);
|
||||
}
|
||||
|
||||
command_result sync(CommandableIf *t)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command_common(t, "AT\r");
|
||||
}
|
||||
|
||||
command_result store_profile(CommandableIf *t)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command_common(t, "AT&W\r");
|
||||
}
|
||||
|
||||
command_result power_down(CommandableIf *t)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command(t, "AT+QPOWD=1\r", "POWERED DOWN", "ERROR", 1000);
|
||||
}
|
||||
|
||||
command_result power_down_sim76xx(CommandableIf *t)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command_common(t, "AT+CPOF\r", 1000);
|
||||
}
|
||||
|
||||
command_result power_down_sim70xx(CommandableIf *t)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command(t, "AT+CPOWD=1\r", "POWER DOWN", "ERROR", 1000);
|
||||
}
|
||||
|
||||
command_result power_down_sim8xx(CommandableIf *t)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command(t, "AT+CPOWD=1\r", "POWER DOWN", "ERROR", 1000);
|
||||
}
|
||||
|
||||
command_result reset(CommandableIf *t)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command(t, "AT+CRESET\r", "PB DONE", "ERROR", 60000);
|
||||
}
|
||||
|
||||
command_result set_baud(CommandableIf *t, int baud)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command_common(t, "AT+IPR=" + std::to_string(baud) + "\r");
|
||||
}
|
||||
|
||||
command_result hang_up(CommandableIf *t)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command_common(t, "ATH\r", 90000);
|
||||
}
|
||||
|
||||
command_result get_battery_status(CommandableIf *t, int &voltage, int &bcs, int &bcl)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
std::string out;
|
||||
auto ret = generic_get_string(t, "AT+CBC\r", out);
|
||||
if (ret != command_result::OK) {
|
||||
@@ -206,7 +208,7 @@ command_result get_battery_status(CommandableIf *t, int &voltage, int &bcs, int
|
||||
|
||||
command_result get_battery_status_sim7xxx(CommandableIf *t, int &voltage, int &bcs, int &bcl)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
std::string out;
|
||||
auto ret = generic_get_string(t, "AT+CBC\r", out);
|
||||
if (ret != command_result::OK) {
|
||||
@@ -235,13 +237,13 @@ command_result get_battery_status_sim7xxx(CommandableIf *t, int &voltage, int &b
|
||||
|
||||
command_result set_flow_control(CommandableIf *t, int dce_flow, int dte_flow)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command_common(t, "AT+IFC=" + std::to_string(dce_flow) + "," + std::to_string(dte_flow) + "\r");
|
||||
}
|
||||
|
||||
command_result get_operator_name(CommandableIf *t, std::string &operator_name, int &act)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
std::string out;
|
||||
auto ret = generic_get_string(t, "AT+COPS?\r", out, 75000);
|
||||
if (ret != command_result::OK) {
|
||||
@@ -272,7 +274,7 @@ command_result get_operator_name(CommandableIf *t, std::string &operator_name, i
|
||||
|
||||
command_result set_echo(CommandableIf *t, bool on)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
if (on) {
|
||||
return generic_command_common(t, "ATE1\r");
|
||||
}
|
||||
@@ -281,7 +283,7 @@ command_result set_echo(CommandableIf *t, bool on)
|
||||
|
||||
command_result set_pdp_context(CommandableIf *t, PdpContext &pdp, uint32_t timeout_ms)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
std::string pdp_command = "AT+CGDCONT=" + std::to_string(pdp.context_id) +
|
||||
",\"" + pdp.protocol_type + "\",\"" + pdp.apn + "\"\r";
|
||||
return generic_command_common(t, pdp_command, timeout_ms);
|
||||
@@ -294,25 +296,25 @@ command_result set_pdp_context(CommandableIf *t, PdpContext &pdp)
|
||||
|
||||
command_result set_data_mode(CommandableIf *t)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command(t, "ATD*99#\r", "CONNECT", "ERROR", 5000);
|
||||
}
|
||||
|
||||
command_result set_data_mode_alt(CommandableIf *t)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command(t, "ATD*99##\r", "CONNECT", "ERROR", 5000);
|
||||
}
|
||||
|
||||
command_result resume_data_mode(CommandableIf *t)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command(t, "ATO\r", "CONNECT", "ERROR", 5000);
|
||||
}
|
||||
|
||||
command_result set_command_mode(CommandableIf *t)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
const auto pass = std::list<std::string_view>({"NO CARRIER", "OK"});
|
||||
const auto fail = std::list<std::string_view>({"ERROR"});
|
||||
return generic_command(t, "+++", pass, fail, 5000);
|
||||
@@ -320,25 +322,25 @@ command_result set_command_mode(CommandableIf *t)
|
||||
|
||||
command_result get_imsi(CommandableIf *t, std::string &imsi_number)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_get_string(t, "AT+CIMI\r", imsi_number, 5000);
|
||||
}
|
||||
|
||||
command_result get_imei(CommandableIf *t, std::string &out)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_get_string(t, "AT+CGSN\r", out, 5000);
|
||||
}
|
||||
|
||||
command_result get_module_name(CommandableIf *t, std::string &out)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_get_string(t, "AT+CGMM\r", out, 5000);
|
||||
}
|
||||
|
||||
command_result sms_txt_mode(CommandableIf *t, bool txt = true)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
if (txt) {
|
||||
return generic_command_common(t, "AT+CMGF=1\r"); // Text mode (default)
|
||||
}
|
||||
@@ -348,13 +350,13 @@ command_result sms_txt_mode(CommandableIf *t, bool txt = true)
|
||||
command_result sms_character_set(CommandableIf *t)
|
||||
{
|
||||
// Sets the default GSM character set
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command_common(t, "AT+CSCS=\"GSM\"\r");
|
||||
}
|
||||
|
||||
command_result send_sms(CommandableIf *t, const std::string &number, const std::string &message)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
auto ret = t->command("AT+CMGS=\"" + number + "\"\r", [&](uint8_t *data, size_t len) {
|
||||
std::string_view response((char *)data, len);
|
||||
ESP_LOGD(TAG, "Send SMS response %.*s", static_cast<int>(response.size()), response.data());
|
||||
@@ -372,13 +374,13 @@ command_result send_sms(CommandableIf *t, const std::string &number, const std::
|
||||
|
||||
command_result set_cmux(CommandableIf *t)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command_common(t, "AT+CMUX=0\r");
|
||||
}
|
||||
|
||||
command_result read_pin(CommandableIf *t, bool &pin_ok)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
std::string out;
|
||||
auto ret = generic_get_string(t, "AT+CPIN?\r", out);
|
||||
if (ret != command_result::OK) {
|
||||
@@ -400,21 +402,21 @@ command_result read_pin(CommandableIf *t, bool &pin_ok)
|
||||
|
||||
command_result set_pin(CommandableIf *t, const std::string &pin)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
std::string set_pin_command = "AT+CPIN=" + pin + "\r";
|
||||
return generic_command_common(t, set_pin_command);
|
||||
}
|
||||
|
||||
command_result at(CommandableIf *t, const std::string &cmd, std::string &out, int timeout = 500)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
std::string at_command = cmd + "\r";
|
||||
return generic_get_string(t, at_command, out, timeout);
|
||||
}
|
||||
|
||||
command_result at_raw(CommandableIf *t, const std::string &cmd, std::string &out, const std::string &pass, const std::string &fail, int timeout = 500)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return t->command(cmd, [&](uint8_t *data, size_t len) {
|
||||
out.assign(reinterpret_cast<char *>(data), len);
|
||||
|
||||
@@ -430,7 +432,7 @@ command_result at_raw(CommandableIf *t, const std::string &cmd, std::string &out
|
||||
|
||||
command_result get_signal_quality(CommandableIf *t, int &rssi, int &ber)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
std::string out;
|
||||
auto ret = generic_get_string(t, "AT+CSQ\r", out);
|
||||
if (ret != command_result::OK) {
|
||||
@@ -456,19 +458,19 @@ command_result get_signal_quality(CommandableIf *t, int &rssi, int &ber)
|
||||
|
||||
command_result set_operator(CommandableIf *t, int mode, int format, const std::string &oper)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command_common(t, "AT+COPS=" + std::to_string(mode) + "," + std::to_string(format) + ",\"" + oper + "\"\r", 90000);
|
||||
}
|
||||
|
||||
command_result set_network_attachment_state(CommandableIf *t, int state)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command_common(t, "AT+CGATT=" + std::to_string(state) + "\r");
|
||||
}
|
||||
|
||||
command_result get_network_attachment_state(CommandableIf *t, int &state)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
std::string out;
|
||||
auto ret = generic_get_string(t, "AT+CGATT?\r", out);
|
||||
if (ret != command_result::OK) {
|
||||
@@ -489,13 +491,13 @@ command_result get_network_attachment_state(CommandableIf *t, int &state)
|
||||
|
||||
command_result set_radio_state(CommandableIf *t, int state)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command_common(t, "AT+CFUN=" + std::to_string(state) + "\r", 15000);
|
||||
}
|
||||
|
||||
command_result get_radio_state(CommandableIf *t, int &state)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
std::string out;
|
||||
auto ret = generic_get_string(t, "AT+CFUN?\r", out);
|
||||
if (ret != command_result::OK) {
|
||||
@@ -516,19 +518,19 @@ command_result get_radio_state(CommandableIf *t, int &state)
|
||||
|
||||
command_result set_network_mode(CommandableIf *t, int mode)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command_common(t, "AT+CNMP=" + std::to_string(mode) + "\r");
|
||||
}
|
||||
|
||||
command_result set_preferred_mode(CommandableIf *t, int mode)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command_common(t, "AT+CMNB=" + std::to_string(mode) + "\r");
|
||||
}
|
||||
|
||||
command_result set_network_bands(CommandableIf *t, const std::string &mode, const int *bands, int size)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
std::string band_string = "";
|
||||
for (int i = 0; i < size - 1; ++i) {
|
||||
band_string += std::to_string(bands[i]) + ",";
|
||||
@@ -542,7 +544,7 @@ command_result set_network_bands(CommandableIf *t, const std::string &mode, cons
|
||||
// any_mode = "0xFFFFFFFF7FFFFFFF";
|
||||
command_result set_network_bands_sim76xx(CommandableIf *t, const std::string &mode, const int *bands, int size)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
static const char *hexDigits = "0123456789ABCDEF";
|
||||
uint64_t band_bits = 0;
|
||||
int hex_len = 16;
|
||||
@@ -560,7 +562,7 @@ command_result set_network_bands_sim76xx(CommandableIf *t, const std::string &mo
|
||||
|
||||
command_result get_network_system_mode(CommandableIf *t, int &mode)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
std::string out;
|
||||
auto ret = generic_get_string(t, "AT+CNSMOD?\r", out);
|
||||
if (ret != command_result::OK) {
|
||||
@@ -582,13 +584,13 @@ command_result get_network_system_mode(CommandableIf *t, int &mode)
|
||||
|
||||
command_result set_gnss_power_mode(CommandableIf *t, int mode)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command_common(t, "AT+CGNSPWR=" + std::to_string(mode) + "\r");
|
||||
}
|
||||
|
||||
command_result get_gnss_power_mode(CommandableIf *t, int &mode)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
std::string out;
|
||||
auto ret = generic_get_string(t, "AT+CGNSPWR?\r", out);
|
||||
if (ret != command_result::OK) {
|
||||
@@ -607,9 +609,72 @@ command_result get_gnss_power_mode(CommandableIf *t, int &mode)
|
||||
return command_result::OK;
|
||||
}
|
||||
|
||||
command_result config_psm(CommandableIf *t, int enabled, const std::string &TAU, const std::string &activeTime)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
if (enabled == true) {
|
||||
return generic_command_common(t, "AT+CPSMS=1,,,\"" + TAU + "\"" + ",\"" + activeTime + "\"\r", 5000);
|
||||
}
|
||||
return generic_command_common(t, "AT+CPSMS=" + std::to_string(enabled) + "\r", 5000);
|
||||
}
|
||||
|
||||
command_result config_network_registration_urc(CommandableIf *t, int value)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command_common(t, "AT+CEREG=" + std::to_string(value) + "\r", 500);
|
||||
}
|
||||
|
||||
command_result get_network_registration_state(CommandableIf *t, int &state)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
std::string out;
|
||||
|
||||
auto ret = generic_get_string(t, "AT+CEREG?\r", out, 500);
|
||||
if (ret != command_result::OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
constexpr std::string_view pattern = "+CEREG: ";
|
||||
int state_pos_start;
|
||||
int state_pos_end;
|
||||
if (out.find(pattern) == std::string::npos || (state_pos_start = out.find(',')) == std::string::npos) {
|
||||
return command_result::FAIL;
|
||||
}
|
||||
|
||||
state_pos_start += 1; // move past the comma
|
||||
|
||||
if (out.find(pattern) == std::string::npos || (state_pos_end = out.find(',', state_pos_start)) == std::string::npos) {
|
||||
if (std::from_chars(out.data() + state_pos_start, out.data() + out.size(), state).ec == std::errc::invalid_argument) {
|
||||
return command_result::FAIL;
|
||||
}
|
||||
} else if (std::from_chars(out.data() + state_pos_start, out.data() + state_pos_end, state).ec == std::errc::invalid_argument) {
|
||||
return command_result::FAIL;
|
||||
}
|
||||
|
||||
return command_result::OK;
|
||||
}
|
||||
|
||||
command_result config_mobile_termination_error(CommandableIf *t, int value)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command_common(t, "AT+CMEE=" + std::to_string(value) + "\r");
|
||||
}
|
||||
command_result config_edrx(CommandableIf *t, int mode, int access_technology, const std::string &edrx_value)
|
||||
{
|
||||
if (mode == 1 || mode == 2) {
|
||||
return dce_commands::generic_command_common(t,
|
||||
"AT+CEDRXS=" +
|
||||
std::to_string(mode) +
|
||||
"," +
|
||||
std::to_string(access_technology) +
|
||||
",\"" +
|
||||
edrx_value + "\"\r");
|
||||
}
|
||||
return dce_commands::generic_command_common(t, "AT+SQNEDRX=" + std::to_string(mode), 500);
|
||||
}
|
||||
command_result set_gnss_power_mode_sim76xx(CommandableIf *t, int mode)
|
||||
{
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
ESP_LOGV(TAG, "%s", __func__);
|
||||
return generic_command_common(t, "AT+CGPS=" + std::to_string(mode) + "\r");
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ namespace transitions {
|
||||
|
||||
static bool exit_data(DTE &dte, ModuleIf &device, Netif &netif)
|
||||
{
|
||||
netif.stop();
|
||||
auto signal = std::make_shared<SignalGroup>();
|
||||
std::weak_ptr<SignalGroup> weak_signal = signal;
|
||||
dte.set_read_cb([&netif, weak_signal](uint8_t *data, size_t len) -> bool {
|
||||
@@ -32,7 +31,7 @@ static bool exit_data(DTE &dte, ModuleIf &device, Netif &netif)
|
||||
if (memchr(data, '\n', len))
|
||||
{
|
||||
ESP_LOG_BUFFER_HEXDUMP("esp-modem: debug_data (CMD)", data, len, ESP_LOG_DEBUG);
|
||||
const auto pass = std::list<std::string_view>({"NO CARRIER", "DISCONNECTED"});
|
||||
const auto pass = std::list<std::string_view>({"NO CARRIER", "DISCONNECTED", "OK"});
|
||||
std::string_view response((char *) data, len);
|
||||
for (auto &it : pass)
|
||||
if (response.find(it) != std::string::npos) {
|
||||
@@ -44,8 +43,14 @@ static bool exit_data(DTE &dte, ModuleIf &device, Netif &netif)
|
||||
}
|
||||
return false;
|
||||
});
|
||||
netif.stop();
|
||||
netif.wait_until_ppp_exits();
|
||||
if (!signal->wait(1, 2000)) {
|
||||
#ifdef ESP_MODEM_PPP_ESCAPE_BEFORE_EXIT
|
||||
std::array<uint8_t, 3> ppp_escape = {'+', '+', '+'};
|
||||
dte.write(ppp_escape.data(), ppp_escape.size());
|
||||
#endif
|
||||
if (!signal->wait(1, 2000)) { // wait for any of the disconnection messages
|
||||
// if no reply -> set device to command mode
|
||||
dte.set_read_cb(nullptr);
|
||||
if (!device.set_mode(modem_mode::COMMAND_MODE)) {
|
||||
return false;
|
||||
@@ -323,12 +328,19 @@ modem_mode DCE_Mode::guess_unsafe(DTE *dte, bool with_cmux)
|
||||
if (reply_pos >= sizeof(probe::ppp::lcp_echo_reply_head)) {
|
||||
// check for initial 2 bytes
|
||||
auto *ptr = static_cast<uint8_t *>(memmem(reply, reply_pos, probe::ppp::lcp_echo_reply_head.data(), 2));
|
||||
// and check the other two bytes for protocol ID: LCP
|
||||
// and check the other two bytes for protocol ID:
|
||||
// * either LCP reply
|
||||
if (ptr && ptr[3] == probe::ppp::lcp_echo_reply_head[3] && ptr[4] == probe::ppp::lcp_echo_reply_head[4]) {
|
||||
if (auto signal = weak_signal.lock()) {
|
||||
signal->set(probe::ppp::mode);
|
||||
}
|
||||
}
|
||||
// * or LCP conf request
|
||||
if (ptr && ptr[3] == probe::ppp::lcp_echo_request[3] && ptr[4] == probe::ppp::lcp_echo_request[4]) {
|
||||
if (auto signal = weak_signal.lock()) {
|
||||
signal->set(probe::ppp::mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (reply_pos >= 4 && memmem(reply, reply_pos, probe::cmd::reply, sizeof(probe::cmd::reply))) {
|
||||
if (reply[0] != 0xf9) { // double check that the reply is not wrapped in CMUX headers
|
||||
|
||||
@@ -14,38 +14,53 @@ using namespace esp_modem;
|
||||
|
||||
static const size_t dte_default_buffer_size = 1000;
|
||||
|
||||
DTE::DTE(const esp_modem_dte_config *config, std::unique_ptr<Terminal> terminal):
|
||||
buffer(config->dte_buffer_size),
|
||||
cmux_term(nullptr), primary_term(std::move(terminal)), secondary_term(primary_term),
|
||||
mode(modem_mode::UNDEF)
|
||||
DTE::DTE(const esp_modem_dte_config *config, std::unique_ptr<Terminal> terminal)
|
||||
: buffer(config->dte_buffer_size),
|
||||
cmux_term(nullptr),
|
||||
primary_term(std::move(terminal)),
|
||||
secondary_term(primary_term),
|
||||
mode(modem_mode::UNDEF)
|
||||
{
|
||||
ESP_MODEM_THROW_IF_FALSE(primary_term != nullptr, "Invalid argument: terminal cannot be null");
|
||||
set_command_callbacks();
|
||||
}
|
||||
|
||||
DTE::DTE(std::unique_ptr<Terminal> terminal):
|
||||
buffer(dte_default_buffer_size),
|
||||
cmux_term(nullptr), primary_term(std::move(terminal)), secondary_term(primary_term),
|
||||
mode(modem_mode::UNDEF)
|
||||
DTE::DTE(std::unique_ptr<Terminal> terminal)
|
||||
: buffer(dte_default_buffer_size),
|
||||
cmux_term(nullptr),
|
||||
primary_term(std::move(terminal)),
|
||||
secondary_term(primary_term),
|
||||
mode(modem_mode::UNDEF)
|
||||
{
|
||||
ESP_MODEM_THROW_IF_FALSE(primary_term != nullptr, "Invalid argument: terminal cannot be null");
|
||||
set_command_callbacks();
|
||||
}
|
||||
|
||||
DTE::DTE(const esp_modem_dte_config *config, std::unique_ptr<Terminal> t, std::unique_ptr<Terminal> s):
|
||||
buffer(config->dte_buffer_size),
|
||||
cmux_term(nullptr), primary_term(std::move(t)), secondary_term(std::move(s)),
|
||||
mode(modem_mode::DUAL_MODE)
|
||||
DTE::DTE(const esp_modem_dte_config *config, std::unique_ptr<Terminal> t, std::unique_ptr<Terminal> s)
|
||||
: buffer(config->dte_buffer_size),
|
||||
cmux_term(nullptr),
|
||||
primary_term(std::move(t)),
|
||||
secondary_term(std::move(s)),
|
||||
mode(modem_mode::DUAL_MODE)
|
||||
{
|
||||
ESP_MODEM_THROW_IF_FALSE(primary_term != nullptr, "Invalid argument: primary terminal cannot be null");
|
||||
ESP_MODEM_THROW_IF_FALSE(secondary_term != nullptr, "Invalid argument: secondary terminal cannot be null");
|
||||
set_command_callbacks();
|
||||
}
|
||||
|
||||
DTE::DTE(std::unique_ptr<Terminal> t, std::unique_ptr<Terminal> s):
|
||||
buffer(dte_default_buffer_size),
|
||||
cmux_term(nullptr), primary_term(std::move(t)), secondary_term(std::move(s)),
|
||||
mode(modem_mode::DUAL_MODE)
|
||||
DTE::DTE(std::unique_ptr<Terminal> t, std::unique_ptr<Terminal> s)
|
||||
: buffer(dte_default_buffer_size),
|
||||
cmux_term(nullptr),
|
||||
primary_term(std::move(t)),
|
||||
secondary_term(std::move(s)),
|
||||
mode(modem_mode::DUAL_MODE)
|
||||
{
|
||||
ESP_MODEM_THROW_IF_FALSE(primary_term != nullptr, "Invalid argument: primary terminal cannot be null");
|
||||
ESP_MODEM_THROW_IF_FALSE(secondary_term != nullptr, "Invalid argument: secondary terminal cannot be null");
|
||||
set_command_callbacks();
|
||||
}
|
||||
|
||||
|
||||
void DTE::set_command_callbacks()
|
||||
{
|
||||
primary_term->set_read_cb([this](uint8_t *data, size_t len) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "cxx_include/esp_modem_api.hpp"
|
||||
#include "cxx_include/esp_modem_dce_module.hpp"
|
||||
#include "generate/esp_modem_command_declare.inc"
|
||||
#include "cxx17_include/esp_modem_command_library_17.hpp"
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
@@ -35,7 +36,7 @@ GenericModule::GenericModule(std::shared_ptr<DTE> dte, const dce_config *config)
|
||||
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, arg_nr, ...) \
|
||||
return_type GenericModule::name(__VA_ARGS__) { return esp_modem::dce_commands::name(dte.get() ARGS(arg_nr) ); }
|
||||
|
||||
DECLARE_ALL_COMMAND_APIS(return_type name(...) )
|
||||
DECLARE_ALL_COMMAND_APIS(return_type name(...))
|
||||
|
||||
#undef ESP_MODEM_DECLARE_DCE_COMMAND
|
||||
|
||||
@@ -87,4 +88,41 @@ command_result BG96::set_pdp_context(esp_modem::PdpContext &pdp)
|
||||
return dce_commands::set_pdp_context(dte.get(), pdp, 300);
|
||||
}
|
||||
|
||||
bool SQNGM02S::setup_data_mode()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
command_result SQNGM02S::connect(PdpContext &pdp)
|
||||
{
|
||||
command_result res;
|
||||
configure_pdp_context(std::make_unique<PdpContext>(pdp));
|
||||
set_pdp_context(*this->pdp);
|
||||
res = config_network_registration_urc(1);
|
||||
if (res != command_result::OK) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res = set_radio_state(1);
|
||||
if (res != command_result::OK) {
|
||||
return res;
|
||||
}
|
||||
|
||||
//wait for +CEREG: 5 or +CEREG: 1.
|
||||
const auto pass = std::list<std::string_view>({"+CEREG: 1", "+CEREG: 5"});
|
||||
const auto fail = std::list<std::string_view>({"ERROR"});
|
||||
res = esp_modem::dce_commands::generic_command(dte.get(), "", pass, fail, 1200000);
|
||||
|
||||
if (res != command_result::OK) {
|
||||
config_network_registration_urc(0);
|
||||
return res;
|
||||
}
|
||||
|
||||
res = config_network_registration_urc(0);
|
||||
if (res != command_result::OK) {
|
||||
return res;
|
||||
}
|
||||
|
||||
return command_result::OK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,6 +99,20 @@ void Netif::stop()
|
||||
signal.clear(PPP_STARTED);
|
||||
}
|
||||
|
||||
void Netif::resume()
|
||||
{
|
||||
ppp_dte->set_read_cb([this](uint8_t *data, size_t len) -> bool {
|
||||
receive(data, len);
|
||||
return true;
|
||||
});
|
||||
signal.set(PPP_STARTED);
|
||||
}
|
||||
|
||||
void Netif::pause()
|
||||
{
|
||||
signal.clear(PPP_STARTED);
|
||||
}
|
||||
|
||||
Netif::~Netif()
|
||||
{
|
||||
if (signal.is_any(PPP_STARTED)) {
|
||||
|
||||
@@ -52,7 +52,6 @@ void Netif::start()
|
||||
|
||||
void Netif::stop()
|
||||
{
|
||||
ppp_dte->set_read_cb(nullptr);
|
||||
signal.clear(PPP_STARTED);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -72,6 +72,7 @@ private:
|
||||
{
|
||||
auto t = static_cast<UartTerminal *>(task_param);
|
||||
t->task();
|
||||
t->task_handle.task_handle = nullptr;
|
||||
vTaskDelete(nullptr);
|
||||
}
|
||||
|
||||
@@ -175,13 +176,20 @@ int UartTerminal::read(uint8_t *data, size_t len)
|
||||
uart_get_buffered_data_len(uart.port, &length);
|
||||
length = std::min(len, length);
|
||||
if (length > 0) {
|
||||
return uart_read_bytes(uart.port, data, length, portMAX_DELAY);
|
||||
int read_len = uart_read_bytes(uart.port, data, length, portMAX_DELAY);
|
||||
#if CONFIG_ESP_MODEM_ADD_DEBUG_LOGS
|
||||
ESP_LOG_BUFFER_HEXDUMP("uart-rx", data, read_len, ESP_LOG_DEBUG);
|
||||
#endif
|
||||
return read_len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int UartTerminal::write(uint8_t *data, size_t len)
|
||||
{
|
||||
#if CONFIG_ESP_MODEM_ADD_DEBUG_LOGS
|
||||
ESP_LOG_BUFFER_HEXDUMP("uart-tx", data, len, ESP_LOG_DEBUG);
|
||||
#endif
|
||||
return uart_write_bytes_compat(uart.port, data, len);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,14 +16,14 @@ menu "Test App Configuration"
|
||||
config TEST_APP_UART_TX_PIN
|
||||
int "TXD Pin Number"
|
||||
default 6
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number of UART TX.
|
||||
|
||||
config TEST_APP_UART_RX_PIN
|
||||
int "RXD Pin Number"
|
||||
default 7
|
||||
range 0 31
|
||||
range 0 56
|
||||
help
|
||||
Pin number of UART RX.
|
||||
|
||||
|
||||
@@ -9,6 +9,20 @@ from threading import Event, Thread
|
||||
import netifaces
|
||||
|
||||
|
||||
def is_esp32(port):
|
||||
"""
|
||||
Check if the given port is connected to an ESP32 using esptool.
|
||||
"""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['esptool.py', '--port', port, 'chip_id'],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, text=True
|
||||
)
|
||||
return 'ESP32' in result.stdout
|
||||
except subprocess.CalledProcessError:
|
||||
return False
|
||||
|
||||
|
||||
def run_server(server_stop, port, server_ip, client_ip, auth, auth_user, auth_password):
|
||||
print('Starting PPP server on port: {}'.format(port))
|
||||
try:
|
||||
@@ -66,13 +80,27 @@ def test_examples_protocol_pppos_connect(dut):
|
||||
)
|
||||
raise
|
||||
|
||||
# the PPP test env uses two ttyUSB's: one for ESP32 board, another one for ppp server
|
||||
# use the other port for PPP server than the DUT/ESP
|
||||
port = '/dev/ttyUSB0' if dut.serial.port == '/dev/ttyUSB1' else '/dev/ttyUSB1'
|
||||
# the PPP test env uses three ttyUSB's: two for ESP32 board and another one for the ppp server
|
||||
# we need to detect the server_port (for PPPD)
|
||||
server_port = None
|
||||
for i in ['/dev/ttyUSB0', '/dev/ttyUSB1', '/dev/ttyUSB2']:
|
||||
if i == dut.serial.port:
|
||||
print(f'DUT port: {i}')
|
||||
elif is_esp32(i):
|
||||
print(f'Some other ESP32: {i}')
|
||||
else:
|
||||
print(f'Port for PPPD: {i}')
|
||||
server_port = i
|
||||
if server_port is None:
|
||||
print(
|
||||
'ENV_TEST_FAILURE: Cannot locate PPPD port'
|
||||
)
|
||||
raise
|
||||
|
||||
# Start the PPP server
|
||||
server_stop = Event()
|
||||
t = Thread(target=run_server,
|
||||
args=(server_stop, port, server_ip, client_ip, auth, auth_user, auth_password))
|
||||
args=(server_stop, server_port, server_ip, client_ip, auth, auth_user, auth_password))
|
||||
t.start()
|
||||
try:
|
||||
ppp_server_timeout = time.time() + 30
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user