Compare commits

...

382 Commits

Author SHA1 Message Date
8821ea3a99 Merge pull request #695 from david-cermak/bump/mdns_1.4.1
bump(mdns): 1.4.0 -> 1.4.1
2024-11-14 10:32:22 +01:00
7de57bb412 bump(mdns): 1.4.0 -> 1.4.1
1.4.1
Features
- Send PTR query for mdns browse when interface is ready (010a404a)
Bug Fixes
- Prevent deadlock when deleting a browse request (3f48f9ea)
- Fix use after free reported by coverity (25b3d5fd)
- Fixed dead-code reported by coverity (11846c7d)
2024-11-13 17:47:19 +01:00
67191f3bb5 Merge pull request #671 from david-cermak/feat/sock_utils
[sock-utils]: Add initial support for socket helpers
2024-11-11 18:29:45 +01:00
6d94ad646d bump(sockutls): Initial version 0.1.0
0.1.0
Features
- Add initial support for socket helpers (31f57ad0)
2024-11-11 16:47:57 +01:00
685d47cd2f fix(common): Disable clang-check for unsecure/deprecated APIs 2024-11-11 16:47:18 +01:00
31f57ad067 feat(sockutls): Add initial support for socket helpers 2024-11-11 16:47:13 +01:00
32ac21b03c Merge pull request #688 from david-cermak/fix/modem_docs_limitations
[modem]: bump: 1.1.0 -> 1.2.0
2024-11-11 16:26:41 +01:00
5b06a3b319 bump(modem): 1.1.0 -> 1.2.0
1.2.0
Features
- Add support for guessing mode (52598e5f)
- Delete CMUX internal implementation even if terminal exit fails (0e0cbd6b)
- Add support for handling URC (1b6a3b3b, #180)
- add ability to change ESP_MODEM_C_API_STR_MAX from Kconfig (17909892)
- Added target test config with CHAP authentication (f8ae7def)
- example add esp32p4 usb support (adafeae5)
- Publish mbedtls component (0140455f)
- host test support of the latest ESP-IDF release (3f74b4e8)
Bug Fixes
- Fix console example to use urc/detect features (1a9eaf3e)
- Update target test builds to use external Catch2 (554f022c)
- Fix arguments names when spawn esp_modem_xxx declarations (b6792c52)
- Remove catch dependency (c3480768)
- Examples: use local configs for MQTT topic/data (f5c13b92)
- Fixed clang-tidy warnings (70fa3af7)
- Fix CI build per IDFv5.3 (d0c17ef0)
- Fixed UART task to check for buffered data periodically (4bdd90cc, #536)
- Cleanup unused configs from PPPoS example (08a62ccc)
- Update CMUX example with SIM7070_gnss cleaned-up (56fe5327)
- Update console example with SIM7070_gnss format comments (5baaf542)
- Fix remaining print format warnings (3b80181d)
Updated
- docs(modem): Fix esp_modem_at_raw() description (C-API) (492a6a00)
- ci(common): updated github actions(checkout, upload, download) v3 to 4, Ubuntu 20.04 to v22.04 (a23a0027)
2024-11-07 12:42:11 +01:00
cc2741d4ad fix(modem): Document CMUX compatibility issue with CAVLI C16QS
Closes https://github.com/espressif/esp-protocols/issues/507
2024-11-07 12:41:47 +01:00
c5653ff204 Merge pull request #677 from david-cermak/fix/docs_links
[asio]: Fix links in documentation
2024-11-06 14:40:23 +01:00
77731c9b36 Merge pull request #678 from david-cermak/fix/modem_docs
[modem]: Fix docs to link tests correctly
2024-11-06 14:40:05 +01:00
2442f6b553 Merge pull request #612 from david-cermak/feat/modem_mode_detect
[modem]: Add support for guessing mode
2024-11-06 14:39:37 +01:00
0b5e362a7b Merge pull request #686 from bryghtlabs-richard/fix/wsExampleLeak
fix(websocket): fix example buffer leak
2024-11-05 17:11:35 +01:00
5219c39d09 fix(websocket): fix example buffer leak 2024-11-04 08:39:13 -06:00
1a9eaf3e98 fix(modem): Fix console example to use urc/detect features 2024-11-01 15:31:39 +01:00
52598e5f03 feat(modem): Add support for guessing mode 2024-11-01 13:49:52 +01:00
542547d38b Merge pull request #684 from david-cermak/fix/ws_disconnect_deadlock
[websocket]: Prevent crash on network disconnect during send
2024-10-31 15:56:20 +01:00
2bcfa45d30 bump(websocket): 1.2.3 -> 1.3.0
1.3.0
Features
- add events for begin/end thread (d7fa24bc)
- Make example to use certificate bundle (aecf6f80)
- propagate esp_tls stack error and cert verify flags (234f579b)
- Add option to set and use cert_common_name in Websocket client (3a6720de)
- adding support for `if_name` when using WSS transport (333a6893)
- allow updating reconnect timeout for retry backoffs (bd9f0627)
- allow using external tcp transport handle (83ea2876)
- adding support for `keep_alive_enable` when using WSS transport (c728eae5)
Bug Fixes
- Prevent crash on network disconnect during send (a453ca1f)
- use proper interface to delete semaphore (991ac40d)
- Move client to different state when disconnecting (0d8f2a6d)
- fix of websocket host example (5ccc018a)
- don't get transport from the list if external transport is used (9d4d5d2d)
- Fix locking issues of `esp_websocket_client_send_with_exact_opcode` API (6393fcd7)
2024-10-31 11:34:02 +01:00
a453ca1f38 fix(websocket): Prevent crash on network disconnect during send
When WiFi disconnects, `esp_websocket_client_task` continues polling
`esp_transport_poll_read()` with a default 1-second timeout.
If a timeout triggers `esp_websocket_client_abort_connection`,
certain resources are released.
However, if `esp_websocket_client_send_with_exact_opcode`
is still blocked at this point, it will cause a crash
when it times out and accesses the released handle.
This fix prevents potential crashes by ensuring proper
synchronization between abort and send functions.

Merges: https://github.com/espressif/esp-protocols/pull/629
2024-10-31 11:33:26 +01:00
72f4f7c7a3 Merge pull request #683 from bryghtlabs-richard/fix/ws-mutex-delete
fix(websocket): use proper interface to delete semaphore
2024-10-31 10:25:25 +01:00
a353702e04 Merge pull request #626 from euripedesrocha/websocket/fix_race_aborting_connection
Fix race condition when client set to not reconnect
2024-10-31 08:21:52 +01:00
991ac40d75 fix(websocket): use proper interface to delete semaphore
On most implementations, including ESP-IDF FreeRTOS, vSemaphoreDelete()
is a macro that calls vQueueDelete(). But since the client semaphore is
created with xSemaphoreCreateRecursiveMutex(), delete it as a semaphore with vSemaphoreDelete().
2024-10-30 16:54:45 -05:00
fbd296f8dd Merge pull request #661 from gytxxsy/feat/monitor_interface_status_for_browsing
[mdns]: send PTR query for mdns browse when interface is ready (IDFGH-13841)
2024-10-25 17:58:40 +02:00
a5b0b9d6ea Merge pull request #676 from arex-ebee/deadlock-on-mdns_browse_delete-call
[mdns]: Prevent deadlock when deleting a browse request (IDFGH-13947)
2024-10-25 16:48:42 +02:00
2d9759265b fix(modem): Fix docs to link tests correctly
Closes https://github.com/espressif/esp-protocols/issues/664
2024-10-25 12:56:08 +02:00
8f1f935858 fix(asio): Fix docs to link examples correctly 2024-10-25 12:43:19 +02:00
3f48f9ea7e fix(mdns): Prevent deadlock when deleting a browse request 2024-10-25 12:00:36 +02:00
8520245657 Merge pull request #672 from david-cermak/fix/publish_mosquitto
[mosquitto]: Fix incorrect link to the component url
2024-10-11 14:29:05 +02:00
185247d220 fix(mosq): Fix incorrent link to the component url 2024-10-11 11:14:07 +02:00
73b3293b86 Merge pull request #610 from david-cermak/feat/mosq_tls
[mosq]: Added TLS transport to mosquitto port
2024-10-11 10:57:05 +02:00
f613c70e00 bump(mosq): Initial version v2.0.28~0
2.0.28~0
Features
- Added support for TLS transport using ESP-TLS (1af4bbe1)
- Add API docs, memory consideration and tests (a20c0c9d)
- Add target tests with localhost broker-client (5c850cda)
- Initial moquitto v2.0.18 port (TCP only) (de4531e8)
Bug Fixes
- Fix clean compilation addressing _GNU_SOURCE redefined (e2392c36)
Updated
- docs(mosq): Prepare mosquitto component for publishing (c2c4bf83)
2024-10-11 09:46:47 +02:00
c2c4bf835a docs(mosq): Prepare mosquitto component for publishing 2024-10-11 08:54:15 +02:00
1af4bbe1ab feat(mosq): Added support for TLS transport using ESP-TLS 2024-10-11 08:38:06 +02:00
f5dc07fdcc Merge pull request #670 from david-cermak/remove/wifi_remote
[wifi-remote]: Moved esp-wifi-remote development to a separate repo
2024-10-09 16:13:52 +02:00
e992787bcd chore(common): Moved esp-wifi-remote devel to separate repo
esp-wifi-remote is being developed in https://github.com/espressif/esp-wifi-remote
from v0.4.0 (last released version from esp-protocols repo)
2024-10-07 15:05:31 +02:00
8c4f392f93 Merge pull request #663 from david-cermak/bump/wifi_remote
[wifi_remote]: Bump 0.3.0 -> 0.4.0
2024-09-26 15:58:05 +02:00
8d8f2bf130 Merge pull request #662 from david-cermak/fix/mosqutto_submodule
[mosquitto]: Fix incorrect upstream mosqutto submodule path
2024-09-26 14:43:50 +02:00
30f121e6a9 bump(wifi_remote): 0.3.0 -> 0.4.0
0.4.0
Features
- Make esp_hosted default RPC library (1b62adbd)
- Add build test for current IDF examples (50c113e4)
- Support for IDF v5.3 in a separate directory (bde97203)
- Support for IDF v5.4 via a separate dir (e9ac41e1)
- Add slave selection and peview targets (345c4577)
Bug Fixes
- Fix CMake to use inherent IDF build vars (c454ec09)
- Update per v5.4 espressif/esp-idf@97e42349 (ff5dac70)
- Fix CI builds to generate configs per slave selection (8795d164)
- Depend on esp_hosted only on targets with no WiFi (7ca5ed1d)
- Update per espressif/esp-idf@27f61966 (2e53b81f)
- Fix checking API compat against reference dir (1a57a878)
2024-09-26 14:36:48 +02:00
29810f4139 ci(mosq): Fix incorrect upstream mosqutto submodule path 2024-09-26 13:34:56 +02:00
2abe55c173 Merge pull request #643 from david-cermak/feat/wifi_remote_with_hosted
[wifi_remote]: Make esp_hosted default RPC library
2024-09-26 13:21:54 +02:00
eb7ea3450e ci(common): Use idf_build_apps >= 2.0 to fix pkg deprecation 2024-09-26 11:58:09 +02:00
1b62adbdf1 feat(wifi_remote): Make esp_hosted default RPC library 2024-09-26 11:58:04 +02:00
d6347a9d5f Merge pull request #660 from david-cermak/feat/wifi_remote_flat
[wifi_remote]: Make flat version structure across IDF releases
2024-09-26 10:07:28 +02:00
c454ec09e6 fix(wifi_remote): Fix CMake to use inherent IDF build vars
IDF_VERSION_MAJOR, IDF_VERSION_MAJOR, rather than environmental variable {ESP_IDF_VERSION}
2024-09-26 08:51:41 +02:00
ff5dac70b7 fix(wifi_remote): Update per v5.4 espressif/esp-idf@97e42349 2024-09-26 08:39:22 +02:00
50c113e412 feat(wifi_remote): Add build test for current IDF examples
Building also standard IDF examples that use esp-wifi-remote (building
for wifiless targets ESP32P4, ESP32H2 and one wifi target ESP32s3)
2024-09-26 08:37:40 +02:00
bde97203ed feat(wifi_remote): Support for IDF v5.3 in a separate directory 2024-09-26 08:37:07 +02:00
8795d16466 fix(wifi_remote): Fix CI builds to generate configs per slave selection
Rather than keeping sdkconfig.ci.*** for the smoke tests in git
2024-09-26 08:35:27 +02:00
e9ac41e1d7 feat(wifi_remote): Support for IDF v5.4 via a separate dir 2024-09-26 08:33:39 +02:00
7ca5ed1d3e fix(wifi_remote): Depend on esp_hosted only on targets with no WiFi 2024-09-26 08:31:37 +02:00
345c457711 feat(wifi_remote): Add slave selection and peview targets 2024-09-26 08:30:53 +02:00
2e53b81f64 fix(wifi_remote): Update per espressif/esp-idf@27f61966 2024-09-26 08:30:14 +02:00
1a57a878be fix(wifi_remote): Fix checking API compat against reference dir
rather than git history, as it might now work in GitHub CI (due to
shallow cloning)
2024-09-26 08:28:05 +02:00
010a404a04 feat(mdns): Send PTR query for mdns browse when interface is ready 2024-09-23 19:01:10 +08:00
8475adf1d1 Merge pull request #655 from david-cermak/fix/modem_target_catch2
[modem]: Update target test builds to use external Catch2
2024-09-20 09:18:14 +02:00
29e5fbdf93 Merge pull request #651 from david-cermak/fix/master_detect_bump
[ci]: Fix for components not published
2024-09-20 09:17:59 +02:00
554f022cbf fix(modem): Update target test builds to use external Catch2
Switched from the deprecated Catch framework (IDF/tools) to Catch2,
as Catch will be removed in v6.0.
Note that Catch2 has higher memory requirements,
necessitating an increase in stack size and partition table.
Additionally, Catch2 increases compilation time due to its larger footprint.
2024-09-20 07:55:41 +02:00
cfd6d6ad90 Merge pull request #653 from embedcat/docs/fix-at-raw-description
[modem]: Fix esp_modem_at_raw() description in docs (C-API)
2024-09-18 11:15:17 +02:00
6f90d85933 Merge pull request #658 from Ant2000/master
[modem] Minor change to exit_cmux behavior
2024-09-18 11:14:30 +02:00
0e0cbd6b17 feat(modem): Delete CMUX internal implementation even if terminal exit fails 2024-09-18 14:08:52 +05:30
e926a2c4e6 Merge pull request #654 from embedcat/feat/fix-arguments-c-api
[modem]: Fix arguments names when spawn esp_modem_xxx declarations
2024-09-18 09:04:25 +02:00
b6792c527c fix(modem): Fix arguments names when spawn esp_modem_xxx declarations 2024-09-18 09:09:44 +03:00
492a6a0029 docs(modem): Fix esp_modem_at_raw() description (C-API) 2024-09-17 14:49:01 +03:00
22ec03b3e6 ci(common): Fix for components not published 2024-09-17 10:42:49 +02:00
6705bcae5e Merge pull request #606 from david-cermak/feat/mosquitto
[mosq]: Support for TCP listener mode of mosquitto broker on ESP32
2024-09-17 10:05:08 +02:00
2208e76e04 Merge pull request #620 from david-cermak/feat/modem_urc
[modem]: Add support for handling URC
2024-09-17 09:54:15 +02:00
c348076849 fix(modem): Remove catch dependency 2024-09-16 19:19:13 +02:00
1b6a3b3b75 feat(modem): Add support for handling URC
Closes https://github.com/espressif/esp-protocols/issues/180
2024-09-16 15:17:29 +02:00
e2392c36fe fix(mosq): Fix clean compilation addressing _GNU_SOURCE redefined 2024-09-16 14:50:36 +02:00
a20c0c9d2c feat(mosq): Add API docs, memory consideration and tests 2024-09-16 14:50:36 +02:00
5c850cdad3 feat(mosq): Add target tests with localhost broker-client 2024-09-16 14:50:36 +02:00
de4531e8c7 feat(mosq): Initial moquitto v2.0.18 port (TCP only) 2024-09-16 14:50:31 +02:00
d2880418e5 Merge pull request #640 from david-cermak/feat/ppp_chap_test
[modem]: Added CHAP authentication test
2024-09-12 10:58:34 +02:00
8e4d43e00d Merge pull request #649 from embedcat/master
[modem]: Add ability to change ESP_MODEM_C_API_STR_MAX from Kconfig (IDFGH-13668)
2024-09-12 09:56:02 +02:00
fb7b0c201d ci(common): Fix clang-tidy job not use deprecated action 2024-09-12 09:37:03 +02:00
f5c13b927f fix(modem): Examples: use local configs for MQTT topic/data
To avoid issues in CI, as we're using public server
and could receive data by people playing with the example
2024-09-12 09:29:46 +02:00
571a741b56 Merge pull request #642 from david-cermak/fix/mdns_coverity
[mdns]: Fix recent issues on v1.4 reported by Coverity
2024-09-12 08:55:47 +02:00
1790989242 feat(modem): add ability to change ESP_MODEM_C_API_STR_MAX from Kconfig 2024-09-11 11:40:09 +03:00
f8ae7defd6 feat(modem): Added target test config with CHAP authentication
Related to https://github.com/espressif/esp-protocols/issues/635
2024-08-27 16:51:44 +02:00
25b3d5fd7b fix(mdns): Fix use after free reported by coverity
Fixes CID 467739: Use after free in mdns.c, mdns_service_remove_for_host
We should look only for one match in the service list, since if we
assume there could be aliases, we might free one and reference the
other.
2024-08-27 15:26:32 +02:00
11846c7d00 fix(mdns): Fixed dead-code reported by coverity
Fixes CID 467738: Logically dead code in mdns.c, _copy_mdns_txt_items
Introduced by probably by a merge confilict, as the fix was added in
two separate PRs, merging d4da9cb0 first and 8a690503 later
2024-08-27 15:20:58 +02:00
73c48307a3 Merge pull request #638 from david-cermak/bump/mdns_1.4
[mdns]: Bump: 1.3.2 -> 1.4.0
2024-08-21 08:41:02 +02:00
b9357b31b5 bump(mdns): 1.3.2 -> 1.4.0
1.4.0
Major changes
- Fixed mdns API issues when add/remove/update records from multiple threads (Fix services API races to directly add/remove services)
Features
- Unit tests for add/remove/update deleg/selfhosted services (0660ece1)
- Add console command for mdns browsing (1e8ede33)
- Console test: set instance for service (f107dcd1)
- Console test: add subtype for service (ee00e97b)
- Console test: set port for (delegated) srvs (07b79abf)
- Console test: add/remove TXT recs for delegated srvs (c9a58d73)
- Console test for changing TXT records (6b9a6ce6)
- Console test for add/remove delegated service APIs (43de7e5c)
- Console test for add/remove delegated host APIs (ce7f326a)
- Console test for lookup service APIs (a91ead8e)
- Add linux console functional tests (50d059af)
- check if the txt items is changed when browsing (e2f0477a)
Bug Fixes
- Fix mdns_delegate_hostname_add() to block until done (2c1b1661)
- Fix API races when removing all services (169405b5)
- Fix API races setting instance name for services (643dc6d4)
- Fix API races while adding subtypes for services (f9f234c4)
- Fix API races removing txt item for services (3f97a822)
- Fix API races adding txt item for services (c62b920b)
- Fix API races while setting txt for services (a927bf3a)
- Fix API races while setting port for services (99d5fb27)
- Fix services API races to directly add/remove services (8a690503)
- Fix mdns mdns_lookup_service() to handle empty TXT (d4da9cb0)
2024-08-21 07:51:53 +02:00
788f0513fa Merge pull request #615 from david-cermak/fix/mdns_hostname_race
fix(mdns): Fix add/remove selfhosted services while hostname changes
2024-08-20 20:58:11 +02:00
bcab28c1b8 Merge pull request #633 from bryghtlabs-richard/feat/websocketBeginEnd
Feat/websocket: begin end thread events (IDFGH-13507)
2024-08-20 16:41:52 +02:00
60817dd384 Merge pull request #630 from johanstokking/fix/websocket-esp-tls-errors
feat(websocket): propagate esp_tls stack error and cert verify flags
2024-08-20 06:11:55 -03:00
2c1b16617e fix(mdns): Fix mdns_delegate_hostname_add() to block until done
Adds action semaphore the same way it's done in mdns_hostname_add()
There could still potentially be a minor issue when calling these two APIs
simultanously. Will solve the same ways as in 8a690503 (tracked as
IDF-10913)
2024-08-19 14:34:08 +02:00
169405b534 fix(mdns): Fix API races when removing all services
Fixes **API race issue** (described in 8a690503) for API
mdns_service_remove_all()
2024-08-19 14:33:27 +02:00
0d8f2a6d53 fix(websocket): Move client to different state when disconnecting
If Websocket client is set to not reconnect, we move to Unknown state to
clean up the task after dispatching disconnected event.
2024-08-19 12:52:37 +02:00
643dc6d43b fix(mdns): Fix API races setting instance name for services
Fixes **API race issue** (described in 8a690503) for API
mdns_service_instance_name_set_for_host()
2024-08-19 12:38:35 +02:00
f9f234c440 fix(mdns): Fix API races while adding subtypes for services
Fixes **API race issue** (described in 8a690503) for API
mdns_service_subtype_add_for_host()
2024-08-19 12:38:28 +02:00
3f97a8228b fix(mdns): Fix API races removing txt item for services
Fixes **API race issue** (described in 8a690503) for API
mdns_service_txt_item_remove_for_host()
2024-08-19 12:38:20 +02:00
c62b920bb9 fix(mdns): Fix API races adding txt item for services
Fixes **API race issue** (described in 8a690503) for API
mdns_service_txt_item_set_for_host_with_explicit_value_len()
2024-08-19 12:38:12 +02:00
a927bf3a8d fix(mdns): Fix API races while setting txt for services
Fixes **API race issue** (described in 8a690503) for API
mdns_service_txt_set_for_host()
2024-08-19 12:38:03 +02:00
99d5fb27e9 fix(mdns): Fix API races while setting port for services
Fixes **API race issue** (described in 8a690503) for API
mdns_service_port_set_for_host()
2024-08-19 12:37:52 +02:00
8a690503ed fix(mdns): Fix services API races to directly add/remove services
Original issue (data race when updating hostname): mdns_service_add()
makes a copy of the local hostname and calls using the local copy
mdns_service_add_for_host().
When mdns's hostname is updated the local copy gets out of sync.
**API race issue**: Most of the current API correctly lock the mdns service,
but sometimes unlocks it before sending an action to the action queue,
so it's possible that the situation changes before the actual action
takes place.
**Fix**: After locking the mdns service, we proceed directly with updating
internal structures and do not post actions into the action queue.
**Fix wrtt hostname**: Use mdns_service_add_for_host(hostname=NULL)
for all self hosted services.
MAJOR CHANGE: Fixed mdns API issues when add/remove/update records from multiple threads
This and the following commits fix the API race issues for these mdns APIs:
* mdns_service_add_for_host
* mdns_service_port_set_for_host
* mdns_service_txt_set_for_host
* mdns_service_txt_item_set_for_host_with_explicit_value_len
* mdns_service_txt_item_remove_for_host
* mdns_service_subtype_add_for_host
* mdns_service_instance_name_set_for_host
* mdns_service_remove_for_host
* mdns_service_remove_all
2024-08-19 12:36:05 +02:00
7e5ac87d09 Merge pull request #619 from david-cermak/feat/more_unit_tests
[mdns]: Add unit test for services
2024-08-19 12:35:11 +02:00
d4da9cb079 fix(mdns): Fix mdns mdns_lookup_service() to handle empty TXT
the lookup_service API calls _copy_mdns_txt_items(), which tries to
allocate new TXT records, but didn't handle the case with no TXT.
Originally the _copy_mdns_txt_items() called calloc() with zero's which
returned NULL (on espressif toolchain), so it's safe, but we could see
an error message:
E (1170) mdns: Cannot allocate memory (line: 6191, free heap: 281368 bytes)
This commit addresses the empty TXT case and gets rid of the error
message.
2024-08-19 11:28:56 +02:00
0660ece128 feat(mdns): Unit tests for add/remove/update deleg/selfhosted services 2024-08-19 11:28:01 +02:00
d7fa24bc20 feat(websocket): add events for begin/end thread
Add events to signal the start and end of the
websocket thread handler, only once each per client.
2024-08-16 14:45:54 -05:00
9cf4163663 docs(websocket): improve websocket event list 2024-08-16 14:45:50 -05:00
a8f13bc861 Merge pull request #632 from david-cermak/fix/ci_jobs
[CI]: Fixes with recent IDF updates
2024-08-16 18:54:31 +02:00
aecf6f80bf feat(websocket): Make example to use certificate bundle
To easy maintenance, makes the example on websocket client to use
certificate bundle by default.
2024-08-16 16:17:10 +02:00
34d7c1b23b ci(common): Ignore nearly full partition on C6 builds 2024-08-16 15:41:53 +02:00
6766be6955 Merge pull request #618 from david-cermak/feat/mdns_console_host_more_tests
[mdns]: More console tests
2024-08-16 09:29:55 +02:00
234f579bd8 feat(websocket): propagate esp_tls stack error and cert verify flags 2024-08-15 21:14:08 +02:00
1e8ede3396 feat(mdns): Add console command for mdns browsing 2024-08-15 16:18:42 +02:00
f107dcd118 feat(mdns): Console test: set instance for service 2024-08-15 16:18:42 +02:00
ee00e97b2b feat(mdns): Console test: add subtype for service 2024-08-15 16:18:42 +02:00
07b79abf62 feat(mdns): Console test: set port for (delegated) srvs 2024-08-15 16:18:42 +02:00
c9a58d7350 feat(mdns): Console test: add/remove TXT recs for delegated srvs 2024-08-15 16:18:42 +02:00
6b9a6ce65b feat(mdns): Console test for changing TXT records 2024-08-15 16:18:42 +02:00
43de7e5c4d feat(mdns): Console test for add/remove delegated service APIs 2024-08-15 16:18:42 +02:00
ce7f326af0 feat(mdns): Console test for add/remove delegated host APIs 2024-08-15 16:18:42 +02:00
a91ead8ef5 feat(mdns): Console test for lookup service APIs 2024-08-15 16:18:42 +02:00
e425a3c504 Merge pull request #617 from david-cermak/feat/mdns_console_host
[mdns]: Add linux console functional tests
2024-08-15 15:59:18 +02:00
50d059af07 feat(mdns): Add linux console functional tests 2024-08-15 15:25:49 +02:00
f198967c98 Merge pull request #584 from espressif-abhikroy/component/console_cmd_ping
feat(console): Added command getaddrinfo, set/get dnsserver to console_cmd_ping
2024-08-15 19:54:26 +10:00
c41e8891ca bump(console): 1.0.0 -> 1.1.0
1.1.0
Features
- Added command getaddrinfo, set/get dnsserver to console_cmd_ping (b80c19d7)
2024-08-15 19:50:27 +10:00
b80c19d72c feat(console): Added command getaddrinfo, set/get dnsserver to console_cmd_ping 2024-08-15 19:49:53 +10:00
5964eadbf5 Merge pull request #613 from gytxxsy/feat/check_if_txt_changed_when_browsing
feat(mdns): check if the txt items is changed when browsing
2024-07-23 18:04:20 +02:00
e583848695 Merge pull request #616 from huming2207/master
fix(websocket): don't fetch transport from the list if external transport is set
2024-07-22 11:34:26 +04:00
cb1bc41386 Merge pull request #605 from gabsuren/ci/websocket_host_fix
CI: fix
2024-07-19 20:31:33 +04:00
8d91f5fd62 fix(ci): allow unsecure node version for self hosted runner 2024-07-19 17:00:00 +04:00
5ccc018a98 fix(websocket): fix of websocket host example 2024-07-19 15:50:07 +04:00
9d4d5d2d49 fix(websocket): don't get transport from the list if external transport is used 2024-07-16 16:53:40 +10:00
e2f0477a00 feat(mdns): check if the txt items is changed when browsing 2024-07-16 10:44:05 +08:00
906e447193 Merge pull request #573 from huming2207/feature/ws-transport-handle
feat(websocket): allow using external TCP transport handle (IDFGH-12825)
2024-07-12 16:50:33 +04:00
15ae280bbe Merge pull request #608 from johanstokking/feature/websocket/tls_keepalive_ifname
feat(websocket): adding support for `if_name` when using WSS transport
2024-07-10 12:37:27 +04:00
e6f9fe2385 Merge pull request #583 from DCSBL/ws-client-common-name
feat(websocket_client): Add option to set and use cert_common_name in Websocket client (IDFGH-12926)
2024-07-10 12:29:52 +04:00
3a6720ded6 feat(websocket): Add option to set and use cert_common_name in Websocket client 2024-07-10 09:19:48 +02:00
333a68936a feat(websocket): adding support for if_name when using WSS transport 2024-07-05 13:34:03 +02:00
25d8423e6d Merge pull request #594 from erkia/erkia/ws-reconnect-timeout
feat(esp_websocket_client): allow updating reconnect timeout for retry backoffs (IDFGH-13016)
2024-07-03 10:16:05 +04:00
bd9f062709 feat(websocket): allow updating reconnect timeout for retry backoffs 2024-07-02 21:07:50 +03:00
9152cfcf82 Merge pull request #598 from euripedesrocha/bump_mqtt_cxx040
bump(mqtt_cxx): 0.3.0 -> 0.4.0
2024-07-02 07:36:30 -03:00
8195fc4b8f Merge pull request #601 from david-cermak/bump/wifi_remote
bump(wifi_remote): 0.2.3 -> 0.3.0
2024-06-28 08:44:02 +02:00
68da69e4d8 Merge pull request #602 from david-cermak/bump/eppp
bump(eppp): 0.1.1 -> 0.2.0
2024-06-28 07:55:05 +02:00
c6e2eb2dac Merge pull request #556 from leeebo/master
feat(esp_modem): example add esp32p4 usb support (IDFGH-12673)
2024-06-24 15:51:57 +02:00
a9dd78ffad bump(eppp): 0.1.1 -> 0.2.0
0.2.0
Features
- Add support for SDIO transport (085dd790)
Bug Fixes
- Fixed strict prototype API decl issue in SDIO (eb09e426)
- Fix SIDO host to check/clear interrupts atomically (402176c9)
2024-06-24 15:50:50 +02:00
eb09e42638 fix(eppp): Fixed strict prototype API decl issue in SDIO 2024-06-24 15:50:40 +02:00
adafeae5cf feat(esp_modem): example add esp32p4 usb support
1. support ec20 cat.4 module in example modem_console and pppos_client
2. support esp32p4 in example modem_console and pppos_client
2024-06-24 18:55:20 +08:00
d7eaa77b89 Merge pull request #511 from david-cermak/feat/eppp_sdio
[eppp]: Add support for SDIO transport
2024-06-24 09:52:20 +02:00
5fe3870494 bump(wifi_remote): 0.2.3 -> 0.3.0
0.3.0
Features
- add esp_wifi_internal_tx_by_ref (ba35d14e)
- Make wifi_remote depend on esp_hosted (ac9972aa)
2024-06-24 09:40:25 +02:00
402176c9e0 fix(eppp): Fix SIDO host to check/clear interrupts atomically 2024-06-24 09:29:42 +02:00
085dd79079 feat(eppp): Add support for SDIO transport 2024-06-24 09:29:42 +02:00
a05fbc7ed9 Merge pull request #599 from SohKamYung-Espressif/feat/wifi_internal_tx_by_ref
feat(wifi_remote): add esp_wifi_internal_tx_by_ref
2024-06-21 17:42:00 +02:00
ba35d14e43 feat(wifi_remote): add esp_wifi_internal_tx_by_ref
Add esp_wifi_internal_tx_by_ref as building with CONFIG_SPIRAM=y will
get a linker error caused by an undefined reference to the function.
2024-06-21 15:24:16 +08:00
83ea2876fc feat(websocket): allow using external tcp transport handle 2024-06-21 14:47:03 +10:00
c714d24d75 bump(mqtt_cxx): 0.3.0 -> 0.4.0
0.4.0
Bug Fixes
- Adds missing configuration fields (d4c6d5ed)
2024-06-18 12:49:02 +02:00
2b64e80acd Merge pull request #596 from SohKamYung-Espressif/feat/depend_on_esp_hosted
feat(wifi_remote): Make wifi_remote depend on esp_hosted (IDFGH-13027)
2024-06-18 11:02:11 +02:00
ac9972aa48 feat(wifi_remote): Make wifi_remote depend on esp_hosted
Co-authored-by: david-cermak <38914379+david-cermak@users.noreply.github.com>
2024-06-18 11:14:09 +08:00
1c5a149b14 Merge pull request #597 from david-cermak/fix/pre_commit_hook_astyle
fix(common): Fix pre-commit hook to use released astyle_py
2024-06-14 15:33:56 +02:00
8d0152f612 fix(common): Fix pre-commit hook to use released astyle_py
The previous version (c00138088) required pyyaml 3.0.0 which is broken
on certain plafroms (e.g. Fedora 39)

Closes https://github.com/espressif/esp-protocols/issues/592
2024-06-14 12:24:31 +02:00
b2272b410d Merge pull request #513 from espressif-abhikroy/component/console_cmd_wifi
feat(console): wifi commands updates
2024-06-11 21:03:09 +10:00
5d43f9660f bump(console): 1.0.1 -> 1.1.0
1.1.0
Features
- Added support to join pre-configured network (bdbf16c1)
2024-06-11 20:50:49 +10:00
bdbf16c113 feat(console): Added support to join pre-configured network 2024-06-11 20:34:01 +10:00
7f248bd03f Merge pull request #591 from david-cermak/fix/modem_clang_tidy
[modem]: Fixes clang-tidy warnings
2024-06-07 17:01:02 +02:00
dabd4bfd0e fix(modem): Fix host tests to run gcov in python virt env 2024-06-07 12:45:23 +02:00
70fa3af771 fix(modem): Fixed clang-tidy warnings
* private field 'netif' is not used [clang-diagnostic-unused-private-field]
* private field 'instance' is not used [clang-diagnostic-unused-private-field]
* Call to virtual method 'FdTerminal::stop' during destruction bypasses virtual dispatch [clang-analyzer-optin.cplusplus.VirtualCall]
* unused variable 'TAG' [clang-diagnostic-unused-const-variable]
* Null pointer passed as 2nd argument to memory copy function [clang-analyzer-unix.cstring.NullArg]
* Array access (from variable 'data') results in a null pointer dereference [clang-analyzer-core.NullDereference]
2024-06-07 12:43:23 +02:00
5d69d3f0ac Merge pull request #588 from gabsuren/mdns_v1.3.2
bump(mdns): 1.3.1 -> 1.3.2
2024-06-05 12:58:45 +04:00
39d59032a2 Merge pull request #582 from david-cermak/fix/wifi_remote_server_sync
[wifi-remote]: Fix server race when receiving command and posting events
2024-06-05 08:14:19 +02:00
e3418b5527 bump(wifi_remote): 0.2.2 -> 0.2.3
0.2.3
Bug Fixes
- Fix server event/command race condtion using eventfd (732b1d5)
- Lock server before marshalling events (9e13870)
2024-06-05 07:27:12 +02:00
21d1540b76 bump(mdns): 1.3.1 -> 1.3.2
1.3.2
Features
- add check of instance when handling PTR query (6af6ca5)
Bug Fixes
- Fix of mdns afl tests (139166c)
- remove same protocol services with different instances (042533a)
2024-06-04 16:43:44 +04:00
186e258798 Merge pull request #587 from gabsuren/fix_mdns_config
fix(mdns): Fix of mdns afl tests
2024-06-04 16:41:52 +04:00
139166c2c5 fix(mdns): Fix of mdns afl tests 2024-06-04 10:23:27 +04:00
7437d31368 Merge pull request #574 from DejinChen/fix/remove_same_protocol_service
fix(mdns): remove same protocol services with different instances
2024-06-03 14:26:40 +04:00
d20255a40c Merge pull request #559 from gytxxsy/feature/add_instance_check_for_existing_answer
feat(mdns): add check of instance when handling PTR query (IDFGH-12701)
2024-06-03 14:24:54 +04:00
6af6ca52a2 feat(mdns): add check of instance when handling PTR query 2024-05-31 17:29:14 +08:00
042533af90 fix(mdns): remove same protocol services with different instances 2024-05-31 16:37:22 +08:00
732b1d5084 fix(wifi_remote): Fix server event/command race condtion using eventfd 2024-05-31 07:47:37 +02:00
9e13870ad4 fix(wifi_remote): Lock server before marshalling events 2024-05-30 15:40:26 +02:00
3f12ef6eea Merge pull request #580 from david-cermak/fix/ci_build_jobs
ci(common): Fix build jobs to install only idf-build-apps in idf cotainer
2024-05-28 17:39:25 +02:00
f1bc070b86 Merge pull request #579 from david-cermak/fix/wifi_remote_netif_example_sta
[wifi-remote]: Pass more netif options to eppp
2024-05-28 17:39:01 +02:00
28c0e0b77b bump(wifi_remote): 0.2.1 -> 0.2.2
0.2.2
Bug Fixes
- Added more netif options for eppp connection (24ce867)
- Do not restrict EPPP config to RSA keys only (f05c765, #570)
2024-05-28 16:37:24 +02:00
24ce86756d fix(wifi_remote): Added more netif options for eppp connection
Configurable in Kconfig:
* routing priority
* netif description
2024-05-28 16:36:16 +02:00
39dfe268a3 Merge pull request #578 from david-cermak/fix/eppp_netif_config
[eppp]: Make some common esp_netif options configurable
2024-05-28 16:34:33 +02:00
d96f45a1f9 bump(eppp): 0.1.0 -> 0.1.1
0.1.1
Bug Fixes
- Make some common netif options configurable (7829e8f)
2024-05-28 16:11:19 +02:00
90fdcfc340 fix(eppp): Add build test for IDF v5.3, fix idf-build-apps deps 2024-05-28 16:10:19 +02:00
7829e8f976 fix(eppp): Make some common netif options configurable 2024-05-28 16:10:19 +02:00
ce27c13352 ci(console): Ignore latest ethernet deprecation warning 2024-05-28 14:57:17 +02:00
eab58de630 ci(common): Fix build jobs to install only idf-build-apps in idf container 2024-05-28 14:40:46 +02:00
fcb60806a9 Merge pull request #575 from david-cermak/fix/wifi_remote_keys
fix(wifi_remote): Do not restrict EPPP config to RSA keys only
2024-05-28 08:52:04 +02:00
22914d4b7b fix(wifi_remote): Fix build test to download only idf-build-apps deps 2024-05-27 17:18:27 +02:00
150a3ec06a Merge pull request #577 from david-cermak/fix/clang_tidy_deps
CI: Fixed clang-tidy job
2024-05-23 17:48:53 +02:00
c12616c91d ci: remove libtinfo5 installation step 2024-05-23 17:25:52 +02:00
f05c765e8b fix(wifi_remote): Do not restrict EPPP config to RSA keys only
Now we can use any kind of certificate and keys, as long as they're in
PEM format.

Closes https://github.com/espressif/esp-protocols/issues/570
2024-05-20 15:13:16 +02:00
ed021a90d4 Merge pull request #550 from gabsuren/fix_websokcet_params
fix(websocket): Fix locking issues of `esp_websocket_client_send_with_exact_opcode` IDF-9380
2024-05-17 13:20:23 +04:00
6393fcd79a fix(websocket): Fix locking issues of esp_websocket_client_send_with_exact_opcode API
Extended examples to cover more cases
Added new config CONFIG_ESP_WS_CLIENT_ENABLE_DYNAMIC_BUFFER for testing
2024-05-17 12:37:10 +04:00
c9439bd3d5 Merge pull request #571 from gabsuren/mdns_v1.3.1_
bump(mdns): 1.3.0 -> 1.3.1
2024-05-14 16:23:35 +04:00
2c4c88b4fb bump(mdns): 1.3.0 -> 1.3.1
1.3.1
Bug Fixes
- free txt value len (afd98bb)
2024-05-14 15:00:27 +04:00
d45c5cef9a Merge pull request #569 from DejinChen/fix/free_txt_value_len
fix(mdns): free txt value len (IDFGH-12817)
2024-05-14 14:58:31 +04:00
afd98bb9c5 fix(mdns): free txt value len 2024-05-10 17:44:48 +08:00
8f19c60c19 Merge pull request #567 from gabsuren/CI/idf_5.3
ci(common): added idf release-v5.2, release-v5.3 targets(IDF-9875)
2024-05-09 22:40:16 +04:00
281e933808 ci(common): added idf release-v5.2, release-v5.3 targets 2024-05-09 20:56:02 +04:00
f4bdf0ab6c Merge pull request #545 from david-cermak/feat/clang_tidy_check
ci(common): Add clang tidy check to esp-protocols
2024-05-09 14:56:01 +02:00
e25b2a1d9d Merge pull request #568 from david-cermak/bump/wifi_remote_with_eppp
[wifi-remote]: Updated eppp dependency and more WiFi functions
2024-05-07 22:53:39 +02:00
608b835680 bump(wifi_remote): 0.2.0 -> 0.2.1
0.2.1
Bug Fixes
- Added misc wifi API in eppp impl (93256d1)
- Updated eppp dependency not to use fixed version (3a48c06)
2024-05-07 20:06:43 +02:00
93256d159b fix(wifi_remote): Added misc wifi API in eppp impl
Adds missing implementation of:
* esp_wifi_deinit()
* esp_wifi_disconnect()
* esp_wifi_set_storage()
2024-05-07 20:06:24 +02:00
3a48c06e96 fix(wifi_remote): Updated eppp dependency not to use fixed version 2024-05-07 20:06:19 +02:00
e011188377 Merge pull request #566 from david-cermak/feat/eppp_force_lwip_opts
[eppp]: Force the `PPP` LWIP opts which are OFF by default
2024-05-07 19:48:18 +02:00
1fb1ea9300 bump(eppp): 0.0.1 -> 0.1.0
0.1.0
Features
- Added CI job to build examples and tests (7eefcf0)
Bug Fixes
- Fixed to select PPP LWIP opts which are OFF by default (16be2f9)
- Example to use iperf component from the registry (bd6b66d)
- Fixed defalt config designated init issue in C++ (8bd4712)
2024-05-07 10:32:55 +02:00
16be2f963b fix(eppp): Fixed to select PPP LWIP opts which are OFF by default 2024-05-07 10:30:43 +02:00
d786f0db88 Merge pull request #555 from gabsuren/websocket_keep_alirve
feat(websocket): adding support for `keep_alive_enable` when using WSS transport (IDFGH-11457)
2024-05-03 14:49:42 +04:00
f6f6ded001 Merge pull request #560 from david-cermak/fix/ci_build_v5.3
Fix CI build per IDFv5.3
2024-05-03 12:44:25 +02:00
eb84eed8d3 ci(common): Add clang tidy check to esp-protocols 2024-04-26 12:39:52 +02:00
5df46437f2 fix(console): Ignore eth_init hidden config warning 2024-04-26 11:57:06 +02:00
bd6b66d9d1 fix(eppp): Example to use iperf component from the registry 2024-04-26 11:32:46 +02:00
d0c17ef0d5 fix(modem): Fix CI build per IDFv5.3 2024-04-26 11:25:30 +02:00
06d013b20b Merge pull request #557 from euripedesrocha/fix_lastwill
Adds missing configuration fields
2024-04-26 02:50:23 -03:00
f032a9f023 Merge pull request #538 from david-cermak/feat/wifi_remote_example
[wifi remote]: Add example without `esp_hosted`
2024-04-25 16:03:15 +02:00
d16387859f bump(wifi_remote): 0.1.12 -> 0.2.0
0.2.0
Features
- Add support for simple eppp based RPC (fd168d8)
Bug Fixes
- Make services restartable, code cleanup (6c82ce2)
- Add examples to CI (d2b7c55)
2024-04-25 15:13:49 +02:00
6c82ce2915 fix(wifi_remote): Make services restartable, code cleanup 2024-04-25 15:11:17 +02:00
d2b7c55b89 fix(wifi_remote): Add examples to CI 2024-04-25 15:11:17 +02:00
fd168d86fc feat(wifi_remote): Add support for simple eppp based RPC 2024-04-25 15:11:09 +02:00
d4c6d5ed5d fix(mqtt_cxx): Adds missing configuration fields
Some aspects of the underlying mqtt client were not set.

Fix #554
2024-04-22 12:30:20 +02:00
c728eae5ea feat(websocket): adding support for keep_alive_enable when using WSS transport 2024-04-22 10:57:36 +04:00
bd6e120509 Merge pull request #509 from david-cermak/feat/mbedtls_cxx_component
fix(tls_cxx): Publish mbedtls-cxx component
2024-04-11 18:32:08 +02:00
13793a8236 bump(tls_cxx): First version [0.1.0]
0.1.0
Features
- Publish mbedtls component (0140455f)
2024-04-11 16:52:51 +02:00
0140455ff7 feat(tls_cxx): Publish mbedtls component
Adds examples and tests.
Also supports DTLS now.
2024-04-11 16:49:54 +02:00
c4d9cc6beb Merge pull request #540 from david-cermak/fix/modem_uart_missed_event
fix(modem): Fixed UART task to check for buffered data periodically
2024-04-11 14:44:51 +02:00
887dbcd73b Merge pull request #549 from gabsuren/mdns_1.3.0
bump(mdns): 1.2.5 -> 1.3.0
2024-04-10 14:36:36 +04:00
b3ba71ff4d bump(mdns): 1.2.5 -> 1.3.0
1.3.0
Features
- add a new mdns query mode `browse` (af330b6)
- Make including mdns_console KConfigurable (27adbfe)
Bug Fixes
- Schedule all queued Tx packets from timer task (d4e693e)
- add lock for some common apis (21c84bf)
- fix mdns answer append while host is invalid (7be16bc)
2024-04-10 11:24:25 +04:00
fbdb2483f5 Merge pull request #522 from zwx1995esp/feature/mdns_add_browse_suport
mdns add browse support (IDFGH-12512)
2024-04-10 09:48:55 +04:00
zwx
af330b6396 feat(mdns): add a new mdns query mode browse 2024-04-10 11:23:24 +08:00
0b94d9ec47 Merge pull request #543 from david-cermak/feat/wifi_remote_publish
fix(wifi_remote): Publish missing esp_wifi_remote and add to README
2024-04-04 10:46:45 +02:00
f26f2f88c2 Merge pull request #537 from david-cermak/fix/eppp_cxx_init
fix(eppp): Fixed default config designated init issue in C++
2024-04-02 14:50:41 +02:00
08d06a4b7d fix(wifi_remote): Publish missing esp_wifi_remote and add to README 2024-04-02 14:42:31 +02:00
cb682a793e Merge pull request #516 from david-cermak/feat/wifi_remote
New component `esp_wifi_remote`
2024-04-02 12:56:12 +02:00
d053d671f4 bump(wifi_remote): Initial version 0.1.12
0.1.12
Features
- Added generation step for wifi_remote based on IDF (dfb00358)
- Move to esp-protocols (edc3c2d)
2024-04-02 11:21:38 +02:00
16b79d170b ci(common): Fix changelog: only add newline for new entries 2024-04-02 11:19:30 +02:00
dfb0035858 feat(wifi_remote): Added generation step for wifi_remote based on IDF 2024-04-02 11:19:24 +02:00
1750a3fda9 Merge pull request #535 from gabsuren/websocket_update
bump(websocket): 1.2.2 -> 1.2.3
2024-03-27 17:35:52 +04:00
2a3db45ef1 Merge pull request #541 from gabsuren/websocket_host_example_4
fix(websocket): fix of websocket host build
2024-03-26 20:33:55 +04:00
fcc61e0929 fix(websocket): fix of websocket host build 2024-03-26 19:00:03 +04:00
4bdd90cc88 fix(modem): Fixed UART task to check for buffered data periodically
Closes https://github.com/espressif/esp-protocols/issues/536
2024-03-26 14:44:59 +01:00
14763888ed Merge pull request #534 from gabsuren/mdns_docs
fix(mdns): updated the document to clarify service advertisment prerequisite (IDFGH-6982)
2024-03-26 13:15:21 +04:00
a5954dda17 Merge pull request #533 from david-cermak/fix/mdns_process_tx_packets
fix(mdns): Schedule all queued Tx packets from timer task
2024-03-26 10:12:41 +01:00
8bd4712677 fix(eppp): Fixed defalt config designated init issue in C++ 2024-03-25 12:48:41 +01:00
a65d81c954 bump(websocket): 1.2.2 -> 1.2.3
1.2.3
Features
- Expanded example to demonstrate the transfer over TLS (0d0630ed76)
Bug Fixes
- fix esp_event dependency management (1fb02a9a60)
- Skip warn on zero timeout and auto reconnect is disabled (5b467cbf5c)
- Fixed to use int return value in Tx functions (9c54b72e1f)
- Fixed Tx functions with DYNAMIC_BUFFER (16174470ee)
- added dependency checks, sdkconfig.defaults and refined README.md (312982e4aa)
- Close websocket and dispatch event if server does not close within a reasonable amount of time. (d85311880d)
- Continue waiting for TCP connection to be closed (2b092e0db4)
Updated
- docs(websocket): Added README for websocket host example (2f7c58259d)
2024-03-22 14:37:13 +04:00
2585565483 fix(mdns): updated the document to clarify service advertisment prerequisite (IDFGH-6982) 2024-03-22 11:57:24 +04:00
b9c675b0b1 Merge pull request #523 from bryghtlabs-richard/master
fix(websocket): fix esp_event dependency management (IDFGH-12301) (IDFGH-12302)
2024-03-20 19:09:29 +01:00
d4e693e392 fix(mdns): Schedule all queued Tx packets from timer task
Co-Authored-By: not-my-real-name <none@interent.com>

Partially addresses: https://github.com/espressif/esp-idf/issues/13333
2024-03-20 11:47:29 +01:00
963b32e7b4 Merge pull request #497 from rretanubun/make-mdns-console-kcconfig
feat(mdns): Make including mdns_console KConfig (IDFGH-11988)
2024-03-20 09:39:34 +01:00
cffe26818b Merge pull request #531 from david-cermak/fix/modem_minor_prs
[esp_modem]: Accept some PRs
2024-03-18 16:34:21 +01:00
08a62ccc85 fix(modem): Cleanup unused configs from PPPoS example
Merges https://github.com/espressif/esp-protocols/pull/403
2024-03-18 14:10:46 +01:00
56fe53279e fix(modem): Update CMUX example with SIM7070_gnss cleaned-up
Merges https://github.com/espressif/esp-protocols/pull/246
2024-03-18 14:10:46 +01:00
5baaf54291 fix(modem): Update console example with SIM7070_gnss format comments
Merges https://github.com/espressif/esp-protocols/pull/245
2024-03-18 14:10:46 +01:00
38de23fb1c Merge pull request #532 from gabsuren/ci_fix_modem
fix(modem): install requirements.txt for modem target tests
2024-03-18 14:09:53 +01:00
84390eb4d4 fix(modem): install requirements.txt for modem target tests 2024-03-18 15:18:44 +04:00
4e844936b7 Merge pull request #529 from zwx1995esp/fix/add_lock_for_mdns_common_api
fix(mdns): add lock for some common apis (IDFGH-12338)
2024-03-15 11:14:16 +04:00
zwx
21c84bfa8d fix(mdns): add lock for some common apis 2024-03-14 17:53:05 +08:00
438449f58f Merge pull request #454 from gabsuren/modem/latest_version
feat(modem): host test support of the latest ESP-IDF release (IDF-7828)
2024-03-14 13:49:05 +04:00
a23a0027fa ci(common): updated github actions(checkout, upload, download) v3 to 4, Ubuntu 20.04 to v22.04 2024-03-12 14:22:01 +04:00
3f74b4e8c0 feat(modem): host test support of the latest ESP-IDF release 2024-03-12 12:05:59 +04:00
46a6244c37 Merge pull request #526 from zwx1995esp/fix/mdns_send_answer_while_host_is_invalid
fix(mdns): fix mdns answer append while host is invalid
2024-03-12 10:26:02 +04:00
zwx
7be16bcc88 fix(mdns): fix mdns answer append while host is invalid 2024-03-11 20:26:38 +08:00
1fb02a9a60 fix(websocket): fix esp_event dependency management
Move esp_event from PRIV_REQUIRES to REQUIRES, as it is
included by esp_websocket_client.h, so any code including
that header also requires esp_event.

This resolves the following build error for files not
explicitly requiring esp_event:

ninja: build stopped: subcommand failed.
Compilation failed because esp_websocket_client.h (in "espressif__esp_websocket_client" component) includes esp_event.h, provided by esp_event component(s).
However, esp_event component(s) is in the private requirements list of "espressif__esp_websocket_client".
To fix this, move esp_event from PRIV_REQUIRES into REQUIRES list of idf_component_register call in ...\managed_components\espressif__esp_websocket_client\CMakeLists.txt.
ninja failed with exit code 1, output of the command is in...
2024-03-08 10:10:48 -06:00
b5be844c92 Merge pull request #521 from johanstokking/fix/websocket/reconnect-timeout-warning
fix(websocket): Skip warn on zero timeout and auto reconnect is disabled  (IDFGH-12288)
2024-03-07 11:49:18 +04:00
5b467cbf5c fix(websocket): Skip warn on zero timeout and auto reconnect is disabled 2024-03-06 22:20:48 +01:00
f8a776d8a5 Merge pull request #519 from gabsuren/mdns1.2.5
bump(mdns): 1.2.4 -> 1.2.5
2024-03-06 10:56:24 +04:00
a82c7922aa bump(mdns): 1.2.4 -> 1.2.5
1.2.5
Bug Fixes
- Fixed build issues for targets without WiFi caps (302b46f)
2024-03-06 10:32:17 +04:00
d31ad025c8 Merge pull request #515 from david-cermak/fix/ws_dyn_buffer
[ws-client]: Fix usage of the dynamic buffer
2024-03-05 16:25:51 +01:00
4977f96a61 Merge pull request #517 from david-cermak/fix/examples_format_warn
Fix remaining format warnings
2024-03-05 15:02:44 +01:00
dcdf31187a Merge pull request #518 from gabsuren/mdns_docs_update
fix(mdns): updated the document to clarify self-querying mechanism (IDFGH-7528)
2024-03-05 14:23:06 +04:00
b6bbe47cae fix(mdns): updated the document to clarify self-querying mechanism 2024-03-05 12:38:07 +04:00
302b46f8e2 fix(mdns): Fixed build issues for targets without WiFi caps 2024-03-01 10:24:29 +01:00
45b1597ac3 fix(examples): Fix SLIP example print format warnings 2024-03-01 10:08:27 +01:00
a06de6431b fix(examples): Fix MQTT example print format warnings
Partially addresses https://github.com/espressif/esp-protocols/issues/79
2024-02-28 19:25:28 +01:00
3b80181d30 fix(modem): Fix remaining print format warnings
Partially addresses https://github.com/espressif/esp-protocols/issues/79
2024-02-28 19:24:52 +01:00
edc3c2dee0 feat(wifi_remote): Move to esp-protocols 2024-02-28 18:44:19 +01:00
943b683d38 fix(wifi_remote): Support for wifi_native injection 2024-02-28 18:37:16 +01:00
d0ace0d1c9 feat(wifi_remote): Initial stubs for wifi-remote 2024-02-28 18:30:47 +01:00
9c54b72e1f fix(websocket): Fixed to use int return value in Tx functions 2024-02-28 12:48:06 +01:00
16174470ee fix(websocket): Fixed Tx functions with DYNAMIC_BUFFER 2024-02-28 12:47:59 +01:00
a363beea6f Merge pull request #462 from david-cermak/feat/eppp_link
New component ESP-PPP-Link
2024-02-23 12:22:43 +01:00
a8035c21a2 bump(eppp): Published ESP-PPP-Link as eppp-v0.0.1 2024-02-23 12:05:21 +01:00
7eefcf084e feat(eppp): Added CI job to build examples and tests 2024-02-23 12:05:02 +01:00
18f845275f feat(eppp): Added support for SPI transport 2024-02-23 11:47:22 +01:00
ad27414a64 feat(eppp): Added support for UART transport 2024-02-23 11:47:15 +01:00
a7610395ef feat(eppp): Introduced ESP-PPP-Link component 2024-02-23 11:11:49 +01:00
9b7c8755e9 Merge pull request #506 from gabsuren/websocket_ssl_example
feat(websocket): Expanded example to demonstrate the transfer over TLS (IDFGH-11681)
2024-02-23 12:39:05 +04:00
0d0630ed76 feat(websocket): Expanded example to demonstrate the transfer over TLS 2024-02-23 12:08:41 +04:00
38a3631a27 Merge pull request #495 from eht-datarespons/master
fix(websocket): Continue waiting for TCP connection to be closed (IDFGH-11965)
2024-02-08 14:37:44 +01:00
96f4ebd994 Merge pull request #504 from gabsuren/mdns_1.2.4
bump(mdns): 1.2.3 -> 1.2.4
2024-02-08 16:39:33 +04:00
247ca41bb7 bump(mdns): 1.2.3 -> 1.2.4
1.2.4
Bug Fixes
- Correction on 6d2c475 MDNS_PREDEF_NETIF_ETH fix (fc59f87c4e)
- fix the logic of creating pcb for networking socket (5000a9a20a)
- fix compiling issue when disabling IPv4 (2646dcd23a)
- Fix compile error when MDNS_PREDEF_NETIF_ETH is defined, but ETH_ENABLED is not (#459) (6d2c475c20)
2024-02-06 11:51:38 +04:00
891384cc53 Merge pull request #414 from wqx6/fix/mdns_disable_ipv4
fix(mdns): fix compiling issue when disabling IPv4 (IDFGH-11453)
2024-02-06 11:45:45 +04:00
38ef603296 Merge pull request #500 from gabsuren/websocket_linux
fix(websocket): added dependency checks, sdkconfig.defaults and refined README.md
2024-02-05 14:05:00 +04:00
312982e4aa fix(websocket): added dependency checks, sdkconfig.defaults and refined README.md 2024-02-05 13:22:39 +04:00
d9d377133e Merge pull request #501 from gabsuren/update_examples
docs(common): Enhance documentation clarity in the examples directory
2024-02-05 13:16:47 +04:00
110536ebb2 docs(common): Enhance documentation clarity in the examples directory 2024-02-05 13:15:25 +04:00
d85311880d fix(websocket): Close websocket and dispatch event if server does not close within a reasonable amount of time. 2024-01-29 08:01:39 +01:00
27adbfeb3b feat(mdns): Make including mdns_console KConfigurable
The CLI that mdns_console offers is very useful for debugging
and bootstrapping mDNS onto new projects, but some projects
may not want console CLI in place to reduce binary size.

This gives a KConfig option to do so.
2024-01-26 13:35:47 -05:00
5ba7cfab8e Merge pull request #496 from gabsuren/readme_websocket_linux
docs(websocket): Added README for websocket host example (IDF-9115)
2024-01-26 20:31:15 +04:00
2f7c58259d docs(websocket): Added README for websocket host example 2024-01-26 20:29:28 +04:00
2b092e0db4 fix(websocket): Continue waiting for TCP connection to be closed
Prevents an issue where WEBSOCKET_EVENT_CLOSED is not sent after
websocket is closed.
2024-01-23 14:58:27 +01:00
f42c0adfc0 Merge pull request #494 from david-cermak/bump/modem_v1.1
bump(modem): 1.0.5 -> 1.1.0
2024-01-22 17:08:55 +01:00
2782277f3f bump(modem): 1.0.5 -> 1.1.0
1.1.0
Features
- Added support for at_raw() command (ae38110, #471)
- Added iperf test for PPP netifs (976e98d)
- Added test that performs OTA to exercise modem layers (f2223dd)
Bug Fixes
- Fixed OTA test to gracefully fail with no verification (1dc4299)
- Added C-API to configure APN (ce7dadd, #485)
- Fixed AT commands to copy strings to prevent overrides (741d166, #463)
- Fixed incorrect dial command format (0998f3d, #433)
- Fixed documentation and example on creating custom device (577de67, #452)
- Removed CI jobs for IDF v4.2 (d88cd61)
- Fixed OAT test to verify server cert and CN (edc3e72)
- Fixed set_pdp_context() command timeout (1d80cbc, #455)
Updated
- docs(modem): Added description of manual test procedure (68ce794)
2024-01-22 16:33:07 +01:00
3225f40c22 Merge pull request #491 from david-cermak/feat/modem_set_apn
fix(modem): Added C-API to configure APN
2024-01-22 16:05:51 +01:00
d63f831fff Merge pull request #466 from gabsuren/websocket_bump_1.2.2
bump(websocket): 1.2.1 -> 1.2.2
2024-01-19 19:27:37 +04:00
f62db5cfa2 Merge pull request #492 from euripedesrocha/mqttcxx_0_3_0
bump(mqtt_cxx): 0.2.0 -> 0.3.0
2024-01-19 08:42:52 -03:00
68ce794098 docs(modem): Added description of manual test procedure 2024-01-19 11:16:18 +01:00
60174f290e bump(mqtt_cxx): 0.2.0 -> 0.3.0
0.3.0
Bug Fixes
- Incorrect documentation link (aa4e9d57)
- reference protocol_examples_common from IDF (e6c0538d)
- specify override_path in example manifest files (fa005c63)
2024-01-19 09:43:07 +01:00
efa26b7062 Merge pull request #484 from david-cermak/fix/modem_docs_ota
fix(modem): Documented some tips on failing OTA
2024-01-18 17:43:03 +01:00
7b777948fc Merge pull request #487 from euripedesrocha/mqttcxx_link_fix
Incorrect documentation link
2024-01-18 05:10:23 -03:00
1dc4299eb0 fix(modem): Fixed OTA test to gracefully fail with no verification 2024-01-17 17:43:47 +01:00
ce7daddc77 fix(modem): Added C-API to configure APN
Closes https://github.com/espressif/esp-protocols/issues/485
2024-01-17 14:30:05 +01:00
09e68cc0c0 Merge pull request #490 from david-cermak/fix/mdns_eth
fix(mdns): Correction on 6d2c475 MDNS_PREDEF_NETIF_ETH fix
2024-01-17 12:53:14 +01:00
fc59f87c4e fix(mdns): Correction on 6d2c475 MDNS_PREDEF_NETIF_ETH fix 2024-01-17 11:51:17 +01:00
7a2b23909f Merge pull request #489 from espressif/revert-478-component/console_cmd_iperf
Revert "feat(console): Added component with iperf command"
2024-01-17 10:24:17 +01:00
d3bf773445 Revert "feat(console): Added component with iperf command" 2024-01-17 20:20:30 +11:00
1c29af9237 Merge pull request #472 from david-cermak/fix/modem_at_corrupt_response
fix(modem): Fixed AT commands to copy strings to prevent overrides
2024-01-17 09:48:24 +01:00
b53981a68c Merge pull request #479 from marekmaskarinec/master
fix(mdns): Fix compile error when MDNS_PREDEF_NETIF_ETH is defined, but ETH_ENABLED is not (IDFGH-11868)
2024-01-17 09:48:05 +01:00
5000a9a20a fix(mdns): fix the logic of creating pcb for networking socket 2024-01-17 10:48:40 +08:00
2646dcd23a fix(mdns): fix compiling issue when disabling IPv4 2024-01-17 10:48:40 +08:00
de8ec67a88 Merge pull request #478 from espressif-abhikroy/component/console_cmd_iperf
feat(console): Added component with iperf command
2024-01-17 00:53:56 +11:00
8dac30781c Merge pull request #488 from gabsuren/fix_docs
docs(common): Added package requirements.txt for esp-docs
2024-01-16 16:59:05 +04:00
ba3f06f942 docs(common): Added package requirements.txt for esp-docs 2024-01-16 16:57:58 +04:00
a10f0008fb bump(console): First version [1.0.0]
1.0.0
Features
- Added component with iperf command (93d14087)
2024-01-16 20:27:56 +11:00
741d166034 fix(modem): Fixed AT commands to copy strings to prevent overrides
Previously we used std::string_view, which pointed to the lower-layers
buffer which might have been reused for other asynchronous operations
before processing it, thus causing corruption of replies.

Closes https://github.com/espressif/esp-protocols/issues/463
2024-01-16 09:51:51 +01:00
93d140875f feat(console): Added component with iperf command 2024-01-16 19:18:01 +11:00
eb7699388c bump(websocket): 1.2.1 -> 1.2.2
1.2.2
Bug Fixes
- continuation after FIN in websocket client (#460) (774d1c75e6)
- Re-applie refs to common comps idf_component.yml (9fe44a4504)
2024-01-16 12:17:25 +04:00
585e4b30b2 Merge pull request #483 from espressif-abhikroy/ci/build_app_failure_fix
fix(common): Fixed scripts for build test failure
2024-01-16 09:07:14 +01:00
aa4e9d5795 fix(mqtt_cxx): Incorrect documentation link
- Link in the component README was incorrect.

Fixes #486
2024-01-16 08:41:55 +01:00
6d2c475c20 fix(mdns): Fix compile error when MDNS_PREDEF_NETIF_ETH is defined, but ETH_ENABLED is not (#459)
Signed-off-by: Marek Maškarinec <marek@mrms.cz>
2024-01-15 16:50:44 +01:00
47736a2556 fix(common): Fixed scripts for build test failure 2024-01-16 01:59:11 +11:00
adde6df6e8 fix(modem): Documented some tips on failing OTA
Closes https://github.com/espressif/esp-protocols/issues/482
2024-01-15 14:58:03 +01:00
1393764dc5 Merge pull request #477 from david-cermak/feat/modem_at_raw
feat(modem): Added support for at_raw() command
2024-01-15 12:31:18 +01:00
0998f3dd4f fix(modem): Fixed incorrect dial command format
ATD command is used to switch generic device to the data mode
by dialing GPRS_SRC. The generic version of the command was incorrect
`ATD*99##` (containing extra trailing # char, which is accepted by most
devices). Command has been fixed, but the extra #'s been kept for devices
that we cannot test (to be fixed in IDFGH-9470).

Closes https://github.com/espressif/esp-protocols/issues/433
2024-01-09 12:48:16 +01:00
577de67c0e fix(modem): Fixed documentation and example on creating custom device
Updates docs and examples per recent changes:
* Modem example does no longer demonstrate how to overwrite an AT method
* PPPoS client example now contains much simpler custom module
definition

Closes https://github.com/espressif/esp-protocols/issues/452
2024-01-09 10:26:39 +01:00
ae38110d84 feat(modem): Added support for at_raw() command
at_raw() sends raw string and supports custom pass/fail phrases for the
API to return OK/FAIL. It also returns raw, unprocessed string as
output.
This allows sending custom requests, such as:
* dce->at_raw("", resp, "RDY", "...", 20000) -- waiting for reset
* esp_modem_at_raw(dce, "+++", resp, "DISCONNECTED", "ERROR", 5000) --
exits PPP mode

Closes https://github.com/espressif/esp-protocols/issues/471
Partially addresses https://github.com/espressif/esp-protocols/issues/468
2024-01-09 08:20:10 +01:00
5ab699d6f4 Merge pull request #354 from david-cermak/feat/modem_iperf_test
feat(modem): Add iperf test of PPP netif
2024-01-08 16:48:02 +01:00
976e98d6ff feat(modem): Added iperf test for PPP netifs 2024-01-08 16:22:22 +01:00
18b2ae103a Merge pull request #476 from david-cermak/fix/ci_examples
fix(examples): Fixed esp_netif_next() warning with IDFv5.3
2024-01-08 12:48:30 +01:00
52a34c21d0 fix(examples): Fixed esp_netif_next() warning with IDFv5.3 2024-01-08 08:02:20 +01:00
9df86641f3 Merge pull request #475 from gabsuren/bump_mdns__v1.2.3
bump(mdns): 1.2.2 -> 1.2.3
2024-01-05 14:22:25 +04:00
75af01670e bump(mdns): 1.2.2 -> 1.2.3
1.2.3
Bug Fixes
- fixed CI issues for host and afl tests (4be5efc84e)
- fix copy delegated host addr (19fb36000c)
- enable CONFIG_ESP_WIFI_ENABLED if CONFIG_SOC_WIFI_SUPPORTED is also enabled (for ESP-IDF <= 5.1) (d20a718320)
- remove protocol_examples_common (1ee9dae6bf)
- move the example into a subdirectory (d28232b9f8)
- reference protocol_examples_common from IDF (c83b76ea8f)
2024-01-05 14:00:34 +04:00
bf79e2f734 Merge pull request #465 from espressif-abhikroy/component/ifconfig_bug_fix
fix(console): Fixed ifconfig command for PPP interface and IPv4 only
2024-01-05 19:36:46 +11:00
a22c9e8da9 bump(console): 1.0.0 -> 1.0.1
1.0.1
Bug Fixes
- Fixed ifconfig command for PPP interface and IPv4 only (8548dabb)
2024-01-05 19:27:16 +11:00
8548dabbd6 fix(console): Fixed ifconfig command for PPP interface and IPv4 only 2024-01-05 19:23:52 +11:00
d2e4370d30 Merge pull request #469 from DejinChen/component/mdns_host_address_fix
fix(mdns): fix copy delegated host addr (IDFGH-11829)
2024-01-04 21:13:58 +04:00
e4c353760c Merge pull request #473 from gabsuren/mdns_fix_kconfig
fix(mdns): fixed CI issues for host and afl tests
2024-01-04 21:12:46 +04:00
4be5efc84e fix(mdns): fixed CI issues for host and afl tests 2024-01-04 17:46:18 +04:00
7451ec2a75 Merge pull request #363 from david-cermak/feat/modem_test_ota
feat(modem): Add OTA test to exercise modem layers
2024-01-03 21:27:36 +01:00
19fb36000c fix(mdns): fix copy delegated host addr 2024-01-03 17:12:41 +08:00
7d0eb5c48c Merge pull request #467 from espressif-abhikroy/component/console_cmd_wifi
fix(console): Fixed license file for console_cmd_wifi
2024-01-03 18:59:32 +11:00
a0a58e60b5 bump(console): 1.0.0 -> 1.0.1
1.0.1
Features
- Console for runtime wifi configuration (194d1179)
Bug Fixes
- Fixed license file for console_cmd_wifi (8285e973)
2023-12-23 21:19:53 +11:00
8285e9730f fix(console): Fixed license file for console_cmd_wifi 2023-12-23 21:19:30 +11:00
cf845cc23e Merge pull request #453 from espressif-abhikroy/component/console_cmd_wifi
feat(console): Console for runtime wifi configuration
2023-12-22 23:54:09 +11:00
a532e76ec1 bump(console): First version [1.0.0]
1.0.0
Features
- Console for runtime wifi configuration (194d1179)
2023-12-22 23:48:44 +11:00
194d1179bf feat(console): Console for runtime wifi configuration 2023-12-22 23:44:16 +11:00
aadda22961 Merge pull request #461 from 0xFEEDC0DE64/fix-websocket-client-fin
fix(websocket): continuation after FIN in websocket client (#460) (IDFGH-11761)
2023-12-22 14:45:51 +04:00
a6845f4cdd Merge pull request #456 from david-cermak/fix/modem_pdp_context_timeout
fix(modem): Fixed set_pdp_context() command timeout
2023-12-21 07:21:31 +01:00
d88cd6123b fix(modem): Removed CI jobs for IDF v4.2 2023-12-19 17:01:51 +01:00
10bb738911 fix(modem): Added CI jobs to build all tests for all targets 2023-12-19 17:01:51 +01:00
edc3e7251f fix(modem): Fixed OAT test to verify server cert and CN 2023-12-19 17:01:30 +01:00
774d1c75e6 fix: continuation after FIN in websocket client (#460) 2023-12-19 17:00:17 +01:00
f2223dd719 feat(modem): Added test that performs OTA to exercise modem layers 2023-12-19 16:55:34 +01:00
1d80cbc179 fix(modem): Fixed set_pdp_context() command timeout
Closes https://github.com/espressif/esp-protocols/issues/455
2023-12-19 16:43:59 +01:00
82c2cf8936 Merge pull request #451 from david-cermak/bump/modem_1.0.5
bump(modem): 1.0.4 -> 1.0.5
2023-12-06 09:54:37 +01:00
997cff5338 bump(modem): 1.0.4 -> 1.0.5
1.0.5
Major changes
- Added support for implementing user defined modules in standard C-API (Support for custom modules with C-API)
Bug Fixes
- Added test injecting unexpected replies (b220d1e, #426)
- Fixed inconsistent state on data after OK (bf99f28, #426)
- TLS example: Added restore session support in mbedtls-wrap (79d38e5)
- Fixed examples to show netif on ppp-changed event (a70b197)
- remove unused GNU Make based buildsystem files (d6b6f63)
- specify override_path in example manifest files (5b78da4)
- Added test-cases that exercise mode transitions (aff571d)
- Fixed mode transitions between any state and UNDEF (93cb2ca, #320)
- Fixed API docs within doxygen comments (020b407)
- Support for custom modules with C-API (0254d50)
- Fix CRLF issue with esp_modem_c_api.cpp (2661b4d)
Updated
- ci(common): Created reusable action for host and coverage tests (9ad04de)
2023-12-06 09:22:39 +01:00
ed8bbf2666 Merge pull request #447 from david-cermak/fix/modem_command_state_consistent_test
fix(modem): Added test injecting unexpected replies
2023-12-06 09:20:27 +01:00
b220d1ee5e fix(modem): Added test injecting unexpected replies
This test exhibits an issue of getting unexpected data just after
completing a command. The DTE rewrites the state to TIMEOUT, but the
signal has been already triggered, thus results in an unexpected state.

Related to Closes https://github.com/espressif/esp-protocols/issues/426
2023-12-06 09:09:47 +01:00
671190bc6d Merge pull request #446 from david-cermak/fix/modem_command_state_consistency
fix(modem): Fixed inconsistent state on data after OK
2023-12-06 09:06:23 +01:00
1bf6843b3e Merge pull request #332 from espressif-abhikroy/components/console_cmd_ifconfig
Added component: Console for runtime network interface configuration
2023-11-30 08:23:15 +01:00
b78569860d Merge pull request #438 from espressif-abhikroy/components/console_cmd_ping
bump(console): First version [1.0.0]
2023-11-30 08:19:43 +01:00
27f955abfa bump(console): First version [1.0.0]
1.0.0
Features
- Added ping command to console component (7babdeb9)
2023-11-30 18:14:59 +11:00
bf99f287bc fix(modem): Fixed inconsistent state on data after OK
If we received response in two chunks and the first one completes the
command (result=OK or FAIL), and the second chunk pre-empts command processing,
then we performed processing again rewritting the result back to
TIMEOUT. This would invalidate the command, but also causes an
exception: ESP_MODEM_THROW_IF_ERROR(ESP_ERR_INVALID_STATE)
Fixed by checking if the processing already finished in process_line().

Closes https://github.com/espressif/esp-protocols/issues/426
2023-11-29 20:24:53 +01:00
909e8d9494 Merge pull request #441 from david-cermak/fix/apply_examples_idf_component_refs
fix(common): Re-applied refs to common comps idf_component.yml
2023-11-28 17:44:13 +01:00
0c6bb4bedc Merge pull request #360 from david-cermak/fix/modem_example_mbedtls_wrapper
fix(modem): TLS example: Add restore session support in mbedtls wrapper
2023-11-28 17:12:10 +01:00
afbca5343e Merge pull request #416 from david-cermak/fix/modem_undef_mode
fix(modem): Fixed mode transitions between any state and UNDEF
2023-11-28 17:11:43 +01:00
3f49583761 Merge pull request #443 from gabsuren/websocket_1.2.1
bump(websocket): 1.2.0 -> 1.2.1
2023-11-28 17:20:14 +04:00
c6448c3bd1 bump(websocket): 1.2.0 -> 1.2.1
1.2.1
Bug Fixes
- consider failure if return value of `esp_websocket_client_send_with_exact_opcode` less than 0 (f523b4d)
- fix of return value for `esp_websocket_client_send_with_opcode` API (ba33588)
2023-11-28 16:42:55 +04:00
f523b4dc84 fix(websocket): consider failure if return value of esp_websocket_client_send_with_exact_opcode less than 0 2023-11-28 16:40:10 +04:00
6fda4c134e Merge pull request #442 from gabsuren/fix/websocket_return_opcode
fix(websocket): fix of return value for `esp_websocket_client_send_with_opcode` API (IDF-8745)
2023-11-28 15:51:27 +04:00
ba33588008 fix(websocket): fix of return value for esp_websocket_client_send_with_opcode API 2023-11-28 12:37:31 +04:00
9fe44a4504 fix(common): Re-applie refs to common comps idf_component.yml
This reverts commit 74fc228cdf.
This reverts commit b176d3abbb.
This reverts commit f9e0281a04.
2023-11-28 09:32:52 +01:00
76a4a9f97a bump(console): First version [1.0.0]
1.0.0
Features
- Console for runtime network interface configuration and monitoring (8bab1420)
2023-11-24 22:12:33 +11:00
8bab1420d3 feat(console): Console for runtime network interface configuration and monitoring 2023-11-24 20:07:33 +11:00
79d38e54f2 fix(modem): TLS example: Added restore session support in mbedtls-wrap
Reusable component in modem_tcp_client example implements a simple
mbedtls wrapper. This update add support for mbedtls deinit() and for
saving and restoring TLS session.
2023-11-23 09:56:01 +01:00
5396de42d0 docs(modem): Added documentation about mode transitions
Closes https://github.com/espressif/esp-protocols/issues/318
2023-11-07 12:35:06 +01:00
aff571df2c fix(modem): Added test-cases that exercise mode transitions 2023-11-07 12:35:06 +01:00
93cb2caadb fix(modem): Fixed mode transitions between any state and UNDEF
Closes https://github.com/espressif/esp-protocols/issues/320
2023-11-07 12:35:00 +01:00
408 changed files with 16932 additions and 1478 deletions

View File

@ -13,16 +13,16 @@ jobs:
name: Build
strategy:
matrix:
idf_ver: ["latest", "release-v5.0", "release-v5.1"]
idf_ver: ["latest", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3"]
idf_target: ["esp32", "esp32s2"]
example: ["asio_chat", "async_request", "socks4", "ssl_client_server", "tcp_echo_server", "udp_echo_server"]
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
container: espressif/idf:${{ matrix.idf_ver }}
env:
TEST_DIR: components/asio/examples
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
@ -43,7 +43,7 @@ jobs:
run: |
. ${IDF_PATH}/export.sh
esptool.py --chip ${{ matrix.idf_target }} merge_bin --fill-flash-size 4MB -o flash_image.bin @flash_args
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.example }}
path: |
@ -64,7 +64,7 @@ jobs:
name: Target tests
strategy:
matrix:
idf_ver: ["latest", "release-v5.0"]
idf_ver: ["latest", "release-v5.0", "release-v5.2", "release-v5.3"]
idf_target: ["esp32"]
example: ["asio_chat", "tcp_echo_server", "udp_echo_server", "ssl_client_server"]
needs: build_asio
@ -76,8 +76,8 @@ jobs:
steps:
- name: Clear repository
run: sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.example }}
path: ${{ env.TEST_DIR }}/${{ matrix.example }}/build
@ -93,7 +93,7 @@ jobs:
working-directory: ${{ env.TEST_DIR }}/${{ matrix.example }}
run: |
python -m pytest --log-cli-level DEBUG --junit-xml=./examples_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.config }}.xml --target=${{ matrix.idf_target }}
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
if: always()
with:
name: examples_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.example }}

55
.github/workflows/clang-tidy.yml vendored Normal file
View File

@ -0,0 +1,55 @@
name: Run clang-tidy
on:
pull_request:
push:
branches:
- master
jobs:
build:
name: Run clang-tidy
runs-on: ubuntu-20.04
container: espressif/idf:latest
steps:
- uses: actions/checkout@v3
with:
submodules: 'true'
- name: Install esp-clang
run: |
${IDF_PATH}/tools/idf_tools.py --non-interactive install esp-clang
- name: Install clang-tidy-sarif
run: |
curl -sSL https://github.com/psastras/sarif-rs/releases/download/clang-tidy-sarif-v0.3.3/clang-tidy-sarif-x86_64-unknown-linux-gnu -o clang-tidy-sarif
chmod +x clang-tidy-sarif
curl -sSL https://raw.githubusercontent.com/espressif/idf-extra-components/master/.github/filter_sarif.py -o filter_sarif.py
- name: Install pyclang
run: |
. ${IDF_PATH}/export.sh
pip install pyclang~=0.2.0
- name: Run code analysis
shell: bash
env:
IDF_TOOLCHAIN: clang
IDF_TARGET: esp32
working-directory: test_app
run: |
. ${IDF_PATH}/export.sh
idf.py clang-check --include-paths $GITHUB_WORKSPACE --exclude-paths $PWD --run-clang-tidy-py run-clang-tidy --run-clang-tidy-options "-checks=-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling"
cp warnings.txt ../
- name: Convert clang-tidy results into SARIF output
run: |
export PATH=$PWD:$PATH
./clang-tidy-sarif -o results.sarif.raw warnings.txt
python3 filter_sarif.py -o results.sarif --include-prefix ${GITHUB_WORKSPACE}/ results.sarif.raw
- uses: actions/upload-artifact@v4
with:
path: |
warnings.txt
results.sarif
results.sarif.raw
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: results.sarif
category: clang-tidy

View File

@ -0,0 +1,38 @@
name: "console_cmd_ifconfig: build-tests"
on:
push:
branches:
- master
pull_request:
types: [opened, synchronize, reopened, labeled]
jobs:
build_console_cmd_ifconfig:
if: contains(github.event.pull_request.labels.*.name, 'console') || github.event_name == 'push'
name: Build
strategy:
matrix:
idf_ver: ["latest", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3"]
idf_target: ["esp32"]
test: [ { app: ifconfig-basic, path: "components/console_cmd_ifconfig/examples"}]
include:
- idf_ver: "latest"
warning: "the choice symbol ETHERNET_PHY_LAN867X\nis deprecated: Please use smi_gpio instead"
runs-on: ubuntu-22.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
env:
EXPECTED_WARNING: ${{ matrix.warning }}
shell: bash
working-directory: ${{matrix.test.path}}
run: |
. ${IDF_PATH}/export.sh
pip install idf-component-manager idf-build-apps --upgrade
python ../../../ci/build_apps.py ./${{ matrix.test.app }} --target ${{ matrix.idf_target }} -vv --preserve-all --pytest-app

View File

@ -13,20 +13,20 @@ jobs:
name: Build
strategy:
matrix:
idf_ver: ["latest", "release-v5.0"]
idf_ver: ["latest", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3"]
idf_target: ["esp32"]
test: [ { app: example, path: "components/console_cmd_ping/examples" }]
runs-on: ubuntu-20.04
test: [ { app: ping-basic, path: "components/console_cmd_ping/examples" }]
runs-on: ubuntu-22.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
shell: bash
working-directory: ${{matrix.test.path}}
run: |
${IDF_PATH}/install.sh --enable-pytest
. ${IDF_PATH}/export.sh
python $IDF_PATH/tools/ci/ci_build_apps.py . --target ${{ matrix.idf_target }} -vv --preserve-all --pytest-app
pip install idf-component-manager idf-build-apps --upgrade
python ../../../ci/build_apps.py ./${{ matrix.test.app }} --target ${{ matrix.idf_target }} -vv --preserve-all --pytest-app

View File

@ -0,0 +1,32 @@
name: "console_cmd_wifi: build-tests"
on:
push:
branches:
- master
pull_request:
types: [opened, synchronize, reopened, labeled]
jobs:
build_console_cmd_wifi:
if: contains(github.event.pull_request.labels.*.name, 'console') || github.event_name == 'push'
name: Build
strategy:
matrix:
idf_ver: ["latest", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3"]
idf_target: ["esp32"]
test: [ { app: wifi-basic, path: "components/console_cmd_wifi/examples" }]
runs-on: ubuntu-22.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
shell: bash
working-directory: ${{matrix.test.path}}
run: |
. ${IDF_PATH}/export.sh
pip install idf-component-manager idf-build-apps --upgrade
python ../../../ci/build_apps.py ./${{ matrix.test.app }} --target ${{ matrix.idf_target }} -vv --preserve-all --pytest-app

View File

@ -13,20 +13,20 @@ jobs:
name: Build
strategy:
matrix:
idf_ver: ["latest", "release-v5.0"]
idf_ver: ["latest", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3"]
idf_target: ["esp32"]
test: [ { app: example, path: "components/console_simple_init/examples" }]
runs-on: ubuntu-20.04
test: [ { app: console_basic, path: "components/console_simple_init/examples" }]
runs-on: ubuntu-22.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
shell: bash
working-directory: ${{matrix.test.path}}
run: |
${IDF_PATH}/install.sh --enable-pytest
. ${IDF_PATH}/export.sh
python $IDF_PATH/tools/ci/ci_build_apps.py . --target ${{ matrix.idf_target }} -vv --preserve-all --pytest-app
pip install idf-component-manager idf-build-apps --upgrade
python ../../../ci/build_apps.py ./${{ matrix.test.app }} --target ${{ matrix.idf_target }} -vv --preserve-all --pytest-app

28
.github/workflows/eppp__build.yml vendored Normal file
View File

@ -0,0 +1,28 @@
name: "eppp_link: build-tests"
on:
push:
branches:
- master
pull_request:
types: [opened, synchronize, reopened, labeled]
jobs:
build_eppp:
if: contains(github.event.pull_request.labels.*.name, 'eppp') || github.event_name == 'push'
name: Build
strategy:
matrix:
idf_ver: ["latest", "release-v5.3"]
test: [ { app: host, path: "examples/host" }, { app: slave, path: "examples/slave" }, { app: test_app, path: "test/test_app" }]
runs-on: ubuntu-20.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v3
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }}
shell: bash
run: |
. ${IDF_PATH}/export.sh
pip install idf-component-manager idf-build-apps --upgrade
python ./ci/build_apps.py ./components/eppp_link/${{matrix.test.path}} -vv --preserve-all

View File

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

View File

@ -13,20 +13,20 @@ jobs:
name: Build
strategy:
matrix:
idf_ver: ["latest", "release-v5.0"]
idf_ver: ["latest", "release-v5.0", "release-v5.2", "release-v5.3"]
test: [ { app: example, path: "examples/query_advertise" }, { app: unit_test, path: "tests/unit_test" }, { app: test_app, path: "tests/test_apps" } ]
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }}
shell: bash
run: |
. ${IDF_PATH}/export.sh
python -m pip install idf-build-apps
# Build default configs for all targets
python ./ci/build_apps.py components/mdns/${{ matrix.test.path }} -r default -m components/mdns/.build-test-rules.yml -d
python ./ci/build_apps.py components/mdns/${{ matrix.test.path }} -r default -d
# Build specific configs for test targets
python ./ci/build_apps.py components/mdns/${{ matrix.test.path }}
cd components/mdns/${{ matrix.test.path }}
@ -34,7 +34,7 @@ jobs:
$GITHUB_WORKSPACE/ci/clean_build_artifacts.sh `pwd`/$dir
zip -qur artifacts.zip $dir
done
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: mdns_bin_esp32_${{ matrix.idf_ver }}_${{ matrix.test.app }}
path: components/mdns/${{ matrix.test.path }}/artifacts.zip
@ -58,8 +58,8 @@ jobs:
steps:
- name: Clear repository
run: sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: mdns_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.test.app }}
path: components/mdns/${{ matrix.test.path }}/ci/
@ -77,7 +77,7 @@ jobs:
mv $dir build
python -m pytest --log-cli-level DEBUG --junit-xml=./results_${{ matrix.test.app }}_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${dir#"ci/build_"}.xml --target=${{ matrix.idf_target }}
done
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
if: always()
with:
name: results_${{ matrix.test.app }}_${{ matrix.idf_target }}_${{ matrix.idf_ver }}.xml

View File

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

View File

@ -8,38 +8,34 @@ on:
types: [opened, synchronize, reopened, labeled]
jobs:
build_esp_modem:
build_esp_modem_examples:
if: contains(github.event.pull_request.labels.*.name, 'modem') || github.event_name == 'push'
name: Build
name: Build examples
strategy:
matrix:
idf_ver: ["latest", "release-v4.2", "release-v4.3", "release-v4.4", "release-v5.0"]
idf_ver: ["latest", "release-v4.4", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3"]
example: ["pppos_client", "modem_console", "modem_tcp_client", "ap_to_pppos", "simple_cmux_client"]
exclude:
- idf_ver: "release-v4.2"
example: simple_cmux_client
- idf_ver: "release-v4.2"
example: modem_tcp_client
- idf_ver: "release-v4.3"
example: modem_tcp_client
- idf_ver: "release-v4.4"
example: modem_tcp_client
include:
- idf_ver: "release-v4.2"
skip_config: usb
- idf_ver: "release-v4.3"
skip_config: usb
- idf_ver: "release-v5.0"
example: "simple_cmux_client"
warning: "Warning: The smallest app partition is nearly full"
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
- name: Check out code (v3) # @v4 failed due to Node 20's requirement, incompatible with older IDF versions
if: matrix.idf_ver != 'latest' && matrix.idf_ver < 'release-v5.0'
uses: actions/checkout@v3
with:
path: protocols
- name: Check out code (v4)
if: matrix.idf_ver == 'latest' || matrix.idf_ver >= 'release-v5.0'
uses: actions/checkout@v4
with:
path: protocols
- if: ${{ matrix.skip_config }}
run: rm -f $GITHUB_WORKSPACE/protocols/components/esp_modem/examples/${{ matrix.example }}/sdkconfig.ci.${{ matrix.skip_config }}*
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }}
@ -50,16 +46,57 @@ jobs:
. ${IDF_PATH}/export.sh
python -m pip install idf-build-apps
cd $GITHUB_WORKSPACE/protocols
python ./ci/build_apps.py components/esp_modem/examples/${{ matrix.example }} -m components/esp_modem/examples/.build-test-rules.yml
python ./ci/build_apps.py components/esp_modem/examples/${{ matrix.example }} -m components/esp_modem/.build-test-rules.yml
build_esp_modem_tests:
if: contains(github.event.pull_request.labels.*.name, 'modem') || github.event_name == 'push'
name: Build tests
strategy:
matrix:
idf_ver: ["release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3", "latest"]
test: ["target", "target_ota", "target_iperf"]
runs-on: ubuntu-22.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v4
with:
path: protocols
- name: Build ${{ matrix.test }} with IDF-${{ matrix.idf_ver }}
env:
EXPECTED_WARNING: ${{ matrix.warning }}
shell: bash
run: |
. ${IDF_PATH}/export.sh
python -m pip install idf-build-apps
cd $GITHUB_WORKSPACE/protocols
python ./ci/build_apps.py components/esp_modem/test/${{ matrix.test }} -m components/esp_modem/.build-test-rules.yml
host_test_esp_modem:
if: contains(github.event.pull_request.labels.*.name, 'modem') || github.event_name == 'push'
uses: "./.github/workflows/run-host-tests.yml"
with:
idf_version: "release-v4.3"
idf_version: "latest"
app_name: "host_modem_test"
app_path: "esp-protocols/components/esp_modem/test/host_test"
component_path: "esp-protocols/components/esp_modem"
upload_artifacts: true
run_executable: true
run_coverage: true
pre_run_script: "esp-protocols/components/esp_modem/test/host_test/env.sh"
publish_unit_test_result: true
build_linux_example:
if: contains(github.event.pull_request.labels.*.name, 'modem') || github.event_name == 'push'
uses: "./.github/workflows/run-host-tests.yml"
with:
idf_version: "latest"
app_name: "linux_modem"
app_path: "esp-protocols/components/esp_modem/examples/linux_modem"
component_path: "esp-protocols/components/esp_modem"
upload_artifacts: true
run_executable: false
run_coverage: false
pre_run_script: "esp-protocols/components/esp_modem/test/host_test/env.sh"

View File

@ -15,18 +15,18 @@ jobs:
matrix:
idf_ver: ["latest"]
idf_target: ["esp32c3"]
test: [ { app: pppd, path: test/target }, { app: sim800_c3, path: examples/pppos_client }, { app: sim800_cmux, path: examples/simple_cmux_client } ]
test: [ { app: pppd, path: test/target }, { app: pppd_chap_auth, path: test/target }, { app: sim800_c3, path: examples/pppos_client }, { app: sim800_cmux, path: examples/simple_cmux_client } ]
include:
- idf_ver: "latest"
idf_target: "esp32s2"
test: { app: usb_a7670_s2, path: examples/pppos_client }
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
container: espressif/idf:${{ matrix.idf_ver }}
env:
TEST_DIR: components/esp_modem/${{ matrix.test.path }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build esp-modem target tests with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
@ -58,7 +58,7 @@ jobs:
matrix:
idf_ver: ["latest"]
idf_target: ["esp32c3"]
test: [ { app: pppd, path: test/target }, { app: sim800_c3, path: examples/pppos_client }, { app: sim800_cmux, path: examples/simple_cmux_client } ]
test: [ { app: pppd, path: test/target }, { app: pppd_chap_auth, path: test/target }, { app: sim800_c3, path: examples/pppos_client }, { app: sim800_cmux, path: examples/simple_cmux_client } ]
include:
- idf_ver: "latest"
idf_target: "esp32s2"
@ -69,9 +69,11 @@ jobs:
- modem
env:
TEST_DIR: components/esp_modem/${{ matrix.test.path }}
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
steps:
- name: Clear repository
run: sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE
run: |
sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
@ -80,4 +82,5 @@ jobs:
- name: Run Example Test on target
working-directory: ${{ env.TEST_DIR }}
run: |
python -m pip install -r $GITHUB_WORKSPACE/ci/requirements.txt
python -m pytest --log-cli-level DEBUG --target=${{ matrix.idf_target }}

73
.github/workflows/mosq__build.yml vendored Normal file
View File

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

View File

@ -13,20 +13,20 @@ jobs:
name: Build
strategy:
matrix:
idf_ver: ["latest", "release-v5.0"]
idf_ver: ["latest", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3"]
idf_target: ["esp32"]
test: [ { app: example, path: "components/esp_mqtt_cxx/examples" }]
runs-on: ubuntu-20.04
test: [ { app: mqtt-basic, path: "components/esp_mqtt_cxx/examples" }]
runs-on: ubuntu-22.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
shell: bash
working-directory: ${{matrix.test.path}}
run: |
${IDF_PATH}/install.sh --enable-pytest
. ${IDF_PATH}/export.sh
python $IDF_PATH/tools/ci/ci_build_apps.py . --target ${{ matrix.idf_target }} -vv --preserve-all --pytest-app
pip install idf-component-manager idf-build-apps --upgrade
python ../../../ci/build_apps.py ./${{ matrix.test.app }} --target ${{ matrix.idf_target }} -vv --preserve-all --pytest-app

View File

@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
ref: ${{ github.base_ref }}
fetch-depth: 20
@ -26,7 +26,7 @@ jobs:
- name: Set up Python environment
uses: actions/setup-python@master
with:
python-version: v3.7
python-version: v3.8
- name: Install python packages
run: |
pip install pre-commit

View File

@ -20,7 +20,7 @@ jobs:
if: github.repository == 'espressif/esp-protocols'
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
persist-credentials: false
fetch-depth: 0
@ -48,7 +48,7 @@ jobs:
run: |
sudo apt-get update
sudo apt-get -y install doxygen clang python3-pip
python -m pip install breathe recommonmark esp-docs==1.4.1
python -m pip install -r docs/requirements.txt
for comp in `ls components`; do
if [[ -d $GITHUB_WORKSPACE/docs/${comp} ]]; then
cd $GITHUB_WORKSPACE/docs/${comp}
@ -92,8 +92,14 @@ jobs:
components/esp_modem;
components/esp_mqtt_cxx;
components/esp_websocket_client;
components/eppp_link;
components/mdns;
components/console_simple_init;
components/console_cmd_ping;
components/console_cmd_ifconfig;
components/console_cmd_wifi;
components/mbedtls_cxx;
components/mosquitto;
components/sock_utils;
namespace: "espressif"
api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }}

View File

@ -18,6 +18,12 @@ on:
upload_artifacts:
type: boolean
required: true
run_executable:
type: boolean
required: true
run_coverage:
type: boolean
required: true
pre_run_script:
type: string
required: false
@ -28,14 +34,14 @@ on:
jobs:
build:
name: Build App
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
permissions:
checks: write
contents: write
container: espressif/idf:${{inputs.idf_version}}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
path: esp-protocols
- name: Build ${{ inputs.app_name }} with IDF-${{ inputs.idf_version }}
@ -51,7 +57,11 @@ jobs:
# The sdkconfig.ci.linux specifies Linux as the build target with apropriate settings.
cp sdkconfig.ci.linux sdkconfig.defaults
idf.py build
./build/${{inputs.app_name}}.elf -r junit -o junit.xml
if [ "${{ inputs.run_executable}}" == "false" ]; then
echo "Executeable wasn't run"
exit 0
fi
./build/${{inputs.app_name}}.elf
- name: Publish Unit Test Result
uses: EnricoMi/publish-unit-test-result-action@v2
if: ${{ inputs.publish_unit_test_result }}
@ -59,6 +69,7 @@ jobs:
files: ${{inputs.component_path}}/**/*junit.xml
- name: Build with Coverage Enabled
shell: bash
if: ${{ inputs.run_coverage }}
run: |
component=$(basename ${{ inputs.component_path }})
if [ -f "${{ inputs.pre_run_script }}" ]; then
@ -74,9 +85,12 @@ jobs:
./build/${{inputs.app_name}}.elf
- name: Run Coverage
shell: bash
if: ${{ inputs.run_coverage }}
run: |
apt-get update && apt-get install -y python3-pip rsync
python -m pip install gcovr
apt-get update && apt-get install -y rsync
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install gcovr
cd $GITHUB_WORKSPACE/${{inputs.component_path}}
component=$(basename ${{ inputs.component_path }})
gcov `find . -name "$component*gcda"`
@ -86,6 +100,7 @@ jobs:
cp index.html ${{inputs.app_name}}_coverage_report
cp -rf ${{inputs.app_name}}_coverage_report ${{inputs.app_name}}_coverage.xml $GITHUB_WORKSPACE
- name: Code Coverage Summary Report
if: ${{ inputs.run_coverage }}
uses: irongut/CodeCoverageSummary@v1.3.0
with:
filename: esp-protocols/**/${{inputs.app_name}}_coverage.xml
@ -99,9 +114,10 @@ jobs:
thresholds: '60 80'
- name: Write to Job Summary
run: cat code-coverage-results.md >> $GITHUB_STEP_SUMMARY
if: ${{ inputs.run_coverage }}
- name: Upload files to artifacts for run-target job
uses: actions/upload-artifact@v3
if: ${{inputs.upload_artifacts}}
uses: actions/upload-artifact@v4
if: ${{ inputs.run_coverage }}
with:
name: ${{inputs.app_name}}_coverage_report
path: |

95
.github/workflows/sockutls_build.yml vendored Normal file
View File

@ -0,0 +1,95 @@
name: "sock_utils: build-tests"
on:
push:
branches:
- master
pull_request:
types: [opened, synchronize, reopened, labeled]
jobs:
build_sock_utils:
if: contains(github.event.pull_request.labels.*.name, 'sock_utils') || github.event_name == 'push'
name: Socket helpers build
strategy:
matrix:
idf_ver: ["latest", "release-v5.3"]
runs-on: ubuntu-22.04
container: espressif/idf:${{ matrix.idf_ver }}
env:
TEST_DIR: components/sock_utils/examples/simple
TARGET_TEST_DIR: build_esp32_default
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build with IDF-${{ matrix.idf_ver }}
shell: bash
run: |
. ${IDF_PATH}/export.sh
pip install idf-component-manager idf-build-apps --upgrade
python ci/build_apps.py ${TEST_DIR}
cd ${TEST_DIR}
${GITHUB_WORKSPACE}/ci/clean_build_artifacts.sh `pwd`/${TARGET_TEST_DIR}
zip -qur artifacts.zip ${TARGET_TEST_DIR}
- uses: actions/upload-artifact@v4
with:
name: sock_utils_target_esp32_${{ matrix.idf_ver }}
path: ${{ env.TEST_DIR }}/artifacts.zip
if-no-files-found: error
host_test_sock_utils:
if: contains(github.event.pull_request.labels.*.name, 'sock_utils') || github.event_name == 'push'
name: Socket helpers host test
strategy:
matrix:
idf_ver: ["latest", "release-v5.3"]
runs-on: ubuntu-22.04
container: espressif/idf:${{ matrix.idf_ver }}
env:
TEST_DIR: components/sock_utils/test/host
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build with IDF-${{ matrix.idf_ver }}
shell: bash
run: |
. ${IDF_PATH}/export.sh
pip install idf-component-manager idf-build-apps --upgrade
cd ${TEST_DIR}
idf.py build
./build/sock_utils_host_test.elf
test_sock_utils:
# Skip running on forks since it won't have access to secrets
if: |
github.repository == 'espressif/esp-protocols' &&
( contains(github.event.pull_request.labels.*.name, 'sock_utils') || github.event_name == 'push' )
name: Socket helpers target test
needs: build_sock_utils
strategy:
matrix:
idf_ver: ["latest", "release-v5.3"]
runs-on:
- self-hosted
- ESP32-ETHERNET-KIT
env:
TEST_DIR: components/sock_utils/examples/simple
TARGET_TEST_DIR: build_esp32_default
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: sock_utils_target_esp32_${{ matrix.idf_ver }}
path: ${{ env.TEST_DIR }}/ci/
- name: Run Test
working-directory: ${{ env.TEST_DIR }}
run: |
unzip ci/artifacts.zip -d ci
for dir in `ls -d ci/build_*`; do
rm -rf build sdkconfig.defaults
mv $dir build
python -m pytest --log-cli-level DEBUG --junit-xml=./results_esp32_${{ matrix.idf_ver }}_${dir#"ci/build_"}.xml --target=esp32
done

30
.github/workflows/tls_cxx__build.yml vendored Normal file
View File

@ -0,0 +1,30 @@
name: "mbedtls-cxx: build-tests"
on:
push:
branches:
- master
pull_request:
types: [opened, synchronize, reopened, labeled]
jobs:
build_tls_cxx:
if: contains(github.event.pull_request.labels.*.name, 'tls_cxx') || github.event_name == 'push'
name: Build
strategy:
matrix:
idf_ver: ["latest", "release-v5.3", "release-v5.2", "release-v5.1"]
test: [ { app: client, path: "examples/tls_client" }, { app: udp, path: "examples/udp_mutual_auth" }, { app: test, path: "tests/uart_mutual_auth" } ]
runs-on: ubuntu-20.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v3
with:
submodules: recursive
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }}
shell: bash
run: |
. ${IDF_PATH}/export.sh
pip install idf-component-manager idf-build-apps --upgrade
python ./ci/build_apps.py ./components/mbedtls_cxx/${{ matrix.test.path }} -vv --preserve-all

View File

@ -17,4 +17,6 @@ jobs:
app_name: "websocket"
app_path: "esp-protocols/components/esp_websocket_client/examples/linux"
component_path: "esp-protocols/components/esp_websocket_client"
run_executable: true
upload_artifacts: true
run_coverage: true

View File

@ -13,15 +13,15 @@ jobs:
name: Build
strategy:
matrix:
idf_ver: ["release-v5.0", "release-v5.1", "latest"]
idf_ver: ["release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3", "latest"]
test: [ { app: example, path: "examples/target" }, { app: unit_test, path: "test" } ]
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
container: espressif/idf:${{ matrix.idf_ver }}
env:
TEST_DIR: components/esp_websocket_client/${{ matrix.test.path }}
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
@ -35,7 +35,7 @@ jobs:
$GITHUB_WORKSPACE/ci/clean_build_artifacts.sh `pwd`/$dir
zip -qur artifacts.zip $dir
done
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: websocket_bin_esp32_${{ matrix.idf_ver }}_${{ matrix.test.app }}
path: ${{ env.TEST_DIR }}/artifacts.zip
@ -51,7 +51,7 @@ jobs:
strategy:
fail-fast: false
matrix:
idf_ver: ["release-v5.0", "release-v5.1", "latest"]
idf_ver: ["release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3", "latest"]
idf_target: ["esp32"]
test: [ { app: example, path: "examples/target" }, { app: unit_test, path: "test" } ]
runs-on:
@ -60,8 +60,8 @@ jobs:
env:
TEST_DIR: components/esp_websocket_client/${{ matrix.test.path }}
steps:
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: websocket_bin_esp32_${{ matrix.idf_ver }}_${{ matrix.test.app }}
path: ${{ env.TEST_DIR }}/ci/
@ -79,7 +79,7 @@ jobs:
mv $dir build
python -m pytest --log-cli-level DEBUG --junit-xml=./results_${{ matrix.test.app }}_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${dir#"ci/build_"}.xml --target=${{ matrix.idf_target }}
done
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
if: always()
with:
name: results_${{ matrix.test.app }}_${{ matrix.idf_target }}_${{ matrix.idf_ver }}.xml

3
.gitmodules vendored
View File

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

View File

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

View File

@ -29,9 +29,8 @@ e.g.
## Creating a new component
Steps:
1. Add a file named .cz.yaml to the root of the component.
Once the commit containing a new component is ready follow the steps below:
1. Add a file named .cz.yaml to the root of the component and add it to your commit.
The template for .cz.yaml should look like this:
```
@ -50,6 +49,8 @@ commitizen:
Replace [component], [version] and [scope] with the specific component name, version and scope you are working with. This command will help you bump the version of the component with the provided details.
Note: It is crucial to adhere to the above steps when introducing a new component. Never merge the code for a new component without first implementing a bump commit.
## Release process
When releasing a new component version we have to:

View File

@ -41,3 +41,28 @@ Please refer to instructions in [ESP-IDF](https://github.com/espressif/esp-idf)
### console_cmd_ping
* Brief introduction [README](components/console_cmd_ping/README.md)
### console_cmd_ifconfig
* Brief introduction [README](components/console_cmd_ifconfig/README.md)
### console_cmd_wifi
* Brief introduction [README](components/console_cmd_wifi/README.md)
### ESP PPP Link (eppp)
* Brief introduction [README](components/eppp_link/README.md)
### mbedtls_cxx
* Brief introduction [README](components/mbedtls_cxx/README.md)
### mosquitto
* Brief introduction [README](components/mosquitto/README.md)
* API documentation [api.md](components/mosquitto/api.md)
### Socket helpers (sock-utils)
* Brief introduction [README](components/sock_utils/README.md)

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
"""
This file is used in CI for esp-protocols build tests
@ -17,6 +17,12 @@ if __name__ == '__main__':
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser.add_argument('paths', nargs='+', help='Paths to the apps to build.')
parser.add_argument(
'-v',
'--verbose',
action='count',
help='Increase the LOGGER level of the script. Can be specified multiple times.',
)
parser.add_argument(
'-t',
'--target',
@ -28,6 +34,8 @@ if __name__ == '__main__':
parser.add_argument('-d', '--delete', action='store_true', help='Delete build artifacts')
parser.add_argument('-c', '--recursive', action='store_true', help='Build recursively')
parser.add_argument('-l', '--linux', action='store_true', help='Include linux build (dont check warnings)')
parser.add_argument('--preserve-all', action='store_true', help='Preserve the binaries for all apps when specified.')
parser.add_argument('--pytest-apps', action='store_true', help='Only build apps required by pytest scripts.')
args = parser.parse_args()
IDF_PATH = os.environ['IDF_PATH']
@ -47,21 +55,18 @@ if __name__ == '__main__':
target=args.target,
build_dir='build_@t_@w',
config_rules_str=args.rules,
build_log_path='build_log.txt',
size_json_path='size.json' if not args.linux else None,
build_log_filename='build_log.txt',
size_json_filename='size.json' if not args.linux else None,
check_warnings=True,
preserve=not args.delete,
manifest_files=args.manifests,
default_build_targets=SUPPORTED_TARGETS,
manifest_rootpath='.',
)
for app in apps:
print(app)
sys.exit(
build_apps(apps,
dry_run=False,
keep_going=False,
no_preserve=args.delete,
ignore_warning_strs=ignore_warning)
)

View File

@ -83,13 +83,14 @@ def main():
changelog += '\n### {}\n\n'.format(sections[section])
for it in item:
changelog += '- {}\n'.format(it)
changelog += '\n'
filename = os.path.join(root_path, 'components', component, 'CHANGELOG.md')
# Check if the changelog file exists.
if not os.path.exists(filename):
# File does not exist, create it
with open(filename, 'w') as file:
file.write('# Changelog\n\n')
else:
changelog += '\n'
# insert the actual changelog to the beginning of the file, just after the title (2nd line)
with open(filename, 'r') as orig_changelog:
changelog_title = orig_changelog.readline(

View File

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

View File

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

0
ci/ignore_astyle.txt Normal file
View File

View File

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

View File

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

View File

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

View File

@ -0,0 +1,6 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#pragma once

View File

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

View File

@ -2,9 +2,5 @@
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
# (Not part of the boilerplate)
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
set(EXTRA_COMPONENT_DIRS ../.. $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(asio_chat)

View File

@ -4,3 +4,5 @@ dependencies:
espressif/asio:
version: "^1.14.1"
override_path: "../../../"
protocol_examples_common:
path: ${IDF_PATH}/examples/common_components/protocol_examples_common

View File

@ -2,9 +2,5 @@
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
# (Not part of the boilerplate)
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(async_http_request)

View File

@ -4,3 +4,5 @@ dependencies:
espressif/asio:
version: "^1.14.1"
override_path: "../../../"
protocol_examples_common:
path: ${IDF_PATH}/examples/common_components/protocol_examples_common

View File

@ -2,9 +2,5 @@
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
# (Not part of the boilerplate)
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(asio_sock4)

View File

@ -4,3 +4,5 @@ dependencies:
espressif/asio:
version: "^1.14.1"
override_path: "../../../"
protocol_examples_common:
path: ${IDF_PATH}/examples/common_components/protocol_examples_common

View File

@ -2,9 +2,6 @@
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
# (Not part of the boilerplate)
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
set(EXCLUDE_COMPONENTS openssl)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)

View File

@ -4,3 +4,5 @@ dependencies:
espressif/asio:
version: "^1.14.1"
override_path: "../../../"
protocol_examples_common:
path: ${IDF_PATH}/examples/common_components/protocol_examples_common

View File

@ -2,9 +2,5 @@
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
# (Not part of the boilerplate)
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(asio_tcp_echo_server)

View File

@ -4,3 +4,5 @@ dependencies:
espressif/asio:
version: "^1.14.1"
override_path: "../../../"
protocol_examples_common:
path: ${IDF_PATH}/examples/common_components/protocol_examples_common

View File

@ -2,9 +2,5 @@
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
# (Not part of the boilerplate)
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(asio_udp_echo_server)

View File

@ -4,3 +4,5 @@ dependencies:
espressif/asio:
version: "^1.14.1"
override_path: "../../../"
protocol_examples_common:
path: ${IDF_PATH}/examples/common_components/protocol_examples_common

View File

@ -0,0 +1,8 @@
---
commitizen:
bump_message: 'bump(console): $current_version -> $new_version'
pre_bump_hooks: python ../../ci/changelog.py console_cmd_ifconfig
tag_format: console_cmd_ifconfig-v$version
version: 1.0.1
version_files:
- idf_component.yml

View File

@ -0,0 +1,13 @@
# Changelog
## [1.0.1](https://github.com/espressif/esp-protocols/commits/console_cmd_ifconfig-v1.0.1)
### Bug Fixes
- Fixed ifconfig command for PPP interface and IPv4 only ([8548dabb](https://github.com/espressif/esp-protocols/commit/8548dabb))
## [1.0.0](https://github.com/espressif/esp-protocols/commits/console_cmd_ifconfig-v1.0.0)
### Features
- Console for runtime network interface configuration and monitoring ([8bab1420](https://github.com/espressif/esp-protocols/commit/8bab1420))

View File

@ -0,0 +1,4 @@
idf_component_register(SRCS "console_ifconfig.c"
INCLUDE_DIRS "."
PRIV_REQUIRES esp_netif console esp_eth
WHOLE_ARCHIVE)

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@ -0,0 +1,113 @@
# Console command ifconfig
The component offers a console with a command that enables runtime network interface configuration and monitoring for any example project.
## API
### Steps to enable console in an example code:
1. Add this component to your project using ```idf.py add-dependency``` command.
2. In the main file of the example, add the following line:
```c
#include "console_ifconfig.h"
```
3. Ensure esp-netif and NVS flash is initialized and default event loop is created in your app_main():
```c
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_err_t ret = nvs_flash_init(); //Initialize NVS
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
```
4. In your app_main() function, add the following line as the last line:
```c
ESP_ERROR_CHECK(console_cmd_init()); // Initialize console
// Register all plugin command added to your project
ESP_ERROR_CHECK(console_cmd_all_register());
// To register only ifconfig command skip calling console_cmd_all_register()
ESP_ERROR_CHECK(console_cmd_ifconfig_register());
ESP_ERROR_CHECK(console_cmd_start()); // Start console
```
### Adding a plugin command or component:
To add a plugin command or any component from IDF component manager into your project, simply include an entry within the `idf_component.yml` file.
For more details refer [IDF Component Manager](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-component-manager.html)
## Suported command:
### Ifconfig:
```
ifconfig help: Prints the help text for all ifconfig commands
ifconfig netif create/destroy <ethernet handle id>/<iface>: Create or destroy a network interface with the specified ethernet handle or interface name
ifconfig eth init/deinit/show: Initialize, deinitialize and display a list of available ethernet handle
ifconfig: Display a list of all esp_netif interfaces along with their information
ifconfig <iface>: Provide the details of the named interface
ifconfig <iface> default: Set the specified interface as the default interface
ifconfig <iface> ip6: Enable IPv6 on the specified interface
ifconfig <iface> up: Enable the specified interface
ifconfig <iface> down: Disable the specified interface
ifconfig <iface> link <up/down>: Enable or disable the link of the specified interface
ifconfig <iface> napt <enable/disable>: Enable or disable NAPT on the specified interface.
ifconfig <iface> ip <ipv4 addr>: Set the IPv4 address of the specified interface
ifconfig <iface> mask <ipv4 addr>: Set the subnet mask of the specified interface
ifconfig <iface> gw <ipv4 addr>: Set the default gateway of the specified interface
ifconfig <iface> staticip: Enables static ip
ifconfig <iface> dhcp server <enable/disable>: Enable or disable the DHCP server.(Note: DHCP server is not supported yet)
ifconfig <iface> dhcp client <enable/disable>: Enable or disable the DHCP client.
Note: Disabling the DHCP server and client enables the use of static IP configuration.
```
## Usage:
### Creating an ethernet interface
```
esp> ifconfig eth init
Internal(IP101): pins: 23,18, Id: 0
esp> ifconfig netif create 0
```
### Removing an interface and deinitializing ethernet
```
esp> ifconfig netif destroy en1
I (8351266) ethernet_init: Ethernet(IP101[23,18]) Link Down
I (8351266) ethernet_init: Ethernet(IP101[23,18]) Stopped
esp> ifconfig eth deinit
```
### Set default interface
```
esp> ifconfig en1 default
```
### Enable NAPT on an interface
```
esp> ifconfig en1 napt enable
I (8467116) console_ifconfig: Setting napt enable on en1
```
### Enable DHCP client on an interface
```
esp> ifconfig en1 dhcp client enable
```
### Enable static IP on an interface
```
esp> ifconfig en1 dhcp client disable
```
### Set static IP address
```
esp> ifconfig en1 ip 192.168.5.2
I (111466) console_ifconfig: Setting ip: 192.168.5.2
esp> ifconfig en1 mask 255.255.255.0
I (130946) console_ifconfig: Setting mask: 255.255.255.0
esp> ifconfig en1 gw 192.168.5.1
I (143576) console_ifconfig: Setting gw: 192.168.5.1
I (143576) esp_netif_handlers: eth ip: 192.168.5.2, mask: 255.255.255.0, gw: 192.168.5.1
```

View File

@ -0,0 +1,682 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <string.h>
#include "sdkconfig.h"
#include "lwip/inet.h"
#include "lwip/netdb.h"
#include "lwip/sockets.h"
#include "esp_netif.h"
#include "esp_eth.h"
#include "esp_console.h"
#include "esp_event.h"
#include "argtable3/argtable3.h"
#include "esp_log.h"
#include "esp_netif_net_stack.h"
#if CONFIG_LWIP_IPV6
#include "lwip/ip6.h"
#endif
#include "lwip/opt.h"
#include "ethernet_init.h"
#include "console_ifconfig.h"
#if IP_NAPT
#include "lwip/lwip_napt.h"
#endif
/**
* Static registration of this plugin is achieved by defining the plugin description
* structure and placing it into .console_cmd_desc section.
* The name of the section and its placement is determined by linker.lf file in 'plugins' component.
*/
static const console_cmd_plugin_desc_t __attribute__((section(".console_cmd_desc"), used)) PLUGIN = {
.name = "console_cmd_ifconfig",
.plugin_regd_fn = &console_cmd_ifconfig_register
};
typedef struct netif_op_t {
char *name;
esp_err_t (*operation)(struct netif_op_t *self, int argc, char *argv[], esp_netif_t *esp_netif);
int arg_cnt;
int start_index;
char *help;
int netif_flag;
} netif_op_t;
static esp_err_t ifcfg_help_op(netif_op_t *self, int argc, char *argv[], esp_netif_t *esp_netif);
static esp_err_t ifcfg_print_op(netif_op_t *self, int argc, char *argv[], esp_netif_t *esp_netif);
static esp_err_t ifcfg_lwip_op(netif_op_t *self, int argc, char *argv[], esp_netif_t *esp_netif);
static esp_err_t ifcfg_basic_op(netif_op_t *self, int argc, char *argv[], esp_netif_t *esp_netif);
static esp_err_t ifcfg_ip_op(netif_op_t *self, int argc, char *argv[], esp_netif_t *esp_netif);
static esp_err_t ifcfg_napt_op(netif_op_t *self, int argc, char *argv[], esp_netif_t *esp_netif);
static esp_err_t ifcfg_addr_op(netif_op_t *self, int argc, char *argv[], esp_netif_t *esp_netif);
static esp_err_t ifcfg_netif_op(netif_op_t *self, int argc, char *argv[], esp_netif_t *esp_netif);
static esp_err_t ifcfg_eth_op(netif_op_t *self, int argc, char *argv[], esp_netif_t *esp_netif);
static const char *TAG = "console_ifconfig";
netif_op_t cmd_list[] = {
{.name = "help", .operation = ifcfg_help_op, .arg_cnt = 2, .start_index = 1, .netif_flag = false, .help = "ifconfig help: Prints the help text for all ifconfig commands"},
{.name = "netif", .operation = ifcfg_netif_op, .arg_cnt = 4, .start_index = 1, .netif_flag = false, .help = "ifconfig netif create/destroy <ethernet handle id>/<iface>: Create or destroy a network interface with the specified ethernet handle or interface name"},
{.name = "eth", .operation = ifcfg_eth_op, .arg_cnt = 3, .start_index = 1, .netif_flag = false, .help = "ifconfig eth init/deinit/show: Initialize, deinitialize and display a list of available ethernet handle"},
{.name = "ifconfig", .operation = ifcfg_print_op, .arg_cnt = 1, .start_index = 0, .netif_flag = false, .help = "ifconfig: Display a list of all esp_netif interfaces along with their information"},
{.name = "ifconfig", .operation = ifcfg_print_op, .arg_cnt = 2, .start_index = 0, .netif_flag = true, .help = "ifconfig <iface>: Provide the details of the named interface"},
{.name = "default", .operation = ifcfg_basic_op, .arg_cnt = 3, .start_index = 2, .netif_flag = true, .help = "ifconfig <iface> default: Set the specified interface as the default interface"},
#if CONFIG_LWIP_IPV6
{.name = "ip6", .operation = ifcfg_basic_op, .arg_cnt = 3, .start_index = 2, .netif_flag = true, .help = "ifconfig <iface> ip6: Enable IPv6 on the specified interface"},
#endif
{.name = "up", .operation = ifcfg_lwip_op, .arg_cnt = 3, .start_index = 2, .netif_flag = true, .help = "ifconfig <iface> up: Enable the specified interface"},
{.name = "down", .operation = ifcfg_lwip_op, .arg_cnt = 3, .start_index = 2, .netif_flag = true, .help = "ifconfig <iface> down: Disable the specified interface"},
{.name = "link", .operation = ifcfg_lwip_op, .arg_cnt = 4, .start_index = 2, .netif_flag = true, .help = "ifconfig <iface> link <up/down>: Enable or disable the link of the specified interface"},
{.name = "napt", .operation = ifcfg_napt_op, .arg_cnt = 4, .start_index = 2, .netif_flag = true, .help = "ifconfig <iface> napt <enable/disable>: Enable or disable NAPT on the specified interface."},
{.name = "ip", .operation = ifcfg_ip_op, .arg_cnt = 4, .start_index = 2, .netif_flag = true, .help = "ifconfig <iface> ip <ipv4 addr>: Set the IPv4 address of the specified interface"},
{.name = "mask", .operation = ifcfg_ip_op, .arg_cnt = 4, .start_index = 2, .netif_flag = true, .help = "ifconfig <iface> mask <ipv4 addr>: Set the subnet mask of the specified interface"},
{.name = "gw", .operation = ifcfg_ip_op, .arg_cnt = 4, .start_index = 2, .netif_flag = true, .help = "ifconfig <iface> gw <ipv4 addr>: Set the default gateway of the specified interface"},
{.name = "staticip", .operation = ifcfg_addr_op, .arg_cnt = 3, .start_index = 2, .netif_flag = true, .help = "ifconfig <iface> staticip: Enables static ip"},
{.name = "dhcp", .operation = ifcfg_addr_op, .arg_cnt = 5, .start_index = 2, .netif_flag = true, .help = "ifconfig <iface> dhcp server <enable/disable>: Enable or disable the DHCP server.(Note: DHCP server is not supported yet)\n ifconfig <iface> dhcp client <enable/disable>: Enable or disable the DHCP client.\nNote: Disabling the DHCP server and client enables the use of static IP configuration."},
};
static esp_err_t ifcfg_help_op(netif_op_t *self, int argc, char *argv[], esp_netif_t *esp_netif)
{
int cmd_count = sizeof(cmd_list) / sizeof(cmd_list[0]);
for (int i = 0; i < cmd_count; i++) {
if ((cmd_list[i].help != NULL) && (strlen(cmd_list[i].help) != 0)) {
printf(" %s\n", cmd_list[i].help);
}
}
return ESP_OK;
}
static esp_netif_t *get_esp_netif_from_ifname(char *if_name)
{
esp_netif_t *esp_netif = NULL;
esp_err_t ret = ESP_FAIL;
char interface[10];
/* Get interface details and obtain the global IPv6 address */
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
while ((esp_netif = esp_netif_next_unsafe(esp_netif)) != NULL) {
#else
while ((esp_netif = esp_netif_next(esp_netif)) != NULL) {
#endif
ret = esp_netif_get_netif_impl_name(esp_netif, interface);
if ((ESP_FAIL == ret) || (NULL == esp_netif)) {
ESP_LOGE(TAG, "No interface available");
return NULL;
}
if (!strcmp(interface, if_name)) {
return esp_netif;
}
}
return NULL;
}
static esp_err_t ifcfg_basic_op(netif_op_t *self, int argc, char *argv[], esp_netif_t *esp_netif)
{
/* Set Default */
if (!strcmp("default", argv[self->start_index])) {
esp_netif_set_default_netif(esp_netif);
return ESP_OK;
}
#if CONFIG_LWIP_IPV6
/* Enable IPv6 on this interface */
if (!strcmp("ip6", argv[self->start_index])) {
ESP_ERROR_CHECK(esp_netif_create_ip6_linklocal(esp_netif));
return ESP_OK;
}
#endif
return ESP_FAIL;
}
static esp_err_t ifcfg_lwip_op(netif_op_t *self, int argc, char *argv[], esp_netif_t *esp_netif)
{
struct netif *lwip_netif = esp_netif_get_netif_impl(esp_netif);
if (NULL == lwip_netif) {
ESP_LOGE(TAG, "lwip interface %s not available", argv[1]);
return ESP_OK;
}
/* Enable/Disable Interface */
if (!strcmp("up", argv[self->start_index])) {
netif_set_up(lwip_netif);
return ESP_OK;
}
if (!strcmp("down", argv[self->start_index])) {
netif_set_down(lwip_netif);
return ESP_OK;
}
/* Enable/Disable link */
if (!strcmp("link", argv[self->start_index])) {
if (!strcmp("up", argv[self->start_index + 1])) {
netif_set_link_up(lwip_netif);
}
if (!strcmp("down", argv[self->start_index + 1])) {
netif_set_down(lwip_netif);
netif_set_link_down(lwip_netif);
}
return ESP_OK;
}
return ESP_FAIL;
}
static esp_err_t ifcfg_ip_op(netif_op_t *self, int argc, char *argv[], esp_netif_t *esp_netif)
{
esp_netif_ip_info_t ip_info = {0};
esp_netif_dhcpc_stop(esp_netif);
esp_netif_get_ip_info(esp_netif, &ip_info);
if (!strcmp("ip", argv[self->start_index])) {
ESP_LOGI(TAG, "Setting ip: %s", argv[self->start_index + 1]);
inet_aton(argv[self->start_index + 1], &ip_info.ip.addr);
esp_netif_set_ip_info(esp_netif, &ip_info);
return ESP_OK;
} else if (!strcmp("mask", argv[self->start_index])) {
ESP_LOGI(TAG, "Setting mask: %s", argv[self->start_index + 1]);
inet_aton(argv[self->start_index + 1], &ip_info.netmask.addr);
esp_netif_set_ip_info(esp_netif, &ip_info);
return ESP_OK;
} else if (!strcmp("gw", argv[self->start_index])) {
ESP_LOGI(TAG, "Setting gw: %s", argv[self->start_index + 1]);
inet_aton(argv[self->start_index + 1], &ip_info.gw.addr);
esp_netif_set_ip_info(esp_netif, &ip_info);
return ESP_OK;
}
return ESP_FAIL;
}
#if IP_NAPT
static esp_err_t set_napt(char *if_name, bool state)
{
esp_netif_t *esp_netif = NULL;
esp_err_t ret = ESP_FAIL;
char interface[10];
/* Get interface details and own global ipv6 address */
for (int i = 0; i < esp_netif_get_nr_of_ifs(); ++i) {
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
esp_netif = esp_netif_next_unsafe(esp_netif);
#else
esp_netif = esp_netif_next(esp_netif);
#endif
ret = esp_netif_get_netif_impl_name(esp_netif, interface);
if ((ESP_FAIL == ret) || (NULL == esp_netif)) {
ESP_LOGE(TAG, "No interface available");
return ESP_FAIL;
}
if (!strcmp(interface, if_name)) {
return esp_netif_napt_enable(esp_netif);
}
}
return ESP_FAIL;
}
#endif
static esp_err_t ifcfg_napt_op(netif_op_t *self, int argc, char *argv[], esp_netif_t *esp_netif)
{
#if IP_NAPT
if (!strcmp("napt", argv[self->start_index])) {
ESP_LOGI(TAG, "Setting napt %s on %s", argv[self->start_index + 1], argv[1]);
if (!strcmp(argv[self->start_index + 1], "enable")) {
return set_napt(argv[1], true);
} else if (!strcmp(argv[self->start_index + 1], "disable")) {
return set_napt(argv[1], false);
} else {
ESP_LOGI(TAG, "Invalid argument: %s", argv[self->start_index + 1]);
}
return ESP_FAIL;
}
#endif
ESP_LOGE(TAG, "NAPT not enabled in menuconfig");
return ESP_OK;
}
static esp_err_t ifcfg_addr_op(netif_op_t *self, int argc, char *argv[], esp_netif_t *esp_netif)
{
if (!strcmp("staticip", argv[self->start_index])) {
esp_netif_dhcpc_stop(esp_netif);
//esp_netif_dhcps_stop(esp_netif);
return ESP_OK;
} else if (!strcmp("server", argv[self->start_index + 1])) { // Server
if (!strcmp("enable", argv[self->start_index + 2])) {
ESP_LOGW(TAG, "DHCP Server configuration is not supported yet."); // TBD
//esp_netif_dhcps_start(esp_netif);
return ESP_OK;
} else if (!strcmp("disable", argv[self->start_index + 2])) {
ESP_LOGW(TAG, "DHCP Server configuration is not supported yet."); // TBD
//esp_netif_dhcps_stop(esp_netif);
return ESP_OK;
}
ESP_LOGE(TAG, "Invalid argument");
return ESP_FAIL;
} else if (!strcmp("client", argv[self->start_index + 1])) { // Client
if (!strcmp("enable", argv[self->start_index + 2])) {
esp_netif_dhcpc_start(esp_netif);
return ESP_OK;
} else if (!strcmp("disable", argv[self->start_index + 2])) {
esp_netif_dhcpc_stop(esp_netif);
return ESP_OK;
}
ESP_LOGE(TAG, "Invalid argument");
return ESP_FAIL;
}
return ESP_FAIL;
}
static void print_iface_details(esp_netif_t *esp_netif)
{
esp_netif_ip_info_t ip_info;
uint8_t mac[NETIF_MAX_HWADDR_LEN];
char interface[10];
#if CONFIG_LWIP_IPV6
int ip6_addrs_count = 0;
esp_ip6_addr_t ip6[LWIP_IPV6_NUM_ADDRESSES];
#endif
esp_err_t ret = ESP_FAIL;
esp_netif_dhcp_status_t status;
struct netif *lwip_netif = esp_netif_get_netif_impl(esp_netif);
/* Print Interface Name and Number */
ret = esp_netif_get_netif_impl_name(esp_netif, interface);
if ((ESP_FAIL == ret) || (NULL == esp_netif)) {
ESP_LOGE(TAG, "No interface available");
return;
}
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0)
if (esp_netif_get_default_netif() == esp_netif) {
ESP_LOGI(TAG, "Interface Name: %s (DEF)", interface);
} else {
ESP_LOGI(TAG, "Interface Name: %s", interface);
}
#else
ESP_LOGI(TAG, "Interface Name: %s", interface);
#endif
if (lwip_netif != NULL) {
ESP_LOGI(TAG, "Interface Number: %d", lwip_netif->num);
}
/* Print MAC address */
esp_netif_get_mac(esp_netif, mac);
ESP_LOGI(TAG, "MAC: %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1],
mac[2], mac[3], mac[4], mac[5]);
/* Print DHCP status */
if (ESP_OK == esp_netif_dhcps_get_status(esp_netif, &status)) {
ESP_LOGI(TAG, "DHCP Server Status: %s", (status == ESP_NETIF_DHCP_STARTED) || (status == ESP_NETIF_DHCP_STOPPED) ? "enabled" : "disabled");
} else if ((ESP_OK == esp_netif_dhcpc_get_status(esp_netif, &status))) {
if (ESP_NETIF_DHCP_STOPPED == status) {
ESP_LOGI(TAG, "Static IP");
} else {
ESP_LOGI(TAG, "DHCP Client Status: %s", status ? "enabled" : "disabled");
}
}
/* Print IP Info */
esp_netif_get_ip_info(esp_netif, &ip_info);
ESP_LOGI(TAG, "IP: " IPSTR ", MASK: " IPSTR ", GW: " IPSTR, IP2STR(&(ip_info.ip)), IP2STR(&(ip_info.netmask)), IP2STR(&(ip_info.gw)));
#if IP_NAPT
/* Print NAPT status*/
if (lwip_netif != NULL) {
ESP_LOGI(TAG, "NAPT: %s", lwip_netif->napt ? "enabled" : "disabled");
}
#endif
#if CONFIG_LWIP_IPV6
/* Print IPv6 Address */
ip6_addrs_count = esp_netif_get_all_ip6(esp_netif, ip6);
for (int j = 0; j < ip6_addrs_count; ++j) {
ESP_LOGI(TAG, "IPv6 address: " IPV6STR, IPV62STR(ip6[j]));
}
#endif
/* Print Interface and Link Status*/
ESP_LOGI(TAG, "Interface Status: %s", esp_netif_is_netif_up(esp_netif) ? "UP" : "DOWN");
if (lwip_netif != NULL) {
ESP_LOGI(TAG, "Link Status: %s", netif_is_link_up(lwip_netif) ? "UP" : "DOWN");
}
ESP_LOGI(TAG, "");
}
static esp_err_t ifcfg_print_op(netif_op_t *self, int argc, char *argv[], esp_netif_t *esp_netif)
{
/* Print interface details */
if (2 == argc) {
print_iface_details(esp_netif);
return ESP_OK;
}
/* Get interface details and own global ipv6 address of all interfaces */
for (int i = 0; i < esp_netif_get_nr_of_ifs(); ++i) {
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
esp_netif = esp_netif_next_unsafe(esp_netif);
#else
esp_netif = esp_netif_next(esp_netif);
#endif
print_iface_details(esp_netif);
}
return ESP_OK;
}
/* Maximum number of interface that can be added */
#define MAX_ETH_NETIF_COUNT (10)
typedef enum {
UNINITIALIZED = 0,
ETH_INITIALIZED = 1,
NETIF_CREATED = 2,
NETIF_DESTROYED = 3,
ETH_DEINITIALIZED = 4
} iface_state;
typedef struct {
esp_netif_t *esp_netif;
esp_eth_handle_t *eth_handle;
esp_eth_netif_glue_handle_t eth_glue;
iface_state state;
} iface_desc;
static iface_desc iface_list[MAX_ETH_NETIF_COUNT];
static uint8_t netif_count;
static uint8_t eth_init_flag = false;
static uint8_t eth_port_cnt_g = 0;
static esp_err_t get_netif_config(uint16_t id, esp_netif_config_t *eth_cfg_o)
{
/* Create new default instance of esp-netif for Ethernet */
char *if_key;
if (asprintf(&if_key, "IFC_ETH%d", id) == -1) {
return ESP_FAIL;
}
esp_netif_inherent_config_t *esp_eth_base_config = malloc(sizeof(esp_netif_inherent_config_t));
if (NULL == esp_eth_base_config) {
return ESP_FAIL;
}
*esp_eth_base_config = (esp_netif_inherent_config_t)ESP_NETIF_INHERENT_DEFAULT_ETH();
esp_eth_base_config->if_key = if_key;
eth_cfg_o->base = esp_eth_base_config;
eth_cfg_o->driver = NULL;
eth_cfg_o->stack = ESP_NETIF_NETSTACK_DEFAULT_ETH;
return ESP_OK;
}
static void free_config(esp_netif_config_t *eth_cfg)
{
if ((NULL != eth_cfg) && (NULL != eth_cfg->base)) {
free((void *)(eth_cfg->base->if_key));
free((void *)(eth_cfg->base));
}
}
static esp_err_t ifcfg_netif_op(netif_op_t *self, int argc, char *argv[], esp_netif_t *esp_netif)
{
int eth_handle_id = atoi(argv[self->start_index + 2]);
if (!strcmp(argv[self->start_index + 1], "create")) {
/* Validate ethernet handle */
if ((eth_handle_id + 1 > eth_port_cnt_g) || (eth_handle_id < 0)) {
ESP_LOGE(TAG, "Invalid ethernet handle: %s", argv[self->start_index + 2]);
return ESP_FAIL;
}
esp_netif_config_t eth_cfg;
ESP_ERROR_CHECK(get_netif_config(eth_handle_id, &eth_cfg));
for (int i = 0; i < MAX_ETH_NETIF_COUNT; i++) {
if (iface_list[i].state == ETH_INITIALIZED) {
esp_netif = esp_netif_new(&eth_cfg);
if (esp_netif == NULL) {
ESP_LOGE(TAG, "Interface with key %s already exists", argv[self->start_index + 2]);
return ESP_FAIL;
}
iface_list[i].eth_glue = esp_eth_new_netif_glue(iface_list[i].eth_handle);
if (iface_list[i].eth_glue == NULL) {
ESP_LOGE(TAG, "%s: eth_glue is NULL", __func__);
esp_netif_destroy(esp_netif);
return ESP_FAIL;
}
iface_list[i].esp_netif = esp_netif;
ESP_ERROR_CHECK(esp_netif_attach(iface_list[i].esp_netif, iface_list[i].eth_glue));
// start Ethernet driver state machine
ESP_ERROR_CHECK(esp_eth_start(iface_list[i].eth_handle));
free_config(&eth_cfg);
iface_list[i].state = NETIF_CREATED;
netif_count++;
break;
}
}
return ESP_OK;
} else if (!strcmp(argv[self->start_index + 1], "destroy")) {
esp_netif = get_esp_netif_from_ifname(argv[self->start_index + 2]);
if (NULL == esp_netif) {
ESP_LOGE(TAG, "interface %s not available", argv[1]);
return ESP_FAIL;
}
for (int i = 0; i < MAX_ETH_NETIF_COUNT; i++) {
if (esp_netif == iface_list[i].esp_netif) {
if (iface_list[i].state == NETIF_CREATED) {
esp_eth_stop(iface_list[i].eth_handle);
esp_eth_del_netif_glue(iface_list[i].eth_glue);
esp_netif_destroy(iface_list[i].esp_netif);
iface_list[i].state = NETIF_DESTROYED;
netif_count--;
return ESP_OK;
} else {
ESP_LOGE(TAG, "Netif is not in created state");
return ESP_FAIL;
}
break;
}
}
ESP_LOGE(TAG, "Something is very wrong. Unauthorized Interface.");
return ESP_FAIL;
}
return ESP_FAIL;
}
static void print_eth_info(eth_dev_info_t eth_info, int id)
{
if (eth_info.type == ETH_DEV_TYPE_INTERNAL_ETH) {
printf("Internal(%s): pins: %2d,%2d, Id: %d\n", eth_info.name, eth_info.pin.eth_internal_mdc, eth_info.pin.eth_internal_mdio, id);
} else if (eth_info.type == ETH_DEV_TYPE_SPI) {
printf(" SPI(%s): pins: %2d,%2d, Id: %d\n", eth_info.name, eth_info.pin.eth_spi_cs, eth_info.pin.eth_spi_int, id);
} else {
printf("ethernet handle id(ETH_DEV_TYPE_UNKNOWN): %d\n", id);
}
}
static esp_err_t ifcfg_eth_op(netif_op_t *self, int argc, char *argv[], esp_netif_t *esp_netif)
{
static esp_eth_handle_t *eth_handle_g = NULL;
eth_dev_info_t eth_info;
if (!strcmp(argv[self->start_index + 1], "init")) {
/* Check if ethernet is initialized */
if (eth_init_flag == false) {
// Initialize Ethernet driver
if (ethernet_init_all(&eth_handle_g, &eth_port_cnt_g) != ESP_OK) {
ESP_LOGE(TAG, "Unable to initialize ethernet");
return ESP_FAIL;
}
eth_init_flag = true;
for (int i = 0; i < eth_port_cnt_g; i++) {
for (int j = 0; j < MAX_ETH_NETIF_COUNT; j++) {
if (iface_list[j].state == UNINITIALIZED) {
iface_list[j].eth_handle = eth_handle_g[i];
iface_list[j].state = ETH_INITIALIZED;
break;
}
}
}
if (eth_port_cnt_g > MAX_ETH_NETIF_COUNT) {
ESP_LOGW(TAG, "Not all ethernet ports can be assigned a network interface.\nPlease reconfigure MAX_ETH_NETIF_COUNT to a higher value.");
}
} else {
ESP_LOGW(TAG, "Ethernet already initialized");
}
/* Display available ethernet handles */
for (int i = 0; i < eth_port_cnt_g; i++) {
eth_info = ethernet_init_get_dev_info(iface_list[i].eth_handle);
print_eth_info(eth_info, i);
}
} else if (!strcmp(argv[self->start_index + 1], "show")) {
/* Check if ethernet is initialized */
if (eth_init_flag == false) {
// Initialize Ethernet driver
ESP_LOGE(TAG, "Ethernet is not initialized.");
return ESP_OK;
}
/* Display available ethernet handles */
for (int i = 0; i < eth_port_cnt_g; i++) {
eth_info = ethernet_init_get_dev_info(iface_list[i].eth_handle);
print_eth_info(eth_info, i);
}
} else if (!strcmp(argv[self->start_index + 1], "deinit")) {
/* Check if ethernet is initialized */
if (eth_init_flag == false) {
// Initialize Ethernet driver
ESP_LOGE(TAG, "Ethernet is not initialized.");
return ESP_OK;
}
/* Stop and Deinit ethernet here */
ethernet_deinit_all(eth_handle_g);
eth_port_cnt_g = 0;
eth_init_flag = false;
} else {
return ESP_FAIL;
}
return ESP_OK;
}
/* handle 'ifconfig' command */
static int do_cmd_ifconfig(int argc, char **argv)
{
esp_netif_t *esp_netif = NULL;
int cmd_count = sizeof(cmd_list) / sizeof(cmd_list[0]);
netif_op_t cmd;
for (int i = 0; i < cmd_count; i++) {
cmd = cmd_list[i];
if (argc < cmd.start_index + 1) {
continue;
}
if (!strcmp(cmd.name, argv[cmd.start_index])) {
/* Get interface for eligible commands */
if (cmd.netif_flag == true) {
esp_netif = get_esp_netif_from_ifname(argv[1]);
if (NULL == esp_netif) {
ESP_LOGE(TAG, "interface %s not available", argv[1]);
return 0;
}
}
if (cmd.arg_cnt == argc) {
if (cmd.operation != NULL) {
if (cmd.operation(&cmd, argc, argv, esp_netif) != ESP_OK) {
ESP_LOGE(TAG, "Usage:\n%s", cmd.help);
return 0;
}
}
return 0;
}
}
}
ESP_LOGE(TAG, "Command not available");
return 1;
}
/**
* @brief Registers the ifconfig command.
*
* @return
* - esp_err_t
*/
esp_err_t console_cmd_ifconfig_register(void)
{
esp_err_t ret;
esp_console_cmd_t command = {
.command = "ifconfig",
.help = "Command for network interface configuration and monitoring\nFor more info run 'ifconfig help'",
.func = &do_cmd_ifconfig
};
ret = esp_console_cmd_register(&command);
if (ret) {
ESP_LOGE(TAG, "Unable to register ifconfig");
}
return ret;
}

View File

@ -0,0 +1,25 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "console_simple_init.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Registers the ifconfig command.
*
* @return
* - esp_err_t
*/
esp_err_t console_cmd_ifconfig_register(void);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,8 @@
# For more information about build system see
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(ifconfig-basic)

View File

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

View File

@ -0,0 +1,6 @@
dependencies:
idf:
version: ">=5.0"
console_cmd_ifconfig:
version: "*"
override_path: '../../../'

View File

@ -0,0 +1,33 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdio.h>
#include "esp_netif.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "esp_event.h"
#include "console_ifconfig.h"
void app_main(void)
{
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_err_t ret = nvs_flash_init(); //Initialize NVS
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
// Initialize console REPL
ESP_ERROR_CHECK(console_cmd_init());
ESP_ERROR_CHECK(console_cmd_ifconfig_register());
// start console REPL
ESP_ERROR_CHECK(console_cmd_start());
}

View File

@ -0,0 +1,21 @@
# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Unlicense OR CC0-1.0
# -*- coding: utf-8 -*-
import pytest
@pytest.mark.esp32
def test_examples_ifconfig_command(dut):
dut.expect('esp>', timeout=30)
dut.write('ifconfig eth init')
dut.expect(r'Internal\(IP101\): pins:', timeout=30)
dut.write('ifconfig netif create 0')
dut.expect(r'ethernet_init: Ethernet\(IP101\[23,18\]\) Link Up', timeout=30)
dut.write('ifconfig')
dut.expect('console_ifconfig: Interface Name: en1', timeout=5)
dut.write('ifconfig netif destroy en1')
dut.expect('esp>', timeout=5)
dut.write('ifconfig eth deinit')
dut.expect('esp>', timeout=5)
pass

View File

@ -0,0 +1,12 @@
version: 1.0.1
url: https://github.com/espressif/esp-protocols/tree/master/components/console_cmd_ifconfig
description: The component offers a console that enables runtime network interface configuration and monitoring.
dependencies:
idf:
version: '>=5.0'
espressif/console_simple_init:
version: '>=1.1.0'
override_path: '../console_simple_init'
public: true
espressif/ethernet_init:
version: '>=0.0.7'

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,23 @@
# Changelog
## [1.1.0](https://github.com/espressif/esp-protocols/commits/console_cmd_wifi-v1.1.0)
### Features
- Added support to join pre-configured network ([bdbf16c1](https://github.com/espressif/esp-protocols/commit/bdbf16c1))
## [1.0.1](https://github.com/espressif/esp-protocols/commits/console_cmd_wifi-v1.0.1)
### Features
- Console for runtime wifi configuration ([194d1179](https://github.com/espressif/esp-protocols/commit/194d1179))
### Bug Fixes
- Fixed license file for console_cmd_wifi ([8285e973](https://github.com/espressif/esp-protocols/commit/8285e973))
## [1.0.0](https://github.com/espressif/esp-protocols/commits/console_cmd_wifi-v1.0.0)
### Features
- Console for runtime wifi configuration ([194d1179](https://github.com/espressif/esp-protocols/commit/194d1179))

View File

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

View File

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

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@ -0,0 +1,48 @@
# Console command wifi
The component offers a console with a command that enables runtime wifi configuration for any example project.
## API
### Steps to enable console in an example code:
1. Add this component to your project using ```idf.py add-dependency``` command.
2. In the main file of the example, add the following line:
```c
#include "console_wifi.h"
```
3. Ensure esp-netif and NVS flash is initialized and default event loop is created in your app_main():
```c
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_err_t ret = nvs_flash_init(); //Initialize NVS
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
```
4. In your app_main() function, add the following line as the last line:
```c
ESP_ERROR_CHECK(console_cmd_init()); // Initialize console
// Register all plugin command added to your project
ESP_ERROR_CHECK(console_cmd_all_register());
// To register only wifi command skip calling console_cmd_all_register()
ESP_ERROR_CHECK(console_cmd_wifi_register());
ESP_ERROR_CHECK(console_cmd_start()); // Start console
```
Note: Auto-registration of a specific plugin command can be disabled from menuconfig.
## Suported command:
### wifi:
```
wifi help: Prints the help text for all wifi commands
wifi show network/sta: Scans and displays all available wifi APs./ Shows the details of wifi station.
wifi sta join <network ssid> <password>: Station joins the given wifi network.
wifi sta join <network ssid>: Station joins the given unsecured wifi network.
wifi sta join: Station joins the pre-configured wifi network.
wifi sta leave: Station leaves the wifi network.
```

View File

@ -0,0 +1,284 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <string.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "esp_netif.h"
#include "esp_console.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_netif_net_stack.h"
#include "lwip/ip6.h"
#include "lwip/opt.h"
#include "esp_wifi.h"
#include "console_wifi.h"
#define DEFAULT_SCAN_LIST_SIZE 10
#if CONFIG_WIFI_CMD_AUTO_REGISTRATION
/**
* Static registration of this plugin is achieved by defining the plugin description
* structure and placing it into .console_cmd_desc section.
* The name of the section and its placement is determined by linker.lf file in 'plugins' component.
*/
static const console_cmd_plugin_desc_t __attribute__((section(".console_cmd_desc"), used)) PLUGIN = {
.name = "console_cmd_wifi",
.plugin_regd_fn = &console_cmd_wifi_register
};
#endif
typedef struct wifi_op_t {
char *name;
esp_err_t (*operation)(struct wifi_op_t *self, int argc, char *argv[]);
int arg_cnt;
int start_index;
char *help;
} wifi_op_t;
static esp_err_t wifi_help_op(wifi_op_t *self, int argc, char *argv[]);
static esp_err_t wifi_show_op(wifi_op_t *self, int argc, char *argv[]);
static esp_err_t wifi_sta_join_op(wifi_op_t *self, int argc, char *argv[]);
static esp_err_t wifi_sta_leave_op(wifi_op_t *self, int argc, char *argv[]);
static const char *TAG = "console_wifi";
#define JOIN_TIMEOUT_MS (10000)
static EventGroupHandle_t wifi_event_group;
static const int STA_STARTED_BIT = BIT0;
static const int CONNECTED_BIT = BIT1;
static wifi_op_t cmd_list[] = {
{.name = "help", .operation = wifi_help_op, .arg_cnt = 2, .start_index = 1, .help = "wifi help: Prints the help text for all wifi commands"},
{.name = "show", .operation = wifi_show_op, .arg_cnt = 3, .start_index = 1, .help = "wifi show network/sta: Scans and displays all available wifi APs./ Shows the details of wifi station."},
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 5, .start_index = 2, .help = "wifi sta join <network ssid> <password>: Station joins the given wifi network."},
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 4, .start_index = 2, .help = "wifi sta join <network ssid>: Station joins the given unsecured wifi network."},
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 3, .start_index = 2, .help = "wifi sta join: Station joins the pre-configured wifi network."},
{.name = "leave", .operation = wifi_sta_leave_op, .arg_cnt = 3, .start_index = 2, .help = "wifi sta leave: Station leaves the wifi network."},
};
static void event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
xEventGroupSetBits(wifi_event_group, STA_STARTED_BIT);
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
esp_wifi_connect();
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
}
}
static esp_err_t wifi_help_op(wifi_op_t *self, int argc, char *argv[])
{
int cmd_count = sizeof(cmd_list) / sizeof(cmd_list[0]);
for (int i = 0; i < cmd_count; i++) {
if ((cmd_list[i].help != NULL) && (strlen(cmd_list[i].help) != 0)) {
printf(" %s\n", cmd_list[i].help);
}
}
return ESP_OK;
}
uint8_t wifi_connection_status = 0;
void wifi_init(void)
{
static bool init_flag = false;
if (init_flag) {
return;
}
wifi_event_group = xEventGroupCreate();
esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
assert(sta_netif);
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_START, &event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_start());
int bits = xEventGroupWaitBits(wifi_event_group, STA_STARTED_BIT,
pdFALSE, pdTRUE, JOIN_TIMEOUT_MS / portTICK_PERIOD_MS);
if ((bits & STA_STARTED_BIT) == 0) {
ESP_LOGE(TAG, "Error: Wifi Connection timed out");
return;
}
init_flag = true;
}
/* Initialize Wi-Fi as sta and set scan method */
static void wifi_scan(void)
{
uint16_t number = DEFAULT_SCAN_LIST_SIZE;
wifi_ap_record_t ap_info[DEFAULT_SCAN_LIST_SIZE];
uint16_t ap_count = 0;
memset(ap_info, 0, sizeof(ap_info));
wifi_init();
esp_wifi_scan_start(NULL, true);
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&number, ap_info));
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(&ap_count));
ESP_LOGI(TAG, "Showing Wifi networks");
ESP_LOGI(TAG, "*********************");
for (int i = 0; i < number; i++) {
ESP_LOGI(TAG, "RSSI: %d\tChannel: %d\tSSID: %s", ap_info[i].rssi, ap_info[i].primary, ap_info[i].ssid);
}
ESP_LOGI(TAG, "Total APs scanned = %u, actual AP number ap_info holds = %u", ap_count, number);
}
static esp_err_t wifi_show_op(wifi_op_t *self, int argc, char *argv[])
{
if (!strcmp("network", argv[self->start_index + 1])) {
wifi_scan();
return ESP_OK;
}
if (!strcmp("sta", argv[self->start_index + 1])) {
{
wifi_config_t wifi_config = { 0 };
wifi_init();
ESP_ERROR_CHECK(esp_wifi_get_config(WIFI_IF_STA, &wifi_config));
ESP_LOGI(TAG, "Showing Joind AP details:");
ESP_LOGI(TAG, "*************************");
ESP_LOGI(TAG, "SSID: %s", wifi_config.sta.ssid);
ESP_LOGI(TAG, "Channel: %d", wifi_config.sta.channel);
ESP_LOGI(TAG, "bssid: %02x:%02x:%02x:%02x:%02x:%02x", wifi_config.sta.bssid[0],
wifi_config.sta.bssid[1], wifi_config.sta.bssid[2], wifi_config.sta.bssid[3],
wifi_config.sta.bssid[4], wifi_config.sta.bssid[5]);
}
return ESP_OK;
}
return ESP_OK;
}
static esp_err_t wifi_sta_join_op(wifi_op_t *self, int argc, char *argv[])
{
wifi_config_t wifi_config = { 0 };
if (strcmp("sta", argv[self->start_index - 1])) {
ESP_LOGE(TAG, "Error: Invalid command\n");
ESP_LOGE(TAG, "%s\n", self->help);
return ESP_FAIL;
}
if (self->arg_cnt == 3) {
strlcpy((char *) wifi_config.sta.ssid, CONFIG_WIFI_CMD_NETWORK_SSID, sizeof(wifi_config.sta.ssid));
strlcpy((char *) wifi_config.sta.password, CONFIG_WIFI_CMD_NETWORK_PASSWORD, sizeof(wifi_config.sta.password));
} else {
strlcpy((char *) wifi_config.sta.ssid, argv[self->start_index + 1], sizeof(wifi_config.sta.ssid));
}
if (self->arg_cnt == 5) {
strlcpy((char *) wifi_config.sta.password, argv[self->start_index + 2], sizeof(wifi_config.sta.password));
}
wifi_init();
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
esp_wifi_connect();
int bits = xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
pdFALSE, pdTRUE, JOIN_TIMEOUT_MS / portTICK_PERIOD_MS);
if ((bits & CONNECTED_BIT) == 0) {
ESP_LOGE(TAG, "Error: Wifi Connection timed out");
return ESP_OK;
}
return ESP_OK;
}
static esp_err_t wifi_sta_leave_op(wifi_op_t *self, int argc, char *argv[])
{
wifi_config_t wifi_config = { 0 };
if (strcmp("sta", argv[self->start_index - 1])) {
ESP_LOGE(TAG, "Error: Invalid command\n");
ESP_LOGE(TAG, "%s\n", self->help);
return ESP_FAIL;
}
esp_wifi_disconnect();
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
return ESP_OK;
}
/* handle 'wifi' command */
static esp_err_t do_cmd_wifi(int argc, char **argv)
{
int cmd_count = sizeof(cmd_list) / sizeof(cmd_list[0]);
wifi_op_t cmd;
for (int i = 0; i < cmd_count; i++) {
cmd = cmd_list[i];
if (argc < cmd.start_index + 1) {
continue;
}
if (!strcmp(cmd.name, argv[cmd.start_index])) {
/* Get interface for eligible commands */
if (cmd.arg_cnt == argc) {
if (cmd.operation != NULL) {
if (cmd.operation(&cmd, argc, argv) != ESP_OK) {
ESP_LOGE(TAG, "Usage:\n%s", cmd.help);
return 0;
}
}
return ESP_OK;
}
}
}
ESP_LOGE(TAG, "Command not available");
return ESP_OK;
}
/**
* @brief Registers the wifi command.
*
* @return
* - esp_err_t
*/
esp_err_t console_cmd_wifi_register(void)
{
esp_err_t ret = ESP_OK;
esp_console_cmd_t command = {
.command = "wifi",
.help = "Command for wifi configuration and monitoring\n For more info run 'wifi help'",
.func = &do_cmd_wifi
};
ret = esp_console_cmd_register(&command);
if (ret) {
ESP_LOGE(TAG, "Unable to register wifi");
}
return ret;
}

View File

@ -0,0 +1,8 @@
# For more information about build system see
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(wifi-basic)

View File

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

View File

@ -0,0 +1,6 @@
dependencies:
idf:
version: ">=5.0"
console_cmd_wifi:
version: "*"
override_path: '../../../'

View File

@ -0,0 +1,32 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdio.h>
#include "esp_netif.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "esp_event.h"
#include "console_wifi.h"
void app_main(void)
{
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_err_t ret = nvs_flash_init(); //Initialize NVS
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
// Initialize console REPL
ESP_ERROR_CHECK(console_cmd_init());
ESP_ERROR_CHECK(console_cmd_wifi_register());
// start console REPL
ESP_ERROR_CHECK(console_cmd_start());
}

View File

@ -0,0 +1,14 @@
# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Unlicense OR CC0-1.0
# -*- coding: utf-8 -*-
import pytest
@pytest.mark.esp32
def test_examples_ifconfig_command(dut):
dut.expect('esp>', timeout=30)
dut.write('wifi show network')
dut.expect(r'Showing Wifi networks', timeout=30)
dut.expect('esp>', timeout=30)

View File

@ -0,0 +1,10 @@
version: 1.1.0
url: https://github.com/espressif/esp-protocols/tree/master/components/console_cmd_wifi
description: The component offers a console that enables runtime wifi configuration and monitoring.
dependencies:
idf:
version: '>=5.0'
espressif/console_simple_init:
version: '>=1.1.0'
override_path: '../console_simple_init'
public: true

View File

@ -0,0 +1,25 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "console_simple_init.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Registers the wifi command.
*
* @return
* - esp_err_t
*/
esp_err_t console_cmd_wifi_register(void);
#ifdef __cplusplus
}
#endif

View File

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

View File

@ -0,0 +1,39 @@
# Changelog
## [0.2.0](https://github.com/espressif/esp-protocols/commits/eppp-v0.2.0)
### Features
- Add support for SDIO transport ([085dd790](https://github.com/espressif/esp-protocols/commit/085dd790))
### Bug Fixes
- Fixed strict prototype API decl issue in SDIO ([eb09e426](https://github.com/espressif/esp-protocols/commit/eb09e426))
- Fix SIDO host to check/clear interrupts atomically ([402176c9](https://github.com/espressif/esp-protocols/commit/402176c9))
## [0.1.1](https://github.com/espressif/esp-protocols/commits/eppp-v0.1.1)
### Bug Fixes
- Make some common netif options configurable ([7829e8f](https://github.com/espressif/esp-protocols/commit/7829e8f))
## [0.1.0](https://github.com/espressif/esp-protocols/commits/eppp-v0.1.0)
### Features
- Added CI job to build examples and tests ([7eefcf0](https://github.com/espressif/esp-protocols/commit/7eefcf0))
### Bug Fixes
- Fixed to select PPP LWIP opts which are OFF by default ([16be2f9](https://github.com/espressif/esp-protocols/commit/16be2f9))
- Example to use iperf component from the registry ([bd6b66d](https://github.com/espressif/esp-protocols/commit/bd6b66d))
- Fixed defalt config designated init issue in C++ ([8bd4712](https://github.com/espressif/esp-protocols/commit/8bd4712))
## [0.0.1](https://github.com/espressif/esp-protocols/commits/eppp-v0.0.1)
### Features
- Added CI job to build examples and tests ([8686977](https://github.com/espressif/esp-protocols/commit/8686977))
- Added support for SPI transport ([18f8452](https://github.com/espressif/esp-protocols/commit/18f8452))
- Added support for UART transport ([ad27414](https://github.com/espressif/esp-protocols/commit/ad27414))
- Introduced ESP-PPP-Link component ([a761039](https://github.com/espressif/esp-protocols/commit/a761039))

View File

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

View File

@ -0,0 +1,70 @@
menu "eppp_link"
config EPPP_LINK_USES_LWIP
bool
default "y"
select LWIP_PPP_SUPPORT
select LWIP_PPP_SERVER_SUPPORT
choice EPPP_LINK_DEVICE
prompt "Choose PPP device"
default EPPP_LINK_DEVICE_UART
help
Select which peripheral to use for PPP link
config EPPP_LINK_DEVICE_UART
bool "UART"
help
Use UART.
config EPPP_LINK_DEVICE_SPI
bool "SPI"
help
Use SPI.
config EPPP_LINK_DEVICE_SDIO
bool "SDIO"
depends on SOC_SDMMC_HOST_SUPPORTED || SOC_SDIO_SLAVE_SUPPORTED
help
Use SDIO.
endchoice
config EPPP_LINK_CONN_MAX_RETRY
int "Maximum retry"
default 6
help
Set the Maximum retry to infinitely avoid reconnecting
This is used only with the simplified API (eppp_connect()
and eppp_listen())
config EPPP_LINK_PACKET_QUEUE_SIZE
int "Packet queue size"
default 64
depends on EPPP_LINK_DEVICE_SPI
help
Size of the Tx packet queue.
You can decrease the number for slower bit rates.
choice EPPP_LINK_SDIO_ROLE
prompt "Choose SDIO host or slave"
depends on EPPP_LINK_DEVICE_SDIO
default EPPP_LINK_DEVICE_SDIO_HOST if SOC_SDMMC_HOST_SUPPORTED
help
Select which either SDIO host or slave
config EPPP_LINK_DEVICE_SDIO_HOST
bool "Host"
depends on SOC_SDMMC_HOST_SUPPORTED
help
Use SDIO host.
config EPPP_LINK_DEVICE_SDIO_SLAVE
bool "SLAVE"
depends on SOC_SDIO_SLAVE_SUPPORTED
help
Use SDIO slave.
endchoice
endmenu

View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@ -0,0 +1,57 @@
# ESP PPP Link component (eppp_link)
The component provides a general purpose connectivity engine between two microcontrollers, one acting as PPP server (slave), the other one as PPP client (host).
This component could be used for extending network using physical serial connection. Applications could vary from providing PRC engine for multiprocessor solutions to serial connection to POSIX machine. This uses a standard PPP protocol to negotiate IP addresses and networking, so standard PPP toolset could be used, e.g. a `pppd` service on linux. Typical application is a WiFi connectivity provider for chips that do not have WiFi
## Typical application
Using this component we can construct a WiFi connectivity gateway on PPP channel. The below diagram depicts an application where
PPP server is running on a WiFi capable chip with NAPT module translating packets between WiFi and PPPoS interface.
We usually call this node a SLAVE microcontroller. The "HOST" microcontroller runs PPP client and connects only to the serial line,
brings in the WiFi connectivity from the "SLAVE" microcontroller.
```
SLAVE micro HOST micro
\|/ +----------------+ +----------------+
| | | serial line | |
+---+ WiFi NAT PPPoS |=== UART / SPI / SDIO =====| PPPoS client |
| (server)| | |
+----------------+ +----------------+
```
## API
### Client
* `eppp_connect()` -- Simplified API. Provides the initialization, starts the task and blocks until we're connected
### Server
* `eppp_listen()` -- Simplified API. Provides the initialization, starts the task and blocks until the client connects
### Manual actions
* `eppp_init()` -- Initializes one endpoint (client/server).
* `eppp_deinit()` -- Destroys the endpoint
* `eppp_netif_start()` -- Starts the network, could be called after startup or whenever a connection is lost
* `eppp_netif_stop()` -- Stops the network
* `eppp_perform()` -- Perform one iteration of the PPP task (need to be called regularly in task-less configuration)
## Throughput
Tested with WiFi-NAPT example
### UART @ 3Mbauds
* TCP - 2Mbits/s
* UDP - 2Mbits/s
### SPI @ 16MHz
* TCP - 5Mbits/s
* UDP - 8Mbits/s
### SDIO
* TCP - 9Mbits/s
* UDP - 11Mbits/s

View File

@ -0,0 +1,887 @@
/*
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <stdint.h>
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "esp_check.h"
#include "esp_event.h"
#include "esp_netif_ppp.h"
#include "eppp_link.h"
#include "esp_serial_slave_link/essl_sdio.h"
#if CONFIG_EPPP_LINK_DEVICE_SPI
#include "driver/spi_master.h"
#include "driver/spi_slave.h"
#include "driver/gpio.h"
#include "esp_timer.h"
#include "esp_rom_crc.h"
#elif CONFIG_EPPP_LINK_DEVICE_UART
#include "driver/uart.h"
#endif
static const int GOT_IPV4 = BIT0;
static const int CONNECTION_FAILED = BIT1;
#define CONNECT_BITS (GOT_IPV4|CONNECTION_FAILED)
static EventGroupHandle_t s_event_group = NULL;
static const char *TAG = "eppp_link";
static int s_retry_num = 0;
static int s_eppp_netif_count = 0; // used as a suffix for the netif key
struct packet {
size_t len;
uint8_t *data;
};
#if CONFIG_EPPP_LINK_DEVICE_SPI
#define MAX_PAYLOAD 1500
#define MIN_TRIGGER_US 20
#define SPI_HEADER_MAGIC 0x1234
static void timer_callback(void *arg);
struct header {
uint16_t magic;
uint16_t size;
uint16_t next_size;
uint16_t check;
} __attribute__((packed));
enum blocked_status {
NONE,
MASTER_BLOCKED,
MASTER_WANTS_READ,
SLAVE_BLOCKED,
SLAVE_WANTS_WRITE,
};
#endif // CONFIG_EPPP_LINK_DEVICE_SPI
struct eppp_handle {
#if CONFIG_EPPP_LINK_DEVICE_SPI
QueueHandle_t out_queue;
QueueHandle_t ready_semaphore;
spi_device_handle_t spi_device;
spi_host_device_t spi_host;
int gpio_intr;
uint16_t next_size;
uint16_t transaction_size;
struct packet outbound;
enum blocked_status blocked;
uint32_t slave_last_edge;
esp_timer_handle_t timer;
#elif CONFIG_EPPP_LINK_DEVICE_UART
QueueHandle_t uart_event_queue;
uart_port_t uart_port;
#endif
esp_netif_t *netif;
eppp_type_t role;
bool stop;
bool exited;
bool netif_stop;
};
typedef esp_err_t (*transmit_t)(void *h, void *buffer, size_t len);
#if CONFIG_EPPP_LINK_DEVICE_SDIO
esp_err_t eppp_sdio_host_tx(void *h, void *buffer, size_t len);
esp_err_t eppp_sdio_host_rx(esp_netif_t *netif);
esp_err_t eppp_sdio_slave_rx(esp_netif_t *netif);
esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len);
esp_err_t eppp_sdio_host_init(struct eppp_config_sdio_s *config);
esp_err_t eppp_sdio_slave_init(void);
void eppp_sdio_slave_deinit(void);
void eppp_sdio_host_deinit(void);
#else
static esp_err_t transmit(void *h, void *buffer, size_t len)
{
struct eppp_handle *handle = h;
#if CONFIG_EPPP_LINK_DEVICE_SPI
struct packet buf = { };
uint8_t *current_buffer = buffer;
size_t remaining = len;
do { // TODO(IDF-9194): Refactor this loop to allocate only once and perform
// fragmentation after receiving from the queue (applicable only if MTU > MAX_PAYLOAD)
size_t batch = remaining > MAX_PAYLOAD ? MAX_PAYLOAD : remaining;
buf.data = malloc(batch);
if (buf.data == NULL) {
ESP_LOGE(TAG, "Failed to allocate packet");
return ESP_ERR_NO_MEM;
}
buf.len = batch;
remaining -= batch;
memcpy(buf.data, current_buffer, batch);
current_buffer += batch;
BaseType_t ret = xQueueSend(handle->out_queue, &buf, 0);
if (ret != pdTRUE) {
ESP_LOGE(TAG, "Failed to queue packet to slave!");
return ESP_ERR_NO_MEM;
}
} while (remaining > 0);
if (handle->role == EPPP_SERVER && handle->blocked == SLAVE_BLOCKED) {
uint32_t now = esp_timer_get_time();
uint32_t diff = now - handle->slave_last_edge;
if (diff < MIN_TRIGGER_US) {
esp_rom_delay_us(MIN_TRIGGER_US - diff);
}
gpio_set_level(handle->gpio_intr, 0);
}
#elif CONFIG_EPPP_LINK_DEVICE_UART
ESP_LOG_BUFFER_HEXDUMP("ppp_uart_send", buffer, len, ESP_LOG_VERBOSE);
uart_write_bytes(handle->uart_port, buffer, len);
#endif // DEVICE UART or SPI
return ESP_OK;
}
#endif
static void netif_deinit(esp_netif_t *netif)
{
if (netif == NULL) {
return;
}
struct eppp_handle *h = esp_netif_get_io_driver(netif);
if (h == NULL) {
return;
}
#if CONFIG_EPPP_LINK_DEVICE_SPI
struct packet buf = { };
while (xQueueReceive(h->out_queue, &buf, 0) == pdTRUE) {
if (buf.len > 0) {
free(buf.data);
}
}
vQueueDelete(h->out_queue);
if (h->role == EPPP_CLIENT) {
vSemaphoreDelete(h->ready_semaphore);
}
#endif
free(h);
esp_netif_destroy(netif);
if (s_eppp_netif_count > 0) {
s_eppp_netif_count--;
}
}
static esp_netif_t *netif_init(eppp_type_t role, eppp_config_t *eppp_config)
{
if (s_eppp_netif_count > 9) { // Limit to max 10 netifs, since we use "EPPPx" as the unique key (where x is 0-9)
ESP_LOGE(TAG, "Cannot create more than 10 instances");
return NULL;
}
// Create the object first
struct eppp_handle *h = calloc(1, sizeof(struct eppp_handle));
if (!h) {
ESP_LOGE(TAG, "Failed to allocate eppp_handle");
return NULL;
}
h->role = role;
#if CONFIG_EPPP_LINK_DEVICE_SPI
h->out_queue = xQueueCreate(CONFIG_EPPP_LINK_PACKET_QUEUE_SIZE, sizeof(struct packet));
if (!h->out_queue) {
ESP_LOGE(TAG, "Failed to create the packet queue");
free(h);
return NULL;
}
if (role == EPPP_CLIENT) {
h->ready_semaphore = xSemaphoreCreateBinary();
if (!h->ready_semaphore) {
ESP_LOGE(TAG, "Failed to create the packet queue");
vQueueDelete(h->out_queue);
free(h);
return NULL;
}
}
h->transaction_size = 0;
h->outbound.data = NULL;
h->outbound.len = 0;
if (role == EPPP_SERVER) {
esp_timer_create_args_t args = {
.callback = &timer_callback,
.arg = h,
.name = "timer"
};
if (esp_timer_create(&args, &h->timer) != ESP_OK) {
ESP_LOGE(TAG, "Failed to create the packet queue");
vQueueDelete(h->out_queue);
vSemaphoreDelete(h->ready_semaphore);
free(h);
return NULL;
}
}
#endif
esp_netif_driver_ifconfig_t driver_cfg = {
.handle = h,
#if CONFIG_EPPP_LINK_DEVICE_SDIO
.transmit = role == EPPP_CLIENT ? eppp_sdio_host_tx : eppp_sdio_slave_tx,
#else
.transmit = transmit,
#endif
};
const esp_netif_driver_ifconfig_t *ppp_driver_cfg = &driver_cfg;
esp_netif_inherent_config_t base_netif_cfg = ESP_NETIF_INHERENT_DEFAULT_PPP();
char if_key[] = "EPPP0"; // netif key needs to be unique
if_key[sizeof(if_key) - 2 /* 2 = two chars before the terminator */ ] += s_eppp_netif_count++;
base_netif_cfg.if_key = if_key;
if (eppp_config->ppp.netif_description) {
base_netif_cfg.if_desc = eppp_config->ppp.netif_description;
} else {
base_netif_cfg.if_desc = role == EPPP_CLIENT ? "pppos_client" : "pppos_server";
}
if (eppp_config->ppp.netif_prio) {
base_netif_cfg.route_prio = eppp_config->ppp.netif_prio;
}
esp_netif_config_t netif_ppp_config = { .base = &base_netif_cfg,
.driver = ppp_driver_cfg,
.stack = ESP_NETIF_NETSTACK_DEFAULT_PPP
};
esp_netif_t *netif = esp_netif_new(&netif_ppp_config);
if (!netif) {
ESP_LOGE(TAG, "Failed to create esp_netif");
#if CONFIG_EPPP_LINK_DEVICE_SPI
vQueueDelete(h->out_queue);
if (h->ready_semaphore) {
vSemaphoreDelete(h->ready_semaphore);
}
#endif
free(h);
return NULL;
}
return netif;
}
esp_err_t eppp_netif_stop(esp_netif_t *netif, int stop_timeout_ms)
{
esp_netif_action_disconnected(netif, 0, 0, 0);
esp_netif_action_stop(netif, 0, 0, 0);
struct eppp_handle *h = esp_netif_get_io_driver(netif);
for (int wait = 0; wait < 100; wait++) {
vTaskDelay(pdMS_TO_TICKS(stop_timeout_ms) / 100);
if (h->netif_stop) {
break;
}
}
if (!h->netif_stop) {
return ESP_FAIL;
}
return ESP_OK;
}
esp_err_t eppp_netif_start(esp_netif_t *netif)
{
esp_netif_action_start(netif, 0, 0, 0);
esp_netif_action_connected(netif, 0, 0, 0);
return ESP_OK;
}
static int get_netif_num(esp_netif_t *netif)
{
if (netif == NULL) {
return -1;
}
const char *ifkey = esp_netif_get_ifkey(netif);
if (strstr(ifkey, "EPPP") == NULL) {
return -1; // not our netif
}
int netif_cnt = ifkey[4] - '0';
if (netif_cnt < 0 || netif_cnt > 9) {
ESP_LOGE(TAG, "Unexpected netif key %s", ifkey);
return -1;
}
return netif_cnt;
}
static void on_ppp_event(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
esp_netif_t **netif = data;
ESP_LOGD(TAG, "PPP status event: %" PRId32, event_id);
if (base == NETIF_PPP_STATUS && event_id == NETIF_PPP_ERRORUSER) {
ESP_LOGI(TAG, "Disconnected %d", get_netif_num(*netif));
struct eppp_handle *h = esp_netif_get_io_driver(*netif);
h->netif_stop = true;
}
}
static void on_ip_event(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
ip_event_got_ip_t *event = (ip_event_got_ip_t *)data;
esp_netif_t *netif = event->esp_netif;
int netif_cnt = get_netif_num(netif);
if (netif_cnt < 0) {
return;
}
if (event_id == IP_EVENT_PPP_GOT_IP) {
ESP_LOGI(TAG, "Got IPv4 event: Interface \"%s(%s)\" address: " IPSTR, esp_netif_get_desc(netif),
esp_netif_get_ifkey(netif), IP2STR(&event->ip_info.ip));
xEventGroupSetBits(s_event_group, GOT_IPV4 << (netif_cnt * 2));
} else if (event_id == IP_EVENT_PPP_LOST_IP) {
ESP_LOGI(TAG, "Disconnected");
s_retry_num++;
if (s_retry_num > CONFIG_EPPP_LINK_CONN_MAX_RETRY) {
ESP_LOGE(TAG, "PPP Connection failed %d times, stop reconnecting.", s_retry_num);
xEventGroupSetBits(s_event_group, CONNECTION_FAILED << (netif_cnt * 2));
} else {
ESP_LOGI(TAG, "PPP Connection failed %d times, try to reconnect.", s_retry_num);
eppp_netif_start(netif);
}
}
}
#if CONFIG_EPPP_LINK_DEVICE_SPI
#define SPI_ALIGN(size) (((size) + 3U) & ~(3U))
#define TRANSFER_SIZE SPI_ALIGN((MAX_PAYLOAD + 6))
#define NEXT_TRANSACTION_SIZE(a,b) (((a)>(b))?(a):(b)) /* next transaction: whichever is bigger */
static void IRAM_ATTR timer_callback(void *arg)
{
struct eppp_handle *h = arg;
if (h->blocked == SLAVE_WANTS_WRITE) {
gpio_set_level(h->gpio_intr, 0);
}
}
static void IRAM_ATTR gpio_isr_handler(void *arg)
{
static uint32_t s_last_time;
uint32_t now = esp_timer_get_time();
uint32_t diff = now - s_last_time;
if (diff < MIN_TRIGGER_US) { // debounce
return;
}
s_last_time = now;
struct eppp_handle *h = arg;
BaseType_t yield = false;
// Positive edge means SPI slave prepared the data
if (gpio_get_level(h->gpio_intr) == 1) {
xSemaphoreGiveFromISR(h->ready_semaphore, &yield);
if (yield) {
portYIELD_FROM_ISR();
}
return;
}
// Negative edge (when master blocked) means that slave wants to transmit
if (h->blocked == MASTER_BLOCKED) {
struct packet buf = { .data = NULL, .len = -1 };
xQueueSendFromISR(h->out_queue, &buf, &yield);
if (yield) {
portYIELD_FROM_ISR();
}
}
}
static esp_err_t deinit_master(esp_netif_t *netif)
{
struct eppp_handle *h = esp_netif_get_io_driver(netif);
ESP_RETURN_ON_ERROR(spi_bus_remove_device(h->spi_device), TAG, "Failed to remove SPI bus");
ESP_RETURN_ON_ERROR(spi_bus_free(h->spi_host), TAG, "Failed to free SPI bus");
return ESP_OK;
}
static esp_err_t init_master(struct eppp_config_spi_s *config, esp_netif_t *netif)
{
struct eppp_handle *h = esp_netif_get_io_driver(netif);
h->spi_host = config->host;
h->gpio_intr = config->intr;
spi_bus_config_t bus_cfg = {};
bus_cfg.mosi_io_num = config->mosi;
bus_cfg.miso_io_num = config->miso;
bus_cfg.sclk_io_num = config->sclk;
bus_cfg.quadwp_io_num = -1;
bus_cfg.quadhd_io_num = -1;
bus_cfg.max_transfer_sz = TRANSFER_SIZE;
bus_cfg.flags = 0;
bus_cfg.intr_flags = 0;
// TODO: Init and deinit SPI bus separately (per Kconfig?)
if (spi_bus_initialize(config->host, &bus_cfg, SPI_DMA_CH_AUTO) != ESP_OK) {
return ESP_FAIL;
}
spi_device_interface_config_t dev_cfg = {};
dev_cfg.clock_speed_hz = config->freq;
dev_cfg.mode = 0;
dev_cfg.spics_io_num = config->cs;
dev_cfg.cs_ena_pretrans = config->cs_ena_pretrans;
dev_cfg.cs_ena_posttrans = config->cs_ena_posttrans;
dev_cfg.duty_cycle_pos = 128;
dev_cfg.input_delay_ns = config->input_delay_ns;
dev_cfg.pre_cb = NULL;
dev_cfg.post_cb = NULL;
dev_cfg.queue_size = 3;
if (spi_bus_add_device(config->host, &dev_cfg, &h->spi_device) != ESP_OK) {
return ESP_FAIL;
}
//GPIO config for the handshake line.
gpio_config_t io_conf = {
.intr_type = GPIO_INTR_ANYEDGE,
.mode = GPIO_MODE_INPUT,
.pull_up_en = 1,
.pin_bit_mask = BIT64(config->intr),
};
gpio_config(&io_conf);
gpio_install_isr_service(0);
gpio_set_intr_type(config->intr, GPIO_INTR_ANYEDGE);
gpio_isr_handler_add(config->intr, gpio_isr_handler, esp_netif_get_io_driver(netif));
return ESP_OK;
}
static void post_setup(spi_slave_transaction_t *trans)
{
struct eppp_handle *h = trans->user;
h->slave_last_edge = esp_timer_get_time();
gpio_set_level(h->gpio_intr, 1);
if (h->transaction_size == 0) { // If no transaction planned:
if (h->outbound.len == 0) { // we're blocked if we don't have any data
h->blocked = SLAVE_BLOCKED;
} else {
h->blocked = SLAVE_WANTS_WRITE; // we notify the master that we want to write
esp_timer_start_once(h->timer, MIN_TRIGGER_US);
}
}
}
static void post_trans(spi_slave_transaction_t *trans)
{
struct eppp_handle *h = trans->user;
h->blocked = NONE;
gpio_set_level(h->gpio_intr, 0);
}
static esp_err_t deinit_slave(esp_netif_t *netif)
{
struct eppp_handle *h = esp_netif_get_io_driver(netif);
ESP_RETURN_ON_ERROR(spi_slave_free(h->spi_host), TAG, "Failed to free SPI slave host");
ESP_RETURN_ON_ERROR(spi_bus_remove_device(h->spi_device), TAG, "Failed to remove SPI device");
ESP_RETURN_ON_ERROR(spi_bus_free(h->spi_host), TAG, "Failed to free SPI bus");
return ESP_OK;
}
static esp_err_t init_slave(struct eppp_config_spi_s *config, esp_netif_t *netif)
{
struct eppp_handle *h = esp_netif_get_io_driver(netif);
h->spi_host = config->host;
h->gpio_intr = config->intr;
spi_bus_config_t bus_cfg = {};
bus_cfg.mosi_io_num = config->mosi;
bus_cfg.miso_io_num = config->miso;
bus_cfg.sclk_io_num = config->sclk;
bus_cfg.quadwp_io_num = -1;
bus_cfg.quadhd_io_num = -1;
bus_cfg.flags = 0;
bus_cfg.intr_flags = 0;
//Configuration for the SPI slave interface
spi_slave_interface_config_t slvcfg = {
.mode = 0,
.spics_io_num = config->cs,
.queue_size = 3,
.flags = 0,
.post_setup_cb = post_setup,
.post_trans_cb = post_trans,
};
//Configuration for the handshake line
gpio_config_t io_conf = {
.intr_type = GPIO_INTR_DISABLE,
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = BIT64(config->intr),
};
gpio_config(&io_conf);
gpio_set_pull_mode(config->mosi, GPIO_PULLUP_ONLY);
gpio_set_pull_mode(config->sclk, GPIO_PULLUP_ONLY);
gpio_set_pull_mode(config->cs, GPIO_PULLUP_ONLY);
//Initialize SPI slave interface
if (spi_slave_initialize(config->host, &bus_cfg, &slvcfg, SPI_DMA_CH_AUTO) != ESP_OK) {
return ESP_FAIL;
}
return ESP_OK;
}
typedef esp_err_t (*perform_transaction_t)(struct eppp_handle *h, size_t len, const void *tx_buffer, void *rx_buffer);
static esp_err_t perform_transaction_master(struct eppp_handle *h, size_t len, const void *tx_buffer, void *rx_buffer)
{
spi_transaction_t t = {};
t.length = len * 8;
t.tx_buffer = tx_buffer;
t.rx_buffer = rx_buffer;
return spi_device_transmit(h->spi_device, &t);
}
static esp_err_t perform_transaction_slave(struct eppp_handle *h, size_t len, const void *tx_buffer, void *rx_buffer)
{
spi_slave_transaction_t t = {};
t.user = h;
t.length = len * 8;
t.tx_buffer = tx_buffer;
t.rx_buffer = rx_buffer;
return spi_slave_transmit(h->spi_host, &t, portMAX_DELAY);
}
esp_err_t eppp_perform(esp_netif_t *netif)
{
static WORD_ALIGNED_ATTR uint8_t out_buf[TRANSFER_SIZE] = {};
static WORD_ALIGNED_ATTR uint8_t in_buf[TRANSFER_SIZE] = {};
struct eppp_handle *h = esp_netif_get_io_driver(netif);
// Perform transaction for master and slave
const perform_transaction_t perform_transaction = h->role == EPPP_CLIENT ? perform_transaction_master : perform_transaction_slave;
if (h->stop) {
return ESP_ERR_TIMEOUT;
}
BaseType_t tx_queue_stat;
bool allow_test_tx = false;
uint16_t next_tx_size = 0;
if (h->role == EPPP_CLIENT) {
// SPI MASTER only code
if (xSemaphoreTake(h->ready_semaphore, pdMS_TO_TICKS(1000)) != pdTRUE) {
// slave might not be ready, but maybe we just missed an interrupt
allow_test_tx = true;
}
if (h->outbound.len == 0 && h->transaction_size == 0 && h->blocked == NONE) {
h->blocked = MASTER_BLOCKED;
xQueueReceive(h->out_queue, &h->outbound, portMAX_DELAY);
h->blocked = NONE;
if (h->outbound.len == -1) {
h->outbound.len = 0;
h->blocked = MASTER_WANTS_READ;
}
} else if (h->blocked == MASTER_WANTS_READ) {
h->blocked = NONE;
}
}
struct header *head = (void *)out_buf;
if (h->outbound.len <= h->transaction_size && allow_test_tx == false) {
// sending outbound
head->size = h->outbound.len;
if (h->outbound.len > 0) {
memcpy(out_buf + sizeof(struct header), h->outbound.data, h->outbound.len);
free(h->outbound.data);
ESP_LOG_BUFFER_HEXDUMP(TAG, out_buf + sizeof(struct header), head->size, ESP_LOG_VERBOSE);
h->outbound.data = NULL;
h->outbound.len = 0;
}
do {
tx_queue_stat = xQueueReceive(h->out_queue, &h->outbound, 0);
} while (tx_queue_stat == pdTRUE && h->outbound.len == -1);
if (h->outbound.len == -1) { // used as a signal only, no actual data
h->outbound.len = 0;
}
} else {
// outbound is bigger, need to transmit in another transaction (keep this empty)
head->size = 0;
}
next_tx_size = head->next_size = h->outbound.len;
head->magic = SPI_HEADER_MAGIC;
head->check = esp_rom_crc16_le(0, out_buf, sizeof(struct header) - sizeof(uint16_t));
esp_err_t ret = perform_transaction(h, sizeof(struct header) + h->transaction_size, out_buf, in_buf);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "spi_device_transmit failed");
h->transaction_size = 0; // need to start with HEADER only transaction
return ESP_FAIL;
}
head = (void *)in_buf;
uint16_t check = esp_rom_crc16_le(0, in_buf, sizeof(struct header) - sizeof(uint16_t));
if (check != head->check || head->magic != SPI_HEADER_MAGIC) {
h->transaction_size = 0; // need to start with HEADER only transaction
if (allow_test_tx) {
return ESP_OK;
}
ESP_LOGE(TAG, "Wrong checksum or magic");
return ESP_FAIL;
}
if (head->size > 0) {
ESP_LOG_BUFFER_HEXDUMP(TAG, in_buf + sizeof(struct header), head->size, ESP_LOG_VERBOSE);
esp_netif_receive(netif, in_buf + sizeof(struct header), head->size, NULL);
}
h->transaction_size = NEXT_TRANSACTION_SIZE(next_tx_size, head->next_size);
return ESP_OK;
}
#elif CONFIG_EPPP_LINK_DEVICE_UART
#define BUF_SIZE (1024)
static esp_err_t init_uart(struct eppp_handle *h, eppp_config_t *config)
{
h->uart_port = config->uart.port;
uart_config_t uart_config = {};
uart_config.baud_rate = config->uart.baud;
uart_config.data_bits = UART_DATA_8_BITS;
uart_config.parity = UART_PARITY_DISABLE;
uart_config.stop_bits = UART_STOP_BITS_1;
uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE;
uart_config.source_clk = UART_SCLK_DEFAULT;
ESP_RETURN_ON_ERROR(uart_driver_install(h->uart_port, config->uart.rx_buffer_size, 0, config->uart.queue_size, &h->uart_event_queue, 0), TAG, "Failed to install UART");
ESP_RETURN_ON_ERROR(uart_param_config(h->uart_port, &uart_config), TAG, "Failed to set params");
ESP_RETURN_ON_ERROR(uart_set_pin(h->uart_port, config->uart.tx_io, config->uart.rx_io, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE), TAG, "Failed to set UART pins");
ESP_RETURN_ON_ERROR(uart_set_rx_timeout(h->uart_port, 1), TAG, "Failed to set UART Rx timeout");
return ESP_OK;
}
static void deinit_uart(struct eppp_handle *h)
{
uart_driver_delete(h->uart_port);
}
esp_err_t eppp_perform(esp_netif_t *netif)
{
static uint8_t buffer[BUF_SIZE] = {};
struct eppp_handle *h = esp_netif_get_io_driver(netif);
uart_event_t event = {};
if (h->stop) {
return ESP_ERR_TIMEOUT;
}
if (xQueueReceive(h->uart_event_queue, &event, pdMS_TO_TICKS(100)) != pdTRUE) {
return ESP_OK;
}
if (event.type == UART_DATA) {
size_t len;
uart_get_buffered_data_len(h->uart_port, &len);
if (len) {
len = uart_read_bytes(h->uart_port, buffer, BUF_SIZE, 0);
ESP_LOG_BUFFER_HEXDUMP("ppp_uart_recv", buffer, len, ESP_LOG_VERBOSE);
esp_netif_receive(netif, buffer, len, NULL);
}
} else {
ESP_LOGW(TAG, "Received UART event: %d", event.type);
}
return ESP_OK;
}
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
esp_err_t eppp_perform(esp_netif_t *netif)
{
struct eppp_handle *h = esp_netif_get_io_driver(netif);
if (h->stop) {
return ESP_ERR_TIMEOUT;
}
if (h->role == EPPP_SERVER) {
return eppp_sdio_slave_rx(netif);
} else {
return eppp_sdio_host_rx(netif);
}
}
#endif // CONFIG_EPPP_LINK_DEVICE_SPI / UART
static void ppp_task(void *args)
{
esp_netif_t *netif = args;
while (eppp_perform(netif) != ESP_ERR_TIMEOUT) {}
struct eppp_handle *h = esp_netif_get_io_driver(netif);
h->exited = true;
vTaskDelete(NULL);
}
static bool have_some_eppp_netif(esp_netif_t *netif, void *ctx)
{
return get_netif_num(netif) > 0;
}
static void remove_handlers(void)
{
esp_netif_t *netif = esp_netif_find_if(have_some_eppp_netif, NULL);
if (netif == NULL) {
// if EPPP netif in the system, we cleanup the statics
vEventGroupDelete(s_event_group);
s_event_group = NULL;
esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, on_ip_event);
esp_event_handler_unregister(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, on_ppp_event);
}
}
void eppp_deinit(esp_netif_t *netif)
{
if (netif == NULL) {
return;
}
#if CONFIG_EPPP_LINK_DEVICE_SPI
struct eppp_handle *h = esp_netif_get_io_driver(netif);
if (h->role == EPPP_CLIENT) {
deinit_master(netif);
} else {
deinit_slave(netif);
}
#elif CONFIG_EPPP_LINK_DEVICE_UART
deinit_uart(esp_netif_get_io_driver(netif));
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
struct eppp_handle *h = esp_netif_get_io_driver(netif);
if (h->role == EPPP_CLIENT) {
eppp_sdio_host_deinit();
} else {
eppp_sdio_slave_deinit();
}
#endif
netif_deinit(netif);
}
esp_netif_t *eppp_init(eppp_type_t role, eppp_config_t *config)
{
if (config == NULL || (role != EPPP_SERVER && role != EPPP_CLIENT)) {
ESP_LOGE(TAG, "Invalid configuration or role");
return NULL;
}
esp_netif_t *netif = netif_init(role, config);
if (!netif) {
ESP_LOGE(TAG, "Failed to initialize PPP netif");
return NULL;
}
esp_netif_ppp_config_t netif_params;
ESP_ERROR_CHECK(esp_netif_ppp_get_params(netif, &netif_params));
netif_params.ppp_our_ip4_addr = config->ppp.our_ip4_addr;
netif_params.ppp_their_ip4_addr = config->ppp.their_ip4_addr;
netif_params.ppp_error_event_enabled = true;
ESP_ERROR_CHECK(esp_netif_ppp_set_params(netif, &netif_params));
#if CONFIG_EPPP_LINK_DEVICE_SPI
if (role == EPPP_CLIENT) {
init_master(&config->spi, netif);
} else {
init_slave(&config->spi, netif);
}
#elif CONFIG_EPPP_LINK_DEVICE_UART
init_uart(esp_netif_get_io_driver(netif), config);
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
esp_err_t ret;
if (role == EPPP_SERVER) {
ret = eppp_sdio_slave_init();
} else {
ret = eppp_sdio_host_init(&config->sdio);
}
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize SDIO %d", ret);
return NULL;
}
#endif
return netif;
}
esp_netif_t *eppp_open(eppp_type_t role, eppp_config_t *config, int connect_timeout_ms)
{
if (config == NULL || (role != EPPP_SERVER && role != EPPP_CLIENT)) {
ESP_LOGE(TAG, "Invalid configuration or role");
return NULL;
}
#if CONFIG_EPPP_LINK_DEVICE_UART
if (config->transport != EPPP_TRANSPORT_UART) {
ESP_LOGE(TAG, "Invalid transport: UART device must be enabled in Kconfig");
return NULL;
}
#endif
#if CONFIG_EPPP_LINK_DEVICE_SPI
if (config->transport != EPPP_TRANSPORT_SPI) {
ESP_LOGE(TAG, "Invalid transport: SPI device must be enabled in Kconfig");
return NULL;
}
#endif
#if CONFIG_EPPP_LINK_DEVICE_SDIO
if (config->transport != EPPP_TRANSPORT_SDIO) {
ESP_LOGE(TAG, "Invalid transport: SDIO device must be enabled in Kconfig");
return NULL;
}
#endif
if (config->task.run_task == false) {
ESP_LOGE(TAG, "task.run_task == false is invalid in this API. Please use eppp_init()");
return NULL;
}
if (s_event_group == NULL) {
s_event_group = xEventGroupCreate();
if (esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, on_ip_event, NULL) != ESP_OK) {
ESP_LOGE(TAG, "Failed to register IP event handler");
remove_handlers();
return NULL;
}
if (esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, on_ppp_event, NULL) != ESP_OK) {
ESP_LOGE(TAG, "Failed to register PPP status handler");
remove_handlers();
return NULL;
}
}
esp_netif_t *netif = eppp_init(role, config);
if (!netif) {
remove_handlers();
return NULL;
}
eppp_netif_start(netif);
if (xTaskCreate(ppp_task, "ppp connect", config->task.stack_size, netif, config->task.priority, NULL) != pdTRUE) {
ESP_LOGE(TAG, "Failed to create a ppp connection task");
eppp_deinit(netif);
return NULL;
}
int netif_cnt = get_netif_num(netif);
if (netif_cnt < 0) {
eppp_close(netif);
return NULL;
}
ESP_LOGI(TAG, "Waiting for IP address %d", netif_cnt);
EventBits_t bits = xEventGroupWaitBits(s_event_group, CONNECT_BITS << (netif_cnt * 2), pdFALSE, pdFALSE, pdMS_TO_TICKS(connect_timeout_ms));
if (bits & (CONNECTION_FAILED << (netif_cnt * 2))) {
ESP_LOGE(TAG, "Connection failed!");
eppp_close(netif);
return NULL;
}
ESP_LOGI(TAG, "Connected! %d", netif_cnt);
return netif;
}
esp_netif_t *eppp_connect(eppp_config_t *config)
{
return eppp_open(EPPP_CLIENT, config, portMAX_DELAY);
}
esp_netif_t *eppp_listen(eppp_config_t *config)
{
return eppp_open(EPPP_SERVER, config, portMAX_DELAY);
}
void eppp_close(esp_netif_t *netif)
{
struct eppp_handle *h = esp_netif_get_io_driver(netif);
if (eppp_netif_stop(netif, 60000) != ESP_OK) {
ESP_LOGE(TAG, "Network didn't exit cleanly");
}
h->stop = true;
for (int wait = 0; wait < 100; wait++) {
vTaskDelay(pdMS_TO_TICKS(10));
if (h->exited) {
break;
}
}
if (!h->exited) {
ESP_LOGE(TAG, "Cannot stop ppp_task");
}
eppp_deinit(netif);
remove_handlers();
}

View File

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

View File

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

View File

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

View File

@ -0,0 +1,7 @@
# The following four lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(pppos_host)

View File

@ -0,0 +1,9 @@
# Client side demo of ESP-PPP-Link
This is a basic demo of using esp-mqtt library, but connects to the internet using a PPPoS client. To run this example, you would need a PPP server that provides connectivity to the MQTT broker used in this example (by default a public broker accessible on the internet).
If configured, this example could also run a ping session and an iperf console.
The PPP server could be a Linux computer with `pppd` service or an ESP32 acting like a connection gateway with PPPoS server (see the "slave" project).

View File

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

View File

@ -0,0 +1,53 @@
menu "Example Configuration"
config EXAMPLE_GLOBAL_DNS
hex "Set global DNS server"
range 0 0xFFFFFFFF
default 0x08080808
help
Global DNS server address.
config EXAMPLE_MQTT
bool "Run mqtt example"
default y
help
Run MQTT client after startup.
config EXAMPLE_BROKER_URL
string "Broker URL"
depends on EXAMPLE_MQTT
default "mqtt://mqtt.eclipseprojects.io"
help
URL of the broker to connect to.
config EXAMPLE_IPERF
bool "Run iperf"
default y
help
Init and run iperf console.
config EXAMPLE_UART_TX_PIN
int "TXD Pin Number"
depends on EPPP_LINK_DEVICE_UART
default 10
range 0 31
help
Pin number of UART TX.
config EXAMPLE_UART_RX_PIN
int "RXD Pin Number"
depends on EPPP_LINK_DEVICE_UART
default 11
range 0 31
help
Pin number of UART RX.
config EXAMPLE_UART_BAUDRATE
int "Baudrate"
depends on EPPP_LINK_DEVICE_UART
default 2000000
range 0 4000000
help
Baudrate used by the PPP over UART
endmenu

View File

@ -0,0 +1,151 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "eppp_link.h"
#include "esp_log.h"
#include "mqtt_client.h"
#include "console_ping.h"
void register_iperf(void);
static const char *TAG = "eppp_host_example";
#if CONFIG_EXAMPLE_MQTT
static void mqtt_event_handler(void *args, esp_event_base_t base, int32_t event_id, void *event_data)
{
ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id);
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
int msg_id;
switch ((esp_mqtt_event_id_t)event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
msg_id = esp_mqtt_client_publish(client, "/topic/qos1", "data_3", 0, 1, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1");
ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
case MQTT_EVENT_SUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
printf("DATA=%.*s\r\n", event->data_len, event->data);
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
}
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
}
}
static void mqtt_app_start(void)
{
esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = "mqtt://mqtt.eclipseprojects.io",
};
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
/* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
esp_mqtt_client_start(client);
}
#endif // MQTT
void app_main(void)
{
ESP_LOGI(TAG, "[APP] Startup..");
ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
/* Sets up the default EPPP-connection
*/
eppp_config_t config = EPPP_DEFAULT_CLIENT_CONFIG();
#if CONFIG_EPPP_LINK_DEVICE_SPI
config.transport = EPPP_TRANSPORT_SPI;
#elif CONFIG_EPPP_LINK_DEVICE_UART
config.transport = EPPP_TRANSPORT_UART;
config.uart.tx_io = CONFIG_EXAMPLE_UART_TX_PIN;
config.uart.rx_io = CONFIG_EXAMPLE_UART_RX_PIN;
config.uart.baud = CONFIG_EXAMPLE_UART_BAUDRATE;
#else
config.transport = EPPP_TRANSPORT_SDIO;
#endif
esp_netif_t *eppp_netif = eppp_connect(&config);
if (eppp_netif == NULL) {
ESP_LOGE(TAG, "Failed to connect");
return ;
}
// Setup global DNS
esp_netif_dns_info_t dns;
dns.ip.u_addr.ip4.addr = esp_netif_htonl(CONFIG_EXAMPLE_GLOBAL_DNS);
dns.ip.type = ESP_IPADDR_TYPE_V4;
ESP_ERROR_CHECK(esp_netif_set_dns_info(eppp_netif, ESP_NETIF_DNS_MAIN, &dns));
// Initialize console REPL
ESP_ERROR_CHECK(console_cmd_init());
#if CONFIG_EXAMPLE_IPERF
register_iperf();
printf("\n =======================================================\n");
printf(" | Steps to Test EPPP-host bandwidth |\n");
printf(" | |\n");
printf(" | 1. Wait for the ESP32 to get an IP |\n");
printf(" | 2. Server: 'iperf -u -s -i 3' (on host) |\n");
printf(" | 3. Client: 'iperf -u -c SERVER_IP -t 60 -i 3' |\n");
printf(" | |\n");
printf(" =======================================================\n\n");
#endif // CONFIG_EXAMPLE_IPERF
// Register the ping command
ESP_ERROR_CHECK(console_cmd_ping_register());
// start console REPL
ESP_ERROR_CHECK(console_cmd_start());
#if CONFIG_EXAMPLE_MQTT
mqtt_app_start();
#endif
}

View File

@ -0,0 +1,7 @@
dependencies:
espressif/iperf-cmd: "^0.1.1"
espressif/eppp_link:
version: "*"
override_path: "../../.."
console_cmd_ping:
version: "*"

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