Compare commits

..

4 Commits

308 changed files with 7495 additions and 9270 deletions

View File

@ -4,7 +4,7 @@ on:
pull_request:
push:
branches:
- master
- test_clang_tidy
jobs:
build:
@ -24,7 +24,6 @@ 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
@ -36,14 +35,14 @@ jobs:
working-directory: test_app
run: |
. ${IDF_PATH}/export.sh
idf.py clang-check --include-paths $GITHUB_WORKSPACE --exclude-paths $PWD --run-clang-tidy-py run-clang-tidy --run-clang-tidy-options "-checks=-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling"
idf.py clang-check --include-paths $GITHUB_WORKSPACE --exclude-paths $PWD --run-clang-tidy-py run-clang-tidy
cp warnings.txt ../
- name: Convert clang-tidy results into SARIF output
run: |
export PATH=$PWD:$PATH
./clang-tidy-sarif -o results.sarif.raw warnings.txt
python3 filter_sarif.py -o results.sarif --include-prefix ${GITHUB_WORKSPACE}/ results.sarif.raw
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v2
with:
path: |
warnings.txt

View File

@ -1,32 +0,0 @@
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

View File

@ -14,17 +14,12 @@ jobs:
strategy:
matrix:
idf_ver: ["latest", "release-v5.1", "release-v5.2", "release-v5.3"]
include:
- idf_ver: "latest"
warning: "Warning: The smallest app partition is nearly full"
runs-on: ubuntu-22.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v4
- name: Build with IDF-${{ matrix.idf_ver }}
env:
EXPECTED_WARNING: ${{ matrix.warning }}
shell: bash
run: |
. ${IDF_PATH}/export.sh

View File

@ -10,30 +10,27 @@ on:
jobs:
host_test_mdns:
if: contains(github.event.pull_request.labels.*.name, 'mdns') || github.event_name == 'push'
name: Host test build
name: Host test
runs-on: ubuntu-22.04
container: espressif/idf:release-v5.3
container: espressif/idf:release-v5.1
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v4
with:
path: protocols
path: esp-protocols
- name: Build and Test
shell: bash
run: |
apt-get update && apt-get install -y dnsutils gcc g++
. ${IDF_PATH}/export.sh
python -m pip install idf-build-apps dnspython pytest pytest-embedded pytest-embedded-serial-esp pytest-embedded-idf
cd $GITHUB_WORKSPACE/protocols
# Build host tests app (with all configs and targets supported)
python ./ci/build_apps.py components/mdns/tests/host_test/
cd components/mdns/tests/host_test
# First run the linux_app and send a quick A query and a reverse query
./build_linux_app/mdns_host.elf &
python dnsfixture.py A myesp.local --ip_only | xargs python dnsfixture.py X
# Next we run the pytest (using the console app)
pytest
cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/tests/host_test
idf.py build
./build/mdns_host.elf &
dig +short -p 5353 @224.0.0.251 myesp.local > ip.txt
cat ip.txt | xargs dig +short -p 5353 @224.0.0.251 -x
cat ip.txt
build_afl_host_test_mdns:
if: contains(github.event.pull_request.labels.*.name, 'mdns') || github.event_name == 'push'

View File

@ -13,8 +13,11 @@ jobs:
name: Build examples
strategy:
matrix:
idf_ver: ["latest", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3", "release-v5.4"]
idf_ver: ["latest", "release-v4.4", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3"]
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"
@ -23,7 +26,13 @@ jobs:
runs-on: ubuntu-22.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Check out code
- 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'
uses: actions/checkout@v4
with:
path: protocols
@ -44,7 +53,7 @@ jobs:
name: Build tests
strategy:
matrix:
idf_ver: ["release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3", "release-v5.4", "latest"]
idf_ver: ["release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3", "latest"]
test: ["target", "target_ota", "target_iperf"]
runs-on: ubuntu-22.04

View File

@ -15,7 +15,7 @@ jobs:
matrix:
idf_ver: ["latest"]
idf_target: ["esp32c3"]
test: [ { app: pppd, path: test/target }, { app: pppd_chap_auth, path: test/target }, { app: sim800_c3, path: examples/pppos_client }, { app: sim800_cmux, path: examples/simple_cmux_client } ]
test: [ { app: pppd, path: test/target }, { app: sim800_c3, path: examples/pppos_client }, { app: sim800_cmux, path: examples/simple_cmux_client } ]
include:
- idf_ver: "latest"
idf_target: "esp32s2"
@ -58,7 +58,7 @@ jobs:
matrix:
idf_ver: ["latest"]
idf_target: ["esp32c3"]
test: [ { app: pppd, path: test/target }, { app: pppd_chap_auth, path: test/target }, { app: sim800_c3, path: examples/pppos_client }, { app: sim800_cmux, path: examples/simple_cmux_client } ]
test: [ { app: pppd, path: test/target }, { app: sim800_c3, path: examples/pppos_client }, { app: sim800_cmux, path: examples/simple_cmux_client } ]
include:
- idf_ver: "latest"
idf_target: "esp32s2"
@ -69,23 +69,16 @@ jobs:
- modem
env:
TEST_DIR: components/esp_modem/${{ matrix.test.path }}
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
steps:
- name: Clear repository
run: |
sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE
run: sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: modem_target_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.test.app }}
path: ${{ env.TEST_DIR }}/build
- name: Run Example Test on target
env:
PIP_EXTRA_INDEX_URL: "https://dl.espressif.com/pypi/"
working-directory: ${{ env.TEST_DIR }}
run: |
python -m venv .venv
source .venv/bin/activate
pip install --prefer-binary cryptography pytest-embedded pytest-embedded-serial-esp pytest-embedded-idf pytest-custom_exit_code esptool
pip install -r $GITHUB_WORKSPACE/ci/requirements.txt
cd ${{ env.TEST_DIR }}
python -m pip install -r $GITHUB_WORKSPACE/ci/requirements.txt
python -m pytest --log-cli-level DEBUG --target=${{ matrix.idf_target }}

View File

@ -1,103 +0,0 @@
name: "mosq: build-tests"
on:
push:
branches:
- master
pull_request:
types: [opened, synchronize, reopened, labeled]
jobs:
build_mosq:
if: contains(github.event.pull_request.labels.*.name, 'mosquitto') || github.event_name == 'push'
name: Mosquitto build
strategy:
matrix:
idf_ver: ["latest", "release-v5.3"]
runs-on: ubuntu-22.04
container: espressif/idf:${{ matrix.idf_ver }}
env:
TEST_DIR: components/mosquitto/examples
TARGET_TEST: broker
TARGET_TEST_DIR: build_esp32_default
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build with IDF-${{ matrix.idf_ver }}
shell: bash
run: |
. ${IDF_PATH}/export.sh
pip install idf-component-manager idf-build-apps --upgrade
python ci/build_apps.py -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 }}/${{ env.TARGET_TEST }}/artifacts.zip
if-no-files-found: error
test_mosq:
# Skip running on forks since it won't have access to secrets
if: |
github.repository == 'espressif/esp-protocols' &&
( contains(github.event.pull_request.labels.*.name, 'mosquitto') || github.event_name == 'push' )
name: Mosquitto target test
needs: build_mosq
strategy:
matrix:
idf_ver: ["latest", "release-v5.3"]
runs-on:
- self-hosted
- ESP32-ETHERNET-KIT
env:
TEST_DIR: components/mosquitto/examples/broker
TARGET_TEST_DIR: build_esp32_default
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: mosq_target_esp32_${{ matrix.idf_ver }}
path: ${{ env.TEST_DIR }}/ci/
- name: Run Test
working-directory: ${{ env.TEST_DIR }}
run: |
python -m pip install pytest-embedded-serial-esp pytest-embedded-idf pytest-rerunfailures pytest-timeout pytest-ignore-test-results
unzip ci/artifacts.zip -d ci
for dir in `ls -d ci/build_*`; do
rm -rf build sdkconfig.defaults
mv $dir build
python -m pytest --log-cli-level DEBUG --junit-xml=./results_esp32_${{ matrix.idf_ver }}_${dir#"ci/build_"}.xml --target=esp32
done
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"

View File

@ -26,7 +26,7 @@ jobs:
- name: Set up Python environment
uses: actions/setup-python@master
with:
python-version: v3.8
python-version: v3.7
- name: Install python packages
run: |
pip install pre-commit

View File

@ -98,9 +98,7 @@ jobs:
components/console_cmd_ping;
components/console_cmd_ifconfig;
components/console_cmd_wifi;
components/console_cmd_mqtt;
components/esp_wifi_remote;
components/mbedtls_cxx;
components/mosquitto;
components/sock_utils;
namespace: "espressif"
api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }}

View File

@ -1,95 +0,0 @@
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

View File

@ -0,0 +1,77 @@
name: "esp_wifi_remote: build-tests"
on:
push:
branches:
- master
pull_request:
types: [opened, synchronize, reopened, labeled]
jobs:
wifi_remote_api_compat:
if: contains(github.event.pull_request.labels.*.name, 'wifi_remote') || github.event_name == 'push'
name: Check API compatibility of WiFi Remote
strategy:
matrix:
idf_ver: ["latest"]
runs-on: ubuntu-20.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v3
- name: Check that headers are the same as generated
shell: bash
run: |
. ${IDF_PATH}/export.sh
pip install idf-component-manager idf-build-apps --upgrade
cd ./components/esp_wifi_remote/scripts
python generate_and_check.py
build_wifi_remote:
if: contains(github.event.pull_request.labels.*.name, 'wifi_remote') || github.event_name == 'push'
name: Build WiFi Remote Test
strategy:
matrix:
idf_ver: ["latest"]
test: [ { app: smoke_test, path: "test/smoke_test" }]
runs-on: ubuntu-20.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v3
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ matrix.idf_ver }}
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }}
shell: bash
run: |
. ${IDF_PATH}/export.sh
pip install idf-component-manager idf-build-apps --upgrade
python ./ci/build_apps.py ./components/esp_wifi_remote/${{matrix.test.path}} -vv --preserve-all
build_wifi_remote_example:
if: contains(github.event.pull_request.labels.*.name, 'wifi_remote') || github.event_name == 'push'
name: Build WiFi Remote Example
strategy:
matrix:
idf_ver: ["latest"]
example: [ { app: host, path: "examples/mqtt" }, { app: slave, path: "examples/server" }]
include:
- idf_ver: "latest"
example: { app: slave, path: "examples/server" }
warning: "Warning: The smallest app partition is nearly full"
runs-on: ubuntu-20.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v3
- name: Build ${{ matrix.example.app }} with IDF-${{ matrix.idf_ver }}
env:
EXPECTED_WARNING: ${{ matrix.warning }}
shell: bash
run: |
. ${IDF_PATH}/export.sh
pip install idf-component-manager idf-build-apps --upgrade
python ./ci/build_apps.py ./components/esp_wifi_remote/${{matrix.example.path}} -vv --preserve-all

3
.gitmodules vendored
View File

@ -1,6 +1,3 @@
[submodule "components/asio/asio"]
path = components/asio/asio
url = https://github.com/espressif/asio
[submodule "components/mosquitto/mosquitto"]
path = components/mosquitto/mosquitto
url = https://github.com/eclipse/mosquitto

View File

@ -48,7 +48,7 @@ repos:
- id: check-copyright
args: ['--ignore', 'ci/check_copyright_ignore.txt', '--config', 'ci/check_copyright_config.yaml']
- repo: https://github.com/igrr/astyle_py.git
rev: v1.0.5
rev: c0013808882a15a0c0c2c1a9b5c903866c53a653
hooks:
- id: astyle_py
args: ['--style=otbs', '--attach-namespaces', '--attach-classes', '--indent=spaces=4', '--convert-tabs', '--align-pointer=name', '--align-reference=name', '--keep-one-line-statements', '--pad-header', '--pad-oper', '--exclude-list=ci/ignore_astyle.txt']
@ -61,8 +61,8 @@ repos:
- repo: local
hooks:
- id: commit message scopes
name: "commit message must be scoped with: mdns, modem, websocket, asio, mqtt_cxx, console, common, eppp, tls_cxx, mosq, sockutls"
entry: '\A(?!(feat|fix|ci|bump|test|docs|chore)\((mdns|modem|common|console|websocket|asio|mqtt_cxx|examples|eppp|tls_cxx|mosq|sockutls)\)\:)'
name: "commit message must be scoped with: mdns, modem, websocket, asio, mqtt_cxx, console, common, eppp, 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)\)\:)'
language: pygrep
args: [--multiline]
stages: [commit-msg]

View File

@ -54,15 +54,10 @@ 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)

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
"""
This file is used in CI for esp-protocols build tests
@ -10,6 +10,8 @@ import sys
from idf_build_apps import build_apps, find_apps, setup_logging
from idf_build_apps.constants import SUPPORTED_TARGETS
from packaging import version
from pkg_resources import get_distribution
if __name__ == '__main__':
parser = argparse.ArgumentParser(
@ -49,24 +51,43 @@ if __name__ == '__main__':
SUPPORTED_TARGETS.append('linux')
ignore_warning = 'warning: ' # Ignore all common warnings on linux builds
setup_logging(2)
apps = find_apps(
args.paths,
recursive=args.recursive,
target=args.target,
build_dir='build_@t_@w',
config_rules_str=args.rules,
build_log_filename='build_log.txt',
size_json_filename='size.json' if not args.linux else None,
check_warnings=True,
manifest_files=args.manifests,
default_build_targets=SUPPORTED_TARGETS,
manifest_rootpath='.',
)
if version.parse(get_distribution('idf_build_apps').version) >= version.parse('2.0.0'):
apps = find_apps(
args.paths,
recursive=args.recursive,
target=args.target,
build_dir='build_@t_@w',
config_rules_str=args.rules,
build_log_filename='build_log.txt',
size_json_filename='size.json' if not args.linux else None,
check_warnings=True,
preserve=not args.delete,
manifest_files=args.manifests,
default_build_targets=SUPPORTED_TARGETS,
manifest_rootpath='.',
)
else:
apps = find_apps(
args.paths,
recursive=args.recursive,
target=args.target,
build_dir='build_@t_@w',
config_rules_str=args.rules,
build_log_path='build_log.txt',
size_json_path='size.json' if not args.linux else None,
check_warnings=True,
preserve=not args.delete,
manifest_files=args.manifests,
default_build_targets=SUPPORTED_TARGETS,
manifest_rootpath='.',
)
for app in apps:
print(app)
sys.exit(
build_apps(apps,
dry_run=False,
keep_going=False,
no_preserve=args.delete,
ignore_warning_strs=ignore_warning)
)

View File

@ -47,14 +47,6 @@ asio_component:
- Apache-2.0
- BSL-1.0
mosquitto_component:
include:
- 'components/mosquitto/port/**'
allowed_licenses:
- EPL-2.0
- Apache-2.0
- BSD-3-Clause
slim_modem_examples:
include:
- 'examples/esp_netif/slip_custom_netif/**'

View File

@ -1 +0,0 @@
components/mosquitto/examples/serverless_mqtt/components/libjuice/port/juice_random.c

View File

@ -22,11 +22,7 @@ if git log -1 -m --name-only --pretty="" | grep -q components/${comp}/idf_compon
if [ $(git tag -l "$tag") ]; then
echo "${comp}: version (${tag}) already exits"
else
# skip components that do not have changelog
[ -f components/${comp}/CHANGELOG.md ] || continue
echo "${comp}: Component version has been updated to ${version}"
# creates release notes from the last entry (between first two "## sections")
awk '/^## \[/{a++};{if(a==1){print}}' components/${comp}/CHANGELOG.md > release_notes.md

View File

@ -0,0 +1,2 @@
# 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

View File

@ -1 +0,0 @@
idf_component_register()

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -12,24 +12,8 @@
#include <stdlib.h>
#include <string.h>
#include "osal/osal_api.h"
#include <semaphore.h>
typedef struct task_notifiers {
sem_t sem;
TaskHandle_t id;
} task_notifiers_t;
typedef struct pthread_params {
void *const param;
TaskFunction_t task;
bool started;
TaskHandle_t handle;
} pthread_params_t;
static uint64_t s_semaphore_data = 0;
static task_notifiers_t *s_notifiers;
static int s_threads = 0;
pthread_mutex_t s_mutex;
typedef enum queue_type_tag {
MUTEX_REC,
@ -105,7 +89,6 @@ BaseType_t xSemaphoreGiveRecursive( QueueHandle_t xQueue)
}
return pdFALSE;
}
BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask )
{
struct generic_queue_handle *h = xQueue;
@ -116,6 +99,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 )
{
struct generic_queue_handle *h = xQueue;
@ -126,6 +110,9 @@ BaseType_t xSemaphoreTakeRecursive( QueueHandle_t xQueue, TickType_t pvTask )
return pdFALSE;
}
void vQueueDelete( QueueHandle_t xQueue )
{
struct generic_queue_handle *h = xQueue;
@ -141,7 +128,8 @@ void vQueueDelete( QueueHandle_t xQueue )
QueueHandle_t xSemaphoreCreateBinary(void)
{
return xQueueCreate(1, 1);
QueueHandle_t sempaphore = xQueueCreate(1, 1);
return sempaphore;
}
QueueHandle_t xSemaphoreCreateMutex(void)
@ -157,13 +145,6 @@ QueueHandle_t xSemaphoreCreateRecursiveMutex(void)
void vTaskDelete(TaskHandle_t *task)
{
for (int i = 0; i < s_threads; ++i) {
if (task == s_notifiers[i].id) {
sem_destroy(&s_notifiers[i].sem);
s_notifiers[i].id = 0;
}
}
if (task == NULL) {
pthread_exit(0);
}
@ -190,21 +171,14 @@ void vTaskDelay( const TickType_t xTicksToDelay )
void *pthread_task(void *params)
{
pthread_params_t *pthread_params = params;
struct {
void *const param;
TaskFunction_t task;
bool started;
} *pthread_params = params;
void *const param = pthread_params->param;
TaskFunction_t task = pthread_params->task;
pthread_params->handle = xTaskGetCurrentTaskHandle();
if (s_threads == 0) {
pthread_mutex_init(&s_mutex, NULL);
}
pthread_mutex_lock(&s_mutex);
s_notifiers = realloc(s_notifiers, sizeof(struct task_notifiers) * (++s_threads));
assert(s_notifiers);
s_notifiers[s_threads - 1].id = pthread_params->handle;
sem_init(&s_notifiers[s_threads - 1].sem, 0, 0);
pthread_mutex_unlock(&s_mutex);
pthread_params->started = true;
task(param);
@ -224,12 +198,16 @@ BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode,
return pdTRUE;
}
BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char *const pcName, const uint32_t usStackDepth, void *const pvParameters, UBaseType_t uxPriority, TaskHandle_t *const pvCreatedTask)
{
pthread_t new_thread = (pthread_t)NULL;
pthread_attr_t attr;
pthread_params_t pthread_params = { .param = pvParameters, .task = pvTaskCode};
struct {
void *const param;
TaskFunction_t task;
bool started;
} pthread_params = { .param = pvParameters, .task = pvTaskCode};
int res = pthread_attr_init(&attr);
assert(res == 0);
res = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
@ -237,33 +215,20 @@ BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char *const pcName, cons
res = pthread_create(&new_thread, &attr, pthread_task, &pthread_params);
assert(res == 0);
if (pvCreatedTask) {
*pvCreatedTask = (void *)new_thread;
}
// just wait till the task started so we can unwind params from the stack
while (pthread_params.started == false) {
usleep(1000);
}
if (pvCreatedTask) {
*pvCreatedTask = pthread_params.handle;
}
return pdTRUE;
}
void xTaskNotifyGive(TaskHandle_t task)
{
int i = 0;
while (true) {
pthread_mutex_lock(&s_mutex);
if (task == s_notifiers[i].id) {
sem_post(&s_notifiers[i].sem);
pthread_mutex_unlock(&s_mutex);
return;
}
pthread_mutex_unlock(&s_mutex);
if (++i == s_threads) {
i = 0;
}
usleep(1000);
}
}
BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time )
@ -273,7 +238,7 @@ BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear,
TaskHandle_t xTaskGetCurrentTaskHandle(void)
{
return (TaskHandle_t)pthread_self();
return NULL;
}
EventGroupHandle_t xEventGroupCreate( void )
@ -305,22 +270,3 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits
{
return osal_signal_wait(xEventGroup, uxBitsToWaitFor, xWaitForAllBits, xTicksToWait);
}
void ulTaskNotifyTake(bool clear_on_exit, uint32_t xTicksToWait)
{
TaskHandle_t task = xTaskGetCurrentTaskHandle();
int i = 0;
while (true) {
pthread_mutex_lock(&s_mutex);
if (task == s_notifiers[i].id) {
pthread_mutex_unlock(&s_mutex);
sem_wait(&s_notifiers[i].sem);
return;
}
pthread_mutex_unlock(&s_mutex);
if (++i == s_threads) {
i = 0;
}
usleep(1000);
}
}

View File

@ -5,7 +5,6 @@
*/
#pragma once
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

View File

@ -11,7 +11,6 @@
extern "C" {
#endif
#define tskNO_AFFINITY ( ( BaseType_t ) 0x7FFFFFFF )
#define TaskHandle_t TaskHandle_t
#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) )
@ -19,8 +18,6 @@ void vTaskDelay( const TickType_t xTicksToDelay );
void xTaskNotifyGive(TaskHandle_t task);
void ulTaskNotifyTake(bool stuff, uint32_t timeout);
TaskHandle_t xTaskGetCurrentTaskHandle(void);
BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time );

View File

@ -1,8 +0,0 @@
---
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

View File

@ -1,7 +0,0 @@
# 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))

View File

@ -1,7 +0,0 @@
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()

View File

@ -1,15 +0,0 @@
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

View File

@ -1,87 +0,0 @@
# 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
```

View File

@ -1,475 +0,0 @@
/*
* 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;
}

View File

@ -1,73 +0,0 @@
/*
* 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

View File

@ -1,11 +0,0 @@
# 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)

View File

@ -1,174 +0,0 @@
| 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
```

View File

@ -1,24 +0,0 @@
-----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-----

View File

@ -1,2 +0,0 @@
idf_component_register(SRCS "mqtt_ssl_auth_console.c"
INCLUDE_DIRS ".")

View File

@ -1,8 +0,0 @@
dependencies:
idf:
version: ">=5.0"
protocol_examples_common:
path: ${IDF_PATH}/examples/common_components/protocol_examples_common
console_cmd_mqtt:
version: "*"
override_path: '../../../'

View File

@ -1,51 +0,0 @@
/*
* 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());
}

View File

@ -1,19 +0,0 @@
# 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)

View File

@ -1,7 +0,0 @@
# 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"

View File

@ -1,11 +0,0 @@
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

View File

@ -3,6 +3,6 @@ commitizen:
bump_message: 'bump(console): $current_version -> $new_version'
pre_bump_hooks: python ../../ci/changelog.py console_cmd_ping
tag_format: console_cmd_ping-v$version
version: 1.1.0
version: 1.0.0
version_files:
- idf_component.yml

View File

@ -1,11 +1,5 @@
# Changelog
## [1.1.0](https://github.com/espressif/esp-protocols/commits/console_cmd_ping-v1.1.0)
### Features
- Added command getaddrinfo, set/get dnsserver to console_cmd_ping ([b80c19d7](https://github.com/espressif/esp-protocols/commit/b80c19d7))
## [1.0.0](https://github.com/espressif/esp-protocols/commits/console_cmd_ping-v1.0.0)
### Features

View File

@ -1,10 +1,4 @@
idf_component_register(SRCS "console_ping.c" "console_getaddrinfo.c" "console_getsetdnsserver.c"
idf_component_register(SRCS "console_ping.c"
INCLUDE_DIRS "."
PRIV_REQUIRES esp_netif console)
if(CONFIG_PING_CMD_AUTO_REGISTRATION)
target_link_libraries(${COMPONENT_LIB} "-u console_cmd_ping_register")
target_link_libraries(${COMPONENT_LIB} "-u console_cmd_getaddrinfo_register")
target_link_libraries(${COMPONENT_LIB} "-u console_cmd_setdnsserver_register")
target_link_libraries(${COMPONENT_LIB} "-u console_cmd_getdnsserver_register")
endif()
PRIV_REQUIRES esp_netif console
WHOLE_ARCHIVE)

View File

@ -1,9 +0,0 @@
menu "Ping command Configuration"
config PING_CMD_AUTO_REGISTRATION
bool "Enable Console command ping/dns Auto-registration"
default y
help
Enabling this allows for the autoregistration of the ping and dns commands.
endmenu

View File

@ -1,5 +1,5 @@
# Console command ping and DNS server configuration
The component provides a console where the 'ping' command, 'getaddrinfo', and DNS server configuration commands can be executed.
# Console command ping
The component provides a console where the 'ping' command can be executed.
## API
@ -27,11 +27,8 @@ The component provides a console where the 'ping' command, 'getaddrinfo', and DN
// Register all plugin command added to your project
ESP_ERROR_CHECK(console_cmd_all_register());
// To register only ping/dns command skip calling console_cmd_all_register()
// To register only ifconfig command skip calling console_cmd_all_register()
ESP_ERROR_CHECK(console_cmd_ping_register());
ESP_ERROR_CHECK(console_cmd_getaddrinfo_register());
ESP_ERROR_CHECK(console_cmd_setdnsserver_register());
ESP_ERROR_CHECK(console_cmd_getdnsserver_register());
ESP_ERROR_CHECK(console_cmd_start()); // Start console
```
@ -39,8 +36,6 @@ The component provides a console where the 'ping' command, 'getaddrinfo', and DN
### Adding a plugin command or component:
To add a plugin command or any component from IDF component manager into your project, simply include an entry within the `idf_component.yml` file.
Note: **Auto-registration** of a specific plugin command can be disabled from menuconfig.
For more details refer [IDF Component Manager](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-component-manager.html)
@ -57,72 +52,4 @@ ping [-W <t>] [-i <t>] [-s <n>] [-c <n>] [-Q <n>] [-T <n>] <host>
-Q, --tos=<n> Set Type of Service related bits in IP datagrams
-T, --ttl=<n> Set Time to Live related bits in IP datagrams
<host> Host address
getaddrinfo [-f <AF>] [-F <FLAGS>]... [-p <port>] <hostname>
Usage: getaddrinfo [options] <hostname> [service]
-f, --family=<AF> Address family (AF_INET, AF_INET6, AF_UNSPEC).
-F, --flags=<FLAGS> Special flags (AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST, AI_V4MAPPED, AI_ALL).
-p, --port=<port> String containing a numeric port number.
<hostname> Host address
setdnsserver <main> [backup] [fallback]
Usage: setdnsserver <main> [backup] [fallback]
<main> The main DNS server IP address.
backup The secondary DNS server IP address (optional).
fallback The fallback DNS server IP address (optional).
getdnsserver
Usage: getdnsserver
```
These commands allow you to configure and retrieve DNS server settings on your ESP32 device, in addition to the existing ping functionality.
## Usage
### Using the setdnsserver command:
1. To set the main DNS server:
```
setdnsserver 8.8.8.8
```
2. To set the main and backup DNS servers:
```
setdnsserver 8.8.8.8 fe80::b0be:83ff:fe77:dd64
```
3. To set the main, backup, and fallback DNS servers:
```
setdnsserver 8.8.8.8 fe80::b0be:83ff:fe77:dd64 www.xyz.com
```
### Using the getdnsserver command:
To get the current DNS server settings:
```
getdnsserver
```
### Using the getaddrinfo command:
1. To get address information for a hostname:
```
getaddrinfo www.example.com
```
2. To specify additional options:
```
getaddrinfo -f AF_INET -F AI_PASSIVE www.example.com
```
### Using the ping command:
1. To ping a host:
```
ping www.example.com
```
2. To specify additional options, such as timeout, interval, packet size, etc.:
```
ping -W 5 -i 1 -s 64 -c 4 -Q 0x10 -T 64 www.example.com
```

View File

@ -1,180 +0,0 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <string.h>
#include "sdkconfig.h"
#include "lwip/inet.h"
#include "lwip/netdb.h"
#include "lwip/sockets.h"
#include "esp_console.h"
#include "esp_log.h"
#include "argtable3/argtable3.h"
#include <netdb.h>
#include "console_ping.h"
static const char *TAG = "console_getaddrinfo";
#if CONFIG_PING_CMD_AUTO_REGISTRATION
/**
* @brief Static registration of the getaddrinfo command plugin.
*
* This section registers the plugin description structure and places it into
* the .console_cmd_desc section, as determined by the linker.lf file in the
* 'plugins' component.
*/
static const console_cmd_plugin_desc_t __attribute__((section(".console_cmd_desc"), used)) PLUGIN = {
.name = "console_cmd_getddrinfo",
.plugin_regd_fn = &console_cmd_getaddrinfo_register
};
#endif
/**
* @brief Structure to hold arguments for the getaddrinfo command.
*/
static struct {
struct arg_str *family;
struct arg_str *flags;
struct arg_str *port_nr;
struct arg_str *hostname;
struct arg_end *end;
} getddrinfo_args;
/**
* @brief Executes the getaddrinfo command.
*
* This function parses arguments, sets hints for address resolution, and calls
* getaddrinfo to resolve the hostname. It then prints the resolved IP addresses
* and associated information.
*
* @param argc Argument count
* @param argv Argument vector
*
* @return int Returns 0 on success, 1 on error.
*/
static int do_getddrinfo_cmd(int argc, char **argv)
{
char ip_str[INET6_ADDRSTRLEN];
struct addrinfo hint = {0};
struct addrinfo *res = NULL, *res_tmp = NULL;
const char *port_nr_str = NULL;
int ret = 0;
int nerrors = arg_parse(argc, argv, (void **)&getddrinfo_args);
if (nerrors != 0) {
arg_print_errors(stderr, getddrinfo_args.end, argv[0]);
return 1;
}
/* Set the address family */
if (getddrinfo_args.family->count > 0) {
if (strcmp(getddrinfo_args.family->sval[0], "AF_INET") == 0) {
hint.ai_family = AF_INET;
} else if (strcmp(getddrinfo_args.family->sval[0], "AF_INET6") == 0) {
hint.ai_family = AF_INET6;
} else if (strcmp(getddrinfo_args.family->sval[0], "AF_UNSPEC") == 0) {
hint.ai_family = AF_UNSPEC;
} else {
ESP_LOGE(TAG, "Unknown family");
return 1;
}
}
/* Set the flags */
if (getddrinfo_args.flags->count > 0) {
for (int i = 0; i < getddrinfo_args.flags->count; i++) {
if (strcmp(getddrinfo_args.flags->sval[i], "AI_PASSIVE") == 0) {
hint.ai_flags |= AI_PASSIVE;
} else if (strcmp(getddrinfo_args.flags->sval[i], "AI_CANONNAME") == 0) {
hint.ai_flags |= AI_CANONNAME;
} else if (strcmp(getddrinfo_args.flags->sval[i], "AI_NUMERICHOST") == 0) {
hint.ai_flags |= AI_NUMERICHOST;
} else if (strcmp(getddrinfo_args.flags->sval[i], "AI_V4MAPPED") == 0) {
hint.ai_flags |= AI_V4MAPPED;
} else if (strcmp(getddrinfo_args.flags->sval[i], "AI_ALL") == 0) {
hint.ai_flags |= AI_ALL;
} else {
ESP_LOGE(TAG, "Unknown flag: %s", getddrinfo_args.flags->sval[i]);
return 1;
}
}
}
if (getddrinfo_args.port_nr->count > 0) {
port_nr_str = getddrinfo_args.port_nr->sval[0];
}
/* Convert hostname to IP address */
if (!strcmp(getddrinfo_args.hostname->sval[0], "NULL")) {
ret = getaddrinfo(NULL, port_nr_str, &hint, &res);
} else {
ret = getaddrinfo(getddrinfo_args.hostname->sval[0], port_nr_str, &hint, &res);
}
if (ret != 0) {
printf("getddrinfo: Failure host:%s(ERROR: %d)\n", getddrinfo_args.hostname->sval[0], ret);
ESP_LOGE(TAG, "Failure host");
return 1;
}
/* Iterate through the results from getaddrinfo */
for (res_tmp = res; res_tmp != NULL; res_tmp = res_tmp->ai_next) {
if (res_tmp->ai_family == AF_INET) {
inet_ntop(AF_INET, &((struct sockaddr_in *)res_tmp->ai_addr)->sin_addr, ip_str, INET_ADDRSTRLEN);
printf("\tIP Address: %s\n", ip_str);
printf("\tAddress Family: AF_INET\n");
} else if (res_tmp->ai_family == AF_INET6) {
inet_ntop(AF_INET6, &((struct sockaddr_in6 *)res_tmp->ai_addr)->sin6_addr, ip_str, INET6_ADDRSTRLEN);
printf("\tIP Address: %s\n", ip_str);
printf("\tAddress Family: AF_INET6\n");
} else {
ESP_LOGE(TAG, "ai_family Unknown: %d\n", res_tmp->ai_family);
}
/* Print the protocol used */
printf("\tProtocol: %d\n", res_tmp->ai_protocol);
/* Print the canonical name if available */
if (res_tmp->ai_canonname) {
printf("\tCanonical Name: %s\n", res_tmp->ai_canonname);
}
}
freeaddrinfo(res);
return 0;
}
/**
* @brief Registers the getaddrinfo command.
*
* @return esp_err_t Returns ESP_OK on success, or an error code on failure.
*/
esp_err_t console_cmd_getaddrinfo_register(void)
{
esp_err_t ret;
getddrinfo_args.family = arg_str0("f", "family", "<AF>", "Address family (AF_INET, AF_INET6, AF_UNSPEC).");
getddrinfo_args.flags = arg_strn("F", "flags", "<FLAGS>", 0, 5, "Special flags (AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST, AI_V4MAPPED, AI_ALL).");
getddrinfo_args.port_nr = arg_str0("p", "port", "<port>", "String containing a numeric port number.");
getddrinfo_args.hostname = arg_str1(NULL, NULL, "<hostname>", "Host address");
getddrinfo_args.end = arg_end(1);
const esp_console_cmd_t getddrinfo_cmd = {
.command = "getaddrinfo",
.help = "Usage: getaddrinfo [options] <hostname> [service]",
.hint = NULL,
.func = &do_getddrinfo_cmd,
.argtable = &getddrinfo_args
};
ret = esp_console_cmd_register(&getddrinfo_cmd);
if (ret) {
ESP_LOGE(TAG, "Unable to register getddrinfo");
}
return ret;
}

View File

@ -1,279 +0,0 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <string.h>
#include "sdkconfig.h"
#include "lwip/inet.h"
#include "lwip/netdb.h"
#include "lwip/sockets.h"
#include "esp_console.h"
#include "esp_netif.h"
#include "lwip/netdb.h"
#include "esp_log.h"
#include "argtable3/argtable3.h"
#include <netdb.h>
#include "console_ping.h"
static const char *TAG = "console_setdnsserver";
#if CONFIG_PING_CMD_AUTO_REGISTRATION
static esp_err_t console_cmd_dnscmd_register(void);
/**
* @brief Static registration of the getaddrinfo command plugin.
*
* This section registers the plugin description structure and places it into
* the .console_cmd_desc section, as determined by the linker.lf file in the
* 'plugins' component.
*/
static const console_cmd_plugin_desc_t __attribute__((section(".console_cmd_desc"), used)) PLUGIN = {
.name = "console_cmd_dnscmd",
.plugin_regd_fn = &console_cmd_dnscmd_register
};
/**
* @brief Registers the DNS commands (setdnsserver and getdnsserver) with the console.
*
* @return esp_err_t Returns ESP_OK.
*/
static esp_err_t console_cmd_dnscmd_register(void)
{
console_cmd_setdnsserver_register();
console_cmd_getdnsserver_register();
return ESP_OK;
}
#endif
/**
* @brief Structure to hold arguments for the setdnsserver command.
*/
static struct {
struct arg_str *main;
struct arg_str *backup;
struct arg_str *fallback;
struct arg_end *end;
} setdnsserver_args;
/**
* @brief Sets the DNS server address for all network interfaces.
*
* This function iterates over all network interfaces available on the ESP32 device
* and sets the DNS server address for the specified DNS type (main, backup, or fallback).
* The DNS address is only set if a valid address is provided (non-zero and not equal to IPADDR_NONE).
*
* @param server IP address of the DNS server.
* @param type Type of the DNS server (main, backup, fallback).
*
* @return esp_err_t Returns ESP_OK on success, or an error code on failure.
*/
static esp_err_t set_dns_server(const char *server, esp_netif_dns_type_t type)
{
int ret = 0;
struct addrinfo hint = {0};
struct addrinfo *res = NULL, *res_tmp = NULL;
esp_netif_t *esp_netif = NULL;
esp_netif_dns_info_t dns;
int addr_cnt = 0;
ret = getaddrinfo(server, NULL, &hint, &res);
if (ret != 0) {
printf("setdnsserver: Failure host:%s(ERROR: %d)\n", server, ret);
ESP_LOGE(TAG, "Failure host");
return 1;
}
for (res_tmp = res; res_tmp != NULL; res_tmp = res_tmp->ai_next) {
if (addr_cnt == 0) {
if (res_tmp->ai_family == AF_INET) {
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
while ((esp_netif = esp_netif_next_unsafe(esp_netif)) != NULL) {
#else
while ((esp_netif = esp_netif_next(esp_netif)) != NULL) {
#endif
struct sockaddr_in *ipv4 = (struct sockaddr_in *)res_tmp->ai_addr;
dns.ip.u_addr.ip4.addr = ipv4->sin_addr.s_addr;
dns.ip.type = IPADDR_TYPE_V4;
ESP_ERROR_CHECK(esp_netif_set_dns_info(esp_netif, type, &dns));
}
} else if (res_tmp->ai_family == AF_INET6) {
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
while ((esp_netif = esp_netif_next_unsafe(esp_netif)) != NULL) {
#else
while ((esp_netif = esp_netif_next(esp_netif)) != NULL) {
#endif
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)res_tmp->ai_addr;
memcpy(dns.ip.u_addr.ip6.addr, &ipv6->sin6_addr, sizeof(dns.ip.u_addr.ip6.addr));
dns.ip.type = IPADDR_TYPE_V6;
ESP_ERROR_CHECK(esp_netif_set_dns_info(esp_netif, type, &dns));
}
} else {
ESP_LOGE(TAG, "ai_family Unknown: %d\n", res_tmp->ai_family);
}
}
addr_cnt++;
}
freeaddrinfo(res);
return ESP_OK;
}
/**
* @brief Command handler for setting DNS server addresses.
*
* @param argc Argument count.
* @param argv Argument values.
*
* @return int: 0 on success, 1 on error.
*/
static int do_setdnsserver_cmd(int argc, char **argv)
{
int nerrors = arg_parse(argc, argv, (void **)&setdnsserver_args);
if (nerrors != 0) {
arg_print_errors(stderr, setdnsserver_args.end, argv[0]);
return 1;
}
set_dns_server(setdnsserver_args.main->sval[0], ESP_NETIF_DNS_MAIN);
if (setdnsserver_args.backup->count > 0) {
set_dns_server(setdnsserver_args.backup->sval[0], ESP_NETIF_DNS_BACKUP);
}
if (setdnsserver_args.fallback->count > 0) {
set_dns_server(setdnsserver_args.fallback->sval[0], ESP_NETIF_DNS_FALLBACK);
}
return 0;
}
/**
* @brief Registers the setdnsserver command.
*
* @return esp_err_t Returns ESP_OK on success, or an error code on failure.
*/
esp_err_t console_cmd_setdnsserver_register(void)
{
esp_err_t ret;
setdnsserver_args.main = arg_str1(NULL, NULL, "<main>", "The main DNS server IP address.");
setdnsserver_args.backup = arg_str0(NULL, NULL, "backup", "The secondary DNS server IP address (optional).");
setdnsserver_args.fallback = arg_str0(NULL, NULL, "fallback", "The fallback DNS server IP address (optional).");
setdnsserver_args.end = arg_end(1);
const esp_console_cmd_t setdnsserver_cmd = {
.command = "setdnsserver",
.help = "Usage: setdnsserver <main> [backup] [fallback]",
.hint = NULL,
.func = &do_setdnsserver_cmd,
.argtable = &setdnsserver_args
};
ret = esp_console_cmd_register(&setdnsserver_cmd);
if (ret) {
ESP_LOGE(TAG, "Unable to register setdnsserver");
}
return ret;
}
/**
* @brief Structure to hold arguments for the getdnsserver command.
*/
static struct {
struct arg_end *end;
} getdnsserver_args;
/**
* @brief Command handler for getting DNS server addresses.
*
* @param argc Argument count.
* @param argv Argument values.
*
* @return int: 0 on success, 1 on error.
*/
static int do_getdnsserver_cmd(int argc, char **argv)
{
esp_netif_t *esp_netif = NULL;
esp_netif_dns_info_t dns_info;
char interface[10];
esp_err_t ret = ESP_FAIL;
int nerrors = arg_parse(argc, argv, (void **)&getdnsserver_args);
if (nerrors != 0) {
arg_print_errors(stderr, getdnsserver_args.end, argv[0]);
return 1;
}
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
while ((esp_netif = esp_netif_next_unsafe(esp_netif)) != NULL) {
#else
while ((esp_netif = esp_netif_next(esp_netif)) != NULL) {
#endif
/* Print Interface Name and Number */
ret = esp_netif_get_netif_impl_name(esp_netif, interface);
if ((ESP_FAIL == ret) || (NULL == esp_netif)) {
ESP_LOGE(TAG, "No interface available");
return 1;
}
printf("Interface Name: %s\n", interface);
ESP_ERROR_CHECK(esp_netif_get_dns_info(esp_netif, ESP_NETIF_DNS_MAIN, &dns_info));
if (dns_info.ip.type == ESP_IPADDR_TYPE_V4) {
printf("Main DNS server : " IPSTR "\n", IP2STR(&dns_info.ip.u_addr.ip4));
} else if (dns_info.ip.type == ESP_IPADDR_TYPE_V6) {
printf("Main DNS server : " IPV6STR "\n", IPV62STR(dns_info.ip.u_addr.ip6));
}
ESP_ERROR_CHECK(esp_netif_get_dns_info(esp_netif, ESP_NETIF_DNS_BACKUP, &dns_info));
if (dns_info.ip.type == ESP_IPADDR_TYPE_V4) {
printf("Backup DNS server : " IPSTR "\n", IP2STR(&dns_info.ip.u_addr.ip4));
} else if (dns_info.ip.type == ESP_IPADDR_TYPE_V6) {
printf("Backup DNS server : " IPV6STR "\n", IPV62STR(dns_info.ip.u_addr.ip6));
}
ESP_ERROR_CHECK(esp_netif_get_dns_info(esp_netif, ESP_NETIF_DNS_FALLBACK, &dns_info));
if (dns_info.ip.type == ESP_IPADDR_TYPE_V4) {
printf("Fallback DNS server : " IPSTR "\n", IP2STR(&dns_info.ip.u_addr.ip4));
} else if (dns_info.ip.type == ESP_IPADDR_TYPE_V6) {
printf("Fallback DNS server : " IPV6STR "\n", IPV62STR(dns_info.ip.u_addr.ip6));
}
}
return 0;
}
/**
* @brief Registers the getdnsserver command.
*
* @return esp_err_t Returns ESP_OK on success, or an error code on failure.
*/
esp_err_t console_cmd_getdnsserver_register(void)
{
esp_err_t ret;
getdnsserver_args.end = arg_end(1);
const esp_console_cmd_t getdnsserver_cmd = {
.command = "getdnsserver",
.help = "Usage: getdnsserver",
.hint = NULL,
.func = &do_getdnsserver_cmd,
.argtable = &getdnsserver_args
};
ret = esp_console_cmd_register(&getdnsserver_cmd);
if (ret) {
ESP_LOGE(TAG, "Unable to register getdnsserver");
}
return ret;
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -20,7 +20,7 @@
static const char *TAG = "console_ping";
SemaphoreHandle_t sync_semaphore;
#if CONFIG_PING_CMD_AUTO_REGISTRATION
/**
* Static registration of this plugin is achieved by defining the plugin description
* structure and placing it into .console_cmd_desc section.
@ -30,7 +30,7 @@ static const console_cmd_plugin_desc_t __attribute__((section(".console_cmd_desc
.name = "console_cmd_ping",
.plugin_regd_fn = &console_cmd_ping_register
};
#endif
static void cmd_ping_on_ping_success(esp_ping_handle_t hdl, void *args)
{
@ -75,13 +75,9 @@ static void cmd_ping_on_ping_end(esp_ping_handle_t hdl, void *args)
loss = 0;
}
if (IP_IS_V4(&target_addr)) {
#if CONFIG_LWIP_IPV4
printf("\n--- %s ping statistics ---\n", inet_ntoa(*ip_2_ip4(&target_addr)));
#endif
} else {
#if CONFIG_LWIP_IPV6
printf("\n--- %s ping statistics ---\n", inet6_ntoa(*ip_2_ip6(&target_addr)));
#endif
}
printf("%" PRIu32 " packets transmitted, %" PRIu32 " received, %" PRIu32 "%% packet loss, time %" PRIu32 "ms\n",
transmitted, received, loss, total_time_ms);
@ -154,15 +150,11 @@ static int do_ping_cmd(int argc, char **argv)
return 1;
}
if (res->ai_family == AF_INET) {
#if CONFIG_LWIP_IPV4
struct in_addr addr4 = ((struct sockaddr_in *) (res->ai_addr))->sin_addr;
inet_addr_to_ip4addr(ip_2_ip4(&target_addr), &addr4);
#endif
} else {
#if CONFIG_LWIP_IPV6
struct in6_addr addr6 = ((struct sockaddr_in6 *) (res->ai_addr))->sin6_addr;
inet6_addr_to_ip6addr(ip_2_ip6(&target_addr), &addr6);
#endif
}
freeaddrinfo(res);
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -20,30 +20,6 @@ extern "C" {
*/
esp_err_t console_cmd_ping_register(void);
/**
* @brief Registers the getddrinfo command.
*
* @return
* - esp_err_t
*/
esp_err_t console_cmd_getaddrinfo_register(void);
/**
* @brief Registers the setdnsserver command.
*
* @return
* - esp_err_t
*/
esp_err_t console_cmd_setdnsserver_register(void);
/**
* @brief Registers the setdnsserver command.
*
* @return
* - esp_err_t
*/
esp_err_t console_cmd_getdnsserver_register(void);
#ifdef __cplusplus
}
#endif

View File

@ -1,4 +1,4 @@
version: 1.1.0
version: 1.0.0
url: https://github.com/espressif/esp-protocols/tree/master/components/console_cmd_ping
description: The component provides a console where the 'ping' command can be executed.
dependencies:

View File

@ -3,6 +3,6 @@ commitizen:
bump_message: 'bump(console): $current_version -> $new_version'
pre_bump_hooks: python ../../ci/changelog.py console_cmd_wifi
tag_format: console_cmd_wifi-v$version
version: 1.1.0
version: 1.0.1
version_files:
- idf_component.yml

View File

@ -1,11 +1,5 @@
# Changelog
## [1.1.0](https://github.com/espressif/esp-protocols/commits/console_cmd_wifi-v1.1.0)
### Features
- Added support to join pre-configured network ([bdbf16c1](https://github.com/espressif/esp-protocols/commit/bdbf16c1))
## [1.0.1](https://github.com/espressif/esp-protocols/commits/console_cmd_wifi-v1.0.1)
### Features

View File

@ -1,8 +1,4 @@
idf_component_register(SRCS "console_wifi.c"
INCLUDE_DIRS "include"
REQUIRES lwip
PRIV_REQUIRES esp_netif console esp_wifi esp_timer)
if(CONFIG_WIFI_CMD_AUTO_REGISTRATION)
target_link_libraries(${COMPONENT_LIB} "-u console_cmd_wifi_register")
endif()
INCLUDE_DIRS "."
PRIV_REQUIRES esp_netif console esp_wifi
WHOLE_ARCHIVE)

View File

@ -1,22 +0,0 @@
menu "Wifi command Configuration"
config WIFI_CMD_AUTO_REGISTRATION
bool "Enable Console command wifi Auto-registration"
default y
help
Enabling this allows for the autoregistration of the wifi command.
config WIFI_CMD_NETWORK_SSID
string "WiFi SSID"
default "myssid"
help
SSID (network name) to connect to.
config WIFI_CMD_NETWORK_PASSWORD
string "WiFi Password"
default "mypassword"
help
WiFi password (WPA or WPA2) to use.
Can be left blank if the network has no security set.
endmenu

View File

@ -33,16 +33,12 @@ The component offers a console with a command that enables runtime wifi configur
ESP_ERROR_CHECK(console_cmd_start()); // Start console
```
Note: Auto-registration of a specific plugin command can be disabled from menuconfig.
## Suported command:
### wifi:
```
wifi help: Prints the help text for all wifi commands
wifi show network/sta: Scans and displays all available wifi APs./ Shows the details of wifi station.
wifi sta join <network ssid> <password>: Station joins the given wifi network.
wifi sta join <network ssid>: Station joins the given unsecured wifi network.
wifi sta join: Station joins the pre-configured wifi network.
wifi sta leave: Station leaves the wifi network.
```
* ```wifi help```: Prints the help text for all wifi commands
* ```wifi show network```: Scans and displays upto 10 available wifi networks.
* ```wifi show sta```: Shows the details of wifi station.
* ```wifi sta join <network ssid> <password>```: Station joins the given wifi network.
* ```wifi sta join <network ssid>```: Station joins the given unsecured wifi network.
* ```wifi sta leave```: Station leaves the wifi network.

View File

@ -21,7 +21,6 @@
#define DEFAULT_SCAN_LIST_SIZE 10
#if CONFIG_WIFI_CMD_AUTO_REGISTRATION
/**
* Static registration of this plugin is achieved by defining the plugin description
* structure and placing it into .console_cmd_desc section.
@ -31,7 +30,6 @@ static const console_cmd_plugin_desc_t __attribute__((section(".console_cmd_desc
.name = "console_cmd_wifi",
.plugin_regd_fn = &console_cmd_wifi_register
};
#endif
typedef struct wifi_op_t {
char *name;
@ -57,9 +55,8 @@ static const int CONNECTED_BIT = BIT1;
static wifi_op_t cmd_list[] = {
{.name = "help", .operation = wifi_help_op, .arg_cnt = 2, .start_index = 1, .help = "wifi help: Prints the help text for all wifi commands"},
{.name = "show", .operation = wifi_show_op, .arg_cnt = 3, .start_index = 1, .help = "wifi show network/sta: Scans and displays all available wifi APs./ Shows the details of wifi station."},
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 5, .start_index = 2, .help = "wifi sta join <network ssid> <password>: Station joins the given wifi network."},
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 4, .start_index = 2, .help = "wifi sta join <network ssid>: Station joins the given unsecured wifi network."},
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 3, .start_index = 2, .help = "wifi sta join: Station joins the pre-configured wifi network."},
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 4, .start_index = 2, .help = "wifi sta join <network ssid> <password>: Station joins the given wifi network."},
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 5, .start_index = 2, .help = "wifi sta join <network ssid>: Station joins the given unsecured wifi network."},
{.name = "leave", .operation = wifi_sta_leave_op, .arg_cnt = 3, .start_index = 2, .help = "wifi sta leave: Station leaves the wifi network."},
};
@ -165,6 +162,7 @@ static esp_err_t wifi_show_op(wifi_op_t *self, int argc, char *argv[])
ESP_LOGI(TAG, "Showing Joind AP details:");
ESP_LOGI(TAG, "*************************");
ESP_LOGI(TAG, "SSID: %s", wifi_config.sta.ssid);
ESP_LOGI(TAG, "Password: %s", wifi_config.sta.password);
ESP_LOGI(TAG, "Channel: %d", wifi_config.sta.channel);
ESP_LOGI(TAG, "bssid: %02x:%02x:%02x:%02x:%02x:%02x", wifi_config.sta.bssid[0],
wifi_config.sta.bssid[1], wifi_config.sta.bssid[2], wifi_config.sta.bssid[3],
@ -186,13 +184,7 @@ static esp_err_t wifi_sta_join_op(wifi_op_t *self, int argc, char *argv[])
return ESP_FAIL;
}
if (self->arg_cnt == 3) {
strlcpy((char *) wifi_config.sta.ssid, CONFIG_WIFI_CMD_NETWORK_SSID, sizeof(wifi_config.sta.ssid));
strlcpy((char *) wifi_config.sta.password, CONFIG_WIFI_CMD_NETWORK_PASSWORD, sizeof(wifi_config.sta.password));
} else {
strlcpy((char *) wifi_config.sta.ssid, argv[self->start_index + 1], sizeof(wifi_config.sta.ssid));
}
strlcpy((char *) wifi_config.sta.ssid, argv[self->start_index + 1], sizeof(wifi_config.sta.ssid));
if (self->arg_cnt == 5) {
strlcpy((char *) wifi_config.sta.password, argv[self->start_index + 2], sizeof(wifi_config.sta.password));
}
@ -268,7 +260,7 @@ static esp_err_t do_cmd_wifi(int argc, char **argv)
*/
esp_err_t console_cmd_wifi_register(void)
{
esp_err_t ret = ESP_OK;
esp_err_t ret;
esp_console_cmd_t command = {
.command = "wifi",
.help = "Command for wifi configuration and monitoring\n For more info run 'wifi help'",

View File

@ -1,4 +1,4 @@
version: 1.1.0
version: 1.0.1
url: https://github.com/espressif/esp-protocols/tree/master/components/console_cmd_wifi
description: The component offers a console that enables runtime wifi configuration and monitoring.
dependencies:

View File

@ -3,6 +3,6 @@ commitizen:
bump_message: 'bump(eppp): $current_version -> $new_version'
pre_bump_hooks: python ../../ci/changelog.py eppp_link
tag_format: eppp-v$version
version: 0.2.0
version: 0.1.1
version_files:
- idf_component.yml

View File

@ -1,16 +1,5 @@
# Changelog
## [0.2.0](https://github.com/espressif/esp-protocols/commits/eppp-v0.2.0)
### Features
- Add support for SDIO transport ([085dd790](https://github.com/espressif/esp-protocols/commit/085dd790))
### Bug Fixes
- Fixed strict prototype API decl issue in SDIO ([eb09e426](https://github.com/espressif/esp-protocols/commit/eb09e426))
- Fix SIDO host to check/clear interrupts atomically ([402176c9](https://github.com/espressif/esp-protocols/commit/402176c9))
## [0.1.1](https://github.com/espressif/esp-protocols/commits/eppp-v0.1.1)
### Bug Fixes

View File

@ -1,3 +1,3 @@
idf_component_register(SRCS eppp_link.c eppp_sdio_slave.c eppp_sdio_host.c
idf_component_register(SRCS "eppp_link.c"
INCLUDE_DIRS "include"
PRIV_REQUIRES esp_netif esp_driver_spi esp_driver_gpio esp_timer driver)

View File

@ -21,13 +21,6 @@ menu "eppp_link"
bool "SPI"
help
Use SPI.
config EPPP_LINK_DEVICE_SDIO
bool "SDIO"
depends on SOC_SDMMC_HOST_SUPPORTED || SOC_SDIO_SLAVE_SUPPORTED
help
Use SDIO.
endchoice
config EPPP_LINK_CONN_MAX_RETRY
@ -41,30 +34,8 @@ menu "eppp_link"
config EPPP_LINK_PACKET_QUEUE_SIZE
int "Packet queue size"
default 64
depends on EPPP_LINK_DEVICE_SPI
help
Size of the Tx packet queue.
You can decrease the number for slower bit rates.
choice EPPP_LINK_SDIO_ROLE
prompt "Choose SDIO host or slave"
depends on EPPP_LINK_DEVICE_SDIO
default EPPP_LINK_DEVICE_SDIO_HOST if SOC_SDMMC_HOST_SUPPORTED
help
Select which either SDIO host or slave
config EPPP_LINK_DEVICE_SDIO_HOST
bool "Host"
depends on SOC_SDMMC_HOST_SUPPORTED
help
Use SDIO host.
config EPPP_LINK_DEVICE_SDIO_SLAVE
bool "SLAVE"
depends on SOC_SDIO_SLAVE_SUPPORTED
help
Use SDIO slave.
endchoice
endmenu

View File

@ -14,7 +14,7 @@ brings in the WiFi connectivity from the "SLAVE" microcontroller.
SLAVE micro HOST micro
\|/ +----------------+ +----------------+
| | | serial line | |
+---+ WiFi NAT PPPoS |=== UART / SPI / SDIO =====| PPPoS client |
+---+ WiFi NAT PPPoS |======== UART / SPI =======| PPPoS client |
| (server)| | |
+----------------+ +----------------+
```
@ -39,19 +39,14 @@ brings in the WiFi connectivity from the "SLAVE" microcontroller.
## Throughput
Tested with WiFi-NAPT example
Tested with WiFi-NAPT example, no IRAM optimizations
### UART @ 3Mbauds
* TCP - 2Mbits/s
* UDP - 2Mbits/s
### SPI @ 16MHz
### SPI @ 20MHz
* TCP - 5Mbits/s
* UDP - 8Mbits/s
### SDIO
* TCP - 9Mbits/s
* UDP - 11Mbits/s
* TCP - 6Mbits/s
* UDP - 10Mbits/s

View File

@ -12,7 +12,6 @@
#include "esp_event.h"
#include "esp_netif_ppp.h"
#include "eppp_link.h"
#include "esp_serial_slave_link/essl_sdio.h"
#if CONFIG_EPPP_LINK_DEVICE_SPI
#include "driver/spi_master.h"
@ -87,18 +86,7 @@ struct eppp_handle {
bool netif_stop;
};
typedef esp_err_t (*transmit_t)(void *h, void *buffer, size_t len);
#if CONFIG_EPPP_LINK_DEVICE_SDIO
esp_err_t eppp_sdio_host_tx(void *h, void *buffer, size_t len);
esp_err_t eppp_sdio_host_rx(esp_netif_t *netif);
esp_err_t eppp_sdio_slave_rx(esp_netif_t *netif);
esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len);
esp_err_t eppp_sdio_host_init(struct eppp_config_sdio_s *config);
esp_err_t eppp_sdio_slave_init(void);
void eppp_sdio_slave_deinit(void);
void eppp_sdio_host_deinit(void);
#else
static esp_err_t transmit(void *h, void *buffer, size_t len)
{
struct eppp_handle *handle = h;
@ -137,10 +125,9 @@ static esp_err_t transmit(void *h, void *buffer, size_t len)
#elif CONFIG_EPPP_LINK_DEVICE_UART
ESP_LOG_BUFFER_HEXDUMP("ppp_uart_send", buffer, len, ESP_LOG_VERBOSE);
uart_write_bytes(handle->uart_port, buffer, len);
#endif // DEVICE UART or SPI
#endif
return ESP_OK;
}
#endif
static void netif_deinit(esp_netif_t *netif)
{
@ -222,11 +209,7 @@ static esp_netif_t *netif_init(eppp_type_t role, eppp_config_t *eppp_config)
esp_netif_driver_ifconfig_t driver_cfg = {
.handle = h,
#if CONFIG_EPPP_LINK_DEVICE_SDIO
.transmit = role == EPPP_CLIENT ? eppp_sdio_host_tx : eppp_sdio_slave_tx,
#else
.transmit = transmit,
#endif
};
const esp_netif_driver_ifconfig_t *ppp_driver_cfg = &driver_cfg;
@ -674,20 +657,6 @@ esp_err_t eppp_perform(esp_netif_t *netif)
}
return ESP_OK;
}
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
esp_err_t eppp_perform(esp_netif_t *netif)
{
struct eppp_handle *h = esp_netif_get_io_driver(netif);
if (h->stop) {
return ESP_ERR_TIMEOUT;
}
if (h->role == EPPP_SERVER) {
return eppp_sdio_slave_rx(netif);
} else {
return eppp_sdio_host_rx(netif);
}
}
#endif // CONFIG_EPPP_LINK_DEVICE_SPI / UART
@ -731,13 +700,6 @@ void eppp_deinit(esp_netif_t *netif)
}
#elif CONFIG_EPPP_LINK_DEVICE_UART
deinit_uart(esp_netif_get_io_driver(netif));
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
struct eppp_handle *h = esp_netif_get_io_driver(netif);
if (h->role == EPPP_CLIENT) {
eppp_sdio_host_deinit();
} else {
eppp_sdio_slave_deinit();
}
#endif
netif_deinit(netif);
}
@ -752,6 +714,7 @@ esp_netif_t *eppp_init(eppp_type_t role, eppp_config_t *config)
esp_netif_t *netif = netif_init(role, config);
if (!netif) {
ESP_LOGE(TAG, "Failed to initialize PPP netif");
remove_handlers();
return NULL;
}
esp_netif_ppp_config_t netif_params;
@ -769,18 +732,6 @@ esp_netif_t *eppp_init(eppp_type_t role, eppp_config_t *config)
}
#elif CONFIG_EPPP_LINK_DEVICE_UART
init_uart(esp_netif_get_io_driver(netif), config);
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
esp_err_t ret;
if (role == EPPP_SERVER) {
ret = eppp_sdio_slave_init();
} else {
ret = eppp_sdio_host_init(&config->sdio);
}
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize SDIO %d", ret);
return NULL;
}
#endif
return netif;
}
@ -803,12 +754,6 @@ esp_netif_t *eppp_open(eppp_type_t role, eppp_config_t *config, int connect_time
return NULL;
}
#endif
#if CONFIG_EPPP_LINK_DEVICE_SDIO
if (config->transport != EPPP_TRANSPORT_SDIO) {
ESP_LOGE(TAG, "Invalid transport: SDIO device must be enabled in Kconfig");
return NULL;
}
#endif
if (config->task.run_task == false) {
ESP_LOGE(TAG, "task.run_task == false is invalid in this API. Please use eppp_init()");

View File

@ -1,19 +0,0 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#define MAX_SDIO_PAYLOAD 1500
#define SDIO_ALIGN(size) (((size) + 3U) & ~(3U))
#define SDIO_PAYLOAD SDIO_ALIGN(MAX_SDIO_PAYLOAD)
#define PPP_SOF 0x7E
// Interrupts and registers
#define SLAVE_INTR 0
#define SLAVE_REG_REQ 0
// Requests from host to slave
#define REQ_RESET 1
#define REQ_INIT 2

View File

@ -1,200 +0,0 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <stdint.h>
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "driver/sdio_slave.h"
#include "esp_serial_slave_link/essl_sdio.h"
#include "eppp_sdio.h"
#include "driver/sdmmc_host.h"
#include "sdmmc_cmd.h"
#include "esp_check.h"
#include "eppp_link.h"
#if CONFIG_EPPP_LINK_DEVICE_SDIO_HOST
// For blocking operations
#define TIMEOUT_MAX UINT32_MAX
// Short timeout for sending/receiving ESSL packets
#define PACKET_TIMEOUT_MS 50
static const char *TAG = "eppp_sdio_host";
static SemaphoreHandle_t s_essl_mutex = NULL;
static essl_handle_t s_essl = NULL;
static sdmmc_card_t *s_card = NULL;
static DRAM_DMA_ALIGNED_ATTR uint8_t send_buffer[SDIO_PAYLOAD];
static DMA_ATTR uint8_t rcv_buffer[SDIO_PAYLOAD];
esp_err_t eppp_sdio_host_tx(void *h, void *buffer, size_t len)
{
if (s_essl == NULL || s_essl_mutex == NULL) {
// silently skip the Tx if the SDIO not fully initialized
return ESP_OK;
}
memcpy(send_buffer, buffer, len);
size_t send_len = SDIO_ALIGN(len);
if (send_len > len) {
// pad with SOF's
memset(&send_buffer[len], PPP_SOF, send_len - len);
}
xSemaphoreTake(s_essl_mutex, portMAX_DELAY);
esp_err_t ret = essl_send_packet(s_essl, send_buffer, send_len, PACKET_TIMEOUT_MS);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Slave not ready to receive packet %x", ret);
vTaskDelay(pdMS_TO_TICKS(1000));
ret = ESP_ERR_NO_MEM; // to inform the upper layers
}
ESP_LOG_BUFFER_HEXDUMP(TAG, send_buffer, send_len, ESP_LOG_VERBOSE);
xSemaphoreGive(s_essl_mutex);
return ret;
}
static esp_err_t request_slave_reset(void)
{
esp_err_t ret = ESP_OK;
ESP_LOGI(TAG, "send reset to slave...");
ESP_GOTO_ON_ERROR(essl_write_reg(s_essl, SLAVE_REG_REQ, REQ_RESET, NULL, TIMEOUT_MAX), err, TAG, "write-reg failed");
ESP_GOTO_ON_ERROR(essl_send_slave_intr(s_essl, BIT(SLAVE_INTR), TIMEOUT_MAX), err, TAG, "send-intr failed");
vTaskDelay(pdMS_TO_TICKS(PACKET_TIMEOUT_MS));
ESP_GOTO_ON_ERROR(essl_wait_for_ready(s_essl, TIMEOUT_MAX), err, TAG, "wait-for-ready failed");
ESP_LOGI(TAG, "slave io ready");
err:
return ret;
}
esp_err_t eppp_sdio_host_init(struct eppp_config_sdio_s *eppp_config)
{
esp_err_t ret = ESP_OK;
ESP_GOTO_ON_ERROR(sdmmc_host_init(), err, TAG, "sdmmc host init failed");
// configure SDIO interface and slot
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
slot_config.width = eppp_config->width;
#ifdef CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
slot_config.clk = eppp_config->clk;
slot_config.cmd = eppp_config->cmd;
slot_config.d0 = eppp_config->d0;
slot_config.d1 = eppp_config->d1;
slot_config.d2 = eppp_config->d2;
slot_config.d3 = eppp_config->d3;
#endif
ESP_GOTO_ON_ERROR(sdmmc_host_init_slot(SDMMC_HOST_SLOT_1, &slot_config), err, TAG, "init sdmmc host slot failed");
sdmmc_host_t config = SDMMC_HOST_DEFAULT();
config.flags = SDMMC_HOST_FLAG_4BIT;
config.flags |= SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF;
config.max_freq_khz = SDMMC_FREQ_HIGHSPEED;
s_card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t));
ESP_GOTO_ON_FALSE(s_card, ESP_ERR_NO_MEM, err, TAG, "card allocation failed");
ESP_GOTO_ON_ERROR(sdmmc_card_init(&config, s_card), err, TAG, "sdmmc card init failed");
essl_sdio_config_t ser_config = {
.card = s_card,
.recv_buffer_size = SDIO_PAYLOAD,
};
ESP_GOTO_ON_FALSE(essl_sdio_init_dev(&s_essl, &ser_config) == ESP_OK && s_essl, ESP_FAIL, err, TAG, "essl_sdio_init_dev failed");
ESP_GOTO_ON_ERROR(essl_init(s_essl, TIMEOUT_MAX), err, TAG, "essl-init failed");
ESP_GOTO_ON_ERROR(request_slave_reset(), err, TAG, "failed to reset the slave");
ESP_GOTO_ON_FALSE((s_essl_mutex = xSemaphoreCreateMutex()), ESP_ERR_NO_MEM, err, TAG, "failed to create semaphore");
return ret;
err:
essl_sdio_deinit_dev(s_essl);
s_essl = NULL;
return ret;
}
static esp_err_t get_intr(uint32_t *out_raw)
{
esp_err_t ret = ESP_OK;
ESP_GOTO_ON_ERROR(essl_get_intr(s_essl, out_raw, NULL, 0), err, TAG, "essl-get-int failed");
ESP_GOTO_ON_ERROR(essl_clear_intr(s_essl, *out_raw, 0), err, TAG, "essl-clear-int failed");
ESP_LOGD(TAG, "intr: %08"PRIX32, *out_raw);
err:
return ret;
}
esp_err_t eppp_sdio_host_rx(esp_netif_t *netif)
{
uint32_t intr;
esp_err_t err = essl_wait_int(s_essl, TIMEOUT_MAX);
if (err == ESP_ERR_TIMEOUT) {
return ESP_OK;
}
xSemaphoreTake(s_essl_mutex, portMAX_DELAY);
err = get_intr(&intr);
if (err == ESP_ERR_TIMEOUT) {
xSemaphoreGive(s_essl_mutex);
return ESP_OK;
}
if (err != ESP_OK) {
ESP_LOGE(TAG, "failed to check for interrupts %d", err);
xSemaphoreGive(s_essl_mutex);
return ESP_FAIL;
}
if (intr & ESSL_SDIO_DEF_ESP32.new_packet_intr_mask) {
esp_err_t ret;
do {
size_t size_read = SDIO_PAYLOAD;
ret = essl_get_packet(s_essl, rcv_buffer, SDIO_PAYLOAD, &size_read, PACKET_TIMEOUT_MS);
if (ret == ESP_ERR_NOT_FOUND) {
ESP_LOGE(TAG, "interrupt but no data can be read");
break;
} else if (ret == ESP_OK) {
ESP_LOGD(TAG, "receive data, size: %d", size_read);
ESP_LOG_BUFFER_HEXDUMP(TAG, rcv_buffer, size_read, ESP_LOG_VERBOSE);
esp_netif_receive(netif, rcv_buffer, size_read, NULL);
break;
} else {
ESP_LOGE(TAG, "rx packet error: %08X", ret);
if (request_slave_reset() != ESP_OK) {
ESP_LOGE(TAG, "Failed to request slave reset %x", ret);
break;
}
}
} while (ret == ESP_ERR_NOT_FINISHED);
}
xSemaphoreGive(s_essl_mutex);
return ESP_OK;
}
void eppp_sdio_host_deinit(void)
{
essl_sdio_deinit_dev(s_essl);
sdmmc_host_deinit();
free(s_card);
s_card = NULL;
s_essl = NULL;
}
#else // SDMMC_HOST NOT-SUPPORTED
esp_err_t eppp_sdio_host_tx(void *handle, void *buffer, size_t len)
{
return ESP_ERR_NOT_SUPPORTED;
}
esp_err_t eppp_sdio_host_rx(esp_netif_t *netif)
{
return ESP_ERR_NOT_SUPPORTED;
}
void eppp_sdio_host_deinit(void)
{
}
esp_err_t eppp_sdio_host_init(struct eppp_config_sdio_s *config)
{
return ESP_ERR_NOT_SUPPORTED;
}
#endif // CONFIG_SOC_SDIO_SLAVE_SUPPORTED

View File

@ -1,174 +0,0 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <stdint.h>
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "driver/sdio_slave.h"
#include "eppp_sdio.h"
#include "esp_check.h"
#if CONFIG_EPPP_LINK_DEVICE_SDIO_SLAVE
#define BUFFER_NUM 4
#define BUFFER_SIZE SDIO_PAYLOAD
static const char *TAG = "eppp_sdio_slave";
static DMA_ATTR uint8_t sdio_slave_rx_buffer[BUFFER_NUM][BUFFER_SIZE];
static DMA_ATTR uint8_t sdio_slave_tx_buffer[SDIO_PAYLOAD];
static int s_slave_request = 0;
esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len)
{
if (s_slave_request != REQ_INIT) {
// silently skip the Tx if the SDIO not fully initialized
return ESP_OK;
}
memcpy(sdio_slave_tx_buffer, buffer, len);
size_t send_len = SDIO_ALIGN(len);
if (send_len > len) {
// pad with SOF's if the size is not 4 bytes aligned
memset(&sdio_slave_tx_buffer[len], PPP_SOF, send_len - len);
}
ESP_LOG_BUFFER_HEXDUMP(TAG, sdio_slave_tx_buffer, send_len, ESP_LOG_VERBOSE);
esp_err_t ret = sdio_slave_transmit(sdio_slave_tx_buffer, send_len);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "sdio slave transmit error, ret : 0x%x", ret);
// to inform the upper layers
return ESP_ERR_NO_MEM;
}
return ESP_OK;
}
static esp_err_t slave_reset(void)
{
esp_err_t ret = ESP_OK;
ESP_LOGI(TAG, "SDIO slave reset");
sdio_slave_stop();
ESP_GOTO_ON_ERROR(sdio_slave_reset(), err, TAG, "slave reset failed");
ESP_GOTO_ON_ERROR(sdio_slave_start(), err, TAG, "slave start failed");
while (1) {
sdio_slave_buf_handle_t handle;
ret = sdio_slave_send_get_finished(&handle, 0);
if (ret == ESP_ERR_TIMEOUT) {
break;
}
ESP_GOTO_ON_ERROR(ret, err, TAG, "slave-get-finished failed");
ESP_GOTO_ON_ERROR(sdio_slave_recv_load_buf(handle), err, TAG, "slave-load-buf failed");
}
err:
return ret;
}
esp_err_t eppp_sdio_slave_rx(esp_netif_t *netif)
{
if (s_slave_request == REQ_RESET) {
ESP_LOGD(TAG, "request: %x", s_slave_request);
slave_reset();
s_slave_request = REQ_INIT;
}
sdio_slave_buf_handle_t handle;
size_t length;
uint8_t *ptr;
esp_err_t ret = sdio_slave_recv_packet(&handle, pdMS_TO_TICKS(1000));
if (ret == ESP_ERR_TIMEOUT) {
return ESP_OK;
}
if (ret == ESP_ERR_NOT_FINISHED || ret == ESP_OK) {
again:
ptr = sdio_slave_recv_get_buf(handle, &length);
esp_netif_receive(netif, ptr, length, NULL);
if (sdio_slave_recv_load_buf(handle) != ESP_OK) {
ESP_LOGE(TAG, "Failed to recycle packet buffer");
return ESP_FAIL;
}
if (ret == ESP_ERR_NOT_FINISHED) {
ret = sdio_slave_recv_packet(&handle, 0);
if (ret == ESP_ERR_NOT_FINISHED || ret == ESP_OK) {
goto again;
}
}
ESP_LOG_BUFFER_HEXDUMP(TAG, ptr, length, ESP_LOG_VERBOSE);
return ESP_OK;
}
ESP_LOGE(TAG, "Error when receiving packet %d", ret);
return ESP_FAIL;
}
static void event_cb(uint8_t pos)
{
ESP_EARLY_LOGI(TAG, "SDIO event: %d", pos);
if (pos == SLAVE_INTR) {
s_slave_request = sdio_slave_read_reg(SLAVE_REG_REQ);
sdio_slave_write_reg(SLAVE_REG_REQ, 0);
}
}
esp_err_t eppp_sdio_slave_init(void)
{
sdio_slave_config_t config = {
.sending_mode = SDIO_SLAVE_SEND_PACKET,
.send_queue_size = BUFFER_NUM,
.recv_buffer_size = BUFFER_SIZE,
.event_cb = event_cb,
};
esp_err_t ret = sdio_slave_initialize(&config);
if (ret != ESP_OK) {
return ret;
}
for (int i = 0; i < BUFFER_NUM; i++) {
sdio_slave_buf_handle_t handle = sdio_slave_recv_register_buf(sdio_slave_rx_buffer[i]);
if (handle == NULL) {
sdio_slave_deinit();
return ESP_FAIL;
}
ret = sdio_slave_recv_load_buf(handle);
if (ret != ESP_OK) {
sdio_slave_deinit();
return ESP_FAIL;
}
}
sdio_slave_set_host_intena(SDIO_SLAVE_HOSTINT_SEND_NEW_PACKET); // only need one interrupt to notify of a new packet
ret = sdio_slave_start();
if (ret != ESP_OK) {
sdio_slave_deinit();
return ESP_FAIL;
}
return ESP_OK;
}
void eppp_sdio_slave_deinit(void)
{
sdio_slave_stop();
sdio_slave_deinit();
}
#else // SOC_SDIO_SLAVE NOT-SUPPORTED
esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len)
{
return ESP_ERR_NOT_SUPPORTED;
}
esp_err_t eppp_sdio_slave_rx(esp_netif_t *netif)
{
return ESP_ERR_NOT_SUPPORTED;
}
void eppp_sdio_slave_deinit(void)
{
}
esp_err_t eppp_sdio_slave_init(void)
{
return ESP_ERR_NOT_SUPPORTED;
}
#endif // CONFIG_SOC_SDIO_SLAVE_SUPPORTED

View File

@ -104,13 +104,11 @@ void app_main(void)
eppp_config_t config = EPPP_DEFAULT_CLIENT_CONFIG();
#if CONFIG_EPPP_LINK_DEVICE_SPI
config.transport = EPPP_TRANSPORT_SPI;
#elif CONFIG_EPPP_LINK_DEVICE_UART
#else
config.transport = EPPP_TRANSPORT_UART;
config.uart.tx_io = CONFIG_EXAMPLE_UART_TX_PIN;
config.uart.rx_io = CONFIG_EXAMPLE_UART_RX_PIN;
config.uart.baud = CONFIG_EXAMPLE_UART_BAUDRATE;
#else
config.transport = EPPP_TRANSPORT_SDIO;
#endif
esp_netif_t *eppp_netif = eppp_connect(&config);
if (eppp_netif == NULL) {

View File

@ -128,21 +128,16 @@ void app_main(void)
ESP_ERROR_CHECK(ret);
init_network_interface(); // WiFi station if withing SoC capabilities (otherwise a placeholder)
// ESP_ERROR_CHECK(esp_netif_init());
// ESP_ERROR_CHECK(esp_event_loop_create_default());
eppp_config_t config = EPPP_DEFAULT_SERVER_CONFIG();
#if CONFIG_EPPP_LINK_DEVICE_SPI
config.transport = EPPP_TRANSPORT_SPI;
#elif CONFIG_EPPP_LINK_DEVICE_UART
#else
config.transport = EPPP_TRANSPORT_UART;
config.uart.tx_io = CONFIG_EXAMPLE_UART_TX_PIN;
config.uart.rx_io = CONFIG_EXAMPLE_UART_RX_PIN;
config.uart.baud = CONFIG_EXAMPLE_UART_BAUDRATE;
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
config.transport = EPPP_TRANSPORT_SDIO;
#endif // transport device
#endif
esp_netif_t *eppp_netif = eppp_listen(&config);
if (eppp_netif == NULL) {
ESP_LOGE(TAG, "Failed to setup connection");

View File

@ -1,6 +1,6 @@
version: 0.2.0
version: 0.1.1
url: https://github.com/espressif/esp-protocols/tree/master/components/eppp_link
description: The component provides a general purpose PPP connectivity, typically used as WiFi-PPP router
dependencies:
idf: '>=5.2'
espressif/esp_serial_slave_link: "^1.1.0"
idf:
version: '>=5.2'

View File

@ -28,16 +28,7 @@
.rx_io = 26, \
.queue_size = 16, \
.rx_buffer_size = 1024, \
}, \
.sdio = { \
.width = 4, \
.clk = 18, \
.cmd = 19, \
.d0 = 49, \
.d1 = 50, \
.d2 = 16, \
.d3 = 17, \
}, \
}, \
. task = { \
.run_task = true, \
.stack_size = 4096, \
@ -62,7 +53,6 @@ typedef enum eppp_type {
typedef enum eppp_transport {
EPPP_TRANSPORT_UART,
EPPP_TRANSPORT_SPI,
EPPP_TRANSPORT_SDIO,
} eppp_transport_t;
@ -91,16 +81,6 @@ typedef struct eppp_config_t {
int rx_buffer_size;
} uart;
struct eppp_config_sdio_s {
int width;
int clk;
int cmd;
int d0;
int d1;
int d2;
int d3;
} sdio;
struct eppp_config_task_s {
bool run_task;
int stack_size;

View File

@ -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.3.0
version: 1.1.0
version_files:
- idf_component.yml

View File

@ -1,63 +1,5 @@
# 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

View File

@ -63,33 +63,4 @@ menu "esp-modem"
dce_factory::Factory::create_unique_dce_from<CustomModule, DCE*>(dce_config, std::move(dte), netif)
Please refer to the pppos_client example for more details.
config ESP_MODEM_C_API_STR_MAX
int "Size in bytes for response from AT commands returning textual values (C-API)"
default 128
help
Some AT commands returns textual values which C-API copy as c-string to user allocated space,
it also truncates the output data to this size. Increase this if some AT answers are truncated.
config ESP_MODEM_URC_HANDLER
bool "Enable support for adding URC handler"
default n
help
If enabled, APIs to add URC handler are available
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

View File

@ -15,3 +15,7 @@ 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.

View File

@ -17,3 +17,7 @@ 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.

View File

@ -16,12 +16,18 @@ class.
### USB DTE support
For USB enabled targets (ESP32-S2, ESP32-S3, or ESP32-P4), it is possible to connect to the modem device via USB.
For USB enabled targets (ESP32-S2 and ESP32-S3), it is possible to connect to the modem device via USB.
1. In menuconfig, navigate to `Example Configuration->Type of serial connection to the modem` and choose `USB`.
2. Connect the modem USB signals to your ESP chip (pin 19 (DATA-) and 20 (DATA+) for ESP32-S2/S3).
2. Connect the modem USB signals to pin 19 (DATA-) and 20 (DATA+) on your ESP chip.
USB example uses Quactel BG96 modem device. BG96 needs a positive pulse on its PWK pin to boot-up.
This example supports USB modem hot-plugging and reconnection. There is one limitation coming from esp_console component:
When esp_console REPL is being destroyed (after USB mode disconnection or after `exit` command), it will block on UART read.
You must send a character to it (via idf.py monitor), so it unblocks and properly exits.
### Supported IDF versions
This example is only supported from `v4.2`, due to support of the console repl mode.
USB example is supported from `v4.4`.

View File

@ -10,7 +10,7 @@ menu "Example Configuration"
Connect to modem via UART.
config EXAMPLE_SERIAL_CONFIG_USB
bool "USB"
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
help
Connect to modem via USB (CDC-ACM class). For IDF version >= 4.4.
endchoice
@ -36,11 +36,6 @@ menu "Example Configuration"
bool "BG96"
help
Quectel BG96 is a series of LTE Cat M1/Cat NB1/EGPRS module.
config EXAMPLE_MODEM_DEVICE_EC20
depends on EXAMPLE_SERIAL_CONFIG_USB
bool "EC20"
help
Quectel EC20 is a series of LTE Cat M4 module.
config EXAMPLE_MODEM_DEVICE_SIM7000
depends on EXAMPLE_SERIAL_CONFIG_UART
bool "SIM7000"
@ -108,28 +103,28 @@ menu "Example Configuration"
config EXAMPLE_MODEM_UART_TX_PIN
int "TXD Pin Number"
default 25
range 0 56
range 0 31
help
Pin number of UART TX.
config EXAMPLE_MODEM_UART_RX_PIN
int "RXD Pin Number"
default 26
range 0 56
range 0 31
help
Pin number of UART RX.
config EXAMPLE_MODEM_UART_RTS_PIN
int "RTS Pin Number"
default 27
range 0 56
range 0 31
help
Pin number of UART RTS.
config EXAMPLE_MODEM_UART_CTS_PIN
int "CTS Pin Number"
default 23
range 0 56
range 0 31
help
Pin number of UART CTS.
@ -179,7 +174,7 @@ menu "Example Configuration"
config EXAMPLE_MODEM_PWRKEY_PIN
int "PWRKEY Pin Number"
default 18
range 0 56
range 0 31
help
Pin number connected to modem's power key pin.
endmenu

View File

@ -6,7 +6,7 @@ dependencies:
version: "^1.0.0"
override_path: "../../../"
espressif/esp_modem_usb_dte:
version: "^1.2.0"
version: "^1.1.0"
rules:
- if: "idf_version >=4.4"
- if: "target in [esp32s2, esp32s3, esp32p4]"
- if: "target in [esp32s2, esp32s3]"

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 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_ESP_MODEM_URC_HANDLER
#ifdef CONFIG_EXAMPLE_MODEM_DEVICE_SHINY
command_result handle_urc(uint8_t *data, size_t len)
{
ESP_LOG_BUFFER_HEXDUMP("on_read", data, len, ESP_LOG_INFO);
@ -160,9 +160,6 @@ extern "C" void app_main(void)
#if CONFIG_EXAMPLE_MODEM_DEVICE_BG96 == 1
ESP_LOGI(TAG, "Initializing esp_modem for the BG96 module...");
struct esp_modem_usb_term_config usb_config = ESP_MODEM_BG96_USB_CONFIG();
#elif CONFIG_EXAMPLE_MODEM_DEVICE_EC20 == 1
ESP_LOGI(TAG, "Initializing esp_modem for the EC20 module...");
struct esp_modem_usb_term_config usb_config = ESP_MODEM_EC20_USB_CONFIG();
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1
ESP_LOGI(TAG, "Initializing esp_modem for the SIM7600 module...");
struct esp_modem_usb_term_config usb_config = ESP_MODEM_SIM7600_USB_CONFIG();
@ -183,7 +180,7 @@ extern "C" void app_main(void)
});
#if CONFIG_EXAMPLE_MODEM_DEVICE_BG96 == 1
std::unique_ptr<DCE> dce = create_BG96_dce(&dce_config, dte, esp_netif);
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1 || CONFIG_EXAMPLE_MODEM_DEVICE_A7670 == 1 || CONFIG_EXAMPLE_MODEM_DEVICE_EC20 == 1
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1 || CONFIG_EXAMPLE_MODEM_DEVICE_A7670 == 1
std::unique_ptr<DCE> dce = create_SIM7600_dce(&dce_config, dte, esp_netif);
#else
#error USB modem not selected
@ -238,9 +235,7 @@ 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 == "AUTO") {
dev_mode = esp_modem::modem_mode::AUTODETECT;
} else if (mode == "UNDEF") {
if (mode == "UNDEF") {
dev_mode = esp_modem::modem_mode::UNDEF;
} else if (mode == "CMUX1") {
dev_mode = esp_modem::modem_mode::CMUX_MANUAL_MODE;
@ -372,30 +367,19 @@ extern "C" void app_main(void)
ESP_LOGI(TAG, "Resetting the module...");
CHECK_ERR(dce->reset(), ESP_LOGI(TAG, "OK"));
});
#ifdef CONFIG_ESP_MODEM_URC_HANDLER
#ifdef CONFIG_EXAMPLE_MODEM_DEVICE_SHINY
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_urc(handle_urc);
dce->set_on_read(handle_urc);
} else {
ESP_LOGI(TAG, "URC removed");
dce->set_urc(nullptr);
dce->set_on_read(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)") {}

View File

@ -1,2 +0,0 @@
CONFIG_IDF_TARGET="esp32p4"
CONFIG_EXAMPLE_SERIAL_CONFIG_USB=y

View File

@ -20,14 +20,14 @@ menu "Example Configuration"
config EXAMPLE_MODEM_UART_TX_PIN
int "TXD Pin Number"
default 4
range 0 56
range 0 31
help
Pin number of UART TX.
config EXAMPLE_MODEM_UART_RX_PIN
int "RXD Pin Number"
default 5
range 0 56
range 0 31
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 56
range 0 31
help
Pin number connected to modem's power key pin.
config EXAMPLE_MODEM_STATUS_PIN
int "STATUS Pin Number"
default 19
range 0 56
range 0 31
help
Pin number connected to modem's status pin.

View File

@ -22,3 +22,7 @@ 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)
![with localhost listener](at_client_localhost.png)
### Supported IDF versions
This example is supported from IDF `v5.0`.

View File

@ -30,28 +30,28 @@ menu "Example Configuration"
config EXAMPLE_MODEM_UART_TX_PIN
int "TXD Pin Number"
default 25
range 0 56
range 0 31
help
Pin number of UART TX.
config EXAMPLE_MODEM_UART_RX_PIN
int "RXD Pin Number"
default 26
range 0 56
range 0 31
help
Pin number of UART RX.
config EXAMPLE_MODEM_UART_RTS_PIN
int "RTS Pin Number"
default 27
range 0 56
range 0 31
help
Pin number of UART RTS.
config EXAMPLE_MODEM_UART_CTS_PIN
int "CTS Pin Number"
default 23
range 0 56
range 0 31
help
Pin number of UART CTS.

View File

@ -11,10 +11,16 @@ See the README.md file in the upper level `pppos` directory for more information
### USB DTE support
For USB enabled targets (ESP32-S2, ESP32-S3, or ESP32-P4), it is possible to connect to the modem device via USB.
For USB enabled targets (ESP32-S2 and ESP32-S3), it is possible to connect to the modem device via USB.
1. In menuconfig, navigate to `Example Configuration->Type of serial connection to the modem` and choose `USB`.
2. Connect the modem USB signals to your ESP chip (pin 19 (DATA-) and 20 (DATA+) for ESP32-S2/S3).
2. Connect the modem USB signals to pin 19 (DATA-) and 20 (DATA+) on your ESP chip.
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`.

View File

@ -9,7 +9,7 @@ menu "Example Configuration"
Connect to modem via UART.
config EXAMPLE_SERIAL_CONFIG_USB
bool "USB"
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
help
Connect to modem via USB (CDC-ACM class). For IDF version >= 4.4.
endchoice
@ -29,11 +29,6 @@ menu "Example Configuration"
bool "BG96"
help
Quectel BG96 is a series of LTE Cat M1/Cat NB1/EGPRS module.
config EXAMPLE_MODEM_DEVICE_EC20
depends on EXAMPLE_SERIAL_CONFIG_USB
bool "EC20"
help
Quectel EC20 is a series of LTE Cat M4 module.
config EXAMPLE_MODEM_DEVICE_SIM7000
depends on EXAMPLE_SERIAL_CONFIG_UART
bool "SIM7000"
@ -100,28 +95,28 @@ menu "Example Configuration"
config EXAMPLE_MODEM_UART_TX_PIN
int "TXD Pin Number"
default 25
range 0 56
range 0 31
help
Pin number of UART TX.
config EXAMPLE_MODEM_UART_RX_PIN
int "RXD Pin Number"
default 26
range 0 56
range 0 31
help
Pin number of UART RX.
config EXAMPLE_MODEM_UART_RTS_PIN
int "RTS Pin Number"
default 27
range 0 56
range 0 31
help
Pin number of UART RTS.
config EXAMPLE_MODEM_UART_CTS_PIN
int "CTS Pin Number"
default 23
range 0 56
range 0 31
help
Pin number of UART CTS.
@ -201,23 +196,4 @@ 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

View File

@ -56,7 +56,7 @@ DCE *esp_modem_create_custom_dce(const esp_modem_dce_config_t *dce_config, std::
/**
* @brief This API is only needed for extending standard C-API, since we added get_time() method to our CustomModule
*
* @note This header is included from esp_modem_c_api.cpp, so it could use CONFIG_ESP_MODEM_C_API_STR_MAX macro
* @note This header is included from esp_modem_c_api.cpp, so it could use ESP_MODEM_C_API_STR_MAX macro
* indicating maximum C-API string size
*
* @note In order to access the newly added API get_time(), we have to static_cast<> the GenericModule from DCE
@ -70,10 +70,10 @@ extern "C" esp_err_t esp_modem_get_time(esp_modem_dce_t *dce_wrap, char *p_time)
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
return ESP_ERR_INVALID_ARG;
}
std::string time{CONFIG_ESP_MODEM_C_API_STR_MAX};
std::string time{ESP_MODEM_C_API_STR_MAX};
auto ret = command_response_to_esp_err(static_cast<SIM7600_WITH_TIME *>(dce_wrap->dce->get_module())->get_time(time));
if (ret == ESP_OK && !time.empty()) {
strlcpy(p_time, time.c_str(), CONFIG_ESP_MODEM_C_API_STR_MAX);
strlcpy(p_time, time.c_str(), ESP_MODEM_C_API_STR_MAX);
}
return ret;
}

View File

@ -6,7 +6,7 @@ dependencies:
version: "^1.0.0"
override_path: "../../../"
espressif/esp_modem_usb_dte:
version: "^1.2.0"
version: "^1.1.0"
rules:
- if: "idf_version >=4.4"
- if: "target in [esp32s2, esp32s3, esp32p4]"
- if: "target in [esp32s2, esp32s3]"

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@ -34,7 +34,6 @@
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
@ -56,7 +55,6 @@ 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; \
}
@ -142,7 +140,6 @@ 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!");
@ -161,7 +158,6 @@ 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);
@ -209,7 +205,7 @@ void app_main(void)
#endif
assert(dce);
if (dte_config.uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
err = esp_modem_set_flow_control(dce, 2, 2); //2/2 means HW Flow Control.
esp_err_t 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;
@ -223,10 +219,6 @@ void app_main(void)
ESP_LOGI(TAG, "Initializing esp_modem for the BG96 module...");
struct esp_modem_usb_term_config usb_config = ESP_MODEM_BG96_USB_CONFIG();
esp_modem_dce_device_t usb_dev_type = ESP_MODEM_DCE_BG96;
#elif CONFIG_EXAMPLE_MODEM_DEVICE_EC20 == 1
ESP_LOGI(TAG, "Initializing esp_modem for the EC20 module...");
struct esp_modem_usb_term_config usb_config = ESP_MODEM_EC20_USB_CONFIG();
esp_modem_dce_device_t usb_dev_type = ESP_MODEM_DCE_EC20;
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1
ESP_LOGI(TAG, "Initializing esp_modem for the SIM7600 module...");
struct esp_modem_usb_term_config usb_config = ESP_MODEM_SIM7600_USB_CONFIG();
@ -250,27 +242,7 @@ void app_main(void)
#error Invalid serial connection to modem.
#endif
#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);
xEventGroupClearBits(event_group, CONNECT_BIT | GOT_DATA_BIT | USB_DISCONNECTED_BIT);
/* Run the modem demo app */
#if CONFIG_EXAMPLE_NEED_SIM_PIN == 1
@ -286,7 +258,7 @@ void app_main(void)
#endif
int rssi, ber;
err = esp_modem_get_signal_quality(dce, &rssi, &ber);
esp_err_t 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;
@ -325,41 +297,22 @@ void app_main(void)
}
/* Wait for IP address */
ESP_LOGI(TAG, "Waiting for IP address");
xEventGroupWaitBits(event_group, CONNECT_BIT | USB_DISCONNECTED_BIT | DISCONNECT_BIT, pdFALSE, pdFALSE,
pdMS_TO_TICKS(60000));
xEventGroupWaitBits(event_group, CONNECT_BIT | USB_DISCONNECTED_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
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);

View File

@ -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', timeout=90)
dut.expect('Modem Connect to PPP Server')
# Check for MQTT connection and the data event
dut.expect('MQTT_EVENT_CONNECTED')
dut.expect('MQTT_EVENT_DATA')

View File

@ -11,7 +11,5 @@ 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

View File

@ -1,2 +0,0 @@
CONFIG_IDF_TARGET="esp32p4"
CONFIG_EXAMPLE_SERIAL_CONFIG_USB=y

View File

@ -11,3 +11,11 @@ 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.

View File

@ -69,28 +69,28 @@ menu "Example Configuration"
config EXAMPLE_MODEM_UART_TX_PIN
int "TXD Pin Number"
default 25
range 0 56
range 0 31
help
Pin number of UART TX.
config EXAMPLE_MODEM_UART_RX_PIN
int "RXD Pin Number"
default 26
range 0 56
range 0 31
help
Pin number of UART RX.
config EXAMPLE_MODEM_UART_RTS_PIN
int "RTS Pin Number"
default 27
range 0 56
range 0 31
help
Pin number of UART RTS.
config EXAMPLE_MODEM_UART_CTS_PIN
int "CTS Pin Number"
default 23
range 0 56
range 0 31
help
Pin number of UART CTS.
endmenu
@ -129,16 +129,4 @@ menu "Example Configuration"
help
URL of an mqtt broker which this example connects to.
config EXAMPLE_MQTT_TEST_TOPIC
string "MQTT topic to publish/subscribe"
default "/topic/esp-pppos"
help
MQTT topic, which we subscribe on and publish to.
config EXAMPLE_MQTT_TEST_DATA
string "MQTT data to publish/receive"
default "esp32-pppos"
help
MQTT data message, which we publish and expect to receive.
endmenu

View File

@ -234,8 +234,8 @@ extern "C" void app_main(void)
}
std::cout << "Connected" << std::endl;
mqtt.subscribe(CONFIG_EXAMPLE_MQTT_TEST_TOPIC);
mqtt.publish(CONFIG_EXAMPLE_MQTT_TEST_TOPIC, CONFIG_EXAMPLE_MQTT_TEST_DATA);
mqtt.subscribe("/topic/esp-modem");
mqtt.publish("/topic/esp-modem", "Hello modem");
if (!handler.wait_for(StatusHandler::MQTT_Data, 60000)) {
ESP_LOGE(TAG, "Didn't receive published data within specified timeout... exiting");
return;

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Unlicense OR CC0-1.0
from __future__ import print_function, unicode_literals
@ -10,17 +10,8 @@ def test_cmux_connection(dut):
2. checks we get an IP
3. checks for the MQTT events
"""
# Get topic and data from Kconfig
topic = ''
data = ''
try:
topic = dut.app.sdkconfig.get('EXAMPLE_MQTT_TEST_TOPIC')
data = dut.app.sdkconfig.get('EXAMPLE_MQTT_TEST_DATA')
except Exception:
print('ENV_TEST_FAILURE: Cannot find broker url in sdkconfig')
raise
# Check the sequence of connecting, publishing, disconnecting
dut.expect('Modem has correctly entered multiplexed')
# Check for MQTT connection and the data event
dut.expect(f'TOPIC: {topic}')
dut.expect(f'DATA: {data}')
dut.expect('TOPIC: /topic/esp-modem')
dut.expect('DATA: Hello modem')

View File

@ -15,5 +15,3 @@ CONFIG_ESP32_PANIC_PRINT_HALT=y
CONFIG_COMPILER_CXX_EXCEPTIONS=y
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
CONFIG_EXAMPLE_CLOSE_CMUX_AT_END=y
CONFIG_EXAMPLE_MQTT_TEST_TOPIC="/ci/esp-modem/pppos-client"
CONFIG_BROKER_URI="mqtt://mqtt.eclipseprojects.io"

View File

@ -1,4 +1,4 @@
version: "1.3.0"
version: "1.1.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

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -30,11 +30,9 @@ 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;
};
@ -81,56 +79,16 @@ 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();
}
#ifdef CONFIG_ESP_MODEM_URC_HANDLER
void set_urc(got_line_cb on_read_cb)
{
dte->set_urc_cb(on_read_cb);
}
#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;

View File

@ -77,9 +77,7 @@ public:
if (set_command_mode() == command_result::OK) {
return true;
}
// send a newline to delimit the escape from the upcoming sync command
uint8_t delim = '\n';
dte->write(&delim, 1);
Task::Delay(1000); // Mandatory 1s pause after escape
if (sync() == command_result::OK) {
return true;
}

Some files were not shown because too many files have changed in this diff Show More