Compare commits

...

93 Commits

Author SHA1 Message Date
46d5afb17f Quote {build.source.path} to allow spaces in path (#4868)
Previously sketches or examples that had spaces anywhere in their absolute
path caused a total build failure. By adding quotes around the path in
platform.txt, they now build correctly

Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
2021-03-26 13:24:21 +02:00
66746750a4 IDF release/v3.3.5 85c43024c (#4976)
esp-face: master 420fc7e
esp32-camera: master 488c308
2021-03-26 12:56:06 +02:00
e7a2759b65 Allow STA SSID length of 32
Fixes: https://github.com/espressif/arduino-esp32/issues/3218
2021-03-23 14:30:19 +02:00
2ee66b54f0 IDF release/v3.3 c43efe150 (#4936)
esp-face: master 420fc7e
esp32-camera: master 488c308
FreeRTOS Static
2021-03-20 14:04:35 +02:00
2d3c57635d Fix: WebServer: Digest authentication failed for some clients
Ports: 4d3850e87e
2021-03-19 02:10:16 +02:00
a299ddc99e Change send_ssl_data to use size_t instead of uint16_t
Fixes: https://github.com/espressif/arduino-esp32/issues/4960
2021-03-18 15:02:37 +02:00
93bcf5f250 Allow passing custom HTTPClient to HTTPUpdate (#4959)
This enables customizing HTTP headers which adds some extra flexibility.
This does not break anything of course because this change introduces a new constructor with a new additional HTTPClient argument for HTTPUpdate class.
2021-03-18 13:12:57 +02:00
bd41334265 Fix ETH not enabling DHCP when configured with INADDR_NONE
Fixes: https://github.com/espressif/arduino-esp32/issues/4778
2021-03-18 00:53:53 +02:00
9a0762ad2a [BLE Client] Fix Deadlock when calling writeValue after registerForNotify
Fixes: https://github.com/espressif/arduino-esp32/issues/4952
2021-03-17 18:46:55 +02:00
a451c9ef0d Fix HTTPClient crash on GET() for url with redirects
Fixes: https://github.com/espressif/arduino-esp32/issues/4931
2021-03-16 21:28:19 +02:00
d362e1ee1a [BLE] Allows you to specify which channels are used to advertise. (#4954)
In some use cases getting rssi signal from one channel is more stable (less variance) than rssi from the three advertising channels.

This change allows you to specify which channels are used to advertise.
2021-03-16 11:56:23 +02:00
33d9f4aa19 Update GitHub Pages Builder
Add some debug and allow building from a branch named `pages`
2021-03-16 02:48:17 +02:00
63c51d51fb Update HTTPUpdate.cpp (#4942)
This is a mirror of a change in esp8266 needed to update with a url that redirects.
2021-03-16 02:14:53 +02:00
5b845272ed Fix BluetoothSerial TX Stall
Fixes: https://github.com/espressif/arduino-esp32/issues/4949
2021-03-16 02:11:59 +02:00
5da4a47bdf Update debian_ubuntu.md (#4907)
* Update debian_ubuntu.md

ERROR: This script does not work on Python 2.7 The minimum supported Python version is 3.6. Please use https://bootstrap.pypa.io/2.7/get-pip.py instead.

* Update debian_ubuntu.md

Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
2021-03-15 13:22:34 +02:00
3253de8792 added scan_method = WIFI_ALL_CHANNEL_SCAN into wifi config in WiFi.begin() to let the scan choose the nearest / strongest AP in case that there are multiple APs with the same SSID (#4947)
In case you have multiple APs with the same SSID/password and WiFi.begin(ssid, pwd) is called, ESP32 defaults to connect to THE FIRST AP FOUND matching ssid - according to:
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_wifi.html#_CPPv418wifi_scan_method_t

This can cause situations that ESP32 is trying to connect to AP which is far away from it (weak signal) even there is AP close to it, just as in my house - I have AP on channel 6 which is in the 1st floor (quite far from room where I do the programming) and AP on channel 13 in the same room I do the programming (which is in the 2nd floor) - result: ESP32 is trying to connect to the AP on channel 6 because it finds it first and never try the AP on channel 13 in the same room, result of this is very unreliable WiFi connection.

When scan_method is set to WIFI_ALL_CHANNEL_SCAN, ESP32 scans all channels and choose the nearest / strongest AP (matching the ssid of course) as expected - result is no connection problems at all.

Therefore I propose adding this parameter into WiFi.begin, connection problems as described above are quite confusing (especially for beginners), I can imagine that for example Schools there are usually using mutliple APs and this can cause intermittent connection problems without obvious reason.
2021-03-15 13:21:43 +02:00
a31f30529d fix spiTransferBytesNL() writes past end of data_out
Fixes: https://github.com/espressif/arduino-esp32/issues/4935
2021-03-15 10:40:50 +02:00
35643bdd9b adds esp8266-style hostname setting (#4938)
a little step to make esp8266 code compile without changes under esp32
2021-03-15 10:10:30 +02:00
8dc70e0add Revert "Update licenses"
This reverts commit 4b3f5c8ed4.
2021-03-11 12:11:53 +02:00
b42739dfa4 Update howsmyssl.com root certificate 2021-03-10 17:55:40 +02:00
93d5b8c672 Fix String::replace()
Fixes: https://github.com/espressif/arduino-esp32/issues/4920
2021-03-10 17:13:14 +02:00
f815a7c636 Add WiFi.softAPSSID()
Fixes: https://github.com/espressif/arduino-esp32/issues/4922
2021-03-10 16:36:51 +02:00
23f6e81d52 Fix AsyncUDP reporting bad address and port
Fixes: https://github.com/espressif/arduino-esp32/issues/4923
2021-03-10 16:20:18 +02:00
e8311b00ae IDF release/v3.3 0bfff0b25 (#4895)
esp-face: master 420fc7e
esp32-camera: master 770f26a
2021-03-10 14:48:35 +02:00
4d95e3a7ea Fix BT not starting correctly and SPP Coex not working
Fixes: https://github.com/espressif/arduino-esp32/issues/4912
2021-03-09 01:56:47 +02:00
7dc769d81c Board name change (ETBoard -> ET-Board) (#4858)
Co-authored-by: ketri-kjy <jinyoung@ketri.re.kr>
Co-authored-by: ketri2484 <ketri2484@gamil.com>
Co-authored-by: me-no-dev <hristo@espressif.com>
2021-03-09 00:32:02 +02:00
4204d1e60a Handle PSRAM libs in PlatformIO build script (#4911)
This PR adds PSRAM-specific libraries to the final linker command depending on the `BOARD_HAS_PSRAM` macro.

cc @me-no-dev
2021-03-09 00:21:52 +02:00
d7fda910fb Update stale.yml (#4902)
Labels names updated. Not sure if the spaces in label's names are going to work.
2021-03-06 14:15:46 +02:00
f7fc8ab377 Use HTTP method table from ESP-IDF's nghttp (#4900)
Fixes: #4884

* Use HTTP method table from ESP-IDF's nghttp
* Parse methods using IDF's HTTP method list
* Make example's loops to allow the CPU to switch tasks
2021-03-05 13:40:52 +02:00
dd834b3372 Ensure that String::setLen() is always after any memory operation
Since `String::setLen()` is now modifying the buffer, this change is required to ensure that the proper buffer is changed.
2021-03-05 12:00:39 +02:00
0e55f775d3 Fixing issue in String::remove 2021-03-04 22:41:46 +02:00
22a488cf23 Fix String::clear() not clearing the string properly
Fixes: https://github.com/espressif/arduino-esp32/issues/4893
2021-03-04 21:20:27 +02:00
6e7cc5210d Update pins_arduino.h for FireBettle-ESP32 (#4867)
* Update pins_arduino.h

Fix the bug that the IDE show: "Error compiling for the board FireBettle-ESP32" 
Detial"error : redefinition of const uint8_t D0~D9"

* Update pins_arduino.h

Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
2021-03-04 17:04:18 +02:00
7a6900a1f2 Correct issue 4871 - change space to underscore in boards.txt setting lolin32-lite.build.board (#4885) 2021-03-04 15:31:23 +02:00
0e0a7565e8 Remove tools/sdk/include/nimble from include path (#4891) 2021-03-04 15:30:34 +02:00
bd3addeb8e Fixed use of Bluedroid instead of BT in HAL. (#4879)
Fixed use of CONFIG_BLUEDROID_ENABLED instead of CONFIG_BT_ENABLED in HAL. This prevented compilation with Nimble-only configuration without apparent benefit.
2021-03-01 23:55:04 +02:00
1cf1c8eb79 Fix several SD card issues (#4876)
- File might not eval to false if opened with write/append and SD is gone
- Allow card to be formatted if FAT partition was not found
- Mark card as gone in certain situations
- Fix several logic errors in low level SD API
2021-03-01 23:52:57 +02:00
3fe7c2e8cd Add div by zero check back into WMath::map (#4853)
* Add div by zero check back into WMath::map
* include esp32-hal-log.h

Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
2021-02-24 19:04:36 +02:00
5d00b6eb16 Fix case where EEPROM will try to return longer string than it should
Fixes: https://github.com/espressif/arduino-esp32/issues/4768
2021-02-24 18:47:11 +02:00
419ba32432 etboard pinmap upload (#4748)
Co-authored-by: ketri-kjy <jinyoung@ketri.re.kr>
Co-authored-by: ketri2484 <ketri2484@gamil.com>
2021-02-23 09:49:38 +02:00
a0ddd8a16e IDF release/v3.3 7a85334d8 (#4813)
esp-face: master 420fc7e
esp32-camera: master a5ccbec
2021-02-23 01:06:41 +02:00
b8dab5ed1a Added possibility to use ESP32-IDF log insted of redefined one (#4845)
With this PR user can select to use the original ESP-IDF log instead of the redefined one.

User can also redefine the log function as per [Logging Library](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/log.html#_CPPv419esp_log_set_vprintf14vprintf_like_t) so he can for example redirect logs to a file.

To enable this change just add -DUSE_ESP32_LOG to build flags.
User can also change the default TAG (that now is ES32) to whatever it wants adding '-DTAG="tag_value"' to build flags
2021-02-23 00:18:15 +02:00
2141313148 Fix PSRAM support (#4850) 2021-02-23 00:15:48 +02:00
44aaf13225 Added BLEAddress operator overload methods (#4839)
Allows BLEAddress to be used as key in std::map etc
2021-02-22 19:37:07 +02:00
560c0f45f5 Fix dropped SSL connection when buffer gets full. (#4820)
mbedTLS requires repeated calls to mbedtls_ssl_write() whenever it returns MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE. this happens when the client sends data faster then the server or the connection can handle.
2021-02-22 19:34:56 +02:00
4b3f5c8ed4 Update licenses 2021-02-18 12:14:35 +02:00
c282cd8f5f Remove temp buffer in WiFiClientSecure::lastError (#4822)
The temp buffer serves no purpose here. Also mbedtls_strerror can be called with size == 0 safely.
2021-02-18 11:44:44 +02:00
7e59971d2f Add Lolin32 Lite and TTGO T7 boards (#4819)
Add the Wemos Lolin32 Lite (no longer being produced same as Lolin32) and
the TTGO T7 v1.3 and v1.4 boards (status unknown). All three are rather
generic ESP32 boards the main difference being pin layouts.
2021-02-18 11:43:11 +02:00
f4b17b3033 Allow releases from different branches 2021-02-17 14:06:30 +02:00
1ab550f6f2 Changed BLE notify_callback from raw function pointer to std::function (#4737) 2021-02-16 22:10:04 +02:00
9be784f69b Improve cleanup in BLEClient (#4742)
- Remove client from the list of devices in case registration fails
- Filter other events not related to registration during registration phase
- Cleanup if connect fails
- Reset if after disconnect
- Disconnect callback *after* cleanup is done so object can be deleted

This fixes some of the issues I had like:
- `BLEClient::connect` hangs up and never recovered because registration failed
- `BLEClient` could not be deleted after disconnect or deletion creating ghost events https://github.com/espressif/arduino-esp32/issues/4047
- `BLEClient` could not be properly reused after a connection was attempted (successful or not) 

* Cleanup in case of registration and connect failure.
Cleanup before calling disconnect callback for safe delete.
Reject other events during registration.
Adresses #4047, #4055

* Clear if after unregister #4047
2021-02-16 11:21:45 +02:00
7cdfb8bc7c Refactor BLEAdvertisedDevice (#4739)
fixes #4596

* Prevent possible undefined behaviour by get methods not taking an index as parameter
* Add methods to get the count of service data UUIDs and service UUIDs
* Various code improvements
2021-02-16 11:02:58 +02:00
8134a42162 Fix leak of memory and possible crashes in AsyncUDP 2021-02-16 10:26:37 +02:00
f13ff65691 AsyncUDP: Added lastErr helper variable (#4789)
The variable is useful when debugging AsyncUDP send problems.
The upper application can read and analyze the error reason.
2021-02-16 02:21:53 +02:00
e831680a41 Fixed a memory leak in BLE (issue #4753) (#4761)
* Fixed crash on delete after disconnect

* Fixed memory leak when getting characteristics

* Removed guard

Co-authored-by: ushiboy <ushiboy.dev@gmail.com>
2021-02-16 01:50:24 +02:00
d964873840 Added more inclusive CORS policy (#4767) 2021-02-16 01:49:30 +02:00
7e8993fc83 Speed up upload by a factor of 17 (#4787)
* Speed up upload by a factor of 17

Uploads are very slow because of an unnecessary "client.connected()" check in _uploadReadByte().

Here is what happens:
client.connected() is called for every byte read.  WiFiClient::connected() calls recv(fd(), &dummy, 0, MSG_DONTWAIT); which takes a relatively long time, so the optimized path of returning a buffered byte via client.read() is effectively nullified.

Removing the one line changed the upload speed for a 2 MB file (discarding the received data) from 22 KB/sec (before) to 367 KB/sec (after).

The change is safe in the face of disconnects because client.read(), when it no longer has buffered data, calls (WiFiClient)  fillBuffer(), which calls recv(), so the disconnection will be detected in due course.

* Move disconnect check into the timeout loop
2021-02-16 01:47:01 +02:00
15bae92a72 Idf release/v3.3 d8082b7f3
* Update IDF to d8082b7f3
2021-02-16 01:37:37 +02:00
6f23cd5988 Make sure that HTTPClient disconnects from the old server if redirecting to new one
Fixes: https://github.com/espressif/arduino-esp32/issues/4763
2021-02-04 02:42:44 +02:00
ad4cf1461b Rework setHostname for WiFi STA
Fixes: https://github.com/espressif/arduino-esp32/issues/2537
2021-02-03 13:17:49 +02:00
5de03a3918 Fix WiFi STA config IP to INADDR_NONE results in 255.255.255.255
Fixes: https://github.com/espressif/arduino-esp32/issues/4732
2021-02-03 11:47:35 +02:00
4b385690bc Move default Arduino partitions to a separate section (#4747) 2021-01-27 13:52:39 +02:00
dd513df124 Add arm64 support for mkspiffs 2021-01-21 14:42:31 +02:00
cee659563d IDF release/v3.3 7e63061fa (#4726)
Co-authored-by: me-no-dev <me-no-dev@github.com>
2021-01-21 14:33:55 +02:00
55442a05a4 Remove an unused variable 'channel' (#4725) 2021-01-21 14:31:25 +02:00
c9b3e512dd Make BLERemoteCharacteristic::getRemoteService() public #3367 (#4735) 2021-01-21 14:30:33 +02:00
8d0e68db4f Added parameter to Preferences::begin to select non-default NVS partition (#4718) 2021-01-15 19:06:51 +02:00
d2530850a3 Copy platformio-build.py in the release package 2021-01-14 11:17:21 +02:00
7ecbb483da Update toolchain and move files to github 2021-01-12 17:53:49 +02:00
b0e896e9ae IDF release/v3.3 cd59d107b (#4708)
Co-authored-by: me-no-dev <me-no-dev@github.com>
2021-01-12 15:24:34 +02:00
08f4665775 Change fetch depth for release so that history can be fetched 2021-01-12 15:09:28 +02:00
2452c1fb53 IDF release/v3.3 71df1f742
esp-face: master 420fc7e
esp32-camera: master 0107093
2021-01-11 14:20:02 +02:00
5f98370707 Add IP101 support (#4620) 2021-01-11 12:00:35 +02:00
81b9130d8d BluetoothSerial SSP Authentication with callbacks (#4634)
Added authentication callbacks and example, resolves #4622.
2021-01-11 11:58:15 +02:00
434d02c49f BLERemoteCharacteristic::registerForNotify: Permit event registration without updating descriptor. (#4659) 2021-01-11 11:44:38 +02:00
15db297130 availableForWrite (#4664)
added availableForWrite to Print.h to make compatible with Arduino Print.h
2021-01-11 11:43:10 +02:00
fe093a5e35 Sanitize compiler warning in BLERemoteService.cpp (issue #4660) (#4669)
Compiler complains on unused parameter pCharacteristicMap:

framework-arduinoespressif32\libraries\BLE\src\BLERemoteService.cpp: In member function 'void BLERemoteService::getCharacteristics(std::map<short unsigned int, BLERemoteCharacteristic*>*)':
\framework-arduinoespressif32\libraries\BLE\src\BLERemoteService.cpp:246:89: warning: parameter 'pCharacteristicMap' set but not used [-Wunused-but-set-parameter]
 void BLERemoteService::getCharacteristics(std::map<uint16_t, BLERemoteCharacteristic*>* pCharacteristicMap) {
2021-01-11 11:42:32 +02:00
a0ef17a9dd Use non-deprecated DPORT values in SPI HAL (#4682) 2021-01-11 11:40:18 +02:00
be77bd4e27 Resolve crash with timer interrupt functions called from ISR (#4684) 2021-01-11 11:39:39 +02:00
ef99cd7fe7 Add WiFiClientSecure::setInsecure() to equalize API with ESP8266 (#4648) 2020-12-21 01:09:37 +02:00
b05bdf6904 Update esptool for Big Sur 2020-12-07 10:19:55 +02:00
442c63a4c6 IDF release/v3.3 b4c075169 (#4604)
esp-face: master 420fc7e
esp32-camera: master 0107093
2020-12-07 10:03:16 +02:00
d1a4b3b822 Add loop task stack size config to Kconfig
Follow up for https://github.com/espressif/arduino-esp32/pull/4564
2020-12-02 11:56:45 +02:00
7d5bf9e385 [1.0.5] Make looptask stack size configurable (#4564)
Added guarded define to set the stacksize on the main looptask.
Advantage of this is that build_flags can be used to provide a different value for the stack size should it be neccessary
default behaviour is unaffected
2020-12-02 11:52:04 +02:00
aac26a4d1e [1.0.5] Update Heltec ESP32 series boards definition (#4577) 2020-12-02 11:50:12 +02:00
804c221499 Update .gitignore 2020-12-01 22:20:06 +02:00
3236358ded Update WiFiClient.cpp (#4573)
Replace (depricated) bzero, bcopy with memset and memcpy.
2020-12-01 16:35:12 +02:00
82e71f9b50 Update ssl_client.cpp (#4574)
Replace (depricated) bzero with memset.
2020-12-01 16:34:36 +02:00
2e12392721 IDF release/v3.3 c33fc7821
esp-face: master 420fc7e
esp32-camera: master 0107093
2020-12-01 16:22:18 +02:00
6b0114366b Fix logic in SPIClass::setHwCs. (#4559)
Fixes #4558
2020-11-23 14:22:43 +02:00
18832bb418 M5TimerCam: add LED_BUILTIN & SS/MOSI/MISO/SCK (#4560) 2020-11-23 14:21:58 +02:00
97dcea2b99 Update library.properties (#4563)
Set the category to silence this warning in the Arduino IDE:
```
WARNING: Category '' in library WiFiProv is not valid. Setting to 'Uncategorized'
```
2020-11-23 14:21:34 +02:00
dcff2e9774 Separate Provisioning library from WiFi library (#4547) 2020-11-19 00:12:16 +02:00
219 changed files with 2718 additions and 971 deletions

View File

@ -87,9 +87,15 @@ function git_safe_upload_to_pages(){
EVENT_JSON=`cat $GITHUB_EVENT_PATH` EVENT_JSON=`cat $GITHUB_EVENT_PATH`
echo "GITHUB_EVENT_PATH: $GITHUB_EVENT_PATH"
echo "EVENT_JSON: $EVENT_JSON"
pages_added=`echo "$EVENT_JSON" | jq -r '.commits[].added[]'` pages_added=`echo "$EVENT_JSON" | jq -r '.commits[].added[]'`
echo "added: $pages_added"
pages_modified=`echo "$EVENT_JSON" | jq -r '.commits[].modified[]'` pages_modified=`echo "$EVENT_JSON" | jq -r '.commits[].modified[]'`
echo "modified: $pages_modified"
pages_removed=`echo "$EVENT_JSON" | jq -r '.commits[].removed[]'` pages_removed=`echo "$EVENT_JSON" | jq -r '.commits[].removed[]'`
echo "removed: $pages_removed"
for page in $pages_added; do for page in $pages_added; do
if [[ $page != "README.md" && $page != "docs/"* ]]; then if [[ $page != "README.md" && $page != "docs/"* ]]; then

View File

@ -171,18 +171,19 @@ mkdir -p "$PKG_DIR/tools"
# Copy all core files to the package folder # Copy all core files to the package folder
echo "Copying files for packaging ..." echo "Copying files for packaging ..."
cp -f "$GITHUB_WORKSPACE/boards.txt" "$PKG_DIR/" cp -f "$GITHUB_WORKSPACE/boards.txt" "$PKG_DIR/"
cp -f "$GITHUB_WORKSPACE/programmers.txt" "$PKG_DIR/" cp -f "$GITHUB_WORKSPACE/programmers.txt" "$PKG_DIR/"
cp -Rf "$GITHUB_WORKSPACE/cores" "$PKG_DIR/" cp -Rf "$GITHUB_WORKSPACE/cores" "$PKG_DIR/"
cp -Rf "$GITHUB_WORKSPACE/libraries" "$PKG_DIR/" cp -Rf "$GITHUB_WORKSPACE/libraries" "$PKG_DIR/"
cp -Rf "$GITHUB_WORKSPACE/variants" "$PKG_DIR/" cp -Rf "$GITHUB_WORKSPACE/variants" "$PKG_DIR/"
cp -f "$GITHUB_WORKSPACE/tools/espota.exe" "$PKG_DIR/tools/" cp -f "$GITHUB_WORKSPACE/tools/espota.exe" "$PKG_DIR/tools/"
cp -f "$GITHUB_WORKSPACE/tools/espota.py" "$PKG_DIR/tools/" cp -f "$GITHUB_WORKSPACE/tools/espota.py" "$PKG_DIR/tools/"
cp -f "$GITHUB_WORKSPACE/tools/esptool.py" "$PKG_DIR/tools/" cp -f "$GITHUB_WORKSPACE/tools/esptool.py" "$PKG_DIR/tools/"
cp -f "$GITHUB_WORKSPACE/tools/gen_esp32part.py" "$PKG_DIR/tools/" cp -f "$GITHUB_WORKSPACE/tools/gen_esp32part.py" "$PKG_DIR/tools/"
cp -f "$GITHUB_WORKSPACE/tools/gen_esp32part.exe" "$PKG_DIR/tools/" cp -f "$GITHUB_WORKSPACE/tools/gen_esp32part.exe" "$PKG_DIR/tools/"
cp -Rf "$GITHUB_WORKSPACE/tools/partitions" "$PKG_DIR/tools/" cp -Rf "$GITHUB_WORKSPACE/tools/partitions" "$PKG_DIR/tools/"
cp -Rf "$GITHUB_WORKSPACE/tools/sdk" "$PKG_DIR/tools/" cp -Rf "$GITHUB_WORKSPACE/tools/sdk" "$PKG_DIR/tools/"
cp -f "$GITHUB_WORKSPACE/tools/platformio-build.py" "$PKG_DIR/tools/"
# Remove unnecessary files in the package folder # Remove unnecessary files in the package folder
echo "Cleaning up folders ..." echo "Cleaning up folders ..."
@ -254,17 +255,30 @@ releasesJson=`curl -sH "Authorization: token $GITHUB_TOKEN" "https://api.github.
if [ $? -ne 0 ]; then echo "ERROR: Get Releases Failed! ($?)"; exit 1; fi if [ $? -ne 0 ]; then echo "ERROR: Get Releases Failed! ($?)"; exit 1; fi
set +e set +e
prev_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false and .prerelease == false)) | sort_by(.created_at | - fromdateiso8601) | .[0].tag_name') prev_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .prerelease == false)) | sort_by(.published_at | - fromdateiso8601) | .[0].tag_name")
prev_any_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false)) | sort_by(.created_at | - fromdateiso8601) | .[0].tag_name') prev_any_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false)) | sort_by(.published_at | - fromdateiso8601) | .[0].tag_name")
prev_branch_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .prerelease == false and .target_commitish == \"$RELEASE_BRANCH\")) | sort_by(.published_at | - fromdateiso8601) | .[0].tag_name")
prev_branch_any_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .target_commitish == \"$RELEASE_BRANCH\")) | sort_by(.published_at | - fromdateiso8601) | .[0].tag_name")
shopt -s nocasematch shopt -s nocasematch
if [ "$prev_any_release" == "$RELEASE_TAG" ]; then if [ "$prev_release" == "$RELEASE_TAG" ]; then
prev_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false and .prerelease == false)) | sort_by(.created_at | - fromdateiso8601) | .[1].tag_name') prev_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .prerelease == false)) | sort_by(.published_at | - fromdateiso8601) | .[1].tag_name")
prev_any_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false)) | sort_by(.created_at | - fromdateiso8601) | .[1].tag_name') fi
if [ "$prev_any_release" == "$RELEASE_TAG" ]; then
prev_any_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false)) | sort_by(.published_at | - fromdateiso8601) | .[1].tag_name")
fi
if [ "$prev_branch_release" == "$RELEASE_TAG" ]; then
prev_branch_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .prerelease == false and .target_commitish == \"$RELEASE_BRANCH\")) | sort_by(.published_at | - fromdateiso8601) | .[1].tag_name")
fi
if [ "$prev_branch_any_release" == "$RELEASE_TAG" ]; then
prev_branch_any_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .target_commitish == \"$RELEASE_BRANCH\")) | sort_by(.published_at | - fromdateiso8601) | .[1].tag_name")
fi fi
COMMITS_SINCE_RELEASE="$prev_any_release"
shopt -u nocasematch shopt -u nocasematch
set -e set -e
echo "Previous Release: $prev_release"
echo "Previous (any)release: $prev_any_release"
echo
# Merge package JSONs with previous releases # Merge package JSONs with previous releases
if [ ! -z "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then if [ ! -z "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then
echo "Merging with JSON from $prev_any_release ..." echo "Merging with JSON from $prev_any_release ..."
@ -272,17 +286,12 @@ if [ ! -z "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then
fi fi
if [ "$RELEASE_PRE" == "false" ]; then if [ "$RELEASE_PRE" == "false" ]; then
COMMITS_SINCE_RELEASE="$prev_release"
if [ ! -z "$prev_release" ] && [ "$prev_release" != "null" ]; then if [ ! -z "$prev_release" ] && [ "$prev_release" != "null" ]; then
echo "Merging with JSON from $prev_release ..." echo "Merging with JSON from $prev_release ..."
merge_package_json "$prev_release/$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL" merge_package_json "$prev_release/$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL"
fi fi
fi fi
echo "Previous Release: $prev_release"
echo "Previous (any)release: $prev_any_release"
echo
# Upload package JSONs # Upload package JSONs
echo "Uploading $PACKAGE_JSON_DEV ..." echo "Uploading $PACKAGE_JSON_DEV ..."
echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_DEV"` echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_DEV"`
@ -327,21 +336,35 @@ if [ $arrLen > 3 ] && [ "${msgArray[0]:0:3}" == "tag" ]; then
fi fi
# Append Commit Messages # Append Commit Messages
echo
echo "Previous Branch Release: $prev_branch_release"
echo "Previous Branch (any)release: $prev_branch_any_release"
echo
commitFile="$OUTPUT_DIR/commits.txt"
COMMITS_SINCE_RELEASE="$prev_branch_any_release"
if [ "$RELEASE_PRE" == "false" ]; then
COMMITS_SINCE_RELEASE="$prev_branch_release"
fi
if [ ! -z "$COMMITS_SINCE_RELEASE" ] && [ "$COMMITS_SINCE_RELEASE" != "null" ]; then if [ ! -z "$COMMITS_SINCE_RELEASE" ] && [ "$COMMITS_SINCE_RELEASE" != "null" ]; then
echo "Getting commits since $COMMITS_SINCE_RELEASE ..." echo "Getting commits since $COMMITS_SINCE_RELEASE ..."
commitFile=$OUTPUT_DIR/commits.txt git -C "$GITHUB_WORKSPACE" log --oneline -n 500 "$COMMITS_SINCE_RELEASE..HEAD" > "$commitFile"
git -C "$GITHUB_WORKSPACE" log --oneline "$COMMITS_SINCE_RELEASE..HEAD" > "$OUTPUT_DIR/commits.txt" elif [ "$RELEASE_BRANCH" != "master" ]; then
releaseNotes+=$'\r\n##### Commits\r\n' echo "Getting all commits on branch '$RELEASE_BRANCH' ..."
IFS=$'\n' git -C "$GITHUB_WORKSPACE" log --oneline -n 500 --cherry-pick --left-only --no-merges HEAD...origin/master > "$commitFile"
for next in `cat $commitFile` else
do echo "Getting all commits on master ..."
IFS=' ' read -r commitId commitMsg <<< "$next" git -C "$GITHUB_WORKSPACE" log --oneline -n 500 --no-merges > "$commitFile"
commitLine="- [$commitId](https://github.com/$GITHUB_REPOSITORY/commit/$commitId) $commitMsg"
releaseNotes+="$commitLine"
releaseNotes+=$'\r\n'
done
rm -f $commitFile
fi fi
releaseNotes+=$'\r\n##### Commits\r\n'
IFS=$'\n'
for next in `cat $commitFile`
do
IFS=' ' read -r commitId commitMsg <<< "$next"
commitLine="- [$commitId](https://github.com/$GITHUB_REPOSITORY/commit/$commitId) $commitMsg"
releaseNotes+="$commitLine"
releaseNotes+=$'\r\n'
done
rm -f $commitFile
# Prepend the original release body # Prepend the original release body
if [ "${RELEASE_BODY: -1}" == $'\r' ]; then if [ "${RELEASE_BODY: -1}" == $'\r' ]; then

11
.github/stale.yml vendored
View File

@ -12,12 +12,9 @@ onlyLabels: []
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
exemptLabels: exemptLabels:
- pinned - "Type: For reference"
- security - "Type: To be implemented"
- "to be implemented" - "Type: Feature request"
- "for reference"
- "move to PR"
- "enhancement"
# Set to true to ignore issues in a project (defaults to false) # Set to true to ignore issues in a project (defaults to false)
exemptProjects: false exemptProjects: false
@ -29,7 +26,7 @@ exemptMilestones: false
exemptAssignees: false exemptAssignees: false
# Label to use when marking as stale # Label to use when marking as stale
staleLabel: stale staleLabel: Status: Stale
# Comment to post when marking as stale. Set to `false` to disable # Comment to post when marking as stale. Set to `false` to disable
markComment: > markComment: >

View File

@ -4,9 +4,12 @@ on:
push: push:
branches: branches:
- master - master
- pages
paths: paths:
- 'README.md' - 'README.md'
- 'docs/**' - 'docs/**'
- '.github/scripts/on-pages.sh'
- '.github/workflows/gh-pages.yml'
jobs: jobs:

View File

@ -11,6 +11,8 @@ jobs:
steps: steps:
- uses: actions/checkout@master - uses: actions/checkout@master
with:
fetch-depth: 0
- uses: actions/setup-python@v1 - uses: actions/setup-python@v1
with: with:
python-version: '3.x' python-version: '3.x'

5
.gitignore vendored
View File

@ -1,9 +1,10 @@
tools/xtensa-esp32-elf tools/xtensa-esp32-elf
tools/xtensa-esp32s2-elf
tools/dist tools/dist
tools/esptool tools/esptool
tools/esptool.exe tools/esptool.exe
tools/mkspiffs/mkspiffs tools/mkspiffs
tools/mkspiffs/mkspiffs.exe tools/mklittlefs
.DS_Store .DS_Store
#Ignore files built by Visual Studio/Visual Micro #Ignore files built by Visual Studio/Visual Micro

View File

@ -7,6 +7,7 @@ set(CORE_SRCS
cores/esp32/esp32-hal-dac.c cores/esp32/esp32-hal-dac.c
cores/esp32/esp32-hal-gpio.c cores/esp32/esp32-hal-gpio.c
cores/esp32/esp32-hal-i2c.c cores/esp32/esp32-hal-i2c.c
cores/esp32/esp32-hal-log.c
cores/esp32/esp32-hal-ledc.c cores/esp32/esp32-hal-ledc.c
cores/esp32/esp32-hal-matrix.c cores/esp32/esp32-hal-matrix.c
cores/esp32/esp32-hal-misc.c cores/esp32/esp32-hal-misc.c
@ -72,11 +73,11 @@ set(LIBRARY_SRCS
libraries/WiFi/src/WiFi.cpp libraries/WiFi/src/WiFi.cpp
libraries/WiFi/src/WiFiGeneric.cpp libraries/WiFi/src/WiFiGeneric.cpp
libraries/WiFi/src/WiFiMulti.cpp libraries/WiFi/src/WiFiMulti.cpp
libraries/WiFi/src/WiFiProv.cpp
libraries/WiFi/src/WiFiScan.cpp libraries/WiFi/src/WiFiScan.cpp
libraries/WiFi/src/WiFiServer.cpp libraries/WiFi/src/WiFiServer.cpp
libraries/WiFi/src/WiFiSTA.cpp libraries/WiFi/src/WiFiSTA.cpp
libraries/WiFi/src/WiFiUdp.cpp libraries/WiFi/src/WiFiUdp.cpp
libraries/WiFiProv/src/WiFiProv.cpp
libraries/Wire/src/Wire.cpp libraries/Wire/src/Wire.cpp
) )
@ -202,6 +203,7 @@ set(COMPONENT_ADD_INCLUDEDIRS
libraries/WebServer/src libraries/WebServer/src
libraries/WiFiClientSecure/src libraries/WiFiClientSecure/src
libraries/WiFi/src libraries/WiFi/src
libraries/WiFiProv/src
libraries/Wire/src libraries/Wire/src
) )

View File

@ -40,6 +40,12 @@ config ARDUINO_RUNNING_CORE
default 1 if ARDUINO_RUN_CORE1 default 1 if ARDUINO_RUN_CORE1
default -1 if ARDUINO_RUN_NO_AFFINITY default -1 if ARDUINO_RUN_NO_AFFINITY
config ARDUINO_LOOP_STACK_SIZE
int "Loop thread stack size"
default 8192
help
Amount of stack available for the Arduino task.
choice ARDUINO_EVENT_RUNNING_CORE choice ARDUINO_EVENT_RUNNING_CORE
bool "Core on which Arduino's event handler is running" bool "Core on which Arduino's event handler is running"
default ARDUINO_EVENT_RUN_CORE1 default ARDUINO_EVENT_RUN_CORE1

File diff suppressed because it is too large Load Diff

View File

@ -73,6 +73,11 @@ public:
} }
size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3))); size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3)));
// add availableForWrite to make compatible with Arduino Print.h
// default to zero, meaning "a single write may block"
// should be overriden by subclasses with buffering
virtual int availableForWrite() { return 0; }
size_t print(const __FlashStringHelper *); size_t print(const __FlashStringHelper *);
size_t print(const String &); size_t print(const String &);
size_t print(const char[]); size_t print(const char[]);

View File

@ -27,6 +27,7 @@ extern "C" {
#include <stdlib.h> #include <stdlib.h>
#include "esp_system.h" #include "esp_system.h"
} }
#include "esp32-hal-log.h"
void randomSeed(unsigned long seed) void randomSeed(unsigned long seed)
{ {
@ -69,7 +70,10 @@ long map(long x, long in_min, long in_max, long out_min, long out_max) {
const long dividend = out_max - out_min; const long dividend = out_max - out_min;
const long divisor = in_max - in_min; const long divisor = in_max - in_min;
const long delta = x - in_min; const long delta = x - in_min;
if(divisor == 0){
log_e("Invalid map input range, min == max");
return -1; //AVR returns -1, SAM returns 0
}
return (delta * dividend + (divisor / 2)) / divisor + out_min; return (delta * dividend + (divisor / 2)) / divisor + out_min;
} }

View File

@ -130,9 +130,9 @@ String::~String() {
inline void String::init(void) { inline void String::init(void) {
setSSO(false); setSSO(false);
setBuffer(nullptr);
setCapacity(0); setCapacity(0);
setLen(0); setLen(0);
setBuffer(nullptr);
} }
void String::invalidate(void) { void String::invalidate(void) {
@ -159,7 +159,7 @@ unsigned char String::changeBuffer(unsigned int maxStrLen) {
// Already using SSO, nothing to do // Already using SSO, nothing to do
uint16_t oldLen = len(); uint16_t oldLen = len();
setSSO(true); setSSO(true);
setLen(oldLen); setLen(oldLen);
return 1; return 1;
} else { // if bufptr && !isSSO() } else { // if bufptr && !isSSO()
// Using bufptr, need to shrink into sso.buff // Using bufptr, need to shrink into sso.buff
@ -168,8 +168,8 @@ unsigned char String::changeBuffer(unsigned int maxStrLen) {
free(wbuffer()); free(wbuffer());
uint16_t oldLen = len(); uint16_t oldLen = len();
setSSO(true); setSSO(true);
setLen(oldLen);
memcpy(wbuffer(), temp, maxStrLen); memcpy(wbuffer(), temp, maxStrLen);
setLen(oldLen);
return 1; return 1;
} }
} }
@ -193,8 +193,8 @@ unsigned char String::changeBuffer(unsigned int maxStrLen) {
} }
setSSO(false); setSSO(false);
setCapacity(newSize - 1); setCapacity(newSize - 1);
setLen(oldLen); // Needed in case of SSO where len() never existed
setBuffer(newbuffer); setBuffer(newbuffer);
setLen(oldLen); // Needed in case of SSO where len() never existed
return 1; return 1;
} }
return 0; return 0;
@ -209,8 +209,8 @@ String & String::copy(const char *cstr, unsigned int length) {
invalidate(); invalidate();
return *this; return *this;
} }
setLen(length);
memmove(wbuffer(), cstr, length + 1); memmove(wbuffer(), cstr, length + 1);
setLen(length);
return *this; return *this;
} }
@ -219,8 +219,8 @@ String & String::copy(const __FlashStringHelper *pstr, unsigned int length) {
invalidate(); invalidate();
return *this; return *this;
} }
setLen(length);
memcpy_P(wbuffer(), (PGM_P)pstr, length + 1); // We know wbuffer() cannot ever be in PROGMEM, so memcpy safe here memcpy_P(wbuffer(), (PGM_P)pstr, length + 1); // We know wbuffer() cannot ever be in PROGMEM, so memcpy safe here
setLen(length);
return *this; return *this;
} }
@ -250,8 +250,8 @@ void String::move(String &rhs) {
setLen(rhs.len()); setLen(rhs.len());
rhs.setSSO(false); rhs.setSSO(false);
rhs.setCapacity(0); rhs.setCapacity(0);
rhs.setLen(0);
rhs.setBuffer(nullptr); rhs.setBuffer(nullptr);
rhs.setLen(0);
} }
#endif #endif
@ -744,6 +744,7 @@ void String::replace(const String& find, const String& replace) {
} }
} else if(diff < 0) { } else if(diff < 0) {
char *writeTo = wbuffer(); char *writeTo = wbuffer();
unsigned int l = len();
while((foundAt = strstr(readFrom, find.buffer())) != NULL) { while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
unsigned int n = foundAt - readFrom; unsigned int n = foundAt - readFrom;
memmove(writeTo, readFrom, n); memmove(writeTo, readFrom, n);
@ -751,9 +752,10 @@ void String::replace(const String& find, const String& replace) {
memmove(writeTo, replace.buffer(), replace.len()); memmove(writeTo, replace.buffer(), replace.len());
writeTo += replace.len(); writeTo += replace.len();
readFrom = foundAt + find.len(); readFrom = foundAt + find.len();
setLen(len() + diff); l += diff;
} }
memmove(writeTo, readFrom, strlen(readFrom)+1); memmove(writeTo, readFrom, strlen(readFrom)+1);
setLen(l);
} else { } else {
unsigned int size = len(); // compute size needed for result unsigned int size = len(); // compute size needed for result
while((foundAt = strstr(readFrom, find.buffer())) != NULL) { while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
@ -768,7 +770,7 @@ void String::replace(const String& find, const String& replace) {
while(index >= 0 && (index = lastIndexOf(find, index)) >= 0) { while(index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
readFrom = wbuffer() + index + find.len(); readFrom = wbuffer() + index + find.len();
memmove(readFrom + diff, readFrom, len() - (readFrom - buffer())); memmove(readFrom + diff, readFrom, len() - (readFrom - buffer()));
int newLen = len() + diff; int newLen = len() + diff;
memmove(wbuffer() + index, replace.buffer(), replace.len()); memmove(wbuffer() + index, replace.buffer(), replace.len());
setLen(newLen); setLen(newLen);
wbuffer()[newLen] = 0; wbuffer()[newLen] = 0;
@ -796,8 +798,8 @@ void String::remove(unsigned int index, unsigned int count) {
} }
char *writeTo = wbuffer() + index; char *writeTo = wbuffer() + index;
unsigned int newlen = len() - count; unsigned int newlen = len() - count;
setLen(newlen);
memmove(writeTo, wbuffer() + index + count, newlen - index); memmove(writeTo, wbuffer() + index + count, newlen - index);
setLen(newlen);
wbuffer()[newlen] = 0; wbuffer()[newlen] = 0;
} }
@ -827,9 +829,9 @@ void String::trim(void) {
while(isspace(*end) && end >= begin) while(isspace(*end) && end >= begin)
end--; end--;
unsigned int newlen = end + 1 - begin; unsigned int newlen = end + 1 - begin;
setLen(newlen);
if(begin > buffer()) if(begin > buffer())
memmove(wbuffer(), begin, newlen); memmove(wbuffer(), begin, newlen);
setLen(newlen);
wbuffer()[newlen] = 0; wbuffer()[newlen] = 0;
} }

View File

@ -301,9 +301,19 @@ class String {
inline unsigned int len() const { return isSSO() ? sso.len : ptr.len; } inline unsigned int len() const { return isSSO() ? sso.len : ptr.len; }
inline unsigned int capacity() const { return isSSO() ? (unsigned int)SSOSIZE - 1 : ptr.cap; } // Size of max string not including terminal NUL inline unsigned int capacity() const { return isSSO() ? (unsigned int)SSOSIZE - 1 : ptr.cap; } // Size of max string not including terminal NUL
inline void setSSO(bool set) { sso.isSSO = set; } inline void setSSO(bool set) { sso.isSSO = set; }
inline void setLen(int len) { if (isSSO()) sso.len = len; else ptr.len = len; } inline void setLen(int len) {
if (isSSO()) {
sso.len = len;
sso.buff[len] = 0;
} else {
ptr.len = len;
if (ptr.buff) {
ptr.buff[len] = 0;
}
}
}
inline void setCapacity(int cap) { if (!isSSO()) ptr.cap = cap; } inline void setCapacity(int cap) { if (!isSSO()) ptr.cap = cap; }
inline void setBuffer(char *buff) { if (!isSSO()) ptr.buff = buff; } inline void setBuffer(char *buff) { if (!isSSO()) ptr.buff = buff; }
// Buffer accessor functions // Buffer accessor functions
inline const char *buffer() const { return (const char *)(isSSO() ? sso.buff : ptr.buff); } inline const char *buffer() const { return (const char *)(isSSO() ? sso.buff : ptr.buff); }
inline char *wbuffer() const { return isSSO() ? const_cast<char *>(sso.buff) : ptr.buff; } // Writable version of buffer inline char *wbuffer() const { return isSSO() ? const_cast<char *>(sso.buff) : ptr.buff; } // Writable version of buffer

View File

@ -18,11 +18,12 @@
bool btInUse(){ return true; } bool btInUse(){ return true; }
#ifdef CONFIG_BLUEDROID_ENABLED
#include "esp_bt.h" #include "esp_bt.h"
#ifdef CONFIG_CLASSIC_BT_ENABLED #ifdef CONFIG_BTDM_CONTROLLER_MODE_BTDM
#define BT_MODE ESP_BT_MODE_BTDM #define BT_MODE ESP_BT_MODE_BTDM
#elif defined(CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY)
#define BT_MODE ESP_BT_MODE_CLASSIC_BT
#else #else
#define BT_MODE ESP_BT_MODE_BLE #define BT_MODE ESP_BT_MODE_BLE
#endif #endif
@ -79,7 +80,7 @@ bool btStop(){
return false; return false;
} }
#else #else // CONFIG_BT_ENABLED
bool btStarted() bool btStarted()
{ {
return false; return false;
@ -94,6 +95,6 @@ bool btStop()
{ {
return false; return false;
} }
#endif
#endif #endif // CONFIG_BT_ENABLED

View File

@ -0,0 +1,19 @@
#ifndef __MY_LOG__
#define __MY_LOG__
#include "stdio.h"
#include "esp32-hal-log.h"
void log_to_esp(char* tag, esp_log_level_t level, const char *format, ...)
{
va_list va_args;
va_start(va_args, format);
char log_buffer[512];
int len = vsnprintf(log_buffer, sizeof(log_buffer), format, va_args);
if (len > 0)
{
ESP_LOG_LEVEL_LOCAL(level, tag, "%s", log_buffer);
}
va_end(va_args);
}
#endif

View File

@ -36,6 +36,9 @@ extern "C"
#define ARDUHAL_LOG_LEVEL CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL #define ARDUHAL_LOG_LEVEL CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL
#else #else
#define ARDUHAL_LOG_LEVEL CORE_DEBUG_LEVEL #define ARDUHAL_LOG_LEVEL CORE_DEBUG_LEVEL
#ifdef USE_ESP_IDF_LOG
#define LOG_LOCAL_LEVEL CORE_DEBUG_LEVEL
#endif
#endif #endif
#ifndef CONFIG_ARDUHAL_LOG_COLORS #ifndef CONFIG_ARDUHAL_LOG_COLORS
@ -71,6 +74,8 @@ extern "C"
#define ARDUHAL_LOG_RESET_COLOR #define ARDUHAL_LOG_RESET_COLOR
#endif #endif
const char * pathToFileName(const char * path); const char * pathToFileName(const char * path);
int log_printf(const char *fmt, ...); int log_printf(const char *fmt, ...);
@ -78,55 +83,92 @@ int log_printf(const char *fmt, ...);
#define ARDUHAL_LOG_FORMAT(letter, format) ARDUHAL_LOG_COLOR_ ## letter "[" #letter "][%s:%u] %s(): " format ARDUHAL_LOG_RESET_COLOR "\r\n", pathToFileName(__FILE__), __LINE__, __FUNCTION__ #define ARDUHAL_LOG_FORMAT(letter, format) ARDUHAL_LOG_COLOR_ ## letter "[" #letter "][%s:%u] %s(): " format ARDUHAL_LOG_RESET_COLOR "\r\n", pathToFileName(__FILE__), __LINE__, __FUNCTION__
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
#ifndef USE_ESP_IDF_LOG
#define log_v(format, ...) log_printf(ARDUHAL_LOG_FORMAT(V, format), ##__VA_ARGS__) #define log_v(format, ...) log_printf(ARDUHAL_LOG_FORMAT(V, format), ##__VA_ARGS__)
#define isr_log_v(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(V, format), ##__VA_ARGS__) #define isr_log_v(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(V, format), ##__VA_ARGS__)
#else #else
#define log_v(format, ...) do {log_to_esp(TAG, ESP_LOG_VERBOSE, format, ##__VA_ARGS__);}while(0)
#define isr_log_v(format, ...) do {ets_printf(LOG_FORMAT(V, format), esp_log_timestamp(), TAG, ##__VA_ARGS__);}while(0)
#endif
#else
#define log_v(format, ...) #define log_v(format, ...)
#define isr_log_v(format, ...) #define isr_log_v(format, ...)
#endif #endif
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG
#ifndef USE_ESP_IDF_LOG
#define log_d(format, ...) log_printf(ARDUHAL_LOG_FORMAT(D, format), ##__VA_ARGS__) #define log_d(format, ...) log_printf(ARDUHAL_LOG_FORMAT(D, format), ##__VA_ARGS__)
#define isr_log_d(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(D, format), ##__VA_ARGS__) #define isr_log_d(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(D, format), ##__VA_ARGS__)
#else #else
#define log_d(format, ...) do {log_to_esp(TAG, ESP_LOG_DEBUG, format, ##__VA_ARGS__);}while(0)
#define isr_log_d(format, ...) do {ets_printf(LOG_FORMAT(D, format), esp_log_timestamp(), TAG, ##__VA_ARGS__);}while(0)
#endif
#else
#define log_d(format, ...) #define log_d(format, ...)
#define isr_log_d(format, ...) #define isr_log_d(format, ...)
#endif #endif
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
#ifndef USE_ESP_IDF_LOG
#define log_i(format, ...) log_printf(ARDUHAL_LOG_FORMAT(I, format), ##__VA_ARGS__) #define log_i(format, ...) log_printf(ARDUHAL_LOG_FORMAT(I, format), ##__VA_ARGS__)
#define isr_log_i(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(I, format), ##__VA_ARGS__) #define isr_log_i(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(I, format), ##__VA_ARGS__)
#else #else
#define log_i(format, ...) do {log_to_esp(TAG, ESP_LOG_INFO, format, ##__VA_ARGS__);}while(0)
#define isr_log_i(format, ...) do {ets_printf(LOG_FORMAT(I, format), esp_log_timestamp(), TAG, ##__VA_ARGS__);}while(0)
#endif
#else
#define log_i(format, ...) #define log_i(format, ...)
#define isr_log_i(format, ...) #define isr_log_i(format, ...)
#endif #endif
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_WARN #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_WARN
#ifndef USE_ESP_IDF_LOG
#define log_w(format, ...) log_printf(ARDUHAL_LOG_FORMAT(W, format), ##__VA_ARGS__) #define log_w(format, ...) log_printf(ARDUHAL_LOG_FORMAT(W, format), ##__VA_ARGS__)
#define isr_log_w(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(W, format), ##__VA_ARGS__) #define isr_log_w(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(W, format), ##__VA_ARGS__)
#else #else
#define log_w(format, ...) do {log_to_esp(TAG, ESP_LOG_WARN, format, ##__VA_ARGS__);}while(0)
#define isr_log_w(format, ...) do {ets_printf(LOG_FORMAT(W, format), esp_log_timestamp(), TAG, ##__VA_ARGS__);}while(0)
#endif
#else
#define log_w(format, ...) #define log_w(format, ...)
#define isr_log_w(format, ...) #define isr_log_w(format, ...)
#endif #endif
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR
#ifndef USE_ESP_IDF_LOG
#define log_e(format, ...) log_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__) #define log_e(format, ...) log_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
#define isr_log_e(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__) #define isr_log_e(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
#else #else
#define log_e(format, ...) do {log_to_esp(TAG, ESP_LOG_ERROR, format, ##__VA_ARGS__);}while(0)
#define isr_log_e(format, ...) do {ets_printf(LOG_FORMAT(E, format), esp_log_timestamp(), TAG, ##__VA_ARGS__);}while(0)
#endif
#else
#define log_e(format, ...) #define log_e(format, ...)
#define isr_log_e(format, ...) #define isr_log_e(format, ...)
#endif #endif
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_NONE #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_NONE
#ifndef USE_ESP_IDF_LOG
#define log_n(format, ...) log_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__) #define log_n(format, ...) log_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
#define isr_log_n(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__) #define isr_log_n(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
#else #else
#define log_n(format, ...) do {log_to_esp(TAG, ESP_LOG_ERROR, format, ##__VA_ARGS__);}while(0)
#define isr_log_n(format, ...) do {ets_printf(LOG_FORMAT(E, format), esp_log_timestamp(), TAG, ##__VA_ARGS__);}while(0)
#endif
#else
#define log_n(format, ...) #define log_n(format, ...)
#define isr_log_n(format, ...) #define isr_log_n(format, ...)
#endif #endif
#include "esp_log.h" #include "esp_log.h"
#ifdef USE_ESP_IDF_LOG
#ifndef TAG
#define TAG "ARDUINO"
#endif
void log_to_esp(char* tag, esp_log_level_t level, const char* format, ...);
//#define log_n(format, ...) myLog(ESP_LOG_NONE, format, ##__VA_ARGS__)
#else
#ifdef CONFIG_ARDUHAL_ESP_LOG #ifdef CONFIG_ARDUHAL_ESP_LOG
#undef ESP_LOGE #undef ESP_LOGE
#undef ESP_LOGW #undef ESP_LOGW
@ -150,6 +192,7 @@ int log_printf(const char *fmt, ...);
#define ESP_EARLY_LOGD(tag, ...) isr_log_d(__VA_ARGS__) #define ESP_EARLY_LOGD(tag, ...) isr_log_d(__VA_ARGS__)
#define ESP_EARLY_LOGV(tag, ...) isr_log_v(__VA_ARGS__) #define ESP_EARLY_LOGV(tag, ...) isr_log_v(__VA_ARGS__)
#endif #endif
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -241,7 +241,6 @@ bool rmtLoop(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
return false; return false;
} }
int channel = rmt->channel;
int allocated_size = MAX_DATA_PER_CHANNEL * rmt->buffers; int allocated_size = MAX_DATA_PER_CHANNEL * rmt->buffers;
if (size > allocated_size) { if (size > allocated_size) {

View File

@ -402,9 +402,9 @@ void spiStopBus(spi_t * spi)
if(!spi) { if(!spi) {
return; return;
} }
removeApbChangeCallback(spi, _on_apb_change); removeApbChangeCallback(spi, _on_apb_change);
SPI_MUTEX_LOCK(); SPI_MUTEX_LOCK();
spiInitBus(spi); spiInitBus(spi);
SPI_MUTEX_UNLOCK(); SPI_MUTEX_UNLOCK();
@ -428,14 +428,14 @@ spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_
#endif #endif
if(spi_num == HSPI) { if(spi_num == HSPI) {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN); DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST);
} else if(spi_num == VSPI) { } else if(spi_num == VSPI) {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_2); DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_2); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST);
} else { } else {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_1); DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_1); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST);
} }
SPI_MUTEX_LOCK(); SPI_MUTEX_LOCK();
@ -914,8 +914,20 @@ void spiTransferBytesNL(spi_t * spi, const void * data_in, uint8_t * data_out, u
spi->dev->cmd.usr = 1; spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr); while(spi->dev->cmd.usr);
if(result){ if(result){
for (int i=0; i<c_longs; i++) { if(c_len & 3){
result[i] = spi->dev->data_buf[i]; for (int i=0; i<(c_longs-1); i++) {
result[i] = spi->dev->data_buf[i];
}
uint32_t last_data = spi->dev->data_buf[c_longs-1];
uint8_t * last_out8 = &result[c_longs-1];
uint8_t * last_data8 = &last_data;
for (int i=0; i<(c_len & 3); i++) {
last_out8[i] = last_data8[i];
}
} else {
for (int i=0; i<c_longs; i++) {
result[i] = spi->dev->data_buf[i];
}
} }
} }
if(data){ if(data){

View File

@ -90,56 +90,56 @@ void IRAM_ATTR __timerISR(void * arg){
} }
} }
uint64_t timerRead(hw_timer_t *timer){ uint64_t IRAM_ATTR timerRead(hw_timer_t *timer){
timer->dev->update = 1; timer->dev->update = 1;
uint64_t h = timer->dev->cnt_high; uint64_t h = timer->dev->cnt_high;
uint64_t l = timer->dev->cnt_low; uint64_t l = timer->dev->cnt_low;
return (h << 32) | l; return (h << 32) | l;
} }
uint64_t timerAlarmRead(hw_timer_t *timer){ uint64_t IRAM_ATTR timerAlarmRead(hw_timer_t *timer){
uint64_t h = timer->dev->alarm_high; uint64_t h = timer->dev->alarm_high;
uint64_t l = timer->dev->alarm_low; uint64_t l = timer->dev->alarm_low;
return (h << 32) | l; return (h << 32) | l;
} }
void timerWrite(hw_timer_t *timer, uint64_t val){ void IRAM_ATTR timerWrite(hw_timer_t *timer, uint64_t val){
timer->dev->load_high = (uint32_t) (val >> 32); timer->dev->load_high = (uint32_t) (val >> 32);
timer->dev->load_low = (uint32_t) (val); timer->dev->load_low = (uint32_t) (val);
timer->dev->reload = 1; timer->dev->reload = 1;
} }
void timerAlarmWrite(hw_timer_t *timer, uint64_t alarm_value, bool autoreload){ void IRAM_ATTR timerAlarmWrite(hw_timer_t *timer, uint64_t alarm_value, bool autoreload){
timer->dev->alarm_high = (uint32_t) (alarm_value >> 32); timer->dev->alarm_high = (uint32_t) (alarm_value >> 32);
timer->dev->alarm_low = (uint32_t) alarm_value; timer->dev->alarm_low = (uint32_t) alarm_value;
timer->dev->config.autoreload = autoreload; timer->dev->config.autoreload = autoreload;
} }
void timerSetConfig(hw_timer_t *timer, uint32_t config){ void IRAM_ATTR timerSetConfig(hw_timer_t *timer, uint32_t config){
timer->dev->config.val = config; timer->dev->config.val = config;
} }
uint32_t timerGetConfig(hw_timer_t *timer){ uint32_t IRAM_ATTR timerGetConfig(hw_timer_t *timer){
return timer->dev->config.val; return timer->dev->config.val;
} }
void timerSetCountUp(hw_timer_t *timer, bool countUp){ void IRAM_ATTR timerSetCountUp(hw_timer_t *timer, bool countUp){
timer->dev->config.increase = countUp; timer->dev->config.increase = countUp;
} }
bool timerGetCountUp(hw_timer_t *timer){ bool IRAM_ATTR timerGetCountUp(hw_timer_t *timer){
return timer->dev->config.increase; return timer->dev->config.increase;
} }
void timerSetAutoReload(hw_timer_t *timer, bool autoreload){ void IRAM_ATTR timerSetAutoReload(hw_timer_t *timer, bool autoreload){
timer->dev->config.autoreload = autoreload; timer->dev->config.autoreload = autoreload;
} }
bool timerGetAutoReload(hw_timer_t *timer){ bool IRAM_ATTR timerGetAutoReload(hw_timer_t *timer){
return timer->dev->config.autoreload; return timer->dev->config.autoreload;
} }
void timerSetDivider(hw_timer_t *timer, uint16_t divider){//2 to 65536 void IRAM_ATTR timerSetDivider(hw_timer_t *timer, uint16_t divider){//2 to 65536
if(!divider){ if(!divider){
divider = 0xFFFF; divider = 0xFFFF;
} else if(divider == 1){ } else if(divider == 1){
@ -151,41 +151,41 @@ void timerSetDivider(hw_timer_t *timer, uint16_t divider){//2 to 65536
timer->dev->config.enable = timer_en; timer->dev->config.enable = timer_en;
} }
uint16_t timerGetDivider(hw_timer_t *timer){ uint16_t IRAM_ATTR timerGetDivider(hw_timer_t *timer){
return timer->dev->config.divider; return timer->dev->config.divider;
} }
void timerStart(hw_timer_t *timer){ void IRAM_ATTR timerStart(hw_timer_t *timer){
timer->dev->config.enable = 1; timer->dev->config.enable = 1;
} }
void timerStop(hw_timer_t *timer){ void IRAM_ATTR timerStop(hw_timer_t *timer){
timer->dev->config.enable = 0; timer->dev->config.enable = 0;
} }
void timerRestart(hw_timer_t *timer){ void IRAM_ATTR timerRestart(hw_timer_t *timer){
timer->dev->config.enable = 0; timer->dev->config.enable = 0;
timer->dev->reload = 1; timer->dev->reload = 1;
timer->dev->config.enable = 1; timer->dev->config.enable = 1;
} }
bool timerStarted(hw_timer_t *timer){ bool IRAM_ATTR timerStarted(hw_timer_t *timer){
return timer->dev->config.enable; return timer->dev->config.enable;
} }
void timerAlarmEnable(hw_timer_t *timer){ void IRAM_ATTR timerAlarmEnable(hw_timer_t *timer){
timer->dev->config.alarm_en = 1; timer->dev->config.alarm_en = 1;
} }
void timerAlarmDisable(hw_timer_t *timer){ void IRAM_ATTR timerAlarmDisable(hw_timer_t *timer){
timer->dev->config.alarm_en = 0; timer->dev->config.alarm_en = 0;
} }
bool timerAlarmEnabled(hw_timer_t *timer){ bool IRAM_ATTR timerAlarmEnabled(hw_timer_t *timer){
return timer->dev->config.alarm_en; return timer->dev->config.alarm_en;
} }
static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb){ static void IRAM_ATTR _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb){
hw_timer_t * timer = (hw_timer_t *)arg; hw_timer_t * timer = (hw_timer_t *)arg;
if(ev_type == APB_BEFORE_CHANGE){ if(ev_type == APB_BEFORE_CHANGE){
timer->dev->config.enable = 0; timer->dev->config.enable = 0;
@ -197,7 +197,7 @@ static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb
} }
} }
hw_timer_t * timerBegin(uint8_t num, uint16_t divider, bool countUp){ hw_timer_t * IRAM_ATTR timerBegin(uint8_t num, uint16_t divider, bool countUp){
if(num > 3){ if(num > 3){
return NULL; return NULL;
} }
@ -222,13 +222,13 @@ hw_timer_t * timerBegin(uint8_t num, uint16_t divider, bool countUp){
return timer; return timer;
} }
void timerEnd(hw_timer_t *timer){ void IRAM_ATTR timerEnd(hw_timer_t *timer){
timer->dev->config.enable = 0; timer->dev->config.enable = 0;
timerAttachInterrupt(timer, NULL, false); timerAttachInterrupt(timer, NULL, false);
removeApbChangeCallback(timer, _on_apb_change); removeApbChangeCallback(timer, _on_apb_change);
} }
void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){ void IRAM_ATTR timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){
static bool initialized = false; static bool initialized = false;
static intr_handle_t intr_handle = NULL; static intr_handle_t intr_handle = NULL;
if(intr_handle){ if(intr_handle){
@ -279,29 +279,29 @@ void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){
} }
} }
void timerDetachInterrupt(hw_timer_t *timer){ void IRAM_ATTR timerDetachInterrupt(hw_timer_t *timer){
timerAttachInterrupt(timer, NULL, false); timerAttachInterrupt(timer, NULL, false);
} }
uint64_t timerReadMicros(hw_timer_t *timer){ uint64_t IRAM_ATTR timerReadMicros(hw_timer_t *timer){
uint64_t timer_val = timerRead(timer); uint64_t timer_val = timerRead(timer);
uint16_t div = timerGetDivider(timer); uint16_t div = timerGetDivider(timer);
return timer_val * div / (getApbFrequency() / 1000000); return timer_val * div / (getApbFrequency() / 1000000);
} }
double timerReadSeconds(hw_timer_t *timer){ double IRAM_ATTR timerReadSeconds(hw_timer_t *timer){
uint64_t timer_val = timerRead(timer); uint64_t timer_val = timerRead(timer);
uint16_t div = timerGetDivider(timer); uint16_t div = timerGetDivider(timer);
return (double)timer_val * div / getApbFrequency(); return (double)timer_val * div / getApbFrequency();
} }
uint64_t timerAlarmReadMicros(hw_timer_t *timer){ uint64_t IRAM_ATTR timerAlarmReadMicros(hw_timer_t *timer){
uint64_t timer_val = timerAlarmRead(timer); uint64_t timer_val = timerAlarmRead(timer);
uint16_t div = timerGetDivider(timer); uint16_t div = timerGetDivider(timer);
return timer_val * div / (getApbFrequency() / 1000000); return timer_val * div / (getApbFrequency() / 1000000);
} }
double timerAlarmReadSeconds(hw_timer_t *timer){ double IRAM_ATTR timerAlarmReadSeconds(hw_timer_t *timer){
uint64_t timer_val = timerAlarmRead(timer); uint64_t timer_val = timerAlarmRead(timer);
uint16_t div = timerGetDivider(timer); uint16_t div = timerGetDivider(timer);
return (double)timer_val * div / getApbFrequency(); return (double)timer_val * div / getApbFrequency();

View File

@ -3,6 +3,10 @@
#include "esp_task_wdt.h" #include "esp_task_wdt.h"
#include "Arduino.h" #include "Arduino.h"
#ifndef CONFIG_ARDUINO_LOOP_STACK_SIZE
#define CONFIG_ARDUINO_LOOP_STACK_SIZE 8192
#endif
TaskHandle_t loopTaskHandle = NULL; TaskHandle_t loopTaskHandle = NULL;
#if CONFIG_AUTOSTART_ARDUINO #if CONFIG_AUTOSTART_ARDUINO
@ -25,7 +29,7 @@ extern "C" void app_main()
{ {
loopTaskWDTEnabled = false; loopTaskWDTEnabled = false;
initArduino(); initArduino();
xTaskCreateUniversal(loopTask, "loopTask", 8192, NULL, 1, &loopTaskHandle, CONFIG_ARDUINO_RUNNING_CORE); xTaskCreateUniversal(loopTask, "loopTask", CONFIG_ARDUINO_LOOP_STACK_SIZE, NULL, 1, &loopTaskHandle, CONFIG_ARDUINO_RUNNING_CORE);
} }
#endif #endif

View File

@ -8,8 +8,8 @@ Installation instructions for Debian / Ubuntu OS
sudo usermod -a -G dialout $USER && \ sudo usermod -a -G dialout $USER && \
sudo apt-get install git && \ sudo apt-get install git && \
wget https://bootstrap.pypa.io/get-pip.py && \ wget https://bootstrap.pypa.io/get-pip.py && \
sudo python get-pip.py && \ sudo python3 get-pip.py && \
sudo pip install pyserial && \ sudo pip3 install pyserial && \
mkdir -p ~/Arduino/hardware/espressif && \ mkdir -p ~/Arduino/hardware/espressif && \
cd ~/Arduino/hardware/espressif && \ cd ~/Arduino/hardware/espressif && \
git clone https://github.com/espressif/arduino-esp32.git esp32 && \ git clone https://github.com/espressif/arduino-esp32.git esp32 && \

View File

@ -277,6 +277,22 @@ void AsyncUDPMessage::flush()
_index = 0; _index = 0;
} }
AsyncUDPPacket::AsyncUDPPacket(AsyncUDPPacket &packet){
_udp = packet._udp;
_pb = packet._pb;
_if = packet._if;
_data = packet._data;
_len = packet._len;
_index = 0;
memcpy(&_remoteIp, &packet._remoteIp, sizeof(ip_addr_t));
memcpy(&_localIp, &packet._localIp, sizeof(ip_addr_t));
_localPort = packet._localPort;
_remotePort = packet._remotePort;
memcpy(_remoteMac, packet._remoteMac, 6);
pbuf_ref(_pb);
}
AsyncUDPPacket::AsyncUDPPacket(AsyncUDP *udp, pbuf *pb, const ip_addr_t *raddr, uint16_t rport, struct netif * ntif) AsyncUDPPacket::AsyncUDPPacket(AsyncUDP *udp, pbuf *pb, const ip_addr_t *raddr, uint16_t rport, struct netif * ntif)
{ {
@ -294,18 +310,18 @@ AsyncUDPPacket::AsyncUDPPacket(AsyncUDP *udp, pbuf *pb, const ip_addr_t *raddr,
_localIp.type = _remoteIp.type; _localIp.type = _remoteIp.type;
eth_hdr* eth = NULL; eth_hdr* eth = NULL;
udp_hdr* udphdr = reinterpret_cast<udp_hdr*>(_data - UDP_HLEN); udp_hdr* udphdr = (udp_hdr *)(_data - UDP_HLEN);
_localPort = ntohs(udphdr->dest); _localPort = ntohs(udphdr->dest);
_remotePort = ntohs(udphdr->src); _remotePort = ntohs(udphdr->src);
if (_remoteIp.type == IPADDR_TYPE_V4) { if (_remoteIp.type == IPADDR_TYPE_V4) {
eth = (eth_hdr *)(((uint8_t *)(pb->payload)) - UDP_HLEN - IP_HLEN - SIZEOF_ETH_HDR); eth = (eth_hdr *)(_data - UDP_HLEN - IP_HLEN - SIZEOF_ETH_HDR);
struct ip_hdr * iphdr = (struct ip_hdr *)(((uint8_t *)(pb->payload)) - UDP_HLEN - IP_HLEN); struct ip_hdr * iphdr = (struct ip_hdr *)(_data - UDP_HLEN - IP_HLEN);
_localIp.u_addr.ip4.addr = iphdr->dest.addr; _localIp.u_addr.ip4.addr = iphdr->dest.addr;
_remoteIp.u_addr.ip4.addr = iphdr->src.addr; _remoteIp.u_addr.ip4.addr = iphdr->src.addr;
} else { } else {
eth = (eth_hdr *)(((uint8_t *)(pb->payload)) - UDP_HLEN - IP6_HLEN - SIZEOF_ETH_HDR); eth = (eth_hdr *)(_data - UDP_HLEN - IP6_HLEN - SIZEOF_ETH_HDR);
struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(((uint8_t *)(pb->payload)) - UDP_HLEN - IP6_HLEN); struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(_data - UDP_HLEN - IP6_HLEN);
memcpy(&_localIp.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16); memcpy(&_localIp.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16);
memcpy(&_remoteIp.u_addr.ip6.addr, (uint8_t *)ip6hdr->src.addr, 16); memcpy(&_remoteIp.u_addr.ip6.addr, (uint8_t *)ip6hdr->src.addr, 16);
} }
@ -479,6 +495,7 @@ AsyncUDP::AsyncUDP()
{ {
_pcb = NULL; _pcb = NULL;
_connected = false; _connected = false;
_lastErr = ERR_OK;
_handler = NULL; _handler = NULL;
} }
@ -517,8 +534,8 @@ bool AsyncUDP::connect(const ip_addr_t *addr, uint16_t port)
} }
close(); close();
UDP_MUTEX_LOCK(); UDP_MUTEX_LOCK();
err_t err = _udp_connect(_pcb, addr, port); _lastErr = _udp_connect(_pcb, addr, port);
if(err != ERR_OK) { if(_lastErr != ERR_OK) {
UDP_MUTEX_UNLOCK(); UDP_MUTEX_UNLOCK();
return false; return false;
} }
@ -646,7 +663,7 @@ size_t AsyncUDP::writeTo(const uint8_t * data, size_t len, const ip_addr_t * add
if(len > CONFIG_TCP_MSS) { if(len > CONFIG_TCP_MSS) {
len = CONFIG_TCP_MSS; len = CONFIG_TCP_MSS;
} }
err_t err = ERR_OK; _lastErr = ERR_OK;
pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
if(pbt != NULL) { if(pbt != NULL) {
uint8_t* dst = reinterpret_cast<uint8_t*>(pbt->payload); uint8_t* dst = reinterpret_cast<uint8_t*>(pbt->payload);
@ -656,16 +673,16 @@ size_t AsyncUDP::writeTo(const uint8_t * data, size_t len, const ip_addr_t * add
void * nif = NULL; void * nif = NULL;
tcpip_adapter_get_netif((tcpip_adapter_if_t)tcpip_if, &nif); tcpip_adapter_get_netif((tcpip_adapter_if_t)tcpip_if, &nif);
if(!nif){ if(!nif){
err = _udp_sendto(_pcb, pbt, addr, port); _lastErr = _udp_sendto(_pcb, pbt, addr, port);
} else { } else {
err = _udp_sendto_if(_pcb, pbt, addr, port, (struct netif *)nif); _lastErr = _udp_sendto_if(_pcb, pbt, addr, port, (struct netif *)nif);
} }
} else { } else {
err = _udp_sendto(_pcb, pbt, addr, port); _lastErr = _udp_sendto(_pcb, pbt, addr, port);
} }
UDP_MUTEX_UNLOCK(); UDP_MUTEX_UNLOCK();
pbuf_free(pbt); pbuf_free(pbt);
if(err < ERR_OK) { if(_lastErr < ERR_OK) {
return 0; return 0;
} }
return len; return len;
@ -682,9 +699,8 @@ void AsyncUDP::_recv(udp_pcb *upcb, pbuf *pb, const ip_addr_t *addr, uint16_t po
if(_handler) { if(_handler) {
AsyncUDPPacket packet(this, this_pb, addr, port, netif); AsyncUDPPacket packet(this, this_pb, addr, port, netif);
_handler(packet); _handler(packet);
} else {
pbuf_free(this_pb);
} }
pbuf_free(this_pb);
} }
} }
@ -870,6 +886,10 @@ bool AsyncUDP::connected()
return _connected; return _connected;
} }
esp_err_t AsyncUDP::lastErr() {
return _lastErr;
}
void AsyncUDP::onPacket(AuPacketHandlerFunctionWithArg cb, void * arg) void AsyncUDP::onPacket(AuPacketHandlerFunctionWithArg cb, void * arg)
{ {
onPacket(std::bind(cb, arg, std::placeholders::_1)); onPacket(std::bind(cb, arg, std::placeholders::_1));

View File

@ -58,6 +58,7 @@ protected:
size_t _len; size_t _len;
size_t _index; size_t _index;
public: public:
AsyncUDPPacket(AsyncUDPPacket &packet);
AsyncUDPPacket(AsyncUDP *udp, pbuf *pb, const ip_addr_t *addr, uint16_t port, struct netif * netif); AsyncUDPPacket(AsyncUDP *udp, pbuf *pb, const ip_addr_t *addr, uint16_t port, struct netif * netif);
virtual ~AsyncUDPPacket(); virtual ~AsyncUDPPacket();
@ -95,6 +96,7 @@ protected:
udp_pcb *_pcb; udp_pcb *_pcb;
//xSemaphoreHandle _lock; //xSemaphoreHandle _lock;
bool _connected; bool _connected;
esp_err_t _lastErr;
AuPacketHandlerFunction _handler; AuPacketHandlerFunction _handler;
bool _init(); bool _init();
@ -144,6 +146,7 @@ public:
IPAddress listenIP(); IPAddress listenIP();
IPv6Address listenIPv6(); IPv6Address listenIPv6();
bool connected(); bool connected();
esp_err_t lastErr();
operator bool(); operator bool();
static void _s_recv(void *arg, udp_pcb *upcb, pbuf *p, const ip_addr_t *addr, uint16_t port, struct netif * netif); static void _s_recv(void *arg, udp_pcb *upcb, pbuf *p, const ip_addr_t *addr, uint16_t port, struct netif * netif);

View File

@ -59,14 +59,37 @@ BLEAddress::BLEAddress(std::string stringAddress) {
* @return True if the addresses are equal. * @return True if the addresses are equal.
*/ */
bool BLEAddress::equals(BLEAddress otherAddress) { bool BLEAddress::equals(BLEAddress otherAddress) {
return memcmp(otherAddress.getNative(), m_address, 6) == 0; return memcmp(otherAddress.getNative(), m_address, ESP_BD_ADDR_LEN) == 0;
} // equals } // equals
bool BLEAddress::operator==(const BLEAddress& otherAddress) const {
return memcmp(otherAddress.m_address, m_address, ESP_BD_ADDR_LEN) == 0;
}
bool BLEAddress::operator!=(const BLEAddress& otherAddress) const {
return !(*this == otherAddress);
}
bool BLEAddress::operator<(const BLEAddress& otherAddress) const {
return memcmp(otherAddress.m_address, m_address, ESP_BD_ADDR_LEN) < 0;
}
bool BLEAddress::operator<=(const BLEAddress& otherAddress) const {
return !(*this > otherAddress);
}
bool BLEAddress::operator>=(const BLEAddress& otherAddress) const {
return !(*this < otherAddress);
}
bool BLEAddress::operator>(const BLEAddress& otherAddress) const {
return memcmp(otherAddress.m_address, m_address, ESP_BD_ADDR_LEN) > 0;
}
/** /**
* @brief Return the native representation of the address. * @brief Return the native representation of the address.
* @return The native representation of the address. * @return The native representation of the address.
*/ */
esp_bd_addr_t *BLEAddress::getNative() { esp_bd_addr_t *BLEAddress::getNative() {
return &m_address; return &m_address;
} // getNative } // getNative

View File

@ -23,6 +23,12 @@ public:
BLEAddress(esp_bd_addr_t address); BLEAddress(esp_bd_addr_t address);
BLEAddress(std::string stringAddress); BLEAddress(std::string stringAddress);
bool equals(BLEAddress otherAddress); bool equals(BLEAddress otherAddress);
bool operator==(const BLEAddress& otherAddress) const;
bool operator!=(const BLEAddress& otherAddress) const;
bool operator<(const BLEAddress& otherAddress) const;
bool operator<=(const BLEAddress& otherAddress) const;
bool operator>(const BLEAddress& otherAddress) const;
bool operator>=(const BLEAddress& otherAddress) const;
esp_bd_addr_t* getNative(); esp_bd_addr_t* getNative();
std::string toString(); std::string toString();

View File

@ -25,6 +25,7 @@ BLEAdvertisedDevice::BLEAdvertisedDevice() {
m_manufacturerData = ""; m_manufacturerData = "";
m_name = ""; m_name = "";
m_rssi = -9999; m_rssi = -9999;
m_serviceUUIDs = {};
m_serviceData = {}; m_serviceData = {};
m_serviceDataUUIDs = {}; m_serviceDataUUIDs = {};
m_txPower = 0; m_txPower = 0;
@ -34,8 +35,6 @@ BLEAdvertisedDevice::BLEAdvertisedDevice() {
m_haveManufacturerData = false; m_haveManufacturerData = false;
m_haveName = false; m_haveName = false;
m_haveRSSI = false; m_haveRSSI = false;
m_haveServiceData = false;
m_haveServiceUUID = false;
m_haveTXPower = false; m_haveTXPower = false;
} // BLEAdvertisedDevice } // BLEAdvertisedDevice
@ -107,11 +106,7 @@ BLEScan* BLEAdvertisedDevice::getScan() {
* @return Number of service data discovered. * @return Number of service data discovered.
*/ */
int BLEAdvertisedDevice::getServiceDataCount() { int BLEAdvertisedDevice::getServiceDataCount() {
if (m_haveServiceData) return m_serviceData.size();
return m_serviceData.size();
else
return 0;
} //getServiceDataCount } //getServiceDataCount
/** /**
@ -119,7 +114,7 @@ int BLEAdvertisedDevice::getServiceDataCount() {
* @return The ServiceData of the advertised device. * @return The ServiceData of the advertised device.
*/ */
std::string BLEAdvertisedDevice::getServiceData() { std::string BLEAdvertisedDevice::getServiceData() {
return m_serviceData[0]; return m_serviceData.empty() ? std::string() : m_serviceData.front();
} //getServiceData } //getServiceData
/** /**
@ -130,12 +125,20 @@ std::string BLEAdvertisedDevice::getServiceData(int i) {
return m_serviceData[i]; return m_serviceData[i];
} //getServiceData } //getServiceData
/**
* @brief Get the number of service data UUIDs.
* @return Number of service data UUIDs discovered.
*/
int BLEAdvertisedDevice::getServiceDataUUIDCount() {
return m_serviceDataUUIDs.size();
} //getServiceDataUUIDCount
/** /**
* @brief Get the service data UUID. * @brief Get the service data UUID.
* @return The service data UUID. * @return The service data UUID.
*/ */
BLEUUID BLEAdvertisedDevice::getServiceDataUUID() { BLEUUID BLEAdvertisedDevice::getServiceDataUUID() {
return m_serviceDataUUIDs[0]; return m_serviceDataUUIDs.empty() ? BLEUUID() : m_serviceDataUUIDs.front();
} // getServiceDataUUID } // getServiceDataUUID
/** /**
@ -146,12 +149,20 @@ BLEUUID BLEAdvertisedDevice::getServiceDataUUID(int i) {
return m_serviceDataUUIDs[i]; return m_serviceDataUUIDs[i];
} // getServiceDataUUID } // getServiceDataUUID
/**
* @brief Get the number of service UUIDs.
* @return Number of service UUIDs discovered.
*/
int BLEAdvertisedDevice::getServiceUUIDCount() {
return m_serviceUUIDs.size();
} //getServiceUUIDCount
/** /**
* @brief Get the Service UUID. * @brief Get the Service UUID.
* @return The Service UUID of the advertised device. * @return The Service UUID of the advertised device.
*/ */
BLEUUID BLEAdvertisedDevice::getServiceUUID() { BLEUUID BLEAdvertisedDevice::getServiceUUID() {
return m_serviceUUIDs[0]; return m_serviceUUIDs.empty() ? BLEUUID() : m_serviceUUIDs.front();
} // getServiceUUID } // getServiceUUID
/** /**
@ -167,7 +178,7 @@ BLEUUID BLEAdvertisedDevice::getServiceUUID(int i) {
* @return Return true if service is advertised * @return Return true if service is advertised
*/ */
bool BLEAdvertisedDevice::isAdvertisingService(BLEUUID uuid){ bool BLEAdvertisedDevice::isAdvertisingService(BLEUUID uuid){
for (int i = 0; i < m_serviceUUIDs.size(); i++) { for (int i = 0; i < getServiceUUIDCount(); i++) {
if (m_serviceUUIDs[i].equals(uuid)) return true; if (m_serviceUUIDs[i].equals(uuid)) return true;
} }
return false; return false;
@ -224,7 +235,7 @@ bool BLEAdvertisedDevice::haveRSSI() {
* @return True if there is a service data value present. * @return True if there is a service data value present.
*/ */
bool BLEAdvertisedDevice::haveServiceData() { bool BLEAdvertisedDevice::haveServiceData() {
return m_haveServiceData; return !m_serviceData.empty();
} // haveServiceData } // haveServiceData
@ -233,7 +244,7 @@ bool BLEAdvertisedDevice::haveServiceData() {
* @return True if there is a service UUID value present. * @return True if there is a service UUID value present.
*/ */
bool BLEAdvertisedDevice::haveServiceUUID() { bool BLEAdvertisedDevice::haveServiceUUID() {
return m_haveServiceUUID; return !m_serviceUUIDs.empty();
} // haveServiceUUID } // haveServiceUUID
@ -486,7 +497,6 @@ void BLEAdvertisedDevice::setServiceUUID(const char* serviceUUID) {
*/ */
void BLEAdvertisedDevice::setServiceUUID(BLEUUID serviceUUID) { void BLEAdvertisedDevice::setServiceUUID(BLEUUID serviceUUID) {
m_serviceUUIDs.push_back(serviceUUID); m_serviceUUIDs.push_back(serviceUUID);
m_haveServiceUUID = true;
log_d("- addServiceUUID(): serviceUUID: %s", serviceUUID.toString().c_str()); log_d("- addServiceUUID(): serviceUUID: %s", serviceUUID.toString().c_str());
} // setServiceUUID } // setServiceUUID
@ -496,7 +506,6 @@ void BLEAdvertisedDevice::setServiceUUID(BLEUUID serviceUUID) {
* @param [in] data ServiceData value. * @param [in] data ServiceData value.
*/ */
void BLEAdvertisedDevice::setServiceData(std::string serviceData) { void BLEAdvertisedDevice::setServiceData(std::string serviceData) {
m_haveServiceData = true; // Set the flag that indicates we have service data.
m_serviceData.push_back(serviceData); // Save the service data that we received. m_serviceData.push_back(serviceData); // Save the service data that we received.
} //setServiceData } //setServiceData
@ -506,7 +515,6 @@ void BLEAdvertisedDevice::setServiceData(std::string serviceData) {
* @param [in] data ServiceDataUUID value. * @param [in] data ServiceDataUUID value.
*/ */
void BLEAdvertisedDevice::setServiceDataUUID(BLEUUID uuid) { void BLEAdvertisedDevice::setServiceDataUUID(BLEUUID uuid) {
m_haveServiceData = true; // Set the flag that indicates we have service data.
m_serviceDataUUIDs.push_back(uuid); m_serviceDataUUIDs.push_back(uuid);
log_d("- addServiceDataUUID(): serviceDataUUID: %s", uuid.toString().c_str()); log_d("- addServiceDataUUID(): serviceDataUUID: %s", uuid.toString().c_str());
} // setServiceDataUUID } // setServiceDataUUID
@ -542,7 +550,7 @@ std::string BLEAdvertisedDevice::toString() {
free(pHex); free(pHex);
} }
if (haveServiceUUID()) { if (haveServiceUUID()) {
for (int i=0; i < m_serviceUUIDs.size(); i++) { for (int i=0; i < getServiceUUIDCount(); i++) {
res += ", serviceUUID: " + getServiceUUID(i).toString(); res += ", serviceUUID: " + getServiceUUID(i).toString();
} }
} }

View File

@ -42,6 +42,8 @@ public:
BLEUUID getServiceUUID(); BLEUUID getServiceUUID();
BLEUUID getServiceUUID(int i); BLEUUID getServiceUUID(int i);
int getServiceDataCount(); int getServiceDataCount();
int getServiceDataUUIDCount();
int getServiceUUIDCount();
int8_t getTXPower(); int8_t getTXPower();
uint8_t* getPayload(); uint8_t* getPayload();
size_t getPayloadLength(); size_t getPayloadLength();
@ -83,8 +85,6 @@ private:
bool m_haveManufacturerData; bool m_haveManufacturerData;
bool m_haveName; bool m_haveName;
bool m_haveRSSI; bool m_haveRSSI;
bool m_haveServiceData;
bool m_haveServiceUUID;
bool m_haveTXPower; bool m_haveTXPower;

View File

@ -91,6 +91,10 @@ void BLEAdvertising::setAdvertisementType(esp_ble_adv_type_t adv_type){
m_advParams.adv_type = adv_type; m_advParams.adv_type = adv_type;
} // setAdvertisementType } // setAdvertisementType
void BLEAdvertising::setAdvertisementChannelMap(esp_ble_adv_channel_t channel_map) {
m_advParams.channel_map = channel_map;
} // setAdvertisementChannelMap
void BLEAdvertising::setMinInterval(uint16_t mininterval) { void BLEAdvertising::setMinInterval(uint16_t mininterval) {
m_advParams.adv_int_min = mininterval; m_advParams.adv_int_min = mininterval;
} // setMinInterval } // setMinInterval

View File

@ -53,6 +53,7 @@ public:
void stop(); void stop();
void setAppearance(uint16_t appearance); void setAppearance(uint16_t appearance);
void setAdvertisementType(esp_ble_adv_type_t adv_type); void setAdvertisementType(esp_ble_adv_type_t adv_type);
void setAdvertisementChannelMap(esp_ble_adv_channel_t channel_map);
void setMaxInterval(uint16_t maxinterval); void setMaxInterval(uint16_t maxinterval);
void setMinInterval(uint16_t mininterval); void setMinInterval(uint16_t mininterval);
void setAdvertisementData(BLEAdvertisementData& advertisementData); void setAdvertisementData(BLEAdvertisementData& advertisementData);

View File

@ -60,6 +60,7 @@ BLEClient::~BLEClient() {
delete myPair.second; delete myPair.second;
} }
m_servicesMap.clear(); m_servicesMap.clear();
m_servicesMapByInstID.clear();
} // ~BLEClient } // ~BLEClient
@ -109,7 +110,17 @@ bool BLEClient::connect(BLEAddress address, esp_ble_addr_type_t type) {
return false; return false;
} }
m_semaphoreRegEvt.wait("connect"); uint32_t rc = m_semaphoreRegEvt.wait("connect");
if (rc != ESP_GATT_OK) {
// fixes ESP_GATT_NO_RESOURCES error mostly
log_e("esp_ble_gattc_app_register_error: rc=%d", rc);
BLEDevice::removePeerDevice(m_appId, true);
// not sure if this is needed here
// esp_ble_gattc_app_unregister(m_gattc_if);
// m_gattc_if = ESP_GATT_IF_NONE;
return false;
}
m_peerAddress = address; m_peerAddress = address;
@ -127,7 +138,13 @@ bool BLEClient::connect(BLEAddress address, esp_ble_addr_type_t type) {
return false; return false;
} }
uint32_t rc = m_semaphoreOpenEvt.wait("connect"); // Wait for the connection to complete. rc = m_semaphoreOpenEvt.wait("connect"); // Wait for the connection to complete.
// check the status of the connection and cleanup in case of failure
if (rc != ESP_GATT_OK) {
BLEDevice::removePeerDevice(m_appId, true);
esp_ble_gattc_app_unregister(m_gattc_if);
m_gattc_if = ESP_GATT_IF_NONE;
}
log_v("<< connect(), rc=%d", rc==ESP_GATT_OK); log_v("<< connect(), rc=%d", rc==ESP_GATT_OK);
return rc == ESP_GATT_OK; return rc == ESP_GATT_OK;
} // connect } // connect
@ -159,6 +176,11 @@ void BLEClient::gattClientEventHandler(
log_d("gattClientEventHandler [esp_gatt_if: %d] ... %s", log_d("gattClientEventHandler [esp_gatt_if: %d] ... %s",
gattc_if, BLEUtils::gattClientEventTypeToString(event).c_str()); gattc_if, BLEUtils::gattClientEventTypeToString(event).c_str());
// it is possible to receive events from other connections while waiting for registration
if (m_gattc_if == ESP_GATT_IF_NONE && event != ESP_GATTC_REG_EVT) {
return;
}
// Execute handler code based on the type of event received. // Execute handler code based on the type of event received.
switch(event) { switch(event) {
@ -183,15 +205,17 @@ void BLEClient::gattClientEventHandler(
if (evtParam->disconnect.conn_id != getConnId()) break; if (evtParam->disconnect.conn_id != getConnId()) break;
// If we receive a disconnect event, set the class flag that indicates that we are // If we receive a disconnect event, set the class flag that indicates that we are
// no longer connected. // no longer connected.
if (m_isConnected && m_pClientCallbacks != nullptr) { bool m_wasConnected = m_isConnected;
m_pClientCallbacks->onDisconnect(this);
}
m_isConnected = false; m_isConnected = false;
esp_ble_gattc_app_unregister(m_gattc_if); esp_ble_gattc_app_unregister(m_gattc_if);
m_gattc_if = ESP_GATT_IF_NONE;
m_semaphoreOpenEvt.give(ESP_GATT_IF_NONE); m_semaphoreOpenEvt.give(ESP_GATT_IF_NONE);
m_semaphoreRssiCmplEvt.give(); m_semaphoreRssiCmplEvt.give();
m_semaphoreSearchCmplEvt.give(1); m_semaphoreSearchCmplEvt.give(1);
BLEDevice::removePeerDevice(m_appId, true); BLEDevice::removePeerDevice(m_appId, true);
if (m_wasConnected && m_pClientCallbacks != nullptr) {
m_pClientCallbacks->onDisconnect(this);
}
break; break;
} // ESP_GATTC_DISCONNECT_EVT } // ESP_GATTC_DISCONNECT_EVT
@ -227,7 +251,8 @@ void BLEClient::gattClientEventHandler(
// //
case ESP_GATTC_REG_EVT: { case ESP_GATTC_REG_EVT: {
m_gattc_if = gattc_if; m_gattc_if = gattc_if;
m_semaphoreRegEvt.give(); // pass on the registration status result, in case of failure
m_semaphoreRegEvt.give(evtParam->reg.status);
break; break;
} // ESP_GATTC_REG_EVT } // ESP_GATTC_REG_EVT

View File

@ -52,6 +52,7 @@ BLERemoteCharacteristic::BLERemoteCharacteristic(
*/ */
BLERemoteCharacteristic::~BLERemoteCharacteristic() { BLERemoteCharacteristic::~BLERemoteCharacteristic() {
removeDescriptors(); // Release resources for any descriptor information we may have allocated. removeDescriptors(); // Release resources for any descriptor information we may have allocated.
free(m_rawData);
} // ~BLERemoteCharacteristic } // ~BLERemoteCharacteristic
@ -245,6 +246,10 @@ void BLERemoteCharacteristic::gattClientEventHandler(esp_gattc_cb_event_t event,
} }
break; break;
case ESP_GATTC_DISCONNECT_EVT:
m_semaphoreWriteCharEvt.give(1);
break;
default: default:
break; break;
} // End switch } // End switch
@ -453,7 +458,7 @@ std::string BLERemoteCharacteristic::readValue() {
* unregistering a notification. * unregistering a notification.
* @return N/A. * @return N/A.
*/ */
void BLERemoteCharacteristic::registerForNotify(notify_callback notifyCallback, bool notifications) { void BLERemoteCharacteristic::registerForNotify(notify_callback notifyCallback, bool notifications, bool descriptorRequiresRegistration) {
log_v(">> registerForNotify(): %s", toString().c_str()); log_v(">> registerForNotify(): %s", toString().c_str());
m_notifyCallback = notifyCallback; // Save the notification callback. m_notifyCallback = notifyCallback; // Save the notification callback.
@ -474,7 +479,7 @@ void BLERemoteCharacteristic::registerForNotify(notify_callback notifyCallback,
uint8_t val[] = {0x01, 0x00}; uint8_t val[] = {0x01, 0x00};
if(!notifications) val[0] = 0x02; if(!notifications) val[0] = 0x02;
BLERemoteDescriptor* desc = getDescriptor(BLEUUID((uint16_t)0x2902)); BLERemoteDescriptor* desc = getDescriptor(BLEUUID((uint16_t)0x2902));
if (desc != nullptr) if (desc != nullptr && descriptorRequiresRegistration)
desc->writeValue(val, 2, true); desc->writeValue(val, 2, true);
} // End Register } // End Register
else { // If we weren't passed a callback function, then this is an unregistration. else { // If we weren't passed a callback function, then this is an unregistration.
@ -490,7 +495,7 @@ void BLERemoteCharacteristic::registerForNotify(notify_callback notifyCallback,
uint8_t val[] = {0x00, 0x00}; uint8_t val[] = {0x00, 0x00};
BLERemoteDescriptor* desc = getDescriptor((uint16_t)0x2902); BLERemoteDescriptor* desc = getDescriptor((uint16_t)0x2902);
if (desc != nullptr) if (desc != nullptr && descriptorRequiresRegistration)
desc->writeValue(val, 2, true); desc->writeValue(val, 2, true);
} // End Unregister } // End Unregister

View File

@ -11,6 +11,7 @@
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include <string> #include <string>
#include <functional>
#include <esp_gattc_api.h> #include <esp_gattc_api.h>
@ -21,8 +22,7 @@
class BLERemoteService; class BLERemoteService;
class BLERemoteDescriptor; class BLERemoteDescriptor;
typedef void (*notify_callback)(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify); typedef std::function<void(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify)> notify_callback;
/** /**
* @brief A model of a remote %BLE characteristic. * @brief A model of a remote %BLE characteristic.
*/ */
@ -39,6 +39,7 @@ public:
bool canWriteNoResponse(); bool canWriteNoResponse();
BLERemoteDescriptor* getDescriptor(BLEUUID uuid); BLERemoteDescriptor* getDescriptor(BLEUUID uuid);
std::map<std::string, BLERemoteDescriptor*>* getDescriptors(); std::map<std::string, BLERemoteDescriptor*>* getDescriptors();
BLERemoteService* getRemoteService();
uint16_t getHandle(); uint16_t getHandle();
BLEUUID getUUID(); BLEUUID getUUID();
std::string readValue(); std::string readValue();
@ -46,7 +47,7 @@ public:
uint16_t readUInt16(); uint16_t readUInt16();
uint32_t readUInt32(); uint32_t readUInt32();
float readFloat(); float readFloat();
void registerForNotify(notify_callback _callback, bool notifications = true); void registerForNotify(notify_callback _callback, bool notifications = true, bool descriptorRequiresRegistration = true);
void writeValue(uint8_t* data, size_t length, bool response = false); void writeValue(uint8_t* data, size_t length, bool response = false);
void writeValue(std::string newValue, bool response = false); void writeValue(std::string newValue, bool response = false);
void writeValue(uint8_t newValue, bool response = false); void writeValue(uint8_t newValue, bool response = false);
@ -63,7 +64,6 @@ private:
// Private member functions // Private member functions
void gattClientEventHandler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* evtParam); void gattClientEventHandler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* evtParam);
BLERemoteService* getRemoteService();
void removeDescriptors(); void removeDescriptors();
void retrieveDescriptors(); void retrieveDescriptors();

View File

@ -245,6 +245,7 @@ std::map<uint16_t, BLERemoteCharacteristic*>* BLERemoteService::getCharacteristi
*/ */
void BLERemoteService::getCharacteristics(std::map<uint16_t, BLERemoteCharacteristic*>* pCharacteristicMap) { void BLERemoteService::getCharacteristics(std::map<uint16_t, BLERemoteCharacteristic*>* pCharacteristicMap) {
log_v(">> getCharacteristics() for service: %s", getUUID().toString().c_str()); log_v(">> getCharacteristics() for service: %s", getUUID().toString().c_str());
(void)pCharacteristicMap;
// If is possible that we have not read the characteristics associated with the service so do that // If is possible that we have not read the characteristics associated with the service so do that
// now. The request to retrieve the characteristics by calling "retrieveCharacteristics" is a blocking // now. The request to retrieve the characteristics by calling "retrieveCharacteristics" is a blocking
// call and does not return until all the characteristics are available. // call and does not return until all the characteristics are available.

View File

@ -0,0 +1,75 @@
//This example code is in the Public Domain (or CC0 licensed, at your option.)
//By Richard Li - 2020
//
//This example creates a bridge between Serial and Classical Bluetooth (SPP with authentication)
//and also demonstrate that SerialBT have the same functionalities of a normal Serial
#include "BluetoothSerial.h"
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
BluetoothSerial SerialBT;
boolean confirmRequestPending = true;
void BTConfirmRequestCallback(uint32_t numVal)
{
confirmRequestPending = true;
Serial.println(numVal);
}
void BTAuthCompleteCallback(boolean success)
{
confirmRequestPending = false;
if (success)
{
Serial.println("Pairing success!!");
}
else
{
Serial.println("Pairing failed, rejected by user!!");
}
}
void setup()
{
Serial.begin(115200);
SerialBT.enableSSP();
SerialBT.onConfirmRequest(BTConfirmRequestCallback);
SerialBT.onAuthComplete(BTAuthCompleteCallback);
SerialBT.begin("ESP32test"); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!");
}
void loop()
{
if (confirmRequestPending)
{
if (Serial.available())
{
int dat = Serial.read();
if (dat == 'Y' || dat == 'y')
{
SerialBT.confirmReply(true);
}
else
{
SerialBT.confirmReply(false);
}
}
}
else
{
if (Serial.available())
{
SerialBT.write(Serial.read());
}
if (SerialBT.available())
{
Serial.write(SerialBT.read());
}
delay(20);
}
}

View File

@ -42,6 +42,10 @@ const char * _spp_server_name = "ESP32SPP";
#define RX_QUEUE_SIZE 512 #define RX_QUEUE_SIZE 512
#define TX_QUEUE_SIZE 32 #define TX_QUEUE_SIZE 32
#define SPP_TX_QUEUE_TIMEOUT 1000
#define SPP_TX_DONE_TIMEOUT 1000
#define SPP_CONGESTED_TIMEOUT 1000
static uint32_t _spp_client = 0; static uint32_t _spp_client = 0;
static xQueueHandle _spp_rx_queue = NULL; static xQueueHandle _spp_rx_queue = NULL;
static xQueueHandle _spp_tx_queue = NULL; static xQueueHandle _spp_tx_queue = NULL;
@ -51,6 +55,9 @@ static EventGroupHandle_t _spp_event_group = NULL;
static boolean secondConnectionAttempt; static boolean secondConnectionAttempt;
static esp_spp_cb_t * custom_spp_callback = NULL; static esp_spp_cb_t * custom_spp_callback = NULL;
static BluetoothSerialDataCb custom_data_callback = NULL; static BluetoothSerialDataCb custom_data_callback = NULL;
static esp_bd_addr_t current_bd_addr;
static ConfirmRequestCb confirm_request_callback = NULL;
static AuthCompleteCb auth_complete_callback = NULL;
#define INQ_LEN 0x10 #define INQ_LEN 0x10
#define INQ_NUM_RSPS 20 #define INQ_NUM_RSPS 20
@ -140,7 +147,7 @@ static esp_err_t _spp_queue_packet(uint8_t *data, size_t len){
} }
packet->len = len; packet->len = len;
memcpy(packet->data, data, len); memcpy(packet->data, data, len);
if (xQueueSend(_spp_tx_queue, &packet, portMAX_DELAY) != pdPASS) { if (!_spp_tx_queue || xQueueSend(_spp_tx_queue, &packet, SPP_TX_QUEUE_TIMEOUT) != pdPASS) {
log_e("SPP TX Queue Send Failed!"); log_e("SPP TX Queue Send Failed!");
free(packet); free(packet);
return ESP_FAIL; return ESP_FAIL;
@ -153,19 +160,25 @@ static uint8_t _spp_tx_buffer[SPP_TX_MAX];
static uint16_t _spp_tx_buffer_len = 0; static uint16_t _spp_tx_buffer_len = 0;
static bool _spp_send_buffer(){ static bool _spp_send_buffer(){
if((xEventGroupWaitBits(_spp_event_group, SPP_CONGESTED, pdFALSE, pdTRUE, portMAX_DELAY) & SPP_CONGESTED) != 0){ if((xEventGroupWaitBits(_spp_event_group, SPP_CONGESTED, pdFALSE, pdTRUE, SPP_CONGESTED_TIMEOUT) & SPP_CONGESTED) != 0){
if(!_spp_client){
log_v("SPP Client Gone!");
return false;
}
log_v("SPP Write %u", _spp_tx_buffer_len);
esp_err_t err = esp_spp_write(_spp_client, _spp_tx_buffer_len, _spp_tx_buffer); esp_err_t err = esp_spp_write(_spp_client, _spp_tx_buffer_len, _spp_tx_buffer);
if(err != ESP_OK){ if(err != ESP_OK){
log_e("SPP Write Failed! [0x%X]", err); log_e("SPP Write Failed! [0x%X]", err);
return false; return false;
} }
_spp_tx_buffer_len = 0; _spp_tx_buffer_len = 0;
if(xSemaphoreTake(_spp_tx_done, portMAX_DELAY) != pdTRUE){ if(xSemaphoreTake(_spp_tx_done, SPP_TX_DONE_TIMEOUT) != pdTRUE){
log_e("SPP Ack Failed!"); log_e("SPP Ack Failed!");
return false; return false;
} }
return true; return true;
} }
log_e("SPP Write Congested!");
return false; return false;
} }
@ -191,13 +204,18 @@ static void _spp_tx_task(void * arg){
_spp_tx_buffer_len = SPP_TX_MAX; _spp_tx_buffer_len = SPP_TX_MAX;
data += to_send; data += to_send;
len -= to_send; len -= to_send;
_spp_send_buffer(); if(!_spp_send_buffer()){
len = 0;
}
while(len >= SPP_TX_MAX){ while(len >= SPP_TX_MAX){
memcpy(_spp_tx_buffer, data, SPP_TX_MAX); memcpy(_spp_tx_buffer, data, SPP_TX_MAX);
_spp_tx_buffer_len = SPP_TX_MAX; _spp_tx_buffer_len = SPP_TX_MAX;
data += SPP_TX_MAX; data += SPP_TX_MAX;
len -= SPP_TX_MAX; len -= SPP_TX_MAX;
_spp_send_buffer(); if(!_spp_send_buffer()){
len = 0;
break;
}
} }
if(len){ if(len){
memcpy(_spp_tx_buffer, data, len); memcpy(_spp_tx_buffer, data, len);
@ -232,26 +250,36 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
break; break;
case ESP_SPP_SRV_OPEN_EVT://Server connection open case ESP_SPP_SRV_OPEN_EVT://Server connection open
log_i("ESP_SPP_SRV_OPEN_EVT"); if (param->srv_open.status == ESP_SPP_SUCCESS) {
if (!_spp_client){ log_i("ESP_SPP_SRV_OPEN_EVT: %u", _spp_client);
_spp_client = param->open.handle; if (!_spp_client){
_spp_client = param->srv_open.handle;
_spp_tx_buffer_len = 0;
} else {
secondConnectionAttempt = true;
esp_spp_disconnect(param->srv_open.handle);
}
xEventGroupClearBits(_spp_event_group, SPP_DISCONNECTED);
xEventGroupSetBits(_spp_event_group, SPP_CONNECTED);
} else { } else {
secondConnectionAttempt = true; log_e("ESP_SPP_SRV_OPEN_EVT Failed!, status:%d", param->srv_open.status);
esp_spp_disconnect(param->open.handle);
} }
xEventGroupClearBits(_spp_event_group, SPP_DISCONNECTED);
xEventGroupSetBits(_spp_event_group, SPP_CONNECTED);
break; break;
case ESP_SPP_CLOSE_EVT://Client connection closed case ESP_SPP_CLOSE_EVT://Client connection closed
log_i("ESP_SPP_CLOSE_EVT"); if ((param->close.async == false && param->close.status == ESP_SPP_SUCCESS) || param->close.async) {
if(secondConnectionAttempt) { log_i("ESP_SPP_CLOSE_EVT: %u", secondConnectionAttempt);
secondConnectionAttempt = false; if(secondConnectionAttempt) {
secondConnectionAttempt = false;
} else {
_spp_client = 0;
xEventGroupSetBits(_spp_event_group, SPP_DISCONNECTED);
xEventGroupSetBits(_spp_event_group, SPP_CONGESTED);
}
xEventGroupClearBits(_spp_event_group, SPP_CONNECTED);
} else { } else {
_spp_client = 0; log_e("ESP_SPP_CLOSE_EVT failed!, status:%d", param->close.status);
xEventGroupSetBits(_spp_event_group, SPP_DISCONNECTED); }
}
xEventGroupClearBits(_spp_event_group, SPP_CONNECTED);
break; break;
case ESP_SPP_CONG_EVT://connection congestion status changed case ESP_SPP_CONG_EVT://connection congestion status changed
@ -264,11 +292,15 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
break; break;
case ESP_SPP_WRITE_EVT://write operation completed case ESP_SPP_WRITE_EVT://write operation completed
if(param->write.cong){ if (param->write.status == ESP_SPP_SUCCESS) {
xEventGroupClearBits(_spp_event_group, SPP_CONGESTED); if(param->write.cong){
xEventGroupClearBits(_spp_event_group, SPP_CONGESTED);
}
log_v("ESP_SPP_WRITE_EVT: %u %s", param->write.len, param->write.cong?"CONGESTED":"");
} else {
log_e("ESP_SPP_WRITE_EVT failed!, status:%d", param->write.status);
} }
xSemaphoreGive(_spp_tx_done);//we can try to send another packet xSemaphoreGive(_spp_tx_done);//we can try to send another packet
log_v("ESP_SPP_WRITE_EVT: %u %s", param->write.len, param->write.cong?"CONGESTED":"FREE");
break; break;
case ESP_SPP_DATA_IND_EVT://connection received data case ESP_SPP_DATA_IND_EVT://connection received data
@ -293,6 +325,8 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
if (param->disc_comp.status == ESP_SPP_SUCCESS) { if (param->disc_comp.status == ESP_SPP_SUCCESS) {
log_i("ESP_SPP_DISCOVERY_COMP_EVT: spp connect to remote"); log_i("ESP_SPP_DISCOVERY_COMP_EVT: spp connect to remote");
esp_spp_connect(ESP_SPP_SEC_AUTHENTICATE, ESP_SPP_ROLE_MASTER, param->disc_comp.scn[0], _peer_bd_addr); esp_spp_connect(ESP_SPP_SEC_AUTHENTICATE, ESP_SPP_ROLE_MASTER, param->disc_comp.scn[0], _peer_bd_addr);
} else {
log_e("ESP_SPP_DISCOVERY_COMP_EVT failed!, status:%d", param->disc_comp.status);
} }
break; break;
@ -306,6 +340,7 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
} }
xEventGroupClearBits(_spp_event_group, SPP_DISCONNECTED); xEventGroupClearBits(_spp_event_group, SPP_DISCONNECTED);
xEventGroupSetBits(_spp_event_group, SPP_CONNECTED); xEventGroupSetBits(_spp_event_group, SPP_CONNECTED);
xEventGroupSetBits(_spp_event_group, SPP_CONGESTED);
break; break;
case ESP_SPP_START_EVT://server started case ESP_SPP_START_EVT://server started
@ -398,8 +433,14 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa
case ESP_BT_GAP_AUTH_CMPL_EVT: case ESP_BT_GAP_AUTH_CMPL_EVT:
if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) { if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) {
log_v("authentication success: %s", param->auth_cmpl.device_name); log_v("authentication success: %s", param->auth_cmpl.device_name);
if (auth_complete_callback) {
auth_complete_callback(true);
}
} else { } else {
log_e("authentication failed, status:%d", param->auth_cmpl.stat); log_e("authentication failed, status:%d", param->auth_cmpl.stat);
if (auth_complete_callback) {
auth_complete_callback(false);
}
} }
break; break;
@ -421,7 +462,13 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa
case ESP_BT_GAP_CFM_REQ_EVT: case ESP_BT_GAP_CFM_REQ_EVT:
log_i("ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val); log_i("ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val);
esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true); if (confirm_request_callback) {
memcpy(current_bd_addr, param->cfm_req.bda, sizeof(esp_bd_addr_t));
confirm_request_callback(param->cfm_req.num_val);
}
else {
esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true);
}
break; break;
case ESP_BT_GAP_KEY_NOTIF_EVT: case ESP_BT_GAP_KEY_NOTIF_EVT:
@ -500,7 +547,9 @@ static bool _init_bt(const char *deviceName)
} }
} }
if (_isMaster && esp_bt_gap_register_callback(esp_bt_gap_cb) != ESP_OK) { // Why only master need this? Slave need this during pairing as well
// if (_isMaster && esp_bt_gap_register_callback(esp_bt_gap_cb) != ESP_OK) {
if (esp_bt_gap_register_callback(esp_bt_gap_cb) != ESP_OK) {
log_e("gap register failed"); log_e("gap register failed");
return false; return false;
} }
@ -515,9 +564,9 @@ static bool _init_bt(const char *deviceName)
return false; return false;
} }
if (esp_bt_sleep_disable() != ESP_OK){ // if (esp_bt_sleep_disable() != ESP_OK){
log_e("esp_bt_sleep_disable failed"); // log_e("esp_bt_sleep_disable failed");
} // }
log_i("device name set"); log_i("device name set");
esp_bt_dev_set_device_name(deviceName); esp_bt_dev_set_device_name(deviceName);
@ -662,7 +711,7 @@ void BluetoothSerial::flush()
{ {
if (_spp_tx_queue != NULL){ if (_spp_tx_queue != NULL){
while(uxQueueMessagesWaiting(_spp_tx_queue) > 0){ while(uxQueueMessagesWaiting(_spp_tx_queue) > 0){
delay(5); delay(100);
} }
} }
} }
@ -672,6 +721,22 @@ void BluetoothSerial::end()
_stop_bt(); _stop_bt();
} }
void BluetoothSerial::onConfirmRequest(ConfirmRequestCb cb)
{
confirm_request_callback = cb;
}
void BluetoothSerial::onAuthComplete(AuthCompleteCb cb)
{
auth_complete_callback = cb;
}
void BluetoothSerial::confirmReply(boolean confirm)
{
esp_bt_gap_ssp_confirm_reply(current_bd_addr, confirm);
}
esp_err_t BluetoothSerial::register_callback(esp_spp_cb_t * callback) esp_err_t BluetoothSerial::register_callback(esp_spp_cb_t * callback)
{ {
custom_spp_callback = callback; custom_spp_callback = callback;

View File

@ -25,6 +25,8 @@
#include <functional> #include <functional>
typedef std::function<void(const uint8_t *buffer, size_t size)> BluetoothSerialDataCb; typedef std::function<void(const uint8_t *buffer, size_t size)> BluetoothSerialDataCb;
typedef std::function<void(uint32_t num_val)> ConfirmRequestCb;
typedef std::function<void(boolean success)> AuthCompleteCb;
class BluetoothSerial: public Stream class BluetoothSerial: public Stream
{ {
@ -44,6 +46,10 @@ class BluetoothSerial: public Stream
void end(void); void end(void);
void onData(BluetoothSerialDataCb cb); void onData(BluetoothSerialDataCb cb);
esp_err_t register_callback(esp_spp_cb_t * callback); esp_err_t register_callback(esp_spp_cb_t * callback);
void onConfirmRequest(ConfirmRequestCb cb);
void onAuthComplete(AuthCompleteCb cb);
void confirmReply(boolean confirm);
void enableSSP(); void enableSSP();
bool setPin(const char *pin); bool setPin(const char *pin);

View File

@ -382,6 +382,9 @@ size_t EEPROMClass::readString (int address, char* value, size_t maxLen)
if (address + len > _size) if (address + len > _size)
return 0; return 0;
if (len > maxLen)
return 0; //Maybe return part of the string instead?
memcpy((uint8_t*) value, _data + address, len); memcpy((uint8_t*) value, _data + address, len);
value[len] = 0; value[len] = 0;
return len; return len;
@ -400,7 +403,7 @@ String EEPROMClass::readString (int address)
if (address + len > _size) if (address + len > _size)
return String(); return String();
char value[len]; char value[len+1];
memcpy((uint8_t*) value, _data + address, len); memcpy((uint8_t*) value, _data + address, len);
value[len] = 0; value[len] = 0;
return String(value); return String(value);

View File

@ -84,7 +84,7 @@ public:
void enableArduino(uint16_t port=3232, bool auth=false); void enableArduino(uint16_t port=3232, bool auth=false);
void disableArduino(); void disableArduino();
void enableWorkstation(wifi_interface_t interface=ESP_IF_WIFI_STA); void enableWorkstation(wifi_interface_t interface=WIFI_IF_STA);
void disableWorkstation(); void disableWorkstation();
IPAddress queryHost(char *host, uint32_t timeout=2000); IPAddress queryHost(char *host, uint32_t timeout=2000);

View File

@ -25,7 +25,7 @@ using namespace fs;
size_t File::write(uint8_t c) size_t File::write(uint8_t c)
{ {
if (!_p) { if (!*this) {
return 0; return 0;
} }
@ -34,7 +34,7 @@ size_t File::write(uint8_t c)
time_t File::getLastWrite() time_t File::getLastWrite()
{ {
if (!_p) { if (!*this) {
return 0; return 0;
} }
@ -43,7 +43,7 @@ time_t File::getLastWrite()
size_t File::write(const uint8_t *buf, size_t size) size_t File::write(const uint8_t *buf, size_t size)
{ {
if (!_p) { if (!*this) {
return 0; return 0;
} }
@ -52,7 +52,7 @@ size_t File::write(const uint8_t *buf, size_t size)
int File::available() int File::available()
{ {
if (!_p) { if (!*this) {
return false; return false;
} }
@ -61,7 +61,7 @@ int File::available()
int File::read() int File::read()
{ {
if (!_p) { if (!*this) {
return -1; return -1;
} }
@ -75,7 +75,7 @@ int File::read()
size_t File::read(uint8_t* buf, size_t size) size_t File::read(uint8_t* buf, size_t size)
{ {
if (!_p) { if (!*this) {
return -1; return -1;
} }
@ -84,7 +84,7 @@ size_t File::read(uint8_t* buf, size_t size)
int File::peek() int File::peek()
{ {
if (!_p) { if (!*this) {
return -1; return -1;
} }
@ -96,7 +96,7 @@ int File::peek()
void File::flush() void File::flush()
{ {
if (!_p) { if (!*this) {
return; return;
} }
@ -105,7 +105,7 @@ void File::flush()
bool File::seek(uint32_t pos, SeekMode mode) bool File::seek(uint32_t pos, SeekMode mode)
{ {
if (!_p) { if (!*this) {
return false; return false;
} }
@ -114,7 +114,7 @@ bool File::seek(uint32_t pos, SeekMode mode)
size_t File::position() const size_t File::position() const
{ {
if (!_p) { if (!*this) {
return 0; return 0;
} }
@ -123,7 +123,7 @@ size_t File::position() const
size_t File::size() const size_t File::size() const
{ {
if (!_p) { if (!*this) {
return 0; return 0;
} }
@ -140,12 +140,12 @@ void File::close()
File::operator bool() const File::operator bool() const
{ {
return !!_p; return _p != nullptr && *_p != false;
} }
const char* File::name() const const char* File::name() const
{ {
if (!_p) { if (!*this) {
return nullptr; return nullptr;
} }
@ -155,7 +155,7 @@ const char* File::name() const
//to implement //to implement
boolean File::isDirectory(void) boolean File::isDirectory(void)
{ {
if (!_p) { if (!*this) {
return false; return false;
} }
return _p->isDirectory(); return _p->isDirectory();
@ -163,7 +163,7 @@ boolean File::isDirectory(void)
File File::openNextFile(const char* mode) File File::openNextFile(const char* mode)
{ {
if (!_p) { if (!*this) {
return File(); return File();
} }
return _p->openNextFile(mode); return _p->openNextFile(mode);
@ -171,7 +171,7 @@ File File::openNextFile(const char* mode)
void File::rewindDirectory(void) void File::rewindDirectory(void)
{ {
if (!_p) { if (!*this) {
return; return;
} }
_p->rewindDirectory(); _p->rewindDirectory();

View File

@ -73,11 +73,15 @@ public:
bool verify(WiFiClient& client, const char* host) override bool verify(WiFiClient& client, const char* host) override
{ {
WiFiClientSecure& wcs = static_cast<WiFiClientSecure&>(client); WiFiClientSecure& wcs = static_cast<WiFiClientSecure&>(client);
wcs.setCACert(_cacert); if (_cacert == nullptr) {
wcs.setCertificate(_clicert); wcs.setInsecure();
wcs.setPrivateKey(_clikey); } else {
return true; wcs.setCACert(_cacert);
wcs.setCertificate(_clicert);
wcs.setPrivateKey(_clikey);
}
return true;
} }
protected: protected:
@ -105,6 +109,12 @@ HTTPClient::~HTTPClient()
if(_currentHeaders) { if(_currentHeaders) {
delete[] _currentHeaders; delete[] _currentHeaders;
} }
if(_tcpDeprecated) {
_tcpDeprecated.reset(nullptr);
}
if(_transportTraits) {
_transportTraits.reset(nullptr);
}
} }
void HTTPClient::clear() void HTTPClient::clear()
@ -265,15 +275,22 @@ bool HTTPClient::beginInternal(String url, const char* expectedProtocol)
// get port // get port
index = host.indexOf(':'); index = host.indexOf(':');
String the_host;
if(index >= 0) { if(index >= 0) {
_host = host.substring(0, index); // hostname the_host = host.substring(0, index); // hostname
host.remove(0, (index + 1)); // remove hostname + : host.remove(0, (index + 1)); // remove hostname + :
_port = host.toInt(); // get port _port = host.toInt(); // get port
} else { } else {
_host = host; the_host = host;
} }
if(_host != the_host && connected()){
log_d("switching host from '%s' to '%s'. disconnecting first", _host.c_str(), the_host.c_str());
_canReuse = false;
disconnect(true);
}
_host = the_host;
_uri = url; _uri = url;
log_d("host: %s port: %d url: %s", _host.c_str(), _port, _uri.c_str()); log_d("protocol: %s, host: %s port: %d url: %s", _protocol.c_str(), _host.c_str(), _port, _uri.c_str());
return true; return true;
} }
@ -365,19 +382,19 @@ void HTTPClient::disconnect(bool preserveClient)
} }
if(_reuse && _canReuse) { if(_reuse && _canReuse) {
log_d("tcp keep open for reuse\n"); log_d("tcp keep open for reuse");
} else { } else {
log_d("tcp stop\n"); log_d("tcp stop");
_client->stop(); _client->stop();
if(!preserveClient) { if(!preserveClient) {
_client = nullptr; _client = nullptr;
}
#ifdef HTTPCLIENT_1_1_COMPATIBLE #ifdef HTTPCLIENT_1_1_COMPATIBLE
if(_tcpDeprecated) { if(_tcpDeprecated) {
_transportTraits.reset(nullptr); _transportTraits.reset(nullptr);
_tcpDeprecated.reset(nullptr); _tcpDeprecated.reset(nullptr);
} }
#endif #endif
}
} }
} else { } else {
log_d("tcp is closed\n"); log_d("tcp is closed\n");
@ -1314,9 +1331,9 @@ int HTTPClient::writeToStreamDataBlock(Stream * stream, int size)
readBytes = buff_size; readBytes = buff_size;
} }
// stop if no more reading // stop if no more reading
if (readBytes == 0) if (readBytes == 0)
break; break;
// read data // read data
int bytesRead = _client->readBytes(buff, readBytes); int bytesRead = _client->readBytes(buff, readBytes);

View File

@ -35,11 +35,13 @@
HTTPUpdate::HTTPUpdate(void) HTTPUpdate::HTTPUpdate(void)
: _httpClientTimeout(8000), _ledPin(-1) : _httpClientTimeout(8000), _ledPin(-1)
{ {
_followRedirects = HTTPC_DISABLE_FOLLOW_REDIRECTS;
} }
HTTPUpdate::HTTPUpdate(int httpClientTimeout) HTTPUpdate::HTTPUpdate(int httpClientTimeout)
: _httpClientTimeout(httpClientTimeout), _ledPin(-1) : _httpClientTimeout(httpClientTimeout), _ledPin(-1)
{ {
_followRedirects = HTTPC_DISABLE_FOLLOW_REDIRECTS;
} }
HTTPUpdate::~HTTPUpdate(void) HTTPUpdate::~HTTPUpdate(void)
@ -56,6 +58,11 @@ HTTPUpdateResult HTTPUpdate::update(WiFiClient& client, const String& url, const
return handleUpdate(http, currentVersion, false); return handleUpdate(http, currentVersion, false);
} }
HTTPUpdateResult HTTPUpdate::updateSpiffs(HTTPClient& httpClient, const String& currentVersion)
{
return handleUpdate(httpClient, currentVersion, true);
}
HTTPUpdateResult HTTPUpdate::updateSpiffs(WiFiClient& client, const String& url, const String& currentVersion) HTTPUpdateResult HTTPUpdate::updateSpiffs(WiFiClient& client, const String& url, const String& currentVersion)
{ {
HTTPClient http; HTTPClient http;
@ -66,6 +73,12 @@ HTTPUpdateResult HTTPUpdate::updateSpiffs(WiFiClient& client, const String& url,
return handleUpdate(http, currentVersion, true); return handleUpdate(http, currentVersion, true);
} }
HTTPUpdateResult HTTPUpdate::update(HTTPClient& httpClient,
const String& currentVersion)
{
return handleUpdate(httpClient, currentVersion, false);
}
HTTPUpdateResult HTTPUpdate::update(WiFiClient& client, const String& host, uint16_t port, const String& uri, HTTPUpdateResult HTTPUpdate::update(WiFiClient& client, const String& host, uint16_t port, const String& uri,
const String& currentVersion) const String& currentVersion)
{ {
@ -175,6 +188,7 @@ HTTPUpdateResult HTTPUpdate::handleUpdate(HTTPClient& http, const String& curren
// use HTTP/1.0 for update since the update handler not support any transfer Encoding // use HTTP/1.0 for update since the update handler not support any transfer Encoding
http.useHTTP10(true); http.useHTTP10(true);
http.setTimeout(_httpClientTimeout); http.setTimeout(_httpClientTimeout);
http.setFollowRedirects(_followRedirects);
http.setUserAgent("ESP32-http-Update"); http.setUserAgent("ESP32-http-Update");
http.addHeader("Cache-Control", "no-cache"); http.addHeader("Cache-Control", "no-cache");
http.addHeader("x-ESP32-STA-MAC", WiFi.macAddress()); http.addHeader("x-ESP32-STA-MAC", WiFi.macAddress());

View File

@ -63,6 +63,15 @@ public:
{ {
_rebootOnUpdate = reboot; _rebootOnUpdate = reboot;
} }
/**
* set redirect follow mode. See `followRedirects_t` enum for avaliable modes.
* @param follow
*/
void setFollowRedirects(followRedirects_t follow)
{
_followRedirects = follow;
}
void setLedPin(int ledPin = -1, uint8_t ledOn = HIGH) void setLedPin(int ledPin = -1, uint8_t ledOn = HIGH)
{ {
@ -77,6 +86,10 @@ public:
t_httpUpdate_return updateSpiffs(WiFiClient& client, const String& url, const String& currentVersion = ""); t_httpUpdate_return updateSpiffs(WiFiClient& client, const String& url, const String& currentVersion = "");
t_httpUpdate_return update(HTTPClient& httpClient,
const String& currentVersion = "");
t_httpUpdate_return updateSpiffs(HTTPClient &httpClient, const String &currentVersion = "");
int getLastError(void); int getLastError(void);
String getLastErrorString(void); String getLastErrorString(void);
@ -89,6 +102,7 @@ protected:
bool _rebootOnUpdate = true; bool _rebootOnUpdate = true;
private: private:
int _httpClientTimeout; int _httpClientTimeout;
followRedirects_t _followRedirects;
int _ledPin; int _ledPin;
uint8_t _ledOn; uint8_t _ledOn;

View File

@ -14,6 +14,7 @@
#include "Preferences.h" #include "Preferences.h"
#include "nvs.h" #include "nvs.h"
#include "nvs_flash.h"
const char * nvs_errors[] = { "OTHER", "NOT_INITIALIZED", "NOT_FOUND", "TYPE_MISMATCH", "READ_ONLY", "NOT_ENOUGH_SPACE", "INVALID_NAME", "INVALID_HANDLE", "REMOVE_FAILED", "KEY_TOO_LONG", "PAGE_FULL", "INVALID_STATE", "INVALID_LENGTH"}; const char * nvs_errors[] = { "OTHER", "NOT_INITIALIZED", "NOT_FOUND", "TYPE_MISMATCH", "READ_ONLY", "NOT_ENOUGH_SPACE", "INVALID_NAME", "INVALID_HANDLE", "REMOVE_FAILED", "KEY_TOO_LONG", "PAGE_FULL", "INVALID_STATE", "INVALID_LENGTH"};
#define nvs_error(e) (((e)>ESP_ERR_NVS_BASE)?nvs_errors[(e)&~(ESP_ERR_NVS_BASE)]:nvs_errors[0]) #define nvs_error(e) (((e)>ESP_ERR_NVS_BASE)?nvs_errors[(e)&~(ESP_ERR_NVS_BASE)]:nvs_errors[0])
@ -28,12 +29,22 @@ Preferences::~Preferences(){
end(); end();
} }
bool Preferences::begin(const char * name, bool readOnly){ bool Preferences::begin(const char * name, bool readOnly, const char* partition_label){
if(_started){ if(_started){
return false; return false;
} }
_readOnly = readOnly; _readOnly = readOnly;
esp_err_t err = nvs_open(name, readOnly?NVS_READONLY:NVS_READWRITE, &_handle); esp_err_t err = ESP_OK;
if (partition_label != NULL) {
err = nvs_flash_init_partition(partition_label);
if (err) {
log_e("nvs_flash_init_partition failed: %s", nvs_error(err));
return false;
}
err = nvs_open_from_partition(partition_label, name, readOnly ? NVS_READONLY : NVS_READWRITE, &_handle);
} else {
err = nvs_open(name, readOnly?NVS_READONLY:NVS_READWRITE, &_handle);
}
if(err){ if(err){
log_e("nvs_open failed: %s", nvs_error(err)); log_e("nvs_open failed: %s", nvs_error(err));
return false; return false;

View File

@ -29,7 +29,7 @@ class Preferences {
Preferences(); Preferences();
~Preferences(); ~Preferences();
bool begin(const char * name, bool readOnly=false); bool begin(const char * name, bool readOnly=false, const char* partition_label=NULL);
void end(); void end();
bool clear(); bool clear();

View File

@ -22,7 +22,7 @@ using namespace fs;
SDFS::SDFS(FSImplPtr impl): FS(impl), _pdrv(0xFF) {} SDFS::SDFS(FSImplPtr impl): FS(impl), _pdrv(0xFF) {}
bool SDFS::begin(uint8_t ssPin, SPIClass &spi, uint32_t frequency, const char * mountpoint, uint8_t max_files) bool SDFS::begin(uint8_t ssPin, SPIClass &spi, uint32_t frequency, const char * mountpoint, uint8_t max_files, bool format_if_empty)
{ {
if(_pdrv != 0xFF) { if(_pdrv != 0xFF) {
return true; return true;
@ -35,7 +35,7 @@ bool SDFS::begin(uint8_t ssPin, SPIClass &spi, uint32_t frequency, const char *
return false; return false;
} }
if(!sdcard_mount(_pdrv, mountpoint, max_files)){ if(!sdcard_mount(_pdrv, mountpoint, max_files, format_if_empty)){
sdcard_unmount(_pdrv); sdcard_unmount(_pdrv);
sdcard_uninit(_pdrv); sdcard_uninit(_pdrv);
_pdrv = 0xFF; _pdrv = 0xFF;

View File

@ -28,7 +28,7 @@ protected:
public: public:
SDFS(FSImplPtr impl); SDFS(FSImplPtr impl);
bool begin(uint8_t ssPin=SS, SPIClass &spi=SPI, uint32_t frequency=4000000, const char * mountpoint="/sd", uint8_t max_files=5); bool begin(uint8_t ssPin=SS, SPIClass &spi=SPI, uint32_t frequency=4000000, const char * mountpoint="/sd", uint8_t max_files=5, bool format_if_empty=false);
void end(); void end();
sdcard_type_t cardType(); sdcard_type_t cardType();
uint64_t cardSize(); uint64_t cardSize();

View File

@ -59,6 +59,31 @@ typedef struct {
static ardu_sdcard_t* s_cards[FF_VOLUMES] = { NULL }; static ardu_sdcard_t* s_cards[FF_VOLUMES] = { NULL };
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR
const char * fferr2str[] = {
"(0) Succeeded",
"(1) A hard error occurred in the low level disk I/O layer",
"(2) Assertion failed",
"(3) The physical drive cannot work",
"(4) Could not find the file",
"(5) Could not find the path",
"(6) The path name format is invalid",
"(7) Access denied due to prohibited access or directory full",
"(8) Access denied due to prohibited access",
"(9) The file/directory object is invalid",
"(10) The physical drive is write protected",
"(11) The logical drive number is invalid",
"(12) The volume has no work area",
"(13) There is no valid FAT volume",
"(14) The f_mkfs() aborted due to any problem",
"(15) Could not get a grant to access the volume within defined period",
"(16) The operation is rejected according to the file sharing policy",
"(17) LFN working buffer could not be allocated",
"(18) Number of open files > FF_FS_LOCK",
"(19) Given parameter is invalid"
};
#endif
/* /*
* SD SPI * SD SPI
* */ * */
@ -72,6 +97,9 @@ bool sdWait(uint8_t pdrv, int timeout)
resp = s_cards[pdrv]->spi->transfer(0xFF); resp = s_cards[pdrv]->spi->transfer(0xFF);
} while (resp == 0x00 && (millis() - start) < (unsigned int)timeout); } while (resp == 0x00 && (millis() - start) < (unsigned int)timeout);
if (!resp) {
log_w("Wait Failed");
}
return (resp > 0x00); return (resp > 0x00);
} }
@ -90,7 +118,10 @@ bool sdSelectCard(uint8_t pdrv)
{ {
ardu_sdcard_t * card = s_cards[pdrv]; ardu_sdcard_t * card = s_cards[pdrv];
digitalWrite(card->ssPin, LOW); digitalWrite(card->ssPin, LOW);
sdWait(pdrv, 300); bool s = sdWait(pdrv, 300);
if (!s) {
log_e("Select Failed");
}
return true; return true;
} }
@ -104,10 +135,11 @@ char sdCommand(uint8_t pdrv, char cmd, unsigned int arg, unsigned int* resp)
token = sdCommand(pdrv, APP_CMD, 0, NULL); token = sdCommand(pdrv, APP_CMD, 0, NULL);
sdDeselectCard(pdrv); sdDeselectCard(pdrv);
if (token > 1) { if (token > 1) {
return token; break;
} }
if(!sdSelectCard(pdrv)) { if(!sdSelectCard(pdrv)) {
return 0xFF; token = 0xFF;
break;
} }
} }
@ -158,7 +190,10 @@ char sdCommand(uint8_t pdrv, char cmd, unsigned int arg, unsigned int* resp)
break; break;
} }
if (token == 0xFF) {
log_e("Card Failed! cmd: 0x%02x", cmd);
card->status = STA_NOINIT;
}
return token; return token;
} }
@ -214,7 +249,7 @@ bool sdReadSector(uint8_t pdrv, char* buffer, unsigned long long sector)
{ {
for (int f = 0; f < 3; f++) { for (int f = 0; f < 3; f++) {
if(!sdSelectCard(pdrv)) { if(!sdSelectCard(pdrv)) {
break; return false;
} }
if (!sdCommand(pdrv, READ_BLOCK_SINGLE, (s_cards[pdrv]->type == CARD_SDHC) ? sector : sector << 9, NULL)) { if (!sdCommand(pdrv, READ_BLOCK_SINGLE, (s_cards[pdrv]->type == CARD_SDHC) ? sector : sector << 9, NULL)) {
bool success = sdReadBytes(pdrv, buffer, 512); bool success = sdReadBytes(pdrv, buffer, 512);
@ -234,7 +269,7 @@ bool sdReadSectors(uint8_t pdrv, char* buffer, unsigned long long sector, int co
{ {
for (int f = 0; f < 3;) { for (int f = 0; f < 3;) {
if(!sdSelectCard(pdrv)) { if(!sdSelectCard(pdrv)) {
break; return false;
} }
if (!sdCommand(pdrv, READ_BLOCK_MULTIPLE, (s_cards[pdrv]->type == CARD_SDHC) ? sector : sector << 9, NULL)) { if (!sdCommand(pdrv, READ_BLOCK_MULTIPLE, (s_cards[pdrv]->type == CARD_SDHC) ? sector : sector << 9, NULL)) {
@ -270,7 +305,7 @@ bool sdWriteSector(uint8_t pdrv, const char* buffer, unsigned long long sector)
{ {
for (int f = 0; f < 3; f++) { for (int f = 0; f < 3; f++) {
if(!sdSelectCard(pdrv)) { if(!sdSelectCard(pdrv)) {
break; return false;
} }
if (!sdCommand(pdrv, WRITE_BLOCK_SINGLE, (s_cards[pdrv]->type == CARD_SDHC) ? sector : sector << 9, NULL)) { if (!sdCommand(pdrv, WRITE_BLOCK_SINGLE, (s_cards[pdrv]->type == CARD_SDHC) ? sector : sector << 9, NULL)) {
char token = sdWriteBytes(pdrv, buffer, 0xFE); char token = sdWriteBytes(pdrv, buffer, 0xFE);
@ -306,12 +341,12 @@ bool sdWriteSectors(uint8_t pdrv, const char* buffer, unsigned long long sector,
for (int f = 0; f < 3;) { for (int f = 0; f < 3;) {
if (card->type != CARD_MMC) { if (card->type != CARD_MMC) {
if (sdTransaction(pdrv, SET_WR_BLK_ERASE_COUNT, currentCount, NULL)) { if (sdTransaction(pdrv, SET_WR_BLK_ERASE_COUNT, currentCount, NULL)) {
break; return false;
} }
} }
if(!sdSelectCard(pdrv)) { if(!sdSelectCard(pdrv)) {
break; return false;
} }
if (!sdCommand(pdrv, WRITE_BLOCK_MULTIPLE, (card->type == CARD_SDHC) ? currentSector : currentSector << 9, NULL)) { if (!sdCommand(pdrv, WRITE_BLOCK_MULTIPLE, (card->type == CARD_SDHC) ? currentSector : currentSector << 9, NULL)) {
@ -343,9 +378,8 @@ bool sdWriteSectors(uint8_t pdrv, const char* buffer, unsigned long long sector,
break; break;
} }
sdDeselectCard(pdrv);
if (token == 0x0A) { if (token == 0x0A) {
sdDeselectCard(pdrv);
unsigned int writtenBlocks = 0; unsigned int writtenBlocks = 0;
if (card->type != CARD_MMC && sdSelectCard(pdrv)) { if (card->type != CARD_MMC && sdSelectCard(pdrv)) {
if (!sdCommand(pdrv, SEND_NUM_WR_BLOCKS, 0, NULL)) { if (!sdCommand(pdrv, SEND_NUM_WR_BLOCKS, 0, NULL)) {
@ -364,7 +398,7 @@ bool sdWriteSectors(uint8_t pdrv, const char* buffer, unsigned long long sector,
currentCount = count - writtenBlocks; currentCount = count - writtenBlocks;
continue; continue;
} else { } else {
return false; break;
} }
} }
} else { } else {
@ -379,7 +413,7 @@ unsigned long sdGetSectorsCount(uint8_t pdrv)
{ {
for (int f = 0; f < 3; f++) { for (int f = 0; f < 3; f++) {
if(!sdSelectCard(pdrv)) { if(!sdSelectCard(pdrv)) {
break; return false;
} }
if (!sdCommand(pdrv, SEND_CSD, 0, NULL)) { if (!sdCommand(pdrv, SEND_CSD, 0, NULL)) {
@ -713,7 +747,7 @@ uint8_t sdcard_unmount(uint8_t pdrv)
return 0; return 0;
} }
bool sdcard_mount(uint8_t pdrv, const char* path, uint8_t max_files) bool sdcard_mount(uint8_t pdrv, const char* path, uint8_t max_files, bool format_if_empty)
{ {
ardu_sdcard_t * card = s_cards[pdrv]; ardu_sdcard_t * card = s_cards[pdrv];
if(pdrv >= FF_VOLUMES || card == NULL){ if(pdrv >= FF_VOLUMES || card == NULL){
@ -738,9 +772,25 @@ bool sdcard_mount(uint8_t pdrv, const char* path, uint8_t max_files)
FRESULT res = f_mount(fs, drv, 1); FRESULT res = f_mount(fs, drv, 1);
if (res != FR_OK) { if (res != FR_OK) {
log_e("f_mount failed 0x(%x)", res); log_e("f_mount failed: %s", fferr2str[res]);
esp_vfs_fat_unregister_path(path); if(res == 13 && format_if_empty){
return false; BYTE work[FF_MAX_SS];
res = f_mkfs(drv, FM_ANY, 0, work, sizeof(work));
if (res != FR_OK) {
log_e("f_mkfs failed: %s", fferr2str[res]);
esp_vfs_fat_unregister_path(path);
return false;
}
res = f_mount(fs, drv, 1);
if (res != FR_OK) {
log_e("f_mount failed: %s", fferr2str[res]);
esp_vfs_fat_unregister_path(path);
return false;
}
} else {
esp_vfs_fat_unregister_path(path);
return false;
}
} }
AcquireSPI lock(card); AcquireSPI lock(card);
card->sectors = sdGetSectorsCount(pdrv); card->sectors = sdGetSectorsCount(pdrv);

View File

@ -21,7 +21,7 @@
uint8_t sdcard_init(uint8_t cs, SPIClass * spi, int hz); uint8_t sdcard_init(uint8_t cs, SPIClass * spi, int hz);
uint8_t sdcard_uninit(uint8_t pdrv); uint8_t sdcard_uninit(uint8_t pdrv);
bool sdcard_mount(uint8_t pdrv, const char* path, uint8_t max_files); bool sdcard_mount(uint8_t pdrv, const char* path, uint8_t max_files, bool format_if_empty);
uint8_t sdcard_unmount(uint8_t pdrv); uint8_t sdcard_unmount(uint8_t pdrv);
sdcard_type_t sdcard_type(uint8_t pdrv); sdcard_type_t sdcard_type(uint8_t pdrv);

View File

@ -35,7 +35,7 @@ SDMMCFS::SDMMCFS(FSImplPtr impl)
: FS(impl), _card(NULL) : FS(impl), _card(NULL)
{} {}
bool SDMMCFS::begin(const char * mountpoint, bool mode1bit) bool SDMMCFS::begin(const char * mountpoint, bool mode1bit, bool format_if_mount_failed)
{ {
if(_card) { if(_card) {
return true; return true;
@ -68,7 +68,7 @@ bool SDMMCFS::begin(const char * mountpoint, bool mode1bit)
} }
esp_vfs_fat_sdmmc_mount_config_t mount_config = { esp_vfs_fat_sdmmc_mount_config_t mount_config = {
.format_if_mount_failed = false, .format_if_mount_failed = format_if_mount_failed,
.max_files = 5, .max_files = 5,
.allocation_unit_size = 0 .allocation_unit_size = 0
}; };

View File

@ -28,7 +28,7 @@ protected:
public: public:
SDMMCFS(FSImplPtr impl); SDMMCFS(FSImplPtr impl);
bool begin(const char * mountpoint="/sdcard", bool mode1bit=false); bool begin(const char * mountpoint="/sdcard", bool mode1bit=false, bool format_if_mount_failed=false);
void end(); void end();
sdcard_type_t cardType(); sdcard_type_t cardType();
uint64_t cardSize(); uint64_t cardSize();

View File

@ -85,7 +85,7 @@ void SPIClass::setHwCs(bool use)
if(use && !_use_hw_ss) { if(use && !_use_hw_ss) {
spiAttachSS(_spi, 0, _ss); spiAttachSS(_spi, 0, _ss);
spiSSEnable(_spi); spiSSEnable(_spi);
} else if(_use_hw_ss) { } else if(!use && _use_hw_ss) {
spiSSDisable(_spi); spiSSDisable(_spi);
spiDetachSS(_spi, _ss); spiDetachSS(_spi, _ss);
} }

View File

@ -125,6 +125,7 @@ void setup(void) {
void loop(void) { void loop(void) {
server.handleClient(); server.handleClient();
delay(2);//allow the cpu to switch to other tasks
} }
void drawGraph() { void drawGraph() {

View File

@ -300,4 +300,5 @@ void setup(void) {
void loop(void) { void loop(void) {
server.handleClient(); server.handleClient();
delay(2);//allow the cpu to switch to other tasks
} }

View File

@ -70,4 +70,5 @@ void setup(void) {
void loop(void) { void loop(void) {
server.handleClient(); server.handleClient();
delay(2);//allow the cpu to switch to other tasks
} }

View File

@ -56,4 +56,5 @@ void setup() {
void loop() { void loop() {
ArduinoOTA.handle(); ArduinoOTA.handle();
server.handleClient(); server.handleClient();
delay(2);//allow the cpu to switch to other tasks
} }

View File

@ -38,4 +38,5 @@ void setup() {
void loop() { void loop() {
ArduinoOTA.handle(); ArduinoOTA.handle();
server.handleClient(); server.handleClient();
delay(2);//allow the cpu to switch to other tasks
} }

View File

@ -53,4 +53,5 @@ void setup(void) {
void loop(void) { void loop(void) {
server.handleClient(); server.handleClient();
delay(2);//allow the cpu to switch to other tasks
} }

View File

@ -310,4 +310,5 @@ void setup(void) {
void loop(void) { void loop(void) {
server.handleClient(); server.handleClient();
delay(2);//allow the cpu to switch to other tasks
} }

View File

@ -129,4 +129,5 @@ void setup(void) {
void loop(void) { void loop(void) {
server.handleClient(); server.handleClient();
delay(2);//allow the cpu to switch to other tasks
} }

View File

@ -65,5 +65,5 @@ void setup(void) {
void loop(void) { void loop(void) {
server.handleClient(); server.handleClient();
delay(1); delay(2);//allow the cpu to switch to other tasks
} }

View File

@ -1,15 +1,9 @@
#ifndef _HTTP_Method_H_ #ifndef _HTTP_Method_H_
#define _HTTP_Method_H_ #define _HTTP_Method_H_
typedef enum { #include "http_parser.h"
HTTP_GET = 0b00000001,
HTTP_POST = 0b00000010, typedef enum http_method HTTPMethod;
HTTP_DELETE = 0b00000100, #define HTTP_ANY (HTTPMethod)(255)
HTTP_PUT = 0b00001000,
HTTP_PATCH = 0b00010000,
HTTP_HEAD = 0b00100000,
HTTP_OPTIONS = 0b01000000,
HTTP_ANY = 0b01111111,
} HTTPMethod;
#endif /* _HTTP_Method_H_ */ #endif /* _HTTP_Method_H_ */

View File

@ -30,6 +30,14 @@
#define WEBSERVER_MAX_POST_ARGS 32 #define WEBSERVER_MAX_POST_ARGS 32
#endif #endif
#define __STR(a) #a
#define _STR(a) __STR(a)
const char * _http_method_str[] = {
#define XX(num, name, string) _STR(name),
HTTP_METHOD_MAP(XX)
#undef XX
};
static const char Content_Type[] PROGMEM = "Content-Type"; static const char Content_Type[] PROGMEM = "Content-Type";
static const char filename[] PROGMEM = "filename"; static const char filename[] PROGMEM = "filename";
@ -96,17 +104,17 @@ bool WebServer::_parseRequest(WiFiClient& client) {
_currentUri = url; _currentUri = url;
_chunked = false; _chunked = false;
HTTPMethod method = HTTP_GET; HTTPMethod method = HTTP_ANY;
if (methodStr == F("POST")) { size_t num_methods = sizeof(_http_method_str) / sizeof(const char *);
method = HTTP_POST; for (size_t i=0; i<num_methods; i++) {
} else if (methodStr == F("DELETE")) { if (methodStr == _http_method_str[i]) {
method = HTTP_DELETE; method = (HTTPMethod)i;
} else if (methodStr == F("OPTIONS")) { break;
method = HTTP_OPTIONS; }
} else if (methodStr == F("PUT")) { }
method = HTTP_PUT; if (method == HTTP_ANY) {
} else if (methodStr == F("PATCH")) { log_e("Unknown HTTP Method: %s", methodStr.c_str());
method = HTTP_PATCH; return false;
} }
_currentMethod = method; _currentMethod = method;
@ -303,7 +311,6 @@ void WebServer::_uploadWriteByte(uint8_t b){
} }
int WebServer::_uploadReadByte(WiFiClient& client){ int WebServer::_uploadReadByte(WiFiClient& client){
if (!client.connected()) return -1;
int res = client.read(); int res = client.read();
if(res < 0) { if(res < 0) {
// keep trying until you either read a valid byte or timeout // keep trying until you either read a valid byte or timeout
@ -311,6 +318,7 @@ int WebServer::_uploadReadByte(WiFiClient& client){
long timeoutIntervalMillis = client.getTimeout(); long timeoutIntervalMillis = client.getTimeout();
boolean timedOut = false; boolean timedOut = false;
for(;;) { for(;;) {
if (!client.connected()) return -1;
// loosely modeled after blinkWithoutDelay pattern // loosely modeled after blinkWithoutDelay pattern
while(!timedOut && !client.available() && client.connected()){ while(!timedOut && !client.available() && client.connected()){
delay(2); delay(2);

View File

@ -33,7 +33,8 @@
static const char AUTHORIZATION_HEADER[] = "Authorization"; static const char AUTHORIZATION_HEADER[] = "Authorization";
static const char qop_auth[] = "qop=\"auth\""; static const char qop_auth[] PROGMEM = "qop=auth";
static const char qop_auth_quoted[] PROGMEM = "qop=\"auth\"";
static const char WWW_Authenticate[] = "WWW-Authenticate"; static const char WWW_Authenticate[] = "WWW-Authenticate";
static const char Content_Length[] = "Content-Length"; static const char Content_Length[] = "Content-Length";
@ -185,7 +186,7 @@ bool WebServer::authenticate(const char * username, const char * password){
} }
// parameters for the RFC 2617 newer Digest // parameters for the RFC 2617 newer Digest
String _nc,_cnonce; String _nc,_cnonce;
if(authReq.indexOf(FPSTR(qop_auth)) != -1) { if(authReq.indexOf(FPSTR(qop_auth)) != -1 || authReq.indexOf(FPSTR(qop_auth_quoted)) != -1) {
_nc = _extractParam(authReq, F("nc="), ','); _nc = _extractParam(authReq, F("nc="), ',');
_cnonce = _extractParam(authReq, F("cnonce=\""),'\"'); _cnonce = _extractParam(authReq, F("cnonce=\""),'\"');
} }
@ -205,7 +206,7 @@ bool WebServer::authenticate(const char * username, const char * password){
} }
log_v("Hash of GET:uri=%s", _H2.c_str()); log_v("Hash of GET:uri=%s", _H2.c_str());
String _responsecheck = ""; String _responsecheck = "";
if(authReq.indexOf(FPSTR(qop_auth)) != -1) { if(authReq.indexOf(FPSTR(qop_auth)) != -1 || authReq.indexOf(FPSTR(qop_auth_quoted)) != -1) {
_responsecheck = md5str(_H1 + ':' + _nonce + ':' + _nc + ':' + _cnonce + F(":auth:") + _H2); _responsecheck = md5str(_H1 + ':' + _nonce + ':' + _nc + ':' + _cnonce + F(":auth:") + _H2);
} else { } else {
_responsecheck = md5str(_H1 + ':' + _nonce + ':' + _H2); _responsecheck = md5str(_H1 + ':' + _nonce + ':' + _H2);
@ -412,6 +413,8 @@ void WebServer::_prepareHeader(String& response, int code, const char* content_t
} }
if (_corsEnabled) { if (_corsEnabled) {
sendHeader(String(FPSTR("Access-Control-Allow-Origin")), String("*")); sendHeader(String(FPSTR("Access-Control-Allow-Origin")), String("*"));
sendHeader(String(FPSTR("Access-Control-Allow-Methods")), String("*"));
sendHeader(String(FPSTR("Access-Control-Allow-Headers")), String("*"));
} }
sendHeader(String(F("Connection")), String(F("close"))); sendHeader(String(F("Connection")), String(F("close")));

View File

@ -22,6 +22,7 @@
#include "eth_phy/phy.h" #include "eth_phy/phy.h"
#include "eth_phy/phy_tlk110.h" #include "eth_phy/phy_tlk110.h"
#include "eth_phy/phy_lan8720.h" #include "eth_phy/phy_lan8720.h"
#include "eth_phy/phy_ip101.h"
#include "lwip/err.h" #include "lwip/err.h"
#include "lwip/dns.h" #include "lwip/dns.h"
@ -78,6 +79,9 @@ bool ETHClass::begin(uint8_t phy_addr, int power, int mdc, int mdio, eth_phy_typ
} else if(type == ETH_PHY_TLK110){ } else if(type == ETH_PHY_TLK110){
eth_config_t config = phy_tlk110_default_ethernet_config; eth_config_t config = phy_tlk110_default_ethernet_config;
memcpy(&eth_config, &config, sizeof(eth_config_t)); memcpy(&eth_config, &config, sizeof(eth_config_t));
} else if(type == ETH_PHY_IP101) {
eth_config_t config = phy_ip101_default_ethernet_config;
memcpy(&eth_config, &config, sizeof(eth_config_t));
} else { } else {
log_e("Bad ETH_PHY type: %u", (uint8_t)type); log_e("Bad ETH_PHY type: %u", (uint8_t)type);
return false; return false;
@ -114,7 +118,7 @@ bool ETHClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, I
esp_err_t err = ESP_OK; esp_err_t err = ESP_OK;
tcpip_adapter_ip_info_t info; tcpip_adapter_ip_info_t info;
if(local_ip != (uint32_t)0x00000000){ if(local_ip != (uint32_t)0x00000000 && local_ip != INADDR_NONE){
info.ip.addr = static_cast<uint32_t>(local_ip); info.ip.addr = static_cast<uint32_t>(local_ip);
info.gw.addr = static_cast<uint32_t>(gateway); info.gw.addr = static_cast<uint32_t>(gateway);
info.netmask.addr = static_cast<uint32_t>(subnet); info.netmask.addr = static_cast<uint32_t>(subnet);
@ -149,13 +153,13 @@ bool ETHClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, I
ip_addr_t d; ip_addr_t d;
d.type = IPADDR_TYPE_V4; d.type = IPADDR_TYPE_V4;
if(dns1 != (uint32_t)0x00000000) { if(dns1 != (uint32_t)0x00000000 && dns1 != INADDR_NONE) {
// Set DNS1-Server // Set DNS1-Server
d.u_addr.ip4.addr = static_cast<uint32_t>(dns1); d.u_addr.ip4.addr = static_cast<uint32_t>(dns1);
dns_setserver(0, &d); dns_setserver(0, &d);
} }
if(dns2 != (uint32_t)0x00000000) { if(dns2 != (uint32_t)0x00000000 && dns2 != INADDR_NONE) {
// Set DNS2-Server // Set DNS2-Server
d.u_addr.ip4.addr = static_cast<uint32_t>(dns2); d.u_addr.ip4.addr = static_cast<uint32_t>(dns2);
dns_setserver(1, &d); dns_setserver(1, &d);

View File

@ -48,7 +48,7 @@
#define ETH_CLK_MODE ETH_CLOCK_GPIO0_IN #define ETH_CLK_MODE ETH_CLOCK_GPIO0_IN
#endif #endif
typedef enum { ETH_PHY_LAN8720, ETH_PHY_TLK110, ETH_PHY_MAX } eth_phy_type_t; typedef enum { ETH_PHY_LAN8720, ETH_PHY_TLK110, ETH_PHY_IP101, ETH_PHY_MAX } eth_phy_type_t;
class ETHClass { class ETHClass {
private: private:

View File

@ -88,4 +88,14 @@ void WiFiClass::printDiag(Print& p)
p.println(conf.sta.bssid_set); p.println(conf.sta.bssid_set);
} }
void WiFiClass::enableProv(bool status)
{
prov_enable = status;
}
bool WiFiClass::isProvEnabled()
{
return prov_enable;
}
WiFiClass WiFi; WiFiClass WiFi;

View File

@ -37,11 +37,17 @@
#include "WiFiClient.h" #include "WiFiClient.h"
#include "WiFiServer.h" #include "WiFiServer.h"
#include "WiFiUdp.h" #include "WiFiUdp.h"
#include "WiFiProv.h"
class WiFiClass : public WiFiGenericClass, public WiFiSTAClass, public WiFiScanClass, public WiFiAPClass, public WiFiProvClass class WiFiClass : public WiFiGenericClass, public WiFiSTAClass, public WiFiScanClass, public WiFiAPClass
{ {
private:
bool prov_enable;
public: public:
WiFiClass()
{
prov_enable = false;
}
using WiFiGenericClass::channel; using WiFiGenericClass::channel;
using WiFiSTAClass::SSID; using WiFiSTAClass::SSID;
@ -60,6 +66,8 @@ public:
friend class WiFiClient; friend class WiFiClient;
friend class WiFiServer; friend class WiFiServer;
friend class WiFiUDP; friend class WiFiUDP;
void enableProv(bool status);
bool isProvEnabled();
}; };
extern WiFiClass WiFi; extern WiFiClass WiFi;

View File

@ -137,6 +137,21 @@ bool WiFiAPClass::softAP(const char* ssid, const char* passphrase, int channel,
return true; return true;
} }
/**
* Return the current SSID associated with the network
* @return SSID
*/
String WiFiAPClass::softAPSSID() const
{
if(WiFiGenericClass::getMode() == WIFI_MODE_NULL){
return String();
}
wifi_config_t info;
if(!esp_wifi_get_config(WIFI_IF_AP, &info)) {
return String(reinterpret_cast<char*>(info.ap.ssid));
}
return String();
}
/** /**
* Configure access point * Configure access point
@ -189,7 +204,7 @@ bool WiFiAPClass::softAPdisconnect(bool wifioff)
wifi_config_t conf; wifi_config_t conf;
if(WiFiGenericClass::getMode() == WIFI_MODE_NULL){ if(WiFiGenericClass::getMode() == WIFI_MODE_NULL){
return ESP_ERR_INVALID_STATE; return false;
} }
*conf.ap.ssid = 0; *conf.ap.ssid = 0;

View File

@ -58,6 +58,8 @@ public:
uint8_t* softAPmacAddress(uint8_t* mac); uint8_t* softAPmacAddress(uint8_t* mac);
String softAPmacAddress(void); String softAPmacAddress(void);
String softAPSSID(void) const;
protected: protected:
}; };

View File

@ -216,9 +216,9 @@ int WiFiClient::connect(IPAddress ip, uint16_t port, int32_t timeout)
uint32_t ip_addr = ip; uint32_t ip_addr = ip;
struct sockaddr_in serveraddr; struct sockaddr_in serveraddr;
bzero((char *) &serveraddr, sizeof(serveraddr)); memset((char *) &serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET; serveraddr.sin_family = AF_INET;
bcopy((const void *)(&ip_addr), (void *)&serveraddr.sin_addr.s_addr, 4); memcpy((void *)&serveraddr.sin_addr.s_addr, (const void *)(&ip_addr), 4);
serveraddr.sin_port = htons(port); serveraddr.sin_port = htons(port);
fd_set fdset; fd_set fdset;
struct timeval tv; struct timeval tv;

View File

@ -379,6 +379,7 @@ esp_err_t WiFiGenericClass::_eventCallback(void *arg, system_event_t *event, wif
} else if(event->event_id == SYSTEM_EVENT_STA_START) { } else if(event->event_id == SYSTEM_EVENT_STA_START) {
WiFiSTAClass::_setStatus(WL_DISCONNECTED); WiFiSTAClass::_setStatus(WL_DISCONNECTED);
setStatusBits(STA_STARTED_BIT); setStatusBits(STA_STARTED_BIT);
tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, WiFiSTAClass::_hostname.c_str());
} else if(event->event_id == SYSTEM_EVENT_STA_STOP) { } else if(event->event_id == SYSTEM_EVENT_STA_STOP) {
WiFiSTAClass::_setStatus(WL_NO_SHIELD); WiFiSTAClass::_setStatus(WL_NO_SHIELD);
clearStatusBits(STA_STARTED_BIT | STA_CONNECTED_BIT | STA_HAS_IP_BIT | STA_HAS_IP6_BIT); clearStatusBits(STA_STARTED_BIT | STA_CONNECTED_BIT | STA_HAS_IP_BIT | STA_HAS_IP6_BIT);

View File

@ -71,6 +71,7 @@ static bool sta_config_equal(const wifi_config_t& lhs, const wifi_config_t& rhs)
bool WiFiSTAClass::_autoReconnect = true; bool WiFiSTAClass::_autoReconnect = true;
bool WiFiSTAClass::_useStaticIp = false; bool WiFiSTAClass::_useStaticIp = false;
String WiFiSTAClass::_hostname = "esp32-arduino";
static wl_status_t _sta_status = WL_NO_SHIELD; static wl_status_t _sta_status = WL_NO_SHIELD;
static EventGroupHandle_t _sta_status_group = NULL; static EventGroupHandle_t _sta_status_group = NULL;
@ -120,7 +121,7 @@ wl_status_t WiFiSTAClass::begin(const char* ssid, const char *passphrase, int32_
return WL_CONNECT_FAILED; return WL_CONNECT_FAILED;
} }
if(!ssid || *ssid == 0x00 || strlen(ssid) > 31) { if(!ssid || *ssid == 0x00 || strlen(ssid) > 32) {
log_e("SSID too long or missing!"); log_e("SSID too long or missing!");
return WL_CONNECT_FAILED; return WL_CONNECT_FAILED;
} }
@ -133,6 +134,7 @@ wl_status_t WiFiSTAClass::begin(const char* ssid, const char *passphrase, int32_
wifi_config_t conf; wifi_config_t conf;
memset(&conf, 0, sizeof(wifi_config_t)); memset(&conf, 0, sizeof(wifi_config_t));
strcpy(reinterpret_cast<char*>(conf.sta.ssid), ssid); strcpy(reinterpret_cast<char*>(conf.sta.ssid), ssid);
conf.sta.scan_method = WIFI_ALL_CHANNEL_SCAN; //force full scan to be able to choose the nearest / strongest AP
if(passphrase) { if(passphrase) {
if (strlen(passphrase) == 64){ // it's not a passphrase, is the PSK if (strlen(passphrase) == 64){ // it's not a passphrase, is the PSK
@ -284,7 +286,7 @@ bool WiFiSTAClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subne
tcpip_adapter_ip_info_t info; tcpip_adapter_ip_info_t info;
if(local_ip != (uint32_t)0x00000000){ if(local_ip != (uint32_t)0x00000000 && local_ip != INADDR_NONE){
info.ip.addr = static_cast<uint32_t>(local_ip); info.ip.addr = static_cast<uint32_t>(local_ip);
info.gw.addr = static_cast<uint32_t>(gateway); info.gw.addr = static_cast<uint32_t>(gateway);
info.netmask.addr = static_cast<uint32_t>(subnet); info.netmask.addr = static_cast<uint32_t>(subnet);
@ -320,13 +322,13 @@ bool WiFiSTAClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subne
ip_addr_t d; ip_addr_t d;
d.type = IPADDR_TYPE_V4; d.type = IPADDR_TYPE_V4;
if(dns1 != (uint32_t)0x00000000) { if(dns1 != (uint32_t)0x00000000 && dns1 != INADDR_NONE) {
// Set DNS1-Server // Set DNS1-Server
d.u_addr.ip4.addr = static_cast<uint32_t>(dns1); d.u_addr.ip4.addr = static_cast<uint32_t>(dns1);
dns_setserver(0, &d); dns_setserver(0, &d);
} }
if(dns2 != (uint32_t)0x00000000) { if(dns2 != (uint32_t)0x00000000 && dns2 != INADDR_NONE) {
// Set DNS2-Server // Set DNS2-Server
d.u_addr.ip4.addr = static_cast<uint32_t>(dns2); d.u_addr.ip4.addr = static_cast<uint32_t>(dns2);
dns_setserver(1, &d); dns_setserver(1, &d);
@ -636,6 +638,7 @@ const char * WiFiSTAClass::getHostname()
*/ */
bool WiFiSTAClass::setHostname(const char * hostname) bool WiFiSTAClass::setHostname(const char * hostname)
{ {
_hostname = hostname;
if(WiFiGenericClass::getMode() == WIFI_MODE_NULL){ if(WiFiGenericClass::getMode() == WIFI_MODE_NULL){
return false; return false;
} }

View File

@ -74,6 +74,7 @@ public:
const char * getHostname(); const char * getHostname();
bool setHostname(const char * hostname); bool setHostname(const char * hostname);
bool hostname(const String& aHostname) { return setHostname(aHostname.c_str()); }
// STA WiFi info // STA WiFi info
static wl_status_t status(); static wl_status_t status();
@ -86,6 +87,7 @@ public:
int8_t RSSI(); int8_t RSSI();
static void _setStatus(wl_status_t status); static void _setStatus(wl_status_t status);
static String _hostname;
protected: protected:
static bool _useStaticIp; static bool _useStaticIp;
static bool _autoReconnect; static bool _autoReconnect;

View File

@ -0,0 +1,61 @@
#include <WiFiClientSecure.h>
const char* ssid = "your-ssid"; // your network SSID (name of wifi network)
const char* password = "your-password"; // your network password
const char* server = "www.howsmyssl.com"; // Server URL
WiFiClientSecure client;
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(115200);
delay(100);
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
// attempt to connect to Wifi network:
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
// wait 1 second for re-trying
delay(1000);
}
Serial.print("Connected to ");
Serial.println(ssid);
Serial.println("\nStarting connection to server...");
client.setInsecure();//skip verification
if (!client.connect(server, 443))
Serial.println("Connection failed!");
else {
Serial.println("Connected to server!");
// Make a HTTP request:
client.println("GET https://www.howsmyssl.com/a/check HTTP/1.0");
client.println("Host: www.howsmyssl.com");
client.println("Connection: close");
client.println();
while (client.connected()) {
String line = client.readStringUntil('\n');
if (line == "\r") {
Serial.println("headers received");
break;
}
}
// if there are incoming bytes available
// from the server, read them and print them:
while (client.available()) {
char c = client.read();
Serial.write(c);
}
client.stop();
}
}
void loop() {
// do nothing
}

View File

@ -19,31 +19,24 @@ const char* server = "www.howsmyssl.com"; // Server URL
const char* test_root_ca= \ const char* test_root_ca= \
"-----BEGIN CERTIFICATE-----\n" \ "-----BEGIN CERTIFICATE-----\n" \
"MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\n" \ "MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/\n" \
"MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n" \ "MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n" \
"DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\n" \ "DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow\n" \
"SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\n" \ "PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD\n" \
"GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\n" \ "Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n" \
"AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\n" \ "AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O\n" \
"q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\n" \ "rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq\n" \
"SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\n" \ "OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b\n" \
"Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\n" \ "xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw\n" \
"a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\n" \ "7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD\n" \
"/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\n" \ "aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV\n" \
"AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\n" \ "HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG\n" \
"CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\n" \ "SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69\n" \
"bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\n" \ "ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr\n" \
"c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\n" \ "AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz\n" \
"VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\n" \ "R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5\n" \
"ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\n" \ "JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo\n" \
"MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\n" \ "Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ\n" \
"Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\n" \
"AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\n" \
"uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\n" \
"wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\n" \
"X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\n" \
"PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\n" \
"KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\n" \
"-----END CERTIFICATE-----\n"; "-----END CERTIFICATE-----\n";
// You can use x.509 client certificates if you want // You can use x.509 client certificates if you want

View File

@ -36,6 +36,7 @@ WiFiClientSecure::WiFiClientSecure()
ssl_init(sslclient); ssl_init(sslclient);
sslclient->socket = -1; sslclient->socket = -1;
sslclient->handshake_timeout = 120000; sslclient->handshake_timeout = 120000;
_use_insecure = false;
_CA_cert = NULL; _CA_cert = NULL;
_cert = NULL; _cert = NULL;
_private_key = NULL; _private_key = NULL;
@ -116,17 +117,17 @@ int WiFiClientSecure::connect(const char *host, uint16_t port, int32_t timeout){
return connect(host, port); return connect(host, port);
} }
int WiFiClientSecure::connect(IPAddress ip, uint16_t port, const char *_CA_cert, const char *_cert, const char *_private_key) int WiFiClientSecure::connect(IPAddress ip, uint16_t port, const char *CA_cert, const char *cert, const char *private_key)
{ {
return connect(ip.toString().c_str(), port, _CA_cert, _cert, _private_key); return connect(ip.toString().c_str(), port, CA_cert, cert, private_key);
} }
int WiFiClientSecure::connect(const char *host, uint16_t port, const char *_CA_cert, const char *_cert, const char *_private_key) int WiFiClientSecure::connect(const char *host, uint16_t port, const char *CA_cert, const char *cert, const char *private_key)
{ {
if(_timeout > 0){ if(_timeout > 0){
sslclient->handshake_timeout = _timeout; sslclient->handshake_timeout = _timeout;
} }
int ret = start_ssl_client(sslclient, host, port, _timeout, _CA_cert, _cert, _private_key, NULL, NULL); int ret = start_ssl_client(sslclient, host, port, _timeout, CA_cert, cert, private_key, NULL, NULL, _use_insecure);
_lastError = ret; _lastError = ret;
if (ret < 0) { if (ret < 0) {
log_e("start_ssl_client: %d", ret); log_e("start_ssl_client: %d", ret);
@ -138,7 +139,7 @@ int WiFiClientSecure::connect(const char *host, uint16_t port, const char *_CA_c
} }
int WiFiClientSecure::connect(IPAddress ip, uint16_t port, const char *pskIdent, const char *psKey) { int WiFiClientSecure::connect(IPAddress ip, uint16_t port, const char *pskIdent, const char *psKey) {
return connect(ip.toString().c_str(), port,_pskIdent, _psKey); return connect(ip.toString().c_str(), port, pskIdent, psKey);
} }
int WiFiClientSecure::connect(const char *host, uint16_t port, const char *pskIdent, const char *psKey) { int WiFiClientSecure::connect(const char *host, uint16_t port, const char *pskIdent, const char *psKey) {
@ -146,7 +147,7 @@ int WiFiClientSecure::connect(const char *host, uint16_t port, const char *pskId
if(_timeout > 0){ if(_timeout > 0){
sslclient->handshake_timeout = _timeout; sslclient->handshake_timeout = _timeout;
} }
int ret = start_ssl_client(sslclient, host, port, _timeout, NULL, NULL, NULL, _pskIdent, _psKey); int ret = start_ssl_client(sslclient, host, port, _timeout, NULL, NULL, NULL, pskIdent, psKey, _use_insecure);
_lastError = ret; _lastError = ret;
if (ret < 0) { if (ret < 0) {
log_e("start_ssl_client: %d", ret); log_e("start_ssl_client: %d", ret);
@ -245,6 +246,16 @@ uint8_t WiFiClientSecure::connected()
return _connected; return _connected;
} }
void WiFiClientSecure::setInsecure()
{
_CA_cert = NULL;
_cert = NULL;
_private_key = NULL;
_pskIdent = NULL;
_psKey = NULL;
_use_insecure = true;
}
void WiFiClientSecure::setCACert (const char *rootCA) void WiFiClientSecure::setCACert (const char *rootCA)
{ {
_CA_cert = rootCA; _CA_cert = rootCA;
@ -322,9 +333,7 @@ int WiFiClientSecure::lastError(char *buf, const size_t size)
if (!_lastError) { if (!_lastError) {
return 0; return 0;
} }
char error_buf[100]; mbedtls_strerror(_lastError, buf, size);
mbedtls_strerror(_lastError, error_buf, 100);
snprintf(buf, size, "%s", error_buf);
return _lastError; return _lastError;
} }

View File

@ -33,6 +33,7 @@ protected:
int _lastError = 0; int _lastError = 0;
int _peek = -1; int _peek = -1;
int _timeout = 0; int _timeout = 0;
bool _use_insecure;
const char *_CA_cert; const char *_CA_cert;
const char *_cert; const char *_cert;
const char *_private_key; const char *_private_key;
@ -62,6 +63,7 @@ public:
void stop(); void stop();
uint8_t connected(); uint8_t connected();
int lastError(char *buf, const size_t size); int lastError(char *buf, const size_t size);
void setInsecure(); // Don't validate the chain, just accept whatever is given. VERY INSECURE!
void setPreSharedKey(const char *pskIdent, const char *psKey); // psKey in Hex void setPreSharedKey(const char *pskIdent, const char *psKey); // psKey in Hex
void setCACert(const char *rootCA); void setCACert(const char *rootCA);
void setCertificate(const char *client_ca); void setCertificate(const char *client_ca);

View File

@ -51,13 +51,17 @@ void ssl_init(sslclient_context *ssl_client)
} }
int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey) int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey, bool insecure)
{ {
char buf[512]; char buf[512];
int ret, flags; int ret, flags;
int enable = 1; int enable = 1;
log_v("Free internal heap before TLS %u", ESP.getFreeHeap()); log_v("Free internal heap before TLS %u", ESP.getFreeHeap());
if (rootCABuff == NULL && pskIdent == NULL && psKey == NULL && !insecure) {
return -1;
}
log_v("Starting socket"); log_v("Starting socket");
ssl_client->socket = -1; ssl_client->socket = -1;
@ -118,7 +122,10 @@ int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t p
// MBEDTLS_SSL_VERIFY_REQUIRED if a CA certificate is defined on Arduino IDE and // MBEDTLS_SSL_VERIFY_REQUIRED if a CA certificate is defined on Arduino IDE and
// MBEDTLS_SSL_VERIFY_NONE if not. // MBEDTLS_SSL_VERIFY_NONE if not.
if (rootCABuff != NULL) { if (insecure) {
mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_NONE);
log_i("WARNING: Skipping SSL Verification. INSECURE!");
} else if (rootCABuff != NULL) {
log_v("Loading CA cert"); log_v("Loading CA cert");
mbedtls_x509_crt_init(&ssl_client->ca_cert); mbedtls_x509_crt_init(&ssl_client->ca_cert);
mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED); mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
@ -126,8 +133,8 @@ int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t p
mbedtls_ssl_conf_ca_chain(&ssl_client->ssl_conf, &ssl_client->ca_cert, NULL); mbedtls_ssl_conf_ca_chain(&ssl_client->ssl_conf, &ssl_client->ca_cert, NULL);
//mbedtls_ssl_conf_verify(&ssl_client->ssl_ctx, my_verify, NULL ); //mbedtls_ssl_conf_verify(&ssl_client->ssl_ctx, my_verify, NULL );
if (ret < 0) { if (ret < 0) {
// free the ca_cert in the case parse failed, otherwise, the old ca_cert still in the heap memory, that lead to "out of memory" crash. // free the ca_cert in the case parse failed, otherwise, the old ca_cert still in the heap memory, that lead to "out of memory" crash.
mbedtls_x509_crt_free(&ssl_client->ca_cert); mbedtls_x509_crt_free(&ssl_client->ca_cert);
return handle_error(ret); return handle_error(ret);
} }
} else if (pskIdent != NULL && psKey != NULL) { } else if (pskIdent != NULL && psKey != NULL) {
@ -161,11 +168,10 @@ int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t p
return handle_error(ret); return handle_error(ret);
} }
} else { } else {
mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_NONE); return -1;
log_i("WARNING: Use certificates for a more secure communication!");
} }
if (cli_cert != NULL && cli_key != NULL) { if (!insecure && cli_cert != NULL && cli_key != NULL) {
mbedtls_x509_crt_init(&ssl_client->client_cert); mbedtls_x509_crt_init(&ssl_client->client_cert);
mbedtls_pk_init(&ssl_client->client_key); mbedtls_pk_init(&ssl_client->client_key);
@ -173,8 +179,8 @@ int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t p
ret = mbedtls_x509_crt_parse(&ssl_client->client_cert, (const unsigned char *)cli_cert, strlen(cli_cert) + 1); ret = mbedtls_x509_crt_parse(&ssl_client->client_cert, (const unsigned char *)cli_cert, strlen(cli_cert) + 1);
if (ret < 0) { if (ret < 0) {
// free the client_cert in the case parse failed, otherwise, the old client_cert still in the heap memory, that lead to "out of memory" crash. // free the client_cert in the case parse failed, otherwise, the old client_cert still in the heap memory, that lead to "out of memory" crash.
mbedtls_x509_crt_free(&ssl_client->client_cert); mbedtls_x509_crt_free(&ssl_client->client_cert);
return handle_error(ret); return handle_error(ret);
} }
@ -211,7 +217,7 @@ int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t p
} }
if((millis()-handshake_start_time)>ssl_client->handshake_timeout) if((millis()-handshake_start_time)>ssl_client->handshake_timeout)
return -1; return -1;
vTaskDelay(10 / portTICK_PERIOD_MS); vTaskDelay(2);//2 ticks
} }
@ -227,7 +233,7 @@ int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t p
log_v("Verifying peer X.509 certificate..."); log_v("Verifying peer X.509 certificate...");
if ((flags = mbedtls_ssl_get_verify_result(&ssl_client->ssl_ctx)) != 0) { if ((flags = mbedtls_ssl_get_verify_result(&ssl_client->ssl_ctx)) != 0) {
bzero(buf, sizeof(buf)); memset(buf, 0, sizeof(buf));
mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags); mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags);
log_e("Failed to verify peer certificate! verification info: %s", buf); log_e("Failed to verify peer certificate! verification info: %s", buf);
stop_ssl_socket(ssl_client, rootCABuff, cli_cert, cli_key); //It's not safe continue. stop_ssl_socket(ssl_client, rootCABuff, cli_cert, cli_key); //It's not safe continue.
@ -284,16 +290,18 @@ int data_to_read(sslclient_context *ssl_client)
return res; return res;
} }
int send_ssl_data(sslclient_context *ssl_client, const uint8_t *data, uint16_t len) int send_ssl_data(sslclient_context *ssl_client, const uint8_t *data, size_t len)
{ {
log_v("Writing HTTP request with %d bytes...", len); //for low level debug log_v("Writing HTTP request with %d bytes...", len); //for low level debug
int ret = -1; int ret = -1;
if ((ret = mbedtls_ssl_write(&ssl_client->ssl_ctx, data, len)) <= 0){ while ((ret = mbedtls_ssl_write(&ssl_client->ssl_ctx, data, len)) <= 0) {
log_v("Handling error %d", ret); //for low level debug if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret < 0) {
return handle_error(ret); log_v("Handling error %d", ret); //for low level debug
} else{ return handle_error(ret);
log_v("Returning with %d bytes written", ret); //for low level debug }
//wait for space to become available
vTaskDelay(2);
} }
return ret; return ret;

View File

@ -29,10 +29,10 @@ typedef struct sslclient_context {
void ssl_init(sslclient_context *ssl_client); void ssl_init(sslclient_context *ssl_client);
int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey); int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey, bool insecure);
void stop_ssl_socket(sslclient_context *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key); void stop_ssl_socket(sslclient_context *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key);
int data_to_read(sslclient_context *ssl_client); int data_to_read(sslclient_context *ssl_client);
int send_ssl_data(sslclient_context *ssl_client, const uint8_t *data, uint16_t len); int send_ssl_data(sslclient_context *ssl_client, const uint8_t *data, size_t len);
int get_ssl_receive(sslclient_context *ssl_client, uint8_t *data, int length); int get_ssl_receive(sslclient_context *ssl_client, uint8_t *data, int length);
bool verify_ssl_fingerprint(sslclient_context *ssl_client, const char* fp, const char* domain_name); bool verify_ssl_fingerprint(sslclient_context *ssl_client, const char* fp, const char* domain_name);
bool verify_ssl_dn(sslclient_context *ssl_client, const char* domain_name); bool verify_ssl_dn(sslclient_context *ssl_client, const char* domain_name);

View File

@ -1,4 +1,4 @@
#include "WiFi.h" #include "WiFiProv.h"
void SysProvEvent(system_event_t *sys_event,wifi_prov_event_t *prov_event) void SysProvEvent(system_event_t *sys_event,wifi_prov_event_t *prov_event)
{ {
if(sys_event) { if(sys_event) {
@ -56,8 +56,8 @@ void setup() {
/* uint8_t uuid[16] = {0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf, /* uint8_t uuid[16] = {0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf,
0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02 };*/ 0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02 };*/
WiFi.onEvent(SysProvEvent); WiFi.onEvent(SysProvEvent);
//WiFi.beginProvision(provSchemeBLE, WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, "abcd1234", "PROV_XXX", NULL, NULL); //WiFiProv.beginProvision(provSchemeBLE, WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, "abcd1234", "PROV_XXX", NULL, NULL);
WiFi.beginProvision(provSchemeSoftAP, WIFI_PROV_EVENT_HANDLER_NONE, WIFI_PROV_SECURITY_1, "abcd1234", NULL, NULL, NULL); WiFiProv.beginProvision(provSchemeSoftAP, WIFI_PROV_EVENT_HANDLER_NONE, WIFI_PROV_SECURITY_1, "abcd1234", NULL, NULL, NULL);
} }
void loop() { void loop() {

View File

@ -0,0 +1,9 @@
name=WiFiProv
version=1.0
author=Switi Mhaiske <sweetymhaiske@gmail.com>
maintainer=Hristo Gochkov <hristo@espressif.com>
sentence=Enables provisioning.
paragraph=With this library you can perform provisioning on esp32 via SoftAP or BLE.
category=Communication
url=
architectures=esp32

View File

@ -31,7 +31,8 @@
#include <wifi_provisioning/scheme_softap.h> #include <wifi_provisioning/scheme_softap.h>
#include <wifi_provisioning/manager.h> #include <wifi_provisioning/manager.h>
#undef IPADDR_NONE #undef IPADDR_NONE
#include "WiFi.h" #include "WiFiProv.h"
#include "SimpleBLE.h"
extern esp_err_t postToSysQueue(system_prov_event_t *); extern esp_err_t postToSysQueue(system_prov_event_t *);
@ -42,13 +43,6 @@ static const uint8_t custom_service_uuid[16] = { 0xb4, 0xdf, 0x5a, 0x1c, 0x3f,
#define SERV_NAME_PREFIX_PROV "PROV_" #define SERV_NAME_PREFIX_PROV "PROV_"
bool WiFiProvClass::prov_enable = true;
bool WiFiProvClass::isProvEnabled()
{
return prov_enable;
}
void provSchemeBLE() void provSchemeBLE()
{ {
prov_scheme = WIFI_PROV_SCHEME_BLE; prov_scheme = WIFI_PROV_SCHEME_BLE;
@ -109,7 +103,7 @@ static void get_device_service_name(char *service_name, size_t max)
void WiFiProvClass :: beginProvision(void (*scheme_cb)(), wifi_prov_event_handler_t scheme_event_handler, wifi_prov_security_t security, const char * pop, const char *service_name, const char *service_key, uint8_t * uuid) void WiFiProvClass :: beginProvision(void (*scheme_cb)(), wifi_prov_event_handler_t scheme_event_handler, wifi_prov_security_t security, const char * pop, const char *service_name, const char *service_key, uint8_t * uuid)
{ {
prov_enable = true; WiFi.enableProv(true);
bool provisioned = false; bool provisioned = false;
scheme_cb(); scheme_cb();
config.scheme_event_handler = scheme_event_handler; config.scheme_event_handler = scheme_event_handler;
@ -152,7 +146,7 @@ void WiFiProvClass :: beginProvision(void (*scheme_cb)(), wifi_prov_event_handle
} else { } else {
wifi_prov_mgr_deinit(); wifi_prov_mgr_deinit();
WiFi.mode(WIFI_MODE_STA); WiFi.mode(WIFI_MODE_STA);
log_i("Aleardy Provisioned, starting Wi-Fi STA"); log_i("Already Provisioned, starting Wi-Fi STA");
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
wifi_config_t conf; wifi_config_t conf;
esp_wifi_get_config(WIFI_IF_STA,&conf); esp_wifi_get_config(WIFI_IF_STA,&conf);
@ -162,4 +156,4 @@ void WiFiProvClass :: beginProvision(void (*scheme_cb)(), wifi_prov_event_handle
WiFi.begin(); WiFi.begin();
} }
} }
WiFiProvClass WiFiProv;

View File

@ -17,10 +17,9 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "WiFi.h"
#include "wifi_provisioning/manager.h" #include "wifi_provisioning/manager.h"
#include "wifi_provisioning/scheme_ble.h" #include "wifi_provisioning/scheme_ble.h"
#include "nvs_flash.h"
#include "SimpleBLE.h"
//Select the scheme using which you want to provision //Select the scheme using which you want to provision
typedef enum typedef enum
{ {
@ -34,19 +33,11 @@ extern void provSchemeBLE();
//Provisioning class //Provisioning class
class WiFiProvClass class WiFiProvClass
{ {
protected:
static bool prov_enable;
public: public:
WiFiProvClass() {
prov_enable = false;
}
bool isProvEnabled(); void beginProvision(void (*scheme_cb)() = provSchemeSoftAP, wifi_prov_event_handler_t scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE, wifi_prov_security_t security = WIFI_PROV_SECURITY_1, const char * pop = "abcd1234", const char * service_name = NULL, const char * service_key = NULL, uint8_t *uuid = NULL);
void beginProvision(void (*scheme_cb)() = provSchemeSoftAP, wifi_prov_event_handler_t scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE, wifi_prov_security_t security = WIFI_PROV_SECURITY_1, const char * pop = "abcd1234", const char * service_name = NULL, const char * service_key = NULL, uint8_t *uuid = NULL);
}; };
extern WiFiProvClass WiFiProv;
/* /*
Event Handler for BLE Event Handler for BLE
- WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM - WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM

View File

@ -36,7 +36,7 @@
{ {
"packager": "esp32", "packager": "esp32",
"name": "xtensa-esp32-elf-gcc", "name": "xtensa-esp32-elf-gcc",
"version": "1.22.0-96-g2852398-5.2.0" "version": "1.22.0-97-gc752ad5-5.2.0"
}, },
{ {
"packager": "esp32", "packager": "esp32",
@ -54,49 +54,49 @@
"tools": [ "tools": [
{ {
"name": "xtensa-esp32-elf-gcc", "name": "xtensa-esp32-elf-gcc",
"version": "1.22.0-96-g2852398-5.2.0", "version": "1.22.0-97-gc752ad5-5.2.0",
"systems": [ "systems": [
{ {
"host": "i686-mingw32", "host": "i686-mingw32",
"url": "https://dl.espressif.com/dl/xtensa-esp32-elf-win32-1.22.0-96-g2852398-5.2.0.zip", "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/xtensa-esp32-elf-win32-1.22.0-97-gc752ad5-5.2.0.zip",
"archiveFileName": "xtensa-esp32-elf-win32-1.22.0-96-g2852398-5.2.0.zip", "archiveFileName": "xtensa-esp32-elf-win32-1.22.0-97-gc752ad5-5.2.0.zip",
"checksum": "SHA-256:8e2a2e25d4714ae6e4b992be1b1c261caed5b523b0cc0887b6749229c9febbb0", "checksum": "SHA-256:80571e5d5a63494f4fa758bb9d8fb882ba4059853a8c412a84d232dc1c1400e6",
"size": "125810912" "size": "125747216"
}, },
{ {
"host": "x86_64-apple-darwin", "host": "x86_64-apple-darwin",
"url": "https://dl.espressif.com/dl/xtensa-esp32-elf-macos-1.22.0-96-g2852398-5.2.0.tar.gz", "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/xtensa-esp32-elf-macos-1.22.0-97-gc752ad5-5.2.0.tar.gz",
"archiveFileName": "xtensa-esp32-elf-macos-1.22.0-96-g2852398-5.2.0.tar.gz", "archiveFileName": "xtensa-esp32-elf-macos-1.22.0-97-gc752ad5-5.2.0.tar.gz",
"checksum": "SHA-256:6aeae9547f0cd7e442d1df21821cea8b15d0a6ce349bbd86466e2997b738a99c", "checksum": "SHA-256:b1ce39a563ae359cf363fb7d8ee80cb1e5226fda83188203cff60f16f55e33ef",
"size": "50520203" "size": "50525386"
}, },
{ {
"host": "x86_64-pc-linux-gnu", "host": "x86_64-pc-linux-gnu",
"url": "https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-96-g2852398-5.2.0.tar.gz", "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/xtensa-esp32-elf-linux64-1.22.0-97-gc752ad5-5.2.0.tar.gz",
"archiveFileName": "xtensa-esp32-elf-linux64-1.22.0-96-g2852398-5.2.0.tar.gz", "archiveFileName": "xtensa-esp32-elf-linux64-1.22.0-97-gc752ad5-5.2.0.tar.gz",
"checksum": "SHA-256:798a8638f11ad37f41b9640582f869c61ffb4da6d932279fde94a2b636ad2dac", "checksum": "SHA-256:96f5f6e7611a0ed1dc47048c54c3113fc5cebffbf0ba90d8bfcd497afc7ef9f3",
"size": "44211883" "size": "44225380"
}, },
{ {
"host": "i686-pc-linux-gnu", "host": "i686-pc-linux-gnu",
"url": "https://dl.espressif.com/dl/xtensa-esp32-elf-linux32-1.22.0-96-g2852398-5.2.0.tar.gz", "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/xtensa-esp32-elf-linux32-1.22.0-97-gc752ad5-5.2.0.tar.gz",
"archiveFileName": "xtensa-esp32-elf-linux32-1.22.0-96-g2852398-5.2.0.tar.gz", "archiveFileName": "xtensa-esp32-elf-linux32-1.22.0-97-gc752ad5-5.2.0.tar.gz",
"checksum": "SHA-256:4eea601188aa8f3c3d45d7936ab4c0fabb75b4970dccf7a061de47dba49e377f", "checksum": "SHA-256:8094a2c30b474e99ce64dd0ba8f310c4614eb3b3cac884a3aea0fd5f565af119",
"size": "45563578" "size": "45575521"
}, },
{ {
"host": "arm-linux-gnueabihf", "host": "arm-linux-gnueabihf",
"url": "https://dl.espressif.com/dl/xtensa-esp32-elf-linux-armel-1.22.0-96-g2852398-5.2.0.tar.gz", "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/xtensa-esp32-elf-linux-armel-1.22.0-97-gc752ad5-5.2.0.tar.gz",
"archiveFileName": "xtensa-esp32-elf-linux-armel-1.22.0-96-g2852398-5.2.0.tar.gz", "archiveFileName": "xtensa-esp32-elf-linux-armel-1.22.0-97-gc752ad5-5.2.0.tar.gz",
"checksum": "SHA-256:abfe06522f7c3479f6c7434c4bf926c50fa2039362b96abe95fa1f05ec519a9b", "checksum": "SHA-256:d70d550f88448fa476b29fa50ef5502ab497a16ac7fa9ca24c6d0a39bb1e681e",
"size": "50670980" "size": "50657803"
}, },
{ {
"host": "aarch64-linux-gnu", "host": "aarch64-linux-gnu",
"url": "https://dl.espressif.com/dl/xtensa-esp32-elf-linux-armel-1.22.0-96-g2852398-5.2.0.tar.gz", "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/xtensa-esp32-elf-linux-armel-1.22.0-97-gc752ad5-5.2.0.tar.gz",
"archiveFileName": "xtensa-esp32-elf-linux-armel-1.22.0-96-g2852398-5.2.0.tar.gz", "archiveFileName": "xtensa-esp32-elf-linux-armel-1.22.0-97-gc752ad5-5.2.0.tar.gz",
"checksum": "SHA-256:abfe06522f7c3479f6c7434c4bf926c50fa2039362b96abe95fa1f05ec519a9b", "checksum": "SHA-256:d70d550f88448fa476b29fa50ef5502ab497a16ac7fa9ca24c6d0a39bb1e681e",
"size": "50670980" "size": "50657803"
} }
] ]
}, },
@ -106,42 +106,42 @@
"systems": [ "systems": [
{ {
"host": "i686-mingw32", "host": "i686-mingw32",
"url": "https://dl.espressif.com/dl/esptool-3.0.0.2-windows.zip", "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/esptool-3.0.0.2-windows.zip",
"archiveFileName": "esptool-3.0.0.2-windows.zip", "archiveFileName": "esptool-3.0.0.2-windows.zip",
"checksum": "SHA-256:b192bfc1545a3c92658ce586b4edcc2aca3f0ad4b3fa8417d658bc8a48f1387e", "checksum": "SHA-256:b192bfc1545a3c92658ce586b4edcc2aca3f0ad4b3fa8417d658bc8a48f1387e",
"size": "3434736" "size": "3434736"
}, },
{ {
"host": "x86_64-apple-darwin", "host": "x86_64-apple-darwin",
"url": "https://dl.espressif.com/dl/esptool-3.0.0.2-macos.tar.gz", "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/esptool-3.0.0.2-macos.tar.gz",
"archiveFileName": "esptool-3.0.0.2-macos.tar.gz", "archiveFileName": "esptool-3.0.0.2-macos.tar.gz",
"checksum": "SHA-256:9213f46d5aa865558da4a2ef4218e87eef4782779128083c15ce2b3e4d07a1ea", "checksum": "SHA-256:2cafab7f1ebce89475b84c115548eaace40b6366d7b3f9862cdb2fc64f806643",
"size": "3849615" "size": "3859642"
}, },
{ {
"host": "x86_64-pc-linux-gnu", "host": "x86_64-pc-linux-gnu",
"url": "https://dl.espressif.com/dl/esptool-3.0.0.2-linux.tar.gz", "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/esptool-3.0.0.2-linux.tar.gz",
"archiveFileName": "esptool-3.0.0.2-linux.tar.gz", "archiveFileName": "esptool-3.0.0.2-linux.tar.gz",
"checksum": "SHA-256:d5cb51da1c74ff69f81b820470d2ecccb5c7c3a2dec7776483d4c89588b00020", "checksum": "SHA-256:d5cb51da1c74ff69f81b820470d2ecccb5c7c3a2dec7776483d4c89588b00020",
"size": "57526" "size": "57526"
}, },
{ {
"host": "i686-pc-linux-gnu", "host": "i686-pc-linux-gnu",
"url": "https://dl.espressif.com/dl/esptool-3.0.0.2-linux.tar.gz", "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/esptool-3.0.0.2-linux.tar.gz",
"archiveFileName": "esptool-3.0.0.2-linux.tar.gz", "archiveFileName": "esptool-3.0.0.2-linux.tar.gz",
"checksum": "SHA-256:d5cb51da1c74ff69f81b820470d2ecccb5c7c3a2dec7776483d4c89588b00020", "checksum": "SHA-256:d5cb51da1c74ff69f81b820470d2ecccb5c7c3a2dec7776483d4c89588b00020",
"size": "57526" "size": "57526"
}, },
{ {
"host": "arm-linux-gnueabihf", "host": "arm-linux-gnueabihf",
"url": "https://dl.espressif.com/dl/esptool-3.0.0.2-linux.tar.gz", "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/esptool-3.0.0.2-linux.tar.gz",
"archiveFileName": "esptool-3.0.0.2-linux.tar.gz", "archiveFileName": "esptool-3.0.0.2-linux.tar.gz",
"checksum": "SHA-256:d5cb51da1c74ff69f81b820470d2ecccb5c7c3a2dec7776483d4c89588b00020", "checksum": "SHA-256:d5cb51da1c74ff69f81b820470d2ecccb5c7c3a2dec7776483d4c89588b00020",
"size": "57526" "size": "57526"
}, },
{ {
"host": "aarch64-linux-gnu", "host": "aarch64-linux-gnu",
"url": "https://dl.espressif.com/dl/esptool-3.0.0.2-linux.tar.gz", "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/esptool-3.0.0.2-linux.tar.gz",
"archiveFileName": "esptool-3.0.0.2-linux.tar.gz", "archiveFileName": "esptool-3.0.0.2-linux.tar.gz",
"checksum": "SHA-256:d5cb51da1c74ff69f81b820470d2ecccb5c7c3a2dec7776483d4c89588b00020", "checksum": "SHA-256:d5cb51da1c74ff69f81b820470d2ecccb5c7c3a2dec7776483d4c89588b00020",
"size": "57526" "size": "57526"
@ -193,6 +193,13 @@
"archiveFileName": "mkspiffs-0.2.3-arduino-esp32-linux-armhf.tar.gz", "archiveFileName": "mkspiffs-0.2.3-arduino-esp32-linux-armhf.tar.gz",
"checksum": "SHA-256:ade3dc00117912ac08a1bdbfbfe76b12d21a34bc5fa1de0cfc45fe7a8d0a0185", "checksum": "SHA-256:ade3dc00117912ac08a1bdbfbfe76b12d21a34bc5fa1de0cfc45fe7a8d0a0185",
"size": "40665" "size": "40665"
},
{
"host": "aarch64-linux-gnu",
"url": "https://github.com/igrr/mkspiffs/releases/download/0.2.3/mkspiffs-0.2.3-arduino-esp32-linux-armhf.tar.gz",
"archiveFileName": "mkspiffs-0.2.3-arduino-esp32-linux-armhf.tar.gz",
"checksum": "SHA-256:ade3dc00117912ac08a1bdbfbfe76b12d21a34bc5fa1de0cfc45fe7a8d0a0185",
"size": "40665"
} }
] ]
} }

View File

@ -22,7 +22,7 @@ compiler.warning_flags.all=-Wall -Werror=all -Wextra
compiler.path={runtime.tools.xtensa-esp32-elf-gcc.path}/bin/ compiler.path={runtime.tools.xtensa-esp32-elf-gcc.path}/bin/
compiler.sdk.path={runtime.platform.path}/tools/sdk compiler.sdk.path={runtime.platform.path}/tools/sdk
compiler.cpreprocessor.flags=-DESP_PLATFORM -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h" -DHAVE_CONFIG_H -DGCC_NOT_5_2_0=0 -DWITH_POSIX "-I{compiler.sdk.path}/include/config" "-I{compiler.sdk.path}/include/app_trace" "-I{compiler.sdk.path}/include/app_update" "-I{compiler.sdk.path}/include/asio" "-I{compiler.sdk.path}/include/bootloader_support" "-I{compiler.sdk.path}/include/bt" "-I{compiler.sdk.path}/include/coap" "-I{compiler.sdk.path}/include/console" "-I{compiler.sdk.path}/include/driver" "-I{compiler.sdk.path}/include/efuse" "-I{compiler.sdk.path}/include/esp-tls" "-I{compiler.sdk.path}/include/esp32" "-I{compiler.sdk.path}/include/esp_adc_cal" "-I{compiler.sdk.path}/include/esp_event" "-I{compiler.sdk.path}/include/esp_http_client" "-I{compiler.sdk.path}/include/esp_http_server" "-I{compiler.sdk.path}/include/esp_https_ota" "-I{compiler.sdk.path}/include/esp_https_server" "-I{compiler.sdk.path}/include/esp_ringbuf" "-I{compiler.sdk.path}/include/esp_websocket_client" "-I{compiler.sdk.path}/include/espcoredump" "-I{compiler.sdk.path}/include/ethernet" "-I{compiler.sdk.path}/include/expat" "-I{compiler.sdk.path}/include/fatfs" "-I{compiler.sdk.path}/include/freemodbus" "-I{compiler.sdk.path}/include/freertos" "-I{compiler.sdk.path}/include/heap" "-I{compiler.sdk.path}/include/idf_test" "-I{compiler.sdk.path}/include/jsmn" "-I{compiler.sdk.path}/include/json" "-I{compiler.sdk.path}/include/libsodium" "-I{compiler.sdk.path}/include/log" "-I{compiler.sdk.path}/include/lwip" "-I{compiler.sdk.path}/include/mbedtls" "-I{compiler.sdk.path}/include/mdns" "-I{compiler.sdk.path}/include/micro-ecc" "-I{compiler.sdk.path}/include/mqtt" "-I{compiler.sdk.path}/include/newlib" "-I{compiler.sdk.path}/include/nghttp" "-I{compiler.sdk.path}/include/nimble" "-I{compiler.sdk.path}/include/nvs_flash" "-I{compiler.sdk.path}/include/openssl" "-I{compiler.sdk.path}/include/protobuf-c" "-I{compiler.sdk.path}/include/protocomm" "-I{compiler.sdk.path}/include/pthread" "-I{compiler.sdk.path}/include/sdmmc" "-I{compiler.sdk.path}/include/smartconfig_ack" "-I{compiler.sdk.path}/include/soc" "-I{compiler.sdk.path}/include/spi_flash" "-I{compiler.sdk.path}/include/spiffs" "-I{compiler.sdk.path}/include/tcp_transport" "-I{compiler.sdk.path}/include/tcpip_adapter" "-I{compiler.sdk.path}/include/ulp" "-I{compiler.sdk.path}/include/unity" "-I{compiler.sdk.path}/include/vfs" "-I{compiler.sdk.path}/include/wear_levelling" "-I{compiler.sdk.path}/include/wifi_provisioning" "-I{compiler.sdk.path}/include/wpa_supplicant" "-I{compiler.sdk.path}/include/xtensa-debug-module" "-I{compiler.sdk.path}/include/esp-face" "-I{compiler.sdk.path}/include/esp32-camera" "-I{compiler.sdk.path}/include/esp-face" "-I{compiler.sdk.path}/include/fb_gfx" compiler.cpreprocessor.flags=-DESP_PLATFORM -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h" -DHAVE_CONFIG_H -DGCC_NOT_5_2_0=0 -DWITH_POSIX "-I{compiler.sdk.path}/include/config" "-I{compiler.sdk.path}/include/app_trace" "-I{compiler.sdk.path}/include/app_update" "-I{compiler.sdk.path}/include/asio" "-I{compiler.sdk.path}/include/bootloader_support" "-I{compiler.sdk.path}/include/bt" "-I{compiler.sdk.path}/include/coap" "-I{compiler.sdk.path}/include/console" "-I{compiler.sdk.path}/include/driver" "-I{compiler.sdk.path}/include/efuse" "-I{compiler.sdk.path}/include/esp-tls" "-I{compiler.sdk.path}/include/esp32" "-I{compiler.sdk.path}/include/esp_adc_cal" "-I{compiler.sdk.path}/include/esp_event" "-I{compiler.sdk.path}/include/esp_http_client" "-I{compiler.sdk.path}/include/esp_http_server" "-I{compiler.sdk.path}/include/esp_https_ota" "-I{compiler.sdk.path}/include/esp_https_server" "-I{compiler.sdk.path}/include/esp_ringbuf" "-I{compiler.sdk.path}/include/esp_websocket_client" "-I{compiler.sdk.path}/include/espcoredump" "-I{compiler.sdk.path}/include/ethernet" "-I{compiler.sdk.path}/include/expat" "-I{compiler.sdk.path}/include/fatfs" "-I{compiler.sdk.path}/include/freemodbus" "-I{compiler.sdk.path}/include/freertos" "-I{compiler.sdk.path}/include/heap" "-I{compiler.sdk.path}/include/idf_test" "-I{compiler.sdk.path}/include/jsmn" "-I{compiler.sdk.path}/include/json" "-I{compiler.sdk.path}/include/libsodium" "-I{compiler.sdk.path}/include/log" "-I{compiler.sdk.path}/include/lwip" "-I{compiler.sdk.path}/include/mbedtls" "-I{compiler.sdk.path}/include/mdns" "-I{compiler.sdk.path}/include/micro-ecc" "-I{compiler.sdk.path}/include/mqtt" "-I{compiler.sdk.path}/include/newlib" "-I{compiler.sdk.path}/include/nghttp" "-I{compiler.sdk.path}/include/nvs_flash" "-I{compiler.sdk.path}/include/openssl" "-I{compiler.sdk.path}/include/protobuf-c" "-I{compiler.sdk.path}/include/protocomm" "-I{compiler.sdk.path}/include/pthread" "-I{compiler.sdk.path}/include/sdmmc" "-I{compiler.sdk.path}/include/smartconfig_ack" "-I{compiler.sdk.path}/include/soc" "-I{compiler.sdk.path}/include/spi_flash" "-I{compiler.sdk.path}/include/spiffs" "-I{compiler.sdk.path}/include/tcp_transport" "-I{compiler.sdk.path}/include/tcpip_adapter" "-I{compiler.sdk.path}/include/ulp" "-I{compiler.sdk.path}/include/unity" "-I{compiler.sdk.path}/include/vfs" "-I{compiler.sdk.path}/include/wear_levelling" "-I{compiler.sdk.path}/include/wifi_provisioning" "-I{compiler.sdk.path}/include/wpa_supplicant" "-I{compiler.sdk.path}/include/xtensa-debug-module" "-I{compiler.sdk.path}/include/esp-face" "-I{compiler.sdk.path}/include/esp32-camera" "-I{compiler.sdk.path}/include/esp-face" "-I{compiler.sdk.path}/include/fb_gfx"
compiler.c.cmd=xtensa-esp32-elf-gcc compiler.c.cmd=xtensa-esp32-elf-gcc
compiler.c.flags=-std=gnu99 -Os -g3 -fstack-protector -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wpointer-arith {compiler.warning_flags} -Wno-maybe-uninitialized -Wno-unused-function -Wno-unused-but-set-variable -Wno-unused-variable -Wno-deprecated-declarations -Wno-unused-parameter -Wno-sign-compare -Wno-old-style-declaration -MMD -c compiler.c.flags=-std=gnu99 -Os -g3 -fstack-protector -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wpointer-arith {compiler.warning_flags} -Wno-maybe-uninitialized -Wno-unused-function -Wno-unused-but-set-variable -Wno-unused-variable -Wno-deprecated-declarations -Wno-unused-parameter -Wno-sign-compare -Wno-old-style-declaration -MMD -c
@ -34,8 +34,8 @@ compiler.S.cmd=xtensa-esp32-elf-gcc
compiler.S.flags=-c -g3 -x assembler-with-cpp -MMD -mlongcalls compiler.S.flags=-c -g3 -x assembler-with-cpp -MMD -mlongcalls
compiler.c.elf.cmd=xtensa-esp32-elf-gcc compiler.c.elf.cmd=xtensa-esp32-elf-gcc
compiler.c.elf.flags=-nostdlib "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" -T esp32_out.ld -T esp32.project.ld -T esp32.rom.ld -T esp32.peripherals.ld -T esp32.rom.libgcc.ld -T esp32.rom.spiram_incompatible_fns.ld -u ld_include_panic_highint_hdl -u call_user_start_cpu0 -Wl,--gc-sections -Wl,-static -Wl,--undefined=uxTopUsedPriority -u __cxa_guard_dummy -u __cxx_fatal_exception compiler.c.elf.flags=-nostdlib "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" -T esp32_out.ld -T esp32.project.ld -T esp32.rom.ld -T esp32.peripherals.ld -T esp32.rom.libgcc.ld -T esp32.rom.spiram_incompatible_fns.ld -u esp_app_desc -u ld_include_panic_highint_hdl -u call_user_start_cpu0 -Wl,--gc-sections -Wl,-static -Wl,--undefined=uxTopUsedPriority -u __cxa_guard_dummy -u __cxx_fatal_exception
compiler.c.elf.libs=-lgcc -lopenssl -lbtdm_app -lfatfs -lwps -lcoexist -lwear_levelling -lesp_http_client -lprotobuf-c -lhal -lnewlib -ldriver -lbootloader_support -lpp -lfreemodbus -lmesh -lsmartconfig -ljsmn -lwpa -lethernet -lphy -lapp_trace -lconsole -lulp -lwpa_supplicant -lfreertos -lbt -lmicro-ecc -lesp32-camera -lcxx -lxtensa-debug-module -ltcp_transport -lod -lmdns -ldetection -lvfs -lpe -lesp_websocket_client -lespcoredump -lesp_ringbuf -lsoc -lcore -lfb_gfx -lsdmmc -llibsodium -lcoap -ltcpip_adapter -lprotocomm -lesp_event -limage_util -lc_nano -lesp-tls -lasio -lrtc -lspi_flash -lwpa2 -lwifi_provisioning -lesp32 -lface_recognition -lapp_update -lnghttp -ldl -lspiffs -lface_detection -lefuse -lunity -lesp_https_server -lespnow -lnvs_flash -lesp_adc_cal -llog -ldetection_cat_face -lsmartconfig_ack -lexpat -lm -lfr -lmqtt -lc -lheap -lmbedtls -llwip -lnet80211 -lesp_http_server -lpthread -ljson -lesp_https_ota -lfd -lstdc++ compiler.c.elf.libs=-lgcc -lesp_websocket_client -lwpa2 -ldetection -lesp_https_server -lwps -lhal -lconsole -lpe -lsoc -lsdmmc -lpthread -llog -lesp_http_client -ljson -lmesh -lesp32-camera -lnet80211 -lwpa_supplicant -lc -lmqtt -lcxx -lesp_https_ota -lulp -lefuse -lpp -lmdns -lbt -lwpa -lspiffs -lheap -limage_util -lunity -lrtc -lmbedtls -lface_recognition -lnghttp -ljsmn -lopenssl -lcore -lfatfs -lm -lprotocomm -lsmartconfig -lxtensa-debug-module -ldl -lesp_event -lesp-tls -lfd -lespcoredump -lesp_http_server -lfr -lsmartconfig_ack -lwear_levelling -ltcp_transport -llwip -lphy -lvfs -lcoap -lesp32 -llibsodium -lbootloader_support -ldriver -lcoexist -lasio -lod -lmicro-ecc -lesp_ringbuf -ldetection_cat_face -lapp_update -lespnow -lface_detection -lapp_trace -lnewlib -lbtdm_app -lwifi_provisioning -lfreertos -lfreemodbus -lethernet -lnvs_flash -lspi_flash -lc_nano -lexpat -lfb_gfx -lprotobuf-c -lesp_adc_cal -ltcpip_adapter -lstdc++
compiler.as.cmd=xtensa-esp32-elf-as compiler.as.cmd=xtensa-esp32-elf-as
@ -53,6 +53,7 @@ build.boot=bootloader
build.code_debug=0 build.code_debug=0
build.defines= build.defines=
build.extra_flags=-DESP32 -DCORE_DEBUG_LEVEL={build.code_debug} {build.defines} build.extra_flags=-DESP32 -DCORE_DEBUG_LEVEL={build.code_debug} {build.defines}
build.extra_libs=
# These can be overridden in platform.local.txt # These can be overridden in platform.local.txt
compiler.c.extra_flags= compiler.c.extra_flags=
@ -66,8 +67,8 @@ compiler.libraries.ldflags=
# Build Dir: {build.path} # Build Dir: {build.path}
# Sketch Dir: {build.source.path} # Sketch Dir: {build.source.path}
recipe.hooks.prebuild.1.pattern=bash -c "[ ! -f {build.source.path}/partitions.csv ] || cp -f {build.source.path}/partitions.csv {build.path}/partitions.csv" recipe.hooks.prebuild.1.pattern=bash -c "[ ! -f "{build.source.path}"/partitions.csv ] || cp -f "{build.source.path}"/partitions.csv "{build.path}"/partitions.csv"
recipe.hooks.prebuild.2.pattern=bash -c "[ -f {build.path}/partitions.csv ] || cp {runtime.platform.path}/tools/partitions/{build.partitions}.csv {build.path}/partitions.csv" recipe.hooks.prebuild.2.pattern=bash -c "[ -f "{build.path}"/partitions.csv ] || cp "{runtime.platform.path}"/tools/partitions/{build.partitions}.csv "{build.path}"/partitions.csv"
recipe.hooks.prebuild.1.pattern.windows=cmd /c if exist "{build.source.path}\partitions.csv" copy /y "{build.source.path}\partitions.csv" "{build.path}\partitions.csv" recipe.hooks.prebuild.1.pattern.windows=cmd /c if exist "{build.source.path}\partitions.csv" copy /y "{build.source.path}\partitions.csv" "{build.path}\partitions.csv"
recipe.hooks.prebuild.2.pattern.windows=cmd /c if not exist "{build.path}\partitions.csv" copy "{runtime.platform.path}\tools\partitions\{build.partitions}.csv" "{build.path}\partitions.csv" recipe.hooks.prebuild.2.pattern.windows=cmd /c if not exist "{build.path}\partitions.csv" copy "{runtime.platform.path}\tools\partitions\{build.partitions}.csv" "{build.path}\partitions.csv"
@ -84,7 +85,7 @@ recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.fla
recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}"
## Combine gc-sections, archives, and objects ## Combine gc-sections, archives, and objects
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} {compiler.libraries.ldflags} -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} -Wl,--end-group -Wl,-EL -o "{build.path}/{build.project_name}.elf" recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} {compiler.libraries.ldflags} -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} {build.extra_libs} -Wl,--end-group -Wl,-EL -o "{build.path}/{build.project_name}.elf"
## Create partitions.bin ## Create partitions.bin
recipe.objcopy.partitions.bin.pattern={tools.gen_esp32part.cmd} -q "{build.path}/partitions.csv" "{build.path}/{build.project_name}.partitions.bin" recipe.objcopy.partitions.bin.pattern={tools.gen_esp32part.cmd} -q "{build.path}/partitions.csv" "{build.path}/{build.project_name}.partitions.bin"

File diff suppressed because it is too large Load Diff

View File

@ -138,7 +138,6 @@ env.Append(
join(FRAMEWORK_DIR, "tools", "sdk", "include", "mqtt"), join(FRAMEWORK_DIR, "tools", "sdk", "include", "mqtt"),
join(FRAMEWORK_DIR, "tools", "sdk", "include", "newlib"), join(FRAMEWORK_DIR, "tools", "sdk", "include", "newlib"),
join(FRAMEWORK_DIR, "tools", "sdk", "include", "nghttp"), join(FRAMEWORK_DIR, "tools", "sdk", "include", "nghttp"),
join(FRAMEWORK_DIR, "tools", "sdk", "include", "nimble"),
join(FRAMEWORK_DIR, "tools", "sdk", "include", "nvs_flash"), join(FRAMEWORK_DIR, "tools", "sdk", "include", "nvs_flash"),
join(FRAMEWORK_DIR, "tools", "sdk", "include", "openssl"), join(FRAMEWORK_DIR, "tools", "sdk", "include", "openssl"),
join(FRAMEWORK_DIR, "tools", "sdk", "include", "protobuf-c"), join(FRAMEWORK_DIR, "tools", "sdk", "include", "protobuf-c"),
@ -171,7 +170,7 @@ env.Append(
], ],
LIBS=[ LIBS=[
"-lgcc", "-lopenssl", "-lbtdm_app", "-lfatfs", "-lwps", "-lcoexist", "-lwear_levelling", "-lesp_http_client", "-lprotobuf-c", "-lhal", "-lnewlib", "-ldriver", "-lbootloader_support", "-lpp", "-lfreemodbus", "-lmesh", "-lsmartconfig", "-ljsmn", "-lwpa", "-lethernet", "-lphy", "-lapp_trace", "-lconsole", "-lulp", "-lwpa_supplicant", "-lfreertos", "-lbt", "-lmicro-ecc", "-lesp32-camera", "-lcxx", "-lxtensa-debug-module", "-ltcp_transport", "-lod", "-lmdns", "-ldetection", "-lvfs", "-lpe", "-lesp_websocket_client", "-lespcoredump", "-lesp_ringbuf", "-lsoc", "-lcore", "-lfb_gfx", "-lsdmmc", "-llibsodium", "-lcoap", "-ltcpip_adapter", "-lprotocomm", "-lesp_event", "-limage_util", "-lc_nano", "-lesp-tls", "-lasio", "-lrtc", "-lspi_flash", "-lwpa2", "-lwifi_provisioning", "-lesp32", "-lface_recognition", "-lapp_update", "-lnghttp", "-ldl", "-lspiffs", "-lface_detection", "-lefuse", "-lunity", "-lesp_https_server", "-lespnow", "-lnvs_flash", "-lesp_adc_cal", "-llog", "-ldetection_cat_face", "-lsmartconfig_ack", "-lexpat", "-lm", "-lfr", "-lmqtt", "-lc", "-lheap", "-lmbedtls", "-llwip", "-lnet80211", "-lesp_http_server", "-lpthread", "-ljson", "-lesp_https_ota", "-lfd", "-lstdc++" "-lgcc", "-lesp_websocket_client", "-lwpa2", "-ldetection", "-lesp_https_server", "-lwps", "-lhal", "-lconsole", "-lpe", "-lsoc", "-lsdmmc", "-lpthread", "-llog", "-lesp_http_client", "-ljson", "-lmesh", "-lesp32-camera", "-lnet80211", "-lwpa_supplicant", "-lc", "-lmqtt", "-lcxx", "-lesp_https_ota", "-lulp", "-lefuse", "-lpp", "-lmdns", "-lbt", "-lwpa", "-lspiffs", "-lheap", "-limage_util", "-lunity", "-lrtc", "-lmbedtls", "-lface_recognition", "-lnghttp", "-ljsmn", "-lopenssl", "-lcore", "-lfatfs", "-lm", "-lprotocomm", "-lsmartconfig", "-lxtensa-debug-module", "-ldl", "-lesp_event", "-lesp-tls", "-lfd", "-lespcoredump", "-lesp_http_server", "-lfr", "-lsmartconfig_ack", "-lwear_levelling", "-ltcp_transport", "-llwip", "-lphy", "-lvfs", "-lcoap", "-lesp32", "-llibsodium", "-lbootloader_support", "-ldriver", "-lcoexist", "-lasio", "-lod", "-lmicro-ecc", "-lesp_ringbuf", "-ldetection_cat_face", "-lapp_update", "-lespnow", "-lface_detection", "-lapp_trace", "-lnewlib", "-lbtdm_app", "-lwifi_provisioning", "-lfreertos", "-lfreemodbus", "-lethernet", "-lnvs_flash", "-lspi_flash", "-lc_nano", "-lexpat", "-lfb_gfx", "-lprotobuf-c", "-lesp_adc_cal", "-ltcpip_adapter", "-lstdc++"
], ],
LIBSOURCE_DIRS=[ LIBSOURCE_DIRS=[
@ -188,6 +187,14 @@ env.Append(
if not env.BoardConfig().get("build.ldscript", ""): if not env.BoardConfig().get("build.ldscript", ""):
env.Replace(LDSCRIPT_PATH=env.BoardConfig().get("build.arduino.ldscript", "")) env.Replace(LDSCRIPT_PATH=env.BoardConfig().get("build.arduino.ldscript", ""))
#
# Add PSRAM-specific libraries
#
flatten_cppdefines = env.Flatten(env["CPPDEFINES"])
if "BOARD_HAS_PSRAM" in flatten_cppdefines:
env.Append(LIBS=["c-psram-workaround", "m-psram-workaround"])
# #
# Target: Build Core Library # Target: Build Core Library
# #
@ -224,7 +231,9 @@ env.Prepend(LIBS=libs)
# #
fwpartitions_dir = join(FRAMEWORK_DIR, "tools", "partitions") fwpartitions_dir = join(FRAMEWORK_DIR, "tools", "partitions")
partitions_csv = env.BoardConfig().get("build.partitions", "default.csv") partitions_csv = env.BoardConfig().get("build.arduino.partitions", "default.csv")
if "build.partitions" in env.BoardConfig():
partitions_csv = env.BoardConfig().get("build.partitions")
env.Replace( env.Replace(
PARTITIONS_TABLE_CSV=abspath( PARTITIONS_TABLE_CSV=abspath(
join(fwpartitions_dir, partitions_csv) if isfile( join(fwpartitions_dir, partitions_csv) if isfile(

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -110,7 +110,11 @@ esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length);
* is enabled but secure boot is not used. This should protect against * is enabled but secure boot is not used. This should protect against
* serial re-flashing of an unauthorised code in absence of secure boot. * serial re-flashing of an unauthorised code in absence of secure boot.
* *
* @return * @note To support disabling UART Download Mode on ESP32 V3 only, this function
* doesn't write protect FLASH_CRYPT_CNT but instead sets it to the max value
* (effectively the same result but allows burning the UART_DL_DIS efuse later on,
* as this is otherwise also disabled if FLASH_CRYPT_CNT is write protected.)
*
*/ */
void esp_flash_write_protect_crypt_cnt(); void esp_flash_write_protect_crypt_cnt();

View File

@ -454,28 +454,6 @@ esp_err_t esp_bt_sleep_enable(void);
*/ */
esp_err_t esp_bt_sleep_disable(void); esp_err_t esp_bt_sleep_disable(void);
/**
* @brief to check whether bluetooth controller is sleeping at the instant, if modem sleep is enabled
*
* Note that this function shall not be invoked before esp_bt_controller_enable()
* This function is supposed to be used ORIG mode of modem sleep
*
* @return true if in modem sleep state, false otherwise
*/
bool esp_bt_controller_is_sleeping(void);
/**
* @brief request controller to wakeup from sleeping state during sleep mode
*
* Note that this function shall not be invoked before esp_bt_controller_enable()
* Note that this function is supposed to be used ORIG mode of modem sleep
* Note that after this request, bluetooth controller may again enter sleep as long as the modem sleep is enabled
*
* Profiling shows that it takes several milliseconds to wakeup from modem sleep after this request.
* Generally it takes longer if 32kHz XTAL is used than the main XTAL, due to the lower frequency of the former as the bluetooth low power clock source.
*/
void esp_bt_controller_wakeup_request(void);
/** /**
* @brief Manually clear scan duplicate list * @brief Manually clear scan duplicate list
* *

View File

@ -287,6 +287,8 @@ typedef enum {
ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTH, ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTH,
/* Enable/Disable OOB support */ /* Enable/Disable OOB support */
ESP_BLE_SM_OOB_SUPPORT, ESP_BLE_SM_OOB_SUPPORT,
/* Appl encryption key size */
ESP_BLE_APP_ENC_KEY_SIZE,
ESP_BLE_SM_MAX_PARAM, ESP_BLE_SM_MAX_PARAM,
} esp_ble_sm_param_t; } esp_ble_sm_param_t;
@ -895,7 +897,7 @@ esp_err_t esp_ble_gap_update_conn_params(esp_ble_conn_update_params_t *params);
esp_err_t esp_ble_gap_set_pkt_data_len(esp_bd_addr_t remote_device, uint16_t tx_data_length); esp_err_t esp_ble_gap_set_pkt_data_len(esp_bd_addr_t remote_device, uint16_t tx_data_length);
/** /**
* @brief This function sets the random address for the application * @brief This function sets the static Random Address and Non-Resolvable Private Address for the application
* *
* @param[in] rand_addr: the random address which should be setting * @param[in] rand_addr: the random address which should be setting
* *
@ -1243,6 +1245,18 @@ esp_err_t esp_ble_oob_req_reply(esp_bd_addr_t bd_addr, uint8_t *TK, uint8_t len)
*/ */
esp_err_t esp_ble_gap_disconnect(esp_bd_addr_t remote_device); esp_err_t esp_ble_gap_disconnect(esp_bd_addr_t remote_device);
/**
* @brief This function is called to authorized a link after Authentication(MITM protection)
*
* @param[in] bd_addr: BD address of the peer device.
* @param[out] authorize: Authorized the link or not.
*
* @return - ESP_OK : success
* - other : failed
*
*/
esp_err_t esp_gap_ble_set_authorization(esp_bd_addr_t bd_addr, bool authorize);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -278,6 +278,8 @@ typedef enum {
#define ESP_GATT_PERM_WRITE_ENC_MITM (1 << 6) /* bit 6 - 0x0040 */ /* relate to BTA_GATT_PERM_WRITE_ENC_MITM in bta/bta_gatt_api.h */ #define ESP_GATT_PERM_WRITE_ENC_MITM (1 << 6) /* bit 6 - 0x0040 */ /* relate to BTA_GATT_PERM_WRITE_ENC_MITM in bta/bta_gatt_api.h */
#define ESP_GATT_PERM_WRITE_SIGNED (1 << 7) /* bit 7 - 0x0080 */ /* relate to BTA_GATT_PERM_WRITE_SIGNED in bta/bta_gatt_api.h */ #define ESP_GATT_PERM_WRITE_SIGNED (1 << 7) /* bit 7 - 0x0080 */ /* relate to BTA_GATT_PERM_WRITE_SIGNED in bta/bta_gatt_api.h */
#define ESP_GATT_PERM_WRITE_SIGNED_MITM (1 << 8) /* bit 8 - 0x0100 */ /* relate to BTA_GATT_PERM_WRITE_SIGNED_MITM in bta/bta_gatt_api.h */ #define ESP_GATT_PERM_WRITE_SIGNED_MITM (1 << 8) /* bit 8 - 0x0100 */ /* relate to BTA_GATT_PERM_WRITE_SIGNED_MITM in bta/bta_gatt_api.h */
#define ESP_GATT_PERM_READ_AUTHORIZATION (1 << 9) /* bit 9 - 0x0200 */
#define ESP_GATT_PERM_WRITE_AUTHORIZATION (1 << 10) /* bit 10 - 0x0400 */
typedef uint16_t esp_gatt_perm_t; typedef uint16_t esp_gatt_perm_t;
/* relate to BTA_GATT_CHAR_PROP_BIT_xxx in bta/bta_gatt_api.h */ /* relate to BTA_GATT_CHAR_PROP_BIT_xxx in bta/bta_gatt_api.h */

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