├── .codespellrc ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── dependabot.yml ├── stale.yml └── workflows │ ├── auto-github-actions.yml │ ├── report-size-deltas.yml │ └── spell-check.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── LibraryPatches └── esp32 │ └── cores │ └── esp32 │ └── Server.h ├── README.md ├── changelog.md ├── examples ├── AsyncUDPClient │ └── AsyncUDPClient.ino ├── AsyncUDPMulticastServer │ └── AsyncUDPMulticastServer.ino ├── AsyncUDPServer │ └── AsyncUDPServer.ino ├── AsyncUdpNTPClient │ └── AsyncUdpNTPClient.ino ├── AsyncUdpSendReceive │ └── AsyncUdpSendReceive.ino └── multiFileProject │ ├── multiFileProject.cpp │ ├── multiFileProject.h │ └── multiFileProject.ino ├── keywords.txt ├── library.json ├── library.properties ├── platformio └── platformio.ini ├── src ├── AsyncUDP_WT32_ETH01.h ├── AsyncUDP_WT32_ETH01.hpp ├── AsyncUDP_WT32_ETH01_Debug.h └── AsyncUDP_WT32_ETH01_Impl.h └── utils ├── astyle_library.conf └── restyle.sh /.codespellrc: -------------------------------------------------------------------------------- 1 | # See: https://github.com/codespell-project/codespell#using-a-config-file 2 | [codespell] 3 | # In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here: 4 | ignore-words-list = , 5 | check-filenames = 6 | check-hidden = 7 | skip = ./.git,./src,./examples,./Packages_Patches,./LibraryPatches 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Describe the bug 11 | 12 | A clear and concise description of what the bug is. 13 | 14 | ### Steps to Reproduce 15 | 16 | Steps to reproduce the behavior. Including the [MRE](https://stackoverflow.com/help/minimal-reproducible-example) sketches 17 | 18 | ### Expected behavior 19 | 20 | A clear and concise description of what you expected to happen. 21 | 22 | ### Actual behavior 23 | 24 | A clear and concise description of what you expected to happen. 25 | 26 | ### Debug and AT-command log (if applicable) 27 | 28 | A clear and concise description of what you expected to happen. 29 | 30 | ### Screenshots 31 | 32 | If applicable, add screenshots to help explain your problem. 33 | 34 | ### Information 35 | 36 | Please ensure to specify the following: 37 | 38 | * Arduino IDE version (e.g. 1.8.19) or Platform.io version 39 | * `ESP32` Core Version (e.g. ESP32 v2.0.5) 40 | * Contextual information (e.g. what you were trying to achieve) 41 | * Simplest possible steps to reproduce 42 | * Anything that might be relevant in your opinion, such as: 43 | * Operating system (Windows, Ubuntu, etc.) and the output of `uname -a` 44 | * Network configuration 45 | 46 | 47 | ### Example 48 | 49 | ``` 50 | Arduino IDE version: 1.8.19 51 | ESP32 Core Version 2.0.5 52 | OS: Ubuntu 20.04 LTS 53 | Linux xy-Inspiron-3593 5.15.0-53-generic #59~20.04.1-Ubuntu SMP Thu Oct 20 15:10:22 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux 54 | 55 | Context: 56 | I encountered a crash while using this library 57 | 58 | Steps to reproduce: 59 | 1. ... 60 | 2. ... 61 | 3. ... 62 | 4. ... 63 | ``` 64 | 65 | --- 66 | 67 | ### Sending Feature Requests 68 | 69 | Feel free to post feature requests. It's helpful if you can explain exactly why the feature would be useful. 70 | 71 | There are usually some outstanding feature requests in the [existing issues list](https://github.com/khoih-prog/AsyncUDP_WT32_ETH01/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement), feel free to add comments to them. 72 | 73 | --- 74 | 75 | ### Sending Pull Requests 76 | 77 | Pull Requests with changes and fixes are also welcome! 78 | 79 | Please use the `astyle` to reformat the updated library code as follows (demo for Ubuntu Linux) 80 | 81 | 1. Change directory to the library GitHub 82 | 83 | ``` 84 | xy@xy-Inspiron-3593:~$ cd Arduino/xy/AsyncUDP_WT32_ETH01_GitHub/ 85 | xy@xy-Inspiron-3593:~/Arduino/xy/AsyncUDP_WT32_ETH01_GitHub$ 86 | ``` 87 | 88 | 2. Issue astyle command 89 | 90 | ``` 91 | xy@xy-Inspiron-3593:~/Arduino/xy/AsyncUDP_WT32_ETH01_GitHub$ bash utils/restyle.sh 92 | ``` 93 | 94 | 95 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # See: https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#about-the-dependabotyml-file 2 | version: 2 3 | 4 | updates: 5 | # Configure check for outdated GitHub Actions actions in workflows. 6 | # See: https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot 7 | - package-ecosystem: github-actions 8 | directory: / # Check the repository's workflows under /.github/workflows/ 9 | schedule: 10 | interval: daily 11 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-stale - https://github.com/probot/stale 2 | 3 | daysUntilStale: 60 4 | daysUntilClose: 14 5 | limitPerRun: 30 6 | staleLabel: stale 7 | exemptLabels: 8 | - pinned 9 | - security 10 | - "to be implemented" 11 | - "for reference" 12 | - "move to PR" 13 | - "enhancement" 14 | 15 | only: issues 16 | onlyLabels: [] 17 | exemptProjects: false 18 | exemptMilestones: false 19 | exemptAssignees: false 20 | 21 | markComment: > 22 | [STALE_SET] This issue has been automatically marked as stale because it has not had 23 | recent activity. It will be closed in 14 days if no further activity occurs. Thank you 24 | for your contributions. 25 | 26 | unmarkComment: > 27 | [STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it opening the future. 28 | 29 | closeComment: > 30 | [STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions. 31 | 32 | -------------------------------------------------------------------------------- /.github/workflows/auto-github-actions.yml: -------------------------------------------------------------------------------- 1 | name: auto-github-actions 2 | on: [push] 3 | jobs: 4 | check-bats-version: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v3 8 | - uses: actions/setup-node@v3 9 | with: 10 | node-version: '14' 11 | - run: npm install -g bats 12 | - run: bats -v 13 | -------------------------------------------------------------------------------- /.github/workflows/report-size-deltas.yml: -------------------------------------------------------------------------------- 1 | name: Report Size Deltas 2 | 3 | on: 4 | schedule: 5 | - cron: '*/5 * * * *' 6 | 7 | jobs: 8 | report: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - name: Comment size deltas reports to PRs 13 | uses: arduino/report-size-deltas@v1 14 | with: 15 | # The name of the workflow artifact created by the "Compile Examples" workflow 16 | sketches-reports-source: sketches-reports 17 | -------------------------------------------------------------------------------- /.github/workflows/spell-check.yml: -------------------------------------------------------------------------------- 1 | name: Spell Check 2 | 3 | on: 4 | pull_request: 5 | push: 6 | schedule: 7 | # run every Tuesday at 3 AM UTC 8 | - cron: "0 3 * * 2" 9 | workflow_dispatch: 10 | repository_dispatch: 11 | 12 | jobs: 13 | spellcheck: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v3 19 | 20 | # See: https://github.com/codespell-project/actions-codespell/blob/master/README.md 21 | - name: Spell check 22 | uses: codespell-project/actions-codespell@master 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # Visual Studio folder and files 35 | .vs 36 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing to AsyncUDP_WT32_ETH01 2 | 3 | ### Reporting Bugs 4 | 5 | Please report bugs in AsyncUDP_WT32_ETH01 if you find them. 6 | 7 | However, before reporting a bug please check through the following: 8 | 9 | * [Existing Open Issues](https://github.com/khoih-prog/AsyncUDP_WT32_ETH01/issues) - someone might have already encountered this. 10 | 11 | If you don't find anything, please [open a new issue](https://github.com/khoih-prog/AsyncUDP_WT32_ETH01/issues/new). 12 | 13 | ### How to submit a bug report 14 | 15 | Please ensure to specify the following: 16 | 17 | * Arduino IDE version (e.g. 1.8.19) or Platform.io version 18 | * `ESP32` Core Version (e.g. ESP32 v2.0.5) 19 | * Contextual information (e.g. what you were trying to achieve) 20 | * Simplest possible steps to reproduce 21 | * Anything that might be relevant in your opinion, such as: 22 | * Operating system (Windows, Ubuntu, etc.) and the output of `uname -a` 23 | * Network configuration 24 | 25 | 26 | ### Example 27 | 28 | ``` 29 | Arduino IDE version: 1.8.19 30 | ESP32 Core Version 2.0.5 31 | OS: Ubuntu 20.04 LTS 32 | Linux xy-Inspiron-3593 5.15.0-53-generic #59~20.04.1-Ubuntu SMP Thu Oct 20 15:10:22 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux 33 | 34 | Context: 35 | I encountered a crash while using this library 36 | 37 | Steps to reproduce: 38 | 1. ... 39 | 2. ... 40 | 3. ... 41 | 4. ... 42 | ``` 43 | 44 | --- 45 | 46 | ### Sending Feature Requests 47 | 48 | Feel free to post feature requests. It's helpful if you can explain exactly why the feature would be useful. 49 | 50 | There are usually some outstanding feature requests in the [existing issues list](https://github.com/khoih-prog/AsyncUDP_WT32_ETH01/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement), feel free to add comments to them. 51 | 52 | --- 53 | 54 | ### Sending Pull Requests 55 | 56 | Pull Requests with changes and fixes are also welcome! 57 | 58 | Please use the `astyle` to reformat the updated library code as follows (demo for Ubuntu Linux) 59 | 60 | 1. Change directory to the library GitHub 61 | 62 | ``` 63 | xy@xy-Inspiron-3593:~$ cd Arduino/xy/AsyncUDP_WT32_ETH01_GitHub/ 64 | xy@xy-Inspiron-3593:~/Arduino/xy/AsyncUDP_WT32_ETH01_GitHub$ 65 | ``` 66 | 67 | 2. Issue astyle command 68 | 69 | ``` 70 | xy@xy-Inspiron-3593:~/Arduino/xy/AsyncUDP_WT32_ETH01_GitHub$ bash utils/restyle.sh 71 | ``` 72 | 73 | 74 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /LibraryPatches/esp32/cores/esp32/Server.h: -------------------------------------------------------------------------------- 1 | /* 2 | Server.h - Base class that provides Server 3 | Copyright (c) 2011 Adrian McEwen. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef server_h 21 | #define server_h 22 | 23 | #include "Print.h" 24 | 25 | class Server: public Print 26 | { 27 | public: 28 | // KH, change to fix compiler error for EthernetWebServer 29 | // error: cannot declare field 'EthernetWebServer::_server' to be of abstract type 'EthernetServer' 30 | // virtual void begin(uint16_t port=0) =0; 31 | //virtual void begin() = 0; 32 | void begin() {}; 33 | }; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AsyncUDP_WT32_ETH01 Library 2 | 3 | 4 | [![arduino-library-badge](https://www.ardu-badge.com/badge/AsyncUDP_WT32_ETH01.svg?)](https://www.ardu-badge.com/AsyncUDP_WT32_ETH01) 5 | [![GitHub release](https://img.shields.io/github/release/khoih-prog/AsyncUDP_WT32_ETH01.svg)](https://github.com/khoih-prog/AsyncUDP_WT32_ETH01/releases) 6 | [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](#Contributing) 7 | [![GitHub issues](https://img.shields.io/github/issues/khoih-prog/AsyncUDP_WT32_ETH01.svg)](http://github.com/khoih-prog/AsyncUDP_WT32_ETH01/issues) 8 | 9 | 10 | Donate to my libraries using BuyMeACoffee 11 | 12 | 13 | --- 14 | --- 15 | 16 | ## Table of Contents 17 | 18 | * [Important Change from v2.1.0](#Important-Change-from-v210) 19 | * [Why do we need this AsyncUDP_WT32_ETH01 library](#why-do-we-need-this-asyncudp_wt32_eth01-library) 20 | * [Features](#features) 21 | * [Why Async is better](#why-async-is-better) 22 | * [Currently supported Boards](#currently-supported-boards) 23 | * [Changelog](changelog.md) 24 | * [Prerequisites](#prerequisites) 25 | * [Installation](#installation) 26 | * [Use Arduino Library Manager](#use-arduino-library-manager) 27 | * [Manual Install](#manual-install) 28 | * [VS Code & PlatformIO](#vs-code--platformio) 29 | * [Libraries' Patches](#libraries-patches) 30 | * [1. For fixing ESP32 compile error](#1-for-fixing-esp32-compile-error) 31 | * [HOWTO Fix `Multiple Definitions` Linker Error](#howto-fix-multiple-definitions-linker-error) 32 | * [HOWTO Use analogRead() with ESP32 running WiFi and/or BlueTooth (BT/BLE)](#howto-use-analogread-with-esp32-running-wifi-andor-bluetooth-btble) 33 | * [1. ESP32 has 2 ADCs, named ADC1 and ADC2](#1--esp32-has-2-adcs-named-adc1-and-adc2) 34 | * [2. ESP32 ADCs functions](#2-esp32-adcs-functions) 35 | * [3. ESP32 WiFi uses ADC2 for WiFi functions](#3-esp32-wifi-uses-adc2-for-wifi-functions) 36 | * [HOWTO Setting up the Async UDP Client](#howto-setting-up-the-async-udp-client) 37 | * [Examples](#examples) 38 | * [ 1. AsyncUDPClient](examples/AsyncUDPClient) 39 | * [ 2. AsyncUdpNTPClient](examples/AsyncUdpNTPClient) 40 | * [ 3. AsyncUdpSendReceive](examples/AsyncUdpSendReceive) 41 | * [ 4. AsyncUDPServer](examples/AsyncUDPServer) 42 | * [ 5. AsyncUDPMulticastServer](examples/AsyncUDPMulticastServer) 43 | * [ 6. **multiFileProject**](examples/multiFileProject) **New** 44 | * [Example AsyncUdpNTPClient](#example-asyncudpntpclient) 45 | * [File AsyncUdpNTPClient.ino](#file-asyncudpntpclientino) 46 | * [Debug Terminal Output Samples](#debug-terminal-output-samples) 47 | * [1. AsyncUdpNTPClient on on ESP32_DEV with ETH_PHY_LAN8720](#1-asyncudpntpclient-on-esp32_dev-with-eth_phy_lan8720) 48 | * [2. AsyncUDPSendReceive on on ESP32_DEV with ETH_PHY_LAN8720](#2-asyncudpsendreceive-on-esp32_dev-with-eth_phy_lan8720) 49 | * [Debug](#debug) 50 | * [Troubleshooting](#troubleshooting) 51 | * [Issues](#issues) 52 | * [TO DO](#to-do) 53 | * [DONE](#done) 54 | * [Contributions and Thanks](#contributions-and-thanks) 55 | * [Contributing](#contributing) 56 | * [License](#license) 57 | * [Copyright](#copyright) 58 | 59 | 60 | --- 61 | --- 62 | 63 | ### Important Change from v2.1.0 64 | 65 | Please have a look at [HOWTO Fix `Multiple Definitions` Linker Error](#howto-fix-multiple-definitions-linker-error) 66 | 67 | 68 | --- 69 | --- 70 | 71 | ### Why do we need this [AsyncUDP_WT32_ETH01 library](https://github.com/khoih-prog/AsyncUDP_WT32_ETH01) 72 | 73 | #### Features 74 | 75 | This [AsyncUDP_WT32_ETH01 library](https://github.com/khoih-prog/AsyncUDP_WT32_ETH01) is a fully asynchronous UDP library, designed for a trouble-free, multi-connection network environment, for WT32_ETH01 (ESP32 + LAN8720 Ethernet). The library is easy to use and includes support for Unicast, Broadcast and Multicast environments. 76 | 77 | This library is based on, modified from: 78 | 79 | 1. [Hristo Gochkov's AsyncUDP](https://github.com/espressif/arduino-esp32/tree/master/libraries/AsyncUDP) 80 | 81 | to apply the better and faster **asynchronous** feature of the **powerful** [AsyncUDP](https://github.com/espressif/arduino-esp32/tree/master/libraries/AsyncUDP) into WT32_ETH01. 82 | 83 | 84 | #### Why Async is better 85 | 86 | - Using asynchronous network means that you can handle **more than one connection at the same time** 87 | - You are called once the request is ready and parsed 88 | - When you send the response, you are **immediately ready** to handle other connections while the server is taking care of sending the response in the background 89 | - **Speed is OMG** 90 | - After connecting to a UDP server as an Async Client, you are **immediately ready** to handle other connections while the Client is taking care of receiving the UDP responding packets in the background. 91 | - You are not required to check in a tight loop() the arrival of the UDP responding packets to process them. 92 | 93 | 94 | #### Currently supported Boards 95 | 96 | 1. **WT32_ETH01 boards** using ESP32-based boards and LAN8720 Ethernet 97 | 98 | --- 99 | --- 100 | 101 | 102 | ## Prerequisites 103 | 104 | 1. [`Arduino IDE 1.8.19+` for Arduino](https://github.com/arduino/Arduino). [![GitHub release](https://img.shields.io/github/release/arduino/Arduino.svg)](https://github.com/arduino/Arduino/releases/latest) 105 | 2. [`ESP32 Core 2.0.5+`](https://github.com/espressif/arduino-esp32) for ESP32-based boards. [![Latest release](https://img.shields.io/github/release/espressif/arduino-esp32.svg)](https://github.com/espressif/arduino-esp32/releases/latest/) 106 | 107 | 3. [`WebServer_WT32_ETH01 library 1.5.1+`](https://github.com/khoih-prog/WebServer_WT32_ETH01). To install, check [![arduino-library-badge](https://www.ardu-badge.com/badge/WebServer_WT32_ETH01.svg?)](https://www.ardu-badge.com/WebServer_WT32_ETH01). 108 | --- 109 | 110 | ### Installation 111 | 112 | The suggested way to install is to: 113 | 114 | #### Use Arduino Library Manager 115 | 116 | The best way is to use `Arduino Library Manager`. Search for `AsyncUDP_WT32_ETH01`, then select / install the latest version. You can also use this link [![arduino-library-badge](https://www.ardu-badge.com/badge/AsyncUDP_WT32_ETH01.svg?)](https://www.ardu-badge.com/AsyncUDP_WT32_ETH01) for more detailed instructions. 117 | 118 | ### Manual Install 119 | 120 | 1. Navigate to [AsyncUDP_WT32_ETH01](https://github.com/khoih-prog/AsyncUDP_WT32_ETH01) page. 121 | 2. Download the latest release `AsyncUDP_WT32_ETH01-main.zip`. 122 | 3. Extract the zip file to `AsyncUDP_WT32_ETH01-main` directory 123 | 4. Copy the whole `AsyncUDP_WT32_ETH01-main` folder to Arduino libraries' directory such as `~/Arduino/libraries/`. 124 | 125 | ### VS Code & PlatformIO: 126 | 127 | 1. Install [VS Code](https://code.visualstudio.com/) 128 | 2. Install [PlatformIO](https://platformio.org/platformio-ide) 129 | 3. Install [**AsyncUDP_WT32_ETH01** library](https://registry.platformio.org/libraries/AsyncUDP_WT32_ETH01) by using [Library Manager](https://registry.platformio.org/libraries/AsyncUDP_WT32_ETH01/installation). Search for AsyncUDP_WT32_ETH01 in [Platform.io Author's Libraries](https://platformio.org/lib/search?query=author:%22Khoi%20Hoang%22) 130 | 4. Use included [platformio.ini](platformio/platformio.ini) file from examples to ensure that all dependent libraries will installed automatically. Please visit documentation for the other options and examples at [Project Configuration File](https://docs.platformio.org/page/projectconf.html) 131 | 132 | --- 133 | --- 134 | 135 | 136 | ### Libraries' Patches 137 | 138 | #### 1. For fixing ESP32 compile error 139 | 140 | To fix [`ESP32 compile error`](https://github.com/espressif/arduino-esp32), just copy the following file into the [`ESP32`](https://github.com/espressif/arduino-esp32) cores/esp32 directory (e.g. ./arduino-1.8.15/hardware/espressif/cores/esp32) to overwrite the old file: 141 | - [Server.h](LibraryPatches/esp32/cores/esp32/Server.h) 142 | 143 | 144 | --- 145 | --- 146 | 147 | 148 | ### HOWTO Fix `Multiple Definitions` Linker Error 149 | 150 | The current library implementation, using `xyz-Impl.h` instead of standard `xyz.cpp`, possibly creates certain `Multiple Definitions` Linker error in certain use cases. 151 | 152 | You can include this `.hpp` file 153 | 154 | ```cpp 155 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 156 | #include "AsyncUDP_WT32_ETH01.hpp" //https://github.com/khoih-prog/AsyncUDP_WT32_ETH01 157 | ``` 158 | 159 | in many files. But be sure to use the following `.h` file **in just 1 `.h`, `.cpp` or `.ino` file**, which must **not be included in any other file**, to avoid `Multiple Definitions` Linker Error 160 | 161 | ```cpp 162 | // To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error 163 | #include "AsyncUDP_WT32_ETH01.h" //https://github.com/khoih-prog/AsyncUDP_WT32_ETH01 164 | ``` 165 | 166 | Check the new [**multiFileProject** example](examples/multiFileProject) for a `HOWTO` demo. 167 | 168 | 169 | 170 | --- 171 | --- 172 | 173 | ### HOWTO Use analogRead() with ESP32 running WiFi and/or BlueTooth (BT/BLE) 174 | 175 | Please have a look at [**ESP_WiFiManager Issue 39: Not able to read analog port when using the autoconnect example**](https://github.com/khoih-prog/ESP_WiFiManager/issues/39) to have more detailed description and solution of the issue. 176 | 177 | #### 1. ESP32 has 2 ADCs, named ADC1 and ADC2 178 | 179 | #### 2. ESP32 ADCs functions 180 | 181 | - ADC1 controls ADC function for pins **GPIO32-GPIO39** 182 | - ADC2 controls ADC function for pins **GPIO0, 2, 4, 12-15, 25-27** 183 | 184 | #### 3.. ESP32 WiFi uses ADC2 for WiFi functions 185 | 186 | Look in file [**adc_common.c**](https://github.com/espressif/esp-idf/blob/master/components/driver/adc_common.c#L61) 187 | 188 | > In ADC2, there're two locks used for different cases: 189 | > 1. lock shared with app and Wi-Fi: 190 | > ESP32: 191 | > When Wi-Fi using the ADC2, we assume it will never stop, so app checks the lock and returns immediately if failed. 192 | > ESP32S2: 193 | > The controller's control over the ADC is determined by the arbiter. There is no need to control by lock. 194 | > 195 | > 2. lock shared between tasks: 196 | > when several tasks sharing the ADC2, we want to guarantee 197 | > all the requests will be handled. 198 | > Since conversions are short (about 31us), app returns the lock very soon, 199 | > we use a spinlock to stand there waiting to do conversions one by one. 200 | > 201 | > adc2_spinlock should be acquired first, then adc2_wifi_lock or rtc_spinlock. 202 | 203 | 204 | - In order to use ADC2 for other functions, we have to **acquire complicated firmware locks and very difficult to do** 205 | - So, it's not advisable to use ADC2 with WiFi/BlueTooth (BT/BLE). 206 | - Use ADC1, and pins GPIO32-GPIO39 207 | - If somehow it's a must to use those pins serviced by ADC2 (**GPIO0, 2, 4, 12, 13, 14, 15, 25, 26 and 27**), use the **fix mentioned at the end** of [**ESP_WiFiManager Issue 39: Not able to read analog port when using the autoconnect example**](https://github.com/khoih-prog/ESP_WiFiManager/issues/39) to work with ESP32 WiFi/BlueTooth (BT/BLE). 208 | 209 | 210 | --- 211 | --- 212 | 213 | ## HOWTO Setting up the Async UDP Client 214 | 215 | ```cpp 216 | #define ASYNC_UDP_WT32_ETH01_DEBUG_PORT Serial 217 | 218 | // Use from 0 to 4. Higher number, more debugging messages and memory usage. 219 | #define _ASYNC_UDP_WT32_ETH01_LOGLEVEL_ 1 220 | 221 | #include 222 | 223 | ///////////////////////////////////////////// 224 | 225 | // Select the IP address according to your local network 226 | IPAddress myIP(192, 168, 2, 232); 227 | IPAddress myGW(192, 168, 2, 1); 228 | IPAddress mySN(255, 255, 255, 0); 229 | 230 | // Google DNS Server IP 231 | IPAddress myDNS(8, 8, 8, 8); 232 | 233 | ///////////////////////////////////////////// 234 | 235 | #include 236 | 237 | // 0.ca.pool.ntp.org 238 | IPAddress timeServerIP = IPAddress(208, 81, 1, 244); 239 | // time.nist.gov 240 | //IPAddress timeServerIP = IPAddress(132, 163, 96, 1); 241 | 242 | #define NTP_REQUEST_PORT 123 243 | 244 | const int NTP_PACKET_SIZE = 48; // NTP timestamp is in the first 48 bytes of the message 245 | 246 | byte packetBuffer[NTP_PACKET_SIZE]; // buffer to hold incoming and outgoing packets 247 | 248 | // A UDP instance to let us send and receive packets over UDP 249 | AsyncUDP Udp; 250 | 251 | // send an NTP request to the time server at the given address 252 | void createNTPpacket(void) 253 | { 254 | ... 255 | } 256 | 257 | void sendNTPPacket(void) 258 | { 259 | createNTPpacket(); 260 | //Send unicast 261 | Udp.write(packetBuffer, sizeof(packetBuffer)); 262 | } 263 | 264 | void parsePacket(AsyncUDPPacket packet) 265 | { 266 | ... 267 | } 268 | 269 | void setup() 270 | { 271 | ... 272 | 273 | //NTP requests are to port NTP_REQUEST_PORT = 123 274 | if (Udp.connect(timeServerIP, NTP_REQUEST_PORT)) 275 | { 276 | // Setting up Async packet Handler 277 | Udp.onPacket([](AsyncUDPPacket packet) 278 | { 279 | parsePacket(packet); 280 | }); 281 | } 282 | } 283 | 284 | void loop() 285 | { 286 | sendNTPPacket(); 287 | 288 | // wait 60 seconds before asking for the time again 289 | delay(60000); 290 | } 291 | ``` 292 | 293 | --- 294 | --- 295 | 296 | ### Examples 297 | 298 | 1. [AsyncUDPClient](examples/AsyncUDPClient) 299 | 2. [AsyncUdpNTPClient](examples/AsyncUdpNTPClient) 300 | 3. [AsyncUdpSendReceive](examples/AsyncUdpSendReceive) 301 | 4. [AsyncUDPServer](examples/AsyncUDPServer) 302 | 5. [AsyncUDPMulticastServer](examples/AsyncUDPMulticastServer) 303 | 6. [**multiFileProject**](examples/multiFileProject) **New** 304 | --- 305 | 306 | ### Example [AsyncUdpNTPClient](examples/AsyncUdpNTPClient) 307 | 308 | #### File [AsyncUdpNTPClient.ino](examples/AsyncUdpNTPClient/AsyncUdpNTPClient.ino) 309 | 310 | https://github.com/khoih-prog/AsyncUDP_WT32_ETH01/blob/38f14694c93ca0a393adfeffaee0027924a7e545/examples/AsyncUdpNTPClient/AsyncUdpNTPClient.ino#L11-L175 311 | 312 | --- 313 | 314 | ### Debug Terminal Output Samples 315 | 316 | #### 1. AsyncUdpNTPClient on ESP32_DEV with ETH_PHY_LAN8720 317 | 318 | This is terminal debug output when running [AsyncUdpNTPClient](https://github.com/khoih-prog/AsyncUDP_WT32_ETH01/tree/main/examples/AsyncUdpNTPClient) on **WT32_ETH01 (ESP32 + LAN8720)**. It connects to NTP Server using AsyncUDP_WT32_ETH01 library, and requests NTP time every 60s. The packet is then **received and processed asynchronously** to print current UTC/GMT time. 319 | 320 | ##### Connect to NTP server time.windows.com (IP=168.61.215.74) 321 | 322 | ```cpp 323 | Starting AsyncUdpNTPClient on ESP32_DEV with ETH_PHY_LAN8720 324 | WebServer_WT32_ETH01 v1.5.1 for core v2.0.0+ 325 | AsyncUdp_WT32_ETH01 v2.1.0 for core v2.0.0+ 326 | ETH Started 327 | ETH Connected 328 | ETH MAC: A8:03:2A:A1:61:73, IPv4: 192.168.2.95 329 | FULL_DUPLEX, 100Mbps 330 | AsyncUdpNTPClient started @ IP address: 192.168.2.232 331 | UDP connected 332 | ============= createNTPpacket ============= 333 | Received UDP Packet Type: Unicast 334 | From: 208.81.1.244:123, To: 192.168.2.232:50549, Length: 48 335 | Seconds since Jan 1 1900 = 3847193050 336 | Epoch/Unix time = 1638204250 337 | The UTC/GMT time is Mon 2021-11-29 16:44:10 GMT 338 | ============= createNTPpacket ============= 339 | Received UDP Packet Type: Unicast 340 | From: 208.81.1.244:123, To: 192.168.2.232:50549, Length: 48 341 | Seconds since Jan 1 1900 = 3847193110 342 | Epoch/Unix time = 1638204310 343 | The UTC/GMT time is Mon 2021-11-29 16:45:10 GMT 344 | ============= createNTPpacket ============= 345 | Received UDP Packet Type: Unicast 346 | From: 208.81.1.244:123, To: 192.168.2.232:50549, Length: 48 347 | Seconds since Jan 1 1900 = 3847193170 348 | Epoch/Unix time = 1638204370 349 | The UTC/GMT time is Mon 2021-11-29 16:46:10 GMT 350 | 351 | ``` 352 | 353 | ##### Connect to NTP server time.nist.gov (IP=132.163.96.1) 354 | 355 | ```cpp 356 | Starting AsyncUdpNTPClient on ESP32_DEV with ETH_PHY_LAN8720 357 | WebServer_WT32_ETH01 v1.5.1 for core v2.0.0+ 358 | AsyncUdp_WT32_ETH01 v2.1.0 for core v2.0.0+ 359 | ETH MAC: A8:03:2A:A1:61:73, IPv4: 192.168.2.232 360 | FULL_DUPLEX, 100Mbps 361 | AsyncUdpNTPClient started @ IP address: 192.168.2.232 362 | UDP connected 363 | ============= createNTPpacket ============= 364 | Received UDP Packet Type: Unicast 365 | From: 132.163.96.1:123, To: 192.168.2.232:50549, Length: 48 366 | Seconds since Jan 1 1900 = 3847193590 367 | Epoch/Unix time = 1638204790 368 | The UTC/GMT time is Mon 2021-11-29 16:53:10 GMT 369 | ============= createNTPpacket ============= 370 | Received UDP Packet Type: Unicast 371 | From: 132.163.96.1:123:123, To: 192.168.2.232:50549, Length: 48 372 | Seconds since Jan 1 1900 = 3847193650 373 | Epoch/Unix time = 1638204850 374 | The UTC/GMT time is Mon 2021-11-29 16:54:10 GMT 375 | ============= createNTPpacket ============= 376 | Received UDP Packet Type: Unicast 377 | From: 132.163.96.1:123:123, To: 192.168.2.232:50549, Length: 48 378 | Seconds since Jan 1 1900 = 3847193710 379 | Epoch/Unix time = 1638204910 380 | The UTC/GMT time is Mon 2021-11-29 16:55:10 GMT 381 | 382 | ``` 383 | 384 | --- 385 | 386 | #### 2. AsyncUDPSendReceive on ESP32_DEV with ETH_PHY_LAN8720 387 | 388 | This is terminal debug output when running [AsyncUDPSendReceive](https://github.com/khoih-prog/AsyncUDP_WT32_ETH01/tree/main/examples/AsyncUdpSendReceive) on **WT32_ETH01 (ESP32 + LAN8720)**. It connects to NTP Server `time.nist.gov` (IP=132.163.96.1) using AsyncUDP_WT32_ETH01 library, and requests NTP time every 60s. The packet is **received and processed asynchronously** to print current UTC/GMT time. The ACK packet is then sent. 389 | 390 | ```cpp 391 | Starting AsyncUDPSendReceive on ESP32_DEV with ETH_PHY_LAN8720 392 | WebServer_WT32_ETH01 v1.5.1 for core v2.0.0+ 393 | AsyncUdp_WT32_ETH01 v2.1.0 for core v2.0.0+ 394 | ETH MAC: A8:03:2A:A1:61:73, IPv4: 192.168.2.232 395 | FULL_DUPLEX, 100Mbps 396 | AsyncUDPSendReceive started @ IP address: 192.168.2.232 397 | 398 | Starting connection to server... 399 | UDP connected 400 | ============= createNTPpacket ============= 401 | Received UDP Packet Type: Unicast 402 | From: 132.163.96.1:123, To: 192.168.2.232:62775, Length: 48 403 | Seconds since Jan 1 1900 = 3834968497 404 | Epoch/Unix time = 1625979697 405 | The UTC/GMT time is Sun 2021-07-11 05:01:37 GMT 406 | ============= sendACKPacket ============= 407 | ============= createNTPpacket ============= 408 | Received UDP Packet Type: Unicast 409 | From: 132.163.96.1:123, To: 192.168.2.232:62775, Length: 48 410 | Seconds since Jan 1 1900 = 3834968557 411 | Epoch/Unix time = 1625979757 412 | The UTC/GMT time is Sun 2021-07-11 05:02:37 GMT 413 | ============= sendACKPacket ============= 414 | ``` 415 | 416 | --- 417 | --- 418 | 419 | ### Debug 420 | 421 | Debug is enabled by default on Serial. To disable, use level 0 422 | 423 | ```cpp 424 | #define ASYNC_UDP_WT32_ETH01_DEBUG_PORT Serial 425 | 426 | // Use from 0 to 4. Higher number, more debugging messages and memory usage. 427 | #define _ASYNC_UDP_WT32_ETH01_LOGLEVEL_ 1 428 | ``` 429 | 430 | You can also change the debugging level from 0 to 4 431 | 432 | ```cpp 433 | #define ASYNC_UDP_WT32_ETH01_DEBUG_PORT Serial 434 | 435 | // Use from 0 to 4. Higher number, more debugging messages and memory usage. 436 | #define _ASYNC_UDP_WT32_ETH01_LOGLEVEL_ 4 437 | ``` 438 | 439 | --- 440 | 441 | ### Troubleshooting 442 | 443 | If you get compilation errors, more often than not, you may need to install a newer version of Arduino IDE, the Arduino `STM32` core or depending libraries. 444 | 445 | Sometimes, the library will only work if you update the `STM32` core to the latest version because I am always using the latest cores /libraries. 446 | 447 | --- 448 | --- 449 | 450 | 451 | ### Issues ### 452 | 453 | Submit issues to: [AsyncUDP_WT32_ETH01 issues](https://github.com/khoih-prog/AsyncUDP_WT32_ETH01/issues) 454 | 455 | --- 456 | 457 | ## TO DO 458 | 459 | 1. Fix bug. Add enhancement 460 | 461 | 462 | ## DONE 463 | 464 | 1. Initial port to to WT32_ETH01 (ESP32 + LAN8720) 465 | 2. Add more examples. 466 | 3. Add debugging features. 467 | 4. Auto detect ESP32 core to use for WT32_ETH01 468 | 5. Fix bug in WT32_ETH01 examples to reduce connection time 469 | 6. Fix `multiple-definitions` linker error. 470 | 7. Add example [multiFileProject](examples/multiFileProject) to demo for multiple-file project 471 | 472 | 473 | --- 474 | --- 475 | 476 | ### Contributions and Thanks 477 | 478 | 1. Based on and modified from [Hristo Gochkov's AsyncUDP](https://github.com/espressif/arduino-esp32/tree/master/libraries/AsyncUDP). Many thanks to [Hristo Gochkov](https://github.com/me-no-dev) for great [AsyncUDP Library]((https://github.com/espressif/arduino-esp32/tree/master/libraries/AsyncUDP)) 479 | 480 | 481 | 482 | 483 | 484 | 485 |
me-no-dev
⭐️⭐️ Hristo Gochkov

486 | 487 | --- 488 | 489 | ### Contributing 490 | 491 | If you want to contribute to this project: 492 | 493 | - Report bugs and errors 494 | - Ask for enhancements 495 | - Create issues and pull requests 496 | - Tell other people about this library 497 | 498 | --- 499 | 500 | ### License 501 | 502 | - The library is licensed under [GPLv3](https://github.com/khoih-prog/AsyncUDP_WT32_ETH01/blob/main/LICENSE) 503 | 504 | --- 505 | 506 | ## Copyright 507 | 508 | Copyright (c) 2018- Hristo Gochkov 509 | 510 | Copyright (c) 2021- Khoi Hoang 511 | 512 | 513 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # AsyncUDP_WT32_ETH01 Library 2 | 3 | 4 | [![arduino-library-badge](https://www.ardu-badge.com/badge/AsyncUDP_WT32_ETH01.svg?)](https://www.ardu-badge.com/AsyncUDP_WT32_ETH01) 5 | [![GitHub release](https://img.shields.io/github/release/khoih-prog/AsyncUDP_WT32_ETH01.svg)](https://github.com/khoih-prog/AsyncUDP_WT32_ETH01/releases) 6 | [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](#Contributing) 7 | [![GitHub issues](https://img.shields.io/github/issues/khoih-prog/AsyncUDP_WT32_ETH01.svg)](http://github.com/khoih-prog/AsyncUDP_WT32_ETH01/issues) 8 | 9 | 10 | Donate to my libraries using BuyMeACoffee 11 | 12 | 13 | 14 | --- 15 | --- 16 | 17 | ## Table of Contents 18 | 19 | * [Changelog](#changelog) 20 | * [Releases v2.1.0](#releases-v210) 21 | * [Releases v2.0.3](#releases-v203) 22 | * [Releases v2.0.2](#releases-v202) 23 | * [Releases v2.0.1](#releases-v201) 24 | * [Initial Releases v2.0.0](#initial-releases-v200) 25 | 26 | --- 27 | --- 28 | 29 | ## Changelog 30 | 31 | #### Releases v2.1.0 32 | 33 | 1. Fix multiple-definitions linker error. Check [Multiple definitions #1](https://github.com/khoih-prog/AsyncUDP_WT32_ETH01/issues/1) 34 | 2. Add example [multiFileProject](examples/multiFileProject) to demo for multiple-file project to avoid `multiple-definitions` linker error 35 | 36 | ### Releases v2.0.3 37 | 38 | ##### Warning: Releases v2.0.3+ can be used and autodetect ESP32 core v2.0.0+ or v1.0.6- for WT32_ETH01 39 | 40 | 1. Auto detect ESP32 core to use for WT32_ETH01 41 | 2. Fix bug in WT32_ETH01 examples to reduce connection time 42 | 3. Remove library's redundant code 43 | 44 | 45 | ### Releases v2.0.2 46 | 47 | 1. Update `platform.ini` and `library.json` to use original `khoih-prog` instead of `khoih.prog` after PIO fix 48 | 49 | ### Releases v2.0.1 50 | 51 | 1. Update to use WebServer_WT32_ETH01 v1.2.0 52 | 53 | ### Initial Releases v2.0.0 54 | 55 | 1. Initial coding to port [AsyncUDP](https://github.com/espressif/arduino-esp32/tree/master/libraries/AsyncUDP) to WT32_ETH01 (ESP32 + LAN8720) 56 | 2. Add more examples. 57 | 3. Add debugging features. 58 | 4. Bump up to v2.0.0 to sync with [AsyncUDP v2.0.0](https://github.com/espressif/arduino-esp32/tree/master/libraries/AsyncUDP). 59 | 60 | 61 | -------------------------------------------------------------------------------- /examples/AsyncUDPClient/AsyncUDPClient.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | Async_UdpClient.ino 3 | 4 | AsyncUDP_WT32_ETH01 is a Async UDP library for the WT32_ETH01 (ESP32 + LAN8720) 5 | 6 | Based on and modified from ESPAsyncUDP Library (https://github.com/me-no-dev/ESPAsyncUDP) 7 | Built by Khoi Hoang https://github.com/khoih-prog/AsyncUDP_WT32_ETH01 8 | Licensed under MIT license 9 | *****************************************************************************************************************************/ 10 | #include 11 | 12 | #define ASYNC_UDP_WT32_ETH01_DEBUG_PORT Serial 13 | 14 | // Use from 0 to 4. Higher number, more debugging messages and memory usage. 15 | #define _ASYNC_UDP_WT32_ETH01_LOGLEVEL_ 1 16 | 17 | #include 18 | 19 | IPAddress remoteIPAddress = IPAddress(192, 168, 2, 112); 20 | 21 | #define UDP_REMOTE_PORT 5698 22 | 23 | ///////////////////////////////////////////// 24 | 25 | // Select the IP address according to your local network 26 | IPAddress myIP(192, 168, 2, 232); 27 | IPAddress myGW(192, 168, 2, 1); 28 | IPAddress mySN(255, 255, 255, 0); 29 | 30 | // Google DNS Server IP 31 | IPAddress myDNS(8, 8, 8, 8); 32 | 33 | ///////////////////////////////////////////// 34 | 35 | AsyncUDP udp; 36 | 37 | void parsePacket(AsyncUDPPacket packet) 38 | { 39 | Serial.print("UDP Packet Type: "); 40 | Serial.print(packet.isBroadcast() ? "Broadcast" : packet.isMulticast() ? "Multicast" : "Unicast"); 41 | Serial.print(", From: "); 42 | Serial.print(packet.remoteIP()); 43 | Serial.print(":"); 44 | Serial.print(packet.remotePort()); 45 | Serial.print(", To: "); 46 | Serial.print(packet.localIP()); 47 | Serial.print(":"); 48 | Serial.print(packet.localPort()); 49 | Serial.print(", Length: "); 50 | Serial.print(packet.length()); 51 | Serial.print(", Data: "); 52 | Serial.write(packet.data(), packet.length()); 53 | Serial.println(); 54 | //reply to the client 55 | packet.printf("Got %u bytes of data", packet.length()); 56 | } 57 | 58 | void setup() 59 | { 60 | Serial.begin(115200); 61 | 62 | while (!Serial); 63 | 64 | Serial.print("\nStarting Async_UDPClient on " + String(ARDUINO_BOARD)); 65 | Serial.println(" with " + String(SHIELD_TYPE)); 66 | Serial.println(WEBSERVER_WT32_ETH01_VERSION); 67 | Serial.println(ASYNC_UDP_WT32_ETH01_VERSION); 68 | 69 | Serial.setDebugOutput(true); 70 | 71 | // To be called before ETH.begin() 72 | WT32_ETH01_onEvent(); 73 | 74 | //bool begin(uint8_t phy_addr=ETH_PHY_ADDR, int power=ETH_PHY_POWER, int mdc=ETH_PHY_MDC, int mdio=ETH_PHY_MDIO, 75 | // eth_phy_type_t type=ETH_PHY_TYPE, eth_clock_mode_t clk_mode=ETH_CLK_MODE); 76 | //ETH.begin(ETH_PHY_ADDR, ETH_PHY_POWER, ETH_PHY_MDC, ETH_PHY_MDIO, ETH_PHY_TYPE, ETH_CLK_MODE); 77 | ETH.begin(ETH_PHY_ADDR, ETH_PHY_POWER); 78 | 79 | // Static IP, leave without this line to get IP via DHCP 80 | //bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = 0, IPAddress dns2 = 0); 81 | ETH.config(myIP, myGW, mySN, myDNS); 82 | 83 | WT32_ETH01_waitForConnect(); 84 | 85 | // Client address 86 | Serial.print("Async_UDPClient started @ IP address: "); 87 | Serial.println(ETH.localIP()); 88 | 89 | if (udp.connect(remoteIPAddress, UDP_REMOTE_PORT)) 90 | { 91 | Serial.println("UDP connected"); 92 | 93 | udp.onPacket([](AsyncUDPPacket packet) 94 | { 95 | parsePacket( packet); 96 | }); 97 | 98 | //Send unicast 99 | udp.print("Hello Server!"); 100 | } 101 | } 102 | 103 | void loop() 104 | { 105 | delay(10000); 106 | //Send broadcast on port UDP_REMOTE_PORT = 1234 107 | udp.broadcastTo("Anyone here?", UDP_REMOTE_PORT); 108 | } 109 | -------------------------------------------------------------------------------- /examples/AsyncUDPMulticastServer/AsyncUDPMulticastServer.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | AsyncUDPMulticastServer.ino 3 | 4 | AsyncUDP_WT32_ETH01 is a Async UDP library for the WT32_ETH01 (ESP32 + LAN8720) 5 | 6 | Based on and modified from ESPAsyncUDP Library (https://github.com/me-no-dev/ESPAsyncUDP) 7 | Built by Khoi Hoang https://github.com/khoih-prog/AsyncUDP_WT32_ETH01 8 | Licensed under MIT license 9 | *****************************************************************************************************************************/ 10 | 11 | #include 12 | 13 | #define ASYNC_UDP_WT32_ETH01_DEBUG_PORT Serial 14 | 15 | // Use from 0 to 4. Higher number, more debugging messages and memory usage. 16 | #define _ASYNC_UDP_WT32_ETH01_LOGLEVEL_ 1 17 | 18 | #include 19 | 20 | ///////////////////////////////////////////// 21 | 22 | // Select the IP address according to your local network 23 | IPAddress myIP(192, 168, 2, 232); 24 | IPAddress myGW(192, 168, 2, 1); 25 | IPAddress mySN(255, 255, 255, 0); 26 | 27 | // Google DNS Server IP 28 | IPAddress myDNS(8, 8, 8, 8); 29 | 30 | ///////////////////////////////////////////// 31 | 32 | AsyncUDP udp; 33 | 34 | void parsePacket(AsyncUDPPacket packet) 35 | { 36 | Serial.print("UDP Packet Type: "); 37 | Serial.print(packet.isBroadcast() ? "Broadcast" : packet.isMulticast() ? "Multicast" : "Unicast"); 38 | Serial.print(", From: "); 39 | Serial.print(packet.remoteIP()); 40 | Serial.print(":"); 41 | Serial.print(packet.remotePort()); 42 | Serial.print(", To: "); 43 | Serial.print(packet.localIP()); 44 | Serial.print(":"); 45 | Serial.print(packet.localPort()); 46 | Serial.print(", Length: "); 47 | Serial.print(packet.length()); 48 | Serial.print(", Data: "); 49 | Serial.write(packet.data(), packet.length()); 50 | Serial.println(); 51 | //reply to the client 52 | packet.printf("Got %u bytes of data", packet.length()); 53 | } 54 | 55 | void setup() 56 | { 57 | Serial.begin(115200); 58 | 59 | while (!Serial); 60 | 61 | Serial.print("\nStarting AsyncUDPMulticastServer on " + String(ARDUINO_BOARD)); 62 | Serial.println(" with " + String(SHIELD_TYPE)); 63 | Serial.println(WEBSERVER_WT32_ETH01_VERSION); 64 | Serial.println(ASYNC_UDP_WT32_ETH01_VERSION); 65 | 66 | Serial.setDebugOutput(true); 67 | 68 | // To be called before ETH.begin() 69 | WT32_ETH01_onEvent(); 70 | 71 | //bool begin(uint8_t phy_addr=ETH_PHY_ADDR, int power=ETH_PHY_POWER, int mdc=ETH_PHY_MDC, int mdio=ETH_PHY_MDIO, 72 | // eth_phy_type_t type=ETH_PHY_TYPE, eth_clock_mode_t clk_mode=ETH_CLK_MODE); 73 | //ETH.begin(ETH_PHY_ADDR, ETH_PHY_POWER, ETH_PHY_MDC, ETH_PHY_MDIO, ETH_PHY_TYPE, ETH_CLK_MODE); 74 | ETH.begin(ETH_PHY_ADDR, ETH_PHY_POWER); 75 | 76 | // Static IP, leave without this line to get IP via DHCP 77 | //bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = 0, IPAddress dns2 = 0); 78 | ETH.config(myIP, myGW, mySN, myDNS); 79 | 80 | WT32_ETH01_waitForConnect(); 81 | 82 | // Client address 83 | Serial.print("Async_UDPClient started @ IP address: "); 84 | Serial.println(ETH.localIP()); 85 | 86 | 87 | if (udp.listenMulticast(IPAddress(239, 1, 2, 3), 1234)) 88 | { 89 | Serial.print("UDP Listening on IP: "); 90 | Serial.println(ETH.localIP()); 91 | 92 | udp.onPacket([](AsyncUDPPacket packet) 93 | { 94 | parsePacket(packet); 95 | }); 96 | 97 | //Send multicast 98 | udp.print("Hello!"); 99 | } 100 | } 101 | 102 | void loop() 103 | { 104 | delay(1000); 105 | //Send multicast 106 | udp.print("Anyone here?"); 107 | } 108 | -------------------------------------------------------------------------------- /examples/AsyncUDPServer/AsyncUDPServer.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | Async_UdpServer.ino 3 | 4 | AsyncUDP_WT32_ETH01 is a Async UDP library for the WT32_ETH01 (ESP32 + LAN8720) 5 | 6 | Based on and modified from ESPAsyncUDP Library (https://github.com/me-no-dev/ESPAsyncUDP) 7 | Built by Khoi Hoang https://github.com/khoih-prog/AsyncUDP_WT32_ETH01 8 | Licensed under MIT license 9 | *****************************************************************************************************************************/ 10 | #include 11 | 12 | #define ASYNC_UDP_WT32_ETH01_DEBUG_PORT Serial 13 | 14 | // Use from 0 to 4. Higher number, more debugging messages and memory usage. 15 | #define _ASYNC_UDP_WT32_ETH01_LOGLEVEL_ 1 16 | 17 | #include 18 | 19 | ///////////////////////////////////////////// 20 | 21 | // Select the IP address according to your local network 22 | IPAddress myIP(192, 168, 2, 232); 23 | IPAddress myGW(192, 168, 2, 1); 24 | IPAddress mySN(255, 255, 255, 0); 25 | 26 | // Google DNS Server IP 27 | IPAddress myDNS(8, 8, 8, 8); 28 | 29 | ///////////////////////////////////////////// 30 | 31 | AsyncUDP udp; 32 | 33 | void setup() 34 | { 35 | Serial.begin(115200); 36 | 37 | while (!Serial); 38 | 39 | Serial.print("\nStarting Async_UDPClient on " + String(ARDUINO_BOARD)); 40 | Serial.println(" with " + String(SHIELD_TYPE)); 41 | Serial.println(WEBSERVER_WT32_ETH01_VERSION); 42 | Serial.println(ASYNC_UDP_WT32_ETH01_VERSION); 43 | 44 | Serial.setDebugOutput(true); 45 | 46 | // To be called before ETH.begin() 47 | WT32_ETH01_onEvent(); 48 | 49 | //bool begin(uint8_t phy_addr=ETH_PHY_ADDR, int power=ETH_PHY_POWER, int mdc=ETH_PHY_MDC, int mdio=ETH_PHY_MDIO, 50 | // eth_phy_type_t type=ETH_PHY_TYPE, eth_clock_mode_t clk_mode=ETH_CLK_MODE); 51 | //ETH.begin(ETH_PHY_ADDR, ETH_PHY_POWER, ETH_PHY_MDC, ETH_PHY_MDIO, ETH_PHY_TYPE, ETH_CLK_MODE); 52 | ETH.begin(ETH_PHY_ADDR, ETH_PHY_POWER); 53 | 54 | // Static IP, leave without this line to get IP via DHCP 55 | //bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = 0, IPAddress dns2 = 0); 56 | ETH.config(myIP, myGW, mySN, myDNS); 57 | 58 | WT32_ETH01_waitForConnect(); 59 | 60 | // Client address 61 | Serial.print("AsyncUDPServer started @ IP address: "); 62 | Serial.println(ETH.localIP()); 63 | 64 | if (udp.listen(1234)) 65 | { 66 | Serial.print("UDP Listening on IP: "); 67 | Serial.println(ETH.localIP()); 68 | 69 | udp.onPacket([](AsyncUDPPacket packet) 70 | { 71 | Serial.print("UDP Packet Type: "); 72 | Serial.print(packet.isBroadcast() ? "Broadcast" : packet.isMulticast() ? "Multicast" : "Unicast"); 73 | Serial.print(", From: "); 74 | Serial.print(packet.remoteIP()); 75 | Serial.print(":"); 76 | Serial.print(packet.remotePort()); 77 | Serial.print(", To: "); 78 | Serial.print(packet.localIP()); 79 | Serial.print(":"); 80 | Serial.print(packet.localPort()); 81 | Serial.print(", Length: "); 82 | Serial.print(packet.length()); 83 | Serial.print(", Data: "); 84 | Serial.write(packet.data(), packet.length()); 85 | Serial.println(); 86 | //reply to the client 87 | packet.printf("Got %u bytes of data", packet.length()); 88 | }); 89 | } 90 | } 91 | 92 | void loop() 93 | { 94 | delay(1000); 95 | //Send broadcast 96 | udp.broadcast("Anyone here?"); 97 | } 98 | -------------------------------------------------------------------------------- /examples/AsyncUdpNTPClient/AsyncUdpNTPClient.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | AsyncUdpNTPClient.ino 3 | 4 | AsyncUDP_WT32_ETH01 is a Async UDP library for the WT32_ETH01 (ESP32 + LAN8720) 5 | 6 | Based on and modified from ESPAsyncUDP Library (https://github.com/me-no-dev/ESPAsyncUDP) 7 | Built by Khoi Hoang https://github.com/khoih-prog/AsyncUDP_WT32_ETH01 8 | Licensed under MIT license 9 | *****************************************************************************************************************************/ 10 | 11 | #define ASYNC_UDP_WT32_ETH01_DEBUG_PORT Serial 12 | 13 | // Use from 0 to 4. Higher number, more debugging messages and memory usage. 14 | #define _ASYNC_UDP_WT32_ETH01_LOGLEVEL_ 2 15 | 16 | #include 17 | 18 | ///////////////////////////////////////////// 19 | 20 | // Select the IP address according to your local network 21 | IPAddress myIP(192, 168, 2, 232); 22 | IPAddress myGW(192, 168, 2, 1); 23 | IPAddress mySN(255, 255, 255, 0); 24 | 25 | // Google DNS Server IP 26 | IPAddress myDNS(8, 8, 8, 8); 27 | 28 | ///////////////////////////////////////////// 29 | 30 | #include 31 | 32 | // 0.ca.pool.ntp.org 33 | IPAddress timeServerIP = IPAddress(208, 81, 1, 244); 34 | // time.nist.gov 35 | //IPAddress timeServerIP = IPAddress(132, 163, 96, 1); 36 | 37 | #define NTP_REQUEST_PORT 123 38 | 39 | const int NTP_PACKET_SIZE = 48; // NTP timestamp is in the first 48 bytes of the message 40 | 41 | byte packetBuffer[NTP_PACKET_SIZE]; // buffer to hold incoming and outgoing packets 42 | 43 | // A UDP instance to let us send and receive packets over UDP 44 | AsyncUDP Udp; 45 | 46 | // send an NTP request to the time server at the given address 47 | void createNTPpacket(void) 48 | { 49 | Serial.println("============= createNTPpacket ============="); 50 | 51 | // set all bytes in the buffer to 0 52 | memset(packetBuffer, 0, NTP_PACKET_SIZE); 53 | // Initialize values needed to form NTP request 54 | // (see URL above for details on the packets) 55 | 56 | packetBuffer[0] = 0b11100011; // LI, Version, Mode 57 | packetBuffer[1] = 0; // Stratum, or type of clock 58 | packetBuffer[2] = 6; // Polling Interval 59 | packetBuffer[3] = 0xEC; // Peer Clock Precision 60 | 61 | // 8 bytes of zero for Root Delay & Root Dispersion 62 | packetBuffer[12] = 49; 63 | packetBuffer[13] = 0x4E; 64 | packetBuffer[14] = 49; 65 | packetBuffer[15] = 52; 66 | } 67 | 68 | void parsePacket(AsyncUDPPacket packet) 69 | { 70 | struct tm ts; 71 | char buf[80]; 72 | 73 | memcpy(packetBuffer, packet.data(), sizeof(packetBuffer)); 74 | 75 | Serial.print("Received UDP Packet Type: "); 76 | Serial.println(packet.isBroadcast() ? "Broadcast" : packet.isMulticast() ? "Multicast" : "Unicast"); 77 | Serial.print("From: "); 78 | Serial.print(packet.remoteIP()); 79 | Serial.print(":"); 80 | Serial.print(packet.remotePort()); 81 | Serial.print(", To: "); 82 | Serial.print(packet.localIP()); 83 | Serial.print(":"); 84 | Serial.print(packet.localPort()); 85 | Serial.print(", Length: "); 86 | Serial.print(packet.length()); 87 | Serial.println(); 88 | 89 | unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); 90 | unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); 91 | 92 | // combine the four bytes (two words) into a long integer 93 | // this is NTP time (seconds since Jan 1 1900): 94 | unsigned long secsSince1900 = highWord << 16 | lowWord; 95 | 96 | Serial.print(F("Seconds since Jan 1 1900 = ")); 97 | Serial.println(secsSince1900); 98 | 99 | // now convert NTP time into )everyday time: 100 | Serial.print(F("Epoch/Unix time = ")); 101 | 102 | // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: 103 | const unsigned long seventyYears = 2208988800UL; 104 | 105 | // subtract seventy years: 106 | unsigned long epoch = secsSince1900 - seventyYears; 107 | time_t epoch_t = epoch; //secsSince1900 - seventyYears; 108 | 109 | // print Unix time: 110 | Serial.println(epoch); 111 | 112 | // print the hour, minute and second: 113 | Serial.print(F("The UTC/GMT time is ")); // UTC is the time at Greenwich Meridian (GMT) 114 | 115 | ts = *localtime(&epoch_t); 116 | strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", &ts); 117 | Serial.println(buf); 118 | } 119 | 120 | void sendNTPPacket(void) 121 | { 122 | createNTPpacket(); 123 | //Send unicast 124 | Udp.write(packetBuffer, sizeof(packetBuffer)); 125 | } 126 | 127 | void setup() 128 | { 129 | Serial.begin(115200); 130 | 131 | while (!Serial); 132 | 133 | Serial.print("\nStarting AsyncUdpNTPClient on " + String(ARDUINO_BOARD)); 134 | Serial.println(" with " + String(SHIELD_TYPE)); 135 | Serial.println(WEBSERVER_WT32_ETH01_VERSION); 136 | Serial.println(ASYNC_UDP_WT32_ETH01_VERSION); 137 | 138 | Serial.setDebugOutput(true); 139 | 140 | // To be called before ETH.begin() 141 | WT32_ETH01_onEvent(); 142 | 143 | //bool begin(uint8_t phy_addr=ETH_PHY_ADDR, int power=ETH_PHY_POWER, int mdc=ETH_PHY_MDC, int mdio=ETH_PHY_MDIO, 144 | // eth_phy_type_t type=ETH_PHY_TYPE, eth_clock_mode_t clk_mode=ETH_CLK_MODE); 145 | //ETH.begin(ETH_PHY_ADDR, ETH_PHY_POWER, ETH_PHY_MDC, ETH_PHY_MDIO, ETH_PHY_TYPE, ETH_CLK_MODE); 146 | ETH.begin(ETH_PHY_ADDR, ETH_PHY_POWER); 147 | 148 | // Static IP, leave without this line to get IP via DHCP 149 | //bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = 0, IPAddress dns2 = 0); 150 | ETH.config(myIP, myGW, mySN, myDNS); 151 | 152 | WT32_ETH01_waitForConnect(); 153 | 154 | // Client address 155 | Serial.print("AsyncUdpNTPClient started @ IP address: "); 156 | Serial.println(ETH.localIP()); 157 | 158 | //NTP requests are to port NTP_REQUEST_PORT = 123 159 | if (Udp.connect(timeServerIP, NTP_REQUEST_PORT)) 160 | { 161 | Serial.println("UDP connected"); 162 | 163 | Udp.onPacket([](AsyncUDPPacket packet) 164 | { 165 | parsePacket(packet); 166 | }); 167 | } 168 | } 169 | 170 | void loop() 171 | { 172 | sendNTPPacket(); 173 | 174 | // wait 60 seconds before asking for the time again 175 | delay(60000); 176 | } 177 | -------------------------------------------------------------------------------- /examples/AsyncUdpSendReceive/AsyncUdpSendReceive.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | AsyncUDPSendReceive.ino 3 | 4 | AsyncUDP_WT32_ETH01 is a Async UDP library for the WT32_ETH01 (ESP32 + LAN8720) 5 | 6 | Based on and modified from ESPAsyncUDP Library (https://github.com/me-no-dev/ESPAsyncUDP) 7 | Built by Khoi Hoang https://github.com/khoih-prog/AsyncUDP_WT32_ETH01 8 | Licensed under MIT license 9 | *****************************************************************************************************************************/ 10 | 11 | #define ASYNC_UDP_WT32_ETH01_DEBUG_PORT Serial 12 | 13 | // Use from 0 to 4. Higher number, more debugging messages and memory usage. 14 | #define _ASYNC_UDP_WT32_ETH01_LOGLEVEL_ 1 15 | 16 | #include 17 | 18 | ///////////////////////////////////////////// 19 | 20 | // Select the IP address according to your local network 21 | IPAddress myIP(192, 168, 2, 232); 22 | IPAddress myGW(192, 168, 2, 1); 23 | IPAddress mySN(255, 255, 255, 0); 24 | 25 | // Google DNS Server IP 26 | IPAddress myDNS(8, 8, 8, 8); 27 | 28 | ///////////////////////////////////////////// 29 | 30 | #include 31 | 32 | // 0.ca.pool.ntp.org 33 | IPAddress timeServerIP = IPAddress(208, 81, 1, 244); 34 | // time.nist.gov 35 | //IPAddress timeServerIP = IPAddress(132, 163, 96, 1); 36 | 37 | #define NTP_REQUEST_PORT 123 38 | 39 | char ReplyBuffer[] = "ACK"; // a string to send back 40 | 41 | char timeServer[] = "time.nist.gov"; // NTP server 42 | 43 | const int NTP_PACKET_SIZE = 48; // NTP timestamp is in the first 48 bytes of the message 44 | 45 | byte packetBuffer[NTP_PACKET_SIZE]; // buffer to hold incoming and outgoing packets 46 | 47 | // A UDP instance to let us send and receive packets over UDP 48 | AsyncUDP Udp; 49 | 50 | void sendACKPacket(void) 51 | { 52 | Serial.println("============= sendACKPacket ============="); 53 | 54 | // Send unicast ACK to the same remoteIP and remotePort we received the packet 55 | // The AsyncUDP_STM32 library will take care of the correct IP and port based on pcb 56 | Udp.write((uint8_t *) ReplyBuffer, sizeof(ReplyBuffer)); 57 | } 58 | 59 | // send an NTP request to the time server at the given address 60 | void createNTPpacket(void) 61 | { 62 | Serial.println("============= createNTPpacket ============="); 63 | 64 | // set all bytes in the buffer to 0 65 | memset(packetBuffer, 0, NTP_PACKET_SIZE); 66 | // Initialize values needed to form NTP request 67 | // (see URL above for details on the packets) 68 | 69 | packetBuffer[0] = 0b11100011; // LI, Version, Mode 70 | packetBuffer[1] = 0; // Stratum, or type of clock 71 | packetBuffer[2] = 6; // Polling Interval 72 | packetBuffer[3] = 0xEC; // Peer Clock Precision 73 | 74 | // 8 bytes of zero for Root Delay & Root Dispersion 75 | packetBuffer[12] = 49; 76 | packetBuffer[13] = 0x4E; 77 | packetBuffer[14] = 49; 78 | packetBuffer[15] = 52; 79 | } 80 | 81 | void sendNTPPacket(void) 82 | { 83 | createNTPpacket(); 84 | //Send unicast 85 | Udp.write(packetBuffer, sizeof(packetBuffer)); 86 | } 87 | 88 | void parsePacket(AsyncUDPPacket packet) 89 | { 90 | struct tm ts; 91 | char buf[80]; 92 | 93 | memcpy(packetBuffer, packet.data(), sizeof(packetBuffer)); 94 | 95 | Serial.print("Received UDP Packet Type: "); 96 | Serial.println(packet.isBroadcast() ? "Broadcast" : packet.isMulticast() ? "Multicast" : "Unicast"); 97 | Serial.print("From: "); 98 | Serial.print(packet.remoteIP()); 99 | Serial.print(":"); 100 | Serial.print(packet.remotePort()); 101 | Serial.print(", To: "); 102 | Serial.print(packet.localIP()); 103 | Serial.print(":"); 104 | Serial.print(packet.localPort()); 105 | Serial.print(", Length: "); 106 | Serial.print(packet.length()); 107 | Serial.println(); 108 | 109 | unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); 110 | unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); 111 | 112 | // combine the four bytes (two words) into a long integer 113 | // this is NTP time (seconds since Jan 1 1900): 114 | unsigned long secsSince1900 = highWord << 16 | lowWord; 115 | 116 | Serial.print(F("Seconds since Jan 1 1900 = ")); 117 | Serial.println(secsSince1900); 118 | 119 | // now convert NTP time into )everyday time: 120 | Serial.print(F("Epoch/Unix time = ")); 121 | 122 | // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: 123 | const unsigned long seventyYears = 2208988800UL; 124 | 125 | // subtract seventy years: 126 | unsigned long epoch = secsSince1900 - seventyYears; 127 | time_t epoch_t = epoch; //secsSince1900 - seventyYears; 128 | 129 | // print Unix time: 130 | Serial.println(epoch); 131 | 132 | // print the hour, minute and second: 133 | Serial.print(F("The UTC/GMT time is ")); // UTC is the time at Greenwich Meridian (GMT) 134 | 135 | ts = *localtime(&epoch_t); 136 | strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", &ts); 137 | Serial.println(buf); 138 | 139 | // send a reply, to the IP address and port that sent us the packet we received 140 | sendACKPacket(); 141 | } 142 | 143 | void setup() 144 | { 145 | Serial.begin(115200); 146 | 147 | while (!Serial); 148 | 149 | Serial.print("\nStarting AsyncUDPSendReceive on " + String(ARDUINO_BOARD)); 150 | Serial.println(" with " + String(SHIELD_TYPE)); 151 | Serial.println(WEBSERVER_WT32_ETH01_VERSION); 152 | Serial.println(ASYNC_UDP_WT32_ETH01_VERSION); 153 | 154 | Serial.setDebugOutput(true); 155 | 156 | // To be called before ETH.begin() 157 | WT32_ETH01_onEvent(); 158 | 159 | //bool begin(uint8_t phy_addr=ETH_PHY_ADDR, int power=ETH_PHY_POWER, int mdc=ETH_PHY_MDC, int mdio=ETH_PHY_MDIO, 160 | // eth_phy_type_t type=ETH_PHY_TYPE, eth_clock_mode_t clk_mode=ETH_CLK_MODE); 161 | //ETH.begin(ETH_PHY_ADDR, ETH_PHY_POWER, ETH_PHY_MDC, ETH_PHY_MDIO, ETH_PHY_TYPE, ETH_CLK_MODE); 162 | ETH.begin(ETH_PHY_ADDR, ETH_PHY_POWER); 163 | 164 | // Static IP, leave without this line to get IP via DHCP 165 | //bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = 0, IPAddress dns2 = 0); 166 | ETH.config(myIP, myGW, mySN, myDNS); 167 | 168 | WT32_ETH01_waitForConnect(); 169 | 170 | // Client address 171 | Serial.print("AsyncUDPSendReceive started @ IP address: "); 172 | Serial.println(ETH.localIP()); 173 | 174 | Serial.println(F("\nStarting connection to server...")); 175 | 176 | //NTP requests are to port NTP_REQUEST_PORT = 123 177 | if (Udp.connect(timeServerIP, NTP_REQUEST_PORT)) 178 | { 179 | Serial.println("UDP connected"); 180 | 181 | Udp.onPacket([](AsyncUDPPacket packet) 182 | { 183 | parsePacket(packet); 184 | }); 185 | } 186 | } 187 | 188 | void loop() 189 | { 190 | sendNTPPacket(); 191 | 192 | // wait 60 seconds before asking for the time again 193 | delay(60000); 194 | } 195 | -------------------------------------------------------------------------------- /examples/multiFileProject/multiFileProject.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | multiFileProject.cpp 3 | AsyncUDP_WT32_ETH01 is a Async UDP library for the WT32_ETH01 (ESP32 + LAN8720) 4 | 5 | Based on and modified from ESPAsyncUDP Library (https://github.com/me-no-dev/ESPAsyncUDP) 6 | Built by Khoi Hoang https://github.com/khoih-prog/AsyncUDP_WT32_ETH01 7 | Licensed under MIT license 8 | *****************************************************************************************************************************/ 9 | 10 | // To demo how to include files in multi-file Projects 11 | 12 | #include "multiFileProject.h" 13 | -------------------------------------------------------------------------------- /examples/multiFileProject/multiFileProject.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | multiFileProject.h 3 | AsyncUDP_WT32_ETH01 is a Async UDP library for the WT32_ETH01 (ESP32 + LAN8720) 4 | 5 | Based on and modified from ESPAsyncUDP Library (https://github.com/me-no-dev/ESPAsyncUDP) 6 | Built by Khoi Hoang https://github.com/khoih-prog/AsyncUDP_WT32_ETH01 7 | Licensed under MIT license 8 | *****************************************************************************************************************************/ 9 | 10 | // To demo how to include files in multi-file Projects 11 | 12 | #pragma once 13 | 14 | #define _ASYNC_UDP_WT32_ETH01_LOGLEVEL_ 1 15 | 16 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 17 | #include "AsyncUDP_WT32_ETH01.hpp" 18 | -------------------------------------------------------------------------------- /examples/multiFileProject/multiFileProject.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | multiFileProject.ino 3 | AsyncUDP_WT32_ETH01 is a Async UDP library for the WT32_ETH01 (ESP32 + LAN8720) 4 | 5 | Based on and modified from ESPAsyncUDP Library (https://github.com/me-no-dev/ESPAsyncUDP) 6 | Built by Khoi Hoang https://github.com/khoih-prog/AsyncUDP_WT32_ETH01 7 | Licensed under MIT license 8 | *****************************************************************************************************************************/ 9 | 10 | // To demo how to include files in multi-file Projects 11 | 12 | #include "multiFileProject.h" 13 | 14 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 15 | #include "AsyncUDP_WT32_ETH01.h" 16 | 17 | void setup() 18 | { 19 | Serial.begin(115200); 20 | 21 | while (!Serial); 22 | 23 | delay(500); 24 | 25 | Serial.println("\nStart multiFileProject"); 26 | Serial.println(WEBSERVER_WT32_ETH01_VERSION); 27 | Serial.println(ASYNC_UDP_WT32_ETH01_VERSION); 28 | 29 | 30 | Serial.print("You're OK now"); 31 | } 32 | 33 | void loop() 34 | { 35 | // put your main code here, to run repeatedly: 36 | } 37 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For Ultrasound 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | AsyncUDP KEYWORD1 10 | AsyncUDPPacket KEYWORD1 11 | AsyncUDPMessage KEYWORD1 12 | ip_addr_t KEYWORD1 13 | 14 | AuPacketHandlerFunction KEYWORD1 15 | AuPacketHandlerFunctionWithArg KEYWORD1 16 | 17 | ####################################### 18 | # Methods and Functions (KEYWORD2) 19 | ####################################### 20 | 21 | ################### 22 | # AsyncUDPMessage 23 | ################### 24 | 25 | write KEYWORD2 26 | space KEYWORD2 27 | data KEYWORD2 28 | length KEYWORD2 29 | flush KEYWORD2 30 | 31 | ################### 32 | # AsyncUDPPacket 33 | ################### 34 | 35 | data KEYWORD2 36 | length KEYWORD2 37 | isBroadcast KEYWORD2 38 | isMulticast KEYWORD2 39 | localIP KEYWORD2 40 | localPort KEYWORD2 41 | remoteIP KEYWORD2 42 | remotePort KEYWORD2 43 | send KEYWORD2 44 | write KEYWORD2 45 | 46 | ################### 47 | # AsyncUDPPacket 48 | ################### 49 | 50 | onPacket KEYWORD2 51 | listen KEYWORD2 52 | listenMulticast KEYWORD2 53 | connect KEYWORD2 54 | close KEYWORD2 55 | write KEYWORD2 56 | broadcastTo KEYWORD2 57 | broadcast KEYWORD2 58 | sendTo KEYWORD2 59 | send KEYWORD2 60 | connected KEYWORD2 61 | 62 | ################### 63 | # Functions 64 | ################### 65 | 66 | WT32_ETH01_Event KEYWORD2 67 | 68 | ####################################### 69 | # Constants (LITERAL1) 70 | ####################################### 71 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"AsyncUDP_WT32_ETH01", 3 | "version": "2.1.0", 4 | "description":"Fully Asynchronous UDP Library for WT32_ETH01 (ESP32 + LAN8720). The library is easy to use and includes support for Unicast, Broadcast and Multicast environments.", 5 | "keywords":"communication, data, async, udp, ntp, time, time-server, server, client, multicast, broadcast, webserver, esp32, esp32-s2, esp32-c3, wt32-eth01, lan8720, lan8720a, udp-server, udp-multicast-server", 6 | "authors": 7 | [ 8 | { 9 | "name": "Hristo Gochkov", 10 | "url": "https://github.com/me-no-dev" 11 | }, 12 | { 13 | "name": "Khoi Hoang", 14 | "url": "https://github.com/khoih-prog", 15 | "email": "khoih.prog@gmail.com", 16 | "maintainer": true 17 | } 18 | ], 19 | "repository": 20 | { 21 | "type": "git", 22 | "url": "https://github.com/khoih-prog/AsyncUDP_WT32_ETH01" 23 | }, 24 | "homepage": "https://github.com/khoih-prog/AsyncUDP_WT32_ETH01", 25 | "export": { 26 | "exclude": [ 27 | "linux", 28 | "extras", 29 | "tests" 30 | ] 31 | }, 32 | "dependencies": 33 | [ 34 | { 35 | "owner": "khoih-prog", 36 | "name": "WebServer_WT32_ETH01", 37 | "version": "^1.5.1", 38 | "platforms": "espressif32" 39 | } 40 | ], 41 | "license": "LGPL-3.0", 42 | "frameworks": "*", 43 | "platforms": ["espressif32"], 44 | "examples": "examples/*/*/*.ino", 45 | "headers": [ "AsyncUDP_WT32_ETH01.h", "AsyncUDP_WT32_ETH01.hpp" ] 46 | } 47 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=AsyncUDP_WT32_ETH01 2 | version=2.1.0 3 | author=Hristo Gochkov,Khoi Hoang 4 | maintainer=Khoi Hoang 5 | sentence=Fully Asynchronous UDP Library for WT32_ETH01 (ESP32 + LAN8720). 6 | paragraph=The library is easy to use and includes support for Unicast, Broadcast and Multicast environments. 7 | category=Communication,AsyncWebServer,Async,UDP 8 | url=https://github.com/khoih-prog/AsyncUDP_WT32_ETH01 9 | repository=https://github.com/khoih-prog/AsyncUDP_WT32_ETH01 10 | architectures=esp32 11 | depends=WebServer_WT32_ETH01 12 | license=GPLv3 13 | includes=AsyncUDP_WT32_ETH01.h, AsyncUDP_WT32_ETH01.hpp 14 | -------------------------------------------------------------------------------- /platformio/platformio.ini: -------------------------------------------------------------------------------- 1 | ;PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [platformio] 12 | ; ============================================================ 13 | ; chose environment: 14 | ; ESP32 15 | ; esp32s2 16 | ; esp32s3 17 | ; esp32c3 18 | 19 | ; ============================================================ 20 | default_envs = ESP32 21 | 22 | [env] 23 | ; ============================================================ 24 | ; Serial configuration 25 | ; choose upload speed, serial-monitor speed 26 | ; ============================================================ 27 | upload_speed = 921600 28 | ;upload_port = COM11 29 | ;monitor_speed = 9600 30 | ;monitor_port = COM11 31 | 32 | ; Checks for the compatibility with frameworks and dev/platforms 33 | lib_compat_mode = strict 34 | lib_ldf_mode = chain+ 35 | ;lib_ldf_mode = deep+ 36 | 37 | lib_deps = 38 | ; PlatformIO 4.x 39 | ; WebServer_WT32_ETH01@~1.5.1 40 | ; PlatformIO 5.x 41 | khoih-prog/WebServer_WT32_ETH01@~1.5.1 42 | 43 | build_flags = 44 | ; set your debug output (default=Serial) 45 | -D DEBUG_ESP_PORT=Serial 46 | ; comment the following line to enable WiFi debugging 47 | -D NDEBUG 48 | 49 | [env:ESP32] 50 | platform = espressif32 51 | framework = arduino 52 | 53 | ; ============================================================ 54 | ; Board configuration 55 | ; choose your board by uncommenting one of the following lines 56 | ; ============================================================ 57 | ;board = esp32cam 58 | ;board = alksesp32 59 | ;board = featheresp32 60 | ;board = espea32 61 | ;board = bpi-bit 62 | ;board = d-duino-32 63 | board = esp32doit-devkit-v1 64 | ;board = pocket_32 65 | ;board = fm-devkit 66 | ;board = pico32 67 | ;board = esp32-evb 68 | ;board = esp32-gateway 69 | ;board = esp32-pro 70 | ;board = esp32-poe 71 | ;board = oroca_edubot 72 | ;board = onehorse32dev 73 | ;board = lopy 74 | ;board = lopy4 75 | ;board = wesp32 76 | ;board = esp32thing 77 | ;board = sparkfun_lora_gateway_1-channel 78 | ;board = ttgo-lora32-v1 79 | ;board = ttgo-t-beam 80 | ;board = turta_iot_node 81 | ;board = lolin_d32 82 | ;board = lolin_d32_pro 83 | ;board = lolin32 84 | ;board = wemosbat 85 | ;board = widora-air 86 | ;board = xinabox_cw02 87 | ;board = iotbusio 88 | ;board = iotbusproteus 89 | ;board = nina_w10 90 | 91 | [env:esp32s2] 92 | platform = espressif32 93 | framework = arduino 94 | 95 | ; toolchain download links see 96 | ; refer "name": "xtensa-esp32s2-elf-gcc","version": "gcc8_4_0-esp-2021r1" section of 97 | ; https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json 98 | ; e.g. Windows: https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-win32.zip 99 | platform_packages = 100 | toolchain-xtensa32s2@file://C:\Users\Max\Downloads\xtensa-esp32s2-elf 101 | framework-arduinoespressif32@https://github.com/espressif/arduino-esp32.git#a4118ea88987c28aac3a49bcb9cc5d6c0acc6f3f 102 | platformio/tool-esptoolpy @ ~1.30100 103 | framework = arduino 104 | board = esp32dev 105 | board_build.mcu = esp32s2 106 | board_build.partitions = huge_app.csv 107 | board_build.variant = esp32s2 108 | board_build.f_cpu = 240000000L 109 | board_build.f_flash = 80000000L 110 | board_build.flash_mode = qio 111 | board_build.arduino.ldscript = esp32s2_out.ld 112 | build_unflags = 113 | -DARDUINO_ESP32_DEV 114 | -DARDUINO_VARIANT="esp32" 115 | build_flags = 116 | -DARDUINO_ESP32S2_DEV 117 | -DARDUINO_VARIANT="esp32s2" 118 | 119 | 120 | [env:esp32s3] 121 | platform = espressif32 122 | framework = arduino 123 | 124 | board_build.mcu = esp32s3 125 | board_build.partitions = huge_app.csv 126 | board_build.variant = esp32s3 127 | board_build.f_cpu = 240000000L 128 | board_build.f_flash = 80000000L 129 | board_build.flash_mode = qio 130 | board_build.arduino.ldscript = esp32s3_out.ld 131 | build_unflags = 132 | -DARDUINO_ESP32_DEV 133 | -DARDUINO_VARIANT="esp32" 134 | build_flags = 135 | -DARDUINO_ESP32S3_DEV 136 | -DARDUINO_VARIANT="esp32s3" 137 | 138 | 139 | [env:esp32sc3] 140 | platform = espressif32 141 | framework = arduino 142 | 143 | board_build.mcu = esp32c3 144 | board_build.partitions = huge_app.csv 145 | board_build.variant = esp32c3 146 | board_build.f_cpu = 160000000L 147 | board_build.f_flash = 80000000L 148 | board_build.flash_mode = qio 149 | board_build.arduino.ldscript = esp32c3_out.ld 150 | build_unflags = 151 | -DARDUINO_ESP32_DEV 152 | -DARDUINO_VARIANT="esp32" 153 | build_flags = 154 | -DARDUINO_ESP32S3_DEV 155 | -DARDUINO_VARIANT="esp32c3" 156 | -------------------------------------------------------------------------------- /src/AsyncUDP_WT32_ETH01.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | AsyncUdp_WT32_ETH01.h 3 | 4 | AsyncUDP_WT32_ETH01 is a Async UDP library for the WT32_ETH01 (ESP32 + LAN8720) 5 | 6 | Based on and modified from ESPAsyncUDP Library (https://github.com/me-no-dev/ESPAsyncUDP) 7 | Built by Khoi Hoang https://github.com/khoih-prog/AsyncUDP_WT32_ETH01 8 | Licensed under MIT license 9 | 10 | Version: 2.1.0 11 | 12 | Version Modified By Date Comments 13 | ------- ----------- ---------- ----------- 14 | 2.0.0 K Hoang 10/07/2021 Initial coding for WT32_ETH01. Bump up version to v2.0.0 to sync with AsyncUDP v2.0.0 15 | 2.0.1 K Hoang 12/07/2021 Update to use WebServer_WT32_ETH01 v1.2.0 16 | 2.0.2 K Hoang 09/10/2021 Update `platform.ini` and `library.json` 17 | 2.0.3 K Hoang 29/11/2021 Auto detect ESP32 core version. Optimize library code. Fix bug in examples 18 | 2.1.0 K Hoang 21/06/2022 Fix multiple-definitions linker error 19 | *****************************************************************************************************************************/ 20 | 21 | #pragma once 22 | 23 | #ifndef ASYNC_UDP_WT32_ETH01_H 24 | #define ASYNC_UDP_WT32_ETH01_H 25 | 26 | //////////////////////////////////////////////// 27 | 28 | #if ( ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) ) && ( ARDUINO_ESP32_GIT_VER != 0x46d5afb1 ) ) 29 | 30 | #if (_ASYNC_UDP_WT32_ETH01_LOGLEVEL_ > 2) 31 | #warning Using code for ESP32 core v2.0.0+ in AsyncUdp_WT32_ETH01.h 32 | #endif 33 | 34 | #define ASYNC_UDP_WT32_ETH01_VERSION "AsyncUdp_WT32_ETH01 v2.1.0 for core v2.0.0+" 35 | 36 | extern "C" 37 | { 38 | #include "lwip/ip_addr.h" 39 | #include "freertos/queue.h" 40 | #include "freertos/semphr.h" 41 | } 42 | 43 | #else 44 | 45 | #if (_ASYNC_UDP_WT32_ETH01_LOGLEVEL_ > 2) 46 | #warning Using code for ESP32 core v1.0.6- in AsyncUdp_WT32_ETH01.h 47 | #endif 48 | 49 | #define ASYNC_UDP_WT32_ETH01_VERSION "AsyncUdp_WT32_ETH01 v2.1.0 for core v1.0.6-" 50 | 51 | extern "C" 52 | { 53 | #include "lwip/ip_addr.h" 54 | #include 55 | #include "freertos/queue.h" 56 | #include "freertos/semphr.h" 57 | } 58 | #endif 59 | 60 | #include "IPAddress.h" 61 | #include "IPv6Address.h" 62 | #include "Print.h" 63 | #include 64 | 65 | //////////////////////////////////////////////// 66 | 67 | #include // https://github.com/khoih-prog/WebServer_WT32_ETH01 68 | 69 | #include "AsyncUDP_WT32_ETH01_Debug.h" 70 | 71 | #include "AsyncUDP_WT32_ETH01.hpp" 72 | #include "AsyncUDP_WT32_ETH01_Impl.h" 73 | 74 | //////////////////////////////////////////////// 75 | 76 | #endif //ASYNC_UDP_WT32_ETH01_H 77 | -------------------------------------------------------------------------------- /src/AsyncUDP_WT32_ETH01.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | AsyncUdp_WT32_ETH01.hpp 3 | 4 | AsyncUDP_WT32_ETH01 is a Async UDP library for the WT32_ETH01 (ESP32 + LAN8720) 5 | 6 | Based on and modified from ESPAsyncUDP Library (https://github.com/me-no-dev/ESPAsyncUDP) 7 | Built by Khoi Hoang https://github.com/khoih-prog/AsyncUDP_WT32_ETH01 8 | Licensed under MIT license 9 | 10 | Version: 2.1.0 11 | 12 | Version Modified By Date Comments 13 | ------- ----------- ---------- ----------- 14 | 2.0.0 K Hoang 10/07/2021 Initial coding for WT32_ETH01. Bump up version to v2.0.0 to sync with AsyncUDP v2.0.0 15 | 2.0.1 K Hoang 12/07/2021 Update to use WebServer_WT32_ETH01 v1.2.0 16 | 2.0.2 K Hoang 09/10/2021 Update `platform.ini` and `library.json` 17 | 2.0.3 K Hoang 29/11/2021 Auto detect ESP32 core version. Optimize library code. Fix bug in examples 18 | 2.1.0 K Hoang 21/06/2022 Fix multiple-definitions linker error 19 | *****************************************************************************************************************************/ 20 | 21 | #pragma once 22 | 23 | #ifndef ASYNC_UDP_WT32_ETH01_HPP 24 | #define ASYNC_UDP_WT32_ETH01_HPP 25 | 26 | //////////////////////////////////////////////// 27 | 28 | #include // https://github.com/khoih-prog/WebServer_WT32_ETH01 29 | 30 | class AsyncUDP; 31 | class AsyncUDPPacket; 32 | class AsyncUDPMessage; 33 | struct udp_pcb; 34 | struct pbuf; 35 | struct netif; 36 | 37 | typedef std::function AuPacketHandlerFunction; 38 | typedef std::function AuPacketHandlerFunctionWithArg; 39 | 40 | //////////////////////////////////////////////// 41 | 42 | class AsyncUDPMessage : public Print 43 | { 44 | protected: 45 | uint8_t * _buffer; 46 | size_t _index; 47 | size_t _size; 48 | 49 | public: 50 | AsyncUDPMessage(size_t size = CONFIG_TCP_MSS); 51 | virtual ~AsyncUDPMessage(); 52 | 53 | size_t write(const uint8_t *data, size_t len); 54 | size_t write(uint8_t data); 55 | size_t space(); 56 | uint8_t * data(); 57 | size_t length(); 58 | void flush(); 59 | 60 | operator bool() 61 | { 62 | return _buffer != NULL; 63 | } 64 | }; 65 | 66 | //////////////////////////////////////////////// 67 | 68 | class AsyncUDPPacket : public Stream 69 | { 70 | protected: 71 | 72 | AsyncUDP * _udp; 73 | pbuf * _pb; 74 | tcpip_adapter_if_t _if; 75 | ip_addr_t _localIp; 76 | uint16_t _localPort; 77 | ip_addr_t _remoteIp; 78 | uint16_t _remotePort; 79 | uint8_t _remoteMac[6]; 80 | uint8_t * _data; 81 | size_t _len; 82 | size_t _index; 83 | 84 | public: 85 | AsyncUDPPacket(AsyncUDPPacket &packet); 86 | AsyncUDPPacket(AsyncUDP *udp, pbuf *pb, const ip_addr_t *addr, uint16_t port, struct netif * netif); 87 | virtual ~AsyncUDPPacket(); 88 | 89 | uint8_t * data(); 90 | size_t length(); 91 | bool isBroadcast(); 92 | bool isMulticast(); 93 | bool isIPv6(); 94 | 95 | tcpip_adapter_if_t interface(); 96 | 97 | IPAddress localIP(); 98 | IPv6Address localIPv6(); 99 | uint16_t localPort(); 100 | IPAddress remoteIP(); 101 | IPv6Address remoteIPv6(); 102 | uint16_t remotePort(); 103 | void remoteMac(uint8_t * mac); 104 | 105 | size_t send(AsyncUDPMessage &message); 106 | 107 | int available(); 108 | size_t read(uint8_t *data, size_t len); 109 | int read(); 110 | int peek(); 111 | void flush(); 112 | 113 | size_t write(const uint8_t *data, size_t len); 114 | size_t write(uint8_t data); 115 | }; 116 | 117 | //////////////////////////////////////////////// 118 | 119 | class AsyncUDP : public Print 120 | { 121 | protected: 122 | 123 | udp_pcb *_pcb; 124 | //xSemaphoreHandle _lock; 125 | bool _connected; 126 | esp_err_t _lastErr; 127 | AuPacketHandlerFunction _handler; 128 | 129 | bool _init(); 130 | void _recv(udp_pcb *upcb, pbuf *pb, const ip_addr_t *addr, uint16_t port, struct netif * netif); 131 | 132 | public: 133 | 134 | AsyncUDP(); 135 | virtual ~AsyncUDP(); 136 | 137 | void onPacket(AuPacketHandlerFunctionWithArg cb, void * arg = NULL); 138 | void onPacket(AuPacketHandlerFunction cb); 139 | 140 | bool listen(const ip_addr_t *addr, uint16_t port); 141 | bool listen(const IPAddress addr, uint16_t port); 142 | bool listen(const IPv6Address addr, uint16_t port); 143 | bool listen(uint16_t port); 144 | 145 | bool listenMulticast(const ip_addr_t *addr, uint16_t port, uint8_t ttl = 1, tcpip_adapter_if_t tcpip_if = TCPIP_ADAPTER_IF_MAX); 146 | bool listenMulticast(const IPAddress addr, uint16_t port, uint8_t ttl = 1, tcpip_adapter_if_t tcpip_if = TCPIP_ADAPTER_IF_MAX); 147 | bool listenMulticast(const IPv6Address addr, uint16_t port, uint8_t ttl = 1, tcpip_adapter_if_t tcpip_if = TCPIP_ADAPTER_IF_MAX); 148 | 149 | bool connect(const ip_addr_t *addr, uint16_t port); 150 | bool connect(const IPAddress addr, uint16_t port); 151 | bool connect(const IPv6Address addr, uint16_t port); 152 | 153 | void close(); 154 | 155 | size_t writeTo(const uint8_t *data, size_t len, const ip_addr_t *addr, uint16_t port, tcpip_adapter_if_t tcpip_if = TCPIP_ADAPTER_IF_MAX); 156 | size_t writeTo(const uint8_t *data, size_t len, const IPAddress addr, uint16_t port, tcpip_adapter_if_t tcpip_if = TCPIP_ADAPTER_IF_MAX); 157 | size_t writeTo(const uint8_t *data, size_t len, const IPv6Address addr, uint16_t port, tcpip_adapter_if_t tcpip_if = TCPIP_ADAPTER_IF_MAX); 158 | size_t write(const uint8_t *data, size_t len); 159 | size_t write(uint8_t data); 160 | 161 | size_t broadcastTo(uint8_t *data, size_t len, uint16_t port, tcpip_adapter_if_t tcpip_if = TCPIP_ADAPTER_IF_MAX); 162 | size_t broadcastTo(const char * data, uint16_t port, tcpip_adapter_if_t tcpip_if = TCPIP_ADAPTER_IF_MAX); 163 | size_t broadcast(uint8_t *data, size_t len); 164 | size_t broadcast(const char * data); 165 | 166 | size_t sendTo(AsyncUDPMessage &message, const ip_addr_t *addr, uint16_t port, tcpip_adapter_if_t tcpip_if = TCPIP_ADAPTER_IF_MAX); 167 | size_t sendTo(AsyncUDPMessage &message, const IPAddress addr, uint16_t port, tcpip_adapter_if_t tcpip_if = TCPIP_ADAPTER_IF_MAX); 168 | size_t sendTo(AsyncUDPMessage &message, const IPv6Address addr, uint16_t port, tcpip_adapter_if_t tcpip_if = TCPIP_ADAPTER_IF_MAX); 169 | size_t send(AsyncUDPMessage &message); 170 | 171 | size_t broadcastTo(AsyncUDPMessage &message, uint16_t port, tcpip_adapter_if_t tcpip_if = TCPIP_ADAPTER_IF_MAX); 172 | size_t broadcast(AsyncUDPMessage &message); 173 | 174 | IPAddress listenIP(); 175 | IPv6Address listenIPv6(); 176 | 177 | bool connected(); 178 | esp_err_t lastErr(); 179 | operator bool(); 180 | 181 | static void _s_recv(void *arg, udp_pcb *upcb, pbuf *p, const ip_addr_t *addr, uint16_t port, struct netif * netif); 182 | }; 183 | 184 | //////////////////////////////////////////////// 185 | 186 | 187 | #endif //ASYNC_UDP_WT32_ETH01_HPP 188 | -------------------------------------------------------------------------------- /src/AsyncUDP_WT32_ETH01_Debug.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | AsyncUDP_Debug_WT32_ETH01.h 3 | 4 | AsyncUDP_WT32_ETH01 is a Async UDP library for the WT32_ETH01 (ESP32 + LAN8720) 5 | 6 | Based on and modified from ESPAsyncUDP Library (https://github.com/me-no-dev/ESPAsyncUDP) 7 | Built by Khoi Hoang https://github.com/khoih-prog/AsyncUDP_WT32_ETH01 8 | Licensed under MIT license 9 | 10 | Version: 2.1.0 11 | 12 | Version Modified By Date Comments 13 | ------- ----------- ---------- ----------- 14 | 2.0.0 K Hoang 10/07/2021 Initial coding for WT32_ETH01. Bump up version to v2.0.0 to sync with AsyncUDP v2.0.0 15 | 2.0.1 K Hoang 12/07/2021 Update to use WebServer_WT32_ETH01 v1.2.0 16 | 2.0.2 K Hoang 09/10/2021 Update `platform.ini` and `library.json` 17 | 2.0.3 K Hoang 29/11/2021 Auto detect ESP32 core version. Optimize library code. Fix bug in examples 18 | 2.1.0 K Hoang 21/06/2022 Fix multiple-definitions linker error 19 | *****************************************************************************************************************************/ 20 | 21 | #pragma once 22 | 23 | #ifndef Async_UDP_WT32_ETH01_Debug_H 24 | #define Async_UDP_WT32_ETH01_Debug_H 25 | 26 | #ifdef ASYNC_UDP_WT32_ETH01_DEBUG_PORT 27 | #define ASYNC_UDP_DBG_PORT ASYNC_UDP_WT32_ETH01_DEBUG_PORT 28 | #else 29 | #define ASYNC_UDP_DBG_PORT Serial 30 | #endif 31 | 32 | // Change _ASYNC_UDP_WT32_ETH01_LOGLEVEL_ to set tracing and logging verbosity 33 | // 0: DISABLED: no logging 34 | // 1: ERROR: errors 35 | // 2: WARN: errors and warnings 36 | // 3: INFO: errors, warnings and informational (default) 37 | // 4: DEBUG: errors, warnings, informational and debug 38 | 39 | #ifndef _ASYNC_UDP_WT32_ETH01_LOGLEVEL_ 40 | #define _ASYNC_UDP_WT32_ETH01_LOGLEVEL_ 0 41 | #endif 42 | 43 | /////////////////////////////////////// 44 | 45 | const char ASYNC_UDP_MARK[] = "[UDP] "; 46 | const char ASYNC_UDP_SP[] = " "; 47 | 48 | #define ASYNC_UDP_PRINT ASYNC_UDP_DBG_PORT.print 49 | #define ASYNC_UDP_PRINTLN ASYNC_UDP_DBG_PORT.println 50 | #define ASYNC_UDP_FLUSH ASYNC_UDP_DBG_PORT.flush 51 | 52 | #define ASYNC_UDP_PRINT_MARK ASYNC_UDP_PRINT(ASYNC_UDP_MARK) 53 | #define ASYNC_UDP_PRINT_SP ASYNC_UDP_PRINT(ASYNC_UDP_SP) 54 | 55 | /////////////////////////////////////// 56 | 57 | #define ASYNC_UDP_LOG(x) { ASYNC_UDP_PRINTLN(x); } 58 | #define ASYNC_UDP_LOG0(x) { ASYNC_UDP_PRINT(x); } 59 | #define ASYNC_UDP_LOG1(x,y) { ASYNC_UDP_PRINT(x); ASYNC_UDP_PRINTLN(y); } 60 | #define ASYNC_UDP_LOG2(x,y,z) { ASYNC_UDP_PRINT(x); ASYNC_UDP_PRINT(y); ASYNC_UDP_PRINTLN(z); } 61 | #define ASYNC_UDP_LOG3(x,y,z,w) { ASYNC_UDP_PRINT(x); ASYNC_UDP_PRINT(y); ASYNC_UDP_PRINT(z); ASYNC_UDP_PRINTLN(w); } 62 | 63 | /////////////////////////////////////// 64 | 65 | #define UDP_LOGERROR(x) if(_ASYNC_UDP_WT32_ETH01_LOGLEVEL_>0) { ASYNC_UDP_PRINT_MARK; ASYNC_UDP_PRINTLN(x); } 66 | #define UDP_LOGERROR0(x) if(_ASYNC_UDP_WT32_ETH01_LOGLEVEL_>0) { ASYNC_UDP_PRINT(x); } 67 | #define UDP_LOGERROR1(x,y) if(_ASYNC_UDP_WT32_ETH01_LOGLEVEL_>0) { ASYNC_UDP_PRINT_MARK; ASYNC_UDP_PRINT(x); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINTLN(y); } 68 | #define UDP_LOGERROR2(x,y,z) if(_ASYNC_UDP_WT32_ETH01_LOGLEVEL_>0) { ASYNC_UDP_PRINT_MARK; ASYNC_UDP_PRINT(x); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINT(y); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINTLN(z); } 69 | #define UDP_LOGERROR3(x,y,z,w) if(_ASYNC_UDP_WT32_ETH01_LOGLEVEL_>0) { ASYNC_UDP_PRINT_MARK; ASYNC_UDP_PRINT(x); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINT(y); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINT(z); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINTLN(w); } 70 | 71 | /////////////////////////////////////// 72 | 73 | #define UDP_LOGWARN(x) if(_ASYNC_UDP_WT32_ETH01_LOGLEVEL_>1) { ASYNC_UDP_PRINT_MARK; ASYNC_UDP_PRINTLN(x); } 74 | #define UDP_LOGWARN0(x) if(_ASYNC_UDP_WT32_ETH01_LOGLEVEL_>1) { ASYNC_UDP_PRINT(x); } 75 | #define UDP_LOGWARN1(x,y) if(_ASYNC_UDP_WT32_ETH01_LOGLEVEL_>1) { ASYNC_UDP_PRINT_MARK; ASYNC_UDP_PRINT(x); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINTLN(y); } 76 | #define UDP_LOGWARN2(x,y,z) if(_ASYNC_UDP_WT32_ETH01_LOGLEVEL_>1) { ASYNC_UDP_PRINT_MARK; ASYNC_UDP_PRINT(x); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINT(y); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINTLN(z); } 77 | #define UDP_LOGWARN3(x,y,z,w) if(_ASYNC_UDP_WT32_ETH01_LOGLEVEL_>1) { ASYNC_UDP_PRINT_MARK; ASYNC_UDP_PRINT(x); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINT(y); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINT(z); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINTLN(w); } 78 | 79 | /////////////////////////////////////// 80 | 81 | #define UDP_LOGINFO(x) if(_ASYNC_UDP_WT32_ETH01_LOGLEVEL_>2) { ASYNC_UDP_PRINT_MARK; ASYNC_UDP_PRINTLN(x); } 82 | #define UDP_LOGINFO0(x) if(_ASYNC_UDP_WT32_ETH01_LOGLEVEL_>2) { ASYNC_UDP_PRINT(x); } 83 | #define UDP_LOGINFO1(x,y) if(_ASYNC_UDP_WT32_ETH01_LOGLEVEL_>2) { ASYNC_UDP_PRINT_MARK; ASYNC_UDP_PRINT(x); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINTLN(y); } 84 | #define UDP_LOGINFO2(x,y,z) if(_ASYNC_UDP_WT32_ETH01_LOGLEVEL_>2) { ASYNC_UDP_PRINT_MARK; ASYNC_UDP_PRINT(x); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINT(y); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINTLN(z); } 85 | #define UDP_LOGINFO3(x,y,z,w) if(_ASYNC_UDP_WT32_ETH01_LOGLEVEL_>2) { ASYNC_UDP_PRINT_MARK; ASYNC_UDP_PRINT(x); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINT(y); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINT(z); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINTLN(w); } 86 | 87 | /////////////////////////////////////// 88 | 89 | #define UDP_LOGDEBUG(x) if(_ASYNC_UDP_WT32_ETH01_LOGLEVEL_>3) { ASYNC_UDP_PRINT_MARK; ASYNC_UDP_PRINTLN(x); } 90 | #define UDP_LOGDEBUG0(x) if(_ASYNC_UDP_WT32_ETH01_LOGLEVEL_>3) { ASYNC_UDP_PRINT(x); } 91 | #define UDP_LOGDEBUG1(x,y) if(_ASYNC_UDP_WT32_ETH01_LOGLEVEL_>3) { ASYNC_UDP_PRINT_MARK; ASYNC_UDP_PRINT(x); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINTLN(y); } 92 | #define UDP_LOGDEBUG2(x,y,z) if(_ASYNC_UDP_WT32_ETH01_LOGLEVEL_>3) { ASYNC_UDP_PRINT_MARK; ASYNC_UDP_PRINT(x); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINT(y); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINTLN(z); } 93 | #define UDP_LOGDEBUG3(x,y,z,w) if(_ASYNC_UDP_WT32_ETH01_LOGLEVEL_>3) { ASYNC_UDP_PRINT_MARK; ASYNC_UDP_PRINT(x); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINT(y); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINT(z); ASYNC_UDP_PRINT_SP; ASYNC_UDP_PRINTLN(w); } 94 | 95 | /////////////////////////////////////// 96 | 97 | #endif //Async_UDP_WT32_ETH01_Debug_H 98 | -------------------------------------------------------------------------------- /src/AsyncUDP_WT32_ETH01_Impl.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | AsyncUdp_WT32_ETH01_Impl.h 3 | 4 | AsyncUDP_WT32_ETH01 is a Async UDP library for the WT32_ETH01 (ESP32 + LAN8720) 5 | 6 | Based on and modified from ESPAsyncUDP Library (https://github.com/me-no-dev/ESPAsyncUDP) 7 | Built by Khoi Hoang https://github.com/khoih-prog/AsyncUDP_WT32_ETH01 8 | Licensed under MIT license 9 | 10 | Version: 2.1.0 11 | 12 | Version Modified By Date Comments 13 | ------- ----------- ---------- ----------- 14 | 2.0.0 K Hoang 10/07/2021 Initial coding for WT32_ETH01. Bump up version to v2.0.0 to sync with AsyncUDP v2.0.0 15 | 2.0.1 K Hoang 12/07/2021 Update to use WebServer_WT32_ETH01 v1.2.0 16 | 2.0.2 K Hoang 09/10/2021 Update `platform.ini` and `library.json` 17 | 2.0.3 K Hoang 29/11/2021 Auto detect ESP32 core version. Optimize library code. Fix bug in examples 18 | 2.1.0 K Hoang 21/06/2022 Fix multiple-definitions linker error 19 | *****************************************************************************************************************************/ 20 | 21 | #pragma once 22 | 23 | #ifndef ASYNC_UDP_WT32_ETH01_IMPL_H 24 | #define ASYNC_UDP_WT32_ETH01_IMPL_H 25 | 26 | extern "C" 27 | { 28 | #include "lwip/opt.h" 29 | #include "lwip/inet.h" 30 | #include "lwip/udp.h" 31 | #include "lwip/igmp.h" 32 | #include "lwip/ip_addr.h" 33 | #include "lwip/mld6.h" 34 | #include "lwip/prot/ethernet.h" 35 | #include 36 | #include 37 | } 38 | 39 | #include "lwip/priv/tcpip_priv.h" 40 | 41 | /* 42 | typedef int32_t esp_err_t; 43 | 44 | // 45 | #define ESP_OK 0 46 | #define ESP_FAIL -1 47 | 48 | #define ESP_ERR_NO_MEM 0x101 // Out of memory 49 | #define ESP_ERR_INVALID_ARG 0x102 // Invalid argument 50 | #define ESP_ERR_INVALID_STATE 0x103 // Invalid state 51 | #define ESP_ERR_INVALID_SIZE 0x104 // Invalid size 52 | #define ESP_ERR_NOT_FOUND 0x105 // Requested resource not found 53 | #define ESP_ERR_NOT_SUPPORTED 0x106 // Operation or feature not supported 54 | #define ESP_ERR_TIMEOUT 0x107 // Operation timed out 55 | #define ESP_ERR_INVALID_RESPONSE 0x108 // Received response was invalid 56 | #define ESP_ERR_INVALID_CRC 0x109 // CRC or checksum was invalid 57 | #define ESP_ERR_INVALID_VERSION 0x10A // Version was invalid 58 | #define ESP_ERR_INVALID_MAC 0x10B // MAC address was invalid 59 | 60 | #define ESP_ERR_WIFI_BASE 0x3000 // Starting number of WiFi error codes 61 | #define ESP_ERR_MESH_BASE 0x4000 // Starting number of MESH error codes 62 | */ 63 | 64 | typedef struct 65 | { 66 | struct tcpip_api_call_data call; 67 | udp_pcb * pcb; 68 | const ip_addr_t *addr; 69 | uint16_t port; 70 | struct pbuf *pb; 71 | struct netif *netif; 72 | err_t err; 73 | } udp_api_call_t; 74 | 75 | static err_t _udp_connect_api(struct tcpip_api_call_data *api_call_msg) 76 | { 77 | udp_api_call_t * msg = (udp_api_call_t *)api_call_msg; 78 | msg->err = udp_connect(msg->pcb, msg->addr, msg->port); 79 | 80 | UDP_LOGDEBUG1(F("_udp_connect_api: Error ="), msg->err); 81 | 82 | return msg->err; 83 | } 84 | 85 | static err_t _udp_connect(struct udp_pcb *pcb, const ip_addr_t *addr, u16_t port) 86 | { 87 | udp_api_call_t msg; 88 | msg.pcb = pcb; 89 | msg.addr = addr; 90 | msg.port = port; 91 | tcpip_api_call(_udp_connect_api, (struct tcpip_api_call_data*)&msg); 92 | 93 | UDP_LOGDEBUG1(F("_udp_connect: Error ="), msg.err); 94 | 95 | return msg.err; 96 | } 97 | 98 | static err_t _udp_disconnect_api(struct tcpip_api_call_data *api_call_msg) 99 | { 100 | udp_api_call_t * msg = (udp_api_call_t *)api_call_msg; 101 | msg->err = 0; 102 | udp_disconnect(msg->pcb); 103 | 104 | UDP_LOGDEBUG1(F("_udp_disconnect_api: Error ="), msg->err); 105 | 106 | return msg->err; 107 | } 108 | 109 | static void _udp_disconnect(struct udp_pcb *pcb) 110 | { 111 | udp_api_call_t msg; 112 | msg.pcb = pcb; 113 | tcpip_api_call(_udp_disconnect_api, (struct tcpip_api_call_data*)&msg); 114 | } 115 | 116 | static err_t _udp_remove_api(struct tcpip_api_call_data *api_call_msg) 117 | { 118 | udp_api_call_t * msg = (udp_api_call_t *)api_call_msg; 119 | msg->err = 0; 120 | udp_remove(msg->pcb); 121 | 122 | UDP_LOGDEBUG1(F("_udp_remove_api: Error ="), msg->err); 123 | 124 | return msg->err; 125 | } 126 | 127 | static void _udp_remove(struct udp_pcb *pcb) 128 | { 129 | udp_api_call_t msg; 130 | msg.pcb = pcb; 131 | tcpip_api_call(_udp_remove_api, (struct tcpip_api_call_data*)&msg); 132 | } 133 | 134 | static err_t _udp_bind_api(struct tcpip_api_call_data *api_call_msg) 135 | { 136 | udp_api_call_t * msg = (udp_api_call_t *)api_call_msg; 137 | msg->err = udp_bind(msg->pcb, msg->addr, msg->port); 138 | 139 | UDP_LOGDEBUG1(F("_udp_bind_api: Error ="), msg->err); 140 | 141 | return msg->err; 142 | } 143 | 144 | static err_t _udp_bind(struct udp_pcb *pcb, const ip_addr_t *addr, u16_t port) 145 | { 146 | udp_api_call_t msg; 147 | msg.pcb = pcb; 148 | msg.addr = addr; 149 | msg.port = port; 150 | tcpip_api_call(_udp_bind_api, (struct tcpip_api_call_data*)&msg); 151 | 152 | UDP_LOGDEBUG1(F("_udp_bind: Error ="), msg.err); 153 | 154 | return msg.err; 155 | } 156 | 157 | static err_t _udp_sendto_api(struct tcpip_api_call_data *api_call_msg) 158 | { 159 | udp_api_call_t * msg = (udp_api_call_t *)api_call_msg; 160 | msg->err = udp_sendto(msg->pcb, msg->pb, msg->addr, msg->port); 161 | 162 | UDP_LOGDEBUG1(F("_udp_sendto_api: Error ="), msg->err); 163 | 164 | return msg->err; 165 | } 166 | 167 | static err_t _udp_sendto(struct udp_pcb *pcb, struct pbuf *pb, const ip_addr_t *addr, u16_t port) 168 | { 169 | udp_api_call_t msg; 170 | msg.pcb = pcb; 171 | msg.addr = addr; 172 | msg.port = port; 173 | msg.pb = pb; 174 | tcpip_api_call(_udp_sendto_api, (struct tcpip_api_call_data*)&msg); 175 | 176 | UDP_LOGDEBUG1(F("_udp_sendto: Error ="), msg.err); 177 | 178 | return msg.err; 179 | } 180 | 181 | static err_t _udp_sendto_if_api(struct tcpip_api_call_data *api_call_msg) 182 | { 183 | udp_api_call_t * msg = (udp_api_call_t *)api_call_msg; 184 | msg->err = udp_sendto_if(msg->pcb, msg->pb, msg->addr, msg->port, msg->netif); 185 | 186 | UDP_LOGDEBUG1(F("_udp_sendto_if_api: Error ="), msg->err); 187 | 188 | return msg->err; 189 | } 190 | 191 | static err_t _udp_sendto_if(struct udp_pcb *pcb, struct pbuf *pb, const ip_addr_t *addr, u16_t port, 192 | struct netif *netif) 193 | { 194 | udp_api_call_t msg; 195 | msg.pcb = pcb; 196 | msg.addr = addr; 197 | msg.port = port; 198 | msg.pb = pb; 199 | msg.netif = netif; 200 | tcpip_api_call(_udp_sendto_if_api, (struct tcpip_api_call_data*)&msg); 201 | 202 | UDP_LOGDEBUG1(F("_udp_sendto_if: Error ="), msg.err); 203 | 204 | return msg.err; 205 | } 206 | 207 | //////////////////////////////////////////////// 208 | 209 | typedef struct 210 | { 211 | void *arg; 212 | udp_pcb *pcb; 213 | pbuf *pb; 214 | const ip_addr_t *addr; 215 | uint16_t port; 216 | struct netif * netif; 217 | } lwip_event_packet_t; 218 | 219 | static xQueueHandle _udp_queue; 220 | static volatile TaskHandle_t _udp_task_handle = NULL; 221 | 222 | static void _udp_task(void *pvParameters) 223 | { 224 | lwip_event_packet_t * e = NULL; 225 | 226 | for (;;) 227 | { 228 | if (xQueueReceive(_udp_queue, &e, portMAX_DELAY) == pdTRUE) 229 | { 230 | if (!e->pb) 231 | { 232 | free((void*)(e)); 233 | continue; 234 | } 235 | 236 | AsyncUDP::_s_recv(e->arg, e->pcb, e->pb, e->addr, e->port, e->netif); 237 | free((void*)(e)); 238 | } 239 | } 240 | 241 | _udp_task_handle = NULL; 242 | vTaskDelete(NULL); 243 | } 244 | 245 | static bool _udp_task_start() 246 | { 247 | if (!_udp_queue) 248 | { 249 | _udp_queue = xQueueCreate(32, sizeof(lwip_event_packet_t *)); 250 | 251 | if (!_udp_queue) 252 | { 253 | return false; 254 | } 255 | } 256 | 257 | if (!_udp_task_handle) 258 | { 259 | xTaskCreateUniversal(_udp_task, "async_udp", 4096, NULL, CONFIG_ARDUINO_UDP_TASK_PRIORITY, 260 | (TaskHandle_t*)&_udp_task_handle, CONFIG_ARDUINO_UDP_RUNNING_CORE); 261 | 262 | if (!_udp_task_handle) 263 | { 264 | return false; 265 | } 266 | } 267 | 268 | return true; 269 | } 270 | 271 | static bool _udp_task_post(void *arg, udp_pcb *pcb, pbuf *pb, const ip_addr_t *addr, uint16_t port, struct netif *netif) 272 | { 273 | if (!_udp_task_handle || !_udp_queue) 274 | { 275 | return false; 276 | } 277 | 278 | lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); 279 | 280 | if (!e) 281 | { 282 | return false; 283 | } 284 | 285 | e->arg = arg; 286 | e->pcb = pcb; 287 | e->pb = pb; 288 | e->addr = addr; 289 | e->port = port; 290 | e->netif = netif; 291 | 292 | if (xQueueSend(_udp_queue, &e, portMAX_DELAY) != pdPASS) 293 | { 294 | free((void*)(e)); 295 | 296 | return false; 297 | } 298 | 299 | return true; 300 | } 301 | 302 | static void _udp_recv(void *arg, udp_pcb *pcb, pbuf *pb, const ip_addr_t *addr, uint16_t port) 303 | { 304 | while (pb != NULL) 305 | { 306 | pbuf * this_pb = pb; 307 | pb = pb->next; 308 | this_pb->next = NULL; 309 | 310 | if (!_udp_task_post(arg, pcb, this_pb, addr, port, ip_current_input_netif())) 311 | { 312 | pbuf_free(this_pb); 313 | } 314 | } 315 | } 316 | 317 | /* 318 | static bool _udp_task_stop() 319 | { 320 | if(!_udp_task_post(NULL, NULL, NULL, NULL, 0, NULL)) 321 | { 322 | return false; 323 | } 324 | 325 | while(_udp_task_handle) 326 | { 327 | vTaskDelay(10); 328 | } 329 | 330 | lwip_event_packet_t * e; 331 | 332 | while (xQueueReceive(_udp_queue, &e, 0) == pdTRUE) 333 | { 334 | if(e->pb) 335 | { 336 | pbuf_free(e->pb); 337 | } 338 | 339 | free((void*)(e)); 340 | } 341 | 342 | vQueueDelete(_udp_queue); 343 | _udp_queue = NULL; 344 | } 345 | */ 346 | 347 | //////////////////////////////////////////////// 348 | 349 | #define UDP_MUTEX_LOCK() //xSemaphoreTake(_lock, portMAX_DELAY) 350 | #define UDP_MUTEX_UNLOCK() //xSemaphoreGive(_lock) 351 | 352 | //////////////////////////////////////////////// 353 | 354 | AsyncUDPMessage::AsyncUDPMessage(size_t size) 355 | { 356 | _index = 0; 357 | 358 | if (size > CONFIG_TCP_MSS) 359 | { 360 | size = CONFIG_TCP_MSS; 361 | } 362 | 363 | _size = size; 364 | _buffer = (uint8_t *)malloc(size); 365 | } 366 | 367 | //////////////////////////////////////////////// 368 | 369 | AsyncUDPMessage::~AsyncUDPMessage() 370 | { 371 | if (_buffer) 372 | { 373 | free(_buffer); 374 | } 375 | } 376 | 377 | //////////////////////////////////////////////// 378 | 379 | size_t AsyncUDPMessage::write(const uint8_t *data, size_t len) 380 | { 381 | if (_buffer == NULL) 382 | { 383 | UDP_LOGDEBUG(F("write: Error NULL _buffer")); 384 | 385 | return 0; 386 | } 387 | 388 | size_t s = space(); 389 | 390 | if (len > s) 391 | { 392 | len = s; 393 | } 394 | 395 | memcpy(_buffer + _index, data, len); 396 | _index += len; 397 | 398 | return len; 399 | } 400 | 401 | //////////////////////////////////////////////// 402 | 403 | size_t AsyncUDPMessage::write(uint8_t data) 404 | { 405 | return write(&data, 1); 406 | } 407 | 408 | //////////////////////////////////////////////// 409 | 410 | size_t AsyncUDPMessage::space() 411 | { 412 | if (_buffer == NULL) 413 | { 414 | UDP_LOGDEBUG(F("space: Error NULL _buffer")); 415 | 416 | return 0; 417 | } 418 | 419 | return _size - _index; 420 | } 421 | 422 | //////////////////////////////////////////////// 423 | 424 | uint8_t * AsyncUDPMessage::data() 425 | { 426 | return _buffer; 427 | } 428 | 429 | //////////////////////////////////////////////// 430 | 431 | size_t AsyncUDPMessage::length() 432 | { 433 | return _index; 434 | } 435 | 436 | //////////////////////////////////////////////// 437 | 438 | void AsyncUDPMessage::flush() 439 | { 440 | _index = 0; 441 | } 442 | 443 | //////////////////////////////////////////////// 444 | 445 | AsyncUDPPacket::AsyncUDPPacket(AsyncUDPPacket &packet) 446 | { 447 | _udp = packet._udp; 448 | _pb = packet._pb; 449 | _if = packet._if; 450 | _data = packet._data; 451 | _len = packet._len; 452 | _index = 0; 453 | 454 | memcpy(&_remoteIp, &packet._remoteIp, sizeof(ip_addr_t)); 455 | memcpy(&_localIp, &packet._localIp, sizeof(ip_addr_t)); 456 | _localPort = packet._localPort; 457 | _remotePort = packet._remotePort; 458 | memcpy(_remoteMac, packet._remoteMac, 6); 459 | 460 | pbuf_ref(_pb); 461 | } 462 | 463 | //////////////////////////////////////////////// 464 | 465 | AsyncUDPPacket::AsyncUDPPacket(AsyncUDP *udp, pbuf *pb, const ip_addr_t *raddr, uint16_t rport, struct netif * ntif) 466 | { 467 | _udp = udp; 468 | _pb = pb; 469 | _if = TCPIP_ADAPTER_IF_MAX; 470 | _data = (uint8_t*)(pb->payload); 471 | _len = pb->len; 472 | _index = 0; 473 | 474 | pbuf_ref(_pb); 475 | 476 | //memcpy(&_remoteIp, raddr, sizeof(ip_addr_t)); 477 | _remoteIp.type = raddr->type; 478 | _localIp.type = _remoteIp.type; 479 | 480 | eth_hdr* eth = NULL; 481 | udp_hdr* udphdr = (udp_hdr *)(_data - UDP_HLEN); 482 | _localPort = ntohs(udphdr->dest); 483 | _remotePort = ntohs(udphdr->src); 484 | 485 | if (_remoteIp.type == IPADDR_TYPE_V4) 486 | { 487 | eth = (eth_hdr *)(_data - UDP_HLEN - IP_HLEN - SIZEOF_ETH_HDR); 488 | struct ip_hdr * iphdr = (struct ip_hdr *)(_data - UDP_HLEN - IP_HLEN); 489 | _localIp.u_addr.ip4.addr = iphdr->dest.addr; 490 | _remoteIp.u_addr.ip4.addr = iphdr->src.addr; 491 | } 492 | else 493 | { 494 | eth = (eth_hdr *)(_data - UDP_HLEN - IP6_HLEN - SIZEOF_ETH_HDR); 495 | struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(_data - UDP_HLEN - IP6_HLEN); 496 | memcpy(&_localIp.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16); 497 | memcpy(&_remoteIp.u_addr.ip6.addr, (uint8_t *)ip6hdr->src.addr, 16); 498 | } 499 | 500 | memcpy(_remoteMac, eth->src.addr, 6); 501 | 502 | struct netif * netif = NULL; 503 | void * nif = NULL; 504 | int i; 505 | 506 | for (i = 0; i < TCPIP_ADAPTER_IF_MAX; i++) 507 | { 508 | tcpip_adapter_get_netif ((tcpip_adapter_if_t)i, &nif); 509 | netif = (struct netif *)nif; 510 | 511 | if (netif && netif == ntif) 512 | { 513 | _if = (tcpip_adapter_if_t)i; 514 | break; 515 | } 516 | } 517 | } 518 | 519 | //////////////////////////////////////////////// 520 | 521 | AsyncUDPPacket::~AsyncUDPPacket() 522 | { 523 | pbuf_free(_pb); 524 | } 525 | 526 | //////////////////////////////////////////////// 527 | 528 | uint8_t * AsyncUDPPacket::data() 529 | { 530 | return _data; 531 | } 532 | 533 | //////////////////////////////////////////////// 534 | 535 | size_t AsyncUDPPacket::length() 536 | { 537 | return _len; 538 | } 539 | 540 | //////////////////////////////////////////////// 541 | 542 | int AsyncUDPPacket::available() 543 | { 544 | return _len - _index; 545 | } 546 | 547 | //////////////////////////////////////////////// 548 | 549 | size_t AsyncUDPPacket::read(uint8_t *data, size_t len) 550 | { 551 | size_t i; 552 | size_t a = _len - _index; 553 | 554 | if (len > a) 555 | { 556 | len = a; 557 | } 558 | 559 | for (i = 0; i < len; i++) 560 | { 561 | data[i] = read(); 562 | } 563 | 564 | return len; 565 | } 566 | 567 | //////////////////////////////////////////////// 568 | 569 | int AsyncUDPPacket::read() 570 | { 571 | if (_index < _len) 572 | { 573 | return _data[_index++]; 574 | } 575 | 576 | return -1; 577 | } 578 | 579 | //////////////////////////////////////////////// 580 | 581 | int AsyncUDPPacket::peek() 582 | { 583 | if (_index < _len) 584 | { 585 | return _data[_index]; 586 | } 587 | 588 | return -1; 589 | } 590 | 591 | //////////////////////////////////////////////// 592 | 593 | void AsyncUDPPacket::flush() 594 | { 595 | _index = _len; 596 | } 597 | 598 | //////////////////////////////////////////////// 599 | 600 | tcpip_adapter_if_t AsyncUDPPacket::interface() 601 | { 602 | return _if; 603 | } 604 | 605 | //////////////////////////////////////////////// 606 | 607 | IPAddress AsyncUDPPacket::localIP() 608 | { 609 | if (_localIp.type != IPADDR_TYPE_V4) 610 | { 611 | return IPAddress(); 612 | } 613 | 614 | return IPAddress(_localIp.u_addr.ip4.addr); 615 | } 616 | 617 | //////////////////////////////////////////////// 618 | 619 | IPv6Address AsyncUDPPacket::localIPv6() 620 | { 621 | if (_localIp.type != IPADDR_TYPE_V6) 622 | { 623 | return IPv6Address(); 624 | } 625 | 626 | return IPv6Address(_localIp.u_addr.ip6.addr); 627 | } 628 | 629 | //////////////////////////////////////////////// 630 | 631 | uint16_t AsyncUDPPacket::localPort() 632 | { 633 | return _localPort; 634 | } 635 | 636 | //////////////////////////////////////////////// 637 | 638 | IPAddress AsyncUDPPacket::remoteIP() 639 | { 640 | if (_remoteIp.type != IPADDR_TYPE_V4) 641 | { 642 | return IPAddress(); 643 | } 644 | 645 | return IPAddress(_remoteIp.u_addr.ip4.addr); 646 | } 647 | 648 | //////////////////////////////////////////////// 649 | 650 | IPv6Address AsyncUDPPacket::remoteIPv6() 651 | { 652 | if (_remoteIp.type != IPADDR_TYPE_V6) 653 | { 654 | return IPv6Address(); 655 | } 656 | 657 | return IPv6Address(_remoteIp.u_addr.ip6.addr); 658 | } 659 | 660 | //////////////////////////////////////////////// 661 | 662 | uint16_t AsyncUDPPacket::remotePort() 663 | { 664 | return _remotePort; 665 | } 666 | 667 | //////////////////////////////////////////////// 668 | 669 | void AsyncUDPPacket::remoteMac(uint8_t * mac) 670 | { 671 | memcpy(mac, _remoteMac, 6); 672 | } 673 | 674 | //////////////////////////////////////////////// 675 | 676 | bool AsyncUDPPacket::isIPv6() 677 | { 678 | return _localIp.type == IPADDR_TYPE_V6; 679 | } 680 | 681 | //////////////////////////////////////////////// 682 | 683 | bool AsyncUDPPacket::isBroadcast() 684 | { 685 | if (_localIp.type == IPADDR_TYPE_V6) 686 | { 687 | return false; 688 | } 689 | 690 | uint32_t ip = _localIp.u_addr.ip4.addr; 691 | 692 | return ip == 0xFFFFFFFF || ip == 0 || (ip & 0xFF000000) == 0xFF000000; 693 | } 694 | 695 | //////////////////////////////////////////////// 696 | 697 | bool AsyncUDPPacket::isMulticast() 698 | { 699 | return ip_addr_ismulticast(&(_localIp)); 700 | } 701 | 702 | //////////////////////////////////////////////// 703 | 704 | size_t AsyncUDPPacket::write(const uint8_t *data, size_t len) 705 | { 706 | if (!data) 707 | { 708 | UDP_LOGDEBUG(F("AsyncUDPPacket::write: Error NULL data")); 709 | 710 | return 0; 711 | } 712 | 713 | return _udp->writeTo(data, len, &_remoteIp, _remotePort, _if); 714 | } 715 | 716 | //////////////////////////////////////////////// 717 | 718 | size_t AsyncUDPPacket::write(uint8_t data) 719 | { 720 | return write(&data, 1); 721 | } 722 | 723 | //////////////////////////////////////////////// 724 | 725 | size_t AsyncUDPPacket::send(AsyncUDPMessage &message) 726 | { 727 | return write(message.data(), message.length()); 728 | } 729 | 730 | //////////////////////////////////////////////// 731 | 732 | bool AsyncUDP::_init() 733 | { 734 | if (_pcb) 735 | { 736 | return true; 737 | } 738 | 739 | _pcb = udp_new(); 740 | 741 | if (!_pcb) 742 | { 743 | return false; 744 | } 745 | 746 | //_lock = xSemaphoreCreateMutex(); 747 | udp_recv(_pcb, &_udp_recv, (void *) this); 748 | 749 | return true; 750 | } 751 | 752 | //////////////////////////////////////////////// 753 | 754 | AsyncUDP::AsyncUDP() 755 | { 756 | _pcb = NULL; 757 | _connected = false; 758 | _lastErr = ERR_OK; 759 | _handler = NULL; 760 | } 761 | 762 | //////////////////////////////////////////////// 763 | 764 | AsyncUDP::~AsyncUDP() 765 | { 766 | close(); 767 | UDP_MUTEX_LOCK(); 768 | 769 | udp_recv(_pcb, NULL, NULL); 770 | _udp_remove(_pcb); 771 | _pcb = NULL; 772 | 773 | UDP_MUTEX_UNLOCK(); 774 | //vSemaphoreDelete(_lock); 775 | } 776 | 777 | //////////////////////////////////////////////// 778 | 779 | void AsyncUDP::close() 780 | { 781 | UDP_MUTEX_LOCK(); 782 | 783 | if (_pcb != NULL) 784 | { 785 | if (_connected) 786 | { 787 | _udp_disconnect(_pcb); 788 | } 789 | 790 | _connected = false; 791 | //todo: unjoin multicast group 792 | } 793 | 794 | UDP_MUTEX_UNLOCK(); 795 | } 796 | 797 | //////////////////////////////////////////////// 798 | 799 | bool AsyncUDP::connect(const ip_addr_t *addr, uint16_t port) 800 | { 801 | if (!_udp_task_start()) 802 | { 803 | log_e("failed to start task"); 804 | UDP_LOGERROR(F("AsyncUDP::connect: failed to start task")); 805 | 806 | return false; 807 | } 808 | 809 | if (!_init()) 810 | { 811 | UDP_LOGERROR(F("AsyncUDP::connect: failed to init")); 812 | 813 | return false; 814 | } 815 | 816 | close(); 817 | UDP_MUTEX_LOCK(); 818 | 819 | _lastErr = _udp_connect(_pcb, addr, port); 820 | 821 | if (_lastErr != ERR_OK) 822 | { 823 | UDP_MUTEX_UNLOCK(); 824 | 825 | UDP_LOGERROR(F("AsyncUDP::connect: _udp_connect failed")); 826 | 827 | return false; 828 | } 829 | 830 | _connected = true; 831 | 832 | UDP_MUTEX_UNLOCK(); 833 | 834 | return true; 835 | } 836 | 837 | //////////////////////////////////////////////// 838 | 839 | bool AsyncUDP::listen(const ip_addr_t *addr, uint16_t port) 840 | { 841 | if (!_udp_task_start()) 842 | { 843 | log_e("failed to start task"); 844 | UDP_LOGERROR(F("AsyncUDP::listen: failed to start task")); 845 | 846 | return false; 847 | } 848 | 849 | if (!_init()) 850 | { 851 | UDP_LOGERROR(F("AsyncUDP::listen: failed to init")); 852 | 853 | return false; 854 | } 855 | 856 | close(); 857 | 858 | if (addr) 859 | { 860 | IP_SET_TYPE_VAL(_pcb->local_ip, addr->type); 861 | IP_SET_TYPE_VAL(_pcb->remote_ip, addr->type); 862 | } 863 | 864 | UDP_MUTEX_LOCK(); 865 | 866 | if (_udp_bind(_pcb, addr, port) != ERR_OK) 867 | { 868 | UDP_MUTEX_UNLOCK(); 869 | 870 | UDP_LOGERROR(F("AsyncUDP::listen: failed to _udp_bind")); 871 | 872 | return false; 873 | } 874 | 875 | _connected = true; 876 | 877 | UDP_MUTEX_UNLOCK(); 878 | 879 | return true; 880 | } 881 | 882 | //////////////////////////////////////////////// 883 | 884 | static esp_err_t joinMulticastGroup(const ip_addr_t *addr, bool join, 885 | tcpip_adapter_if_t tcpip_if = TCPIP_ADAPTER_IF_MAX) 886 | { 887 | struct netif * netif = NULL; 888 | 889 | if (tcpip_if < TCPIP_ADAPTER_IF_MAX) 890 | { 891 | void * nif = NULL; 892 | esp_err_t err = tcpip_adapter_get_netif(tcpip_if, &nif); 893 | 894 | if (err) 895 | { 896 | UDP_LOGERROR(F("joinMulticastGroup: failed to get_netif")); 897 | 898 | return ESP_ERR_INVALID_ARG; 899 | } 900 | 901 | netif = (struct netif *)nif; 902 | 903 | if (addr->type == IPADDR_TYPE_V4) 904 | { 905 | if (join) 906 | { 907 | if (igmp_joingroup_netif(netif, (const ip4_addr *) & (addr->u_addr.ip4))) 908 | { 909 | UDP_LOGERROR(F("joinMulticastGroup: IPv4 failed to joingroup")); 910 | 911 | return ESP_ERR_INVALID_STATE; 912 | } 913 | } 914 | else 915 | { 916 | if (igmp_leavegroup_netif(netif, (const ip4_addr *) & (addr->u_addr.ip4))) 917 | { 918 | UDP_LOGERROR(F("joinMulticastGroup: IPv4 failed to leavegroup")); 919 | 920 | return ESP_ERR_INVALID_STATE; 921 | } 922 | } 923 | } 924 | else 925 | { 926 | if (join) 927 | { 928 | if (mld6_joingroup_netif(netif, &(addr->u_addr.ip6))) 929 | { 930 | UDP_LOGERROR(F("joinMulticastGroup: IPv6 failed to joingroup")); 931 | 932 | return ESP_ERR_INVALID_STATE; 933 | } 934 | } 935 | else 936 | { 937 | if (mld6_leavegroup_netif(netif, &(addr->u_addr.ip6))) 938 | { 939 | UDP_LOGERROR(F("joinMulticastGroup: IPv6 failed to leavegroup")); 940 | 941 | return ESP_ERR_INVALID_STATE; 942 | } 943 | } 944 | } 945 | } 946 | else 947 | { 948 | if (addr->type == IPADDR_TYPE_V4) 949 | { 950 | if (join) 951 | { 952 | if (igmp_joingroup((const ip4_addr *)IP4_ADDR_ANY, (const ip4_addr *) & (addr->u_addr.ip4))) 953 | { 954 | return ESP_ERR_INVALID_STATE; 955 | } 956 | } 957 | else 958 | { 959 | if (igmp_leavegroup((const ip4_addr *)IP4_ADDR_ANY, (const ip4_addr *) & (addr->u_addr.ip4))) 960 | { 961 | return ESP_ERR_INVALID_STATE; 962 | } 963 | } 964 | } 965 | else 966 | { 967 | if (join) 968 | { 969 | if (mld6_joingroup((const ip6_addr *)IP6_ADDR_ANY, &(addr->u_addr.ip6))) 970 | { 971 | return ESP_ERR_INVALID_STATE; 972 | } 973 | } 974 | else 975 | { 976 | if (mld6_leavegroup((const ip6_addr *)IP6_ADDR_ANY, &(addr->u_addr.ip6))) 977 | { 978 | return ESP_ERR_INVALID_STATE; 979 | } 980 | } 981 | } 982 | } 983 | 984 | return ESP_OK; 985 | } 986 | 987 | //////////////////////////////////////////////// 988 | 989 | bool AsyncUDP::listenMulticast(const ip_addr_t *addr, uint16_t port, uint8_t ttl, tcpip_adapter_if_t tcpip_if) 990 | { 991 | if (!ip_addr_ismulticast(addr)) 992 | { 993 | UDP_LOGERROR(F("listenMulticast: not addr_ismulticast")); 994 | 995 | return false; 996 | } 997 | 998 | if (joinMulticastGroup(addr, true, tcpip_if) != ERR_OK) 999 | { 1000 | UDP_LOGERROR(F("listenMulticast: error joinMulticast")); 1001 | 1002 | return false; 1003 | } 1004 | 1005 | if (!listen(NULL, port)) 1006 | { 1007 | UDP_LOGERROR1(F("listenMulticast: error listen to port ="), port); 1008 | 1009 | return false; 1010 | } 1011 | 1012 | UDP_MUTEX_LOCK(); 1013 | 1014 | _pcb->mcast_ttl = ttl; 1015 | _pcb->remote_port = port; 1016 | ip_addr_copy(_pcb->remote_ip, *addr); 1017 | //ip_addr_copy(_pcb->remote_ip, ip_addr_any_type); 1018 | 1019 | UDP_MUTEX_UNLOCK(); 1020 | 1021 | return true; 1022 | } 1023 | 1024 | //////////////////////////////////////////////// 1025 | 1026 | size_t AsyncUDP::writeTo(const uint8_t * data, size_t len, const ip_addr_t * addr, uint16_t port, 1027 | tcpip_adapter_if_t tcpip_if) 1028 | { 1029 | if (!_pcb) 1030 | { 1031 | UDP_MUTEX_LOCK(); 1032 | 1033 | _pcb = udp_new(); 1034 | 1035 | UDP_MUTEX_UNLOCK(); 1036 | 1037 | if (_pcb == NULL) 1038 | { 1039 | return 0; 1040 | } 1041 | } 1042 | 1043 | if (len > CONFIG_TCP_MSS) 1044 | { 1045 | len = CONFIG_TCP_MSS; 1046 | } 1047 | 1048 | _lastErr = ERR_OK; 1049 | pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); 1050 | 1051 | if (pbt != NULL) 1052 | { 1053 | uint8_t* dst = reinterpret_cast(pbt->payload); 1054 | memcpy(dst, data, len); 1055 | 1056 | UDP_MUTEX_LOCK(); 1057 | 1058 | if (tcpip_if < TCPIP_ADAPTER_IF_MAX) 1059 | { 1060 | void * nif = NULL; 1061 | tcpip_adapter_get_netif((tcpip_adapter_if_t)tcpip_if, &nif); 1062 | 1063 | if (!nif) 1064 | { 1065 | _lastErr = _udp_sendto(_pcb, pbt, addr, port); 1066 | } 1067 | else 1068 | { 1069 | _lastErr = _udp_sendto_if(_pcb, pbt, addr, port, (struct netif *)nif); 1070 | } 1071 | } 1072 | else 1073 | { 1074 | _lastErr = _udp_sendto(_pcb, pbt, addr, port); 1075 | } 1076 | 1077 | UDP_MUTEX_UNLOCK(); 1078 | 1079 | pbuf_free(pbt); 1080 | 1081 | if (_lastErr < ERR_OK) 1082 | { 1083 | UDP_LOGERROR1(F("AsyncUDP::writeTo: _lastErr ="), _lastErr); 1084 | 1085 | return 0; 1086 | } 1087 | 1088 | UDP_LOGDEBUG1(F("AsyncUDP::writeTo: len ="), len); 1089 | 1090 | return len; 1091 | } 1092 | 1093 | UDP_LOGERROR(F("AsyncUDP::writeTo: Error NULL pbt")); 1094 | 1095 | return 0; 1096 | } 1097 | 1098 | //////////////////////////////////////////////// 1099 | 1100 | void AsyncUDP::_recv(udp_pcb *upcb, pbuf *pb, const ip_addr_t *addr, uint16_t port, struct netif * netif) 1101 | { 1102 | while (pb != NULL) 1103 | { 1104 | pbuf * this_pb = pb; 1105 | pb = pb->next; 1106 | this_pb->next = NULL; 1107 | 1108 | if (_handler) 1109 | { 1110 | AsyncUDPPacket packet(this, this_pb, addr, port, netif); 1111 | _handler(packet); 1112 | } 1113 | 1114 | pbuf_free(this_pb); 1115 | } 1116 | } 1117 | 1118 | //////////////////////////////////////////////// 1119 | 1120 | void AsyncUDP::_s_recv(void *arg, udp_pcb *upcb, pbuf *p, const ip_addr_t *addr, uint16_t port, struct netif * netif) 1121 | { 1122 | reinterpret_cast(arg)->_recv(upcb, p, addr, port, netif); 1123 | } 1124 | 1125 | //////////////////////////////////////////////// 1126 | 1127 | bool AsyncUDP::listen(uint16_t port) 1128 | { 1129 | return listen(IP_ANY_TYPE, port); 1130 | } 1131 | 1132 | //////////////////////////////////////////////// 1133 | 1134 | bool AsyncUDP::listen(const IPAddress addr, uint16_t port) 1135 | { 1136 | ip_addr_t laddr; 1137 | laddr.type = IPADDR_TYPE_V4; 1138 | laddr.u_addr.ip4.addr = addr; 1139 | 1140 | return listen(&laddr, port); 1141 | } 1142 | 1143 | //////////////////////////////////////////////// 1144 | 1145 | bool AsyncUDP::listenMulticast(const IPAddress addr, uint16_t port, uint8_t ttl, tcpip_adapter_if_t tcpip_if) 1146 | { 1147 | ip_addr_t laddr; 1148 | laddr.type = IPADDR_TYPE_V4; 1149 | laddr.u_addr.ip4.addr = addr; 1150 | 1151 | return listenMulticast(&laddr, port, ttl, tcpip_if); 1152 | } 1153 | 1154 | //////////////////////////////////////////////// 1155 | 1156 | bool AsyncUDP::connect(const IPAddress addr, uint16_t port) 1157 | { 1158 | ip_addr_t daddr; 1159 | daddr.type = IPADDR_TYPE_V4; 1160 | daddr.u_addr.ip4.addr = addr; 1161 | 1162 | return connect(&daddr, port); 1163 | } 1164 | 1165 | //////////////////////////////////////////////// 1166 | 1167 | size_t AsyncUDP::writeTo(const uint8_t *data, size_t len, const IPAddress addr, uint16_t port, 1168 | tcpip_adapter_if_t tcpip_if) 1169 | { 1170 | ip_addr_t daddr; 1171 | daddr.type = IPADDR_TYPE_V4; 1172 | daddr.u_addr.ip4.addr = addr; 1173 | 1174 | return writeTo(data, len, &daddr, port, tcpip_if); 1175 | } 1176 | 1177 | //////////////////////////////////////////////// 1178 | 1179 | IPAddress AsyncUDP::listenIP() 1180 | { 1181 | if (!_pcb || _pcb->remote_ip.type != IPADDR_TYPE_V4) 1182 | { 1183 | return IPAddress(); 1184 | } 1185 | 1186 | return IPAddress(_pcb->remote_ip.u_addr.ip4.addr); 1187 | } 1188 | 1189 | //////////////////////////////////////////////// 1190 | 1191 | bool AsyncUDP::listen(const IPv6Address addr, uint16_t port) 1192 | { 1193 | ip_addr_t laddr; 1194 | laddr.type = IPADDR_TYPE_V6; 1195 | memcpy((uint8_t*)(laddr.u_addr.ip6.addr), (const uint8_t*)addr, 16); 1196 | 1197 | return listen(&laddr, port); 1198 | } 1199 | 1200 | //////////////////////////////////////////////// 1201 | 1202 | bool AsyncUDP::listenMulticast(const IPv6Address addr, uint16_t port, uint8_t ttl, tcpip_adapter_if_t tcpip_if) 1203 | { 1204 | ip_addr_t laddr; 1205 | laddr.type = IPADDR_TYPE_V6; 1206 | memcpy((uint8_t*)(laddr.u_addr.ip6.addr), (const uint8_t*)addr, 16); 1207 | 1208 | return listenMulticast(&laddr, port, ttl, tcpip_if); 1209 | } 1210 | 1211 | //////////////////////////////////////////////// 1212 | 1213 | bool AsyncUDP::connect(const IPv6Address addr, uint16_t port) 1214 | { 1215 | ip_addr_t daddr; 1216 | daddr.type = IPADDR_TYPE_V6; 1217 | memcpy((uint8_t*)(daddr.u_addr.ip6.addr), (const uint8_t*)addr, 16); 1218 | 1219 | return connect(&daddr, port); 1220 | } 1221 | 1222 | //////////////////////////////////////////////// 1223 | 1224 | size_t AsyncUDP::writeTo(const uint8_t *data, size_t len, const IPv6Address addr, uint16_t port, 1225 | tcpip_adapter_if_t tcpip_if) 1226 | { 1227 | ip_addr_t daddr; 1228 | daddr.type = IPADDR_TYPE_V6; 1229 | memcpy((uint8_t*)(daddr.u_addr.ip6.addr), (const uint8_t*)addr, 16); 1230 | 1231 | return writeTo(data, len, &daddr, port, tcpip_if); 1232 | } 1233 | 1234 | //////////////////////////////////////////////// 1235 | 1236 | IPv6Address AsyncUDP::listenIPv6() 1237 | { 1238 | if (!_pcb || _pcb->remote_ip.type != IPADDR_TYPE_V6) 1239 | { 1240 | return IPv6Address(); 1241 | } 1242 | 1243 | return IPv6Address(_pcb->remote_ip.u_addr.ip6.addr); 1244 | } 1245 | 1246 | //////////////////////////////////////////////// 1247 | 1248 | size_t AsyncUDP::write(const uint8_t *data, size_t len) 1249 | { 1250 | return writeTo(data, len, &(_pcb->remote_ip), _pcb->remote_port); 1251 | } 1252 | 1253 | //////////////////////////////////////////////// 1254 | 1255 | size_t AsyncUDP::write(uint8_t data) 1256 | { 1257 | return write(&data, 1); 1258 | } 1259 | 1260 | //////////////////////////////////////////////// 1261 | 1262 | size_t AsyncUDP::broadcastTo(uint8_t *data, size_t len, uint16_t port, tcpip_adapter_if_t tcpip_if) 1263 | { 1264 | return writeTo(data, len, IP_ADDR_BROADCAST, port, tcpip_if); 1265 | } 1266 | 1267 | //////////////////////////////////////////////// 1268 | 1269 | size_t AsyncUDP::broadcastTo(const char * data, uint16_t port, tcpip_adapter_if_t tcpip_if) 1270 | { 1271 | return broadcastTo((uint8_t *)data, strlen(data), port, tcpip_if); 1272 | } 1273 | 1274 | //////////////////////////////////////////////// 1275 | 1276 | size_t AsyncUDP::broadcast(uint8_t *data, size_t len) 1277 | { 1278 | if (_pcb->local_port != 0) 1279 | { 1280 | return broadcastTo(data, len, _pcb->local_port); 1281 | } 1282 | 1283 | return 0; 1284 | } 1285 | 1286 | //////////////////////////////////////////////// 1287 | 1288 | size_t AsyncUDP::broadcast(const char * data) 1289 | { 1290 | return broadcast((uint8_t *)data, strlen(data)); 1291 | } 1292 | 1293 | //////////////////////////////////////////////// 1294 | 1295 | size_t AsyncUDP::sendTo(AsyncUDPMessage &message, const ip_addr_t *addr, uint16_t port, tcpip_adapter_if_t tcpip_if) 1296 | { 1297 | if (!message) 1298 | { 1299 | return 0; 1300 | } 1301 | 1302 | return writeTo(message.data(), message.length(), addr, port, tcpip_if); 1303 | } 1304 | 1305 | //////////////////////////////////////////////// 1306 | 1307 | size_t AsyncUDP::sendTo(AsyncUDPMessage &message, const IPAddress addr, uint16_t port, tcpip_adapter_if_t tcpip_if) 1308 | { 1309 | if (!message) 1310 | { 1311 | return 0; 1312 | } 1313 | 1314 | return writeTo(message.data(), message.length(), addr, port, tcpip_if); 1315 | } 1316 | 1317 | //////////////////////////////////////////////// 1318 | 1319 | size_t AsyncUDP::sendTo(AsyncUDPMessage &message, const IPv6Address addr, uint16_t port, tcpip_adapter_if_t tcpip_if) 1320 | { 1321 | if (!message) 1322 | { 1323 | return 0; 1324 | } 1325 | 1326 | return writeTo(message.data(), message.length(), addr, port, tcpip_if); 1327 | } 1328 | 1329 | //////////////////////////////////////////////// 1330 | 1331 | size_t AsyncUDP::send(AsyncUDPMessage &message) 1332 | { 1333 | if (!message) 1334 | { 1335 | return 0; 1336 | } 1337 | 1338 | return writeTo(message.data(), message.length(), &(_pcb->remote_ip), _pcb->remote_port); 1339 | } 1340 | 1341 | //////////////////////////////////////////////// 1342 | 1343 | size_t AsyncUDP::broadcastTo(AsyncUDPMessage &message, uint16_t port, tcpip_adapter_if_t tcpip_if) 1344 | { 1345 | if (!message) 1346 | { 1347 | return 0; 1348 | } 1349 | 1350 | return broadcastTo(message.data(), message.length(), port, tcpip_if); 1351 | } 1352 | 1353 | //////////////////////////////////////////////// 1354 | 1355 | size_t AsyncUDP::broadcast(AsyncUDPMessage &message) 1356 | { 1357 | if (!message) 1358 | { 1359 | return 0; 1360 | } 1361 | 1362 | return broadcast(message.data(), message.length()); 1363 | } 1364 | 1365 | //////////////////////////////////////////////// 1366 | 1367 | AsyncUDP::operator bool() 1368 | { 1369 | return _connected; 1370 | } 1371 | 1372 | //////////////////////////////////////////////// 1373 | 1374 | bool AsyncUDP::connected() 1375 | { 1376 | return _connected; 1377 | } 1378 | 1379 | //////////////////////////////////////////////// 1380 | 1381 | esp_err_t AsyncUDP::lastErr() 1382 | { 1383 | return _lastErr; 1384 | } 1385 | 1386 | //////////////////////////////////////////////// 1387 | 1388 | void AsyncUDP::onPacket(AuPacketHandlerFunctionWithArg cb, void * arg) 1389 | { 1390 | onPacket(std::bind(cb, arg, std::placeholders::_1)); 1391 | } 1392 | 1393 | //////////////////////////////////////////////// 1394 | 1395 | void AsyncUDP::onPacket(AuPacketHandlerFunction cb) 1396 | { 1397 | _handler = cb; 1398 | } 1399 | 1400 | //////////////////////////////////////////////// 1401 | 1402 | 1403 | #endif // ASYNC_UDP_WT32_ETH01_IMPL_H 1404 | -------------------------------------------------------------------------------- /utils/astyle_library.conf: -------------------------------------------------------------------------------- 1 | # Code formatting rules for Arduino libraries, modified from for KH libraries: 2 | # 3 | # https://github.com/arduino/Arduino/blob/master/build/shared/examples_formatter.conf 4 | # 5 | 6 | # astyle --style=allman -s2 -t2 -C -S -xW -Y -M120 -f -p -xg -H -xb -c --xC120 -xL *.h *.cpp *.ino 7 | 8 | --mode=c 9 | --lineend=linux 10 | --style=allman 11 | 12 | # -r or -R 13 | #--recursive 14 | 15 | # -c => Converts tabs into spaces 16 | convert-tabs 17 | 18 | # -s2 => 2 spaces indentation 19 | --indent=spaces=2 20 | 21 | # -t2 => tab =2 spaces 22 | #--indent=tab=2 23 | 24 | # -C 25 | --indent-classes 26 | 27 | # -S 28 | --indent-switches 29 | 30 | # -xW 31 | --indent-preproc-block 32 | 33 | # -Y => indent classes, switches (and cases), comments starting at column 1 34 | --indent-col1-comments 35 | 36 | # -M120 => maximum of 120 spaces to indent a continuation line 37 | --max-continuation-indent=120 38 | 39 | # -xC120 => max‑code‑length will break a line if the code exceeds # characters 40 | --max-code-length=120 41 | 42 | # -f => 43 | --break-blocks 44 | 45 | # -p => put a space around operators 46 | --pad-oper 47 | 48 | # -xg => Insert space padding after commas 49 | --pad-comma 50 | 51 | # -H => put a space after if/for/while 52 | pad-header 53 | 54 | # -xb => Break one line headers (e.g. if/for/while) 55 | --break-one-line-headers 56 | 57 | # -c => Converts tabs into spaces 58 | #--convert-tabs 59 | 60 | # if you like one-liners, keep them 61 | #keep-one-line-statements 62 | 63 | # -xV 64 | --attach-closing-while 65 | 66 | #unpad-paren 67 | 68 | # -xp 69 | remove-comment-prefix 70 | 71 | -------------------------------------------------------------------------------- /utils/restyle.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for dir in . ; do 4 | find $dir -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" -o -name "*.ino" \) -exec astyle --suffix=none --options=./utils/astyle_library.conf \{\} \; 5 | done 6 | 7 | --------------------------------------------------------------------------------