├── .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 | [](https://www.ardu-badge.com/AsyncUDP_WT32_ETH01)
5 | [](https://github.com/khoih-prog/AsyncUDP_WT32_ETH01/releases)
6 | [](#Contributing)
7 | [](http://github.com/khoih-prog/AsyncUDP_WT32_ETH01/issues)
8 |
9 |
10 |
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). [](https://github.com/arduino/Arduino/releases/latest)
105 | 2. [`ESP32 Core 2.0.5+`](https://github.com/espressif/arduino-esp32) for ESP32-based boards. [](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 [](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 [](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 |
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 | [](https://www.ardu-badge.com/AsyncUDP_WT32_ETH01)
5 | [](https://github.com/khoih-prog/AsyncUDP_WT32_ETH01/releases)
6 | [](#Contributing)
7 | [](http://github.com/khoih-prog/AsyncUDP_WT32_ETH01/issues)
8 |
9 |
10 |
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 |
--------------------------------------------------------------------------------