forked from espressif/esp-protocols
Compare commits
187 Commits
websocket-
...
docs/docs_
Author | SHA1 | Date | |
---|---|---|---|
a3e8421de8 | |||
3bf0511938 | |||
319fce018e | |||
44bae24c78 | |||
d047ff569c | |||
02be2b76f8 | |||
1c850ddacf | |||
9ae88aab48 | |||
c6db3ea84c | |||
b23eedac3a | |||
1407dfc2e7 | |||
34c6f52f70 | |||
c674b8855d | |||
256389613f | |||
2865255ec0 | |||
7b2470ddd6 | |||
dda2722563 | |||
36db37ea2b | |||
4f013e3522 | |||
231392d0c6 | |||
9fb01ca534 | |||
d464ed7d30 | |||
b94a211e4b | |||
73f2800b59 | |||
e00e056162 | |||
1b134486db | |||
7ba1085e9f | |||
3bdb2067e0 | |||
1d6888445d | |||
d68624ec4f | |||
d4825f5c53 | |||
de1480a072 | |||
b9b4a75000 | |||
cc259aa035 | |||
91134f10ff | |||
fb8a2f0198 | |||
b87bef52e5 | |||
28813148b2 | |||
ae38f27997 | |||
d0c9070715 | |||
a8339e4618 | |||
12cfcb5aed | |||
2cfffb056e | |||
0247926219 | |||
05fff94b91 | |||
8958d5e37c | |||
f71192b876 | |||
f9b47900f2 | |||
0e215b118f | |||
dc8b916561 | |||
a01096f621 | |||
3de4727385 | |||
59053b8c98 | |||
2956477353 | |||
1d9b6f7e90 | |||
6b684ceb0f | |||
5304a6ec0e | |||
c7f20ee98e | |||
7d47ec3b6b | |||
e4c8a5932c | |||
b56b1c577b | |||
4e212c31fe | |||
9a7bd90ad9 | |||
4314c78ca0 | |||
457f8335bb | |||
42565ff5d7 | |||
6e2bb518fd | |||
2180ab17d8 | |||
ac5d43882b | |||
3f0262dfe5 | |||
74787c9aa8 | |||
045009bb82 | |||
79c11e9ecd | |||
c73c797595 | |||
3330b96b10 | |||
1547aa8c03 | |||
1ca139109a | |||
55c1223a1e | |||
0643613eee | |||
55dc56462f | |||
698fb3ae00 | |||
23a537b19b | |||
aee016d6e4 | |||
f1ae14f263 | |||
65c0e0e195 | |||
f71f61ff0a | |||
652314e73d | |||
71a2388acb | |||
ebc36a3519 | |||
5097065a22 | |||
193ac643e4 | |||
945bd17701 | |||
9d45d505d5 | |||
96fcbc0694 | |||
6b4767cba0 | |||
f148c98b13 | |||
06103e4bb4 | |||
c6fc267e5f | |||
52b7f001a2 | |||
cf504ec900 | |||
ab2e08f96c | |||
511ed541b8 | |||
8d0e2aab6b | |||
a02bf05eed | |||
85a2e25093 | |||
a9b5e66d0f | |||
988b3f9905 | |||
53b59332dc | |||
bf84ae940a | |||
a89a0ab7a3 | |||
fe536e476c | |||
afafcb7c24 | |||
55b4775ca8 | |||
1c6c610f20 | |||
9b48b0a5e0 | |||
25ac2d98c6 | |||
ce175df376 | |||
9d9d0db1ee | |||
b704aaa33b | |||
7a21db23ad | |||
fcd6f0bb14 | |||
52d7458b99 | |||
56cb58ced7 | |||
77a7538a02 | |||
c8d0a13f0e | |||
582f5b5ff6 | |||
06dd536d52 | |||
e66b19c414 | |||
0ad6cad8b2 | |||
ffa13e4b90 | |||
0fc1fc6b23 | |||
f1d1d79daf | |||
36d0d32b35 | |||
3bf488eb86 | |||
061885ad23 | |||
ab70791625 | |||
62cb235aa9 | |||
04c711f757 | |||
467fec5c9b | |||
5193ebc6ea | |||
3498e86d8b | |||
07a347f907 | |||
d9c9681094 | |||
7310a7a0bc | |||
accf9244ca | |||
290197c210 | |||
b8d1e58778 | |||
cc4d33d871 | |||
ef0e48a678 | |||
187ef7676e | |||
a8714730fb | |||
d2f519f9e5 | |||
a045c1c885 | |||
543521a220 | |||
85be67e708 | |||
5b1b2cce75 | |||
1029078541 | |||
0015e5411c | |||
65b64e1fc1 | |||
d07237b2ce | |||
3c65fde2a7 | |||
35833d2730 | |||
bbb4b7e686 | |||
64e31dae48 | |||
63ce3a5d59 | |||
5dd138c883 | |||
088f7ac3f8 | |||
e079f8ba98 | |||
ff2b0734ea | |||
330332a0fb | |||
48c157bc46 | |||
98bf3efeb6 | |||
ae8479c77e | |||
444fae9066 | |||
bb4c002841 | |||
656ab21c9b | |||
2099434b3f | |||
8f00fc182a | |||
d74c296182 | |||
c4e85bd099 | |||
85ba60e405 | |||
89e1bd27b3 | |||
341fcb0f40 | |||
469f953b28 | |||
381eb314dc | |||
1ffc20c8e3 | |||
3456781494 |
140
.flake8
Normal file
140
.flake8
Normal file
@ -0,0 +1,140 @@
|
||||
[flake8]
|
||||
|
||||
select =
|
||||
# Full lists are given in order to suppress all errors from other plugins
|
||||
# Full list of pyflakes error codes:
|
||||
F401, # module imported but unused
|
||||
F402, # import module from line N shadowed by loop variable
|
||||
F403, # 'from module import *' used; unable to detect undefined names
|
||||
F404, # future import(s) name after other statements
|
||||
F405, # name may be undefined, or defined from star imports: module
|
||||
F406, # 'from module import *' only allowed at module level
|
||||
F407, # an undefined __future__ feature name was imported
|
||||
F601, # dictionary key name repeated with different values
|
||||
F602, # dictionary key variable name repeated with different values
|
||||
F621, # too many expressions in an assignment with star-unpacking
|
||||
F622, # two or more starred expressions in an assignment (a, *b, *c = d)
|
||||
F631, # assertion test is a tuple, which are always True
|
||||
F701, # a break statement outside of a while or for loop
|
||||
F702, # a continue statement outside of a while or for loop
|
||||
F703, # a continue statement in a finally block in a loop
|
||||
F704, # a yield or yield from statement outside of a function
|
||||
F705, # a return statement with arguments inside a generator
|
||||
F706, # a return statement outside of a function/method
|
||||
F707, # an except: block as not the last exception handler
|
||||
F721, F722, # doctest syntax error syntax error in forward type annotation
|
||||
F811, # redefinition of unused name from line N
|
||||
F812, # list comprehension redefines name from line N
|
||||
F821, # undefined name name
|
||||
F822, # undefined name name in __all__
|
||||
F823, # local variable name referenced before assignment
|
||||
F831, # duplicate argument name in function definition
|
||||
F841, # local variable name is assigned to but never used
|
||||
F901, # raise NotImplemented should be raise NotImplementedError
|
||||
|
||||
# Full list of pycodestyle violations:
|
||||
E101, # indentation contains mixed spaces and tabs
|
||||
E111, # indentation is not a multiple of four
|
||||
E112, # expected an indented block
|
||||
E113, # unexpected indentation
|
||||
E114, # indentation is not a multiple of four (comment)
|
||||
E115, # expected an indented block (comment)
|
||||
E116, # unexpected indentation (comment)
|
||||
E121, # continuation line under-indented for hanging indent
|
||||
E122, # continuation line missing indentation or outdented
|
||||
E123, # closing bracket does not match indentation of opening bracket's line
|
||||
E124, # closing bracket does not match visual indentation
|
||||
E125, # continuation line with same indent as next logical line
|
||||
E126, # continuation line over-indented for hanging indent
|
||||
E127, # continuation line over-indented for visual indent
|
||||
E128, # continuation line under-indented for visual indent
|
||||
E129, # visually indented line with same indent as next logical line
|
||||
E131, # continuation line unaligned for hanging indent
|
||||
E133, # closing bracket is missing indentation
|
||||
E201, # whitespace after '('
|
||||
E202, # whitespace before ')'
|
||||
E203, # whitespace before ':'
|
||||
E211, # whitespace before '('
|
||||
E221, # multiple spaces before operator
|
||||
E222, # multiple spaces after operator
|
||||
E223, # tab before operator
|
||||
E224, # tab after operator
|
||||
E225, # missing whitespace around operator
|
||||
E226, # missing whitespace around arithmetic operator
|
||||
E227, # missing whitespace around bitwise or shift operator
|
||||
E228, # missing whitespace around modulo operator
|
||||
E231, # missing whitespace after ',', ';', or ':'
|
||||
E241, # multiple spaces after ','
|
||||
E242, # tab after ','
|
||||
E251, # unexpected spaces around keyword / parameter equals
|
||||
E261, # at least two spaces before inline comment
|
||||
E262, # inline comment should start with '# '
|
||||
E265, # block comment should start with '# '
|
||||
E266, # too many leading '#' for block comment
|
||||
E271, # multiple spaces after keyword
|
||||
E272, # multiple spaces before keyword
|
||||
E273, # tab after keyword
|
||||
E274, # tab before keyword
|
||||
E275, # missing whitespace after keyword
|
||||
E301, # expected 1 blank line, found 0
|
||||
E302, # expected 2 blank lines, found 0
|
||||
E303, # too many blank lines
|
||||
E304, # blank lines found after function decorator
|
||||
E305, # expected 2 blank lines after end of function or class
|
||||
E306, # expected 1 blank line before a nested definition
|
||||
E401, # multiple imports on one line
|
||||
E402, # module level import not at top of file
|
||||
E501, # line too long (82 > 79 characters)
|
||||
E502, # the backslash is redundant between brackets
|
||||
E701, # multiple statements on one line (colon)
|
||||
E702, # multiple statements on one line (semicolon)
|
||||
E703, # statement ends with a semicolon
|
||||
E704, # multiple statements on one line (def)
|
||||
E711, # comparison to None should be 'if cond is None:'
|
||||
E712, # comparison to True should be 'if cond is True:' or 'if cond:'
|
||||
E713, # test for membership should be 'not in'
|
||||
E714, # test for object identity should be 'is not'
|
||||
E721, # do not compare types, use 'isinstance()'
|
||||
E722, # do not use bare except, specify exception instead
|
||||
E731, # do not assign a lambda expression, use a def
|
||||
E741, # do not use variables named 'l', 'O', or 'I'
|
||||
E742, # do not define classes named 'l', 'O', or 'I'
|
||||
E743, # do not define functions named 'l', 'O', or 'I'
|
||||
E901, # SyntaxError or IndentationError
|
||||
E902, # IOError
|
||||
W191, # indentation contains tabs
|
||||
W291, # trailing whitespace
|
||||
W292, # no newline at end of file
|
||||
W293, # blank line contains whitespace
|
||||
W391, # blank line at end of file
|
||||
W503, # line break before binary operator
|
||||
W504, # line break after binary operator
|
||||
W505, # doc line too long (82 > 79 characters)
|
||||
W601, # .has_key() is deprecated, use 'in'
|
||||
W602, # deprecated form of raising exception
|
||||
W603, # '<>' is deprecated, use '!='
|
||||
W604, # backticks are deprecated, use 'repr()'
|
||||
W605, # invalid escape sequence 'x'
|
||||
W606, # 'async' and 'await' are reserved keywords starting with Python 3.7
|
||||
|
||||
# Full list of flake8 violations
|
||||
E999, # failed to compile a file into an Abstract Syntax Tree for the plugins that require it
|
||||
|
||||
# Full list of mccabe violations
|
||||
C901 # complexity value provided by the user
|
||||
|
||||
ignore =
|
||||
E221, # multiple spaces before operator
|
||||
E231, # missing whitespace after ',', ';', or ':'
|
||||
E241, # multiple spaces after ','
|
||||
W503, # line break before binary operator
|
||||
W504 # line break after binary operator
|
||||
|
||||
max-line-length = 160
|
||||
|
||||
show_source = True
|
||||
|
||||
statistics = True
|
||||
|
||||
exclude =
|
||||
components/asio/docs/conf_common.py
|
2
.git-blame-ignore-revs
Normal file
2
.git-blame-ignore-revs
Normal file
@ -0,0 +1,2 @@
|
||||
# Formating according pre-commit hooks
|
||||
945bd177011d984b705daee9b895f88212292a42
|
92
.github/workflows/gcov_analyzer.yml
vendored
Normal file
92
.github/workflows/gcov_analyzer.yml
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
name: Code Coverage Analyzer
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
gcovr_analyzer_esp_modem:
|
||||
name: Run gcovr on esp modem host test
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:release-v4.3
|
||||
env:
|
||||
lwip: lwip-2.1.2
|
||||
lwip_contrib: contrib-2.1.0
|
||||
lwip_uri: http://download.savannah.nongnu.org/releases/lwip
|
||||
COMP_DIR: esp-protocols/components/esp_modem
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: esp-protocols
|
||||
persist-credentials: false
|
||||
- name: Build and Test
|
||||
shell: bash
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get update && apt-get install -y gcc-8 g++-8 python3-pip
|
||||
apt-get install -y rsync
|
||||
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 800 --slave /usr/bin/g++ g++ /usr/bin/g++-8
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
export LWIP_PATH=`pwd`/${{ env.lwip }}
|
||||
export LWIP_CONTRIB_PATH=`pwd`/${{ env.lwip_contrib }}
|
||||
. ${IDF_PATH}/export.sh
|
||||
${{ env.COMP_DIR }}/test/host_test/env.sh $lwip $lwip_uri $lwip_contrib
|
||||
cd $GITHUB_WORKSPACE/${{ env.COMP_DIR }}/test/host_test
|
||||
cat sdkconfig.ci.coverage >> sdkconfig.defaults
|
||||
idf.py build
|
||||
./build/host_modem_test.elf
|
||||
- name: Run gcovr
|
||||
shell: bash
|
||||
run: |
|
||||
python -m pip install gcovr
|
||||
cd $GITHUB_WORKSPACE/${{ env.COMP_DIR }}
|
||||
gcov-8 `find . -name "esp_modem*gcda" -printf '%h\n' | head -n 1`/*
|
||||
gcovr --gcov-ignore-parse-errors -g -k -r . --html index.html -x esp_modem_coverage.xml
|
||||
mkdir docs_gcovr
|
||||
cp $GITHUB_WORKSPACE/${{ env.COMP_DIR }}/index.html docs_gcovr
|
||||
touch docs_gcovr/.nojekyll
|
||||
|
||||
- name: Code Coverage Summary Report
|
||||
uses: irongut/CodeCoverageSummary@v1.3.0
|
||||
with:
|
||||
filename: esp-protocols/**/esp_modem_coverage.xml
|
||||
badge: true
|
||||
fail_below_min: false
|
||||
format: markdown
|
||||
hide_branch_rate: false
|
||||
hide_complexity: false
|
||||
indicators: true
|
||||
output: both
|
||||
thresholds: '60 80'
|
||||
|
||||
- name: Write to Job Summary
|
||||
run: cat code-coverage-results.md >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: docs_gcovr
|
||||
path: |
|
||||
${{ env.COMP_DIR }}/docs_gcovr
|
||||
if-no-files-found: error
|
||||
|
||||
# show_report_data:
|
||||
# name: Publish-Results
|
||||
# if: github.ref == 'refs/heads/master' || github.repository != 'espressif/esp-protocols'
|
||||
# runs-on: ubuntu-22.04
|
||||
# needs: gcovr_analyzer_esp_modem
|
||||
# steps:
|
||||
# - name: Checkout 🛎️
|
||||
# uses: actions/checkout@v3
|
||||
# with:
|
||||
# persist-credentials: false
|
||||
# - name: Download Artifacts
|
||||
# uses: actions/download-artifact@v1
|
||||
# with:
|
||||
# name: docs_gcovr
|
||||
#
|
||||
# - name: Deploy generated docs
|
||||
# uses: JamesIves/github-pages-deploy-action@v4
|
||||
# with:
|
||||
# branch: gh-pages
|
||||
# folder: 'docs_gcovr'
|
35
.github/workflows/host-test.yml
vendored
35
.github/workflows/host-test.yml
vendored
@ -3,16 +3,15 @@ name: Host test
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
host_test:
|
||||
name: Build and Test on Host
|
||||
host_test_esp_modem:
|
||||
name: esp-modem Build and Test on Host
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:release-v4.3
|
||||
env:
|
||||
lwip: lwip-2.1.2
|
||||
lwip_contrib: contrib-2.1.0
|
||||
lwip_uri: http://download.savannah.nongnu.org/releases/lwip
|
||||
|
||||
|
||||
COMP_DIR: esp-protocols/components/esp_modem
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@master
|
||||
@ -26,11 +25,8 @@ jobs:
|
||||
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 800 --slave /usr/bin/g++ g++ /usr/bin/g++-8
|
||||
export LWIP_PATH=`pwd`/${{ env.lwip }}
|
||||
export LWIP_CONTRIB_PATH=`pwd`/${{ env.lwip_contrib }}
|
||||
wget --no-verbose ${lwip_uri}/${lwip}.zip
|
||||
unzip -oq ${lwip}.zip
|
||||
wget --no-verbose ${lwip_uri}/${lwip_contrib}.zip
|
||||
unzip -oq ${lwip_contrib}.zip
|
||||
. ${IDF_PATH}/export.sh
|
||||
$GITHUB_WORKSPACE/${{ env.COMP_DIR }}/test/host_test/env.sh $lwip $lwip_uri $lwip_contrib
|
||||
cd $GITHUB_WORKSPACE/esp-protocols/components/esp_modem/examples/linux_modem
|
||||
idf.py build
|
||||
cd $GITHUB_WORKSPACE/esp-protocols/components/esp_modem/test/host_test
|
||||
@ -42,3 +38,26 @@ jobs:
|
||||
if: always()
|
||||
with:
|
||||
files: esp-protocols/components/esp_modem/test/host_test/junit.xml
|
||||
|
||||
host_test_mdns:
|
||||
name: mdns Build and Test on Host
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:latest
|
||||
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
path: esp-protocols
|
||||
|
||||
- name: Build and Test
|
||||
shell: bash
|
||||
run: |
|
||||
apt-get update && apt-get install -y dnsutils gcc g++
|
||||
. ${IDF_PATH}/export.sh
|
||||
cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/tests/host_test
|
||||
idf.py build
|
||||
./build/mdns_host.elf &
|
||||
dig +short -p 5353 @224.0.0.251 myesp.local > ip.txt
|
||||
cat ip.txt | xargs dig +short -p 5353 @224.0.0.251 -x
|
||||
cat ip.txt
|
||||
|
40
.github/workflows/pre_commit_check.yml
vendored
Normal file
40
.github/workflows/pre_commit_check.yml
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
name: Check pre-commit rules
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, reopened, synchronize]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
pre_commit_check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Fetch head and base refs
|
||||
# This is necessary for pre-commit to check the changes in the PR branch
|
||||
run: |
|
||||
git fetch origin ${{ github.base_ref }}:base_ref
|
||||
git fetch origin pull/${{ github.event.pull_request.number }}/head:pr_ref
|
||||
- name: Set up Python environment
|
||||
uses: actions/setup-python@master
|
||||
with:
|
||||
python-version: v3.7
|
||||
- name: Install python packages
|
||||
run: |
|
||||
pip install pre-commit
|
||||
pre-commit install-hooks
|
||||
- name: Run pre-commit and check for any changes
|
||||
run: |
|
||||
echo "Commits being checked:"
|
||||
git log --oneline --no-decorate base_ref..pr_ref
|
||||
echo ""
|
||||
if ! pre-commit run --from-ref base_ref --to-ref pr_ref --show-diff-on-failure ; then
|
||||
echo ""
|
||||
echo "::notice::It looks like the commits in this PR have been made without having pre-commit hooks installed."
|
||||
echo "::notice::Please see https://github.com/espressif/esp-protocols/CONTRIBUTING.md for instructions."
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
3
.github/workflows/publish-docs-component.yml
vendored
3
.github/workflows/publish-docs-component.yml
vendored
@ -9,6 +9,8 @@ jobs:
|
||||
docs_build:
|
||||
name: Docs-Build-And-Upload
|
||||
runs-on: ubuntu-latest
|
||||
# Skip running on forks since it won't have access to secrets
|
||||
if: github.repository == 'espressif/esp-protocols'
|
||||
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
@ -16,6 +18,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
|
||||
- name: Generate docs
|
||||
run: |
|
||||
|
77
.github/workflows/publish-docs.yml
vendored
Normal file
77
.github/workflows/publish-docs.yml
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
name: Docs and Publish New
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
env:
|
||||
DOCS_DEPLOY_URL_BASE: "${{ secrets.DOCS_PREVIEW_SERVER_URL }}"
|
||||
#DOCS_DEPLOY_SERVER: "ci.espressif.cn:42348"
|
||||
DOCS_DEPLOY_SERVER: "ci.espressif.cn:42348"
|
||||
DOCS_DEPLOY_SERVER_USER: "${{ secrets.DOCS_SERVER_USER }}"
|
||||
DOCS_DEPLOY_PRIVATEKEY : "${{ secrets.DOCS_DEPLOY_KEY }}"
|
||||
DOCS_DEPLOY_KEY: "${{ secrets.DOCS_DEPLOY_KEY }}"
|
||||
DOCS_DEPLOY_PATH : "${{ secrets.DOCS_PATH }}"
|
||||
|
||||
jobs:
|
||||
docs_build:
|
||||
name: Docs-Build-And-Upload
|
||||
runs-on: ubuntu-latest
|
||||
# Skip running on forks since it won't have access to secrets
|
||||
#if: github.repository == 'espressif/esp-protocols'
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
- name: Generate and delploying docs
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install doxygen clang python3-pip
|
||||
python -m pip install breathe recommonmark esp-docs
|
||||
cd $GITHUB_WORKSPACE/components/esp_websocket_client/docs
|
||||
./generate_docs
|
||||
source $GITHUB_WORKSPACE/docs/utils.sh
|
||||
add_doc_server_ssh_keys $DOCS_DEPLOY_PRIVATEKEY $DOCS_DEPLOY_SERVER $DOCS_DEPLOY_SERVER_USER
|
||||
export GIT_VER=$(git describe --always)
|
||||
ls -l $GITHUB_WORKSPACE/components/esp_websocket_client/docs
|
||||
export DOCS_BUILD_DIR=$GITHUB_WORKSPACE/components/esp_websocket_client/docs
|
||||
deploy-docs
|
||||
|
||||
#build_docs:
|
||||
# stage: build
|
||||
# image: $ESP_DOCS_ENV_IMAGE
|
||||
# tags:
|
||||
# - build_docs
|
||||
# artifacts:
|
||||
# when: always
|
||||
# paths:
|
||||
# - docs/_build/*/*/*.txt
|
||||
# - docs/_build/*/*/html/*
|
||||
# expire_in: 4 days
|
||||
# # No cleaning when the artifacts
|
||||
# after_script: []
|
||||
# script:
|
||||
# - cd docs
|
||||
# - pip install -r requirements.txt
|
||||
# - build-docs -l en -t esp32
|
||||
#
|
||||
#.deploy_docs_template:
|
||||
# stage: deploy
|
||||
# image: $ESP_DOCS_ENV_IMAGE
|
||||
# tags:
|
||||
# - deploy_docs
|
||||
# needs:
|
||||
# - build_docs
|
||||
# only:
|
||||
# changes:
|
||||
# - "docs/**/*"
|
||||
# script:
|
||||
# - source ${CI_PROJECT_DIR}/docs/utils.sh
|
||||
# - add_doc_server_ssh_keys ${{ secrets.DOCS_DEPLOY_PRIVATEKEY }} ${{ secrets.DOCS_DEPLOY_SERVER }} ${{ secrets.DOCS_DEPLOY_SERVER_USER }}
|
||||
# - export GIT_VER=$(git describe --always)
|
||||
# - pip install -r ${CI_PROJECT_DIR}/docs/requirements.txt
|
||||
# - deploy-docs
|
||||
#
|
338
.github/workflows/target-test.yml
vendored
338
.github/workflows/target-test.yml
vendored
@ -6,7 +6,7 @@ jobs:
|
||||
build_esp_modem:
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v4.1", "release-v4.2", "release-v4.3", "release-v4.4"]
|
||||
idf_ver: ["latest", "release-v4.1", "release-v4.2", "release-v4.3", "release-v4.4", "release-v5.0"]
|
||||
example: ["pppos_client", "modem_console", "ap_to_pppos", "simple_cmux_client"]
|
||||
idf_target: ["esp32"]
|
||||
exclude:
|
||||
@ -35,12 +35,34 @@ jobs:
|
||||
cd $GITHUB_WORKSPACE/esp-protocols/components/esp_modem/examples/${{ matrix.example }}
|
||||
idf.py build
|
||||
|
||||
build_esp_modem_usb:
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v4.4", "release-v5.0"]
|
||||
example: ["modem_console", "pppos_client"]
|
||||
idf_target: ["esp32s2", "esp32s3"]
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
working-directory: components/esp_modem/examples/${{ matrix.example }}
|
||||
env:
|
||||
IDF_TARGET: ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
cat sdkconfig.ci.usb >> sdkconfig.defaults
|
||||
idf.py build
|
||||
|
||||
build_mdns:
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
idf_target: ["esp32", "esp32s2", "esp32c3"]
|
||||
|
||||
test: [ { app: example, path: "components/mdns/examples" }, { app: unit_test, path: "components/mdns/tests/unit_test" } ]
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
@ -48,26 +70,23 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
path: esp-protocols
|
||||
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
env:
|
||||
IDF_TARGET: ${{ matrix.idf_target }}
|
||||
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
working-directory: ${{ matrix.test.path }}
|
||||
run: |
|
||||
${IDF_PATH}/install.sh --enable-pytest
|
||||
. ${IDF_PATH}/export.sh
|
||||
cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/examples/
|
||||
idf.py set-target ${{ matrix.idf_target }}
|
||||
cat sdkconfig.ci.eth_def >> sdkconfig.defaults
|
||||
idf.py build
|
||||
rm sdkconfig.defaults
|
||||
cat sdkconfig.ci.eth_custom_netif >> sdkconfig.defaults
|
||||
idf.py build
|
||||
rm sdkconfig.defaults
|
||||
cat sdkconfig.ci.eth_socket >> sdkconfig.defaults
|
||||
idf.py build
|
||||
cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/tests/test_apps/
|
||||
idf.py set-target ${{ matrix.idf_target }}
|
||||
idf.py build
|
||||
python $IDF_PATH/tools/ci/ci_build_apps.py . --target ${{ matrix.idf_target }} -vv --preserve-all --pytest-app
|
||||
for dir in `ls -d build_*`; do
|
||||
$GITHUB_WORKSPACE/ci/clean_build_artifacts.sh `pwd`/$dir
|
||||
zip -qur artifacts.zip $dir
|
||||
done
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: ${{ matrix.idf_target }} == "esp32"
|
||||
with:
|
||||
name: mdns_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.test.app }}
|
||||
path: ${{ matrix.test.path }}/artifacts.zip
|
||||
if-no-files-found: error
|
||||
|
||||
build_asio:
|
||||
strategy:
|
||||
@ -75,62 +94,113 @@ jobs:
|
||||
idf_ver: ["latest"]
|
||||
idf_target: ["esp32", "esp32s2"]
|
||||
example: ["asio_chat", "async_request", "socks4", "ssl_client_server", "tcp_echo_server", "udp_echo_server"]
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
env:
|
||||
TEST_DIR: components/asio/examples
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
path: esp-protocols
|
||||
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
working-directory: ${{ env.TEST_DIR }}/${{ matrix.example }}
|
||||
env:
|
||||
IDF_TARGET: ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
cd $GITHUB_WORKSPACE/esp-protocols/components/asio/examples/${{ matrix.example }}
|
||||
test -f sdkconfig.ci && cat sdkconfig.ci >> sdkconfig.defaults || echo "No sdkconfig.ci"
|
||||
idf.py set-target ${{ matrix.idf_target }}
|
||||
idf.py build
|
||||
|
||||
build_websocket:
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
idf_target: ["esp32"]
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
env:
|
||||
IDF_TARGET: ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
working-directory: components/esp_websocket_client/examples/
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
cat sdkconfig.ci >> sdkconfig.defaults
|
||||
idf.py build
|
||||
- name: Merge binaries
|
||||
working-directory: components/esp_websocket_client/examples/build
|
||||
- name: Merge binaries with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }} for ${{ matrix.example }}
|
||||
working-directory: ${{ env.TEST_DIR }}/${{ matrix.example }}/build
|
||||
env:
|
||||
IDF_TARGET: ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
esptool.py --chip ${{ matrix.idf_target }} merge_bin --fill-flash-size 4MB -o flash_image.bin @flash_args
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}
|
||||
path: components/esp_websocket_client/examples/build/
|
||||
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.example }}
|
||||
path: |
|
||||
${{ env.TEST_DIR }}/${{ matrix.example }}/build/bootloader/bootloader.bin
|
||||
${{ env.TEST_DIR }}/${{ matrix.example }}/build//partition_table/partition-table.bin
|
||||
${{ env.TEST_DIR }}/${{ matrix.example }}/build/*.bin
|
||||
${{ env.TEST_DIR }}/${{ matrix.example }}/build/*.elf
|
||||
${{ env.TEST_DIR }}/${{ matrix.example }}/build/flasher_args.json
|
||||
${{ env.TEST_DIR }}/${{ matrix.example }}/build/config/sdkconfig.h
|
||||
${{ env.TEST_DIR }}/${{ matrix.example }}/build/config/sdkconfig.json
|
||||
if-no-files-found: error
|
||||
|
||||
run-target:
|
||||
|
||||
build_websocket:
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
idf_target: ["esp32"]
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
env:
|
||||
TEST_DIR: components/esp_websocket_client/examples
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
env:
|
||||
IDF_TARGET: ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
working-directory: ${{ env.TEST_DIR }}
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
cat sdkconfig.ci >> sdkconfig.defaults
|
||||
idf.py build
|
||||
- name: Merge binaries
|
||||
working-directory: ${{ env.TEST_DIR }}/build
|
||||
env:
|
||||
IDF_TARGET: ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
esptool.py --chip ${{ matrix.idf_target }} merge_bin --fill-flash-size 4MB -o flash_image.bin @flash_args
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}
|
||||
path: |
|
||||
${{ env.TEST_DIR }}/build/bootloader/bootloader.bin
|
||||
${{ env.TEST_DIR }}/build/partition_table/partition-table.bin
|
||||
${{ env.TEST_DIR }}/build/*.bin
|
||||
${{ env.TEST_DIR }}/build/*.elf
|
||||
${{ env.TEST_DIR }}/build/flasher_args.json
|
||||
${{ env.TEST_DIR }}/build/config/sdkconfig.h
|
||||
${{ env.TEST_DIR }}/build/config/sdkconfig.json
|
||||
if-no-files-found: error
|
||||
|
||||
build_esp_mqtt_cxx:
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.0"]
|
||||
idf_target: ["esp32"]
|
||||
test: [ { app: example, path: "components/esp_mqtt_cxx/examples" }]
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
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}/install.sh --enable-pytest
|
||||
. ${IDF_PATH}/export.sh
|
||||
python $IDF_PATH/tools/ci/ci_build_apps.py . --target ${{ matrix.idf_target }} -vv --preserve-all --pytest-app
|
||||
|
||||
run-target-websocket:
|
||||
name: Run Websocket Example Test on target
|
||||
needs: build_websocket
|
||||
strategy:
|
||||
@ -141,29 +211,173 @@ jobs:
|
||||
runs-on:
|
||||
- self-hosted
|
||||
- ESP32-ETHERNET-KIT
|
||||
container:
|
||||
image: python:3.7-buster
|
||||
options: --privileged # Privileged mode has access to serial ports
|
||||
env:
|
||||
TEST_DIR: components/esp_websocket_client/examples
|
||||
# Skip running on forks since it won't have access to secrets
|
||||
if: github.repository == 'espressif/esp-protocols'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/download-artifact@v2
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}
|
||||
path: components/esp_websocket_client/examples/build/
|
||||
path: ${{ env.TEST_DIR }}/build/
|
||||
- name: Install Python packages
|
||||
env:
|
||||
PIP_EXTRA_INDEX_URL: "https://www.piwheels.org/simple"
|
||||
run: |
|
||||
pip install -r $GITHUB_WORKSPACE/components/esp_websocket_client/examples/requirements.txt
|
||||
pip install --only-binary cryptography --extra-index-url https://dl.espressif.com/pypi/ -r $GITHUB_WORKSPACE/ci/requirements.txt
|
||||
- name: Download Example Test to target
|
||||
run: python -m esptool --chip ${{ matrix.idf_target }} write_flash 0x0 components/esp_websocket_client/examples/build/flash_image.bin
|
||||
- name: Run Example Test on target
|
||||
working-directory: components/esp_websocket_client/examples
|
||||
working-directory: ${{ env.TEST_DIR }}
|
||||
run: |
|
||||
cp sdkconfig.ci sdkconfig.defaults
|
||||
pytest --log-cli-level DEBUG --junit-xml=./test_app_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}.xml --target=${{ matrix.idf_target }}
|
||||
- uses: actions/upload-artifact@v2
|
||||
python -m pytest --log-cli-level DEBUG --junit-xml=./examples_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}.xml --target=${{ matrix.idf_target }}
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: examples_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}
|
||||
path: examples/*.xml
|
||||
path: ${{ env.TEST_DIR }}/*.xml
|
||||
|
||||
run-target-mdns:
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
idf_target: ["esp32"]
|
||||
test: [ { app: example, path: "components/mdns/examples" }, { app: unit_test, path: "components/mdns/tests/unit_test" } ]
|
||||
name: Run mDNS target tests
|
||||
needs: build_mdns
|
||||
runs-on:
|
||||
- self-hosted
|
||||
- ESP32-ETHERNET-KIT
|
||||
# Skip running on forks since it won't have access to secrets
|
||||
if: github.repository == 'espressif/esp-protocols'
|
||||
steps:
|
||||
- name: Clear repository
|
||||
run: sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: mdns_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.test.app }}
|
||||
path: ${{ matrix.test.path }}/ci/
|
||||
- name: Install Python packages
|
||||
env:
|
||||
PIP_EXTRA_INDEX_URL: "https://www.piwheels.org/simple"
|
||||
run: |
|
||||
sudo apt-get install -y dnsutils
|
||||
- name: Run ${{ matrix.test.app }} application on ${{ matrix.idf_target }}
|
||||
working-directory: ${{ matrix.test.path }}
|
||||
run: |
|
||||
unzip ci/artifacts.zip -d ci
|
||||
for dir in `ls -d ci/build_*`; do
|
||||
rm -rf build sdkconfig.defaults
|
||||
mv $dir build
|
||||
python -m pytest --log-cli-level DEBUG --junit-xml=./results_${{ matrix.test.app }}_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${dir#"ci/build_"}.xml --target=${{ matrix.idf_target }}
|
||||
done
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: results_${{ matrix.test.app }}_${{ matrix.idf_target }}_${{ matrix.idf_ver }}.xml
|
||||
path: ${{ matrix.test.path }}/*.xml
|
||||
|
||||
run-target-asio:
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
idf_target: ["esp32"]
|
||||
example: ["asio_chat", "tcp_echo_server", "udp_echo_server", "ssl_client_server"]
|
||||
name: Run ASIO Example Test on target
|
||||
needs: build_asio
|
||||
runs-on:
|
||||
- self-hosted
|
||||
- ESP32-ETHERNET-KIT
|
||||
env:
|
||||
TEST_DIR: components/asio/examples
|
||||
# Skip running on forks since it won't have access to secrets
|
||||
if: github.repository == 'espressif/esp-protocols'
|
||||
steps:
|
||||
- name: Clear repository
|
||||
run: sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.example }}
|
||||
path: ${{ env.TEST_DIR }}/${{ matrix.example }}/build
|
||||
- name: Install Python packages
|
||||
env:
|
||||
PIP_EXTRA_INDEX_URL: "https://www.piwheels.org/simple"
|
||||
run: |
|
||||
sudo apt-get install -y dnsutils
|
||||
- name: Download Example Test to target ${{ matrix.config }}
|
||||
run: |
|
||||
python -m esptool --chip ${{ matrix.idf_target }} write_flash 0x0 ${{ env.TEST_DIR }}/${{ matrix.example }}/build/flash_image.bin
|
||||
- name: Run Example Test ${{ matrix.example }} on target
|
||||
working-directory: ${{ env.TEST_DIR }}/${{ matrix.example }}
|
||||
run: |
|
||||
python -m pytest --log-cli-level DEBUG --junit-xml=./examples_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.config }}.xml --target=${{ matrix.idf_target }}
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: examples_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.example }}
|
||||
path: ${{ env.TEST_DIR }}/${{ matrix.example }}/*.xml
|
||||
|
||||
build_esp_modem_tests:
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
idf_target: ["esp32c3"]
|
||||
test: [ { app: pppd, path: test/target }, { app: sim800, path: examples/pppos_client } ]
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
env:
|
||||
TEST_DIR: components/esp_modem/${{ matrix.test.path }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build esp-modem target tests with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
env:
|
||||
IDF_TARGET: ${{ matrix.idf_target }}
|
||||
SDKCONFIG: sdkconfig.ci.${{ matrix.test.app }}
|
||||
shell: bash
|
||||
working-directory: ${{ env.TEST_DIR }}
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
rm -rf sdkconfig build
|
||||
[ -f ${SDKCONFIG} ] && cp ${SDKCONFIG} sdkconfig.defaults
|
||||
idf.py set-target ${{ matrix.idf_target }}
|
||||
idf.py build
|
||||
$GITHUB_WORKSPACE/ci/clean_build_artifacts.sh ${GITHUB_WORKSPACE}/${TEST_DIR}/build
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: modem_target_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.test.app }}
|
||||
path: ${{ env.TEST_DIR }}/build
|
||||
if-no-files-found: error
|
||||
|
||||
run_esp_modem_tests:
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
idf_target: ["esp32c3"]
|
||||
test: [ { app: pppd, path: test/target }, { app: sim800, path: examples/pppos_client } ]
|
||||
name: Run esp_modem Test on target
|
||||
needs: build_esp_modem_tests
|
||||
runs-on:
|
||||
- self-hosted
|
||||
- BrnoRPI-GH006
|
||||
env:
|
||||
TEST_DIR: components/esp_modem/${{ matrix.test.path }}
|
||||
# Skip running on forks since it won't have access to secrets
|
||||
if: github.repository == 'espressif/esp-protocols'
|
||||
steps:
|
||||
- name: Clear repository
|
||||
run: sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/download-artifact@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
|
||||
working-directory: ${{ env.TEST_DIR }}
|
||||
run: |
|
||||
python -m pytest --log-cli-level DEBUG --target=${{ matrix.idf_target }}
|
||||
|
94
.github/workflows/test_apps.yml
vendored
Normal file
94
.github/workflows/test_apps.yml
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
name: Build and Run Test apps
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'components/mdns/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'components/mdns/**'
|
||||
|
||||
jobs:
|
||||
build_mdns_app:
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
idf_target: ["esp32", "esp32s2", "esp32c3"]
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Setup Build Environment
|
||||
working-directory: components/mdns/tests/test_apps
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install -r $GITHUB_WORKSPACE/ci/requirements.txt
|
||||
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
env:
|
||||
IDF_TARGET: ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
working-directory: components/mdns/tests/test_apps
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
python $IDF_PATH/tools/ci/ci_build_apps.py . --target ${{ matrix.idf_target }} -vv --pytest-apps
|
||||
- name: Merge binaries with IDF-${{ matrix.idf_ver }}
|
||||
working-directory: components/mdns/tests/test_apps/build_${{ matrix.idf_target }}_default
|
||||
env:
|
||||
IDF_TARGET: ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
esptool.py --chip ${{ matrix.idf_target }} merge_bin --fill-flash-size 4MB -o flash_image.bin @flash_args
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}
|
||||
path: |
|
||||
components/mdns/tests/test_apps/build_${{ matrix.idf_target }}_default/bootloader/bootloader.bin
|
||||
components/mdns/tests/test_apps/build_${{ matrix.idf_target }}_default/partition_table/partition-table.bin
|
||||
components/mdns/tests/test_apps/build_${{ matrix.idf_target }}_default/*.bin
|
||||
components/mdns/tests/test_apps/build_${{ matrix.idf_target }}_default/*.elf
|
||||
components/mdns/tests/test_apps/build_${{ matrix.idf_target }}_default/flasher_args.json
|
||||
components/mdns/tests/test_apps/build_${{ matrix.idf_target }}_default/config/sdkconfig.h
|
||||
components/mdns/tests/test_apps/build_${{ matrix.idf_target }}_default/config/sdkconfig.json
|
||||
if-no-files-found: error
|
||||
|
||||
run-target-mdns-app:
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
idf_target: ["esp32"]
|
||||
name: Run mDNS Test apps on target
|
||||
needs: build_mdns_app
|
||||
runs-on:
|
||||
- self-hosted
|
||||
- ESP32-ETHERNET-KIT
|
||||
# Skip running on forks since it won't have access to secrets
|
||||
if: github.repository == 'espressif/esp-protocols'
|
||||
steps:
|
||||
- name: Clear repository
|
||||
run: sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}
|
||||
path: components/mdns/tests/test_apps/build
|
||||
- name: Install Python packages
|
||||
env:
|
||||
PIP_EXTRA_INDEX_URL: "https://www.piwheels.org/simple"
|
||||
run: |
|
||||
sudo apt-get install -y dnsutils
|
||||
- name: Download Test apps to target
|
||||
run: |
|
||||
python -m esptool --chip ${{ matrix.idf_target }} write_flash 0x0 components/mdns/tests/test_apps/build/flash_image.bin
|
||||
- name: Run Example Test on target
|
||||
working-directory: components/mdns/tests/test_apps
|
||||
run: |
|
||||
python -m pytest --log-cli-level DEBUG --junit-xml=./examples_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}.xml --target=${{matrix.idf_target}}
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: always()
|
||||
with:
|
||||
name: test_apps_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}
|
||||
path: components/mdns/tests/test_apps/*.xml
|
26
.mypy.ini
Normal file
26
.mypy.ini
Normal file
@ -0,0 +1,26 @@
|
||||
[mypy]
|
||||
|
||||
# Specifies the Python version used to parse and check the target program
|
||||
python_version = 3.9
|
||||
|
||||
# Disallows defining functions without type annotations or with incomplete type annotations
|
||||
# True => enforce type annotation in all function definitions
|
||||
disallow_untyped_defs = True
|
||||
|
||||
# Shows a warning when returning a value with type Any from a function declared with a non- Any return type
|
||||
warn_return_any = True
|
||||
|
||||
# Shows errors for missing return statements on some execution paths
|
||||
warn_no_return = True
|
||||
|
||||
# Suppress error messages about imports that cannot be resolved
|
||||
# True => ignore all import errors
|
||||
ignore_missing_imports = True
|
||||
|
||||
# Disallows defining functions with incomplete type annotations
|
||||
disallow_incomplete_defs = False
|
||||
|
||||
# Directs what to do with imports when the imported module is found as a .py file and not part of the files,
|
||||
# modules and packages provided on the command line.
|
||||
# SKIP -> mypy checks only single file, not included imports
|
||||
follow_imports = skip
|
52
.pre-commit-config.yaml
Normal file
52
.pre-commit-config.yaml
Normal file
@ -0,0 +1,52 @@
|
||||
# See https://pre-commit.com for more information
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.3.0
|
||||
hooks:
|
||||
- id: check-yaml
|
||||
- id: check-added-large-files
|
||||
- id: fix-byte-order-marker
|
||||
- id: check-case-conflict
|
||||
- id: end-of-file-fixer
|
||||
- id: trailing-whitespace
|
||||
- id: mixed-line-ending
|
||||
- id: debug-statements
|
||||
- repo: https://github.com/pycqa/flake8
|
||||
rev: 5.0.4
|
||||
hooks:
|
||||
- id: flake8
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v0.981
|
||||
hooks:
|
||||
- id: mypy
|
||||
exclude: >
|
||||
(?x)^(
|
||||
.*.py
|
||||
)$
|
||||
- repo: https://github.com/myint/unify
|
||||
rev: v0.5
|
||||
hooks:
|
||||
- id: unify
|
||||
- repo: https://github.com/pre-commit/mirrors-yapf
|
||||
rev: "v0.32.0"
|
||||
hooks:
|
||||
- id: yapf
|
||||
- repo: https://github.com/pre-commit/mirrors-isort
|
||||
rev: v5.10.1
|
||||
hooks:
|
||||
- id: isort
|
||||
- repo: https://github.com/myint/eradicate/
|
||||
rev: v2.1.0
|
||||
hooks:
|
||||
- id: eradicate
|
||||
- repo: https://github.com/espressif/check-copyright/
|
||||
rev: v1.0.1
|
||||
hooks:
|
||||
- id: check-copyright
|
||||
args: ['--ignore', 'ci/check_copyright_ignore.txt', '--config', 'ci/check_copyright_config.yaml']
|
||||
- repo: https://github.com/igrr/astyle_py.git
|
||||
rev: c0013808882a15a0c0c2c1a9b5c903866c53a653
|
||||
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']
|
13
CONTRIBUTING.md
Normal file
13
CONTRIBUTING.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Information for Contributors
|
||||
|
||||
Contributions in the form of pull requests, issue reports, and feature requests are welcome!
|
||||
|
||||
## Submitting a PR
|
||||
|
||||
- [ ] Fork the [esp-protocols repository on GitHub](https://github.com/espressif/esp-protocols) to start making your changes.
|
||||
|
||||
- [ ] Install pre-commit hooks: `pip install pre-commit && pre-commit install`
|
||||
|
||||
- [ ] Send a pull request (PR) and work with us until it gets merged and published. Contributions may need some modifications, so a few rounds of review and fixing may be necessary.
|
||||
|
||||
For quick merging, the contribution should be short, and concentrated on a single feature or topic. The larger the contribution is, the longer it would take to review it and merge it.
|
64
ci/check_copyright_config.yaml
Normal file
64
ci/check_copyright_config.yaml
Normal file
@ -0,0 +1,64 @@
|
||||
# don't modify this section!
|
||||
DEFAULT:
|
||||
perform_check: yes # should the check be performed?
|
||||
# Sections setting this to 'no' don't need to include any other options as they are ignored
|
||||
# When a file is using a section with the option set to 'no', no checks are performed.
|
||||
|
||||
# what licenses (or license expressions) are allowed for files in this section
|
||||
# when setting this option in a section, you need to list all the allowed licenses
|
||||
allowed_licenses:
|
||||
- Apache-2.0
|
||||
license_for_new_files: Apache-2.0 # license to be used when inserting a new copyright notice
|
||||
new_notice_c: | # notice for new C, CPP, H, HPP and LD files
|
||||
/*
|
||||
* SPDX-FileCopyrightText: {years} Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: {license}
|
||||
*/
|
||||
new_notice_python: | # notice for new python files
|
||||
# SPDX-FileCopyrightText: {years} Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: {license}
|
||||
|
||||
# comment lines matching:
|
||||
# SPDX-FileCopyrightText: year[-year] Espressif Systems
|
||||
# or
|
||||
# SPDX-FileContributor: year[-year] Espressif Systems
|
||||
# are replaced with this template prefixed with the correct comment notation (# or // or *) and SPDX- notation
|
||||
espressif_copyright: '{years} Espressif Systems (Shanghai) CO LTD'
|
||||
|
||||
# this section sets the default license for examples and unit tests of components
|
||||
examples_and_unit_tests:
|
||||
include:
|
||||
- 'components/**/examples/**'
|
||||
- 'components/**/test/**'
|
||||
- 'components/**/tests/**'
|
||||
- 'common_components/**'
|
||||
allowed_licenses:
|
||||
- Apache-2.0
|
||||
- Unlicense
|
||||
- CC0-1.0
|
||||
license_for_new_files: Unlicense OR CC0-1.0
|
||||
|
||||
asio_component:
|
||||
include:
|
||||
- 'components/asio/port/**'
|
||||
allowed_licenses:
|
||||
- Apache-2.0
|
||||
- BSL-1.0
|
||||
|
||||
slim_modem_examples:
|
||||
include:
|
||||
- 'examples/esp_netif/slip_custom_netif/**'
|
||||
allowed_licenses:
|
||||
- Apache-2.0
|
||||
- Unlicense
|
||||
- CC0-1.0
|
||||
|
||||
ignore:
|
||||
perform_check: no
|
||||
include:
|
||||
- 'components/**/docs/**'
|
||||
- 'components/esp_modem/port/linux/**'
|
||||
- 'components/asio/examples/**'
|
||||
- 'components/mdns/**/esp_system_protocols_linux/**'
|
||||
- 'common_components/protocol_examples_common/**'
|
0
ci/check_copyright_ignore.txt
Normal file
0
ci/check_copyright_ignore.txt
Normal file
7
ci/clean_build_artifacts.sh
Executable file
7
ci/clean_build_artifacts.sh
Executable file
@ -0,0 +1,7 @@
|
||||
# Remove everything, but
|
||||
# - elf/bin files in the build dir
|
||||
# - partition-table and bootloader binaries
|
||||
# - flasher args
|
||||
# - sdkconfigs (header and json)
|
||||
# (Ignoring the command failure as it refuses to delete nonempty dirs)
|
||||
find $1 ! -regex ".*/build[^/]*/[^/]+.\(bin\|elf\)" -a ! -regex ".*\(bootloader\|partition-table\).bin" -a ! -name "flasher_args.json" -a ! -regex ".*/build[^/]*/config/sdkconfig.\(h\|json\)" -delete || true
|
8
ci/requirements.txt
Normal file
8
ci/requirements.txt
Normal file
@ -0,0 +1,8 @@
|
||||
pytest-embedded-serial-esp
|
||||
pytest-embedded-idf
|
||||
junit_xml
|
||||
SimpleWebSocketServer
|
||||
dpkt
|
||||
pytest
|
||||
idf_build_apps
|
||||
netifaces
|
@ -26,7 +26,7 @@ esp_err_t get_addr_from_stdin(int port, int sock_type, int *ip_protocol, int *ad
|
||||
do {
|
||||
fgets(host_ip, HOST_IP_SIZE, stdin);
|
||||
len = strlen(host_ip);
|
||||
} while (len<=1 && host_ip[0] == '\n');
|
||||
} while (len <= 1 && host_ip[0] == '\n');
|
||||
host_ip[len - 1] = '\0';
|
||||
|
||||
struct addrinfo hints, *addr_list, *cur;
|
||||
@ -36,16 +36,16 @@ esp_err_t get_addr_from_stdin(int port, int sock_type, int *ip_protocol, int *ad
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = sock_type;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
if( getaddrinfo( host_ip, NULL, &hints, &addr_list ) != 0 ) {
|
||||
if ( getaddrinfo( host_ip, NULL, &hints, &addr_list ) != 0 ) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
for( cur = addr_list; cur != NULL; cur = cur->ai_next ) {
|
||||
for ( cur = addr_list; cur != NULL; cur = cur->ai_next ) {
|
||||
memcpy(dest_addr, cur->ai_addr, sizeof(*dest_addr));
|
||||
if (cur->ai_family == AF_INET) {
|
||||
*ip_protocol = IPPROTO_IP;
|
||||
*addr_family = AF_INET;
|
||||
// add port number and return on first IPv4 match
|
||||
((struct sockaddr_in*)dest_addr)->sin_port = htons(port);
|
||||
((struct sockaddr_in *)dest_addr)->sin_port = htons(port);
|
||||
freeaddrinfo( addr_list );
|
||||
return ESP_OK;
|
||||
|
||||
@ -55,8 +55,8 @@ esp_err_t get_addr_from_stdin(int port, int sock_type, int *ip_protocol, int *ad
|
||||
*ip_protocol = IPPROTO_IPV6;
|
||||
*addr_family = AF_INET6;
|
||||
// add port and interface number and return on first IPv6 match
|
||||
((struct sockaddr_in6*)dest_addr)->sin6_port = htons(port);
|
||||
((struct sockaddr_in6*)dest_addr)->sin6_scope_id = esp_netif_get_netif_impl_index(EXAMPLE_INTERFACE);
|
||||
((struct sockaddr_in6 *)dest_addr)->sin6_port = htons(port);
|
||||
((struct sockaddr_in6 *)dest_addr)->sin6_scope_id = esp_netif_get_netif_impl_index(EXAMPLE_INTERFACE);
|
||||
freeaddrinfo( addr_list );
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
/* Common functions for protocol examples, to establish Wi-Fi or Ethernet connection.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
/*
|
||||
* Common functions for protocol examples, to establish Wi-Fi or Ethernet connection.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@ -396,7 +397,9 @@ static esp_netif_t *eth_start(void)
|
||||
#endif
|
||||
#elif CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
||||
gpio_install_isr_service(0);
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
spi_device_handle_t spi_handle = NULL;
|
||||
#endif
|
||||
spi_bus_config_t buscfg = {
|
||||
.miso_io_num = CONFIG_EXAMPLE_ETH_SPI_MISO_GPIO,
|
||||
.mosi_io_num = CONFIG_EXAMPLE_ETH_SPI_MOSI_GPIO,
|
||||
@ -414,9 +417,14 @@ static esp_netif_t *eth_start(void)
|
||||
.spics_io_num = CONFIG_EXAMPLE_ETH_SPI_CS_GPIO,
|
||||
.queue_size = 20
|
||||
};
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle));
|
||||
/* dm9051 ethernet driver is based on spi driver */
|
||||
eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle);
|
||||
#else
|
||||
eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg);
|
||||
#endif // ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
|
||||
dm9051_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
|
||||
s_mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
|
||||
s_phy = esp_eth_phy_new_dm9051(&phy_config);
|
||||
@ -429,9 +437,13 @@ static esp_netif_t *eth_start(void)
|
||||
.spics_io_num = CONFIG_EXAMPLE_ETH_SPI_CS_GPIO,
|
||||
.queue_size = 20
|
||||
};
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle));
|
||||
/* w5500 ethernet driver is based on spi driver */
|
||||
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle);
|
||||
#else
|
||||
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg);
|
||||
#endif // ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
w5500_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
|
||||
s_mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
|
||||
s_phy = esp_eth_phy_new_w5500(&phy_config);
|
||||
|
@ -1,13 +1,14 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
/* Common utilities for socket address input interface:
|
||||
The API get_addr_from_stdin() is mainly used by socket client examples which read IP address from stdin (if configured).
|
||||
This option is typically used in the CI, but could be enabled in the project configuration.
|
||||
In that case this component is used to receive a string that is evaluated and processed to output
|
||||
socket structures to open a connectio
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
@ -1,10 +1,11 @@
|
||||
/* Common functions for protocol examples, to establish Wi-Fi or Ethernet connection.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
/*
|
||||
* Common functions for protocol examples, to establish Wi-Fi or Ethernet connection.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
@ -1,10 +1,11 @@
|
||||
/* Common functions for protocol examples, to configure stdin and stdout.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
/*
|
||||
* Common functions for protocol examples, to configure stdin and stdout.
|
||||
*/
|
||||
|
||||
#include "protocol_examples_common.h"
|
||||
@ -19,7 +20,7 @@ esp_err_t example_configure_stdin_stdout(void)
|
||||
setvbuf(stdin, NULL, _IONBF, 0);
|
||||
/* Install UART driver for interrupt-driven reads and writes */
|
||||
ESP_ERROR_CHECK( uart_driver_install( (uart_port_t)CONFIG_ESP_CONSOLE_UART_NUM,
|
||||
256, 0, 0, NULL, 0) );
|
||||
256, 0, 0, NULL, 0) );
|
||||
/* Tell VFS to use UART driver */
|
||||
esp_vfs_dev_uart_use_driver(CONFIG_ESP_CONSOLE_UART_NUM);
|
||||
esp_vfs_dev_uart_port_set_rx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CR);
|
||||
|
@ -1,5 +1,7 @@
|
||||
# ASIO port
|
||||
|
||||
[](https://components.espressif.com/components/espressif/asio)
|
||||
|
||||
Asio is a cross-platform C++ library, see https://think-async.com/Asio/. It provides a consistent asynchronous model using a modern C++ approach.
|
||||
|
||||
## Examples
|
||||
|
@ -1,10 +1,11 @@
|
||||
from esp_docs.conf_docs import * # noqa: F403,F401
|
||||
|
||||
extensions += ['sphinx_copybutton',
|
||||
# Needed as a trigger for running doxygen
|
||||
'esp_docs.esp_extensions.dummy_build_system',
|
||||
'esp_docs.esp_extensions.run_doxygen',
|
||||
]
|
||||
extensions += [
|
||||
'sphinx_copybutton',
|
||||
# Needed as a trigger for running doxygen
|
||||
'esp_docs.esp_extensions.dummy_build_system',
|
||||
'esp_docs.esp_extensions.run_doxygen',
|
||||
]
|
||||
|
||||
# link roles config
|
||||
github_repo = 'espressif/esp-protocols'
|
||||
@ -14,7 +15,7 @@ html_context['github_user'] = 'espressif'
|
||||
html_context['github_repo'] = 'esp-protocols'
|
||||
|
||||
# Extra options required by sphinx_idf_theme
|
||||
project_slug = 'esp-idf' # >=5.0
|
||||
project_slug = 'esp-idf' # >=5.0
|
||||
versions_url = 'https://github.com/espressif/esp-protocols/docs/docs_versions.js'
|
||||
|
||||
idf_targets = ['esp32']
|
||||
|
@ -24,4 +24,3 @@ window.onload =(function() {
|
||||
|
||||
})();
|
||||
</script>" >> html/index.html
|
||||
|
||||
|
@ -1,29 +0,0 @@
|
||||
# This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, this
|
||||
# software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
# CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import print_function, unicode_literals
|
||||
|
||||
import re
|
||||
|
||||
import ttfw_idf
|
||||
|
||||
|
||||
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC')
|
||||
def test_examples_asio_chat(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None
|
||||
msg = 'asio-chat: received hi'
|
||||
dut = env.get_dut('asio_chat', 'examples/protocols/asio/asio_chat')
|
||||
# start the test and expect the client to receive back it's original data
|
||||
dut.start_app()
|
||||
dut.expect(re.compile(r'{}'.format('Waiting for input')), timeout=30)
|
||||
dut.write(msg)
|
||||
dut.write('exit')
|
||||
dut.expect(re.compile(r'{}'.format(msg)), timeout=30)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_examples_asio_chat()
|
@ -53,14 +53,15 @@ void start_client(void)
|
||||
#ifdef CONFIG_EXAMPLE_CHAT_SERVER
|
||||
std::lock_guard<std::mutex> guard(server_ready);
|
||||
#endif
|
||||
std::thread t([&io_context]() { try {
|
||||
io_context.run();
|
||||
} catch (const std::exception &e) {
|
||||
ESP_LOGE(TAG, "Exception occured during client thread execution %s", e.what());
|
||||
}
|
||||
catch (...) {
|
||||
ESP_LOGE(TAG, "Unknown exception");
|
||||
}});
|
||||
std::thread t([&io_context]() {
|
||||
try {
|
||||
io_context.run();
|
||||
} catch (const std::exception &e) {
|
||||
ESP_LOGE(TAG, "Exception occured during client thread execution %s", e.what());
|
||||
} catch (...) {
|
||||
ESP_LOGE(TAG, "Unknown exception");
|
||||
}
|
||||
});
|
||||
do {
|
||||
ESP_LOGI(TAG, "CLIENT: Waiting for input");
|
||||
get_string(line, sizeof(line));
|
||||
@ -95,14 +96,14 @@ extern "C" void app_main(void)
|
||||
asio::io_context io_context;
|
||||
chat_server server(io_context, tcp::endpoint(tcp::v4(), std::atoi(CONFIG_EXAMPLE_CHAT_SERVER_BIND_PORT)));
|
||||
std::thread t = std::thread([&io_context]() { // Chat server starting here
|
||||
try {
|
||||
io_context.run();
|
||||
} catch (const std::exception &e) {
|
||||
ESP_LOGE(TAG, "Exception occured during server thread execution %s", e.what());
|
||||
}
|
||||
catch (...) {
|
||||
ESP_LOGE(TAG, "Unknown exception");
|
||||
}});;
|
||||
try {
|
||||
io_context.run();
|
||||
} catch (const std::exception &e) {
|
||||
ESP_LOGE(TAG, "Exception occured during server thread execution %s", e.what());
|
||||
} catch (...) {
|
||||
ESP_LOGE(TAG, "Unknown exception");
|
||||
}
|
||||
});;
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLE_CHAT_CLIENT
|
||||
start_client();
|
||||
|
@ -15,77 +15,76 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
class chat_message
|
||||
{
|
||||
class chat_message {
|
||||
public:
|
||||
static constexpr std::size_t header_length = 4;
|
||||
static constexpr std::size_t max_body_length = 512;
|
||||
static constexpr std::size_t header_length = 4;
|
||||
static constexpr std::size_t max_body_length = 512;
|
||||
|
||||
chat_message()
|
||||
: body_length_(0)
|
||||
{
|
||||
}
|
||||
|
||||
const char* data() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
char* data()
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
std::size_t length() const
|
||||
{
|
||||
return header_length + body_length_;
|
||||
}
|
||||
|
||||
const char* body() const
|
||||
{
|
||||
return data_ + header_length;
|
||||
}
|
||||
|
||||
char* body()
|
||||
{
|
||||
return data_ + header_length;
|
||||
}
|
||||
|
||||
std::size_t body_length() const
|
||||
{
|
||||
return body_length_;
|
||||
}
|
||||
|
||||
void body_length(std::size_t new_length)
|
||||
{
|
||||
body_length_ = new_length;
|
||||
if (body_length_ > max_body_length)
|
||||
body_length_ = max_body_length;
|
||||
}
|
||||
|
||||
bool decode_header()
|
||||
{
|
||||
char header[header_length + 1] = "";
|
||||
std::strncat(header, data_, header_length);
|
||||
body_length_ = std::atoi(header);
|
||||
if (body_length_ > max_body_length)
|
||||
chat_message()
|
||||
: body_length_(0)
|
||||
{
|
||||
body_length_ = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void encode_header()
|
||||
{
|
||||
char header[header_length + 1] = "";
|
||||
std::sprintf(header, "%4d", static_cast<int>(body_length_));
|
||||
std::memcpy(data_, header, header_length);
|
||||
}
|
||||
const char *data() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
char *data()
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
std::size_t length() const
|
||||
{
|
||||
return header_length + body_length_;
|
||||
}
|
||||
|
||||
const char *body() const
|
||||
{
|
||||
return data_ + header_length;
|
||||
}
|
||||
|
||||
char *body()
|
||||
{
|
||||
return data_ + header_length;
|
||||
}
|
||||
|
||||
std::size_t body_length() const
|
||||
{
|
||||
return body_length_;
|
||||
}
|
||||
|
||||
void body_length(std::size_t new_length)
|
||||
{
|
||||
body_length_ = new_length;
|
||||
if (body_length_ > max_body_length) {
|
||||
body_length_ = max_body_length;
|
||||
}
|
||||
}
|
||||
|
||||
bool decode_header()
|
||||
{
|
||||
char header[header_length + 1] = "";
|
||||
std::strncat(header, data_, header_length);
|
||||
body_length_ = std::atoi(header);
|
||||
if (body_length_ > max_body_length) {
|
||||
body_length_ = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void encode_header()
|
||||
{
|
||||
char header[header_length + 1] = "";
|
||||
std::sprintf(header, "%4d", static_cast<int>(body_length_));
|
||||
std::memcpy(data_, header, header_length);
|
||||
}
|
||||
|
||||
private:
|
||||
char data_[header_length + max_body_length];
|
||||
std::size_t body_length_;
|
||||
char data_[header_length + max_body_length];
|
||||
std::size_t body_length_;
|
||||
};
|
||||
|
||||
#endif // CHAT_MESSAGE_HPP
|
||||
|
@ -17,107 +17,91 @@
|
||||
|
||||
typedef std::deque<chat_message> chat_message_queue;
|
||||
|
||||
class chat_client
|
||||
{
|
||||
class chat_client {
|
||||
public:
|
||||
chat_client(asio::io_context& io_context,
|
||||
const asio::ip::tcp::resolver::results_type& endpoints)
|
||||
: io_context_(io_context),
|
||||
socket_(io_context)
|
||||
{
|
||||
do_connect(endpoints);
|
||||
}
|
||||
chat_client(asio::io_context &io_context,
|
||||
const asio::ip::tcp::resolver::results_type &endpoints)
|
||||
: io_context_(io_context),
|
||||
socket_(io_context)
|
||||
{
|
||||
do_connect(endpoints);
|
||||
}
|
||||
|
||||
void write(const chat_message& msg)
|
||||
{
|
||||
asio::post(io_context_,
|
||||
[this, msg]()
|
||||
{
|
||||
bool write_in_progress = !write_msgs_.empty();
|
||||
write_msgs_.push_back(msg);
|
||||
if (!write_in_progress)
|
||||
{
|
||||
do_write();
|
||||
}
|
||||
void write(const chat_message &msg)
|
||||
{
|
||||
asio::post(io_context_,
|
||||
[this, msg]() {
|
||||
bool write_in_progress = !write_msgs_.empty();
|
||||
write_msgs_.push_back(msg);
|
||||
if (!write_in_progress) {
|
||||
do_write();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
asio::post(io_context_, [this]() { socket_.close(); });
|
||||
}
|
||||
void close()
|
||||
{
|
||||
asio::post(io_context_, [this]() {
|
||||
socket_.close();
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
void do_connect(const asio::ip::tcp::resolver::results_type& endpoints)
|
||||
void do_connect(const asio::ip::tcp::resolver::results_type &endpoints)
|
||||
{
|
||||
asio::async_connect(socket_, endpoints,
|
||||
[this](std::error_code ec, asio::ip::tcp::endpoint)
|
||||
{
|
||||
if (!ec)
|
||||
{
|
||||
do_read_header();
|
||||
asio::async_connect(socket_, endpoints,
|
||||
[this](std::error_code ec, asio::ip::tcp::endpoint) {
|
||||
if (!ec) {
|
||||
do_read_header();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void do_read_header()
|
||||
{
|
||||
asio::async_read(socket_,
|
||||
asio::buffer(read_msg_.data(), chat_message::header_length),
|
||||
[this](std::error_code ec, std::size_t /*length*/)
|
||||
{
|
||||
if (!ec && read_msg_.decode_header())
|
||||
{
|
||||
do_read_body();
|
||||
asio::async_read(socket_,
|
||||
asio::buffer(read_msg_.data(), chat_message::header_length),
|
||||
[this](std::error_code ec, std::size_t /*length*/) {
|
||||
if (!ec && read_msg_.decode_header()) {
|
||||
do_read_body();
|
||||
} else {
|
||||
socket_.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
socket_.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void do_read_body()
|
||||
{
|
||||
asio::async_read(socket_,
|
||||
asio::buffer(read_msg_.body(), read_msg_.body_length()),
|
||||
[this](std::error_code ec, std::size_t /*length*/)
|
||||
{
|
||||
if (!ec)
|
||||
{
|
||||
do_read_header();
|
||||
asio::async_read(socket_,
|
||||
asio::buffer(read_msg_.body(), read_msg_.body_length()),
|
||||
[this](std::error_code ec, std::size_t /*length*/) {
|
||||
if (!ec) {
|
||||
do_read_header();
|
||||
} else {
|
||||
socket_.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
socket_.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void do_write()
|
||||
{
|
||||
asio::async_write(socket_,
|
||||
asio::buffer(write_msgs_.front().data(),
|
||||
write_msgs_.front().length()),
|
||||
[this](std::error_code ec, std::size_t /*length*/)
|
||||
{
|
||||
if (!ec)
|
||||
{
|
||||
write_msgs_.pop_front();
|
||||
if (!write_msgs_.empty())
|
||||
{
|
||||
do_write();
|
||||
}
|
||||
void do_write()
|
||||
{
|
||||
asio::async_write(socket_,
|
||||
asio::buffer(write_msgs_.front().data(),
|
||||
write_msgs_.front().length()),
|
||||
[this](std::error_code ec, std::size_t /*length*/) {
|
||||
if (!ec) {
|
||||
write_msgs_.pop_front();
|
||||
if (!write_msgs_.empty()) {
|
||||
do_write();
|
||||
}
|
||||
} else {
|
||||
socket_.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
socket_.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
asio::io_context& io_context_;
|
||||
asio::io_context &io_context_;
|
||||
asio::ip::tcp::socket socket_;
|
||||
chat_message read_msg_;
|
||||
chat_message_queue write_msgs_;
|
||||
|
@ -27,176 +27,159 @@ extern std::mutex server_ready;
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
||||
class chat_participant
|
||||
{
|
||||
class chat_participant {
|
||||
public:
|
||||
virtual ~chat_participant() {}
|
||||
virtual void deliver(const chat_message& msg) = 0;
|
||||
virtual ~chat_participant() {}
|
||||
virtual void deliver(const chat_message &msg) = 0;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<chat_participant> chat_participant_ptr;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
class chat_room
|
||||
{
|
||||
class chat_room {
|
||||
public:
|
||||
void join(chat_participant_ptr participant)
|
||||
{
|
||||
participants_.insert(participant);
|
||||
for (auto msg: recent_msgs_)
|
||||
participant->deliver(msg);
|
||||
}
|
||||
void join(chat_participant_ptr participant)
|
||||
{
|
||||
participants_.insert(participant);
|
||||
for (auto msg : recent_msgs_) {
|
||||
participant->deliver(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void leave(chat_participant_ptr participant)
|
||||
{
|
||||
participants_.erase(participant);
|
||||
}
|
||||
void leave(chat_participant_ptr participant)
|
||||
{
|
||||
participants_.erase(participant);
|
||||
}
|
||||
|
||||
void deliver(const chat_message& msg)
|
||||
{
|
||||
recent_msgs_.push_back(msg);
|
||||
while (recent_msgs_.size() > max_recent_msgs)
|
||||
recent_msgs_.pop_front();
|
||||
void deliver(const chat_message &msg)
|
||||
{
|
||||
recent_msgs_.push_back(msg);
|
||||
while (recent_msgs_.size() > max_recent_msgs) {
|
||||
recent_msgs_.pop_front();
|
||||
}
|
||||
|
||||
for (auto participant: participants_)
|
||||
participant->deliver(msg);
|
||||
}
|
||||
for (auto participant : participants_) {
|
||||
participant->deliver(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::set<chat_participant_ptr> participants_;
|
||||
enum { max_recent_msgs = 100 };
|
||||
chat_message_queue recent_msgs_;
|
||||
std::set<chat_participant_ptr> participants_;
|
||||
enum { max_recent_msgs = 100 };
|
||||
chat_message_queue recent_msgs_;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
||||
class chat_session
|
||||
: public chat_participant,
|
||||
public std::enable_shared_from_this<chat_session>
|
||||
{
|
||||
: public chat_participant,
|
||||
public std::enable_shared_from_this<chat_session> {
|
||||
public:
|
||||
chat_session(asio::ip::tcp::socket socket, chat_room& room)
|
||||
: socket_(std::move(socket)),
|
||||
room_(room)
|
||||
{
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
room_.join(shared_from_this());
|
||||
do_read_header();
|
||||
}
|
||||
|
||||
void deliver(const chat_message& msg)
|
||||
{
|
||||
bool write_in_progress = !write_msgs_.empty();
|
||||
write_msgs_.push_back(msg);
|
||||
if (!write_in_progress)
|
||||
chat_session(asio::ip::tcp::socket socket, chat_room &room)
|
||||
: socket_(std::move(socket)),
|
||||
room_(room)
|
||||
{
|
||||
do_write();
|
||||
}
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
room_.join(shared_from_this());
|
||||
do_read_header();
|
||||
}
|
||||
|
||||
void deliver(const chat_message &msg)
|
||||
{
|
||||
bool write_in_progress = !write_msgs_.empty();
|
||||
write_msgs_.push_back(msg);
|
||||
if (!write_in_progress) {
|
||||
do_write();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void do_read_header()
|
||||
{
|
||||
auto self(shared_from_this());
|
||||
asio::async_read(socket_,
|
||||
asio::buffer(read_msg_.data(), chat_message::header_length),
|
||||
[this, self](std::error_code ec, std::size_t /*length*/)
|
||||
{
|
||||
if (!ec && read_msg_.decode_header())
|
||||
{
|
||||
do_read_body();
|
||||
}
|
||||
else
|
||||
{
|
||||
room_.leave(shared_from_this());
|
||||
}
|
||||
});
|
||||
}
|
||||
void do_read_header()
|
||||
{
|
||||
auto self(shared_from_this());
|
||||
asio::async_read(socket_,
|
||||
asio::buffer(read_msg_.data(), chat_message::header_length),
|
||||
[this, self](std::error_code ec, std::size_t /*length*/) {
|
||||
if (!ec && read_msg_.decode_header()) {
|
||||
do_read_body();
|
||||
} else {
|
||||
room_.leave(shared_from_this());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void do_read_body()
|
||||
{
|
||||
auto self(shared_from_this());
|
||||
asio::async_read(socket_,
|
||||
asio::buffer(read_msg_.body(), read_msg_.body_length()),
|
||||
[this, self](std::error_code ec, std::size_t /*length*/)
|
||||
{
|
||||
if (!ec)
|
||||
{
|
||||
ESP_LOGD("asio-chat:", "%s", read_msg_.body());
|
||||
room_.deliver(read_msg_);
|
||||
do_read_header();
|
||||
}
|
||||
else
|
||||
{
|
||||
room_.leave(shared_from_this());
|
||||
}
|
||||
});
|
||||
}
|
||||
void do_read_body()
|
||||
{
|
||||
auto self(shared_from_this());
|
||||
asio::async_read(socket_,
|
||||
asio::buffer(read_msg_.body(), read_msg_.body_length()),
|
||||
[this, self](std::error_code ec, std::size_t /*length*/) {
|
||||
if (!ec) {
|
||||
ESP_LOGD("asio-chat:", "%s", read_msg_.body());
|
||||
room_.deliver(read_msg_);
|
||||
do_read_header();
|
||||
} else {
|
||||
room_.leave(shared_from_this());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void do_write()
|
||||
{
|
||||
auto self(shared_from_this());
|
||||
asio::async_write(socket_,
|
||||
asio::buffer(write_msgs_.front().data(),
|
||||
write_msgs_.front().length()),
|
||||
[this, self](std::error_code ec, std::size_t /*length*/)
|
||||
{
|
||||
if (!ec)
|
||||
{
|
||||
write_msgs_.pop_front();
|
||||
if (!write_msgs_.empty())
|
||||
{
|
||||
do_write();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
room_.leave(shared_from_this());
|
||||
}
|
||||
});
|
||||
}
|
||||
void do_write()
|
||||
{
|
||||
auto self(shared_from_this());
|
||||
asio::async_write(socket_,
|
||||
asio::buffer(write_msgs_.front().data(),
|
||||
write_msgs_.front().length()),
|
||||
[this, self](std::error_code ec, std::size_t /*length*/) {
|
||||
if (!ec) {
|
||||
write_msgs_.pop_front();
|
||||
if (!write_msgs_.empty()) {
|
||||
do_write();
|
||||
}
|
||||
} else {
|
||||
room_.leave(shared_from_this());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
asio::ip::tcp::socket socket_;
|
||||
chat_room& room_;
|
||||
chat_message read_msg_;
|
||||
chat_message_queue write_msgs_;
|
||||
};
|
||||
asio::ip::tcp::socket socket_;
|
||||
chat_room &room_;
|
||||
chat_message read_msg_;
|
||||
chat_message_queue write_msgs_;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
class chat_server
|
||||
{
|
||||
class chat_server {
|
||||
public:
|
||||
chat_server(asio::io_context& io_context,
|
||||
const asio::ip::tcp::endpoint& endpoint)
|
||||
: acceptor_(io_context, endpoint)
|
||||
{
|
||||
do_accept();
|
||||
}
|
||||
chat_server(asio::io_context &io_context,
|
||||
const asio::ip::tcp::endpoint &endpoint)
|
||||
: acceptor_(io_context, endpoint)
|
||||
{
|
||||
do_accept();
|
||||
}
|
||||
|
||||
private:
|
||||
void do_accept()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(server_ready);
|
||||
acceptor_.async_accept(
|
||||
[this](std::error_code ec, asio::ip::tcp::socket socket)
|
||||
{
|
||||
if (!ec)
|
||||
{
|
||||
std::make_shared<chat_session>(std::move(socket), room_)->start();
|
||||
}
|
||||
void do_accept()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(server_ready);
|
||||
acceptor_.async_accept(
|
||||
[this](std::error_code ec, asio::ip::tcp::socket socket) {
|
||||
if (!ec) {
|
||||
std::make_shared<chat_session>(std::move(socket), room_)->start();
|
||||
}
|
||||
|
||||
do_accept();
|
||||
});
|
||||
}
|
||||
do_accept();
|
||||
});
|
||||
}
|
||||
|
||||
asio::ip::tcp::acceptor acceptor_;
|
||||
chat_room room_;
|
||||
asio::ip::tcp::acceptor acceptor_;
|
||||
chat_room room_;
|
||||
};
|
||||
|
||||
#endif // CHAT_SERVER_HPP
|
||||
|
16
components/asio/examples/asio_chat/pytest_asio_chat_test.py
Normal file
16
components/asio/examples/asio_chat/pytest_asio_chat_test.py
Normal file
@ -0,0 +1,16 @@
|
||||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import re
|
||||
|
||||
|
||||
def test_examples_asio_chat(dut):
|
||||
msg = 'asio-chat: received hi'
|
||||
# start the test and expect the client to receive back it's original data
|
||||
dut.expect(re.compile(b'Waiting for input'), timeout=30)
|
||||
dut.write(msg)
|
||||
dut.write('exit')
|
||||
msg = bytes(msg, encoding='utf8')
|
||||
dut.expect(re.compile(msg), timeout=30)
|
@ -1,2 +1,8 @@
|
||||
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
|
||||
CONFIG_COMPILER_CXX_EXCEPTIONS=y
|
||||
|
||||
#
|
||||
# Partition Table
|
||||
#
|
||||
# Leave some room for larger apps without needing to reduce other features
|
||||
CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y
|
||||
|
@ -70,4 +70,3 @@ ssh -N -v -D 0.0.0.0:1080 localhost
|
||||
# Async operations composition and automatic lifetime control
|
||||
|
||||
For documentation about the structure of this example look into [async\_request README](../async_request/README.md).
|
||||
|
||||
|
@ -183,7 +183,7 @@ void async_connect(asio::io_context &context, std::string proxy, std::string pro
|
||||
std::make_shared<Connection>(context)->start(proxy_resolution,
|
||||
[resolver, host_resolution, completion_handler](std::shared_ptr<Connection> connection) {
|
||||
auto connect_data = std::make_shared<ConnectionData>(socks4::request::connect, *host_resolution, "");
|
||||
ESP_LOGI(TAG, "Sending Request to proxy for host connection.");
|
||||
ESP_LOGI(TAG, "Sending Request to proxy for host connection.");
|
||||
connection->write_async(connect_data->request.buffers(), [connection, connect_data, completion_handler](std::error_code error, std::size_t bytes_received) {
|
||||
if (error) {
|
||||
ESP_LOGE(TAG, "Proxy request write error: %s", error.message().c_str());
|
||||
|
@ -20,122 +20,115 @@ namespace socks4 {
|
||||
|
||||
const unsigned char version = 0x04;
|
||||
|
||||
class request
|
||||
{
|
||||
class request {
|
||||
public:
|
||||
enum command_type
|
||||
{
|
||||
connect = 0x01,
|
||||
bind = 0x02
|
||||
};
|
||||
enum command_type {
|
||||
connect = 0x01,
|
||||
bind = 0x02
|
||||
};
|
||||
|
||||
request(command_type cmd, const asio::ip::tcp::endpoint& endpoint,
|
||||
const std::string& user_id)
|
||||
: version_(version),
|
||||
command_(cmd),
|
||||
user_id_(user_id),
|
||||
null_byte_(0)
|
||||
{
|
||||
// Only IPv4 is supported by the SOCKS 4 protocol.
|
||||
if (endpoint.protocol() != asio::ip::tcp::v4())
|
||||
request(command_type cmd, const asio::ip::tcp::endpoint &endpoint,
|
||||
const std::string &user_id)
|
||||
: version_(version),
|
||||
command_(cmd),
|
||||
user_id_(user_id),
|
||||
null_byte_(0)
|
||||
{
|
||||
throw asio::system_error(
|
||||
asio::error::address_family_not_supported);
|
||||
// Only IPv4 is supported by the SOCKS 4 protocol.
|
||||
if (endpoint.protocol() != asio::ip::tcp::v4()) {
|
||||
throw asio::system_error(
|
||||
asio::error::address_family_not_supported);
|
||||
}
|
||||
|
||||
// Convert port number to network byte order.
|
||||
unsigned short port = endpoint.port();
|
||||
port_high_byte_ = (port >> 8) & 0xff;
|
||||
port_low_byte_ = port & 0xff;
|
||||
|
||||
// Save IP address in network byte order.
|
||||
address_ = endpoint.address().to_v4().to_bytes();
|
||||
}
|
||||
|
||||
// Convert port number to network byte order.
|
||||
unsigned short port = endpoint.port();
|
||||
port_high_byte_ = (port >> 8) & 0xff;
|
||||
port_low_byte_ = port & 0xff;
|
||||
|
||||
// Save IP address in network byte order.
|
||||
address_ = endpoint.address().to_v4().to_bytes();
|
||||
}
|
||||
|
||||
std::array<asio::const_buffer, 7> buffers() const
|
||||
{
|
||||
return
|
||||
std::array<asio::const_buffer, 7> buffers() const
|
||||
{
|
||||
{
|
||||
asio::buffer(&version_, 1),
|
||||
asio::buffer(&command_, 1),
|
||||
asio::buffer(&port_high_byte_, 1),
|
||||
asio::buffer(&port_low_byte_, 1),
|
||||
asio::buffer(address_),
|
||||
asio::buffer(user_id_),
|
||||
asio::buffer(&null_byte_, 1)
|
||||
}
|
||||
};
|
||||
}
|
||||
return {
|
||||
{
|
||||
asio::buffer(&version_, 1),
|
||||
asio::buffer(&command_, 1),
|
||||
asio::buffer(&port_high_byte_, 1),
|
||||
asio::buffer(&port_low_byte_, 1),
|
||||
asio::buffer(address_),
|
||||
asio::buffer(user_id_),
|
||||
asio::buffer(&null_byte_, 1)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned char version_;
|
||||
unsigned char command_;
|
||||
unsigned char port_high_byte_;
|
||||
unsigned char port_low_byte_;
|
||||
asio::ip::address_v4::bytes_type address_;
|
||||
std::string user_id_;
|
||||
unsigned char null_byte_;
|
||||
unsigned char version_;
|
||||
unsigned char command_;
|
||||
unsigned char port_high_byte_;
|
||||
unsigned char port_low_byte_;
|
||||
asio::ip::address_v4::bytes_type address_;
|
||||
std::string user_id_;
|
||||
unsigned char null_byte_;
|
||||
};
|
||||
|
||||
class reply
|
||||
{
|
||||
class reply {
|
||||
public:
|
||||
enum status_type
|
||||
{
|
||||
request_granted = 0x5a,
|
||||
request_failed = 0x5b,
|
||||
request_failed_no_identd = 0x5c,
|
||||
request_failed_bad_user_id = 0x5d
|
||||
};
|
||||
|
||||
reply()
|
||||
: null_byte_(0),
|
||||
status_()
|
||||
{
|
||||
}
|
||||
|
||||
std::array<asio::mutable_buffer, 5> buffers()
|
||||
{
|
||||
return
|
||||
{
|
||||
{
|
||||
asio::buffer(&null_byte_, 1),
|
||||
asio::buffer(&status_, 1),
|
||||
asio::buffer(&port_high_byte_, 1),
|
||||
asio::buffer(&port_low_byte_, 1),
|
||||
asio::buffer(address_)
|
||||
}
|
||||
enum status_type {
|
||||
request_granted = 0x5a,
|
||||
request_failed = 0x5b,
|
||||
request_failed_no_identd = 0x5c,
|
||||
request_failed_bad_user_id = 0x5d
|
||||
};
|
||||
}
|
||||
|
||||
bool success() const
|
||||
{
|
||||
return null_byte_ == 0 && status_ == request_granted;
|
||||
}
|
||||
reply()
|
||||
: null_byte_(0),
|
||||
status_()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned char status() const
|
||||
{
|
||||
return status_;
|
||||
}
|
||||
std::array<asio::mutable_buffer, 5> buffers()
|
||||
{
|
||||
return {
|
||||
{
|
||||
asio::buffer(&null_byte_, 1),
|
||||
asio::buffer(&status_, 1),
|
||||
asio::buffer(&port_high_byte_, 1),
|
||||
asio::buffer(&port_low_byte_, 1),
|
||||
asio::buffer(address_)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
asio::ip::tcp::endpoint endpoint() const
|
||||
{
|
||||
unsigned short port = port_high_byte_;
|
||||
port = (port << 8) & 0xff00;
|
||||
port = port | port_low_byte_;
|
||||
bool success() const
|
||||
{
|
||||
return null_byte_ == 0 && status_ == request_granted;
|
||||
}
|
||||
|
||||
asio::ip::address_v4 address(address_);
|
||||
unsigned char status() const
|
||||
{
|
||||
return status_;
|
||||
}
|
||||
|
||||
return asio::ip::tcp::endpoint(address, port);
|
||||
}
|
||||
asio::ip::tcp::endpoint endpoint() const
|
||||
{
|
||||
unsigned short port = port_high_byte_;
|
||||
port = (port << 8) & 0xff00;
|
||||
port = port | port_low_byte_;
|
||||
|
||||
asio::ip::address_v4 address(address_);
|
||||
|
||||
return asio::ip::tcp::endpoint(address, port);
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned char null_byte_;
|
||||
unsigned char status_;
|
||||
unsigned char port_high_byte_;
|
||||
unsigned char port_low_byte_;
|
||||
asio::ip::address_v4::bytes_type address_;
|
||||
unsigned char null_byte_;
|
||||
unsigned char status_;
|
||||
unsigned char port_high_byte_;
|
||||
unsigned char port_low_byte_;
|
||||
asio::ip::address_v4::bytes_type address_;
|
||||
};
|
||||
|
||||
} // namespace socks4
|
||||
|
@ -1,16 +0,0 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import ttfw_idf
|
||||
|
||||
|
||||
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32', 'esp32c3'])
|
||||
def test_examples_asio_ssl(env, extra_data):
|
||||
|
||||
dut = env.get_dut('asio_ssl_client_server', 'examples/protocols/asio/ssl_client_server')
|
||||
dut.start_app()
|
||||
|
||||
dut.expect('Reply: GET / HTTP/1.1')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_examples_asio_ssl()
|
@ -0,0 +1,7 @@
|
||||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
||||
def test_examples_asio_ssl(dut):
|
||||
dut.expect('Reply: GET / HTTP/1.1')
|
@ -1,47 +0,0 @@
|
||||
import os
|
||||
import re
|
||||
import socket
|
||||
|
||||
import ttfw_idf
|
||||
|
||||
|
||||
@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols')
|
||||
def test_examples_protocol_asio_tcp_server(env, extra_data):
|
||||
"""
|
||||
steps: |
|
||||
1. join AP
|
||||
2. Start server
|
||||
3. Test connects to server and sends a test message
|
||||
4. Test evaluates received test message from server
|
||||
5. Test evaluates received test message on server stdout
|
||||
"""
|
||||
test_msg = b'echo message from client to server'
|
||||
dut1 = env.get_dut('tcp_echo_server', 'examples/protocols/asio/tcp_echo_server', dut_class=ttfw_idf.ESP32DUT)
|
||||
# check and log bin size
|
||||
binary_file = os.path.join(dut1.app.binary_path, 'asio_tcp_echo_server.bin')
|
||||
bin_size = os.path.getsize(binary_file)
|
||||
ttfw_idf.log_performance('asio_tcp_echo_server_bin_size', '{}KB'.format(bin_size // 1024))
|
||||
# 1. start test
|
||||
dut1.start_app()
|
||||
# 2. get the server IP address
|
||||
data = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30)
|
||||
# 3. create tcp client and connect to server
|
||||
dut1.expect('ASIO engine is up and running', timeout=1)
|
||||
cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
cli.settimeout(30)
|
||||
cli.connect((data[0], 2222))
|
||||
cli.send(test_msg)
|
||||
data = cli.recv(1024)
|
||||
# 4. check the message received back from the server
|
||||
if (data == test_msg):
|
||||
print('PASS: Received correct message')
|
||||
pass
|
||||
else:
|
||||
print('Failure!')
|
||||
raise ValueError('Wrong data received from asi tcp server: {} (expected:{})'.format(data, test_msg))
|
||||
# 5. check the client message appears also on server terminal
|
||||
dut1.expect(test_msg.decode())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_examples_protocol_asio_tcp_server()
|
@ -1,3 +1,8 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include "asio.hpp"
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
@ -8,78 +13,70 @@
|
||||
using asio::ip::tcp;
|
||||
|
||||
class session
|
||||
: public std::enable_shared_from_this<session>
|
||||
{
|
||||
: public std::enable_shared_from_this<session> {
|
||||
public:
|
||||
session(tcp::socket socket)
|
||||
: socket_(std::move(socket))
|
||||
{
|
||||
}
|
||||
session(tcp::socket socket)
|
||||
: socket_(std::move(socket))
|
||||
{
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
do_read();
|
||||
}
|
||||
void start()
|
||||
{
|
||||
do_read();
|
||||
}
|
||||
|
||||
private:
|
||||
void do_read()
|
||||
{
|
||||
auto self(shared_from_this());
|
||||
socket_.async_read_some(asio::buffer(data_, max_length),
|
||||
[this, self](std::error_code ec, std::size_t length)
|
||||
{
|
||||
if (!ec)
|
||||
{
|
||||
data_[length] = 0;
|
||||
std::cout << data_ << std::endl;
|
||||
do_write(length);
|
||||
}
|
||||
void do_read()
|
||||
{
|
||||
auto self(shared_from_this());
|
||||
socket_.async_read_some(asio::buffer(data_, max_length),
|
||||
[this, self](std::error_code ec, std::size_t length) {
|
||||
if (!ec) {
|
||||
data_[length] = 0;
|
||||
std::cout << data_ << std::endl;
|
||||
do_write(length);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void do_write(std::size_t length)
|
||||
{
|
||||
auto self(shared_from_this());
|
||||
asio::async_write(socket_, asio::buffer(data_, length),
|
||||
[this, self](std::error_code ec, std::size_t length)
|
||||
{
|
||||
if (!ec)
|
||||
{
|
||||
do_read();
|
||||
}
|
||||
void do_write(std::size_t length)
|
||||
{
|
||||
auto self(shared_from_this());
|
||||
asio::async_write(socket_, asio::buffer(data_, length),
|
||||
[this, self](std::error_code ec, std::size_t length) {
|
||||
if (!ec) {
|
||||
do_read();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
tcp::socket socket_;
|
||||
enum { max_length = 1024 };
|
||||
char data_[max_length];
|
||||
tcp::socket socket_;
|
||||
enum { max_length = 1024 };
|
||||
char data_[max_length];
|
||||
};
|
||||
|
||||
class server
|
||||
{
|
||||
class server {
|
||||
public:
|
||||
server(asio::io_context& io_context, short port)
|
||||
: acceptor_(io_context, tcp::endpoint(tcp::v4(), port))
|
||||
{
|
||||
do_accept();
|
||||
}
|
||||
server(asio::io_context &io_context, short port)
|
||||
: acceptor_(io_context, tcp::endpoint(tcp::v4(), port))
|
||||
{
|
||||
do_accept();
|
||||
}
|
||||
|
||||
private:
|
||||
void do_accept()
|
||||
{
|
||||
acceptor_.async_accept(
|
||||
[this](std::error_code ec, tcp::socket socket)
|
||||
{
|
||||
if (!ec)
|
||||
{
|
||||
std::make_shared<session>(std::move(socket))->start();
|
||||
}
|
||||
void do_accept()
|
||||
{
|
||||
acceptor_.async_accept(
|
||||
[this](std::error_code ec, tcp::socket socket) {
|
||||
if (!ec) {
|
||||
std::make_shared<session>(std::move(socket))->start();
|
||||
}
|
||||
|
||||
do_accept();
|
||||
do_accept();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
tcp::acceptor acceptor_;
|
||||
tcp::acceptor acceptor_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -0,0 +1,39 @@
|
||||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
import re
|
||||
import socket
|
||||
|
||||
|
||||
def test_examples_protocol_asio_tcp_server(dut):
|
||||
"""
|
||||
steps: |
|
||||
1. join AP
|
||||
2. Start server
|
||||
3. Test connects to server and sends a test message
|
||||
4. Test evaluates received test message from server
|
||||
5. Test evaluates received test message on server stdout
|
||||
"""
|
||||
test_msg = b'echo message from client to server'
|
||||
# 2. get the server IP address
|
||||
data = dut.expect(
|
||||
re.compile(
|
||||
b' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), # noqa: W605
|
||||
timeout=30).group(1).decode()
|
||||
# 3. create tcp client and connect to server
|
||||
dut.expect('ASIO engine is up and running', timeout=1)
|
||||
cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
cli.settimeout(30)
|
||||
cli.connect((data, 2222))
|
||||
cli.send(test_msg)
|
||||
data = cli.recv(1024)
|
||||
# 4. check the message received back from the server
|
||||
if (data == test_msg):
|
||||
print('PASS: Received correct message')
|
||||
pass
|
||||
else:
|
||||
print('Failure!')
|
||||
raise ValueError(
|
||||
'Wrong data received from asi tcp server: {} (expected:{})'.format(
|
||||
data, test_msg))
|
||||
# 5. check the client message appears also on server terminal
|
||||
dut.expect(test_msg.decode())
|
2
components/asio/examples/tcp_echo_server/sdkconfig.ci
Normal file
2
components/asio/examples/tcp_echo_server/sdkconfig.ci
Normal file
@ -0,0 +1,2 @@
|
||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
@ -1,47 +0,0 @@
|
||||
import os
|
||||
import re
|
||||
import socket
|
||||
|
||||
import ttfw_idf
|
||||
|
||||
|
||||
@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols')
|
||||
def test_examples_protocol_asio_udp_server(env, extra_data):
|
||||
"""
|
||||
steps: |
|
||||
1. join AP
|
||||
2. Start server
|
||||
3. Test connects to server and sends a test message
|
||||
4. Test evaluates received test message from server
|
||||
5. Test evaluates received test message on server stdout
|
||||
"""
|
||||
test_msg = b'echo message from client to server'
|
||||
dut1 = env.get_dut('udp_echo_server', 'examples/protocols/asio/udp_echo_server', dut_class=ttfw_idf.ESP32DUT)
|
||||
# check and log bin size
|
||||
binary_file = os.path.join(dut1.app.binary_path, 'asio_udp_echo_server.bin')
|
||||
bin_size = os.path.getsize(binary_file)
|
||||
ttfw_idf.log_performance('asio_udp_echo_server_bin_size', '{}KB'.format(bin_size // 1024))
|
||||
# 1. start test
|
||||
dut1.start_app()
|
||||
# 2. get the server IP address
|
||||
data = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30)
|
||||
# 3. create tcp client and connect to server
|
||||
dut1.expect('ASIO engine is up and running', timeout=1)
|
||||
cli = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
cli.settimeout(30)
|
||||
cli.connect((data[0], 2222))
|
||||
cli.send(test_msg)
|
||||
data = cli.recv(1024)
|
||||
# 4. check the message received back from the server
|
||||
if (data == test_msg):
|
||||
print('PASS: Received correct message')
|
||||
pass
|
||||
else:
|
||||
print('Failure!')
|
||||
raise ValueError('Wrong data received from asio udp server: {} (expected:{})'.format(data, test_msg))
|
||||
# 5. check the client message appears also on server terminal
|
||||
dut1.expect(test_msg.decode())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_examples_protocol_asio_udp_server()
|
@ -20,49 +20,43 @@
|
||||
|
||||
using asio::ip::udp;
|
||||
|
||||
class server
|
||||
{
|
||||
class server {
|
||||
public:
|
||||
server(asio::io_context& io_context, short port)
|
||||
: socket_(io_context, udp::endpoint(udp::v4(), port))
|
||||
{
|
||||
do_receive();
|
||||
}
|
||||
server(asio::io_context &io_context, short port)
|
||||
: socket_(io_context, udp::endpoint(udp::v4(), port))
|
||||
{
|
||||
do_receive();
|
||||
}
|
||||
|
||||
void do_receive()
|
||||
{
|
||||
socket_.async_receive_from(
|
||||
asio::buffer(data_, max_length), sender_endpoint_,
|
||||
[this](std::error_code ec, std::size_t bytes_recvd)
|
||||
{
|
||||
if (!ec && bytes_recvd > 0)
|
||||
{
|
||||
data_[bytes_recvd] = 0;
|
||||
std::cout << data_ << std::endl;
|
||||
do_send(bytes_recvd);
|
||||
}
|
||||
else
|
||||
{
|
||||
void do_receive()
|
||||
{
|
||||
socket_.async_receive_from(
|
||||
asio::buffer(data_, max_length), sender_endpoint_,
|
||||
[this](std::error_code ec, std::size_t bytes_recvd) {
|
||||
if (!ec && bytes_recvd > 0) {
|
||||
data_[bytes_recvd] = 0;
|
||||
std::cout << data_ << std::endl;
|
||||
do_send(bytes_recvd);
|
||||
} else {
|
||||
do_receive();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void do_send(std::size_t length)
|
||||
{
|
||||
socket_.async_send_to(
|
||||
asio::buffer(data_, length), sender_endpoint_,
|
||||
[this](std::error_code /*ec*/, std::size_t bytes /*bytes_sent*/) {
|
||||
do_receive();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void do_send(std::size_t length)
|
||||
{
|
||||
socket_.async_send_to(
|
||||
asio::buffer(data_, length), sender_endpoint_,
|
||||
[this](std::error_code /*ec*/, std::size_t bytes /*bytes_sent*/)
|
||||
{
|
||||
do_receive();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
udp::socket socket_;
|
||||
udp::endpoint sender_endpoint_;
|
||||
enum { max_length = 1024 };
|
||||
char data_[max_length];
|
||||
udp::socket socket_;
|
||||
udp::endpoint sender_endpoint_;
|
||||
enum { max_length = 1024 };
|
||||
char data_[max_length];
|
||||
};
|
||||
|
||||
extern "C" void app_main(void)
|
||||
|
@ -0,0 +1,37 @@
|
||||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
import re
|
||||
import socket
|
||||
|
||||
|
||||
def test_examples_protocol_asio_udp_server(dut):
|
||||
"""
|
||||
steps: |
|
||||
1. join AP
|
||||
2. Start server
|
||||
3. Test connects to server and sends a test message
|
||||
4. Test evaluates received test message from server
|
||||
5. Test evaluates received test message on server stdout
|
||||
"""
|
||||
test_msg = b'echo message from client to server'
|
||||
data = dut.expect(
|
||||
re.compile(
|
||||
b' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), # noqa: W605
|
||||
timeout=30).group(1).decode()
|
||||
dut.expect('ASIO engine is up and running', timeout=1)
|
||||
cli = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
cli.settimeout(30)
|
||||
cli.connect((data, 2222))
|
||||
cli.send(test_msg)
|
||||
data = cli.recv(1024)
|
||||
# 4. check the message received back from the server
|
||||
if (data == test_msg):
|
||||
print('PASS: Received correct message')
|
||||
pass
|
||||
else:
|
||||
print('Failure!')
|
||||
raise ValueError(
|
||||
'Wrong data received from asio udp server: {} (expected:{})'.
|
||||
format(data, test_msg))
|
||||
# 5. check the client message appears also on server terminal
|
||||
dut.expect(test_msg.decode())
|
2
components/asio/examples/udp_echo_server/sdkconfig.ci
Normal file
2
components/asio/examples/udp_echo_server/sdkconfig.ci
Normal file
@ -0,0 +1,2 @@
|
||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
@ -1,4 +1,4 @@
|
||||
version: "1.0.2"
|
||||
version: "1.14.1~3"
|
||||
description: ASIO
|
||||
dependencies:
|
||||
idf:
|
||||
|
@ -19,12 +19,13 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
template <typename Exception>
|
||||
void throw_exception(const Exception& e)
|
||||
void throw_exception(const Exception &e)
|
||||
{
|
||||
ESP_LOGE("esp32_asio_exception", "Caught exception: %s!", e.what());
|
||||
abort();
|
||||
ESP_LOGE("esp32_asio_exception", "Caught exception: %s!", e.what());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
#endif // CONFIG_COMPILER_CXX_EXCEPTIONS==1 && defined (ASIO_NO_EXCEPTIONS)
|
||||
|
||||
#endif // _ESP_EXCEPTION_H_
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
// SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
@ -16,9 +16,9 @@
|
||||
#define SSL_OP_SINGLE_DH_USE 0
|
||||
#define SSL_OP_NO_COMPRESSION 0
|
||||
|
||||
#define SSL_OP_NO_SSLv2 0x01000000L
|
||||
#define SSL_OP_NO_SSLv3 0x02000000L
|
||||
#define SSL_OP_NO_TLSv1 0x04000000L
|
||||
#define SSL_OP_NO_SSLv2 0x01000000L
|
||||
#define SSL_OP_NO_SSLv3 0x02000000L
|
||||
#define SSL_OP_NO_TLSv1 0x04000000L
|
||||
|
||||
#define SSL_VERIFY_NONE 0x00
|
||||
#define SSL_VERIFY_PEER 0x01
|
||||
@ -35,12 +35,14 @@ namespace mbedtls {
|
||||
class engine;
|
||||
class bio;
|
||||
class shared_ctx;
|
||||
} } } // namespace asio::ssl::mbedtls
|
||||
}
|
||||
}
|
||||
} // namespace asio::ssl::mbedtls
|
||||
|
||||
//
|
||||
// Supply OpenSSL types as aliases to mbedtls classes
|
||||
//
|
||||
using X509_STORE_CTX=void;
|
||||
using BIO=asio::ssl::mbedtls::bio;
|
||||
using SSL_CTX=asio::ssl::mbedtls::shared_ctx;
|
||||
using SSL=asio::ssl::mbedtls::engine;
|
||||
using X509_STORE_CTX = void;
|
||||
using BIO = asio::ssl::mbedtls::bio;
|
||||
using SSL_CTX = asio::ssl::mbedtls::shared_ctx;
|
||||
using SSL = asio::ssl::mbedtls::engine;
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
// SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
@ -87,7 +87,7 @@ public:
|
||||
return flags_ & BIO_FLAGS_READ;
|
||||
}
|
||||
|
||||
static std::pair<std::shared_ptr<bio>, std::shared_ptr<bio>> new_pair(const char* error_location)
|
||||
static std::pair<std::shared_ptr<bio>, std::shared_ptr<bio>> new_pair(const char *error_location)
|
||||
{
|
||||
auto b1 = std::shared_ptr<bio>(new (std::nothrow) bio);
|
||||
auto b2 = std::shared_ptr<bio>(new (std::nothrow) bio);
|
||||
@ -110,4 +110,6 @@ private:
|
||||
size_t flags_ {0};
|
||||
};
|
||||
|
||||
} } } // namespace asio::ssl::mbedtls
|
||||
}
|
||||
}
|
||||
} // namespace asio::ssl::mbedtls
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
// SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
@ -11,13 +11,13 @@
|
||||
namespace asio {
|
||||
namespace error {
|
||||
|
||||
const asio::error_category& get_mbedtls_category();
|
||||
const asio::error_category &get_mbedtls_category();
|
||||
} // namespace error
|
||||
|
||||
namespace ssl {
|
||||
namespace mbedtls {
|
||||
|
||||
void throw_alloc_failure(const char* location);
|
||||
void throw_alloc_failure(const char *location);
|
||||
|
||||
const char *error_message(int error_code);
|
||||
|
||||
@ -26,11 +26,10 @@ enum class container {
|
||||
};
|
||||
|
||||
template <typename T, typename... Args>
|
||||
inline T* create(const char * location, Args &&... args)
|
||||
inline T *create(const char *location, Args &&... args)
|
||||
{
|
||||
T* t = new (std::nothrow) T(std::forward<Args>(args)...);
|
||||
if (t == nullptr)
|
||||
{
|
||||
T *t = new (std::nothrow) T(std::forward<Args>(args)...);
|
||||
if (t == nullptr) {
|
||||
throw_alloc_failure(location);
|
||||
}
|
||||
return t;
|
||||
@ -43,12 +42,12 @@ public:
|
||||
const unsigned char *data(container c) const
|
||||
{
|
||||
switch (c) {
|
||||
case container::CERT:
|
||||
return static_cast<const unsigned char *>(cert_chain_.data());
|
||||
case container::CA_CERT:
|
||||
return static_cast<const unsigned char *>(ca_cert_.data());
|
||||
case container::PRIVKEY:
|
||||
return static_cast<const unsigned char *>(private_key_.data());
|
||||
case container::CERT:
|
||||
return static_cast<const unsigned char *>(cert_chain_.data());
|
||||
case container::CA_CERT:
|
||||
return static_cast<const unsigned char *>(ca_cert_.data());
|
||||
case container::PRIVKEY:
|
||||
return static_cast<const unsigned char *>(private_key_.data());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -56,12 +55,12 @@ public:
|
||||
std::size_t size(container c) const
|
||||
{
|
||||
switch (c) {
|
||||
case container::CERT:
|
||||
return cert_chain_.size();
|
||||
case container::CA_CERT:
|
||||
return ca_cert_.size();
|
||||
case container::PRIVKEY:
|
||||
return private_key_.size();
|
||||
case container::CERT:
|
||||
return cert_chain_.size();
|
||||
case container::CA_CERT:
|
||||
return ca_cert_.size();
|
||||
case container::PRIVKEY:
|
||||
return private_key_.size();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -80,11 +79,10 @@ public:
|
||||
*/
|
||||
class shared_ctx {
|
||||
public:
|
||||
static SSL_CTX *create(const char* location, context_base::method m)
|
||||
static SSL_CTX *create(const char *location, context_base::method m)
|
||||
{
|
||||
auto wrapped = asio::ssl::mbedtls::create<shared_ctx>(location, m);
|
||||
if (wrapped->ctx_ == nullptr)
|
||||
{
|
||||
if (wrapped->ctx_ == nullptr) {
|
||||
throw_alloc_failure(location);
|
||||
}
|
||||
return wrapped;
|
||||
@ -96,10 +94,12 @@ public:
|
||||
}
|
||||
|
||||
explicit shared_ctx(context_base::method m)
|
||||
:ctx_(std::shared_ptr<context>(new (std::nothrow) context(m))) { }
|
||||
: ctx_(std::shared_ptr<context>(new (std::nothrow) context(m))) { }
|
||||
|
||||
private:
|
||||
std::shared_ptr<mbedtls::context> ctx_;
|
||||
};
|
||||
|
||||
} } } // namespace asio::ssl::mbedtls
|
||||
}
|
||||
}
|
||||
} // namespace asio::ssl::mbedtls
|
||||
|
@ -23,7 +23,7 @@ const char *error_message(int error_code)
|
||||
return error_buf;
|
||||
}
|
||||
|
||||
void throw_alloc_failure(const char* location)
|
||||
void throw_alloc_failure(const char *location)
|
||||
{
|
||||
asio::error_code ec( MBEDTLS_ERR_SSL_ALLOC_FAILED, asio::error::get_mbedtls_category());
|
||||
asio::detail::throw_error(ec, location);
|
||||
@ -62,7 +62,7 @@ public:
|
||||
verify_mode_ = mode;
|
||||
}
|
||||
|
||||
bio* ext_bio() const
|
||||
bio *ext_bio() const
|
||||
{
|
||||
return bio_.second.get();
|
||||
}
|
||||
@ -95,14 +95,14 @@ public:
|
||||
int write(const void *buffer, int len)
|
||||
{
|
||||
int ret = impl_.write(buffer, len);
|
||||
state_ = ret == len ? IDLE: WRITING;
|
||||
state_ = ret == len ? IDLE : WRITING;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int read(void *buffer, int len)
|
||||
{
|
||||
int ret = impl_.read(buffer, len);
|
||||
state_ = ret == len ? IDLE: READING;
|
||||
state_ = ret == len ? IDLE : READING;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -117,7 +117,7 @@ private:
|
||||
|
||||
static int bio_read(void *ctx, unsigned char *buf, size_t len)
|
||||
{
|
||||
auto bio = static_cast<BIO*>(ctx);
|
||||
auto bio = static_cast<BIO *>(ctx);
|
||||
int read = bio->read(buf, len);
|
||||
if (read <= 0 && bio->should_read()) {
|
||||
return MBEDTLS_ERR_SSL_WANT_READ;
|
||||
@ -127,7 +127,7 @@ private:
|
||||
|
||||
static int bio_write(void *ctx, const unsigned char *buf, size_t len)
|
||||
{
|
||||
auto bio = static_cast<BIO*>(ctx);
|
||||
auto bio = static_cast<BIO *>(ctx);
|
||||
int written = bio->write(buf, len);
|
||||
if (written <= 0 && bio->should_write()) {
|
||||
return MBEDTLS_ERR_SSL_WANT_WRITE;
|
||||
@ -163,25 +163,27 @@ private:
|
||||
{
|
||||
int mode = MBEDTLS_SSL_VERIFY_UNSET;
|
||||
if (is_client_not_server) {
|
||||
if (verify_mode_ & SSL_VERIFY_PEER)
|
||||
if (verify_mode_ & SSL_VERIFY_PEER) {
|
||||
mode = MBEDTLS_SSL_VERIFY_REQUIRED;
|
||||
else if (verify_mode_ == SSL_VERIFY_NONE)
|
||||
} else if (verify_mode_ == SSL_VERIFY_NONE) {
|
||||
mode = MBEDTLS_SSL_VERIFY_NONE;
|
||||
}
|
||||
} else {
|
||||
if (verify_mode_ & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
|
||||
if (verify_mode_ & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) {
|
||||
mode = MBEDTLS_SSL_VERIFY_REQUIRED;
|
||||
else if (verify_mode_ & SSL_VERIFY_PEER)
|
||||
} else if (verify_mode_ & SSL_VERIFY_PEER) {
|
||||
mode = MBEDTLS_SSL_VERIFY_OPTIONAL;
|
||||
else if (verify_mode_ == SSL_VERIFY_NONE)
|
||||
} else if (verify_mode_ == SSL_VERIFY_NONE) {
|
||||
mode = MBEDTLS_SSL_VERIFY_NONE;
|
||||
}
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
struct impl {
|
||||
static void print_error(const char* function, int error_code)
|
||||
static void print_error(const char *function, int error_code)
|
||||
{
|
||||
constexpr const char *TAG="mbedtls-engine-impl";
|
||||
constexpr const char *TAG = "mbedtls-engine-impl";
|
||||
ESP_LOGE(TAG, "%s() returned -0x%04X", function, -error_code);
|
||||
ESP_LOGI(TAG, "-0x%04X: %s", -error_code, error_message(error_code));
|
||||
}
|
||||
@ -230,7 +232,7 @@ private:
|
||||
mbedtls_x509_crt_init(&public_cert_);
|
||||
mbedtls_pk_init(&pk_key_);
|
||||
mbedtls_x509_crt_init(&ca_cert_);
|
||||
int ret = mbedtls_ssl_config_defaults(&conf_, is_client_not_server ? MBEDTLS_SSL_IS_CLIENT: MBEDTLS_SSL_IS_SERVER,
|
||||
int ret = mbedtls_ssl_config_defaults(&conf_, is_client_not_server ? MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
|
||||
if (ret) {
|
||||
print_error("mbedtls_ssl_config_defaults", ret);
|
||||
@ -290,4 +292,6 @@ private:
|
||||
asio::ssl::verify_mode verify_mode_;
|
||||
};
|
||||
|
||||
} } } // namespace asio::ssl::mbedtls
|
||||
}
|
||||
}
|
||||
} // namespace asio::ssl::mbedtls
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
// SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
@ -14,30 +14,29 @@ namespace asio {
|
||||
namespace error {
|
||||
namespace detail {
|
||||
|
||||
class mbedtls_category : public asio::error_category
|
||||
{
|
||||
class mbedtls_category : public asio::error_category {
|
||||
public:
|
||||
const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT
|
||||
const char *name() const ASIO_ERROR_CATEGORY_NOEXCEPT
|
||||
{
|
||||
return "asio.ssl";
|
||||
}
|
||||
|
||||
std::string message(int value) const
|
||||
{
|
||||
const char* s = asio::ssl::mbedtls::error_message(value);
|
||||
const char *s = asio::ssl::mbedtls::error_message(value);
|
||||
return s ? s : "asio.mbedtls error";
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
const asio::error_category& get_mbedtls_category()
|
||||
const asio::error_category &get_mbedtls_category()
|
||||
{
|
||||
static detail::mbedtls_category instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
const asio::error_category& get_ssl_category()
|
||||
const asio::error_category &get_ssl_category()
|
||||
{
|
||||
return asio::error::get_mbedtls_category();
|
||||
}
|
||||
@ -47,9 +46,11 @@ const asio::error_category& get_ssl_category()
|
||||
namespace ssl {
|
||||
namespace error {
|
||||
|
||||
const asio::error_category& get_stream_category()
|
||||
const asio::error_category &get_stream_category()
|
||||
{
|
||||
return asio::error::get_mbedtls_category();
|
||||
}
|
||||
|
||||
} } } // namespace asio::ssl::error
|
||||
}
|
||||
}
|
||||
} // namespace asio::ssl::error
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
// SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
// SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
// SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
// SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
// SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
// SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
@ -4,7 +4,7 @@
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
// SPDX-FileContributor: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
// SPDX-FileContributor: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
@ -22,19 +22,19 @@ namespace ssl {
|
||||
|
||||
|
||||
context::context(context::method m)
|
||||
: handle_(0)
|
||||
: handle_(0)
|
||||
{
|
||||
handle_ = mbedtls::shared_ctx::create("mbedtls-context", m);
|
||||
set_options(no_compression);
|
||||
}
|
||||
|
||||
context::context(context&& other)
|
||||
context::context(context &&other)
|
||||
{
|
||||
handle_ = other.handle_;
|
||||
other.handle_ = 0;
|
||||
}
|
||||
|
||||
context& context::operator=(context&& other)
|
||||
context &context::operator=(context &&other)
|
||||
{
|
||||
context tmp(ASIO_MOVE_CAST(context)(*this));
|
||||
handle_ = other.handle_;
|
||||
@ -60,14 +60,14 @@ void context::set_options(context::options o)
|
||||
}
|
||||
|
||||
ASIO_SYNC_OP_VOID context::set_options(
|
||||
context::options o, asio::error_code& ec)
|
||||
context::options o, asio::error_code &ec)
|
||||
{
|
||||
handle_->get()->options_ = o;
|
||||
ec = asio::error_code();
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
void context::add_certificate_authority(const const_buffer& ca)
|
||||
void context::add_certificate_authority(const const_buffer &ca)
|
||||
{
|
||||
asio::error_code ec;
|
||||
add_certificate_authority(ca, ec);
|
||||
@ -75,13 +75,13 @@ void context::add_certificate_authority(const const_buffer& ca)
|
||||
}
|
||||
|
||||
ASIO_SYNC_OP_VOID context::add_certificate_authority(
|
||||
const const_buffer& ca, asio::error_code& ec)
|
||||
const const_buffer &ca, asio::error_code &ec)
|
||||
{
|
||||
handle_->get()->ca_cert_ = ca;
|
||||
ASIO_SYNC_OP_VOID_RETURN(asio::error_code());
|
||||
}
|
||||
|
||||
void context::use_certificate_chain(const const_buffer& chain)
|
||||
void context::use_certificate_chain(const const_buffer &chain)
|
||||
{
|
||||
asio::error_code ec;
|
||||
use_certificate_chain(chain, ec);
|
||||
@ -89,14 +89,14 @@ void context::use_certificate_chain(const const_buffer& chain)
|
||||
}
|
||||
|
||||
ASIO_SYNC_OP_VOID context::use_certificate_chain(
|
||||
const const_buffer& chain, asio::error_code& ec)
|
||||
const const_buffer &chain, asio::error_code &ec)
|
||||
{
|
||||
handle_->get()->cert_chain_ = chain;
|
||||
ASIO_SYNC_OP_VOID_RETURN(asio::error_code());
|
||||
}
|
||||
|
||||
void context::use_private_key(
|
||||
const const_buffer& private_key, context::file_format format)
|
||||
const const_buffer &private_key, context::file_format format)
|
||||
{
|
||||
asio::error_code ec;
|
||||
use_private_key(private_key, format, ec);
|
||||
@ -104,8 +104,8 @@ void context::use_private_key(
|
||||
}
|
||||
|
||||
ASIO_SYNC_OP_VOID context::use_private_key(
|
||||
const const_buffer& private_key, context::file_format format,
|
||||
asio::error_code& ec)
|
||||
const const_buffer &private_key, context::file_format format,
|
||||
asio::error_code &ec)
|
||||
{
|
||||
handle_->get()->private_key_ = private_key;
|
||||
ASIO_SYNC_OP_VOID_RETURN(asio::error_code());
|
||||
|
@ -3,7 +3,7 @@
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
// SPDX-FileContributor: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
// SPDX-FileContributor: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
@ -24,8 +24,8 @@ namespace ssl {
|
||||
namespace detail {
|
||||
|
||||
|
||||
engine::engine(SSL_CTX* context)
|
||||
: ssl_(nullptr)
|
||||
engine::engine(SSL_CTX *context)
|
||||
: ssl_(nullptr)
|
||||
{
|
||||
ssl_ = mbedtls::create<mbedtls::engine>("mbedtls-engine", context->get());
|
||||
}
|
||||
@ -35,49 +35,47 @@ engine::~engine()
|
||||
delete ssl_;
|
||||
}
|
||||
|
||||
SSL* engine::native_handle()
|
||||
SSL *engine::native_handle()
|
||||
{
|
||||
return ssl_;
|
||||
}
|
||||
|
||||
asio::error_code engine::set_verify_mode(
|
||||
verify_mode v, asio::error_code& ec)
|
||||
verify_mode v, asio::error_code &ec)
|
||||
{
|
||||
ssl_->set_verify_mode(v);
|
||||
return {};
|
||||
}
|
||||
|
||||
engine::want engine::handshake(
|
||||
stream_base::handshake_type type, asio::error_code& ec)
|
||||
stream_base::handshake_type type, asio::error_code &ec)
|
||||
{
|
||||
return perform((type == asio::ssl::stream_base::client)
|
||||
? &engine::do_connect : &engine::do_accept, 0, 0, ec, 0);
|
||||
}
|
||||
|
||||
engine::want engine::shutdown(asio::error_code& ec)
|
||||
engine::want engine::shutdown(asio::error_code &ec)
|
||||
{
|
||||
return perform(&engine::do_shutdown, 0, 0, ec, 0);
|
||||
}
|
||||
|
||||
engine::want engine::write(const asio::const_buffer& data,
|
||||
asio::error_code& ec, std::size_t& bytes_transferred)
|
||||
engine::want engine::write(const asio::const_buffer &data,
|
||||
asio::error_code &ec, std::size_t &bytes_transferred)
|
||||
{
|
||||
if (data.size() == 0)
|
||||
{
|
||||
if (data.size() == 0) {
|
||||
ec = asio::error_code();
|
||||
return engine::want_nothing;
|
||||
}
|
||||
|
||||
return perform(&engine::do_write,
|
||||
const_cast<void*>(data.data()),
|
||||
const_cast<void *>(data.data()),
|
||||
data.size(), ec, &bytes_transferred);
|
||||
}
|
||||
|
||||
engine::want engine::read(const asio::mutable_buffer& data,
|
||||
asio::error_code& ec, std::size_t& bytes_transferred)
|
||||
engine::want engine::read(const asio::mutable_buffer &data,
|
||||
asio::error_code &ec, std::size_t &bytes_transferred)
|
||||
{
|
||||
if (data.size() == 0)
|
||||
{
|
||||
if (data.size() == 0) {
|
||||
ec = asio::error_code();
|
||||
return engine::want_nothing;
|
||||
}
|
||||
@ -87,7 +85,7 @@ engine::want engine::read(const asio::mutable_buffer& data,
|
||||
}
|
||||
|
||||
asio::mutable_buffer engine::get_output(
|
||||
const asio::mutable_buffer& data)
|
||||
const asio::mutable_buffer &data)
|
||||
{
|
||||
int length = ssl_->ext_bio()->read(data.data(), static_cast<int>(data.size()));
|
||||
|
||||
@ -96,7 +94,7 @@ asio::mutable_buffer engine::get_output(
|
||||
}
|
||||
|
||||
asio::const_buffer engine::put_input(
|
||||
const asio::const_buffer& data)
|
||||
const asio::const_buffer &data)
|
||||
{
|
||||
int length = ssl_->ext_bio()->write(data.data(), static_cast<int>(data.size()));
|
||||
|
||||
@ -104,23 +102,22 @@ asio::const_buffer engine::put_input(
|
||||
(length > 0 ? static_cast<std::size_t>(length) : 0));
|
||||
}
|
||||
|
||||
const asio::error_code& engine::map_error_code(
|
||||
asio::error_code& ec) const
|
||||
const asio::error_code &engine::map_error_code(
|
||||
asio::error_code &ec) const
|
||||
{
|
||||
// We only want to map the error::eof code.
|
||||
if (ec != asio::error::eof)
|
||||
if (ec != asio::error::eof) {
|
||||
return ec;
|
||||
}
|
||||
|
||||
// If there's data yet to be read, it's an error.
|
||||
if (ssl_->ext_bio()->wpending())
|
||||
{
|
||||
if (ssl_->ext_bio()->wpending()) {
|
||||
ec = asio::ssl::error::stream_truncated;
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Otherwise, the peer should have negotiated a proper shutdown.
|
||||
if (ssl_->shutdown() != 0)
|
||||
{
|
||||
if (ssl_->shutdown() != 0) {
|
||||
ec = asio::ssl::error::stream_truncated;
|
||||
}
|
||||
|
||||
@ -129,47 +126,39 @@ const asio::error_code& engine::map_error_code(
|
||||
|
||||
// This is a simplified implementation of a generic ssl io operation
|
||||
// original implementation using openssl's SSL object is in asio/include/asio/ssl/detail/impl/engine.ipp
|
||||
engine::want engine::perform(int (engine::* op)(void*, std::size_t),
|
||||
void* data, std::size_t length, asio::error_code& ec,
|
||||
std::size_t* bytes_transferred)
|
||||
engine::want engine::perform(int (engine::* op)(void *, std::size_t),
|
||||
void *data, std::size_t length, asio::error_code &ec,
|
||||
std::size_t *bytes_transferred)
|
||||
{
|
||||
std::size_t pending_output_before = ssl_->ext_bio()->ctrl_pending();
|
||||
int result = (this->*op)(data, length);
|
||||
|
||||
std::size_t pending_output_after = ssl_->ext_bio()->ctrl_pending();
|
||||
|
||||
if (mbedtls::error_codes::is_error(result))
|
||||
{
|
||||
if (mbedtls::error_codes::is_error(result)) {
|
||||
ec = asio::error_code(result, asio::error::get_mbedtls_category());
|
||||
return pending_output_after > pending_output_before ? want_output : want_nothing;
|
||||
}
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
if (result == 0) {
|
||||
return pending_output_after > pending_output_before
|
||||
? want_output : want_nothing;
|
||||
}
|
||||
|
||||
if (result > 0 && bytes_transferred)
|
||||
if (result > 0 && bytes_transferred) {
|
||||
*bytes_transferred = static_cast<std::size_t>(result);
|
||||
}
|
||||
|
||||
if (mbedtls::error_codes::want_write(result))
|
||||
{
|
||||
if (mbedtls::error_codes::want_write(result)) {
|
||||
ec = asio::error_code();
|
||||
return want_output_and_retry;
|
||||
}
|
||||
else if (pending_output_after > pending_output_before)
|
||||
{
|
||||
} else if (pending_output_after > pending_output_before) {
|
||||
ec = asio::error_code();
|
||||
return result > 0 ? want_output : want_output_and_retry;
|
||||
}
|
||||
else if (mbedtls::error_codes::want_read(result))
|
||||
{
|
||||
} else if (mbedtls::error_codes::want_read(result)) {
|
||||
ec = asio::error_code();
|
||||
return want_input_and_retry;
|
||||
}
|
||||
else if (ssl_->get_state() == mbedtls::CLOSED)
|
||||
{
|
||||
} else if (ssl_->get_state() == mbedtls::CLOSED) {
|
||||
ec = asio::error::eof;
|
||||
return want_nothing;
|
||||
}
|
||||
@ -178,27 +167,27 @@ engine::want engine::perform(int (engine::* op)(void*, std::size_t),
|
||||
return want_nothing;
|
||||
}
|
||||
|
||||
int engine::do_accept(void*, std::size_t)
|
||||
int engine::do_accept(void *, std::size_t)
|
||||
{
|
||||
return ssl_->accept();
|
||||
}
|
||||
|
||||
int engine::do_connect(void*, std::size_t)
|
||||
int engine::do_connect(void *, std::size_t)
|
||||
{
|
||||
return ssl_->connect();
|
||||
}
|
||||
|
||||
int engine::do_shutdown(void*, std::size_t)
|
||||
int engine::do_shutdown(void *, std::size_t)
|
||||
{
|
||||
return ssl_->shutdown();
|
||||
}
|
||||
|
||||
int engine::do_read(void* data, std::size_t length)
|
||||
int engine::do_read(void *data, std::size_t length)
|
||||
{
|
||||
return ssl_->read(data, length < INT_MAX ? static_cast<int>(length) : INT_MAX);
|
||||
}
|
||||
|
||||
int engine::do_write(void* data, std::size_t length)
|
||||
int engine::do_write(void *data, std::size_t length)
|
||||
{
|
||||
return ssl_->write(data, length < INT_MAX ? static_cast<int>(length) : INT_MAX);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
// SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
@ -17,4 +17,6 @@ asio::detail::shared_ptr<openssl_init_base::do_init> openssl_init_base::instance
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} } } // namespace asio::ssl::detail
|
||||
}
|
||||
}
|
||||
} // namespace asio::ssl::detail
|
||||
|
3
components/esp_modem/.gitignore
vendored
3
components/esp_modem/.gitignore
vendored
@ -91,3 +91,6 @@ dependencies.lock
|
||||
|
||||
# ignore generated docs
|
||||
docs/html
|
||||
|
||||
# esp-idf managed components
|
||||
**/managed_components/**
|
||||
|
@ -14,6 +14,7 @@ else()
|
||||
set(dependencies driver esp_event esp_netif)
|
||||
endif()
|
||||
|
||||
|
||||
set(srcs ${platform_srcs}
|
||||
"src/esp_modem_dte.cpp"
|
||||
"src/esp_modem_dce.cpp"
|
||||
@ -34,15 +35,27 @@ idf_component_register(SRCS "${srcs}"
|
||||
PRIV_INCLUDE_DIRS private_include
|
||||
REQUIRES ${dependencies})
|
||||
|
||||
|
||||
set_target_properties(${COMPONENT_LIB} PROPERTIES
|
||||
CXX_STANDARD 17
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
CXX_EXTENSIONS ON
|
||||
)
|
||||
|
||||
|
||||
if(${target} STREQUAL "linux")
|
||||
# This is needed for ESP_LOGx() macros, as integer formats differ on ESP32(..) and x64
|
||||
set_target_properties(${COMPONENT_LIB} PROPERTIES COMPILE_FLAGS -Wno-format)
|
||||
endif()
|
||||
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
if(CONFIG_GCOV_ENABLED)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage -fprofile-arcs -ftest-coverage")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage -fprofile-arcs -ftest-coverage")
|
||||
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
CMAKE_CXX_FLAGS_COVERAGE
|
||||
CMAKE_C_FLAGS_COVERAGE
|
||||
CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
|
||||
endif()
|
||||
|
28
components/esp_modem/Kconfig
Normal file
28
components/esp_modem/Kconfig
Normal file
@ -0,0 +1,28 @@
|
||||
menu "esp-modem"
|
||||
|
||||
config ESP_MODEM_CMUX_DEFRAGMENT_PAYLOAD
|
||||
bool "Defragment CMUX messages internally"
|
||||
default y
|
||||
help
|
||||
If enabled (default), the esp-modem automatically defragments CMUX messages
|
||||
to only pass the completed CMUX message to higher layers.
|
||||
This is useful for messages in command mode (if they're received fragmented).
|
||||
It's not a problem for messages in data mode as the upper layer (PPP protocol)
|
||||
defines message boundaries.
|
||||
Keep the default to true for most cases (as most devices use simply 1 byte CMUX
|
||||
length, as the internal Rx buffer of size >= 256 bytes won't overflow)
|
||||
Set to false if your devices uses 2 byte CMUX payload (e.g. A7672S).
|
||||
The operation would work without an issue in data mode, but some replies
|
||||
in command mode might come fragmented in rare cases so might need to retry
|
||||
AT commands.
|
||||
|
||||
config ESP_MODEM_CMUX_DELAY_AFTER_DLCI_SETUP
|
||||
int "Delay in ms to wait before creating another virtual terminal"
|
||||
default 0
|
||||
help
|
||||
Some devices might need a pause before sending SABM command that creates
|
||||
virtual terminal. This delay applies only to establishing a CMUX mode.
|
||||
The typical reason for failing SABM request without a delay is that
|
||||
some devices (SIM800) send MSC requests just after opening a new DLCI.
|
||||
|
||||
endmenu
|
@ -1,5 +1,7 @@
|
||||
# ESP MODEM
|
||||
|
||||
[](https://components.espressif.com/components/espressif/esp_modem)
|
||||
|
||||
The `esp-modem` component is a managed component for `esp-idf` that is used for communication with GSM/LTE modems
|
||||
that support AT commands and PPP protocol as a network interface.
|
||||
|
||||
|
@ -2522,4 +2522,3 @@ DOT_CLEANUP = YES
|
||||
#DOT_GRAPH_MAX_NODES = 100
|
||||
#MAX_DOT_GRAPH_DEPTH = 0
|
||||
#DOT_TRANSPARENT = YES
|
||||
|
||||
|
@ -69,10 +69,24 @@ after creating multiple virtual terminals, designating some of them solely to da
|
||||
|
||||
### DTE's
|
||||
|
||||
Currently we support only UART, but modern modules support other communication interfaces, such as USB, SPI.
|
||||
Currently, we support only UART (and USB as a preview feature), but modern modules support other communication interfaces, such as USB, SPI.
|
||||
|
||||
### Other devices
|
||||
|
||||
Adding a new device is a must-have requirement for the esp-modem component. Different modules support different commands,
|
||||
or some commands might have a different implementation. Adding a new device means to provide a new implementation
|
||||
as a class derived from `GenericModule`, where we could add new commands or modify the existing ones.
|
||||
|
||||
## Configuration
|
||||
|
||||
Modem abstraction is configurable both compile-time and run-time.
|
||||
|
||||
### Component Kconfig
|
||||
|
||||
Compile-time configuration is provided using menuconfig. Please check the description for the CMUX mode configuration options.
|
||||
|
||||
### Runtime configuration
|
||||
|
||||
Is defined using standard configuration structures for `DTE` and `DCE` objects separately. Please find documentation of
|
||||
* :cpp:class:`esp_modem_dte_config_t`
|
||||
* :cpp:class:`esp_modem_dce_config_t`
|
||||
|
@ -46,4 +46,3 @@ a custom DTE object and supply it into :ref:`the DCE factory<dce_factory>`. The
|
||||
- Create the DTE which uses the custom Terminal
|
||||
|
||||
Please refer to the implementation of the existing UART DTE.
|
||||
|
||||
|
@ -2,11 +2,6 @@
|
||||
#
|
||||
# English Language RTD & Sphinx config file
|
||||
#
|
||||
import os
|
||||
import os.path
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
# General information about the project.
|
||||
project = u'esp-modem'
|
||||
@ -18,11 +13,12 @@ language = 'en'
|
||||
|
||||
extensions = ['breathe', 'recommonmark']
|
||||
|
||||
|
||||
breathe_projects = {'esp_modem': 'xml'}
|
||||
|
||||
breathe_default_project = "esp_modem"
|
||||
breathe_default_project = 'esp_modem'
|
||||
|
||||
source_suffix = ['.rst', '.md']
|
||||
|
||||
source_parsers = {'.md': 'recommonmark.parser.CommonMarkParser', }
|
||||
source_parsers = {
|
||||
'.md': 'recommonmark.parser.CommonMarkParser',
|
||||
}
|
||||
|
@ -115,8 +115,3 @@ Modem types
|
||||
|
||||
.. doxygengroup:: ESP_MODEM_TYPES
|
||||
:members:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -7,3 +7,4 @@ endif()
|
||||
idf_component_register(SRCS "ap_to_pppos.c"
|
||||
${NETWORK_DCE}
|
||||
INCLUDE_DIRS ".")
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
|
@ -1,24 +1,26 @@
|
||||
/* softAP to PPPoS Example
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
/*
|
||||
* softAP to PPPoS Example
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "esp_system.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_idf_version.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "lwip/lwip_napt.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "network_dce.h"
|
||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
||||
#include "esp_mac.h"
|
||||
#include "dhcpserver/dhcpserver.h"
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
#include "esp_mac.h"
|
||||
#include "dhcpserver/dhcpserver.h"
|
||||
#endif
|
||||
|
||||
#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID
|
||||
@ -76,15 +78,15 @@ static esp_err_t set_dhcps_dns(esp_netif_t *netif, uint32_t addr)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void* event_data)
|
||||
static void wifi_event_handler(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
if (event_id == WIFI_EVENT_AP_STACONNECTED) {
|
||||
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
|
||||
wifi_event_ap_staconnected_t *event = (wifi_event_ap_staconnected_t *) event_data;
|
||||
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
|
||||
MAC2STR(event->mac), event->aid);
|
||||
} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
|
||||
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
|
||||
wifi_event_ap_stadisconnected_t *event = (wifi_event_ap_stadisconnected_t *) event_data;
|
||||
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
|
||||
MAC2STR(event->mac), event->aid);
|
||||
}
|
||||
@ -97,10 +99,10 @@ void wifi_init_softap(void)
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
|
||||
ESP_EVENT_ANY_ID,
|
||||
&wifi_event_handler,
|
||||
NULL,
|
||||
NULL));
|
||||
ESP_EVENT_ANY_ID,
|
||||
&wifi_event_handler,
|
||||
NULL,
|
||||
NULL));
|
||||
|
||||
wifi_config_t wifi_config = {
|
||||
.ap = {
|
||||
@ -161,8 +163,8 @@ void app_main(void)
|
||||
// Initialize NVS
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
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(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
|
@ -1,10 +1,11 @@
|
||||
/* softAP to PPPoS Example (network_dce)
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
/*
|
||||
* softAP to PPPoS Example (network_dce)
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
@ -1,10 +1,11 @@
|
||||
/* softAP to PPPoS Example (network_dce)
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
/*
|
||||
* softAP to PPPoS Example (network_dce)
|
||||
*/
|
||||
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
@ -92,8 +93,9 @@ public:
|
||||
bool check_signal()
|
||||
{
|
||||
int rssi, ber;
|
||||
if (dce_commands::get_signal_quality(dte.get(), rssi, ber) != command_result::OK)
|
||||
if (dce_commands::get_signal_quality(dte.get(), rssi, ber) != command_result::OK) {
|
||||
return false;
|
||||
}
|
||||
return rssi != 99 && rssi > 5;
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,11 @@
|
||||
/* softAP to PPPoS Example (network_dce)
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
/*
|
||||
* softAP to PPPoS Example (network_dce)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
@ -1,3 +1,8 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
#include <unistd.h>
|
||||
@ -61,7 +66,7 @@ int main()
|
||||
|
||||
bool pin_ok = true;
|
||||
if (dce->read_pin(pin_ok) == command_result::OK && !pin_ok) {
|
||||
throw_if_false(dce->set_pin(CONFIG_EXAMPLE_SIM_PIN) == command_result::OK, "Cannot set PIN!");
|
||||
ESP_MODEM_THROW_IF_FALSE(dce->set_pin(CONFIG_EXAMPLE_SIM_PIN) == command_result::OK, "Cannot set PIN!");
|
||||
usleep(1000000);
|
||||
}
|
||||
std::string str;
|
||||
|
@ -2,15 +2,5 @@
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS "../..")
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/version.cmake)
|
||||
|
||||
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "4.4")
|
||||
if(("${IDF_TARGET}" STREQUAL "esp32s2") OR ("${IDF_TARGET}" STREQUAL "esp32s3"))
|
||||
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/examples/peripherals/usb/host/cdc/common")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(modem-console)
|
||||
|
@ -8,4 +8,3 @@ PROJECT_NAME := modem-console
|
||||
EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
||||
|
@ -20,7 +20,11 @@ For USB enabled targets (ESP32-S2 and ESP32-S3), it is possible to connect to th
|
||||
1. In menuconfig, navigate to `Example Configuration->Type of serial connection to the modem` and choose `USB`.
|
||||
2. Connect the modem USB signals to pin 19 (DATA-) and 20 (DATA+) on your ESP chip.
|
||||
|
||||
USB example uses Quactel BG96 modem device.
|
||||
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
|
||||
|
||||
|
@ -1,19 +0,0 @@
|
||||
include($ENV{IDF_PATH}/tools/cmake/version.cmake)
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
|
||||
# USB is supported on S2 and S3 targets and IDF version >= 4.4
|
||||
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "4.4")
|
||||
if(("${target}" STREQUAL "esp32s2") OR ("${target}" STREQUAL "esp32s3"))
|
||||
|
||||
idf_component_register(SRCS "esp_modem_usb.cpp" "esp_modem_usb_api_target.cpp"
|
||||
REQUIRES cdc_acm_host esp_modem
|
||||
REQUIRED_IDF_TARGETS esp32s2 esp32s3
|
||||
PRIV_INCLUDE_DIRS "private_include"
|
||||
INCLUDE_DIRS "include")
|
||||
|
||||
set_target_properties(${COMPONENT_LIB} PROPERTIES
|
||||
CXX_STANDARD 17
|
||||
)
|
||||
|
||||
endif()
|
||||
endif()
|
@ -1,191 +0,0 @@
|
||||
// Copyright 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_modem_config.h"
|
||||
#include "esp_modem_usb_config.h"
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "usb/usb_host.h"
|
||||
#include "usb/cdc_acm_host.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "usb_terminal.hpp"
|
||||
|
||||
static const char *TAG = "usb_terminal";
|
||||
|
||||
/**
|
||||
* @brief USB Host task
|
||||
*
|
||||
* This task is created only if install_usb_host is set to true in DTE configuration.
|
||||
* In case the user doesn't want in install USB Host driver here, he must install it before creating UsbTerminal object.
|
||||
*
|
||||
* @param arg Unused
|
||||
*/
|
||||
void usb_host_task(void *arg)
|
||||
{
|
||||
while (1) {
|
||||
// Start handling system events
|
||||
uint32_t event_flags;
|
||||
usb_host_lib_handle_events(portMAX_DELAY, &event_flags);
|
||||
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {
|
||||
ESP_LOGD(TAG, "No more clients: clean up\n");
|
||||
usb_host_device_free_all();
|
||||
}
|
||||
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
|
||||
ESP_LOGD(TAG, "All free: uninstall USB lib\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up USB Host
|
||||
vTaskDelay(10); // Short delay to allow clients clean-up
|
||||
usb_host_lib_handle_events(0, NULL); // Make sure there are now pending events
|
||||
usb_host_uninstall();
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
namespace esp_modem {
|
||||
class UsbTerminal : public Terminal, private CdcAcmDevice {
|
||||
public:
|
||||
explicit UsbTerminal(const esp_modem_dte_config *config)
|
||||
{
|
||||
const struct esp_modem_usb_term_config* usb_config = (struct esp_modem_usb_term_config*)(config->extension_config);
|
||||
|
||||
// Install USB Host driver
|
||||
if (usb_config->install_usb_host) {
|
||||
const usb_host_config_t host_config = {
|
||||
.skip_phy_setup = false,
|
||||
.intr_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
};
|
||||
throw_if_esp_fail(usb_host_install(&host_config), "USB Host install failed");
|
||||
ESP_LOGD(TAG, "USB Host installed");
|
||||
throw_if_false(pdTRUE == xTaskCreatePinnedToCore(usb_host_task, "usb_host", 4096, NULL, config->task_priority + 1, NULL, usb_config->xCoreID), "USB host task failed");
|
||||
}
|
||||
|
||||
// Install CDC-ACM driver
|
||||
const cdc_acm_host_driver_config_t esp_modem_cdc_acm_driver_config = {
|
||||
.driver_task_stack_size = config->task_stack_size,
|
||||
.driver_task_priority = config->task_priority,
|
||||
.xCoreID = (BaseType_t)usb_config->xCoreID
|
||||
};
|
||||
|
||||
// Silently continue of error: CDC-ACM driver might be already installed
|
||||
cdc_acm_host_install(&esp_modem_cdc_acm_driver_config);
|
||||
|
||||
// Open CDC-ACM device
|
||||
const cdc_acm_host_device_config_t esp_modem_cdc_acm_device_config = {
|
||||
.connection_timeout_ms = usb_config->timeout_ms,
|
||||
.out_buffer_size = config->dte_buffer_size,
|
||||
.event_cb = handle_notif,
|
||||
.data_cb = handle_rx,
|
||||
.user_arg = this
|
||||
};
|
||||
|
||||
if (usb_config->cdc_compliant) {
|
||||
throw_if_esp_fail(this->CdcAcmDevice::open(usb_config->vid, usb_config->pid,
|
||||
usb_config->interface_idx, &esp_modem_cdc_acm_device_config),
|
||||
"USB Device open failed");
|
||||
} else {
|
||||
throw_if_esp_fail(this->CdcAcmDevice::open_vendor_specific(usb_config->vid, usb_config->pid,
|
||||
usb_config->interface_idx, &esp_modem_cdc_acm_device_config),
|
||||
"USB Device open failed");
|
||||
}
|
||||
};
|
||||
|
||||
~UsbTerminal()
|
||||
{
|
||||
this->CdcAcmDevice::close();
|
||||
};
|
||||
|
||||
void start() override
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void stop() override
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int write(uint8_t *data, size_t len) override
|
||||
{
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, data, len, ESP_LOG_DEBUG);
|
||||
if (this->CdcAcmDevice::tx_blocking(data, len) != ESP_OK) {
|
||||
return -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int read(uint8_t *data, size_t len) override
|
||||
{
|
||||
// This function should never be called. UsbTerminal provides data through Terminal::on_read callback
|
||||
ESP_LOGW(TAG, "Unexpected call to UsbTerminal::read function");
|
||||
return -1;
|
||||
}
|
||||
|
||||
private:
|
||||
UsbTerminal() = delete;
|
||||
UsbTerminal(const UsbTerminal ©) = delete;
|
||||
UsbTerminal &operator=(const UsbTerminal ©) = delete;
|
||||
bool operator== (const UsbTerminal ¶m) const = delete;
|
||||
bool operator!= (const UsbTerminal ¶m) const = delete;
|
||||
|
||||
static void handle_rx(uint8_t *data, size_t data_len, void *user_arg)
|
||||
{
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, data, data_len, ESP_LOG_DEBUG);
|
||||
UsbTerminal *this_terminal = static_cast<UsbTerminal *>(user_arg);
|
||||
if (data_len > 0 && this_terminal->on_read) {
|
||||
this_terminal->on_read(data, data_len);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Unhandled RX data");
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_notif(cdc_acm_dev_hdl_t cdc_hdl, const cdc_acm_host_dev_event_data_t *event, void *user_ctx)
|
||||
{
|
||||
UsbTerminal *this_terminal = static_cast<UsbTerminal *>(user_ctx);
|
||||
|
||||
switch (event->type) {
|
||||
// Notifications like Ring, Rx Carrier indication or Network connection indication are not relevant for USB terminal
|
||||
case CDC_ACM_HOST_NETWORK_CONNECTION:
|
||||
case CDC_ACM_HOST_SERIAL_STATE:
|
||||
break;
|
||||
case CDC_ACM_HOST_DEVICE_DISCONNECTED:
|
||||
ESP_LOGW(TAG, "USB terminal disconnected");
|
||||
cdc_acm_host_close(cdc_hdl);
|
||||
if (this_terminal->on_error) {
|
||||
this_terminal->on_error(terminal_error::UNEXPECTED_CONTROL_FLOW);
|
||||
}
|
||||
break;
|
||||
case CDC_ACM_HOST_ERROR:
|
||||
ESP_LOGE(TAG, "Unexpected CDC-ACM error: %d.", event->data.error);
|
||||
if (this_terminal->on_error) {
|
||||
this_terminal->on_error(terminal_error::UNEXPECTED_CONTROL_FLOW);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
std::unique_ptr<Terminal> create_usb_terminal(const esp_modem_dte_config *config)
|
||||
{
|
||||
TRY_CATCH_RET_NULL(
|
||||
return std::make_unique<UsbTerminal>(config);
|
||||
)
|
||||
}
|
||||
} // namespace esp_modem
|
@ -1,32 +0,0 @@
|
||||
// Copyright 2021-2022 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "usb_terminal.hpp"
|
||||
#include "cxx_include/esp_modem_api.hpp"
|
||||
#include "cxx_include/esp_modem_netif.hpp"
|
||||
|
||||
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||
static const char *TAG = "modem_usb_api_target";
|
||||
#endif
|
||||
|
||||
namespace esp_modem {
|
||||
std::shared_ptr<DTE> create_usb_dte(const dte_config *config)
|
||||
{
|
||||
TRY_CATCH_RET_NULL(
|
||||
auto term = create_usb_terminal(config);
|
||||
return std::make_shared<DTE>(config, std::move(term));
|
||||
)
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
// Copyright 2021-2022 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
#include "cxx_include/esp_modem_dce.hpp"
|
||||
#include "cxx_include/esp_modem_dce_module.hpp"
|
||||
|
||||
namespace esp_modem {
|
||||
/**
|
||||
* @brief Create USB DTE
|
||||
*
|
||||
* @param config DTE configuration
|
||||
* @return shared ptr to DTE on success
|
||||
* nullptr on failure (either due to insufficient memory or wrong dte configuration)
|
||||
* if exceptions are disabled the API abort()'s on error
|
||||
*/
|
||||
std::shared_ptr<DTE> create_usb_dte(const dte_config *config);
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
// Copyright 2021-2022 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
* @brief USB configuration structure
|
||||
* @see USB host CDC-ACM driver documentation for details about interfaces settings
|
||||
*/
|
||||
struct esp_modem_usb_term_config {
|
||||
uint16_t vid; /*!< Vendor ID of the USB device */
|
||||
uint16_t pid; /*!< Product ID of the USB device */
|
||||
int interface_idx; /*!< USB Interface index that will be used */
|
||||
uint32_t timeout_ms; /*!< Time for a USB modem to connect to USB host. 0 means wait forever. */
|
||||
int xCoreID; /*!< Core affinity of created tasks: CDC-ACM driver task and optional USB Host task */
|
||||
bool cdc_compliant; /*!< Treat the USB device as CDC-compliant. Read CDC-ACM driver documentation for more details */
|
||||
bool install_usb_host; /*!< Flag whether USB Host driver should be installed */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief ESP Mode USB DTE Default Configuration
|
||||
*
|
||||
* @param[in] _usb_config esp_modem_usb_term_config configuration structure. Can be obtained by ESP_MODEM_DEFAULT_USB_CONFIG
|
||||
*
|
||||
*/
|
||||
#define ESP_MODEM_DTE_DEFAULT_USB_CONFIG(_usb_config) \
|
||||
{ \
|
||||
.dte_buffer_size = 512, \
|
||||
.task_stack_size = 4096, \
|
||||
.task_priority = 5, \
|
||||
.extension_config = &_usb_config \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ESP Modem USB Default Configuration
|
||||
*
|
||||
* @param[in] _vid USB Vendor ID
|
||||
* @param[in] _pid USB Product ID
|
||||
* @see USB host CDC-ACM driver documentation for details about interfaces settings
|
||||
*/
|
||||
#define ESP_MODEM_DEFAULT_USB_CONFIG(_vid, _pid) \
|
||||
{ \
|
||||
.vid = _vid, \
|
||||
.pid = _pid, \
|
||||
.interface_idx = 0, \
|
||||
.timeout_ms = 0, \
|
||||
.xCoreID = 0, \
|
||||
.cdc_compliant = false, \
|
||||
.install_usb_host = true \
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
// Copyright 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
struct esp_modem_dte_config;
|
||||
|
||||
// Copy-pasted from esp_modem/private_include/exception_stub.hpp
|
||||
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||
#define TRY_CATCH_OR_DO(block, action) \
|
||||
try { block \
|
||||
} catch (std::bad_alloc& e) { \
|
||||
ESP_LOGE(TAG, "Out of memory"); \
|
||||
action; \
|
||||
} catch (::esp_modem::esp_err_exception& e) { \
|
||||
esp_err_t err = e.get_err_t(); \
|
||||
ESP_LOGE(TAG, "%s: Exception caught with ESP err_code=%d", __func__, err); \
|
||||
ESP_LOGE(TAG, "%s", e.what()); \
|
||||
action; \
|
||||
}
|
||||
|
||||
#define TRY_CATCH_RET_NULL(block) TRY_CATCH_OR_DO(block, return nullptr)
|
||||
#else
|
||||
|
||||
#define TRY_CATCH_OR_DO(block, action) \
|
||||
block
|
||||
|
||||
#define TRY_CATCH_RET_NULL(block) \
|
||||
block
|
||||
|
||||
#endif
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
std::unique_ptr<Terminal> create_usb_terminal(const esp_modem_dte_config *config);
|
||||
|
||||
} // namespace esp_modem
|
@ -2,6 +2,6 @@ idf_component_register(SRCS "modem_console_main.cpp"
|
||||
"console_helper.cpp"
|
||||
"httpget_handle.c"
|
||||
"ping_handle.c"
|
||||
REQUIRES console esp_http_client nvs_flash esp_modem esp_modem_usb_dte
|
||||
REQUIRES console esp_http_client nvs_flash
|
||||
INCLUDE_DIRS ".")
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
|
@ -14,4 +14,159 @@ menu "Example Configuration"
|
||||
help
|
||||
Connect to modem via USB (CDC-ACM class). For IDF version >= 4.4.
|
||||
endchoice
|
||||
|
||||
choice EXAMPLE_MODEM_DEVICE
|
||||
depends on EXAMPLE_SERIAL_CONFIG_UART
|
||||
prompt "Choose supported modem device (DCE)"
|
||||
default EXAMPLE_MODEM_DEVICE_BG96
|
||||
help
|
||||
Select modem device connected to the ESP DTE.
|
||||
config EXAMPLE_MODEM_DEVICE_SHINY
|
||||
bool "SHINY"
|
||||
help
|
||||
SHINY is a GSM/GPRS module.
|
||||
It supports SHINY.
|
||||
config EXAMPLE_MODEM_DEVICE_SIM800
|
||||
bool "SIM800"
|
||||
help
|
||||
SIMCom SIM800L is a GSM/GPRS module.
|
||||
It supports Quad-band 850/900/1800/1900MHz.
|
||||
config EXAMPLE_MODEM_DEVICE_BG96
|
||||
bool "BG96"
|
||||
help
|
||||
Quectel BG96 is a series of LTE Cat M1/Cat NB1/EGPRS module.
|
||||
config EXAMPLE_MODEM_DEVICE_SIM7000
|
||||
bool "SIM7000"
|
||||
help
|
||||
SIM7000 is a Multi-Band LTE-FDD and GSM/GPRS/EDGE module.
|
||||
config EXAMPLE_MODEM_DEVICE_SIM7070
|
||||
bool "SIM7070"
|
||||
help
|
||||
SIM7070 is Multi-Band CAT M and NB IoT module.
|
||||
config EXAMPLE_MODEM_DEVICE_SIM7600
|
||||
bool "SIM7600"
|
||||
help
|
||||
SIM7600 is a Multi-Band LTE-TDD/LTE-FDD/HSPA+ and GSM/GPRS/EDGE module.
|
||||
endchoice
|
||||
|
||||
config EXAMPLE_MODEM_PPP_APN
|
||||
string "Set MODEM APN"
|
||||
default "internet"
|
||||
help
|
||||
Set APN (Access Point Name), a logical name to choose data network
|
||||
|
||||
config EXAMPLE_MODEM_PPP_AUTH_USERNAME
|
||||
string "Set username for authentication"
|
||||
default "espressif"
|
||||
depends on !EXAMPLE_MODEM_PPP_AUTH_NONE
|
||||
help
|
||||
Set username for PPP Authentication.
|
||||
|
||||
config EXAMPLE_MODEM_PPP_AUTH_PASSWORD
|
||||
string "Set password for authentication"
|
||||
default "esp32"
|
||||
depends on !EXAMPLE_MODEM_PPP_AUTH_NONE
|
||||
help
|
||||
Set password for PPP Authentication.
|
||||
|
||||
config EXAMPLE_MODEM_PPP_AUTH_NONE
|
||||
bool "Skip PPP authentication"
|
||||
default n
|
||||
help
|
||||
Set to true for the PPP client to skip authentication
|
||||
|
||||
menu "UART Configuration"
|
||||
depends on EXAMPLE_SERIAL_CONFIG_UART
|
||||
|
||||
choice EXAMPLE_FLOW_CONTROL
|
||||
bool "Set preferred modem control flow"
|
||||
default EXAMPLE_FLOW_CONTROL_NONE
|
||||
help
|
||||
Set the modem's preferred control flow
|
||||
|
||||
config EXAMPLE_FLOW_CONTROL_NONE
|
||||
bool "No control flow"
|
||||
config EXAMPLE_FLOW_CONTROL_SW
|
||||
bool "SW control flow"
|
||||
config EXAMPLE_FLOW_CONTROL_HW
|
||||
bool "HW control flow"
|
||||
endchoice
|
||||
|
||||
config EXAMPLE_MODEM_UART_TX_PIN
|
||||
int "TXD Pin Number"
|
||||
default 25
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART TX.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RX_PIN
|
||||
int "RXD Pin Number"
|
||||
default 26
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART RX.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RTS_PIN
|
||||
int "RTS Pin Number"
|
||||
default 27
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART RTS.
|
||||
|
||||
config EXAMPLE_MODEM_UART_CTS_PIN
|
||||
int "CTS Pin Number"
|
||||
default 23
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART CTS.
|
||||
|
||||
config EXAMPLE_MODEM_UART_EVENT_TASK_STACK_SIZE
|
||||
int "UART Event Task Stack Size"
|
||||
range 2000 6000
|
||||
default 4096
|
||||
help
|
||||
Stack size of UART event task.
|
||||
|
||||
config EXAMPLE_MODEM_UART_EVENT_TASK_PRIORITY
|
||||
int "UART Event Task Priority"
|
||||
range 3 22
|
||||
default 5
|
||||
help
|
||||
Priority of UART event task.
|
||||
|
||||
config EXAMPLE_MODEM_UART_EVENT_QUEUE_SIZE
|
||||
int "UART Event Queue Size"
|
||||
range 10 40
|
||||
default 30
|
||||
help
|
||||
Length of UART event queue.
|
||||
|
||||
config EXAMPLE_MODEM_UART_PATTERN_QUEUE_SIZE
|
||||
int "UART Pattern Queue Size"
|
||||
range 10 40
|
||||
default 20
|
||||
help
|
||||
Length of UART pattern queue.
|
||||
|
||||
config EXAMPLE_MODEM_UART_TX_BUFFER_SIZE
|
||||
int "UART TX Buffer Size"
|
||||
range 256 2048
|
||||
default 512
|
||||
help
|
||||
Buffer size of UART TX buffer.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RX_BUFFER_SIZE
|
||||
int "UART RX Buffer Size"
|
||||
range 256 2048
|
||||
default 1024
|
||||
help
|
||||
Buffer size of UART RX buffer.
|
||||
endmenu
|
||||
|
||||
config EXAMPLE_MODEM_PWRKEY_PIN
|
||||
int "PWRKEY Pin Number"
|
||||
default 18
|
||||
range 0 31
|
||||
help
|
||||
Pin number connected to modem's power key pin.
|
||||
endmenu
|
||||
|
@ -1,10 +1,11 @@
|
||||
/* Modem console example
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
/*
|
||||
* Modem console example
|
||||
*/
|
||||
|
||||
#include "console_helper.hpp"
|
||||
@ -18,6 +19,16 @@ ConsoleCommand::ConsoleCommand(const char *command, const char *help, const std:
|
||||
RegisterCommand(command, help, args);
|
||||
}
|
||||
|
||||
ConsoleCommand::~ConsoleCommand()
|
||||
{
|
||||
// Find this command in static list of commands and remove it
|
||||
auto cmd = std::find(console_commands.begin(), console_commands.end(), this);
|
||||
if (cmd != console_commands.end()) {
|
||||
console_commands.erase(cmd);
|
||||
last_command--;
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleCommand::RegisterCommand(const char *command, const char *help, const std::vector<CommandArgs> &args)
|
||||
{
|
||||
assert(last_command <= MAX_REPEAT_NR);
|
||||
|
@ -1,10 +1,11 @@
|
||||
/* Modem console example
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
/*
|
||||
* Modem console example
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -92,6 +93,11 @@ public:
|
||||
*/
|
||||
explicit ConsoleCommand(const char *command, const char *help, const std::vector<CommandArgs> &args, std::function<bool(ConsoleCommand *)> f);
|
||||
|
||||
/**
|
||||
* @brief Destructor of ConsoleCommand
|
||||
*/
|
||||
~ConsoleCommand();
|
||||
|
||||
/**
|
||||
* @brief Utility getters of various params from the argument list
|
||||
*/
|
||||
|
@ -1,10 +1,12 @@
|
||||
/* Modem console example
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
/*
|
||||
* Modem console example
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@ -19,34 +21,34 @@ static const char *TAG = "modem_console_httpget";
|
||||
|
||||
static esp_err_t http_event_handler(esp_http_client_event_t *evt)
|
||||
{
|
||||
switch(evt->event_id) {
|
||||
case HTTP_EVENT_ERROR:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
|
||||
break;
|
||||
case HTTP_EVENT_ON_CONNECTED:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
|
||||
break;
|
||||
case HTTP_EVENT_HEADER_SENT:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
|
||||
break;
|
||||
case HTTP_EVENT_ON_HEADER:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
|
||||
break;
|
||||
case HTTP_EVENT_ON_DATA:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
|
||||
if ((bool)evt->user_data &&
|
||||
switch (evt->event_id) {
|
||||
case HTTP_EVENT_ERROR:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
|
||||
break;
|
||||
case HTTP_EVENT_ON_CONNECTED:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
|
||||
break;
|
||||
case HTTP_EVENT_HEADER_SENT:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
|
||||
break;
|
||||
case HTTP_EVENT_ON_HEADER:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
|
||||
break;
|
||||
case HTTP_EVENT_ON_DATA:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
|
||||
if ((bool)evt->user_data &&
|
||||
!esp_http_client_is_chunked_response(evt->client)) {
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, evt->data, evt->data_len, ESP_LOG_INFO);
|
||||
}
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, evt->data, evt->data_len, ESP_LOG_INFO);
|
||||
}
|
||||
|
||||
break;
|
||||
case HTTP_EVENT_ON_FINISH:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
|
||||
break;
|
||||
case HTTP_EVENT_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
|
||||
break;
|
||||
default: break;
|
||||
break;
|
||||
case HTTP_EVENT_ON_FINISH:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
|
||||
break;
|
||||
case HTTP_EVENT_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -65,7 +67,7 @@ static int do_http_client(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
esp_http_client_config_t config = {
|
||||
.event_handler = http_event_handler,
|
||||
.event_handler = http_event_handler,
|
||||
};
|
||||
|
||||
if (http_args.host->count > 0) {
|
||||
@ -76,11 +78,11 @@ static int do_http_client(int argc, char **argv)
|
||||
|
||||
if (http_args.hex->count > 0) {
|
||||
// show hex data from http-get
|
||||
config.user_data = (void*)true;
|
||||
config.user_data = (void *)true;
|
||||
}
|
||||
|
||||
|
||||
esp_http_client_handle_t client = esp_http_client_init(&config);
|
||||
esp_http_client_handle_t client = esp_http_client_init(&config);
|
||||
|
||||
esp_err_t err = esp_http_client_perform(client);
|
||||
if (err == ESP_OK) {
|
||||
@ -99,11 +101,11 @@ void modem_console_register_http(void)
|
||||
http_args.hex = arg_litn("p", "print-hex", 0, 1, "print hex output"),
|
||||
http_args.end = arg_end(1);
|
||||
const esp_console_cmd_t http_cmd = {
|
||||
.command = "httpget",
|
||||
.help = "http get command to test data mode",
|
||||
.hint = NULL,
|
||||
.func = &do_http_client,
|
||||
.argtable = &http_args
|
||||
.command = "httpget",
|
||||
.help = "http get command to test data mode",
|
||||
.hint = NULL,
|
||||
.func = &do_http_client,
|
||||
.argtable = &http_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&http_cmd));
|
||||
}
|
||||
|
@ -0,0 +1,12 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
## Required IDF version
|
||||
idf: ">=4.1.0"
|
||||
espressif/esp_modem:
|
||||
version: "^0.1.20"
|
||||
override_path: "../../../"
|
||||
espressif/esp_modem_usb_dte:
|
||||
version: "^1.0.0"
|
||||
rules:
|
||||
- if: "idf_version >=4.4"
|
||||
- if: "target in [esp32s2, esp32s3]"
|
@ -1,10 +1,11 @@
|
||||
/* Modem console example
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
/*
|
||||
* Modem console example
|
||||
*/
|
||||
|
||||
#include <cstdio>
|
||||
@ -15,10 +16,12 @@
|
||||
#include "esp_console.h"
|
||||
#include "esp_event.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "esp_modem_config.h"
|
||||
#include "cxx_include/esp_modem_api.hpp"
|
||||
#if defined(CONFIG_USB_OTG_SUPPORTED)
|
||||
#if defined(CONFIG_EXAMPLE_SERIAL_CONFIG_USB)
|
||||
#include "esp_modem_usb_config.h"
|
||||
#include "cxx_include/esp_modem_usb_api.hpp"
|
||||
#endif
|
||||
@ -26,6 +29,14 @@
|
||||
#include "console_helper.hpp"
|
||||
#include "my_module_dce.hpp"
|
||||
|
||||
#if defined(CONFIG_EXAMPLE_FLOW_CONTROL_NONE)
|
||||
#define EXAMPLE_FLOW_CONTROL ESP_MODEM_FLOW_CONTROL_NONE
|
||||
#elif defined(CONFIG_EXAMPLE_FLOW_CONTROL_SW)
|
||||
#define EXAMPLE_FLOW_CONTROL ESP_MODEM_FLOW_CONTROL_SW
|
||||
#elif defined(CONFIG_EXAMPLE_FLOW_CONTROL_HW)
|
||||
#define EXAMPLE_FLOW_CONTROL ESP_MODEM_FLOW_CONTROL_HW
|
||||
#endif
|
||||
|
||||
#define CHECK_ERR(cmd, success_action) do { \
|
||||
auto err = cmd; \
|
||||
if (err == command_result::OK) { \
|
||||
@ -33,7 +44,7 @@
|
||||
return 0; \
|
||||
} else { \
|
||||
ESP_LOGE(TAG, "Failed with %s", err == command_result::TIMEOUT ? "TIMEOUT":"ERROR"); \
|
||||
return 1; \
|
||||
return 1; \
|
||||
} } while (0)
|
||||
|
||||
/**
|
||||
@ -41,6 +52,9 @@
|
||||
*/
|
||||
#define DEFAULT_APN "my_apn"
|
||||
|
||||
#define GPIO_OUTPUT_PWRKEY (gpio_num_t)CONFIG_EXAMPLE_MODEM_PWRKEY_PIN
|
||||
#define GPIO_OUTPUT_PIN_SEL (1ULL<<GPIO_OUTPUT_PWRKEY)
|
||||
|
||||
extern "C" void modem_console_register_http(void);
|
||||
extern "C" void modem_console_register_ping(void);
|
||||
|
||||
@ -48,10 +62,40 @@ static const char *TAG = "modem_console";
|
||||
static esp_console_repl_t *s_repl = nullptr;
|
||||
|
||||
using namespace esp_modem;
|
||||
static SignalGroup exit_signal;
|
||||
|
||||
|
||||
void config_gpio(void)
|
||||
{
|
||||
gpio_config_t io_conf = {}; //zero-initialize the config structure.
|
||||
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE; //disable interrupt
|
||||
io_conf.mode = GPIO_MODE_OUTPUT; //set as output mode
|
||||
io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL; //bit mask of the pins that you want to set,e.g.GPIO18/19
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; //disable pull-down mode
|
||||
io_conf.pull_up_en = GPIO_PULLUP_DISABLE; //disable pull-up mode
|
||||
|
||||
gpio_config(&io_conf); //configure GPIO with the given settings
|
||||
}
|
||||
|
||||
void wakeup_modem(void)
|
||||
{
|
||||
/* Power on the modem */
|
||||
ESP_LOGI(TAG, "Power on the modem");
|
||||
gpio_set_level(GPIO_OUTPUT_PWRKEY, 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
gpio_set_level(GPIO_OUTPUT_PWRKEY, 0);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
}
|
||||
|
||||
extern "C" void app_main(void)
|
||||
{
|
||||
static RTC_RODATA_ATTR char apn_rtc[20] = DEFAULT_APN;
|
||||
static RTC_DATA_ATTR modem_mode mode_rtc = esp_modem::modem_mode::COMMAND_MODE;
|
||||
|
||||
config_gpio();
|
||||
|
||||
ESP_ERROR_CHECK(nvs_flash_init());
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
@ -64,17 +108,58 @@ extern "C" void app_main(void)
|
||||
|
||||
#if defined(CONFIG_EXAMPLE_SERIAL_CONFIG_UART)
|
||||
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
||||
/* setup UART specific configuration based on kconfig options */
|
||||
dte_config.uart_config.tx_io_num = CONFIG_EXAMPLE_MODEM_UART_TX_PIN;
|
||||
dte_config.uart_config.rx_io_num = CONFIG_EXAMPLE_MODEM_UART_RX_PIN;
|
||||
dte_config.uart_config.rts_io_num = CONFIG_EXAMPLE_MODEM_UART_RTS_PIN;
|
||||
dte_config.uart_config.cts_io_num = CONFIG_EXAMPLE_MODEM_UART_CTS_PIN;
|
||||
dte_config.uart_config.flow_control = EXAMPLE_FLOW_CONTROL;
|
||||
dte_config.uart_config.rx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE;
|
||||
dte_config.uart_config.tx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_TX_BUFFER_SIZE;
|
||||
dte_config.uart_config.event_queue_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_QUEUE_SIZE;
|
||||
dte_config.task_stack_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_STACK_SIZE;
|
||||
dte_config.task_priority = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_PRIORITY;
|
||||
dte_config.dte_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE / 2;
|
||||
auto uart_dte = create_uart_dte(&dte_config);
|
||||
|
||||
#if CONFIG_EXAMPLE_MODEM_DEVICE_SHINY == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the SHINY module...");
|
||||
auto dce = create_shiny_dce(&dce_config, uart_dte, esp_netif);
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_BG96 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the BG96 module...");
|
||||
auto dce = create_BG96_dce(&dce_config, uart_dte, esp_netif);
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM800 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the SIM800 module...");
|
||||
auto dce = create_SIM800_dce(&dce_config, uart_dte, esp_netif);
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7000 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the SIM7000 module...");
|
||||
auto dce = create_SIM7000_dce(&dce_config, uart_dte, esp_netif);
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7070 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the SIM7070 module...");
|
||||
auto dce = create_SIM7070_dce(&dce_config, uart_dte, esp_netif);
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the SIM7600 module...");
|
||||
auto dce = create_SIM7600_dce(&dce_config, uart_dte, esp_netif);
|
||||
#else
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for a generic module...");
|
||||
auto dce = create_generic_dce(&dce_config, uart_dte, esp_netif);
|
||||
#endif
|
||||
|
||||
|
||||
#elif defined(CONFIG_EXAMPLE_SERIAL_CONFIG_USB)
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_DEFAULT_USB_CONFIG(0x2C7C, 0x0296); // VID and PID of BG96 modem
|
||||
// BG96 modem implements Vendor Specific class, that is CDC-ACM like. Interface for AT commands has index no. 2.
|
||||
usb_config.interface_idx = 2;
|
||||
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_USB_CONFIG(usb_config);
|
||||
ESP_LOGI(TAG, "Waiting for USB device connection...");
|
||||
auto dte = create_usb_dte(&dte_config);
|
||||
std::unique_ptr<DCE> dce = create_BG96_dce(&dce_config, dte, esp_netif);
|
||||
while (1) {
|
||||
exit_signal.clear(1);
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_DEFAULT_USB_CONFIG(0x2C7C, 0x0296, 2); // VID, PID and interface num of BG96 modem
|
||||
const esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_USB_CONFIG(usb_config);
|
||||
ESP_LOGI(TAG, "Waiting for USB device connection...");
|
||||
auto dte = create_usb_dte(&dte_config);
|
||||
dte->set_error_cb([&](terminal_error err) {
|
||||
ESP_LOGI(TAG, "error handler %d", err);
|
||||
if (err == terminal_error::DEVICE_GONE) {
|
||||
exit_signal.set(1);
|
||||
}
|
||||
});
|
||||
std::unique_ptr<DCE> dce = create_BG96_dce(&dce_config, dte, esp_netif);
|
||||
|
||||
#else
|
||||
#error Invalid serial connection to modem.
|
||||
@ -82,11 +167,39 @@ extern "C" void app_main(void)
|
||||
|
||||
assert(dce != nullptr);
|
||||
|
||||
if (dte_config.uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
|
||||
if (command_result::OK != dce->set_flow_control(2, 2)) {
|
||||
ESP_LOGE(TAG, "Failed to set the set_flow_control mode");
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(TAG, "set_flow_control OK");
|
||||
}
|
||||
|
||||
// init console REPL environment
|
||||
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
|
||||
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &s_repl));
|
||||
|
||||
switch (esp_sleep_get_wakeup_cause()) {
|
||||
case ESP_SLEEP_WAKEUP_TIMER:
|
||||
if (esp_modem::modem_mode::CMUX_MODE == mode_rtc) {
|
||||
ESP_LOGI(TAG, "Deep sleep reset\n");
|
||||
|
||||
/* Set APN */
|
||||
auto new_pdp = std::unique_ptr<PdpContext>(new PdpContext(apn_rtc));
|
||||
dce->get_module()->configure_pdp_context(std::move(new_pdp));
|
||||
|
||||
/* Set CMUX mode */
|
||||
if (!dce->set_mode(mode_rtc)) {
|
||||
ESP_LOGE(TAG, "Failed to set the desired mode");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ESP_SLEEP_WAKEUP_UNDEFINED:
|
||||
default:
|
||||
ESP_LOGD(TAG, "Not a deep sleep reset\n");
|
||||
}
|
||||
|
||||
modem_console_register_http();
|
||||
modem_console_register_ping();
|
||||
const struct SetModeArgs {
|
||||
@ -97,12 +210,25 @@ 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 == "CMD") {
|
||||
if (mode == "CMUX1") {
|
||||
dev_mode = esp_modem::modem_mode::CMUX_MANUAL_MODE;
|
||||
} else if (mode == "CMUX2") {
|
||||
dev_mode = esp_modem::modem_mode::CMUX_MANUAL_EXIT;
|
||||
} else if (mode == "CMUX3") {
|
||||
dev_mode = esp_modem::modem_mode::CMUX_MANUAL_SWAP;
|
||||
} else if (mode == "CMUX4") {
|
||||
dev_mode = esp_modem::modem_mode::CMUX_MANUAL_DATA;
|
||||
} else if (mode == "CMUX5") {
|
||||
dev_mode = esp_modem::modem_mode::CMUX_MANUAL_COMMAND;
|
||||
} else if (mode == "CMD") {
|
||||
dev_mode = esp_modem::modem_mode::COMMAND_MODE;
|
||||
} else if (mode == "PPP") {
|
||||
dev_mode = esp_modem::modem_mode::DATA_MODE;
|
||||
} else if (mode == "CMUX") {
|
||||
/* Even if switching to CMUX fails, we make the DTE multiplex terminal.
|
||||
(This is potentially a bug and might be fixed eventually) */
|
||||
dev_mode = esp_modem::modem_mode::CMUX_MODE;
|
||||
mode_rtc = dev_mode;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Unsupported mode: %s", mode.c_str());
|
||||
return 1;
|
||||
@ -112,6 +238,8 @@ extern "C" void app_main(void)
|
||||
ESP_LOGE(TAG, "Failed to set the desired mode");
|
||||
return 1;
|
||||
}
|
||||
mode_rtc = dev_mode;
|
||||
|
||||
ESP_LOGI(TAG, "OK");
|
||||
}
|
||||
return 0;
|
||||
@ -219,6 +347,7 @@ extern "C" void app_main(void)
|
||||
if (c->get_count_of(&SetApn::apn)) {
|
||||
auto apn = c->get_string_of(&SetApn::apn);
|
||||
ESP_LOGI(TAG, "Setting the APN=%s...", apn.c_str());
|
||||
strcpy(apn_rtc, apn.c_str());
|
||||
auto new_pdp = std::unique_ptr<PdpContext>(new PdpContext(apn));
|
||||
dce->get_module()->configure_pdp_context(std::move(new_pdp));
|
||||
ESP_LOGI(TAG, "OK");
|
||||
@ -226,16 +355,96 @@ extern "C" void app_main(void)
|
||||
return 0;
|
||||
});
|
||||
|
||||
SignalGroup exit_signal;
|
||||
const ConsoleCommand ExitConsole("exit", "exit the console application", no_args, [&](ConsoleCommand * c) {
|
||||
ESP_LOGI(TAG, "Exiting...");
|
||||
exit_signal.set(1);
|
||||
s_repl->del(s_repl);
|
||||
return 0;
|
||||
});
|
||||
|
||||
/* Put the esp32 into deep sleep */
|
||||
const struct DeepSleepArgs {
|
||||
DeepSleepArgs(): timeout(INT1, nullptr, nullptr, "<tout>", "TIMEOUT") {}
|
||||
CommandArgs timeout;
|
||||
} deep_sleep_args;
|
||||
const ConsoleCommand SetDeepSleep("set_deep_sleep", "Put esp32 to deep sleep", &deep_sleep_args, sizeof(deep_sleep_args), [&](ConsoleCommand * c) {
|
||||
int tout = c->get_int_of(&DeepSleepArgs::timeout);
|
||||
ESP_LOGI(TAG, "Entering deep sleep for %d sec", tout);
|
||||
ESP_LOGI(TAG, "Wakeup Cause: %d ", esp_sleep_get_wakeup_cause());
|
||||
esp_deep_sleep(tout * 1000000);
|
||||
return 0;
|
||||
});
|
||||
|
||||
/* Wake up modem */
|
||||
const ConsoleCommand WakeupModem("wakeup_modem", "Wakes up the modem from PSM", no_args, [&](ConsoleCommand * c) {
|
||||
wakeup_modem();
|
||||
ESP_LOGI(TAG, "OK");
|
||||
return 0;
|
||||
});
|
||||
|
||||
/* Enable PSM modem */
|
||||
const ConsoleCommand EnablePSM("enable_psm", "Enables PSM on the modem", no_args, [&](ConsoleCommand * c) {
|
||||
std::string out;
|
||||
CHECK_ERR(dce->at("AT+CPSMS=1", out, 500), ESP_LOGI(TAG, "OK. %s", out.c_str()));
|
||||
return 0;
|
||||
});
|
||||
|
||||
/* Disable PSM modem */
|
||||
const ConsoleCommand DisablePSM("disable_psm", "Disables PSM on the modem", no_args, [&](ConsoleCommand * c) {
|
||||
std::string out;
|
||||
CHECK_ERR(dce->at("AT+CPSMS=0", out, 500), ESP_LOGI(TAG, "OK. %s", out.c_str()));
|
||||
return 0;
|
||||
});
|
||||
|
||||
/* Get modem PSM cfg */
|
||||
const ConsoleCommand GetModemCfg("get_psm_cfg", "Get PSM config", no_args, [&](ConsoleCommand * c) {
|
||||
std::string out;
|
||||
CHECK_ERR(dce->at("AT+CPSMS?", out, 500), ESP_LOGI(TAG, "OK. %s", out.c_str()));
|
||||
return 0;
|
||||
});
|
||||
|
||||
/* Set modem PSM config */
|
||||
const struct SetPsmCfgArgs {
|
||||
SetPsmCfgArgs():
|
||||
periodic_tau(STR1, nullptr, nullptr, "<Requested_Periodic-TAU>", "T3412 Timer in 8-bit format"),
|
||||
active_time(STR0, nullptr, nullptr, "<Requested_Active-Time>", "T3324 Timer in 8-bit format") {}
|
||||
CommandArgs periodic_tau;
|
||||
CommandArgs active_time;
|
||||
} set_psm_cfg_args;
|
||||
const ConsoleCommand SetPsmCfg("set_psm_cfg", "Set PSM config", &set_psm_cfg_args, sizeof(set_psm_cfg_args), [&](ConsoleCommand * c) {
|
||||
std::string out;
|
||||
auto periodic_tau = c->get_string_of(&SetPsmCfgArgs::periodic_tau);
|
||||
auto active_time = c->get_string_of(&SetPsmCfgArgs::active_time);
|
||||
|
||||
/* Validate input */
|
||||
if ((strlen(periodic_tau.c_str()) != strlen("00000000")) ||
|
||||
(strlen(active_time.c_str()) != strlen("00000000"))) {
|
||||
ESP_LOGE(TAG, "Failed with ERROR: Invalid argument length");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get PSM config */
|
||||
dce->at("AT+CPSMS?", out, 500);
|
||||
|
||||
/* Update PSM config */
|
||||
if (out.size() > 8) {
|
||||
std::string set_cmd = "AT+CPSMS=" + std::to_string(out.c_str()[8] - '0') + ",,,\"" + periodic_tau.c_str() + "\",\"" + active_time.c_str() + "\"";
|
||||
CHECK_ERR(dce->at(set_cmd, out, 500), ESP_LOGI(TAG, "OK. %s", out.c_str()));
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed with ERROR: Invalid AT+CPSMS? return length");
|
||||
}
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
|
||||
// start console REPL
|
||||
ESP_ERROR_CHECK(esp_console_start_repl(s_repl));
|
||||
// wait for exit
|
||||
exit_signal.wait_any(1, UINT32_MAX);
|
||||
s_repl->del(s_repl);
|
||||
ESP_LOGI(TAG, "Exiting...%d", esp_get_free_heap_size());
|
||||
#if defined(CONFIG_EXAMPLE_SERIAL_CONFIG_USB)
|
||||
// USB example runs in a loop to demonstrate hot-plugging and sudden disconnection features.
|
||||
} // while (1)
|
||||
#endif
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
/* Modem console example: Custom DCE
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
/*
|
||||
* Modem console example: Custom DCE
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
@ -1,10 +1,10 @@
|
||||
/* Ping handle example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
/*
|
||||
* Ping handle example
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@ -29,7 +29,7 @@ static void cmd_ping_on_ping_success(esp_ping_handle_t hdl, void *args)
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_SIZE, &recv_len, sizeof(recv_len));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time));
|
||||
ESP_LOGI(TAG, "%d bytes from %s icmp_seq=%d ttl=%d time=%d ms\n",
|
||||
recv_len, inet_ntoa(target_addr.u_addr.ip4), seqno, ttl, elapsed_time);
|
||||
recv_len, inet_ntoa(target_addr.u_addr.ip4), seqno, ttl, elapsed_time);
|
||||
}
|
||||
|
||||
static void cmd_ping_on_ping_timeout(esp_ping_handle_t hdl, void *args)
|
||||
@ -58,7 +58,7 @@ static void cmd_ping_on_ping_end(esp_ping_handle_t hdl, void *args)
|
||||
ESP_LOGI(TAG, "\n--- %s ping statistics ---\n", inet6_ntoa(*ip_2_ip6(&target_addr)));
|
||||
}
|
||||
ESP_LOGI(TAG, "%d packets transmitted, %d received, %d%% packet loss, time %dms\n",
|
||||
transmitted, received, loss, total_time_ms);
|
||||
transmitted, received, loss, total_time_ms);
|
||||
// delete the ping sessions, so that we clean up all resources and can create a new ping session
|
||||
// we don't have to call delete function in the callback, instead we can call delete function from other tasks
|
||||
esp_ping_delete_session(hdl);
|
||||
@ -112,10 +112,10 @@ static int do_ping_cmd(int argc, char **argv)
|
||||
|
||||
/* set callback functions */
|
||||
esp_ping_callbacks_t cbs = {
|
||||
.on_ping_success = cmd_ping_on_ping_success,
|
||||
.on_ping_timeout = cmd_ping_on_ping_timeout,
|
||||
.on_ping_end = cmd_ping_on_ping_end,
|
||||
.cb_args = NULL
|
||||
.on_ping_success = cmd_ping_on_ping_success,
|
||||
.on_ping_timeout = cmd_ping_on_ping_timeout,
|
||||
.on_ping_end = cmd_ping_on_ping_end,
|
||||
.cb_args = NULL
|
||||
};
|
||||
esp_ping_handle_t ping;
|
||||
esp_ping_new_session(&config, &cbs, &ping);
|
||||
@ -131,11 +131,11 @@ void modem_console_register_ping(void)
|
||||
ping_args.host = arg_str1(NULL, NULL, "<host>", "Host address");
|
||||
ping_args.end = arg_end(1);
|
||||
const esp_console_cmd_t ping_cmd = {
|
||||
.command = "ping",
|
||||
.help = "send ICMP ECHO_REQUEST to network hosts",
|
||||
.hint = NULL,
|
||||
.func = &do_ping_cmd,
|
||||
.argtable = &ping_args
|
||||
.command = "ping",
|
||||
.help = "send ICMP ECHO_REQUEST to network hosts",
|
||||
.hint = NULL,
|
||||
.func = &do_ping_cmd,
|
||||
.argtable = &ping_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&ping_cmd));
|
||||
}
|
@ -0,0 +1 @@
|
||||
CONFIG_EXAMPLE_SERIAL_CONFIG_USB=y
|
@ -1,8 +1,7 @@
|
||||
# Override some defaults to enable PPP
|
||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
|
||||
#
|
||||
CONFIG_ESP_MAIN_TASK_STACK_SIZE=7168
|
||||
CONFIG_LWIP_PPP_SUPPORT=y
|
||||
# CONFIG_LWIP_PPP_ENABLE_IPV6 is not set
|
||||
CONFIG_LWIP_PPP_PAP_SUPPORT=y
|
||||
CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096
|
||||
# Do not enable IPV6 in dte<->dce link local
|
||||
CONFIG_LWIP_PPP_ENABLE_IPV6=n
|
||||
# Disable legacy API
|
||||
CONFIG_MODEM_LEGACY_API=n
|
||||
|
10
components/esp_modem/examples/modem_psm/CMakeLists.txt
Normal file
10
components/esp_modem/examples/modem_psm/CMakeLists.txt
Normal file
@ -0,0 +1,10 @@
|
||||
# For more information about build system see
|
||||
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
|
||||
# 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)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS "../..")
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(modem_psm)
|
32
components/esp_modem/examples/modem_psm/README.md
Normal file
32
components/esp_modem/examples/modem_psm/README.md
Normal file
@ -0,0 +1,32 @@
|
||||
# Modem Power Saving Mode, sleep modes example
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
This example demonstrates Power Saving Mode(PSM) in Sim70XX modems along with Deep sleep and Light Sleep modes in esp32.
|
||||
This example enables Power saving mode in Sim70XX modem and tries to synchronise the sleep cycle of the modem with esp32.
|
||||
When the modem wakes up from PSM sleep it wakes up the esp32. While the modem is awake esp32 goes to light sleep.
|
||||
|
||||
This example is tested on a SIM7080 modem.
|
||||
|
||||
## Supported devices
|
||||
|
||||
This example is supported only on ESP32, ESP32-S2 and ESP32-S3.
|
||||
|
||||
## Configuration
|
||||
|
||||
* EXAMPLE_MODEM_UART_TX_PIN: Connect this pin to the UART Tx pin of the modem.
|
||||
* EXAMPLE_MODEM_UART_RX_PIN: Connect this pin to the UART Rx pin of the modem.
|
||||
* EXAMPLE_MODEM_PWRKEY_PIN: Connect this pin to the PWRKEY pin of the modem.
|
||||
* EXAMPLE_MODEM_STATUS_PIN: Connect this pin to the Status pin of the modem.
|
||||
|
||||
The status pin might not be exposed on a modem. It needs to tapped out from the LED indicator marked as STS.
|
||||
|
||||
* EXAMPLE_MODEM_LIGHT_SLEEP_DURATION: Duration for which the esp32 will go into light sleep, while the modem is awake.
|
||||
|
||||
If the esp32 goes into deep sleep while the modem is awake, esp32 will be awaken by the STATUS pin. So it's recommended to go to light sleep while the modem is awake.
|
||||
|
||||
* EXAMPLE_MODEM_T3412_PERIODIC_TAU: T3412 timer is the duration of one awake and sleep cycle of the modem in PSM.
|
||||
* EXAMPLE_MODEM_T3324_ACTIVE_TIME: T3324 timer is the duration for which the modem stays PSM.
|
||||
|
||||
The timeout information is coded in bit format for T3412 and T3324 timer.
|
@ -0,0 +1,3 @@
|
||||
|
||||
idf_component_register(SRCS "modem_psm.c"
|
||||
INCLUDE_DIRS ".")
|
109
components/esp_modem/examples/modem_psm/main/Kconfig.projbuild
Normal file
109
components/esp_modem/examples/modem_psm/main/Kconfig.projbuild
Normal file
@ -0,0 +1,109 @@
|
||||
|
||||
menu "Example Configuration"
|
||||
|
||||
choice EXAMPLE_MODEM_DEVICE
|
||||
prompt "Choose supported modem device (DCE)"
|
||||
default EXAMPLE_MODEM_DEVICE_SIM7080
|
||||
help
|
||||
Select modem device connected to the ESP DTE.
|
||||
config EXAMPLE_MODEM_DEVICE_SIM7070
|
||||
bool "SIM7070"
|
||||
help
|
||||
SIM7070 is Multi-Band CAT M and NB IoT module.
|
||||
config EXAMPLE_MODEM_DEVICE_SIM7080
|
||||
bool "SIM7080"
|
||||
help
|
||||
SIM7080 is Multi-Band CAT M and NB IoT module.
|
||||
endchoice
|
||||
|
||||
menu "UART Configuration"
|
||||
config EXAMPLE_MODEM_UART_TX_PIN
|
||||
int "TXD Pin Number"
|
||||
default 4
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART TX.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RX_PIN
|
||||
int "RXD Pin Number"
|
||||
default 5
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART RX.
|
||||
|
||||
config EXAMPLE_MODEM_UART_EVENT_TASK_STACK_SIZE
|
||||
int "UART Event Task Stack Size"
|
||||
range 2000 6000
|
||||
default 4096
|
||||
help
|
||||
Stack size of UART event task.
|
||||
|
||||
config EXAMPLE_MODEM_UART_EVENT_TASK_PRIORITY
|
||||
int "UART Event Task Priority"
|
||||
range 3 22
|
||||
default 5
|
||||
help
|
||||
Priority of UART event task.
|
||||
|
||||
config EXAMPLE_MODEM_UART_EVENT_QUEUE_SIZE
|
||||
int "UART Event Queue Size"
|
||||
range 10 40
|
||||
default 30
|
||||
help
|
||||
Length of UART event queue.
|
||||
|
||||
config EXAMPLE_MODEM_UART_TX_BUFFER_SIZE
|
||||
int "UART TX Buffer Size"
|
||||
range 256 2048
|
||||
default 512
|
||||
help
|
||||
Buffer size of UART TX buffer.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RX_BUFFER_SIZE
|
||||
int "UART RX Buffer Size"
|
||||
range 256 2048
|
||||
default 1024
|
||||
help
|
||||
Buffer size of UART RX buffer.
|
||||
endmenu
|
||||
|
||||
config EXAMPLE_MODEM_PWRKEY_PIN
|
||||
int "PWRKEY Pin Number"
|
||||
default 18
|
||||
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 31
|
||||
help
|
||||
Pin number connected to modem's status pin.
|
||||
|
||||
config EXAMPLE_MODEM_LIGHT_SLEEP_DURATION
|
||||
int "Light Sleep Duration"
|
||||
default 10
|
||||
range 0 15000
|
||||
help
|
||||
Duration in seconds, of which the esp32 goes into light sleep while the modem is awake.
|
||||
|
||||
config EXAMPLE_MODEM_PPP_APN
|
||||
string "Set MODEM APN"
|
||||
default "internet"
|
||||
help
|
||||
Set APN (Access Point Name), a logical name to choose data network
|
||||
|
||||
config EXAMPLE_MODEM_T3412_PERIODIC_TAU
|
||||
string "T3412 Requester Periodic TAU"
|
||||
default "00000100"
|
||||
help
|
||||
T3412 timer, i.e the duration of one awake and sleep cycle of the modem in PSM.
|
||||
|
||||
config EXAMPLE_MODEM_T3324_ACTIVE_TIME
|
||||
string "T3324 Requester Active Time"
|
||||
default "00000001"
|
||||
help
|
||||
T3324 timer, i.e the duration for which the modem stays PSM.
|
||||
|
||||
endmenu
|
202
components/esp_modem/examples/modem_psm/main/modem_psm.c
Normal file
202
components/esp_modem/examples/modem_psm/main/modem_psm.c
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Power Saving Mode(PSM) in Sim70XX modems along with
|
||||
* Deep sleep and Light Sleep modes in esp32.
|
||||
*/
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/uart.h"
|
||||
#include "string.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "esp_modem_api.h"
|
||||
#include "esp_event.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
|
||||
#define BUF_SIZE 1024
|
||||
|
||||
#define TXD_PIN ((gpio_num_t)CONFIG_EXAMPLE_MODEM_UART_TX_PIN)
|
||||
#define RXD_PIN ((gpio_num_t)CONFIG_EXAMPLE_MODEM_UART_RX_PIN)
|
||||
#define GPIO_INPUT_STATUS ((gpio_num_t)CONFIG_EXAMPLE_MODEM_STATUS_PIN)
|
||||
#define GPIO_OUTPUT_PWRKEY ((gpio_num_t)CONFIG_EXAMPLE_MODEM_PWRKEY_PIN)
|
||||
#define GPIO_OUTPUT_PIN_SEL (1ULL<<GPIO_OUTPUT_PWRKEY)
|
||||
|
||||
#define CHECK_ERR(cmd, success_action) do { \
|
||||
esp_err_t ret = cmd; \
|
||||
if (ret == ESP_OK) { \
|
||||
success_action; \
|
||||
} else { \
|
||||
ESP_LOGE(TAG, "Failed with %s", ret == ESP_ERR_TIMEOUT ? "TIMEOUT":"ERROR"); \
|
||||
} } while (0)
|
||||
|
||||
|
||||
const char *TAG = "modem_psm";
|
||||
RTC_DATA_ATTR static int boot_count = 0;
|
||||
|
||||
|
||||
void dce_init(esp_modem_dce_t **dce, esp_netif_t **esp_netif)
|
||||
{
|
||||
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(CONFIG_EXAMPLE_MODEM_PPP_APN);
|
||||
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
||||
esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP();
|
||||
*esp_netif = esp_netif_new(&netif_ppp_config);
|
||||
assert(*esp_netif);
|
||||
|
||||
/* setup UART specific configuration based on kconfig options */
|
||||
dte_config.uart_config.tx_io_num = CONFIG_EXAMPLE_MODEM_UART_TX_PIN;
|
||||
dte_config.uart_config.rx_io_num = CONFIG_EXAMPLE_MODEM_UART_RX_PIN;
|
||||
dte_config.uart_config.rx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE;
|
||||
dte_config.uart_config.tx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_TX_BUFFER_SIZE;
|
||||
dte_config.uart_config.event_queue_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_QUEUE_SIZE;
|
||||
dte_config.task_stack_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_STACK_SIZE;
|
||||
dte_config.task_priority = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_PRIORITY;
|
||||
dte_config.dte_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE / 2;
|
||||
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for a generic module...");
|
||||
*dce = esp_modem_new(&dte_config, &dce_config, *esp_netif);
|
||||
assert(*dce);
|
||||
}
|
||||
|
||||
void config_pwrkey_gpio(void)
|
||||
{
|
||||
gpio_config_t io_conf = {}; //zero-initialize the config structure.
|
||||
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE; //disable interrupt
|
||||
io_conf.mode = GPIO_MODE_OUTPUT; //set as output mode
|
||||
io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL; //bit mask of the pins that you want to set,e.g.GPIO18/19
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; //disable pull-down mode
|
||||
io_conf.pull_up_en = GPIO_PULLUP_DISABLE; //disable pull-up mode
|
||||
|
||||
gpio_config(&io_conf); //configure GPIO with the given settings
|
||||
}
|
||||
|
||||
void power_on_modem(esp_modem_dce_t *dce)
|
||||
{
|
||||
rtc_gpio_hold_dis(GPIO_OUTPUT_PWRKEY);
|
||||
|
||||
/* Power on the modem */
|
||||
ESP_LOGI(TAG, "Power on the modem");
|
||||
gpio_set_level(GPIO_OUTPUT_PWRKEY, 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
gpio_set_level(GPIO_OUTPUT_PWRKEY, 0);
|
||||
|
||||
rtc_gpio_hold_en(GPIO_OUTPUT_PWRKEY);
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
|
||||
CHECK_ERR(esp_modem_sync(dce), ESP_LOGI(TAG, "OK"));
|
||||
}
|
||||
|
||||
void power_down_modem(esp_modem_dce_t *dce)
|
||||
{
|
||||
char data[BUF_SIZE];
|
||||
|
||||
ESP_LOGI(TAG, "Power down the modem");
|
||||
|
||||
/* Power down the modem by AT command */
|
||||
CHECK_ERR(esp_modem_at(dce, "AT+CPOWD=1", data, 500), ESP_LOGI(TAG, "OK. %s", data));
|
||||
}
|
||||
|
||||
void run_at(esp_modem_dce_t *dce, uint8_t count)
|
||||
{
|
||||
for (int i = 0; i < count; i++) {
|
||||
CHECK_ERR(esp_modem_sync(dce), ESP_LOGI(TAG, "OK"));
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
}
|
||||
|
||||
void run_at_ping(esp_modem_dce_t *dce)
|
||||
{
|
||||
char data[BUF_SIZE];
|
||||
int rssi, ber;
|
||||
CHECK_ERR(esp_modem_get_signal_quality(dce, &rssi, &ber), ESP_LOGI(TAG, "OK. rssi=%d, ber=%d", rssi, ber));
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
|
||||
CHECK_ERR(esp_modem_at(dce, "AT+CPSMS?", data, 500), ESP_LOGI(TAG, "OK. %s", data));
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
|
||||
CHECK_ERR(esp_modem_at(dce, "AT+CPSI?", data, 500), ESP_LOGI(TAG, "OK. %s", data)); // Inquiring UE system information
|
||||
CHECK_ERR(esp_modem_at(dce, "AT+CNACT=0,1", data, 500), ESP_LOGI(TAG, "OK. %s", data)); // Activate the APP network
|
||||
CHECK_ERR(esp_modem_at(dce, "AT+SNPDPID=0", data, 500), ESP_LOGI(TAG, "OK. %s", data)); // Select PDP index for PING
|
||||
CHECK_ERR(esp_modem_at(dce, "AT+SNPING4=\"8.8.8.8\",3,16,1000", data, 500), ESP_LOGI(TAG, "OK. %s", data)); // Send IPv4 PING
|
||||
CHECK_ERR(esp_modem_at(dce, "AT+CNACT=0,0", data, 500), ESP_LOGI(TAG, "OK. %s", data)); // Deactivate the APP network
|
||||
}
|
||||
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
char *cmd;
|
||||
char data[BUF_SIZE];
|
||||
esp_modem_dce_t *dce = NULL;
|
||||
esp_netif_t *esp_netif = NULL;
|
||||
esp_sleep_wakeup_cause_t wakeup_cause = esp_sleep_get_wakeup_cause();
|
||||
ESP_LOGI(TAG, "Deep sleep Wake Up Cause: %d\n", wakeup_cause);
|
||||
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
dce_init(&dce, &esp_netif);
|
||||
|
||||
switch (wakeup_cause) {
|
||||
case ESP_SLEEP_WAKEUP_UNDEFINED:
|
||||
/* Power on the modem */
|
||||
config_pwrkey_gpio();
|
||||
power_on_modem(dce);
|
||||
|
||||
run_at(dce, 3);
|
||||
|
||||
/* Configure Power Saving Mode in the modem */
|
||||
asprintf(&cmd, "AT+CPSMS=1,,,\"%s\",\"%s\"\r\n", CONFIG_EXAMPLE_MODEM_T3412_PERIODIC_TAU,
|
||||
CONFIG_EXAMPLE_MODEM_T3324_ACTIVE_TIME);
|
||||
CHECK_ERR(esp_modem_at(dce, cmd, data, 500), ESP_LOGI(TAG, "OK. %s", data));
|
||||
free(cmd);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
|
||||
/* Perform Communication tasks */
|
||||
run_at_ping(dce);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
break;
|
||||
|
||||
case ESP_SLEEP_WAKEUP_EXT0:
|
||||
run_at(dce, 3);
|
||||
|
||||
/* Perform Communication tasks */
|
||||
run_at_ping(dce);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGI(TAG, "Not a deep sleep reset: %d\n", wakeup_cause);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Light sleep before going to Deep sleep\n\n");
|
||||
|
||||
/* Enter light sleep mode as long as the modem is awake */
|
||||
esp_sleep_enable_timer_wakeup(CONFIG_EXAMPLE_MODEM_LIGHT_SLEEP_DURATION * 1000000);
|
||||
esp_light_sleep_start();
|
||||
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER); // Disabling timer before going to deep sleep.
|
||||
wakeup_cause = esp_sleep_get_wakeup_cause();
|
||||
ESP_LOGI(TAG, "Light sleep wakeup cause: %d\n", wakeup_cause);
|
||||
|
||||
/* DCE and netif clean-up */
|
||||
/* In Deep-sleep mode, the CPUs, most of the RAM, and all digital peripherals are powered off.
|
||||
* So dce and netif would be lost anyway if they are not explicitly destroyed.
|
||||
* But since dce is also linked with UART communication with the modem it's better to exit gracefully before going to deep sleep.
|
||||
*/
|
||||
esp_modem_destroy(dce);
|
||||
esp_netif_destroy(esp_netif);
|
||||
|
||||
/* Enable wakeup if status pin is high */
|
||||
esp_sleep_enable_ext0_wakeup(GPIO_INPUT_STATUS, 1);
|
||||
|
||||
ESP_LOGI(TAG, "Entering deep sleep: %d\n", boot_count++);
|
||||
esp_deep_sleep_start();
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user