Compare commits

...

233 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
6d256b6454 IDF release/v3.3 68b237fe5 with Disable IRAM optimisation for WiFi 2020-11-16 13:06:50 +02:00
f6bf0f7aa2 IDF release/v3.3 68b237fe5 2020-11-16 12:44:07 +02:00
a59eb5d51e Merge branch 'master' into idf-release/v3.3 2020-11-16 12:09:23 +02:00
adafd9d7c0 Merge pull request #4538 from loick111/feature/custom_variants_dir
The goal is to allow custom configuration for `variants_dir` to define our own board variant directly in the project.

With this functionnality, we are now allowed to define in our projects a custom board **AND** a custom variant.
https://docs.platformio.org/en/latest/platforms/creating_board.html#custom-embedded-boards

Here is an example of how to define a custom board with custom variant:
```
my_project
├── boards
│   └── custom_esp32dev.json
└── variants
    └── custom-esp32dev
        └── pins_arduino.h
```

custom_esp32dev.json
```json
{
  "build": {
    "arduino":{
      "ldscript": "esp32_out.ld"
    },
    "core": "esp32",
    "extra_flags": "-DARDUINO_ESP32_DEV",
    "f_cpu": "240000000L",
    "f_flash": "40000000L",
    "flash_mode": "dio",
    "mcu": "esp32",
    "variants_dir": "variants",
    "variant": "custom-esp32dev"
  },
  "connectivity": [
    "wifi",
    "bluetooth",
    "ethernet",
    "can"
  ],
  "debug": {
    "openocd_board": "esp-wroom-32.cfg"
  },
  "frameworks": [
    "arduino",
    "espidf"
  ],
  "name": "My Custom Espressif ESP32 Dev Module",
  "upload": {
    "flash_size": "4MB",
    "maximum_ram_size": 327680,
    "maximum_size": 4194304,
    "require_upload_port": true,
    "speed": 460800
  },
  "url": "https://en.wikipedia.org/wiki/ESP32",
  "vendor": "Espressif"
}
```
2020-11-15 20:43:43 +02:00
ac9fdeffe4 Allow custom variants directory 2020-11-15 16:20:02 +01:00
cee7b4237c Merge branch 'master' into idf-release/v3.3 2020-11-15 12:02:51 +02:00
954df2fc3e Disable IRAM optimization for WiFi 2020-11-15 11:56:01 +02:00
e41fb08b2a Update esptool to work on BigSur 2020-11-15 08:53:07 +02:00
d8b1fc81c0 Added usedBytes to match other filesystems (#4534) 2020-11-15 08:48:21 +02:00
378b6ac032 Fix issue in webserver with Chrome based browsers
https://github.com/espressif/arduino-esp32/issues/3652
2020-11-15 08:46:23 +02:00
cecef8e930 IDF release/v3.3 68b237fe5 2020-11-14 00:33:27 +00:00
a8e99baeab Merge branch 'master' into idf-release/v3.3 2020-11-12 21:29:57 +02:00
b6cc108d49 Update WiFiProv.cpp (#4519)
Do not pollute the global namespace with generic names like 'config' by declaring global variables 'static'.
2020-11-10 20:51:10 +02:00
8816bb5505 Added #define LED_BUILTIN to all pins_arduino.h that need it. (#4520) 2020-11-10 20:50:35 +02:00
3274602eb0 Notify the batteryLevel change (#4517) 2020-11-10 13:02:00 +02:00
534f0810a6 fix bitWrite macro (#4507)
Fixes https://github.com/espressif/arduino-esp32/issues/4466
2020-11-09 17:08:13 +02:00
28a8073069 Fix issue 4095 (#4503)
pgmspace.h missing 'pgm_get_far_address'
2020-11-08 04:55:59 +02:00
7494c4e76d IDF release/v3.3 44ec7972b 2020-11-08 00:36:32 +00:00
486a4c66c4 SDCARD: First sector always written twice if multiple sectors are updated 2020-11-06 22:20:20 +02:00
c1951670d1 IDF release/v3.3 66d3783c8 2020-11-06 18:15:23 +00:00
ad07d36932 Update README.md 2020-11-06 17:21:12 +02:00
c6a8da61f7 Allow faster reuse of socket, to be able to restart WifiServer. (#4306)
See #3960 for more details of the problem and the solution. I only implemented what was proposed in this ticket, as it solves my problem, which was the same as in this ticket. Credits for the code going to @etrinh ;-)

This also is a more consistence behaviour compared to esp8266, where it also is possible to restart the wifiserver immediately on the same port.
2020-11-06 14:16:50 +02:00
dd1a15478f add TimerCAM and CoreInk board (#4498) 2020-11-06 13:30:57 +02:00
bcb7012a32 Change variants folder T-Beam (#4496) 2020-11-06 12:42:18 +02:00
3968821834 HttpClient uses Serial.printf() (#4488)
changed to log_d()
2020-11-04 14:49:33 +02:00
90f869e772 Fix BUG: Parsing of first line fails (#4484)
..because a firstLine = false; is missing ;)
2020-11-04 02:24:01 +02:00
be4d3b6cb8 Try to fix issue with GIT 2.29.0 2020-11-03 22:22:35 +02:00
60606e5ad0 Update on-release.sh 2020-11-03 21:53:22 +02:00
22b427df0f IDF release/v3.3 (#3672)
ESP-IDF release/v3.3: 66d3783c8
esp-face: 420fc7e
esp32-camera: 0107093
2020-11-03 21:20:00 +02:00
6e5be78838 Update install-arduino-ide.sh 2020-11-03 21:12:05 +02:00
e2452c0dfc Added isKey method to Preferences (#4441)
Checks to see if a string is a key in the namespace. 

Fixes #4440
2020-11-03 17:03:04 +02:00
56a7ae8712 Trailing spaces (#3738)
* fix typo in WiFiMulti

* clean up trailing spaces

* clean up script file used in cleaning

Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
2020-11-02 22:11:26 +02:00
e4b008e712 Handle stream timeouts properly, for slow HTTP/HTTPS links (#3752)
This patch fixes update timeouts (error #6) on slow HTTP/HTTPS links.
2020-11-02 22:01:27 +02:00
76afaf2d6b Add more options to the AI thinker cam. (#4253)
* Add more options to the AI thinker cam.

The reason is power saving and compatibility of cheap chines clones with crappy flash chips.
2020-11-02 21:21:22 +02:00
dccb4e8608 improve & fix BLEScan when wantDuplicates (#3995)
* improve & fix BLEScan when too many BLE devices
- when wantDuplicates, no need to check duplicate and no more insert into vector
- delete advertisedDevice when not insert into vector, fix memory leak
- add showParse when you just want raw advertised data
2020-11-02 20:41:50 +02:00
c2346c37da Add initial support for arm64 toolchain. (#4117)
Closes #4111.
gcc: I was not able to find an arm64 build on espressif's website so I choosed to put the armhf version, even if this should works this is only ok as temporary, arm64 runs better on arm64 than armhf :)
esptool: being interpreted python its ok
mkspiff: need igrr/mkspiffs#74 to be merged and artifacts added in /package/package_esp32_index.template.json.
2020-11-02 20:39:31 +02:00
3491ca7845 Add virtual beginMulticast(...) stub to UDP class (#4061)
https://github.com/arduino/ArduinoCore-sam/pull/6/files

It is used here:
https://github.com/arduino-libraries/ArduinoMDNS/blob/master/MDNS.cpp#L150
2020-11-02 20:26:50 +02:00
0e341a6192 Add sdkconfig option CONFIG_ARDUINO_UDP_TASK_PRIORITY, which sets the task priority for the UDP vtask." (#4131) 2020-11-02 20:21:59 +02:00
76cd2e2375 Fix BLE connection handling (#4137)
Remove device from Peer list if connection fails.

Only call onConnect callback if connection was successful.

Only call onDisconnect callback if the connection was previously connected (ESP_GATTC_DISCONNECT_EVT is fired on a unsuccessful connection attempt also).

Resolves a number of issues with phantom events and callbacks being fired.
2020-11-02 20:20:40 +02:00
9f7ff009c6 Fix parameter to BLEDevice::updatePeerDevice (#4133)
::addPeerDevice and ::removePeerDevice are called with m_appId, so should ::updatePeerDevice as all use the same parameter for the underlying map's key.
2020-11-02 20:20:16 +02:00
704b71dabe Fix header parsing
fixes #4454

closes #4455
2020-11-02 20:10:22 +02:00
7c0572172c Fix for issue #4158: BLEAdvertising - Crash with stack trace originating in Bluedroid (#4182)
* Fix for issue #4158: Crash with stack trace originating in Bluedroid
Improved configuration of scan response data in 'BLEAdvertising' avoids the crash:
- Added member variable 'm_scanRespData' to configure scan response differently from advertising data
- Initialization of 'm_scanRespData' in BLEAdvertising constructor
- Use of 'm_scanRespData' within BLEAdvertising::start() to configure the scan response
- 'Flags' and 'Appearance' are cleared in the scan response data
- With this fix, device names of up to 29 characters can be used without causing a crash.
2020-11-02 19:39:20 +02:00
f57c36782f Add sendContent overload that takes a const char* and a length (#4276)
The web server currently lacks the ability to send a buffer. Only strings are supported.

This PR adds an overload to sendContent.
2020-11-02 19:17:02 +02:00
3054bdf5a5 HTTPUpdateServer library (#4244) 2020-11-02 19:16:23 +02:00
1014ba40af Update ISSUE_TEMPLATE.md (#4416)
Make options list into a table
2020-11-02 18:59:46 +02:00
d6b91872cb Fix for espressif#3460 issue (#4424)
Fixes: #3460

This code has been run in production for 1 month and it looks stable, no data dropped and it definitely fixes the issue described. I think that this can be merged to avoid using custom package referencing in PlatformIO that has been used in quite a few projects for now.

Co-authored-by: Ivan Golubic <ivan@mvt-solutions.com>
2020-11-02 18:59:03 +02:00
d6b383f84b Merge pull request #4429 from Bmooij/feature/Add_flash_helper_constructor_to_Uri
Add flash helper constructor to Uri
2020-11-02 18:56:08 +02:00
cadbad8850 Add partition label argument to Update and ArduinoOTA classThe UpdateClass in the Updater component has the ability to update data toa SPIFFS partition. It selects the first available partition using theESP-IDF esp_partition_find_first() function.That behaviour is problematic if one has multiple SPIFFS partitions.This change allows a user to pass the label argument (defaults to NULL)to UpdateClass::begin() so a specific SPIFFS partition can be updated.Additionally, ArduinoOTA can set this partition label using thenew method ArduinoOTAClass::setPartitionLabel which is optional.This change does not break compatibility. (#4442)
The UpdateClass in the Updater component has the ability to update data to
a SPIFFS partition. It selects the first available partition using the
ESP-IDF esp_partition_find_first() function.
That behaviour is problematic if one has multiple SPIFFS partitions.

This change allows a user to pass the label argument (defaults to NULL)
to UpdateClass::begin() so a specific SPIFFS partition can be updated.

Additionally, ArduinoOTA can set this partition label using the
new method ArduinoOTAClass::setPartitionLabel which is optional.

This change does not break compatibility.
2020-11-02 18:49:24 +02:00
3cbfa2ffef Add partition label argument to SPIFFS (#4443)
* Add partition label argument to SPIFFSSPIFFS currently assumes there is only ever one partition.This change allows a user to pass the label argument (defaults to NULL)to SPIFFS::begin() so a specific SPIFFS partition can be referenced.This change does not break compatibility.
2020-11-02 18:47:36 +02:00
360e04fa36 Fixing BLE GATT Characteristic notification and Characteristic Descriptor read (#4464)
* BLERemoteChar: fix descriptor 2902 write for characteristic notifications

When registering a notification on a characteristic, the 2902 descriptor
(CCCD) value is set to 1 (or 2 for indication).
According to the BLUETOOTH CORE SPECIFICATION Version 5.2, Revision Date
2019-12-31, section 4.12.3 "Write Characteristic Descriptors" (page 1588),
the characteristic descriptor write must expect a response.
Currently, the descriptor write is performed without expecting a reponse,
which prevents the notification to be functional with some BLE stacks.
This commit modify the write to expect the response.

Signed-off-by: Jimmy Durand Wesolowski <jimmy.durand.wesolowski@commsolid.com>

* BLERemoteChar: forward GATT client event to characteristic descriptors

This commits prevents a permanent wait when calling BLERemoteDescriptor
readValue function, on the m_semaphoreReadDescrEvt semaphore.

ESP32 BLE stack calls to remote characteristic
- notification,
- value read
- value write
and remote characteristic descriptor
- value read
are asynchronous.

When such a call is performed by this library, a semaphore is taken prior
to the BLE stack read or write operation, and waited on after it.

Releasing the semaphore is done by the characteristic event handling
function (gattClientEventHandler), when the appropriate event is received.

However, the characteristic descriptor events are discarded, and the
value read semaphore is never released.

This commits forwards the GATT client events from the remote
characteristic down to their remote characteristic descriptor, and
implements their event handling.

Adding a semaphore for the remote characteristic descriptor value write
will be done in a separate commit.

Signed-off-by: Jimmy Durand Wesolowski <jimmy.durand.wesolowski@commsolid.com>

* BLERemoteDescriptor: add semaphore to characteristic descriptor write

This adds a semaphore to characteristic descriptor value write, to mimic
the value read function, and to ensure completion of the operation before
we carry on.

Signed-off-by: Jimmy Durand Wesolowski <jimmy.durand.wesolowski@commsolid.com>

Co-authored-by: Jimmy Durand Wesolowski <jimmy.durand.wesolowski@commsolid.com>
2020-11-02 18:36:25 +02:00
57145ade6f Small description comment correction (#4471)
esp8266 --> esp32
2020-11-02 18:35:23 +02:00
f39024675c Don't convert to null-terminated string prior to writeValue (#4473)
fixes: #4472
2020-11-02 18:34:57 +02:00
f7fb00632e #4293 added missing '<tr>' (#4450)
Fixes issue #4293
2020-10-27 15:35:54 +02:00
7e40de226f Fixes #4435 - WiFiClient improperly treats zero data available for read as an error (#4448) 2020-10-27 12:01:41 +02:00
ae240a3902 Add flash helper constructor to Uri 2020-10-19 16:20:49 +02:00
1287c52933 Add missing "-mlongcalls" flag to PlatformIO build script (#4420)
Fixes possible issues with assembly files in external libraries
2020-10-16 21:58:05 +03:00
25bd585c25 Corrections of Stream.Find, FindUntil and added FindMulti - like AVR-Core Libraries (#3442)
* Corrections of Find, FindUntil and FindMulti

Find has some bug that is not working with Ethernet.find() so, I copied code from Stream.h and Stream.cpp in AVR-CORE library and now it's working perfectly.
I don't know where was the error, but an Ethernet.find compiled to MEGA2560 was working but not working when compiled to esp32, after corrections of code (copy of AVR-Core libraries) it's working perfect.
So probably has some error on original ESP32-Core library.

Below is part of code that was working with MEGA2560 and not with ESP32 libraries.
client.find never return TRUE with ESP32 original library and with AVR it's works.

boolean esp32_fw_update(EthernetClient &client, DecodedHeader &header, const String &field_filename, const String &field_crc) {

  char bound[header.boundary.length()+3];
  char term[]="\r\n";
  
  strcpy(bound,header.boundary.c_str());
  strcat(bound,term);
  while (client.find(bound)) { 
    String line=client.readStringUntil('\r');

* Update Stream.h

* Update Stream.cpp

Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
2020-10-14 15:20:40 +03:00
d79a1f3d10 Add an aditional (void *) arg to the RMT callback (much like Ticker() et.al.). (#3345)
* Add an aditional (void *) arg to the RMT callback - to allow more flexible handling of the callback (e.g. by passing a private struct or a class pointer). Same pattern as used by the Ticker() and many others. Example updated & new example with a trapoline added.

* Fix example for new API

* Fix lint warnings

* Add a second missed example.

* Correct timeout & improve socket error handling.
2020-10-14 14:41:50 +03:00
831f0ac29a Rename eep -> partitions.bin & hex -> bin (#4143)
This is in line with the
[arduino platform specification](https://arduino.github.io/arduino-cli/platform-specification/#recipes-for-extraction-of-executable-files-and-other-binary-data)
specifying that the file extension after recipe.objcopy is arbitrary and
that the AVR platform uses `eep` & `hex`, while the esp32 platform seems
to have file extensions `partition.bin` & `bin`
2020-10-14 14:34:14 +03:00
ee3bb16c77 Fix support for following redirects added by ee88c42c3b (#4240) (#4385) 2020-10-14 14:32:47 +03:00
d8dca9c73b bugfix (#4389) 2020-10-14 14:30:32 +03:00
c3f3497048 fixed some typos (#4395) 2020-10-14 14:27:49 +03:00
18c3345451 fix typos in WiFiSTA.cpp (#4396)
* fix typos

* made return value description a bit more helpful
2020-10-14 14:27:19 +03:00
b07f1c11fe Updated Readme.md (#4400)
* Updated Readme.md

Added links to latest release. Made it look a lot cleaner.

* Update README.md
2020-10-14 14:26:41 +03:00
2685a5dd7b Certificate isn't be free in case parse failure. (#4412)
I met problem while I was working with the WiFiClientSecure.
I tried to found the source of the problem, and I found it in the sll_client.cpp.
Please check my contribution.

I've open this problem in #4335 but received no response.
2020-10-14 14:25:26 +03:00
675a40b257 Fix Not by reference. But the value was updated. (#3279) 2020-10-03 03:41:03 +03:00
3570d48eb9 Added the DoIT ESPduino-32 board (#1520) 2020-10-03 03:06:40 +03:00
f76ec4f50b adds debugging to dnsserver (#1046) 2020-10-03 02:59:55 +03:00
fb6d5ad234 Add Inex OpenKB Board (#4002)
Please add OpenKB Board Product from INEX Co. Ltd.

https://inex.co.th/shop/openkb.html
2020-10-03 02:20:10 +03:00
219ff3005b Add missing slashes in HTTPUpdate examples (#4238)
I spent quite a while today figuring out how to get an OTA update over HTTPS on a custom port working. A part of my problem was not putting a slash before the .bin filename, since it wasn't there in the example. This produced invalid HTTP requests. Adding the slash would make it clear that it needs to be there.

Given that the URL in line 53 contains the same words "server" and "file.bin", one might assume that in line 55, the slash after the port number would get added automatically, however I have found out that without a slash you get an invalid request. Adding the slash removes any doubt.
2020-10-03 02:13:27 +03:00
ccab428e4d Added definitions for TTGO-LoRA32-V2.1.6 (#4205) 2020-10-03 02:06:11 +03:00
d2d24a14e0 add board WiFiduino32 (#4218) 2020-10-03 02:04:10 +03:00
af11921535 Add support for S.ODI_Ultra_v1.0 (#4372)
Add a new Dev Board S.ODI Ultra v1 in esp32 library
2020-10-03 01:59:53 +03:00
82112384ca Fix missing headers when compiling as IDF component with Cmake (#4377)
* HttpsOTAUpdate introduced new IDF component requirements.
These have been added to CMakeLists.txt to correct compilation errors when using Cmake.
2020-10-01 15:45:52 +03:00
99aa866477 Update MDNSResponder::addService to return a boolean (#4365)
I was playing with the mDNS service and noticed the method MDNSResponder::addService could return a Boolean with the way it is implemented just like other functions in this library.

This would be handy to know at a higher level weather or not the service was added correctly to the mDNS server of the ESP32.
2020-10-01 15:44:24 +03:00
82670b96f8 Fix for missed scan response data (BLEScan). (#4358)
This is a fix for missing scan responses after a first successfull scan.

While running the BLE_scan.ino sketch with wantDuplicates=false, i got
only one result with correct advertising and scan response length (31,26):

pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks(), false);
pBLEScan->start(scanTime, false);
...
[W][BLEScan.cpp:109] handleGAPEvent(): bytes length: 31 + 26, addr type: 1

All following calls to start() just returned the advertising data without
scan response data:

pBLEScan->start(scanTime, false);
[W][BLEScan.cpp:109] handleGAPEvent(): bytes length: 31 + 0, addr type: 1

With "wantDuplicates=true" i got:

pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks(), true);
pBLEScan->start(scanTime, false);
[W][BLEScan.cpp:109] handleGAPEvent(): bytes length: 31 + 26, addr type: 1
[W][BLEScan.cpp:109] handleGAPEvent(): bytes length: 31 + 26, addr type: 1
[W][BLEScan.cpp:73] handleGAPEvent(): ESP_GAP_SEARCH_INQ_CMPL_EVT
Devices found: 1
Scan done!
pBLEScan->start(scanTime, false);
[W][BLEScan.cpp:109] handleGAPEvent(): bytes length: 31 + 0, addr type: 1
[W][BLEScan.cpp:109] handleGAPEvent(): bytes length: 0 + 26, addr type: 1
[W][BLEScan.cpp:109] handleGAPEvent(): bytes length: 31 + 0, addr type: 1
[W][BLEScan.cpp:109] handleGAPEvent(): bytes length: 0 + 26, addr type: 1

Explicitly initializing m_scan_params.scan_duplicate of BLEScan solves
this issue (In my case the un-initialized value was
m_scan_params.scan_duplicate == 1073599044).

Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
2020-10-01 15:43:30 +03:00
9e7b13e46d WebServer.handleClient delay (#4350)
* If WebServer.handleClient is run in a tight loop, it will starve other processes.  So, if there is no connection, throw in a delay(1).  Fixes #4348

* Made a variable to control the delay behavior
2020-10-01 15:42:23 +03:00
2243081f85 add I2C_RX_FIFO_OVF_INT_ST handling to i2c_isr_handler_default (#4342)
Fixes crash on ESP32 when I2C FiFo overflows and interrupt function is unable to handle crash and throws this error:
[E][esp32-hal-i2c.c:1013] i2c_isr_handler_default(): unknown int=4

Co-authored-by: 0xDEADBEEF <0xde4dbeef@gmail.com>
2020-10-01 15:40:42 +03:00
1f4491f4ee Updated AzureIoT submodule. (#4322) 2020-10-01 15:38:56 +03:00
aa529eb5a0 Fix getString() freeze on empty responses (#4317) 2020-10-01 15:36:23 +03:00
a9cb7c6d6f mismatched parameter names. Fixes #4310 (#4313) 2020-10-01 15:35:40 +03:00
45d47e2be0 Fix duplicated pin constant (#4282)
G22 was defined twice, changing the first one to G21
2020-10-01 15:31:56 +03:00
99c94bb482 Set SD state to idle before unregister (reduces power) (#4272) 2020-10-01 15:31:16 +03:00
f98fc7ee9f fix hwSerial tx only flush (#4263) 2020-10-01 15:30:45 +03:00
0957776855 Reinit updater md5 related fields (#4260)
MD5 cleanup on begin
Typos
2020-10-01 15:29:58 +03:00
d93245d0f5 add m5stack-core2 board (#4255)
* add m5stack-core2 board
2020-10-01 15:28:40 +03:00
c917ed2504 shallow clone to make installation faster (#4246)
shallow clone (board and submodules) to make installation faster
2020-10-01 14:43:48 +03:00
ee88c42c3b Add support for following redirects in HTTPClient (#4240) 2020-10-01 14:41:54 +03:00
837cc3d271 Added SparkFun ESP32 Thing Plus board (#4224) 2020-10-01 14:39:39 +03:00
9b2ae12fb7 Added D pin numbers (#4220)
Source: https://wiki.dfrobot.com/FireBeetle_ESP32_IOT_Microcontroller(V3.0)__Supports_Wi-Fi_&_Bluetooth__SKU__DFR0478
2020-10-01 14:39:01 +03:00
86e221d087 Update HelloServer.ino (#4219)
Change name esp8266 for esp32 in welcome message
2020-10-01 14:38:26 +03:00
663effa00e Update Parsing.cpp (#4217)
* Update Parsing.cpp

When uploading TLS cert files the end of file "-----END CERTIFICATE-----" (or any kind of file with the sequence "CRLF--") is taken as posible end boundary. Then it is compared to the start boundary string. As it is expected, comparison turns to be false, and the whole end boundary string is put to _currentUpload->buf through _uploadWriteByte(). Here you have the problem: if you read boundary.length() bytes from HTTP request and you have some of the actual end boundary bytes in it, when you put all those bytes into _currentUpload->buf you are making a mistake. You will miss the actual end boundary string because some of those bytes were put in _currentUpload->buf.

* Update Parsing.cpp
2020-10-01 14:37:59 +03:00
6f237a8415 Fix ttgo twatch & tbeam board definition error (#4212) 2020-10-01 14:36:32 +03:00
c3c38a8eb5 Enable precompiled libraries (#4209)
The latest versions of Arduino IDE shifted the responsibility for precompiled libraries support to the core developers, which breaks precompiled library support in esp32 Arduino core. See https://github.com/arduino/ArduinoCore-avr/pull/52 for more details:

```
In this new version of the builder we are not doing any heuristics to find the right spot where the ldflags should be inserted (this was causing many bugs on its own); instead, we fully trust the core makers to add explicit support to precompiled libs.
```

This chage re-enables precompiled library support in the esp32 Arduino core.
2020-10-01 14:32:20 +03:00
8fcc914853 Added facility to invert the polarity of input UART bits. (#4200) 2020-10-01 13:58:48 +03:00
d03f8f1277 Update pins_arduino.h (#4190) 2020-10-01 13:54:01 +03:00
882b12c44e rmdir causes issues in SPIFFS. Fixes #4138, albeit not very cleanly (#4154)
SPIFFS causes crashes if you attempt to rmdir. Since there are no true directories in spiffs, this ought to be a noop. It looks like @me-no-dev worked around this by using unlink instead of rmdir, which works in fatfs and doesn't panic spiffs. This behavior is not universal. In order to get littlefs working, it would be good to get this back to conformity. Rather than digging deep into the upstream spiffs, I just check the mountpoint and noop if it is "/spiffs". So, if the user has changed the mountpoint, this will not work, but I think it's a pretty good tradeoff.
2020-10-01 13:52:24 +03:00
93d850f783 Fixed comment with correct FQDN (#4152) 2020-10-01 13:51:36 +03:00
4f48caca2c Set scan_duplicate in BLE scan params (#4126)
This value is uninitialised and as such can be a random (and invalid) value. It's needs to be set per the espressif documentation here:

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/bluetooth/esp_gap_ble.html#_CPPv4N21esp_ble_scan_params_t14scan_duplicateE

This PR sets it to DUPLICATE_DISABLE. Chosen as this is needed to ensure all scan data is populated in the scan callback, per this comment in the IDF:

https://github.com/espressif/esp-idf/blob/master/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c#L3591

"//if scan duplicate is enabled, the adv packet without scan response is allowed to report to higher layer"

We **don't** want it to report to the higher layer (ie BLEScan.cpp) **unless** it has the active scan response.

Seems to resolve #3770 #3677 and possibly others.
2020-10-01 13:45:45 +03:00
80e9e42c3b Fix issue #3522 (WiFi does not restart after stopped) (#4114)
This commit fixes issue https://github.com/espressif/arduino-esp32/issues/3522 where WiFi service fails to start after a WiFi.disconnect(true) or a WiFi.mode(WIFI_OFF).
2020-09-30 15:34:10 +03:00
494061af26 WebServer: Fix OOB write (#4088)
Successful exploitation could lead to arbitrary code execution.

The bug can be reproduced by running the following in a browser:
```
const formData = new FormData();
for (let i = 0;i < 33;++i) { formData.append("foo", i.toString()); }
await fetch("http://esp.local", { method: 'POST', body: formData });
```
2020-09-30 15:28:28 +03:00
2fd3d042b2 Fix #4046 Details below: (#4086)
Informed by the discussion in the bug and the code in 'that other branch'
the fix was clear.  Just set a flag if we start handling a write, and
use that flag to guard the long write complete call.
2020-09-30 15:27:35 +03:00
b551310c37 Minor change but could confuse some (#4084) 2020-09-30 15:26:38 +03:00
f30edd040e Update CaptivePortal.ino (#4080)
* Update CaptivePortal.ino

Illegal SSID used for SoftAP

* Fixed ordering problem.  Now actually works
2020-09-30 15:26:15 +03:00
b7c5e502e7 Add static pin support (#4078) 2020-09-30 15:25:42 +03:00
fa8a1c38d5 fix #4071 (#4072)
SPIFFS File object evaluates as true even if the file could not be opened.
2020-09-30 15:24:59 +03:00
d56267bd8c Update GetChipID.ino (#4070)
Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
2020-09-30 15:24:29 +03:00
1f6b0b35f8 Have BLECLient gattc event handlers verify conn_id (#4064)
Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
2020-09-30 15:21:59 +03:00
342b9cf2d8 Fix handling of registerForNotify in BLERemoteCharacteristic.cpp (#4063) 2020-09-30 15:20:28 +03:00
11d071b1c8 Fix to allow more than one certificate to be loaded (espressif#3248). (#4056)
Co-authored-by: Mark Hale <mark.hale@physics.org>
2020-09-30 15:19:41 +03:00
f48d9016fd Update T_Watch board properties and add revision selection (#4025)
Co-authored-by: lewis he <lewisxhe@outlook.com>
2020-09-30 15:18:17 +03:00
a55265f74b Fix clockCyclesPerMicrosecond Change from fixed value to current value (#3993) 2020-09-30 15:16:20 +03:00
c1a7198e7d Don't change owner if take() doesnt succeed (#3987) 2020-09-30 15:15:47 +03:00
4d4a1fde36 Added HealthyPi 4 Board Support (#3985)
Co-authored-by: Ashwin <ashwin@circuitects.com>
2020-09-30 15:14:39 +03:00
d219e56872 Update pins_arduino.h (#3908)
Update in accordance with Firebeetle's official firebeetle32 pins_arduino.h. Without it, digital pins weren't definable, and analogue pins didnt line up.

Taken from http://download.dfrobot.top/FireBeetle/DFRobot_FireBeetle-ESP32-0.0.9.zip
2020-09-30 15:07:26 +03:00
19ccc479c3 WIFI_PS_MAX_MODEM feature requested #3896 (#3900) 2020-09-30 15:06:58 +03:00
c18d50cb91 Use esp_partition_* functions in Updater.cpp (#3898)
Background

The current implementation of Update() uses the spi_flash_* api to write and read from flash. These functions ignore the partition->encrypted flag and always write raw data to flash even if the partition is marked as encrypted.

Changes in this PR

Update() now uses the esp_partition_* api.
Wrapper functions for esp_partition_* added to ESP.cpp. This was done to maintain a consistent approach to the way the spi_flash_* functions were used. I note though that not all of the esp-idf functions are used are wrapped, for example esp_ota_get_next_update_partition() so it may be that these should not be added?
The current implementation of Update() changes the first (magic) byte of firmware to 0xFF on write, and then when the firmware is completely written changes it back to ESP_IMAGE_HEADER_MAGIC. This works without erasing the sector because flash bits can be changed from 1->0 (but not 0->1). If the flash is encrypted then the actual data written to flash will not be all ones, so this approach will not work. In addition, encrypted flash must be written in 16 byte blocks. So, instead of changing the first byte the changed code stashes the first 16 bytes, and starts writing at the 17th byte, leaving the first 16 bytes as 0xFF. Then, in _enablePartition() the stashed bytes can be successfully written.
Benefits

Whilst it's not possible to use encrypted flash directly from either the Arduino IDE or PIO it's reasonably straightforward to compile and flash a bootloader with the necessary support from a simple esp-idf project and then use ArduinoOTA for subsequent updates. This PR enables the use of this workflow until such time as encrypted flash is supported, and is a first (small) step toward adding support.
Regardless of the above, the esp_partition_* api is recommended over the api_flash_* api.
Application code should mostly use these esp_partition_* API functions instead of lower level spi_flash_* API functions. Partition table API functions do bounds checking and calculate correct offsets in flash, based on data stored in a partition table.
2020-09-30 15:06:19 +03:00
80418fadcf Fixes UART detach. Fixes #3878 (#3894)
* Fixes UART detach.  Fixes #3878

* 0 is not a good holder value for pins!

* 0 is not a good holder value for pins!
2020-09-30 15:04:18 +03:00
8b6d020352 added new board Logsens V1p1 (#3880)
* Added new board variant for Imbrios LogSens V1.1

Imbrios LogSens V1.1 new board variant

* added new board Imbrios LogSens V1.1

Added new board details: Imbrios LogSens V1.1
2020-09-30 15:01:51 +03:00
5197916983 Fix BLEClient disconnect bug (#3876)
By default the disconnect is broadcasted to every clients. So if you call disconnect on one connected client, they'll all be disconnected if we don't filter the event by conn_id.
2020-09-30 15:01:02 +03:00
7e9d42da68 ESP.getChipModel() and ESP.getChipCores() (#3847)
* ESP.getChipModel() returns model of the chip

* ESP.getChipCores() returns the core count.

* Example gives chip model, revision and core count.

* Read efuse for chipmodel

Co-authored-by: Martijn Scheepers <ms@SDNengineering.nl>
2020-09-30 14:57:36 +03:00
e34e0b45de Fixed bug where mutex would not be unlocked (#3837)
Fixed bug where uartResizeRxBuffer() did not unlock mutex if creation of queue failed.
2020-09-30 14:56:41 +03:00
ef2b54547e Fix issue #3833, data parsing of Eddystone TLM data frame (#3836)
* Fix issue #3833, data parsing of Eddystone TLM data frame    
Add Beacon scanner example to show usage of BLEEddystoneTLM class and  BLEEddystoneURL class     
Add EddystoneTLM beacon example    
Add EddystoneURL beacon example

* Fix buffer size for .toString()
2020-09-30 14:55:58 +03:00
9856f0cc28 Update RMTLoopback.ino (#3823)
BUGFIX: avoids assertion in xEventGroupWaitBits()
(/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/event_groups.c:350 (xEventGroupWaitBits)- assert failed!)
2020-09-30 14:52:22 +03:00
daa8c55667 add new board mpython (#3814) 2020-09-30 14:49:57 +03:00
af7ec4ead1 fix EEPROM class example (#3786) 2020-09-30 14:43:05 +03:00
9e65ed1af1 Process compiler.libraries.ldflags (#3783)
Add support for the v1.8.6 compiler.libraries.ldflags:

https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification

This fixes the issue reported here:

https://community.bosch-sensortec.com/t5/MEMS-sensors-forum/BSEC-1-4-7-4-compilation-error-on-ESP32-1-0-3-rc1/td-p/9120
2020-09-30 14:42:04 +03:00
7a92f89d12 Set TLS cert options before calling connect on client, so verify works (#3774)
When connecting using transportTraits, the CA and client certificates are ignored after the initial _client->connect() is called. This is because on connect, WiFiClientSecure will call start_ssl_client with _CA_Cert and other cert options set to null unless setCACert, setCertificate etc. are called before connect. Running _transportTraits->verify after connect therefore does exactly nothing. It's easy to verify that this is the case by passing a CACert to HTTPClient with verbose logging enabled - the logs will say "WARNING: Use certificates for a more secure communication!" which is only present when both PSK and CA are null. This change fixes the issue.
2020-09-30 14:41:03 +03:00
5871ca9ce9 UpdateClass::printError now accepts the Print object (#3763) 2020-09-30 14:39:25 +03:00
0dfa5babc2 fix typo in WiFiMulti (#3737) 2020-09-30 14:37:21 +03:00
e4b2ce4e81 DNS resolving timeout change to prevent stack overlapping (#3731)
Real DNS resolving timeout used by lwip library is 14[s] (7[s] for DNS1 + 7[s] for DNS2). Function WiFiGenericClass::hostByName() has timeout set to lower value (only 4[s]), so callback function may be called after this low timeout and it may overlappe stack memory used now by other function.
Fixes #3722
2020-09-30 14:35:53 +03:00
7af4490fcc Update SPI.h 2020-09-30 14:34:37 +03:00
4204869ec9 Extend Print class for 64bit integers. (#3688)
* Extend Print class for 64bit integers.

modulo 32bit and 64bit tuned for code size.

* Fix 32bit long used in long long printNumber.
2020-09-30 14:31:36 +03:00
ab23e8a656 Greatly reduces error rate (half, or 0 zero errors, depends on in/out ranges) for round-trip mapping at the same performance. (#3655)
(Based on "improved_map" from ESP8266's Servo.cpp)
2020-09-30 14:28:51 +03:00
5999b7ba46 removed double delete of characteristics (#3521) 2020-09-30 14:25:31 +03:00
7b613c1238 Added documentation regarding delay() resolution in esp-idf component (#3014) 2020-09-30 14:17:53 +03:00
cee2359e33 Update pins_arduino.h (#4211)
fix some mistake
2020-09-28 10:24:06 +03:00
37a7fb3d6a Update PlatformIO CI script (#4307) 2020-08-31 18:06:34 +03:00
9d547a8a44 Provisioning fixes for: 1.Space 2.Provisioned (#4291) 2020-08-25 11:03:06 +03:00
1fd5cd79c5 Add OTA update feature
This sketch provide functionality for OTA firmware upgrade.
2020-08-25 11:01:58 +03:00
487 changed files with 12632 additions and 2248 deletions

View File

@ -48,16 +48,22 @@ else
export ARDUINO_USR_PATH="$HOME/Arduino"
fi
# Updated as of Nov 3rd 2020
ARDUINO_IDE_URL="https://github.com/espressif/arduino-esp32/releases/download/1.0.4/arduino-nightly-"
# Currently not working
#ARDUINO_IDE_URL="https://www.arduino.cc/download.php?f=/arduino-nightly-"
if [ ! -d "$ARDUINO_IDE_PATH" ]; then
echo "Installing Arduino IDE on $OS_NAME ..."
echo "Downloading 'arduino-nightly-$OS_NAME.$ARCHIVE_FORMAT' to 'arduino.$ARCHIVE_FORMAT' ..."
echo "Downloading '$ARDUINO_IDE_URL$OS_NAME.$ARCHIVE_FORMAT' to 'arduino.$ARCHIVE_FORMAT' ..."
if [ "$OS_IS_LINUX" == "1" ]; then
wget -O "arduino.$ARCHIVE_FORMAT" "https://www.arduino.cc/download.php?f=/arduino-nightly-$OS_NAME.$ARCHIVE_FORMAT" > /dev/null 2>&1
wget -O "arduino.$ARCHIVE_FORMAT" "$ARDUINO_IDE_URL$OS_NAME.$ARCHIVE_FORMAT" > /dev/null 2>&1
echo "Extracting 'arduino.$ARCHIVE_FORMAT' ..."
tar xf "arduino.$ARCHIVE_FORMAT" > /dev/null
mv arduino-nightly "$ARDUINO_IDE_PATH"
else
curl -o "arduino.$ARCHIVE_FORMAT" -L "https://www.arduino.cc/download.php?f=/arduino-nightly-$OS_NAME.$ARCHIVE_FORMAT" > /dev/null 2>&1
curl -o "arduino.$ARCHIVE_FORMAT" -L "$ARDUINO_IDE_URL$OS_NAME.$ARCHIVE_FORMAT" > /dev/null 2>&1
echo "Extracting 'arduino.$ARCHIVE_FORMAT' ..."
unzip "arduino.$ARCHIVE_FORMAT" > /dev/null
if [ "$OS_IS_MACOS" == "1" ]; then

View File

@ -12,19 +12,14 @@ echo "Installing Platform ESP32 ..."
python -m platformio platform install https://github.com/platformio/platform-espressif32.git > /dev/null 2>&1
echo "Replacing the framework version ..."
if [[ "$OSTYPE" == "darwin"* ]]; then
sed 's/https:\/\/github\.com\/espressif\/arduino-esp32\.git/*/' "$HOME/.platformio/platforms/espressif32/platform.json" > "platform.json"
mv -f "platform.json" "$HOME/.platformio/platforms/espressif32/platform.json"
else
sed -i 's/https:\/\/github\.com\/espressif\/arduino-esp32\.git/*/' "$HOME/.platformio/platforms/espressif32/platform.json"
fi
python -c "import json; import os; fp=open(os.path.expanduser('~/.platformio/platforms/espressif32/platform.json'), 'r+'); data=json.load(fp); data['packages']['framework-arduinoespressif32']['version'] = '*'; del data['packages']['framework-arduinoespressif32']['owner']; fp.seek(0); fp.truncate(); json.dump(data, fp); fp.close()"
if [ "$GITHUB_REPOSITORY" == "espressif/arduino-esp32" ]; then
echo "Linking Core..."
ln -s $GITHUB_WORKSPACE "$PLATFORMIO_ESP32_PATH"
else
echo "Cloning Core Repository ..."
git clone https://github.com/espressif/arduino-esp32.git "$PLATFORMIO_ESP32_PATH" > /dev/null 2>&1
git clone --recursive https://github.com/espressif/arduino-esp32.git "$PLATFORMIO_ESP32_PATH" > /dev/null 2>&1
fi
echo "PlatformIO for ESP32 has been installed"

View File

@ -87,9 +87,15 @@ function git_safe_upload_to_pages(){
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[]'`
echo "added: $pages_added"
pages_modified=`echo "$EVENT_JSON" | jq -r '.commits[].modified[]'`
echo "modified: $pages_modified"
pages_removed=`echo "$EVENT_JSON" | jq -r '.commits[].removed[]'`
echo "removed: $pages_removed"
for page in $pages_added; do
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
echo "Copying files for packaging ..."
cp -f "$GITHUB_WORKSPACE/boards.txt" "$PKG_DIR/"
cp -f "$GITHUB_WORKSPACE/programmers.txt" "$PKG_DIR/"
cp -Rf "$GITHUB_WORKSPACE/cores" "$PKG_DIR/"
cp -Rf "$GITHUB_WORKSPACE/libraries" "$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.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.exe" "$PKG_DIR/tools/"
cp -Rf "$GITHUB_WORKSPACE/tools/partitions" "$PKG_DIR/tools/"
cp -Rf "$GITHUB_WORKSPACE/tools/sdk" "$PKG_DIR/tools/"
cp -f "$GITHUB_WORKSPACE/boards.txt" "$PKG_DIR/"
cp -f "$GITHUB_WORKSPACE/programmers.txt" "$PKG_DIR/"
cp -Rf "$GITHUB_WORKSPACE/cores" "$PKG_DIR/"
cp -Rf "$GITHUB_WORKSPACE/libraries" "$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.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.exe" "$PKG_DIR/tools/"
cp -Rf "$GITHUB_WORKSPACE/tools/partitions" "$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
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
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_any_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == 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(.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
if [ "$prev_any_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_any_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false)) | sort_by(.created_at | - fromdateiso8601) | .[1].tag_name')
if [ "$prev_release" == "$RELEASE_TAG" ]; then
prev_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .prerelease == false)) | sort_by(.published_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
COMMITS_SINCE_RELEASE="$prev_any_release"
shopt -u nocasematch
set -e
echo "Previous Release: $prev_release"
echo "Previous (any)release: $prev_any_release"
echo
# Merge package JSONs with previous releases
if [ ! -z "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then
echo "Merging with JSON from $prev_any_release ..."
@ -272,17 +286,12 @@ if [ ! -z "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then
fi
if [ "$RELEASE_PRE" == "false" ]; then
COMMITS_SINCE_RELEASE="$prev_release"
if [ ! -z "$prev_release" ] && [ "$prev_release" != "null" ]; then
echo "Merging with JSON from $prev_release ..."
merge_package_json "$prev_release/$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL"
fi
fi
echo "Previous Release: $prev_release"
echo "Previous (any)release: $prev_any_release"
echo
# Upload package JSONs
echo "Uploading $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
# 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
echo "Getting commits since $COMMITS_SINCE_RELEASE ..."
commitFile=$OUTPUT_DIR/commits.txt
git -C "$GITHUB_WORKSPACE" log --oneline $COMMITS_SINCE_RELEASE.. > "$OUTPUT_DIR/commits.txt"
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
git -C "$GITHUB_WORKSPACE" log --oneline -n 500 "$COMMITS_SINCE_RELEASE..HEAD" > "$commitFile"
elif [ "$RELEASE_BRANCH" != "master" ]; then
echo "Getting all commits on branch '$RELEASE_BRANCH' ..."
git -C "$GITHUB_WORKSPACE" log --oneline -n 500 --cherry-pick --left-only --no-merges HEAD...origin/master > "$commitFile"
else
echo "Getting all commits on master ..."
git -C "$GITHUB_WORKSPACE" log --oneline -n 500 --no-merges > "$commitFile"
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
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
exemptLabels:
- pinned
- security
- "to be implemented"
- "for reference"
- "move to PR"
- "enhancement"
- "Type: For reference"
- "Type: To be implemented"
- "Type: Feature request"
# Set to true to ignore issues in a project (defaults to false)
exemptProjects: false
@ -29,7 +26,7 @@ exemptMilestones: false
exemptAssignees: false
# Label to use when marking as stale
staleLabel: stale
staleLabel: Status: Stale
# Comment to post when marking as stale. Set to `false` to disable
markComment: >

View File

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

View File

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

5
.gitignore vendored
View File

@ -1,9 +1,10 @@
tools/xtensa-esp32-elf
tools/xtensa-esp32s2-elf
tools/dist
tools/esptool
tools/esptool.exe
tools/mkspiffs/mkspiffs
tools/mkspiffs/mkspiffs.exe
tools/mkspiffs
tools/mklittlefs
.DS_Store
#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-gpio.c
cores/esp32/esp32-hal-i2c.c
cores/esp32/esp32-hal-log.c
cores/esp32/esp32-hal-ledc.c
cores/esp32/esp32-hal-matrix.c
cores/esp32/esp32-hal-misc.c
@ -60,6 +61,7 @@ set(LIBRARY_SRCS
libraries/SPI/src/SPI.cpp
libraries/Ticker/src/Ticker.cpp
libraries/Update/src/Updater.cpp
libraries/Update/src/HttpsOTAUpdate.cpp
libraries/WebServer/src/WebServer.cpp
libraries/WebServer/src/Parsing.cpp
libraries/WebServer/src/detail/mimetable.cpp
@ -71,11 +73,11 @@ set(LIBRARY_SRCS
libraries/WiFi/src/WiFi.cpp
libraries/WiFi/src/WiFiGeneric.cpp
libraries/WiFi/src/WiFiMulti.cpp
libraries/WiFi/src/WiFiProv.cpp
libraries/WiFi/src/WiFiScan.cpp
libraries/WiFi/src/WiFiServer.cpp
libraries/WiFi/src/WiFiSTA.cpp
libraries/WiFi/src/WiFiUdp.cpp
libraries/WiFiProv/src/WiFiProv.cpp
libraries/Wire/src/Wire.cpp
)
@ -201,13 +203,14 @@ set(COMPONENT_ADD_INCLUDEDIRS
libraries/WebServer/src
libraries/WiFiClientSecure/src
libraries/WiFi/src
libraries/WiFiProv/src
libraries/Wire/src
)
set(COMPONENT_PRIV_INCLUDEDIRS cores/esp32/libb64)
set(COMPONENT_REQUIRES spi_flash mbedtls mdns ethernet esp_adc_cal wifi_provisioning)
set(COMPONENT_PRIV_REQUIRES fatfs nvs_flash app_update spiffs bootloader_support openssl bt)
set(COMPONENT_PRIV_REQUIRES fatfs nvs_flash app_update spiffs bootloader_support openssl bt esp_http_client esp_https_ota)
register_component()

View File

@ -40,6 +40,12 @@ config ARDUINO_RUNNING_CORE
default 1 if ARDUINO_RUN_CORE1
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
bool "Core on which Arduino's event handler is running"
default ARDUINO_EVENT_RUN_CORE1
@ -76,13 +82,18 @@ choice ARDUINO_UDP_RUNNING_CORE
endchoice
config ARDUINO_UDP_TASK_PRIORITY
int "Priority of the UDP task"
default 3
help
Select at what priority you want the UDP task to run.
config ARDUINO_UDP_RUNNING_CORE
int
default 0 if ARDUINO_UDP_RUN_CORE0
default 1 if ARDUINO_UDP_RUN_CORE1
default -1 if ARDUINO_UDP_RUN_NO_AFFINITY
config DISABLE_HAL_LOCKS
bool "Disable mutex locks for HAL"
default "n"

View File

@ -11,9 +11,11 @@
- [ESP32Dev Board PINMAP](#esp32dev-board-pinmap)
### Development Status
[Latest stable release ![Release Version](https://img.shields.io/github/release/espressif/arduino-esp32.svg?style=plastic) ![Release Date](https://img.shields.io/github/release-date/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) ![Downloads](https://img.shields.io/github/downloads/espressif/arduino-esp32/latest/total.svg?style=plastic)
[Latest development release ![Development Version](https://img.shields.io/github/release/espressif/arduino-esp32/all.svg?style=plastic) ![Development Date](https://img.shields.io/github/release-date-pre/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) ![Downloads](https://img.shields.io/github/downloads-pre/espressif/arduino-esp32/latest/total.svg?style=plastic)
Latest Stable Release [![Release Version](https://img.shields.io/github/release/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) [![Release Date](https://img.shields.io/github/release-date/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) [![Downloads](https://img.shields.io/github/downloads/espressif/arduino-esp32/latest/total.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/)
Latest Development Release [![Release Version](https://img.shields.io/github/release/espressif/arduino-esp32/all.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) [![Release Date](https://img.shields.io/github/release-date-pre/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) [![Downloads](https://img.shields.io/github/downloads-pre/espressif/arduino-esp32/latest/total.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/)
### Installation Instructions
- Using Arduino IDE Boards Manager (preferred)

1778
boards.txt

File diff suppressed because it is too large Load Diff

View File

@ -78,7 +78,7 @@
#define interrupts() sei()
#define noInterrupts() cli()
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
#define clockCyclesPerMicrosecond() ( (long int)getCpuFrequencyMhz() )
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
@ -88,7 +88,7 @@
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit))
// avr-libc defines _NOP() since 1.6.2
#ifndef _NOP

View File

@ -218,6 +218,33 @@ uint8_t EspClass::getChipRevision(void)
return chip_info.revision;
}
const char * EspClass::getChipModel(void)
{
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
uint32_t pkg_ver = chip_ver & 0x7;
switch (pkg_ver) {
case EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ6 :
return "ESP32-D0WDQ6";
case EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ5 :
return "ESP32-D0WDQ5";
case EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 :
return "ESP32-D2WDQ5";
case EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2 :
return "ESP32-PICO-D2";
case EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4 :
return "ESP32-PICO-D4";
default:
return "Unknown";
}
}
uint8_t EspClass::getChipCores(void)
{
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
return chip_info.cores;
}
const char * EspClass::getSdkVersion(void)
{
return esp_get_idf_version();
@ -309,6 +336,20 @@ bool EspClass::flashRead(uint32_t offset, uint32_t *data, size_t size)
return spi_flash_read(offset, (uint32_t*) data, size) == ESP_OK;
}
bool EspClass::partitionEraseRange(const esp_partition_t *partition, uint32_t offset, size_t size)
{
return esp_partition_erase_range(partition, offset, size) == ESP_OK;
}
bool EspClass::partitionWrite(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size)
{
return esp_partition_write(partition, offset, data, size) == ESP_OK;
}
bool EspClass::partitionRead(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size)
{
return esp_partition_read(partition, offset, data, size) == ESP_OK;
}
uint64_t EspClass::getEfuseMac(void)
{

View File

@ -21,6 +21,7 @@
#define ESP_H
#include <Arduino.h>
#include <esp_partition.h>
/**
* AVR macros for WDT managment
@ -75,6 +76,8 @@ public:
uint32_t getMaxAllocPsram();
uint8_t getChipRevision();
const char * getChipModel();
uint8_t getChipCores();
uint32_t getCpuFreqMHz(){ return getCpuFrequencyMhz(); }
inline uint32_t getCycleCount() __attribute__((always_inline));
const char * getSdkVersion();
@ -97,6 +100,10 @@ public:
bool flashWrite(uint32_t offset, uint32_t *data, size_t size);
bool flashRead(uint32_t offset, uint32_t *data, size_t size);
bool partitionEraseRange(const esp_partition_t *partition, uint32_t offset, size_t size);
bool partitionWrite(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size);
bool partitionRead(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size);
uint64_t getEfuseMac();
};

View File

@ -53,6 +53,8 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
}
_uart = uartBegin(_uart_nr, baud ? baud : 9600, config, rxPin, txPin, 256, invert);
_tx_pin = txPin;
_rx_pin = rxPin;
if(!baud) {
uartStartDetectBaudrate(_uart);
@ -70,6 +72,8 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
} else {
log_e("Could not detect baudrate. Serial data at the port must be present within the timeout for detection to be possible");
_uart = NULL;
_tx_pin = 255;
_rx_pin = 255;
}
}
}
@ -84,7 +88,8 @@ void HardwareSerial::end()
if(uartGetDebug() == _uart_nr) {
uartSetDebug(0);
}
uartEnd(_uart);
log_v("pins %d %d",_tx_pin, _rx_pin);
uartEnd(_uart, _tx_pin, _rx_pin);
_uart = 0;
}
@ -179,3 +184,8 @@ HardwareSerial::operator bool() const
{
return true;
}
void HardwareSerial::setRxInvert(bool invert)
{
uartSetRxInvert(_uart, invert);
}

View File

@ -100,10 +100,14 @@ public:
size_t setRxBufferSize(size_t);
void setDebugOutput(bool);
void setRxInvert(bool);
protected:
int _uart_nr;
uart_t* _uart;
uint8_t _tx_pin;
uint8_t _rx_pin;
};
extern void serialEventRun(void) __attribute__((weak));

View File

@ -111,18 +111,12 @@ size_t Print::print(unsigned int n, int base)
size_t Print::print(long n, int base)
{
if(base == 0) {
return write(n);
} else if(base == 10) {
if(n < 0) {
int t = print('-');
n = -n;
return printNumber(n, 10) + t;
}
return printNumber(n, 10);
} else {
return printNumber(n, base);
int t = 0;
if (base == 10 && n < 0) {
t = print('-');
n = -n;
}
return printNumber(static_cast<unsigned long>(n), base) + t;
}
size_t Print::print(unsigned long n, int base)
@ -134,6 +128,25 @@ size_t Print::print(unsigned long n, int base)
}
}
size_t Print::print(long long n, int base)
{
int t = 0;
if (base == 10 && n < 0) {
t = print('-');
n = -n;
}
return printNumber(static_cast<unsigned long long>(n), base) + t;
}
size_t Print::print(unsigned long long n, int base)
{
if (base == 0) {
return write(n);
} else {
return printNumber(n, base);
}
}
size_t Print::print(double n, int digits)
{
return printFloat(n, digits);
@ -226,6 +239,20 @@ size_t Print::println(unsigned long num, int base)
return n;
}
size_t Print::println(long long num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(unsigned long long num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(double num, int digits)
{
size_t n = print(num, digits);
@ -251,7 +278,7 @@ size_t Print::println(struct tm * timeinfo, const char * format)
size_t Print::printNumber(unsigned long n, uint8_t base)
{
char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
char buf[8 * sizeof(n) + 1]; // Assumes 8-bit chars plus zero byte.
char *str = &buf[sizeof(buf) - 1];
*str = '\0';
@ -262,11 +289,34 @@ size_t Print::printNumber(unsigned long n, uint8_t base)
}
do {
unsigned long m = n;
char c = n % base;
n /= base;
*--str = c < 10 ? c + '0' : c + 'A' - 10;
} while (n);
return write(str);
}
size_t Print::printNumber(unsigned long long n, uint8_t base)
{
char buf[8 * sizeof(n) + 1]; // Assumes 8-bit chars plus zero byte.
char* str = &buf[sizeof(buf) - 1];
*str = '\0';
// prevent crash if called with base == 1
if (base < 2) {
base = 10;
}
do {
auto m = n;
n /= base;
char c = m - base * n;
*--str = c < 10 ? c + '0' : c + 'A' - 10;
} while(n);
} while (n);
return write(str);
}

View File

@ -36,6 +36,7 @@ class Print
private:
int write_error;
size_t printNumber(unsigned long, uint8_t);
size_t printNumber(unsigned long long, uint8_t);
size_t printFloat(double, uint8_t);
protected:
void setWriteError(int err = 1)
@ -72,6 +73,11 @@ public:
}
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 String &);
size_t print(const char[]);
@ -81,6 +87,8 @@ public:
size_t print(unsigned int, int = DEC);
size_t print(long, int = DEC);
size_t print(unsigned long, int = DEC);
size_t print(long long, int = DEC);
size_t print(unsigned long long, int = DEC);
size_t print(double, int = 2);
size_t print(const Printable&);
size_t print(struct tm * timeinfo, const char * format = NULL);
@ -94,6 +102,8 @@ public:
size_t println(unsigned int, int = DEC);
size_t println(long, int = DEC);
size_t println(unsigned long, int = DEC);
size_t println(long long, int = DEC);
size_t println(unsigned long long, int = DEC);
size_t println(double, int = 2);
size_t println(const Printable&);
size_t println(struct tm * timeinfo, const char * format = NULL);

View File

@ -87,22 +87,22 @@ unsigned long Stream::getTimeout(void) {
}
// find returns true if the target string is found
bool Stream::find(const char *target)
bool Stream::find(const char *target)
{
return findUntil(target, (char*) "");
return findUntil(target, strlen(target), NULL, 0);
}
// reads data from the stream until the target string of given length is found
// returns true if target string is found, false if timed out
bool Stream::find(const char *target, size_t length)
{
return findUntil(target, length, NULL, 0);
return findUntil(target, length, NULL, 0);
}
// as find but search ends if the terminator string is found
bool Stream::findUntil(const char *target, const char *terminator)
bool Stream::findUntil(const char *target, const char *terminator)
{
return findUntil(target, strlen(target), terminator, strlen(terminator));
return findUntil(target, strlen(target), terminator, strlen(terminator));
}
// reads data from the stream until the target string of the given length is found
@ -110,35 +110,78 @@ bool Stream::findUntil(const char *target, const char *terminator)
// returns true if target string is found, false if terminated or timed out
bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen)
{
size_t index = 0; // maximum target string length is 64k bytes!
size_t termIndex = 0;
int c;
if (terminator == NULL) {
MultiTarget t[1] = {{target, targetLen, 0}};
return findMulti(t, 1) == 0 ? true : false;
} else {
MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}};
return findMulti(t, 2) == 0 ? true : false;
}
}
if(*target == 0) {
return true; // return true if target is a null string
int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) {
// any zero length target string automatically matches and would make
// a mess of the rest of the algorithm.
for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
if (t->len <= 0)
return t - targets;
}
while (1) {
int c = timedRead();
if (c < 0)
return -1;
for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
// the simple case is if we match, deal with that first.
if (c == t->str[t->index]) {
if (++t->index == t->len)
return t - targets;
else
continue;
}
// if not we need to walk back and see if we could have matched further
// down the stream (ie '1112' doesn't match the first position in '11112'
// but it will match the second position so we can't just reset the current
// index to 0 when we find a mismatch.
if (t->index == 0)
continue;
int origIndex = t->index;
do {
--t->index;
// first check if current char works against the new current index
if (c != t->str[t->index])
continue;
// if it's the only char then we're good, nothing more to check
if (t->index == 0) {
t->index++;
break;
}
// otherwise we need to check the rest of the found string
int diff = origIndex - t->index;
size_t i;
for (i = 0; i < t->index; ++i) {
if (t->str[i] != t->str[i + diff])
break;
}
// if we successfully got through the previous loop then our current
// index is good.
if (i == t->index) {
t->index++;
break;
}
// otherwise we just try the next index
} while (t->index);
}
while((c = timedRead()) > 0) {
if(c != target[index]) {
index = 0; // reset index if any char does not match
}
if(c == target[index]) {
//////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
if(++index >= targetLen) { // return true if all chars in the target match
return true;
}
}
if(termLen > 0 && c == terminator[termIndex]) {
if(++termIndex >= termLen) {
return false; // return false if terminate string found before target string
}
} else {
termIndex = 0;
}
}
return false;
}
// unreachable
return -1;
}
// returns the first valid (long) integer value from the current position.

View File

@ -60,6 +60,7 @@ public:
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
unsigned long getTimeout(void);
bool find(const char *target); // reads data from the stream until the target string is found
bool find(uint8_t *target)
{
@ -123,6 +124,17 @@ protected:
// this allows format characters (typically commas) in values to be ignored
float parseFloat(char skipChar); // as above but the given skipChar is ignored
struct MultiTarget {
const char *str; // string you're searching for
size_t len; // length of string you're searching for
size_t index; // index used by the search routine.
};
// This allows you to search for an arbitrary number of strings.
// Returns index of the target that is found first or -1 if timeout occurs.
int findMulti(struct MultiTarget *targets, int tCount);
};
#endif

View File

@ -43,6 +43,7 @@ class UDP: public Stream
public:
virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
virtual uint8_t beginMulticast(IPAddress, uint16_t) { return 0; } // initialize, start listening on specified multicast IP address and port. Returns 1 if successful, 0 on failure
virtual void stop() =0; // Finish with the UDP socket
// Sending UDP packets

View File

@ -27,6 +27,7 @@ extern "C" {
#include <stdlib.h>
#include "esp_system.h"
}
#include "esp32-hal-log.h"
void randomSeed(unsigned long seed)
{
@ -44,7 +45,7 @@ long random(long howbig)
uint32_t t = -howbig;
if (t >= howbig) {
t -= howbig;
if (t >= howbig)
if (t >= howbig)
t %= howbig;
}
while (l < t) {
@ -66,11 +67,14 @@ long random(long howsmall, long howbig)
}
long map(long x, long in_min, long in_max, long out_min, long out_max) {
long divisor = (in_max - in_min);
const long dividend = out_max - out_min;
const long divisor = in_max - 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 (x - in_min) * (out_max - out_min) / divisor + out_min;
return (delta * dividend + (divisor / 2)) / divisor + out_min;
}
unsigned int makeWord(unsigned int w)

View File

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

View File

@ -18,11 +18,12 @@
bool btInUse(){ return true; }
#ifdef CONFIG_BLUEDROID_ENABLED
#include "esp_bt.h"
#ifdef CONFIG_CLASSIC_BT_ENABLED
#ifdef CONFIG_BTDM_CONTROLLER_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
#define BT_MODE ESP_BT_MODE_BLE
#endif
@ -79,7 +80,7 @@ bool btStop(){
return false;
}
#else
#else // CONFIG_BT_ENABLED
bool btStarted()
{
return false;
@ -94,6 +95,6 @@ bool btStop()
{
return false;
}
#endif
#endif
#endif // CONFIG_BT_ENABLED

View File

@ -945,6 +945,14 @@ static void IRAM_ATTR i2c_isr_handler_default(void* arg)
activeInt &=~I2C_RXFIFO_FULL_INT_ST;
}
if(activeInt & I2C_RXFIFO_OVF_INT_ST) {
emptyRxFifo(p_i2c);
p_i2c->dev->int_clr.rx_fifo_full=1;
p_i2c->dev->int_ena.rx_fifo_full=1; //why?
activeInt &=~I2C_RXFIFO_OVF_INT_ST;
}
if (activeInt & I2C_ACK_ERR_INT_ST_M) {//fatal error, abort i2c service
if (p_i2c->mode == I2C_MASTER) {
i2c_update_error_byte_cnt(p_i2c); // calc which byte caused ack Error, check if address or data

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
#else
#define ARDUHAL_LOG_LEVEL CORE_DEBUG_LEVEL
#ifdef USE_ESP_IDF_LOG
#define LOG_LOCAL_LEVEL CORE_DEBUG_LEVEL
#endif
#endif
#ifndef CONFIG_ARDUHAL_LOG_COLORS
@ -71,6 +74,8 @@ extern "C"
#define ARDUHAL_LOG_RESET_COLOR
#endif
const char * pathToFileName(const char * path);
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__
#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 isr_log_v(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(V, format), ##__VA_ARGS__)
#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 isr_log_v(format, ...)
#endif
#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 isr_log_d(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(D, format), ##__VA_ARGS__)
#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 isr_log_d(format, ...)
#endif
#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 isr_log_i(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(I, format), ##__VA_ARGS__)
#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 isr_log_i(format, ...)
#endif
#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 isr_log_w(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(W, format), ##__VA_ARGS__)
#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 isr_log_w(format, ...)
#endif
#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 isr_log_e(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
#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 isr_log_e(format, ...)
#endif
#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 isr_log_n(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
#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 isr_log_n(format, ...)
#endif
#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
#undef ESP_LOGE
#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_LOGV(tag, ...) isr_log_v(__VA_ARGS__)
#endif
#endif
#ifdef __cplusplus
}

View File

@ -94,6 +94,7 @@ struct rmt_obj_s
transaction_state_t tx_state;
rmt_rx_data_cb_t cb;
bool data_alloc;
void * arg;
};
/**
@ -104,14 +105,14 @@ static xSemaphoreHandle g_rmt_objlocks[MAX_CHANNELS] = {
};
static rmt_obj_t g_rmt_objects[MAX_CHANNELS] = {
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
};
/**
@ -240,7 +241,6 @@ bool rmtLoop(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
return false;
}
int channel = rmt->channel;
int allocated_size = MAX_DATA_PER_CHANNEL * rmt->buffers;
if (size > allocated_size) {
@ -324,6 +324,7 @@ bool rmtReadData(rmt_obj_t* rmt, uint32_t* data, size_t size)
return true;
}
bool rmtBeginReceive(rmt_obj_t* rmt)
{
if (!rmt) {
@ -357,7 +358,7 @@ bool rmtReceiveCompleted(rmt_obj_t* rmt)
}
}
bool rmtRead(rmt_obj_t* rmt, rmt_rx_data_cb_t cb)
bool rmtRead(rmt_obj_t* rmt, rmt_rx_data_cb_t cb, void * arg)
{
if (!rmt && !cb) {
return false;
@ -365,6 +366,7 @@ bool rmtRead(rmt_obj_t* rmt, rmt_rx_data_cb_t cb)
int channel = rmt->channel;
RMT_MUTEX_LOCK(channel);
rmt->arg = arg;
rmt->intr_mode = E_RX_INTR;
rmt->tx_state = E_FIRST_HALF;
rmt->cb = cb;
@ -391,6 +393,19 @@ bool rmtRead(rmt_obj_t* rmt, rmt_rx_data_cb_t cb)
return true;
}
bool rmtEnd(rmt_obj_t* rmt) {
if (!rmt) {
return false;
}
int channel = rmt->channel;
RMT_MUTEX_LOCK(channel);
RMT.conf_ch[channel].conf1.rx_en = 1;
RMT_MUTEX_UNLOCK(channel);
return true;
}
bool rmtReadAsync(rmt_obj_t* rmt, rmt_data_t* data, size_t size, void* eventFlag, bool waitForData, uint32_t timeout)
{
if (!rmt) {
@ -523,6 +538,8 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
rmt->tx_not_rx = tx_not_rx;
rmt->buffers =buffers;
rmt->channel = channel;
rmt->arg = NULL;
_initPin(pin, channel, tx_not_rx);
// Initialize the registers in default mode:
@ -544,6 +561,7 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
RMT.conf_ch[channel].conf1.idle_out_lv = 0; // signal level for idle
RMT.conf_ch[channel].conf1.idle_out_en = 1; // enable idle
RMT.conf_ch[channel].conf1.ref_always_on = 0; // base clock
RMT.apb_conf.fifo_mask = 1;
if (tx_not_rx) {
@ -659,7 +677,7 @@ static void IRAM_ATTR _rmt_isr(void* arg)
}
if (g_rmt_objects[ch].cb) {
// actually received data ptr
(g_rmt_objects[ch].cb)(data_received, _rmt_get_mem_len(ch));
(g_rmt_objects[ch].cb)(data_received, _rmt_get_mem_len(ch), g_rmt_objects[ch].arg);
// restart the reception
RMT.conf_ch[ch].conf1.mem_owner = 1;

View File

@ -40,7 +40,7 @@ typedef enum {
typedef struct rmt_obj_s rmt_obj_t;
typedef void (*rmt_rx_data_cb_t)(uint32_t *data, size_t len);
typedef void (*rmt_rx_data_cb_t)(uint32_t *data, size_t len, void *arg);
typedef struct {
union {
@ -90,8 +90,13 @@ bool rmtReadAsync(rmt_obj_t* rmt, rmt_data_t* data, size_t size, void* eventFlag
* and callback with data from ISR
*
*/
bool rmtRead(rmt_obj_t* rmt, rmt_rx_data_cb_t cb);
bool rmtRead(rmt_obj_t* rmt, rmt_rx_data_cb_t cb, void * arg);
/***
* Ends async receive started with rmtRead(); but does not
* rmtDeInit().
*/
bool rmtEnd(rmt_obj_t* rmt);
/* Additional interface */

View File

@ -402,9 +402,9 @@ void spiStopBus(spi_t * spi)
if(!spi) {
return;
}
removeApbChangeCallback(spi, _on_apb_change);
SPI_MUTEX_LOCK();
spiInitBus(spi);
SPI_MUTEX_UNLOCK();
@ -428,14 +428,14 @@ spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_
#endif
if(spi_num == HSPI) {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST);
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_SPI2_RST);
} else if(spi_num == VSPI) {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_2);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_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_SPI3_RST);
} else {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_1);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_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_SPI01_RST);
}
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;
while(spi->dev->cmd.usr);
if(result){
for (int i=0; i<c_longs; i++) {
result[i] = spi->dev->data_buf[i];
if(c_len & 3){
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){

View File

@ -54,7 +54,7 @@ extern "C" {
struct spi_struct_t;
typedef struct spi_struct_t spi_t;
spi_t * spiStartBus(uint8_t spi_num, uint32_t freq, uint8_t dataMode, uint8_t bitOrder);
spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_t bitOrder);
void spiStopBus(spi_t * spi);
//Attach/Detach Signal Pins

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;
uint64_t h = timer->dev->cnt_high;
uint64_t l = timer->dev->cnt_low;
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 l = timer->dev->alarm_low;
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_low = (uint32_t) (val);
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_low = (uint32_t) alarm_value;
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;
}
uint32_t timerGetConfig(hw_timer_t *timer){
uint32_t IRAM_ATTR timerGetConfig(hw_timer_t *timer){
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;
}
bool timerGetCountUp(hw_timer_t *timer){
bool IRAM_ATTR timerGetCountUp(hw_timer_t *timer){
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;
}
bool timerGetAutoReload(hw_timer_t *timer){
bool IRAM_ATTR timerGetAutoReload(hw_timer_t *timer){
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){
divider = 0xFFFF;
} 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;
}
uint16_t timerGetDivider(hw_timer_t *timer){
uint16_t IRAM_ATTR timerGetDivider(hw_timer_t *timer){
return timer->dev->config.divider;
}
void timerStart(hw_timer_t *timer){
void IRAM_ATTR timerStart(hw_timer_t *timer){
timer->dev->config.enable = 1;
}
void timerStop(hw_timer_t *timer){
void IRAM_ATTR timerStop(hw_timer_t *timer){
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->reload = 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;
}
void timerAlarmEnable(hw_timer_t *timer){
void IRAM_ATTR timerAlarmEnable(hw_timer_t *timer){
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;
}
bool timerAlarmEnabled(hw_timer_t *timer){
bool IRAM_ATTR timerAlarmEnabled(hw_timer_t *timer){
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;
if(ev_type == APB_BEFORE_CHANGE){
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){
return NULL;
}
@ -222,13 +222,13 @@ hw_timer_t * timerBegin(uint8_t num, uint16_t divider, bool countUp){
return timer;
}
void timerEnd(hw_timer_t *timer){
void IRAM_ATTR timerEnd(hw_timer_t *timer){
timer->dev->config.enable = 0;
timerAttachInterrupt(timer, NULL, false);
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 intr_handle_t intr_handle = NULL;
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);
}
uint64_t timerReadMicros(hw_timer_t *timer){
uint64_t IRAM_ATTR timerReadMicros(hw_timer_t *timer){
uint64_t timer_val = timerRead(timer);
uint16_t div = timerGetDivider(timer);
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);
uint16_t div = timerGetDivider(timer);
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);
uint16_t div = timerGetDivider(timer);
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);
uint16_t div = timerGetDivider(timer);
return (double)timer_val * div / getApbFrequency();

View File

@ -124,21 +124,21 @@ void uartDisableInterrupt(uart_t* uart)
UART_MUTEX_UNLOCK();
}
void uartDetachRx(uart_t* uart)
void uartDetachRx(uart_t* uart, uint8_t rxPin)
{
if(uart == NULL) {
return;
}
pinMatrixInDetach(UART_RXD_IDX(uart->num), false, false);
pinMatrixInDetach(rxPin, false, false);
uartDisableInterrupt(uart);
}
void uartDetachTx(uart_t* uart)
void uartDetachTx(uart_t* uart, uint8_t txPin)
{
if(uart == NULL) {
return;
}
pinMatrixOutDetach(UART_TXD_IDX(uart->num), false, false);
pinMatrixOutDetach(txPin, false, false);
}
void uartAttachRx(uart_t* uart, uint8_t rxPin, bool inverted)
@ -226,7 +226,7 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
return uart;
}
void uartEnd(uart_t* uart)
void uartEnd(uart_t* uart, uint8_t txPin, uint8_t rxPin)
{
if(uart == NULL) {
return;
@ -243,8 +243,8 @@ void uartEnd(uart_t* uart)
UART_MUTEX_UNLOCK();
uartDetachRx(uart);
uartDetachTx(uart);
uartDetachRx(uart, rxPin);
uartDetachTx(uart, txPin);
}
size_t uartResizeRxBuffer(uart_t * uart, size_t new_size) {
@ -257,6 +257,7 @@ size_t uartResizeRxBuffer(uart_t * uart, size_t new_size) {
vQueueDelete(uart->queue);
uart->queue = xQueueCreate(new_size, sizeof(uint8_t));
if(uart->queue == NULL) {
UART_MUTEX_UNLOCK();
return NULL;
}
}
@ -265,6 +266,17 @@ size_t uartResizeRxBuffer(uart_t * uart, size_t new_size) {
return new_size;
}
void uartSetRxInvert(uart_t* uart, bool invert)
{
if (uart == NULL)
return;
if (invert)
uart->dev->conf0.rxd_inv = 1;
else
uart->dev->conf0.rxd_inv = 0;
}
uint32_t uartAvailable(uart_t* uart)
{
if(uart == NULL || uart->queue == NULL) {
@ -359,7 +371,7 @@ void uartWriteBuf(uart_t* uart, const uint8_t * data, size_t len)
void uartFlush(uart_t* uart)
{
uartFlushTxOnly(uart,false);
uartFlushTxOnly(uart,true);
}
void uartFlushTxOnly(uart_t* uart, bool txOnly)

View File

@ -52,7 +52,7 @@ struct uart_struct_t;
typedef struct uart_struct_t uart_t;
uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint16_t queueLen, bool inverted);
void uartEnd(uart_t* uart);
void uartEnd(uart_t* uart, uint8_t rxPin, uint8_t txPin);
uint32_t uartAvailable(uart_t* uart);
uint32_t uartAvailableForWrite(uart_t* uart);
@ -70,6 +70,8 @@ uint32_t uartGetBaudRate(uart_t* uart);
size_t uartResizeRxBuffer(uart_t* uart, size_t new_size);
void uartSetRxInvert(uart_t* uart, bool invert);
void uartSetDebug(uart_t* uart);
int uartGetDebug();

View File

@ -3,6 +3,10 @@
#include "esp_task_wdt.h"
#include "Arduino.h"
#ifndef CONFIG_ARDUINO_LOOP_STACK_SIZE
#define CONFIG_ARDUINO_LOOP_STACK_SIZE 8192
#endif
TaskHandle_t loopTaskHandle = NULL;
#if CONFIG_AUTOSTART_ARDUINO
@ -25,7 +29,7 @@ extern "C" void app_main()
{
loopTaskWDTEnabled = false;
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

View File

@ -53,6 +53,8 @@ typedef unsigned long prog_uint32_t;
*(void * const *)(_addr); \
})
#define pgm_get_far_address(x) ((uint32_t)(&(x)))
#define pgm_read_byte_near(addr) pgm_read_byte(addr)
#define pgm_read_word_near(addr) pgm_read_word(addr)
#define pgm_read_dword_near(addr) pgm_read_dword(addr)

View File

@ -16,7 +16,7 @@
Boston, MA 02111-1307 USA
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
*/
#include "esp32-hal.h"
#include "wiring_private.h"

View File

@ -1,26 +1,28 @@
Make your question, not a Statement, inclusive. Include all pertinent information:
What you are trying to do.
Describe your system( Hardware, computer, O/S, core version, environment)
Describe what is failing
Show the shortest possible code that will duplicate the error
Show the EXACT error message(it doesn't work is not enough)
What you are trying to do
Describe your system (Hardware, computer, O/S, core version, environment)
Describe what is failing
Show the shortest possible code that will duplicate the error
Show the EXACT error message (it doesn't work is not enough)
Then if someone is interested and knowledgeable you might get a answer. All of this work on your part shows us that you have worked to solve YOUR problem. The more complete your issue posting is, the more likely someone will volunteer their time to help you.
If you have a Guru Meditation Error or Backtrace, ***please decode it***:
https://github.com/me-no-dev/EspExceptionDecoder
[ExceptionDecoder](https://github.com/me-no-dev/EspExceptionDecoder)
----------------------------- Remove above -----------------------------
### Hardware:
Board: ?ESP32 Dev Module? ?node32? ?ttgo_lora?
Core Installation/update date: ?11/jul/2017?
IDE name: ?Arduino IDE? ?Platform.io? ?IDF component?
Flash Frequency: ?40Mhz?
PSRAM enabled: ?no?
Upload Speed: ?115200?
Computer OS: ?Windows 10? ?Mac OSX? ?Ubuntu?
|||||||
|:---|---|---|---|---|---|
|<B>Board</B>|ESP32 Dev Module|node32|ttgo_lora|ESP32-S2-Saola|Custom w/ ESP32-S2-WROVER 16MB|
|<B>Version/Date</B>|1.0.4|2.0.0|0badbeef|11/jul/2017|today's master|
|<B>IDE name</B>|Arduino IDE|Atom + Platform.io|IDF component|VSCode|
|<B>Flash Frequency</B>|40Mhz|80Mhz|
|<B>PSRAM enabled</B>|yes|no|
|<B>Upload Speed</B>|115200|
|<B>Computer OS</B>|Windows 10|Mac OSX|Ubuntu|
### Description:
Describe your problem here

View File

@ -4,7 +4,7 @@
- Stable release link: `https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json`
- Development release link: `https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json`
Starting with 1.6.4, Arduino allows installation of third-party platform packages using Boards Manager. We have packages available for Windows, Mac OS, and Linux (32, 64 bit and ARM).
Starting with 1.6.4, Arduino allows installation of third-party platform packages using Boards Manager. We have packages available for Windows, Mac OS, and Linux (x86, amd64, armhf and arm64).
- Install the current upstream Arduino IDE at the 1.8 level or later. The current version is at the [Arduino website](http://www.arduino.cc/en/main/software).
- Start Arduino and open Preferences window.

View File

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

View File

@ -7,9 +7,9 @@ Installation instructions for Mac OS
```bash
mkdir -p ~/Documents/Arduino/hardware/espressif && \
cd ~/Documents/Arduino/hardware/espressif && \
git clone https://github.com/espressif/arduino-esp32.git esp32 && \
git clone https://github.com/espressif/arduino-esp32.git esp32 --depth 1 && \
cd esp32 && \
git submodule update --init --recursive && \
git submodule update --init --recursive --depth 1 && \
cd tools && \
python get.py
```

View File

@ -72,6 +72,11 @@ If you are writing code that does not require Arduino to compile and you want yo
#endif
```
## FreeRTOS Tick Rate (Hz)
You might notice that Arduino-esp32's `delay()` function will only work in multiples of 10ms. That is because, by default, esp-idf handles task events 100 times per second.
To fix that behavior you need to set FreeRTOS tick rate to 1000Hz in `make menuconfig` -> `Component config` -> `FreeRTOS` -> `Tick rate`.
## Compilation Errors
As commits are made to esp-idf and submodules, the codebases can develop incompatibilities which cause compilation errors. If you have problems compiling, follow the instructions in [Issue #1142](https://github.com/espressif/arduino-esp32/issues/1142) to roll esp-idf back to a known good version.

View File

@ -14,7 +14,7 @@ WebServer server(80);
* Login page
*/
const char* loginIndex =
const char* loginIndex =
"<form name='loginForm'>"
"<table width='20%' bgcolor='A09F9F' align='center'>"
"<tr>"
@ -25,8 +25,9 @@ const char* loginIndex =
"<br>"
"<br>"
"</tr>"
"<td>Username:</td>"
"<td><input type='text' size=25 name='userid'><br></td>"
"<tr>"
"<td>Username:</td>"
"<td><input type='text' size=25 name='userid'><br></td>"
"</tr>"
"<br>"
"<br>"
@ -54,12 +55,12 @@ const char* loginIndex =
"}"
"}"
"</script>";
/*
* Server Index Page
*/
const char* serverIndex =
const char* serverIndex =
"<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>"
"<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>"
"<input type='file' name='update'>"
@ -88,7 +89,7 @@ const char* serverIndex =
"return xhr;"
"},"
"success:function(d, s) {"
"console.log('success!')"
"console.log('success!')"
"},"
"error: function (a, b, c) {"
"}"

View File

@ -88,6 +88,17 @@ ArduinoOTAClass& ArduinoOTAClass::setPasswordHash(const char * password) {
return *this;
}
ArduinoOTAClass& ArduinoOTAClass::setPartitionLabel(const char * partition_label) {
if (!_initialized && !_partition_label.length() && partition_label) {
_partition_label = partition_label;
}
return *this;
}
String ArduinoOTAClass::getPartitionLabel() {
return _partition_label;
}
ArduinoOTAClass& ArduinoOTAClass::setRebootOnSuccess(bool reboot){
_rebootOnSuccess = reboot;
return *this;
@ -235,7 +246,8 @@ void ArduinoOTAClass::_onRx(){
}
void ArduinoOTAClass::_runUpdate() {
if (!Update.begin(_size, _cmd)) {
const char *partition_label = _partition_label.length() ? _partition_label.c_str() : NULL;
if (!Update.begin(_size, _cmd, -1, LOW, partition_label)) {
log_e("Begin ERROR: %s", Update.errorString());
@ -358,7 +370,7 @@ void ArduinoOTAClass::end() {
void ArduinoOTAClass::handle() {
if (!_initialized) {
return;
return;
}
if (_state == OTA_RUNUPDATE) {
_runUpdate();

View File

@ -44,6 +44,10 @@ class ArduinoOTAClass
//Sets the password as above but in the form MD5(password). Default NULL
ArduinoOTAClass& setPasswordHash(const char *password);
//Sets the partition label to write to when updating SPIFFS. Default NULL
ArduinoOTAClass &setPartitionLabel(const char *partition_label);
String getPartitionLabel();
//Sets if the device should be rebooted after successful update. Default true
ArduinoOTAClass& setRebootOnSuccess(bool reboot);
@ -80,6 +84,7 @@ class ArduinoOTAClass
int _port;
String _password;
String _hostname;
String _partition_label;
String _nonce;
WiFiUDP _udp_ota;
bool _initialized;

View File

@ -150,7 +150,7 @@ static bool _udp_task_start(){
}
}
if(!_udp_task_handle){
xTaskCreateUniversal(_udp_task, "async_udp", 4096, NULL, 3, (TaskHandle_t*)&_udp_task_handle, CONFIG_ARDUINO_UDP_RUNNING_CORE);
xTaskCreateUniversal(_udp_task, "async_udp", 4096, NULL, CONFIG_ARDUINO_UDP_TASK_PRIORITY, (TaskHandle_t*)&_udp_task_handle, CONFIG_ARDUINO_UDP_RUNNING_CORE);
if(!_udp_task_handle){
return false;
}
@ -277,6 +277,22 @@ void AsyncUDPMessage::flush()
_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)
{
@ -294,18 +310,18 @@ AsyncUDPPacket::AsyncUDPPacket(AsyncUDP *udp, pbuf *pb, const ip_addr_t *raddr,
_localIp.type = _remoteIp.type;
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);
_remotePort = ntohs(udphdr->src);
if (_remoteIp.type == IPADDR_TYPE_V4) {
eth = (eth_hdr *)(((uint8_t *)(pb->payload)) - UDP_HLEN - IP_HLEN - SIZEOF_ETH_HDR);
struct ip_hdr * iphdr = (struct ip_hdr *)(((uint8_t *)(pb->payload)) - UDP_HLEN - IP_HLEN);
eth = (eth_hdr *)(_data - UDP_HLEN - IP_HLEN - SIZEOF_ETH_HDR);
struct ip_hdr * iphdr = (struct ip_hdr *)(_data - UDP_HLEN - IP_HLEN);
_localIp.u_addr.ip4.addr = iphdr->dest.addr;
_remoteIp.u_addr.ip4.addr = iphdr->src.addr;
} else {
eth = (eth_hdr *)(((uint8_t *)(pb->payload)) - UDP_HLEN - IP6_HLEN - SIZEOF_ETH_HDR);
struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(((uint8_t *)(pb->payload)) - UDP_HLEN - IP6_HLEN);
eth = (eth_hdr *)(_data - UDP_HLEN - IP6_HLEN - SIZEOF_ETH_HDR);
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(&_remoteIp.u_addr.ip6.addr, (uint8_t *)ip6hdr->src.addr, 16);
}
@ -479,6 +495,7 @@ AsyncUDP::AsyncUDP()
{
_pcb = NULL;
_connected = false;
_lastErr = ERR_OK;
_handler = NULL;
}
@ -517,8 +534,8 @@ bool AsyncUDP::connect(const ip_addr_t *addr, uint16_t port)
}
close();
UDP_MUTEX_LOCK();
err_t err = _udp_connect(_pcb, addr, port);
if(err != ERR_OK) {
_lastErr = _udp_connect(_pcb, addr, port);
if(_lastErr != ERR_OK) {
UDP_MUTEX_UNLOCK();
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) {
len = CONFIG_TCP_MSS;
}
err_t err = ERR_OK;
_lastErr = ERR_OK;
pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
if(pbt != NULL) {
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;
tcpip_adapter_get_netif((tcpip_adapter_if_t)tcpip_if, &nif);
if(!nif){
err = _udp_sendto(_pcb, pbt, addr, port);
_lastErr = _udp_sendto(_pcb, pbt, addr, port);
} else {
err = _udp_sendto_if(_pcb, pbt, addr, port, (struct netif *)nif);
_lastErr = _udp_sendto_if(_pcb, pbt, addr, port, (struct netif *)nif);
}
} else {
err = _udp_sendto(_pcb, pbt, addr, port);
_lastErr = _udp_sendto(_pcb, pbt, addr, port);
}
UDP_MUTEX_UNLOCK();
pbuf_free(pbt);
if(err < ERR_OK) {
if(_lastErr < ERR_OK) {
return 0;
}
return len;
@ -682,9 +699,8 @@ void AsyncUDP::_recv(udp_pcb *upcb, pbuf *pb, const ip_addr_t *addr, uint16_t po
if(_handler) {
AsyncUDPPacket packet(this, this_pb, addr, port, netif);
_handler(packet);
} else {
pbuf_free(this_pb);
}
pbuf_free(this_pb);
}
}
@ -870,6 +886,10 @@ bool AsyncUDP::connected()
return _connected;
}
esp_err_t AsyncUDP::lastErr() {
return _lastErr;
}
void AsyncUDP::onPacket(AuPacketHandlerFunctionWithArg cb, void * arg)
{
onPacket(std::bind(cb, arg, std::placeholders::_1));

View File

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

View File

@ -0,0 +1,153 @@
/*
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp
Ported to Arduino ESP32 by Evandro Copercini
Changed to a beacon scanner to report iBeacon, EddystoneURL and EddystoneTLM beacons by beegee-tokyo
*/
#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include <BLEEddystoneURL.h>
#include <BLEEddystoneTLM.h>
#include <BLEBeacon.h>
#define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00) >> 8) + (((x)&0xFF) << 8))
int scanTime = 5; //In seconds
BLEScan *pBLEScan;
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
{
void onResult(BLEAdvertisedDevice advertisedDevice)
{
if (advertisedDevice.haveName())
{
Serial.print("Device name: ");
Serial.println(advertisedDevice.getName().c_str());
Serial.println("");
}
if (advertisedDevice.haveServiceUUID())
{
BLEUUID devUUID = advertisedDevice.getServiceUUID();
Serial.print("Found ServiceUUID: ");
Serial.println(devUUID.toString().c_str());
Serial.println("");
}
else
{
if (advertisedDevice.haveManufacturerData() == true)
{
std::string strManufacturerData = advertisedDevice.getManufacturerData();
uint8_t cManufacturerData[100];
strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0);
if (strManufacturerData.length() == 25 && cManufacturerData[0] == 0x4C && cManufacturerData[1] == 0x00)
{
Serial.println("Found an iBeacon!");
BLEBeacon oBeacon = BLEBeacon();
oBeacon.setData(strManufacturerData);
Serial.printf("iBeacon Frame\n");
Serial.printf("ID: %04X Major: %d Minor: %d UUID: %s Power: %d\n", oBeacon.getManufacturerId(), ENDIAN_CHANGE_U16(oBeacon.getMajor()), ENDIAN_CHANGE_U16(oBeacon.getMinor()), oBeacon.getProximityUUID().toString().c_str(), oBeacon.getSignalPower());
}
else
{
Serial.println("Found another manufacturers beacon!");
Serial.printf("strManufacturerData: %d ", strManufacturerData.length());
for (int i = 0; i < strManufacturerData.length(); i++)
{
Serial.printf("[%X]", cManufacturerData[i]);
}
Serial.printf("\n");
}
}
return;
}
uint8_t *payLoad = advertisedDevice.getPayload();
BLEUUID checkUrlUUID = (uint16_t)0xfeaa;
if (advertisedDevice.getServiceUUID().equals(checkUrlUUID))
{
if (payLoad[11] == 0x10)
{
Serial.println("Found an EddystoneURL beacon!");
BLEEddystoneURL foundEddyURL = BLEEddystoneURL();
std::string eddyContent((char *)&payLoad[11]); // incomplete EddystoneURL struct!
foundEddyURL.setData(eddyContent);
std::string bareURL = foundEddyURL.getURL();
if (bareURL[0] == 0x00)
{
size_t payLoadLen = advertisedDevice.getPayloadLength();
Serial.println("DATA-->");
for (int idx = 0; idx < payLoadLen; idx++)
{
Serial.printf("0x%08X ", payLoad[idx]);
}
Serial.println("\nInvalid Data");
return;
}
Serial.printf("Found URL: %s\n", foundEddyURL.getURL().c_str());
Serial.printf("Decoded URL: %s\n", foundEddyURL.getDecodedURL().c_str());
Serial.printf("TX power %d\n", foundEddyURL.getPower());
Serial.println("\n");
}
else if (payLoad[11] == 0x20)
{
Serial.println("Found an EddystoneTLM beacon!");
BLEEddystoneTLM foundEddyURL = BLEEddystoneTLM();
std::string eddyContent((char *)&payLoad[11]); // incomplete EddystoneURL struct!
eddyContent = "01234567890123";
for (int idx = 0; idx < 14; idx++)
{
eddyContent[idx] = payLoad[idx + 11];
}
foundEddyURL.setData(eddyContent);
Serial.printf("Reported battery voltage: %dmV\n", foundEddyURL.getVolt());
Serial.printf("Reported temperature from TLM class: %.2fC\n", (double)foundEddyURL.getTemp());
int temp = (int)payLoad[16] + (int)(payLoad[15] << 8);
float calcTemp = temp / 256.0f;
Serial.printf("Reported temperature from data: %.2fC\n", calcTemp);
Serial.printf("Reported advertise count: %d\n", foundEddyURL.getCount());
Serial.printf("Reported time since last reboot: %ds\n", foundEddyURL.getTime());
Serial.println("\n");
Serial.print(foundEddyURL.toString().c_str());
Serial.println("\n");
}
}
}
};
void setup()
{
Serial.begin(115200);
Serial.println("Scanning...");
BLEDevice::init("");
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
pBLEScan->setInterval(100);
pBLEScan->setWindow(99); // less or equal setInterval value
}
void loop()
{
// put your main code here, to run repeatedly:
BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
Serial.print("Devices found: ");
Serial.println(foundDevices.getCount());
Serial.println("Scan done!");
pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory
delay(2000);
}

View File

@ -0,0 +1,9 @@
## BLE Beacon Scanner
Initiates a BLE device scan.
Checks if the discovered devices are
- an iBeacon
- an Eddystone TLM beacon
- an Eddystone URL beacon
and sends the decoded beacon information over Serial log

View File

@ -0,0 +1,116 @@
/*
EddystoneTLM beacon by BeeGee based on https://github.com/pcbreflux/espressif/blob/master/esp32/arduino/sketchbook/ESP32_Eddystone_TLM_deepsleep/ESP32_Eddystone_TLM_deepsleep.ino
EddystoneTLM frame specification https://github.com/google/eddystone/blob/master/eddystone-tlm/tlm-plain.md
*/
/*
Create a BLE server that will send periodic Eddystone URL frames.
The design of creating the BLE server is:
1. Create a BLE Server
2. Create advertising data
3. Start advertising.
4. wait
5. Stop advertising.
6. deep sleep
*/
#include "sys/time.h"
#include <Arduino.h>
#include "BLEDevice.h"
#include "BLEUtils.h"
#include "BLEBeacon.h"
#include "BLEAdvertising.h"
#include "BLEEddystoneURL.h"
#include "esp_sleep.h"
#define GPIO_DEEP_SLEEP_DURATION 10 // sleep x seconds and then wake up
RTC_DATA_ATTR static time_t last; // remember last boot in RTC Memory
RTC_DATA_ATTR static uint32_t bootcount; // remember number of boots in RTC Memory
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
BLEAdvertising *pAdvertising;
struct timeval nowTimeStruct;
time_t lastTenth;
#define BEACON_UUID "8ec76ea3-6668-48da-9866-75be8bc86f4d" // UUID 1 128-Bit (may use linux tool uuidgen or random numbers via https://www.uuidgenerator.net/)
// Check
// https://github.com/google/eddystone/blob/master/eddystone-tlm/tlm-plain.md
// and http://www.hugi.scene.org/online/coding/hugi%2015%20-%20cmtadfix.htm
// for the temperature value. It is a 8.8 fixed-point notation
void setBeacon()
{
char beacon_data[25];
uint16_t beconUUID = 0xFEAA;
uint16_t volt = random(2800, 3700); // 3300mV = 3.3V
float tempFloat = random(2000, 3100) / 100.0f;
Serial.printf("Random temperature is %.2fC\n", tempFloat);
int temp = (int)(tempFloat * 256); //(uint16_t)((float)23.00);
Serial.printf("Converted to 8.8 format %0X%0X\n", (temp >> 8), (temp & 0xFF));
BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
BLEAdvertisementData oScanResponseData = BLEAdvertisementData();
oScanResponseData.setFlags(0x06); // GENERAL_DISC_MODE 0x02 | BR_EDR_NOT_SUPPORTED 0x04
oScanResponseData.setCompleteServices(BLEUUID(beconUUID));
beacon_data[0] = 0x20; // Eddystone Frame Type (Unencrypted Eddystone-TLM)
beacon_data[1] = 0x00; // TLM version
beacon_data[2] = (volt >> 8); // Battery voltage, 1 mV/bit i.e. 0xCE4 = 3300mV = 3.3V
beacon_data[3] = (volt & 0xFF); //
beacon_data[4] = (temp >> 8); // Beacon temperature
beacon_data[5] = (temp & 0xFF); //
beacon_data[6] = ((bootcount & 0xFF000000) >> 24); // Advertising PDU count
beacon_data[7] = ((bootcount & 0xFF0000) >> 16); //
beacon_data[8] = ((bootcount & 0xFF00) >> 8); //
beacon_data[9] = (bootcount & 0xFF); //
beacon_data[10] = ((lastTenth & 0xFF000000) >> 24); // Time since power-on or reboot as 0.1 second resolution counter
beacon_data[11] = ((lastTenth & 0xFF0000) >> 16); //
beacon_data[12] = ((lastTenth & 0xFF00) >> 8); //
beacon_data[13] = (lastTenth & 0xFF); //
oScanResponseData.setServiceData(BLEUUID(beconUUID), std::string(beacon_data, 14));
oAdvertisementData.setName("TLMBeacon");
pAdvertising->setAdvertisementData(oAdvertisementData);
pAdvertising->setScanResponseData(oScanResponseData);
}
void setup()
{
Serial.begin(115200);
gettimeofday(&nowTimeStruct, NULL);
Serial.printf("start ESP32 %d\n", bootcount++);
Serial.printf("deep sleep (%lds since last reset, %lds since last boot)\n", nowTimeStruct.tv_sec, nowTimeStruct.tv_sec - last);
last = nowTimeStruct.tv_sec;
lastTenth = nowTimeStruct.tv_sec * 10; // Time since last reset as 0.1 second resolution counter
// Create the BLE Device
BLEDevice::init("TLMBeacon");
BLEDevice::setPower(ESP_PWR_LVL_N12);
pAdvertising = BLEDevice::getAdvertising();
setBeacon();
// Start advertising
pAdvertising->start();
Serial.println("Advertizing started for 10s ...");
delay(10000);
pAdvertising->stop();
Serial.printf("enter deep sleep for 10s\n");
esp_deep_sleep(1000000LL * GPIO_DEEP_SLEEP_DURATION);
Serial.printf("in deep sleep\n");
}
void loop()
{
}

View File

@ -0,0 +1,14 @@
## Eddystone TLM beacon
EddystoneTLM beacon by BeeGee based on
[pcbreflux ESP32 Eddystone TLM deepsleep](https://github.com/pcbreflux/espressif/blob/master/esp32/arduino/sketchbook/ESP32_Eddystone_TLM_deepsleep/ESP32_Eddystone_TLM_deepsleep.ino)
[EddystoneTLM frame specification](https://github.com/google/eddystone/blob/master/eddystone-tlm/tlm-plain.md)
Create a BLE server that will send periodic Eddystone TLM frames.
The design of creating the BLE server is:
1. Create a BLE Server
2. Create advertising data
3. Start advertising.
4. wait
5. Stop advertising.
6. deep sleep

View File

@ -0,0 +1,192 @@
/*
EddystoneURL beacon by BeeGee
EddystoneURL frame specification https://github.com/google/eddystone/blob/master/eddystone-url/README.md
*/
/*
Create a BLE server that will send periodic Eddystone URL frames.
The design of creating the BLE server is:
1. Create a BLE Server
2. Create advertising data
3. Start advertising.
4. wait
5. Stop advertising.
6. deep sleep
*/
#include "sys/time.h"
#include <Arduino.h>
#include "BLEDevice.h"
#include "BLEUtils.h"
#include "BLEBeacon.h"
#include "BLEAdvertising.h"
#include "BLEEddystoneURL.h"
#include "esp_sleep.h"
#define GPIO_DEEP_SLEEP_DURATION 10 // sleep x seconds and then wake up
RTC_DATA_ATTR static time_t last; // remember last boot in RTC Memory
RTC_DATA_ATTR static uint32_t bootcount; // remember number of boots in RTC Memory
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
BLEAdvertising *pAdvertising;
struct timeval now;
#define BEACON_UUID "8ec76ea3-6668-48da-9866-75be8bc86f4d" // UUID 1 128-Bit (may use linux tool uuidgen or random numbers via https://www.uuidgenerator.net/)
static const char *eddystone_url_prefix_subs[] = {
"http://www.",
"https://www.",
"http://",
"https://",
"urn:uuid:",
NULL
};
static const char *eddystone_url_suffix_subs[] = {
".com/",
".org/",
".edu/",
".net/",
".info/",
".biz/",
".gov/",
".com",
".org",
".edu",
".net",
".info",
".biz",
".gov",
NULL
};
static int string_begin_with(const char *str, const char *prefix)
{
int prefix_len = strlen(prefix);
if (strncmp(prefix, str, prefix_len) == 0)
{
return prefix_len;
}
return 0;
}
void setBeacon()
{
BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
BLEAdvertisementData oScanResponseData = BLEAdvertisementData();
const char url[] = "https://d.giesecke.tk";
int scheme_len, ext_len = 1, i, idx, url_idx;
char *ret_data;
int url_len = strlen(url);
ret_data = (char *)calloc(1, url_len + 13);
ret_data[0] = 2; // Len
ret_data[1] = 0x01; // Type Flags
ret_data[2] = 0x06; // GENERAL_DISC_MODE 0x02 | BR_EDR_NOT_SUPPORTED 0x04
ret_data[3] = 3; // Len
ret_data[4] = 0x03; // Type 16-Bit UUID
ret_data[5] = 0xAA; // Eddystone UUID 2 -> 0xFEAA LSB
ret_data[6] = 0xFE; // Eddystone UUID 1 MSB
ret_data[7] = 19; // Length of Beacon Data
ret_data[8] = 0x16; // Type Service Data
ret_data[9] = 0xAA; // Eddystone UUID 2 -> 0xFEAA LSB
ret_data[10] = 0xFE; // Eddystone UUID 1 MSB
ret_data[11] = 0x10; // Eddystone Frame Type
ret_data[12] = 0xF4; // Beacons TX power at 0m
i = 0, idx = 13, url_idx = 0;
//replace prefix
scheme_len = 0;
while (eddystone_url_prefix_subs[i] != NULL)
{
if ((scheme_len = string_begin_with(url, eddystone_url_prefix_subs[i])) > 0)
{
ret_data[idx] = i;
idx++;
url_idx += scheme_len;
break;
}
i++;
}
while (url_idx < url_len)
{
i = 0;
ret_data[idx] = url[url_idx];
ext_len = 1;
while (eddystone_url_suffix_subs[i] != NULL)
{
if ((ext_len = string_begin_with(&url[url_idx], eddystone_url_suffix_subs[i])) > 0)
{
ret_data[idx] = i;
break;
}
else
{
ext_len = 1; //inc 1
}
i++;
}
url_idx += ext_len;
idx++;
}
ret_data[7] = idx - 8;
Serial.printf("struct size %d url size %d reported len %d\n",
url_len + 13,
url_len, ret_data[7]);
Serial.printf("URL in data %s\n", &ret_data[13]);
std::string eddyStoneData(ret_data);
oAdvertisementData.addData(eddyStoneData);
oScanResponseData.setName("URLBeacon");
pAdvertising->setAdvertisementData(oAdvertisementData);
pAdvertising->setScanResponseData(oScanResponseData);
}
void setup()
{
Serial.begin(115200);
gettimeofday(&now, NULL);
Serial.printf("start ESP32 %d\n", bootcount++);
Serial.printf("deep sleep (%lds since last reset, %lds since last boot)\n", now.tv_sec, now.tv_sec - last);
last = now.tv_sec;
// Create the BLE Device
BLEDevice::init("URLBeacon");
BLEDevice::setPower(ESP_PWR_LVL_N12);
// Create the BLE Server
// BLEServer *pServer = BLEDevice::createServer(); // <-- no longer required to instantiate BLEServer, less flash and ram usage
pAdvertising = BLEDevice::getAdvertising();
setBeacon();
// Start advertising
pAdvertising->start();
Serial.println("Advertizing started...");
delay(10000);
pAdvertising->stop();
Serial.printf("enter deep sleep\n");
esp_deep_sleep(1000000LL * GPIO_DEEP_SLEEP_DURATION);
Serial.printf("in deep sleep\n");
}
void loop()
{
}

View File

@ -0,0 +1,14 @@
## Eddystone URL beacon
EddystoneURL beacon by BeeGee based on
[pcbreflux ESP32 Eddystone URL deepsleep](https://github.com/pcbreflux/espressif/tree/master/esp32/arduino/sketchbook/ESP32_Eddystone_URL_deepsleep)
[EddystoneURL frame specification](https://github.com/google/eddystone/blob/master/eddystone-url/README.md)
Create a BLE server that will send periodic Eddystone URL frames.
The design of creating the BLE server is:
1. Create a BLE Server
2. Create advertising data
3. Start advertising.
4. wait
5. Stop advertising.
6. deep sleep

View File

@ -59,14 +59,37 @@ BLEAddress::BLEAddress(std::string stringAddress) {
* @return True if the addresses are equal.
*/
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
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.
* @return The native representation of the address.
*/
*/
esp_bd_addr_t *BLEAddress::getNative() {
return &m_address;
} // getNative

View File

@ -23,6 +23,12 @@ public:
BLEAddress(esp_bd_addr_t address);
BLEAddress(std::string stringAddress);
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();
std::string toString();

View File

@ -25,6 +25,7 @@ BLEAdvertisedDevice::BLEAdvertisedDevice() {
m_manufacturerData = "";
m_name = "";
m_rssi = -9999;
m_serviceUUIDs = {};
m_serviceData = {};
m_serviceDataUUIDs = {};
m_txPower = 0;
@ -34,8 +35,6 @@ BLEAdvertisedDevice::BLEAdvertisedDevice() {
m_haveManufacturerData = false;
m_haveName = false;
m_haveRSSI = false;
m_haveServiceData = false;
m_haveServiceUUID = false;
m_haveTXPower = false;
} // BLEAdvertisedDevice
@ -107,11 +106,7 @@ BLEScan* BLEAdvertisedDevice::getScan() {
* @return Number of service data discovered.
*/
int BLEAdvertisedDevice::getServiceDataCount() {
if (m_haveServiceData)
return m_serviceData.size();
else
return 0;
return m_serviceData.size();
} //getServiceDataCount
/**
@ -119,7 +114,7 @@ int BLEAdvertisedDevice::getServiceDataCount() {
* @return The ServiceData of the advertised device.
*/
std::string BLEAdvertisedDevice::getServiceData() {
return m_serviceData[0];
return m_serviceData.empty() ? std::string() : m_serviceData.front();
} //getServiceData
/**
@ -130,12 +125,20 @@ std::string BLEAdvertisedDevice::getServiceData(int i) {
return m_serviceData[i];
} //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.
* @return The service data UUID.
*/
BLEUUID BLEAdvertisedDevice::getServiceDataUUID() {
return m_serviceDataUUIDs[0];
return m_serviceDataUUIDs.empty() ? BLEUUID() : m_serviceDataUUIDs.front();
} // getServiceDataUUID
/**
@ -146,12 +149,20 @@ BLEUUID BLEAdvertisedDevice::getServiceDataUUID(int i) {
return m_serviceDataUUIDs[i];
} // 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.
* @return The Service UUID of the advertised device.
*/
BLEUUID BLEAdvertisedDevice::getServiceUUID() {
return m_serviceUUIDs[0];
return m_serviceUUIDs.empty() ? BLEUUID() : m_serviceUUIDs.front();
} // getServiceUUID
/**
@ -167,7 +178,7 @@ BLEUUID BLEAdvertisedDevice::getServiceUUID(int i) {
* @return Return true if service is advertised
*/
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;
}
return false;
@ -224,7 +235,7 @@ bool BLEAdvertisedDevice::haveRSSI() {
* @return True if there is a service data value present.
*/
bool BLEAdvertisedDevice::haveServiceData() {
return m_haveServiceData;
return !m_serviceData.empty();
} // haveServiceData
@ -233,7 +244,7 @@ bool BLEAdvertisedDevice::haveServiceData() {
* @return True if there is a service UUID value present.
*/
bool BLEAdvertisedDevice::haveServiceUUID() {
return m_haveServiceUUID;
return !m_serviceUUIDs.empty();
} // haveServiceUUID
@ -388,6 +399,15 @@ void BLEAdvertisedDevice::parseAdvertisement(uint8_t* payload, size_t total_len)
} // !finished
} // parseAdvertisement
/**
* @brief Parse the advertising payload.
* @param [in] payload The payload of the advertised device.
* @param [in] total_len The length of payload
*/
void BLEAdvertisedDevice::setPayload(uint8_t* payload, size_t total_len) {
m_payload = payload;
m_payloadLength = total_len;
} // setPayload
/**
* @brief Set the address of the advertised device.
@ -477,7 +497,6 @@ void BLEAdvertisedDevice::setServiceUUID(const char* serviceUUID) {
*/
void BLEAdvertisedDevice::setServiceUUID(BLEUUID serviceUUID) {
m_serviceUUIDs.push_back(serviceUUID);
m_haveServiceUUID = true;
log_d("- addServiceUUID(): serviceUUID: %s", serviceUUID.toString().c_str());
} // setServiceUUID
@ -487,7 +506,6 @@ void BLEAdvertisedDevice::setServiceUUID(BLEUUID serviceUUID) {
* @param [in] data ServiceData value.
*/
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.
} //setServiceData
@ -497,7 +515,6 @@ void BLEAdvertisedDevice::setServiceData(std::string serviceData) {
* @param [in] data ServiceDataUUID value.
*/
void BLEAdvertisedDevice::setServiceDataUUID(BLEUUID uuid) {
m_haveServiceData = true; // Set the flag that indicates we have service data.
m_serviceDataUUIDs.push_back(uuid);
log_d("- addServiceDataUUID(): serviceDataUUID: %s", uuid.toString().c_str());
} // setServiceDataUUID
@ -533,7 +550,7 @@ std::string BLEAdvertisedDevice::toString() {
free(pHex);
}
if (haveServiceUUID()) {
for (int i=0; i < m_serviceUUIDs.size(); i++) {
for (int i=0; i < getServiceUUIDCount(); i++) {
res += ", serviceUUID: " + getServiceUUID(i).toString();
}
}

View File

@ -42,6 +42,8 @@ public:
BLEUUID getServiceUUID();
BLEUUID getServiceUUID(int i);
int getServiceDataCount();
int getServiceDataUUIDCount();
int getServiceUUIDCount();
int8_t getTXPower();
uint8_t* getPayload();
size_t getPayloadLength();
@ -64,6 +66,7 @@ private:
friend class BLEScan;
void parseAdvertisement(uint8_t* payload, size_t total_len=62);
void setPayload(uint8_t* payload, size_t total_len=62);
void setAddress(BLEAddress address);
void setAdFlag(uint8_t adFlag);
void setAdvertizementResult(uint8_t* payload);
@ -82,8 +85,6 @@ private:
bool m_haveManufacturerData;
bool m_haveName;
bool m_haveRSSI;
bool m_haveServiceData;
bool m_haveServiceUUID;
bool m_haveTXPower;

View File

@ -28,7 +28,9 @@
* @brief Construct a default advertising object.
*
*/
BLEAdvertising::BLEAdvertising() {
BLEAdvertising::BLEAdvertising()
: m_scanRespData{}
{
m_advData.set_scan_rsp = false;
m_advData.include_name = true;
m_advData.include_txpower = true;
@ -89,6 +91,10 @@ void BLEAdvertising::setAdvertisementType(esp_ble_adv_type_t adv_type){
m_advParams.adv_type = adv_type;
} // setAdvertisementType
void BLEAdvertising::setAdvertisementChannelMap(esp_ble_adv_channel_t channel_map) {
m_advParams.channel_map = channel_map;
} // setAdvertisementChannelMap
void BLEAdvertising::setMinInterval(uint16_t mininterval) {
m_advParams.adv_int_min = mininterval;
} // setMinInterval
@ -215,10 +221,15 @@ void BLEAdvertising::start() {
}
if (!m_customScanResponseData && m_scanResp) {
m_advData.set_scan_rsp = true;
m_advData.include_name = m_scanResp;
m_advData.include_txpower = m_scanResp;
errRc = ::esp_ble_gap_config_adv_data(&m_advData);
// Set the configuration for scan response.
memcpy(&m_scanRespData, &m_advData, sizeof(esp_ble_adv_data_t)); // Copy the content of m_advData.
m_scanRespData.set_scan_rsp = true; // Define this struct as scan response data
m_scanRespData.include_name = true; // Caution: This may lead to a crash if the device name has more than 29 characters
m_scanRespData.include_txpower = true;
m_scanRespData.appearance = 0; // If defined the 'Appearance' attribute is already included in the advertising data
m_scanRespData.flag = 0; // 'Flags' attribute should no be included in the scan response
errRc = ::esp_ble_gap_config_adv_data(&m_scanRespData);
if (errRc != ESP_OK) {
log_e("<< esp_ble_gap_config_adv_data (Scan response): rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
return;

View File

@ -30,7 +30,7 @@ public:
void setPartialServices(BLEUUID uuid);
void setServiceData(BLEUUID uuid, std::string data);
void setShortName(std::string name);
void addData(std::string data); // Add data to the payload.
void addData(std::string data); // Add data to the payload.
std::string getPayload(); // Retrieve the current advert payload.
private:
@ -53,6 +53,7 @@ public:
void stop();
void setAppearance(uint16_t appearance);
void setAdvertisementType(esp_ble_adv_type_t adv_type);
void setAdvertisementChannelMap(esp_ble_adv_channel_t channel_map);
void setMaxInterval(uint16_t maxinterval);
void setMinInterval(uint16_t mininterval);
void setAdvertisementData(BLEAdvertisementData& advertisementData);
@ -68,12 +69,13 @@ public:
private:
esp_ble_adv_data_t m_advData;
esp_ble_adv_data_t m_scanRespData; // Used for configuration of scan response data when m_scanResp is true
esp_ble_adv_params_t m_advParams;
std::vector<BLEUUID> m_serviceUUIDs;
bool m_customAdvData = false; // Are we using custom advertising data?
bool m_customScanResponseData = false; // Are we using custom scan response data?
FreeRTOS::Semaphore m_semaphoreSetAdv = FreeRTOS::Semaphore("startAdvert");
bool m_scanResp = true;
bool m_scanResp = true;
};
#endif /* CONFIG_BT_ENABLED */

View File

@ -219,19 +219,22 @@ void BLECharacteristic::handleGATTServerEvent(
// - uint8_t exec_write_flag - Either ESP_GATT_PREP_WRITE_EXEC or ESP_GATT_PREP_WRITE_CANCEL
//
case ESP_GATTS_EXEC_WRITE_EVT: {
if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) {
m_value.commit();
m_pCallbacks->onWrite(this); // Invoke the onWrite callback handler.
} else {
m_value.cancel();
}
// ???
esp_err_t errRc = ::esp_ble_gatts_send_response(
gatts_if,
param->write.conn_id,
param->write.trans_id, ESP_GATT_OK, nullptr);
if (errRc != ESP_OK) {
log_e("esp_ble_gatts_send_response: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
if(m_writeEvt){
m_writeEvt = false;
if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) {
m_value.commit();
m_pCallbacks->onWrite(this); // Invoke the onWrite callback handler.
} else {
m_value.cancel();
}
// ???
esp_err_t errRc = ::esp_ble_gatts_send_response(
gatts_if,
param->write.conn_id,
param->write.trans_id, ESP_GATT_OK, nullptr);
if (errRc != ESP_OK) {
log_e("esp_ble_gatts_send_response: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
}
}
break;
} // ESP_GATTS_EXEC_WRITE_EVT
@ -277,6 +280,7 @@ void BLECharacteristic::handleGATTServerEvent(
if (param->write.handle == m_handle) {
if (param->write.is_prep) {
m_value.addPart(param->write.value, param->write.len);
m_writeEvt = true;
} else {
setValue(param->write.value, param->write.len);
}

View File

@ -107,6 +107,7 @@ private:
BLEService* m_pService;
BLEValue m_value;
esp_gatt_perm_t m_permissions = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE;
bool m_writeEvt = false; // If we have started a long write, this tells the commit code that we were the target
void handleGATTServerEvent(
esp_gatts_cb_event_t event,

View File

@ -60,6 +60,7 @@ BLEClient::~BLEClient() {
delete myPair.second;
}
m_servicesMap.clear();
m_servicesMapByInstID.clear();
} // ~BLEClient
@ -105,10 +106,21 @@ bool BLEClient::connect(BLEAddress address, esp_ble_addr_type_t type) {
esp_err_t errRc = ::esp_ble_gattc_app_register(m_appId);
if (errRc != ESP_OK) {
log_e("esp_ble_gattc_app_register: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
BLEDevice::removePeerDevice(m_appId, true);
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;
@ -122,10 +134,17 @@ bool BLEClient::connect(BLEAddress address, esp_ble_addr_type_t type) {
);
if (errRc != ESP_OK) {
log_e("esp_ble_gattc_open: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
BLEDevice::removePeerDevice(m_appId, true);
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);
return rc == ESP_GATT_OK;
} // connect
@ -157,6 +176,11 @@ void BLEClient::gattClientEventHandler(
log_d("gattClientEventHandler [esp_gatt_if: %d] ... %s",
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.
switch(event) {
@ -178,17 +202,20 @@ void BLEClient::gattClientEventHandler(
// - uint16_t conn_id
// - esp_bd_addr_t remote_bda
case ESP_GATTC_DISCONNECT_EVT: {
if (evtParam->disconnect.conn_id != getConnId()) break;
// If we receive a disconnect event, set the class flag that indicates that we are
// no longer connected.
bool m_wasConnected = m_isConnected;
m_isConnected = false;
if (m_pClientCallbacks != nullptr) {
m_pClientCallbacks->onDisconnect(this);
}
esp_ble_gattc_app_unregister(m_gattc_if);
m_gattc_if = ESP_GATT_IF_NONE;
m_semaphoreOpenEvt.give(ESP_GATT_IF_NONE);
m_semaphoreRssiCmplEvt.give();
m_semaphoreSearchCmplEvt.give(1);
BLEDevice::removePeerDevice(m_appId, true);
if (m_wasConnected && m_pClientCallbacks != nullptr) {
m_pClientCallbacks->onDisconnect(this);
}
break;
} // ESP_GATTC_DISCONNECT_EVT
@ -202,11 +229,13 @@ void BLEClient::gattClientEventHandler(
//
case ESP_GATTC_OPEN_EVT: {
m_conn_id = evtParam->open.conn_id;
if (m_pClientCallbacks != nullptr) {
m_pClientCallbacks->onConnect(this);
}
if (evtParam->open.status == ESP_GATT_OK) {
m_isConnected = true; // Flag us as connected.
if (m_pClientCallbacks != nullptr) {
m_pClientCallbacks->onConnect(this);
}
} else {
log_e("Failed to connect, status=%s", GeneralUtils::errorToString(evtParam->open.status));
}
m_semaphoreOpenEvt.give(evtParam->open.status);
break;
@ -222,11 +251,13 @@ void BLEClient::gattClientEventHandler(
//
case ESP_GATTC_REG_EVT: {
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;
} // ESP_GATTC_REG_EVT
case ESP_GATTC_CFG_MTU_EVT:
if (evtParam->cfg_mtu.conn_id != getConnId()) break;
if(evtParam->cfg_mtu.status != ESP_GATT_OK) {
log_e("Config mtu failed");
}
@ -234,7 +265,8 @@ void BLEClient::gattClientEventHandler(
break;
case ESP_GATTC_CONNECT_EVT: {
BLEDevice::updatePeerDevice(this, true, m_gattc_if);
if (evtParam->connect.conn_id != getConnId()) break;
BLEDevice::updatePeerDevice(this, true, m_appId);
esp_err_t errRc = esp_ble_gattc_send_mtu_req(gattc_if, evtParam->connect.conn_id);
if (errRc != ESP_OK) {
log_e("esp_ble_gattc_send_mtu_req: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
@ -255,6 +287,7 @@ void BLEClient::gattClientEventHandler(
// - uint16_t conn_id
//
case ESP_GATTC_SEARCH_CMPL_EVT: {
if (evtParam->search_cmpl.conn_id != getConnId()) break;
esp_ble_gattc_cb_param_t* p_data = (esp_ble_gattc_cb_param_t*)evtParam;
if (p_data->search_cmpl.status != ESP_GATT_OK){
log_e("search service failed, error status = %x", p_data->search_cmpl.status);
@ -285,6 +318,7 @@ void BLEClient::gattClientEventHandler(
// - esp_gatt_id_t srvc_id
//
case ESP_GATTC_SEARCH_RES_EVT: {
if (evtParam->search_res.conn_id != getConnId()) break;
BLEUUID uuid = BLEUUID(evtParam->search_res.srvc_id);
BLERemoteService* pRemoteService = new BLERemoteService(
evtParam->search_res.srvc_id,

View File

@ -3,6 +3,11 @@
*
* Created on: Mar 12, 2018
* Author: pcbreflux
* Edited on: Mar 20, 2020 by beegee-tokyo
* Fix temperature value (8.8 fixed format)
* Fix time stamp (0.1 second resolution)
* Fixes based on EddystoneTLM frame specification https://github.com/google/eddystone/blob/master/eddystone-tlm/tlm-plain.md
*
*/
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
@ -20,7 +25,7 @@ BLEEddystoneTLM::BLEEddystoneTLM() {
m_eddystoneData.frameType = EDDYSTONE_TLM_FRAME_TYPE;
m_eddystoneData.version = 0;
m_eddystoneData.volt = 3300; // 3300mV = 3.3V
m_eddystoneData.temp = (uint16_t) ((float) 23.00);
m_eddystoneData.temp = (uint16_t) ((float) 23.00)/256;
m_eddystoneData.advCount = 0;
m_eddystoneData.tmil = 0;
} // BLEEddystoneTLM
@ -38,41 +43,50 @@ uint8_t BLEEddystoneTLM::getVersion() {
} // getVersion
uint16_t BLEEddystoneTLM::getVolt() {
return m_eddystoneData.volt;
return ENDIAN_CHANGE_U16(m_eddystoneData.volt);
} // getVolt
float BLEEddystoneTLM::getTemp() {
return (float)m_eddystoneData.temp;
return ENDIAN_CHANGE_U16(m_eddystoneData.temp) / 256.0f;
} // getTemp
uint32_t BLEEddystoneTLM::getCount() {
return m_eddystoneData.advCount;
return ENDIAN_CHANGE_U32(m_eddystoneData.advCount);
} // getCount
uint32_t BLEEddystoneTLM::getTime() {
return m_eddystoneData.tmil;
return (ENDIAN_CHANGE_U32(m_eddystoneData.tmil)) / 10;
} // getTime
std::string BLEEddystoneTLM::toString() {
std::string out = "";
uint32_t rawsec = ENDIAN_CHANGE_U32(m_eddystoneData.tmil);
char val[6];
char val[12];
out += "Version " + m_eddystoneData.version;
out += "Version "; // + std::string(m_eddystoneData.version);
snprintf(val, sizeof(val), "%d", m_eddystoneData.version);
out += val;
out += "\n";
out += "Battery Voltage " + ENDIAN_CHANGE_U16(m_eddystoneData.volt);
out += "Battery Voltage "; // + ENDIAN_CHANGE_U16(m_eddystoneData.volt);
snprintf(val, sizeof(val), "%d", ENDIAN_CHANGE_U16(m_eddystoneData.volt));
out += val;
out += " mV\n";
out += "Temperature ";
snprintf(val, sizeof(val), "%d", m_eddystoneData.temp);
snprintf(val, sizeof(val), "%.2f", ENDIAN_CHANGE_U16(m_eddystoneData.temp) / 256.0f);
out += val;
out += ".0 °C\n";
out += " C\n";
out += "Adv. Count ";
snprintf(val, sizeof(val), "%d", ENDIAN_CHANGE_U32(m_eddystoneData.advCount));
out += val;
out += "\n";
out += "Time in seconds ";
snprintf(val, sizeof(val), "%d", rawsec/10);
out += val;
out += "\n";
out += "Time ";
snprintf(val, sizeof(val), "%04d", rawsec / 864000);

View File

@ -194,6 +194,7 @@ BLECharacteristic* BLEHIDDevice::protocolMode() {
void BLEHIDDevice::setBatteryLevel(uint8_t level) {
m_batteryLevelCharacteristic->setValue(&level, 1);
m_batteryLevelCharacteristic->notify();
}
/*
* @brief Returns battery level characteristic

View File

@ -52,6 +52,7 @@ BLERemoteCharacteristic::BLERemoteCharacteristic(
*/
BLERemoteCharacteristic::~BLERemoteCharacteristic() {
removeDescriptors(); // Release resources for any descriptor information we may have allocated.
free(m_rawData);
} // ~BLERemoteCharacteristic
@ -237,7 +238,18 @@ void BLERemoteCharacteristic::gattClientEventHandler(esp_gattc_cb_event_t event,
break;
} // ESP_GATTC_WRITE_CHAR_EVT
case ESP_GATTC_READ_DESCR_EVT:
case ESP_GATTC_WRITE_DESCR_EVT:
for (auto &myPair : m_descriptorMap) {
myPair.second->gattClientEventHandler(
event, gattc_if, evtParam);
}
break;
case ESP_GATTC_DISCONNECT_EVT:
m_semaphoreWriteCharEvt.give(1);
break;
default:
break;
} // End switch
@ -446,7 +458,7 @@ std::string BLERemoteCharacteristic::readValue() {
* unregistering a notification.
* @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());
m_notifyCallback = notifyCallback; // Save the notification callback.
@ -467,7 +479,8 @@ void BLERemoteCharacteristic::registerForNotify(notify_callback notifyCallback,
uint8_t val[] = {0x01, 0x00};
if(!notifications) val[0] = 0x02;
BLERemoteDescriptor* desc = getDescriptor(BLEUUID((uint16_t)0x2902));
desc->writeValue(val, 2);
if (desc != nullptr && descriptorRequiresRegistration)
desc->writeValue(val, 2, true);
} // End Register
else { // If we weren't passed a callback function, then this is an unregistration.
esp_err_t errRc = ::esp_ble_gattc_unregister_for_notify(
@ -482,7 +495,8 @@ void BLERemoteCharacteristic::registerForNotify(notify_callback notifyCallback,
uint8_t val[] = {0x00, 0x00};
BLERemoteDescriptor* desc = getDescriptor((uint16_t)0x2902);
desc->writeValue(val, 2);
if (desc != nullptr && descriptorRequiresRegistration)
desc->writeValue(val, 2, true);
} // End Unregister
m_semaphoreRegForNotifyEvt.wait("registerForNotify");
@ -533,7 +547,7 @@ std::string BLERemoteCharacteristic::toString() {
* @return N/A.
*/
void BLERemoteCharacteristic::writeValue(std::string newValue, bool response) {
writeValue((uint8_t*)newValue.c_str(), strlen(newValue.c_str()), response);
writeValue((uint8_t*)newValue.data(), newValue.length(), response);
} // writeValue

View File

@ -11,6 +11,7 @@
#if defined(CONFIG_BT_ENABLED)
#include <string>
#include <functional>
#include <esp_gattc_api.h>
@ -21,8 +22,7 @@
class BLERemoteService;
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.
*/
@ -39,6 +39,7 @@ public:
bool canWriteNoResponse();
BLERemoteDescriptor* getDescriptor(BLEUUID uuid);
std::map<std::string, BLERemoteDescriptor*>* getDescriptors();
BLERemoteService* getRemoteService();
uint16_t getHandle();
BLEUUID getUUID();
std::string readValue();
@ -46,7 +47,7 @@ public:
uint16_t readUInt16();
uint32_t readUInt32();
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(std::string newValue, bool response = false);
void writeValue(uint8_t newValue, bool response = false);
@ -63,7 +64,6 @@ private:
// Private member functions
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 retrieveDescriptors();

View File

@ -49,6 +49,23 @@ BLEUUID BLERemoteDescriptor::getUUID() {
return m_uuid;
} // getUUID
void BLERemoteDescriptor::gattClientEventHandler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* evtParam) {
switch(event) {
case ESP_GATTC_READ_DESCR_EVT:
if (evtParam->read.handle != getHandle())
break;
m_semaphoreReadDescrEvt.give();
break;
case ESP_GATTC_WRITE_DESCR_EVT:
if (evtParam->write.handle != getHandle())
break;
m_semaphoreWriteDescrEvt.give();
break;
default:
break;
}
}
std::string BLERemoteDescriptor::readValue() {
log_v(">> readValue: %s", toString().c_str());
@ -137,6 +154,8 @@ void BLERemoteDescriptor::writeValue(uint8_t* data, size_t length, bool response
return;
}
m_semaphoreWriteDescrEvt.take("writeValue");
esp_err_t errRc = ::esp_ble_gattc_write_char_descr(
m_pRemoteCharacteristic->getRemoteService()->getClient()->getGattcIf(),
m_pRemoteCharacteristic->getRemoteService()->getClient()->getConnId(),
@ -149,6 +168,8 @@ void BLERemoteDescriptor::writeValue(uint8_t* data, size_t length, bool response
if (errRc != ESP_OK) {
log_e("esp_ble_gattc_write_char_descr: %d", errRc);
}
m_semaphoreWriteDescrEvt.wait("writeValue");
log_v("<< writeValue");
} // writeValue

View File

@ -35,7 +35,7 @@ public:
void writeValue(std::string newValue, bool response = false);
void writeValue(uint8_t newValue, bool response = false);
void setAuth(esp_gatt_auth_req_t auth);
void gattClientEventHandler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* evtParam);
private:
friend class BLERemoteCharacteristic;
@ -49,6 +49,7 @@ private:
std::string m_value; // Last received value of the descriptor.
BLERemoteCharacteristic* m_pRemoteCharacteristic; // Reference to the Remote characteristic of which this descriptor is associated.
FreeRTOS::Semaphore m_semaphoreReadDescrEvt = FreeRTOS::Semaphore("ReadDescrEvt");
FreeRTOS::Semaphore m_semaphoreWriteDescrEvt = FreeRTOS::Semaphore("WriteDescrEvt");
esp_gatt_auth_req_t m_auth;

View File

@ -244,7 +244,16 @@ std::map<uint16_t, BLERemoteCharacteristic*>* BLERemoteService::getCharacteristi
* @brief This function is designed to get characteristics map when we have multiple characteristics with the same UUID
*/
void BLERemoteService::getCharacteristics(std::map<uint16_t, BLERemoteCharacteristic*>* pCharacteristicMap) {
pCharacteristicMap = &m_characteristicMapByHandle;
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
// now. The request to retrieve the characteristics by calling "retrieveCharacteristics" is a blocking
// call and does not return until all the characteristics are available.
if (!m_haveCharacteristics) {
retrieveCharacteristics();
}
log_v("<< getCharacteristics() for service: %s", getUUID().toString().c_str());
*pCharacteristicMap = m_characteristicMapByHandle;
} // Get the characteristics map.
/**
@ -302,13 +311,10 @@ std::string BLERemoteService::getValue(BLEUUID characteristicUuid) {
* @return N/A.
*/
void BLERemoteService::removeCharacteristics() {
for (auto &myPair : m_characteristicMap) {
delete myPair.second;
//m_characteristicMap.erase(myPair.first); // Should be no need to delete as it will be deleted by the clear
}
m_characteristicMap.clear(); // Clear the map
for (auto &myPair : m_characteristicMapByHandle) {
delete myPair.second;
// delete the characteristics only once
}
m_characteristicMapByHandle.clear(); // Clear the map
} // removeCharacteristics

View File

@ -22,12 +22,15 @@
* Constructor
*/
BLEScan::BLEScan() {
memset(&m_scan_params, 0, sizeof(m_scan_params)); // Initialize all params
m_scan_params.scan_type = BLE_SCAN_TYPE_PASSIVE; // Default is a passive scan.
m_scan_params.own_addr_type = BLE_ADDR_TYPE_PUBLIC;
m_scan_params.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL;
m_scan_params.scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE;
m_pAdvertisedDeviceCallbacks = nullptr;
m_stopped = true;
m_wantDuplicates = false;
m_shouldParse = true;
setInterval(100);
setWindow(100);
} // BLEScan
@ -88,15 +91,18 @@ void BLEScan::handleGAPEvent(
// ignore it.
BLEAddress advertisedAddress(param->scan_rst.bda);
bool found = false;
bool shouldDelete = true;
if (m_scanResults.m_vectorAdvertisedDevices.count(advertisedAddress.toString()) != 0) {
found = true;
}
if (!m_wantDuplicates) {
if (m_scanResults.m_vectorAdvertisedDevices.count(advertisedAddress.toString()) != 0) {
found = true;
}
if (found && !m_wantDuplicates) { // If we found a previous entry AND we don't want duplicates, then we are done.
log_d("Ignoring %s, already seen it.", advertisedAddress.toString().c_str());
vTaskDelay(1); // <--- allow to switch task in case we scan infinity and dont have new devices to report, or we are blocked here
break;
if (found) { // If we found a previous entry AND we don't want duplicates, then we are done.
log_d("Ignoring %s, already seen it.", advertisedAddress.toString().c_str());
vTaskDelay(1); // <--- allow to switch task in case we scan infinity and dont have new devices to report, or we are blocked here
break;
}
}
// We now construct a model of the advertised device that we have just found for the first
@ -107,19 +113,23 @@ void BLEScan::handleGAPEvent(
advertisedDevice->setAddress(advertisedAddress);
advertisedDevice->setRSSI(param->scan_rst.rssi);
advertisedDevice->setAdFlag(param->scan_rst.flag);
advertisedDevice->parseAdvertisement((uint8_t*)param->scan_rst.ble_adv, param->scan_rst.adv_data_len + param->scan_rst.scan_rsp_len);
if (m_shouldParse) {
advertisedDevice->parseAdvertisement((uint8_t*)param->scan_rst.ble_adv, param->scan_rst.adv_data_len + param->scan_rst.scan_rsp_len);
} else {
advertisedDevice->setPayload((uint8_t*)param->scan_rst.ble_adv, param->scan_rst.adv_data_len + param->scan_rst.scan_rsp_len);
}
advertisedDevice->setScan(this);
advertisedDevice->setAddressType(param->scan_rst.ble_addr_type);
if (!found) { // If we have previously seen this device, don't record it again.
m_scanResults.m_vectorAdvertisedDevices.insert(std::pair<std::string, BLEAdvertisedDevice*>(advertisedAddress.toString(), advertisedDevice));
}
if (m_pAdvertisedDeviceCallbacks) {
if (m_pAdvertisedDeviceCallbacks) { // if has callback, no need to record to vector
m_pAdvertisedDeviceCallbacks->onResult(*advertisedDevice);
} else if (!m_wantDuplicates && !found) { // if no callback and not want duplicate, and not already in vector, record it
m_scanResults.m_vectorAdvertisedDevices.insert(std::pair<std::string, BLEAdvertisedDevice*>(advertisedAddress.toString(), advertisedDevice));
shouldDelete = false;
}
if(found)
if (shouldDelete) {
delete advertisedDevice;
}
break;
} // ESP_GAP_SEARCH_INQ_RES_EVT
@ -159,13 +169,14 @@ void BLEScan::setActiveScan(bool active) {
* @brief Set the call backs to be invoked.
* @param [in] pAdvertisedDeviceCallbacks Call backs to be invoked.
* @param [in] wantDuplicates True if we wish to be called back with duplicates. Default is false.
* @param [in] shouldParse True if we wish to parse advertised package or raw payload. Default is true.
*/
void BLEScan::setAdvertisedDeviceCallbacks(BLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks, bool wantDuplicates) {
void BLEScan::setAdvertisedDeviceCallbacks(BLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks, bool wantDuplicates, bool shouldParse) {
m_wantDuplicates = wantDuplicates;
m_pAdvertisedDeviceCallbacks = pAdvertisedDeviceCallbacks;
m_shouldParse = shouldParse;
} // setAdvertisedDeviceCallbacks
/**
* @brief Set the interval to scan.
* @param [in] The interval in msecs.

View File

@ -51,7 +51,8 @@ public:
void setActiveScan(bool active);
void setAdvertisedDeviceCallbacks(
BLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks,
bool wantDuplicates = false);
bool wantDuplicates = false,
bool shouldParse = true);
void setInterval(uint16_t intervalMSecs);
void setWindow(uint16_t windowMSecs);
bool start(uint32_t duration, void (*scanCompleteCB)(BLEScanResults), bool is_continue = false);
@ -73,6 +74,7 @@ private:
esp_ble_scan_params_t m_scan_params;
BLEAdvertisedDeviceCallbacks* m_pAdvertisedDeviceCallbacks = nullptr;
bool m_stopped = true;
bool m_shouldParse = true;
FreeRTOS::Semaphore m_semaphoreScanEnd = FreeRTOS::Semaphore("ScanEnd");
BLEScanResults m_scanResults;
bool m_wantDuplicates;

View File

@ -61,6 +61,17 @@ void BLESecurity::setKeySize(uint8_t key_size) {
esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &m_keySize, sizeof(uint8_t));
} //setKeySize
/**
* Setup for static PIN connection, call it first and then call setAuthenticationMode eventually to change it
*/
void BLESecurity::setStaticPIN(uint32_t pin){
uint32_t passkey = pin;
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, &passkey, sizeof(uint32_t));
setCapability(ESP_IO_CAP_OUT);
setKeySize();
setAuthenticationMode(ESP_LE_AUTH_REQ_SC_ONLY);
setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);
}
/**
* @brief Debug function to display what keys are exchanged by peers

View File

@ -21,6 +21,7 @@ public:
void setInitEncryptionKey(uint8_t init_key);
void setRespEncryptionKey(uint8_t resp_key);
void setKeySize(uint8_t key_size = 16);
void setStaticPIN(uint32_t pin);
static char* esp_key_type_to_str(esp_ble_key_type_t key_type);
private:

View File

@ -193,8 +193,8 @@ bool FreeRTOS::Semaphore::take(std::string owner) {
} else {
rc = ::xSemaphoreTake(m_semaphore, portMAX_DELAY) == pdTRUE;
}
m_owner = owner;
if (rc) {
m_owner = owner;
log_v("Semaphore taken: %s", toString().c_str());
} else {
log_e("Semaphore NOT taken: %s", toString().c_str());
@ -218,8 +218,8 @@ bool FreeRTOS::Semaphore::take(uint32_t timeoutMs, std::string owner) {
} else {
rc = ::xSemaphoreTake(m_semaphore, timeoutMs / portTICK_PERIOD_MS) == pdTRUE;
}
m_owner = owner;
if (rc) {
m_owner = owner;
log_v("Semaphore taken: %s", toString().c_str());
} else {
log_e("Semaphore NOT taken: %s", toString().c_str());

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 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 xQueueHandle _spp_rx_queue = NULL;
static xQueueHandle _spp_tx_queue = NULL;
@ -51,6 +55,9 @@ static EventGroupHandle_t _spp_event_group = NULL;
static boolean secondConnectionAttempt;
static esp_spp_cb_t * custom_spp_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_NUM_RSPS 20
@ -140,7 +147,7 @@ static esp_err_t _spp_queue_packet(uint8_t *data, size_t len){
}
packet->len = 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!");
free(packet);
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 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);
if(err != ESP_OK){
log_e("SPP Write Failed! [0x%X]", err);
return false;
}
_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!");
return false;
}
return true;
}
log_e("SPP Write Congested!");
return false;
}
@ -191,13 +204,18 @@ static void _spp_tx_task(void * arg){
_spp_tx_buffer_len = SPP_TX_MAX;
data += to_send;
len -= to_send;
_spp_send_buffer();
if(!_spp_send_buffer()){
len = 0;
}
while(len >= SPP_TX_MAX){
memcpy(_spp_tx_buffer, data, SPP_TX_MAX);
_spp_tx_buffer_len = SPP_TX_MAX;
data += SPP_TX_MAX;
len -= SPP_TX_MAX;
_spp_send_buffer();
if(!_spp_send_buffer()){
len = 0;
break;
}
}
if(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;
case ESP_SPP_SRV_OPEN_EVT://Server connection open
log_i("ESP_SPP_SRV_OPEN_EVT");
if (!_spp_client){
_spp_client = param->open.handle;
if (param->srv_open.status == ESP_SPP_SUCCESS) {
log_i("ESP_SPP_SRV_OPEN_EVT: %u", _spp_client);
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 {
secondConnectionAttempt = true;
esp_spp_disconnect(param->open.handle);
log_e("ESP_SPP_SRV_OPEN_EVT Failed!, status:%d", param->srv_open.status);
}
xEventGroupClearBits(_spp_event_group, SPP_DISCONNECTED);
xEventGroupSetBits(_spp_event_group, SPP_CONNECTED);
break;
case ESP_SPP_CLOSE_EVT://Client connection closed
log_i("ESP_SPP_CLOSE_EVT");
if(secondConnectionAttempt) {
secondConnectionAttempt = false;
if ((param->close.async == false && param->close.status == ESP_SPP_SUCCESS) || param->close.async) {
log_i("ESP_SPP_CLOSE_EVT: %u", secondConnectionAttempt);
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 {
_spp_client = 0;
xEventGroupSetBits(_spp_event_group, SPP_DISCONNECTED);
}
xEventGroupClearBits(_spp_event_group, SPP_CONNECTED);
log_e("ESP_SPP_CLOSE_EVT failed!, status:%d", param->close.status);
}
break;
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;
case ESP_SPP_WRITE_EVT://write operation completed
if(param->write.cong){
xEventGroupClearBits(_spp_event_group, SPP_CONGESTED);
if (param->write.status == ESP_SPP_SUCCESS) {
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
log_v("ESP_SPP_WRITE_EVT: %u %s", param->write.len, param->write.cong?"CONGESTED":"FREE");
break;
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) {
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);
} else {
log_e("ESP_SPP_DISCOVERY_COMP_EVT failed!, status:%d", param->disc_comp.status);
}
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);
xEventGroupSetBits(_spp_event_group, SPP_CONNECTED);
xEventGroupSetBits(_spp_event_group, SPP_CONGESTED);
break;
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:
if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) {
log_v("authentication success: %s", param->auth_cmpl.device_name);
if (auth_complete_callback) {
auth_complete_callback(true);
}
} else {
log_e("authentication failed, status:%d", param->auth_cmpl.stat);
if (auth_complete_callback) {
auth_complete_callback(false);
}
}
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:
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;
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");
return false;
}
@ -515,9 +564,9 @@ static bool _init_bt(const char *deviceName)
return false;
}
if (esp_bt_sleep_disable() != ESP_OK){
log_e("esp_bt_sleep_disable failed");
}
// if (esp_bt_sleep_disable() != ESP_OK){
// log_e("esp_bt_sleep_disable failed");
// }
log_i("device name set");
esp_bt_dev_set_device_name(deviceName);
@ -662,7 +711,7 @@ void BluetoothSerial::flush()
{
if (_spp_tx_queue != NULL){
while(uxQueueMessagesWaiting(_spp_tx_queue) > 0){
delay(5);
delay(100);
}
}
}
@ -672,6 +721,22 @@ void BluetoothSerial::end()
_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)
{
custom_spp_callback = callback;

View File

@ -25,6 +25,8 @@
#include <functional>
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
{
@ -44,6 +46,10 @@ class BluetoothSerial: public Stream
void end(void);
void onData(BluetoothSerialDataCb cb);
esp_err_t register_callback(esp_spp_cb_t * callback);
void onConfirmRequest(ConfirmRequestCb cb);
void onAuthComplete(AuthCompleteCb cb);
void confirmReply(boolean confirm);
void enableSSP();
bool setPin(const char *pin);

View File

@ -2,7 +2,7 @@
#include <DNSServer.h>
const byte DNS_PORT = 53;
IPAddress apIP(192, 168, 1, 1);
IPAddress apIP(8,8,4,4); // The default android DNS
DNSServer dnsServer;
WiFiServer server(80);
@ -12,11 +12,9 @@ String responseHTML = ""
"be redirected here.</p></body></html>";
void setup() {
WiFi.disconnect(); //added to start with the wifi off, avoid crashing
WiFi.mode(WIFI_OFF); //added to start with the wifi off, avoid crashing
WiFi.mode(WIFI_AP);
WiFi.softAP("ESP32-DNSServer");
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
WiFi.softAP("DNSServer CaptivePortal example");
// if DNSServer is started with "*" for domain name, it will reply with
// provided IP to all DNS request

View File

@ -2,6 +2,12 @@
#include <lwip/def.h>
#include <Arduino.h>
// #define DEBUG_ESP_DNS
#ifdef DEBUG_ESP_PORT
#define DEBUG_OUTPUT DEBUG_ESP_PORT
#else
#define DEBUG_OUTPUT Serial
#endif
DNSServer::DNSServer()
{
@ -184,6 +190,11 @@ void DNSServer::replyWithIP()
_udp.write((unsigned char*) &answerIPv4, 2 );
_udp.write(_resolvedIP, sizeof(_resolvedIP)); // The IP address to return
_udp.endPacket();
#ifdef DEBUG_ESP_DNS
DEBUG_OUTPUT.printf("DNS responds: %s for %s\n",
IPAddress(_resolvedIP).toString().c_str(), getDomainNameWithoutWwwPrefix().c_str() );
#endif
}
void DNSServer::replyWithCustomCode()

View File

@ -17,6 +17,7 @@ EEPROMClass AGE("eeprom2", 0x100);
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("Testing EEPROMClass\n");
if (!NAMES.begin(NAMES.length())) {
Serial.println("Failed to initialise NAMES");
@ -43,7 +44,7 @@ void setup() {
uint32_t age = 47;
// Write: Variables ---> EEPROM stores
NAMES.put(0, name);
NAMES.writeString(0, name);
HEIGHT.put(0, height);
AGE.put(0, age);
Serial.print("name: "); Serial.println(name);

View File

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

View File

@ -1,14 +1,30 @@
uint64_t chipid;
/* The true ESP32 chip ID is essentially its MAC address.
This sketch provides an alternate chip ID that matches
the output of the ESP.getChipId() function on ESP8266
(i.e. a 32-bit integer matching the last 3 bytes of
the MAC address. This is less unique than the
MAC address chip ID, but is helpful when you need
an identifier that can be no more than a 32-bit integer
(like for switch...case).
created 2020-06-07 by cweinhofer
with help from Cicicok */
uint32_t chipId = 0;
void setup() {
Serial.begin(115200);
}
void loop() {
chipid=ESP.getEfuseMac();//The chip ID is essentially its MAC address(length: 6 bytes).
Serial.printf("ESP32 Chip ID = %04X",(uint16_t)(chipid>>32));//print High 2 bytes
Serial.printf("%08X\n",(uint32_t)chipid);//print Low 4bytes.
for(int i=0; i<17; i=i+8) {
chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
}
Serial.printf("ESP32 Chip model = %s Rev %d\n", ESP.getChipModel(), ESP.getChipRevision());
Serial.printf("This chip has %d cores\n", ESP.getChipCores());
Serial.print("Chip ID: "); Serial.println(chipId);
delay(3000);
}

View File

@ -0,0 +1,64 @@
#include "Arduino.h"
#include "esp32-hal.h"
extern "C" void receive_trampoline(uint32_t *data, size_t len, void * arg);
class MyProcessor {
private:
rmt_obj_t* rmt_recv = NULL;
float realNanoTick;
uint32_t buff; // rolling buffer of most recent 32 bits.
int at = 0;
public:
MyProcessor(uint8_t pin, float nanoTicks) {
assert((rmt_recv = rmtInit(21, false, RMT_MEM_192)));
realNanoTick = rmtSetTick(rmt_recv, nanoTicks);
};
void begin() {
rmtRead(rmt_recv, receive_trampoline, this);
};
void process(rmt_data_t *data, size_t len) {
for (int i = 0; len; len--) {
if (data[i].duration0 == 0)
break;
buff = (buff << 1) | (data[i].level0 ? 1 : 0);
i++;
if (data[i].duration1 == 0)
break;
buff = (buff << 1) | (data[i].level1 ? 1 : 0);
i++;
};
};
uint32_t val() {
return buff;
}
};
void receive_trampoline(uint32_t *data, size_t len, void * arg)
{
MyProcessor * p = (MyProcessor *)arg;
p->process((rmt_data_t*) data, len);
}
// Attach 3 processors to GPIO 4, 5 and 10 with different tick/speeds.
MyProcessor mp1 = MyProcessor(4, 1000);
MyProcessor mp2 = MyProcessor(5, 1000);
MyProcessor mp3 = MyProcessor(10, 500);
void setup()
{
Serial.begin(115200);
mp1.begin();
mp2.begin();
mp3.begin();
}
void loop()
{
Serial.printf("GPIO 4: %08x 5: %08x 6: %08x\n", mp1.val(), mp2.val(), mp3.val());
delay(500);
}

View File

@ -16,6 +16,7 @@ static EventGroupHandle_t events;
void setup()
{
Serial.begin(115200);
events = xEventGroupCreate();
if ((rmt_send = rmtInit(18, true, RMT_MEM_64)) == NULL)
{

View File

@ -172,7 +172,7 @@ void parseRmt(rmt_data_t* items, size_t len, uint32_t* channels){
}
}
extern "C" void receive_data(uint32_t *data, size_t len)
extern "C" void receive_data(uint32_t *data, size_t len, void * arg)
{
parseRmt((rmt_data_t*) data, len, channels);
}
@ -192,7 +192,7 @@ void setup()
Serial.printf("real tick set to: %fns\n", realTick);
// Ask to start reading
rmtRead(rmt_recv, receive_data);
rmtRead(rmt_recv, receive_data, NULL);
}
void loop()

View File

@ -47,7 +47,7 @@ void setup(void)
// Set up mDNS responder:
// - first argument is the domain name, in this example
// the fully-qualified domain name is "esp8266.local"
// the fully-qualified domain name is "esp32.local"
// - second argument is the IP address to advertise
// we send our IP address on the WiFi network
if (!MDNS.begin("esp32")) {

View File

@ -130,7 +130,7 @@ void MDNSResponder::disableWorkstation(){
}
}
void MDNSResponder::addService(char *name, char *proto, uint16_t port){
bool MDNSResponder::addService(char *name, char *proto, uint16_t port){
char _name[strlen(name)+2];
char _proto[strlen(proto)+2];
if (name[0] == '_') {
@ -146,7 +146,9 @@ void MDNSResponder::addService(char *name, char *proto, uint16_t port){
if(mdns_service_add(NULL, _name, _proto, port, NULL, 0)) {
log_e("Failed adding service %s.%s.\n", name, proto);
return false;
}
return true;
}
bool MDNSResponder::addServiceTxt(char *name, char *proto, char *key, char *value){

View File

@ -65,12 +65,12 @@ public:
setInstanceName(String(name));
}
void addService(char *service, char *proto, uint16_t port);
void addService(const char *service, const char *proto, uint16_t port){
addService((char *)service, (char *)proto, port);
bool addService(char *service, char *proto, uint16_t port);
bool addService(const char *service, const char *proto, uint16_t port){
return addService((char *)service, (char *)proto, port);
}
void addService(String service, String proto, uint16_t port){
addService(service.c_str(), proto.c_str(), port);
bool addService(String service, String proto, uint16_t port){
return addService(service.c_str(), proto.c_str(), port);
}
bool addServiceTxt(char *name, char *proto, char * key, char * value);
@ -84,7 +84,7 @@ public:
void enableArduino(uint16_t port=3232, bool auth=false);
void disableArduino();
void enableWorkstation(wifi_interface_t interface=ESP_IF_WIFI_STA);
void enableWorkstation(wifi_interface_t interface=WIFI_IF_STA);
void disableWorkstation();
IPAddress queryHost(char *host, uint32_t timeout=2000);

View File

@ -135,6 +135,21 @@ size_t F_Fat::totalBytes()
return tot_sect * sect_size;
}
size_t F_Fat::usedBytes()
{
FATFS *fs;
DWORD free_clust, used_sect, sect_size;
BYTE pdrv = ff_diskio_get_pdrv_wl(_wl_handle);
char drv[3] = {(char)(48+pdrv), ':', 0};
if ( f_getfree(drv, &free_clust, &fs) != FR_OK){
return 0;
}
used_sect = (fs->n_fatent - 2 - free_clust) * fs->csize;
sect_size = CONFIG_WL_SECTOR_SIZE;
return used_sect * sect_size;
}
size_t F_Fat::freeBytes()
{

View File

@ -31,6 +31,7 @@ public:
bool begin(bool formatOnFail=false, const char * basePath="/ffat", uint8_t maxOpenFiles=10, const char * partitionLabel = (char*)FFAT_PARTITION_LABEL);
bool format(bool full_wipe = FFAT_WIPE_QUICK, char* partitionLabel = (char*)FFAT_PARTITION_LABEL);
size_t totalBytes();
size_t usedBytes();
size_t freeBytes();
void end();
bool exists(const char* path);

View File

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

View File

@ -184,6 +184,11 @@ bool VFSImpl::rmdir(const char *path)
return false;
}
if (strcmp(_mountpoint, "/spiffs") == 0) {
log_e("rmdir is unnecessary in SPIFFS");
return false;
}
VFSFileImpl f(this, path, "r");
if(!f || !f.isDirectory()) {
if(f) {
@ -200,7 +205,7 @@ bool VFSImpl::rmdir(const char *path)
return false;
}
sprintf(temp,"%s%s", _mountpoint, path);
auto rc = unlink(temp);
auto rc = ::rmdir(temp);
free(temp);
return rc == 0;
}

View File

@ -73,11 +73,15 @@ public:
bool verify(WiFiClient& client, const char* host) override
{
WiFiClientSecure& wcs = static_cast<WiFiClientSecure&>(client);
wcs.setCACert(_cacert);
wcs.setCertificate(_clicert);
wcs.setPrivateKey(_clikey);
return true;
WiFiClientSecure& wcs = static_cast<WiFiClientSecure&>(client);
if (_cacert == nullptr) {
wcs.setInsecure();
} else {
wcs.setCACert(_cacert);
wcs.setCertificate(_clicert);
wcs.setPrivateKey(_clikey);
}
return true;
}
protected:
@ -105,6 +109,12 @@ HTTPClient::~HTTPClient()
if(_currentHeaders) {
delete[] _currentHeaders;
}
if(_tcpDeprecated) {
_tcpDeprecated.reset(nullptr);
}
if(_transportTraits) {
_transportTraits.reset(nullptr);
}
}
void HTTPClient::clear()
@ -265,15 +275,22 @@ bool HTTPClient::beginInternal(String url, const char* expectedProtocol)
// get port
index = host.indexOf(':');
String the_host;
if(index >= 0) {
_host = host.substring(0, index); // hostname
the_host = host.substring(0, index); // hostname
host.remove(0, (index + 1)); // remove hostname + :
_port = host.toInt(); // get port
} 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;
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;
}
@ -365,19 +382,19 @@ void HTTPClient::disconnect(bool preserveClient)
}
if(_reuse && _canReuse) {
log_d("tcp keep open for reuse\n");
log_d("tcp keep open for reuse");
} else {
log_d("tcp stop\n");
log_d("tcp stop");
_client->stop();
if(!preserveClient) {
_client = nullptr;
}
#ifdef HTTPCLIENT_1_1_COMPATIBLE
if(_tcpDeprecated) {
_transportTraits.reset(nullptr);
_tcpDeprecated.reset(nullptr);
}
if(_tcpDeprecated) {
_transportTraits.reset(nullptr);
_tcpDeprecated.reset(nullptr);
}
#endif
}
}
} else {
log_d("tcp is closed\n");
@ -548,29 +565,106 @@ int HTTPClient::sendRequest(const char * type, String payload)
*/
int HTTPClient::sendRequest(const char * type, uint8_t * payload, size_t size)
{
// connect to server
if(!connect()) {
return returnError(HTTPC_ERROR_CONNECTION_REFUSED);
}
if(payload && size > 0) {
addHeader(F("Content-Length"), String(size));
}
// send Header
if(!sendHeader(type)) {
return returnError(HTTPC_ERROR_SEND_HEADER_FAILED);
}
// send Payload if needed
if(payload && size > 0) {
if(_client->write(&payload[0], size) != size) {
return returnError(HTTPC_ERROR_SEND_PAYLOAD_FAILED);
int code;
bool redirect = false;
uint16_t redirectCount = 0;
do {
// wipe out any existing headers from previous request
for(size_t i = 0; i < _headerKeysCount; i++) {
if (_currentHeaders[i].value.length() > 0) {
_currentHeaders[i].value.clear();
}
}
}
log_d("request type: '%s' redirCount: %d\n", type, redirectCount);
// connect to server
if(!connect()) {
return returnError(HTTPC_ERROR_CONNECTION_REFUSED);
}
if(payload && size > 0) {
addHeader(F("Content-Length"), String(size));
}
// send Header
if(!sendHeader(type)) {
return returnError(HTTPC_ERROR_SEND_HEADER_FAILED);
}
// send Payload if needed
if(payload && size > 0) {
if(_client->write(&payload[0], size) != size) {
return returnError(HTTPC_ERROR_SEND_PAYLOAD_FAILED);
}
}
code = handleHeaderResponse();
log_d("sendRequest code=%d\n", code);
// Handle redirections as stated in RFC document:
// https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
//
// Implementing HTTP_CODE_FOUND as redirection with GET method,
// to follow most of existing user agent implementations.
//
redirect = false;
if (
_followRedirects != HTTPC_DISABLE_FOLLOW_REDIRECTS &&
redirectCount < _redirectLimit &&
_location.length() > 0
) {
switch (code) {
// redirecting using the same method
case HTTP_CODE_MOVED_PERMANENTLY:
case HTTP_CODE_TEMPORARY_REDIRECT: {
if (
// allow to force redirections on other methods
// (the RFC require user to accept the redirection)
_followRedirects == HTTPC_FORCE_FOLLOW_REDIRECTS ||
// allow GET and HEAD methods without force
!strcmp(type, "GET") ||
!strcmp(type, "HEAD")
) {
redirectCount += 1;
log_d("following redirect (the same method): '%s' redirCount: %d\n", _location.c_str(), redirectCount);
if (!setURL(_location)) {
log_d("failed setting URL for redirection\n");
// no redirection
break;
}
// redirect using the same request method and payload, diffrent URL
redirect = true;
}
break;
}
// redirecting with method dropped to GET or HEAD
// note: it does not need `HTTPC_FORCE_FOLLOW_REDIRECTS` for any method
case HTTP_CODE_FOUND:
case HTTP_CODE_SEE_OTHER: {
redirectCount += 1;
log_d("following redirect (dropped to GET/HEAD): '%s' redirCount: %d\n", _location.c_str(), redirectCount);
if (!setURL(_location)) {
log_d("failed setting URL for redirection\n");
// no redirection
break;
}
// redirect after changing method to GET/HEAD and dropping payload
type = "GET";
payload = nullptr;
size = 0;
redirect = true;
break;
}
default:
break;
}
}
} while (redirect);
// handle Server Response (Header)
return returnError(handleHeaderResponse());
return returnError(code);
}
/**
@ -842,18 +936,19 @@ int HTTPClient::writeToStream(Stream * stream)
*/
String HTTPClient::getString(void)
{
StreamString sstring;
if(_size) {
// try to reserve needed memmory
if(!sstring.reserve((_size + 1))) {
// _size can be -1 when Server sends no Content-Length header
if(_size > 0 || _size == -1) {
StreamString sstring;
// try to reserve needed memory (noop if _size == -1)
if(sstring.reserve((_size + 1))) {
writeToStream(&sstring);
return sstring;
} else {
log_d("not enough memory to reserve a string! need: %d", (_size + 1));
return "";
}
}
writeToStream(&sstring);
return sstring;
return "";
}
/**
@ -1012,7 +1107,13 @@ bool HTTPClient::connect(void)
log_d("HTTPClient::begin was not called or returned error");
return false;
}
#ifdef HTTPCLIENT_1_1_COMPATIBLE
if (_tcpDeprecated && !_transportTraits->verify(*_client, _host.c_str())) {
log_d("transport level verify failed");
_client->stop();
return false;
}
#endif
if(!_client->connect(_host.c_str(), _port, _connectTimeout)) {
log_d("failed connect to %s:%u", _host.c_str(), _port);
return false;
@ -1023,14 +1124,6 @@ bool HTTPClient::connect(void)
log_d(" connected to %s:%u", _host.c_str(), _port);
#ifdef HTTPCLIENT_1_1_COMPATIBLE
if (_tcpDeprecated && !_transportTraits->verify(*_client, _host.c_str())) {
log_d("transport level verify failed");
_client->stop();
return false;
}
#endif
/*
#ifdef ESP8266
@ -1110,6 +1203,7 @@ int HTTPClient::handleHeaderResponse()
_transferEncoding = HTTPC_TE_IDENTITY;
unsigned long lastDataTime = millis();
bool firstLine = true;
while(connected()) {
size_t len = _client->available();
@ -1121,11 +1215,13 @@ int HTTPClient::handleHeaderResponse()
log_v("RX: '%s'", headerLine.c_str());
if(headerLine.startsWith("HTTP/1.")) {
if(_canReuse) {
if(firstLine) {
firstLine = false;
if(_canReuse && headerLine.startsWith("HTTP/1.")) {
_canReuse = (headerLine[sizeof "HTTP/1." - 1] != '0');
}
_returnCode = headerLine.substring(9, headerLine.indexOf(' ', 9)).toInt();
int codePos = headerLine.indexOf(' ') + 1;
_returnCode = headerLine.substring(codePos, headerLine.indexOf(' ', codePos)).toInt();
} else if(headerLine.indexOf(':')) {
String headerName = headerLine.substring(0, headerLine.indexOf(':'));
String headerValue = headerLine.substring(headerLine.indexOf(':') + 1);
@ -1145,6 +1241,10 @@ int HTTPClient::handleHeaderResponse()
transferEncoding = headerValue;
}
if (headerName.equalsIgnoreCase("Location")) {
_location = headerValue;
}
for(size_t i = 0; i < _headerKeysCount; i++) {
if(_currentHeaders[i].key.equalsIgnoreCase(headerName)) {
_currentHeaders[i].value = headerValue;
@ -1231,9 +1331,9 @@ int HTTPClient::writeToStreamDataBlock(Stream * stream, int size)
readBytes = buff_size;
}
// stop if no more reading
if (readBytes == 0)
break;
// stop if no more reading
if (readBytes == 0)
break;
// read data
int bytesRead = _client->readBytes(buff, readBytes);
@ -1322,3 +1422,52 @@ int HTTPClient::returnError(int error)
}
return error;
}
void HTTPClient::setFollowRedirects(followRedirects_t follow)
{
_followRedirects = follow;
}
void HTTPClient::setRedirectLimit(uint16_t limit)
{
_redirectLimit = limit;
}
/**
* set the URL to a new value. Handy for following redirects.
* @param url
*/
bool HTTPClient::setURL(const String& url)
{
// if the new location is only a path then only update the URI
if (url && url[0] == '/') {
_uri = url;
clear();
return true;
}
if (!url.startsWith(_protocol + ':')) {
log_d("new URL not the same protocol, expected '%s', URL: '%s'\n", _protocol.c_str(), url.c_str());
return false;
}
// check if the port is specified
int indexPort = url.indexOf(':', 6); // find the first ':' excluding the one from the protocol
int indexURI = url.indexOf('/', 7); // find where the URI starts to make sure the ':' is not part of it
if (indexPort == -1 || indexPort > indexURI) {
// the port is not specified
_port = (_protocol == "https" ? 443 : 80);
}
// disconnect but preserve _client.
// Also have to keep the connection otherwise it will free some of the memory used by _client
// and will blow up later when trying to do _client->available() or similar
_canReuse = true;
disconnect(true);
return beginInternal(url, _protocol.c_str());
}
const String &HTTPClient::getLocation(void)
{
return _location;
}

View File

@ -119,6 +119,24 @@ typedef enum {
HTTPC_TE_CHUNKED
} transferEncoding_t;
/**
* redirection follow mode.
* + `HTTPC_DISABLE_FOLLOW_REDIRECTS` - no redirection will be followed.
* + `HTTPC_STRICT_FOLLOW_REDIRECTS` - strict RFC2616, only requests using
* GET or HEAD methods will be redirected (using the same method),
* since the RFC requires end-user confirmation in other cases.
* + `HTTPC_FORCE_FOLLOW_REDIRECTS` - all redirections will be followed,
* regardless of a used method. New request will use the same method,
* and they will include the same body data and the same headers.
* In the sense of the RFC, it's just like every redirection is confirmed.
*/
typedef enum {
HTTPC_DISABLE_FOLLOW_REDIRECTS,
HTTPC_STRICT_FOLLOW_REDIRECTS,
HTTPC_FORCE_FOLLOW_REDIRECTS
} followRedirects_t;
#ifdef HTTPCLIENT_1_1_COMPATIBLE
class TransportTraits;
typedef std::unique_ptr<TransportTraits> TransportTraitsPtr;
@ -156,6 +174,11 @@ public:
void setConnectTimeout(int32_t connectTimeout);
void setTimeout(uint16_t timeout);
// Redirections
void setFollowRedirects(followRedirects_t follow);
void setRedirectLimit(uint16_t limit); // max redirects to follow for a single request
bool setURL(const String &url);
void useHTTP10(bool usehttp10 = true);
/// request handling
@ -182,6 +205,7 @@ public:
int getSize(void);
const String &getLocation(void);
WiFiClient& getStream(void);
WiFiClient* getStreamPtr(void);
@ -235,6 +259,9 @@ protected:
int _returnCode = 0;
int _size = -1;
bool _canReuse = false;
followRedirects_t _followRedirects = HTTPC_DISABLE_FOLLOW_REDIRECTS;
uint16_t _redirectLimit = 10;
String _location;
transferEncoding_t _transferEncoding = HTTPC_TE_IDENTITY;
};

View File

@ -52,7 +52,7 @@ void loop() {
t_httpUpdate_return ret = httpUpdate.update(client, "http://server/file.bin");
// Or:
//t_httpUpdate_return ret = httpUpdate.update(client, "server", 80, "file.bin");
//t_httpUpdate_return ret = httpUpdate.update(client, "server", 80, "/file.bin");
switch (ret) {
case HTTP_UPDATE_FAILED:

View File

@ -108,7 +108,7 @@ void loop() {
t_httpUpdate_return ret = httpUpdate.update(client, "https://server/file.bin");
// Or:
//t_httpUpdate_return ret = httpUpdate.update(client, "server", 443, "file.bin");
//t_httpUpdate_return ret = httpUpdate.update(client, "server", 443, "/file.bin");
switch (ret) {

View File

@ -35,11 +35,13 @@
HTTPUpdate::HTTPUpdate(void)
: _httpClientTimeout(8000), _ledPin(-1)
{
_followRedirects = HTTPC_DISABLE_FOLLOW_REDIRECTS;
}
HTTPUpdate::HTTPUpdate(int httpClientTimeout)
: _httpClientTimeout(httpClientTimeout), _ledPin(-1)
{
_followRedirects = HTTPC_DISABLE_FOLLOW_REDIRECTS;
}
HTTPUpdate::~HTTPUpdate(void)
@ -56,6 +58,11 @@ HTTPUpdateResult HTTPUpdate::update(WiFiClient& client, const String& url, const
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)
{
HTTPClient http;
@ -66,6 +73,12 @@ HTTPUpdateResult HTTPUpdate::updateSpiffs(WiFiClient& client, const String& url,
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,
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
http.useHTTP10(true);
http.setTimeout(_httpClientTimeout);
http.setFollowRedirects(_followRedirects);
http.setUserAgent("ESP32-http-Update");
http.addHeader("Cache-Control", "no-cache");
http.addHeader("x-ESP32-STA-MAC", WiFi.macAddress());

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