mirror of
https://github.com/0xFEEDC0DE64/arduino-esp32.git
synced 2025-06-25 18:01:33 +02:00
Compare commits
40 Commits
Author | SHA1 | Date | |
---|---|---|---|
142fceb856 | |||
ba591fd958 | |||
4453ca5493 | |||
ce2cd111a1 | |||
5f6d093d4a | |||
51bf1832b8 | |||
384dbc2081 | |||
f2cfe78705 | |||
45583af189 | |||
f60cd8a069 | |||
5fa0c2010e | |||
adfaaecc65 | |||
0dd517dc9f | |||
823fe77e41 | |||
a9d33de70e | |||
d7ffd573d0 | |||
b88a70a0bd | |||
f3bdfb31f9 | |||
d8a99ed449 | |||
0a1ba74b60 | |||
1aa16104ff | |||
22c51579da | |||
f0636d515f | |||
b3c203db26 | |||
323bbbf63b | |||
02f4178b72 | |||
e1c9606531 | |||
fb60efd592 | |||
12045d335b | |||
45b7fa05b6 | |||
d3340837c7 | |||
6cfe4613e4 | |||
7dc8ca4e1e | |||
d4e20294e5 | |||
f1acc432af | |||
6fe1c4c5d6 | |||
5d6b9d0939 | |||
6b72fee59b | |||
a1409ef90d | |||
ab197e12a9 |
9
.github/ISSUE_TEMPLATE/Issue-report.yml
vendored
9
.github/ISSUE_TEMPLATE/Issue-report.yml
vendored
@ -39,7 +39,8 @@ body:
|
||||
label: Version
|
||||
description: What version of Arduino ESP32 are you running? If possible, consider updating to the latest version.
|
||||
options:
|
||||
- latest master
|
||||
- latest master (checkout manually)
|
||||
- latest development Release Candidate (RC-X)
|
||||
- v2.0.2
|
||||
- v2.0.1
|
||||
- v2.0.0
|
||||
@ -52,7 +53,7 @@ body:
|
||||
attributes:
|
||||
label: IDE Name
|
||||
description: What IDE are you using?
|
||||
placeholder: eg. Arduino IDE, PlatformIO, IDF component...
|
||||
placeholder: eg. Arduino IDE, PlatformIO, Sloeber...
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
@ -101,8 +102,8 @@ body:
|
||||
id: sketch
|
||||
attributes:
|
||||
label: Sketch
|
||||
description: Please provide your sketch/code which was run
|
||||
placeholder: ex. related part of the code
|
||||
description: Please provide full minimal sketch/code which can be run to reproduce your issue
|
||||
placeholder: ex. Related part of the code to replicate the issue
|
||||
render: cpp
|
||||
validations:
|
||||
required: true
|
||||
|
21
.github/PULL_REQUEST_TEMPLATE.md
vendored
21
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,18 +1,23 @@
|
||||
*By completing this PR sufficiently, you help us to improve the quality of Release Notes*
|
||||
*By completing this PR sufficiently, you help us to review this Pull Request quicker and also help improve the quality of Release Notes*
|
||||
|
||||
### Checklist
|
||||
1. [ ] Please provide specific title of the PR describing the change, including the component name (eg. *„Update of Documentation link on Readme.md“*)
|
||||
2. [ ] Please provide related links (eg. Issue, other Project, submodule PR..)
|
||||
3. [ ] Please check [Contributing guide](https://docs.espressif.com/projects/arduino-esp32/en/latest/contributing.html)
|
||||
1. [ ] Please provide specific title of the PR describing the change, including the component name (*eg. „Update of Documentation link on Readme.md“*)
|
||||
2. [ ] Please provide related links (*eg. Issue which will be closed by this Pull Request*)
|
||||
3. [ ] Please **update relevant Documentation** if applicable
|
||||
4. [ ] Please check [Contributing guide](https://docs.espressif.com/projects/arduino-esp32/en/latest/contributing.html)
|
||||
|
||||
*This entire section above can be deleted if all items are checked.*
|
||||
|
||||
-----------
|
||||
## Summary
|
||||
Please describe your proposed PR and what it contains.
|
||||
## Description of Change
|
||||
Please describe your proposed Pull Request and it's impact.
|
||||
|
||||
## Impact
|
||||
Please describe impact of your PR and it's function.
|
||||
## Tests scenarios
|
||||
Please describe on what Hardware and Software combinations you have tested this Pull Request and how.
|
||||
|
||||
(*eg. I have tested my Pull Request on Arduino-esp32 core v2.0.2 with ESP32 and ESP32-S2 Board with this scenario*)
|
||||
|
||||
## Related links
|
||||
Please provide links to related issue, PRs etc.
|
||||
|
||||
(*eg. Closes #number of issue*)
|
||||
|
2
.github/scripts/install-platformio-esp32.sh
vendored
2
.github/scripts/install-platformio-esp32.sh
vendored
@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
export PLATFORMIO_ESP32_PATH="$HOME/.platformio/packages/framework-arduinoespressif32"
|
||||
PLATFORMIO_ESP32_URL="https://github.com/platformio/platform-espressif32.git#feature/arduino-idf-master"
|
||||
PLATFORMIO_ESP32_URL="https://github.com/platformio/platform-espressif32.git"
|
||||
|
||||
TOOLCHAIN_VERSION="8.4.0+2021r2-patch3"
|
||||
ESPTOOLPY_VERSION="~1.30100.0"
|
||||
|
1
.github/scripts/on-release.sh
vendored
1
.github/scripts/on-release.sh
vendored
@ -172,6 +172,7 @@ 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/package.json" "$PKG_DIR/"
|
||||
cp -f "$GITHUB_WORKSPACE/programmers.txt" "$PKG_DIR/"
|
||||
cp -Rf "$GITHUB_WORKSPACE/cores" "$PKG_DIR/"
|
||||
cp -Rf "$GITHUB_WORKSPACE/libraries" "$PKG_DIR/"
|
||||
|
15
.github/scripts/sketch_utils.sh
vendored
15
.github/scripts/sketch_utils.sh
vendored
@ -7,12 +7,6 @@ function build_sketch(){ # build_sketch <ide_path> <user_path> <fqbn> <path-to-i
|
||||
return 1
|
||||
fi
|
||||
|
||||
ARDUINO_CACHE_DIR="$HOME/.arduino/cache.tmp"
|
||||
if [ -z "$ARDUINO_BUILD_DIR" ]; then
|
||||
build_dir="$(dirname $sketch)/build"
|
||||
else
|
||||
build_dir="$ARDUINO_BUILD_DIR"
|
||||
fi
|
||||
local ide_path=$1
|
||||
local usr_path=$2
|
||||
local fqbn=$3
|
||||
@ -20,6 +14,15 @@ function build_sketch(){ # build_sketch <ide_path> <user_path> <fqbn> <path-to-i
|
||||
local xtra_opts=$5
|
||||
local win_opts=$6
|
||||
|
||||
ARDUINO_CACHE_DIR="$HOME/.arduino/cache.tmp"
|
||||
if [ -z "$ARDUINO_BUILD_DIR" ]; then
|
||||
build_dir="$(dirname $sketch)/build"
|
||||
else
|
||||
build_dir="$ARDUINO_BUILD_DIR"
|
||||
fi
|
||||
|
||||
echo $sketch
|
||||
|
||||
rm -rf "$build_dir"
|
||||
mkdir -p "$build_dir"
|
||||
mkdir -p "$ARDUINO_CACHE_DIR"
|
||||
|
4
.github/scripts/update-version.sh
vendored
4
.github/scripts/update-version.sh
vendored
@ -1,5 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
# For reference: add tools for all boards by replacing one line in each board
|
||||
# "[board].upload.tool=esptool_py" to "[board].upload.tool=esptool_py\n[board].upload.tool.default=esptool_py\n[board].upload.tool.network=esp_ota"
|
||||
#cat boards.txt | sed "s/\([a-zA-Z0-9_\-]*\)\.upload\.tool\=esptool_py/\1\.upload\.tool\=esptool_py\\n\1\.upload\.tool\.default\=esptool_py\\n\1\.upload\.tool\.network\=esp_ota/"
|
||||
|
||||
if [ ! $# -eq 3 ]; then
|
||||
echo "Bad number of arguments: $#" >&2
|
||||
echo "usage: $0 <major> <minor> <patch>" >&2
|
||||
|
26
.github/stale.yml
vendored
26
.github/stale.yml
vendored
@ -1,26 +0,0 @@
|
||||
# This workflow firstly warns and then closes issues that have had no activity for a specified amount of time.
|
||||
#
|
||||
# You can adjust the behavior by modifying this file.
|
||||
# For more information can be found here: https://github.com/actions/stale
|
||||
|
||||
name: Mark stale issues
|
||||
on:
|
||||
schedule:
|
||||
- cron: '30 9 * * *'
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
steps:
|
||||
- uses: actions/stale@v3
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.'
|
||||
days-before-stale: 60
|
||||
days-before-close: 14
|
||||
exempt-issue-labels: 'Type: For reference,Type: To be implemented,Type: Feature request'
|
||||
stale-issue-label: 'Status: Stale'
|
12
.github/workflows/hil.yml
vendored
12
.github/workflows/hil.yml
vendored
@ -67,7 +67,12 @@ jobs:
|
||||
Test:
|
||||
needs: [gen_chunks, Build]
|
||||
name: ${{matrix.chip}}-Test#${{matrix.chunks}}
|
||||
runs-on: ESP32
|
||||
runs-on:
|
||||
- ESP32
|
||||
- ESP32-S2
|
||||
- ESP32-S3
|
||||
- ESP32-C3
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@ -87,11 +92,6 @@ jobs:
|
||||
name: ${{matrix.chip}}-${{matrix.chunks}}.artifacts
|
||||
path: tests/
|
||||
|
||||
- name: Check Artifacts
|
||||
run: |
|
||||
ls -R tests
|
||||
cat tests/*/build/build.options.json
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install -U pip
|
||||
|
3
.github/workflows/publish.yml
vendored
3
.github/workflows/publish.yml
vendored
@ -14,7 +14,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.event.workflow_run.event == 'pull_request' &&
|
||||
github.event.workflow_run.conclusion != 'skipped'
|
||||
(github.event.workflow_run.conclusion == 'success' ||
|
||||
github.event.workflow_run.conclusion == 'failure')
|
||||
steps:
|
||||
- name: Download and Extract Artifacts
|
||||
env:
|
||||
|
27
.github/workflows/push.yml
vendored
27
.github/workflows/push.yml
vendored
@ -78,3 +78,30 @@ jobs:
|
||||
python-version: '3.x'
|
||||
- name: Build Sketches
|
||||
run: bash ./.github/scripts/on-push.sh 1 1 #equal and non-zero to trigger PIO
|
||||
|
||||
build-esp-idf-component:
|
||||
name: Build with ESP-IDF ${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
# The version names here correspond to the versions of espressif/idf Docker image.
|
||||
# See https://hub.docker.com/r/espressif/idf/tags and
|
||||
# https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-docker-image.html
|
||||
# for details.
|
||||
idf_ver: ["release-v4.4"]
|
||||
idf_target: ["esp32", "esp32s2", "esp32s3", "esp32c3"]
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Check out arduino-esp32 as a component
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
path: components/arduino-esp32
|
||||
- name: Build
|
||||
env:
|
||||
IDF_TARGET: ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
idf.py create-project test
|
||||
idf.py -C test -DEXTRA_COMPONENT_DIRS=$PWD/components build
|
||||
|
21
README.md
21
README.md
@ -2,13 +2,17 @@
|
||||
|
||||
 [](https://docs.espressif.com/projects/arduino-esp32/en/latest/?badge=latest)
|
||||
|
||||
### Need help or have a question? Join the chat at [](https://gitter.im/espressif/arduino-esp32?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
### Need help or have a question? Join the chat at [](https://gitter.im/espressif/arduino-esp32?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) or [open a new Discussion](https://github.com/espressif/arduino-esp32/discussions)
|
||||
|
||||
## Contents
|
||||
|
||||
- [Development Status](#development-status)
|
||||
- [Decoding Exceptions](#decoding-exceptions)
|
||||
- [Issue/Bug report template](#issuebug-report-template)
|
||||
- [Development Status](#development-status)
|
||||
- [Development Planning](#development-planning)
|
||||
- [Documentation](#documentation)
|
||||
- [Supported Chips](#supported-chips)
|
||||
- [Decoding exceptions](#decoding-exceptions)
|
||||
- [Issue/Bug report template](#issuebug-report-template)
|
||||
- [Contributing](#contributing)
|
||||
|
||||
### Development Status
|
||||
|
||||
@ -16,9 +20,15 @@ Latest Stable Release [](https://github.com/espressif/arduino-esp32/releases/) [](https://github.com/espressif/arduino-esp32/releases/) [](https://github.com/espressif/arduino-esp32/releases/)
|
||||
|
||||
### Development Planning
|
||||
|
||||
Our Development is fully tracked on this public **[Roadmap 🎉](https://github.com/orgs/espressif/projects/3)**
|
||||
|
||||
For even more information you can take a look at [Sprint Meeting notes](https://github.com/espressif/arduino-esp32/discussions/categories/sprints-meeting-notes) or join [Monthly Community Meetings 🔔](https://github.com/espressif/arduino-esp32/discussions/categories/monthly-community-meetings)
|
||||
|
||||
### Documentation
|
||||
|
||||
You can use [Arduino-ESP32 Online Documentation](https://docs.espressif.com/projects/arduino-esp32/en/latest/) to get all information about this project.
|
||||
You can use the [Arduino-ESP32 Online Documentation](https://docs.espressif.com/projects/arduino-esp32/en/latest/) to get all information about this project.
|
||||
|
||||
* [Getting Started](https://docs.espressif.com/projects/arduino-esp32/en/latest/getting_started.html)
|
||||
* [Installing (Windows, Linux and macOS)](https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html)
|
||||
@ -36,6 +46,7 @@ Visit the [supported chips](https://docs.espressif.com/projects/arduino-esp32/en
|
||||
You can use [EspExceptionDecoder](https://github.com/me-no-dev/EspExceptionDecoder) to get meaningful call trace.
|
||||
|
||||
### Issue/Bug report template
|
||||
|
||||
Before reporting an issue, make sure you've searched for similar one that was already created. Also make sure to go through all the issues labelled as [Type: For reference](https://github.com/espressif/arduino-esp32/issues?q=is%3Aissue+label%3A%22Type%3A+For+reference%22+).
|
||||
|
||||
Finally, if you are sure no one else had the issue, follow the **Issue template** or **Feature request template** while reporting any [new Issue](https://github.com/espressif/arduino-esp32/issues/new/choose).
|
||||
|
1308
boards.txt
Executable file → Normal file
1308
boards.txt
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
@ -120,3 +120,6 @@ bool IPAddress::fromString(const char *address)
|
||||
_address.bytes[3] = acc;
|
||||
return true;
|
||||
}
|
||||
|
||||
// declared one time - as external in IPAddress.h
|
||||
IPAddress INADDR_NONE(0, 0, 0, 0);
|
||||
|
@ -91,6 +91,6 @@ public:
|
||||
friend class DNSClient;
|
||||
};
|
||||
|
||||
const IPAddress INADDR_NONE(0, 0, 0, 0);
|
||||
|
||||
// changed to extern because const declaration creates copies in BSS of INADDR_NONE for each CPP unit that includes it
|
||||
extern IPAddress INADDR_NONE;
|
||||
#endif
|
||||
|
@ -42,20 +42,15 @@ extern "C" {
|
||||
|
||||
//GPIO FUNCTIONS
|
||||
#define INPUT 0x01
|
||||
#define OUTPUT 0x02
|
||||
// Changed OUTPUT from 0x02 to behave the same as Arduino pinMode(pin,OUTPUT)
|
||||
// where you can read the state of pin even when it is set as OUTPUT
|
||||
#define OUTPUT 0x03
|
||||
#define PULLUP 0x04
|
||||
#define INPUT_PULLUP 0x05
|
||||
#define PULLDOWN 0x08
|
||||
#define INPUT_PULLDOWN 0x09
|
||||
#define OPEN_DRAIN 0x10
|
||||
#define OUTPUT_OPEN_DRAIN 0x12
|
||||
#define SPECIAL 0xF0
|
||||
#define FUNCTION_1 0x00
|
||||
#define FUNCTION_2 0x20
|
||||
#define FUNCTION_3 0x40
|
||||
#define FUNCTION_4 0x60
|
||||
#define FUNCTION_5 0x80
|
||||
#define FUNCTION_6 0xA0
|
||||
#define ANALOG 0xC0
|
||||
|
||||
//Interrupt Modes
|
||||
|
@ -719,10 +719,12 @@ static void i2c_slave_isr_handler(void* arg)
|
||||
}
|
||||
if(slave_rw){ // READ
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//SEND TX Event
|
||||
i2c_slave_queue_event_t event;
|
||||
event.event = I2C_SLAVE_EVT_TX;
|
||||
pxHigherPriorityTaskWoken |= i2c_slave_send_event(i2c, &event);
|
||||
if(i2c->dev->status_reg.scl_main_state_last == 6){
|
||||
//SEND TX Event
|
||||
i2c_slave_queue_event_t event;
|
||||
event.event = I2C_SLAVE_EVT_TX;
|
||||
pxHigherPriorityTaskWoken |= i2c_slave_send_event(i2c, &event);
|
||||
}
|
||||
#else
|
||||
//reset TX data
|
||||
i2c_ll_txfifo_rst(i2c->dev);
|
||||
|
@ -317,6 +317,8 @@ esp_err_t i2cSetClock(uint8_t i2c_num, uint32_t frequency){
|
||||
hal.dev = I2C_LL_GET_HW(i2c_num);
|
||||
i2c_hal_set_bus_timing(&(hal), frequency, src_clk);
|
||||
bus[i2c_num].frequency = frequency;
|
||||
//Clock Stretching Timeout: 20b:esp32, 5b:esp32-c3, 24b:esp32-s2
|
||||
i2c_set_timeout((i2c_port_t)i2c_num, I2C_LL_MAX_TIMEOUT);
|
||||
}
|
||||
|
||||
end:
|
||||
|
@ -54,7 +54,7 @@
|
||||
|
||||
uint8_t channels_resolution[LEDC_CHANNELS] = {0};
|
||||
|
||||
double ledcSetup(uint8_t chan, double freq, uint8_t bit_num)
|
||||
uint32_t ledcSetup(uint8_t chan, uint32_t freq, uint8_t bit_num)
|
||||
{
|
||||
if(chan >= LEDC_CHANNELS || bit_num > LEDC_MAX_BIT_WIDTH){
|
||||
log_e("No more LEDC channels available! (maximum %u) or bit width too big (maximum %u)", LEDC_CHANNELS, LEDC_MAX_BIT_WIDTH);
|
||||
@ -106,7 +106,7 @@ uint32_t ledcRead(uint8_t chan)
|
||||
return ledc_get_duty(group,channel);
|
||||
}
|
||||
|
||||
double ledcReadFreq(uint8_t chan)
|
||||
uint32_t ledcReadFreq(uint8_t chan)
|
||||
{
|
||||
if(!ledcRead(chan)){
|
||||
return 0;
|
||||
@ -115,7 +115,7 @@ double ledcReadFreq(uint8_t chan)
|
||||
return ledc_get_freq(group,timer);
|
||||
}
|
||||
|
||||
double ledcWriteTone(uint8_t chan, double freq)
|
||||
uint32_t ledcWriteTone(uint8_t chan, uint32_t freq)
|
||||
{
|
||||
if(chan >= LEDC_CHANNELS){
|
||||
return 0;
|
||||
@ -142,12 +142,12 @@ double ledcWriteTone(uint8_t chan, double freq)
|
||||
}
|
||||
channels_resolution[chan] = 10;
|
||||
|
||||
double res_freq = ledc_get_freq(group,timer);
|
||||
uint32_t res_freq = ledc_get_freq(group,timer);
|
||||
ledcWrite(chan, 0x1FF);
|
||||
return res_freq;
|
||||
}
|
||||
|
||||
double ledcWriteNote(uint8_t chan, note_t note, uint8_t octave){
|
||||
uint32_t ledcWriteNote(uint8_t chan, note_t note, uint8_t octave){
|
||||
const uint16_t noteFrequencyBase[12] = {
|
||||
// C C# D Eb E F F# G G# A Bb B
|
||||
4186, 4435, 4699, 4978, 5274, 5588, 5920, 6272, 6645, 7040, 7459, 7902
|
||||
@ -156,7 +156,7 @@ double ledcWriteNote(uint8_t chan, note_t note, uint8_t octave){
|
||||
if(octave > 8 || note >= NOTE_MAX){
|
||||
return 0;
|
||||
}
|
||||
double noteFreq = (double)noteFrequencyBase[note] / (double)(1 << (8-octave));
|
||||
uint32_t noteFreq = (uint32_t)noteFrequencyBase[note] / (uint32_t)(1 << (8-octave));
|
||||
return ledcWriteTone(chan, noteFreq);
|
||||
}
|
||||
|
||||
@ -184,7 +184,7 @@ void ledcDetachPin(uint8_t pin)
|
||||
pinMatrixOutDetach(pin, false, false);
|
||||
}
|
||||
|
||||
double ledcChangeFrequency(uint8_t chan, double freq, uint8_t bit_num)
|
||||
uint32_t ledcChangeFrequency(uint8_t chan, uint32_t freq, uint8_t bit_num)
|
||||
{
|
||||
if(chan >= LEDC_CHANNELS || bit_num > LEDC_MAX_BIT_WIDTH){
|
||||
log_e("LEDC channel not available! (maximum %u) or bit width too big (maximum %u)", LEDC_CHANNELS, LEDC_MAX_BIT_WIDTH);
|
||||
|
@ -27,15 +27,15 @@ typedef enum {
|
||||
} note_t;
|
||||
|
||||
//channel 0-15 resolution 1-16bits freq limits depend on resolution
|
||||
double ledcSetup(uint8_t channel, double freq, uint8_t resolution_bits);
|
||||
uint32_t ledcSetup(uint8_t channel, uint32_t freq, uint8_t resolution_bits);
|
||||
void ledcWrite(uint8_t channel, uint32_t duty);
|
||||
double ledcWriteTone(uint8_t channel, double freq);
|
||||
double ledcWriteNote(uint8_t channel, note_t note, uint8_t octave);
|
||||
uint32_t ledcWriteTone(uint8_t channel, uint32_t freq);
|
||||
uint32_t ledcWriteNote(uint8_t channel, note_t note, uint8_t octave);
|
||||
uint32_t ledcRead(uint8_t channel);
|
||||
double ledcReadFreq(uint8_t channel);
|
||||
uint32_t ledcReadFreq(uint8_t channel);
|
||||
void ledcAttachPin(uint8_t pin, uint8_t channel);
|
||||
void ledcDetachPin(uint8_t pin);
|
||||
double ledcChangeFrequency(uint8_t channel, double freq, uint8_t resolution_bits);
|
||||
uint32_t ledcChangeFrequency(uint8_t channel, uint32_t freq, uint8_t resolution_bits);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -206,16 +206,16 @@ void log_print_buf(const uint8_t *b, size_t len);
|
||||
#undef ESP_EARLY_LOGD
|
||||
#undef ESP_EARLY_LOGV
|
||||
|
||||
#define ESP_LOGE(tag, ...) log_e(__VA_ARGS__)
|
||||
#define ESP_LOGW(tag, ...) log_w(__VA_ARGS__)
|
||||
#define ESP_LOGI(tag, ...) log_i(__VA_ARGS__)
|
||||
#define ESP_LOGD(tag, ...) log_d(__VA_ARGS__)
|
||||
#define ESP_LOGV(tag, ...) log_v(__VA_ARGS__)
|
||||
#define ESP_EARLY_LOGE(tag, ...) isr_log_e(__VA_ARGS__)
|
||||
#define ESP_EARLY_LOGW(tag, ...) isr_log_w(__VA_ARGS__)
|
||||
#define ESP_EARLY_LOGI(tag, ...) isr_log_i(__VA_ARGS__)
|
||||
#define ESP_EARLY_LOGD(tag, ...) isr_log_d(__VA_ARGS__)
|
||||
#define ESP_EARLY_LOGV(tag, ...) isr_log_v(__VA_ARGS__)
|
||||
#define ESP_LOGE(tag, format, ...) log_e("[%s] " format, tag, ##__VA_ARGS__)
|
||||
#define ESP_LOGW(tag, format, ...) log_w("[%s] " format, tag, ##__VA_ARGS__)
|
||||
#define ESP_LOGI(tag, format, ...) log_i("[%s] " format, tag, ##__VA_ARGS__)
|
||||
#define ESP_LOGD(tag, format, ...) log_d("[%s] " format, tag, ##__VA_ARGS__)
|
||||
#define ESP_LOGV(tag, format, ...) log_v("[%s] " format, tag, ##__VA_ARGS__)
|
||||
#define ESP_EARLY_LOGE(tag, format, ...) isr_log_e("[%s] " format, tag, ##__VA_ARGS__)
|
||||
#define ESP_EARLY_LOGW(tag, format, ...) isr_log_w("[%s] " format, tag, ##__VA_ARGS__)
|
||||
#define ESP_EARLY_LOGI(tag, format, ...) isr_log_i("[%s] " format, tag, ##__VA_ARGS__)
|
||||
#define ESP_EARLY_LOGD(tag, format, ...) isr_log_d("[%s] " format, tag, ##__VA_ARGS__)
|
||||
#define ESP_EARLY_LOGV(tag, format, ...) isr_log_v("[%s] " format, tag, ##__VA_ARGS__)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -119,11 +119,6 @@ static void __touchInit()
|
||||
if (err != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// Initial no Threshold and setup
|
||||
for (int i = 0; i < SOC_TOUCH_SENSOR_NUM; i++) {
|
||||
__touchInterruptHandlers[i].fn = NULL;
|
||||
touch_pad_config(i, SOC_TOUCH_PAD_THRESHOLD_MAX); // returns ESP_OK
|
||||
}
|
||||
// keep ISR activated - it can run all together (ISR + touchRead())
|
||||
err = touch_pad_isr_register(__touchISR, NULL);
|
||||
if (err != ESP_OK) {
|
||||
@ -148,18 +143,7 @@ static void __touchInit()
|
||||
// Touch Sensor Timer initiated
|
||||
touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); // returns ESP_OK
|
||||
touch_pad_fsm_start(); // returns ESP_OK
|
||||
|
||||
// Initial no Threshold and setup - TOUCH0 is internal denoise channel
|
||||
for (int i = 1; i < SOC_TOUCH_SENSOR_NUM; i++) {
|
||||
__touchInterruptHandlers[i].fn = NULL;
|
||||
touch_pad_config(i); // returns ESP_OK
|
||||
}
|
||||
// keep ISR activated - it can run all together (ISR + touchRead())
|
||||
err = touch_pad_isr_register(__touchISR, NULL, TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE);
|
||||
if (err != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE); // returns ESP_OK
|
||||
//ISR setup moved to __touchChannelInit
|
||||
#endif
|
||||
|
||||
initialized = true;
|
||||
@ -170,13 +154,43 @@ err:
|
||||
return;
|
||||
}
|
||||
|
||||
static void __touchChannelInit(int pad)
|
||||
{
|
||||
static bool channels_initialized[SOC_TOUCH_SENSOR_NUM] = { false };
|
||||
if(channels_initialized[pad]){
|
||||
return;
|
||||
}
|
||||
|
||||
#if SOC_TOUCH_VERSION_1 // ESP32
|
||||
// Initial no Threshold and setup
|
||||
__touchInterruptHandlers[pad].fn = NULL;
|
||||
touch_pad_config(pad, SOC_TOUCH_PAD_THRESHOLD_MAX); // returns ESP_OK
|
||||
#elif SOC_TOUCH_VERSION_2 // ESP32S2, ESP32S3
|
||||
// Initial no Threshold and setup
|
||||
__touchInterruptHandlers[pad].fn = NULL;
|
||||
touch_pad_config(pad); // returns ESP_OK
|
||||
// keep ISR activated - it can run all together (ISR + touchRead())
|
||||
esp_err_t err = touch_pad_isr_register(__touchISR, NULL, TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE);
|
||||
if (err != ESP_OK) {
|
||||
log_e(" Touch sensor initialization error.");
|
||||
return;
|
||||
}
|
||||
touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE); // returns ESP_OK
|
||||
#endif
|
||||
|
||||
channels_initialized[pad] = true;
|
||||
delay(20); //delay needed before reading from touch channel after config
|
||||
}
|
||||
|
||||
static touch_value_t __touchRead(uint8_t pin)
|
||||
{
|
||||
int8_t pad = digitalPinToTouchChannel(pin);
|
||||
if(pad < 0){
|
||||
return 0;
|
||||
}
|
||||
|
||||
__touchInit();
|
||||
__touchChannelInit(pad);
|
||||
|
||||
touch_value_t touch_value;
|
||||
touch_pad_read_raw_data(pad, &touch_value);
|
||||
@ -198,6 +212,9 @@ static void __touchConfigInterrupt(uint8_t pin, void (*userFunc)(void), void *Ar
|
||||
} else {
|
||||
// attach ISR User Call
|
||||
__touchInit();
|
||||
#if SOC_TOUCH_VERSION_2 // ESP32S2, ESP32S3
|
||||
__touchChannelInit(pad);
|
||||
#endif
|
||||
__touchInterruptHandlers[pad].fn = userFunc;
|
||||
__touchInterruptHandlers[pad].callWithArgs = callWithArgs;
|
||||
__touchInterruptHandlers[pad].arg = Args;
|
||||
|
@ -71,48 +71,70 @@ Installing using PlatformIO
|
||||
:width: 200
|
||||
:figclass: align-center
|
||||
|
||||
PlatformIO is one of most popular embedded development tool. Currently, it supports Arduino ESP32 and ESP-IDF from Espressif (other platforms are also supported).
|
||||
PlatformIO is a professional collaborative platform for embedded development. It has out-of-the-box support for ESP32 SoCs and allows working with Arduino ESP32 as well as ESP-IDF from Espressif without changing your development environment. PlatformIO includes lots of instruments for the most common development tasks such as debugging, unit testing, and static code analysis.
|
||||
|
||||
To install PIO, you can follow this Getting Started, provided by PIO at `docs.platformio.org`_.
|
||||
A detailed overview of the PlatformIO ecosystem and its philosophy can be found in `the official documentation <https://docs.platformio.org/en/latest/core/index.html>`_.
|
||||
|
||||
To test the latest Arduino ESP32, you need to change your project *platform.ini* accordingly.
|
||||
PlatformIO can be used in two flavors:
|
||||
|
||||
- Start a new project and select one of the available board. You can change after by changing the *platform.ini* file.
|
||||
- `PlatformIO IDE <https://platformio.org/platformio-ide>`_ is a toolset for embedded C/C++ development available on Windows, macOS and Linux platforms
|
||||
|
||||
- `PlatformIO Core (CLI) <https://docs.platformio.org/en/latest/core/index.html>`_ is a command-line tool that consists of a multi-platform build system, platform and library managers and other integration components. It can be used with a variety of code development environments and allows integration with cloud platforms and web services
|
||||
|
||||
To install PlatformIO, you can follow this Getting Started, provided at `docs.platformio.org`_.
|
||||
|
||||
Using the stable code
|
||||
*********************
|
||||
|
||||
.. note::
|
||||
A detailed overview of supported development boards, examples and frameworks can be found on `the official Espressif32 dev-platform page <https://registry.platformio.org/platforms/platformio/espressif32>`_ in the PlatformIO Registry.
|
||||
|
||||
The most reliable and easiest way to get started is to use the latest stable version of the ESP32 development platform that passed all tests/verifications and can be used in production.
|
||||
|
||||
Create a new project and select one of the available boards. You can change after by changing the `platformio.ini <https://docs.platformio.org/en/latest/projectconf/index.html>`_ file.
|
||||
|
||||
- For ESP32
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
[env:arduino-esp32]
|
||||
platform = https://github.com/platformio/platform-espressif32.git#feature/arduino-upstream
|
||||
[env:esp32dev]
|
||||
platform = espressif32
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
platform_packages =
|
||||
framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32#master
|
||||
|
||||
- For ESP32-S2 (ESP32-S2-Saola-1 board)
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
[env:arduino-esp32s2]
|
||||
platform = https://github.com/platformio/platform-espressif32.git#feature/arduino-upstream
|
||||
[env:esp32-s2-saola-1]
|
||||
platform = espressif32
|
||||
board = esp32-s2-saola-1
|
||||
framework = arduino
|
||||
platform_packages =
|
||||
framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32#master
|
||||
|
||||
- For ESP32-C3 (ESP32-S3-DevKitM-1 board)
|
||||
- For ESP32-C3 (ESP32-C3-DevKitM-1 board)
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
[env:arduino-esp32c3]
|
||||
platform = https://github.com/platformio/platform-espressif32.git#feature/arduino-upstream
|
||||
[env:esp32-c3-devkitm-1]
|
||||
platform = espressif32
|
||||
board = esp32-c3-devkitm-1
|
||||
framework = arduino
|
||||
|
||||
How to update to the latest code
|
||||
********************************
|
||||
|
||||
To test the latest Arduino ESP32, you need to change your project *platformio.ini* accordingly.
|
||||
The following configuration uses the upstream version of the Espressif development platform and the latest Arduino core directly from the Espressif GitHub repository:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
[env:esp32-c3-devkitm-1]
|
||||
platform = https://github.com/platformio/platform-espressif32.git
|
||||
board = esp32-c3-devkitm-1
|
||||
framework = arduino
|
||||
platform_packages =
|
||||
framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32#master
|
||||
framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32#master
|
||||
|
||||
Now you're able to use the latest Arduino ESP32 support directly from Espressif GitHub repository.
|
||||
|
||||
To get more information about PlatformIO, see the following links:
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "Stream.h"
|
||||
#include <functional>
|
||||
extern "C" {
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "esp_netif.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
@ -71,7 +71,7 @@ bool BLEAddress::operator!=(const BLEAddress& otherAddress) const {
|
||||
}
|
||||
|
||||
bool BLEAddress::operator<(const BLEAddress& otherAddress) const {
|
||||
return memcmp(otherAddress.m_address, m_address, ESP_BD_ADDR_LEN) < 0;
|
||||
return memcmp(m_address, otherAddress.m_address, ESP_BD_ADDR_LEN) < 0;
|
||||
}
|
||||
|
||||
bool BLEAddress::operator<=(const BLEAddress& otherAddress) const {
|
||||
@ -83,7 +83,7 @@ bool BLEAddress::operator>=(const BLEAddress& otherAddress) const {
|
||||
}
|
||||
|
||||
bool BLEAddress::operator>(const BLEAddress& otherAddress) const {
|
||||
return memcmp(otherAddress.m_address, m_address, ESP_BD_ADDR_LEN) > 0;
|
||||
return memcmp(m_address, otherAddress.m_address, ESP_BD_ADDR_LEN) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,114 @@
|
||||
/**
|
||||
* Bluetooth Classic Example
|
||||
* Scan for devices - asyncronously, print device as soon as found
|
||||
* query devices for SPP - SDP profile
|
||||
* connect to first device offering a SPP connection
|
||||
*
|
||||
* Example python server:
|
||||
* source: https://gist.github.com/ukBaz/217875c83c2535d22a16ba38fc8f2a91
|
||||
*
|
||||
* Tested with Raspberry Pi onboard Wifi/BT, USB BT 4.0 dongles, USB BT 1.1 dongles,
|
||||
* 202202: does NOT work with USB BT 2.0 dongles when esp32 aduino lib is compiled with SSP support!
|
||||
* see https://github.com/espressif/esp-idf/issues/8394
|
||||
*
|
||||
* use ESP_SPP_SEC_ENCRYPT|ESP_SPP_SEC_AUTHENTICATE in connect() if remote side requests 'RequireAuthentication': dbus.Boolean(True),
|
||||
* use ESP_SPP_SEC_NONE or ESP_SPP_SEC_ENCRYPT|ESP_SPP_SEC_AUTHENTICATE in connect() if remote side has Authentication: False
|
||||
*/
|
||||
|
||||
#include <map>
|
||||
#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
|
||||
|
||||
#if !defined(CONFIG_BT_SPP_ENABLED)
|
||||
#error Serial Bluetooth not available or not enabled. It is only available for the ESP32 chip.
|
||||
#endif
|
||||
|
||||
BluetoothSerial SerialBT;
|
||||
|
||||
|
||||
#define BT_DISCOVER_TIME 10000
|
||||
esp_spp_sec_t sec_mask=ESP_SPP_SEC_NONE; // or ESP_SPP_SEC_ENCRYPT|ESP_SPP_SEC_AUTHENTICATE to request pincode confirmation
|
||||
esp_spp_role_t role=ESP_SPP_ROLE_SLAVE; // or ESP_SPP_ROLE_MASTER
|
||||
|
||||
// std::map<BTAddress, BTAdvertisedDeviceSet> btDeviceList;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
if(! SerialBT.begin("ESP32test", true) ) {
|
||||
Serial.println("========== serialBT failed!");
|
||||
abort();
|
||||
}
|
||||
// SerialBT.setPin("1234"); // doesn't seem to change anything
|
||||
// SerialBT.enableSSP(); // doesn't seem to change anything
|
||||
|
||||
|
||||
Serial.println("Starting discoverAsync...");
|
||||
BTScanResults* btDeviceList = SerialBT.getScanResults(); // maybe accessing from different threads!
|
||||
if (SerialBT.discoverAsync([](BTAdvertisedDevice* pDevice) {
|
||||
// BTAdvertisedDeviceSet*set = reinterpret_cast<BTAdvertisedDeviceSet*>(pDevice);
|
||||
// btDeviceList[pDevice->getAddress()] = * set;
|
||||
Serial.printf(">>>>>>>>>>>Found a new device asynchronously: %s\n", pDevice->toString().c_str());
|
||||
} )
|
||||
) {
|
||||
delay(BT_DISCOVER_TIME);
|
||||
Serial.print("Stopping discoverAsync... ");
|
||||
SerialBT.discoverAsyncStop();
|
||||
Serial.println("discoverAsync stopped");
|
||||
delay(5000);
|
||||
if(btDeviceList->getCount() > 0) {
|
||||
BTAddress addr;
|
||||
int channel=0;
|
||||
Serial.println("Found devices:");
|
||||
for (int i=0; i < btDeviceList->getCount(); i++) {
|
||||
BTAdvertisedDevice *device=btDeviceList->getDevice(i);
|
||||
Serial.printf(" ----- %s %s %d\n", device->getAddress().toString().c_str(), device->getName().c_str(), device->getRSSI());
|
||||
std::map<int,std::string> channels=SerialBT.getChannels(device->getAddress());
|
||||
Serial.printf("scanned for services, found %d\n", channels.size());
|
||||
for(auto const &entry : channels) {
|
||||
Serial.printf(" channel %d (%s)\n", entry.first, entry.second.c_str());
|
||||
}
|
||||
if(channels.size() > 0) {
|
||||
addr = device->getAddress();
|
||||
channel=channels.begin()->first;
|
||||
}
|
||||
}
|
||||
if(addr) {
|
||||
Serial.printf("connecting to %s - %d\n", addr.toString().c_str(), channel);
|
||||
SerialBT.connect(addr, channel, sec_mask, role);
|
||||
}
|
||||
} else {
|
||||
Serial.println("Didn't find any devices");
|
||||
}
|
||||
} else {
|
||||
Serial.println("Error on discoverAsync f.e. not workin after a \"connect\"");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String sendData="Hi from esp32!\n";
|
||||
|
||||
void loop() {
|
||||
if(! SerialBT.isClosed() && SerialBT.connected()) {
|
||||
if( SerialBT.write((const uint8_t*) sendData.c_str(),sendData.length()) != sendData.length()) {
|
||||
Serial.println("tx: error");
|
||||
} else {
|
||||
Serial.printf("tx: %s",sendData.c_str());
|
||||
}
|
||||
if(SerialBT.available()) {
|
||||
Serial.print("rx: ");
|
||||
while(SerialBT.available()) {
|
||||
int c=SerialBT.read();
|
||||
if(c >= 0) {
|
||||
Serial.print((char) c);
|
||||
}
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
} else {
|
||||
Serial.println("not connected");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
@ -29,6 +29,9 @@ BTAddress::BTAddress(esp_bd_addr_t address) {
|
||||
memcpy(m_address, address, ESP_BD_ADDR_LEN);
|
||||
} // BTAddress
|
||||
|
||||
BTAddress::BTAddress() {
|
||||
bzero(m_address, ESP_BD_ADDR_LEN);
|
||||
} // BTAddress
|
||||
|
||||
/**
|
||||
* @brief Create an address from a hex string
|
||||
@ -64,13 +67,20 @@ bool BTAddress::equals(BTAddress otherAddress) {
|
||||
return memcmp(otherAddress.getNative(), m_address, 6) == 0;
|
||||
} // equals
|
||||
|
||||
BTAddress::operator bool () const {
|
||||
for(int i = 0; i < ESP_BD_ADDR_LEN; i++){
|
||||
if(this->m_address[i])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} // operator ()
|
||||
|
||||
/**
|
||||
* @brief Return the native representation of the address.
|
||||
* @return The native representation of the address.
|
||||
*/
|
||||
esp_bd_addr_t *BTAddress::getNative() {
|
||||
return &m_address;
|
||||
esp_bd_addr_t *BTAddress::getNative() const {
|
||||
return const_cast<esp_bd_addr_t *>(&m_address);
|
||||
} // getNative
|
||||
|
||||
|
||||
@ -85,7 +95,7 @@ esp_bd_addr_t *BTAddress::getNative() {
|
||||
*
|
||||
* @return The string representation of the address.
|
||||
*/
|
||||
std::string BTAddress::toString() {
|
||||
std::string BTAddress::toString() const {
|
||||
auto size = 18;
|
||||
char *res = (char*)malloc(size);
|
||||
snprintf(res, size, "%02x:%02x:%02x:%02x:%02x:%02x", m_address[0], m_address[1], m_address[2], m_address[3], m_address[4], m_address[5]);
|
||||
|
@ -22,11 +22,14 @@
|
||||
*/
|
||||
class BTAddress {
|
||||
public:
|
||||
BTAddress();
|
||||
BTAddress(esp_bd_addr_t address);
|
||||
BTAddress(std::string stringAddress);
|
||||
bool equals(BTAddress otherAddress);
|
||||
esp_bd_addr_t* getNative();
|
||||
std::string toString();
|
||||
operator bool () const;
|
||||
|
||||
esp_bd_addr_t* getNative() const;
|
||||
std::string toString() const;
|
||||
|
||||
private:
|
||||
esp_bd_addr_t m_address;
|
||||
|
@ -16,14 +16,14 @@ public:
|
||||
virtual ~BTAdvertisedDevice() = default;
|
||||
|
||||
virtual BTAddress getAddress();
|
||||
virtual uint32_t getCOD();
|
||||
virtual std::string getName();
|
||||
virtual int8_t getRSSI();
|
||||
virtual uint32_t getCOD() const;
|
||||
virtual std::string getName() const;
|
||||
virtual int8_t getRSSI() const;
|
||||
|
||||
|
||||
virtual bool haveCOD();
|
||||
virtual bool haveName();
|
||||
virtual bool haveRSSI();
|
||||
virtual bool haveCOD() const;
|
||||
virtual bool haveName() const;
|
||||
virtual bool haveRSSI() const;
|
||||
|
||||
virtual std::string toString();
|
||||
};
|
||||
@ -35,14 +35,14 @@ public:
|
||||
|
||||
|
||||
BTAddress getAddress();
|
||||
uint32_t getCOD();
|
||||
std::string getName();
|
||||
int8_t getRSSI();
|
||||
uint32_t getCOD() const;
|
||||
std::string getName() const;
|
||||
int8_t getRSSI() const;
|
||||
|
||||
|
||||
bool haveCOD();
|
||||
bool haveName();
|
||||
bool haveRSSI();
|
||||
bool haveCOD() const;
|
||||
bool haveName() const;
|
||||
bool haveRSSI() const;
|
||||
|
||||
std::string toString();
|
||||
|
||||
|
@ -25,14 +25,14 @@ BTAdvertisedDeviceSet::BTAdvertisedDeviceSet() {
|
||||
} // BTAdvertisedDeviceSet
|
||||
|
||||
BTAddress BTAdvertisedDeviceSet::getAddress() { return m_address; }
|
||||
uint32_t BTAdvertisedDeviceSet::getCOD() { return m_cod; }
|
||||
std::string BTAdvertisedDeviceSet::getName() { return m_name; }
|
||||
int8_t BTAdvertisedDeviceSet::getRSSI() { return m_rssi; }
|
||||
uint32_t BTAdvertisedDeviceSet::getCOD() const { return m_cod; }
|
||||
std::string BTAdvertisedDeviceSet::getName() const { return m_name; }
|
||||
int8_t BTAdvertisedDeviceSet::getRSSI() const { return m_rssi; }
|
||||
|
||||
|
||||
bool BTAdvertisedDeviceSet::haveCOD() { return m_haveCOD; }
|
||||
bool BTAdvertisedDeviceSet::haveName() { return m_haveName; }
|
||||
bool BTAdvertisedDeviceSet::haveRSSI() { return m_haveRSSI; }
|
||||
bool BTAdvertisedDeviceSet::haveCOD() const { return m_haveCOD; }
|
||||
bool BTAdvertisedDeviceSet::haveName() const { return m_haveName; }
|
||||
bool BTAdvertisedDeviceSet::haveRSSI() const { return m_haveRSSI; }
|
||||
|
||||
/**
|
||||
* @brief Create a string representation of this device.
|
||||
|
@ -72,18 +72,30 @@ static esp_bt_pin_code_t _pin_code;
|
||||
static int _pin_len;
|
||||
static bool _isPinSet;
|
||||
static bool _enableSSP;
|
||||
static esp_spp_sec_t _sec_mask;
|
||||
static esp_spp_role_t _role;
|
||||
// start connect on ESP_SPP_DISCOVERY_COMP_EVT or save entry for getChannels
|
||||
static bool _doConnect;
|
||||
static std::map <int, std::string> sdpRecords;
|
||||
|
||||
static BTScanResultsSet scanResults;
|
||||
static BTAdvertisedDeviceCb advertisedDeviceCb = nullptr;
|
||||
|
||||
// _spp_event_group
|
||||
#define SPP_RUNNING 0x01
|
||||
#define SPP_CONNECTED 0x02
|
||||
#define SPP_CONGESTED 0x04
|
||||
// true until OPEN successful, changes to false on CLOSE
|
||||
#define SPP_DISCONNECTED 0x08
|
||||
// true until connect(), changes to true on CLOSE
|
||||
#define SPP_CLOSED 0x10
|
||||
|
||||
// _bt_event_group
|
||||
#define BT_DISCOVERY_RUNNING 0x01
|
||||
#define BT_DISCOVERY_COMPLETED 0x02
|
||||
|
||||
#define BT_SDP_RUNNING 0x04
|
||||
#define BT_SDP_COMPLETED 0x08
|
||||
|
||||
typedef struct {
|
||||
size_t len;
|
||||
@ -98,7 +110,7 @@ static char *bda2str(esp_bd_addr_t bda, char *str, size_t size)
|
||||
}
|
||||
|
||||
uint8_t *p = bda;
|
||||
sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
snprintf(str, size, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
p[0], p[1], p[2], p[3], p[4], p[5]);
|
||||
return str;
|
||||
}
|
||||
@ -280,13 +292,15 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
|
||||
|
||||
case ESP_SPP_CLOSE_EVT://Client connection closed
|
||||
if ((param->close.async == false && param->close.status == ESP_SPP_SUCCESS) || param->close.async) {
|
||||
log_i("ESP_SPP_CLOSE_EVT: %u", secondConnectionAttempt);
|
||||
log_i("ESP_SPP_CLOSE_EVT status:%d handle:%d close_by_remote:%d attempt %u", param->close.status,
|
||||
param->close.handle, param->close.async, secondConnectionAttempt);
|
||||
if(secondConnectionAttempt) {
|
||||
secondConnectionAttempt = false;
|
||||
} else {
|
||||
_spp_client = 0;
|
||||
xEventGroupSetBits(_spp_event_group, SPP_DISCONNECTED);
|
||||
xEventGroupSetBits(_spp_event_group, SPP_CONGESTED);
|
||||
xEventGroupSetBits(_spp_event_group, SPP_CLOSED);
|
||||
}
|
||||
xEventGroupClearBits(_spp_event_group, SPP_CONNECTED);
|
||||
} else {
|
||||
@ -333,13 +347,37 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
|
||||
break;
|
||||
|
||||
case ESP_SPP_DISCOVERY_COMP_EVT://discovery complete
|
||||
log_i("ESP_SPP_DISCOVERY_COMP_EVT");
|
||||
log_i("ESP_SPP_DISCOVERY_COMP_EVT num=%d", param->disc_comp.scn_num);
|
||||
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);
|
||||
for(int i=0; i < param->disc_comp.scn_num; i++) {
|
||||
log_d("ESP_SPP_DISCOVERY_COMP_EVT: spp [%d] channel: %d service name:%s", i, param->disc_comp.scn[i], param->disc_comp.service_name[0]);
|
||||
}
|
||||
if(_doConnect) {
|
||||
if(param->disc_comp.scn_num > 0) {
|
||||
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)
|
||||
char bda_str[18];
|
||||
log_i("ESP_SPP_DISCOVERY_COMP_EVT: spp connect to remote %s channel %d",
|
||||
bda2str(_peer_bd_addr, bda_str, sizeof(bda_str)),
|
||||
param->disc_comp.scn[0]);
|
||||
#endif
|
||||
xEventGroupClearBits(_spp_event_group, SPP_CLOSED);
|
||||
if(esp_spp_connect(_sec_mask, _role, param->disc_comp.scn[0], _peer_bd_addr) != ESP_OK) {
|
||||
log_e("ESP_SPP_DISCOVERY_COMP_EVT connect failed");
|
||||
xEventGroupSetBits(_spp_event_group, SPP_CLOSED);
|
||||
}
|
||||
} else {
|
||||
log_e("ESP_SPP_DISCOVERY_COMP_EVT remote doesn't offer an SPP channel");
|
||||
xEventGroupSetBits(_spp_event_group, SPP_CLOSED);
|
||||
}
|
||||
} else {
|
||||
for(int i=0; i < param->disc_comp.scn_num; i++) {
|
||||
sdpRecords[param->disc_comp.scn[i]] = param->disc_comp.service_name[0];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log_e("ESP_SPP_DISCOVERY_COMP_EVT failed!, status:%d", param->disc_comp.status);
|
||||
}
|
||||
xEventGroupSetBits(_bt_event_group, BT_SDP_COMPLETED);
|
||||
break;
|
||||
|
||||
case ESP_SPP_OPEN_EVT://Client connection open
|
||||
@ -360,10 +398,15 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
|
||||
break;
|
||||
|
||||
case ESP_SPP_CL_INIT_EVT://client initiated a connection
|
||||
log_i("ESP_SPP_CL_INIT_EVT");
|
||||
if (param->cl_init.status == ESP_SPP_SUCCESS) {
|
||||
log_i("ESP_SPP_CL_INIT_EVT handle:%d sec_id:%d", param->cl_init.handle, param->cl_init.sec_id);
|
||||
} else {
|
||||
log_i("ESP_SPP_CL_INIT_EVT status:%d", param->cl_init.status);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
log_i("ESP_SPP_* event unhandled %d", event);
|
||||
break;
|
||||
}
|
||||
if(custom_spp_callback)(*custom_spp_callback)(event, param);
|
||||
@ -377,7 +420,7 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa
|
||||
{
|
||||
switch(event){
|
||||
case ESP_BT_GAP_DISC_RES_EVT: {
|
||||
log_i("ESP_BT_GAP_DISC_RES_EVT");
|
||||
log_i("ESP_BT_GAP_DISC_RES_EVT properties=%d", param->disc_res.num_prop);
|
||||
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)
|
||||
char bda_str[18];
|
||||
log_i("Scanned device: %s", bda2str(param->disc_res.bda, bda_str, 18));
|
||||
@ -417,28 +460,29 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa
|
||||
break;
|
||||
|
||||
case ESP_BT_GAP_DEV_PROP_COD:
|
||||
log_d("ESP_BT_GAP_DEV_PROP_COD");
|
||||
if (param->disc_res.prop[i].len <= sizeof(int)) {
|
||||
uint32_t cod = 0;
|
||||
memcpy(&cod, param->disc_res.prop[i].val, param->disc_res.prop[i].len);
|
||||
advertisedDevice.setCOD(cod);
|
||||
log_d("ESP_BT_GAP_DEV_PROP_COD 0x%x", cod);
|
||||
} else {
|
||||
log_d("Value size larger than integer");
|
||||
log_d("ESP_BT_GAP_DEV_PROP_COD invalid COD: Value size larger than integer");
|
||||
}
|
||||
break;
|
||||
|
||||
case ESP_BT_GAP_DEV_PROP_RSSI:
|
||||
log_d("ESP_BT_GAP_DEV_PROP_RSSI");
|
||||
if (param->disc_res.prop[i].len <= sizeof(int)) {
|
||||
uint8_t rssi = 0;
|
||||
memcpy(&rssi, param->disc_res.prop[i].val, param->disc_res.prop[i].len);
|
||||
log_d("ESP_BT_GAP_DEV_PROP_RSSI %d", rssi);
|
||||
advertisedDevice.setRSSI(rssi);
|
||||
} else {
|
||||
log_d("Value size larger than integer");
|
||||
log_d("ESP_BT_GAP_DEV_PROP_RSSI invalid RSSI: Value size larger than integer");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
log_i("ESP_BT_GAP_DISC_RES_EVT unknown property [%d]:type:%d", i, param->disc_res.prop[i].type);
|
||||
break;
|
||||
}
|
||||
if (_isRemoteAddressSet)
|
||||
@ -455,11 +499,12 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa
|
||||
break;
|
||||
|
||||
case ESP_BT_GAP_DISC_STATE_CHANGED_EVT:
|
||||
log_i("ESP_BT_GAP_DISC_STATE_CHANGED_EVT");
|
||||
if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STOPPED) {
|
||||
log_i("ESP_BT_GAP_DISC_STATE_CHANGED_EVT stopped");
|
||||
xEventGroupClearBits(_bt_event_group, BT_DISCOVERY_RUNNING);
|
||||
xEventGroupSetBits(_bt_event_group, BT_DISCOVERY_COMPLETED);
|
||||
} else { // ESP_BT_GAP_DISCOVERY_STARTED
|
||||
log_i("ESP_BT_GAP_DISC_STATE_CHANGED_EVT started");
|
||||
xEventGroupClearBits(_bt_event_group, BT_DISCOVERY_COMPLETED);
|
||||
xEventGroupSetBits(_bt_event_group, BT_DISCOVERY_RUNNING);
|
||||
}
|
||||
@ -522,7 +567,24 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa
|
||||
log_i("ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!");
|
||||
break;
|
||||
|
||||
case ESP_BT_GAP_CONFIG_EIR_DATA_EVT:
|
||||
log_i("ESP_BT_GAP_CONFIG_EIR_DATA_EVT: stat:%d num:%d", param->config_eir_data.stat, param->config_eir_data.eir_type_num);
|
||||
break;
|
||||
|
||||
case ESP_BT_GAP_READ_REMOTE_NAME_EVT:
|
||||
if (param->read_rmt_name.stat == ESP_BT_STATUS_SUCCESS ) {
|
||||
log_i("ESP_BT_GAP_READ_REMOTE_NAME_EVT: %s", param->read_rmt_name.rmt_name);
|
||||
} else {
|
||||
log_i("ESP_BT_GAP_READ_REMOTE_NAME_EVT: no success stat:%d", param->read_rmt_name.stat);
|
||||
}
|
||||
break;
|
||||
|
||||
case ESP_BT_GAP_MODE_CHG_EVT:
|
||||
log_i("ESP_BT_GAP_MODE_CHG_EVT: mode: %d", param->mode_chg.mode);
|
||||
break;
|
||||
|
||||
default:
|
||||
log_i("ESP-BT_GAP_* unknown message: %d", event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -546,6 +608,7 @@ static bool _init_bt(const char *deviceName)
|
||||
xEventGroupClearBits(_spp_event_group, 0xFFFFFF);
|
||||
xEventGroupSetBits(_spp_event_group, SPP_CONGESTED);
|
||||
xEventGroupSetBits(_spp_event_group, SPP_DISCONNECTED);
|
||||
xEventGroupSetBits(_spp_event_group, SPP_CLOSED);
|
||||
}
|
||||
if (_spp_rx_queue == NULL){
|
||||
_spp_rx_queue = xQueueCreate(RX_QUEUE_SIZE, sizeof(uint8_t)); //initialize the queue
|
||||
@ -623,6 +686,7 @@ static bool _init_bt(const char *deviceName)
|
||||
esp_bt_dev_set_device_name(deviceName);
|
||||
|
||||
if (_isPinSet) {
|
||||
log_i("pin set");
|
||||
btSetPin();
|
||||
}
|
||||
|
||||
@ -690,7 +754,16 @@ static bool _stop_bt()
|
||||
|
||||
static bool waitForConnect(int timeout) {
|
||||
TickType_t xTicksToWait = timeout / portTICK_PERIOD_MS;
|
||||
return (xEventGroupWaitBits(_spp_event_group, SPP_CONNECTED, pdFALSE, pdTRUE, xTicksToWait) & SPP_CONNECTED) != 0;
|
||||
// wait for connected or closed
|
||||
EventBits_t rc = xEventGroupWaitBits(_spp_event_group, SPP_CONNECTED | SPP_CLOSED, pdFALSE, pdFALSE, xTicksToWait);
|
||||
if((rc & SPP_CONNECTED) != 0)
|
||||
return true;
|
||||
else if((rc & SPP_CLOSED) != 0) {
|
||||
log_d("connection closed!");
|
||||
return false;
|
||||
}
|
||||
log_d("timeout");
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool waitForDiscovered(int timeout) {
|
||||
@ -698,6 +771,11 @@ static bool waitForDiscovered(int timeout) {
|
||||
return (xEventGroupWaitBits(_spp_event_group, BT_DISCOVERY_COMPLETED, pdFALSE, pdTRUE, xTicksToWait) & BT_DISCOVERY_COMPLETED) != 0;
|
||||
}
|
||||
|
||||
static bool waitForSDPRecord(int timeout) {
|
||||
TickType_t xTicksToWait = timeout / portTICK_PERIOD_MS;
|
||||
return (xEventGroupWaitBits(_bt_event_group, BT_SDP_COMPLETED, pdFALSE, pdTRUE, xTicksToWait) & BT_SDP_COMPLETED) != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Serial Bluetooth Arduino
|
||||
*
|
||||
@ -713,6 +791,9 @@ BluetoothSerial::~BluetoothSerial(void)
|
||||
_stop_bt();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Param isMaster set to true if you want to connect to an other device
|
||||
*/
|
||||
bool BluetoothSerial::begin(String localName, bool isMaster)
|
||||
{
|
||||
_isMaster = isMaster;
|
||||
@ -733,7 +814,7 @@ int BluetoothSerial::available(void)
|
||||
int BluetoothSerial::peek(void)
|
||||
{
|
||||
uint8_t c;
|
||||
if (_spp_rx_queue && xQueuePeek(_spp_rx_queue, &c, 0)){
|
||||
if (_spp_rx_queue && xQueuePeek(_spp_rx_queue, &c, this->timeoutTicks)){
|
||||
return c;
|
||||
}
|
||||
return -1;
|
||||
@ -744,16 +825,24 @@ bool BluetoothSerial::hasClient(void)
|
||||
return _spp_client > 0;
|
||||
}
|
||||
|
||||
int BluetoothSerial::read(void)
|
||||
int BluetoothSerial::read()
|
||||
{
|
||||
|
||||
uint8_t c = 0;
|
||||
if (_spp_rx_queue && xQueueReceive(_spp_rx_queue, &c, 0)){
|
||||
if (_spp_rx_queue && xQueueReceive(_spp_rx_queue, &c, this->timeoutTicks)){
|
||||
return c;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set timeout for read / peek
|
||||
*/
|
||||
void BluetoothSerial::setTimeout(int timeoutMS)
|
||||
{
|
||||
this->timeoutTicks=timeoutMS / portTICK_PERIOD_MS;
|
||||
}
|
||||
|
||||
size_t BluetoothSerial::write(uint8_t c)
|
||||
{
|
||||
return write(&c, 1);
|
||||
@ -812,6 +901,7 @@ void BluetoothSerial::enableSSP() {
|
||||
* Use fixed pin code
|
||||
*/
|
||||
bool BluetoothSerial::setPin(const char *pin) {
|
||||
log_i("pin: %s", pin);
|
||||
bool isEmpty = !(pin && *pin);
|
||||
if (isEmpty && !_isPinSet) {
|
||||
return true; // nothing to do
|
||||
@ -837,7 +927,10 @@ bool BluetoothSerial::connect(String remoteName)
|
||||
return false;
|
||||
}
|
||||
disconnect();
|
||||
_doConnect = true;
|
||||
_isRemoteAddressSet = false;
|
||||
_sec_mask = ESP_SPP_SEC_ENCRYPT|ESP_SPP_SEC_AUTHENTICATE;
|
||||
_role = ESP_SPP_ROLE_MASTER;
|
||||
strncpy(_remote_name, remoteName.c_str(), ESP_BT_GAP_MAX_BDNAME_LEN);
|
||||
_remote_name[ESP_BT_GAP_MAX_BDNAME_LEN] = 0;
|
||||
log_i("master : remoteName");
|
||||
@ -847,13 +940,23 @@ bool BluetoothSerial::connect(String remoteName)
|
||||
#else
|
||||
esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
|
||||
#endif
|
||||
xEventGroupClearBits(_spp_event_group, SPP_CLOSED);
|
||||
if (esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, INQ_LEN, INQ_NUM_RSPS) == ESP_OK) {
|
||||
return waitForConnect(SCAN_TIMEOUT);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BluetoothSerial::connect(uint8_t remoteAddress[])
|
||||
/**
|
||||
* @Param channel: specify channel or 0 for auto-detect
|
||||
* @Param sec_mask:
|
||||
* ESP_SPP_SEC_ENCRYPT|ESP_SPP_SEC_AUTHENTICATE
|
||||
* ESP_SPP_SEC_NONE
|
||||
* @Param role:
|
||||
* ESP_SPP_ROLE_MASTER master can handle up to 7 connections to slaves
|
||||
* ESP_SPP_ROLE_SLAVE can only have one connection to a master
|
||||
*/
|
||||
bool BluetoothSerial::connect(uint8_t remoteAddress[], int channel, esp_spp_sec_t sec_mask, esp_spp_role_t role)
|
||||
{
|
||||
if (!isReady(true, READY_TIMEOUT)) return false;
|
||||
if (!remoteAddress) {
|
||||
@ -861,10 +964,35 @@ bool BluetoothSerial::connect(uint8_t remoteAddress[])
|
||||
return false;
|
||||
}
|
||||
disconnect();
|
||||
_doConnect = true;
|
||||
_remote_name[0] = 0;
|
||||
_isRemoteAddressSet = true;
|
||||
_sec_mask = sec_mask;
|
||||
_role = role;
|
||||
memcpy(_peer_bd_addr, remoteAddress, ESP_BD_ADDR_LEN);
|
||||
log_i("master : remoteAddress");
|
||||
xEventGroupClearBits(_spp_event_group, SPP_CLOSED);
|
||||
if (channel > 0) {
|
||||
char bda_str[18];
|
||||
log_i("spp connect to remote %s channel %d",
|
||||
bda2str(_peer_bd_addr, bda_str, sizeof(bda_str)),
|
||||
channel);
|
||||
if(esp_spp_connect(sec_mask, role, channel, _peer_bd_addr) != ESP_OK ) {
|
||||
log_e("spp connect failed");
|
||||
return false;
|
||||
}
|
||||
bool rc=waitForConnect(READY_TIMEOUT);
|
||||
if(rc) {
|
||||
log_i("connected");
|
||||
} else {
|
||||
if(this->isClosed()) {
|
||||
log_e("connect failed");
|
||||
} else {
|
||||
log_e("connect timed out after %dms", READY_TIMEOUT);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
if (esp_spp_start_discovery(_peer_bd_addr) == ESP_OK) {
|
||||
return waitForConnect(READY_TIMEOUT);
|
||||
}
|
||||
@ -874,6 +1002,7 @@ bool BluetoothSerial::connect(uint8_t remoteAddress[])
|
||||
bool BluetoothSerial::connect()
|
||||
{
|
||||
if (!isReady(true, READY_TIMEOUT)) return false;
|
||||
_doConnect = true;
|
||||
if (_isRemoteAddressSet){
|
||||
disconnect();
|
||||
// use resolved or set address first
|
||||
@ -924,6 +1053,13 @@ bool BluetoothSerial::connected(int timeout) {
|
||||
return waitForConnect(timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* true if a connection terminated or a connection attempt failed
|
||||
*/
|
||||
bool BluetoothSerial::isClosed() {
|
||||
return xEventGroupGetBits(_spp_event_group) & SPP_CLOSED;
|
||||
}
|
||||
|
||||
bool BluetoothSerial::isReady(bool checkMaster, int timeout) {
|
||||
if (checkMaster && !_isMaster) {
|
||||
log_e("Master mode is not active. Call begin(localName, true) to enable Master mode");
|
||||
@ -956,6 +1092,7 @@ BTScanResults* BluetoothSerial::discover(int timeoutMs) {
|
||||
esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
|
||||
if (esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, timeout, 0) == ESP_OK) {
|
||||
waitForDiscovered(timeoutMs);
|
||||
log_i("gap_cancel_discovery()");
|
||||
esp_bt_gap_cancel_discovery();
|
||||
}
|
||||
return &scanResults;
|
||||
@ -1008,4 +1145,31 @@ BluetoothSerial::operator bool() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* SDP scan address
|
||||
* esp_spp_start_discovery doesn't tell us the btAddress in the callback, so we have to wait until it's finished
|
||||
*/
|
||||
std::map<int, std::string> BluetoothSerial::getChannels(const BTAddress &remoteAddress) {
|
||||
if(xEventGroupGetBits(_bt_event_group) & BT_SDP_RUNNING) {
|
||||
log_e("getChannels failed - already running");
|
||||
}
|
||||
xEventGroupSetBits(_bt_event_group, BT_SDP_RUNNING);
|
||||
xEventGroupClearBits(_bt_event_group, BT_SDP_COMPLETED);
|
||||
_doConnect = false;
|
||||
sdpRecords.clear();
|
||||
log_d("esp_spp_start_discovery");
|
||||
if (esp_spp_start_discovery(*remoteAddress.getNative()) != ESP_OK) {
|
||||
log_e("esp_spp_start_discovery failed");
|
||||
} else {
|
||||
if(! waitForSDPRecord(READY_TIMEOUT)) {
|
||||
log_e("getChannels failed timeout");
|
||||
}
|
||||
log_d("esp_spp_start_discovery wait for BT_SDP_COMPLETED done (%dms)", READY_TIMEOUT);
|
||||
}
|
||||
log_d("esp_spp_start_discovery done, found %d services", sdpRecords.size());
|
||||
xEventGroupClearBits(_bt_event_group, BT_SDP_RUNNING);
|
||||
return sdpRecords;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <esp_gap_bt_api.h>
|
||||
#include <esp_spp_api.h>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include "BTScan.h"
|
||||
|
||||
typedef std::function<void(const uint8_t *buffer, size_t size)> BluetoothSerialDataCb;
|
||||
@ -50,6 +51,7 @@ class BluetoothSerial: public Stream
|
||||
size_t write(const uint8_t *buffer, size_t size);
|
||||
void flush();
|
||||
void end(void);
|
||||
void setTimeout(int timeoutMS);
|
||||
void onData(BluetoothSerialDataCb cb);
|
||||
esp_err_t register_callback(esp_spp_cb_t * callback);
|
||||
|
||||
@ -60,9 +62,12 @@ class BluetoothSerial: public Stream
|
||||
void enableSSP();
|
||||
bool setPin(const char *pin);
|
||||
bool connect(String remoteName);
|
||||
bool connect(uint8_t remoteAddress[]);
|
||||
bool connect(uint8_t remoteAddress[], int channel=0, esp_spp_sec_t sec_mask=(ESP_SPP_SEC_ENCRYPT|ESP_SPP_SEC_AUTHENTICATE), esp_spp_role_t role=ESP_SPP_ROLE_MASTER);
|
||||
bool connect(const BTAddress &remoteAddress, int channel=0, esp_spp_sec_t sec_mask=(ESP_SPP_SEC_ENCRYPT|ESP_SPP_SEC_AUTHENTICATE), esp_spp_role_t role=ESP_SPP_ROLE_MASTER) {
|
||||
return connect(*remoteAddress.getNative(), channel, sec_mask); };
|
||||
bool connect();
|
||||
bool connected(int timeout=0);
|
||||
bool isClosed();
|
||||
bool isReady(bool checkMaster=false, int timeout=0);
|
||||
bool disconnect();
|
||||
bool unpairDevice(uint8_t remoteAddress[]);
|
||||
@ -73,6 +78,8 @@ class BluetoothSerial: public Stream
|
||||
void discoverClear();
|
||||
BTScanResults* getScanResults();
|
||||
|
||||
std::map<int, std::string> getChannels(const BTAddress &remoteAddress);
|
||||
|
||||
const int INQ_TIME = 1280; // Inquire Time unit 1280 ms
|
||||
const int MIN_INQ_TIME = (ESP_BT_GAP_MIN_INQ_LEN * INQ_TIME);
|
||||
const int MAX_INQ_TIME = (ESP_BT_GAP_MAX_INQ_LEN * INQ_TIME);
|
||||
@ -80,7 +87,7 @@ class BluetoothSerial: public Stream
|
||||
operator bool() const;
|
||||
private:
|
||||
String local_name;
|
||||
|
||||
int timeoutTicks=0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -6,22 +6,35 @@
|
||||
// Ensure ESP32 Wrover Module or other board with PSRAM is selected
|
||||
// Partial images will be transmitted if image exceeds buffer size
|
||||
//
|
||||
// You must select partition scheme from the board menu that has at least 3MB APP space.
|
||||
// Face Recognition is DISABLED for ESP32 and ESP32-S2, because it takes up from 15
|
||||
// seconds to process single frame. Face Detection is ENABLED if PSRAM is enabled as well
|
||||
|
||||
// ===================
|
||||
// Select camera model
|
||||
#define CAMERA_MODEL_WROVER_KIT // Has PSRAM
|
||||
// ===================
|
||||
//#define CAMERA_MODEL_WROVER_KIT // Has PSRAM
|
||||
//#define CAMERA_MODEL_ESP_EYE // Has PSRAM
|
||||
//#define CAMERA_MODEL_ESP32S3_EYE // Has PSRAM
|
||||
//#define CAMERA_MODEL_M5STACK_PSRAM // Has PSRAM
|
||||
//#define CAMERA_MODEL_M5STACK_V2_PSRAM // M5Camera version B Has PSRAM
|
||||
//#define CAMERA_MODEL_M5STACK_WIDE // Has PSRAM
|
||||
//#define CAMERA_MODEL_M5STACK_ESP32CAM // No PSRAM
|
||||
//#define CAMERA_MODEL_M5STACK_UNITCAM // No PSRAM
|
||||
//#define CAMERA_MODEL_AI_THINKER // Has PSRAM
|
||||
#define CAMERA_MODEL_AI_THINKER // Has PSRAM
|
||||
//#define CAMERA_MODEL_TTGO_T_JOURNAL // No PSRAM
|
||||
// ** Espressif Internal Boards **
|
||||
//#define CAMERA_MODEL_ESP32_CAM_BOARD
|
||||
//#define CAMERA_MODEL_ESP32S2_CAM_BOARD
|
||||
//#define CAMERA_MODEL_ESP32S3_CAM_LCD
|
||||
|
||||
#include "camera_pins.h"
|
||||
|
||||
const char* ssid = "*********";
|
||||
const char* password = "*********";
|
||||
// ===========================
|
||||
// Enter your WiFi credentials
|
||||
// ===========================
|
||||
const char* ssid = "**********";
|
||||
const char* password = "**********";
|
||||
|
||||
void startCameraServer();
|
||||
|
||||
@ -50,19 +63,32 @@ void setup() {
|
||||
config.pin_pwdn = PWDN_GPIO_NUM;
|
||||
config.pin_reset = RESET_GPIO_NUM;
|
||||
config.xclk_freq_hz = 20000000;
|
||||
config.pixel_format = PIXFORMAT_JPEG;
|
||||
config.frame_size = FRAMESIZE_UXGA;
|
||||
config.pixel_format = PIXFORMAT_JPEG; // for streaming
|
||||
//config.pixel_format = PIXFORMAT_RGB565; // for face detection/recognition
|
||||
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
|
||||
config.fb_location = CAMERA_FB_IN_PSRAM;
|
||||
config.jpeg_quality = 12;
|
||||
config.fb_count = 1;
|
||||
|
||||
// if PSRAM IC present, init with UXGA resolution and higher JPEG quality
|
||||
// for larger pre-allocated frame buffer.
|
||||
if(psramFound()){
|
||||
config.frame_size = FRAMESIZE_UXGA;
|
||||
config.jpeg_quality = 10;
|
||||
config.fb_count = 2;
|
||||
if(config.pixel_format == PIXFORMAT_JPEG){
|
||||
if(psramFound()){
|
||||
config.jpeg_quality = 10;
|
||||
config.fb_count = 2;
|
||||
config.grab_mode = CAMERA_GRAB_LATEST;
|
||||
} else {
|
||||
// Limit the frame size when PSRAM is not available
|
||||
config.frame_size = FRAMESIZE_SVGA;
|
||||
config.fb_location = CAMERA_FB_IN_DRAM;
|
||||
}
|
||||
} else {
|
||||
config.frame_size = FRAMESIZE_SVGA;
|
||||
config.jpeg_quality = 12;
|
||||
config.fb_count = 1;
|
||||
config.fb_location = CAMERA_FB_IN_DRAM;
|
||||
// Best option for face detection/recognition
|
||||
config.frame_size = FRAMESIZE_240X240;
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
config.fb_count = 2;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CAMERA_MODEL_ESP_EYE)
|
||||
@ -85,14 +111,21 @@ void setup() {
|
||||
s->set_saturation(s, -2); // lower the saturation
|
||||
}
|
||||
// drop down frame size for higher initial frame rate
|
||||
s->set_framesize(s, FRAMESIZE_QVGA);
|
||||
if(config.pixel_format == PIXFORMAT_JPEG){
|
||||
s->set_framesize(s, FRAMESIZE_QVGA);
|
||||
}
|
||||
|
||||
#if defined(CAMERA_MODEL_M5STACK_WIDE) || defined(CAMERA_MODEL_M5STACK_ESP32CAM)
|
||||
s->set_vflip(s, 1);
|
||||
s->set_hmirror(s, 1);
|
||||
#endif
|
||||
|
||||
#if defined(CAMERA_MODEL_ESP32S3_EYE)
|
||||
s->set_vflip(s, 1);
|
||||
#endif
|
||||
|
||||
WiFi.begin(ssid, password);
|
||||
WiFi.setSleep(false);
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
@ -109,6 +142,6 @@ void setup() {
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// put your main code here, to run repeatedly:
|
||||
// Do nothing. Everything is done in another task by the web server
|
||||
delay(10000);
|
||||
}
|
||||
|
@ -28,14 +28,37 @@
|
||||
static const char *TAG = "camera_httpd";
|
||||
#endif
|
||||
|
||||
// Face Detection will not work on boards without (or with disabled) PSRAM
|
||||
#ifdef BOARD_HAS_PSRAM
|
||||
#define CONFIG_ESP_FACE_DETECT_ENABLED 1
|
||||
// Face Recognition takes upward from 15 seconds per frame on chips other than ESP32S3
|
||||
// Makes no sense to have it enabled for them
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
#define CONFIG_ESP_FACE_RECOGNITION_ENABLED 1
|
||||
#else
|
||||
#define CONFIG_ESP_FACE_RECOGNITION_ENABLED 0
|
||||
#endif
|
||||
#else
|
||||
#define CONFIG_ESP_FACE_DETECT_ENABLED 0
|
||||
#define CONFIG_ESP_FACE_RECOGNITION_ENABLED 0
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_FACE_DETECT_ENABLED
|
||||
|
||||
#include "fd_forward.h"
|
||||
#include <vector>
|
||||
#include "human_face_detect_msr01.hpp"
|
||||
#include "human_face_detect_mnp01.hpp"
|
||||
|
||||
#define TWO_STAGE 1 /*<! 1: detect by two-stage which is more accurate but slower(with keypoints). */
|
||||
/*<! 0: detect by one-stage which is less accurate but faster(without keypoints). */
|
||||
|
||||
#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
|
||||
#include "fr_forward.h"
|
||||
#include "face_recognition_tool.hpp"
|
||||
#include "face_recognition_112_v1_s16.hpp"
|
||||
#include "face_recognition_112_v1_s8.hpp"
|
||||
|
||||
#define QUANT_TYPE 0 //if set to 1 => very large firmware, very slow, reboots when streaming...
|
||||
|
||||
#define ENROLL_CONFIRM_TIMES 5
|
||||
#define FACE_ID_SAVE_NUMBER 7
|
||||
#endif
|
||||
|
||||
@ -77,12 +100,24 @@ httpd_handle_t camera_httpd = NULL;
|
||||
|
||||
static int8_t detection_enabled = 0;
|
||||
|
||||
static mtmn_config_t mtmn_config = {0};
|
||||
// #if TWO_STAGE
|
||||
// static HumanFaceDetectMSR01 s1(0.1F, 0.5F, 10, 0.2F);
|
||||
// static HumanFaceDetectMNP01 s2(0.5F, 0.3F, 5);
|
||||
// #else
|
||||
// static HumanFaceDetectMSR01 s1(0.3F, 0.5F, 10, 0.2F);
|
||||
// #endif
|
||||
|
||||
#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
|
||||
static int8_t recognition_enabled = 0;
|
||||
static int8_t is_enrolling = 0;
|
||||
static face_id_list id_list = {0};
|
||||
|
||||
#if QUANT_TYPE
|
||||
// S16 model
|
||||
FaceRecognition112V1S16 recognizer;
|
||||
#else
|
||||
// S8 model
|
||||
FaceRecognition112V1S8 recognizer;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -133,18 +168,12 @@ static int ra_filter_run(ra_filter_t *filter, int value)
|
||||
|
||||
#if CONFIG_ESP_FACE_DETECT_ENABLED
|
||||
#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
|
||||
static void rgb_print(dl_matrix3du_t *image_matrix, uint32_t color, const char *str)
|
||||
static void rgb_print(fb_data_t *fb, uint32_t color, const char *str)
|
||||
{
|
||||
fb_data_t fb;
|
||||
fb.width = image_matrix->w;
|
||||
fb.height = image_matrix->h;
|
||||
fb.data = image_matrix->item;
|
||||
fb.bytes_per_pixel = 3;
|
||||
fb.format = FB_BGR888;
|
||||
fb_gfx_print(&fb, (fb.width - (strlen(str) * 14)) / 2, 10, color, str);
|
||||
fb_gfx_print(fb, (fb->width - (strlen(str) * 14)) / 2, 10, color, str);
|
||||
}
|
||||
|
||||
static int rgb_printf(dl_matrix3du_t *image_matrix, uint32_t color, const char *format, ...)
|
||||
static int rgb_printf(fb_data_t *fb, uint32_t color, const char *format, ...)
|
||||
{
|
||||
char loc_buf[64];
|
||||
char *temp = loc_buf;
|
||||
@ -165,7 +194,7 @@ static int rgb_printf(dl_matrix3du_t *image_matrix, uint32_t color, const char *
|
||||
}
|
||||
vsnprintf(temp, len + 1, format, arg);
|
||||
va_end(arg);
|
||||
rgb_print(image_matrix, color, temp);
|
||||
rgb_print(fb, color, temp);
|
||||
if (len > 64)
|
||||
{
|
||||
free(temp);
|
||||
@ -173,9 +202,9 @@ static int rgb_printf(dl_matrix3du_t *image_matrix, uint32_t color, const char *
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
static void draw_face_boxes(dl_matrix3du_t *image_matrix, box_array_t *boxes, int face_id)
|
||||
static void draw_face_boxes(fb_data_t *fb, std::list<dl::detect::result_t> *results, int face_id)
|
||||
{
|
||||
int x, y, w, h, i;
|
||||
int x, y, w, h;
|
||||
uint32_t color = FACE_COLOR_YELLOW;
|
||||
if (face_id < 0)
|
||||
{
|
||||
@ -185,89 +214,64 @@ static void draw_face_boxes(dl_matrix3du_t *image_matrix, box_array_t *boxes, in
|
||||
{
|
||||
color = FACE_COLOR_GREEN;
|
||||
}
|
||||
fb_data_t fb;
|
||||
fb.width = image_matrix->w;
|
||||
fb.height = image_matrix->h;
|
||||
fb.data = image_matrix->item;
|
||||
fb.bytes_per_pixel = 3;
|
||||
fb.format = FB_BGR888;
|
||||
for (i = 0; i < boxes->len; i++)
|
||||
if(fb->bytes_per_pixel == 2){
|
||||
//color = ((color >> 8) & 0xF800) | ((color >> 3) & 0x07E0) | (color & 0x001F);
|
||||
color = ((color >> 16) & 0x001F) | ((color >> 3) & 0x07E0) | ((color << 8) & 0xF800);
|
||||
}
|
||||
int i = 0;
|
||||
for (std::list<dl::detect::result_t>::iterator prediction = results->begin(); prediction != results->end(); prediction++, i++)
|
||||
{
|
||||
// rectangle box
|
||||
x = (int)boxes->box[i].box_p[0];
|
||||
y = (int)boxes->box[i].box_p[1];
|
||||
w = (int)boxes->box[i].box_p[2] - x + 1;
|
||||
h = (int)boxes->box[i].box_p[3] - y + 1;
|
||||
fb_gfx_drawFastHLine(&fb, x, y, w, color);
|
||||
fb_gfx_drawFastHLine(&fb, x, y + h - 1, w, color);
|
||||
fb_gfx_drawFastVLine(&fb, x, y, h, color);
|
||||
fb_gfx_drawFastVLine(&fb, x + w - 1, y, h, color);
|
||||
#if 0
|
||||
// landmark
|
||||
x = (int)prediction->box[0];
|
||||
y = (int)prediction->box[1];
|
||||
w = (int)prediction->box[2] - x + 1;
|
||||
h = (int)prediction->box[3] - y + 1;
|
||||
if((x + w) > fb->width){
|
||||
w = fb->width - x;
|
||||
}
|
||||
if((y + h) > fb->height){
|
||||
h = fb->height - y;
|
||||
}
|
||||
fb_gfx_drawFastHLine(fb, x, y, w, color);
|
||||
fb_gfx_drawFastHLine(fb, x, y + h - 1, w, color);
|
||||
fb_gfx_drawFastVLine(fb, x, y, h, color);
|
||||
fb_gfx_drawFastVLine(fb, x + w - 1, y, h, color);
|
||||
#if TWO_STAGE
|
||||
// landmarks (left eye, mouth left, nose, right eye, mouth right)
|
||||
int x0, y0, j;
|
||||
for (j = 0; j < 10; j+=2) {
|
||||
x0 = (int)boxes->landmark[i].landmark_p[j];
|
||||
y0 = (int)boxes->landmark[i].landmark_p[j+1];
|
||||
fb_gfx_fillRect(&fb, x0, y0, 3, 3, color);
|
||||
x0 = (int)prediction->keypoint[j];
|
||||
y0 = (int)prediction->keypoint[j+1];
|
||||
fb_gfx_fillRect(fb, x0, y0, 3, 3, color);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
|
||||
static int run_face_recognition(dl_matrix3du_t *image_matrix, box_array_t *net_boxes)
|
||||
static int run_face_recognition(fb_data_t *fb, std::list<dl::detect::result_t> *results)
|
||||
{
|
||||
dl_matrix3du_t *aligned_face = NULL;
|
||||
int matched_id = 0;
|
||||
std::vector<int> landmarks = results->front().keypoint;
|
||||
int id = -1;
|
||||
|
||||
aligned_face = dl_matrix3du_alloc(1, FACE_WIDTH, FACE_HEIGHT, 3);
|
||||
if (!aligned_face)
|
||||
{
|
||||
ESP_LOGE(TAG, "Could not allocate face recognition buffer");
|
||||
return matched_id;
|
||||
}
|
||||
if (align_face(net_boxes, image_matrix, aligned_face) == ESP_OK)
|
||||
{
|
||||
if (is_enrolling == 1)
|
||||
{
|
||||
int8_t left_sample_face = enroll_face(&id_list, aligned_face);
|
||||
Tensor<uint8_t> tensor;
|
||||
tensor.set_element((uint8_t *)fb->data).set_shape({fb->height, fb->width, 3}).set_auto_free(false);
|
||||
|
||||
if (left_sample_face == (ENROLL_CONFIRM_TIMES - 1))
|
||||
{
|
||||
ESP_LOGD(TAG, "Enrolling Face ID: %d", id_list.tail);
|
||||
}
|
||||
ESP_LOGD(TAG, "Enrolling Face ID: %d sample %d", id_list.tail, ENROLL_CONFIRM_TIMES - left_sample_face);
|
||||
rgb_printf(image_matrix, FACE_COLOR_CYAN, "ID[%u] Sample[%u]", id_list.tail, ENROLL_CONFIRM_TIMES - left_sample_face);
|
||||
if (left_sample_face == 0)
|
||||
{
|
||||
is_enrolling = 0;
|
||||
ESP_LOGD(TAG, "Enrolled Face ID: %d", id_list.tail);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
matched_id = recognize_face(&id_list, aligned_face);
|
||||
if (matched_id >= 0)
|
||||
{
|
||||
ESP_LOGW(TAG, "Match Face ID: %u", matched_id);
|
||||
rgb_printf(image_matrix, FACE_COLOR_GREEN, "Hello Subject %u", matched_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGW(TAG, "No Match Found");
|
||||
rgb_print(image_matrix, FACE_COLOR_RED, "Intruder Alert!");
|
||||
matched_id = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGW(TAG, "Face Not Aligned");
|
||||
//rgb_print(image_matrix, FACE_COLOR_YELLOW, "Human Detected");
|
||||
int enrolled_count = recognizer.get_enrolled_id_num();
|
||||
|
||||
if (enrolled_count < FACE_ID_SAVE_NUMBER && is_enrolling){
|
||||
id = recognizer.enroll_id(tensor, landmarks, "", true);
|
||||
ESP_LOGI(TAG, "Enrolled ID: %d", id);
|
||||
rgb_printf(fb, FACE_COLOR_CYAN, "ID[%u]", id);
|
||||
}
|
||||
|
||||
dl_matrix3du_free(aligned_face);
|
||||
return matched_id;
|
||||
face_info_t recognize = recognizer.recognize(tensor, landmarks);
|
||||
if(recognize.id >= 0){
|
||||
rgb_printf(fb, FACE_COLOR_GREEN, "ID[%u]: %.2f", recognize.id, recognize.similarity);
|
||||
} else {
|
||||
rgb_print(fb, FACE_COLOR_RED, "Intruder Alert!");
|
||||
}
|
||||
return recognize.id;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@ -398,55 +402,88 @@ static esp_err_t capture_handler(httpd_req_t *req)
|
||||
#if CONFIG_ESP_FACE_DETECT_ENABLED
|
||||
}
|
||||
|
||||
dl_matrix3du_t *image_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3);
|
||||
if (!image_matrix)
|
||||
{
|
||||
esp_camera_fb_return(fb);
|
||||
ESP_LOGE(TAG, "dl_matrix3du_alloc failed");
|
||||
httpd_resp_send_500(req);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
out_buf = image_matrix->item;
|
||||
out_len = fb->width * fb->height * 3;
|
||||
out_width = fb->width;
|
||||
out_height = fb->height;
|
||||
|
||||
s = fmt2rgb888(fb->buf, fb->len, fb->format, out_buf);
|
||||
esp_camera_fb_return(fb);
|
||||
if (!s)
|
||||
{
|
||||
dl_matrix3du_free(image_matrix);
|
||||
ESP_LOGE(TAG, "to rgb888 failed");
|
||||
httpd_resp_send_500(req);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
box_array_t *net_boxes = face_detect(image_matrix, &mtmn_config);
|
||||
|
||||
if (net_boxes)
|
||||
{
|
||||
detected = true;
|
||||
#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
|
||||
if (recognition_enabled)
|
||||
{
|
||||
face_id = run_face_recognition(image_matrix, net_boxes);
|
||||
}
|
||||
#endif
|
||||
draw_face_boxes(image_matrix, net_boxes, face_id);
|
||||
dl_lib_free(net_boxes->score);
|
||||
dl_lib_free(net_boxes->box);
|
||||
if (net_boxes->landmark != NULL)
|
||||
dl_lib_free(net_boxes->landmark);
|
||||
dl_lib_free(net_boxes);
|
||||
}
|
||||
|
||||
jpg_chunking_t jchunk = {req, 0};
|
||||
s = fmt2jpg_cb(out_buf, out_len, out_width, out_height, PIXFORMAT_RGB888, 90, jpg_encode_stream, &jchunk);
|
||||
dl_matrix3du_free(image_matrix);
|
||||
if (!s)
|
||||
|
||||
if (fb->format == PIXFORMAT_RGB565
|
||||
#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
|
||||
&& !recognition_enabled
|
||||
#endif
|
||||
){
|
||||
#if TWO_STAGE
|
||||
HumanFaceDetectMSR01 s1(0.1F, 0.5F, 10, 0.2F);
|
||||
HumanFaceDetectMNP01 s2(0.5F, 0.3F, 5);
|
||||
std::list<dl::detect::result_t> &candidates = s1.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3});
|
||||
std::list<dl::detect::result_t> &results = s2.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3}, candidates);
|
||||
#else
|
||||
HumanFaceDetectMSR01 s1(0.3F, 0.5F, 10, 0.2F);
|
||||
std::list<dl::detect::result_t> &results = s1.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3});
|
||||
#endif
|
||||
if (results.size() > 0) {
|
||||
fb_data_t rfb;
|
||||
rfb.width = fb->width;
|
||||
rfb.height = fb->height;
|
||||
rfb.data = fb->buf;
|
||||
rfb.bytes_per_pixel = 2;
|
||||
rfb.format = FB_RGB565;
|
||||
detected = true;
|
||||
draw_face_boxes(&rfb, &results, face_id);
|
||||
}
|
||||
s = fmt2jpg_cb(fb->buf, fb->len, fb->width, fb->height, PIXFORMAT_RGB565, 90, jpg_encode_stream, &jchunk);
|
||||
esp_camera_fb_return(fb);
|
||||
} else
|
||||
{
|
||||
out_len = fb->width * fb->height * 3;
|
||||
out_width = fb->width;
|
||||
out_height = fb->height;
|
||||
out_buf = (uint8_t*)malloc(out_len);
|
||||
if (!out_buf) {
|
||||
ESP_LOGE(TAG, "out_buf malloc failed");
|
||||
httpd_resp_send_500(req);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
s = fmt2rgb888(fb->buf, fb->len, fb->format, out_buf);
|
||||
esp_camera_fb_return(fb);
|
||||
if (!s) {
|
||||
free(out_buf);
|
||||
ESP_LOGE(TAG, "to rgb888 failed");
|
||||
httpd_resp_send_500(req);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
fb_data_t rfb;
|
||||
rfb.width = out_width;
|
||||
rfb.height = out_height;
|
||||
rfb.data = out_buf;
|
||||
rfb.bytes_per_pixel = 3;
|
||||
rfb.format = FB_BGR888;
|
||||
|
||||
#if TWO_STAGE
|
||||
HumanFaceDetectMSR01 s1(0.1F, 0.5F, 10, 0.2F);
|
||||
HumanFaceDetectMNP01 s2(0.5F, 0.3F, 5);
|
||||
std::list<dl::detect::result_t> &candidates = s1.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3});
|
||||
std::list<dl::detect::result_t> &results = s2.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3}, candidates);
|
||||
#else
|
||||
HumanFaceDetectMSR01 s1(0.3F, 0.5F, 10, 0.2F);
|
||||
std::list<dl::detect::result_t> &results = s1.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3});
|
||||
#endif
|
||||
|
||||
if (results.size() > 0) {
|
||||
detected = true;
|
||||
#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
|
||||
if (recognition_enabled) {
|
||||
face_id = run_face_recognition(&rfb, &results);
|
||||
}
|
||||
#endif
|
||||
draw_face_boxes(&rfb, &results, face_id);
|
||||
}
|
||||
|
||||
s = fmt2jpg_cb(out_buf, out_len, out_width, out_height, PIXFORMAT_RGB888, 90, jpg_encode_stream, &jchunk);
|
||||
free(out_buf);
|
||||
}
|
||||
|
||||
if (!s) {
|
||||
ESP_LOGE(TAG, "JPEG compression failed");
|
||||
httpd_resp_send_500(req);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
@ -465,7 +502,6 @@ static esp_err_t stream_handler(httpd_req_t *req)
|
||||
uint8_t *_jpg_buf = NULL;
|
||||
char *part_buf[128];
|
||||
#if CONFIG_ESP_FACE_DETECT_ENABLED
|
||||
dl_matrix3du_t *image_matrix = NULL;
|
||||
bool detected = false;
|
||||
int face_id = 0;
|
||||
int64_t fr_start = 0;
|
||||
@ -473,6 +509,16 @@ static esp_err_t stream_handler(httpd_req_t *req)
|
||||
int64_t fr_face = 0;
|
||||
int64_t fr_recognize = 0;
|
||||
int64_t fr_encode = 0;
|
||||
|
||||
size_t out_len = 0, out_width = 0, out_height = 0;
|
||||
uint8_t *out_buf = NULL;
|
||||
bool s = false;
|
||||
#if TWO_STAGE
|
||||
HumanFaceDetectMSR01 s1(0.1F, 0.5F, 10, 0.2F);
|
||||
HumanFaceDetectMNP01 s2(0.5F, 0.3F, 5);
|
||||
#else
|
||||
HumanFaceDetectMSR01 s1(0.3F, 0.5F, 10, 0.2F);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int64_t last_frame = 0;
|
||||
@ -541,65 +587,94 @@ static esp_err_t stream_handler(httpd_req_t *req)
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
image_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3);
|
||||
|
||||
if (!image_matrix)
|
||||
{
|
||||
ESP_LOGE(TAG, "dl_matrix3du_alloc failed");
|
||||
res = ESP_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!fmt2rgb888(fb->buf, fb->len, fb->format, image_matrix->item))
|
||||
{
|
||||
ESP_LOGE(TAG, "fmt2rgb888 failed");
|
||||
if (fb->format == PIXFORMAT_RGB565
|
||||
#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
|
||||
&& !recognition_enabled
|
||||
#endif
|
||||
){
|
||||
fr_ready = esp_timer_get_time();
|
||||
#if TWO_STAGE
|
||||
std::list<dl::detect::result_t> &candidates = s1.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3});
|
||||
std::list<dl::detect::result_t> &results = s2.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3}, candidates);
|
||||
#else
|
||||
std::list<dl::detect::result_t> &results = s1.infer((uint16_t *)fb->buf, {(int)fb->height, (int)fb->width, 3});
|
||||
#endif
|
||||
fr_face = esp_timer_get_time();
|
||||
fr_recognize = fr_face;
|
||||
if (results.size() > 0) {
|
||||
fb_data_t rfb;
|
||||
rfb.width = fb->width;
|
||||
rfb.height = fb->height;
|
||||
rfb.data = fb->buf;
|
||||
rfb.bytes_per_pixel = 2;
|
||||
rfb.format = FB_RGB565;
|
||||
detected = true;
|
||||
draw_face_boxes(&rfb, &results, face_id);
|
||||
}
|
||||
s = fmt2jpg(fb->buf, fb->len, fb->width, fb->height, PIXFORMAT_RGB565, 80, &_jpg_buf, &_jpg_buf_len);
|
||||
esp_camera_fb_return(fb);
|
||||
fb = NULL;
|
||||
if (!s) {
|
||||
ESP_LOGE(TAG, "fmt2jpg failed");
|
||||
res = ESP_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
fr_ready = esp_timer_get_time();
|
||||
box_array_t *net_boxes = NULL;
|
||||
if (detection_enabled)
|
||||
{
|
||||
net_boxes = face_detect(image_matrix, &mtmn_config);
|
||||
}
|
||||
fr_face = esp_timer_get_time();
|
||||
fr_recognize = fr_face;
|
||||
if (net_boxes || fb->format != PIXFORMAT_JPEG)
|
||||
{
|
||||
if (net_boxes)
|
||||
{
|
||||
fr_encode = esp_timer_get_time();
|
||||
} else
|
||||
{
|
||||
out_len = fb->width * fb->height * 3;
|
||||
out_width = fb->width;
|
||||
out_height = fb->height;
|
||||
out_buf = (uint8_t*)malloc(out_len);
|
||||
if (!out_buf) {
|
||||
ESP_LOGE(TAG, "out_buf malloc failed");
|
||||
res = ESP_FAIL;
|
||||
} else {
|
||||
s = fmt2rgb888(fb->buf, fb->len, fb->format, out_buf);
|
||||
esp_camera_fb_return(fb);
|
||||
fb = NULL;
|
||||
if (!s) {
|
||||
free(out_buf);
|
||||
ESP_LOGE(TAG, "to rgb888 failed");
|
||||
res = ESP_FAIL;
|
||||
} else {
|
||||
fr_ready = esp_timer_get_time();
|
||||
|
||||
fb_data_t rfb;
|
||||
rfb.width = out_width;
|
||||
rfb.height = out_height;
|
||||
rfb.data = out_buf;
|
||||
rfb.bytes_per_pixel = 3;
|
||||
rfb.format = FB_BGR888;
|
||||
|
||||
#if TWO_STAGE
|
||||
std::list<dl::detect::result_t> &candidates = s1.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3});
|
||||
std::list<dl::detect::result_t> &results = s2.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3}, candidates);
|
||||
#else
|
||||
std::list<dl::detect::result_t> &results = s1.infer((uint8_t *)out_buf, {(int)out_height, (int)out_width, 3});
|
||||
#endif
|
||||
|
||||
fr_face = esp_timer_get_time();
|
||||
fr_recognize = fr_face;
|
||||
|
||||
if (results.size() > 0) {
|
||||
detected = true;
|
||||
#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
|
||||
if (recognition_enabled)
|
||||
{
|
||||
face_id = run_face_recognition(image_matrix, net_boxes);
|
||||
if (recognition_enabled) {
|
||||
face_id = run_face_recognition(&rfb, &results);
|
||||
fr_recognize = esp_timer_get_time();
|
||||
}
|
||||
fr_recognize = esp_timer_get_time();
|
||||
#endif
|
||||
draw_face_boxes(image_matrix, net_boxes, face_id);
|
||||
dl_lib_free(net_boxes->score);
|
||||
dl_lib_free(net_boxes->box);
|
||||
if (net_boxes->landmark != NULL)
|
||||
dl_lib_free(net_boxes->landmark);
|
||||
dl_lib_free(net_boxes);
|
||||
draw_face_boxes(&rfb, &results, face_id);
|
||||
}
|
||||
if (!fmt2jpg(image_matrix->item, fb->width * fb->height * 3, fb->width, fb->height, PIXFORMAT_RGB888, 90, &_jpg_buf, &_jpg_buf_len))
|
||||
{
|
||||
s = fmt2jpg(out_buf, out_len, out_width, out_height, PIXFORMAT_RGB888, 90, &_jpg_buf, &_jpg_buf_len);
|
||||
free(out_buf);
|
||||
if (!s) {
|
||||
ESP_LOGE(TAG, "fmt2jpg failed");
|
||||
res = ESP_FAIL;
|
||||
}
|
||||
esp_camera_fb_return(fb);
|
||||
fb = NULL;
|
||||
fr_encode = esp_timer_get_time();
|
||||
}
|
||||
else
|
||||
{
|
||||
_jpg_buf = fb->buf;
|
||||
_jpg_buf_len = fb->len;
|
||||
}
|
||||
fr_encode = esp_timer_get_time();
|
||||
}
|
||||
dl_matrix3du_free(image_matrix);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -630,6 +705,7 @@ static esp_err_t stream_handler(httpd_req_t *req)
|
||||
}
|
||||
if (res != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "send frame failed failed");
|
||||
break;
|
||||
}
|
||||
int64_t fr_end = esp_timer_get_time();
|
||||
@ -784,8 +860,10 @@ static esp_err_t cmd_handler(httpd_req_t *req)
|
||||
#endif
|
||||
}
|
||||
#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
|
||||
else if (!strcmp(variable, "face_enroll"))
|
||||
is_enrolling = val;
|
||||
else if (!strcmp(variable, "face_enroll")){
|
||||
is_enrolling = !is_enrolling;
|
||||
ESP_LOGI(TAG, "Enrolling: %s", is_enrolling?"true":"false");
|
||||
}
|
||||
else if (!strcmp(variable, "face_recognize")) {
|
||||
recognition_enabled = val;
|
||||
if (recognition_enabled) {
|
||||
@ -1150,26 +1228,11 @@ void startCameraServer()
|
||||
|
||||
ra_filter_init(&ra_filter, 20);
|
||||
|
||||
#if CONFIG_ESP_FACE_DETECT_ENABLED
|
||||
|
||||
mtmn_config.type = FAST;
|
||||
mtmn_config.min_face = 80;
|
||||
mtmn_config.pyramid = 0.707;
|
||||
mtmn_config.pyramid_times = 4;
|
||||
mtmn_config.p_threshold.score = 0.6;
|
||||
mtmn_config.p_threshold.nms = 0.7;
|
||||
mtmn_config.p_threshold.candidate_number = 20;
|
||||
mtmn_config.r_threshold.score = 0.7;
|
||||
mtmn_config.r_threshold.nms = 0.7;
|
||||
mtmn_config.r_threshold.candidate_number = 10;
|
||||
mtmn_config.o_threshold.score = 0.7;
|
||||
mtmn_config.o_threshold.nms = 0.7;
|
||||
mtmn_config.o_threshold.candidate_number = 1;
|
||||
|
||||
#if CONFIG_ESP_FACE_RECOGNITION_ENABLED
|
||||
face_id_init(&id_list, FACE_ID_SAVE_NUMBER, ENROLL_CONFIRM_TIMES);
|
||||
#endif
|
||||
recognizer.set_partition(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "fr");
|
||||
|
||||
// load ids from flash partition
|
||||
recognizer.set_ids_from_flash();
|
||||
#endif
|
||||
ESP_LOGI(TAG, "Starting web server on port: '%d'", config.server_port);
|
||||
if (httpd_start(&camera_httpd, &config) == ESP_OK)
|
||||
|
@ -170,6 +170,104 @@
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP32_CAM_BOARD)
|
||||
// The 18 pin header on the board has Y5 and Y3 swapped
|
||||
#define USE_BOARD_HEADER 0
|
||||
#define PWDN_GPIO_NUM 32
|
||||
#define RESET_GPIO_NUM 33
|
||||
#define XCLK_GPIO_NUM 4
|
||||
#define SIOD_GPIO_NUM 18
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 36
|
||||
#define Y8_GPIO_NUM 19
|
||||
#define Y7_GPIO_NUM 21
|
||||
#define Y6_GPIO_NUM 39
|
||||
#if USE_BOARD_HEADER
|
||||
#define Y5_GPIO_NUM 13
|
||||
#else
|
||||
#define Y5_GPIO_NUM 35
|
||||
#endif
|
||||
#define Y4_GPIO_NUM 14
|
||||
#if USE_BOARD_HEADER
|
||||
#define Y3_GPIO_NUM 35
|
||||
#else
|
||||
#define Y3_GPIO_NUM 13
|
||||
#endif
|
||||
#define Y2_GPIO_NUM 34
|
||||
#define VSYNC_GPIO_NUM 5
|
||||
#define HREF_GPIO_NUM 27
|
||||
#define PCLK_GPIO_NUM 25
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP32S3_CAM_LCD)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 40
|
||||
#define SIOD_GPIO_NUM 17
|
||||
#define SIOC_GPIO_NUM 18
|
||||
|
||||
#define Y9_GPIO_NUM 39
|
||||
#define Y8_GPIO_NUM 41
|
||||
#define Y7_GPIO_NUM 42
|
||||
#define Y6_GPIO_NUM 12
|
||||
#define Y5_GPIO_NUM 3
|
||||
#define Y4_GPIO_NUM 14
|
||||
#define Y3_GPIO_NUM 47
|
||||
#define Y2_GPIO_NUM 13
|
||||
#define VSYNC_GPIO_NUM 21
|
||||
#define HREF_GPIO_NUM 38
|
||||
#define PCLK_GPIO_NUM 11
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP32S2_CAM_BOARD)
|
||||
// The 18 pin header on the board has Y5 and Y3 swapped
|
||||
#define USE_BOARD_HEADER 0
|
||||
#define PWDN_GPIO_NUM 1
|
||||
#define RESET_GPIO_NUM 2
|
||||
#define XCLK_GPIO_NUM 42
|
||||
#define SIOD_GPIO_NUM 41
|
||||
#define SIOC_GPIO_NUM 18
|
||||
|
||||
#define Y9_GPIO_NUM 16
|
||||
#define Y8_GPIO_NUM 39
|
||||
#define Y7_GPIO_NUM 40
|
||||
#define Y6_GPIO_NUM 15
|
||||
#if USE_BOARD_HEADER
|
||||
#define Y5_GPIO_NUM 12
|
||||
#else
|
||||
#define Y5_GPIO_NUM 13
|
||||
#endif
|
||||
#define Y4_GPIO_NUM 5
|
||||
#if USE_BOARD_HEADER
|
||||
#define Y3_GPIO_NUM 13
|
||||
#else
|
||||
#define Y3_GPIO_NUM 12
|
||||
#endif
|
||||
#define Y2_GPIO_NUM 14
|
||||
#define VSYNC_GPIO_NUM 38
|
||||
#define HREF_GPIO_NUM 4
|
||||
#define PCLK_GPIO_NUM 3
|
||||
|
||||
#elif defined(CAMERA_MODEL_ESP32S3_EYE)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 15
|
||||
#define SIOD_GPIO_NUM 4
|
||||
#define SIOC_GPIO_NUM 5
|
||||
|
||||
#define Y2_GPIO_NUM 11
|
||||
#define Y3_GPIO_NUM 9
|
||||
#define Y4_GPIO_NUM 8
|
||||
#define Y5_GPIO_NUM 10
|
||||
#define Y6_GPIO_NUM 12
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y8_GPIO_NUM 17
|
||||
#define Y9_GPIO_NUM 16
|
||||
|
||||
#define VSYNC_GPIO_NUM 6
|
||||
#define HREF_GPIO_NUM 7
|
||||
#define PCLK_GPIO_NUM 13
|
||||
|
||||
#else
|
||||
#error "Camera model not selected"
|
||||
#endif
|
||||
|
@ -0,0 +1,5 @@
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x5000,
|
||||
otadata, data, ota, 0xe000, 0x2000,
|
||||
app0, app, ota_0, 0x10000, 0x3d0000,
|
||||
fr, data, , 0x3e0000, 0x20000,
|
|
@ -123,7 +123,7 @@ static esp_err_t on_lowlevel_init_done(esp_eth_handle_t eth_handle){
|
||||
//gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_EMAC_TX_CLK);
|
||||
//PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[0]);
|
||||
pinMode(0, INPUT);
|
||||
pinMode(0, FUNCTION_6);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[0], 5);
|
||||
EMAC_EXT.ex_clk_ctrl.ext_en = 1;
|
||||
EMAC_EXT.ex_clk_ctrl.int_en = 0;
|
||||
EMAC_EXT.ex_oscclk_conf.clk_sel = 1;
|
||||
@ -135,7 +135,7 @@ static esp_err_t on_lowlevel_init_done(esp_eth_handle_t eth_handle){
|
||||
//gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
|
||||
//PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[0]);
|
||||
pinMode(0, OUTPUT);
|
||||
pinMode(0, FUNCTION_2);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[0], 1);
|
||||
// Choose the APLL clock to output on GPIO
|
||||
REG_WRITE(PIN_CTRL, 6);
|
||||
#endif
|
||||
@ -145,7 +145,7 @@ static esp_err_t on_lowlevel_init_done(esp_eth_handle_t eth_handle){
|
||||
//gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO16_U, FUNC_GPIO16_EMAC_CLK_OUT);
|
||||
//PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[16]);
|
||||
pinMode(16, OUTPUT);
|
||||
pinMode(16, FUNCTION_6);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[16], 5);
|
||||
#endif
|
||||
} else if(eth_clock_mode == ETH_CLOCK_GPIO17_OUT){
|
||||
#if CONFIG_ETH_RMII_CLK_OUT_GPIO != 17
|
||||
@ -153,7 +153,7 @@ static esp_err_t on_lowlevel_init_done(esp_eth_handle_t eth_handle){
|
||||
//gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO17_U, FUNC_GPIO17_EMAC_CLK_OUT_180);
|
||||
//PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[17]);
|
||||
pinMode(17, OUTPUT);
|
||||
pinMode(17, FUNCTION_6);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[17], 5);
|
||||
#endif
|
||||
}
|
||||
#if CONFIG_ETH_RMII_CLK_INPUT
|
||||
|
@ -130,6 +130,15 @@ size_t File::size() const
|
||||
return _p->size();
|
||||
}
|
||||
|
||||
bool File::setBufferSize(size_t size)
|
||||
{
|
||||
if (!*this) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _p->setBufferSize(size);
|
||||
}
|
||||
|
||||
void File::close()
|
||||
{
|
||||
if (_p) {
|
||||
|
@ -70,6 +70,7 @@ public:
|
||||
}
|
||||
size_t position() const;
|
||||
size_t size() const;
|
||||
bool setBufferSize(size_t size);
|
||||
void close();
|
||||
operator bool() const;
|
||||
time_t getLastWrite();
|
||||
|
@ -36,6 +36,7 @@ public:
|
||||
virtual bool seek(uint32_t pos, SeekMode mode) = 0;
|
||||
virtual size_t position() const = 0;
|
||||
virtual size_t size() const = 0;
|
||||
virtual bool setBufferSize(size_t size) = 0;
|
||||
virtual void close() = 0;
|
||||
virtual time_t getLastWrite() = 0;
|
||||
virtual const char* path() const = 0;
|
||||
|
@ -13,11 +13,10 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include "vfs_api.h"
|
||||
#include <stdio_ext.h>
|
||||
|
||||
using namespace fs;
|
||||
|
||||
#define READ_SIZE_SWITCH 128 //swithc to read func when read size > 128bytes
|
||||
#define DEFAULT_FILE_BUFFER_SIZE 4096
|
||||
|
||||
FileImplPtr VFSImpl::open(const char* fpath, const char* mode, const bool create)
|
||||
{
|
||||
@ -283,6 +282,10 @@ VFSFileImpl::VFSFileImpl(VFSImpl* fs, const char* fpath, const char* mode)
|
||||
if(!_f) {
|
||||
log_e("fopen(%s) failed", temp);
|
||||
}
|
||||
if(_f && (_stat.st_blksize == 0))
|
||||
{
|
||||
setvbuf(_f,NULL,_IOFBF,DEFAULT_FILE_BUFFER_SIZE);
|
||||
}
|
||||
} else if(S_ISDIR(_stat.st_mode)) {
|
||||
_isDirectory = true;
|
||||
_d = opendir(temp);
|
||||
@ -310,6 +313,10 @@ VFSFileImpl::VFSFileImpl(VFSImpl* fs, const char* fpath, const char* mode)
|
||||
if(!_f) {
|
||||
log_e("fopen(%s) failed", temp);
|
||||
}
|
||||
if(_f && (_stat.st_blksize == 0))
|
||||
{
|
||||
setvbuf(_f,NULL,_IOFBF,DEFAULT_FILE_BUFFER_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(temp);
|
||||
@ -377,28 +384,7 @@ size_t VFSFileImpl::read(uint8_t* buf, size_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//ERASE BYTEBUFFER and use read when size > READ_SIZE_SWITCH always
|
||||
if(size > READ_SIZE_SWITCH)
|
||||
{
|
||||
//check some data in buffer exists –> clear buffer and move pointer to deleted data
|
||||
size_t bytesinbuf = __fpending(_f);
|
||||
if (bytesinbuf && (bytesinbuf != 128)) //buffer lenght is 128 bytes
|
||||
{
|
||||
fpurge(_f);
|
||||
lseek(fileno(_f),(-128+bytesinbuf),SEEK_CUR);
|
||||
}
|
||||
|
||||
int res = ::read(fileno(_f), buf, size);
|
||||
if (res < 0) {
|
||||
// an error occurred
|
||||
return 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
return fread(buf, 1, size, _f);
|
||||
}
|
||||
return fread(buf, 1, size, _f);
|
||||
}
|
||||
|
||||
void VFSFileImpl::flush()
|
||||
@ -439,6 +425,19 @@ size_t VFSFileImpl::size() const
|
||||
return _stat.st_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Change size of files internal buffer used for read / write operations.
|
||||
* Need to be called right after opening file before any other operation!
|
||||
*/
|
||||
bool VFSFileImpl::setBufferSize(size_t size)
|
||||
{
|
||||
if(_isDirectory || !_f) {
|
||||
return 0;
|
||||
}
|
||||
int res = setvbuf(_f,NULL,_IOFBF,size);
|
||||
return res == 0;
|
||||
}
|
||||
|
||||
const char* VFSFileImpl::path() const
|
||||
{
|
||||
return (const char*) _path;
|
||||
|
@ -65,10 +65,11 @@ public:
|
||||
bool seek(uint32_t pos, SeekMode mode) override;
|
||||
size_t position() const override;
|
||||
size_t size() const override;
|
||||
bool setBufferSize(size_t size);
|
||||
void close() override;
|
||||
const char* path() const override;
|
||||
const char* name() const override;
|
||||
time_t getLastWrite() override;
|
||||
time_t getLastWrite() override;
|
||||
boolean isDirectory(void) override;
|
||||
FileImplPtr openNextFile(const char* mode) override;
|
||||
void rewindDirectory(void) override;
|
||||
|
@ -276,7 +276,7 @@ protected:
|
||||
/// request handling
|
||||
String _host;
|
||||
uint16_t _port = 0;
|
||||
int32_t _connectTimeout = -1;
|
||||
int32_t _connectTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT;
|
||||
bool _reuse = true;
|
||||
uint16_t _tcpTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT;
|
||||
bool _useHTTP10 = false;
|
||||
|
@ -16,17 +16,6 @@ framework = arduino
|
||||
|
||||
[env:esp32]
|
||||
platform = espressif32
|
||||
;platform = https://github.com/platformio/platform-espressif32.git
|
||||
;board_build.mcu = esp32
|
||||
platform_packages = framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git
|
||||
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-D=${PIOENV}
|
||||
;-D CONFIG_LITTLEFS_FOR_IDF_3_2
|
||||
|
||||
lib_deps = https://github.com/lorol/LITTLEFS.git
|
||||
|
||||
board = esp32dev
|
||||
;board_build.partitions = partitions_custom.csv
|
||||
monitor_filters = esp32_exception_decoder
|
||||
|
@ -1,10 +1,13 @@
|
||||
# ESP RainMaker Examples
|
||||
|
||||
While building any examples for ESP RainMaker, take care of the following:
|
||||
|
||||
1. Change partition scheme in Arduino IDE to RainMaker (Tools -> Partition Scheme -> RainMaker).
|
||||
2. Once ESP RainMaker gets started, compulsorily call `WiFi.beginProvision()` which is responsible for user-node mapping.
|
||||
3. Use appropriate provisioning scheme as per the board.
|
||||
3. Use the appropriate provisioning scheme as per the board.
|
||||
- ESP32 Board: BLE Provisioning
|
||||
- ESP32S2 Board: SoftAP Provisioning
|
||||
4. Set debug level to Info (Tools -> Core Debug Level -> Info). This is recommended, but not mandatory.
|
||||
- ESP32-C3 Board: BLE Provisioning
|
||||
- ESP32-S3 Board: BLE Provisioning
|
||||
- ESP32-S2 Board: SoftAP Provisioning
|
||||
4. Set debug level to Info (Tools -> Core Debug Level -> Info). This is recommended debug level but not mandatory to run RainMaker.
|
||||
|
||||
|
@ -9,10 +9,15 @@ const char *service_name = "PROV_1234";
|
||||
const char *pop = "abcd1234";
|
||||
|
||||
//GPIO for push button
|
||||
static int gpio_0 = 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
static int gpio_0 = 9;
|
||||
static int gpio_dimmer = 7;
|
||||
#else
|
||||
//GPIO for virtual device
|
||||
static int gpio_0 = 0;
|
||||
static int gpio_dimmer = 16;
|
||||
/* Variable for reading pin status*/
|
||||
#endif
|
||||
|
||||
bool dimmer_state = true;
|
||||
|
||||
// The framework provides some standard device types like switch, lightbulb, fan, temperature sensor.
|
||||
@ -23,12 +28,12 @@ void sysProvEvent(arduino_event_t *sys_event)
|
||||
{
|
||||
switch (sys_event->event_id) {
|
||||
case ARDUINO_EVENT_PROV_START:
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on BLE\n", service_name, pop);
|
||||
printQR(service_name, pop, "ble");
|
||||
#else
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on SoftAP\n", service_name, pop);
|
||||
printQR(service_name, pop, "softap");
|
||||
#else
|
||||
Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on BLE\n", service_name, pop);
|
||||
printQR(service_name, pop, "ble");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@ -89,10 +94,10 @@ void setup()
|
||||
RMaker.start();
|
||||
|
||||
WiFi.onEvent(sysProvEvent);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, pop, service_name);
|
||||
#else
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
WiFiProv.beginProvision(WIFI_PROV_SCHEME_SOFTAP, WIFI_PROV_SCHEME_HANDLER_NONE, WIFI_PROV_SECURITY_1, pop, service_name);
|
||||
#else
|
||||
WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, pop, service_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -8,9 +8,15 @@ const char *service_name = "PROV_1234";
|
||||
const char *pop = "abcd1234";
|
||||
|
||||
//GPIO for push button
|
||||
static int gpio_0 = 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
static int gpio_0 = 9;
|
||||
static int gpio_switch = 7;
|
||||
#else
|
||||
//GPIO for virtual device
|
||||
static int gpio_0 = 0;
|
||||
static int gpio_switch = 16;
|
||||
#endif
|
||||
|
||||
/* Variable for reading pin status*/
|
||||
bool switch_state = true;
|
||||
|
||||
@ -21,12 +27,12 @@ void sysProvEvent(arduino_event_t *sys_event)
|
||||
{
|
||||
switch (sys_event->event_id) {
|
||||
case ARDUINO_EVENT_PROV_START:
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on BLE\n", service_name, pop);
|
||||
printQR(service_name, pop, "ble");
|
||||
#else
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on SoftAP\n", service_name, pop);
|
||||
printQR(service_name, pop, "softap");
|
||||
#else
|
||||
Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on BLE\n", service_name, pop);
|
||||
printQR(service_name, pop, "ble");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@ -74,10 +80,10 @@ void setup()
|
||||
RMaker.start();
|
||||
|
||||
WiFi.onEvent(sysProvEvent);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, pop, service_name);
|
||||
#else
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
WiFiProv.beginProvision(WIFI_PROV_SCHEME_SOFTAP, WIFI_PROV_SCHEME_HANDLER_NONE, WIFI_PROV_SECURITY_1, pop, service_name);
|
||||
#else
|
||||
WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, pop, service_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -58,5 +58,6 @@ void Ticker::detach() {
|
||||
}
|
||||
|
||||
bool Ticker::active() {
|
||||
if (!_timer) return false;
|
||||
return esp_timer_is_active(_timer);
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
#ifndef HTPSPOTUADATE_H
|
||||
#define HTPSPOTUADATE_H
|
||||
#include "esp_http_client.h"
|
||||
#define HttpEvent_t esp_http_client_event_t
|
||||
|
||||
@ -19,3 +21,4 @@ class HttpsOTAUpdateClass {
|
||||
};
|
||||
|
||||
extern HttpsOTAUpdateClass HttpsOTA;
|
||||
#endif
|
||||
|
@ -375,7 +375,7 @@
|
||||
|
||||
function createTreeLeaf(path, name, size){
|
||||
var leaf = document.createElement("li");
|
||||
leaf.id = (((path == "/")?"":path)+"/"+name).toLowerCase();
|
||||
leaf.id = name.toLowerCase();
|
||||
var label = document.createElement("span");
|
||||
label.textContent = name.toLowerCase();
|
||||
leaf.appendChild(label);
|
||||
@ -398,7 +398,7 @@
|
||||
var leaf = document.createElement("li");
|
||||
var check = document.createElement("input");
|
||||
check.type = "checkbox";
|
||||
check.id = (((path == "/")?"":path)+"/"+name).toLowerCase();
|
||||
check.id = name.toLowerCase();
|
||||
if(typeof disabled !== "undefined" && disabled) check.disabled = "disabled";
|
||||
leaf.appendChild(check);
|
||||
var label = document.createElement("label");
|
||||
|
@ -175,11 +175,11 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
WiFiClient::WiFiClient():_connected(false),next(NULL)
|
||||
WiFiClient::WiFiClient():_connected(false),_timeout(WIFI_CLIENT_DEF_CONN_TIMEOUT_MS),next(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
WiFiClient::WiFiClient(int fd):_connected(true),next(NULL)
|
||||
WiFiClient::WiFiClient(int fd):_connected(true),_timeout(WIFI_CLIENT_DEF_CONN_TIMEOUT_MS),next(NULL)
|
||||
{
|
||||
clientSocketHandle.reset(new WiFiClientSocketHandle(fd));
|
||||
_rxBuffer.reset(new WiFiClientRxBuffer(fd));
|
||||
@ -208,10 +208,11 @@ void WiFiClient::stop()
|
||||
|
||||
int WiFiClient::connect(IPAddress ip, uint16_t port)
|
||||
{
|
||||
return connect(ip,port,WIFI_CLIENT_DEF_CONN_TIMEOUT_MS);
|
||||
}
|
||||
int WiFiClient::connect(IPAddress ip, uint16_t port, int32_t timeout )
|
||||
return connect(ip,port,_timeout);
|
||||
}
|
||||
int WiFiClient::connect(IPAddress ip, uint16_t port, int32_t timeout)
|
||||
{
|
||||
_timeout = timeout;
|
||||
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfd < 0) {
|
||||
log_e("socket: %d", errno);
|
||||
@ -229,8 +230,8 @@ int WiFiClient::connect(IPAddress ip, uint16_t port)
|
||||
struct timeval tv;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(sockfd, &fdset);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = timeout * 1000;
|
||||
tv.tv_sec = _timeout / 1000;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
#ifdef ESP_IDF_VERSION_MAJOR
|
||||
int res = lwip_connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
|
||||
@ -243,13 +244,13 @@ int WiFiClient::connect(IPAddress ip, uint16_t port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
res = select(sockfd + 1, nullptr, &fdset, nullptr, timeout<0 ? nullptr : &tv);
|
||||
res = select(sockfd + 1, nullptr, &fdset, nullptr, _timeout<0 ? nullptr : &tv);
|
||||
if (res < 0) {
|
||||
log_e("select on fd %d, errno: %d, \"%s\"", sockfd, errno, strerror(errno));
|
||||
close(sockfd);
|
||||
return 0;
|
||||
} else if (res == 0) {
|
||||
log_i("select returned due to timeout %d ms for fd %d", timeout, sockfd);
|
||||
log_i("select returned due to timeout %d ms for fd %d", _timeout, sockfd);
|
||||
close(sockfd);
|
||||
return 0;
|
||||
} else {
|
||||
@ -270,18 +271,28 @@ int WiFiClient::connect(IPAddress ip, uint16_t port)
|
||||
}
|
||||
}
|
||||
|
||||
#define ROE_WIFICLIENT(x,msg) { if (((x)<0)) { log_e("Setsockopt '" msg "'' on fd %d failed. errno: %d, \"%s\"", sockfd, errno, strerror(errno)); return 0; }}
|
||||
ROE_WIFICLIENT(setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)),"SO_SNDTIMEO");
|
||||
ROE_WIFICLIENT(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)),"SO_RCVTIMEO");
|
||||
|
||||
// These are also set in WiFiClientSecure, should be set here too?
|
||||
//ROE_WIFICLIENT(setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable)),"TCP_NODELAY");
|
||||
//ROE_WIFICLIENT (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)),"SO_KEEPALIVE");
|
||||
|
||||
fcntl( sockfd, F_SETFL, fcntl( sockfd, F_GETFL, 0 ) & (~O_NONBLOCK) );
|
||||
clientSocketHandle.reset(new WiFiClientSocketHandle(sockfd));
|
||||
_rxBuffer.reset(new WiFiClientRxBuffer(sockfd));
|
||||
|
||||
_connected = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WiFiClient::connect(const char *host, uint16_t port)
|
||||
{
|
||||
return connect(host,port,WIFI_CLIENT_DEF_CONN_TIMEOUT_MS);
|
||||
}
|
||||
int WiFiClient::connect(const char *host, uint16_t port, int32_t timeout )
|
||||
return connect(host,port,_timeout);
|
||||
}
|
||||
|
||||
int WiFiClient::connect(const char *host, uint16_t port, int32_t timeout)
|
||||
{
|
||||
IPAddress srv((uint32_t)0);
|
||||
if(!WiFiGenericClass::hostByName(host, srv)){
|
||||
@ -301,14 +312,20 @@ int WiFiClient::setSocketOption(int option, char* value, size_t len)
|
||||
|
||||
int WiFiClient::setTimeout(uint32_t seconds)
|
||||
{
|
||||
Client::setTimeout(seconds * 1000);
|
||||
struct timeval tv;
|
||||
tv.tv_sec = seconds;
|
||||
tv.tv_usec = 0;
|
||||
if(setSocketOption(SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)) < 0) {
|
||||
return -1;
|
||||
Client::setTimeout(seconds * 1000); // This should be here?
|
||||
_timeout = seconds * 1000;
|
||||
if(fd() >= 0) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = seconds;
|
||||
tv.tv_usec = 0;
|
||||
if(setSocketOption(SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return setSocketOption(SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval));
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
return setSocketOption(SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval));
|
||||
}
|
||||
|
||||
int WiFiClient::setOption(int option, int *value)
|
||||
|
@ -42,6 +42,7 @@ protected:
|
||||
std::shared_ptr<WiFiClientSocketHandle> clientSocketHandle;
|
||||
std::shared_ptr<WiFiClientRxBuffer> _rxBuffer;
|
||||
bool _connected;
|
||||
int _timeout;
|
||||
|
||||
public:
|
||||
WiFiClient *next;
|
||||
|
@ -83,7 +83,7 @@ static bool sta_config_equal(const wifi_config_t& lhs, const wifi_config_t& rhs)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void wifi_sta_config(wifi_config_t * wifi_config, const char * ssid=NULL, const char * password=NULL, const uint8_t * bssid=NULL, uint8_t channel=0, wifi_scan_method_t scan_method=WIFI_ALL_CHANNEL_SCAN, wifi_sort_method_t sort_method=WIFI_CONNECT_AP_BY_SIGNAL, uint16_t listen_interval=0, bool pmf_required=false){
|
||||
static void wifi_sta_config(wifi_config_t * wifi_config, const char * ssid=NULL, const char * password=NULL, const uint8_t * bssid=NULL, uint8_t channel=0, wifi_auth_mode_t min_security=WIFI_AUTH_WPA2_PSK, wifi_scan_method_t scan_method=WIFI_ALL_CHANNEL_SCAN, wifi_sort_method_t sort_method=WIFI_CONNECT_AP_BY_SIGNAL, uint16_t listen_interval=0, bool pmf_required=false){
|
||||
wifi_config->sta.channel = channel;
|
||||
wifi_config->sta.listen_interval = listen_interval;
|
||||
wifi_config->sta.scan_method = scan_method;//WIFI_ALL_CHANNEL_SCAN or WIFI_FAST_SCAN
|
||||
@ -99,7 +99,7 @@ static void wifi_sta_config(wifi_config_t * wifi_config, const char * ssid=NULL,
|
||||
if(ssid != NULL && ssid[0] != 0){
|
||||
_wifi_strncpy((char*)wifi_config->sta.ssid, ssid, 32);
|
||||
if(password != NULL && password[0] != 0){
|
||||
wifi_config->sta.threshold.authmode = WIFI_AUTH_WPA2_PSK;
|
||||
wifi_config->sta.threshold.authmode = min_security;
|
||||
_wifi_strncpy((char*)wifi_config->sta.password, password, 64);
|
||||
}
|
||||
if(bssid != NULL){
|
||||
@ -115,6 +115,9 @@ static void wifi_sta_config(wifi_config_t * wifi_config, const char * ssid=NULL,
|
||||
|
||||
bool WiFiSTAClass::_autoReconnect = true;
|
||||
bool WiFiSTAClass::_useStaticIp = false;
|
||||
wifi_auth_mode_t WiFiSTAClass::_minSecurity = WIFI_AUTH_WPA2_PSK;
|
||||
wifi_scan_method_t WiFiSTAClass::_scanMethod = WIFI_FAST_SCAN;
|
||||
wifi_sort_method_t WiFiSTAClass::_sortMethod = WIFI_CONNECT_AP_BY_SIGNAL;
|
||||
|
||||
static wl_status_t _sta_status = WL_NO_SHIELD;
|
||||
static EventGroupHandle_t _sta_status_group = NULL;
|
||||
@ -243,12 +246,7 @@ wl_status_t WiFiSTAClass::begin(const char* ssid, const char *passphrase, int32_
|
||||
_wifi_strncpy(reinterpret_cast<char*>(conf.sta.password), passphrase, 64);
|
||||
}
|
||||
|
||||
if(channel == 0) {
|
||||
// If no specific channel specified, then do an slower WIFI_ALL_CHANNEL_SCAN
|
||||
wifi_sta_config(&conf, ssid, passphrase, bssid, channel, WIFI_ALL_CHANNEL_SCAN);
|
||||
}
|
||||
else
|
||||
wifi_sta_config(&conf, ssid, passphrase, bssid, channel, WIFI_FAST_SCAN);
|
||||
wifi_sta_config(&conf, ssid, passphrase, bssid, channel, _minSecurity, _scanMethod, _sortMethod);
|
||||
|
||||
wifi_config_t current_conf;
|
||||
if(esp_wifi_get_config((wifi_interface_t)ESP_IF_WIFI_STA, ¤t_conf) != ESP_OK){
|
||||
@ -404,6 +402,37 @@ bool WiFiSTAClass::isConnected()
|
||||
return (status() == WL_CONNECTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the minimum security for AP to be considered connectable
|
||||
* Must be called before WiFi.begin()
|
||||
* @param minSecurity wifi_auth_mode_t
|
||||
*/
|
||||
void WiFiSTAClass::setMinSecurity(wifi_auth_mode_t minSecurity)
|
||||
{
|
||||
_minSecurity = minSecurity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the way that AP is chosen.
|
||||
* First SSID match[WIFI_FAST_SCAN] or Sorted[WIFI_ALL_CHANNEL_SCAN] (RSSI or Security)
|
||||
* Must be called before WiFi.begin()
|
||||
* @param scanMethod wifi_scan_method_t
|
||||
*/
|
||||
void WiFiSTAClass::setScanMethod(wifi_scan_method_t scanMethod)
|
||||
{
|
||||
_scanMethod = scanMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the way that AP is sorted. (requires scanMethod WIFI_ALL_CHANNEL_SCAN)
|
||||
* By SSID[WIFI_CONNECT_AP_BY_SIGNAL] or Security[WIFI_CONNECT_AP_BY_SECURITY]
|
||||
* Must be called before WiFi.begin()
|
||||
* @param sortMethod wifi_sort_method_t
|
||||
*/
|
||||
void WiFiSTAClass::setSortMethod(wifi_sort_method_t sortMethod)
|
||||
{
|
||||
_sortMethod = sortMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setting the ESP32 station to connect to the AP (which is recorded)
|
||||
|
@ -64,6 +64,11 @@ public:
|
||||
|
||||
uint8_t waitForConnectResult(unsigned long timeoutLength = 60000);
|
||||
|
||||
// Next group functions must be called before WiFi.begin()
|
||||
void setMinSecurity(wifi_auth_mode_t minSecurity);// Default is WIFI_AUTH_WPA2_PSK
|
||||
void setScanMethod(wifi_scan_method_t scanMethod);// Default is WIFI_FAST_SCAN
|
||||
void setSortMethod(wifi_sort_method_t sortMethod);// Default is WIFI_CONNECT_AP_BY_SIGNAL
|
||||
|
||||
// STA network info
|
||||
IPAddress localIP();
|
||||
|
||||
@ -96,6 +101,9 @@ public:
|
||||
protected:
|
||||
static bool _useStaticIp;
|
||||
static bool _autoReconnect;
|
||||
static wifi_auth_mode_t _minSecurity;
|
||||
static wifi_scan_method_t _scanMethod;
|
||||
static wifi_sort_method_t _sortMethod;
|
||||
|
||||
public:
|
||||
bool beginSmartConfig(smartconfig_type_t type = SC_TYPE_ESPTOUCH, char* crypt_key = NULL);
|
||||
|
@ -81,7 +81,7 @@ void* WiFiScanClass::_scanResult = 0;
|
||||
* @param show_hidden show hidden networks
|
||||
* @return Number of discovered networks
|
||||
*/
|
||||
int16_t WiFiScanClass::scanNetworks(bool async, bool show_hidden, bool passive, uint32_t max_ms_per_chan, uint8_t channel)
|
||||
int16_t WiFiScanClass::scanNetworks(bool async, bool show_hidden, bool passive, uint32_t max_ms_per_chan, uint8_t channel, const char * ssid, const uint8_t * bssid)
|
||||
{
|
||||
if(WiFiGenericClass::getStatusBits() & WIFI_SCANNING_BIT) {
|
||||
return WIFI_SCAN_RUNNING;
|
||||
@ -95,8 +95,8 @@ int16_t WiFiScanClass::scanNetworks(bool async, bool show_hidden, bool passive,
|
||||
scanDelete();
|
||||
|
||||
wifi_scan_config_t config;
|
||||
config.ssid = 0;
|
||||
config.bssid = 0;
|
||||
config.ssid = (uint8_t*)ssid;
|
||||
config.bssid = (uint8_t*)bssid;
|
||||
config.channel = channel;
|
||||
config.show_hidden = show_hidden;
|
||||
if(passive){
|
||||
|
@ -31,7 +31,7 @@ class WiFiScanClass
|
||||
|
||||
public:
|
||||
|
||||
int16_t scanNetworks(bool async = false, bool show_hidden = false, bool passive = false, uint32_t max_ms_per_chan = 300, uint8_t channel = 0);
|
||||
int16_t scanNetworks(bool async = false, bool show_hidden = false, bool passive = false, uint32_t max_ms_per_chan = 300, uint8_t channel = 0, const char * ssid=nullptr, const uint8_t * bssid=nullptr);
|
||||
|
||||
int16_t scanComplete();
|
||||
void scanDelete();
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "Arduino.h"
|
||||
#include "Server.h"
|
||||
#include "WiFiClient.h"
|
||||
#include "arpa/inet.h"
|
||||
#include "IPAddress.h"
|
||||
|
||||
class WiFiServer : public Server {
|
||||
@ -38,7 +37,8 @@ class WiFiServer : public Server {
|
||||
public:
|
||||
void listenOnLocalhost(){}
|
||||
|
||||
WiFiServer(uint16_t port=80, uint8_t max_clients=4):sockfd(-1),_accepted_sockfd(-1),_addr(INADDR_ANY),_port(port),_max_clients(max_clients),_listening(false),_noDelay(false) {
|
||||
// _addr(INADDR_ANY) is the same as _addr() ==> 0.0.0.0
|
||||
WiFiServer(uint16_t port=80, uint8_t max_clients=4):sockfd(-1),_accepted_sockfd(-1),_addr(),_port(port),_max_clients(max_clients),_listening(false),_noDelay(false) {
|
||||
log_v("WiFiServer::WiFiServer(port=%d, ...)", port);
|
||||
}
|
||||
WiFiServer(const IPAddress& addr, uint16_t port=80, uint8_t max_clients=4):sockfd(-1),_accepted_sockfd(-1),_addr(addr),_port(port),_max_clients(max_clients),_listening(false),_noDelay(false) {
|
||||
|
@ -23,6 +23,8 @@
|
||||
#ifndef ESP32WIFITYPE_H_
|
||||
#define ESP32WIFITYPE_H_
|
||||
|
||||
#include "esp_wifi_types.h"
|
||||
|
||||
#define WIFI_SCAN_RUNNING (-1)
|
||||
#define WIFI_SCAN_FAILED (-2)
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
WiFiClientSecure::WiFiClientSecure()
|
||||
{
|
||||
_connected = false;
|
||||
_timeout = 30000; // Same default as ssl_client
|
||||
|
||||
sslclient = new sslclient_context;
|
||||
ssl_init(sslclient);
|
||||
@ -52,7 +53,7 @@ WiFiClientSecure::WiFiClientSecure()
|
||||
WiFiClientSecure::WiFiClientSecure(int sock)
|
||||
{
|
||||
_connected = false;
|
||||
_timeout = 0;
|
||||
_timeout = 30000; // Same default as ssl_client
|
||||
|
||||
sslclient = new sslclient_context;
|
||||
ssl_init(sslclient);
|
||||
@ -128,9 +129,6 @@ int WiFiClientSecure::connect(IPAddress ip, uint16_t port, const char *CA_cert,
|
||||
|
||||
int WiFiClientSecure::connect(const char *host, uint16_t port, const char *CA_cert, const char *cert, const char *private_key)
|
||||
{
|
||||
if(_timeout > 0){
|
||||
sslclient->handshake_timeout = _timeout;
|
||||
}
|
||||
int ret = start_ssl_client(sslclient, host, port, _timeout, CA_cert, _use_ca_bundle, cert, private_key, NULL, NULL, _use_insecure, _alpn_protos);
|
||||
_lastError = ret;
|
||||
if (ret < 0) {
|
||||
@ -148,9 +146,6 @@ int WiFiClientSecure::connect(IPAddress ip, uint16_t port, const char *pskIdent,
|
||||
|
||||
int WiFiClientSecure::connect(const char *host, uint16_t port, const char *pskIdent, const char *psKey) {
|
||||
log_v("start_ssl_client with PSK");
|
||||
if(_timeout > 0){
|
||||
sslclient->handshake_timeout = _timeout;
|
||||
}
|
||||
int ret = start_ssl_client(sslclient, host, port, _timeout, NULL, false, NULL, NULL, pskIdent, psKey, _use_insecure, _alpn_protos);
|
||||
_lastError = ret;
|
||||
if (ret < 0) {
|
||||
@ -315,6 +310,7 @@ char *WiFiClientSecure::_streamLoad(Stream& stream, size_t size) {
|
||||
}
|
||||
|
||||
bool WiFiClientSecure::loadCACert(Stream& stream, size_t size) {
|
||||
if (_CA_cert != NULL) free(const_cast<char*>(_CA_cert));
|
||||
char *dest = _streamLoad(stream, size);
|
||||
bool ret = false;
|
||||
if (dest) {
|
||||
@ -325,6 +321,7 @@ bool WiFiClientSecure::loadCACert(Stream& stream, size_t size) {
|
||||
}
|
||||
|
||||
bool WiFiClientSecure::loadCertificate(Stream& stream, size_t size) {
|
||||
if (_cert != NULL) free(const_cast<char*>(_cert));
|
||||
char *dest = _streamLoad(stream, size);
|
||||
bool ret = false;
|
||||
if (dest) {
|
||||
@ -335,6 +332,7 @@ bool WiFiClientSecure::loadCertificate(Stream& stream, size_t size) {
|
||||
}
|
||||
|
||||
bool WiFiClientSecure::loadPrivateKey(Stream& stream, size_t size) {
|
||||
if (_private_key != NULL) free(const_cast<char*>(_private_key));
|
||||
char *dest = _streamLoad(stream, size);
|
||||
bool ret = false;
|
||||
if (dest) {
|
||||
@ -362,3 +360,27 @@ void WiFiClientSecure::setAlpnProtocols(const char **alpn_protos)
|
||||
{
|
||||
_alpn_protos = alpn_protos;
|
||||
}
|
||||
int WiFiClientSecure::setTimeout(uint32_t seconds)
|
||||
{
|
||||
_timeout = seconds * 1000;
|
||||
if (sslclient->socket >= 0) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = seconds;
|
||||
tv.tv_usec = 0;
|
||||
if(setSocketOption(SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return setSocketOption(SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval));
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
int WiFiClientSecure::setSocketOption(int option, char* value, size_t len)
|
||||
{
|
||||
int res = setsockopt(sslclient->socket, SOL_SOCKET, option, value, len);
|
||||
if(res < 0) {
|
||||
log_e("%X : %d", option, errno);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ protected:
|
||||
|
||||
int _lastError = 0;
|
||||
int _peek = -1;
|
||||
int _timeout = 0;
|
||||
int _timeout;
|
||||
bool _use_insecure;
|
||||
const char *_CA_cert;
|
||||
const char *_cert;
|
||||
@ -79,7 +79,8 @@ public:
|
||||
void setAlpnProtocols(const char **alpn_protos);
|
||||
const mbedtls_x509_crt* getPeerCertificate() { return mbedtls_ssl_get_peer_cert(&sslclient->ssl_ctx); };
|
||||
bool getFingerprintSHA256(uint8_t sha256_result[32]) { return get_peer_fingerprint(sslclient, sha256_result); };
|
||||
int setTimeout(uint32_t seconds){ return 0; }
|
||||
int setTimeout(uint32_t seconds);
|
||||
int setSocketOption(int option, char* value, size_t len);
|
||||
|
||||
operator bool()
|
||||
{
|
||||
|
@ -28,6 +28,9 @@
|
||||
{
|
||||
"name": "ESP32-S2 Dev Board"
|
||||
},
|
||||
{
|
||||
"name": "ESP32-S3 Dev Board"
|
||||
},
|
||||
{
|
||||
"name": "ESP32-C3 Dev Board"
|
||||
}
|
||||
|
88
platform.txt
88
platform.txt
File diff suppressed because one or more lines are too long
@ -0,0 +1,8 @@
|
||||
esptool.name=Esptool
|
||||
esptool.communication=serial
|
||||
esptool.protocol=serial
|
||||
esptool.program.protocol=serial
|
||||
esptool.program.tool=esptool_py
|
||||
esptool.program.tool.default=esptool_py
|
||||
esptool.program.extra_params=
|
||||
esptool.extra_params=
|
||||
|
@ -24,7 +24,7 @@ http://arduino.cc/en/Reference/HomePage
|
||||
|
||||
# Extends: https://github.com/platformio/platform-espressif32/blob/develop/builder/main.py
|
||||
|
||||
from os.path import abspath, isdir, isfile, join, basename
|
||||
from os.path import abspath, basename, isdir, isfile, join
|
||||
|
||||
from SCons.Script import DefaultEnvironment
|
||||
|
||||
@ -100,6 +100,7 @@ env.Append(
|
||||
"-u", "pthread_include_pthread_cond_impl",
|
||||
"-u", "pthread_include_pthread_local_storage_impl",
|
||||
"-u", "pthread_include_pthread_rwlock_impl",
|
||||
"-u", "include_esp_phy_override",
|
||||
"-u", "ld_include_highint_hdl",
|
||||
"-u", "start_app",
|
||||
"-u", "start_app_other_cores",
|
||||
@ -309,7 +310,7 @@ env.Append(
|
||||
"UNITY_INCLUDE_CONFIG_H",
|
||||
"WITH_POSIX",
|
||||
"_GNU_SOURCE",
|
||||
("IDF_VER", '\\"v4.4-367-gc29343eb94\\"'),
|
||||
("IDF_VER", '\\"v4.4.1-1-gb8050b365e\\"'),
|
||||
"ESP_PLATFORM",
|
||||
"_POSIX_READER_WRITER_LOCKS",
|
||||
"ARDUINO_ARCH_ESP32",
|
||||
@ -318,7 +319,8 @@ env.Append(
|
||||
("ARDUINO", 10812),
|
||||
("ARDUINO_VARIANT", '\\"%s\\"' % env.BoardConfig().get("build.variant").replace('"', "")),
|
||||
("ARDUINO_BOARD", '\\"%s\\"' % env.BoardConfig().get("name").replace('"', "")),
|
||||
"ARDUINO_PARTITION_%s" % env.BoardConfig().get("build.partitions", "default.csv").replace(".csv", "")
|
||||
"ARDUINO_PARTITION_%s" % basename(env.BoardConfig().get(
|
||||
"build.partitions", "default.csv")).replace(".csv", "").replace("-", "_")
|
||||
],
|
||||
|
||||
LIBSOURCE_DIRS=[
|
||||
@ -330,6 +332,12 @@ env.Append(
|
||||
("0x8000", join(env.subst("$BUILD_DIR"), "partitions.bin")),
|
||||
("0xe000", join(FRAMEWORK_DIR, "tools", "partitions", "boot_app0.bin"))
|
||||
]
|
||||
+ [
|
||||
(offset, join(FRAMEWORK_DIR, img))
|
||||
for offset, img in env.BoardConfig().get(
|
||||
"upload.arduino.flash_extra_images", []
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
#
|
||||
|
@ -24,7 +24,7 @@ http://arduino.cc/en/Reference/HomePage
|
||||
|
||||
# Extends: https://github.com/platformio/platform-espressif32/blob/develop/builder/main.py
|
||||
|
||||
from os.path import abspath, isdir, isfile, join, basename
|
||||
from os.path import abspath, basename, isdir, isfile, join
|
||||
|
||||
from SCons.Script import DefaultEnvironment
|
||||
|
||||
@ -101,6 +101,7 @@ env.Append(
|
||||
"-u", "pthread_include_pthread_cond_impl",
|
||||
"-u", "pthread_include_pthread_local_storage_impl",
|
||||
"-u", "pthread_include_pthread_rwlock_impl",
|
||||
"-u", "include_esp_phy_override",
|
||||
"-u", "start_app",
|
||||
"-u", "__ubsan_include",
|
||||
"-u", "__assert_func",
|
||||
@ -302,7 +303,7 @@ env.Append(
|
||||
"UNITY_INCLUDE_CONFIG_H",
|
||||
"WITH_POSIX",
|
||||
"_GNU_SOURCE",
|
||||
("IDF_VER", '\\"v4.4-367-gc29343eb94\\"'),
|
||||
("IDF_VER", '\\"v4.4.1-1-gb8050b365e\\"'),
|
||||
"ESP_PLATFORM",
|
||||
"_POSIX_READER_WRITER_LOCKS",
|
||||
"ARDUINO_ARCH_ESP32",
|
||||
@ -311,7 +312,8 @@ env.Append(
|
||||
("ARDUINO", 10812),
|
||||
("ARDUINO_VARIANT", '\\"%s\\"' % env.BoardConfig().get("build.variant").replace('"', "")),
|
||||
("ARDUINO_BOARD", '\\"%s\\"' % env.BoardConfig().get("name").replace('"', "")),
|
||||
"ARDUINO_PARTITION_%s" % env.BoardConfig().get("build.partitions", "default.csv").replace(".csv", "")
|
||||
"ARDUINO_PARTITION_%s" % basename(env.BoardConfig().get(
|
||||
"build.partitions", "default.csv")).replace(".csv", "").replace("-", "_")
|
||||
],
|
||||
|
||||
LIBSOURCE_DIRS=[
|
||||
@ -323,6 +325,12 @@ env.Append(
|
||||
("0x8000", join(env.subst("$BUILD_DIR"), "partitions.bin")),
|
||||
("0xe000", join(FRAMEWORK_DIR, "tools", "partitions", "boot_app0.bin"))
|
||||
]
|
||||
+ [
|
||||
(offset, join(FRAMEWORK_DIR, img))
|
||||
for offset, img in env.BoardConfig().get(
|
||||
"upload.arduino.flash_extra_images", []
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
#
|
||||
|
@ -24,7 +24,7 @@ http://arduino.cc/en/Reference/HomePage
|
||||
|
||||
# Extends: https://github.com/platformio/platform-espressif32/blob/develop/builder/main.py
|
||||
|
||||
from os.path import abspath, isdir, isfile, join, basename
|
||||
from os.path import abspath, basename, isdir, isfile, join
|
||||
|
||||
from SCons.Script import DefaultEnvironment
|
||||
|
||||
@ -97,6 +97,7 @@ env.Append(
|
||||
"-u", "pthread_include_pthread_cond_impl",
|
||||
"-u", "pthread_include_pthread_local_storage_impl",
|
||||
"-u", "pthread_include_pthread_rwlock_impl",
|
||||
"-u", "include_esp_phy_override",
|
||||
"-u", "ld_include_highint_hdl",
|
||||
"-u", "start_app",
|
||||
"-u", "__ubsan_include",
|
||||
@ -304,7 +305,7 @@ env.Append(
|
||||
"UNITY_INCLUDE_CONFIG_H",
|
||||
"WITH_POSIX",
|
||||
"_GNU_SOURCE",
|
||||
("IDF_VER", '\\"v4.4-367-gc29343eb94\\"'),
|
||||
("IDF_VER", '\\"v4.4.1-1-gb8050b365e\\"'),
|
||||
"ESP_PLATFORM",
|
||||
"_POSIX_READER_WRITER_LOCKS",
|
||||
"ARDUINO_ARCH_ESP32",
|
||||
@ -313,7 +314,8 @@ env.Append(
|
||||
("ARDUINO", 10812),
|
||||
("ARDUINO_VARIANT", '\\"%s\\"' % env.BoardConfig().get("build.variant").replace('"', "")),
|
||||
("ARDUINO_BOARD", '\\"%s\\"' % env.BoardConfig().get("name").replace('"', "")),
|
||||
"ARDUINO_PARTITION_%s" % env.BoardConfig().get("build.partitions", "default.csv").replace(".csv", "")
|
||||
"ARDUINO_PARTITION_%s" % basename(env.BoardConfig().get(
|
||||
"build.partitions", "default.csv")).replace(".csv", "").replace("-", "_")
|
||||
],
|
||||
|
||||
LIBSOURCE_DIRS=[
|
||||
@ -325,6 +327,12 @@ env.Append(
|
||||
("0x8000", join(env.subst("$BUILD_DIR"), "partitions.bin")),
|
||||
("0xe000", join(FRAMEWORK_DIR, "tools", "partitions", "boot_app0.bin"))
|
||||
]
|
||||
+ [
|
||||
(offset, join(FRAMEWORK_DIR, img))
|
||||
for offset, img in env.BoardConfig().get(
|
||||
"upload.arduino.flash_extra_images", []
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
#
|
||||
|
@ -24,7 +24,7 @@ http://arduino.cc/en/Reference/HomePage
|
||||
|
||||
# Extends: https://github.com/platformio/platform-espressif32/blob/develop/builder/main.py
|
||||
|
||||
from os.path import abspath, isdir, isfile, join, basename
|
||||
from os.path import abspath, basename, isdir, isfile, join
|
||||
|
||||
from SCons.Script import DefaultEnvironment
|
||||
|
||||
@ -96,6 +96,7 @@ env.Append(
|
||||
"-u", "pthread_include_pthread_cond_impl",
|
||||
"-u", "pthread_include_pthread_local_storage_impl",
|
||||
"-u", "pthread_include_pthread_rwlock_impl",
|
||||
"-u", "include_esp_phy_override",
|
||||
"-u", "ld_include_highint_hdl",
|
||||
"-u", "start_app",
|
||||
"-u", "start_app_other_cores",
|
||||
@ -321,7 +322,7 @@ env.Append(
|
||||
"UNITY_INCLUDE_CONFIG_H",
|
||||
"WITH_POSIX",
|
||||
"_GNU_SOURCE",
|
||||
("IDF_VER", '\\"v4.4-367-gc29343eb94\\"'),
|
||||
("IDF_VER", '\\"v4.4.1-1-gb8050b365e\\"'),
|
||||
"ESP_PLATFORM",
|
||||
"_POSIX_READER_WRITER_LOCKS",
|
||||
"ARDUINO_ARCH_ESP32",
|
||||
@ -330,7 +331,8 @@ env.Append(
|
||||
("ARDUINO", 10812),
|
||||
("ARDUINO_VARIANT", '\\"%s\\"' % env.BoardConfig().get("build.variant").replace('"', "")),
|
||||
("ARDUINO_BOARD", '\\"%s\\"' % env.BoardConfig().get("name").replace('"', "")),
|
||||
"ARDUINO_PARTITION_%s" % env.BoardConfig().get("build.partitions", "default.csv").replace(".csv", "")
|
||||
"ARDUINO_PARTITION_%s" % basename(env.BoardConfig().get(
|
||||
"build.partitions", "default.csv")).replace(".csv", "").replace("-", "_")
|
||||
],
|
||||
|
||||
LIBSOURCE_DIRS=[
|
||||
@ -342,6 +344,12 @@ env.Append(
|
||||
("0x8000", join(env.subst("$BUILD_DIR"), "partitions.bin")),
|
||||
("0xe000", join(FRAMEWORK_DIR, "tools", "partitions", "boot_app0.bin"))
|
||||
]
|
||||
+ [
|
||||
(offset, join(FRAMEWORK_DIR, img))
|
||||
for offset, img in env.BoardConfig().get(
|
||||
"upload.arduino.flash_extra_images", []
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
#
|
||||
|
@ -23,7 +23,7 @@ extern "C" {
|
||||
/** Minor version number (x.X.x) */
|
||||
#define ESP_IDF_VERSION_MINOR 4
|
||||
/** Patch version number (x.x.X) */
|
||||
#define ESP_IDF_VERSION_PATCH 0
|
||||
#define ESP_IDF_VERSION_PATCH 1
|
||||
|
||||
/**
|
||||
* Macro to convert IDF version number into an integer
|
||||
|
@ -52,6 +52,10 @@ uint8_t regi2c_ctrl_read_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_ad
|
||||
void regi2c_ctrl_write_reg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data);
|
||||
void regi2c_ctrl_write_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb, uint8_t data);
|
||||
|
||||
/* enter the critical section that protects internal registers. Don't use it in SDK. Use the functions above. */
|
||||
void regi2c_enter_critical(void);
|
||||
void regi2c_exit_critical(void);
|
||||
|
||||
#endif // BOOTLOADER_BUILD
|
||||
|
||||
/* Convenience macros for the above functions, these use register definitions
|
||||
|
@ -1,24 +1,9 @@
|
||||
#ifndef ESP_LITTLEFS_H__
|
||||
#define ESP_LITTLEFS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <utime.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_err.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/reent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/dirent.h>
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "littlefs/lfs.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -154,6 +154,10 @@ typedef enum {
|
||||
ESP_RMAKER_REQ_SRC_CLOUD,
|
||||
/** Request received when a schedule has triggered */
|
||||
ESP_RMAKER_REQ_SRC_SCHEDULE,
|
||||
/** Request received when a scene has been activated */
|
||||
ESP_RMAKER_REQ_SRC_SCENE_ACTIVATE,
|
||||
/** Request received when a scene has been deactivated */
|
||||
ESP_RMAKER_REQ_SRC_SCENE_DEACTIVATE,
|
||||
/** Request received from a local controller */
|
||||
ESP_RMAKER_REQ_SRC_LOCAL,
|
||||
/** This will always be the last value. Any value equal to or
|
||||
|
@ -0,0 +1,38 @@
|
||||
// Copyright 2022 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <esp_err.h>
|
||||
|
||||
/** Enable Scenes
|
||||
*
|
||||
* This API enables the scenes service for the node. For more information,
|
||||
* check [here](https://rainmaker.espressif.com/docs/scenes.html)
|
||||
*
|
||||
* @note This API should be called after esp_rmaker_node_init() but before esp_rmaker_start().
|
||||
*
|
||||
* @return ESP_OK on success.
|
||||
* @return error in case of failure.
|
||||
*/
|
||||
esp_err_t esp_rmaker_scenes_enable(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -45,6 +45,7 @@ extern "C"
|
||||
#define ESP_RMAKER_DEF_TIMEZONE_NAME "TZ"
|
||||
#define ESP_RMAKER_DEF_TIMEZONE_POSIX_NAME "TZ-POSIX"
|
||||
#define ESP_RMAKER_DEF_SCHEDULE_NAME "Schedules"
|
||||
#define ESP_RMAKER_DEF_SCENES_NAME "Scenes"
|
||||
#define ESP_RMAKER_DEF_REBOOT_NAME "Reboot"
|
||||
#define ESP_RMAKER_DEF_FACTORY_RESET_NAME "Factory-Reset"
|
||||
#define ESP_RMAKER_DEF_WIFI_RESET_NAME "Wi-Fi-Reset"
|
||||
@ -265,6 +266,20 @@ esp_rmaker_param_t *esp_rmaker_timezone_posix_param_create(const char *param_nam
|
||||
*/
|
||||
esp_rmaker_param_t *esp_rmaker_schedules_param_create(const char *param_name, int max_schedules);
|
||||
|
||||
/**
|
||||
* Create standard Scenes param
|
||||
*
|
||||
* This will create the standard scenes parameter. Default value
|
||||
* is set internally.
|
||||
*
|
||||
* @param[in] param_name Name of the parameter
|
||||
* @param[in] max_scenes Maximum number of scenes allowed
|
||||
*
|
||||
* @return Parameter handle on success.
|
||||
* @return NULL in case of failures.
|
||||
*/
|
||||
esp_rmaker_param_t *esp_rmaker_scenes_param_create(const char *param_name, int max_scenes);
|
||||
|
||||
/**
|
||||
* Create standard Reboot param
|
||||
*
|
||||
|
@ -71,6 +71,24 @@ esp_rmaker_device_t *esp_rmaker_time_service_create(const char *serv_name, const
|
||||
*/
|
||||
esp_rmaker_device_t *esp_rmaker_create_schedule_service(const char *serv_name, esp_rmaker_device_write_cb_t write_cb, esp_rmaker_device_read_cb_t read_cb, int max_schedules, void *priv_data);
|
||||
|
||||
/** Create a standard Scenes service
|
||||
*
|
||||
* This creates a Scenes service with the mandatory parameters. The default parameter names will be used.
|
||||
* Refer \ref esp_rmaker_standard_params.h for default names.
|
||||
*
|
||||
* @param[in] serv_name The unique service name
|
||||
* @param[in] write_cb Write callback.
|
||||
* @param[in] read_cb Read callback.
|
||||
* @param[in] max_scenes Maximum number of scenes supported.
|
||||
* @param[in] deactivation_support Deactivation callback support.
|
||||
* @param[in] priv_data (Optional) Private data associated with the service. This should stay
|
||||
* allocated throughout the lifetime of the service.
|
||||
*
|
||||
* @return service_handle on success.
|
||||
* @return NULL in case of any error.
|
||||
*/
|
||||
esp_rmaker_device_t *esp_rmaker_create_scenes_service(const char *serv_name, esp_rmaker_device_write_cb_t write_cb, esp_rmaker_device_read_cb_t read_cb, int max_scenes, bool deactivation_support, void *priv_data);
|
||||
|
||||
/** Create a standard System service
|
||||
*
|
||||
* This creates an empty System service. Appropriate parameters should be added by the caller.
|
||||
|
@ -44,6 +44,7 @@ extern "C"
|
||||
#define ESP_RMAKER_PARAM_TIMEZONE "esp.param.tz"
|
||||
#define ESP_RMAKER_PARAM_TIMEZONE_POSIX "esp.param.tz_posix"
|
||||
#define ESP_RMAKER_PARAM_SCHEDULES "esp.param.schedules"
|
||||
#define ESP_RMAKER_PARAM_SCENES "esp.param.scenes"
|
||||
#define ESP_RMAKER_PARAM_REBOOT "esp.param.reboot"
|
||||
#define ESP_RMAKER_PARAM_FACTORY_RESET "esp.param.factory-reset"
|
||||
#define ESP_RMAKER_PARAM_WIFI_RESET "esp.param.wifi-reset"
|
||||
@ -63,6 +64,7 @@ extern "C"
|
||||
#define ESP_RMAKER_SERVICE_OTA "esp.service.ota"
|
||||
#define ESP_RMAKER_SERVICE_TIME "esp.service.time"
|
||||
#define ESP_RMAKER_SERVICE_SCHEDULE "esp.service.schedule"
|
||||
#define ESP_RMAKER_SERVICE_SCENES "esp.service.scenes"
|
||||
#define ESP_RMAKER_SERVICE_SYSTEM "esp.service.system"
|
||||
#define ESP_RMAKER_SERVICE_LOCAL_CONTROL "esp.service.local_control"
|
||||
|
||||
|
@ -19,7 +19,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
FB_RGB888, FB_BGR888, FB_RGB565, FB_BGR565
|
||||
FB_RGB888, FB_BGR888, FB_RGB565, FB_BGR565, FB_GRAY
|
||||
} fb_format_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -15,7 +15,7 @@
|
||||
#ifndef _WIFI_PROV_CONFIG_H_
|
||||
#define _WIFI_PROV_CONFIG_H_
|
||||
|
||||
#include <lwip/inet.h>
|
||||
#include <lwip/ip4_addr.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -57,6 +57,7 @@
|
||||
#define CONFIG_ESP_RMAKER_OTA_AUTOFETCH_PERIOD 0
|
||||
#define CONFIG_ESP_RMAKER_OTA_HTTP_RX_BUFFER_SIZE 1024
|
||||
#define CONFIG_ESP_RMAKER_SCHEDULING_MAX_SCHEDULES 10
|
||||
#define CONFIG_ESP_RMAKER_SCENES_MAX_SCENES 10
|
||||
#define CONFIG_ENABLE_ARDUINO_DEPENDS 1
|
||||
#define CONFIG_AUTOSTART_ARDUINO 1
|
||||
#define CONFIG_ARDUINO_RUN_CORE1 1
|
||||
@ -166,7 +167,6 @@
|
||||
#define CONFIG_SPIRAM 1
|
||||
#define CONFIG_SPIRAM_USE_MALLOC 1
|
||||
#define CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL 4096
|
||||
#define CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP 1
|
||||
#define CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL 0
|
||||
#define CONFIG_SPIRAM_CACHE_WORKAROUND 1
|
||||
#define CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_MEMW 1
|
||||
@ -691,5 +691,5 @@
|
||||
#define CONFIG_ULP_COPROC_RESERVE_MEM CONFIG_ESP32_ULP_COPROC_RESERVE_MEM
|
||||
#define CONFIG_WARN_WRITE_STRINGS CONFIG_COMPILER_WARN_WRITE_STRINGS
|
||||
#define CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP
|
||||
#define CONFIG_ARDUINO_IDF_COMMIT "c29343eb94"
|
||||
#define CONFIG_ARDUINO_IDF_COMMIT "b8050b365e"
|
||||
#define CONFIG_ARDUINO_IDF_BRANCH "release/v4.4"
|
||||
|
Binary file not shown.
Binary file not shown.
@ -162,6 +162,13 @@ CONFIG_ESP_RMAKER_OTA_HTTP_RX_BUFFER_SIZE=1024
|
||||
#
|
||||
CONFIG_ESP_RMAKER_SCHEDULING_MAX_SCHEDULES=10
|
||||
# end of ESP RainMaker Scheduling
|
||||
|
||||
#
|
||||
# ESP RainMaker Scenes
|
||||
#
|
||||
CONFIG_ESP_RMAKER_SCENES_MAX_SCENES=10
|
||||
# CONFIG_ESP_RMAKER_SCENES_DEACTIVATE_SUPPORT is not set
|
||||
# end of ESP RainMaker Scenes
|
||||
# end of ESP RainMaker Config
|
||||
|
||||
#
|
||||
|
@ -23,7 +23,7 @@ extern "C" {
|
||||
/** Minor version number (x.X.x) */
|
||||
#define ESP_IDF_VERSION_MINOR 4
|
||||
/** Patch version number (x.x.X) */
|
||||
#define ESP_IDF_VERSION_PATCH 0
|
||||
#define ESP_IDF_VERSION_PATCH 1
|
||||
|
||||
/**
|
||||
* Macro to convert IDF version number into an integer
|
||||
|
@ -65,6 +65,10 @@ uint8_t regi2c_ctrl_read_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_ad
|
||||
void regi2c_ctrl_write_reg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data);
|
||||
void regi2c_ctrl_write_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb, uint8_t data);
|
||||
|
||||
/* enter the critical section that protects internal registers. Don't use it in SDK. Use the functions above. */
|
||||
void regi2c_enter_critical(void);
|
||||
void regi2c_exit_critical(void);
|
||||
|
||||
#endif // BOOTLOADER_BUILD
|
||||
|
||||
/* Convenience macros for the above functions, these use register definitions
|
||||
|
@ -1,24 +1,9 @@
|
||||
#ifndef ESP_LITTLEFS_H__
|
||||
#define ESP_LITTLEFS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <utime.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_err.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/reent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/dirent.h>
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "littlefs/lfs.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -154,6 +154,10 @@ typedef enum {
|
||||
ESP_RMAKER_REQ_SRC_CLOUD,
|
||||
/** Request received when a schedule has triggered */
|
||||
ESP_RMAKER_REQ_SRC_SCHEDULE,
|
||||
/** Request received when a scene has been activated */
|
||||
ESP_RMAKER_REQ_SRC_SCENE_ACTIVATE,
|
||||
/** Request received when a scene has been deactivated */
|
||||
ESP_RMAKER_REQ_SRC_SCENE_DEACTIVATE,
|
||||
/** Request received from a local controller */
|
||||
ESP_RMAKER_REQ_SRC_LOCAL,
|
||||
/** This will always be the last value. Any value equal to or
|
||||
|
@ -0,0 +1,38 @@
|
||||
// Copyright 2022 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <esp_err.h>
|
||||
|
||||
/** Enable Scenes
|
||||
*
|
||||
* This API enables the scenes service for the node. For more information,
|
||||
* check [here](https://rainmaker.espressif.com/docs/scenes.html)
|
||||
*
|
||||
* @note This API should be called after esp_rmaker_node_init() but before esp_rmaker_start().
|
||||
*
|
||||
* @return ESP_OK on success.
|
||||
* @return error in case of failure.
|
||||
*/
|
||||
esp_err_t esp_rmaker_scenes_enable(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -45,6 +45,7 @@ extern "C"
|
||||
#define ESP_RMAKER_DEF_TIMEZONE_NAME "TZ"
|
||||
#define ESP_RMAKER_DEF_TIMEZONE_POSIX_NAME "TZ-POSIX"
|
||||
#define ESP_RMAKER_DEF_SCHEDULE_NAME "Schedules"
|
||||
#define ESP_RMAKER_DEF_SCENES_NAME "Scenes"
|
||||
#define ESP_RMAKER_DEF_REBOOT_NAME "Reboot"
|
||||
#define ESP_RMAKER_DEF_FACTORY_RESET_NAME "Factory-Reset"
|
||||
#define ESP_RMAKER_DEF_WIFI_RESET_NAME "Wi-Fi-Reset"
|
||||
@ -265,6 +266,20 @@ esp_rmaker_param_t *esp_rmaker_timezone_posix_param_create(const char *param_nam
|
||||
*/
|
||||
esp_rmaker_param_t *esp_rmaker_schedules_param_create(const char *param_name, int max_schedules);
|
||||
|
||||
/**
|
||||
* Create standard Scenes param
|
||||
*
|
||||
* This will create the standard scenes parameter. Default value
|
||||
* is set internally.
|
||||
*
|
||||
* @param[in] param_name Name of the parameter
|
||||
* @param[in] max_scenes Maximum number of scenes allowed
|
||||
*
|
||||
* @return Parameter handle on success.
|
||||
* @return NULL in case of failures.
|
||||
*/
|
||||
esp_rmaker_param_t *esp_rmaker_scenes_param_create(const char *param_name, int max_scenes);
|
||||
|
||||
/**
|
||||
* Create standard Reboot param
|
||||
*
|
||||
|
@ -71,6 +71,24 @@ esp_rmaker_device_t *esp_rmaker_time_service_create(const char *serv_name, const
|
||||
*/
|
||||
esp_rmaker_device_t *esp_rmaker_create_schedule_service(const char *serv_name, esp_rmaker_device_write_cb_t write_cb, esp_rmaker_device_read_cb_t read_cb, int max_schedules, void *priv_data);
|
||||
|
||||
/** Create a standard Scenes service
|
||||
*
|
||||
* This creates a Scenes service with the mandatory parameters. The default parameter names will be used.
|
||||
* Refer \ref esp_rmaker_standard_params.h for default names.
|
||||
*
|
||||
* @param[in] serv_name The unique service name
|
||||
* @param[in] write_cb Write callback.
|
||||
* @param[in] read_cb Read callback.
|
||||
* @param[in] max_scenes Maximum number of scenes supported.
|
||||
* @param[in] deactivation_support Deactivation callback support.
|
||||
* @param[in] priv_data (Optional) Private data associated with the service. This should stay
|
||||
* allocated throughout the lifetime of the service.
|
||||
*
|
||||
* @return service_handle on success.
|
||||
* @return NULL in case of any error.
|
||||
*/
|
||||
esp_rmaker_device_t *esp_rmaker_create_scenes_service(const char *serv_name, esp_rmaker_device_write_cb_t write_cb, esp_rmaker_device_read_cb_t read_cb, int max_scenes, bool deactivation_support, void *priv_data);
|
||||
|
||||
/** Create a standard System service
|
||||
*
|
||||
* This creates an empty System service. Appropriate parameters should be added by the caller.
|
||||
|
@ -44,6 +44,7 @@ extern "C"
|
||||
#define ESP_RMAKER_PARAM_TIMEZONE "esp.param.tz"
|
||||
#define ESP_RMAKER_PARAM_TIMEZONE_POSIX "esp.param.tz_posix"
|
||||
#define ESP_RMAKER_PARAM_SCHEDULES "esp.param.schedules"
|
||||
#define ESP_RMAKER_PARAM_SCENES "esp.param.scenes"
|
||||
#define ESP_RMAKER_PARAM_REBOOT "esp.param.reboot"
|
||||
#define ESP_RMAKER_PARAM_FACTORY_RESET "esp.param.factory-reset"
|
||||
#define ESP_RMAKER_PARAM_WIFI_RESET "esp.param.wifi-reset"
|
||||
@ -63,6 +64,7 @@ extern "C"
|
||||
#define ESP_RMAKER_SERVICE_OTA "esp.service.ota"
|
||||
#define ESP_RMAKER_SERVICE_TIME "esp.service.time"
|
||||
#define ESP_RMAKER_SERVICE_SCHEDULE "esp.service.schedule"
|
||||
#define ESP_RMAKER_SERVICE_SCENES "esp.service.scenes"
|
||||
#define ESP_RMAKER_SERVICE_SYSTEM "esp.service.system"
|
||||
#define ESP_RMAKER_SERVICE_LOCAL_CONTROL "esp.service.local_control"
|
||||
|
||||
|
@ -19,7 +19,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
FB_RGB888, FB_BGR888, FB_RGB565, FB_BGR565
|
||||
FB_RGB888, FB_BGR888, FB_RGB565, FB_BGR565, FB_GRAY
|
||||
} fb_format_t;
|
||||
|
||||
typedef struct {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user