mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-25 08:17:28 +02:00
Compare commits
453 Commits
modem-v0.1
...
mdns-v1.0.
Author | SHA1 | Date | |
---|---|---|---|
8fe2a3a661 | |||
417591b99f | |||
b6b20ad399 | |||
8863ed944d | |||
78001ec871 | |||
4a52cf23f5 | |||
00e7675913 | |||
87c269911d | |||
eb536a74a0 | |||
b720d02fca | |||
3e93ea9b76 | |||
2c764b1b7a | |||
f836ae7f65 | |||
e9a1c26e0c | |||
4b5f24f5b8 | |||
05675c7d63 | |||
30f37c0565 | |||
ddc58e8220 | |||
fa951bf320 | |||
605d1fab73 | |||
58bf2186f7 | |||
d39a4c744e | |||
ec491ec536 | |||
defdfd59b6 | |||
7f42c31252 | |||
94ae672041 | |||
e5a3a3df1d | |||
7710ea9a11 | |||
034c55e18a | |||
ec03fec3d3 | |||
5909e9e54c | |||
82e2a5dcc1 | |||
48e4d4035c | |||
ba3fa24a96 | |||
869f5b75af | |||
ac6dcb6830 | |||
085dbd8c4e | |||
f78e8cfce8 | |||
6cdf5ee074 | |||
fcb5515f1e | |||
9fdbe5f130 | |||
20e6e9e7fe | |||
3c5b13ea0d | |||
c588263b45 | |||
6258edf23b | |||
c8b0d5ea9d | |||
5252b1d801 | |||
4e11cc86fe | |||
7af91ec490 | |||
01256d3e34 | |||
5a2d4eab6d | |||
9de3f534e2 | |||
bcabc8ea16 | |||
dfb27b39cc | |||
076c095aec | |||
7dd0bc1fff | |||
7e82a7cef7 | |||
ae381b779f | |||
d0f4e68c7a | |||
941dc5c42f | |||
525c64915e | |||
f0839d909b | |||
69902ea8e1 | |||
d5001e894f | |||
145a8d2291 | |||
d0bbe880b6 | |||
4a9d55edf7 | |||
be2a924674 | |||
76fcd4128a | |||
fd8499c874 | |||
38b4fe2353 | |||
eb7eeb58d3 | |||
b26606252f | |||
5e087d82d6 | |||
91a3d95f96 | |||
6d6dd2b75e | |||
0611b0cb67 | |||
cf6ed1cc53 | |||
52306e914f | |||
d37ab6dd25 | |||
05dcd8f0ee | |||
5c55ea6e02 | |||
0c71c7bfe1 | |||
4c368c0090 | |||
c2abeff476 | |||
6a92d3253f | |||
af2275341e | |||
b0957e70fd | |||
47c7266103 | |||
40da0d29be | |||
5f6b6f9273 | |||
8a120829e2 | |||
46f28a8011 | |||
5a81eaea3f | |||
2ddaee2b6e | |||
73b1763029 | |||
27fc285000 | |||
93e6efedc7 | |||
bc4cda8ea7 | |||
8a8d58d4dc | |||
402baebfee | |||
9fa25ef3b6 | |||
121b525108 | |||
418fb60dd9 | |||
4049b3b5ed | |||
c8821199a2 | |||
1eb5df9780 | |||
b62b4b3e25 | |||
4d8aec1ad3 | |||
6d649102ab | |||
3ad559bf3f | |||
ab3fa69b8f | |||
c3a5826d60 | |||
cbcbe4ffd7 | |||
adc34309dc | |||
7a8329cb5c | |||
c30617d872 | |||
1e5eeb16ec | |||
22c7c0a195 | |||
eda5d72acf | |||
1623c0e729 | |||
b114ed69de | |||
49a00c2455 | |||
dec1d7dcf8 | |||
2ffd22382d | |||
487287157d | |||
1fe901f70f | |||
2cf9fd8891 | |||
89439e0a9b | |||
becd5d0266 | |||
0d7a30944e | |||
e2653e7fb0 | |||
df6a208f45 | |||
1fdffbbbab | |||
d5566971fb | |||
988d120902 | |||
fd47df3e30 | |||
2cb3a6e35e | |||
ccd48bc9a9 | |||
825652f3e1 | |||
fc53888115 | |||
7635c0479b | |||
d5fe42bffb | |||
e0bc60a586 | |||
9772e49b26 | |||
110f1f652d | |||
ed77d65a82 | |||
6021a88657 | |||
78f71ecdf6 | |||
07f57523c8 | |||
ad67a23097 | |||
078abd8161 | |||
f1f6c5de05 | |||
12fb6d8e15 | |||
2258d5bcef | |||
54f5c6f29c | |||
3319844745 | |||
ac70c9aba8 | |||
123ae8db62 | |||
e24cc7d1ae | |||
9d9aac1569 | |||
ef9a758662 | |||
2a23f355c7 | |||
07399011f7 | |||
2b7d43e1f8 | |||
7bf23a7fe9 | |||
881ca095f0 | |||
d9fa457b4f | |||
4eb3e89841 | |||
74aee42f80 | |||
b5e5a64e7f | |||
6713ffedcc | |||
817c4fd2e8 | |||
8f0dc6d578 | |||
7a3aa26df8 | |||
c7ff8ba0c9 | |||
80ce63d73e | |||
d20666f3a0 | |||
cd3cc0be3b | |||
1734e59057 | |||
662a4ce050 | |||
fb1de80fd7 | |||
1f35e9a728 | |||
573855031d | |||
d1c62628b8 | |||
48b819bbc1 | |||
dfcefc38fd | |||
879a6cdfa3 | |||
53e2aa3241 | |||
3cc64469c1 | |||
248b11bb0a | |||
d52dddfea5 | |||
67d310b988 | |||
901124b7ee | |||
f6ff165be9 | |||
d8d6b35553 | |||
f44c569422 | |||
7dfe14c83d | |||
286c646725 | |||
0582187b9a | |||
28d5b74a00 | |||
c70d527d80 | |||
7cdf96cffa | |||
407875d9c5 | |||
3e753f5e2d | |||
aaba3fc47a | |||
144d4ad1d4 | |||
e431b6b7fe | |||
ed71a239a8 | |||
680bad646f | |||
271665e0cb | |||
7fb6686716 | |||
4912bef740 | |||
181a22ec2b | |||
4172219225 | |||
9a0803ad7e | |||
05ddd5f0e4 | |||
7e3b35efd9 | |||
98d2c1a073 | |||
84cbb1f3cf | |||
4c6818ee97 | |||
c440114d14 | |||
c0f65a6997 | |||
778eaa6ced | |||
25f8656fbc | |||
6ea0ea93fa | |||
d9aec9fc71 | |||
985e69117e | |||
75deebbf03 | |||
fdd27dc9fa | |||
2ec3b558ea | |||
450cbf03cf | |||
34f6d8dd33 | |||
b6efc688b5 | |||
11e4aebefd | |||
90e4babc61 | |||
c546ab8dea | |||
6582b41cd1 | |||
358d26c8a1 | |||
8d08e5ed95 | |||
2ac83d0f27 | |||
98e3171db6 | |||
2f85c075be | |||
b30a7fec27 | |||
7a4fdad16d | |||
b4e57424f9 | |||
2763bcdb8d | |||
dce0b26ef8 | |||
ade4aeffa5 | |||
8cd0e8a501 | |||
9b3b41c3f1 | |||
ea2300753e | |||
81c219d4ee | |||
0c17121ad7 | |||
67173f6770 | |||
fed787f54f | |||
b4ab30b5de | |||
dd714947d6 | |||
39de491597 | |||
19acac76eb | |||
0191d6fcd7 | |||
b26c8665f8 | |||
98069f9ca2 | |||
ad29d34bb6 | |||
9f1be3668e | |||
450c9de67b | |||
c7701d41f8 | |||
b9726db48e | |||
f1ccc4052e | |||
84bd1d7e88 | |||
259d3fc609 | |||
6d99957f2d | |||
7784d002fc | |||
9ebd9852ca | |||
26f00e8ddb | |||
bce7d5231c | |||
ef924f1aa5 | |||
ad8c92db52 | |||
3aa605fe24 | |||
00a72b8920 | |||
907e7ee29e | |||
b367484361 | |||
4a8582f500 | |||
75de31cea3 | |||
4acf639afc | |||
1a1cf71a84 | |||
5924dafd94 | |||
91bb5095f5 | |||
caa4884b3a | |||
441a53c604 | |||
7fbf8e5247 | |||
7346ed9765 | |||
76298ff70e | |||
0875008a46 | |||
a661e51f7e | |||
3ced2d9709 | |||
ba88d7fdbc | |||
4f3c4299d6 | |||
2a4e684848 | |||
541b391c3e | |||
279a3cb6e0 | |||
60bb0eea99 | |||
52de8f1b2a | |||
503218b3ba | |||
38149c8d9b | |||
1984da150d | |||
9e37f537bd | |||
e55f54b69e | |||
6e4d8a19ed | |||
e98cf16859 | |||
be3d2ece55 | |||
15ed885035 | |||
b72a9ae710 | |||
0733ea8ff4 | |||
15cbc9bd50 | |||
bb7f198bea | |||
d3f7ea67fb | |||
6e5bede4c7 | |||
d191a720d1 | |||
cc0d52793b | |||
804a8d5df6 | |||
74040cfd1a | |||
16ea3f7eb8 | |||
1f5eb396c5 | |||
827bebd2bc | |||
745201b188 | |||
ca266cabd0 | |||
e54b240870 | |||
4ccc32ffb5 | |||
91a177edd4 | |||
f303cdc70b | |||
ab8c2da395 | |||
80c3cf0f02 | |||
b3c777ad43 | |||
8ce791e969 | |||
fc7ed90d74 | |||
59e82695e7 | |||
755f16222f | |||
bece6e7045 | |||
46bd32d952 | |||
525c70c0b2 | |||
c4c323666e | |||
19c0455b4d | |||
665c520faf | |||
9118e0f044 | |||
fbdbd550c0 | |||
028be5a8d7 | |||
de7cd72f70 | |||
4a608ec1cd | |||
f0351ff378 | |||
9219ff710a | |||
86aa0b8d39 | |||
1933367f63 | |||
cf697a1a1b | |||
95cf983502 | |||
8a6c320a29 | |||
d1dd6ece38 | |||
36167db336 | |||
d376480766 | |||
e90272c812 | |||
fda070ba39 | |||
6d12d06605 | |||
1455bc0305 | |||
01b4f640d9 | |||
6ab0aea841 | |||
5f2a50f09f | |||
b71c49c277 | |||
f8e3ba7813 | |||
7a5b2d5a7d | |||
42920d7fb5 | |||
2b044f2434 | |||
2b6022c85d | |||
fae2343b19 | |||
17281a515e | |||
aec6a75d40 | |||
a6be8e2e3d | |||
09453e4694 | |||
3b0488cfdc | |||
f21a2f32e0 | |||
a48b0fafe8 | |||
1fcc001ae8 | |||
a41e3383b3 | |||
d0121b964d | |||
f55d8391c9 | |||
fe26b734b5 | |||
f5a26c4d32 | |||
23f6a1d46e | |||
2553d65e64 | |||
67949f94f4 | |||
bfc88ab76c | |||
343fbfdcc9 | |||
4d644954fe | |||
da74a4a489 | |||
f718676083 | |||
13a40d2344 | |||
35d6f9a2c6 | |||
f3a0586663 | |||
04a7643d67 | |||
8b3d420055 | |||
50b083a58c | |||
325a1933c4 | |||
face03e4e5 | |||
5d27b2681a | |||
2cb74cf8d0 | |||
d879e82a42 | |||
4f1d31f9b7 | |||
bece4efa09 | |||
8417e232aa | |||
5f0832a0ad | |||
464baeeb83 | |||
5d9ad9cffd | |||
9fbd6e658a | |||
8465b14653 | |||
e7ae0301ae | |||
96498760bf | |||
cf990d1a87 | |||
5299b425e8 | |||
bcb1ab99bd | |||
2c21aa1113 | |||
b9ff1e4e12 | |||
23dbdb584e | |||
1d0cc49c3f | |||
c1249aec17 | |||
2bbcb95e53 | |||
58887170d2 | |||
cc7aa03a37 | |||
15a858b735 | |||
01e2a9c109 | |||
c0021ceeb2 | |||
fec83e5915 | |||
c8c24ed2fc | |||
b380ded5fa | |||
38f6eb963a | |||
2a2d27086f | |||
9dd1bd5ed0 | |||
918db0d2f1 | |||
c1b1330680 | |||
fb7295e91a | |||
8236b3d490 | |||
fb6029b66c | |||
6e34954677 | |||
148a9300a4 | |||
1fb9150bcc | |||
a61e9e2d40 | |||
dc64f862c4 | |||
3332c27978 | |||
84b0dcfea4 | |||
e0e65856f0 | |||
28433de4ad | |||
8f17a90026 | |||
69ad3ea589 | |||
a67d74999e | |||
ab93c13823 |
36
.github/workflows/build.yml
vendored
Normal file
36
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
name: Build
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v4.1", "release-v4.2", "release-v4.3", "release-v4.4"]
|
||||
example: ["pppos_client", "modem_console", "ap_to_pppos", "simple_cmux_client"]
|
||||
idf_target: ["esp32"]
|
||||
exclude:
|
||||
- idf_ver: "release-v4.1"
|
||||
example: modem_console
|
||||
- idf_ver: "release-v4.1"
|
||||
example: ap_to_pppos
|
||||
- idf_ver: "release-v4.1"
|
||||
example: simple_cmux_client
|
||||
- idf_ver: "release-v4.2"
|
||||
example: simple_cmux_client
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
path: esp-protocols
|
||||
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
env:
|
||||
IDF_TARGET: ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
cd $GITHUB_WORKSPACE/esp-protocols/components/esp_modem/examples/${{ matrix.example }}
|
||||
idf.py build
|
76
.github/workflows/build_and_run_example_test.yml
vendored
Normal file
76
.github/workflows/build_and_run_example_test.yml
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
name: Build Websockets
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
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@v1
|
||||
- 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
|
||||
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/esp_websocket_client/examples/build/
|
||||
if-no-files-found: error
|
||||
|
||||
run-target:
|
||||
name: Run Example Test on target
|
||||
needs: build
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
idf_target: ["esp32"]
|
||||
runs-on:
|
||||
- self-hosted
|
||||
- ESP32-ETHERNET-KIT
|
||||
container:
|
||||
image: python:3.7-buster
|
||||
options: --privileged # Privileged mode has access to serial ports
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}
|
||||
path: components/esp_websocket_client/examples/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
|
||||
- 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
|
||||
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
|
||||
if: always()
|
||||
with:
|
||||
name: examples_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}
|
||||
path: examples/*.xml
|
35
.github/workflows/build_and_run_example_test_mdns.yml
vendored
Normal file
35
.github/workflows/build_and_run_example_test_mdns.yml
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
name: Build mDNS
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
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@master
|
||||
with:
|
||||
path: esp-protocols
|
||||
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
env:
|
||||
IDF_TARGET: ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/examples/
|
||||
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 build
|
44
.github/workflows/host-test.yml
vendored
Normal file
44
.github/workflows/host-test.yml
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
name: Host test
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
host_test:
|
||||
name: Build and test
|
||||
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
|
||||
|
||||
|
||||
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 gcc-8 g++-8
|
||||
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
|
||||
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
|
||||
idf.py build
|
||||
./build/host_modem_test.elf -r junit -o junit.xml
|
||||
|
||||
- name: Publish Results
|
||||
uses: EnricoMi/publish-unit-test-result-action@v1
|
||||
if: always()
|
||||
with:
|
||||
files: esp-protocols/components/esp_modem/test/host_test/junit.xml
|
61
.github/workflows/publish-docs-component.yml
vendored
Normal file
61
.github/workflows/publish-docs-component.yml
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
name: Docs and Publish
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
docs_build:
|
||||
name: Docs-Build-And-Upload
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Generate docs
|
||||
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_modem/docs
|
||||
./generate_docs
|
||||
mkdir -p $GITHUB_WORKSPACE/docs/esp_modem
|
||||
cp -r html/. $GITHUB_WORKSPACE/docs/esp_modem
|
||||
|
||||
cd $GITHUB_WORKSPACE/components/esp_websocket_client/docs
|
||||
./generate_docs
|
||||
mkdir -p $GITHUB_WORKSPACE/docs/esp_websocket_client
|
||||
cp -r html/. $GITHUB_WORKSPACE/docs/esp_websocket_client
|
||||
|
||||
cd $GITHUB_WORKSPACE/components/mdns/docs
|
||||
./generate_docs
|
||||
mkdir -p $GITHUB_WORKSPACE/docs/mdns/en
|
||||
mkdir -p $GITHUB_WORKSPACE/docs/mdns/zh_CN
|
||||
cp -r html_en/. $GITHUB_WORKSPACE/docs/mdns/en
|
||||
cp -r html_zh_CN/. $GITHUB_WORKSPACE/docs/mdns/zh_CN
|
||||
|
||||
cd $GITHUB_WORKSPACE/docs
|
||||
touch .nojekyll
|
||||
echo '<a href="esp_modem/index.html">esp-modem</a><br>' > index.html
|
||||
echo '<a href="esp_websocket_client/index.html">esp-websocket-client</a><br>' >> index.html
|
||||
echo '<a href="mdns/en/index.html">mDNS_en</a><br>' >> index.html
|
||||
echo '<a href="mdns/zh_CN/index.html">mDNS_zh_CN</a><br>' >> index.html
|
||||
|
||||
|
||||
- name: Upload components to component service
|
||||
uses: espressif/github-actions/upload_components@master
|
||||
with:
|
||||
directories: "components/esp_modem;components/esp_websocket_client;components/mdns"
|
||||
namespace: "espressif"
|
||||
api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }}
|
||||
|
||||
- name: Deploy generated docs
|
||||
uses: JamesIves/github-pages-deploy-action@4.1.5
|
||||
with:
|
||||
branch: gh-pages
|
||||
folder: docs
|
21
.github/workflows/sync_issues.yml
vendored
Normal file
21
.github/workflows/sync_issues.yml
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
name: Sync issue comments to JIRA
|
||||
|
||||
# This workflow will be triggered when new issue is created
|
||||
# or a new issue/PR comment is created
|
||||
on: [issues, issue_comment]
|
||||
|
||||
jobs:
|
||||
sync_issue_comments_to_jira:
|
||||
name: Sync Issue Comments to Jira
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Sync issue comments to JIRA
|
||||
uses: espressif/github-actions/sync_issues_to_jira@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
JIRA_PASS: ${{ secrets.JIRA_PASS }}
|
||||
JIRA_PROJECT: IDFGH
|
||||
JIRA_COMPONENT: esp-protocols
|
||||
JIRA_URL: ${{ secrets.JIRA_URL }}
|
||||
JIRA_USER: ${{ secrets.JIRA_USER }}
|
30
.github/workflows/test_afl_fuzzer.yml
vendored
Normal file
30
.github/workflows/test_afl_fuzzer.yml
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
name: AFL fuzzer compilation test
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
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@master
|
||||
with:
|
||||
path: esp-protocols
|
||||
- name: Install Necessary Libs
|
||||
run: |
|
||||
apt-get update -y
|
||||
apt-get install -y libbsd-dev
|
||||
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
env:
|
||||
IDF_TARGET: ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/tests/test_afl_fuzz_host/
|
||||
make INSTR=off
|
22
README.md
22
README.md
@ -1 +1,21 @@
|
||||
# Collection of components for ESP-IDF
|
||||
# Collection of protocol components for ESP-IDF
|
||||
|
||||
[Documentation of esp-protocol](https://espressif.github.io/esp-protocols)
|
||||
|
||||
## Components
|
||||
|
||||
### esp_modem
|
||||
|
||||
* Brief introduction [README](components/esp_modem/README.md)
|
||||
* Full html [documentation](https://espressif.github.io/esp-protocols/esp_modem/index.html)
|
||||
|
||||
### mDNS
|
||||
|
||||
* Brief introduction [README](components/mdns/README.md)
|
||||
* Full html [documentation(English)](https://espressif.github.io/esp-protocols/mdns/en/index.html)
|
||||
* Full html [documentation(Chinese)](https://espressif.github.io/esp-protocols/mdns/zh_CN/index.html)
|
||||
|
||||
### esp_websocket_client
|
||||
|
||||
* Brief introduction [README](components/esp_websocket_client/README.md)
|
||||
* Full html [documentation](https://espressif.github.io/esp-protocols/esp_websocket_client/index.html)
|
||||
|
@ -0,0 +1,4 @@
|
||||
idf_component_register(SRCS "connect.c" "stdin_out.c" "addr_from_stdin.c"
|
||||
INCLUDE_DIRS "include"
|
||||
PRIV_REQUIRES esp_netif driver
|
||||
)
|
322
common_components/protocol_examples_common/Kconfig.projbuild
Normal file
322
common_components/protocol_examples_common/Kconfig.projbuild
Normal file
@ -0,0 +1,322 @@
|
||||
menu "Example Connection Configuration"
|
||||
|
||||
orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps"
|
||||
|
||||
config EXAMPLE_CONNECT_WIFI
|
||||
bool "connect using WiFi interface"
|
||||
default y
|
||||
help
|
||||
Protocol examples can use Wi-Fi and/or Ethernet to connect to the network.
|
||||
Choose this option to connect with WiFi
|
||||
|
||||
if EXAMPLE_CONNECT_WIFI
|
||||
config EXAMPLE_WIFI_SSID
|
||||
string "WiFi SSID"
|
||||
default "myssid"
|
||||
help
|
||||
SSID (network name) for the example to connect to.
|
||||
|
||||
config EXAMPLE_WIFI_PASSWORD
|
||||
string "WiFi Password"
|
||||
default "mypassword"
|
||||
help
|
||||
WiFi password (WPA or WPA2) for the example to use.
|
||||
Can be left blank if the network has no security set.
|
||||
|
||||
choice EXAMPLE_WIFI_SCAN_METHOD
|
||||
prompt "WiFi Scan Method"
|
||||
default EXAMPLE_WIFI_SCAN_METHOD_ALL_CHANNEL
|
||||
help
|
||||
WiFi scan method:
|
||||
|
||||
If "Fast" is selected, scan will end after find SSID match AP.
|
||||
|
||||
If "All Channel" is selected, scan will end after scan all the channel.
|
||||
|
||||
config EXAMPLE_WIFI_SCAN_METHOD_FAST
|
||||
bool "Fast"
|
||||
config EXAMPLE_WIFI_SCAN_METHOD_ALL_CHANNEL
|
||||
bool "All Channel"
|
||||
endchoice
|
||||
|
||||
menu "WiFi Scan threshold"
|
||||
config EXAMPLE_WIFI_SCAN_RSSI_THRESHOLD
|
||||
int "WiFi minimum rssi"
|
||||
range -127 0
|
||||
|
||||
default -127
|
||||
help
|
||||
The minimum rssi to accept in the scan mode.
|
||||
|
||||
choice EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD
|
||||
prompt "WiFi Scan auth mode threshold"
|
||||
default EXAMPLE_WIFI_AUTH_OPEN
|
||||
help
|
||||
The weakest authmode to accept in the scan mode.
|
||||
|
||||
config EXAMPLE_WIFI_AUTH_OPEN
|
||||
bool "OPEN"
|
||||
config EXAMPLE_WIFI_AUTH_WEP
|
||||
bool "WEP"
|
||||
config EXAMPLE_WIFI_AUTH_WPA_PSK
|
||||
bool "WPA PSK"
|
||||
config EXAMPLE_WIFI_AUTH_WPA2_PSK
|
||||
bool "WPA2 PSK"
|
||||
config EXAMPLE_WIFI_AUTH_WPA_WPA2_PSK
|
||||
bool "WPA WPA2 PSK"
|
||||
config EXAMPLE_WIFI_AUTH_WPA2_ENTERPRISE
|
||||
bool "WPA2 ENTERPRISE"
|
||||
config EXAMPLE_WIFI_AUTH_WPA3_PSK
|
||||
bool "WPA3 PSK"
|
||||
config EXAMPLE_WIFI_AUTH_WPA2_WPA3_PSK
|
||||
bool "WPA2 WPA3 PSK"
|
||||
config EXAMPLE_WIFI_AUTH_WAPI_PSK
|
||||
bool "WAPI PSK"
|
||||
endchoice
|
||||
endmenu
|
||||
|
||||
choice EXAMPLE_WIFI_CONNECT_AP_SORT_METHOD
|
||||
prompt "WiFi Connect AP Sort Method"
|
||||
default EXAMPLE_WIFI_CONNECT_AP_BY_SIGNAL
|
||||
help
|
||||
WiFi connect AP sort method:
|
||||
|
||||
If "Signal" is selected, Sort matched APs in scan list by RSSI.
|
||||
|
||||
If "Security" is selected, Sort matched APs in scan list by security mode.
|
||||
|
||||
config EXAMPLE_WIFI_CONNECT_AP_BY_SIGNAL
|
||||
bool "Signal"
|
||||
config EXAMPLE_WIFI_CONNECT_AP_BY_SECURITY
|
||||
bool "Security"
|
||||
endchoice
|
||||
endif
|
||||
|
||||
config EXAMPLE_CONNECT_ETHERNET
|
||||
bool "connect using Ethernet interface"
|
||||
default n
|
||||
help
|
||||
Protocol examples can use Wi-Fi and/or Ethernet to connect to the network.
|
||||
Choose this option to connect with Ethernet
|
||||
|
||||
if EXAMPLE_CONNECT_ETHERNET
|
||||
config EXAMPLE_USE_SPI_ETHERNET
|
||||
bool
|
||||
|
||||
choice EXAMPLE_ETHERNET_TYPE
|
||||
prompt "Ethernet Type"
|
||||
default EXAMPLE_USE_INTERNAL_ETHERNET if IDF_TARGET_ESP32
|
||||
default EXAMPLE_USE_W5500
|
||||
help
|
||||
Select which kind of Ethernet will be used in the example.
|
||||
|
||||
config EXAMPLE_USE_INTERNAL_ETHERNET
|
||||
depends on IDF_TARGET_ESP32
|
||||
select ETH_USE_ESP32_EMAC
|
||||
bool "Internal EMAC"
|
||||
help
|
||||
Select internal Ethernet MAC controller.
|
||||
|
||||
config EXAMPLE_USE_DM9051
|
||||
bool "DM9051 Module"
|
||||
select EXAMPLE_USE_SPI_ETHERNET
|
||||
select ETH_USE_SPI_ETHERNET
|
||||
select ETH_SPI_ETHERNET_DM9051
|
||||
help
|
||||
Select external SPI-Ethernet module.
|
||||
|
||||
config EXAMPLE_USE_W5500
|
||||
bool "W5500 Module"
|
||||
select EXAMPLE_USE_SPI_ETHERNET
|
||||
select ETH_USE_SPI_ETHERNET
|
||||
select ETH_SPI_ETHERNET_W5500
|
||||
help
|
||||
Select external SPI-Ethernet module (W5500).
|
||||
|
||||
config EXAMPLE_USE_OPENETH
|
||||
bool "OpenCores Ethernet MAC (EXPERIMENTAL)"
|
||||
select ETH_USE_OPENETH
|
||||
help
|
||||
When this option is enabled, the example is built with support for
|
||||
OpenCores Ethernet MAC, which allows testing the example in QEMU.
|
||||
Note that this option is used for internal testing purposes, and
|
||||
not officially supported. Examples built with this option enabled
|
||||
will not run on a real ESP32 chip.
|
||||
|
||||
endchoice # EXAMPLE_ETHERNET_TYPE
|
||||
|
||||
if EXAMPLE_USE_INTERNAL_ETHERNET
|
||||
choice EXAMPLE_ETH_PHY_MODEL
|
||||
prompt "Ethernet PHY Device"
|
||||
default EXAMPLE_ETH_PHY_IP101
|
||||
help
|
||||
Select the Ethernet PHY device to use in the example.
|
||||
|
||||
config EXAMPLE_ETH_PHY_IP101
|
||||
bool "IP101"
|
||||
help
|
||||
IP101 is a single port 10/100 MII/RMII/TP/Fiber Fast Ethernet Transceiver.
|
||||
Goto http://www.icplus.com.tw/pp-IP101G.html for more information about it.
|
||||
|
||||
config EXAMPLE_ETH_PHY_RTL8201
|
||||
bool "RTL8201/SR8201"
|
||||
help
|
||||
RTL8201F/SR8201F is a single port 10/100Mb Ethernet Transceiver with auto MDIX.
|
||||
Goto http://www.corechip-sz.com/productsview.asp?id=22 for more information about it.
|
||||
|
||||
config EXAMPLE_ETH_PHY_LAN87XX
|
||||
bool "LAN87xx"
|
||||
help
|
||||
Below chips are supported:
|
||||
LAN8710A is a small footprint MII/RMII 10/100 Ethernet Transceiver with HP Auto-MDIX and
|
||||
flexPWR® Technology.
|
||||
LAN8720A is a small footprint RMII 10/100 Ethernet Transceiver with HP Auto-MDIX Support.
|
||||
LAN8740A/LAN8741A is a small footprint MII/RMII 10/100 Energy Efficient Ethernet Transceiver
|
||||
with HP Auto-MDIX and flexPWR® Technology.
|
||||
LAN8742A is a small footprint RMII 10/100 Ethernet Transceiver with HP Auto-MDIX and
|
||||
flexPWR® Technology.
|
||||
Goto https://www.microchip.com for more information about them.
|
||||
|
||||
config EXAMPLE_ETH_PHY_DP83848
|
||||
bool "DP83848"
|
||||
help
|
||||
DP83848 is a single port 10/100Mb/s Ethernet Physical Layer Transceiver.
|
||||
Goto http://www.ti.com/product/DP83848J for more information about it.
|
||||
|
||||
config EXAMPLE_ETH_PHY_KSZ80XX
|
||||
bool "KSZ80xx"
|
||||
help
|
||||
With the KSZ80xx series, Microchip offers single-chip 10BASE-T/100BASE-TX
|
||||
Ethernet Physical Layer Tranceivers (PHY).
|
||||
The following chips are supported: KSZ8001, KSZ8021, KSZ8031, KSZ8041,
|
||||
KSZ8051, KSZ8061, KSZ8081, KSZ8091
|
||||
Goto https://www.microchip.com for more information about them.
|
||||
endchoice
|
||||
|
||||
config EXAMPLE_ETH_MDC_GPIO
|
||||
int "SMI MDC GPIO number"
|
||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
||||
default 23
|
||||
help
|
||||
Set the GPIO number used by SMI MDC.
|
||||
|
||||
config EXAMPLE_ETH_MDIO_GPIO
|
||||
int "SMI MDIO GPIO number"
|
||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
||||
default 18
|
||||
help
|
||||
Set the GPIO number used by SMI MDIO.
|
||||
endif
|
||||
|
||||
if EXAMPLE_USE_SPI_ETHERNET
|
||||
config EXAMPLE_ETH_SPI_HOST
|
||||
int "SPI Host Number"
|
||||
range 0 2
|
||||
default 1
|
||||
help
|
||||
Set the SPI host used to communicate with the SPI Ethernet Controller.
|
||||
|
||||
config EXAMPLE_ETH_SPI_SCLK_GPIO
|
||||
int "SPI SCLK GPIO number"
|
||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
||||
default 14
|
||||
help
|
||||
Set the GPIO number used by SPI SCLK.
|
||||
|
||||
config EXAMPLE_ETH_SPI_MOSI_GPIO
|
||||
int "SPI MOSI GPIO number"
|
||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
||||
default 13
|
||||
help
|
||||
Set the GPIO number used by SPI MOSI.
|
||||
|
||||
config EXAMPLE_ETH_SPI_MISO_GPIO
|
||||
int "SPI MISO GPIO number"
|
||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX
|
||||
default 12
|
||||
help
|
||||
Set the GPIO number used by SPI MISO.
|
||||
|
||||
config EXAMPLE_ETH_SPI_CS_GPIO
|
||||
int "SPI CS GPIO number"
|
||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
||||
default 15
|
||||
help
|
||||
Set the GPIO number used by SPI CS.
|
||||
|
||||
config EXAMPLE_ETH_SPI_CLOCK_MHZ
|
||||
int "SPI clock speed (MHz)"
|
||||
range 5 80
|
||||
default 36
|
||||
help
|
||||
Set the clock speed (MHz) of SPI interface.
|
||||
|
||||
config EXAMPLE_ETH_SPI_INT_GPIO
|
||||
int "Interrupt GPIO number"
|
||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX
|
||||
default 4
|
||||
help
|
||||
Set the GPIO number used by the SPI Ethernet module interrupt line.
|
||||
endif # EXAMPLE_USE_SPI_ETHERNET
|
||||
|
||||
config EXAMPLE_ETH_PHY_RST_GPIO
|
||||
int "PHY Reset GPIO number"
|
||||
range -1 ENV_GPIO_OUT_RANGE_MAX
|
||||
default 5
|
||||
help
|
||||
Set the GPIO number used to reset PHY chip.
|
||||
Set to -1 to disable PHY chip hardware reset.
|
||||
|
||||
config EXAMPLE_ETH_PHY_ADDR
|
||||
int "PHY Address"
|
||||
range 0 31 if EXAMPLE_USE_INTERNAL_ETHERNET
|
||||
default 1
|
||||
help
|
||||
Set PHY address according your board schematic.
|
||||
endif # EXAMPLE_CONNECT_ETHERNET
|
||||
|
||||
config EXAMPLE_CONNECT_IPV6
|
||||
bool "Obtain IPv6 address"
|
||||
default y
|
||||
depends on EXAMPLE_CONNECT_WIFI || EXAMPLE_CONNECT_ETHERNET
|
||||
select LWIP_IPV6
|
||||
help
|
||||
By default, examples will wait until IPv4 and IPv6 local link addresses are obtained.
|
||||
Disable this option if the network does not support IPv6.
|
||||
Choose the preferred IPv6 address type if the connection code should wait until other than
|
||||
the local link address gets assigned.
|
||||
Consider enabling IPv6 stateless address autoconfiguration (SLAAC) in the LWIP component.
|
||||
|
||||
if EXAMPLE_CONNECT_IPV6
|
||||
choice EXAMPLE_CONNECT_PREFERRED_IPV6
|
||||
prompt "Preferred IPv6 Type"
|
||||
default EXAMPLE_CONNECT_IPV6_PREF_LOCAL_LINK
|
||||
help
|
||||
Select which kind of IPv6 address the connect logic waits for.
|
||||
|
||||
config EXAMPLE_CONNECT_IPV6_PREF_LOCAL_LINK
|
||||
bool "Local Link Address"
|
||||
help
|
||||
Blocks until Local link address assigned.
|
||||
|
||||
config EXAMPLE_CONNECT_IPV6_PREF_GLOBAL
|
||||
bool "Global Address"
|
||||
help
|
||||
Blocks until Global address assigned.
|
||||
|
||||
config EXAMPLE_CONNECT_IPV6_PREF_SITE_LOCAL
|
||||
bool "Site Local Address"
|
||||
help
|
||||
Blocks until Site link address assigned.
|
||||
|
||||
config EXAMPLE_CONNECT_IPV6_PREF_UNIQUE_LOCAL
|
||||
bool "Unique Local Link Address"
|
||||
help
|
||||
Blocks until Unique local address assigned.
|
||||
|
||||
endchoice
|
||||
|
||||
endif
|
||||
|
||||
|
||||
endmenu
|
68
common_components/protocol_examples_common/addr_from_stdin.c
Normal file
68
common_components/protocol_examples_common/addr_from_stdin.c
Normal file
@ -0,0 +1,68 @@
|
||||
#include <string.h>
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_netif.h"
|
||||
#include "protocol_examples_common.h"
|
||||
|
||||
#include "lwip/sockets.h"
|
||||
#include <lwip/netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define HOST_IP_SIZE 128
|
||||
|
||||
esp_err_t get_addr_from_stdin(int port, int sock_type, int *ip_protocol, int *addr_family, struct sockaddr_storage *dest_addr)
|
||||
{
|
||||
char host_ip[HOST_IP_SIZE];
|
||||
int len;
|
||||
static bool already_init = false;
|
||||
|
||||
// this function could be called multiple times -> make sure UART init runs only once
|
||||
if (!already_init) {
|
||||
example_configure_stdin_stdout();
|
||||
already_init = true;
|
||||
}
|
||||
|
||||
// ignore empty or LF only string (could receive from DUT class)
|
||||
do {
|
||||
fgets(host_ip, HOST_IP_SIZE, stdin);
|
||||
len = strlen(host_ip);
|
||||
} while (len<=1 && host_ip[0] == '\n');
|
||||
host_ip[len - 1] = '\0';
|
||||
|
||||
struct addrinfo hints, *addr_list, *cur;
|
||||
memset( &hints, 0, sizeof( hints ) );
|
||||
|
||||
// run getaddrinfo() to decide on the IP protocol
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = sock_type;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
if( getaddrinfo( host_ip, NULL, &hints, &addr_list ) != 0 ) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
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);
|
||||
freeaddrinfo( addr_list );
|
||||
return ESP_OK;
|
||||
|
||||
}
|
||||
#if CONFIG_LWIP_IPV6
|
||||
else if (cur->ai_family == AF_INET6) {
|
||||
*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);
|
||||
freeaddrinfo( addr_list );
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// no match found
|
||||
freeaddrinfo( addr_list );
|
||||
return ESP_FAIL;
|
||||
}
|
515
common_components/protocol_examples_common/connect.c
Normal file
515
common_components/protocol_examples_common/connect.c
Normal file
@ -0,0 +1,515 @@
|
||||
/* Common functions for protocol examples, to establish Wi-Fi or Ethernet connection.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "protocol_examples_common.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_wifi_default.h"
|
||||
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||
#include "esp_eth.h"
|
||||
#if CONFIG_ETH_USE_SPI_ETHERNET
|
||||
#include "driver/spi_master.h"
|
||||
#endif // CONFIG_ETH_USE_SPI_ETHERNET
|
||||
#endif // CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||
#include "esp_log.h"
|
||||
#include "esp_netif.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
||||
#define MAX_IP6_ADDRS_PER_NETIF (5)
|
||||
#define NR_OF_IP_ADDRESSES_TO_WAIT_FOR (s_active_interfaces*2)
|
||||
|
||||
#if defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_LOCAL_LINK)
|
||||
#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_LINK_LOCAL
|
||||
#elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_GLOBAL)
|
||||
#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_GLOBAL
|
||||
#elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_SITE_LOCAL)
|
||||
#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_SITE_LOCAL
|
||||
#elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_UNIQUE_LOCAL)
|
||||
#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_UNIQUE_LOCAL
|
||||
#endif // if-elif CONFIG_EXAMPLE_CONNECT_IPV6_PREF_...
|
||||
|
||||
#else
|
||||
#define NR_OF_IP_ADDRESSES_TO_WAIT_FOR (s_active_interfaces)
|
||||
#endif
|
||||
|
||||
#define EXAMPLE_DO_CONNECT CONFIG_EXAMPLE_CONNECT_WIFI || CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||
|
||||
#if CONFIG_EXAMPLE_WIFI_SCAN_METHOD_FAST
|
||||
#define EXAMPLE_WIFI_SCAN_METHOD WIFI_FAST_SCAN
|
||||
#elif CONFIG_EXAMPLE_WIFI_SCAN_METHOD_ALL_CHANNEL
|
||||
#define EXAMPLE_WIFI_SCAN_METHOD WIFI_ALL_CHANNEL_SCAN
|
||||
#endif
|
||||
|
||||
#if CONFIG_EXAMPLE_WIFI_CONNECT_AP_BY_SIGNAL
|
||||
#define EXAMPLE_WIFI_CONNECT_AP_SORT_METHOD WIFI_CONNECT_AP_BY_SIGNAL
|
||||
#elif CONFIG_EXAMPLE_WIFI_CONNECT_AP_BY_SECURITY
|
||||
#define EXAMPLE_WIFI_CONNECT_AP_SORT_METHOD WIFI_CONNECT_AP_BY_SECURITY
|
||||
#endif
|
||||
|
||||
#if CONFIG_EXAMPLE_WIFI_AUTH_OPEN
|
||||
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN
|
||||
#elif CONFIG_EXAMPLE_WIFI_AUTH_WEP
|
||||
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP
|
||||
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA_PSK
|
||||
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK
|
||||
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA2_PSK
|
||||
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK
|
||||
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA_WPA2_PSK
|
||||
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK
|
||||
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA2_ENTERPRISE
|
||||
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_ENTERPRISE
|
||||
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA3_PSK
|
||||
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK
|
||||
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA2_WPA3_PSK
|
||||
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK
|
||||
#elif CONFIG_EXAMPLE_WIFI_AUTH_WAPI_PSK
|
||||
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK
|
||||
#endif
|
||||
|
||||
static int s_active_interfaces = 0;
|
||||
static SemaphoreHandle_t s_semph_get_ip_addrs;
|
||||
static esp_netif_t *s_example_esp_netif = NULL;
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
||||
static esp_ip6_addr_t s_ipv6_addr;
|
||||
|
||||
/* types of ipv6 addresses to be displayed on ipv6 events */
|
||||
static const char *s_ipv6_addr_types[] = {
|
||||
"ESP_IP6_ADDR_IS_UNKNOWN",
|
||||
"ESP_IP6_ADDR_IS_GLOBAL",
|
||||
"ESP_IP6_ADDR_IS_LINK_LOCAL",
|
||||
"ESP_IP6_ADDR_IS_SITE_LOCAL",
|
||||
"ESP_IP6_ADDR_IS_UNIQUE_LOCAL",
|
||||
"ESP_IP6_ADDR_IS_IPV4_MAPPED_IPV6"
|
||||
};
|
||||
#endif
|
||||
|
||||
static const char *TAG = "example_connect";
|
||||
|
||||
#if CONFIG_EXAMPLE_CONNECT_WIFI
|
||||
static esp_netif_t *wifi_start(void);
|
||||
static void wifi_stop(void);
|
||||
#endif
|
||||
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||
static esp_netif_t *eth_start(void);
|
||||
static void eth_stop(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Checks the netif description if it contains specified prefix.
|
||||
* All netifs created withing common connect component are prefixed with the module TAG,
|
||||
* so it returns true if the specified netif is owned by this module
|
||||
*/
|
||||
static bool is_our_netif(const char *prefix, esp_netif_t *netif)
|
||||
{
|
||||
return strncmp(prefix, esp_netif_get_desc(netif), strlen(prefix) - 1) == 0;
|
||||
}
|
||||
|
||||
/* set up connection, Wi-Fi and/or Ethernet */
|
||||
static void start(void)
|
||||
{
|
||||
|
||||
#if CONFIG_EXAMPLE_CONNECT_WIFI
|
||||
s_example_esp_netif = wifi_start();
|
||||
s_active_interfaces++;
|
||||
#endif
|
||||
|
||||
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||
s_example_esp_netif = eth_start();
|
||||
s_active_interfaces++;
|
||||
#endif
|
||||
|
||||
#if CONFIG_EXAMPLE_CONNECT_WIFI && CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||
/* if both intefaces at once, clear out to indicate that multiple netifs are active */
|
||||
s_example_esp_netif = NULL;
|
||||
#endif
|
||||
|
||||
#if EXAMPLE_DO_CONNECT
|
||||
/* create semaphore if at least one interface is active */
|
||||
s_semph_get_ip_addrs = xSemaphoreCreateCounting(NR_OF_IP_ADDRESSES_TO_WAIT_FOR, 0);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* tear down connection, release resources */
|
||||
static void stop(void)
|
||||
{
|
||||
#if CONFIG_EXAMPLE_CONNECT_WIFI
|
||||
wifi_stop();
|
||||
s_active_interfaces--;
|
||||
#endif
|
||||
|
||||
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||
eth_stop();
|
||||
s_active_interfaces--;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if EXAMPLE_DO_CONNECT
|
||||
static esp_ip4_addr_t s_ip_addr;
|
||||
|
||||
static void on_got_ip(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
||||
if (!is_our_netif(TAG, event->esp_netif)) {
|
||||
ESP_LOGW(TAG, "Got IPv4 from another interface \"%s\": ignored", esp_netif_get_desc(event->esp_netif));
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(TAG, "Got IPv4 event: Interface \"%s\" address: " IPSTR, esp_netif_get_desc(event->esp_netif), IP2STR(&event->ip_info.ip));
|
||||
memcpy(&s_ip_addr, &event->ip_info.ip, sizeof(s_ip_addr));
|
||||
xSemaphoreGive(s_semph_get_ip_addrs);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
||||
|
||||
static void on_got_ipv6(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
|
||||
if (!is_our_netif(TAG, event->esp_netif)) {
|
||||
ESP_LOGW(TAG, "Got IPv6 from another netif: ignored");
|
||||
return;
|
||||
}
|
||||
esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip);
|
||||
ESP_LOGI(TAG, "Got IPv6 event: Interface \"%s\" address: " IPV6STR ", type: %s", esp_netif_get_desc(event->esp_netif),
|
||||
IPV62STR(event->ip6_info.ip), s_ipv6_addr_types[ipv6_type]);
|
||||
if (ipv6_type == EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE) {
|
||||
memcpy(&s_ipv6_addr, &event->ip6_info.ip, sizeof(s_ipv6_addr));
|
||||
xSemaphoreGive(s_semph_get_ip_addrs);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CONFIG_EXAMPLE_CONNECT_IPV6
|
||||
|
||||
esp_err_t example_connect(void)
|
||||
{
|
||||
#if EXAMPLE_DO_CONNECT
|
||||
if (s_semph_get_ip_addrs != NULL) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
#endif
|
||||
start();
|
||||
ESP_ERROR_CHECK(esp_register_shutdown_handler(&stop));
|
||||
ESP_LOGI(TAG, "Waiting for IP(s)");
|
||||
for (int i = 0; i < NR_OF_IP_ADDRESSES_TO_WAIT_FOR; ++i) {
|
||||
xSemaphoreTake(s_semph_get_ip_addrs, portMAX_DELAY);
|
||||
}
|
||||
// iterate over active interfaces, and print out IPs of "our" netifs
|
||||
esp_netif_t *netif = NULL;
|
||||
esp_netif_ip_info_t ip;
|
||||
for (int i = 0; i < esp_netif_get_nr_of_ifs(); ++i) {
|
||||
netif = esp_netif_next(netif);
|
||||
if (is_our_netif(TAG, netif)) {
|
||||
ESP_LOGI(TAG, "Connected to %s", esp_netif_get_desc(netif));
|
||||
ESP_ERROR_CHECK(esp_netif_get_ip_info(netif, &ip));
|
||||
|
||||
ESP_LOGI(TAG, "- IPv4 address: " IPSTR, IP2STR(&ip.ip));
|
||||
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
||||
esp_ip6_addr_t ip6[MAX_IP6_ADDRS_PER_NETIF];
|
||||
int ip6_addrs = esp_netif_get_all_ip6(netif, ip6);
|
||||
for (int j = 0; j < ip6_addrs; ++j) {
|
||||
esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&(ip6[j]));
|
||||
ESP_LOGI(TAG, "- IPv6 address: " IPV6STR ", type: %s", IPV62STR(ip6[j]), s_ipv6_addr_types[ipv6_type]);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t example_disconnect(void)
|
||||
{
|
||||
if (s_semph_get_ip_addrs == NULL) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
vSemaphoreDelete(s_semph_get_ip_addrs);
|
||||
s_semph_get_ip_addrs = NULL;
|
||||
stop();
|
||||
ESP_ERROR_CHECK(esp_unregister_shutdown_handler(&stop));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_CONNECT_WIFI
|
||||
|
||||
static void on_wifi_disconnect(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
ESP_LOGI(TAG, "Wi-Fi disconnected, trying to reconnect...");
|
||||
esp_err_t err = esp_wifi_connect();
|
||||
if (err == ESP_ERR_WIFI_NOT_STARTED) {
|
||||
return;
|
||||
}
|
||||
ESP_ERROR_CHECK(err);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
||||
|
||||
static void on_wifi_connect(void *esp_netif, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
esp_netif_create_ip6_linklocal(esp_netif);
|
||||
}
|
||||
|
||||
#endif // CONFIG_EXAMPLE_CONNECT_IPV6
|
||||
|
||||
static esp_netif_t *wifi_start(void)
|
||||
{
|
||||
char *desc;
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_WIFI_STA();
|
||||
// Prefix the interface description with the module TAG
|
||||
// Warning: the interface desc is used in tests to capture actual connection details (IP, gw, mask)
|
||||
asprintf(&desc, "%s: %s", TAG, esp_netif_config.if_desc);
|
||||
esp_netif_config.if_desc = desc;
|
||||
esp_netif_config.route_prio = 128;
|
||||
esp_netif_t *netif = esp_netif_create_wifi(WIFI_IF_STA, &esp_netif_config);
|
||||
free(desc);
|
||||
esp_wifi_set_default_wifi_sta_handlers();
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip, NULL));
|
||||
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &on_wifi_connect, netif));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL));
|
||||
#endif
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
|
||||
wifi_config_t wifi_config = {
|
||||
.sta = {
|
||||
.ssid = CONFIG_EXAMPLE_WIFI_SSID,
|
||||
.password = CONFIG_EXAMPLE_WIFI_PASSWORD,
|
||||
.scan_method = EXAMPLE_WIFI_SCAN_METHOD,
|
||||
.sort_method = EXAMPLE_WIFI_CONNECT_AP_SORT_METHOD,
|
||||
.threshold.rssi = CONFIG_EXAMPLE_WIFI_SCAN_RSSI_THRESHOLD,
|
||||
.threshold.authmode = EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD,
|
||||
},
|
||||
};
|
||||
ESP_LOGI(TAG, "Connecting to %s...", wifi_config.sta.ssid);
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
esp_wifi_connect();
|
||||
return netif;
|
||||
}
|
||||
|
||||
static void wifi_stop(void)
|
||||
{
|
||||
esp_netif_t *wifi_netif = get_example_netif_from_desc("sta");
|
||||
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect));
|
||||
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip));
|
||||
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
||||
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6));
|
||||
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &on_wifi_connect));
|
||||
#endif
|
||||
esp_err_t err = esp_wifi_stop();
|
||||
if (err == ESP_ERR_WIFI_NOT_INIT) {
|
||||
return;
|
||||
}
|
||||
ESP_ERROR_CHECK(err);
|
||||
ESP_ERROR_CHECK(esp_wifi_deinit());
|
||||
ESP_ERROR_CHECK(esp_wifi_clear_default_wifi_driver_and_handlers(wifi_netif));
|
||||
esp_netif_destroy(wifi_netif);
|
||||
s_example_esp_netif = NULL;
|
||||
}
|
||||
#endif // CONFIG_EXAMPLE_CONNECT_WIFI
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
||||
|
||||
/** Event handler for Ethernet events */
|
||||
static void on_eth_event(void *esp_netif, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
switch (event_id) {
|
||||
case ETHERNET_EVENT_CONNECTED:
|
||||
ESP_LOGI(TAG, "Ethernet Link Up");
|
||||
ESP_ERROR_CHECK(esp_netif_create_ip6_linklocal(esp_netif));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CONFIG_EXAMPLE_CONNECT_IPV6
|
||||
|
||||
static esp_eth_handle_t s_eth_handle = NULL;
|
||||
static esp_eth_mac_t *s_mac = NULL;
|
||||
static esp_eth_phy_t *s_phy = NULL;
|
||||
static esp_eth_netif_glue_handle_t s_eth_glue = NULL;
|
||||
|
||||
static esp_netif_t *eth_start(void)
|
||||
{
|
||||
char *desc;
|
||||
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
|
||||
// Prefix the interface description with the module TAG
|
||||
// Warning: the interface desc is used in tests to capture actual connection details (IP, gw, mask)
|
||||
asprintf(&desc, "%s: %s", TAG, esp_netif_config.if_desc);
|
||||
esp_netif_config.if_desc = desc;
|
||||
esp_netif_config.route_prio = 64;
|
||||
esp_netif_config_t netif_config = {
|
||||
.base = &esp_netif_config,
|
||||
.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH
|
||||
};
|
||||
esp_netif_t *netif = esp_netif_new(&netif_config);
|
||||
assert(netif);
|
||||
free(desc);
|
||||
|
||||
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
||||
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
||||
phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR;
|
||||
phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO;
|
||||
#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
|
||||
eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
|
||||
esp32_emac_config.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO;
|
||||
esp32_emac_config.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO;
|
||||
s_mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
|
||||
#if CONFIG_EXAMPLE_ETH_PHY_IP101
|
||||
s_phy = esp_eth_phy_new_ip101(&phy_config);
|
||||
#elif CONFIG_EXAMPLE_ETH_PHY_RTL8201
|
||||
s_phy = esp_eth_phy_new_rtl8201(&phy_config);
|
||||
#elif CONFIG_EXAMPLE_ETH_PHY_LAN87XX
|
||||
s_phy = esp_eth_phy_new_lan87xx(&phy_config);
|
||||
#elif CONFIG_EXAMPLE_ETH_PHY_DP83848
|
||||
s_phy = esp_eth_phy_new_dp83848(&phy_config);
|
||||
#elif CONFIG_EXAMPLE_ETH_PHY_KSZ80XX
|
||||
s_phy = esp_eth_phy_new_ksz80xx(&phy_config);
|
||||
#endif
|
||||
#elif CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
||||
gpio_install_isr_service(0);
|
||||
spi_device_handle_t spi_handle = NULL;
|
||||
spi_bus_config_t buscfg = {
|
||||
.miso_io_num = CONFIG_EXAMPLE_ETH_SPI_MISO_GPIO,
|
||||
.mosi_io_num = CONFIG_EXAMPLE_ETH_SPI_MOSI_GPIO,
|
||||
.sclk_io_num = CONFIG_EXAMPLE_ETH_SPI_SCLK_GPIO,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
};
|
||||
ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_ETH_SPI_HOST, &buscfg, 1));
|
||||
#if CONFIG_EXAMPLE_USE_DM9051
|
||||
spi_device_interface_config_t devcfg = {
|
||||
.command_bits = 1,
|
||||
.address_bits = 7,
|
||||
.mode = 0,
|
||||
.clock_speed_hz = CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ * 1000 * 1000,
|
||||
.spics_io_num = CONFIG_EXAMPLE_ETH_SPI_CS_GPIO,
|
||||
.queue_size = 20
|
||||
};
|
||||
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);
|
||||
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);
|
||||
#elif CONFIG_EXAMPLE_USE_W5500
|
||||
spi_device_interface_config_t devcfg = {
|
||||
.command_bits = 16, // Actually it's the address phase in W5500 SPI frame
|
||||
.address_bits = 8, // Actually it's the control phase in W5500 SPI frame
|
||||
.mode = 0,
|
||||
.clock_speed_hz = CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ * 1000 * 1000,
|
||||
.spics_io_num = CONFIG_EXAMPLE_ETH_SPI_CS_GPIO,
|
||||
.queue_size = 20
|
||||
};
|
||||
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);
|
||||
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);
|
||||
#endif
|
||||
#elif CONFIG_EXAMPLE_USE_OPENETH
|
||||
phy_config.autonego_timeout_ms = 100;
|
||||
s_mac = esp_eth_mac_new_openeth(&mac_config);
|
||||
s_phy = esp_eth_phy_new_dp83848(&phy_config);
|
||||
#endif
|
||||
|
||||
// Install Ethernet driver
|
||||
esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy);
|
||||
ESP_ERROR_CHECK(esp_eth_driver_install(&config, &s_eth_handle));
|
||||
#if !CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
|
||||
/* The SPI Ethernet module might doesn't have a burned factory MAC address, we cat to set it manually.
|
||||
02:00:00 is a Locally Administered OUI range so should not be used except when testing on a LAN under your control.
|
||||
*/
|
||||
ESP_ERROR_CHECK(esp_eth_ioctl(s_eth_handle, ETH_CMD_S_MAC_ADDR, (uint8_t[]) {
|
||||
0x02, 0x00, 0x00, 0x12, 0x34, 0x56
|
||||
}));
|
||||
#endif
|
||||
// combine driver with netif
|
||||
s_eth_glue = esp_eth_new_netif_glue(s_eth_handle);
|
||||
esp_netif_attach(netif, s_eth_glue);
|
||||
|
||||
// Register user defined event handers
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &on_got_ip, NULL));
|
||||
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event, netif));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL));
|
||||
#endif
|
||||
|
||||
esp_eth_start(s_eth_handle);
|
||||
return netif;
|
||||
}
|
||||
|
||||
static void eth_stop(void)
|
||||
{
|
||||
esp_netif_t *eth_netif = get_example_netif_from_desc("eth");
|
||||
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, &on_got_ip));
|
||||
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
||||
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6));
|
||||
ESP_ERROR_CHECK(esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event));
|
||||
#endif
|
||||
ESP_ERROR_CHECK(esp_eth_stop(s_eth_handle));
|
||||
ESP_ERROR_CHECK(esp_eth_del_netif_glue(s_eth_glue));
|
||||
ESP_ERROR_CHECK(esp_eth_driver_uninstall(s_eth_handle));
|
||||
s_eth_handle = NULL;
|
||||
ESP_ERROR_CHECK(s_phy->del(s_phy));
|
||||
ESP_ERROR_CHECK(s_mac->del(s_mac));
|
||||
|
||||
esp_netif_destroy(eth_netif);
|
||||
s_example_esp_netif = NULL;
|
||||
}
|
||||
|
||||
esp_eth_handle_t get_example_eth_handle(void)
|
||||
{
|
||||
return s_eth_handle;
|
||||
}
|
||||
|
||||
#endif // CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||
|
||||
esp_netif_t *get_example_netif(void)
|
||||
{
|
||||
return s_example_esp_netif;
|
||||
}
|
||||
|
||||
esp_netif_t *get_example_netif_from_desc(const char *desc)
|
||||
{
|
||||
esp_netif_t *netif = NULL;
|
||||
char *expected_desc;
|
||||
asprintf(&expected_desc, "%s: %s", TAG, desc);
|
||||
while ((netif = esp_netif_next(netif)) != NULL) {
|
||||
if (strcmp(esp_netif_get_desc(netif), expected_desc) == 0) {
|
||||
free(expected_desc);
|
||||
return netif;
|
||||
}
|
||||
}
|
||||
free(expected_desc);
|
||||
return netif;
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/* 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
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "lwip/sys.h"
|
||||
#include <lwip/netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
/**
|
||||
* @brief Read and evaluate IP address from stdin
|
||||
*
|
||||
* This API reads stdin and parses the input address using getaddrinfo()
|
||||
* to fill in struct sockaddr_storage (for both IPv4 and IPv6) used to open
|
||||
* a socket. IP protocol is guessed from the IP address string.
|
||||
*
|
||||
* @param[in] port port number of expected connection
|
||||
* @param[in] sock_type expected protocol: SOCK_STREAM or SOCK_DGRAM
|
||||
* @param[out] ip_protocol resultant IP protocol: IPPROTO_IP or IPPROTO_IP6
|
||||
* @param[out] addr_family resultant address family: AF_INET or AF_INET6
|
||||
* @param[out] dest_addr sockaddr_storage structure (for both IPv4 and IPv6)
|
||||
* @return ESP_OK on success, ESP_FAIL otherwise
|
||||
*/
|
||||
esp_err_t get_addr_from_stdin(int port, int sock_type,
|
||||
int *ip_protocol,
|
||||
int *addr_family,
|
||||
struct sockaddr_storage *dest_addr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,92 @@
|
||||
/* Common functions for protocol examples, to establish Wi-Fi or Ethernet connection.
|
||||
|
||||
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
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_netif.h"
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||
#define EXAMPLE_INTERFACE get_example_netif()
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_CONNECT_WIFI
|
||||
#define EXAMPLE_INTERFACE get_example_netif()
|
||||
#endif
|
||||
|
||||
#if !defined (CONFIG_EXAMPLE_CONNECT_ETHERNET) && !defined (CONFIG_EXAMPLE_CONNECT_WIFI)
|
||||
// This is useful for some tests which do not need a network connection
|
||||
#define EXAMPLE_INTERFACE NULL
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Configure Wi-Fi or Ethernet, connect, wait for IP
|
||||
*
|
||||
* This all-in-one helper function is used in protocols examples to
|
||||
* reduce the amount of boilerplate in the example.
|
||||
*
|
||||
* It is not intended to be used in real world applications.
|
||||
* See examples under examples/wifi/getting_started/ and examples/ethernet/
|
||||
* for more complete Wi-Fi or Ethernet initialization code.
|
||||
*
|
||||
* Read "Establishing Wi-Fi or Ethernet Connection" section in
|
||||
* examples/protocols/README.md for more information about this function.
|
||||
*
|
||||
* @return ESP_OK on successful connection
|
||||
*/
|
||||
esp_err_t example_connect(void);
|
||||
|
||||
/**
|
||||
* Counterpart to example_connect, de-initializes Wi-Fi or Ethernet
|
||||
*/
|
||||
esp_err_t example_disconnect(void);
|
||||
|
||||
/**
|
||||
* @brief Configure stdin and stdout to use blocking I/O
|
||||
*
|
||||
* This helper function is used in ASIO examples. It wraps installing the
|
||||
* UART driver and configuring VFS layer to use UART driver for console I/O.
|
||||
*/
|
||||
esp_err_t example_configure_stdin_stdout(void);
|
||||
|
||||
/**
|
||||
* @brief Returns esp-netif pointer created by example_connect()
|
||||
*
|
||||
* @note If multiple interfaces active at once, this API return NULL
|
||||
* In that case the get_example_netif_from_desc() should be used
|
||||
* to get esp-netif pointer based on interface description
|
||||
*/
|
||||
esp_netif_t *get_example_netif(void);
|
||||
|
||||
/**
|
||||
* @brief Returns esp-netif pointer created by example_connect() described by
|
||||
* the supplied desc field
|
||||
*
|
||||
* @param desc Textual interface of created network interface, for example "sta"
|
||||
* indicate default WiFi station, "eth" default Ethernet interface.
|
||||
*
|
||||
*/
|
||||
esp_netif_t *get_example_netif_from_desc(const char *desc);
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||
/**
|
||||
* @brief Get the example Ethernet driver handle
|
||||
*
|
||||
* @return esp_eth_handle_t
|
||||
*/
|
||||
esp_eth_handle_t get_example_eth_handle(void);
|
||||
#endif // CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
29
common_components/protocol_examples_common/stdin_out.c
Normal file
29
common_components/protocol_examples_common/stdin_out.c
Normal file
@ -0,0 +1,29 @@
|
||||
/* Common functions for protocol examples, to configure stdin and stdout.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "protocol_examples_common.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_vfs_dev.h"
|
||||
#include "driver/uart.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
esp_err_t example_configure_stdin_stdout(void)
|
||||
{
|
||||
// Initialize VFS & UART so we can use std::cout/cin
|
||||
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) );
|
||||
/* 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);
|
||||
/* Move the caret to the beginning of the next line on '\n' */
|
||||
esp_vfs_dev_uart_port_set_tx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CRLF);
|
||||
return ESP_OK;
|
||||
}
|
9
components/esp_modem/.gitignore
vendored
9
components/esp_modem/.gitignore
vendored
@ -51,9 +51,9 @@ tools/unit-test-app/test_configs
|
||||
log_ut_cmake
|
||||
|
||||
# test application build files
|
||||
tools/test_apps/**/build
|
||||
tools/test_apps/**/sdkconfig
|
||||
tools/test_apps/**/sdkconfig.old
|
||||
test/**/build
|
||||
test/**/sdkconfig
|
||||
test/**/sdkconfig.old
|
||||
|
||||
# IDF monitor test
|
||||
tools/test_idf_monitor/outputs
|
||||
@ -88,3 +88,6 @@ build
|
||||
|
||||
# lock files for examples and components
|
||||
dependencies.lock
|
||||
|
||||
# ignore generated docs
|
||||
docs/html
|
@ -7,6 +7,7 @@ if(${target} STREQUAL "linux")
|
||||
set(dependencies esp_system_protocols_linux)
|
||||
else()
|
||||
set(platform_srcs src/esp_modem_primitives_freertos.cpp
|
||||
src/esp_modem_api_target.cpp
|
||||
src/esp_modem_uart.cpp
|
||||
src/esp_modem_term_uart.cpp
|
||||
src/esp_modem_netif.cpp)
|
||||
@ -22,6 +23,8 @@ set(srcs ${platform_srcs}
|
||||
"src/esp_modem_cmux.cpp"
|
||||
"src/esp_modem_command_library.cpp"
|
||||
"src/esp_modem_term_fs.cpp"
|
||||
"src/esp_modem_vfs_uart_creator.cpp"
|
||||
"src/esp_modem_vfs_socket_creator.cpp"
|
||||
"src/esp_modem_modules.cpp")
|
||||
|
||||
set(include_dirs "include")
|
||||
@ -31,7 +34,11 @@ idf_component_register(SRCS "${srcs}"
|
||||
PRIV_INCLUDE_DIRS private_include
|
||||
REQUIRES ${dependencies})
|
||||
|
||||
target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17)
|
||||
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
|
||||
|
@ -1,6 +1,6 @@
|
||||
# ESP MODEM
|
||||
|
||||
The `esp-modem` component is a managed component for `esp-idf` that could be used for communication with GSM/LTE modems
|
||||
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.
|
||||
|
||||
## Examples
|
||||
@ -16,4 +16,4 @@ Get started with one of the examples:
|
||||
## Documentation
|
||||
|
||||
* Continue with esp-modem [brief overview](docs/README.md)
|
||||
* View the full [html documentation ](docs/html/index.html)
|
||||
* View the full [html documentation](https://espressif.github.io/esp-protocols/esp_modem/index.html)
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 26 KiB |
@ -36,11 +36,11 @@ After the object is created, the application interaction with the DCE is in
|
||||
* switching between data and command mode
|
||||
|
||||
### DTE
|
||||
Is an abstraction of the connected interface. Current implementation supports only UART
|
||||
Is an abstraction of the physical interface connected to the modem. Current implementation supports only UART
|
||||
|
||||
### PPP
|
||||
### PPP netif
|
||||
|
||||
Is used to connect the specific network interface to the modem data mode. Currently implementation supports only PPPoS protocol.
|
||||
Is used to attach the specific network interface to a network communication protocol used by the modem. Currently implementation supports only PPPoS protocol.
|
||||
|
||||
### Module
|
||||
|
||||
@ -48,7 +48,7 @@ Abstraction of the specific modem device. Currently the component supports SIM80
|
||||
|
||||
## Use cases
|
||||
|
||||
Users could interact with the esp-modem using the DCE's interface, to basically
|
||||
Users interact with the esp-modem using the DCE's interface, to basically
|
||||
* Switch between command and data mode to connect to the internet via cellular network.
|
||||
* Send various commands to the device (e.g. send SMS)
|
||||
|
||||
@ -57,16 +57,15 @@ IP address changes.
|
||||
|
||||
Common use cases of the esp-modem are also listed as the examples:
|
||||
* `examples/pppos_client` -- simple client which reads some module properties and switches to the data mode to connect to a public mqtt broker.
|
||||
* `examples/modem_console` -- is an example to exercise all possible modules commands in a console application.
|
||||
* `examples/ap_to_pppos` -- this example focuses on the network connectivity of the esp-modem and provides a WiFi AP
|
||||
that forwards packets (and uses NAT) to and from the PPPoS connection.
|
||||
* `examples/modem_console` -- is an example to exercise all possible module commands in a console application.
|
||||
* `examples/ap_to_pppos` -- this example focuses on the network connectivity of the esp-modem and provides a WiFi AP that forwards packets (and uses NAT) to and from the PPPoS connection.
|
||||
|
||||
## Extensibility
|
||||
|
||||
### CMUX
|
||||
|
||||
Implementation of virtual terminals is an experimental feature, which allows users to also issue commands in the data mode,
|
||||
after creating multiple virtual terminals, designating some of them solely to the data mode, while other to command mode.
|
||||
after creating multiple virtual terminals, designating some of them solely to data mode, others solely to command mode.
|
||||
|
||||
### DTE's
|
||||
|
||||
@ -74,6 +73,6 @@ Currently we support only UART, but modern modules support other communication i
|
||||
|
||||
### Other devices
|
||||
|
||||
Adding a new device is a must-have requirement for the esp-component. Different modules support different commands,
|
||||
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.
|
||||
|
@ -19,14 +19,15 @@ All the functionality is provided by the DCE factory
|
||||
.. doxygengroup:: ESP_MODEM_DCE_FACTORY
|
||||
:members:
|
||||
|
||||
.. _create_custom_module:
|
||||
|
||||
Create custom module
|
||||
--------------------
|
||||
|
||||
Creating a custom module is necessary if the application needs to use a specific device that is not supported
|
||||
and their commands differ from any of the supported devices. In this case it is recommended to define a new class
|
||||
representing this specific device and derive from the :cpp:class:`GenericModule`. In order to instantiate
|
||||
the appropriate DCE of this module, application could use :ref:`the DCE factory<dce_factory>`, but build the DCE with
|
||||
representing this specific device and derive from the :cpp:class:`esp_modem::GenericModule`. In order to instantiate
|
||||
the appropriate DCE of this module, application could use :ref:`the DCE factory<dce_factory>`, and build the DCE with
|
||||
the specific module, using :cpp:func:`esp_modem::dce_factory::Factory::build`.
|
||||
|
||||
Please refer to the implementation of the existing modules.
|
||||
@ -41,7 +42,7 @@ Create new communication interface
|
||||
In order to connect to a device using an unsupported interface (e.g. SPI or I2C), it is necessary to implement
|
||||
a custom DTE object and supply it into :ref:`the DCE factory<dce_factory>`. The DCE is typically created in two steps:
|
||||
|
||||
- Define and create the corresponding terminal, which can communicate on the custom interface. This terminal should support basic IO methods defined in :cpp:class:`esp_modem::Terminal` and derive from it.
|
||||
- Define and create the corresponding terminal, which communicates on the custom interface. This terminal should support basic IO methods defined in :cpp:class:`esp_modem::Terminal` and derive from it.
|
||||
- Create the DTE which uses the custom Terminal
|
||||
|
||||
Please refer to the implementation of the existing UART DTE.
|
||||
|
@ -1,15 +1,15 @@
|
||||
.. _c_api:
|
||||
|
||||
API Guide for C interface
|
||||
=========================
|
||||
C API Documentation
|
||||
===================
|
||||
|
||||
|
||||
C API is very simple and consist of these two basic parts:
|
||||
The C API is very simple and consist of these two basic parts:
|
||||
|
||||
- :ref:`lifecycle_api`
|
||||
- :ref:`modem_commands`
|
||||
|
||||
Typical application workflow is to:
|
||||
The Typical application workflow is to:
|
||||
|
||||
- Create a DCE instance (using :cpp:func:`esp_modem_new`)
|
||||
- Call specific functions to issue AT commands (:ref:`modem_commands`)
|
||||
@ -41,6 +41,9 @@ Modem commands
|
||||
|
||||
These functions are the actual commands to communicate with the modem using AT command interface.
|
||||
|
||||
Note that the functions which implement AT commands returning textual values use plain ``char *``
|
||||
pointer as the return value. The API expects the output data to point to user allocated space of at least
|
||||
``ESP_MODEM_C_API_STR_MAX`` (64 by default) bytes, it also truncates the output data to this size.
|
||||
|
||||
.. doxygenfile:: esp_modem_api_commands.h
|
||||
|
||||
|
@ -16,7 +16,8 @@ copyright = u'2016 - 2021, Espressif Systems (Shanghai) Co., Ltd'
|
||||
# for a list of supported languages.
|
||||
language = 'en'
|
||||
|
||||
extensions = ['breathe']
|
||||
extensions = ['breathe', 'recommonmark']
|
||||
|
||||
|
||||
breathe_projects = {'esp_modem': 'xml'}
|
||||
|
||||
|
@ -1,25 +0,0 @@
|
||||
|
||||
- :cpp:func:`esp_modem::DCE::sync`
|
||||
- :cpp:func:`esp_modem::DCE::get_operator_name`
|
||||
- :cpp:func:`esp_modem::DCE::store_profile`
|
||||
- :cpp:func:`esp_modem::DCE::set_pin`
|
||||
- :cpp:func:`esp_modem::DCE::read_pin`
|
||||
- :cpp:func:`esp_modem::DCE::set_echo`
|
||||
- :cpp:func:`esp_modem::DCE::sms_txt_mode`
|
||||
- :cpp:func:`esp_modem::DCE::sms_character_set`
|
||||
- :cpp:func:`esp_modem::DCE::send_sms`
|
||||
- :cpp:func:`esp_modem::DCE::resume_data_mode`
|
||||
- :cpp:func:`esp_modem::DCE::set_pdp_context`
|
||||
- :cpp:func:`esp_modem::DCE::set_command_mode`
|
||||
- :cpp:func:`esp_modem::DCE::set_cmux`
|
||||
- :cpp:func:`esp_modem::DCE::get_imsi`
|
||||
- :cpp:func:`esp_modem::DCE::get_imei`
|
||||
- :cpp:func:`esp_modem::DCE::get_module_name`
|
||||
- :cpp:func:`esp_modem::DCE::set_data_mode`
|
||||
- :cpp:func:`esp_modem::DCE::get_signal_quality`
|
||||
- :cpp:func:`esp_modem::DCE::set_flow_control`
|
||||
- :cpp:func:`esp_modem::DCE::hang_up`
|
||||
- :cpp:func:`esp_modem::DCE::get_battery_status`
|
||||
- :cpp:func:`esp_modem::DCE::power_down`
|
||||
- :cpp:func:`esp_modem::DCE::reset`
|
||||
- :cpp:func:`esp_modem::DCE::set_baud`
|
@ -1,99 +0,0 @@
|
||||
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -CC -xc -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > c_api.h
|
||||
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -xc -I../include -DGENERATE_DOCS -DGENERATE_RST_LINKS - | sed 's/NL/\n/g' > cxx_api_links.rst
|
||||
|
||||
// call parametrs by names for documentation
|
||||
|
||||
|
||||
// --- DCE command documentation starts here ---
|
||||
/**
|
||||
* @brief Sends the initial AT sequence to sync up with the device
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_sync (); /**
|
||||
* @brief Reads the operator name
|
||||
* @param[out] name module name
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_get_operator_name (char* name); /**
|
||||
* @brief Stores current user profile
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_store_profile (); /**
|
||||
* @brief Sets the supplied PIN code
|
||||
* @param[in] pin Pin
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/command_result esp_modem_set_pin (const char* pin); /**
|
||||
* @brief Checks if the SIM needs a PIN
|
||||
* @param[out] pin_ok true if the SIM card doesn't need a PIN to unlock
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_read_pin (bool* pin_ok); /**
|
||||
* @brief Sets echo mode
|
||||
* @param[in] echo_on true if echo mode on (repeats the commands)
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_set_echo (const bool echo_on); /**
|
||||
* @brief Sets the Txt or Pdu mode for SMS (only txt is supported)
|
||||
* @param[in] txt true if txt mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_sms_txt_mode (const bool txt); /**
|
||||
* @brief Sets the default (GSM) charater set
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_sms_character_set (); /**
|
||||
* @brief Sends SMS message in txt mode
|
||||
* @param[in] number Phone number to send the message to
|
||||
* @param[in] message Text message to be sent
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_send_sms (const char* number, const char* message); /**
|
||||
* @brief Resumes data mode (Switches back to th data mode, which was temporarily suspended)
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_resume_data_mode (); /**
|
||||
* @brief Sets php context
|
||||
* @param[in] x PdP context struct to setup modem cellular connection
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_set_pdp_context (struct PdpContext* x); /**
|
||||
* @brief Switches to the command mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_set_command_mode (); /**
|
||||
* @brief Switches to the CMUX mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_set_cmux (); /**
|
||||
* @brief Reads the IMSI number
|
||||
* @param[out] imsi Module's IMSI number
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_get_imsi (char* imsi); /**
|
||||
* @brief Reads the IMEI number
|
||||
* @param[out] imei Module's IMEI number
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_get_imei (char* imei); /**
|
||||
* @brief Reads the module name
|
||||
* @param[out] name module name
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_get_module_name (char* name); /**
|
||||
* @brief Sets the modem to data mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_set_data_mode (); /**
|
||||
* @brief Get Signal quality
|
||||
* @param[out] rssi signal strength indication
|
||||
* @param[out] ber channel bit error rate
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_get_signal_quality (int* rssi, int* ber); /**
|
||||
* @brief Sets HW control flow
|
||||
* @param[in] dce_flow 0=none, 2=RTS hw flow control of DCE
|
||||
* @param[in] dte_flow 0=none, 2=CTS hw flow control of DTE
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_set_flow_control (int dce_flow, int dte_flow); /**
|
||||
* @brief Hangs up current data call
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_hang_up (); /**
|
||||
* @brief Get voltage levels of modem power up circuitry
|
||||
* @param[out] voltage Current status in mV
|
||||
* @param[out] bcs charge status (-1-Not available, 0-Not charging, 1-Charging, 2-Charging done)
|
||||
* @param[out] bcl 1-100% battery capacity, -1-Not available
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_get_battery_status (int* voltage, int* bcs, int* bcl); /**
|
||||
* @brief Power down the module
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_power_down (); /**
|
||||
* @brief Reset the module
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_reset (); /**
|
||||
* @brief Configures the baudrate
|
||||
* @param[in] baud Desired baud rate of the DTE
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_set_baud (int baud);
|
@ -1,111 +0,0 @@
|
||||
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -CC -xc -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > c_api.h
|
||||
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -xc -I../include -DGENERATE_DOCS -DGENERATE_RST_LINKS - | sed 's/NL/\n/g' > cxx_api_links.rst
|
||||
|
||||
// call parametrs by names for documentation
|
||||
|
||||
|
||||
// --- DCE command documentation starts here ---
|
||||
|
||||
class esp_modem::DCE: public DCE_T<GenericModule> {
|
||||
public:
|
||||
using DCE_T<GenericModule>::DCE_T;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sends the initial AT sequence to sync up with the device
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result sync (); /**
|
||||
* @brief Reads the operator name
|
||||
* @param[out] name module name
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result get_operator_name (std::string& name); /**
|
||||
* @brief Stores current user profile
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result store_profile (); /**
|
||||
* @brief Sets the supplied PIN code
|
||||
* @param[in] pin Pin
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/command_result set_pin (const std::string& pin); /**
|
||||
* @brief Checks if the SIM needs a PIN
|
||||
* @param[out] pin_ok true if the SIM card doesn't need a PIN to unlock
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result read_pin (bool& pin_ok); /**
|
||||
* @brief Sets echo mode
|
||||
* @param[in] echo_on true if echo mode on (repeats the commands)
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result set_echo (const bool echo_on); /**
|
||||
* @brief Sets the Txt or Pdu mode for SMS (only txt is supported)
|
||||
* @param[in] txt true if txt mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result sms_txt_mode (const bool txt); /**
|
||||
* @brief Sets the default (GSM) charater set
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result sms_character_set (); /**
|
||||
* @brief Sends SMS message in txt mode
|
||||
* @param[in] number Phone number to send the message to
|
||||
* @param[in] message Text message to be sent
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result send_sms (const std::string& number, const std::string& message); /**
|
||||
* @brief Resumes data mode (Switches back to th data mode, which was temporarily suspended)
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result resume_data_mode (); /**
|
||||
* @brief Sets php context
|
||||
* @param[in] x PdP context struct to setup modem cellular connection
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result set_pdp_context (PdpContext& x); /**
|
||||
* @brief Switches to the command mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result set_command_mode (); /**
|
||||
* @brief Switches to the CMUX mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result set_cmux (); /**
|
||||
* @brief Reads the IMSI number
|
||||
* @param[out] imsi Module's IMSI number
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result get_imsi (std::string& imsi); /**
|
||||
* @brief Reads the IMEI number
|
||||
* @param[out] imei Module's IMEI number
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result get_imei (std::string& imei); /**
|
||||
* @brief Reads the module name
|
||||
* @param[out] name module name
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result get_module_name (std::string& name); /**
|
||||
* @brief Sets the modem to data mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result set_data_mode (); /**
|
||||
* @brief Get Signal quality
|
||||
* @param[out] rssi signal strength indication
|
||||
* @param[out] ber channel bit error rate
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result get_signal_quality (int& rssi, int& ber); /**
|
||||
* @brief Sets HW control flow
|
||||
* @param[in] dce_flow 0=none, 2=RTS hw flow control of DCE
|
||||
* @param[in] dte_flow 0=none, 2=CTS hw flow control of DTE
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result set_flow_control (int dce_flow, int dte_flow); /**
|
||||
* @brief Hangs up current data call
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result hang_up (); /**
|
||||
* @brief Get voltage levels of modem power up circuitry
|
||||
* @param[out] voltage Current status in mV
|
||||
* @param[out] bcs charge status (-1-Not available, 0-Not charging, 1-Charging, 2-Charging done)
|
||||
* @param[out] bcl 1-100% battery capacity, -1-Not available
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result get_battery_status (int& voltage, int& bcs, int& bcl); /**
|
||||
* @brief Power down the module
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result power_down (); /**
|
||||
* @brief Reset the module
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result reset (); /**
|
||||
* @brief Configures the baudrate
|
||||
* @param[in] baud Desired baud rate of the DTE
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result set_baud (int baud);
|
||||
};
|
@ -19,5 +19,5 @@ doxygen
|
||||
# Generate the docs
|
||||
python -u -m sphinx.cmd.build -b html . html
|
||||
|
||||
# Cleanup the doxygen xml's
|
||||
rm -rf xml
|
||||
# Cleanup the doxygen xml's and temporary headers
|
||||
rm -rf xml esp_modem_api_commands.h esp_modem_dce.hpp cxx_api_links.rst
|
||||
|
@ -9,6 +9,13 @@ The esp-modem actually implements the DCE class, which in turn aggregates these
|
||||
- :ref:`Netif<netif_impl>` to provide the network connectivity
|
||||
- :ref:`Module<module_impl>` to define the specific command library
|
||||
|
||||
Developers would typically have to
|
||||
|
||||
* Add support for a new module
|
||||
* Implement a generic (common for all modules) AT command
|
||||
|
||||
This is explained in the :ref:`Module<module_impl>` section, as :ref:`Adding new module or command<module_addition>`
|
||||
|
||||
------------
|
||||
|
||||
.. doxygengroup:: ESP_MODEM_DCE
|
||||
@ -63,6 +70,36 @@ Module abstraction
|
||||
.. doxygengroup:: ESP_MODEM_MODULE
|
||||
:members:
|
||||
|
||||
.. _module_addition:
|
||||
|
||||
Adding new devices
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To support a new module, developers would have to implement a new class derived from :cpp:class:`esp_modem::GenericModule` the same way
|
||||
as it is described in the :ref:`Advanced user manual<create_custom_module>`. The only difference is that the new class (and factory extension)
|
||||
would be available in the esp_modem code base.
|
||||
|
||||
Implement a new generic command
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Adding a generic command, i.e. the command that is shared for all modules and is included in the :cpp:class:`esp_modem::GenericModule`,
|
||||
has to be declared first in the ``include/generate/esp_modem_command_declare.inc`` file, which is the single source
|
||||
of supported command definitions, that is used in:
|
||||
|
||||
* public C API
|
||||
* public CPP API
|
||||
* generated documentation
|
||||
* implementation of the command
|
||||
|
||||
Therefore, a care must be taken, to correctly specify all parameters and types, especially:
|
||||
|
||||
* Keep number of parameters low (<= 6, used in preprocessor's forwarding to the command library)
|
||||
* Use macros to specify parameter types (as they are used both from C and C++ with different underlying types)
|
||||
* Parameter names are used only for clarity and documentation, they get expanded to numbered arguments.
|
||||
|
||||
Please use the following pattern: ``INT_IN(p1, baud)``, meaning that the parameter is an input integer,
|
||||
human readable argument name is ``baud``, it's the first argument, so expands to ``p1`` (second argument would be ``p2``, etc)
|
||||
|
||||
Command library
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -15,3 +15,7 @@ By default, this example simply connects to the PPP server using a supported dev
|
||||
This example however, doesn't rely on sending specific AT commands, just the bare minimum to setup the cellular network.
|
||||
Thus, if the `EXAMPLE_USE_MINIMAL_DCE` option is enabled, we directly inherit from the `ModuleIf` and implement only the basic commands.
|
||||
Also, to demonstrate the dce_factory functionality, a new `NetDCE_Factory` is implemented for creating the network module and the DCE.
|
||||
|
||||
### Supported IDF versions
|
||||
|
||||
This example is only supported from `v4.2`, since is uses NAPT feature.
|
@ -31,9 +31,16 @@ menu "Example Configuration"
|
||||
help
|
||||
Set APN (Access Point Name), a logical name to choose data network
|
||||
|
||||
config EXAMPLE_NEED_SIM_PIN
|
||||
bool "SIM PIN needed"
|
||||
default n
|
||||
help
|
||||
Enable to set SIM PIN before starting the example
|
||||
|
||||
config EXAMPLE_SIM_PIN
|
||||
string "Set SIM PIN"
|
||||
default "1234"
|
||||
depends on EXAMPLE_NEED_SIM_PIN
|
||||
help
|
||||
Pin to unlock the SIM
|
||||
|
||||
|
@ -16,6 +16,10 @@
|
||||
#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"
|
||||
#endif
|
||||
|
||||
#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID
|
||||
#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD
|
||||
@ -32,36 +36,32 @@ static const int DISCONNECT_BIT = BIT1;
|
||||
static void on_ip_event(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
if (event_base == IP_EVENT) {
|
||||
ESP_LOGD(TAG, "IP event! %d", event_id);
|
||||
if (event_id == IP_EVENT_PPP_GOT_IP) {
|
||||
esp_netif_dns_info_t dns_info;
|
||||
ESP_LOGD(TAG, "IP event! %d", event_id);
|
||||
if (event_id == IP_EVENT_PPP_GOT_IP) {
|
||||
esp_netif_dns_info_t dns_info;
|
||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
||||
esp_netif_t *netif = event->esp_netif;
|
||||
|
||||
ESP_LOGI(TAG, "Modem Connect to PPP Server");
|
||||
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
||||
ESP_LOGI(TAG, "IP : " IPSTR, IP2STR(&event->ip_info.ip));
|
||||
ESP_LOGI(TAG, "Netmask : " IPSTR, IP2STR(&event->ip_info.netmask));
|
||||
ESP_LOGI(TAG, "Gateway : " IPSTR, IP2STR(&event->ip_info.gw));
|
||||
esp_netif_get_dns_info(netif, 0, &dns_info);
|
||||
ESP_LOGI(TAG, "Name Server1: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
|
||||
esp_netif_get_dns_info(netif, 1, &dns_info);
|
||||
ESP_LOGI(TAG, "Name Server2: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
|
||||
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
||||
xEventGroupSetBits(event_group, CONNECT_BIT);
|
||||
|
||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
||||
esp_netif_t *netif = event->esp_netif;
|
||||
|
||||
ESP_LOGI(TAG, "Modem Connect to PPP Server");
|
||||
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
||||
ESP_LOGI(TAG, "IP : " IPSTR, IP2STR(&event->ip_info.ip));
|
||||
ESP_LOGI(TAG, "Netmask : " IPSTR, IP2STR(&event->ip_info.netmask));
|
||||
ESP_LOGI(TAG, "Gateway : " IPSTR, IP2STR(&event->ip_info.gw));
|
||||
esp_netif_get_dns_info(netif, 0, &dns_info);
|
||||
ESP_LOGI(TAG, "Name Server1: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
|
||||
esp_netif_get_dns_info(netif, 1, &dns_info);
|
||||
ESP_LOGI(TAG, "Name Server2: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
|
||||
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
||||
xEventGroupSetBits(event_group, CONNECT_BIT);
|
||||
|
||||
ESP_LOGI(TAG, "GOT ip event!!!");
|
||||
} else if (event_id == IP_EVENT_PPP_LOST_IP) {
|
||||
ESP_LOGI(TAG, "Modem Disconnect from PPP Server");
|
||||
xEventGroupSetBits(event_group, DISCONNECT_BIT);
|
||||
} else if (event_id == IP_EVENT_GOT_IP6) {
|
||||
ESP_LOGI(TAG, "GOT IPv6 event!");
|
||||
ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
|
||||
ESP_LOGI(TAG, "Got IPv6 address " IPV6STR, IPV62STR(event->ip6_info.ip));
|
||||
}
|
||||
ESP_LOGI(TAG, "GOT ip event!!!");
|
||||
} else if (event_id == IP_EVENT_PPP_LOST_IP) {
|
||||
ESP_LOGI(TAG, "Modem Disconnect from PPP Server");
|
||||
xEventGroupSetBits(event_group, DISCONNECT_BIT);
|
||||
} else if (event_id == IP_EVENT_GOT_IP6) {
|
||||
ESP_LOGI(TAG, "GOT IPv6 event!");
|
||||
ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
|
||||
ESP_LOGI(TAG, "Got IPv6 address " IPV6STR, IPV62STR(event->ip6_info.ip));
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,7 +93,6 @@ static void wifi_event_handler(void* arg, esp_event_base_t event_base,
|
||||
|
||||
void wifi_init_softap(void)
|
||||
{
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
|
@ -25,6 +25,7 @@ esp_err_t modem_init_network(esp_netif_t *netif)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_NEED_SIM_PIN
|
||||
// configure the PIN
|
||||
bool pin_ok = false;
|
||||
if (esp_modem_read_pin(dce, &pin_ok) == ESP_OK && pin_ok == false) {
|
||||
@ -34,6 +35,7 @@ esp_err_t modem_init_network(esp_netif_t *netif)
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_EXAMPLE_NEED_SIM_PIN
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
@ -19,40 +19,28 @@ using namespace esp_modem;
|
||||
using namespace esp_modem::dce_factory;
|
||||
|
||||
class NetModule;
|
||||
typedef DCE_T<NetModule> NetDCE;
|
||||
|
||||
/**
|
||||
* @brief Local network object used to setup PPP network
|
||||
*/
|
||||
class PPPNetwork {
|
||||
public:
|
||||
esp_err_t init(esp_netif_t *netif, const std::string& apn, const std::string &pin_number);
|
||||
void deinit();
|
||||
NetDCE * get_dce();
|
||||
private:
|
||||
NetDCE *dce;
|
||||
};
|
||||
using NetDCE = DCE_T<NetModule>;
|
||||
|
||||
/**
|
||||
* @brief The PPP network is a singleton, allocate statically here
|
||||
*/
|
||||
static PPPNetwork ppp_network;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Custom factory for creating NetDCE and NetModule
|
||||
*/
|
||||
class NetDCE_Factory: public Factory {
|
||||
public:
|
||||
template <typename T, typename ...Args>
|
||||
static DCE_T<T>* create(const config *cfg, Args&&... args)
|
||||
template <typename Module, typename ...Args>
|
||||
static DCE_T<Module> *create(const config *cfg, Args &&... args)
|
||||
{
|
||||
return build_generic_DCE<T>(cfg, std::forward<Args>(args)...);
|
||||
return build_generic_DCE<Module>(cfg, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename ...Args>
|
||||
static std::shared_ptr<T> create_module(const config *cfg, Args&&... args)
|
||||
template <typename Module, typename ...Args>
|
||||
static std::shared_ptr<Module> create_module(const config *cfg, Args &&... args)
|
||||
{
|
||||
return build_shared_module<T>(cfg, std::forward<Args>(args)...);
|
||||
return build_shared_module<Module>(cfg, std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
@ -65,42 +53,48 @@ public:
|
||||
class NetModule: public ModuleIf {
|
||||
public:
|
||||
explicit NetModule(std::shared_ptr<DTE> dte, const esp_modem_dce_config *cfg):
|
||||
dte(std::move(dte)), apn(std::string(cfg->apn)) {}
|
||||
dte(std::move(dte)), apn(std::string(cfg->apn)) {}
|
||||
|
||||
bool setup_data_mode() override
|
||||
[[nodiscard]] bool setup_data_mode() override
|
||||
{
|
||||
PdpContext pdp(apn);
|
||||
if (set_pdp_context(pdp) != command_result::OK)
|
||||
if (set_pdp_context(pdp) != command_result::OK) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool set_mode(modem_mode mode) override
|
||||
{
|
||||
if (mode == modem_mode::DATA_MODE) {
|
||||
if (set_data_mode() != command_result::OK)
|
||||
switch (mode) {
|
||||
case esp_modem::modem_mode::DATA_MODE:
|
||||
if (set_data_mode() != command_result::OK) {
|
||||
return resume_data_mode() == command_result::OK;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (mode == modem_mode::COMMAND_MODE) {
|
||||
case esp_modem::modem_mode::COMMAND_MODE:
|
||||
return set_command_mode() == command_result::OK;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool init(const std::string& pin)
|
||||
[[maybe_unused]] bool init_sim(const std::string &pin)
|
||||
{
|
||||
// switch to command mode (in case we were in PPP mode)
|
||||
static_cast<void>(set_command_mode()); // ignore the potential failure, as we might be in command mode after startup
|
||||
bool is_pin_ok;
|
||||
if (read_pin(is_pin_ok) != command_result::OK)
|
||||
if (read_pin(is_pin_ok) != command_result::OK) {
|
||||
return false;
|
||||
}
|
||||
if (!is_pin_ok) {
|
||||
if (set_pin(pin) != command_result::OK)
|
||||
if (set_pin(pin) != command_result::OK) {
|
||||
return false;
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
if (read_pin(is_pin_ok) != command_result::OK || !is_pin_ok)
|
||||
if (read_pin(is_pin_ok) != command_result::OK || !is_pin_ok) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -109,68 +103,83 @@ private:
|
||||
std::shared_ptr<DTE> dte;
|
||||
std::string apn;
|
||||
|
||||
[[nodiscard]] command_result set_pdp_context(PdpContext& pdp) { return dce_commands::set_pdp_context(dte.get(),pdp); }
|
||||
[[nodiscard]] command_result set_pin(const std::string &pin) { return dce_commands::set_pin(dte.get(), pin); }
|
||||
[[nodiscard]] command_result read_pin(bool& pin_ok) { return dce_commands::read_pin(dte.get(), pin_ok); }
|
||||
[[nodiscard]] command_result set_data_mode() { return dce_commands::set_data_mode(dte.get()); }
|
||||
[[nodiscard]] command_result resume_data_mode() { return dce_commands::resume_data_mode(dte.get()); }
|
||||
[[nodiscard]] command_result set_command_mode() { return dce_commands::set_command_mode(dte.get()); }
|
||||
[[nodiscard]] command_result set_pdp_context(PdpContext &pdp)
|
||||
{
|
||||
return dce_commands::set_pdp_context(dte.get(), pdp);
|
||||
}
|
||||
[[nodiscard]] command_result set_pin(const std::string &pin)
|
||||
{
|
||||
return dce_commands::set_pin(dte.get(), pin);
|
||||
}
|
||||
[[nodiscard]] command_result read_pin(bool &pin_ok)
|
||||
{
|
||||
return dce_commands::read_pin(dte.get(), pin_ok);
|
||||
}
|
||||
[[nodiscard]] command_result set_data_mode()
|
||||
{
|
||||
return dce_commands::set_data_mode(dte.get());
|
||||
}
|
||||
[[nodiscard]] command_result resume_data_mode()
|
||||
{
|
||||
return dce_commands::resume_data_mode(dte.get());
|
||||
}
|
||||
[[nodiscard]] command_result set_command_mode()
|
||||
{
|
||||
return dce_commands::set_command_mode(dte.get());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
esp_err_t PPPNetwork::init(esp_netif_t *netif, const std::string& apn, const std::string &pin_number)
|
||||
/**
|
||||
* @brief Implement the C-API for the AP-2-PPP functionality
|
||||
*/
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* @brief Local network object used to setup PPP network
|
||||
*/
|
||||
NetDCE *dce = nullptr;
|
||||
|
||||
extern "C" esp_err_t modem_init_network(esp_netif_t *netif)
|
||||
{
|
||||
// configure
|
||||
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
||||
dte_config.uart_config.rx_buffer_size = 16384;
|
||||
dte_config.uart_config.tx_buffer_size = 2048;
|
||||
esp_modem_dce_config dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(apn.c_str());
|
||||
esp_modem_dce_config dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(CONFIG_EXAMPLE_MODEM_PPP_APN);
|
||||
|
||||
// create DTE and minimal network DCE
|
||||
auto uart_dte = create_uart_dte(&dte_config);
|
||||
|
||||
// create the specific device (and initialize it)
|
||||
auto dev = NetDCE_Factory::create_module<NetModule>(&dce_config, uart_dte, netif);
|
||||
if (!dev->init(pin_number))
|
||||
#if CONFIG_EXAMPLE_NEED_SIM_PIN == 1
|
||||
if (!dev->init_sim(CONFIG_EXAMPLE_SIM_PIN)) {
|
||||
return ESP_FAIL;
|
||||
|
||||
}
|
||||
#endif
|
||||
// now create the DCE from our already existent device
|
||||
dce = NetDCE_Factory::create<NetModule>(&dce_config, uart_dte, netif, dev);
|
||||
if (dce == nullptr)
|
||||
if (dce == nullptr) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void PPPNetwork::deinit()
|
||||
extern "C" void modem_start_network()
|
||||
{
|
||||
dce->set_mode(esp_modem::modem_mode::DATA_MODE);
|
||||
}
|
||||
|
||||
extern "C" void modem_stop_network()
|
||||
{
|
||||
dce->set_mode(esp_modem::modem_mode::COMMAND_MODE);
|
||||
}
|
||||
|
||||
extern "C" void modem_deinit_network()
|
||||
{
|
||||
free(dce);
|
||||
dce = nullptr;
|
||||
}
|
||||
|
||||
NetDCE *PPPNetwork::get_dce()
|
||||
{
|
||||
return dce;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Implement the C-API for the AP-2-PPP functionality
|
||||
*/
|
||||
extern "C" esp_err_t modem_init_network(esp_netif_t *netif)
|
||||
{
|
||||
return ppp_network.init(netif, CONFIG_EXAMPLE_MODEM_PPP_APN, CONFIG_EXAMPLE_SIM_PIN);
|
||||
}
|
||||
|
||||
extern "C" void modem_start_network()
|
||||
{
|
||||
ppp_network.get_dce()->set_mode(esp_modem::modem_mode::DATA_MODE);
|
||||
}
|
||||
|
||||
extern "C" void modem_stop_network()
|
||||
{
|
||||
ppp_network.get_dce()->set_mode(esp_modem::modem_mode::COMMAND_MODE);
|
||||
}
|
||||
|
||||
extern "C" void modem_deinit_network()
|
||||
{
|
||||
ppp_network.deinit();
|
||||
}
|
||||
}
|
@ -7,8 +7,7 @@
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#ifndef _NETWORK_DCE_H_
|
||||
#define _NETWORK_DCE_H_
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -43,5 +42,3 @@ void modem_stop_network();
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //_NETWORK_DCE_H_
|
||||
|
@ -17,3 +17,7 @@ over PPPoS, i.e. over the modem serial line.
|
||||
* Experiment with the network, after getting the IP from the modem device
|
||||
- directly in the code
|
||||
- in the system (need to set `tun` interface IP, dns servers, and routing the desired traffic over the tun interface)
|
||||
|
||||
### Supported IDF versions
|
||||
|
||||
This example (using the default CMake IDF build system) is only supported from `v4.4`, since is uses `idf.py`'s linux target.
|
@ -5,5 +5,9 @@ set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(${COMPONENT_LIB} PRIVATE Threads::Threads)
|
||||
|
||||
target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17)
|
||||
set_target_properties(${COMPONENT_LIB} PROPERTIES
|
||||
CXX_STANDARD 17
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
CXX_EXTENSIONS ON
|
||||
)
|
||||
target_compile_definitions(${COMPONENT_LIB} PRIVATE "-DCONFIG_IDF_TARGET_LINUX")
|
||||
|
@ -7,39 +7,54 @@
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "esp_modem_config.h"
|
||||
#include "esp_netif.h"
|
||||
#include "vfs_resource/vfs_create.hpp"
|
||||
|
||||
|
||||
#define CONFIG_EXAMPLE_SIM_PIN "1234"
|
||||
#define CONFIG_USE_VFS_UART 1
|
||||
|
||||
using namespace esp_modem;
|
||||
|
||||
[[maybe_unused]] static const char *TAG = "linux_modem_main";
|
||||
[[maybe_unused]] constexpr auto TAG = "linux_modem_main";
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
// init the DTE
|
||||
esp_modem_dte_config_t dte_config = {
|
||||
.dte_buffer_size = 512,
|
||||
.task_stack_size = 1024,
|
||||
.task_priority = 10,
|
||||
.uart_config = { },
|
||||
.vfs_config = { }
|
||||
.dte_buffer_size = 512,
|
||||
.task_stack_size = 1024,
|
||||
.task_priority = 10,
|
||||
.vfs_config = {}
|
||||
};
|
||||
dte_config.vfs_config.dev_name = "/dev/ttyUSB0";
|
||||
dte_config.vfs_config.resource = ESP_MODEM_VFS_IS_UART; // This tells the VFS to init the UART (use termux to setup baudrate, etc.)
|
||||
#if CONFIG_USE_VFS_UART == 1
|
||||
struct esp_modem_vfs_uart_creator uart_config = {
|
||||
.dev_name = "/dev/ttyUSB0",
|
||||
.uart = {}
|
||||
};
|
||||
assert(vfs_create_uart(&uart_config, &dte_config.vfs_config) == true);
|
||||
#else
|
||||
/**
|
||||
* @note: It is possible to setup a serial to socket bridge, running a this on a remote host which connects `/dev/ttyS0` to the modem
|
||||
* socat TCP-L:2222 GOPEN:/dev/ttyS0,ispeed=115200,ospeed=1152000,b115200,raw,echo=0
|
||||
*/
|
||||
struct esp_modem_vfs_socket_creator socket_config = {
|
||||
.host_name = "raspberrypi.local",
|
||||
.port = 2222
|
||||
};
|
||||
assert(vfs_create_socket(&socket_config, &dte_config.vfs_config) == true);
|
||||
#endif
|
||||
auto dte = create_vfs_dte(&dte_config);
|
||||
|
||||
esp_netif_config_t netif_config = {
|
||||
.dev_name = "/dev/net/tun",
|
||||
.if_name = "tun0"
|
||||
.dev_name = "/dev/net/tun",
|
||||
.if_name = "tun0"
|
||||
};
|
||||
esp_netif_t *tun_netif = esp_netif_new(&netif_config);
|
||||
auto uart_dte = create_vfs_dte(&dte_config);
|
||||
|
||||
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("internet");
|
||||
|
||||
auto dce = create_SIM7600_dce(&dce_config, uart_dte, tun_netif);
|
||||
auto dce = create_SIM7600_dce(&dce_config, dte, tun_netif);
|
||||
assert(dce != nullptr);
|
||||
|
||||
dce->set_command_mode();
|
||||
@ -50,16 +65,18 @@ int main()
|
||||
usleep(1000000);
|
||||
}
|
||||
std::string str;
|
||||
dce->set_mode(esp_modem::modem_mode::CMUX_MODE);
|
||||
// dce->set_mode(esp_modem::modem_mode::CMUX_MODE);
|
||||
dce->get_imsi(str);
|
||||
ESP_LOGI(TAG, "Modem IMSI number: %s",str.c_str());
|
||||
ESP_LOGI(TAG, "Modem IMSI number: %s", str.c_str());
|
||||
dce->get_imei(str);
|
||||
ESP_LOGI(TAG, "Modem IMEI number: %s",str.c_str());
|
||||
dce->get_operator_name(str);
|
||||
ESP_LOGI(TAG, "Operator name: %s",str.c_str());
|
||||
ESP_LOGI(TAG, "Modem IMEI number: %s", str.c_str());
|
||||
while (command_result::OK != dce->get_operator_name(str)) {
|
||||
printf(".\n");
|
||||
}
|
||||
ESP_LOGI(TAG, "Operator name: %s", str.c_str());
|
||||
|
||||
dce->set_mode(esp_modem::modem_mode::DATA_MODE);
|
||||
|
||||
usleep(100'000'000);
|
||||
usleep(15'000'000);
|
||||
esp_netif_destroy(tun_netif);
|
||||
}
|
@ -4,5 +4,13 @@ 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)
|
||||
|
@ -1,6 +1,4 @@
|
||||
# PPPoS simple client example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
# Modem console example
|
||||
|
||||
## Overview
|
||||
|
||||
@ -14,4 +12,18 @@ This example implements two very simple network commands to demonstrate and test
|
||||
To demonstrate creating custom modem devices, this example creates a DCE object using a locally defined create method,
|
||||
that sets up the DCE based on a custom module implemented in the `my_module_dce.hpp` file. The module class only overrides
|
||||
`get_module_name()` method supplying a user defined name, but keeps all other commands the same as defined in the `GenericModule`
|
||||
class.
|
||||
class.
|
||||
|
||||
### USB DTE support
|
||||
|
||||
For USB enabled targets (ESP32-S2 and ESP32-S3), it is possible to connect to the modem device via USB.
|
||||
1. In menuconfig, navigate to `Example Configuration->Type of serial connection to the modem` and choose `USB`.
|
||||
2. Connect the modem USB signals to pin 19 (DATA-) and 20 (DATA+) on your ESP chip.
|
||||
|
||||
USB example uses Quactel BG96 modem device.
|
||||
|
||||
### Supported IDF versions
|
||||
|
||||
This example is only supported from `v4.2`, due to support of the console repl mode.
|
||||
|
||||
USB example is supported from `v4.4`.
|
@ -0,0 +1,19 @@
|
||||
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()
|
@ -0,0 +1,191 @@
|
||||
// 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
|
@ -0,0 +1,32 @@
|
||||
// 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));
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
// 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);
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
// 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 \
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
// 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,4 +2,5 @@ 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
|
||||
INCLUDE_DIRS ".")
|
||||
|
@ -0,0 +1,17 @@
|
||||
|
||||
menu "Example Configuration"
|
||||
|
||||
choice EXAMPLE_SERIAL_CONFIG
|
||||
prompt "Type of serial connection to the modem"
|
||||
default EXAMPLE_SERIAL_CONFIG_UART
|
||||
config EXAMPLE_SERIAL_CONFIG_UART
|
||||
bool "UART"
|
||||
help
|
||||
Connect to modem via UART.
|
||||
config EXAMPLE_SERIAL_CONFIG_USB
|
||||
bool "USB"
|
||||
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
help
|
||||
Connect to modem via USB (CDC-ACM class). For IDF version >= 4.4.
|
||||
endchoice
|
||||
endmenu
|
@ -12,50 +12,52 @@
|
||||
|
||||
static const char *TAG = "modem_console_helper";
|
||||
|
||||
ConsoleCommand::ConsoleCommand(const char* command, const char* help, const std::vector<CommandArgs>& args, std::function<bool(ConsoleCommand *)> f):
|
||||
func(std::move(f))
|
||||
ConsoleCommand::ConsoleCommand(const char *command, const char *help, const std::vector<CommandArgs> &args, std::function<bool(ConsoleCommand *)> f):
|
||||
func(std::move(f))
|
||||
{
|
||||
RegisterCommand(command, help, args);
|
||||
}
|
||||
|
||||
void ConsoleCommand::RegisterCommand(const char* command, const char* help, const std::vector<CommandArgs>& args)
|
||||
void ConsoleCommand::RegisterCommand(const char *command, const char *help, const std::vector<CommandArgs> &args)
|
||||
{
|
||||
assert(last_command <= MAX_REPEAT_NR);
|
||||
void * common_arg = nullptr;
|
||||
for (auto it: args) {
|
||||
switch(it.type) {
|
||||
case ARG_END:
|
||||
break;
|
||||
case STR0:
|
||||
common_arg = arg_str0(it.shortopts, it.longopts, it.datatype, it.glossary);
|
||||
break;
|
||||
case STR1:
|
||||
common_arg = arg_str1(it.shortopts, it.longopts, it.datatype, it.glossary);
|
||||
break;
|
||||
case INT0:
|
||||
common_arg = arg_int0(it.shortopts, it.longopts, it.datatype, it.glossary);
|
||||
break;
|
||||
case INT1:
|
||||
common_arg = arg_int1(it.shortopts, it.longopts, it.datatype, it.glossary);
|
||||
break;
|
||||
case LIT0:
|
||||
common_arg = arg_lit0(it.shortopts, it.longopts, it.glossary);
|
||||
break;
|
||||
arg_type common_arg = { };
|
||||
for (auto &it : args) {
|
||||
switch (it.type) {
|
||||
case ARG_END:
|
||||
break;
|
||||
case STR0:
|
||||
common_arg.str = arg_str0(it.shortopts, it.longopts, it.datatype, it.glossary);
|
||||
break;
|
||||
case STR1:
|
||||
common_arg.str = arg_str1(it.shortopts, it.longopts, it.datatype, it.glossary);
|
||||
break;
|
||||
case INT0:
|
||||
common_arg.intx = arg_int0(it.shortopts, it.longopts, it.datatype, it.glossary);
|
||||
break;
|
||||
case INT1:
|
||||
common_arg.intx = arg_int1(it.shortopts, it.longopts, it.datatype, it.glossary);
|
||||
break;
|
||||
case LIT0:
|
||||
common_arg.lit = arg_lit0(it.shortopts, it.longopts, it.glossary);
|
||||
break;
|
||||
}
|
||||
if (common_arg) {
|
||||
if (common_arg.is_null()) {
|
||||
arg_table.emplace_back(common_arg);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Creating argument parser failed for %s", it.glossary);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
arg_table.emplace_back( arg_end(1));
|
||||
|
||||
arg_type end = { .end = arg_end(1) };
|
||||
arg_table.emplace_back(end);
|
||||
const esp_console_cmd_t command_def = {
|
||||
.command = command,
|
||||
.help = help,
|
||||
.hint = nullptr,
|
||||
.func = command_func_pts[last_command],
|
||||
.argtable = &arg_table[0]
|
||||
.command = command,
|
||||
.help = help,
|
||||
.hint = nullptr,
|
||||
.func = command_func_pts[last_command],
|
||||
.argtable = &arg_table[0]
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&command_def));
|
||||
last_command++;
|
||||
@ -64,13 +66,13 @@ void ConsoleCommand::RegisterCommand(const char* command, const char* help, cons
|
||||
|
||||
int ConsoleCommand::get_count(int index)
|
||||
{
|
||||
return ((struct arg_str *)arg_table[index])->count;
|
||||
return (arg_table[index].str)->count;
|
||||
}
|
||||
|
||||
std::string ConsoleCommand::get_string(int index)
|
||||
{
|
||||
if (get_count(index) > 0) {
|
||||
return std::string(((struct arg_str *)arg_table[index])->sval[0]);
|
||||
return std::string(arg_table[index].str->sval[0]);
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
@ -78,17 +80,18 @@ std::string ConsoleCommand::get_string(int index)
|
||||
int ConsoleCommand::get_int(int index)
|
||||
{
|
||||
if (get_count(index) > 0) {
|
||||
return *((struct arg_int *)arg_table[index])->ival;
|
||||
return *(arg_table[index].intx)->ival;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int ConsoleCommand::command_func(int argc, char **argv) {
|
||||
void * plain_arg_array = &arg_table[0];
|
||||
int ConsoleCommand::command_func(int argc, char **argv)
|
||||
{
|
||||
arg_type *plain_arg_array = &arg_table[0];
|
||||
int nerrors = arg_parse(argc, argv, (void **)plain_arg_array);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, (struct arg_end *) arg_table.back(), argv[0]);
|
||||
arg_print_errors(stderr, arg_table.back().end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
if (func) {
|
||||
@ -120,7 +123,7 @@ const esp_console_cmd_func_t ConsoleCommand::command_func_pts[] = {
|
||||
|
||||
#define ITEM_TO_REPEAT(index) StaticCommands::command_func_ ## index ,
|
||||
|
||||
_DO_REPEAT_ITEM()
|
||||
_DO_REPEAT_ITEM()
|
||||
|
||||
#undef ITEM_TO_REPEAT
|
||||
};
|
||||
@ -128,5 +131,5 @@ const esp_console_cmd_func_t ConsoleCommand::command_func_pts[] = {
|
||||
/**
|
||||
* @brief Static members defined for ConsoleCommand
|
||||
*/
|
||||
std::vector<ConsoleCommand*> ConsoleCommand::console_commands;
|
||||
std::vector<ConsoleCommand *> ConsoleCommand::console_commands;
|
||||
int ConsoleCommand::last_command = 0;
|
||||
|
@ -7,8 +7,7 @@
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#ifndef MODEM_CONSOLE_CONSOLE_HELPER_H
|
||||
#define MODEM_CONSOLE_CONSOLE_HELPER_H
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
@ -35,10 +34,10 @@ enum arg_type {
|
||||
* Command argument struct definition for list of arguments of one command
|
||||
*/
|
||||
struct CommandArgs {
|
||||
CommandArgs(arg_type t, const char * shopts, const char * lopts, const char * data, const char * glos):
|
||||
CommandArgs(arg_type t, const char *shopts, const char *lopts, const char *data, const char *glos):
|
||||
type(t), shortopts(shopts), longopts(lopts), datatype(data), glossary(glos) {}
|
||||
CommandArgs(arg_type t, const char * shopts, const char * lopts, const char * glos):
|
||||
type(t), shortopts(shopts), longopts(lopts), datatype(nullptr), glossary(glos) {}
|
||||
CommandArgs(arg_type t, const char *shopts, const char *lopts, const char *glos):
|
||||
type(t), shortopts(shopts), longopts(lopts), datatype(nullptr), glossary(glos) {}
|
||||
|
||||
arg_type type;
|
||||
const char *shortopts;
|
||||
@ -53,6 +52,21 @@ class StaticCommands;
|
||||
* @brief This class simplifies console command definition in more object wise fashion
|
||||
*/
|
||||
class ConsoleCommand {
|
||||
/**
|
||||
* @brief Common argument types to be stored internally for parsing later
|
||||
*/
|
||||
using arg_type =
|
||||
union {
|
||||
struct arg_int *intx;
|
||||
struct arg_str *str;
|
||||
struct arg_lit *lit;
|
||||
struct arg_end *end;
|
||||
void *__raw_ptr;
|
||||
bool is_null() const {
|
||||
return __raw_ptr;
|
||||
}
|
||||
};
|
||||
|
||||
friend class StaticCommands;
|
||||
public:
|
||||
/**
|
||||
@ -63,8 +77,8 @@ public:
|
||||
* @param srg_struct_size Size of the argument struct
|
||||
* @param f Function callback for the command
|
||||
*/
|
||||
template<typename T> explicit ConsoleCommand(const char* command, const char* help, const T *arg_struct, size_t srg_struct_size,
|
||||
std::function<bool(ConsoleCommand *)> f): func(std::move(f))
|
||||
template<typename T> explicit ConsoleCommand(const char *command, const char *help, const T *arg_struct, size_t srg_struct_size,
|
||||
std::function<bool(ConsoleCommand *)> f): func(std::move(f))
|
||||
{
|
||||
size_t args_plain_size = srg_struct_size / sizeof(CommandArgs);
|
||||
auto first_arg = reinterpret_cast<const CommandArgs *>(arg_struct);
|
||||
@ -75,29 +89,38 @@ public:
|
||||
/**
|
||||
* @brief Another method of Console command definitions using vector arg struct
|
||||
*/
|
||||
explicit ConsoleCommand(const char* command, const char* help, const std::vector<CommandArgs>& args, std::function<bool(ConsoleCommand *)> f);
|
||||
explicit ConsoleCommand(const char *command, const char *help, const std::vector<CommandArgs> &args, std::function<bool(ConsoleCommand *)> f);
|
||||
|
||||
/**
|
||||
* @brief Utility getters of various params from the argument list
|
||||
*/
|
||||
template<typename T> int get_count_of(CommandArgs T::*member) { return get_count(index_arg(member)); }
|
||||
template<typename T> std::string get_string_of(CommandArgs T::*member) { return get_string(index_arg(member)); }
|
||||
template<typename T> int get_int_of(CommandArgs T::*member) { return get_int(index_arg(member)); }
|
||||
template<typename T> int get_count_of(CommandArgs T::*member)
|
||||
{
|
||||
return get_count(index_arg(member));
|
||||
}
|
||||
template<typename T> std::string get_string_of(CommandArgs T::*member)
|
||||
{
|
||||
return get_string(index_arg(member));
|
||||
}
|
||||
template<typename T> int get_int_of(CommandArgs T::*member)
|
||||
{
|
||||
return get_int(index_arg(member));
|
||||
}
|
||||
std::string get_string(int index);
|
||||
int get_int(int index);
|
||||
|
||||
private:
|
||||
int get_count(int index);
|
||||
void RegisterCommand(const char* command, const char* help, const std::vector<CommandArgs>& args);
|
||||
void RegisterCommand(const char *command, const char *help, const std::vector<CommandArgs> &args);
|
||||
template<typename T> static constexpr size_t index_arg(CommandArgs T::*member)
|
||||
{ return ((uint8_t *)&((T*)nullptr->*member) - (uint8_t *)nullptr)/sizeof(CommandArgs); }
|
||||
std::vector<void*> arg_table;
|
||||
{
|
||||
return ((uint8_t *) & ((T *)nullptr->*member) - (uint8_t *)nullptr) / sizeof(CommandArgs);
|
||||
}
|
||||
std::vector<arg_type> arg_table;
|
||||
int command_func(int argc, char **argv);
|
||||
|
||||
static int last_command;
|
||||
static std::vector<ConsoleCommand*> console_commands;
|
||||
static std::vector<ConsoleCommand *> console_commands;
|
||||
std::function<bool(ConsoleCommand *)> func;
|
||||
const static esp_console_cmd_func_t command_func_pts[];
|
||||
};
|
||||
|
||||
#endif //MODEM_CONSOLE_CONSOLE_HELPER_H
|
||||
|
@ -46,6 +46,7 @@ static esp_err_t http_event_handler(esp_http_client_event_t *evt)
|
||||
case HTTP_EVENT_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -83,9 +84,9 @@ static int do_http_client(int argc, char **argv)
|
||||
|
||||
esp_err_t err = esp_http_client_perform(client);
|
||||
if (err == ESP_OK) {
|
||||
ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %d",
|
||||
esp_http_client_get_status_code(client),
|
||||
esp_http_client_get_content_length(client));
|
||||
uint64_t content_length = esp_http_client_get_content_length(client);
|
||||
ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %lld",
|
||||
esp_http_client_get_status_code(client), content_length);
|
||||
return 0;
|
||||
}
|
||||
ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));
|
||||
@ -105,4 +106,4 @@ void modem_console_register_http(void)
|
||||
.argtable = &http_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&http_cmd));
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,10 @@
|
||||
#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)
|
||||
#include "esp_modem_usb_config.h"
|
||||
#include "cxx_include/esp_modem_usb_api.hpp"
|
||||
#endif
|
||||
#include "esp_log.h"
|
||||
#include "console_helper.hpp"
|
||||
#include "my_module_dce.hpp"
|
||||
@ -53,13 +57,29 @@ extern "C" void app_main(void)
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
// init the netif, DTE and DCE respectively
|
||||
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
||||
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(DEFAULT_APN);
|
||||
esp_netif_config_t ppp_netif_config = ESP_NETIF_DEFAULT_PPP();
|
||||
esp_netif_t *esp_netif = esp_netif_new(&ppp_netif_config);
|
||||
assert(esp_netif);
|
||||
|
||||
#if defined(CONFIG_EXAMPLE_SERIAL_CONFIG_UART)
|
||||
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
||||
auto uart_dte = create_uart_dte(&dte_config);
|
||||
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(DEFAULT_APN);
|
||||
auto dce = create_shiny_dce(&dce_config, uart_dte, esp_netif);
|
||||
|
||||
#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);
|
||||
|
||||
#else
|
||||
#error Invalid serial connection to modem.
|
||||
#endif
|
||||
|
||||
assert(dce != nullptr);
|
||||
|
||||
// init console REPL environment
|
||||
@ -73,7 +93,7 @@ extern "C" void app_main(void)
|
||||
SetModeArgs(): mode(STR1, nullptr, nullptr, "<mode>", "PPP, CMD or CMUX") {}
|
||||
CommandArgs mode;
|
||||
} set_mode_args;
|
||||
const ConsoleCommand SetModeParser("set_mode", "sets modem mode", &set_mode_args, sizeof(set_mode_args), [&](ConsoleCommand *c){
|
||||
const ConsoleCommand SetModeParser("set_mode", "sets modem mode", &set_mode_args, sizeof(set_mode_args), [&](ConsoleCommand * c) {
|
||||
if (c->get_count_of(&SetModeArgs::mode)) {
|
||||
auto mode = c->get_string_of(&SetModeArgs::mode);
|
||||
modem_mode dev_mode;
|
||||
@ -101,7 +121,7 @@ extern "C" void app_main(void)
|
||||
SetPinArgs(): pin(STR1, nullptr, nullptr, "<pin>", "PIN") {}
|
||||
CommandArgs pin;
|
||||
} set_pin_args;
|
||||
const ConsoleCommand SetPinParser("set_pin", "sets SIM card PIN", &set_pin_args, sizeof(set_pin_args), [&](ConsoleCommand *c){
|
||||
const ConsoleCommand SetPinParser("set_pin", "sets SIM card PIN", &set_pin_args, sizeof(set_pin_args), [&](ConsoleCommand * c) {
|
||||
if (c->get_count_of(&SetPinArgs::pin)) {
|
||||
auto pin = c->get_string_of(&SetPinArgs::pin);
|
||||
ESP_LOGI(TAG, "Setting pin=%s...", pin.c_str());
|
||||
@ -109,7 +129,7 @@ extern "C" void app_main(void)
|
||||
if (err == command_result::OK) {
|
||||
ESP_LOGI(TAG, "OK");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed %s", err == command_result::TIMEOUT ? "TIMEOUT":"");
|
||||
ESP_LOGE(TAG, "Failed %s", err == command_result::TIMEOUT ? "TIMEOUT" : "");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -117,26 +137,26 @@ extern "C" void app_main(void)
|
||||
});
|
||||
|
||||
const std::vector<CommandArgs> no_args;
|
||||
const ConsoleCommand ReadPinArgs("read_pin", "checks if SIM is unlocked", no_args, [&](ConsoleCommand *c){
|
||||
const ConsoleCommand ReadPinArgs("read_pin", "checks if SIM is unlocked", no_args, [&](ConsoleCommand * c) {
|
||||
bool pin_ok;
|
||||
ESP_LOGI(TAG, "Checking pin...");
|
||||
auto err = dce->read_pin(pin_ok);
|
||||
if (err == command_result::OK) {
|
||||
ESP_LOGI(TAG, "OK. Pin status: %s", pin_ok ? "true": "false");
|
||||
ESP_LOGI(TAG, "OK. Pin status: %s", pin_ok ? "true" : "false");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed %s", err == command_result::TIMEOUT ? "TIMEOUT":"");
|
||||
ESP_LOGE(TAG, "Failed %s", err == command_result::TIMEOUT ? "TIMEOUT" : "");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
const ConsoleCommand GetModuleName("get_module_name", "reads the module name", no_args, [&](ConsoleCommand *c){
|
||||
const ConsoleCommand GetModuleName("get_module_name", "reads the module name", no_args, [&](ConsoleCommand * c) {
|
||||
std::string module_name;
|
||||
ESP_LOGI(TAG, "Reading module name...");
|
||||
CHECK_ERR(dce->get_module_name(module_name), ESP_LOGI(TAG, "OK. Module name: %s", module_name.c_str()));
|
||||
});
|
||||
|
||||
const ConsoleCommand GetOperatorName("get_operator_name", "reads the operator name", no_args, [&](ConsoleCommand *c){
|
||||
const ConsoleCommand GetOperatorName("get_operator_name", "reads the operator name", no_args, [&](ConsoleCommand * c) {
|
||||
std::string operator_name;
|
||||
ESP_LOGI(TAG, "Reading operator name...");
|
||||
CHECK_ERR(dce->get_operator_name(operator_name), ESP_LOGI(TAG, "OK. Operator name: %s", operator_name.c_str()));
|
||||
@ -153,39 +173,41 @@ extern "C" void app_main(void)
|
||||
CommandArgs pattern;
|
||||
CommandArgs no_cr;
|
||||
} send_cmd_args;
|
||||
const ConsoleCommand SendCommand("cmd", "sends generic AT command, no_args", &send_cmd_args, sizeof(send_cmd_args), [&](ConsoleCommand *c) {
|
||||
const ConsoleCommand SendCommand("cmd", "sends generic AT command, no_args", &send_cmd_args, sizeof(send_cmd_args), [&](ConsoleCommand * c) {
|
||||
auto cmd = c->get_string_of(&GenericCommandArgs::cmd);
|
||||
auto timeout = c->get_count_of(&GenericCommandArgs::timeout) ? c->get_int_of(&GenericCommandArgs::timeout)
|
||||
: 1000;
|
||||
: 1000;
|
||||
ESP_LOGI(TAG, "Sending command %s with timeout %d", cmd.c_str(), timeout);
|
||||
auto pattern = c->get_string_of(&GenericCommandArgs::pattern);
|
||||
if (c->get_count_of(&GenericCommandArgs::no_cr) == 0) {
|
||||
cmd += '\r';
|
||||
}
|
||||
ESP_LOGI(TAG, "Sending command %s with timeout %d", cmd.c_str(), timeout);
|
||||
CHECK_ERR(dce->command(cmd, [&](uint8_t *data, size_t len) {
|
||||
std::string response((char *) data, len);
|
||||
ESP_LOGI(TAG, "%s", response.c_str());
|
||||
if (pattern.empty() || response.find(pattern) != std::string::npos)
|
||||
if (pattern.empty() || response.find(pattern) != std::string::npos) {
|
||||
return command_result::OK;
|
||||
if (response.find(pattern) != std::string::npos)
|
||||
}
|
||||
if (response.find(pattern) != std::string::npos) {
|
||||
return command_result::OK;
|
||||
}
|
||||
return command_result::TIMEOUT;
|
||||
}, timeout),);
|
||||
});
|
||||
|
||||
const ConsoleCommand GetSignalQuality("get_signal_quality", "Gets signal quality", no_args, [&](ConsoleCommand *c){
|
||||
const ConsoleCommand GetSignalQuality("get_signal_quality", "Gets signal quality", no_args, [&](ConsoleCommand * c) {
|
||||
int rssi, ber;
|
||||
CHECK_ERR(dce->get_signal_quality(rssi, ber), ESP_LOGI(TAG, "OK. rssi=%d, ber=%d", rssi, ber));
|
||||
});
|
||||
const ConsoleCommand GetBatteryStatus("get_battery_status", "Reads voltage/battery status", no_args, [&](ConsoleCommand *c){
|
||||
const ConsoleCommand GetBatteryStatus("get_battery_status", "Reads voltage/battery status", no_args, [&](ConsoleCommand * c) {
|
||||
int volt, bcl, bcs;
|
||||
CHECK_ERR(dce->get_battery_status(volt, bcl, bcs), ESP_LOGI(TAG, "OK. volt=%d, bcl=%d, bcs=%d", volt, bcl, bcs));
|
||||
});
|
||||
const ConsoleCommand PowerDown("power_down", "power down the module", no_args, [&](ConsoleCommand *c){
|
||||
const ConsoleCommand PowerDown("power_down", "power down the module", no_args, [&](ConsoleCommand * c) {
|
||||
ESP_LOGI(TAG, "Power down the module...");
|
||||
CHECK_ERR(dce->power_down(), ESP_LOGI(TAG, "OK"));
|
||||
});
|
||||
const ConsoleCommand Reset("reset", "reset the module", no_args, [&](ConsoleCommand *c){
|
||||
const ConsoleCommand Reset("reset", "reset the module", no_args, [&](ConsoleCommand * c) {
|
||||
ESP_LOGI(TAG, "Resetting the module...");
|
||||
CHECK_ERR(dce->reset(), ESP_LOGI(TAG, "OK"));
|
||||
});
|
||||
@ -193,7 +215,7 @@ extern "C" void app_main(void)
|
||||
SetApn(): apn(STR1, nullptr, nullptr, "<apn>", "APN (Access Point Name)") {}
|
||||
CommandArgs apn;
|
||||
} set_apn;
|
||||
const ConsoleCommand SetApnParser("set_apn", "sets APN", &set_apn, sizeof(set_apn), [&](ConsoleCommand *c){
|
||||
const ConsoleCommand SetApnParser("set_apn", "sets APN", &set_apn, sizeof(set_apn), [&](ConsoleCommand * c) {
|
||||
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());
|
||||
@ -205,7 +227,7 @@ extern "C" void app_main(void)
|
||||
});
|
||||
|
||||
SignalGroup exit_signal;
|
||||
const ConsoleCommand ExitConsole("exit", "exit the console application", no_args, [&](ConsoleCommand *c){
|
||||
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);
|
||||
|
@ -7,8 +7,7 @@
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#ifndef __MY_MODULE_DCE_HPP__
|
||||
#define __MY_MODULE_DCE_HPP__
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "cxx_include/esp_modem_dce_factory.hpp"
|
||||
@ -21,7 +20,7 @@
|
||||
class MyShinyModem: public esp_modem::GenericModule {
|
||||
using GenericModule::GenericModule;
|
||||
public:
|
||||
esp_modem::command_result get_module_name(std::string& name) override
|
||||
esp_modem::command_result get_module_name(std::string &name) override
|
||||
{
|
||||
name = "Custom Shiny Module";
|
||||
return esp_modem::command_result::OK;
|
||||
@ -33,11 +32,8 @@ public:
|
||||
* @return unique pointer of the resultant DCE
|
||||
*/
|
||||
std::unique_ptr<esp_modem::DCE> create_shiny_dce(const esp_modem::dce_config *config,
|
||||
std::shared_ptr<esp_modem::DTE> dte,
|
||||
esp_netif_t *netif)
|
||||
std::shared_ptr<esp_modem::DTE> dte,
|
||||
esp_netif_t *netif)
|
||||
{
|
||||
return esp_modem::dce_factory::Factory::build_unique<MyShinyModem>(config, std::move(dte), netif);
|
||||
}
|
||||
|
||||
|
||||
#endif //__MY_MODULE_DCE_HPP__
|
@ -8,3 +8,7 @@ This example shows how to act as a MQTT client after the PPPoS channel created b
|
||||
## How to use this example
|
||||
|
||||
See the README.md file in the upper level `pppos` directory for more information about the PPPoS examples.
|
||||
|
||||
### Supported IDF versions
|
||||
|
||||
This example is only supported from `v4.1`, as this is the default dependency of `esp-modem` component.
|
@ -143,7 +143,21 @@ void app_main(void)
|
||||
// Init netif object
|
||||
esp_netif_t *esp_netif = esp_netif_new(&netif_ppp_config);
|
||||
assert(esp_netif);
|
||||
|
||||
#if CONFIG_EXAMPLE_MODEM_DEVICE_BG96 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the BG96 module...");
|
||||
esp_modem_dce_t *dce = esp_modem_new_dev(ESP_MODEM_DCE_BG96, &dte_config, &dce_config, esp_netif);
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM800 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the SIM800 module...");
|
||||
esp_modem_dce_t *dce = esp_modem_new_dev(ESP_MODEM_DCE_SIM800, &dte_config, &dce_config, esp_netif);
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the SIM7600 module...");
|
||||
esp_modem_dce_t *dce = esp_modem_new_dev(ESP_MODEM_DCE_SIM7600, &dte_config, &dce_config, esp_netif);
|
||||
#else
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for a generic module...");
|
||||
esp_modem_dce_t *dce = esp_modem_new(&dte_config, &dce_config, esp_netif);
|
||||
#endif
|
||||
assert(dce);
|
||||
|
||||
#if CONFIG_EXAMPLE_NEED_SIM_PIN == 1
|
||||
// check if PIN needed
|
||||
|
@ -15,3 +15,7 @@ The example uses the following configuration options to demonstrate basic esp-mo
|
||||
## About the esp_modem
|
||||
|
||||
Please check the component [README](../../README.md)
|
||||
|
||||
### Supported IDF versions
|
||||
|
||||
This example is only supported from `v4.3`, since is uses an experimental `esp_event_cxx` component.
|
@ -1,2 +1,2 @@
|
||||
idf_component_register(SRCS "simple_client.cpp" "simple_mqtt_client.cpp"
|
||||
idf_component_register(SRCS "simple_cmux_client_main.cpp" "simple_mqtt_client.cpp"
|
||||
INCLUDE_DIRS ".")
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include "simple_mqtt_client.hpp"
|
||||
#include "esp_vfs_dev.h" // For optional VFS support
|
||||
#include "esp_https_ota.h" // For potential OTA configuration
|
||||
|
||||
#include "vfs_resource/vfs_create.hpp"
|
||||
|
||||
#define BROKER_URL "mqtt://mqtt.eclipseprojects.io"
|
||||
|
||||
@ -46,11 +46,11 @@ extern "C" void app_main(void)
|
||||
* so doesn't give any practical benefit besides the FD use demonstration and a placeholder
|
||||
* to use FD terminal for other devices
|
||||
*/
|
||||
dte_config.vfs_config.dev_name = "/dev/uart/1";
|
||||
dte_config.vfs_config.resource = ESP_MODEM_VFS_IS_UART;
|
||||
dte_config.uart_config.event_queue_size = 0;
|
||||
struct esp_modem_vfs_uart_creator uart_config = ESP_MODEM_VFS_DEFAULT_UART_CONFIG("/dev/uart/1");
|
||||
assert(vfs_create_uart(&uart_config, &dte_config.vfs_config) == true);
|
||||
|
||||
auto dte = create_vfs_dte(&dte_config);
|
||||
esp_vfs_dev_uart_use_driver(dte_config.uart_config.port_num);
|
||||
esp_vfs_dev_uart_use_driver(uart_config.uart.port_num);
|
||||
#else
|
||||
auto dte = create_uart_dte(&dte_config);
|
||||
#endif // CONFIG_EXAMPLE_USE_VFS_TERM
|
||||
@ -70,9 +70,9 @@ extern "C" void app_main(void)
|
||||
#if CONFIG_EXAMPLE_MODEM_DEVICE_BG96 == 1
|
||||
std::unique_ptr<DCE> dce = create_BG96_dce(&dce_config, dte, esp_netif);
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM800 == 1
|
||||
std::unique_ptr<DCE> dce = create_SIM800_dce(&dce_config, uart_dte, esp_netif);
|
||||
std::unique_ptr<DCE> dce = create_SIM800_dce(&dce_config, dte, esp_netif);
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1
|
||||
std::unique_ptr<DCE> dce = create_SIM7600_dce(&dce_config, uart_dte, esp_netif);
|
||||
std::unique_ptr<DCE> dce = create_SIM7600_dce(&dce_config, dte, esp_netif);
|
||||
#else
|
||||
#error "Unsupported device"
|
||||
#endif
|
||||
@ -122,10 +122,10 @@ extern "C" void app_main(void)
|
||||
event_handler.listen_to(MqttClient::get_event(MqttClient::Event::DATA));
|
||||
|
||||
auto reg = loop->register_event(MqttClient::get_event(MqttClient::Event::DATA),
|
||||
[&mqtt](const ESPEvent &event, void *data) {
|
||||
std::cout << " TOPIC:" << mqtt.get_topic(data) << std::endl;
|
||||
std::cout << " DATA:" << mqtt.get_data(data) << std::endl;
|
||||
});
|
||||
[&mqtt](const ESPEvent & event, void *data) {
|
||||
std::cout << " TOPIC:" << mqtt.get_topic(data) << std::endl;
|
||||
std::cout << " DATA:" << mqtt.get_data(data) << std::endl;
|
||||
});
|
||||
mqtt.connect();
|
||||
while (true) {
|
||||
result = event_handler.wait_event_for(std::chrono::milliseconds(60000));
|
@ -22,9 +22,8 @@ ESP_EVENT_DECLARE_BASE(MQTT_EVENTS);
|
||||
/**
|
||||
* Thin wrapper around C mqtt_client
|
||||
*/
|
||||
struct MqttClientHandle
|
||||
{
|
||||
explicit MqttClientHandle(const std::string & uri)
|
||||
struct MqttClientHandle {
|
||||
explicit MqttClientHandle(const std::string &uri)
|
||||
{
|
||||
esp_mqtt_client_config_t config = { };
|
||||
config.uri = uri.c_str();
|
||||
@ -49,9 +48,9 @@ struct MqttClientHandle
|
||||
/**
|
||||
* @brief Definitions of MqttClient methods
|
||||
*/
|
||||
MqttClient::MqttClient(const std::string & uri):
|
||||
MqttClient::MqttClient(const std::string &uri):
|
||||
h(std::unique_ptr<MqttClientHandle>(new MqttClientHandle(uri)))
|
||||
{}
|
||||
{}
|
||||
|
||||
void MqttClient::connect()
|
||||
{
|
||||
@ -61,11 +60,11 @@ void MqttClient::connect()
|
||||
idf::event::ESPEvent MqttClient::get_event(MqttClient::Event ev)
|
||||
{
|
||||
switch (ev) {
|
||||
case Event::CONNECT: {
|
||||
return { MQTT_EVENTS, ESPEventID(MQTT_EVENT_CONNECTED) };
|
||||
}
|
||||
case Event::DATA:
|
||||
return { MQTT_EVENTS, ESPEventID(MQTT_EVENT_DATA) };
|
||||
case Event::CONNECT: {
|
||||
return { MQTT_EVENTS, ESPEventID(MQTT_EVENT_CONNECTED) };
|
||||
}
|
||||
case Event::DATA:
|
||||
return { MQTT_EVENTS, ESPEventID(MQTT_EVENT_DATA) };
|
||||
}
|
||||
return { };
|
||||
}
|
||||
@ -80,7 +79,7 @@ int MqttClient::subscribe(const std::string &topic, int qos)
|
||||
return esp_mqtt_client_subscribe(h->client, topic.c_str(), qos);
|
||||
}
|
||||
|
||||
std::string MqttClient::get_topic(void * event_data)
|
||||
std::string MqttClient::get_topic(void *event_data)
|
||||
{
|
||||
auto event = (esp_mqtt_event_handle_t)event_data;
|
||||
if (event == nullptr || event->client != h->client)
|
||||
@ -89,7 +88,7 @@ std::string MqttClient::get_topic(void * event_data)
|
||||
return std::string(event->topic, event->topic_len);
|
||||
}
|
||||
|
||||
std::string MqttClient::get_data(void * event_data)
|
||||
std::string MqttClient::get_data(void *event_data)
|
||||
{
|
||||
auto event = (esp_mqtt_event_handle_t)event_data;
|
||||
if (event == nullptr || event->client != h->client)
|
||||
|
@ -6,8 +6,7 @@
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#ifndef _SIMPLE_MQTT_CLIENT_H_
|
||||
#define _SIMPLE_MQTT_CLIENT_H_
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
@ -25,7 +24,7 @@ public:
|
||||
DATA,
|
||||
};
|
||||
|
||||
explicit MqttClient(const std::string & uri);
|
||||
explicit MqttClient(const std::string &uri);
|
||||
~MqttClient();
|
||||
|
||||
/**
|
||||
@ -40,7 +39,7 @@ public:
|
||||
* @param qos QoS (0 by default)
|
||||
* @return message id
|
||||
*/
|
||||
int publish(const std::string & topic, const std::string & data, int qos = 0);
|
||||
int publish(const std::string &topic, const std::string &data, int qos = 0);
|
||||
|
||||
/**
|
||||
* @brief Subscribe to a topic
|
||||
@ -48,7 +47,7 @@ public:
|
||||
* @param qos QoS (0 by default)
|
||||
* @return message id
|
||||
*/
|
||||
int subscribe(const std::string & topic, int qos = 0);
|
||||
int subscribe(const std::string &topic, int qos = 0);
|
||||
|
||||
/**
|
||||
* @brief Get topic from event data
|
||||
@ -72,6 +71,3 @@ public:
|
||||
private:
|
||||
std::unique_ptr<MqttClientHandle> h;
|
||||
};
|
||||
|
||||
|
||||
#endif //_SIMPLE_MQTT_CLIENT_H_
|
||||
|
@ -6,5 +6,7 @@ CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096
|
||||
CONFIG_LWIP_PPP_ENABLE_IPV6=n
|
||||
CONFIG_COMPILER_CXX_EXCEPTIONS=y
|
||||
CONFIG_PARTITION_TABLE_TWO_OTA=y
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF=y
|
||||
CONFIG_NEWLIB_STDIN_LINE_ENDING_LF=y
|
||||
CONFIG_NEWLIB_STDIN_LINE_ENDING_LF=y
|
||||
CONFIG_MAIN_TASK_STACK_SIZE=8192
|
@ -1,5 +1,6 @@
|
||||
version: "0.1.5"
|
||||
version: "0.1.16"
|
||||
description: esp modem
|
||||
url: https://github.com/espressif/esp-protocols/tree/master/components/esp_modem
|
||||
dependencies:
|
||||
# Required IDF version
|
||||
idf:
|
||||
|
@ -12,8 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_MODEM_API_HPP_
|
||||
#define _ESP_MODEM_API_HPP_
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include "cxx_include/esp_modem_dce.hpp"
|
||||
@ -74,7 +73,7 @@ std::shared_ptr<DTE> create_vfs_dte(const dte_config *config);
|
||||
/**
|
||||
* @brief Create DCE based on SIM7600 module
|
||||
* @param config DCE configuration
|
||||
* @param DTE reference to the communicating DTE
|
||||
* @param dte reference to the communicating DTE
|
||||
* @param netif reference to the network interface
|
||||
*
|
||||
* @return unique ptr to the created DCE on success
|
||||
@ -83,6 +82,17 @@ std::shared_ptr<DTE> create_vfs_dte(const dte_config *config);
|
||||
*/
|
||||
std::unique_ptr<DCE> create_SIM7600_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif);
|
||||
|
||||
/**
|
||||
* @brief Create DCE based on SIM7070 module
|
||||
*/
|
||||
std::unique_ptr<DCE> create_SIM7070_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif);
|
||||
|
||||
/**
|
||||
* @brief Create DCE based on SIM7000 module
|
||||
*/
|
||||
std::unique_ptr<DCE> create_SIM7000_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create DCE based on SIM800 module
|
||||
*/
|
||||
@ -103,5 +113,3 @@ std::unique_ptr<DCE> create_generic_dce(const dce_config *config, std::shared_pt
|
||||
*/
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _ESP_MODEM_API_HPP_
|
@ -12,14 +12,13 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_MODEM_CMUX_HPP_
|
||||
#define _ESP_MODEM_CMUX_HPP_
|
||||
#pragma once
|
||||
|
||||
#include "esp_modem_terminal.hpp"
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
constexpr size_t max_terms = 2;
|
||||
constexpr size_t MAX_TERMINALS_NUM = 2;
|
||||
/**
|
||||
* @defgroup ESP_MODEM_CMUX ESP_MODEM CMUX class
|
||||
* @brief Definition of CMUX terminal
|
||||
@ -51,38 +50,79 @@ class CMuxInstance;
|
||||
|
||||
/**
|
||||
* @brief CMux class which consumes the original terminal and creates multiple virtual terminals from it.
|
||||
* This class is not usable applicable as a DTE terminal
|
||||
* This class itself is not usable as a DTE terminal, only via its instances defined in `CMuxInstance`
|
||||
*/
|
||||
class CMux {
|
||||
public:
|
||||
explicit CMux(std::unique_ptr<Terminal> t, std::unique_ptr<uint8_t[]> b, size_t buff_size):
|
||||
term(std::move(t)), buffer_size(buff_size), buffer(std::move(b)), payload_start(nullptr), total_payload_size(0) {}
|
||||
term(std::move(t)), payload_start(nullptr), total_payload_size(0), buffer_size(buff_size), buffer(std::move(b)) {}
|
||||
~CMux() = default;
|
||||
|
||||
/**
|
||||
* @brief Initializes CMux protocol
|
||||
* @return true on success
|
||||
*/
|
||||
[[nodiscard]] bool init();
|
||||
|
||||
/**
|
||||
* @brief Sets read callback for the appropriate terminal
|
||||
* @param inst Index of the terminal
|
||||
* @param f function pointer
|
||||
*/
|
||||
void set_read_cb(int inst, std::function<bool(uint8_t *data, size_t len)> f);
|
||||
|
||||
/**
|
||||
* @brief Writes to the appropriate terminal
|
||||
* @param i Index of the terminal
|
||||
* @param data Data to write
|
||||
* @param len Data length to write
|
||||
* @return The actual written length
|
||||
*/
|
||||
int write(int i, uint8_t *data, size_t len);
|
||||
|
||||
private:
|
||||
std::function<bool(uint8_t *data, size_t len)> read_cb[max_terms];
|
||||
void data_available(uint8_t *data, size_t len);
|
||||
void send_sabm(size_t i);
|
||||
std::unique_ptr<Terminal> term;
|
||||
cmux_state state;
|
||||
static uint8_t fcs_crc(const uint8_t frame[6]); /*!< Utility to calculate FCS CRC */
|
||||
void data_available(uint8_t *data, size_t len); /*!< Called when valid data available */
|
||||
void send_sabm(size_t i); /*!< Sending initial SABM */
|
||||
bool on_cmux(uint8_t *data, size_t len); /*!< Called from terminal layer when raw CMUX protocol data available */
|
||||
|
||||
struct CMuxFrame; /*!< Forward declare the Frame struct, used in protocol decoders */
|
||||
/**
|
||||
* These methods serve different states of the CMUX protocols
|
||||
* @param frame Currently available cmux frame (basically data, size, methods)
|
||||
* @return - true if the state processed successfully
|
||||
* - false if more data needed to process the current state
|
||||
*/
|
||||
bool on_recovery(CMuxFrame &frame);
|
||||
bool on_init(CMuxFrame &frame);
|
||||
bool on_header(CMuxFrame &frame);
|
||||
bool on_payload(CMuxFrame &frame);
|
||||
bool on_footer(CMuxFrame &frame);
|
||||
|
||||
std::function<bool(uint8_t *data, size_t len)> read_cb[MAX_TERMINALS_NUM]; /*!< Function pointers to read callbacks */
|
||||
std::unique_ptr<Terminal> term; /*!< The original terminal */
|
||||
cmux_state state; /*!< CMux protocol state */
|
||||
|
||||
/**
|
||||
* CMux control fields and offsets
|
||||
*/
|
||||
uint8_t dlci;
|
||||
uint8_t type;
|
||||
size_t payload_len;
|
||||
uint8_t frame_header[6];
|
||||
size_t frame_header_offset;
|
||||
size_t buffer_size;
|
||||
std::unique_ptr<uint8_t[]> buffer;
|
||||
bool on_cmux(uint8_t *data, size_t len);
|
||||
static uint8_t fcs_crc(const uint8_t frame[6]);
|
||||
Lock lock;
|
||||
int instance;
|
||||
int sabm_ack;
|
||||
uint8_t *payload_start;
|
||||
size_t total_payload_size;
|
||||
int instance;
|
||||
int sabm_ack;
|
||||
|
||||
/**
|
||||
* Processing buffer size and pointer
|
||||
*/
|
||||
size_t buffer_size;
|
||||
std::unique_ptr<uint8_t[]> buffer;
|
||||
|
||||
Lock lock;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -93,14 +133,23 @@ class CMuxInstance: public Terminal {
|
||||
public:
|
||||
explicit CMuxInstance(std::shared_ptr<CMux> parent, int i): cmux(std::move(parent)), instance(i) {}
|
||||
|
||||
int write(uint8_t *data, size_t len) override { return cmux->write(instance, data, len); }
|
||||
void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f) override { return cmux->set_read_cb(instance, std::move(f)); }
|
||||
int read(uint8_t *data, size_t len) override { return 0; }
|
||||
int write(uint8_t *data, size_t len) override
|
||||
{
|
||||
return cmux->write(instance, data, len);
|
||||
}
|
||||
void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f) override
|
||||
{
|
||||
return cmux->set_read_cb(instance, std::move(f));
|
||||
}
|
||||
int read(uint8_t *data, size_t len) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void start() override { }
|
||||
void stop() override { }
|
||||
private:
|
||||
std::shared_ptr<CMux> cmux;
|
||||
int instance;
|
||||
size_t instance;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -108,5 +157,3 @@ private:
|
||||
*/
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _ESP_MODEM_CMUX_HPP_
|
||||
|
@ -12,8 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_MODEM_COMMAND_LIBRARY_HPP_
|
||||
#define _ESP_MODEM_COMMAND_LIBRARY_HPP_
|
||||
#pragma once
|
||||
|
||||
#include "esp_modem_dte.hpp"
|
||||
#include "esp_modem_dce_module.hpp"
|
||||
@ -37,17 +36,20 @@ namespace dce_commands {
|
||||
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, num, ...) \
|
||||
return_type name(CommandableIf *t, ## __VA_ARGS__);
|
||||
|
||||
DECLARE_ALL_COMMAND_APIS(declare name(Commandable *p, ...);)
|
||||
DECLARE_ALL_COMMAND_APIS(declare name(Commandable *p, ...);)
|
||||
|
||||
#undef ESP_MODEM_DECLARE_DCE_COMMAND
|
||||
|
||||
/**
|
||||
* @brief Following commands that are different for some specific modules
|
||||
*/
|
||||
command_result get_battery_status_sim7xxx(CommandableIf* t, int& voltage, int &bcs, int &bcl);
|
||||
command_result power_down_sim7xxx(CommandableIf* t);
|
||||
command_result power_down_sim8xx(CommandableIf* t);
|
||||
command_result set_data_mode_sim8xx(CommandableIf* t);
|
||||
command_result get_battery_status_sim7xxx(CommandableIf *t, int &voltage, int &bcs, int &bcl);
|
||||
command_result set_gnss_power_mode_sim76xx(CommandableIf *t, int mode);
|
||||
command_result power_down_sim76xx(CommandableIf *t);
|
||||
command_result power_down_sim70xx(CommandableIf *t);
|
||||
command_result set_network_bands_sim76xx(CommandableIf *t, const std::string& mode, const int* bands, int size);
|
||||
command_result power_down_sim8xx(CommandableIf *t);
|
||||
command_result set_data_mode_sim8xx(CommandableIf *t);
|
||||
|
||||
/**
|
||||
* @}
|
||||
@ -55,5 +57,3 @@ command_result set_data_mode_sim8xx(CommandableIf* t);
|
||||
|
||||
} // dce_commands
|
||||
} // esp_modem
|
||||
|
||||
#endif //_ESP_MODEM_COMMAND_LIBRARY_HPP_
|
||||
|
@ -12,8 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_MODEM_DCE_HPP_
|
||||
#define _ESP_MODEM_DCE_HPP_
|
||||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
#include "cxx_include/esp_modem_netif.hpp"
|
||||
@ -35,7 +34,7 @@ namespace esp_modem {
|
||||
*/
|
||||
class DCE_Mode {
|
||||
public:
|
||||
DCE_Mode(): mode(modem_mode::COMMAND_MODE) {}
|
||||
DCE_Mode(): mode(modem_mode::UNDEF) {}
|
||||
~DCE_Mode() = default;
|
||||
bool set(DTE *dte, ModuleIf *module, Netif &netif, modem_mode m);
|
||||
modem_mode get();
|
||||
@ -53,8 +52,8 @@ template<class SpecificModule>
|
||||
class DCE_T {
|
||||
static_assert(std::is_base_of<ModuleIf, SpecificModule>::value, "DCE must be instantiated with Module class only");
|
||||
public:
|
||||
explicit DCE_T(const std::shared_ptr<DTE>& dte, std::shared_ptr<SpecificModule> dev, esp_netif_t * netif):
|
||||
dte(dte), device(std::move(dev)), netif(dte, netif)
|
||||
explicit DCE_T(const std::shared_ptr<DTE> &dte, std::shared_ptr<SpecificModule> dev, esp_netif_t *netif):
|
||||
dte(dte), device(std::move(dev)), netif(dte, netif)
|
||||
{ }
|
||||
|
||||
~DCE_T() = default;
|
||||
@ -62,20 +61,35 @@ public:
|
||||
/**
|
||||
* @brief Set data mode!
|
||||
*/
|
||||
void set_data() { set_mode(modem_mode::DATA_MODE); }
|
||||
void set_data()
|
||||
{
|
||||
set_mode(modem_mode::DATA_MODE);
|
||||
}
|
||||
|
||||
void exit_data() { set_mode(modem_mode::COMMAND_MODE); }
|
||||
void exit_data()
|
||||
{
|
||||
set_mode(modem_mode::COMMAND_MODE);
|
||||
}
|
||||
|
||||
void set_cmux() { set_mode(modem_mode::CMUX_MODE); }
|
||||
void set_cmux()
|
||||
{
|
||||
set_mode(modem_mode::CMUX_MODE);
|
||||
}
|
||||
|
||||
SpecificModule* get_module() { return device.get(); }
|
||||
SpecificModule *get_module()
|
||||
{
|
||||
return device.get();
|
||||
}
|
||||
|
||||
command_result command(const std::string& command, got_line_cb got_line, uint32_t time_ms)
|
||||
command_result command(const std::string &command, got_line_cb got_line, uint32_t time_ms)
|
||||
{
|
||||
return dte->command(command, std::move(got_line), time_ms);
|
||||
}
|
||||
|
||||
bool set_mode(modem_mode m) { return mode.set(dte.get(), device.get(), netif, m); }
|
||||
bool set_mode(modem_mode m)
|
||||
{
|
||||
return mode.set(dte.get(), device.get(), netif, m);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::shared_ptr<DTE> dte;
|
||||
@ -86,9 +100,9 @@ protected:
|
||||
|
||||
/**
|
||||
* @brief Common abstraction of the modem DCE, specialized by the GenericModule which is a parent class for the supported
|
||||
* defices and most common modems, as well.
|
||||
* devices and most common modems, as well.
|
||||
*/
|
||||
class DCE: public DCE_T<GenericModule> {
|
||||
class DCE : public DCE_T<GenericModule> {
|
||||
public:
|
||||
|
||||
using DCE_T<GenericModule>::DCE_T;
|
||||
@ -99,7 +113,10 @@ public:
|
||||
return device->name(std::forward<Agrs>(args)...); \
|
||||
}
|
||||
|
||||
DECLARE_ALL_COMMAND_APIS(forwards name(...) { device->name(...); } )
|
||||
DECLARE_ALL_COMMAND_APIS(forwards name(...)
|
||||
{
|
||||
device->name(...);
|
||||
} )
|
||||
|
||||
#undef ESP_MODEM_DECLARE_DCE_COMMAND
|
||||
|
||||
@ -110,5 +127,3 @@ public:
|
||||
*/
|
||||
|
||||
} // esp_modem
|
||||
|
||||
#endif // _ESP_MODEM_DCE_HPP_
|
@ -12,8 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_MODEM_DCE_FACTORY_HPP_
|
||||
#define _ESP_MODEM_DCE_FACTORY_HPP_
|
||||
#pragma once
|
||||
#include "esp_log.h"
|
||||
|
||||
/**
|
||||
* @defgroup ESP_MODEM_DCE_FACTORY
|
||||
@ -31,85 +31,94 @@ using config = ::esp_modem_dce_config;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Helper class for creating a uder define pointer in a specific way, either as a plain pointer, shared_ptr or unique_ptr
|
||||
* @brief Helper class for creating a user define pointer in a specific way, either as a plain pointer, shared_ptr or unique_ptr
|
||||
*/
|
||||
class FactoryHelper {
|
||||
public:
|
||||
static std::unique_ptr<PdpContext> create_pdp_context(std::string &apn);
|
||||
|
||||
template <typename T, typename Ptr, typename ...Args>
|
||||
static auto make(Args&&... args) -> typename std::enable_if<std::is_same<Ptr, T*>::value, T*>::type
|
||||
template <typename T, typename T_Ptr, typename ...Args>
|
||||
static auto make(Args &&... args) -> typename std::enable_if<std::is_same<T_Ptr, T *>::value, T *>::type
|
||||
{
|
||||
return new T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename Ptr, typename ...Args>
|
||||
static auto make(Args&&... args) -> typename std::enable_if<std::is_same<Ptr, std::shared_ptr<T>>::value, std::shared_ptr<T>>::type
|
||||
template <typename T, typename T_Ptr, typename ...Args>
|
||||
static auto make(Args &&... args) -> typename std::enable_if<std::is_same<T_Ptr, std::shared_ptr<T>>::value, std::shared_ptr<T>>::type
|
||||
{
|
||||
return std::make_shared<T>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename Ptr = std::unique_ptr<T>, typename ...Args>
|
||||
static auto make(Args&&... args) -> typename std::enable_if<std::is_same<Ptr, std::unique_ptr<T>>::value, std::unique_ptr<T>>::type
|
||||
template <typename T, typename T_Ptr = std::unique_ptr<T>, typename ...Args>
|
||||
static auto make(Args && ... args) -> typename std::enable_if<std::is_same<T_Ptr, std::unique_ptr<T>>::value, std::unique_ptr<T>>::type
|
||||
{
|
||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Builder class for building a DCE_T<Module> in a specific way, either form a Module object or by default from the DTE and netif
|
||||
* @brief Creator class for building a DCE_T<Module> in a specific way, either from a Module object or by default from the DTE and netif
|
||||
*
|
||||
* @throws
|
||||
* - esp_modem::esp_err_exception on invalid arguments
|
||||
* - std::bad_alloc if failed to allocate
|
||||
*/
|
||||
template<typename Module>
|
||||
class Builder {
|
||||
static_assert(std::is_base_of<ModuleIf, Module>::value, "Builder must be used only for Module classes");
|
||||
template<typename T_Module>
|
||||
class Creator {
|
||||
static_assert(std::is_base_of<ModuleIf, T_Module>::value, "Builder must be used only for Module classes");
|
||||
public:
|
||||
Builder(std::shared_ptr<DTE> x, esp_netif_t* esp_netif): dte(std::move(x)), device(nullptr), netif(esp_netif)
|
||||
Creator(std::shared_ptr<DTE> dte, esp_netif_t *esp_netif): dte(std::move(dte)), device(nullptr), netif(esp_netif)
|
||||
{
|
||||
throw_if_false(netif != nullptr, "Null netif");
|
||||
}
|
||||
|
||||
Builder(std::shared_ptr<DTE> dte, esp_netif_t* esp_netif, std::shared_ptr<Module> dev): dte(std::move(dte)), device(std::move(dev)), netif(esp_netif)
|
||||
Creator(std::shared_ptr<DTE> dte, esp_netif_t *esp_netif, std::shared_ptr<T_Module> dev): dte(std::move(dte)), device(std::move(dev)), netif(esp_netif)
|
||||
{
|
||||
throw_if_false(netif != nullptr, "Null netif");
|
||||
}
|
||||
|
||||
~Builder()
|
||||
~Creator()
|
||||
{
|
||||
throw_if_false(device == nullptr, "module was captured or created but never used");
|
||||
if (device != nullptr) {
|
||||
ESP_LOGE("dce_factory::~Creator", "module was captured or created but never used");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Ptr>
|
||||
auto create_module(const esp_modem_dce_config *config) -> Ptr
|
||||
template<typename T_Ptr>
|
||||
auto create_module(const esp_modem_dce_config *config) -> T_Ptr
|
||||
{
|
||||
return FactoryHelper::make<Module, Ptr>(dte, config);
|
||||
return FactoryHelper::make<T_Module, T_Ptr>(dte, config);
|
||||
}
|
||||
|
||||
template<typename DceT, typename Ptr>
|
||||
auto create(const esp_modem_dce_config *config) -> Ptr
|
||||
template<typename T_Dce, typename T_Ptr>
|
||||
auto create(const esp_modem_dce_config *config) -> T_Ptr
|
||||
{
|
||||
if (dte == nullptr)
|
||||
if (dte == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (device == nullptr) {
|
||||
device = create_module<decltype(device)>(config);
|
||||
if (device == nullptr)
|
||||
if (device == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return FactoryHelper::make<DceT, Ptr>(std::move(dte), std::move(device), netif);
|
||||
return FactoryHelper::make<T_Dce, T_Ptr>(std::move(dte), std::move(device), netif);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<DTE> dte;
|
||||
std::shared_ptr<Module> device;
|
||||
std::shared_ptr<T_Module> device;
|
||||
esp_netif_t *netif;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Specific modem choice when creating by the Factory
|
||||
*/
|
||||
enum class Modem {
|
||||
enum class ModemType {
|
||||
GenericModule, /*!< Default generic module with the most common commands */
|
||||
SIM7600, /*!< Derived from the GenericModule, specifics applied to SIM7600 model */
|
||||
SIM7070, /*!< Derived from the GenericModule, specifics applied to SIM7070 model */
|
||||
SIM7000, /*!< Derived from the GenericModule, specifics applied to SIM7000 model */
|
||||
BG96, /*!< Derived from the GenericModule, specifics applied to BG69 model */
|
||||
SIM800, /*!< Derived from the GenericModule with specifics applied to SIM800 model */
|
||||
};
|
||||
@ -120,7 +129,7 @@ enum class Modem {
|
||||
*/
|
||||
class Factory {
|
||||
public:
|
||||
explicit Factory(Modem modem): m(modem) {}
|
||||
explicit Factory(ModemType modem): m(modem) {}
|
||||
|
||||
/**
|
||||
* @brief Create a default unique_ptr DCE in a specific way (from the module)
|
||||
@ -130,10 +139,10 @@ public:
|
||||
* @param args typically a DTE object and a netif handle for PPP network
|
||||
* @return unique_ptr DCE of the created DCE on success
|
||||
*/
|
||||
template <typename Module, typename ...Args>
|
||||
static std::unique_ptr<DCE> build_unique(const config *cfg, Args&&... args)
|
||||
template <typename T_Module, typename ...Args>
|
||||
static std::unique_ptr<DCE> build_unique(const config *cfg, Args &&... args)
|
||||
{
|
||||
return build_generic_DCE<Module, DCE, std::unique_ptr<DCE>>(cfg, std::forward<Args>(args)...);
|
||||
return build_generic_DCE<T_Module, DCE, std::unique_ptr<DCE>>(cfg, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,34 +153,38 @@ public:
|
||||
* @param args typically a DTE object and a netif handle for PPP network
|
||||
* @return DCE pointer the created DCE on success
|
||||
*/
|
||||
template <typename Module, typename ...Args>
|
||||
static DCE* build(const config *cfg, Args&&... args)
|
||||
template <typename T_Module, typename ...Args>
|
||||
static DCE *build(const config *cfg, Args &&... args)
|
||||
{
|
||||
return build_generic_DCE<Module, DCE>(cfg, std::forward<Args>(args)...);
|
||||
return build_generic_DCE<T_Module, DCE>(cfg, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
template <typename Module, typename ...Args>
|
||||
static std::shared_ptr<Module> build_shared_module(const config *cfg, Args&&... args)
|
||||
template <typename T_Module, typename ...Args>
|
||||
static std::shared_ptr<T_Module> build_shared_module(const config *cfg, Args &&... args)
|
||||
{
|
||||
return build_module_T<Module>(cfg, std::forward<Args>(args)...);
|
||||
return build_module_T<T_Module>(cfg, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
template <typename ...Args>
|
||||
std::shared_ptr<GenericModule> build_shared_module(const config *cfg, Args&&... args)
|
||||
std::shared_ptr<GenericModule> build_shared_module(const config *cfg, Args &&... args)
|
||||
{
|
||||
switch (m) {
|
||||
case Modem::SIM800:
|
||||
return build_shared_module<SIM800>(cfg, std::forward<Args>(args)...);
|
||||
case Modem::SIM7600:
|
||||
return build_shared_module<SIM7600>(cfg, std::forward<Args>(args)...);
|
||||
case Modem::BG96:
|
||||
return build_shared_module<BG96>(cfg, std::forward<Args>(args)...);
|
||||
case Modem::GenericModule:
|
||||
return build_shared_module<GenericModule>(cfg, std::forward<Args>(args)...);
|
||||
default:
|
||||
break;
|
||||
case ModemType::SIM800:
|
||||
return build_shared_module<SIM800>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::SIM7600:
|
||||
return build_shared_module<SIM7600>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::SIM7070:
|
||||
return build_shared_module<SIM7070>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::SIM7000:
|
||||
return build_shared_module<SIM7000>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::BG96:
|
||||
return build_shared_module<BG96>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::GenericModule:
|
||||
return build_shared_module<GenericModule>(cfg, std::forward<Args>(args)...);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -184,58 +197,66 @@ public:
|
||||
* @return unique_ptr DCE of the created DCE on success
|
||||
*/
|
||||
template <typename ...Args>
|
||||
std::unique_ptr<DCE> build_unique(const config *cfg, Args&&... args)
|
||||
std::unique_ptr<DCE> build_unique(const config *cfg, Args &&... args)
|
||||
{
|
||||
switch (m) {
|
||||
case Modem::SIM800:
|
||||
return build_unique<SIM800>(cfg, std::forward<Args>(args)...);
|
||||
case Modem::SIM7600:
|
||||
return build_unique<SIM7600>(cfg, std::forward<Args>(args)...);
|
||||
case Modem::BG96:
|
||||
return build_unique<BG96>(cfg, std::forward<Args>(args)...);
|
||||
case Modem::GenericModule:
|
||||
return build_unique<GenericModule>(cfg, std::forward<Args>(args)...);
|
||||
default:
|
||||
break;
|
||||
case ModemType::SIM800:
|
||||
return build_unique<SIM800>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::SIM7600:
|
||||
return build_unique<SIM7600>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::SIM7070:
|
||||
return build_unique<SIM7070>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::SIM7000:
|
||||
return build_unique<SIM7000>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::BG96:
|
||||
return build_unique<BG96>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::GenericModule:
|
||||
return build_unique<GenericModule>(cfg, std::forward<Args>(args)...);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
DCE* build(const config *cfg, Args&&... args)
|
||||
DCE *build(const config *cfg, Args &&... args)
|
||||
{
|
||||
switch (m) {
|
||||
case Modem::SIM800:
|
||||
return build<SIM800>(cfg, std::forward<Args>(args)...);
|
||||
case Modem::SIM7600:
|
||||
return build<SIM7600>(cfg, std::forward<Args>(args)...);
|
||||
case Modem::BG96:
|
||||
return build<BG96>(cfg, std::forward<Args>(args)...);
|
||||
case Modem::GenericModule:
|
||||
return build<GenericModule>(cfg, std::forward<Args>(args)...);
|
||||
default:
|
||||
break;
|
||||
case ModemType::SIM800:
|
||||
return build<SIM800>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::SIM7600:
|
||||
return build<SIM7600>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::SIM7070:
|
||||
return build<SIM7070>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::SIM7000:
|
||||
return build<SIM7000>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::BG96:
|
||||
return build<BG96>(cfg, std::forward<Args>(args)...);
|
||||
case ModemType::GenericModule:
|
||||
return build<GenericModule>(cfg, std::forward<Args>(args)...);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
Modem m;
|
||||
ModemType m;
|
||||
|
||||
protected:
|
||||
template <typename Module, typename Ptr = std::shared_ptr<Module>, typename ...Args>
|
||||
static Ptr build_module_T(const config *cfg, Args&&... args)
|
||||
template <typename T_Module, typename Ptr = std::shared_ptr<T_Module>, typename ...Args>
|
||||
static Ptr build_module_T(const config *cfg, Args && ... args)
|
||||
{
|
||||
Builder<Module> b(std::forward<Args>(args)...);
|
||||
return b.template create_module<Ptr>(cfg);
|
||||
Creator<T_Module> creator(std::forward<Args>(args)...);
|
||||
return creator.template create_module<Ptr>(cfg);
|
||||
}
|
||||
|
||||
|
||||
template <typename Module, typename Dce = DCE_T<Module>, typename DcePtr = Dce*, typename ...Args>
|
||||
static DcePtr build_generic_DCE(const config *cfg, Args&&... args)
|
||||
template <typename T_Module, typename T_Dce = DCE_T<T_Module>, typename T_DcePtr = T_Dce *, typename ...Args>
|
||||
static auto build_generic_DCE(const config *cfg, Args && ... args) -> T_DcePtr
|
||||
{
|
||||
Builder<Module> b(std::forward<Args>(args)...);
|
||||
return b.template create<Dce, DcePtr>(cfg);
|
||||
Creator<T_Module> creator(std::forward<Args>(args)...);
|
||||
return creator.template create<T_Dce, T_DcePtr>(cfg);
|
||||
}
|
||||
};
|
||||
|
||||
@ -244,6 +265,3 @@ protected:
|
||||
*/
|
||||
|
||||
} // namespace esp_modem::dce_factory
|
||||
|
||||
|
||||
#endif // _ESP_MODEM_DCE_FACTORY_HPP_
|
||||
|
@ -12,8 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_MODEM_DCE_MODULE_
|
||||
#define _ESP_MODEM_DCE_MODULE_
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
@ -48,8 +47,8 @@ public:
|
||||
* The configuration could be either the dce-config struct or just a pdp context
|
||||
*/
|
||||
explicit GenericModule(std::shared_ptr<DTE> dte, std::unique_ptr<PdpContext> pdp):
|
||||
dte(std::move(dte)), pdp(std::move(pdp)) {}
|
||||
explicit GenericModule(std::shared_ptr<DTE> dte, const esp_modem_dce_config* config);
|
||||
dte(std::move(dte)), pdp(std::move(pdp)) {}
|
||||
explicit GenericModule(std::shared_ptr<DTE> dte, const esp_modem_dce_config *config);
|
||||
|
||||
/**
|
||||
* @brief This is a mandatory method for ModuleIf class, which sets up the device
|
||||
@ -59,10 +58,12 @@ public:
|
||||
*/
|
||||
bool setup_data_mode() override
|
||||
{
|
||||
if (set_echo(false) != command_result::OK)
|
||||
if (set_echo(false) != command_result::OK) {
|
||||
return false;
|
||||
if (set_pdp_context(*pdp) != command_result::OK)
|
||||
}
|
||||
if (set_pdp_context(*pdp) != command_result::OK) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -73,10 +74,12 @@ public:
|
||||
bool set_mode(modem_mode mode) override
|
||||
{
|
||||
if (mode == modem_mode::DATA_MODE) {
|
||||
if (set_data_mode() != command_result::OK)
|
||||
if (set_data_mode() != command_result::OK) {
|
||||
return resume_data_mode() == command_result::OK;
|
||||
}
|
||||
return true;
|
||||
} else if (mode == modem_mode::COMMAND_MODE) {
|
||||
Task::Delay(1000); // Mandatory 1s pause
|
||||
return set_command_mode() == command_result::OK;
|
||||
} else if (mode == modem_mode::CMUX_MODE) {
|
||||
return set_cmux() == command_result::OK;
|
||||
@ -116,8 +119,27 @@ protected:
|
||||
class SIM7600: public GenericModule {
|
||||
using GenericModule::GenericModule;
|
||||
public:
|
||||
command_result get_module_name(std::string& name) override;
|
||||
command_result get_battery_status(int& voltage, int &bcs, int &bcl) override;
|
||||
command_result get_battery_status(int &voltage, int &bcs, int &bcl) override;
|
||||
command_result power_down() override;
|
||||
command_result set_gnss_power_mode(int mode) override;
|
||||
command_result set_network_bands(const std::string& mode, const int* bands, int size) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Specific definition of the SIM7070 module
|
||||
*/
|
||||
class SIM7070: public GenericModule {
|
||||
using GenericModule::GenericModule;
|
||||
public:
|
||||
command_result power_down() override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Specific definition of the SIM7000 module
|
||||
*/
|
||||
class SIM7000: public GenericModule {
|
||||
using GenericModule::GenericModule;
|
||||
public:
|
||||
command_result power_down() override;
|
||||
};
|
||||
|
||||
@ -127,7 +149,6 @@ public:
|
||||
class SIM800: public GenericModule {
|
||||
using GenericModule::GenericModule;
|
||||
public:
|
||||
command_result get_module_name(std::string& name) override;
|
||||
command_result power_down() override;
|
||||
command_result set_data_mode() override;
|
||||
};
|
||||
@ -137,8 +158,6 @@ public:
|
||||
*/
|
||||
class BG96: public GenericModule {
|
||||
using GenericModule::GenericModule;
|
||||
public:
|
||||
command_result get_module_name(std::string& name) override;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -146,5 +165,3 @@ public:
|
||||
*/
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _ESP_MODEM_DCE_MODULE_
|
@ -12,8 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_MODEM_DTE_HPP_
|
||||
#define _ESP_MODEM_DTE_HPP_
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <cstddef>
|
||||
@ -117,5 +116,3 @@ private:
|
||||
*/
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _ESP_MODEM_DTE_HPP_
|
||||
|
@ -12,8 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_MODEM_EXCEPTION_HPP_
|
||||
#define _ESP_MODEM_EXCEPTION_HPP_
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "esp_err.h"
|
||||
@ -27,9 +26,13 @@ public:
|
||||
explicit esp_err_exception(esp_err_t err): esp_err(err) {}
|
||||
explicit esp_err_exception(std::string msg): esp_err(ESP_FAIL), message(std::move(msg)) {}
|
||||
explicit esp_err_exception(std::string msg, esp_err_t err): esp_err(err), message(std::move(msg)) {}
|
||||
virtual esp_err_t get_err_t() { return esp_err; }
|
||||
virtual esp_err_t get_err_t()
|
||||
{
|
||||
return esp_err;
|
||||
}
|
||||
~esp_err_exception() noexcept override = default;
|
||||
virtual const char* what() const noexcept {
|
||||
virtual const char *what() const noexcept
|
||||
{
|
||||
return message.c_str();
|
||||
}
|
||||
private:
|
||||
@ -62,5 +65,3 @@ static inline void throw_if_esp_fail(esp_err_t err)
|
||||
}
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif //_ESP_MODEM_EXCEPTION_HPP_
|
||||
|
@ -12,8 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_MODEM_NETIF_HPP
|
||||
#define _ESP_MODEM_NETIF_HPP
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <cstddef>
|
||||
@ -74,7 +73,7 @@ private:
|
||||
|
||||
std::shared_ptr<DTE> ppp_dte;
|
||||
esp_netif_t *netif;
|
||||
struct ppp_netif_driver driver{};
|
||||
struct ppp_netif_driver driver {};
|
||||
SignalGroup signal;
|
||||
static const size_t PPP_STARTED = SignalGroup::bit0;
|
||||
static const size_t PPP_EXIT = SignalGroup::bit1;
|
||||
@ -85,5 +84,3 @@ private:
|
||||
*/
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _ESP_MODEM_NETIF_HPP
|
||||
|
@ -12,8 +12,9 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_MODEM_PRIMITIVES_HPP_
|
||||
#define _ESP_MODEM_PRIMITIVES_HPP_
|
||||
#pragma once
|
||||
|
||||
#include "esp_event.h"
|
||||
#include "esp_modem_exception.hpp"
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_LINUX)
|
||||
@ -21,9 +22,9 @@
|
||||
#include <thread>
|
||||
|
||||
#else
|
||||
#include "freertos/event_groups.h"
|
||||
// forward declarations of FreeRTOS primitives
|
||||
struct QueueDefinition;
|
||||
typedef void * EventGroupHandle_t;
|
||||
#endif
|
||||
|
||||
|
||||
@ -31,10 +32,10 @@ namespace esp_modem {
|
||||
|
||||
// Forward declaration for both linux/FreeRTOS targets
|
||||
//
|
||||
using TaskFunction_t = void (*)(void*);
|
||||
using TaskFunction_t = void (*)(void *);
|
||||
#if !defined(CONFIG_IDF_TARGET_LINUX)
|
||||
struct Lock {
|
||||
using MutexT = QueueDefinition*;
|
||||
using MutexT = QueueHandle_t;
|
||||
explicit Lock();
|
||||
~Lock();
|
||||
void lock();
|
||||
@ -42,8 +43,8 @@ struct Lock {
|
||||
private:
|
||||
MutexT m{};
|
||||
};
|
||||
using TaskT = void*;
|
||||
using SignalT = void*;
|
||||
using TaskT = TaskHandle_t;
|
||||
using SignalT = EventGroupHandle_t;
|
||||
#else
|
||||
using Lock = std::mutex;
|
||||
struct SignalGroupInternal;
|
||||
@ -55,11 +56,17 @@ static constexpr uint32_t portMAX_DELAY = UINT32_MAX;
|
||||
template<class T>
|
||||
class Scoped {
|
||||
public:
|
||||
explicit Scoped(T &l):lock(l) { lock.lock(); }
|
||||
~Scoped() { lock.unlock(); }
|
||||
explicit Scoped(T &l): lock(l)
|
||||
{
|
||||
lock.lock();
|
||||
}
|
||||
~Scoped()
|
||||
{
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
T& lock;
|
||||
T &lock;
|
||||
};
|
||||
|
||||
class Task {
|
||||
@ -69,6 +76,7 @@ public:
|
||||
|
||||
static void Delete();
|
||||
static void Relinquish();
|
||||
static void Delay(uint32_t delay);
|
||||
private:
|
||||
TaskT task_handle;
|
||||
};
|
||||
@ -102,5 +110,3 @@ private:
|
||||
};
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _ESP_MODEM_PRIMITIVES_HPP_
|
||||
|
@ -12,8 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_MODEM_TERMINAL_HPP_
|
||||
#define _ESP_MODEM_TERMINAL_HPP_
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
@ -45,15 +44,21 @@ enum class terminal_error {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Terminal interface. All communication interfaces must comply this interface in order to be used as a DTE
|
||||
* @brief Terminal interface. All communication interfaces must comply to this interface in order to be used as a DTE
|
||||
*/
|
||||
class Terminal {
|
||||
public:
|
||||
virtual ~Terminal() = default;
|
||||
|
||||
void set_error_cb(std::function<void(terminal_error)> f) { on_error = std::move(f); }
|
||||
void set_error_cb(std::function<void(terminal_error)> f)
|
||||
{
|
||||
on_error = std::move(f);
|
||||
}
|
||||
|
||||
virtual void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f) { on_data = std::move(f); }
|
||||
virtual void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f)
|
||||
{
|
||||
on_read = std::move(f);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes data to the terminal
|
||||
@ -76,7 +81,7 @@ public:
|
||||
virtual void stop() = 0;
|
||||
|
||||
protected:
|
||||
std::function<bool(uint8_t *data, size_t len)> on_data;
|
||||
std::function<bool(uint8_t *data, size_t len)> on_read;
|
||||
std::function<void(terminal_error)> on_error;
|
||||
};
|
||||
|
||||
@ -85,5 +90,3 @@ protected:
|
||||
*/
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _ESP_MODEM_TERMINAL_HPP_
|
||||
|
@ -12,8 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_MODEM_TYPES_HPP_
|
||||
#define _ESP_MODEM_TYPES_HPP_
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
@ -68,6 +67,12 @@ struct PdpContext {
|
||||
*/
|
||||
class CommandableIf {
|
||||
public:
|
||||
CommandableIf() = default;
|
||||
CommandableIf(const CommandableIf&) = delete;
|
||||
CommandableIf& operator=(const CommandableIf&) = delete;
|
||||
CommandableIf(CommandableIf&&) = delete;
|
||||
CommandableIf& operator=(CommandableIf&&) = delete;
|
||||
virtual ~CommandableIf() = default;
|
||||
/**
|
||||
* @brief Sends custom AT command
|
||||
* @param command Command to be sent
|
||||
@ -84,8 +89,14 @@ public:
|
||||
*/
|
||||
class ModuleIf {
|
||||
public:
|
||||
ModuleIf() = default;
|
||||
ModuleIf(const ModuleIf&) = delete;
|
||||
ModuleIf& operator=(const ModuleIf&) = delete;
|
||||
ModuleIf(ModuleIf&&) = delete;
|
||||
ModuleIf& operator=(ModuleIf&&) = delete;
|
||||
virtual ~ModuleIf() = default;
|
||||
/**
|
||||
* @brief Sets the data mode up (provides the necessary configuration to connect to the cellular network
|
||||
* @brief Sets the data mode up (provides the necessary configuration to connect to the cellular network)
|
||||
* @return true on success
|
||||
*/
|
||||
virtual bool setup_data_mode() = 0;
|
||||
@ -103,5 +114,3 @@ public:
|
||||
*/
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _ESP_MODEM_TYPES_HPP_
|
||||
|
@ -12,8 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_MODEM_API_H_
|
||||
#define _ESP_MODEM_API_H_
|
||||
#pragma once
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "generate/esp_modem_command_declare.inc"
|
||||
@ -35,6 +34,3 @@ DECLARE_ALL_COMMAND_APIS(declares esp_modem_<API>(esp_modem_t * dce, ...);)
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif // _CLIENT_ESP_MODEM_API_H_
|
||||
|
@ -12,8 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_MODEM_C_API_TYPES_H_
|
||||
#define _ESP_MODEM_C_API_TYPES_H_
|
||||
#pragma once
|
||||
|
||||
#include "esp_modem_config.h"
|
||||
|
||||
@ -49,6 +48,8 @@ typedef enum esp_modem_dce_device
|
||||
{
|
||||
ESP_MODEM_DCE_GENETIC, /**< The most generic device */
|
||||
ESP_MODEM_DCE_SIM7600,
|
||||
ESP_MODEM_DCE_SIM7070,
|
||||
ESP_MODEM_DCE_SIM7000,
|
||||
ESP_MODEM_DCE_BG96,
|
||||
ESP_MODEM_DCE_SIM800,
|
||||
} esp_modem_dce_device_t;
|
||||
@ -98,5 +99,3 @@ esp_err_t esp_modem_set_mode(esp_modem_dce_t * dce, esp_modem_dce_mode_t mode);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //_ESP_MODEM_C_API_TYPES_H_
|
||||
|
@ -12,11 +12,15 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_MODEM_CONFIG_H_
|
||||
#define _ESP_MODEM_CONFIG_H_
|
||||
#pragma once
|
||||
|
||||
#include "driver/uart.h"
|
||||
#include "esp_modem_dce_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup ESP_MODEM_CONFIG
|
||||
* @brief Configuration structures for DTE and DCE
|
||||
@ -56,23 +60,17 @@ struct esp_modem_uart_term_config {
|
||||
int event_queue_size; /*!< UART Event Queue Size, set to 0 if no event queue needed */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Resources used by VFS terminal
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_MODEM_VFS_IS_EXTERN = 0, /*!< External resource: internal VFS terminal takes no action to setup this */
|
||||
ESP_MODEM_VFS_IS_UART, /*!< VFS uses UART: internal VFS initializes UART based on esp_modem_uart_term_config */
|
||||
} esp_modem_vfs_resource_t;
|
||||
|
||||
// Forward declare the resource struct
|
||||
struct esp_modem_vfs_resource;
|
||||
|
||||
/**
|
||||
* @brief VFS configuration structure
|
||||
*
|
||||
*/
|
||||
struct esp_modem_vfs_term_config {
|
||||
const char* dev_name; /*!< VFS device name, e.g. /dev/uart/n */
|
||||
esp_modem_vfs_resource_t resource; /*!< Underlying device which gets initialized during VFS init */
|
||||
int fd; /*!< Already created file descriptor */
|
||||
void (*deleter)(int, struct esp_modem_vfs_resource*); /*!< Custom close function for the fd */
|
||||
struct esp_modem_vfs_resource *resource; /*!< Resource attached to the VFS (need for clenaup) */
|
||||
};
|
||||
|
||||
/**
|
||||
@ -85,9 +83,12 @@ struct esp_modem_vfs_term_config {
|
||||
struct esp_modem_dte_config {
|
||||
size_t dte_buffer_size; /*!< DTE buffer size */
|
||||
uint32_t task_stack_size; /*!< Terminal task stack size */
|
||||
int task_priority; /*!< Terminal task priority */
|
||||
struct esp_modem_uart_term_config uart_config; /*!< Configuration for UART Terminal */
|
||||
struct esp_modem_vfs_term_config vfs_config; /*!< Configuration for VFS Terminal */
|
||||
unsigned task_priority; /*!< Terminal task priority */
|
||||
union {
|
||||
struct esp_modem_uart_term_config uart_config; /*!< Configuration for UART Terminal */
|
||||
struct esp_modem_vfs_term_config vfs_config; /*!< Configuration for VFS Terminal */
|
||||
void *extension_config; /*!< Configuration for app specific Terminal */
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -115,10 +116,6 @@ struct esp_modem_dte_config {
|
||||
.tx_buffer_size = 512, \
|
||||
.event_queue_size = 30, \
|
||||
}, \
|
||||
.vfs_config = { \
|
||||
.dev_name = "/null", \
|
||||
.resource = ESP_MODEM_VFS_IS_EXTERN \
|
||||
}\
|
||||
}
|
||||
|
||||
typedef struct esp_modem_dte_config esp_modem_dte_config_t;
|
||||
@ -127,4 +124,6 @@ typedef struct esp_modem_dte_config esp_modem_dte_config_t;
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif // _ESP_MODEM_CONFIG_H_
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -12,8 +12,11 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_MODEM_DCE_CONFIG_H_
|
||||
#define _ESP_MODEM_DCE_CONFIG_H_
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @addtogroup ESP_MODEM_CONFIG
|
||||
* @{
|
||||
@ -41,5 +44,6 @@ struct esp_modem_dce_config {
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#endif // _ESP_MODEM_DCE_CONFIG_H_
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -28,15 +28,17 @@
|
||||
#define BOOL_IN(param, name) const bool _ARG(param, name)
|
||||
#define BOOL_OUT(param, name) bool& _ARG(param, name)
|
||||
#define INT_OUT(param, name) int& _ARG(param, name)
|
||||
#define INTEGER_LIST_IN(param, name) const int* _ARG(param, name)
|
||||
|
||||
#define STRUCT_OUT(struct_name, x) struct_name& x
|
||||
#define STRUCT_OUT(struct_name, p1) struct_name& p1
|
||||
#else
|
||||
#define STRING_IN(param, name) const char* _ARG(param, name)
|
||||
#define STRING_OUT(param, name) char* _ARG(param, name)
|
||||
#define BOOL_IN(param, name) const bool _ARG(param, name)
|
||||
#define BOOL_OUT(param, name) bool* _ARG(param, name)
|
||||
#define INT_OUT(param, name) int* _ARG(param, name)
|
||||
#define STRUCT_OUT(struct_name, x) struct struct_name* x
|
||||
#define INTEGER_LIST_IN(param, name) const int* _ARG(param, name)
|
||||
#define STRUCT_OUT(struct_name, p1) struct struct_name* p1
|
||||
#endif
|
||||
|
||||
#define DECLARE_ALL_COMMAND_APIS(...) \
|
||||
@ -47,10 +49,10 @@
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(sync, command_result, 0) \
|
||||
/**
|
||||
* @brief Reads the operator name
|
||||
* @param[out] name module name
|
||||
* @param[out] operator name
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_operator_name, command_result, 1, STRING_OUT(x, name)) \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_operator_name, command_result, 1, STRING_OUT(p1, name)) \
|
||||
\
|
||||
/**
|
||||
* @brief Stores current user profile
|
||||
@ -63,28 +65,28 @@ ESP_MODEM_DECLARE_DCE_COMMAND(store_profile, command_result, 0) \
|
||||
* @param[in] pin Pin
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/\
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_pin, command_result, 1, STRING_IN(x, pin)) \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_pin, command_result, 1, STRING_IN(p1, pin)) \
|
||||
\
|
||||
/**
|
||||
* @brief Checks if the SIM needs a PIN
|
||||
* @param[out] pin_ok true if the SIM card doesn't need a PIN to unlock
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(read_pin, command_result, 1, BOOL_OUT(x, pin_ok)) \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(read_pin, command_result, 1, BOOL_OUT(p1, pin_ok)) \
|
||||
\
|
||||
/**
|
||||
* @brief Sets echo mode
|
||||
* @param[in] echo_on true if echo mode on (repeats the commands)
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_echo, command_result, 1, BOOL_IN(x, echo_on)) \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_echo, command_result, 1, BOOL_IN(p1, echo_on)) \
|
||||
\
|
||||
/**
|
||||
* @brief Sets the Txt or Pdu mode for SMS (only txt is supported)
|
||||
* @param[in] txt true if txt mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(sms_txt_mode, command_result, 1, BOOL_IN(x, txt)) \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(sms_txt_mode, command_result, 1, BOOL_IN(p1, txt)) \
|
||||
\
|
||||
/**
|
||||
* @brief Sets the default (GSM) charater set
|
||||
@ -98,7 +100,7 @@ ESP_MODEM_DECLARE_DCE_COMMAND(sms_character_set, command_result, 0) \
|
||||
* @param[in] message Text message to be sent
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(send_sms, command_result, 2, STRING_IN(x, number), STRING_IN(y, message)) \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(send_sms, command_result, 2, STRING_IN(p1, number), STRING_IN(p2, message)) \
|
||||
\
|
||||
/**
|
||||
* @brief Resumes data mode (Switches back to th data mode, which was temporarily suspended)
|
||||
@ -108,10 +110,10 @@ ESP_MODEM_DECLARE_DCE_COMMAND(resume_data_mode, command_result, 0) \
|
||||
\
|
||||
/**
|
||||
* @brief Sets php context
|
||||
* @param[in] x PdP context struct to setup modem cellular connection
|
||||
* @param[in] p1 PdP context struct to setup modem cellular connection
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_pdp_context, command_result, 1, STRUCT_OUT(PdpContext, x)) \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_pdp_context, command_result, 1, STRUCT_OUT(PdpContext, p1)) \
|
||||
\
|
||||
/**
|
||||
* @brief Switches to the command mode
|
||||
@ -130,21 +132,21 @@ ESP_MODEM_DECLARE_DCE_COMMAND(set_cmux, command_result, 0) \
|
||||
* @param[out] imsi Module's IMSI number
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_imsi, command_result, 1, STRING_OUT(x, imsi)) \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_imsi, command_result, 1, STRING_OUT(p1, imsi)) \
|
||||
\
|
||||
/**
|
||||
* @brief Reads the IMEI number
|
||||
* @param[out] imei Module's IMEI number
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_imei, command_result, 1, STRING_OUT(x, imei)) \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_imei, command_result, 1, STRING_OUT(p1, imei)) \
|
||||
\
|
||||
/**
|
||||
* @brief Reads the module name
|
||||
* @param[out] name module name
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_module_name, command_result, 1, STRING_OUT(x, name)) \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_module_name, command_result, 1, STRING_OUT(p1, name)) \
|
||||
\
|
||||
/**
|
||||
* @brief Sets the modem to data mode
|
||||
@ -158,7 +160,7 @@ ESP_MODEM_DECLARE_DCE_COMMAND(set_data_mode, command_result, 0) \
|
||||
* @param[out] ber channel bit error rate
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_signal_quality, command_result, 2, INT_OUT(x, rssi), INT_OUT(y, ber)) \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_signal_quality, command_result, 2, INT_OUT(p1, rssi), INT_OUT(p2, ber)) \
|
||||
\
|
||||
/**
|
||||
* @brief Sets HW control flow
|
||||
@ -166,7 +168,7 @@ ESP_MODEM_DECLARE_DCE_COMMAND(get_signal_quality, command_result, 2, INT_OUT(x,
|
||||
* @param[in] dte_flow 0=none, 2=CTS hw flow control of DTE
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_flow_control, command_result, 2, INT_IN(x, dce_flow), INT_IN(y, dte_flow)) \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_flow_control, command_result, 2, INT_IN(p1, dce_flow), INT_IN(p2, dte_flow)) \
|
||||
\
|
||||
/**
|
||||
* @brief Hangs up current data call
|
||||
@ -181,7 +183,7 @@ ESP_MODEM_DECLARE_DCE_COMMAND(hang_up, command_result, 0) \
|
||||
* @param[out] bcl 1-100% battery capacity, -1-Not available
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_battery_status, command_result, 3, INT_OUT(x, voltage), INT_OUT(y, bcs), INT_OUT(z, bcl)) \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_battery_status, command_result, 3, INT_OUT(p1, voltage), INT_OUT(p2, bcs), INT_OUT(p3, bcl)) \
|
||||
\
|
||||
/**
|
||||
* @brief Power down the module
|
||||
@ -193,14 +195,95 @@ ESP_MODEM_DECLARE_DCE_COMMAND(power_down, command_result, 0) \
|
||||
* @brief Reset the module
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(reset, command_result, 0)\
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(reset, command_result, 0) \
|
||||
\
|
||||
/**
|
||||
* @brief Configures the baudrate
|
||||
* @param[in] baud Desired baud rate of the DTE
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_baud, command_result, 1, INT_IN(x, baud))
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_baud, command_result, 1, INT_IN(p1, baud)) \
|
||||
\
|
||||
/**
|
||||
* @brief Force an attempt to connect to a specific operator
|
||||
* @param[in] mode mode of attempt
|
||||
* mode=0 - automatic
|
||||
* mode=1 - manual
|
||||
* mode=2 - deregister
|
||||
* mode=3 - set format for read operation
|
||||
* mode=4 - manual with fallback to automatic
|
||||
* @param[in] format what format the operator is given in
|
||||
* format=0 - long format
|
||||
* format=1 - short format
|
||||
* format=2 - numeric
|
||||
* @param[in] oper the operator to connect to
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_operator, command_result, 3, INT_IN(p1, mode), INT_IN(p2, format), STRING_IN(p3, oper)) \
|
||||
\
|
||||
/**
|
||||
* @brief Attach or detach from the GPRS service
|
||||
* @param[in] state 1-attach 0-detach
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_network_attachment_state, command_result, 1, INT_IN(p1, state)) \
|
||||
\
|
||||
/**
|
||||
* @brief Get network attachment state
|
||||
* @param[out] state 1-attached 0-detached
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_network_attachment_state, command_result, 1, INT_OUT(p1, state)) \
|
||||
\
|
||||
/**
|
||||
* @brief What mode the radio should be set to
|
||||
* @param[in] state state 1-full 0-minimum ...
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_radio_state, command_result, 1, INT_IN(p1, state)) \
|
||||
\
|
||||
/**
|
||||
* @brief Get current radio state
|
||||
* @param[out] state 1-full 0-minimum ...
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_radio_state, command_result, 1, INT_OUT(p1, state)) \
|
||||
\
|
||||
/**
|
||||
* @brief Set network mode
|
||||
* @param[in] mode preferred mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_network_mode, command_result, 1, INT_IN(p1, mode)) \
|
||||
\
|
||||
/**
|
||||
* @brief Preferred network mode (CAT-M and/or NB-IoT)
|
||||
* @param[in] mode preferred selection
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_preferred_mode, command_result, 1, INT_IN(p1, mode)) \
|
||||
\
|
||||
/**
|
||||
* @brief Set network bands for CAT-M or NB-IoT
|
||||
* @param[in] mode CAT-M or NB-IoT
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_network_bands, command_result, 3, STRING_IN(p1, mode), INTEGER_LIST_IN(p2, bands), INT_IN(p3, size)) \
|
||||
\
|
||||
/**
|
||||
* @brief Show network system mode
|
||||
* @param[out] mode current network mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_network_system_mode, command_result, 1, INT_OUT(p1, mode)) \
|
||||
\
|
||||
/**
|
||||
* @brief GNSS power control
|
||||
* @param[out] mode power mode (0 - off, 1 - on)
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_gnss_power_mode, command_result, 1, INT_IN(p1, mode)) \
|
||||
\
|
||||
|
||||
|
||||
#ifdef GENERATE_DOCS
|
||||
@ -213,7 +296,7 @@ ESP_MODEM_DECLARE_DCE_COMMAND(set_baud, command_result, 1, INT_IN(x, baud))
|
||||
#define _ARG(param, name) name
|
||||
// --- DCE command documentation starts here ---
|
||||
#ifdef __cplusplus
|
||||
class esp_modem::DCE: public DCE_T<GenericModule> {
|
||||
class esp_modem::DCE : public DCE_T<GenericModule> {
|
||||
public:
|
||||
using DCE_T<GenericModule>::DCE_T;
|
||||
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, ...) return_type name (__VA_ARGS__);
|
||||
|
68
components/esp_modem/include/vfs_resource/vfs_create.hpp
Normal file
68
components/esp_modem/include/vfs_resource/vfs_create.hpp
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright 2021 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
|
||||
|
||||
#define ESP_MODEM_VFS_DEFAULT_UART_CONFIG(name) { \
|
||||
.dev_name = (name), \
|
||||
.uart = { \
|
||||
.port_num = UART_NUM_1, \
|
||||
.data_bits = UART_DATA_8_BITS, \
|
||||
.stop_bits = UART_STOP_BITS_1, \
|
||||
.parity = UART_PARITY_DISABLE, \
|
||||
.flow_control = ESP_MODEM_FLOW_CONTROL_NONE,\
|
||||
.baud_rate = 115200, \
|
||||
.tx_io_num = 25, \
|
||||
.rx_io_num = 26, \
|
||||
.rts_io_num = 27, \
|
||||
.cts_io_num = 23, \
|
||||
.rx_buffer_size = 4096, \
|
||||
.tx_buffer_size = 512, \
|
||||
.event_queue_size = 0, \
|
||||
}, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief UART init struct for VFS
|
||||
*/
|
||||
struct esp_modem_vfs_uart_creator {
|
||||
const char *dev_name; /*!< VFS device name, e.g. /dev/uart/n */
|
||||
const struct esp_modem_uart_term_config uart; /*!< UART driver init struct */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief UART init struct for VFS
|
||||
*/
|
||||
struct esp_modem_vfs_socket_creator {
|
||||
const char *host_name; /*!< VFS socket: host name (or IP address) */
|
||||
int port; /*!< VFS socket: port number */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a socket VFS and configures the DTE struct
|
||||
*
|
||||
* @param config Socket config option, basically host + port
|
||||
* @param created_config reference to the VFS portion of the DTE config to be set up
|
||||
* @return true on success
|
||||
*/
|
||||
bool vfs_create_socket(struct esp_modem_vfs_socket_creator *config, struct esp_modem_vfs_term_config *created_config);
|
||||
|
||||
/**
|
||||
* @brief Creates a uart VFS and configures the DTE struct
|
||||
*
|
||||
* @param config Uart config option, basically file name and console options
|
||||
* @param created_config reference to the VFS portion of the DTE config to be set up
|
||||
* @return true on success
|
||||
*/
|
||||
bool vfs_create_uart(struct esp_modem_vfs_uart_creator *config, struct esp_modem_vfs_term_config *created_config);
|
@ -11,8 +11,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MDNS_HOST_ESP_EVENT_H
|
||||
#define MDNS_HOST_ESP_EVENT_H
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_netif.h"
|
||||
@ -38,4 +37,4 @@ esp_err_t esp_event_handler_register(const char * event_base, int32_t event_id,
|
||||
|
||||
esp_err_t esp_event_handler_unregister(const char * event_base, int32_t event_id, void* event_handler);
|
||||
|
||||
#endif //MDNS_HOST_ESP_EVENT_H
|
||||
typedef void * QueueHandle_t;
|
||||
|
@ -11,8 +11,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MDNS_HOST_ESP_EVENT_BASE_H
|
||||
#define MDNS_HOST_ESP_EVENT_BASE_H
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
WIFI_EVENT_STA_CONNECTED, /**< ESP32 station connected to AP */
|
||||
@ -25,4 +24,3 @@ typedef enum {
|
||||
|
||||
typedef void * esp_event_base_t;
|
||||
|
||||
#endif //MDNS_HOST_ESP_EVENT_BASE_H
|
||||
|
@ -3,18 +3,20 @@ set(LWIP_CONTRIB_DIR "$ENV{LWIP_CONTRIB_PATH}")
|
||||
|
||||
set(lwipcontribportunix_SRCS ${LWIP_CONTRIB_DIR}/ports/unix/port/sys_arch.c)
|
||||
|
||||
include(${LWIP_DIR}/src/Filelists.cmake)
|
||||
if(NOT CMAKE_BUILD_EARLY_EXPANSION)
|
||||
|
||||
set (LWIP_INCLUDE_DIRS
|
||||
include(${LWIP_DIR}/src/Filelists.cmake)
|
||||
|
||||
set (LWIP_INCLUDE_DIRS
|
||||
"${LWIP_DIR}/src/include"
|
||||
"${LWIP_CONTRIB_DIR}/ports/unix/port/include")
|
||||
|
||||
list(REMOVE_ITEM lwipnoapps_SRCS "${LWIP_DIR}/src/netif/slipif.c")
|
||||
list(REMOVE_ITEM lwipnoapps_SRCS "${LWIP_DIR}/src/core/ip4.c")
|
||||
list(REMOVE_ITEM lwipnoapps_SRCS "${LWIP_DIR}/src/core/ipv6/ip6.c")
|
||||
list(REMOVE_ITEM lwipnoapps_SRCS "${LWIP_DIR}/src/netif/slipif.c")
|
||||
list(REMOVE_ITEM lwipnoapps_SRCS "${LWIP_DIR}/src/core/ipv4/ip4.c")
|
||||
list(REMOVE_ITEM lwipnoapps_SRCS "${LWIP_DIR}/src/core/ipv6/ip6.c")
|
||||
endif()
|
||||
|
||||
|
||||
idf_component_register(SRCS esp_netif_linux.cpp tun_io.c ip6_stub.c ${lwipnoapps_SRCS} ${lwipcontribportunix_SRCS}
|
||||
idf_component_register(SRCS esp_netif_linux.cpp tun_io.c ip4_stub.c ip6_stub.c ${lwipnoapps_SRCS} ${lwipcontribportunix_SRCS}
|
||||
INCLUDE_DIRS include ${LWIP_INCLUDE_DIRS}
|
||||
PRIV_INCLUDE_DIRS .
|
||||
REQUIRES esp_system_protocols_linux)
|
||||
|
@ -35,8 +35,7 @@ class NetifStorage;
|
||||
|
||||
void read_task(NetifStorage *netif);
|
||||
|
||||
class NetifStorage: public esp_netif_obj
|
||||
{
|
||||
class NetifStorage: public esp_netif_obj {
|
||||
public:
|
||||
explicit NetifStorage(const esp_netif_config_t *config) : esp_netif_obj(), exit(false)
|
||||
{
|
||||
@ -91,46 +90,9 @@ public:
|
||||
extern "C" esp_netif_t *esp_netif_new(const esp_netif_config_t *config)
|
||||
{
|
||||
return new NetifStorage(config);
|
||||
// struct ifreq ifr = { };
|
||||
// esp_netif_t * netif = netif_storage;
|
||||
// if (netif == NULL) {
|
||||
// return NULL;
|
||||
// }
|
||||
// if ((netif->fd = open(config->dev_name, O_RDWR)) == -1) {
|
||||
// ESP_LOGE(TAG, "Cannot open %s", config->dev_name);
|
||||
// goto cleanup;
|
||||
// }
|
||||
// ifr.ifr_flags = IFF_TUN;
|
||||
// strncpy(ifr.ifr_name, config->if_name, IFNAMSIZ);
|
||||
//
|
||||
// if (ioctl(netif->fd, TUNSETIFF, (void *)&ifr) == -1) {
|
||||
// ESP_LOGE(TAG, "Cannot set ioctl TUNSETIFF %m");
|
||||
// goto cleanup;
|
||||
// }
|
||||
// ioctl(netif->fd, TUNSETNOCSUM, 1);
|
||||
//
|
||||
// netif->in_buf = new uint8_t[BUF_SIZE];
|
||||
// netif->out_buf = new uint8_t[BUF_SIZE];
|
||||
// if (netif->in_buf == nullptr || netif->out_buf == nullptr) {
|
||||
// goto cleanup;
|
||||
// }
|
||||
//
|
||||
// if (!ppp_netif_init(netif)) {
|
||||
// ESP_LOGE(TAG, "Cannot initialize pppos lwip netif %m");
|
||||
// goto cleanup;
|
||||
// }
|
||||
//
|
||||
// return netif;
|
||||
//
|
||||
//cleanup:
|
||||
// close(netif->fd);
|
||||
// delete[] netif->in_buf;
|
||||
// delete[] netif->out_buf;
|
||||
// delete netif_storage;
|
||||
// return nullptr;
|
||||
}
|
||||
|
||||
void esp_netif_destroy(esp_netif_t *netif)
|
||||
{
|
||||
delete static_cast<NetifStorage*>(netif);
|
||||
delete static_cast<NetifStorage *>(netif);
|
||||
}
|
||||
|
@ -11,8 +11,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _HOST_ESP_NETIF_H_
|
||||
#define _HOST_ESP_NETIF_H_
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
@ -63,5 +62,3 @@ void esp_netif_destroy(esp_netif_t *esp_netif);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _HOST_ESP_NETIF_H_
|
||||
|
@ -12,8 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_NETIF_IP_ADDR_H_
|
||||
#define _ESP_NETIF_IP_ADDR_H_
|
||||
#pragma once
|
||||
|
||||
#include <endian.h>
|
||||
|
||||
@ -164,5 +163,3 @@ esp_ip6_addr_type_t esp_netif_ip6_get_addr_type(esp_ip6_addr_t* ip6_addr);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //_ESP_NETIF_IP_ADDR_H_
|
||||
|
@ -13,10 +13,6 @@
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#ifndef _ESP_NETIF_PPP_H_
|
||||
#define _ESP_NETIF_PPP_H_
|
||||
#pragma once
|
||||
|
||||
#define NETIF_PP_PHASE_OFFSET 0x100
|
||||
|
||||
|
||||
#endif //_ESP_NETIF_PPP_H_
|
||||
|
17
components/esp_modem/port/linux/esp_netif_linux/ip4_stub.c
Normal file
17
components/esp_modem/port/linux/esp_netif_linux/ip4_stub.c
Normal file
@ -0,0 +1,17 @@
|
||||
#include "lwip/ip4.h"
|
||||
|
||||
err_t
|
||||
ip4_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest,
|
||||
u8_t ttl, u8_t tos,
|
||||
u8_t proto, struct netif *netif)
|
||||
{ return ERR_OK; }
|
||||
|
||||
struct netif *
|
||||
ip4_route(const ip4_addr_t *dest)
|
||||
{ return NULL; }
|
||||
|
||||
err_t
|
||||
ip4_output_if_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest,
|
||||
u8_t ttl, u8_t tos,
|
||||
u8_t proto, struct netif *netif)
|
||||
{ return ERR_OK; }
|
@ -12,6 +12,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
typedef int uart_port_t;
|
||||
typedef int uart_word_length_t;
|
||||
|
@ -11,6 +11,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef int esp_err_t;
|
||||
|
||||
#define ESP_FAIL -1
|
||||
|
@ -11,8 +11,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MDNS_HOST_ESP_LOG_H
|
||||
#define MDNS_HOST_ESP_LOG_H
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@ -46,4 +45,3 @@ printf(LOG_COLOR_D); printf("(%s) ", TAG); printf(__VA_ARGS__); printf(LOG_RESET
|
||||
#define ESP_LOGV(TAG, ...) do { \
|
||||
printf(LOG_COLOR_V); printf("(%s) ", TAG); printf(__VA_ARGS__); printf(LOG_RESET_COLOR "\n"); } while(0)
|
||||
|
||||
#endif //MDNS_HOST_ESP_LOG_H
|
||||
|
@ -11,9 +11,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MDNS_HOST_ENDIAN_H
|
||||
#define MDNS_HOST_ENDIAN_H
|
||||
#pragma once
|
||||
|
||||
#include_next "endian.h"
|
||||
|
||||
#endif //MDNS_HOST_ENDIAN_H
|
||||
|
8
components/esp_modem/pre_upload.sh
Normal file
8
components/esp_modem/pre_upload.sh
Normal file
@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
apt-get update
|
||||
apt-get -y install doxygen clang python3-pip
|
||||
python -m pip install breathe recommonmark
|
||||
pushd components/esp_modem/docs
|
||||
./generate_docs
|
||||
popd
|
@ -12,25 +12,28 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _EXCEPTION_STUB_HPP_
|
||||
#define _EXCEPTION_STUB_HPP_
|
||||
#pragma once
|
||||
|
||||
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||
#define TRY_CATCH_RET_NULL(block) \
|
||||
#define TRY_CATCH_OR_DO(block, action) \
|
||||
try { block \
|
||||
} catch (std::bad_alloc& e) { \
|
||||
ESP_LOGE(TAG, "Out of memory"); \
|
||||
return nullptr; \
|
||||
} catch (esp_err_exception& e) { \
|
||||
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()); \
|
||||
return nullptr; \
|
||||
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
|
||||
|
||||
|
||||
#endif // _EXCEPTION_STUB_HPP_
|
||||
|
32
components/esp_modem/private_include/uart_compat.h
Normal file
32
components/esp_modem/private_include/uart_compat.h
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2021 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 "esp_log.h"
|
||||
#include "driver/uart.h"
|
||||
|
||||
/**
|
||||
* @brief This is a compatible header, which just takes care of different data ptr type
|
||||
* across different IDF version in driver/uart
|
||||
*/
|
||||
static inline int uart_write_bytes_compat(uart_port_t uart_num, const void* src, size_t size)
|
||||
{
|
||||
#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3
|
||||
const void *data = src;
|
||||
#else
|
||||
auto *data = reinterpret_cast<const char*>(src);
|
||||
#endif
|
||||
return uart_write_bytes(uart_num, data, size);
|
||||
}
|
@ -12,13 +12,12 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _UART_RESOURCE_HPP_
|
||||
#define _UART_RESOURCE_HPP_
|
||||
#pragma once
|
||||
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "esp_modem_config.h"
|
||||
|
||||
struct esp_modem_dte_config;
|
||||
struct esp_modem_uart_term_config;
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
@ -26,13 +25,12 @@ namespace esp_modem {
|
||||
* @brief Uart Resource is a platform specific struct which is implemented separately for ESP_PLATFORM and linux target
|
||||
*/
|
||||
struct uart_resource {
|
||||
explicit uart_resource(const esp_modem_dte_config *config, struct QueueDefinition** event_queue, int fd);
|
||||
explicit uart_resource(const esp_modem_uart_term_config *config, QueueHandle_t *event_queue, int fd);
|
||||
|
||||
~uart_resource();
|
||||
|
||||
uart_port_t port{};
|
||||
};
|
||||
|
||||
std::unique_ptr<Terminal> create_vfs_terminal(const esp_modem_dte_config *config);
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _UART_RESOURCE_HPP_
|
||||
|
@ -12,8 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _UART_TERMINAL_HPP_
|
||||
#define _UART_TERMINAL_HPP_
|
||||
#pragma once
|
||||
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
|
||||
@ -25,4 +24,3 @@ std::unique_ptr<Terminal> create_uart_terminal(const esp_modem_dte_config *confi
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _UART_TERMINAL_HPP_
|
||||
|
@ -12,8 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _VFS_TERMINAL_HPP_
|
||||
#define _VFS_TERMINAL_HPP_
|
||||
#pragma once
|
||||
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
|
||||
@ -24,5 +23,3 @@ namespace esp_modem {
|
||||
std::unique_ptr<Terminal> create_vfs_terminal(const esp_modem_dte_config *config);
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _VFS_TERMINAL_HPP_
|
||||
|
@ -30,43 +30,53 @@ struct PdpContext;
|
||||
static const char *TAG = "modem_api";
|
||||
#endif
|
||||
|
||||
std::shared_ptr<DTE> create_uart_dte(const dte_config *config) {
|
||||
TRY_CATCH_RET_NULL(
|
||||
auto term = create_uart_terminal(config);
|
||||
return std::make_shared<DTE>(config, std::move(term));
|
||||
)
|
||||
}
|
||||
|
||||
std::shared_ptr<DTE> create_vfs_dte(const dte_config *config) {
|
||||
std::shared_ptr<DTE> create_vfs_dte(const dte_config *config)
|
||||
{
|
||||
TRY_CATCH_RET_NULL(
|
||||
auto term = create_vfs_terminal(config);
|
||||
return std::make_shared<DTE>(config, std::move(term));
|
||||
auto term = create_vfs_terminal(config);
|
||||
return std::make_shared<DTE>(config, std::move(term));
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
static inline std::unique_ptr<DCE>
|
||||
create_modem_dce(dce_factory::Modem m, const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif) {
|
||||
create_modem_dce(dce_factory::ModemType m, const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif)
|
||||
{
|
||||
dce_factory::Factory f(m);
|
||||
TRY_CATCH_RET_NULL(
|
||||
return f.build_unique(config, std::move(dte), netif);
|
||||
return f.build_unique(config, std::move(dte), netif);
|
||||
)
|
||||
}
|
||||
|
||||
std::unique_ptr<DCE> create_SIM7600_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif) {
|
||||
return create_modem_dce(dce_factory::Modem::SIM7600, config, std::move(dte), netif);
|
||||
std::unique_ptr<DCE> create_SIM7600_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif)
|
||||
{
|
||||
return create_modem_dce(dce_factory::ModemType::SIM7600, config, std::move(dte), netif);
|
||||
}
|
||||
|
||||
std::unique_ptr<DCE> create_SIM800_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif) {
|
||||
return create_modem_dce(dce_factory::Modem::SIM800, config, std::move(dte), netif);
|
||||
std::unique_ptr<DCE> create_SIM7070_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif)
|
||||
{
|
||||
return create_modem_dce(dce_factory::ModemType::SIM7070, config, std::move(dte), netif);
|
||||
}
|
||||
|
||||
std::unique_ptr<DCE> create_BG96_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif) {
|
||||
return create_modem_dce(dce_factory::Modem::BG96, config, std::move(dte), netif);
|
||||
std::unique_ptr<DCE> create_SIM7000_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif)
|
||||
{
|
||||
return create_modem_dce(dce_factory::ModemType::SIM7000, config, std::move(dte), netif);
|
||||
}
|
||||
|
||||
std::unique_ptr<DCE> create_generic_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif) {
|
||||
return create_modem_dce(dce_factory::Modem::GenericModule, config, std::move(dte), netif);
|
||||
std::unique_ptr<DCE> create_SIM800_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif)
|
||||
{
|
||||
return create_modem_dce(dce_factory::ModemType::SIM800, config, std::move(dte), netif);
|
||||
}
|
||||
|
||||
std::unique_ptr<DCE> create_BG96_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif)
|
||||
{
|
||||
return create_modem_dce(dce_factory::ModemType::BG96, config, std::move(dte), netif);
|
||||
}
|
||||
|
||||
std::unique_ptr<DCE> create_generic_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif)
|
||||
{
|
||||
return create_modem_dce(dce_factory::ModemType::GenericModule, config, std::move(dte), netif);
|
||||
}
|
||||
|
||||
} // namespace esp_modem
|
||||
|
39
components/esp_modem/src/esp_modem_api_target.cpp
Normal file
39
components/esp_modem/src/esp_modem_api_target.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright 2021 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 <cassert>
|
||||
#include "esp_log.h"
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "uart_terminal.hpp"
|
||||
#include "vfs_termial.hpp"
|
||||
#include "cxx_include/esp_modem_api.hpp"
|
||||
#include "cxx_include/esp_modem_dce_factory.hpp"
|
||||
#include "esp_modem_config.h"
|
||||
#include "exception_stub.hpp"
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||
static const char *TAG = "modem_api_target";
|
||||
#endif
|
||||
|
||||
std::shared_ptr<DTE> create_uart_dte(const dte_config *config)
|
||||
{
|
||||
TRY_CATCH_RET_NULL(
|
||||
auto term = create_uart_terminal(config);
|
||||
return std::make_shared<DTE>(config, std::move(term));
|
||||
)
|
||||
}
|
||||
|
||||
} // namespace esp_modem
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user