mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-27 01:07:27 +02:00
Compare commits
170 Commits
wifi_remot
...
mdns-v1.7.
Author | SHA1 | Date | |
---|---|---|---|
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 | |||
b65cff3a0b | |||
e711f26670 | |||
4a1cb65c67 | |||
6c61dd39cf | |||
8821ea3a99 | |||
062b8dcacc | |||
7de57bb412 | |||
67191f3bb5 | |||
6d94ad646d | |||
685d47cd2f | |||
31f57ad067 | |||
32ac21b03c | |||
5b06a3b319 | |||
cc2741d4ad | |||
c5653ff204 | |||
77731c9b36 | |||
2442f6b553 | |||
0b5e362a7b | |||
5219c39d09 | |||
1a9eaf3e98 | |||
52598e5f03 | |||
542547d38b | |||
2bcfa45d30 | |||
a453ca1f38 | |||
72f4f7c7a3 | |||
a353702e04 | |||
991ac40d75 | |||
fbd296f8dd | |||
a5b0b9d6ea | |||
2d9759265b | |||
8f1f935858 | |||
3f48f9ea7e | |||
8520245657 | |||
185247d220 | |||
73b3293b86 | |||
f613c70e00 | |||
c2c4bf835a | |||
1af4bbe1ab | |||
f5dc07fdcc | |||
e992787bcd | |||
010a404a04 | |||
0d8f2a6d53 |
@ -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
|
||||
|
3
.github/workflows/clang-tidy.yml
vendored
3
.github/workflows/clang-tidy.yml
vendored
@ -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
|
||||
@ -35,7 +36,7 @@ jobs:
|
||||
working-directory: test_app
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
idf.py clang-check --include-paths $GITHUB_WORKSPACE --exclude-paths $PWD --run-clang-tidy-py run-clang-tidy
|
||||
idf.py clang-check --include-paths $GITHUB_WORKSPACE --exclude-paths $PWD --run-clang-tidy-py run-clang-tidy --run-clang-tidy-options "-checks=-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling"
|
||||
cp warnings.txt ../
|
||||
- name: Convert clang-tidy results into SARIF output
|
||||
run: |
|
||||
|
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
|
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
|
||||
|
15
.github/workflows/modem__build-host-tests.yml
vendored
15
.github/workflows/modem__build-host-tests.yml
vendored
@ -13,11 +13,8 @@ jobs:
|
||||
name: Build examples
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v4.4", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3"]
|
||||
idf_ver: ["latest", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3", "release-v5.4"]
|
||||
example: ["pppos_client", "modem_console", "modem_tcp_client", "ap_to_pppos", "simple_cmux_client"]
|
||||
exclude:
|
||||
- idf_ver: "release-v4.4"
|
||||
example: modem_tcp_client
|
||||
include:
|
||||
- idf_ver: "release-v5.0"
|
||||
example: "simple_cmux_client"
|
||||
@ -26,13 +23,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Check out code (v3) # @v4 failed due to Node 20's requirement, incompatible with older IDF versions
|
||||
if: matrix.idf_ver != 'latest' && matrix.idf_ver < 'release-v5.0'
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: protocols
|
||||
- name: Check out code (v4)
|
||||
if: matrix.idf_ver == 'latest' || matrix.idf_ver >= 'release-v5.0'
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: protocols
|
||||
@ -53,7 +44,7 @@ jobs:
|
||||
name: Build tests
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3", "latest"]
|
||||
idf_ver: ["release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3", "release-v5.4", "latest"]
|
||||
test: ["target", "target_ota", "target_iperf"]
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
|
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 }}
|
||||
|
116
.github/workflows/mosq__build.yml
vendored
116
.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:
|
||||
@ -64,9 +66,115 @@ jobs:
|
||||
- name: Run Test
|
||||
working-directory: ${{ env.TEST_DIR }}
|
||||
run: |
|
||||
python -m pip install pytest-embedded-serial-esp pytest-embedded-idf pytest-rerunfailures pytest-timeout pytest-ignore-test-results
|
||||
unzip ci/artifacts.zip -d ci
|
||||
for dir in `ls -d ci/build_*`; do
|
||||
rm -rf build sdkconfig.defaults
|
||||
mv $dir build
|
||||
python -m pytest --log-cli-level DEBUG --junit-xml=./results_esp32_${{ matrix.idf_ver }}_${dir#"ci/build_"}.xml --target=esp32
|
||||
done
|
||||
|
||||
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-20.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"
|
||||
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
|
||||
|
4
.github/workflows/publish-docs-component.yml
vendored
4
.github/workflows/publish-docs-component.yml
vendored
@ -98,7 +98,9 @@ jobs:
|
||||
components/console_cmd_ping;
|
||||
components/console_cmd_ifconfig;
|
||||
components/console_cmd_wifi;
|
||||
components/esp_wifi_remote;
|
||||
components/console_cmd_mqtt;
|
||||
components/mbedtls_cxx;
|
||||
components/mosquitto;
|
||||
components/sock_utils;
|
||||
namespace: "espressif"
|
||||
api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }}
|
||||
|
95
.github/workflows/sockutls_build.yml
vendored
Normal file
95
.github/workflows/sockutls_build.yml
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
name: "sock_utils: build-tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, labeled]
|
||||
|
||||
jobs:
|
||||
build_sock_utils:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'sock_utils') || github.event_name == 'push'
|
||||
name: Socket helpers build
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.3"]
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
env:
|
||||
TEST_DIR: components/sock_utils/examples/simple
|
||||
TARGET_TEST_DIR: build_esp32_default
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build with IDF-${{ matrix.idf_ver }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
python ci/build_apps.py ${TEST_DIR}
|
||||
cd ${TEST_DIR}
|
||||
${GITHUB_WORKSPACE}/ci/clean_build_artifacts.sh `pwd`/${TARGET_TEST_DIR}
|
||||
zip -qur artifacts.zip ${TARGET_TEST_DIR}
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sock_utils_target_esp32_${{ matrix.idf_ver }}
|
||||
path: ${{ env.TEST_DIR }}/artifacts.zip
|
||||
if-no-files-found: error
|
||||
host_test_sock_utils:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'sock_utils') || github.event_name == 'push'
|
||||
name: Socket helpers host test
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.3"]
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
env:
|
||||
TEST_DIR: components/sock_utils/test/host
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build with IDF-${{ matrix.idf_ver }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
cd ${TEST_DIR}
|
||||
idf.py build
|
||||
./build/sock_utils_host_test.elf
|
||||
|
||||
test_sock_utils:
|
||||
# Skip running on forks since it won't have access to secrets
|
||||
if: |
|
||||
github.repository == 'espressif/esp-protocols' &&
|
||||
( contains(github.event.pull_request.labels.*.name, 'sock_utils') || github.event_name == 'push' )
|
||||
name: Socket helpers target test
|
||||
needs: build_sock_utils
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.3"]
|
||||
runs-on:
|
||||
- self-hosted
|
||||
- ESP32-ETHERNET-KIT
|
||||
env:
|
||||
TEST_DIR: components/sock_utils/examples/simple
|
||||
TARGET_TEST_DIR: build_esp32_default
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: sock_utils_target_esp32_${{ matrix.idf_ver }}
|
||||
path: ${{ env.TEST_DIR }}/ci/
|
||||
- name: Run Test
|
||||
working-directory: ${{ env.TEST_DIR }}
|
||||
run: |
|
||||
unzip ci/artifacts.zip -d ci
|
||||
for dir in `ls -d ci/build_*`; do
|
||||
rm -rf build sdkconfig.defaults
|
||||
mv $dir build
|
||||
python -m pytest --log-cli-level DEBUG --junit-xml=./results_esp32_${{ matrix.idf_ver }}_${dir#"ci/build_"}.xml --target=esp32
|
||||
done
|
112
.github/workflows/wifi_remote__build.yml
vendored
112
.github/workflows/wifi_remote__build.yml
vendored
@ -1,112 +0,0 @@
|
||||
name: "esp_wifi_remote: build-tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, labeled]
|
||||
|
||||
jobs:
|
||||
wifi_remote_api_compat:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'wifi_remote') || github.event_name == 'push'
|
||||
name: Check API compatibility of WiFi Remote
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.3"]
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
- name: Check that headers are the same as generated
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
cp -r ./components/esp_wifi_remote ./components/esp_wifi_remote_base
|
||||
cd ./components/esp_wifi_remote/scripts
|
||||
python generate_and_check.py --base-dir ../../esp_wifi_remote_base
|
||||
|
||||
build_wifi_remote:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'wifi_remote') || github.event_name == 'push'
|
||||
name: Build WiFi Remote Test
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.3"]
|
||||
test: [ { app: smoke_test, path: "test/smoke_test" }]
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: ${{ matrix.idf_ver }}
|
||||
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
python ./components/esp_wifi_remote/scripts/generate_slave_configs.py ./components/esp_wifi_remote/${{matrix.test.path}}
|
||||
python ./ci/build_apps.py ./components/esp_wifi_remote/${{matrix.test.path}} -vv --preserve-all
|
||||
|
||||
build_wifi_remote_example:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'wifi_remote') || github.event_name == 'push'
|
||||
name: Build WiFi Remote Example
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
example: [ { app: host, path: "examples/mqtt" }, { app: slave, path: "examples/server" }]
|
||||
include:
|
||||
- idf_ver: "latest"
|
||||
example: { app: slave, path: "examples/server" }
|
||||
warning: "Warning: The smallest app partition is nearly full"
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
- name: Build ${{ matrix.example.app }} with IDF-${{ matrix.idf_ver }}
|
||||
env:
|
||||
EXPECTED_WARNING: ${{ matrix.warning }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
python ./ci/build_apps.py ./components/esp_wifi_remote/${{matrix.example.path}} -vv --preserve-all
|
||||
|
||||
build_idf_examples_with_wifi_remote:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'wifi_remote') || github.event_name == 'push'
|
||||
name: Build IDF examples with WiFi Remote
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.3"]
|
||||
idf_target: ["esp32p4", "esp32h2", "esp32s3"]
|
||||
test: [ { app: idf_mqtt_example, path: "examples/protocols/mqtt/tcp" }]
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: ${{ matrix.idf_ver }}
|
||||
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
export OVERRIDE_PATH=`pwd`/components/esp_wifi_remote
|
||||
echo ${OVERRIDE_PATH}
|
||||
sed -i '/espressif\/esp_wifi_remote:/a \ \ \ \ override_path: "${OVERRIDE_PATH}"' ${IDF_PATH}/${{matrix.test.path}}/main/idf_component.yml
|
||||
cat ${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* -vv --target ${{ matrix.idf_target }}
|
||||
idf-build-apps build --config sdkconfig.ci* -vv --target ${{ matrix.idf_target }}
|
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -1,6 +1,6 @@
|
||||
[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
|
||||
|
@ -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, wifi_remote, tls_cxx"
|
||||
entry: '\A(?!(feat|fix|ci|bump|test|docs)\((mdns|modem|common|console|websocket|asio|mqtt_cxx|examples|eppp|wifi_remote|tls_cxx|mosq)\)\:)'
|
||||
name: "commit message must be scoped with: mdns, modem, websocket, asio, mqtt_cxx, console, common, eppp, tls_cxx, mosq, sockutls"
|
||||
entry: '\A(?!(feat|fix|ci|bump|test|docs|chore)\((mdns|modem|common|console|websocket|asio|mqtt_cxx|examples|eppp|tls_cxx|mosq|sockutls)\)\:)'
|
||||
language: pygrep
|
||||
args: [--multiline]
|
||||
stages: [commit-msg]
|
||||
|
13
README.md
13
README.md
@ -54,10 +54,15 @@ Please refer to instructions in [ESP-IDF](https://github.com/espressif/esp-idf)
|
||||
|
||||
* Brief introduction [README](components/eppp_link/README.md)
|
||||
|
||||
### esp_wifi_remote
|
||||
|
||||
* Brief introduction [README](components/esp_wifi_remote/README.md)
|
||||
|
||||
### mbedtls_cxx
|
||||
|
||||
* Brief introduction [README](components/mbedtls_cxx/README.md)
|
||||
|
||||
### mosquitto
|
||||
|
||||
* Brief introduction [README](components/mosquitto/README.md)
|
||||
* API documentation [api.md](components/mosquitto/api.md)
|
||||
|
||||
### Socket helpers (sock-utils)
|
||||
|
||||
* Brief introduction [README](components/sock_utils/README.md)
|
||||
|
@ -53,6 +53,7 @@ mosquitto_component:
|
||||
allowed_licenses:
|
||||
- EPL-2.0
|
||||
- Apache-2.0
|
||||
- BSD-3-Clause
|
||||
|
||||
slim_modem_examples:
|
||||
include:
|
||||
|
@ -0,0 +1 @@
|
||||
components/mosquitto/examples/serverless_mqtt/components/libjuice/port/juice_random.c
|
||||
|
@ -1,2 +0,0 @@
|
||||
# The below file is generated from esp_wifi_types_native.h in IDF, which doesn't follow atyle
|
||||
components/esp_wifi_remote/include/esp_wifi_types_native.h
|
||||
|
@ -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) {
|
||||
@ -176,14 +176,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 +212,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 +280,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 +290,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.1.0
|
||||
version: 1.3.0
|
||||
version_files:
|
||||
- idf_component.yml
|
||||
|
@ -1,5 +1,63 @@
|
||||
# Changelog
|
||||
|
||||
## [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
|
||||
|
||||
- Add support for guessing mode ([52598e5f](https://github.com/espressif/esp-protocols/commit/52598e5f))
|
||||
- Delete CMUX internal implementation even if terminal exit fails ([0e0cbd6b](https://github.com/espressif/esp-protocols/commit/0e0cbd6b))
|
||||
- Add support for handling URC ([1b6a3b3b](https://github.com/espressif/esp-protocols/commit/1b6a3b3b), [#180](https://github.com/espressif/esp-protocols/issues/180))
|
||||
- add ability to change ESP_MODEM_C_API_STR_MAX from Kconfig ([17909892](https://github.com/espressif/esp-protocols/commit/17909892))
|
||||
- Added target test config with CHAP authentication ([f8ae7def](https://github.com/espressif/esp-protocols/commit/f8ae7def))
|
||||
- example add esp32p4 usb support ([adafeae5](https://github.com/espressif/esp-protocols/commit/adafeae5))
|
||||
- Publish mbedtls component ([0140455f](https://github.com/espressif/esp-protocols/commit/0140455f))
|
||||
- host test support of the latest ESP-IDF release ([3f74b4e8](https://github.com/espressif/esp-protocols/commit/3f74b4e8))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix console example to use urc/detect features ([1a9eaf3e](https://github.com/espressif/esp-protocols/commit/1a9eaf3e))
|
||||
- Update target test builds to use external Catch2 ([554f022c](https://github.com/espressif/esp-protocols/commit/554f022c))
|
||||
- Fix arguments names when spawn esp_modem_xxx declarations ([b6792c52](https://github.com/espressif/esp-protocols/commit/b6792c52))
|
||||
- Remove catch dependency ([c3480768](https://github.com/espressif/esp-protocols/commit/c3480768))
|
||||
- Examples: use local configs for MQTT topic/data ([f5c13b92](https://github.com/espressif/esp-protocols/commit/f5c13b92))
|
||||
- Fixed clang-tidy warnings ([70fa3af7](https://github.com/espressif/esp-protocols/commit/70fa3af7))
|
||||
- Fix CI build per IDFv5.3 ([d0c17ef0](https://github.com/espressif/esp-protocols/commit/d0c17ef0))
|
||||
- Fixed UART task to check for buffered data periodically ([4bdd90cc](https://github.com/espressif/esp-protocols/commit/4bdd90cc), [#536](https://github.com/espressif/esp-protocols/issues/536))
|
||||
- Cleanup unused configs from PPPoS example ([08a62ccc](https://github.com/espressif/esp-protocols/commit/08a62ccc))
|
||||
- Update CMUX example with SIM7070_gnss cleaned-up ([56fe5327](https://github.com/espressif/esp-protocols/commit/56fe5327))
|
||||
- Update console example with SIM7070_gnss format comments ([5baaf542](https://github.com/espressif/esp-protocols/commit/5baaf542))
|
||||
- Fix remaining print format warnings ([3b80181d](https://github.com/espressif/esp-protocols/commit/3b80181d))
|
||||
|
||||
### Updated
|
||||
|
||||
- docs(modem): Fix esp_modem_at_raw() description (C-API) ([492a6a00](https://github.com/espressif/esp-protocols/commit/492a6a00))
|
||||
- ci(common): updated github actions(checkout, upload, download) v3 to 4, Ubuntu 20.04 to v22.04 ([a23a0027](https://github.com/espressif/esp-protocols/commit/a23a0027))
|
||||
|
||||
## [1.1.0](https://github.com/espressif/esp-protocols/commits/modem-v1.1.0)
|
||||
|
||||
### Features
|
||||
|
@ -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.
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
@ -89,7 +89,7 @@ void wakeup_modem(void)
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_MODEM_DEVICE_SHINY
|
||||
#ifdef CONFIG_ESP_MODEM_URC_HANDLER
|
||||
command_result handle_urc(uint8_t *data, size_t len)
|
||||
{
|
||||
ESP_LOG_BUFFER_HEXDUMP("on_read", data, len, ESP_LOG_INFO);
|
||||
@ -238,7 +238,9 @@ extern "C" void app_main(void)
|
||||
if (c->get_count_of(&SetModeArgs::mode)) {
|
||||
auto mode = c->get_string_of(&SetModeArgs::mode);
|
||||
modem_mode dev_mode;
|
||||
if (mode == "UNDEF") {
|
||||
if (mode == "AUTO") {
|
||||
dev_mode = esp_modem::modem_mode::AUTODETECT;
|
||||
} else if (mode == "UNDEF") {
|
||||
dev_mode = esp_modem::modem_mode::UNDEF;
|
||||
} else if (mode == "CMUX1") {
|
||||
dev_mode = esp_modem::modem_mode::CMUX_MANUAL_MODE;
|
||||
@ -370,19 +372,30 @@ extern "C" void app_main(void)
|
||||
ESP_LOGI(TAG, "Resetting the module...");
|
||||
CHECK_ERR(dce->reset(), ESP_LOGI(TAG, "OK"));
|
||||
});
|
||||
#ifdef CONFIG_EXAMPLE_MODEM_DEVICE_SHINY
|
||||
#ifdef CONFIG_ESP_MODEM_URC_HANDLER
|
||||
const ConsoleCommand HandleURC("urc", "toggle urc handling", no_args, [&](ConsoleCommand * c) {
|
||||
static int cnt = 0;
|
||||
if (++cnt % 2) {
|
||||
ESP_LOGI(TAG, "Adding URC handler");
|
||||
dce->set_on_read(handle_urc);
|
||||
dce->set_urc(handle_urc);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "URC removed");
|
||||
dce->set_on_read(nullptr);
|
||||
dce->set_urc(nullptr);
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
#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)") {}
|
||||
|
@ -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
|
||||
|
@ -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.1.0"
|
||||
version: "1.3.0"
|
||||
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
|
||||
|
@ -30,9 +30,11 @@ public:
|
||||
~DCE_Mode() = default;
|
||||
bool set(DTE *dte, ModuleIf *module, Netif &netif, modem_mode m);
|
||||
modem_mode get();
|
||||
modem_mode guess(DTE *dte, bool with_cmux = false);
|
||||
|
||||
private:
|
||||
bool set_unsafe(DTE *dte, ModuleIf *module, Netif &netif, modem_mode m);
|
||||
modem_mode guess_unsafe(DTE *dte, bool with_cmux);
|
||||
modem_mode mode;
|
||||
|
||||
};
|
||||
@ -79,11 +81,21 @@ public:
|
||||
return dte->command(command, std::move(got_line), time_ms);
|
||||
}
|
||||
|
||||
modem_mode guess_mode(bool with_cmux = false)
|
||||
{
|
||||
return mode.guess(dte.get(), with_cmux);
|
||||
}
|
||||
|
||||
bool set_mode(modem_mode m)
|
||||
{
|
||||
return mode.set(dte.get(), device.get(), netif, m);
|
||||
}
|
||||
|
||||
modem_mode get_mode()
|
||||
{
|
||||
return mode.get();
|
||||
}
|
||||
|
||||
bool recover()
|
||||
{
|
||||
return dte->recover();
|
||||
@ -96,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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -65,6 +65,18 @@ public:
|
||||
|
||||
int write(DTE_Command command);
|
||||
|
||||
/**
|
||||
* @brief send data to the selected terminal, by default (without term_id argument)
|
||||
* this API works the same as write: sends data to the secondary terminal, which is
|
||||
* typically used as data terminal (for networking).
|
||||
*
|
||||
* @param data Data pointer to write
|
||||
* @param len Data len to write
|
||||
* @param term_id Terminal id: Primary if id==0, Secondary if id==1
|
||||
* @return number of bytes written
|
||||
*/
|
||||
int send(uint8_t *data, size_t len, int term_id = 1);
|
||||
|
||||
/**
|
||||
* @brief Reading from the underlying terminal
|
||||
* @param d Returning the data pointer of the received payload
|
||||
@ -133,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
|
||||
@ -192,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:
|
||||
|
@ -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
|
||||
*/
|
||||
@ -37,6 +37,17 @@ enum class modem_mode {
|
||||
CMUX_MANUAL_DATA, /*!< Sets the primary terminal to DATA mode in manual CMUX */
|
||||
CMUX_MANUAL_COMMAND, /*!< Sets the primary terminal to COMMAND mode in manual CMUX */
|
||||
CMUX_MANUAL_SWAP, /*!< Swaps virtual terminals in manual CMUX mode (primary <-> secondary) */
|
||||
RESUME_DATA_MODE, /*!< This is used when the device is already in DATA mode and we need the modem lib to
|
||||
* enter the mode without switching. On success, we would end up in DATA-mode, UNDEF otherwise */
|
||||
RESUME_COMMAND_MODE, /*!< This is used when the device is already in COMMAND mode and we want to resume it
|
||||
* On success, we would end up in DATA-mode, UNDEF otherwise */
|
||||
RESUME_CMUX_MANUAL_MODE, /*!< This is used when the device is already in CMUX mode and we need the modem lib to
|
||||
* enter it without switching. On success, we would end up in CMUX_MANUAL-mode, UNDEF otherwise */
|
||||
RESUME_CMUX_MANUAL_DATA, /*!< This is used when the device is already in CMUX-DATA mode and we need the modem lib to
|
||||
* enter it without switching. On success, we would end up in CMUX_MANUAL-DATA mode, UNDEF otherwise */
|
||||
AUTODETECT, /*!< Auto-detection command: It tries to send a few packets in order to recognize which mode the
|
||||
* the device currently is and update the modem library mode. On success the modem is updated,
|
||||
* otherwise it's set to UNDEF */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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,13 +45,15 @@ 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,
|
||||
@ -141,6 +147,33 @@ 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
|
||||
|
||||
/**
|
||||
* @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);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
@ -44,7 +44,7 @@ inline dce_factory::ModemType convert_modem_enum(esp_modem_dce_device_t module)
|
||||
case ESP_MODEM_DCE_SIM800:
|
||||
return esp_modem::dce_factory::ModemType::SIM800;
|
||||
default:
|
||||
case ESP_MODEM_DCE_GENETIC:
|
||||
case ESP_MODEM_DCE_GENERIC:
|
||||
return esp_modem::dce_factory::ModemType::GenericModule;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
@ -451,3 +484,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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -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;
|
||||
@ -103,6 +108,51 @@ bool DCE_Mode::set_unsafe(DTE *dte, ModuleIf *device, Netif &netif, modem_mode m
|
||||
return true;
|
||||
case modem_mode::DUAL_MODE: // Only DTE can be in Dual mode
|
||||
break;
|
||||
case modem_mode::AUTODETECT: {
|
||||
auto guessed = guess_unsafe(dte, true);
|
||||
if (guessed == modem_mode::UNDEF) {
|
||||
return false;
|
||||
}
|
||||
// prepare the undefined mode before to allow all possible transitions
|
||||
if (!dte->set_mode(modem_mode::UNDEF)) {
|
||||
return false;
|
||||
}
|
||||
mode = modem_mode::UNDEF;
|
||||
ESP_LOGD("DCE mode", "Detected mode: %d", static_cast<int>(guessed));
|
||||
if (guessed == modem_mode::DATA_MODE) {
|
||||
return set_unsafe(dte, device, netif, esp_modem::modem_mode::RESUME_DATA_MODE);
|
||||
} else if (guessed == esp_modem::modem_mode::COMMAND_MODE) {
|
||||
return set_unsafe(dte, device, netif, esp_modem::modem_mode::RESUME_COMMAND_MODE);
|
||||
} else if (guessed == esp_modem::modem_mode::CMUX_MODE) {
|
||||
if (!set_unsafe(dte, device, netif, esp_modem::modem_mode::RESUME_CMUX_MANUAL_MODE)) {
|
||||
return false;
|
||||
}
|
||||
// now we guess the mode for each terminal
|
||||
guessed = guess_unsafe(dte, false);
|
||||
ESP_LOGD("DCE mode", "Detected mode on primary term: %d", static_cast<int>(guessed));
|
||||
// now we need to access the second terminal, so we could simply send a SWAP command
|
||||
// (switching to data mode does the swapping internally, so we only swap if we're in CMD mode)
|
||||
if (guessed == modem_mode::DATA_MODE) {
|
||||
// switch to DATA on the primary terminal and swap terminals
|
||||
if (!set_unsafe(dte, device, netif, esp_modem::modem_mode::RESUME_CMUX_MANUAL_DATA)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// swap terminals
|
||||
if (!set_unsafe(dte, device, netif, esp_modem::modem_mode::CMUX_MANUAL_SWAP)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
guessed = guess_unsafe(dte, false);
|
||||
ESP_LOGD("DCE mode", "Detected mode on secondary term: %d", static_cast<int>(guessed));
|
||||
if (guessed == modem_mode::DATA_MODE) {
|
||||
if (!set_unsafe(dte, device, netif, esp_modem::modem_mode::RESUME_CMUX_MANUAL_DATA)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case modem_mode::COMMAND_MODE:
|
||||
if (mode == modem_mode::COMMAND_MODE || mode >= modem_mode::CMUX_MANUAL_MODE) {
|
||||
return false;
|
||||
@ -122,6 +172,32 @@ bool DCE_Mode::set_unsafe(DTE *dte, ModuleIf *device, Netif &netif, modem_mode m
|
||||
}
|
||||
mode = m;
|
||||
return true;
|
||||
case modem_mode::RESUME_DATA_MODE:
|
||||
if (!dte->set_mode(modem_mode::DATA_MODE)) {
|
||||
return false;
|
||||
}
|
||||
netif.start();
|
||||
mode = modem_mode::DATA_MODE;
|
||||
return true;
|
||||
case modem_mode::RESUME_COMMAND_MODE:
|
||||
if (!dte->set_mode(modem_mode::COMMAND_MODE)) {
|
||||
return false;
|
||||
}
|
||||
mode = modem_mode::COMMAND_MODE;
|
||||
return true;
|
||||
case modem_mode::RESUME_CMUX_MANUAL_MODE:
|
||||
if (!dte->set_mode(modem_mode::CMUX_MANUAL_MODE)) {
|
||||
return false;
|
||||
}
|
||||
mode = modem_mode::CMUX_MANUAL_MODE;
|
||||
return true;
|
||||
case modem_mode::RESUME_CMUX_MANUAL_DATA:
|
||||
if (!dte->set_mode(modem_mode::CMUX_MANUAL_SWAP)) {
|
||||
return false;
|
||||
}
|
||||
netif.start();
|
||||
mode = modem_mode::CMUX_MANUAL_MODE;
|
||||
return true;
|
||||
case modem_mode::DATA_MODE:
|
||||
if (mode == modem_mode::DATA_MODE || mode == modem_mode::CMUX_MODE || mode >= modem_mode::CMUX_MANUAL_MODE) {
|
||||
return false;
|
||||
@ -191,4 +267,121 @@ modem_mode DCE_Mode::get()
|
||||
return mode;
|
||||
}
|
||||
|
||||
modem_mode DCE_Mode::guess(DTE *dte, bool with_cmux)
|
||||
{
|
||||
Scoped<DTE> lock(*dte);
|
||||
return guess_unsafe(dte, with_cmux);
|
||||
}
|
||||
|
||||
/**
|
||||
* This namespace contains probe packets and expected replies on 3 different protocols,
|
||||
* the modem device could use (as well as timeouts and mode ids for synchronisation)
|
||||
*/
|
||||
namespace probe {
|
||||
|
||||
namespace ppp {
|
||||
// Test that we're in the PPP mode by sending an LCP protocol echo request and expecting LCP echo reply
|
||||
constexpr std::array<uint8_t, 16> lcp_echo_request = {0x7e, 0xff, 0x03, 0xc0, 0x21, 0x09, 0x01, 0x00, 0x08, 0x99, 0xd1, 0x35, 0xc1, 0x8e, 0x2c, 0x7e };
|
||||
constexpr std::array<uint8_t, 5> lcp_echo_reply_head = {0x7e, 0xff, 0x7d, 0x23, 0xc0};
|
||||
const size_t mode = 1 << 0;
|
||||
const int timeout = 200;
|
||||
}
|
||||
|
||||
namespace cmd {
|
||||
// For command mode, we just send a simple AT command
|
||||
const char at[] = "\r\nAT\r\n";
|
||||
const size_t max_at_reply = 16; // account for some whitespaces and/or CMUX encapsulation
|
||||
const char reply[] = { 'O', 'K' };
|
||||
const int mode = 1 << 1;
|
||||
const int timeout = 500;
|
||||
}
|
||||
|
||||
namespace cmux {
|
||||
// For CMUX mode, we send an SABM on control terminal (0)
|
||||
const uint8_t sabm0_reqest[] = {0xf9, 0x03, 0x3f, 0x01, 0x1c, 0xf9};
|
||||
const uint8_t sabm0_reply[] = {0xf9, 0x03, 0x73, 0x01};
|
||||
const int mode = 1 << 0;
|
||||
const int timeout = 200;
|
||||
}
|
||||
};
|
||||
|
||||
modem_mode DCE_Mode::guess_unsafe(DTE *dte, bool with_cmux)
|
||||
{
|
||||
// placeholder for reply and its size, since it could come in pieces, and we have to cache
|
||||
// this is captured by the lambda by reference.
|
||||
// must make sure the lambda is cleared before exiting this function (done by dte->on_read(nullptr))
|
||||
uint8_t reply[std::max(probe::cmd::max_at_reply, std::max(sizeof(probe::ppp::lcp_echo_request), sizeof(probe::cmux::sabm0_reply)))];
|
||||
size_t reply_pos = 0;
|
||||
auto signal = std::make_shared<SignalGroup>();
|
||||
std::weak_ptr<SignalGroup> weak_signal = signal;
|
||||
dte->on_read([weak_signal, with_cmux, &reply, &reply_pos](uint8_t *data, size_t len) {
|
||||
// storing the response in the `reply` array and de-fragmenting
|
||||
if (reply_pos >= sizeof(reply)) {
|
||||
return command_result::TIMEOUT;
|
||||
}
|
||||
auto reply_size = std::min((size_t)sizeof(reply) - reply_pos, len);
|
||||
::memcpy(reply + reply_pos, data, reply_size);
|
||||
reply_pos += reply_size;
|
||||
ESP_LOG_BUFFER_HEXDUMP("esp-modem: guess mode data:", reply, reply_pos, ESP_LOG_DEBUG);
|
||||
|
||||
// Check whether the response resembles the "golden" reply (for these 3 protocols)
|
||||
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:
|
||||
// * 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
|
||||
if (auto signal = weak_signal.lock()) {
|
||||
signal->set(probe::cmd::mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (with_cmux && reply_pos >= sizeof(probe::cmux::sabm0_reply)) {
|
||||
// checking the initial 3 bytes
|
||||
auto *ptr = static_cast<uint8_t *>(memmem(reply, reply_pos, probe::cmux::sabm0_reply, 3));
|
||||
// and checking that DLCI is 0 (control frame)
|
||||
if (ptr && (ptr[3] >> 2) == 0) {
|
||||
if (auto signal = weak_signal.lock()) {
|
||||
signal->set(probe::cmux::mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
return command_result::TIMEOUT;
|
||||
});
|
||||
auto guessed = modem_mode::UNDEF;
|
||||
// Check the PPP mode fist by sending LCP echo request
|
||||
dte->send((uint8_t *)probe::ppp::lcp_echo_request.data(), sizeof(probe::ppp::lcp_echo_request), 0);
|
||||
if (signal->wait(probe::ppp::mode, probe::ppp::timeout)) {
|
||||
guessed = modem_mode::DATA_MODE;
|
||||
} else { // LCP echo timeout
|
||||
// now check for AT mode
|
||||
reply_pos = 0;
|
||||
dte->send((uint8_t *)probe::cmd::at, sizeof(probe::cmd::at), 0);
|
||||
if (signal->wait(probe::cmd::mode, probe::cmd::timeout)) {
|
||||
guessed = modem_mode::COMMAND_MODE;
|
||||
} else if (with_cmux) { // no AT reply, check for CMUX mode (if requested)
|
||||
reply_pos = 0;
|
||||
dte->send((uint8_t *) probe::cmux::sabm0_reqest, sizeof(probe::cmux::sabm0_reqest), 0);
|
||||
if (signal->wait(probe::cmux::mode, probe::cmux::timeout)) {
|
||||
guessed = modem_mode::CMUX_MODE;
|
||||
}
|
||||
}
|
||||
}
|
||||
dte->on_read(nullptr);
|
||||
return guessed;
|
||||
}
|
||||
|
||||
} // esp_modem
|
||||
|
@ -223,13 +223,13 @@ bool DTE::set_mode(modem_mode m)
|
||||
}
|
||||
}
|
||||
// transitions (COMMAND|DUAL|CMUX|UNDEF) -> DATA
|
||||
if (m == modem_mode::DATA_MODE) {
|
||||
if (m == modem_mode::DATA_MODE || m == modem_mode::RESUME_DATA_MODE) {
|
||||
if (mode == modem_mode::CMUX_MODE || mode == modem_mode::CMUX_MANUAL_MODE || mode == modem_mode::DUAL_MODE) {
|
||||
// mode stays the same, but need to swap terminals (as command has been switched)
|
||||
secondary_term.swap(primary_term);
|
||||
set_command_callbacks();
|
||||
} else {
|
||||
mode = m;
|
||||
mode = modem_mode::DATA_MODE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -316,6 +316,12 @@ int DTE::write(uint8_t *data, size_t len)
|
||||
return secondary_term->write(data, len);
|
||||
}
|
||||
|
||||
int DTE::send(uint8_t *data, size_t len, int term_id)
|
||||
{
|
||||
Terminal *term = term_id == 0 ? primary_term.get() : secondary_term.get();
|
||||
return term->write(data, len);
|
||||
}
|
||||
|
||||
int DTE::write(DTE_Command command)
|
||||
{
|
||||
return primary_term->write(command.data, command.len);
|
||||
|
@ -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
|
||||
*/
|
||||
@ -87,8 +87,10 @@ void Netif::start()
|
||||
receive(data, len);
|
||||
return true;
|
||||
});
|
||||
signal.set(PPP_STARTED);
|
||||
esp_netif_action_start(driver.base.netif, nullptr, 0, nullptr);
|
||||
if (!signal.is_any(PPP_STARTED)) {
|
||||
signal.set(PPP_STARTED);
|
||||
esp_netif_action_start(driver.base.netif, nullptr, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void Netif::stop()
|
||||
@ -97,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
|
||||
|
@ -3,6 +3,6 @@ commitizen:
|
||||
bump_message: 'bump(websocket): $current_version -> $new_version'
|
||||
pre_bump_hooks: python ../../ci/changelog.py esp_websocket_client
|
||||
tag_format: websocket-v$version
|
||||
version: 1.2.3
|
||||
version: 1.4.0
|
||||
version_files:
|
||||
- idf_component.yml
|
||||
|
@ -1,5 +1,45 @@
|
||||
# Changelog
|
||||
|
||||
## [1.4.0](https://github.com/espressif/esp-protocols/commits/websocket-v1.4.0)
|
||||
|
||||
### Features
|
||||
|
||||
- Support DS peripheral for mutual TLS ([55385ec3](https://github.com/espressif/esp-protocols/commit/55385ec3))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- wait for task on destroy ([42674b49](https://github.com/espressif/esp-protocols/commit/42674b49))
|
||||
- Fix pytest to verify client correctly ([9046af8f](https://github.com/espressif/esp-protocols/commit/9046af8f))
|
||||
- propagate error type ([eeeb9006](https://github.com/espressif/esp-protocols/commit/eeeb9006))
|
||||
- fix example buffer leak ([5219c39d](https://github.com/espressif/esp-protocols/commit/5219c39d))
|
||||
|
||||
### Updated
|
||||
|
||||
- chore(websocket): align structure members ([beb6e57e](https://github.com/espressif/esp-protocols/commit/beb6e57e))
|
||||
- chore(websocket): remove unused client variable ([15d3a01e](https://github.com/espressif/esp-protocols/commit/15d3a01e))
|
||||
|
||||
## [1.3.0](https://github.com/espressif/esp-protocols/commits/websocket-v1.3.0)
|
||||
|
||||
### Features
|
||||
|
||||
- add events for begin/end thread ([d7fa24bc](https://github.com/espressif/esp-protocols/commit/d7fa24bc))
|
||||
- Make example to use certificate bundle ([aecf6f80](https://github.com/espressif/esp-protocols/commit/aecf6f80))
|
||||
- propagate esp_tls stack error and cert verify flags ([234f579b](https://github.com/espressif/esp-protocols/commit/234f579b))
|
||||
- Add option to set and use cert_common_name in Websocket client ([3a6720de](https://github.com/espressif/esp-protocols/commit/3a6720de))
|
||||
- adding support for `if_name` when using WSS transport ([333a6893](https://github.com/espressif/esp-protocols/commit/333a6893))
|
||||
- allow updating reconnect timeout for retry backoffs ([bd9f0627](https://github.com/espressif/esp-protocols/commit/bd9f0627))
|
||||
- allow using external tcp transport handle ([83ea2876](https://github.com/espressif/esp-protocols/commit/83ea2876))
|
||||
- adding support for `keep_alive_enable` when using WSS transport ([c728eae5](https://github.com/espressif/esp-protocols/commit/c728eae5))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Prevent crash on network disconnect during send ([a453ca1f](https://github.com/espressif/esp-protocols/commit/a453ca1f))
|
||||
- use proper interface to delete semaphore ([991ac40d](https://github.com/espressif/esp-protocols/commit/991ac40d))
|
||||
- Move client to different state when disconnecting ([0d8f2a6d](https://github.com/espressif/esp-protocols/commit/0d8f2a6d))
|
||||
- fix of websocket host example ([5ccc018a](https://github.com/espressif/esp-protocols/commit/5ccc018a))
|
||||
- don't get transport from the list if external transport is used ([9d4d5d2d](https://github.com/espressif/esp-protocols/commit/9d4d5d2d))
|
||||
- Fix locking issues of `esp_websocket_client_send_with_exact_opcode` API ([6393fcd7](https://github.com/espressif/esp-protocols/commit/6393fcd7))
|
||||
|
||||
## [1.2.3](https://github.com/espressif/esp-protocols/commits/websocket-v1.2.3)
|
||||
|
||||
### Features
|
||||
|
@ -93,10 +93,13 @@ typedef struct {
|
||||
size_t client_cert_len;
|
||||
const char *client_key;
|
||||
size_t client_key_len;
|
||||
#if CONFIG_ESP_TLS_USE_DS_PERIPHERAL
|
||||
void *client_ds_data;
|
||||
#endif
|
||||
bool use_global_ca_store;
|
||||
bool skip_cert_common_name_check;
|
||||
const char *cert_common_name;
|
||||
esp_err_t (*crt_bundle_attach)(void *conf);
|
||||
esp_err_t (*crt_bundle_attach)(void *conf);
|
||||
esp_transport_handle_t ext_transport;
|
||||
} websocket_config_storage_t;
|
||||
|
||||
@ -122,12 +125,11 @@ struct esp_websocket_client {
|
||||
uint64_t ping_tick_ms;
|
||||
uint64_t pingpong_tick_ms;
|
||||
int wait_timeout_ms;
|
||||
int auto_reconnect;
|
||||
bool run;
|
||||
bool wait_for_pong_resp;
|
||||
bool selected_for_destroying;
|
||||
EventGroupHandle_t status_bits;
|
||||
SemaphoreHandle_t lock;
|
||||
SemaphoreHandle_t lock;
|
||||
size_t errormsg_size;
|
||||
char *errormsg_buffer;
|
||||
char *rx_buffer;
|
||||
@ -186,9 +188,9 @@ static void esp_websocket_free_buf(esp_websocket_client_handle_t client, bool is
|
||||
}
|
||||
|
||||
static esp_err_t esp_websocket_client_dispatch_event(esp_websocket_client_handle_t client,
|
||||
esp_websocket_event_id_t event,
|
||||
const char *data,
|
||||
int data_len)
|
||||
esp_websocket_event_id_t event,
|
||||
const char *data,
|
||||
int data_len)
|
||||
{
|
||||
esp_err_t err;
|
||||
esp_websocket_event_data_t event_data;
|
||||
@ -204,8 +206,8 @@ static esp_err_t esp_websocket_client_dispatch_event(esp_websocket_client_handle
|
||||
|
||||
if (client->error_handle.error_type == WEBSOCKET_ERROR_TYPE_TCP_TRANSPORT) {
|
||||
event_data.error_handle.esp_tls_last_esp_err = esp_tls_get_and_clear_last_error(esp_transport_get_error_handle(client->transport),
|
||||
&client->error_handle.esp_tls_stack_err,
|
||||
&client->error_handle.esp_tls_cert_verify_flags);
|
||||
&client->error_handle.esp_tls_stack_err,
|
||||
&client->error_handle.esp_tls_cert_verify_flags);
|
||||
event_data.error_handle.esp_tls_stack_err = client->error_handle.esp_tls_stack_err;
|
||||
event_data.error_handle.esp_tls_cert_verify_flags = client->error_handle.esp_tls_cert_verify_flags;
|
||||
event_data.error_handle.esp_transport_sock_errno = esp_transport_get_errno(client->transport);
|
||||
@ -229,18 +231,20 @@ static esp_err_t esp_websocket_client_abort_connection(esp_websocket_client_hand
|
||||
ESP_WS_CLIENT_STATE_CHECK(TAG, client, return ESP_FAIL);
|
||||
esp_transport_close(client->transport);
|
||||
|
||||
if (client->config->auto_reconnect) {
|
||||
if (!client->config->auto_reconnect) {
|
||||
client->run = false;
|
||||
client->state = WEBSOCKET_STATE_UNKNOW;
|
||||
} else {
|
||||
client->reconnect_tick_ms = _tick_get_ms();
|
||||
ESP_LOGI(TAG, "Reconnect after %d ms", client->wait_timeout_ms);
|
||||
client->state = WEBSOCKET_STATE_WAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
client->error_handle.error_type = error_type;
|
||||
client->state = WEBSOCKET_STATE_WAIT_TIMEOUT;
|
||||
esp_websocket_client_dispatch_event(client, WEBSOCKET_EVENT_DISCONNECTED, NULL, 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_websocket_client_error(esp_websocket_client_handle_t client, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
|
||||
static esp_err_t esp_websocket_client_error(esp_websocket_client_handle_t client, const char *format, ...) __attribute__((format(printf, 2, 3)));
|
||||
static esp_err_t esp_websocket_client_error(esp_websocket_client_handle_t client, const char *format, ...)
|
||||
{
|
||||
va_list myargs;
|
||||
@ -434,7 +438,7 @@ static void destroy_and_free_resources(esp_websocket_client_handle_t client)
|
||||
if (client->transport_list) {
|
||||
esp_transport_list_destroy(client->transport_list);
|
||||
}
|
||||
vQueueDelete(client->lock);
|
||||
vSemaphoreDelete(client->lock);
|
||||
free(client->tx_buffer);
|
||||
free(client->rx_buffer);
|
||||
free(client->errormsg_buffer);
|
||||
@ -445,6 +449,21 @@ static void destroy_and_free_resources(esp_websocket_client_handle_t client)
|
||||
client = NULL;
|
||||
}
|
||||
|
||||
static esp_err_t stop_wait_task(esp_websocket_client_handle_t client)
|
||||
{
|
||||
/* A running client cannot be stopped from the websocket task/event handler */
|
||||
TaskHandle_t running_task = xTaskGetCurrentTaskHandle();
|
||||
if (running_task == client->task_handle) {
|
||||
ESP_LOGE(TAG, "Client cannot be stopped from websocket task");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
client->run = false;
|
||||
xEventGroupWaitBits(client->status_bits, STOPPED_BIT, false, true, portMAX_DELAY);
|
||||
client->state = WEBSOCKET_STATE_UNKNOW;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t set_websocket_transport_optional_settings(esp_websocket_client_handle_t client, const char *scheme)
|
||||
{
|
||||
esp_transport_handle_t trans = esp_transport_list_get_transport(client->transport_list, scheme);
|
||||
@ -530,6 +549,10 @@ static esp_err_t esp_websocket_client_create_transport(esp_websocket_client_hand
|
||||
} else {
|
||||
esp_transport_ssl_set_client_key_data_der(ssl, client->config->client_key, client->config->client_key_len);
|
||||
}
|
||||
#if CONFIG_ESP_TLS_USE_DS_PERIPHERAL
|
||||
} else if (client->config->client_ds_data) {
|
||||
esp_transport_ssl_set_ds_data(ssl, client->config->client_ds_data);
|
||||
#endif
|
||||
}
|
||||
if (client->config->crt_bundle_attach) {
|
||||
#ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
|
||||
@ -652,7 +675,7 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie
|
||||
client->keep_alive_cfg.keep_alive_enable = true;
|
||||
client->keep_alive_cfg.keep_alive_idle = (config->keep_alive_idle == 0) ? WEBSOCKET_KEEP_ALIVE_IDLE : config->keep_alive_idle;
|
||||
client->keep_alive_cfg.keep_alive_interval = (config->keep_alive_interval == 0) ? WEBSOCKET_KEEP_ALIVE_INTERVAL : config->keep_alive_interval;
|
||||
client->keep_alive_cfg.keep_alive_count = (config->keep_alive_count == 0) ? WEBSOCKET_KEEP_ALIVE_COUNT : config->keep_alive_count;
|
||||
client->keep_alive_cfg.keep_alive_count = (config->keep_alive_count == 0) ? WEBSOCKET_KEEP_ALIVE_COUNT : config->keep_alive_count;
|
||||
}
|
||||
|
||||
if (config->if_name) {
|
||||
@ -695,6 +718,9 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie
|
||||
client->config->client_cert_len = config->client_cert_len;
|
||||
client->config->client_key = config->client_key;
|
||||
client->config->client_key_len = config->client_key_len;
|
||||
#if CONFIG_ESP_TLS_USE_DS_PERIPHERAL
|
||||
client->config->client_ds_data = config->client_ds_data;
|
||||
#endif
|
||||
client->config->skip_cert_common_name_check = config->skip_cert_common_name_check;
|
||||
client->config->cert_common_name = config->cert_common_name;
|
||||
client->config->crt_bundle_attach = config->crt_bundle_attach;
|
||||
@ -743,6 +769,7 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie
|
||||
ESP_WS_CLIENT_MEM_CHECK(TAG, client->status_bits, {
|
||||
goto _websocket_init_fail;
|
||||
});
|
||||
xEventGroupSetBits(client->status_bits, STOPPED_BIT);
|
||||
|
||||
client->buffer_size = buffer_size;
|
||||
return client;
|
||||
@ -757,9 +784,11 @@ esp_err_t esp_websocket_client_destroy(esp_websocket_client_handle_t client)
|
||||
if (client == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (client->run) {
|
||||
esp_websocket_client_stop(client);
|
||||
|
||||
if (client->status_bits && (STOPPED_BIT & xEventGroupGetBits(client->status_bits)) == 0) {
|
||||
stop_wait_task(client);
|
||||
}
|
||||
|
||||
destroy_and_free_resources(client);
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -921,7 +950,7 @@ static esp_err_t esp_websocket_client_recv(esp_websocket_client_handle_t client)
|
||||
client->last_fin = esp_transport_ws_get_fin_flag(client->transport);
|
||||
client->last_opcode = esp_transport_ws_get_read_opcode(client->transport);
|
||||
|
||||
if (rlen == 0 && client->last_opcode == WS_TRANSPORT_OPCODES_NONE ) {
|
||||
if (rlen == 0 && client->last_opcode == WS_TRANSPORT_OPCODES_NONE) {
|
||||
ESP_LOGV(TAG, "esp_transport_read timeouts");
|
||||
esp_websocket_free_buf(client, false);
|
||||
return ESP_OK;
|
||||
@ -1027,7 +1056,7 @@ static void esp_websocket_client_task(void *pv)
|
||||
}
|
||||
}
|
||||
|
||||
if ( _tick_get_ms() - client->pingpong_tick_ms > client->config->pingpong_timeout_sec * 1000 ) {
|
||||
if (_tick_get_ms() - client->pingpong_tick_ms > client->config->pingpong_timeout_sec * 1000) {
|
||||
if (client->wait_for_pong_resp) {
|
||||
esp_websocket_client_error(client, "Error, no PONG received for more than %d seconds after PING", client->config->pingpong_timeout_sec);
|
||||
esp_websocket_client_abort_connection(client, WEBSOCKET_ERROR_TYPE_PONG_TIMEOUT);
|
||||
@ -1051,10 +1080,6 @@ static void esp_websocket_client_task(void *pv)
|
||||
break;
|
||||
case WEBSOCKET_STATE_WAIT_TIMEOUT:
|
||||
|
||||
if (!client->config->auto_reconnect) {
|
||||
client->run = false;
|
||||
break;
|
||||
}
|
||||
if (_tick_get_ms() - client->reconnect_tick_ms > client->wait_timeout_ms) {
|
||||
client->state = WEBSOCKET_STATE_INIT;
|
||||
client->reconnect_tick_ms = _tick_get_ms();
|
||||
@ -1085,7 +1110,9 @@ static void esp_websocket_client_task(void *pv)
|
||||
} else {
|
||||
esp_websocket_client_error(client, "esp_transport_poll_read() returned %d, errno=%d", read_select, errno);
|
||||
}
|
||||
xSemaphoreTakeRecursive(client->lock, lock_timeout);
|
||||
esp_websocket_client_abort_connection(client, WEBSOCKET_ERROR_TYPE_TCP_TRANSPORT);
|
||||
xSemaphoreGiveRecursive(client->lock);
|
||||
}
|
||||
} else if (WEBSOCKET_STATE_WAIT_TIMEOUT == client->state) {
|
||||
// waiting for reconnecting...
|
||||
@ -1150,23 +1177,13 @@ esp_err_t esp_websocket_client_stop(esp_websocket_client_handle_t client)
|
||||
if (client == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (!client->run) {
|
||||
|
||||
if (xEventGroupGetBits(client->status_bits) & STOPPED_BIT) {
|
||||
ESP_LOGW(TAG, "Client was not started");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* A running client cannot be stopped from the websocket task/event handler */
|
||||
TaskHandle_t running_task = xTaskGetCurrentTaskHandle();
|
||||
if (running_task == client->task_handle) {
|
||||
ESP_LOGE(TAG, "Client cannot be stopped from websocket task");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
|
||||
client->run = false;
|
||||
xEventGroupWaitBits(client->status_bits, STOPPED_BIT, false, true, portMAX_DELAY);
|
||||
client->state = WEBSOCKET_STATE_UNKNOW;
|
||||
return ESP_OK;
|
||||
return stop_wait_task(client);
|
||||
}
|
||||
|
||||
static int esp_websocket_client_send_close(esp_websocket_client_handle_t client, int code, const char *additional_data, int total_len, TickType_t timeout)
|
||||
@ -1356,3 +1373,13 @@ esp_err_t esp_websocket_register_events(esp_websocket_client_handle_t client,
|
||||
}
|
||||
return esp_event_handler_register_with(client->event_handle, WEBSOCKET_EVENTS, event, event_handler, event_handler_arg);
|
||||
}
|
||||
|
||||
esp_err_t esp_websocket_unregister_events(esp_websocket_client_handle_t client,
|
||||
esp_websocket_event_id_t event,
|
||||
esp_event_handler_t event_handler)
|
||||
{
|
||||
if (client == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return esp_event_handler_unregister_with(client->event_handle, WEBSOCKET_EVENTS, event, event_handler);
|
||||
}
|
||||
|
@ -222,10 +222,12 @@ static void websocket_app_start(void)
|
||||
char *long_data = malloc(size);
|
||||
memset(long_data, 'a', size);
|
||||
esp_websocket_client_send_text(client, long_data, size, portMAX_DELAY);
|
||||
free(long_data);
|
||||
|
||||
xSemaphoreTake(shutdown_sema, portMAX_DELAY);
|
||||
esp_websocket_client_close(client, portMAX_DELAY);
|
||||
ESP_LOGI(TAG, "Websocket Stopped");
|
||||
esp_websocket_unregister_events(client, WEBSOCKET_EVENT_ANY, websocket_event_handler);
|
||||
esp_websocket_client_destroy(client);
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ class Websocket(object):
|
||||
ssl_context.load_cert_chain(certfile='main/certs/server/server_cert.pem', keyfile='main/certs/server/server_key.pem')
|
||||
if self.client_verify is True:
|
||||
ssl_context.load_verify_locations(cafile='main/certs/ca_cert.pem')
|
||||
ssl_context.verify = ssl.CERT_REQUIRED
|
||||
ssl_context.verify_mode = ssl.CERT_REQUIRED
|
||||
ssl_context.check_hostname = False
|
||||
self.server = SimpleSSLWebSocketServer('', self.port, WebsocketTestEcho, ssl_context=ssl_context)
|
||||
else:
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: "1.2.3"
|
||||
version: "1.4.0"
|
||||
description: WebSocket protocol client for ESP-IDF
|
||||
url: https://github.com/espressif/esp-protocols/tree/master/components/esp_websocket_client
|
||||
dependencies:
|
||||
|
@ -108,10 +108,13 @@ typedef struct {
|
||||
int buffer_size; /*!< Websocket buffer size */
|
||||
const char *cert_pem; /*!< Pointer to certificate data in PEM or DER format for server verify (with SSL), default is NULL, not required to verify the server. PEM-format must have a terminating NULL-character. DER-format requires the length to be passed in cert_len. */
|
||||
size_t cert_len; /*!< Length of the buffer pointed to by cert_pem. May be 0 for null-terminated pem */
|
||||
const char *client_cert; /*!< Pointer to certificate data in PEM or DER format for SSL mutual authentication, default is NULL, not required if mutual authentication is not needed. If it is not NULL, also `client_key` has to be provided. PEM-format must have a terminating NULL-character. DER-format requires the length to be passed in client_cert_len. */
|
||||
const char *client_cert; /*!< Pointer to certificate data in PEM or DER format for SSL mutual authentication, default is NULL, not required if mutual authentication is not needed. If it is not NULL, also `client_key` or `client_ds_data` (if supported) has to be provided. PEM-format must have a terminating NULL-character. DER-format requires the length to be passed in client_cert_len. */
|
||||
size_t client_cert_len; /*!< Length of the buffer pointed to by client_cert. May be 0 for null-terminated pem */
|
||||
const char *client_key; /*!< Pointer to private key data in PEM or DER format for SSL mutual authentication, default is NULL, not required if mutual authentication is not needed. If it is not NULL, also `client_cert` has to be provided. PEM-format must have a terminating NULL-character. DER-format requires the length to be passed in client_key_len */
|
||||
const char *client_key; /*!< Pointer to private key data in PEM or DER format for SSL mutual authentication, default is NULL, not required if mutual authentication is not needed. If it is not NULL, also `client_cert` has to be provided and `client_ds_data` (if supported) gets ignored. PEM-format must have a terminating NULL-character. DER-format requires the length to be passed in client_key_len */
|
||||
size_t client_key_len; /*!< Length of the buffer pointed to by client_key_pem. May be 0 for null-terminated pem */
|
||||
#if CONFIG_ESP_TLS_USE_DS_PERIPHERAL
|
||||
void *client_ds_data; /*!< Pointer to the encrypted private key data for SSL mutual authentication using the DS peripheral, default is NULL, not required if mutual authentication is not needed. If it is not NULL, also `client_cert` has to be provided. It is ignored if `client_key` is provided */
|
||||
#endif
|
||||
esp_websocket_transport_t transport; /*!< Websocket transport type, see `esp_websocket_transport_t */
|
||||
const char *subprotocol; /*!< Websocket subprotocol */
|
||||
const char *user_agent; /*!< Websocket user-agent */
|
||||
@ -457,6 +460,18 @@ esp_err_t esp_websocket_register_events(esp_websocket_client_handle_t client,
|
||||
esp_event_handler_t event_handler,
|
||||
void *event_handler_arg);
|
||||
|
||||
/**
|
||||
* @brief Unegister the Websocket Events
|
||||
*
|
||||
* @param client The client handle
|
||||
* @param event The event id
|
||||
* @param event_handler The callback function
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t esp_websocket_unregister_events(esp_websocket_client_handle_t client,
|
||||
esp_websocket_event_id_t event,
|
||||
esp_event_handler_t event_handler);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,8 +0,0 @@
|
||||
---
|
||||
commitizen:
|
||||
bump_message: 'bump(wifi_remote): $current_version -> $new_version'
|
||||
pre_bump_hooks: python ../../ci/changelog.py esp_wifi_remote
|
||||
tag_format: wifi_remote-v$version
|
||||
version: 0.4.0
|
||||
version_files:
|
||||
- idf_component.yml
|
@ -1,66 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
## [0.4.0](https://github.com/espressif/esp-protocols/commits/wifi_remote-v0.4.0)
|
||||
|
||||
### Features
|
||||
|
||||
- Make esp_hosted default RPC library ([1b62adbd](https://github.com/espressif/esp-protocols/commit/1b62adbd))
|
||||
- Add build test for current IDF examples ([50c113e4](https://github.com/espressif/esp-protocols/commit/50c113e4))
|
||||
- Support for IDF v5.3 in a separate directory ([bde97203](https://github.com/espressif/esp-protocols/commit/bde97203))
|
||||
- Support for IDF v5.4 via a separate dir ([e9ac41e1](https://github.com/espressif/esp-protocols/commit/e9ac41e1))
|
||||
- Add slave selection and peview targets ([345c4577](https://github.com/espressif/esp-protocols/commit/345c4577))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix CMake to use inherent IDF build vars ([c454ec09](https://github.com/espressif/esp-protocols/commit/c454ec09))
|
||||
- Update per v5.4 espressif/esp-idf@97e42349 ([ff5dac70](https://github.com/espressif/esp-protocols/commit/ff5dac70))
|
||||
- Fix CI builds to generate configs per slave selection ([8795d164](https://github.com/espressif/esp-protocols/commit/8795d164))
|
||||
- Depend on esp_hosted only on targets with no WiFi ([7ca5ed1d](https://github.com/espressif/esp-protocols/commit/7ca5ed1d))
|
||||
- Update per espressif/esp-idf@27f61966 ([2e53b81f](https://github.com/espressif/esp-protocols/commit/2e53b81f))
|
||||
- Fix checking API compat against reference dir ([1a57a878](https://github.com/espressif/esp-protocols/commit/1a57a878))
|
||||
|
||||
## [0.3.0](https://github.com/espressif/esp-protocols/commits/wifi_remote-v0.3.0)
|
||||
|
||||
### Features
|
||||
|
||||
- add esp_wifi_internal_tx_by_ref ([ba35d14e](https://github.com/espressif/esp-protocols/commit/ba35d14e))
|
||||
- Make wifi_remote depend on esp_hosted ([ac9972aa](https://github.com/espressif/esp-protocols/commit/ac9972aa))
|
||||
|
||||
## [0.2.3](https://github.com/espressif/esp-protocols/commits/wifi_remote-v0.2.3)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix server event/command race condtion using eventfd ([732b1d5](https://github.com/espressif/esp-protocols/commit/732b1d5))
|
||||
- Lock server before marshalling events ([9e13870](https://github.com/espressif/esp-protocols/commit/9e13870))
|
||||
|
||||
## [0.2.2](https://github.com/espressif/esp-protocols/commits/wifi_remote-v0.2.2)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Added more netif options for eppp connection ([24ce867](https://github.com/espressif/esp-protocols/commit/24ce867))
|
||||
- Do not restrict EPPP config to RSA keys only ([f05c765](https://github.com/espressif/esp-protocols/commit/f05c765), [#570](https://github.com/espressif/esp-protocols/issues/570))
|
||||
|
||||
## [0.2.1](https://github.com/espressif/esp-protocols/commits/wifi_remote-v0.2.1)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Added misc wifi API in eppp impl ([93256d1](https://github.com/espressif/esp-protocols/commit/93256d1))
|
||||
- Updated eppp dependency not to use fixed version ([3a48c06](https://github.com/espressif/esp-protocols/commit/3a48c06))
|
||||
|
||||
## [0.2.0](https://github.com/espressif/esp-protocols/commits/wifi_remote-v0.2.0)
|
||||
|
||||
### Features
|
||||
|
||||
- Add support for simple eppp based RPC ([fd168d8](https://github.com/espressif/esp-protocols/commit/fd168d8))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Make services restartable, code cleanup ([6c82ce2](https://github.com/espressif/esp-protocols/commit/6c82ce2))
|
||||
- Add examples to CI ([d2b7c55](https://github.com/espressif/esp-protocols/commit/d2b7c55))
|
||||
|
||||
## [0.1.12](https://github.com/espressif/esp-protocols/commits/wifi_remote-v0.1.12)
|
||||
|
||||
### Features
|
||||
|
||||
- Added generation step for wifi_remote based on IDF ([dfb00358](https://github.com/espressif/esp-protocols/commit/dfb00358))
|
||||
- Move to esp-protocols ([edc3c2d](https://github.com/espressif/esp-protocols/commit/edc3c2d))
|
@ -1,22 +0,0 @@
|
||||
set(IDF_VER_DIR "idf_v${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}")
|
||||
|
||||
if(NOT CONFIG_ESP_WIFI_ENABLED)
|
||||
set(src_wifi_is_remote esp_wifi_remote.c ${IDF_VER_DIR}/esp_wifi_with_remote.c esp_wifi_remote_net.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_ESP_WIFI_REMOTE_LIBRARY_EPPP)
|
||||
set(src_wifi_remote_eppp eppp/wifi_remote_rpc_client.cpp eppp/wifi_remote_rpc_server.cpp eppp/eppp_init.c)
|
||||
else()
|
||||
set(src_wifi_remote_weak ${IDF_VER_DIR}/esp_wifi_remote_weak.c)
|
||||
endif()
|
||||
|
||||
idf_component_register(INCLUDE_DIRS include ${IDF_VER_DIR}/include
|
||||
SRCS ${src_wifi_remote_weak}
|
||||
${src_wifi_remote_eppp}
|
||||
${src_wifi_is_remote}
|
||||
PRIV_INCLUDE_DIRS eppp
|
||||
REQUIRES esp_event esp_netif
|
||||
PRIV_REQUIRES esp_wifi esp-tls vfs)
|
||||
|
||||
idf_component_get_property(wifi esp_wifi COMPONENT_LIB)
|
||||
target_link_libraries(${wifi} PUBLIC ${COMPONENT_LIB})
|
@ -1,14 +0,0 @@
|
||||
menu "Wi-Fi Remote"
|
||||
config ESP_WIFI_REMOTE_ENABLED
|
||||
bool
|
||||
default y
|
||||
|
||||
orsource "./idf_v$ESP_IDF_VERSION/Kconfig.slave_select.in"
|
||||
orsource "./idf_v$ESP_IDF_VERSION/Kconfig.soc_wifi_caps.in"
|
||||
orsource "./Kconfig.rpc.in"
|
||||
|
||||
menu "Wi-Fi configuration"
|
||||
orsource "./idf_v$ESP_IDF_VERSION/Kconfig.wifi.in"
|
||||
endmenu
|
||||
|
||||
endmenu # Wi-Fi Remote
|
@ -1,74 +0,0 @@
|
||||
choice ESP_WIFI_REMOTE_LIBRARY
|
||||
prompt "Choose WiFi-remote implementation"
|
||||
default ESP_WIFI_REMOTE_LIBRARY_HOSTED
|
||||
help
|
||||
Select type of WiFi Remote implementation
|
||||
|
||||
ESP-HOSTED is the default and most versatile option.
|
||||
It's also possible to use EPPP, which uses PPPoS link between micros and NAPT, so it's slower
|
||||
and less universal.
|
||||
|
||||
config ESP_WIFI_REMOTE_LIBRARY_HOSTED
|
||||
bool "ESP-HOSTED"
|
||||
config ESP_WIFI_REMOTE_LIBRARY_EPPP
|
||||
bool "EPPP"
|
||||
endchoice
|
||||
|
||||
if ESP_WIFI_REMOTE_LIBRARY_EPPP
|
||||
|
||||
config ESP_WIFI_REMOTE_EPPP_UART_TX_PIN
|
||||
int "TXD Pin Number"
|
||||
default 10
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART TX.
|
||||
|
||||
config ESP_WIFI_REMOTE_EPPP_UART_RX_PIN
|
||||
int "RXD Pin Number"
|
||||
default 11
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART RX.
|
||||
|
||||
config ESP_WIFI_REMOTE_EPPP_NETIF_PRIORITY
|
||||
int "Routing priority of eppp netif"
|
||||
default 100
|
||||
range 0 256
|
||||
help
|
||||
Set the priority of the wifi-remote netif.
|
||||
The bigger the number the higher the priority.
|
||||
The interface which is up and with the highest priority will act as a default GW.
|
||||
|
||||
config ESP_WIFI_REMOTE_EPPP_NETIF_DESCRIPTION
|
||||
string "eppp network interface description"
|
||||
default "example_netif_sta"
|
||||
help
|
||||
Textual description of the wifi remote network interface.
|
||||
By default it is set to "example_netif_sta" to be used in IDF protocol example
|
||||
as default wifi station substitution.
|
||||
|
||||
config ESP_WIFI_REMOTE_EPPP_SERVER_CA
|
||||
string "Servers CA certificate"
|
||||
default "--- Please copy content of the CA certificate ---"
|
||||
|
||||
config ESP_WIFI_REMOTE_EPPP_CLIENT_CRT
|
||||
string "Client certificate"
|
||||
default "--- Please copy content of the Client certificate ---"
|
||||
|
||||
config ESP_WIFI_REMOTE_EPPP_CLIENT_KEY
|
||||
string "Client key"
|
||||
default "--- Please copy content of the Client key ---"
|
||||
|
||||
config ESP_WIFI_REMOTE_EPPP_CLIENT_CA
|
||||
string "Clients CA certificate"
|
||||
default "--- Please copy content of the CA certificate ---"
|
||||
|
||||
config ESP_WIFI_REMOTE_EPPP_SERVER_CRT
|
||||
string "Server certificate"
|
||||
default "--- Please copy content of the Client certificate ---"
|
||||
|
||||
config ESP_WIFI_REMOTE_EPPP_SERVER_KEY
|
||||
string "Server key"
|
||||
default "--- Please copy content of the Client key ---"
|
||||
|
||||
endif
|
@ -1,26 +0,0 @@
|
||||
# esp_wifi_remote
|
||||
|
||||
[](https://components.espressif.com/components/espressif/esp_wifi_remote)
|
||||
|
||||
The `esp_wifi_remote` component is designed to extend WiFi functionality to ESP chipsets that lack native WiFi support. By simply adding a dependency to this component from your project, you gain access to WiFi capabilities via the WiFi-remote menuconfig and standard `esp_wifi` interface.
|
||||
|
||||
Moreover, `esp_wifi_remote` can be utilized on ESP chipsets that do support native WiFi, providing an additional WiFi interface through the `esp_wifi_remote` API.
|
||||
|
||||
To employ this component, a slave device -- capable of WiFi connectivity -- must be connected to your target device in a specified manner, as defined by the transport layer of [`esp_hosted`](https://github.com/espressif/esp-hosted).
|
||||
|
||||
Functionally, `esp_wifi_remote` wraps the public API of `esp_wifi`, offering a set of function call namespaces prefixed with esp_wifi_remote. These calls are translated into Remote Procedure Calls (RPC) to another target device (referred to as the "slave" device), which then executes the appropriate `esp_wifi` APIs.
|
||||
|
||||
Notably, `esp_wifi_remote` heavily relies on a specific version of the `esp_wifi` component. Consequently, the majority of its headers, sources, and configuration files are pre-generated based on the actual version of `esp_wifi`.
|
||||
|
||||
It's important to highlight that `esp_wifi_remote` does not directly implement the RPC calls; rather, it relies on dependencies for this functionality. Presently, only esp_hosted is supported to provide the RPC functionality required by esp_wifi_remote.
|
||||
|
||||
|
||||
## Dependencies on `esp_wifi`
|
||||
|
||||
Public API needs to correspond exactly to the `esp_wifi` API. Some of the internal types depend on the actual wifi target, as well as some default configuration values. Therefore it's easier to maintain consistency between this component and the exact version of `esp_wifi` automatically in CI:
|
||||
|
||||
* We extract function prototypes from `esp_wifi.h` and use them to generate `esp_wifi_remote` function declarations.
|
||||
* We process the local `esp_wifi_types_native.h` and replace `CONFIG_IDF_TARGET` to `CONFIG_SLAVE_IDF_TARGET` and `CONFIG_SOC_WIFI_...` to `CONFIG_SLAVE_....`
|
||||
* Similarly we process `esp_wifi`'s Kconfig, so the dependencies are on the slave target and slave SOC capabilities.
|
||||
|
||||
Please check the [README.md](./scripts/README.md) for more details on the generation step and testing consistency.
|
@ -1,22 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "esp_log.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "eppp_link.h"
|
||||
|
||||
__attribute__((weak)) esp_netif_t *wifi_remote_eppp_init(eppp_type_t role)
|
||||
{
|
||||
uint32_t our_ip = role == EPPP_SERVER ? EPPP_DEFAULT_SERVER_IP() : EPPP_DEFAULT_CLIENT_IP();
|
||||
uint32_t their_ip = role == EPPP_SERVER ? EPPP_DEFAULT_CLIENT_IP() : EPPP_DEFAULT_SERVER_IP();
|
||||
eppp_config_t config = EPPP_DEFAULT_CONFIG(our_ip, their_ip);
|
||||
// We currently support only UART transport
|
||||
config.transport = EPPP_TRANSPORT_UART;
|
||||
config.uart.tx_io = CONFIG_ESP_WIFI_REMOTE_EPPP_UART_TX_PIN;
|
||||
config.uart.rx_io = CONFIG_ESP_WIFI_REMOTE_EPPP_UART_RX_PIN;
|
||||
config.ppp.netif_description = CONFIG_ESP_WIFI_REMOTE_EPPP_NETIF_DESCRIPTION;
|
||||
config.ppp.netif_prio = CONFIG_ESP_WIFI_REMOTE_EPPP_NETIF_PRIORITY;
|
||||
return eppp_open(role, &config, portMAX_DELAY);
|
||||
}
|
@ -1,318 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <netdb.h>
|
||||
#include <memory>
|
||||
#include <cinttypes>
|
||||
#include "esp_log.h"
|
||||
#include "esp_tls.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_check.h"
|
||||
#include "wifi_remote_rpc_impl.hpp"
|
||||
#include "eppp_link.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "wifi_remote_rpc_params.h"
|
||||
|
||||
extern "C" esp_netif_t *wifi_remote_eppp_init(eppp_type_t role);
|
||||
|
||||
namespace eppp_rpc {
|
||||
|
||||
namespace client {
|
||||
const char *TAG = "rpc_client";
|
||||
|
||||
const unsigned char ca_crt[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_CA "\n-----END CERTIFICATE-----";
|
||||
const unsigned char crt[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_CRT "\n-----END CERTIFICATE-----";
|
||||
const unsigned char key[] = "-----BEGIN PRIVATE KEY-----\n" CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_KEY "\n-----END PRIVATE KEY-----";
|
||||
// TODO: Add option to supply keys and certs via a global symbol (file)
|
||||
|
||||
}
|
||||
|
||||
using namespace client;
|
||||
|
||||
class Sync {
|
||||
friend class RpcInstance;
|
||||
public:
|
||||
void lock()
|
||||
{
|
||||
xSemaphoreTake(mutex, portMAX_DELAY);
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
xSemaphoreGive(mutex);
|
||||
}
|
||||
esp_err_t init()
|
||||
{
|
||||
mutex = xSemaphoreCreateMutex();
|
||||
events = xEventGroupCreate();
|
||||
return mutex == nullptr || events == nullptr ? ESP_ERR_NO_MEM : ESP_OK;
|
||||
}
|
||||
esp_err_t wait_for(EventBits_t bits, uint32_t timeout = portMAX_DELAY)
|
||||
{
|
||||
return (xEventGroupWaitBits(events, bits, pdTRUE, pdTRUE, timeout) & bits) == bits ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
esp_err_t notify(EventBits_t bits)
|
||||
{
|
||||
xEventGroupSetBits(events, bits);
|
||||
return ESP_OK;
|
||||
}
|
||||
~Sync()
|
||||
{
|
||||
if (mutex) {
|
||||
vSemaphoreDelete(mutex);
|
||||
}
|
||||
if (events) {
|
||||
vEventGroupDelete(events);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
SemaphoreHandle_t mutex{nullptr};
|
||||
EventGroupHandle_t events{nullptr};
|
||||
|
||||
const int request = 1;
|
||||
const int resp_header = 2;
|
||||
const int resp_payload = 4;
|
||||
const int restart = 8;
|
||||
};
|
||||
|
||||
class RpcInstance {
|
||||
friend class Sync;
|
||||
public:
|
||||
|
||||
template<typename T>
|
||||
esp_err_t send(api_id id, T *t)
|
||||
{
|
||||
pending_resp = id;
|
||||
ESP_RETURN_ON_ERROR(sync.notify(sync.request), TAG, "failed to notify req");
|
||||
ESP_RETURN_ON_ERROR(rpc.send<T>(id, t), TAG, "Failed to send request");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// overload of the templated method (used for functions with no arguments)
|
||||
esp_err_t send(api_id id)
|
||||
{
|
||||
pending_resp = id;
|
||||
ESP_RETURN_ON_ERROR(sync.notify(sync.request), TAG, "failed to notify req");
|
||||
ESP_RETURN_ON_ERROR(rpc.send(id), TAG, "Failed to send request");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T get_resp(api_id id)
|
||||
{
|
||||
sync.wait_for(sync.resp_header);
|
||||
auto ret = rpc.template get_payload<T>(id, pending_header);
|
||||
sync.notify(sync.resp_payload);
|
||||
return ret;
|
||||
}
|
||||
esp_err_t init()
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(netif = wifi_remote_eppp_init(EPPP_CLIENT), ESP_FAIL, TAG, "Failed to connect to EPPP server");
|
||||
ESP_RETURN_ON_ERROR(esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_GOT_IP, got_ip, this), TAG, "Failed to register event");
|
||||
ESP_RETURN_ON_ERROR(sync.init(), TAG, "Failed to init sync primitives");
|
||||
ESP_RETURN_ON_ERROR(rpc.init(), TAG, "Failed to init RPC engine");
|
||||
return xTaskCreate(task, "client", 8192, this, 5, nullptr) == pdTRUE ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
RpcEngine rpc{eppp_rpc::role::CLIENT};
|
||||
Sync sync;
|
||||
private:
|
||||
api_id pending_resp{api_id::UNDEF};
|
||||
RpcHeader pending_header{};
|
||||
esp_err_t process_ip_event(RpcHeader &header)
|
||||
{
|
||||
auto event = rpc.get_payload<esp_wifi_remote_eppp_ip_event>(api_id::IP_EVENT, header);
|
||||
// Now bypass network layers with EPPP interface
|
||||
ESP_RETURN_ON_ERROR(esp_netif_set_dns_info(netif, ESP_NETIF_DNS_MAIN, &event.dns), TAG, "Failed to set DNS info");
|
||||
ESP_RETURN_ON_ERROR(esp_netif_set_default_netif(netif), TAG, "Failed to set default netif to EPPP");
|
||||
ip_event_got_ip_t evt = {
|
||||
.esp_netif = netif,
|
||||
.ip_info = {},
|
||||
.ip_changed = true,
|
||||
};
|
||||
esp_netif_get_ip_info(netif, &evt.ip_info);
|
||||
ESP_RETURN_ON_ERROR(esp_event_post(IP_EVENT, IP_EVENT_STA_GOT_IP, &evt, sizeof(evt), 0), TAG, "Failed to post IP event");
|
||||
ESP_LOGI(TAG, "Main DNS:" IPSTR, IP2STR(&event.dns.ip.u_addr.ip4));
|
||||
ESP_LOGI(TAG, "EPPP IP:" IPSTR, IP2STR(&event.ppp_ip.ip));
|
||||
ESP_LOGI(TAG, "WIFI IP:" IPSTR, IP2STR(&event.wifi_ip.ip));
|
||||
ESP_LOGI(TAG, "WIFI GW:" IPSTR, IP2STR(&event.wifi_ip.gw));
|
||||
ESP_LOGI(TAG, "WIFI mask:" IPSTR, IP2STR(&event.wifi_ip.netmask));
|
||||
return ESP_OK;
|
||||
}
|
||||
esp_err_t process_wifi_event(RpcHeader &header)
|
||||
{
|
||||
auto event_id = rpc.get_payload<int32_t>(api_id::WIFI_EVENT, header);
|
||||
ESP_RETURN_ON_ERROR(esp_event_post(WIFI_EVENT, event_id, nullptr, 0, 0), TAG, "Failed to post WiFi event");
|
||||
return ESP_OK;
|
||||
}
|
||||
esp_err_t perform()
|
||||
{
|
||||
auto header = rpc.get_header();
|
||||
if (api_id(header.id) == api_id::ERROR) { // network error
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (api_id(header.id) == api_id::UNDEF) { // network timeout
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (api_id(header.id) == api_id::IP_EVENT) {
|
||||
return process_ip_event(header);
|
||||
}
|
||||
if (api_id(header.id) == api_id::WIFI_EVENT) {
|
||||
return process_wifi_event(header);
|
||||
}
|
||||
if (sync.wait_for(sync.request, 0) == ESP_OK && api_id(header.id) == pending_resp) {
|
||||
pending_header = header;
|
||||
pending_resp = api_id::UNDEF;
|
||||
sync.notify(sync.resp_header);
|
||||
sync.wait_for(sync.resp_payload);
|
||||
return ESP_OK;
|
||||
}
|
||||
ESP_LOGE(TAG, "Unexpected header %" PRIi32, static_cast<uint32_t>(header.id));
|
||||
return ESP_FAIL;
|
||||
|
||||
}
|
||||
static void task(void *ctx)
|
||||
{
|
||||
auto instance = static_cast<RpcInstance *>(ctx);
|
||||
do {
|
||||
while (instance->perform() == ESP_OK) {}
|
||||
} while (instance->restart() == ESP_OK);
|
||||
vTaskDelete(nullptr);
|
||||
}
|
||||
esp_err_t restart()
|
||||
{
|
||||
rpc.deinit();
|
||||
ESP_RETURN_ON_ERROR(sync.wait_for(sync.restart, pdMS_TO_TICKS(10000)), TAG, "Didn't receive EPPP address in time");
|
||||
return rpc.init();
|
||||
}
|
||||
static void got_ip(void *ctx, esp_event_base_t base, int32_t id, void *data)
|
||||
{
|
||||
auto instance = static_cast<RpcInstance *>(ctx);
|
||||
instance->sync.notify(instance->sync.restart);
|
||||
}
|
||||
esp_netif_t *netif{nullptr};
|
||||
};
|
||||
|
||||
|
||||
namespace client {
|
||||
constinit RpcInstance instance;
|
||||
} // namespace client
|
||||
|
||||
RpcInstance *RpcEngine::init_client()
|
||||
{
|
||||
char host[4 * 4 + 1] = {}; // IPv4: 4 x (3 numbers + '.') + \0
|
||||
esp_ip4_addr_t ip = { .addr = EPPP_DEFAULT_SERVER_IP() };
|
||||
if (esp_ip4addr_ntoa(&ip, host, sizeof(host)) == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
esp_tls_cfg_t cfg = {};
|
||||
cfg.cacert_buf = client::ca_crt;
|
||||
cfg.cacert_bytes = sizeof(client::ca_crt);
|
||||
cfg.clientcert_buf = client::crt;
|
||||
cfg.clientcert_bytes = sizeof(client::crt);
|
||||
cfg.clientkey_buf = client::key;
|
||||
cfg.clientkey_bytes = sizeof(client::key);
|
||||
cfg.common_name = "espressif.local";
|
||||
|
||||
ESP_RETURN_ON_FALSE(tls_ = esp_tls_init(), nullptr, TAG, "Failed to create ESP-TLS instance");
|
||||
int retries = 0;
|
||||
while (esp_tls_conn_new_sync(host, strlen(host), rpc_port, &cfg, tls_) <= 0) {
|
||||
esp_tls_conn_destroy(tls_);
|
||||
tls_ = nullptr;
|
||||
ESP_RETURN_ON_FALSE(retries++ < 3, nullptr, TAG, "Failed to open connection to %s", host);
|
||||
ESP_LOGW(TAG, "Connection to RPC server failed! Will retry in %d second(s)", retries);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000 * retries));
|
||||
ESP_RETURN_ON_FALSE(tls_ = esp_tls_init(), nullptr, TAG, "Failed to create ESP-TLS instance");
|
||||
}
|
||||
return &client::instance;
|
||||
}
|
||||
} // namespace eppp_rpc
|
||||
|
||||
//
|
||||
// esp_wifi_remote API implementation
|
||||
//
|
||||
using namespace eppp_rpc;
|
||||
using namespace client;
|
||||
|
||||
extern "C" esp_err_t esp_wifi_remote_init(const wifi_init_config_t *config)
|
||||
{
|
||||
// Here we initialize this client's RPC
|
||||
ESP_RETURN_ON_ERROR(instance.init(), TAG, "Failed to initialize eppp-rpc");
|
||||
|
||||
std::lock_guard<Sync> lock(instance.sync);
|
||||
ESP_RETURN_ON_ERROR(instance.send(api_id::INIT, config), TAG, "Failed to send request");
|
||||
return instance.get_resp<esp_err_t>(api_id::INIT);
|
||||
}
|
||||
|
||||
extern "C" esp_err_t esp_wifi_remote_set_config(wifi_interface_t interface, wifi_config_t *conf)
|
||||
{
|
||||
esp_wifi_remote_config params = { .interface = interface, .conf = {} };
|
||||
memcpy(¶ms.conf, conf, sizeof(wifi_config_t));
|
||||
std::lock_guard<Sync> lock(instance.sync);
|
||||
ESP_RETURN_ON_ERROR(instance.send(api_id::SET_CONFIG, ¶ms), TAG, "Failed to send request");
|
||||
return instance.get_resp<esp_err_t>(api_id::SET_CONFIG);
|
||||
}
|
||||
|
||||
extern "C" esp_err_t esp_wifi_remote_start(void)
|
||||
{
|
||||
std::lock_guard<Sync> lock(instance.sync);
|
||||
ESP_RETURN_ON_ERROR(instance.send(api_id::START), TAG, "Failed to send request");
|
||||
return instance.get_resp<esp_err_t>(api_id::START);
|
||||
}
|
||||
|
||||
extern "C" esp_err_t esp_wifi_remote_stop(void)
|
||||
{
|
||||
std::lock_guard<Sync> lock(instance.sync);
|
||||
ESP_RETURN_ON_ERROR(instance.send(api_id::STOP), TAG, "Failed to send request");
|
||||
return instance.get_resp<esp_err_t>(api_id::STOP);
|
||||
}
|
||||
|
||||
extern "C" esp_err_t esp_wifi_remote_connect(void)
|
||||
{
|
||||
std::lock_guard<Sync> lock(instance.sync);
|
||||
ESP_RETURN_ON_ERROR(instance.send(api_id::CONNECT), TAG, "Failed to send request");
|
||||
return instance.get_resp<esp_err_t>(api_id::CONNECT);
|
||||
}
|
||||
|
||||
extern "C" esp_err_t esp_wifi_remote_get_mac(wifi_interface_t ifx, uint8_t mac[6])
|
||||
{
|
||||
std::lock_guard<Sync> lock(instance.sync);
|
||||
ESP_RETURN_ON_ERROR(instance.send(api_id::GET_MAC, &ifx), TAG, "Failed to send request");
|
||||
auto ret = instance.get_resp<esp_wifi_remote_mac_t>(api_id::GET_MAC);
|
||||
ESP_LOG_BUFFER_HEXDUMP("MAC", ret.mac, 6, ESP_LOG_DEBUG);
|
||||
memcpy(mac, ret.mac, 6);
|
||||
return ret.err;
|
||||
}
|
||||
|
||||
extern "C" esp_err_t esp_wifi_remote_set_mode(wifi_mode_t mode)
|
||||
{
|
||||
std::lock_guard<Sync> lock(instance.sync);
|
||||
ESP_RETURN_ON_ERROR(instance.send(api_id::SET_MODE, &mode), TAG, "Failed to send request");
|
||||
return instance.get_resp<esp_err_t>(api_id::SET_MODE);
|
||||
}
|
||||
|
||||
extern "C" esp_err_t esp_wifi_remote_deinit(void)
|
||||
{
|
||||
std::lock_guard<Sync> lock(instance.sync);
|
||||
ESP_RETURN_ON_ERROR(instance.send(api_id::DEINIT), TAG, "Failed to send request");
|
||||
return instance.get_resp<esp_err_t>(api_id::DEINIT);
|
||||
}
|
||||
|
||||
extern "C" esp_err_t esp_wifi_remote_disconnect(void)
|
||||
{
|
||||
std::lock_guard<Sync> lock(instance.sync);
|
||||
ESP_RETURN_ON_ERROR(instance.send(api_id::DISCONNECT), TAG, "Failed to send request");
|
||||
return instance.get_resp<esp_err_t>(api_id::DISCONNECT);
|
||||
}
|
||||
|
||||
extern "C" esp_err_t esp_wifi_remote_set_storage(wifi_storage_t storage)
|
||||
{
|
||||
std::lock_guard<Sync> lock(instance.sync);
|
||||
ESP_RETURN_ON_ERROR(instance.send(api_id::SET_STORAGE, &storage), TAG, "Failed to send request");
|
||||
return instance.get_resp<esp_err_t>(api_id::SET_STORAGE);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user