mirror of
https://github.com/0xFEEDC0DE64/arduino-esp32.git
synced 2025-06-25 09:51:33 +02:00
Compare commits
120 Commits
Author | SHA1 | Date | |
---|---|---|---|
4638628873 | |||
6f70e27011 | |||
d0b064a1ee | |||
85c77a9c3f | |||
c8e3f0c732 | |||
5ad468f9dc | |||
38c4c06108 | |||
b334b2c2f9 | |||
8a46697168 | |||
270a2759d9 | |||
01d9345d28 | |||
71e3d515f3 | |||
64cfb33deb | |||
5f1dff7dad | |||
40ebee1cb1 | |||
ed96d2a1b7 | |||
caa391ab34 | |||
3b71e136e1 | |||
1c77790a5b | |||
5bff89f0be | |||
9bbd720d4c | |||
589bb7032d | |||
f8c06894c5 | |||
a5c873b786 | |||
895a150840 | |||
ca88fdc273 | |||
f32083a6d0 | |||
b30e55efff | |||
0ac2de7aab | |||
0eec630314 | |||
731fd19bdf | |||
298c6104a2 | |||
8ea12f89f3 | |||
b3ba80d570 | |||
a5935ce1cc | |||
96d6975bd5 | |||
9eaeeb660c | |||
e22d8b6787 | |||
56fe2dbaff | |||
06a399b84a | |||
4ce2cc3c1d | |||
07390157df | |||
bab3a70f54 | |||
cd4f9038ee | |||
7fe2812f7f | |||
9710fedaf0 | |||
f5cacfee1a | |||
f71a4bd406 | |||
5f77b0108b | |||
717ca79ecb | |||
07613b3158 | |||
80ea521940 | |||
5c04de6f39 | |||
0d163a1ce2 | |||
2a7e509978 | |||
1b8c7e34f9 | |||
7a574399b1 | |||
fd089d8fd3 | |||
f356ccd54a | |||
6daf773464 | |||
70a896481d | |||
390da0d090 | |||
d5e2bb12ca | |||
f4acac4c2b | |||
5137fc5c80 | |||
03066e42ef | |||
cd5257ad78 | |||
ee6336a312 | |||
61f71930e9 | |||
ec40c4c96f | |||
2bda4a9617 | |||
91b9fae111 | |||
2a1fde7736 | |||
a12d609b22 | |||
73576674b8 | |||
007a93ec7e | |||
a5f3fc6fad | |||
65e256c40a | |||
fa55a2c91d | |||
a070884441 | |||
a9c8b46b1a | |||
6954150176 | |||
548f712df2 | |||
56ce580b0e | |||
509d31ba51 | |||
9e32cec9a2 | |||
3376ea1bd5 | |||
1c7e329140 | |||
c17b212cd0 | |||
7dbda4988b | |||
d1134fd45e | |||
d5fdd715ef | |||
ca7106e97e | |||
87e5787cf7 | |||
c13d11e7d1 | |||
b0d8d4dd44 | |||
05de017bd5 | |||
e1548e9b7e | |||
c29ec9da3d | |||
b3783fba95 | |||
a22ec4a978 | |||
20498cf8b1 | |||
02e51728c4 | |||
d2816b2f32 | |||
2e32022611 | |||
74ffdac74a | |||
4ee17ec3ee | |||
476660f763 | |||
f558e69181 | |||
5bf3aab527 | |||
1aced120ba | |||
7d7824701f | |||
89feacb813 | |||
aae6f24a37 | |||
43b781a158 | |||
e055b28d1a | |||
714ba948e6 | |||
e57de64a3c | |||
fd5a2f08f9 | |||
e9389e3122 |
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -24,7 +24,7 @@ https://github.com/me-no-dev/EspExceptionDecoder
|
||||
|
||||
### Hardware:
|
||||
Board: ?ESP32 Dev Module? ?node32? ?ttgo_lora?
|
||||
Core Installation version: ?1.0.0? ?1.0.1-rc4? ?1.0.1? ?1.0.1-git?
|
||||
Core Installation version: ?1.0.0? ?1.0.1-rc4? ?1.0.1? ?1.0.1-git? ?1.0.2? ?1.0.3?
|
||||
IDE name: ?Arduino IDE? ?Platform.io? ?IDF component?
|
||||
Flash Frequency: ?40Mhz?
|
||||
PSRAM enabled: ?no? ?yes?
|
||||
|
@ -8,10 +8,10 @@
|
||||
|
||||
set -e
|
||||
|
||||
cd "`dirname $0`/.." # cd to arduino-esp32 root
|
||||
# pull all submodules
|
||||
git submodule update --init --recursive
|
||||
|
||||
# find all source files in repo
|
||||
#REPO_SRCS=`find cores/esp32/ libraries/ -name 'examples' -prune -o -name 'main.cpp' -prune -o -name '*.c' -print -o -name '*.cpp' -print | sort`
|
||||
REPO_SRCS=`find cores/esp32/ libraries/ -name 'examples' -prune -o -name '*.c' -print -o -name '*.cpp' -print | sort`
|
||||
|
||||
# find all source files named in CMakeLists.txt COMPONENT_SRCS
|
36
.github/scripts/install-arduino-core-esp32.sh
vendored
Executable file
36
.github/scripts/install-arduino-core-esp32.sh
vendored
Executable file
@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
|
||||
export ARDUINO_ESP32_PATH="$ARDUINO_USR_PATH/hardware/espressif/esp32"
|
||||
if [ ! -d "$ARDUINO_ESP32_PATH" ]; then
|
||||
echo "Installing ESP32 Arduino Core ..."
|
||||
script_init_path="$PWD"
|
||||
mkdir -p "$ARDUINO_USR_PATH/hardware/espressif"
|
||||
cd "$ARDUINO_USR_PATH/hardware/espressif"
|
||||
|
||||
echo "Installing Python Serial ..."
|
||||
pip install pyserial > /dev/null
|
||||
|
||||
if [ "$OS_IS_WINDOWS" == "1" ]; then
|
||||
echo "Installing Python Requests ..."
|
||||
pip install requests > /dev/null
|
||||
fi
|
||||
|
||||
if [ "$GITHUB_REPOSITORY" == "espressif/arduino-esp32" ]; then
|
||||
echo "Linking Core..."
|
||||
ln -s $GITHUB_WORKSPACE esp32
|
||||
else
|
||||
echo "Cloning Core Repository..."
|
||||
git clone https://github.com/espressif/arduino-esp32.git esp32 > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
echo "Updating Submodules ..."
|
||||
cd esp32
|
||||
git submodule update --init --recursive > /dev/null 2>&1
|
||||
|
||||
echo "Installing Platform Tools ..."
|
||||
cd tools && python get.py
|
||||
cd $script_init_path
|
||||
|
||||
echo "ESP32 Arduino has been installed in '$ARDUINO_ESP32_PATH'"
|
||||
echo ""
|
||||
fi
|
217
.github/scripts/install-arduino-ide.sh
vendored
Executable file
217
.github/scripts/install-arduino-ide.sh
vendored
Executable file
@ -0,0 +1,217 @@
|
||||
#!/bin/bash
|
||||
|
||||
#OSTYPE: 'linux-gnu', ARCH: 'x86_64' => linux64
|
||||
#OSTYPE: 'msys', ARCH: 'x86_64' => win32
|
||||
#OSTYPE: 'darwin18', ARCH: 'i386' => macos
|
||||
|
||||
OSBITS=`arch`
|
||||
if [[ "$OSTYPE" == "linux"* ]]; then
|
||||
export OS_IS_LINUX="1"
|
||||
ARCHIVE_FORMAT="tar.xz"
|
||||
if [[ "$OSBITS" == "i686" ]]; then
|
||||
OS_NAME="linux32"
|
||||
elif [[ "$OSBITS" == "x86_64" ]]; then
|
||||
OS_NAME="linux64"
|
||||
elif [[ "$OSBITS" == "armv7l" || "$OSBITS" == "aarch64" ]]; then
|
||||
OS_NAME="linuxarm"
|
||||
else
|
||||
OS_NAME="$OSTYPE-$OSBITS"
|
||||
echo "Unknown OS '$OS_NAME'"
|
||||
exit 1
|
||||
fi
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
export OS_IS_MACOS="1"
|
||||
ARCHIVE_FORMAT="zip"
|
||||
OS_NAME="macosx"
|
||||
elif [[ "$OSTYPE" == "cygwin" ]] || [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then
|
||||
export OS_IS_WINDOWS="1"
|
||||
ARCHIVE_FORMAT="zip"
|
||||
OS_NAME="windows"
|
||||
else
|
||||
OS_NAME="$OSTYPE-$OSBITS"
|
||||
echo "Unknown OS '$OS_NAME'"
|
||||
exit 1
|
||||
fi
|
||||
export OS_NAME
|
||||
|
||||
ARDUINO_BUILD_DIR="$HOME/.arduino/build.tmp"
|
||||
ARDUINO_CACHE_DIR="$HOME/.arduino/cache.tmp"
|
||||
|
||||
if [ "$OS_IS_MACOS" == "1" ]; then
|
||||
export ARDUINO_IDE_PATH="/Applications/Arduino.app/Contents/Java"
|
||||
export ARDUINO_USR_PATH="$HOME/Documents/Arduino"
|
||||
else
|
||||
export ARDUINO_IDE_PATH="$HOME/arduino_ide"
|
||||
export ARDUINO_USR_PATH="$HOME/Arduino"
|
||||
fi
|
||||
|
||||
if [ ! -d "$ARDUINO_IDE_PATH" ]; then
|
||||
echo "Installing Arduino IDE on $OS_NAME ..."
|
||||
echo "Downloading 'arduino-nightly-$OS_NAME.$ARCHIVE_FORMAT' to 'arduino.$ARCHIVE_FORMAT' ..."
|
||||
if [ "$OS_IS_LINUX" == "1" ]; then
|
||||
wget -O "arduino.$ARCHIVE_FORMAT" "https://www.arduino.cc/download.php?f=/arduino-nightly-$OS_NAME.$ARCHIVE_FORMAT" > /dev/null 2>&1
|
||||
echo "Extracting 'arduino.$ARCHIVE_FORMAT' ..."
|
||||
tar xf "arduino.$ARCHIVE_FORMAT" > /dev/null
|
||||
mv arduino-nightly "$ARDUINO_IDE_PATH"
|
||||
else
|
||||
curl -o "arduino.$ARCHIVE_FORMAT" -L "https://www.arduino.cc/download.php?f=/arduino-nightly-$OS_NAME.$ARCHIVE_FORMAT" > /dev/null 2>&1
|
||||
echo "Extracting 'arduino.$ARCHIVE_FORMAT' ..."
|
||||
unzip "arduino.$ARCHIVE_FORMAT" > /dev/null
|
||||
if [ "$OS_IS_MACOS" == "1" ]; then
|
||||
mv "Arduino.app" "/Applications/Arduino.app"
|
||||
else
|
||||
mv arduino-nightly "$ARDUINO_IDE_PATH"
|
||||
fi
|
||||
fi
|
||||
rm -rf "arduino.$ARCHIVE_FORMAT"
|
||||
|
||||
mkdir -p "$ARDUINO_USR_PATH/libraries"
|
||||
mkdir -p "$ARDUINO_USR_PATH/hardware"
|
||||
|
||||
echo "Arduino IDE Installed in '$ARDUINO_IDE_PATH'"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
function build_sketch(){ # build_sketch <fqbn> <path-to-ino> [extra-options]
|
||||
if [ "$#" -lt 2 ]; then
|
||||
echo "ERROR: Illegal number of parameters"
|
||||
echo "USAGE: build_sketch <fqbn> <path-to-ino> [extra-options]"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local fqbn="$1"
|
||||
local sketch="$2"
|
||||
local xtra_opts="$3"
|
||||
local win_opts=""
|
||||
if [ "$OS_IS_WINDOWS" == "1" ]; then
|
||||
local ctags_version=`ls "$ARDUINO_IDE_PATH/tools-builder/ctags/"`
|
||||
local preprocessor_version=`ls "$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/"`
|
||||
win_opts="-prefs=runtime.tools.ctags.path=$ARDUINO_IDE_PATH/tools-builder/ctags/$ctags_version -prefs=runtime.tools.arduino-preprocessor.path=$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/$preprocessor_version"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Compiling '"$(basename "$sketch")"' ..."
|
||||
mkdir -p "$ARDUINO_BUILD_DIR"
|
||||
mkdir -p "$ARDUINO_CACHE_DIR"
|
||||
$ARDUINO_IDE_PATH/arduino-builder -compile -logger=human -core-api-version=10810 \
|
||||
-fqbn=$fqbn \
|
||||
-warnings="all" \
|
||||
-tools "$ARDUINO_IDE_PATH/tools-builder" \
|
||||
-tools "$ARDUINO_IDE_PATH/tools" \
|
||||
-built-in-libraries "$ARDUINO_IDE_PATH/libraries" \
|
||||
-hardware "$ARDUINO_IDE_PATH/hardware" \
|
||||
-hardware "$ARDUINO_USR_PATH/hardware" \
|
||||
-libraries "$ARDUINO_USR_PATH/libraries" \
|
||||
-build-cache "$ARDUINO_CACHE_DIR" \
|
||||
-build-path "$ARDUINO_BUILD_DIR" \
|
||||
$win_opts $xtra_opts "$sketch"
|
||||
}
|
||||
|
||||
function count_sketches() # count_sketches <examples-path>
|
||||
{
|
||||
local examples="$1"
|
||||
rm -rf sketches.txt
|
||||
if [ ! -d "$examples" ]; then
|
||||
touch sketches.txt
|
||||
return 0
|
||||
fi
|
||||
local sketches=$(find $examples -name *.ino)
|
||||
local sketchnum=0
|
||||
for sketch in $sketches; do
|
||||
local sketchdir=$(dirname $sketch)
|
||||
local sketchdirname=$(basename $sketchdir)
|
||||
local sketchname=$(basename $sketch)
|
||||
if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then
|
||||
continue
|
||||
fi;
|
||||
if [[ -f "$sketchdir/.test.skip" ]]; then
|
||||
continue
|
||||
fi
|
||||
echo $sketch >> sketches.txt
|
||||
sketchnum=$(($sketchnum + 1))
|
||||
done
|
||||
return $sketchnum
|
||||
}
|
||||
|
||||
function build_sketches() # build_sketches <fqbn> <examples-path> <chunk> <total-chunks> [extra-options]
|
||||
{
|
||||
local fqbn=$1
|
||||
local examples=$2
|
||||
local chunk_idex=$3
|
||||
local chunks_num=$4
|
||||
local xtra_opts=$5
|
||||
|
||||
if [ "$#" -lt 2 ]; then
|
||||
echo "ERROR: Illegal number of parameters"
|
||||
echo "USAGE: build_sketches <fqbn> <examples-path> [<chunk> <total-chunks>] [extra-options]"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$#" -lt 4 ]; then
|
||||
chunk_idex="0"
|
||||
chunks_num="1"
|
||||
xtra_opts=$3
|
||||
fi
|
||||
|
||||
if [ "$chunks_num" -le 0 ]; then
|
||||
echo "ERROR: Chunks count must be positive number"
|
||||
return 1
|
||||
fi
|
||||
if [ "$chunk_idex" -ge "$chunks_num" ]; then
|
||||
echo "ERROR: Chunk index must be less than chunks count"
|
||||
return 1
|
||||
fi
|
||||
|
||||
set +e
|
||||
count_sketches "$examples"
|
||||
local sketchcount=$?
|
||||
set -e
|
||||
local sketches=$(cat sketches.txt)
|
||||
rm -rf sketches.txt
|
||||
|
||||
local chunk_size=$(( $sketchcount / $chunks_num ))
|
||||
local all_chunks=$(( $chunks_num * $chunk_size ))
|
||||
if [ "$all_chunks" -lt "$sketchcount" ]; then
|
||||
chunk_size=$(( $chunk_size + 1 ))
|
||||
fi
|
||||
|
||||
local start_index=$(( $chunk_idex * $chunk_size ))
|
||||
if [ "$sketchcount" -le "$start_index" ]; then
|
||||
echo "Skipping job"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local end_index=$(( $(( $chunk_idex + 1 )) * $chunk_size ))
|
||||
if [ "$end_index" -gt "$sketchcount" ]; then
|
||||
end_index=$sketchcount
|
||||
fi
|
||||
|
||||
local start_num=$(( $start_index + 1 ))
|
||||
echo "Found $sketchcount Sketches";
|
||||
echo "Chunk Count : $chunks_num"
|
||||
echo "Chunk Size : $chunk_size"
|
||||
echo "Start Sketch: $start_num"
|
||||
echo "End Sketch : $end_index"
|
||||
|
||||
local sketchnum=0
|
||||
for sketch in $sketches; do
|
||||
local sketchdir=$(dirname $sketch)
|
||||
local sketchdirname=$(basename $sketchdir)
|
||||
local sketchname=$(basename $sketch)
|
||||
if [ "${sketchdirname}.ino" != "$sketchname" ] \
|
||||
|| [ -f "$sketchdir/.test.skip" ]; then
|
||||
continue
|
||||
fi
|
||||
sketchnum=$(($sketchnum + 1))
|
||||
if [ "$sketchnum" -le "$start_index" ] \
|
||||
|| [ "$sketchnum" -gt "$end_index" ]; then
|
||||
continue
|
||||
fi
|
||||
build_sketch "$fqbn" "$sketch" "$xtra_opts"
|
||||
local result=$?
|
||||
if [ $result -ne 0 ]; then
|
||||
return $result
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
}
|
153
.github/scripts/install-platformio-esp32.sh
vendored
Executable file
153
.github/scripts/install-platformio-esp32.sh
vendored
Executable file
@ -0,0 +1,153 @@
|
||||
#!/bin/bash
|
||||
|
||||
export PLATFORMIO_ESP32_PATH="$HOME/.platformio/packages/framework-arduinoespressif32"
|
||||
|
||||
echo "Installing Python Wheel ..."
|
||||
pip install wheel > /dev/null 2>&1
|
||||
|
||||
echo "Installing PlatformIO ..."
|
||||
pip install -U https://github.com/platformio/platformio/archive/develop.zip > /dev/null 2>&1
|
||||
|
||||
echo "Installing Platform ESP32 ..."
|
||||
python -m platformio platform install https://github.com/platformio/platform-espressif32.git#feature/stage > /dev/null 2>&1
|
||||
|
||||
echo "Replacing the framework version ..."
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
sed 's/https:\/\/github\.com\/espressif\/arduino-esp32\.git/*/' "$HOME/.platformio/platforms/espressif32/platform.json" > "platform.json"
|
||||
mv -f "platform.json" "$HOME/.platformio/platforms/espressif32/platform.json"
|
||||
else
|
||||
sed -i 's/https:\/\/github\.com\/espressif\/arduino-esp32\.git/*/' "$HOME/.platformio/platforms/espressif32/platform.json"
|
||||
fi
|
||||
|
||||
if [ "$GITHUB_REPOSITORY" == "espressif/arduino-esp32" ]; then
|
||||
echo "Linking Core..."
|
||||
ln -s $GITHUB_WORKSPACE "$PLATFORMIO_ESP32_PATH"
|
||||
else
|
||||
echo "Cloning Core Repository ..."
|
||||
git clone https://github.com/espressif/arduino-esp32.git "$PLATFORMIO_ESP32_PATH" > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
echo "PlatformIO for ESP32 has been installed"
|
||||
echo ""
|
||||
|
||||
function build_pio_sketch(){ # build_pio_sketch <board> <path-to-ino>
|
||||
if [ "$#" -lt 2 ]; then
|
||||
echo "ERROR: Illegal number of parameters"
|
||||
echo "USAGE: build_pio_sketch <board> <path-to-ino>"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local board="$1"
|
||||
local sketch="$2"
|
||||
local sketch_dir=$(dirname "$sketch")
|
||||
echo ""
|
||||
echo "Compiling '"$(basename "$sketch")"' ..."
|
||||
python -m platformio ci --board "$board" "$sketch_dir" --project-option="board_build.partitions = huge_app.csv"
|
||||
}
|
||||
|
||||
function count_sketches() # count_sketches <examples-path>
|
||||
{
|
||||
local examples="$1"
|
||||
rm -rf sketches.txt
|
||||
if [ ! -d "$examples" ]; then
|
||||
touch sketches.txt
|
||||
return 0
|
||||
fi
|
||||
local sketches=$(find $examples -name *.ino)
|
||||
local sketchnum=0
|
||||
for sketch in $sketches; do
|
||||
local sketchdir=$(dirname $sketch)
|
||||
local sketchdirname=$(basename $sketchdir)
|
||||
local sketchname=$(basename $sketch)
|
||||
if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then
|
||||
continue
|
||||
fi;
|
||||
if [[ -f "$sketchdir/.test.skip" ]]; then
|
||||
continue
|
||||
fi
|
||||
echo $sketch >> sketches.txt
|
||||
sketchnum=$(($sketchnum + 1))
|
||||
done
|
||||
return $sketchnum
|
||||
}
|
||||
|
||||
function build_pio_sketches() # build_pio_sketches <board> <examples-path> <chunk> <total-chunks>
|
||||
{
|
||||
if [ "$#" -lt 2 ]; then
|
||||
echo "ERROR: Illegal number of parameters"
|
||||
echo "USAGE: build_pio_sketches <board> <examples-path> [<chunk> <total-chunks>]"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local board=$1
|
||||
local examples=$2
|
||||
local chunk_idex=$3
|
||||
local chunks_num=$4
|
||||
|
||||
if [ "$#" -lt 4 ]; then
|
||||
chunk_idex="0"
|
||||
chunks_num="1"
|
||||
fi
|
||||
|
||||
if [ "$chunks_num" -le 0 ]; then
|
||||
echo "ERROR: Chunks count must be positive number"
|
||||
return 1
|
||||
fi
|
||||
if [ "$chunk_idex" -ge "$chunks_num" ]; then
|
||||
echo "ERROR: Chunk index must be less than chunks count"
|
||||
return 1
|
||||
fi
|
||||
|
||||
set +e
|
||||
count_sketches "$examples"
|
||||
local sketchcount=$?
|
||||
set -e
|
||||
local sketches=$(cat sketches.txt)
|
||||
rm -rf sketches.txt
|
||||
|
||||
local chunk_size=$(( $sketchcount / $chunks_num ))
|
||||
local all_chunks=$(( $chunks_num * $chunk_size ))
|
||||
if [ "$all_chunks" -lt "$sketchcount" ]; then
|
||||
chunk_size=$(( $chunk_size + 1 ))
|
||||
fi
|
||||
|
||||
local start_index=$(( $chunk_idex * $chunk_size ))
|
||||
if [ "$sketchcount" -le "$start_index" ]; then
|
||||
echo "Skipping job"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local end_index=$(( $(( $chunk_idex + 1 )) * $chunk_size ))
|
||||
if [ "$end_index" -gt "$sketchcount" ]; then
|
||||
end_index=$sketchcount
|
||||
fi
|
||||
|
||||
local start_num=$(( $start_index + 1 ))
|
||||
echo "Found $sketchcount Sketches";
|
||||
echo "Chunk Count : $chunks_num"
|
||||
echo "Chunk Size : $chunk_size"
|
||||
echo "Start Sketch: $start_num"
|
||||
echo "End Sketch : $end_index"
|
||||
|
||||
local sketchnum=0
|
||||
for sketch in $sketches; do
|
||||
local sketchdir=$(dirname $sketch)
|
||||
local sketchdirname=$(basename $sketchdir)
|
||||
local sketchname=$(basename $sketch)
|
||||
if [ "${sketchdirname}.ino" != "$sketchname" ] \
|
||||
|| [ -f "$sketchdir/.test.skip" ]; then
|
||||
continue
|
||||
fi
|
||||
sketchnum=$(($sketchnum + 1))
|
||||
if [ "$sketchnum" -le "$start_index" ] \
|
||||
|| [ "$sketchnum" -gt "$end_index" ]; then
|
||||
continue
|
||||
fi
|
||||
build_pio_sketch "$board" "$sketch"
|
||||
local result=$?
|
||||
if [ $result -ne 0 ]; then
|
||||
return $result
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
}
|
6
package/merge_packages.py → .github/scripts/merge_packages.py
vendored
Normal file → Executable file
6
package/merge_packages.py → .github/scripts/merge_packages.py
vendored
Normal file → Executable file
@ -36,7 +36,11 @@ def pkgVersionNormalized(versionString):
|
||||
verParts = re.split('\.|-rc', verStr, flags=re.IGNORECASE)
|
||||
|
||||
if len(verParts) == 3:
|
||||
verStr = str(versionString) + '-rc' + str(sys.maxint)
|
||||
if (sys.version_info > (3, 0)): # Python 3
|
||||
verStr = str(versionString) + '-rc' + str(sys.maxsize)
|
||||
else: # Python 2
|
||||
verStr = str(versionString) + '-rc' + str(sys.maxint)
|
||||
|
||||
elif len(verParts) != 4:
|
||||
print("pkgVersionNormalized WARNING: unexpected version format: {0})".format(verStr), file=sys.stderr)
|
||||
|
131
.github/scripts/on-pages.sh
vendored
Normal file
131
.github/scripts/on-pages.sh
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
#/bin/bash
|
||||
set -e
|
||||
|
||||
function get_file_size(){
|
||||
local file="$1"
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
eval `stat -s "$file"`
|
||||
local res="$?"
|
||||
echo "$st_size"
|
||||
return $res
|
||||
else
|
||||
stat --printf="%s" "$file"
|
||||
return $?
|
||||
fi
|
||||
}
|
||||
|
||||
#git_remove_from_pages <file>
|
||||
function git_remove_from_pages(){
|
||||
local path=$1
|
||||
local info=`curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages"`
|
||||
local type=`echo "$info" | jq -r '.type'`
|
||||
if [ ! $type == "file" ]; then
|
||||
if [ ! $type == "null" ]; then
|
||||
echo "Wrong type '$type'"
|
||||
else
|
||||
echo "File is not on Pages"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
local sha=`echo "$info" | jq -r '.sha'`
|
||||
local message="Deleting "$(basename $path)
|
||||
local json="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"sha\":\"$sha\"}"
|
||||
echo "$json" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X DELETE --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path"
|
||||
}
|
||||
|
||||
function git_upload_to_pages(){
|
||||
local path=$1
|
||||
local src=$2
|
||||
|
||||
if [ ! -f "$src" ]; then
|
||||
>&2 echo "Input is not a file! Aborting..."
|
||||
return 1
|
||||
fi
|
||||
|
||||
local info=`curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages"`
|
||||
local type=`echo "$info" | jq -r '.type'`
|
||||
local message=$(basename $path)
|
||||
local sha=""
|
||||
local content=""
|
||||
|
||||
if [ $type == "file" ]; then
|
||||
sha=`echo "$info" | jq -r '.sha'`
|
||||
sha=",\"sha\":\"$sha\""
|
||||
message="Updating $message"
|
||||
elif [ ! $type == "null" ]; then
|
||||
>&2 echo "Wrong type '$type'"
|
||||
return 1
|
||||
else
|
||||
message="Creating $message"
|
||||
fi
|
||||
|
||||
content=`base64 -i "$src"`
|
||||
data="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"content\":\"$content\"$sha}"
|
||||
|
||||
echo "$data" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X PUT --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path"
|
||||
}
|
||||
|
||||
function git_safe_upload_to_pages(){
|
||||
local path=$1
|
||||
local file="$2"
|
||||
local name=$(basename "$file")
|
||||
local size=`get_file_size "$file"`
|
||||
local upload_res=`git_upload_to_pages "$path" "$file"`
|
||||
if [ $? -ne 0 ]; then
|
||||
>&2 echo "ERROR: Failed to upload '$name' ($?)"
|
||||
return 1
|
||||
fi
|
||||
up_size=`echo "$upload_res" | jq -r '.content.size'`
|
||||
if [ $up_size -ne $size ]; then
|
||||
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
|
||||
#git_delete_asset
|
||||
return 1
|
||||
fi
|
||||
echo "$upload_res" | jq -r '.content.download_url'
|
||||
return $?
|
||||
}
|
||||
|
||||
EVENT_JSON=`cat $GITHUB_EVENT_PATH`
|
||||
|
||||
pages_added=`echo "$EVENT_JSON" | jq -r '.commits[].added[]'`
|
||||
pages_modified=`echo "$EVENT_JSON" | jq -r '.commits[].modified[]'`
|
||||
pages_removed=`echo "$EVENT_JSON" | jq -r '.commits[].removed[]'`
|
||||
|
||||
for page in $pages_added; do
|
||||
if [[ $page != "README.md" && $page != "docs/"* ]]; then
|
||||
continue
|
||||
fi
|
||||
echo "Adding '$page' to pages ..."
|
||||
if [[ $page == "README.md" ]]; then
|
||||
git_safe_upload_to_pages "index.md" "README.md"
|
||||
else
|
||||
git_safe_upload_to_pages "$page" "$page"
|
||||
fi
|
||||
done
|
||||
|
||||
for page in $pages_modified; do
|
||||
if [[ $page != "README.md" && $page != "docs/"* ]]; then
|
||||
continue
|
||||
fi
|
||||
echo "Modifying '$page' ..."
|
||||
if [[ $page == "README.md" ]]; then
|
||||
git_safe_upload_to_pages "index.md" "README.md"
|
||||
else
|
||||
git_safe_upload_to_pages "$page" "$page"
|
||||
fi
|
||||
done
|
||||
|
||||
for page in $pages_removed; do
|
||||
if [[ $page != "README.md" && $page != "docs/"* ]]; then
|
||||
continue
|
||||
fi
|
||||
echo "Removing '$page' from pages ..."
|
||||
if [[ $page == "README.md" ]]; then
|
||||
git_remove_from_pages "README.md" > /dev/null
|
||||
else
|
||||
git_remove_from_pages "$page" > /dev/null
|
||||
fi
|
||||
done
|
||||
|
||||
echo
|
||||
echo "DONE!"
|
71
.github/scripts/on-push.sh
vendored
Executable file
71
.github/scripts/on-push.sh
vendored
Executable file
@ -0,0 +1,71 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ ! -z "$TRAVIS_TAG" ]; then
|
||||
echo "Skipping Test: Tagged build"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ ! -z "$GITHUB_WORKSPACE" ]; then
|
||||
export TRAVIS_BUILD_DIR="$GITHUB_WORKSPACE"
|
||||
export TRAVIS_REPO_SLUG="$GITHUB_REPOSITORY"
|
||||
elif [ ! -z "$TRAVIS_BUILD_DIR" ]; then
|
||||
export GITHUB_WORKSPACE="$TRAVIS_BUILD_DIR"
|
||||
export GITHUB_REPOSITORY="$TRAVIS_REPO_SLUG"
|
||||
else
|
||||
export GITHUB_WORKSPACE="$PWD"
|
||||
export GITHUB_REPOSITORY="espressif/arduino-esp32"
|
||||
fi
|
||||
|
||||
CHUNK_INDEX=$1
|
||||
CHUNKS_CNT=$2
|
||||
BUILD_PIO=0
|
||||
if [ "$#" -lt 2 ] || [ "$CHUNKS_CNT" -le 0 ]; then
|
||||
CHUNK_INDEX=0
|
||||
CHUNKS_CNT=1
|
||||
elif [ "$CHUNK_INDEX" -gt "$CHUNKS_CNT" ]; then
|
||||
CHUNK_INDEX=$CHUNKS_CNT
|
||||
elif [ "$CHUNK_INDEX" -eq "$CHUNKS_CNT" ]; then
|
||||
BUILD_PIO=1
|
||||
fi
|
||||
|
||||
echo "Updating submodules ..."
|
||||
git -C "$GITHUB_WORKSPACE" submodule update --init --recursive > /dev/null 2>&1
|
||||
|
||||
if [ "$BUILD_PIO" -eq 0 ]; then
|
||||
# ArduinoIDE Test
|
||||
FQBN="espressif:esp32:esp32:PSRAM=enabled,PartitionScheme=huge_app"
|
||||
source ./.github/scripts/install-arduino-ide.sh
|
||||
source ./.github/scripts/install-arduino-core-esp32.sh
|
||||
if [ "$OS_IS_WINDOWS" == "1" ]; then
|
||||
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino" && \
|
||||
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/BLE/examples/BLE_server/BLE_server.ino" && \
|
||||
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/AzureIoT/examples/GetStarted/GetStarted.ino" && \
|
||||
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino"
|
||||
elif [ "$OS_IS_MACOS" == "1" ]; then
|
||||
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFi/examples/WiFiClient/WiFiClient.ino" && \
|
||||
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino" && \
|
||||
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/BluetoothSerial/examples/SerialToSerialBT/SerialToSerialBT.ino" && \
|
||||
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/BLE/examples/BLE_server/BLE_server.ino" && \
|
||||
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/AzureIoT/examples/GetStarted/GetStarted.ino" && \
|
||||
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino"
|
||||
else
|
||||
# CMake Test
|
||||
if [ "$CHUNK_INDEX" -eq 0 ]; then
|
||||
bash "$ARDUINO_ESP32_PATH/.github/scripts/check-cmakelists.sh"
|
||||
fi
|
||||
build_sketches "$FQBN" "$ARDUINO_ESP32_PATH/libraries" "$CHUNK_INDEX" "$CHUNKS_CNT"
|
||||
fi
|
||||
else
|
||||
# PlatformIO Test
|
||||
source ./.github/scripts/install-platformio-esp32.sh
|
||||
BOARD="esp32dev"
|
||||
build_pio_sketch "$BOARD" "$PLATFORMIO_ESP32_PATH/libraries/WiFi/examples/WiFiClient/WiFiClient.ino" && \
|
||||
build_pio_sketch "$BOARD" "$PLATFORMIO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino" && \
|
||||
build_pio_sketch "$BOARD" "$PLATFORMIO_ESP32_PATH/libraries/BluetoothSerial/examples/SerialToSerialBT/SerialToSerialBT.ino" && \
|
||||
build_pio_sketch "$BOARD" "$PLATFORMIO_ESP32_PATH/libraries/BLE/examples/BLE_server/BLE_server.ino" && \
|
||||
build_pio_sketch "$BOARD" "$PLATFORMIO_ESP32_PATH/libraries/AzureIoT/examples/GetStarted/GetStarted.ino" && \
|
||||
build_pio_sketch "$BOARD" "$PLATFORMIO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino"
|
||||
#build_pio_sketches esp32dev "$PLATFORMIO_ESP32_PATH/libraries"
|
||||
fi
|
380
.github/scripts/on-release.sh
vendored
Executable file
380
.github/scripts/on-release.sh
vendored
Executable file
@ -0,0 +1,380 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! $GITHUB_EVENT_NAME == "release" ]; then
|
||||
echo "Wrong event '$GITHUB_EVENT_NAME'!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
EVENT_JSON=`cat $GITHUB_EVENT_PATH`
|
||||
|
||||
action=`echo $EVENT_JSON | jq -r '.action'`
|
||||
if [ ! $action == "published" ]; then
|
||||
echo "Wrong action '$action'. Exiting now..."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
draft=`echo $EVENT_JSON | jq -r '.release.draft'`
|
||||
if [ $draft == "true" ]; then
|
||||
echo "It's a draft release. Exiting now..."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
RELEASE_PRE=`echo $EVENT_JSON | jq -r '.release.prerelease'`
|
||||
RELEASE_TAG=`echo $EVENT_JSON | jq -r '.release.tag_name'`
|
||||
RELEASE_BRANCH=`echo $EVENT_JSON | jq -r '.release.target_commitish'`
|
||||
RELEASE_ID=`echo $EVENT_JSON | jq -r '.release.id'`
|
||||
RELEASE_BODY=`echo $EVENT_JSON | jq -r '.release.body'`
|
||||
|
||||
OUTPUT_DIR="$GITHUB_WORKSPACE/build"
|
||||
PACKAGE_NAME="esp32-$RELEASE_TAG"
|
||||
PACKAGE_JSON_MERGE="$GITHUB_WORKSPACE/.github/scripts/merge_packages.py"
|
||||
PACKAGE_JSON_TEMPLATE="$GITHUB_WORKSPACE/package/package_esp32_index.template.json"
|
||||
PACKAGE_JSON_DEV="package_esp32_dev_index.json"
|
||||
PACKAGE_JSON_REL="package_esp32_index.json"
|
||||
|
||||
echo "Event: $GITHUB_EVENT_NAME, Repo: $GITHUB_REPOSITORY, Path: $GITHUB_WORKSPACE, Ref: $GITHUB_REF"
|
||||
echo "Action: $action, Branch: $RELEASE_BRANCH, ID: $RELEASE_ID"
|
||||
echo "Tag: $RELEASE_TAG, Draft: $draft, Pre-Release: $RELEASE_PRE"
|
||||
|
||||
function get_file_size(){
|
||||
local file="$1"
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
eval `stat -s "$file"`
|
||||
local res="$?"
|
||||
echo "$st_size"
|
||||
return $res
|
||||
else
|
||||
stat --printf="%s" "$file"
|
||||
return $?
|
||||
fi
|
||||
}
|
||||
|
||||
function git_upload_asset(){
|
||||
local name=$(basename "$1")
|
||||
# local mime=$(file -b --mime-type "$1")
|
||||
curl -k -X POST -sH "Authorization: token $GITHUB_TOKEN" -H "Content-Type: application/octet-stream" --data-binary @"$1" "https://uploads.github.com/repos/$GITHUB_REPOSITORY/releases/$RELEASE_ID/assets?name=$name"
|
||||
}
|
||||
|
||||
function git_safe_upload_asset(){
|
||||
local file="$1"
|
||||
local name=$(basename "$file")
|
||||
local size=`get_file_size "$file"`
|
||||
local upload_res=`git_upload_asset "$file"`
|
||||
if [ $? -ne 0 ]; then
|
||||
>&2 echo "ERROR: Failed to upload '$name' ($?)"
|
||||
return 1
|
||||
fi
|
||||
up_size=`echo "$upload_res" | jq -r '.size'`
|
||||
if [ $up_size -ne $size ]; then
|
||||
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
|
||||
#git_delete_asset
|
||||
return 1
|
||||
fi
|
||||
echo "$upload_res" | jq -r '.browser_download_url'
|
||||
return $?
|
||||
}
|
||||
|
||||
function git_upload_to_pages(){
|
||||
local path=$1
|
||||
local src=$2
|
||||
|
||||
if [ ! -f "$src" ]; then
|
||||
>&2 echo "Input is not a file! Aborting..."
|
||||
return 1
|
||||
fi
|
||||
|
||||
local info=`curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages"`
|
||||
local type=`echo "$info" | jq -r '.type'`
|
||||
local message=$(basename $path)
|
||||
local sha=""
|
||||
local content=""
|
||||
|
||||
if [ $type == "file" ]; then
|
||||
sha=`echo "$info" | jq -r '.sha'`
|
||||
sha=",\"sha\":\"$sha\""
|
||||
message="Updating $message"
|
||||
elif [ ! $type == "null" ]; then
|
||||
>&2 echo "Wrong type '$type'"
|
||||
return 1
|
||||
else
|
||||
message="Creating $message"
|
||||
fi
|
||||
|
||||
content=`base64 -i "$src"`
|
||||
data="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"content\":\"$content\"$sha}"
|
||||
|
||||
echo "$data" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X PUT --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path"
|
||||
}
|
||||
|
||||
function git_safe_upload_to_pages(){
|
||||
local path=$1
|
||||
local file="$2"
|
||||
local name=$(basename "$file")
|
||||
local size=`get_file_size "$file"`
|
||||
local upload_res=`git_upload_to_pages "$path" "$file"`
|
||||
if [ $? -ne 0 ]; then
|
||||
>&2 echo "ERROR: Failed to upload '$name' ($?)"
|
||||
return 1
|
||||
fi
|
||||
up_size=`echo "$upload_res" | jq -r '.content.size'`
|
||||
if [ $up_size -ne $size ]; then
|
||||
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
|
||||
#git_delete_asset
|
||||
return 1
|
||||
fi
|
||||
echo "$upload_res" | jq -r '.content.download_url'
|
||||
return $?
|
||||
}
|
||||
|
||||
function merge_package_json(){
|
||||
local jsonLink=$1
|
||||
local jsonOut=$2
|
||||
local old_json=$OUTPUT_DIR/oldJson.json
|
||||
local merged_json=$OUTPUT_DIR/mergedJson.json
|
||||
|
||||
echo "Downloading previous JSON $jsonLink ..."
|
||||
curl -L -o "$old_json" "https://github.com/$GITHUB_REPOSITORY/releases/download/$jsonLink?access_token=$GITHUB_TOKEN" 2>/dev/null
|
||||
if [ $? -ne 0 ]; then echo "ERROR: Download Failed! $?"; exit 1; fi
|
||||
|
||||
echo "Creating new JSON ..."
|
||||
set +e
|
||||
stdbuf -oL python "$PACKAGE_JSON_MERGE" "$jsonOut" "$old_json" > "$merged_json"
|
||||
set -e
|
||||
|
||||
set -v
|
||||
if [ ! -s $merged_json ]; then
|
||||
rm -f "$merged_json"
|
||||
echo "Nothing to merge"
|
||||
else
|
||||
rm -f "$jsonOut"
|
||||
mv "$merged_json" "$jsonOut"
|
||||
echo "JSON data successfully merged"
|
||||
fi
|
||||
rm -f "$old_json"
|
||||
set +v
|
||||
}
|
||||
|
||||
set -e
|
||||
|
||||
##
|
||||
## PACKAGE ZIP
|
||||
##
|
||||
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
PKG_DIR="$OUTPUT_DIR/$PACKAGE_NAME"
|
||||
PACKAGE_ZIP="$PACKAGE_NAME.zip"
|
||||
|
||||
echo "Updating submodules ..."
|
||||
git -C "$GITHUB_WORKSPACE" submodule update --init --recursive > /dev/null 2>&1
|
||||
|
||||
mkdir -p "$PKG_DIR/tools"
|
||||
|
||||
# Copy all core files to the package folder
|
||||
echo "Copying files for packaging ..."
|
||||
cp -f "$GITHUB_WORKSPACE/boards.txt" "$PKG_DIR/"
|
||||
cp -f "$GITHUB_WORKSPACE/programmers.txt" "$PKG_DIR/"
|
||||
cp -Rf "$GITHUB_WORKSPACE/cores" "$PKG_DIR/"
|
||||
cp -Rf "$GITHUB_WORKSPACE/libraries" "$PKG_DIR/"
|
||||
cp -Rf "$GITHUB_WORKSPACE/variants" "$PKG_DIR/"
|
||||
cp -f "$GITHUB_WORKSPACE/tools/espota.exe" "$PKG_DIR/tools/"
|
||||
cp -f "$GITHUB_WORKSPACE/tools/espota.py" "$PKG_DIR/tools/"
|
||||
cp -f "$GITHUB_WORKSPACE/tools/esptool.py" "$PKG_DIR/tools/"
|
||||
cp -f "$GITHUB_WORKSPACE/tools/gen_esp32part.py" "$PKG_DIR/tools/"
|
||||
cp -f "$GITHUB_WORKSPACE/tools/gen_esp32part.exe" "$PKG_DIR/tools/"
|
||||
cp -Rf "$GITHUB_WORKSPACE/tools/partitions" "$PKG_DIR/tools/"
|
||||
cp -Rf "$GITHUB_WORKSPACE/tools/sdk" "$PKG_DIR/tools/"
|
||||
|
||||
# Remove unnecessary files in the package folder
|
||||
echo "Cleaning up folders ..."
|
||||
find "$PKG_DIR" -name '*.DS_Store' -exec rm -f {} \;
|
||||
find "$PKG_DIR" -name '*.git*' -type f -delete
|
||||
|
||||
# Replace tools locations in platform.txt
|
||||
echo "Generating platform.txt..."
|
||||
cat "$GITHUB_WORKSPACE/platform.txt" | \
|
||||
sed "s/version=.*/version=$ver$extent/g" | \
|
||||
sed 's/runtime.tools.xtensa-esp32-elf-gcc.path={runtime.platform.path}\/tools\/xtensa-esp32-elf//g' | \
|
||||
sed 's/tools.esptool_py.path={runtime.platform.path}\/tools\/esptool/tools.esptool_py.path=\{runtime.tools.esptool_py.path\}/g' \
|
||||
> "$PKG_DIR/platform.txt"
|
||||
|
||||
# Add header with version information
|
||||
echo "Generating core_version.h ..."
|
||||
ver_define=`echo $RELEASE_TAG | tr "[:lower:].\055" "[:upper:]_"`
|
||||
ver_hex=`git -C "$GITHUB_WORKSPACE" rev-parse --short=8 HEAD 2>/dev/null`
|
||||
echo \#define ARDUINO_ESP32_GIT_VER 0x$ver_hex > "$PKG_DIR/cores/esp32/core_version.h"
|
||||
echo \#define ARDUINO_ESP32_GIT_DESC `git -C "$GITHUB_WORKSPACE" describe --tags 2>/dev/null` >> "$PKG_DIR/cores/esp32/core_version.h"
|
||||
echo \#define ARDUINO_ESP32_RELEASE_$ver_define >> "$PKG_DIR/cores/esp32/core_version.h"
|
||||
echo \#define ARDUINO_ESP32_RELEASE \"$ver_define\" >> "$PKG_DIR/cores/esp32/core_version.h"
|
||||
|
||||
# Compress package folder
|
||||
echo "Creating ZIP ..."
|
||||
pushd "$OUTPUT_DIR" >/dev/null
|
||||
zip -qr "$PACKAGE_ZIP" "$PACKAGE_NAME"
|
||||
if [ $? -ne 0 ]; then echo "ERROR: Failed to create $PACKAGE_ZIP ($?)"; exit 1; fi
|
||||
|
||||
# Calculate SHA-256
|
||||
echo "Calculating SHA sum ..."
|
||||
PACKAGE_PATH="$OUTPUT_DIR/$PACKAGE_ZIP"
|
||||
PACKAGE_SHA=`shasum -a 256 "$PACKAGE_ZIP" | cut -f 1 -d ' '`
|
||||
PACKAGE_SIZE=`get_file_size "$PACKAGE_ZIP"`
|
||||
popd >/dev/null
|
||||
rm -rf "$PKG_DIR"
|
||||
echo "'$PACKAGE_ZIP' Created! Size: $PACKAGE_SIZE, SHA-256: $PACKAGE_SHA"
|
||||
echo
|
||||
|
||||
# Upload package to release page
|
||||
echo "Uploading package to release page ..."
|
||||
PACKAGE_URL=`git_safe_upload_asset "$PACKAGE_PATH"`
|
||||
echo "Package Uploaded"
|
||||
echo "Download URL: $PACKAGE_URL"
|
||||
echo
|
||||
|
||||
##
|
||||
## PACKAGE JSON
|
||||
##
|
||||
|
||||
# Construct JQ argument with package data
|
||||
jq_arg=".packages[0].platforms[0].version = \"$RELEASE_TAG\" | \
|
||||
.packages[0].platforms[0].url = \"$PACKAGE_URL\" |\
|
||||
.packages[0].platforms[0].archiveFileName = \"$PACKAGE_ZIP\" |\
|
||||
.packages[0].platforms[0].size = \"$PACKAGE_SIZE\" |\
|
||||
.packages[0].platforms[0].checksum = \"SHA-256:$PACKAGE_SHA\""
|
||||
|
||||
# Generate package JSONs
|
||||
echo "Genarating $PACKAGE_JSON_DEV ..."
|
||||
cat "$PACKAGE_JSON_TEMPLATE" | jq "$jq_arg" > "$OUTPUT_DIR/$PACKAGE_JSON_DEV"
|
||||
if [ "$RELEASE_PRE" == "false" ]; then
|
||||
echo "Genarating $PACKAGE_JSON_REL ..."
|
||||
cat "$PACKAGE_JSON_TEMPLATE" | jq "$jq_arg" > "$OUTPUT_DIR/$PACKAGE_JSON_REL"
|
||||
fi
|
||||
|
||||
# Figure out the last release or pre-release
|
||||
echo "Getting previous releases ..."
|
||||
releasesJson=`curl -sH "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/$GITHUB_REPOSITORY/releases" 2>/dev/null`
|
||||
if [ $? -ne 0 ]; then echo "ERROR: Get Releases Failed! ($?)"; exit 1; fi
|
||||
|
||||
set +e
|
||||
prev_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false and .prerelease == false)) | sort_by(.created_at | - fromdateiso8601) | .[0].tag_name')
|
||||
prev_any_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false)) | sort_by(.created_at | - fromdateiso8601) | .[0].tag_name')
|
||||
shopt -s nocasematch
|
||||
if [ "$prev_any_release" == "$RELEASE_TAG" ]; then
|
||||
prev_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false and .prerelease == false)) | sort_by(.created_at | - fromdateiso8601) | .[1].tag_name')
|
||||
prev_any_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false)) | sort_by(.created_at | - fromdateiso8601) | .[1].tag_name')
|
||||
fi
|
||||
COMMITS_SINCE_RELEASE="$prev_any_release"
|
||||
shopt -u nocasematch
|
||||
set -e
|
||||
|
||||
# Merge package JSONs with previous releases
|
||||
if [ ! -z "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then
|
||||
echo "Merging with JSON from $prev_any_release ..."
|
||||
merge_package_json "$prev_any_release/$PACKAGE_JSON_DEV" "$OUTPUT_DIR/$PACKAGE_JSON_DEV"
|
||||
fi
|
||||
|
||||
if [ "$RELEASE_PRE" == "false" ]; then
|
||||
COMMITS_SINCE_RELEASE="$prev_release"
|
||||
if [ ! -z "$prev_release" ] && [ "$prev_release" != "null" ]; then
|
||||
echo "Merging with JSON from $prev_release ..."
|
||||
merge_package_json "$prev_release/$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Previous Release: $prev_release"
|
||||
echo "Previous (any)release: $prev_any_release"
|
||||
echo
|
||||
|
||||
# Upload package JSONs
|
||||
echo "Uploading $PACKAGE_JSON_DEV ..."
|
||||
echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_DEV"`
|
||||
echo "Pages URL: "`git_safe_upload_to_pages "$PACKAGE_JSON_DEV" "$OUTPUT_DIR/$PACKAGE_JSON_DEV"`
|
||||
echo
|
||||
if [ "$RELEASE_PRE" == "false" ]; then
|
||||
echo "Uploading $PACKAGE_JSON_REL ..."
|
||||
echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_REL"`
|
||||
echo "Pages URL: "`git_safe_upload_to_pages "$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL"`
|
||||
echo
|
||||
fi
|
||||
|
||||
##
|
||||
## RELEASE NOTES
|
||||
##
|
||||
|
||||
# Create release notes
|
||||
echo "Preparing release notes ..."
|
||||
releaseNotes=""
|
||||
|
||||
# Process annotated tags
|
||||
relNotesRaw=`git -C "$GITHUB_WORKSPACE" show -s --format=%b $RELEASE_TAG`
|
||||
readarray -t msgArray <<<"$relNotesRaw"
|
||||
arrLen=${#msgArray[@]}
|
||||
if [ $arrLen > 3 ] && [ "${msgArray[0]:0:3}" == "tag" ]; then
|
||||
ind=3
|
||||
while [ $ind -lt $arrLen ]; do
|
||||
if [ $ind -eq 3 ]; then
|
||||
releaseNotes="#### ${msgArray[ind]}"
|
||||
releaseNotes+=$'\r\n'
|
||||
else
|
||||
oneLine="$(echo -e "${msgArray[ind]}" | sed -e 's/^[[:space:]]*//')"
|
||||
if [ ${#oneLine} -gt 0 ]; then
|
||||
if [ "${oneLine:0:2}" == "* " ]; then oneLine=$(echo ${oneLine/\*/-}); fi
|
||||
if [ "${oneLine:0:2}" != "- " ]; then releaseNotes+="- "; fi
|
||||
releaseNotes+="$oneLine"
|
||||
releaseNotes+=$'\r\n'
|
||||
fi
|
||||
fi
|
||||
let ind=$ind+1
|
||||
done
|
||||
fi
|
||||
|
||||
# Append Commit Messages
|
||||
if [ ! -z "$COMMITS_SINCE_RELEASE" ] && [ "$COMMITS_SINCE_RELEASE" != "null" ]; then
|
||||
echo "Getting commits since $COMMITS_SINCE_RELEASE ..."
|
||||
commitFile=$OUTPUT_DIR/commits.txt
|
||||
git -C "$GITHUB_WORKSPACE" log --oneline $COMMITS_SINCE_RELEASE.. > "$OUTPUT_DIR/commits.txt"
|
||||
releaseNotes+=$'\r\n##### Commits\r\n'
|
||||
IFS=$'\n'
|
||||
for next in `cat $commitFile`
|
||||
do
|
||||
IFS=' ' read -r commitId commitMsg <<< "$next"
|
||||
commitLine="- [$commitId](https://github.com/$GITHUB_REPOSITORY/commit/$commitId) $commitMsg"
|
||||
releaseNotes+="$commitLine"
|
||||
releaseNotes+=$'\r\n'
|
||||
done
|
||||
rm -f $commitFile
|
||||
fi
|
||||
|
||||
# Prepend the original release body
|
||||
if [ "${RELEASE_BODY: -1}" == $'\r' ]; then
|
||||
RELEASE_BODY="${RELEASE_BODY:0:-1}"
|
||||
else
|
||||
RELEASE_BODY="$RELEASE_BODY"
|
||||
fi
|
||||
RELEASE_BODY+=$'\r\n'
|
||||
releaseNotes="$RELEASE_BODY$releaseNotes"
|
||||
|
||||
# Update release page
|
||||
echo "Updating release notes ..."
|
||||
releaseNotes=$(printf '%s' "$releaseNotes" | python -c 'import json,sys; print(json.dumps(sys.stdin.read()))')
|
||||
releaseNotes=${releaseNotes:1:-1}
|
||||
curlData="{\"body\": \"$releaseNotes\"}"
|
||||
releaseData=`curl --data "$curlData" "https://api.github.com/repos/$GITHUB_REPOSITORY/releases/$RELEASE_ID?access_token=$GITHUB_TOKEN" 2>/dev/null`
|
||||
if [ $? -ne 0 ]; then echo "ERROR: Updating Release Failed: $?"; exit 1; fi
|
||||
echo "Release notes successfully updated"
|
||||
echo
|
||||
|
||||
##
|
||||
## SUBMODULE VERSIONS
|
||||
##
|
||||
|
||||
# Upload submodules versions
|
||||
echo "Generating submodules.txt ..."
|
||||
git -C "$GITHUB_WORKSPACE" submodule status > "$OUTPUT_DIR/submodules.txt"
|
||||
echo "Uploading submodules.txt ..."
|
||||
echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/submodules.txt"`
|
||||
echo ""
|
||||
set +e
|
||||
|
||||
##
|
||||
## DONE
|
||||
##
|
||||
echo "DONE!"
|
64
.github/stale.yml
vendored
Normal file
64
.github/stale.yml
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request becomes stale
|
||||
daysUntilStale: 60
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
|
||||
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
|
||||
daysUntilClose: 14
|
||||
|
||||
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
|
||||
onlyLabels: []
|
||||
|
||||
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
- "to be implemented"
|
||||
- "for reference"
|
||||
- "move to PR"
|
||||
- "enhancement"
|
||||
|
||||
# Set to true to ignore issues in a project (defaults to false)
|
||||
exemptProjects: false
|
||||
|
||||
# Set to true to ignore issues in a milestone (defaults to false)
|
||||
exemptMilestones: false
|
||||
|
||||
# Set to true to ignore issues with an assignee (defaults to false)
|
||||
exemptAssignees: false
|
||||
|
||||
# Label to use when marking as stale
|
||||
staleLabel: stale
|
||||
|
||||
# Comment to post when marking as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
[STALE_SET] 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.
|
||||
|
||||
# Comment to post when removing the stale label.
|
||||
unmarkComment: >
|
||||
[STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it openin the future.
|
||||
|
||||
# Comment to post when closing a stale Issue or Pull Request.
|
||||
closeComment: >
|
||||
[STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions.
|
||||
|
||||
# Limit the number of actions per hour, from 1-30. Default is 30
|
||||
limitPerRun: 30
|
||||
|
||||
# Limit to only `issues` or `pulls`
|
||||
only: issues
|
||||
|
||||
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
|
||||
# pulls:
|
||||
# daysUntilStale: 30
|
||||
# markComment: >
|
||||
# This pull request has been automatically marked as stale because it has not had
|
||||
# recent activity. It will be closed if no further activity occurs. Thank you
|
||||
# for your contributions.
|
||||
|
||||
# issues:
|
||||
# exemptLabels:
|
||||
# - confirmed
|
21
.github/workflows/gh-pages.yml
vendored
Normal file
21
.github/workflows/gh-pages.yml
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
name: GitHub Pages CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'README.md'
|
||||
- 'docs/**'
|
||||
|
||||
jobs:
|
||||
|
||||
build-pages:
|
||||
name: Build GitHub Pages
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Copy Files
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: bash ./.github/scripts/on-pages.sh
|
49
.github/workflows/push.yml
vendored
Normal file
49
.github/workflows/push.yml
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
name: ESP32 Arduino CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release/*
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
|
||||
# Ubuntu
|
||||
build-arduino-linux:
|
||||
name: Arduino ${{ matrix.chunk }} on ubuntu-latest
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
chunk: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Build Sketches
|
||||
run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} 15
|
||||
|
||||
# Windows and MacOS
|
||||
build-arduino-win-mac:
|
||||
name: Arduino on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-latest, macOS-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Build Sketches
|
||||
run: bash ./.github/scripts/on-push.sh
|
||||
|
||||
# PlatformIO on Windows, Ubuntu and Mac
|
||||
build-platformio:
|
||||
name: PlatformIO on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Build Sketches
|
||||
run: bash ./.github/scripts/on-push.sh 1 1 #equal and non-zero to trigger PIO
|
17
.github/workflows/release.yml
vendored
Normal file
17
.github/workflows/release.yml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
name: ESP32 Arduino Release
|
||||
|
||||
on:
|
||||
release:
|
||||
types: published
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Publish Release
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Build Release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: bash ./.github/scripts/on-release.sh
|
7
.gitignore
vendored
7
.gitignore
vendored
@ -5,3 +5,10 @@ tools/esptool.exe
|
||||
tools/mkspiffs/mkspiffs
|
||||
tools/mkspiffs/mkspiffs.exe
|
||||
.DS_Store
|
||||
|
||||
#Ignore files built by Visual Studio/Visual Micro
|
||||
[Dd]ebug*/
|
||||
[Rr]elease*/
|
||||
.vs/
|
||||
__vm/
|
||||
*.vcxproj*
|
||||
|
46
.travis.yml
46
.travis.yml
@ -1,8 +1,6 @@
|
||||
sudo: false
|
||||
|
||||
language: python
|
||||
python:
|
||||
- "2.7"
|
||||
|
||||
os:
|
||||
- linux
|
||||
@ -10,22 +8,40 @@ os:
|
||||
git:
|
||||
depth: false
|
||||
|
||||
env:
|
||||
global:
|
||||
- secure: "l/4Dt+KQ/mACtGAHDUsPr66fUte840PZoQ4xpPikqWZI0uARu4l+Ym7+sHinnT6fBqrj8AJeBYGz4nFa8NK4LutZn9mSD40w+sxl0wSV4oHV8rzKe3Cd8+sMG3+o33yWoikMNjSvqa73Q0rm+SgrlInNdZbuAyixL+a2alaWSnGPm4F2xwUGj+S33TOy5P/Xp77CYtCV5S8vzyk/eEdNhoF0GYePJVdfuzCOUjXMyT5OWxORkzzQ7Hnn/Ka/RDfV8Si4HgujLQBrK5q6iPnNBFqBSqilYBepSMn4opnOBpIm0SCgePz7XQEFC83buA7GUcnCnfg38bf+dCwHaODf1d1PmqVRYt2QmfinexXtM4afAtL0iBUDtvrfnXHzwW9w82VeZhpbJSVh9DUQvB0IlsZeCz9J9PUBAi3N+SMX+9l+BomYwRUlPuKY+Ef2JKk9q6mxtUkky5R0daAlVxEhpVdQks1rT+T+NMoDMemxQ3SKEiqAHh6EgHecruszffmZ71uLX9MpERpew0qN+UFiafws+jkTjx+3yF9yut0Hf9sMbeAYzzkGzRqJTUEBJ6B29Cql8M0yRXCNN/8wuuTHhG8esstozga4ZQoIVrq7mEAgup376PTcNfr1+imbbWVQ7lJdYIuDe6OS5V3OX6np11vgK/DbhfyzvQv9Z1zAGnM="
|
||||
- REMOTE_URL=https://github.com/$TRAVIS_REPO_SLUG/releases/download/$TRAVIS_TAG
|
||||
|
||||
script:
|
||||
- bash $TRAVIS_BUILD_DIR/tools/build.sh
|
||||
before_install:
|
||||
- git submodule update --init --recursive
|
||||
|
||||
deploy:
|
||||
provider: script
|
||||
skip_cleanup: true
|
||||
script: bash $TRAVIS_BUILD_DIR/tools/deploy.sh -t$TRAVIS_TAG -a$ESP32_GITHUB_TOKEN -s$TRAVIS_REPO_SLUG -drelease
|
||||
stages:
|
||||
- build
|
||||
- deploy
|
||||
|
||||
on:
|
||||
tags: true
|
||||
jobs:
|
||||
include:
|
||||
|
||||
- name: "Build Arduino 0"
|
||||
if: tag IS blank AND (type = pull_request OR (type = push AND branch = master))
|
||||
stage: build
|
||||
script: $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 0 10
|
||||
|
||||
- name: "Build Arduino 1"
|
||||
if: tag IS blank AND (type = pull_request OR (type = push AND branch = master))
|
||||
stage: build
|
||||
script: $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 1 10
|
||||
|
||||
- name: "Build Arduino 2"
|
||||
if: tag IS blank AND (type = pull_request OR (type = push AND branch = master))
|
||||
stage: build
|
||||
script: $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 2 10
|
||||
|
||||
- name: "Build Arduino 3"
|
||||
if: tag IS blank AND (type = pull_request OR (type = push AND branch = master))
|
||||
stage: build
|
||||
script: $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 3 10
|
||||
|
||||
- name: "Build PlatformIO"
|
||||
if: tag IS blank AND (type = pull_request OR (type = push AND branch = master))
|
||||
stage: build
|
||||
script: $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 1 1
|
||||
|
||||
notifications:
|
||||
email:
|
||||
|
@ -209,3 +209,8 @@ set(COMPONENT_REQUIRES spi_flash mbedtls mdns ethernet)
|
||||
set(COMPONENT_PRIV_REQUIRES fatfs nvs_flash app_update spiffs bootloader_support openssl bt)
|
||||
|
||||
register_component()
|
||||
|
||||
set_source_files_properties(libraries/AzureIoT/src/az_iot/iothub_client/src/iothubtransport_mqtt_common.c
|
||||
PROPERTIES COMPILE_FLAGS
|
||||
-Wno-maybe-uninitialized
|
||||
)
|
||||
|
@ -232,6 +232,12 @@ config ARDUINO_SELECTIVE_ESPmDNS
|
||||
select ARDUINO_SELECTIVE_WiFi
|
||||
default y
|
||||
|
||||
config ARDUINO_SELECTIVE_FFat
|
||||
bool "Enable FFat"
|
||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||
select ARDUINO_SELECTIVE_FS
|
||||
default y
|
||||
|
||||
config ARDUINO_SELECTIVE_FS
|
||||
bool "Enable FS"
|
||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||
|
21
README.md
21
README.md
@ -1,4 +1,5 @@
|
||||
# Arduino core for ESP32 WiFi chip [](https://travis-ci.org/espressif/arduino-esp32)
|
||||
# Arduino core for the ESP32
|
||||
[](https://travis-ci.org/espressif/arduino-esp32) 
|
||||
|
||||
### 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)
|
||||
|
||||
@ -9,17 +10,12 @@
|
||||
- [Issue/Bug report template](#issuebug-report-template)
|
||||
- [ESP32Dev Board PINMAP](#esp32dev-board-pinmap)
|
||||
|
||||
## Development Status
|
||||
### Development Status
|
||||
[Latest stable release  ](https://github.com/espressif/arduino-esp32/releases/latest/) 
|
||||
|
||||
[Latest development release  ](https://github.com/espressif/arduino-esp32/releases/latest/) 
|
||||
|
||||
Most of the framework is implemented. Most noticable is the missing analogWrite. While analogWrite is on it's way, there are a few other options that you can use:
|
||||
- 16 channels [LEDC](cores/esp32/esp32-hal-ledc.h) which is PWM
|
||||
- 8 channels [SigmaDelta](cores/esp32/esp32-hal-sigmadelta.h) which uses SigmaDelta modulation
|
||||
- 2 channels [DAC](cores/esp32/esp32-hal-dac.h) which gives real analog output
|
||||
|
||||
## Installation Instructions
|
||||
### Installation Instructions
|
||||
- Using Arduino IDE Boards Manager (preferred)
|
||||
+ [Instructions for Boards Manager](docs/arduino-ide/boards_manager.md)
|
||||
- Using Arduino IDE with the development repository
|
||||
@ -33,20 +29,19 @@ Most of the framework is implemented. Most noticable is the missing analogWrite.
|
||||
- [Using as ESP-IDF component](docs/esp-idf_component.md)
|
||||
- [Using OTAWebUpdater](docs/OTAWebUpdate/OTAWebUpdate.md)
|
||||
|
||||
#### Decoding exceptions
|
||||
### Decoding exceptions
|
||||
|
||||
You can use [EspExceptionDecoder](https://github.com/me-no-dev/EspExceptionDecoder) to get meaningful call trace.
|
||||
|
||||
#### Issue/Bug report template
|
||||
### 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 [for reference](https://github.com/espressif/arduino-esp32/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3A%22for%20reference%22%20).
|
||||
|
||||
Finally, if you're sure no one else had the issue, follow the [ISSUE_TEMPLATE](docs/ISSUE_TEMPLATE.md) while reporting any issue.
|
||||
|
||||
|
||||
## ESP32Dev Board PINMAP
|
||||
### ESP32Dev Board PINMAP
|
||||
|
||||

|
||||
|
||||
## Hint
|
||||
### Hint
|
||||
|
||||
Sometimes to program ESP32 via serial you must keep GPIO0 LOW during the programming process
|
||||
|
19
appveyor.yml
19
appveyor.yml
@ -1,19 +0,0 @@
|
||||
build: off
|
||||
environment:
|
||||
|
||||
matrix:
|
||||
- PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiClient"
|
||||
- PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiClientBasic"
|
||||
- PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiClientEvents"
|
||||
- PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiIPv6"
|
||||
- PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiScan"
|
||||
- PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiSmartConfig"
|
||||
|
||||
install:
|
||||
- cmd: git submodule update --init --recursive
|
||||
- cmd: SET PATH=%PATH%;C:\Python27\Scripts
|
||||
- cmd: pip install -U https://github.com/platformio/platformio/archive/develop.zip
|
||||
- cmd: platformio platform install https://github.com/platformio/platform-espressif32.git#feature/stage
|
||||
|
||||
test_script:
|
||||
- cmd: platformio ci -b esp32dev -b nano32 -b node32s
|
339
boards.txt
339
boards.txt
@ -44,6 +44,9 @@ esp32.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIF
|
||||
esp32.menu.PartitionScheme.default.build.partitions=default
|
||||
esp32.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS)
|
||||
esp32.menu.PartitionScheme.defaultffat.build.partitions=default_ffat
|
||||
esp32.menu.PartitionScheme.default_8MB=8M Flash (3MB APP/1.5MB FAT)
|
||||
esp32.menu.PartitionScheme.default_8MB.build.partitions=default_8MB
|
||||
esp32.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336
|
||||
esp32.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS)
|
||||
esp32.menu.PartitionScheme.minimal.build.partitions=minimal
|
||||
esp32.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS)
|
||||
@ -66,6 +69,10 @@ esp32.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs
|
||||
esp32.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080
|
||||
esp32.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FAT)
|
||||
esp32.menu.PartitionScheme.fatflash.build.partitions=ffat
|
||||
esp32.menu.PartitionScheme.fatflash.upload.maximum_size=2097152
|
||||
esp32.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9MB FATFS)
|
||||
esp32.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB
|
||||
esp32.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728
|
||||
|
||||
esp32.menu.CPUFreq.240=240MHz (WiFi/BT)
|
||||
esp32.menu.CPUFreq.240.build.f_cpu=240000000L
|
||||
@ -104,12 +111,14 @@ esp32.menu.FlashFreq.40.build.flash_freq=40m
|
||||
|
||||
esp32.menu.FlashSize.4M=4MB (32Mb)
|
||||
esp32.menu.FlashSize.4M.build.flash_size=4MB
|
||||
esp32.menu.FlashSize.8M=8MB (64Mb)
|
||||
esp32.menu.FlashSize.8M.build.flash_size=8MB
|
||||
esp32.menu.FlashSize.8M.build.partitions=default_8MB
|
||||
esp32.menu.FlashSize.2M=2MB (16Mb)
|
||||
esp32.menu.FlashSize.2M.build.flash_size=2MB
|
||||
esp32.menu.FlashSize.2M.build.partitions=minimal
|
||||
esp32.menu.FlashSize.16M=16MB (128Mb)
|
||||
esp32.menu.FlashSize.16M.build.flash_size=16MB
|
||||
esp32.menu.FlashSize.16M.build.partitions=ffat
|
||||
|
||||
esp32.menu.UploadSpeed.921600=921600
|
||||
esp32.menu.UploadSpeed.921600.upload.speed=921600
|
||||
@ -164,19 +173,34 @@ esp32wrover.build.boot=dio
|
||||
esp32wrover.build.partitions=default
|
||||
esp32wrover.build.defines=-DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue
|
||||
|
||||
esp32wrover.menu.PartitionScheme.default=Default
|
||||
esp32wrover.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS)
|
||||
esp32wrover.menu.PartitionScheme.default.build.partitions=default
|
||||
esp32wrover.menu.PartitionScheme.minimal=Minimal (2MB FLASH)
|
||||
esp32wrover.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS)
|
||||
esp32wrover.menu.PartitionScheme.defaultffat.build.partitions=default_ffat
|
||||
esp32wrover.menu.PartitionScheme.default_8MB=8M Flash (3MB APP/1.5MB FAT)
|
||||
esp32wrover.menu.PartitionScheme.default_8MB.build.partitions=default_8MB
|
||||
esp32wrover.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS)
|
||||
esp32wrover.menu.PartitionScheme.minimal.build.partitions=minimal
|
||||
esp32wrover.menu.PartitionScheme.no_ota=No OTA (Large APP)
|
||||
esp32wrover.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS)
|
||||
esp32wrover.menu.PartitionScheme.no_ota.build.partitions=no_ota
|
||||
esp32wrover.menu.PartitionScheme.no_ota.upload.maximum_size=2097152
|
||||
esp32wrover.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA)
|
||||
esp32wrover.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS)
|
||||
esp32wrover.menu.PartitionScheme.noota_3g.build.partitions=noota_3g
|
||||
esp32wrover.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576
|
||||
esp32wrover.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS)
|
||||
esp32wrover.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat
|
||||
esp32wrover.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152
|
||||
esp32wrover.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS)
|
||||
esp32wrover.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat
|
||||
esp32wrover.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576
|
||||
esp32wrover.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS)
|
||||
esp32wrover.menu.PartitionScheme.huge_app.build.partitions=huge_app
|
||||
esp32wrover.menu.PartitionScheme.huge_app.upload.maximum_size=3145728
|
||||
esp32wrover.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (Large APPS with OTA)
|
||||
esp32wrover.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS)
|
||||
esp32wrover.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs
|
||||
esp32wrover.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080
|
||||
esp32wrover.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FAT)
|
||||
esp32wrover.menu.PartitionScheme.fatflash.build.partitions=ffat
|
||||
|
||||
esp32wrover.menu.FlashMode.qio=QIO
|
||||
esp32wrover.menu.FlashMode.qio.build.flash_mode=dio
|
||||
@ -225,7 +249,6 @@ esp32wrover.menu.DebugLevel.verbose=Verbose
|
||||
esp32wrover.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
##############################################################
|
||||
|
||||
pico32.name=ESP32 Pico Kit
|
||||
|
||||
pico32.upload.tool=esptool_py
|
||||
@ -249,6 +272,15 @@ pico32.build.boot=dio
|
||||
pico32.build.partitions=default
|
||||
pico32.build.defines=
|
||||
|
||||
pico32.menu.PartitionScheme.default=Default
|
||||
pico32.menu.PartitionScheme.default.build.partitions=default
|
||||
pico32.menu.PartitionScheme.no_ota=No OTA (Large APP)
|
||||
pico32.menu.PartitionScheme.no_ota.build.partitions=no_ota
|
||||
pico32.menu.PartitionScheme.no_ota.upload.maximum_size=2097152
|
||||
pico32.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (Large APPS with OTA)
|
||||
pico32.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs
|
||||
pico32.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080
|
||||
|
||||
pico32.menu.UploadSpeed.921600=921600
|
||||
pico32.menu.UploadSpeed.921600.upload.speed=921600
|
||||
pico32.menu.UploadSpeed.115200=115200
|
||||
@ -279,6 +311,110 @@ pico32.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
##############################################################
|
||||
|
||||
tinypico.name=TinyPICO
|
||||
|
||||
tinypico.upload.tool=esptool_py
|
||||
tinypico.upload.maximum_size=1310720
|
||||
tinypico.upload.maximum_data_size=327680
|
||||
tinypico.upload.wait_for_upload_port=true
|
||||
|
||||
tinypico.serial.disableDTR=true
|
||||
tinypico.serial.disableRTS=true
|
||||
|
||||
tinypico.build.mcu=esp32
|
||||
tinypico.build.core=esp32
|
||||
tinypico.build.variant=pico32
|
||||
tinypico.build.board=ESP32_PICO
|
||||
|
||||
tinypico.build.f_cpu=240000000L
|
||||
tinypico.build.flash_size=4MB
|
||||
tinypico.build.flash_freq=80m
|
||||
tinypico.build.flash_mode=dio
|
||||
tinypico.build.boot=dio
|
||||
tinypico.build.partitions=default
|
||||
tinypico.build.defines=
|
||||
|
||||
tinypico.menu.UploadSpeed.921600=921600
|
||||
tinypico.menu.UploadSpeed.921600.upload.speed=921600
|
||||
tinypico.menu.UploadSpeed.115200=115200
|
||||
tinypico.menu.UploadSpeed.115200.upload.speed=115200
|
||||
tinypico.menu.UploadSpeed.256000.windows=256000
|
||||
tinypico.menu.UploadSpeed.256000.upload.speed=256000
|
||||
tinypico.menu.UploadSpeed.230400.windows.upload.speed=256000
|
||||
tinypico.menu.UploadSpeed.230400=230400
|
||||
tinypico.menu.UploadSpeed.230400.upload.speed=230400
|
||||
tinypico.menu.UploadSpeed.460800.linux=460800
|
||||
tinypico.menu.UploadSpeed.460800.macosx=460800
|
||||
tinypico.menu.UploadSpeed.460800.upload.speed=460800
|
||||
tinypico.menu.UploadSpeed.512000.windows=512000
|
||||
tinypico.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
tinypico.menu.FlashMode.qio=QIO
|
||||
tinypico.menu.FlashMode.qio.build.flash_mode=dio
|
||||
tinypico.menu.FlashMode.qio.build.boot=qio
|
||||
tinypico.menu.FlashMode.dio=DIO
|
||||
tinypico.menu.FlashMode.dio.build.flash_mode=dio
|
||||
tinypico.menu.FlashMode.dio.build.boot=dio
|
||||
|
||||
tinypico.menu.FlashFreq.80=80MHz
|
||||
tinypico.menu.FlashFreq.80.build.flash_freq=80m
|
||||
tinypico.menu.FlashFreq.40=40MHz
|
||||
tinypico.menu.FlashFreq.40.build.flash_freq=40m
|
||||
|
||||
tinypico.menu.PSRAM.enabled=Enabled
|
||||
tinypico.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue
|
||||
tinypico.menu.PSRAM.disabled=Disabled
|
||||
tinypico.menu.PSRAM.disabled.build.defines=
|
||||
|
||||
tinypico.menu.DebugLevel.none=None
|
||||
tinypico.menu.DebugLevel.none.build.code_debug=0
|
||||
tinypico.menu.DebugLevel.error=Error
|
||||
tinypico.menu.DebugLevel.error.build.code_debug=1
|
||||
tinypico.menu.DebugLevel.warn=Warn
|
||||
tinypico.menu.DebugLevel.warn.build.code_debug=2
|
||||
tinypico.menu.DebugLevel.info=Info
|
||||
tinypico.menu.DebugLevel.info.build.code_debug=3
|
||||
tinypico.menu.DebugLevel.debug=Debug
|
||||
tinypico.menu.DebugLevel.debug.build.code_debug=4
|
||||
tinypico.menu.DebugLevel.verbose=Verbose
|
||||
tinypico.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
##############################################################
|
||||
magicbit.name=MagicBit
|
||||
|
||||
magicbit.upload.tool=esptool_py
|
||||
magicbit.upload.maximum_size=1310720
|
||||
magicbit.upload.maximum_data_size=327680
|
||||
magicbit.upload.wait_for_upload_port=true
|
||||
|
||||
magicbit.serial.disableDTR=true
|
||||
magicbit.serial.disableRTS=true
|
||||
|
||||
magicbit.build.mcu=esp32
|
||||
magicbit.build.core=esp32
|
||||
magicbit.build.variant=magicbit
|
||||
magicbit.build.board=ESP32_DEV
|
||||
|
||||
magicbit.build.f_cpu=240000000L
|
||||
magicbit.build.flash_size=4MB
|
||||
magicbit.build.flash_freq=40m
|
||||
magicbit.build.flash_mode=dio
|
||||
magicbit.build.boot=dio
|
||||
magicbit.build.partitions=default
|
||||
|
||||
magicbit.menu.CPUFreq.240=240MHz (WiFi/BT)
|
||||
magicbit.menu.CPUFreq.240.build.f_cpu=240000000L
|
||||
magicbit.menu.CPUFreq.160=160MHz (WiFi/BT)
|
||||
magicbit.menu.CPUFreq.160.build.f_cpu=160000000L
|
||||
magicbit.menu.CPUFreq.80=80MHz (WiFi/BT)
|
||||
magicbit.menu.CPUFreq.80.build.f_cpu=80000000L
|
||||
magicbit.menu.CPUFreq.40=40MHz (40MHz XTAL)
|
||||
|
||||
magicbit.menu.UploadSpeed.921600=921600
|
||||
magicbit.menu.UploadSpeed.921600.upload.speed=921600
|
||||
magicbit.menu.UploadSpeed.115200=115200
|
||||
magicbit.menu.UploadSpeed.115200.upload.speed=115200
|
||||
##############################################################
|
||||
turta_iot_node.name=Turta IoT Node
|
||||
|
||||
turta_iot_node.upload.tool=esptool_py
|
||||
@ -1079,7 +1215,7 @@ pocket_32.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
##############################################################
|
||||
|
||||
WeMosBat.name="WeMos" WiFi&Bluetooth Battery
|
||||
WeMosBat.name=WeMos WiFi&Bluetooth Battery
|
||||
|
||||
WeMosBat.upload.tool=esptool_py
|
||||
WeMosBat.upload.maximum_size=1310720
|
||||
@ -1542,6 +1678,15 @@ featheresp32.menu.DebugLevel.debug.build.code_debug=4
|
||||
featheresp32.menu.DebugLevel.verbose=Verbose
|
||||
featheresp32.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
featheresp32.menu.PartitionScheme.default=Default
|
||||
featheresp32.menu.PartitionScheme.default.build.partitions=default
|
||||
featheresp32.menu.PartitionScheme.no_ota=No OTA (Large APP)
|
||||
featheresp32.menu.PartitionScheme.no_ota.build.partitions=no_ota
|
||||
featheresp32.menu.PartitionScheme.no_ota.upload.maximum_size=2097152
|
||||
featheresp32.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (Large APPS with OTA)
|
||||
featheresp32.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs
|
||||
featheresp32.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080
|
||||
|
||||
##############################################################
|
||||
|
||||
nodemcu-32s.name=NodeMCU-32S
|
||||
@ -1953,6 +2098,121 @@ esp32-poe.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080
|
||||
|
||||
##############################################################
|
||||
|
||||
esp32-poe-iso.name=OLIMEX ESP32-PoE-ISO
|
||||
|
||||
esp32-poe-iso.upload.tool=esptool_py
|
||||
esp32-poe-iso.upload.maximum_size=1310720
|
||||
esp32-poe-iso.upload.maximum_data_size=327680
|
||||
esp32-poe-iso.upload.wait_for_upload_port=true
|
||||
|
||||
esp32-poe-iso.serial.disableDTR=true
|
||||
esp32-poe-iso.serial.disableRTS=true
|
||||
|
||||
esp32-poe-iso.build.mcu=esp32
|
||||
esp32-poe-iso.build.core=esp32
|
||||
esp32-poe-iso.build.variant=esp32-poe-iso
|
||||
esp32-poe-iso.build.board=ESP32_POE_ISO
|
||||
|
||||
esp32-poe-iso.build.f_cpu=240000000L
|
||||
esp32-poe-iso.build.flash_mode=dio
|
||||
esp32-poe-iso.build.flash_size=4MB
|
||||
esp32-poe-iso.build.boot=dio
|
||||
esp32-poe-iso.build.partitions=default
|
||||
esp32-poe-iso.build.defines=
|
||||
|
||||
esp32-poe-iso.menu.FlashFreq.80=80MHz
|
||||
esp32-poe-iso.menu.FlashFreq.80.build.flash_freq=80m
|
||||
esp32-poe-iso.menu.FlashFreq.40=40MHz
|
||||
esp32-poe-iso.menu.FlashFreq.40.build.flash_freq=40m
|
||||
|
||||
|
||||
esp32-poe-iso.menu.UploadSpeed.115200=115200
|
||||
esp32-poe-iso.menu.UploadSpeed.115200.upload.speed=115200
|
||||
|
||||
esp32-poe-iso.menu.PartitionScheme.default=Default
|
||||
esp32-poe-iso.menu.PartitionScheme.default.build.partitions=default
|
||||
esp32-poe-iso.menu.PartitionScheme.no_ota=No OTA (Large APP)
|
||||
esp32-poe-iso.menu.PartitionScheme.no_ota.build.partitions=no_ota
|
||||
esp32-poe-iso.menu.PartitionScheme.no_ota.upload.maximum_size=2097152
|
||||
esp32-poe-iso.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (Large APPS with OTA)
|
||||
esp32-poe-iso.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs
|
||||
esp32-poe-iso.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080
|
||||
|
||||
##############################################################
|
||||
|
||||
esp32-DevKitLipo.name=OLIMEX ESP32-DevKit-LiPo
|
||||
|
||||
esp32-DevKitLipo.upload.tool=esptool_py
|
||||
esp32-DevKitLipo.upload.maximum_size=1310720
|
||||
esp32-DevKitLipo.upload.maximum_data_size=327680
|
||||
esp32-DevKitLipo.upload.wait_for_upload_port=true
|
||||
|
||||
esp32-DevKitLipo.serial.disableDTR=true
|
||||
esp32-DevKitLipo.serial.disableRTS=true
|
||||
|
||||
esp32-DevKitLipo.build.mcu=esp32
|
||||
esp32-DevKitLipo.build.core=esp32
|
||||
esp32-DevKitLipo.build.variant=esp32-devkit-lipo
|
||||
esp32-DevKitLipo.build.board=ESP32_DEVKIT_LIPO
|
||||
|
||||
esp32-DevKitLipo.build.f_cpu=240000000L
|
||||
esp32-DevKitLipo.build.flash_size=4MB
|
||||
esp32-DevKitLipo.build.flash_freq=40m
|
||||
esp32-DevKitLipo.build.flash_mode=dio
|
||||
esp32-DevKitLipo.build.boot=dio
|
||||
esp32-DevKitLipo.build.partitions=default
|
||||
esp32-DevKitLipo.build.defines=
|
||||
|
||||
esp32-DevKitLipo.menu.PartitionScheme.default=Default
|
||||
esp32-DevKitLipo.menu.PartitionScheme.default.build.partitions=default
|
||||
esp32-DevKitLipo.menu.PartitionScheme.minimal=Minimal (2MB FLASH)
|
||||
esp32-DevKitLipo.menu.PartitionScheme.minimal.build.partitions=minimal
|
||||
esp32-DevKitLipo.menu.PartitionScheme.no_ota=No OTA (Large APP)
|
||||
esp32-DevKitLipo.menu.PartitionScheme.no_ota.build.partitions=no_ota
|
||||
esp32-DevKitLipo.menu.PartitionScheme.no_ota.upload.maximum_size=2097152
|
||||
esp32-DevKitLipo.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA)
|
||||
esp32-DevKitLipo.menu.PartitionScheme.huge_app.build.partitions=huge_app
|
||||
esp32-DevKitLipo.menu.PartitionScheme.huge_app.upload.maximum_size=3145728
|
||||
esp32-DevKitLipo.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (Large APPS with OTA)
|
||||
esp32-DevKitLipo.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs
|
||||
esp32-DevKitLipo.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080
|
||||
esp32-DevKitLipo.menu.PartitionScheme.fatflash=16M Fat
|
||||
esp32-DevKitLipo.menu.PartitionScheme.fatflash.build.partitions=ffat
|
||||
|
||||
esp32-DevKitLipo.menu.FlashMode.qio=QIO
|
||||
esp32-DevKitLipo.menu.FlashMode.qio.build.flash_mode=dio
|
||||
esp32-DevKitLipo.menu.FlashMode.qio.build.boot=qio
|
||||
esp32-DevKitLipo.menu.FlashMode.dio=DIO
|
||||
esp32-DevKitLipo.menu.FlashMode.dio.build.flash_mode=dio
|
||||
esp32-DevKitLipo.menu.FlashMode.dio.build.boot=dio
|
||||
esp32-DevKitLipo.menu.FlashMode.qout=QOUT
|
||||
esp32-DevKitLipo.menu.FlashMode.qout.build.flash_mode=dout
|
||||
esp32-DevKitLipo.menu.FlashMode.qout.build.boot=qout
|
||||
esp32-DevKitLipo.menu.FlashMode.dout=DOUT
|
||||
esp32-DevKitLipo.menu.FlashMode.dout.build.flash_mode=dout
|
||||
esp32-DevKitLipo.menu.FlashMode.dout.build.boot=dout
|
||||
|
||||
esp32-DevKitLipo.menu.FlashFreq.80=80MHz
|
||||
esp32-DevKitLipo.menu.FlashFreq.80.build.flash_freq=80m
|
||||
esp32-DevKitLipo.menu.FlashFreq.40=40MHz
|
||||
esp32-DevKitLipo.menu.FlashFreq.40.build.flash_freq=40m
|
||||
|
||||
esp32-DevKitLipo.menu.UploadSpeed.921600=921600
|
||||
esp32-DevKitLipo.menu.UploadSpeed.921600.upload.speed=921600
|
||||
esp32-DevKitLipo.menu.UploadSpeed.115200=115200
|
||||
esp32-DevKitLipo.menu.UploadSpeed.115200.upload.speed=115200
|
||||
esp32-DevKitLipo.menu.UploadSpeed.256000.windows=256000
|
||||
esp32-DevKitLipo.menu.UploadSpeed.256000.upload.speed=256000
|
||||
esp32-DevKitLipo.menu.UploadSpeed.230400.windows.upload.speed=256000
|
||||
esp32-DevKitLipo.menu.UploadSpeed.230400=230400
|
||||
esp32-DevKitLipo.menu.UploadSpeed.230400.upload.speed=230400
|
||||
esp32-DevKitLipo.menu.UploadSpeed.460800.linux=460800
|
||||
esp32-DevKitLipo.menu.UploadSpeed.460800.macosx=460800
|
||||
esp32-DevKitLipo.menu.UploadSpeed.460800.upload.speed=460800
|
||||
esp32-DevKitLipo.menu.UploadSpeed.512000.windows=512000
|
||||
esp32-DevKitLipo.menu.UploadSpeed.512000.upload.speed=512000
|
||||
##############################################################
|
||||
|
||||
espino32.name=ThaiEasyElec's ESPino32
|
||||
|
||||
espino32.upload.tool=esptool_py
|
||||
@ -2106,6 +2366,7 @@ m5stack-fire.menu.PSRAM.disabled.build.defines=
|
||||
|
||||
m5stack-fire.menu.PartitionScheme.default=Default (2 x 6.5 MB app, 3.6 MB SPIFFS)
|
||||
m5stack-fire.menu.PartitionScheme.default.build.partitions=default_16MB
|
||||
m5stack-fire.menu.PartitionScheme.default.upload.maximum_size=6553600
|
||||
m5stack-fire.menu.PartitionScheme.large_spiffs=Large SPIFFS (7 MB)
|
||||
m5stack-fire.menu.PartitionScheme.large_spiffs.build.partitions=large_spiffs_16MB
|
||||
m5stack-fire.menu.PartitionScheme.large_spiffs.upload.maximum_size=4685824
|
||||
@ -2535,6 +2796,7 @@ heltec_wifi_lora_32_V2.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM -mfix-
|
||||
|
||||
heltec_wifi_lora_32_V2.menu.PartitionScheme.default=default_8MB
|
||||
heltec_wifi_lora_32_V2.menu.PartitionScheme.default.build.partitions=default_8MB
|
||||
heltec_wifi_lora_32_V2.menu.PartitionScheme.default.upload.maximum_size=3342336
|
||||
heltec_wifi_lora_32_V2.menu.PartitionScheme.minimal=Minimal (2MB FLASH)
|
||||
heltec_wifi_lora_32_V2.menu.PartitionScheme.minimal.build.partitions=minimal
|
||||
heltec_wifi_lora_32_V2.menu.PartitionScheme.no_ota=No OTA (Large APP)
|
||||
@ -2582,7 +2844,7 @@ heltec_wifi_lora_32_V2.menu.FlashFreq.40.build.flash_freq=40m
|
||||
|
||||
heltec_wifi_lora_32_V2.menu.FlashSize.8M=8MB (64Mb)
|
||||
heltec_wifi_lora_32_V2.menu.FlashSize.8M.build.flash_size=8MB
|
||||
heltec_wifi_lora_32_V2.menu.FlashSize.2M.build.partitions=default_8MB
|
||||
heltec_wifi_lora_32_V2.menu.FlashSize.8M.build.partitions=default_8MB
|
||||
heltec_wifi_lora_32_V2.menu.FlashSize.4M=4MB (32Mb)
|
||||
heltec_wifi_lora_32_V2.menu.FlashSize.4M.build.flash_size=4MB
|
||||
heltec_wifi_lora_32_V2.menu.FlashSize.2M=2MB (16Mb)
|
||||
@ -2652,6 +2914,7 @@ heltec_wireless_stick.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM -mfix-e
|
||||
|
||||
heltec_wireless_stick.menu.PartitionScheme.default=default_8MB
|
||||
heltec_wireless_stick.menu.PartitionScheme.default.build.partitions=default_8MB
|
||||
heltec_wireless_stick.menu.PartitionScheme.default.upload.maximum_size=3342336
|
||||
heltec_wireless_stick.menu.PartitionScheme.minimal=Minimal (2MB FLASH)
|
||||
heltec_wireless_stick.menu.PartitionScheme.minimal.build.partitions=minimal
|
||||
heltec_wireless_stick.menu.PartitionScheme.no_ota=No OTA (Large APP)
|
||||
@ -3732,6 +3995,7 @@ ttgo-t-watch.menu.PSRAM.disabled.build.defines=
|
||||
|
||||
ttgo-t-watch.menu.PartitionScheme.default=Default (2 x 6.5 MB app, 3.6 MB SPIFFS)
|
||||
ttgo-t-watch.menu.PartitionScheme.default.build.partitions=default_16MB
|
||||
ttgo-t-watch.menu.PartitionScheme.default.upload.maximum_size=6553600
|
||||
ttgo-t-watch.menu.PartitionScheme.large_spiffs=Large SPIFFS (7 MB)
|
||||
ttgo-t-watch.menu.PartitionScheme.large_spiffs.build.partitions=large_spiffs_16MB
|
||||
ttgo-t-watch.menu.PartitionScheme.large_spiffs.upload.maximum_size=4685824
|
||||
@ -3896,3 +4160,60 @@ gpy.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
##############################################################
|
||||
|
||||
vintlabs-devkit-v1.name=VintLabs ESP32 Devkit
|
||||
|
||||
vintlabs-devkit-v1.upload.tool=esptool_py
|
||||
vintlabs-devkit-v1.upload.maximum_size=1310720
|
||||
vintlabs-devkit-v1.upload.maximum_data_size=327680
|
||||
vintlabs-devkit-v1.upload.wait_for_upload_port=true
|
||||
|
||||
vintlabs-devkit-v1.serial.disableDTR=true
|
||||
vintlabs-devkit-v1.serial.disableRTS=true
|
||||
|
||||
vintlabs-devkit-v1.build.mcu=esp32
|
||||
vintlabs-devkit-v1.build.core=esp32
|
||||
vintlabs-devkit-v1.build.variant=vintlabsdevkitv1
|
||||
vintlabs-devkit-v1.build.board=ESP32_DEV
|
||||
|
||||
vintlabs-devkit-v1.build.f_cpu=240000000L
|
||||
vintlabs-devkit-v1.build.flash_mode=dio
|
||||
vintlabs-devkit-v1.build.flash_size=4MB
|
||||
vintlabs-devkit-v1.build.boot=dio
|
||||
vintlabs-devkit-v1.build.partitions=default
|
||||
vintlabs-devkit-v1.build.defines=
|
||||
|
||||
vintlabs-devkit-v1.menu.FlashFreq.80=80MHz
|
||||
vintlabs-devkit-v1.menu.FlashFreq.80.build.flash_freq=80m
|
||||
vintlabs-devkit-v1.menu.FlashFreq.40=40MHz
|
||||
vintlabs-devkit-v1.menu.FlashFreq.40.build.flash_freq=40m
|
||||
|
||||
vintlabs-devkit-v1.menu.UploadSpeed.2000000=2000000
|
||||
vintlabs-devkit-v1.menu.UploadSpeed.2000000.upload.speed=2000000
|
||||
vintlabs-devkit-v1.menu.UploadSpeed.921600=921600
|
||||
vintlabs-devkit-v1.menu.UploadSpeed.921600.upload.speed=921600
|
||||
vintlabs-devkit-v1.menu.UploadSpeed.115200=115200
|
||||
vintlabs-devkit-v1.menu.UploadSpeed.115200.upload.speed=115200
|
||||
vintlabs-devkit-v1.menu.UploadSpeed.256000.windows=256000
|
||||
vintlabs-devkit-v1.menu.UploadSpeed.256000.upload.speed=256000
|
||||
vintlabs-devkit-v1.menu.UploadSpeed.230400.windows.upload.speed=256000
|
||||
vintlabs-devkit-v1.menu.UploadSpeed.230400=230400
|
||||
vintlabs-devkit-v1.menu.UploadSpeed.230400.upload.speed=230400
|
||||
vintlabs-devkit-v1.menu.UploadSpeed.460800.linux=460800
|
||||
vintlabs-devkit-v1.menu.UploadSpeed.460800.macosx=460800
|
||||
vintlabs-devkit-v1.menu.UploadSpeed.460800.upload.speed=460800
|
||||
vintlabs-devkit-v1.menu.UploadSpeed.512000.windows=512000
|
||||
vintlabs-devkit-v1.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
vintlabs-devkit-v1.menu.DebugLevel.none=None
|
||||
vintlabs-devkit-v1.menu.DebugLevel.none.build.code_debug=0
|
||||
vintlabs-devkit-v1.menu.DebugLevel.error=Error
|
||||
vintlabs-devkit-v1.menu.DebugLevel.error.build.code_debug=1
|
||||
vintlabs-devkit-v1.menu.DebugLevel.warn=Warn
|
||||
vintlabs-devkit-v1.menu.DebugLevel.warn.build.code_debug=2
|
||||
vintlabs-devkit-v1.menu.DebugLevel.info=Info
|
||||
vintlabs-devkit-v1.menu.DebugLevel.info.build.code_debug=3
|
||||
vintlabs-devkit-v1.menu.DebugLevel.debug=Debug
|
||||
vintlabs-devkit-v1.menu.DebugLevel.debug.build.code_debug=4
|
||||
|
||||
##############################################################
|
||||
|
||||
|
@ -28,8 +28,6 @@ class Client: public Stream
|
||||
public:
|
||||
virtual int connect(IPAddress ip, uint16_t port) =0;
|
||||
virtual int connect(const char *host, uint16_t port) =0;
|
||||
virtual int connect(IPAddress ip, uint16_t port, int timeout) =0;
|
||||
virtual int connect(const char *host, uint16_t port, int timeout) =0;
|
||||
virtual size_t write(uint8_t) =0;
|
||||
virtual size_t write(const uint8_t *buf, size_t size) =0;
|
||||
virtual int available() = 0;
|
||||
|
@ -92,13 +92,6 @@ void EspClass::deepSleep(uint32_t time_us)
|
||||
esp_deep_sleep(time_us);
|
||||
}
|
||||
|
||||
uint32_t EspClass::getCycleCount()
|
||||
{
|
||||
uint32_t ccount;
|
||||
__asm__ __volatile__("esync; rsr %0,ccount":"=a" (ccount));
|
||||
return ccount;
|
||||
}
|
||||
|
||||
void EspClass::restart(void)
|
||||
{
|
||||
esp_restart();
|
||||
|
@ -75,8 +75,8 @@ public:
|
||||
uint32_t getMaxAllocPsram();
|
||||
|
||||
uint8_t getChipRevision();
|
||||
uint8_t getCpuFreqMHz(){ return CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ; }
|
||||
uint32_t getCycleCount();
|
||||
uint32_t getCpuFreqMHz(){ return getCpuFrequencyMhz(); }
|
||||
inline uint32_t getCycleCount() __attribute__((always_inline));
|
||||
const char * getSdkVersion();
|
||||
|
||||
void deepSleep(uint32_t time_us);
|
||||
@ -101,6 +101,13 @@ public:
|
||||
|
||||
};
|
||||
|
||||
uint32_t IRAM_ATTR EspClass::getCycleCount()
|
||||
{
|
||||
uint32_t ccount;
|
||||
__asm__ __volatile__("esync; rsr %0,ccount":"=a" (ccount));
|
||||
return ccount;
|
||||
}
|
||||
|
||||
extern EspClass ESP;
|
||||
|
||||
#endif //ESP_H
|
||||
|
@ -55,6 +55,7 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
|
||||
_uart = uartBegin(_uart_nr, baud ? baud : 9600, config, rxPin, txPin, 256, invert);
|
||||
|
||||
if(!baud) {
|
||||
uartStartDetectBaudrate(_uart);
|
||||
time_t startMillis = millis();
|
||||
unsigned long detectedBaudRate = 0;
|
||||
while(millis() - startMillis < timeout_ms && !(detectedBaudRate = uartDetectBaudrate(_uart))) {
|
||||
|
@ -52,19 +52,24 @@ size_t Print::printf(const char *format, ...)
|
||||
va_list copy;
|
||||
va_start(arg, format);
|
||||
va_copy(copy, arg);
|
||||
size_t len = vsnprintf(NULL, 0, format, arg);
|
||||
int len = vsnprintf(temp, sizeof(loc_buf), format, copy);
|
||||
va_end(copy);
|
||||
if(len < 0) {
|
||||
va_end(arg);
|
||||
return 0;
|
||||
};
|
||||
if(len >= sizeof(loc_buf)){
|
||||
temp = new char[len+1];
|
||||
temp = (char*) malloc(len+1);
|
||||
if(temp == NULL) {
|
||||
va_end(arg);
|
||||
return 0;
|
||||
}
|
||||
len = vsnprintf(temp, len+1, format, arg);
|
||||
}
|
||||
len = vsnprintf(temp, len+1, format, arg);
|
||||
write((uint8_t*)temp, len);
|
||||
va_end(arg);
|
||||
if(len >= sizeof(loc_buf)){
|
||||
delete[] temp;
|
||||
len = write((uint8_t*)temp, len);
|
||||
if(temp != loc_buf){
|
||||
free(temp);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
@ -154,8 +159,10 @@ size_t Print::print(struct tm * timeinfo, const char * format)
|
||||
}
|
||||
char buf[64];
|
||||
size_t written = strftime(buf, 64, f, timeinfo);
|
||||
print(buf);
|
||||
return written;
|
||||
if(written == 0){
|
||||
return written;
|
||||
}
|
||||
return print(buf);
|
||||
}
|
||||
|
||||
size_t Print::println(void)
|
||||
|
@ -65,9 +65,12 @@ long random(long howsmall, long howbig)
|
||||
return random(diff) + howsmall;
|
||||
}
|
||||
|
||||
long map(long x, long in_min, long in_max, long out_min, long out_max)
|
||||
{
|
||||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||
long map(long x, long in_min, long in_max, long out_min, long out_max) {
|
||||
long divisor = (in_max - in_min);
|
||||
if(divisor == 0){
|
||||
return -1; //AVR returns -1, SAM returns 0
|
||||
}
|
||||
return (x - in_min) * (out_max - out_min) / divisor + out_min;
|
||||
}
|
||||
|
||||
unsigned int makeWord(unsigned int w)
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
String::String(const char *cstr) {
|
||||
init();
|
||||
if(cstr)
|
||||
if (cstr)
|
||||
copy(cstr, strlen(cstr));
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ inline void String::init(void) {
|
||||
}
|
||||
|
||||
void String::invalidate(void) {
|
||||
if(!sso() && wbuffer())
|
||||
if(!isSSO() && wbuffer())
|
||||
free(wbuffer());
|
||||
init();
|
||||
}
|
||||
@ -154,17 +154,21 @@ unsigned char String::reserve(unsigned int size) {
|
||||
|
||||
unsigned char String::changeBuffer(unsigned int maxStrLen) {
|
||||
// Can we use SSO here to avoid allocation?
|
||||
if (maxStrLen < sizeof(sso_buf)) {
|
||||
if (sso() || !buffer()) {
|
||||
if (maxStrLen < sizeof(sso.buff) - 1) {
|
||||
if (isSSO() || !buffer()) {
|
||||
// Already using SSO, nothing to do
|
||||
uint16_t oldLen = len();
|
||||
setSSO(true);
|
||||
setLen(oldLen);
|
||||
return 1;
|
||||
} else { // if bufptr && !sso()
|
||||
// Using bufptr, need to shrink into sso_buff
|
||||
char temp[sizeof(sso_buf)];
|
||||
} else { // if bufptr && !isSSO()
|
||||
// Using bufptr, need to shrink into sso.buff
|
||||
char temp[sizeof(sso.buff)];
|
||||
memcpy(temp, buffer(), maxStrLen);
|
||||
free(wbuffer());
|
||||
uint16_t oldLen = len();
|
||||
setSSO(true);
|
||||
setLen(oldLen);
|
||||
memcpy(wbuffer(), temp, maxStrLen);
|
||||
return 1;
|
||||
}
|
||||
@ -176,12 +180,12 @@ unsigned char String::changeBuffer(unsigned int maxStrLen) {
|
||||
return false;
|
||||
}
|
||||
uint16_t oldLen = len();
|
||||
char *newbuffer = (char *) realloc(sso() ? nullptr : wbuffer(), newSize);
|
||||
if(newbuffer) {
|
||||
char *newbuffer = (char *) realloc(isSSO() ? nullptr : wbuffer(), newSize);
|
||||
if (newbuffer) {
|
||||
size_t oldSize = capacity() + 1; // include NULL.
|
||||
if (sso()) {
|
||||
if (isSSO()) {
|
||||
// Copy the SSO buffer into allocated space
|
||||
memcpy(newbuffer, sso_buf, sizeof(sso_buf));
|
||||
memmove(newbuffer, sso.buff, sizeof(sso.buff));
|
||||
}
|
||||
if (newSize > oldSize)
|
||||
{
|
||||
@ -206,7 +210,7 @@ String & String::copy(const char *cstr, unsigned int length) {
|
||||
return *this;
|
||||
}
|
||||
setLen(length);
|
||||
strcpy(wbuffer(), cstr);
|
||||
memmove(wbuffer(), cstr, length + 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -216,7 +220,7 @@ String & String::copy(const __FlashStringHelper *pstr, unsigned int length) {
|
||||
return *this;
|
||||
}
|
||||
setLen(length);
|
||||
strcpy_P(wbuffer(), (PGM_P)pstr);
|
||||
memcpy_P(wbuffer(), (PGM_P)pstr, length + 1); // We know wbuffer() cannot ever be in PROGMEM, so memcpy safe here
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -224,20 +228,20 @@ String & String::copy(const __FlashStringHelper *pstr, unsigned int length) {
|
||||
void String::move(String &rhs) {
|
||||
if(buffer()) {
|
||||
if(capacity() >= rhs.len()) {
|
||||
strcpy(wbuffer(), rhs.buffer());
|
||||
memmove(wbuffer(), rhs.buffer(), rhs.length() + 1);
|
||||
setLen(rhs.len());
|
||||
rhs.invalidate();
|
||||
return;
|
||||
} else {
|
||||
if (!sso()) {
|
||||
if (!isSSO()) {
|
||||
free(wbuffer());
|
||||
setBuffer(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rhs.sso()) {
|
||||
if (rhs.isSSO()) {
|
||||
setSSO(true);
|
||||
memmove(sso_buf, rhs.sso_buf, sizeof(sso_buf));
|
||||
memmove(sso.buff, rhs.sso.buff, sizeof(sso.buff));
|
||||
} else {
|
||||
setSSO(false);
|
||||
setBuffer(rhs.wbuffer());
|
||||
@ -309,7 +313,7 @@ unsigned char String::concat(const String &s) {
|
||||
return 1;
|
||||
if (!reserve(newlen))
|
||||
return 0;
|
||||
memcpy(wbuffer() + len(), buffer(), len());
|
||||
memmove(wbuffer() + len(), buffer(), len());
|
||||
setLen(newlen);
|
||||
wbuffer()[len()] = 0;
|
||||
return 1;
|
||||
@ -326,7 +330,12 @@ unsigned char String::concat(const char *cstr, unsigned int length) {
|
||||
return 1;
|
||||
if(!reserve(newlen))
|
||||
return 0;
|
||||
strcpy(wbuffer() + len(), cstr);
|
||||
if (cstr >= wbuffer() && cstr < wbuffer() + len())
|
||||
// compatible with SSO in ram #6155 (case "x += x.c_str()")
|
||||
memmove(wbuffer() + len(), cstr, length + 1);
|
||||
else
|
||||
// compatible with source in flash #6367
|
||||
memcpy_P(wbuffer() + len(), cstr, length + 1);
|
||||
setLen(newlen);
|
||||
return 1;
|
||||
}
|
||||
@ -392,7 +401,7 @@ unsigned char String::concat(const __FlashStringHelper * str) {
|
||||
if (length == 0) return 1;
|
||||
unsigned int newlen = len() + length;
|
||||
if (!reserve(newlen)) return 0;
|
||||
strcpy_P(wbuffer() + len(), (PGM_P)str);
|
||||
memcpy_P(wbuffer() + len(), (PGM_P)str, length + 1);
|
||||
setLen(newlen);
|
||||
return 1;
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <pgmspace.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// An inherited class for holding the result of a concatenation. These
|
||||
// result objects are assumed to be writable by subsequent concatenations.
|
||||
@ -35,7 +36,8 @@ class StringSumHelper;
|
||||
// an abstract class used as a means to proide a unique pointer type
|
||||
// but really has no body
|
||||
class __FlashStringHelper;
|
||||
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
|
||||
#define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))
|
||||
#define F(string_literal) (FPSTR(PSTR(string_literal)))
|
||||
|
||||
// The string class
|
||||
class String {
|
||||
@ -81,6 +83,12 @@ class String {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
inline void clear(void) {
|
||||
setLen(0);
|
||||
}
|
||||
inline bool isEmpty(void) const {
|
||||
return length() == 0;
|
||||
}
|
||||
|
||||
// creates a copy of the assigned value. if the value is null or
|
||||
// invalid, or if the memory allocation fails, the string will be
|
||||
@ -97,7 +105,7 @@ class String {
|
||||
|
||||
// returns true on success, false on failure (in which case, the string
|
||||
// is left unchanged). if the argument is null or invalid, the
|
||||
// concatenation is considered unsucessful.
|
||||
// concatenation is considered unsuccessful.
|
||||
unsigned char concat(const String &str);
|
||||
unsigned char concat(const char *cstr);
|
||||
unsigned char concat(char c);
|
||||
@ -198,7 +206,7 @@ class String {
|
||||
unsigned char startsWith(const String &prefix, unsigned int offset) const;
|
||||
unsigned char endsWith(const String &suffix) const;
|
||||
|
||||
// character acccess
|
||||
// character access
|
||||
char charAt(unsigned int index) const;
|
||||
void setCharAt(unsigned int index, char c);
|
||||
char operator [](unsigned int index) const;
|
||||
@ -249,27 +257,29 @@ class String {
|
||||
uint16_t cap;
|
||||
uint16_t len;
|
||||
};
|
||||
|
||||
// SSO is handled by checking the last byte of sso_buff.
|
||||
// When not in SSO mode, that byte is set to 0xff, while when in SSO mode it is always 0x00 (so it can serve as the string terminator as well as a flag)
|
||||
// This allows strings up up to 12 (11 + \0 termination) without any extra space.
|
||||
enum { SSOSIZE = sizeof(struct _ptr) + 4 }; // Characters to allocate space for SSO, must be 12 or more
|
||||
enum { CAPACITY_MAX = 65535 }; // If size of capacity changed, be sure to update this enum
|
||||
// This allows strings up up to 11 (10 + \0 termination) without any extra space.
|
||||
enum { SSOSIZE = sizeof(struct _ptr) + 4 - 1 }; // Characters to allocate space for SSO, must be 12 or more
|
||||
struct _sso {
|
||||
char buff[SSOSIZE];
|
||||
unsigned char len : 7; // Ensure only one byte is allocated by GCC for the bitfields
|
||||
unsigned char isSSO : 1;
|
||||
} __attribute__((packed)); // Ensure that GCC doesn't expand the flag byte to a 32-bit word for alignment issues
|
||||
enum { CAPACITY_MAX = 65535 }; // If typeof(cap) changed from uint16_t, be sure to update this enum to the max value storable in the type
|
||||
union {
|
||||
struct _ptr ptr;
|
||||
char sso_buf[SSOSIZE];
|
||||
struct _sso sso;
|
||||
};
|
||||
// Accessor functions
|
||||
inline bool sso() const { return sso_buf[SSOSIZE - 1] == 0; }
|
||||
inline unsigned int len() const { return sso() ? strlen(sso_buf) : ptr.len; }
|
||||
inline unsigned int capacity() const { return sso() ? SSOSIZE - 1 : ptr.cap; }
|
||||
inline void setSSO(bool sso) { sso_buf[SSOSIZE - 1] = sso ? 0x00 : 0xff; }
|
||||
inline void setLen(int len) { if (!sso()) ptr.len = len; }
|
||||
inline void setCapacity(int cap) { if (!sso()) ptr.cap = cap; }
|
||||
inline void setBuffer(char *buff) { if (!sso()) ptr.buff = buff; }
|
||||
inline bool isSSO() const { return sso.isSSO; }
|
||||
inline unsigned int len() const { return isSSO() ? sso.len : ptr.len; }
|
||||
inline unsigned int capacity() const { return isSSO() ? (unsigned int)SSOSIZE - 1 : ptr.cap; } // Size of max string not including terminal NUL
|
||||
inline void setSSO(bool set) { sso.isSSO = set; }
|
||||
inline void setLen(int len) { if (isSSO()) sso.len = len; else ptr.len = len; }
|
||||
inline void setCapacity(int cap) { if (!isSSO()) ptr.cap = cap; }
|
||||
inline void setBuffer(char *buff) { if (!isSSO()) ptr.buff = buff; }
|
||||
// Buffer accessor functions
|
||||
inline const char *buffer() const { return (const char *)(sso() ? sso_buf : ptr.buff); }
|
||||
inline char *wbuffer() const { return sso() ? const_cast<char *>(sso_buf) : ptr.buff; } // Writable version of buffer
|
||||
inline const char *buffer() const { return (const char *)(isSSO() ? sso.buff : ptr.buff); }
|
||||
inline char *wbuffer() const { return isSSO() ? const_cast<char *>(sso.buff) : ptr.buff; } // Writable version of buffer
|
||||
|
||||
protected:
|
||||
void init(void);
|
||||
|
@ -31,11 +31,11 @@ extern "C" {
|
||||
|
||||
/**
|
||||
* convert input data to base64
|
||||
* @param data uint8_t *
|
||||
* @param data const uint8_t *
|
||||
* @param length size_t
|
||||
* @return String
|
||||
*/
|
||||
String base64::encode(uint8_t * data, size_t length)
|
||||
String base64::encode(const uint8_t * data, size_t length)
|
||||
{
|
||||
size_t size = base64_encode_expected_len(length) + 1;
|
||||
char * buffer = (char *) malloc(size);
|
||||
@ -54,10 +54,10 @@ String base64::encode(uint8_t * data, size_t length)
|
||||
|
||||
/**
|
||||
* convert input data to base64
|
||||
* @param text String
|
||||
* @param text const String&
|
||||
* @return String
|
||||
*/
|
||||
String base64::encode(String text)
|
||||
String base64::encode(const String& text)
|
||||
{
|
||||
return base64::encode((uint8_t *) text.c_str(), text.length());
|
||||
}
|
||||
|
@ -4,8 +4,8 @@
|
||||
class base64
|
||||
{
|
||||
public:
|
||||
static String encode(uint8_t * data, size_t length);
|
||||
static String encode(String text);
|
||||
static String encode(const uint8_t * data, size_t length);
|
||||
static String encode(const String& text);
|
||||
private:
|
||||
};
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "rom/rtc.h"
|
||||
#include "soc/apb_ctrl_reg.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "esp32-hal.h"
|
||||
#include "esp32-hal-cpu.h"
|
||||
|
||||
@ -150,6 +151,15 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz){
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//check if cpu supports the frequency
|
||||
if(cpu_freq_mhz == 240){
|
||||
//Check if ESP32 is rated for a CPU frequency of 160MHz only
|
||||
if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_RATED) &&
|
||||
REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_LOW)) {
|
||||
log_e("Can not switch to 240 MHz! Chip CPU frequency rated for 160MHz.");
|
||||
cpu_freq_mhz = 160;
|
||||
}
|
||||
}
|
||||
//Get current CPU clock configuration
|
||||
rtc_clk_cpu_freq_get_config(&cconf);
|
||||
//return if frequency has not changed
|
||||
|
@ -1270,7 +1270,7 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
|
||||
|
||||
i2c->dev->ctr.trans_start=1; // go for it
|
||||
|
||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR
|
||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG
|
||||
portTickType tBefore=xTaskGetTickCount();
|
||||
#endif
|
||||
|
||||
@ -1278,7 +1278,7 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
|
||||
|
||||
uint32_t eBits = xEventGroupWaitBits(i2c->i2c_event,EVENT_DONE,pdFALSE,pdTRUE,ticksTimeOut);
|
||||
|
||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR
|
||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG
|
||||
portTickType tAfter=xTaskGetTickCount();
|
||||
#endif
|
||||
|
||||
|
@ -165,6 +165,7 @@ void timerStop(hw_timer_t *timer){
|
||||
|
||||
void timerRestart(hw_timer_t *timer){
|
||||
timer->dev->config.enable = 0;
|
||||
timer->dev->reload = 1;
|
||||
timer->dev->config.enable = 1;
|
||||
}
|
||||
|
||||
|
@ -343,6 +343,8 @@ void uartFlush(uart_t* uart)
|
||||
READ_PERI_REG(UART_FIFO_REG(uart->num));
|
||||
}
|
||||
|
||||
xQueueReset(uart->queue);
|
||||
|
||||
UART_MUTEX_UNLOCK();
|
||||
}
|
||||
|
||||
@ -399,7 +401,12 @@ uint32_t uartGetBaudRate(uart_t* uart)
|
||||
if(uart == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t clk_div = (uart->dev->clk_div.div_int << 4) | (uart->dev->clk_div.div_frag & 0x0F);
|
||||
if(!clk_div) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ((getApbFrequency()<<4)/clk_div);
|
||||
}
|
||||
|
||||
@ -520,6 +527,14 @@ unsigned long uartBaudrateDetect(uart_t *uart, bool flg)
|
||||
* detected calling uartBadrateDetect(). The raw baudrate is computed using the UART_CLK_FREQ. The raw baudrate is
|
||||
* rounded to the closed real baudrate.
|
||||
*/
|
||||
void uartStartDetectBaudrate(uart_t *uart) {
|
||||
if(!uart) return;
|
||||
|
||||
uart->dev->auto_baud.glitch_filt = 0x08;
|
||||
uart->dev->auto_baud.en = 0;
|
||||
uart->dev->auto_baud.en = 1;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
uartDetectBaudrate(uart_t *uart)
|
||||
{
|
||||
|
@ -72,6 +72,7 @@ size_t uartResizeRxBuffer(uart_t* uart, size_t new_size);
|
||||
void uartSetDebug(uart_t* uart);
|
||||
int uartGetDebug();
|
||||
|
||||
void uartStartDetectBaudrate(uart_t *uart);
|
||||
unsigned long uartDetectBaudrate(uart_t *uart);
|
||||
|
||||
bool uartRxActive(uart_t* uart);
|
||||
|
@ -32,7 +32,6 @@ typedef unsigned long prog_uint32_t;
|
||||
#define PROGMEM
|
||||
#define PGM_P const char *
|
||||
#define PGM_VOID_P const void *
|
||||
#define FPSTR(p) ((const char *)(p))
|
||||
#define PSTR(s) (s)
|
||||
#define _SFR_BYTE(n) (n)
|
||||
|
||||
|
@ -10,4 +10,4 @@ Starting with 1.6.4, Arduino allows installation of third-party platform package
|
||||
|
||||
Stable release link: `https://dl.espressif.com/dl/package_esp32_index.json`
|
||||
|
||||
Development release link: `https://dl.espressif.com/dl/package_esp32_dev_index.json`
|
||||
Development release link: `https://espressif.github.io/arduino-esp32/package_esp32_dev_index.json`
|
||||
|
@ -1,11 +1,11 @@
|
||||
Installation instructions for using PlatformIO
|
||||
=================================================
|
||||
|
||||
- [What is PlatformIO?](http://docs.platformio.org/en/latest/what-is-platformio.html?utm_source=github&utm_medium=arduino-esp32)
|
||||
- [PlatformIO IDE](http://platformio.org/platformio-ide?utm_source=github&utm_medium=arduino-esp32)
|
||||
- [PlatformIO Core](http://docs.platformio.org/en/latest/core.html?utm_source=github&utm_medium=arduino-esp32) (command line tool)
|
||||
- [Advanced usage](http://docs.platformio.org/en/latest/platforms/espressif32.html?utm_source=github&utm_medium=arduino-esp32) -
|
||||
- [What is PlatformIO?](https://docs.platformio.org/en/latest/what-is-platformio.html?utm_source=github&utm_medium=arduino-esp32)
|
||||
- [PlatformIO IDE](https://platformio.org/platformio-ide?utm_source=github&utm_medium=arduino-esp32)
|
||||
- [PlatformIO Core](https://docs.platformio.org/en/latest/core.html?utm_source=github&utm_medium=arduino-esp32) (command line tool)
|
||||
- [Advanced usage](https://docs.platformio.org/en/latest/platforms/espressif32.html?utm_source=github&utm_medium=arduino-esp32) -
|
||||
custom settings, uploading to SPIFFS, Over-the-Air (OTA), staging version
|
||||
- [Integration with Cloud and Standalone IDEs](http://docs.platformio.org/en/latest/ide.html?utm_source=github&utm_medium=arduino-esp32) -
|
||||
- [Integration with Cloud and Standalone IDEs](https://docs.platformio.org/en/latest/ide.html?utm_source=github&utm_medium=arduino-esp32) -
|
||||
Cloud9, Codeanywhere, Eclipse Che (Codenvy), Atom, CLion, Eclipse, Emacs, NetBeans, Qt Creator, Sublime Text, VIM, Visual Studio, and VSCode
|
||||
- [Project Examples](http://docs.platformio.org/en/latest/platforms/espressif32.html?utm_source=github&utm_medium=arduino-esp32#examples)
|
||||
- [Project Examples](https://docs.platformio.org/en/latest/platforms/espressif32.html?utm_source=github&utm_medium=arduino-esp32#examples)
|
||||
|
@ -127,9 +127,7 @@ void ArduinoOTAClass::begin() {
|
||||
}
|
||||
_initialized = true;
|
||||
_state = OTA_IDLE;
|
||||
#ifdef OTA_DEBUG
|
||||
OTA_DEBUG.printf("OTA server at: %s.local:%u\n", _hostname.c_str(), _port);
|
||||
#endif
|
||||
log_i("OTA server at: %s.local:%u", _hostname.c_str(), _port);
|
||||
}
|
||||
|
||||
int ArduinoOTAClass::parseInt(){
|
||||
@ -173,6 +171,7 @@ void ArduinoOTAClass::_onRx(){
|
||||
_md5 = readStringUntil('\n');
|
||||
_md5.trim();
|
||||
if(_md5.length() != 32){
|
||||
log_e("bad md5 length");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -198,6 +197,7 @@ void ArduinoOTAClass::_onRx(){
|
||||
} else if (_state == OTA_WAITAUTH) {
|
||||
int cmd = parseInt();
|
||||
if (cmd != U_AUTH) {
|
||||
log_e("%d was expected. got %d instead", U_AUTH, cmd);
|
||||
_state = OTA_IDLE;
|
||||
return;
|
||||
}
|
||||
@ -205,6 +205,7 @@ void ArduinoOTAClass::_onRx(){
|
||||
String cnonce = readStringUntil(' ');
|
||||
String response = readStringUntil('\n');
|
||||
if (cnonce.length() != 32 || response.length() != 32) {
|
||||
log_e("auth param fail");
|
||||
_state = OTA_IDLE;
|
||||
return;
|
||||
}
|
||||
@ -225,6 +226,7 @@ void ArduinoOTAClass::_onRx(){
|
||||
} else {
|
||||
_udp_ota.beginPacket(_udp_ota.remoteIP(), _udp_ota.remotePort());
|
||||
_udp_ota.print("Authentication Failed");
|
||||
log_w("Authentication Failed");
|
||||
_udp_ota.endPacket();
|
||||
if (_error_callback) _error_callback(OTA_AUTH_ERROR);
|
||||
_state = OTA_IDLE;
|
||||
@ -234,9 +236,9 @@ void ArduinoOTAClass::_onRx(){
|
||||
|
||||
void ArduinoOTAClass::_runUpdate() {
|
||||
if (!Update.begin(_size, _cmd)) {
|
||||
#ifdef OTA_DEBUG
|
||||
Update.printError(OTA_DEBUG);
|
||||
#endif
|
||||
|
||||
log_e("Begin ERROR: %s", Update.errorString());
|
||||
|
||||
if (_error_callback) {
|
||||
_error_callback(OTA_BEGIN_ERROR);
|
||||
}
|
||||
@ -272,21 +274,15 @@ void ArduinoOTAClass::_runUpdate() {
|
||||
}
|
||||
if (!waited){
|
||||
if(written && tried++ < 3){
|
||||
#ifdef OTA_DEBUG
|
||||
OTA_DEBUG.printf("Try[%u]: %u\n", tried, written);
|
||||
#endif
|
||||
log_i("Try[%u]: %u", tried, written);
|
||||
if(!client.printf("%u", written)){
|
||||
#ifdef OTA_DEBUG
|
||||
OTA_DEBUG.printf("failed to respond\n");
|
||||
#endif
|
||||
log_e("failed to respond");
|
||||
_state = OTA_IDLE;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
#ifdef OTA_DEBUG
|
||||
OTA_DEBUG.printf("Receive Failed\n");
|
||||
#endif
|
||||
log_e("Receive Failed");
|
||||
if (_error_callback) {
|
||||
_error_callback(OTA_RECEIVE_ERROR);
|
||||
}
|
||||
@ -295,9 +291,7 @@ void ArduinoOTAClass::_runUpdate() {
|
||||
return;
|
||||
}
|
||||
if(!available){
|
||||
#ifdef OTA_DEBUG
|
||||
OTA_DEBUG.printf("No Data: %u\n", waited);
|
||||
#endif
|
||||
log_e("No Data: %u", waited);
|
||||
_state = OTA_IDLE;
|
||||
break;
|
||||
}
|
||||
@ -317,18 +311,14 @@ void ArduinoOTAClass::_runUpdate() {
|
||||
log_w("didn't write enough! %u != %u", written, r);
|
||||
}
|
||||
if(!client.printf("%u", written)){
|
||||
#ifdef OTA_DEBUG
|
||||
OTA_DEBUG.printf("failed to respond\n");
|
||||
#endif
|
||||
log_w("failed to respond");
|
||||
}
|
||||
total += written;
|
||||
if(_progress_callback) {
|
||||
_progress_callback(total, _size);
|
||||
}
|
||||
} else {
|
||||
#ifdef OTA_DEBUG
|
||||
Update.printError(OTA_DEBUG);
|
||||
#endif
|
||||
log_e("Write ERROR: %s", Update.errorString());
|
||||
}
|
||||
}
|
||||
|
||||
@ -351,10 +341,7 @@ void ArduinoOTAClass::_runUpdate() {
|
||||
Update.printError(client);
|
||||
client.stop();
|
||||
delay(10);
|
||||
#ifdef OTA_DEBUG
|
||||
OTA_DEBUG.print("Update ERROR: ");
|
||||
Update.printError(OTA_DEBUG);
|
||||
#endif
|
||||
log_e("Update ERROR: %s", Update.errorString());
|
||||
_state = OTA_IDLE;
|
||||
}
|
||||
}
|
||||
@ -366,9 +353,7 @@ void ArduinoOTAClass::end() {
|
||||
MDNS.end();
|
||||
}
|
||||
_state = OTA_IDLE;
|
||||
#ifdef OTA_DEBUG
|
||||
OTA_DEBUG.println("OTA server stopped.");
|
||||
#endif
|
||||
log_i("OTA server stopped.");
|
||||
}
|
||||
|
||||
void ArduinoOTAClass::handle() {
|
||||
@ -395,4 +380,4 @@ void ArduinoOTAClass::setTimeout(int timeoutInMillis) {
|
||||
|
||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_ARDUINOOTA)
|
||||
ArduinoOTAClass ArduinoOTA;
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1,17 +0,0 @@
|
||||
{
|
||||
"name":"AsyncUDP",
|
||||
"description":"Asynchronous UDP Library for ESP32",
|
||||
"keywords":"async,udp,server,client,multicast,broadcast",
|
||||
"authors":
|
||||
{
|
||||
"name": "Hristo Gochkov",
|
||||
"maintainer": true
|
||||
},
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/me-no-dev/ESPAsyncUDP.git"
|
||||
},
|
||||
"frameworks": "arduino",
|
||||
"platforms":"espressif"
|
||||
}
|
@ -682,8 +682,9 @@ void AsyncUDP::_recv(udp_pcb *upcb, pbuf *pb, const ip_addr_t *addr, uint16_t po
|
||||
if(_handler) {
|
||||
AsyncUDPPacket packet(this, this_pb, addr, port, netif);
|
||||
_handler(packet);
|
||||
} else {
|
||||
pbuf_free(this_pb);
|
||||
}
|
||||
pbuf_free(this_pb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,6 +87,7 @@ bool connectToServer() {
|
||||
pRemoteCharacteristic->registerForNotify(notifyCallback);
|
||||
|
||||
connected = true;
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Scan for BLE servers and find the first one that advertises the service we are looking for.
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <iomanip>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#include "esp32-hal-log.h"
|
||||
#endif
|
||||
@ -83,13 +84,11 @@ esp_bd_addr_t *BLEAddress::getNative() {
|
||||
* @return The string representation of the address.
|
||||
*/
|
||||
std::string BLEAddress::toString() {
|
||||
std::stringstream stream;
|
||||
stream << std::setfill('0') << std::setw(2) << std::hex << (int) ((uint8_t*) (m_address))[0] << ':';
|
||||
stream << std::setfill('0') << std::setw(2) << std::hex << (int) ((uint8_t*) (m_address))[1] << ':';
|
||||
stream << std::setfill('0') << std::setw(2) << std::hex << (int) ((uint8_t*) (m_address))[2] << ':';
|
||||
stream << std::setfill('0') << std::setw(2) << std::hex << (int) ((uint8_t*) (m_address))[3] << ':';
|
||||
stream << std::setfill('0') << std::setw(2) << std::hex << (int) ((uint8_t*) (m_address))[4] << ':';
|
||||
stream << std::setfill('0') << std::setw(2) << std::hex << (int) ((uint8_t*) (m_address))[5];
|
||||
return stream.str();
|
||||
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]);
|
||||
std::string ret(res);
|
||||
free(res);
|
||||
return ret;
|
||||
} // toString
|
||||
#endif
|
||||
|
@ -484,23 +484,29 @@ void BLEAdvertisedDevice::setTXPower(int8_t txPower) {
|
||||
* @return A string representation of this device.
|
||||
*/
|
||||
std::string BLEAdvertisedDevice::toString() {
|
||||
std::stringstream ss;
|
||||
ss << "Name: " << getName() << ", Address: " << getAddress().toString();
|
||||
std::string res = "Name: " + getName() + ", Address: " + getAddress().toString();
|
||||
if (haveAppearance()) {
|
||||
ss << ", appearance: " << getAppearance();
|
||||
char val[6];
|
||||
snprintf(val, sizeof(val), "%d", getAppearance());
|
||||
res += ", appearance: ";
|
||||
res += val;
|
||||
}
|
||||
if (haveManufacturerData()) {
|
||||
char *pHex = BLEUtils::buildHexData(nullptr, (uint8_t*)getManufacturerData().data(), getManufacturerData().length());
|
||||
ss << ", manufacturer data: " << pHex;
|
||||
res += ", manufacturer data: ";
|
||||
res += pHex;
|
||||
free(pHex);
|
||||
}
|
||||
if (haveServiceUUID()) {
|
||||
ss << ", serviceUUID: " << getServiceUUID().toString();
|
||||
res += ", serviceUUID: " + getServiceUUID().toString();
|
||||
}
|
||||
if (haveTXPower()) {
|
||||
ss << ", txPower: " << (int)getTXPower();
|
||||
char val[4];
|
||||
snprintf(val, sizeof(val), "%d", getTXPower());
|
||||
res += ", txPower: ";
|
||||
res += val;
|
||||
}
|
||||
return ss.str();
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
uint8_t* BLEAdvertisedDevice::getPayload() {
|
||||
|
@ -262,7 +262,7 @@ void BLEAdvertising::stop() {
|
||||
|
||||
void BLEAdvertising::setDeviceAddress(esp_bd_addr_t addr, esp_ble_addr_type_t type)
|
||||
{
|
||||
log_v(">> setPrivateAddress")
|
||||
log_v(">> setPrivateAddress");
|
||||
|
||||
m_advParams.own_addr_type = type;
|
||||
esp_err_t errRc = esp_ble_gap_set_rand_addr((uint8_t*)addr);
|
||||
@ -271,7 +271,7 @@ void BLEAdvertising::setDeviceAddress(esp_bd_addr_t addr, esp_ble_addr_type_t ty
|
||||
log_e("esp_ble_gap_set_rand_addr: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
|
||||
return;
|
||||
}
|
||||
log_v("<< setPrivateAddress")
|
||||
log_v("<< setPrivateAddress");
|
||||
} // setPrivateAddress
|
||||
|
||||
/**
|
||||
@ -505,7 +505,7 @@ void BLEAdvertising::handleGAPEvent(
|
||||
}
|
||||
case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: {
|
||||
log_i("STOP advertising");
|
||||
start();
|
||||
//start();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#define NULL_HANDLE (0xffff)
|
||||
|
||||
static BLECharacteristicCallbacks defaultCallback; //null-object-pattern
|
||||
|
||||
/**
|
||||
* @brief Construct a characteristic
|
||||
@ -40,7 +41,7 @@ BLECharacteristic::BLECharacteristic(BLEUUID uuid, uint32_t properties) {
|
||||
m_bleUUID = uuid;
|
||||
m_handle = NULL_HANDLE;
|
||||
m_properties = (esp_gatt_char_prop_t)0;
|
||||
m_pCallbacks = nullptr;
|
||||
m_pCallbacks = &defaultCallback;
|
||||
|
||||
setBroadcastProperty((properties & PROPERTY_BROADCAST) != 0);
|
||||
setReadProperty((properties & PROPERTY_READ) != 0);
|
||||
@ -220,9 +221,7 @@ void BLECharacteristic::handleGATTServerEvent(
|
||||
case ESP_GATTS_EXEC_WRITE_EVT: {
|
||||
if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) {
|
||||
m_value.commit();
|
||||
if (m_pCallbacks != nullptr) {
|
||||
m_pCallbacks->onWrite(this); // Invoke the onWrite callback handler.
|
||||
}
|
||||
m_pCallbacks->onWrite(this); // Invoke the onWrite callback handler.
|
||||
} else {
|
||||
m_value.cancel();
|
||||
}
|
||||
@ -307,7 +306,7 @@ void BLECharacteristic::handleGATTServerEvent(
|
||||
}
|
||||
} // Response needed
|
||||
|
||||
if (m_pCallbacks != nullptr && param->write.is_prep != true) {
|
||||
if (param->write.is_prep != true) {
|
||||
m_pCallbacks->onWrite(this); // Invoke the onWrite callback handler.
|
||||
}
|
||||
} // Match on handles.
|
||||
@ -378,6 +377,10 @@ void BLECharacteristic::handleGATTServerEvent(
|
||||
}
|
||||
} else { // read.is_long == false
|
||||
|
||||
// If is.long is false then this is the first (or only) request to read data, so invoke the callback
|
||||
// Invoke the read callback.
|
||||
m_pCallbacks->onRead(this);
|
||||
|
||||
std::string value = m_value.getValue();
|
||||
|
||||
if (value.length() + 1 > maxOffset) {
|
||||
@ -392,10 +395,6 @@ void BLECharacteristic::handleGATTServerEvent(
|
||||
rsp.attr_value.offset = 0;
|
||||
memcpy(rsp.attr_value.value, value.data(), rsp.attr_value.len);
|
||||
}
|
||||
|
||||
if (m_pCallbacks != nullptr) { // If is.long is false then this is the first (or only) request to read data, so invoke the callback
|
||||
m_pCallbacks->onRead(this); // Invoke the read callback.
|
||||
}
|
||||
}
|
||||
rsp.attr_value.handle = param->read.handle;
|
||||
rsp.attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE;
|
||||
@ -480,10 +479,13 @@ void BLECharacteristic::notify(bool is_notification) {
|
||||
assert(getService() != nullptr);
|
||||
assert(getService()->getServer() != nullptr);
|
||||
|
||||
m_pCallbacks->onNotify(this); // Invoke the notify callback.
|
||||
|
||||
GeneralUtils::hexDump((uint8_t*)m_value.getValue().data(), m_value.getValue().length());
|
||||
|
||||
if (getService()->getServer()->getConnectedCount() == 0) {
|
||||
log_v("<< notify: No connected clients.");
|
||||
m_pCallbacks->onStatus(this, BLECharacteristicCallbacks::Status::ERROR_NO_CLIENT, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -494,12 +496,14 @@ void BLECharacteristic::notify(bool is_notification) {
|
||||
if(is_notification) {
|
||||
if (p2902 != nullptr && !p2902->getNotifications()) {
|
||||
log_v("<< notifications disabled; ignoring");
|
||||
m_pCallbacks->onStatus(this, BLECharacteristicCallbacks::Status::ERROR_NOTIFY_DISABLED, 0); // Invoke the notify callback.
|
||||
return;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (p2902 != nullptr && !p2902->getIndications()) {
|
||||
log_v("<< indications disabled; ignoring");
|
||||
m_pCallbacks->onStatus(this, BLECharacteristicCallbacks::Status::ERROR_INDICATE_DISABLED, 0); // Invoke the notify callback.
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -510,7 +514,7 @@ void BLECharacteristic::notify(bool is_notification) {
|
||||
}
|
||||
|
||||
size_t length = m_value.getValue().length();
|
||||
if(!is_notification)
|
||||
if(!is_notification) // is indication
|
||||
m_semaphoreConfEvt.take("indicate");
|
||||
esp_err_t errRc = ::esp_ble_gatts_send_indicate(
|
||||
getService()->getServer()->getGattsIf(),
|
||||
@ -519,10 +523,23 @@ void BLECharacteristic::notify(bool is_notification) {
|
||||
if (errRc != ESP_OK) {
|
||||
log_e("<< esp_ble_gatts_send_ %s: rc=%d %s",is_notification?"notify":"indicate", errRc, GeneralUtils::errorToString(errRc));
|
||||
m_semaphoreConfEvt.give();
|
||||
m_pCallbacks->onStatus(this, BLECharacteristicCallbacks::Status::ERROR_GATT, errRc); // Invoke the notify callback.
|
||||
return;
|
||||
}
|
||||
if(!is_notification)
|
||||
m_semaphoreConfEvt.wait("indicate");
|
||||
if(!is_notification){ // is indication
|
||||
if(!m_semaphoreConfEvt.timedWait("indicate", indicationTimeout)){
|
||||
m_pCallbacks->onStatus(this, BLECharacteristicCallbacks::Status::ERROR_INDICATE_TIMEOUT, 0); // Invoke the notify callback.
|
||||
} else {
|
||||
auto code = (esp_gatt_status_t) m_semaphoreConfEvt.value();
|
||||
if(code == ESP_GATT_OK) {
|
||||
m_pCallbacks->onStatus(this, BLECharacteristicCallbacks::Status::SUCCESS_INDICATE, code); // Invoke the notify callback.
|
||||
} else {
|
||||
m_pCallbacks->onStatus(this, BLECharacteristicCallbacks::Status::ERROR_INDICATE_FAILURE, code);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m_pCallbacks->onStatus(this, BLECharacteristicCallbacks::Status::SUCCESS_NOTIFY, 0); // Invoke the notify callback.
|
||||
}
|
||||
}
|
||||
log_v("<< notify");
|
||||
} // Notify
|
||||
@ -551,7 +568,11 @@ void BLECharacteristic::setBroadcastProperty(bool value) {
|
||||
*/
|
||||
void BLECharacteristic::setCallbacks(BLECharacteristicCallbacks* pCallbacks) {
|
||||
log_v(">> setCallbacks: 0x%x", (uint32_t)pCallbacks);
|
||||
m_pCallbacks = pCallbacks;
|
||||
if (pCallbacks != nullptr){
|
||||
m_pCallbacks = pCallbacks;
|
||||
} else {
|
||||
m_pCallbacks = &defaultCallback;
|
||||
}
|
||||
log_v("<< setCallbacks");
|
||||
} // setCallbacks
|
||||
|
||||
@ -628,7 +649,9 @@ void BLECharacteristic::setValue(uint8_t* data, size_t length) {
|
||||
log_e("Size %d too large, must be no bigger than %d", length, ESP_GATT_MAX_ATTR_LEN);
|
||||
return;
|
||||
}
|
||||
m_semaphoreSetValue.take();
|
||||
m_value.setValue(data, length);
|
||||
m_semaphoreSetValue.give();
|
||||
log_v("<< setValue");
|
||||
} // setValue
|
||||
|
||||
@ -670,15 +693,13 @@ void BLECharacteristic::setValue(int& data32) {
|
||||
} // setValue
|
||||
|
||||
void BLECharacteristic::setValue(float& data32) {
|
||||
uint8_t temp[4];
|
||||
*((float*)temp) = data32;
|
||||
setValue(temp, 4);
|
||||
float temp = data32;
|
||||
setValue((uint8_t*)&temp, 4);
|
||||
} // setValue
|
||||
|
||||
void BLECharacteristic::setValue(double& data64) {
|
||||
uint8_t temp[8];
|
||||
*((double*)temp) = data64;
|
||||
setValue(temp, 8);
|
||||
double temp = data64;
|
||||
setValue((uint8_t*)&temp, 8);
|
||||
} // setValue
|
||||
|
||||
|
||||
@ -715,17 +736,18 @@ void BLECharacteristic::setWriteProperty(bool value) {
|
||||
* @return A string representation of the characteristic.
|
||||
*/
|
||||
std::string BLECharacteristic::toString() {
|
||||
std::stringstream stringstream;
|
||||
stringstream << std::hex << std::setfill('0');
|
||||
stringstream << "UUID: " << m_bleUUID.toString() + ", handle: 0x" << std::setw(2) << m_handle;
|
||||
stringstream << " " <<
|
||||
((m_properties & ESP_GATT_CHAR_PROP_BIT_READ) ? "Read " : "") <<
|
||||
((m_properties & ESP_GATT_CHAR_PROP_BIT_WRITE) ? "Write " : "") <<
|
||||
((m_properties & ESP_GATT_CHAR_PROP_BIT_WRITE_NR) ? "WriteNoResponse " : "") <<
|
||||
((m_properties & ESP_GATT_CHAR_PROP_BIT_BROADCAST) ? "Broadcast " : "") <<
|
||||
((m_properties & ESP_GATT_CHAR_PROP_BIT_NOTIFY) ? "Notify " : "") <<
|
||||
((m_properties & ESP_GATT_CHAR_PROP_BIT_INDICATE) ? "Indicate " : "");
|
||||
return stringstream.str();
|
||||
std::string res = "UUID: " + m_bleUUID.toString() + ", handle : 0x";
|
||||
char hex[5];
|
||||
snprintf(hex, sizeof(hex), "%04x", m_handle);
|
||||
res += hex;
|
||||
res += " ";
|
||||
if (m_properties & ESP_GATT_CHAR_PROP_BIT_READ) res += "Read ";
|
||||
if (m_properties & ESP_GATT_CHAR_PROP_BIT_WRITE) res += "Write ";
|
||||
if (m_properties & ESP_GATT_CHAR_PROP_BIT_WRITE_NR) res += "WriteNoResponse ";
|
||||
if (m_properties & ESP_GATT_CHAR_PROP_BIT_BROADCAST) res += "Broadcast ";
|
||||
if (m_properties & ESP_GATT_CHAR_PROP_BIT_NOTIFY) res += "Notify ";
|
||||
if (m_properties & ESP_GATT_CHAR_PROP_BIT_INDICATE) res += "Indicate ";
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
|
||||
@ -751,4 +773,27 @@ void BLECharacteristicCallbacks::onWrite(BLECharacteristic* pCharacteristic) {
|
||||
log_d("BLECharacteristicCallbacks", "<< onWrite");
|
||||
} // onWrite
|
||||
|
||||
|
||||
/**
|
||||
* @brief Callback function to support a Notify request.
|
||||
* @param [in] pCharacteristic The characteristic that is the source of the event.
|
||||
*/
|
||||
void BLECharacteristicCallbacks::onNotify(BLECharacteristic* pCharacteristic) {
|
||||
log_d("BLECharacteristicCallbacks", ">> onNotify: default");
|
||||
log_d("BLECharacteristicCallbacks", "<< onNotify");
|
||||
} // onNotify
|
||||
|
||||
|
||||
/**
|
||||
* @brief Callback function to support a Notify/Indicate Status report.
|
||||
* @param [in] pCharacteristic The characteristic that is the source of the event.
|
||||
* @param [in] s Status of the notification/indication
|
||||
* @param [in] code Additional code of underlying errors
|
||||
*/
|
||||
void BLECharacteristicCallbacks::onStatus(BLECharacteristic* pCharacteristic, Status s, uint32_t code) {
|
||||
log_d("BLECharacteristicCallbacks", ">> onStatus: default");
|
||||
log_d("BLECharacteristicCallbacks", "<< onStatus");
|
||||
} // onStatus
|
||||
|
||||
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
|
@ -90,6 +90,8 @@ public:
|
||||
static const uint32_t PROPERTY_INDICATE = 1<<4;
|
||||
static const uint32_t PROPERTY_WRITE_NR = 1<<5;
|
||||
|
||||
static const uint32_t indicationTimeout = 1000;
|
||||
|
||||
private:
|
||||
|
||||
friend class BLEServer;
|
||||
@ -117,6 +119,7 @@ private:
|
||||
void setHandle(uint16_t handle);
|
||||
FreeRTOS::Semaphore m_semaphoreCreateEvt = FreeRTOS::Semaphore("CreateEvt");
|
||||
FreeRTOS::Semaphore m_semaphoreConfEvt = FreeRTOS::Semaphore("ConfEvt");
|
||||
FreeRTOS::Semaphore m_semaphoreSetValue = FreeRTOS::Semaphore("SetValue");
|
||||
}; // BLECharacteristic
|
||||
|
||||
|
||||
@ -129,9 +132,22 @@ private:
|
||||
*/
|
||||
class BLECharacteristicCallbacks {
|
||||
public:
|
||||
typedef enum {
|
||||
SUCCESS_INDICATE,
|
||||
SUCCESS_NOTIFY,
|
||||
ERROR_INDICATE_DISABLED,
|
||||
ERROR_NOTIFY_DISABLED,
|
||||
ERROR_GATT,
|
||||
ERROR_NO_CLIENT,
|
||||
ERROR_INDICATE_TIMEOUT,
|
||||
ERROR_INDICATE_FAILURE
|
||||
}Status;
|
||||
|
||||
virtual ~BLECharacteristicCallbacks();
|
||||
virtual void onRead(BLECharacteristic* pCharacteristic);
|
||||
virtual void onWrite(BLECharacteristic* pCharacteristic);
|
||||
virtual void onNotify(BLECharacteristic* pCharacteristic);
|
||||
virtual void onStatus(BLECharacteristic* pCharacteristic, Status s, uint32_t code);
|
||||
};
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
#endif /* COMPONENTS_CPP_UTILS_BLECHARACTERISTIC_H_ */
|
||||
|
@ -116,17 +116,18 @@ void BLECharacteristicMap::setByUUID(BLECharacteristic* pCharacteristic, BLEUUID
|
||||
* @return A string representation of the characteristic map.
|
||||
*/
|
||||
std::string BLECharacteristicMap::toString() {
|
||||
std::stringstream stringStream;
|
||||
stringStream << std::hex << std::setfill('0');
|
||||
std::string res;
|
||||
int count = 0;
|
||||
char hex[5];
|
||||
for (auto &myPair: m_uuidMap) {
|
||||
if (count > 0) {
|
||||
stringStream << "\n";
|
||||
}
|
||||
if (count > 0) {res += "\n";}
|
||||
snprintf(hex, sizeof(hex), "%04x", myPair.first->getHandle());
|
||||
count++;
|
||||
stringStream << "handle: 0x" << std::setw(2) << myPair.first->getHandle() << ", uuid: " + myPair.first->getUUID().toString();
|
||||
res += "handle: 0x";
|
||||
res += hex;
|
||||
res += ", uuid: " + myPair.first->getUUID().toString();
|
||||
}
|
||||
return stringStream.str();
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
|
||||
|
@ -184,10 +184,11 @@ void BLEClient::gattClientEventHandler(
|
||||
if (m_pClientCallbacks != nullptr) {
|
||||
m_pClientCallbacks->onDisconnect(this);
|
||||
}
|
||||
BLEDevice::removePeerDevice(m_appId, true);
|
||||
esp_ble_gattc_app_unregister(m_gattc_if);
|
||||
m_semaphoreOpenEvt.give(ESP_GATT_IF_NONE);
|
||||
m_semaphoreRssiCmplEvt.give();
|
||||
m_semaphoreSearchCmplEvt.give(1);
|
||||
BLEDevice::removePeerDevice(m_appId, true);
|
||||
break;
|
||||
} // ESP_GATTC_DISCONNECT_EVT
|
||||
|
||||
@ -515,14 +516,13 @@ uint16_t BLEClient::getMTU() {
|
||||
* @return A string representation of this client.
|
||||
*/
|
||||
std::string BLEClient::toString() {
|
||||
std::ostringstream ss;
|
||||
ss << "peer address: " << m_peerAddress.toString();
|
||||
ss << "\nServices:\n";
|
||||
std::string res = "peer address: " + m_peerAddress.toString();
|
||||
res += "\nServices:\n";
|
||||
for (auto &myPair : m_servicesMap) {
|
||||
ss << myPair.second->toString() << "\n";
|
||||
res += myPair.second->toString() + "\n";
|
||||
// myPair.second is the value
|
||||
}
|
||||
return ss.str();
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <string.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "BLEExceptions.h"
|
||||
//#include "BLEExceptions.h"
|
||||
#include "BLERemoteService.h"
|
||||
#include "BLEService.h"
|
||||
#include "BLEAddress.h"
|
||||
|
@ -255,10 +255,10 @@ void BLEDescriptor::setAccessPermissions(esp_gatt_perm_t perm) {
|
||||
* @return A string representation of the descriptor.
|
||||
*/
|
||||
std::string BLEDescriptor::toString() {
|
||||
std::stringstream stringstream;
|
||||
stringstream << std::hex << std::setfill('0');
|
||||
stringstream << "UUID: " << m_bleUUID.toString() + ", handle: 0x" << std::setw(2) << m_handle;
|
||||
return stringstream.str();
|
||||
char hex[5];
|
||||
snprintf(hex, sizeof(hex), "%04x", m_handle);
|
||||
std::string res = "UUID: " + m_bleUUID.toString() + ", handle: 0x" + hex;
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
|
||||
|
@ -90,17 +90,18 @@ void BLEDescriptorMap::setByHandle(uint16_t handle, BLEDescriptor* pDescriptor)
|
||||
* @return A string representation of the descriptor map.
|
||||
*/
|
||||
std::string BLEDescriptorMap::toString() {
|
||||
std::stringstream stringStream;
|
||||
stringStream << std::hex << std::setfill('0');
|
||||
std::string res;
|
||||
char hex[5];
|
||||
int count = 0;
|
||||
for (auto &myPair : m_uuidMap) {
|
||||
if (count > 0) {
|
||||
stringStream << "\n";
|
||||
}
|
||||
if (count > 0) {res += "\n";}
|
||||
snprintf(hex, sizeof(hex), "%04x", myPair.first->getHandle());
|
||||
count++;
|
||||
stringStream << "handle: 0x" << std::setw(2) << myPair.first->getHandle() << ", uuid: " + myPair.first->getUUID().toString();
|
||||
res += "handle: 0x";
|
||||
res += hex;
|
||||
res += ", uuid: " + myPair.first->getUUID().toString();
|
||||
}
|
||||
return stringStream.str();
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
|
||||
|
@ -32,14 +32,8 @@
|
||||
#include "esp32-hal-bt.h"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ARDUHAL_ESP_LOG)
|
||||
#include "esp32-hal-log.h"
|
||||
|
||||
#else
|
||||
#include "esp_log.h"
|
||||
static const char* LOG_TAG = "BLEDevice";
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Singletons for the BLEDevice.
|
||||
@ -479,9 +473,8 @@ gatts_event_handler BLEDevice::m_customGattsHandler = nullptr;
|
||||
* @return A string representation of the nature of this device.
|
||||
*/
|
||||
/* STATIC */ std::string BLEDevice::toString() {
|
||||
std::ostringstream oss;
|
||||
oss << "BD Address: " << getAddress().toString();
|
||||
return oss.str();
|
||||
std::string res = "BD Address: " + getAddress().toString();
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
|
||||
@ -626,7 +619,7 @@ void BLEDevice::removePeerDevice(uint16_t conn_id, bool _client) {
|
||||
esp_bluedroid_deinit();
|
||||
esp_bt_controller_disable();
|
||||
esp_bt_controller_deinit();
|
||||
#ifndef ARDUINO_ARCH_ESP32
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
if (release_memory) {
|
||||
esp_bt_controller_mem_release(ESP_BT_MODE_BTDM); // <-- require tests because we released classic BT memory and this can cause crash (most likely not, esp-idf takes care of it)
|
||||
} else {
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#include <string.h>
|
||||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
#include "esp32-hal-log.h"
|
||||
#include "BLEEddystoneTLM.h"
|
||||
|
||||
@ -54,62 +54,44 @@ uint32_t BLEEddystoneTLM::getTime() {
|
||||
} // getTime
|
||||
|
||||
std::string BLEEddystoneTLM::toString() {
|
||||
std::stringstream ss;
|
||||
std::string out = "";
|
||||
uint32_t rawsec;
|
||||
ss << "Version ";
|
||||
ss << std::dec << m_eddystoneData.version;
|
||||
ss << "\n";
|
||||
std::string out = "";
|
||||
uint32_t rawsec = ENDIAN_CHANGE_U32(m_eddystoneData.tmil);
|
||||
char val[6];
|
||||
|
||||
ss << "Battery Voltage ";
|
||||
ss << std::dec << ENDIAN_CHANGE_U16(m_eddystoneData.volt);
|
||||
ss << " mV\n";
|
||||
out += "Version " + m_eddystoneData.version;
|
||||
out += "\n";
|
||||
out += "Battery Voltage " + ENDIAN_CHANGE_U16(m_eddystoneData.volt);
|
||||
out += " mV\n";
|
||||
|
||||
ss << "Temperature ";
|
||||
ss << (float) m_eddystoneData.temp;
|
||||
ss << " °C\n";
|
||||
out += "Temperature ";
|
||||
snprintf(val, sizeof(val), "%d", m_eddystoneData.temp);
|
||||
out += val;
|
||||
out += ".0 °C\n";
|
||||
|
||||
ss << "Adv. Count ";
|
||||
ss << std::dec << ENDIAN_CHANGE_U32(m_eddystoneData.advCount);
|
||||
out += "Adv. Count ";
|
||||
snprintf(val, sizeof(val), "%d", ENDIAN_CHANGE_U32(m_eddystoneData.advCount));
|
||||
out += val;
|
||||
out += "\n";
|
||||
|
||||
ss << "\n";
|
||||
out += "Time ";
|
||||
|
||||
ss << "Time ";
|
||||
snprintf(val, sizeof(val), "%04d", rawsec / 864000);
|
||||
out += val;
|
||||
out += ".";
|
||||
|
||||
rawsec = ENDIAN_CHANGE_U32(m_eddystoneData.tmil);
|
||||
std::stringstream buffstream;
|
||||
buffstream << "0000";
|
||||
buffstream << std::dec << rawsec / 864000;
|
||||
std::string buff = buffstream.str();
|
||||
snprintf(val, sizeof(val), "%02d", (rawsec / 36000) % 24);
|
||||
out += val;
|
||||
out += ":";
|
||||
|
||||
ss << buff.substr(buff.length() - 4, buff.length());
|
||||
ss << ".";
|
||||
snprintf(val, sizeof(val), "%02d", (rawsec / 600) % 60);
|
||||
out += val;
|
||||
out += ":";
|
||||
|
||||
buffstream.str("");
|
||||
buffstream.clear();
|
||||
buffstream << "00";
|
||||
buffstream << std::dec << (rawsec / 36000) % 24;
|
||||
buff = buffstream.str();
|
||||
ss << buff.substr(buff.length()-2, buff.length());
|
||||
ss << ":";
|
||||
snprintf(val, sizeof(val), "%02d", (rawsec / 10) % 60);
|
||||
out += val;
|
||||
out += "\n";
|
||||
|
||||
buffstream.str("");
|
||||
buffstream.clear();
|
||||
buffstream << "00";
|
||||
buffstream << std::dec << (rawsec / 600) % 60;
|
||||
buff = buffstream.str();
|
||||
ss << buff.substr(buff.length() - 2, buff.length());
|
||||
ss << ":";
|
||||
|
||||
buffstream.str("");
|
||||
buffstream.clear();
|
||||
buffstream << "00";
|
||||
buffstream << std::dec << (rawsec / 10) % 60;
|
||||
buff = buffstream.str();
|
||||
ss << buff.substr(buff.length() - 2, buff.length());
|
||||
ss << "\n";
|
||||
|
||||
return ss.str();
|
||||
return out;
|
||||
} // toString
|
||||
|
||||
/**
|
||||
|
@ -5,5 +5,5 @@
|
||||
* Author: kolban
|
||||
*/
|
||||
|
||||
#include "BLEExceptions.h"
|
||||
//#include "BLEExceptions.h"
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include <esp_err.h>
|
||||
|
||||
#include <sstream>
|
||||
#include "BLEExceptions.h"
|
||||
//#include "BLEExceptions.h"
|
||||
#include "BLEUtils.h"
|
||||
#include "GeneralUtils.h"
|
||||
#include "BLERemoteDescriptor.h"
|
||||
@ -39,6 +39,7 @@ BLERemoteCharacteristic::BLERemoteCharacteristic(
|
||||
m_charProp = charProp;
|
||||
m_pRemoteService = pRemoteService;
|
||||
m_notifyCallback = nullptr;
|
||||
m_rawData = nullptr;
|
||||
|
||||
retrieveDescriptors(); // Get the descriptors for this characteristic
|
||||
log_v("<< BLERemoteCharacteristic");
|
||||
@ -399,7 +400,7 @@ std::string BLERemoteCharacteristic::readValue() {
|
||||
// Check to see that we are connected.
|
||||
if (!getRemoteService()->getClient()->isConnected()) {
|
||||
log_e("Disconnected");
|
||||
throw BLEDisconnectedException();
|
||||
return std::string();
|
||||
}
|
||||
|
||||
m_semaphoreReadCharEvt.take("readValue");
|
||||
@ -500,11 +501,16 @@ void BLERemoteCharacteristic::removeDescriptors() {
|
||||
* @return a String representation.
|
||||
*/
|
||||
std::string BLERemoteCharacteristic::toString() {
|
||||
std::ostringstream ss;
|
||||
ss << "Characteristic: uuid: " << m_uuid.toString() <<
|
||||
", handle: " << getHandle() << " 0x" << std::hex << getHandle() <<
|
||||
", props: " << BLEUtils::characteristicPropertiesToString(m_charProp);
|
||||
return ss.str();
|
||||
std::string res = "Characteristic: uuid: " + m_uuid.toString();
|
||||
char val[6];
|
||||
res += ", handle: ";
|
||||
snprintf(val, sizeof(val), "%d", getHandle());
|
||||
res += val;
|
||||
res += " 0x";
|
||||
snprintf(val, sizeof(val), "%04x", getHandle());
|
||||
res += val;
|
||||
res += ", props: " + BLEUtils::characteristicPropertiesToString(m_charProp);
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
|
||||
@ -545,7 +551,7 @@ void BLERemoteCharacteristic::writeValue(uint8_t* data, size_t length, bool resp
|
||||
// Check to see that we are connected.
|
||||
if (!getRemoteService()->getClient()->isConnected()) {
|
||||
log_e("Disconnected");
|
||||
throw BLEDisconnectedException();
|
||||
return;
|
||||
}
|
||||
|
||||
m_semaphoreWriteCharEvt.take("writeValue");
|
||||
|
@ -55,7 +55,7 @@ std::string BLERemoteDescriptor::readValue() {
|
||||
// Check to see that we are connected.
|
||||
if (!getRemoteCharacteristic()->getRemoteService()->getClient()->isConnected()) {
|
||||
log_e("Disconnected");
|
||||
throw BLEDisconnectedException();
|
||||
return std::string();
|
||||
}
|
||||
|
||||
m_semaphoreReadDescrEvt.take("readValue");
|
||||
@ -113,9 +113,12 @@ uint32_t BLERemoteDescriptor::readUInt32() {
|
||||
* @retun A string representation of this BLE Remote Descriptor.
|
||||
*/
|
||||
std::string BLERemoteDescriptor::toString() {
|
||||
std::stringstream ss;
|
||||
ss << "handle: " << getHandle() << ", uuid: " << getUUID().toString();
|
||||
return ss.str();
|
||||
char val[6];
|
||||
snprintf(val, sizeof(val), "%d", getHandle());
|
||||
std::string res = "handle: ";
|
||||
res += val;
|
||||
res += ", uuid: " + getUUID().toString();
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
|
||||
@ -130,7 +133,7 @@ void BLERemoteDescriptor::writeValue(uint8_t* data, size_t length, bool response
|
||||
// Check to see that we are connected.
|
||||
if (!getRemoteCharacteristic()->getRemoteService()->getClient()->isConnected()) {
|
||||
log_e("Disconnected");
|
||||
throw BLEDisconnectedException();
|
||||
return;
|
||||
}
|
||||
|
||||
esp_err_t errRc = ::esp_ble_gattc_write_char_descr(
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include <esp_err.h>
|
||||
#include "esp32-hal-log.h"
|
||||
|
||||
#pragma GCC diagnostic warning "-Wunused-but-set-parameter"
|
||||
|
||||
BLERemoteService::BLERemoteService(
|
||||
esp_gatt_id_t srvcId,
|
||||
BLEClient* pClient,
|
||||
@ -164,7 +166,7 @@ void BLERemoteService::retrieveCharacteristics() {
|
||||
uint16_t offset = 0;
|
||||
esp_gattc_char_elem_t result;
|
||||
while (true) {
|
||||
uint16_t count = 10; // this value is used as in parameter that allows to search max 10 chars with the same uuid
|
||||
uint16_t count = 1; // only room for 1 result allocated, so go one by one
|
||||
esp_gatt_status_t status = ::esp_ble_gattc_get_all_char(
|
||||
getClient()->getGattcIf(),
|
||||
getClient()->getConnId(),
|
||||
@ -224,11 +226,24 @@ std::map<std::string, BLERemoteCharacteristic*>* BLERemoteService::getCharacteri
|
||||
return &m_characteristicMap;
|
||||
} // getCharacteristics
|
||||
|
||||
/**
|
||||
* @brief Retrieve a map of all the characteristics of this service.
|
||||
* @return A map of all the characteristics of this service.
|
||||
*/
|
||||
std::map<uint16_t, BLERemoteCharacteristic*>* BLERemoteService::getCharacteristicsByHandle() {
|
||||
// If is possible that we have not read the characteristics associated with the service so do that
|
||||
// now. The request to retrieve the characteristics by calling "retrieveCharacteristics" is a blocking
|
||||
// call and does not return until all the characteristics are available.
|
||||
if (!m_haveCharacteristics) {
|
||||
retrieveCharacteristics();
|
||||
}
|
||||
return &m_characteristicMapByHandle;
|
||||
} // getCharacteristicsByHandle
|
||||
|
||||
/**
|
||||
* @brief This function is designed to get characteristics map when we have multiple characteristics with the same UUID
|
||||
*/
|
||||
void BLERemoteService::getCharacteristics(std::map<uint16_t, BLERemoteCharacteristic*>* pCharacteristicMap) {
|
||||
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
|
||||
pCharacteristicMap = &m_characteristicMapByHandle;
|
||||
} // Get the characteristics map.
|
||||
|
||||
@ -317,15 +332,25 @@ void BLERemoteService::setValue(BLEUUID characteristicUuid, std::string value) {
|
||||
* @return A string representation of this remote service.
|
||||
*/
|
||||
std::string BLERemoteService::toString() {
|
||||
std::ostringstream ss;
|
||||
ss << "Service: uuid: " + m_uuid.toString();
|
||||
ss << ", start_handle: " << std::dec << m_startHandle << " 0x" << std::hex << m_startHandle <<
|
||||
", end_handle: " << std::dec << m_endHandle << " 0x" << std::hex << m_endHandle;
|
||||
std::string res = "Service: uuid: " + m_uuid.toString();
|
||||
char val[6];
|
||||
res += ", start_handle: ";
|
||||
snprintf(val, sizeof(val), "%d", m_startHandle);
|
||||
res += val;
|
||||
snprintf(val, sizeof(val), "%04x", m_startHandle);
|
||||
res += " 0x";
|
||||
res += val;
|
||||
res += ", end_handle: ";
|
||||
snprintf(val, sizeof(val), "%d", m_endHandle);
|
||||
res += val;
|
||||
snprintf(val, sizeof(val), "%04x", m_endHandle);
|
||||
res += " 0x";
|
||||
res += val;
|
||||
for (auto &myPair : m_characteristicMap) {
|
||||
ss << "\n" << myPair.second->toString();
|
||||
res += "\n" + myPair.second->toString();
|
||||
// myPair.second is the value
|
||||
}
|
||||
return ss.str();
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
|
||||
|
@ -412,4 +412,9 @@ void BLEServer::updateConnParams(esp_bd_addr_t remote_bda, uint16_t minInterval,
|
||||
conn_params.timeout = timeout; // timeout = 400*10ms = 4000ms
|
||||
esp_ble_gap_update_conn_params(&conn_params);
|
||||
}
|
||||
|
||||
void BLEServer::disconnect(uint16_t connId) {
|
||||
esp_ble_gatts_close(m_gatts_if, connId);
|
||||
}
|
||||
|
||||
#endif // CONFIG_BT_ENABLED
|
||||
|
@ -72,6 +72,7 @@ public:
|
||||
BLEService* getServiceByUUID(const char* uuid);
|
||||
BLEService* getServiceByUUID(BLEUUID uuid);
|
||||
bool connect(BLEAddress address);
|
||||
void disconnect(uint16_t connId);
|
||||
uint16_t m_appId;
|
||||
void updateConnParams(esp_bd_addr_t remote_bda, uint16_t minInterval, uint16_t maxInterval, uint16_t latency, uint16_t timeout);
|
||||
|
||||
|
@ -381,10 +381,12 @@ BLECharacteristic* BLEService::getCharacteristic(BLEUUID uuid) {
|
||||
* @return A string representation of this service.
|
||||
*/
|
||||
std::string BLEService::toString() {
|
||||
std::stringstream stringStream;
|
||||
stringStream << "UUID: " << getUUID().toString() <<
|
||||
", handle: 0x" << std::hex << std::setfill('0') << std::setw(2) << getHandle();
|
||||
return stringStream.str();
|
||||
std::string res = "UUID: " + getUUID().toString();
|
||||
char hex[5];
|
||||
snprintf(hex, sizeof(hex), "%04x", getHandle());
|
||||
res += ", handle: 0x";
|
||||
res += hex;
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
#include <iomanip>
|
||||
#include "BLEService.h"
|
||||
|
||||
@ -73,12 +73,15 @@ void BLEServiceMap::setByHandle(uint16_t handle, BLEService* service) {
|
||||
* @return A string representation of the service map.
|
||||
*/
|
||||
std::string BLEServiceMap::toString() {
|
||||
std::stringstream stringStream;
|
||||
stringStream << std::hex << std::setfill('0');
|
||||
std::string res;
|
||||
char hex[5];
|
||||
for (auto &myPair: m_handleMap) {
|
||||
stringStream << "handle: 0x" << std::setw(2) << myPair.first << ", uuid: " + myPair.second->getUUID().toString() << "\n";
|
||||
res += "handle: 0x";
|
||||
snprintf(hex, sizeof(hex), "%04x", myPair.first);
|
||||
res += hex;
|
||||
res += ", uuid: " + myPair.second->getUUID().toString() + "\n";
|
||||
}
|
||||
return stringStream.str();
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
void BLEServiceMap::handleGATTServerEvent(
|
||||
|
@ -349,51 +349,38 @@ BLEUUID BLEUUID::to128() {
|
||||
*/
|
||||
std::string BLEUUID::toString() {
|
||||
if (!m_valueSet) return "<NULL>"; // If we have no value, nothing to format.
|
||||
|
||||
// If the UUIDs are 16 or 32 bit, pad correctly.
|
||||
std::stringstream ss;
|
||||
|
||||
if (m_uuid.len == ESP_UUID_LEN_16) { // If the UUID is 16bit, pad correctly.
|
||||
ss << "0000" <<
|
||||
std::hex <<
|
||||
std::setfill('0') <<
|
||||
std::setw(4) <<
|
||||
m_uuid.uuid.uuid16 <<
|
||||
"-0000-1000-8000-00805f9b34fb";
|
||||
return ss.str(); // Return the string
|
||||
char hex[9];
|
||||
snprintf(hex, sizeof(hex), "%08x", m_uuid.uuid.uuid16);
|
||||
return std::string(hex) + "-0000-1000-8000-00805f9b34fb";
|
||||
} // End 16bit UUID
|
||||
|
||||
if (m_uuid.len == ESP_UUID_LEN_32) { // If the UUID is 32bit, pad correctly.
|
||||
ss << std::hex <<
|
||||
std::setfill('0') <<
|
||||
std::setw(8) <<
|
||||
m_uuid.uuid.uuid32 <<
|
||||
"-0000-1000-8000-00805f9b34fb";
|
||||
return ss.str(); // return the string
|
||||
char hex[9];
|
||||
snprintf(hex, sizeof(hex), "%08x", m_uuid.uuid.uuid32);
|
||||
return std::string(hex) + "-0000-1000-8000-00805f9b34fb";
|
||||
} // End 32bit UUID
|
||||
|
||||
// The UUID is not 16bit or 32bit which means that it is 128bit.
|
||||
//
|
||||
// UUID string format:
|
||||
// AABBCCDD-EEFF-GGHH-IIJJ-KKLLMMNNOOPP
|
||||
ss << std::hex << std::setfill('0') <<
|
||||
std::setw(2) << (int) m_uuid.uuid.uuid128[15] <<
|
||||
std::setw(2) << (int) m_uuid.uuid.uuid128[14] <<
|
||||
std::setw(2) << (int) m_uuid.uuid.uuid128[13] <<
|
||||
std::setw(2) << (int) m_uuid.uuid.uuid128[12] << "-" <<
|
||||
std::setw(2) << (int) m_uuid.uuid.uuid128[11] <<
|
||||
std::setw(2) << (int) m_uuid.uuid.uuid128[10] << "-" <<
|
||||
std::setw(2) << (int) m_uuid.uuid.uuid128[9] <<
|
||||
std::setw(2) << (int) m_uuid.uuid.uuid128[8] << "-" <<
|
||||
std::setw(2) << (int) m_uuid.uuid.uuid128[7] <<
|
||||
std::setw(2) << (int) m_uuid.uuid.uuid128[6] << "-" <<
|
||||
std::setw(2) << (int) m_uuid.uuid.uuid128[5] <<
|
||||
std::setw(2) << (int) m_uuid.uuid.uuid128[4] <<
|
||||
std::setw(2) << (int) m_uuid.uuid.uuid128[3] <<
|
||||
std::setw(2) << (int) m_uuid.uuid.uuid128[2] <<
|
||||
std::setw(2) << (int) m_uuid.uuid.uuid128[1] <<
|
||||
std::setw(2) << (int) m_uuid.uuid.uuid128[0];
|
||||
return ss.str();
|
||||
auto size = 37; // 32 for UUID data, 4 for '-' delimiters and one for a terminator == 37 chars
|
||||
char *hex = (char *)malloc(size);
|
||||
snprintf(hex, size, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
||||
m_uuid.uuid.uuid128[15], m_uuid.uuid.uuid128[14],
|
||||
m_uuid.uuid.uuid128[13], m_uuid.uuid.uuid128[12],
|
||||
m_uuid.uuid.uuid128[11], m_uuid.uuid.uuid128[10],
|
||||
m_uuid.uuid.uuid128[9], m_uuid.uuid.uuid128[8],
|
||||
m_uuid.uuid.uuid128[7], m_uuid.uuid.uuid128[6],
|
||||
m_uuid.uuid.uuid128[5], m_uuid.uuid.uuid128[4],
|
||||
m_uuid.uuid.uuid128[3], m_uuid.uuid.uuid128[2],
|
||||
m_uuid.uuid.uuid128[1], m_uuid.uuid.uuid128[0]);
|
||||
std::string res(hex);
|
||||
free(hex);
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
|
@ -604,26 +604,32 @@ static const gattService_t g_gattServices[] = {
|
||||
* @return A string representation of characteristic properties.
|
||||
*/
|
||||
std::string BLEUtils::characteristicPropertiesToString(esp_gatt_char_prop_t prop) {
|
||||
std::stringstream stream;
|
||||
stream <<
|
||||
"broadcast: " << ((prop & ESP_GATT_CHAR_PROP_BIT_BROADCAST)?"1":"0") <<
|
||||
", read: " << ((prop & ESP_GATT_CHAR_PROP_BIT_READ)?"1":"0") <<
|
||||
", write_nr: " << ((prop & ESP_GATT_CHAR_PROP_BIT_WRITE_NR)?"1":"0") <<
|
||||
", write: " << ((prop & ESP_GATT_CHAR_PROP_BIT_WRITE)?"1":"0") <<
|
||||
", notify: " << ((prop & ESP_GATT_CHAR_PROP_BIT_NOTIFY)?"1":"0") <<
|
||||
", indicate: " << ((prop & ESP_GATT_CHAR_PROP_BIT_INDICATE)?"1":"0") <<
|
||||
", auth: " << ((prop & ESP_GATT_CHAR_PROP_BIT_AUTH)?"1":"0");
|
||||
return stream.str();
|
||||
std::string res = "broadcast: ";
|
||||
res += ((prop & ESP_GATT_CHAR_PROP_BIT_BROADCAST)?"1":"0");
|
||||
res += ", read: ";
|
||||
res += ((prop & ESP_GATT_CHAR_PROP_BIT_READ)?"1":"0");
|
||||
res += ", write_nr: ";
|
||||
res += ((prop & ESP_GATT_CHAR_PROP_BIT_WRITE_NR)?"1":"0");
|
||||
res += ", write: ";
|
||||
res += ((prop & ESP_GATT_CHAR_PROP_BIT_WRITE)?"1":"0");
|
||||
res += ", notify: ";
|
||||
res += ((prop & ESP_GATT_CHAR_PROP_BIT_NOTIFY)?"1":"0");
|
||||
res += ", indicate: ";
|
||||
res += ((prop & ESP_GATT_CHAR_PROP_BIT_INDICATE)?"1":"0");
|
||||
res += ", auth: ";
|
||||
res += ((prop & ESP_GATT_CHAR_PROP_BIT_AUTH)?"1":"0");
|
||||
return res;
|
||||
} // characteristicPropertiesToString
|
||||
|
||||
/**
|
||||
* @brief Convert an esp_gatt_id_t to a string.
|
||||
*/
|
||||
static std::string gattIdToString(esp_gatt_id_t gattId) {
|
||||
std::stringstream stream;
|
||||
stream << "uuid: " << BLEUUID(gattId.uuid).toString() << ", inst_id: " << (int)gattId.inst_id;
|
||||
//sprintf(buffer, "uuid: %s, inst_id: %d", uuidToString(gattId.uuid).c_str(), gattId.inst_id);
|
||||
return stream.str();
|
||||
std::string res = "uuid: " + BLEUUID(gattId.uuid).toString() + ", inst_id: ";
|
||||
char val[8];
|
||||
snprintf(val, sizeof(val), "%d", (int)gattId.inst_id);
|
||||
res += val;
|
||||
return res;
|
||||
} // gattIdToString
|
||||
|
||||
|
||||
@ -654,23 +660,23 @@ const char* BLEUtils::addressTypeToString(esp_ble_addr_type_t type) {
|
||||
* @return std::string A string representation of the advertising flags.
|
||||
*/
|
||||
std::string BLEUtils::adFlagsToString(uint8_t adFlags) {
|
||||
std::stringstream ss;
|
||||
std::string res;
|
||||
if (adFlags & (1 << 0)) {
|
||||
ss << "[LE Limited Discoverable Mode] ";
|
||||
res += "[LE Limited Discoverable Mode] ";
|
||||
}
|
||||
if (adFlags & (1 << 1)) {
|
||||
ss << "[LE General Discoverable Mode] ";
|
||||
res += "[LE General Discoverable Mode] ";
|
||||
}
|
||||
if (adFlags & (1 << 2)) {
|
||||
ss << "[BR/EDR Not Supported] ";
|
||||
res += "[BR/EDR Not Supported] ";
|
||||
}
|
||||
if (adFlags & (1 << 3)) {
|
||||
ss << "[Simultaneous LE and BR/EDR to Same Device Capable (Controller)] ";
|
||||
res += "[Simultaneous LE and BR/EDR to Same Device Capable (Controller)] ";
|
||||
}
|
||||
if (adFlags & (1 << 4)) {
|
||||
ss << "[Simultaneous LE and BR/EDR to Same Device Capable (Host)] ";
|
||||
res += "[Simultaneous LE and BR/EDR to Same Device Capable (Host)] ";
|
||||
}
|
||||
return ss.str();
|
||||
return res;
|
||||
} // adFlagsToString
|
||||
|
||||
|
||||
@ -802,13 +808,13 @@ char* BLEUtils::buildHexData(uint8_t* target, uint8_t* source, uint8_t length) {
|
||||
* @return A string representation of a piece of memory.
|
||||
*/
|
||||
std::string BLEUtils::buildPrintData(uint8_t* source, size_t length) {
|
||||
std::ostringstream ss;
|
||||
std::string res;
|
||||
for (int i = 0; i < length; i++) {
|
||||
char c = *source;
|
||||
ss << (isprint(c) ? c : '.');
|
||||
res += (isprint(c) ? c : '.');
|
||||
source++;
|
||||
}
|
||||
return ss.str();
|
||||
return res;
|
||||
} // buildPrintData
|
||||
|
||||
|
||||
@ -1848,14 +1854,22 @@ std::string BLEUtils::gattDescriptorUUIDToString(uint32_t descriptorUUID) {
|
||||
* @return A string representation of an esp_gattc_service_elem_t.
|
||||
*/
|
||||
std::string BLEUtils::gattcServiceElementToString(esp_gattc_service_elem_t* pGATTCServiceElement) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "[uuid: " << BLEUUID(pGATTCServiceElement->uuid).toString() <<
|
||||
", start_handle: " << pGATTCServiceElement->start_handle <<
|
||||
" 0x" << std::hex << pGATTCServiceElement->start_handle <<
|
||||
", end_handle: " << std::dec << pGATTCServiceElement->end_handle <<
|
||||
" 0x" << std::hex << pGATTCServiceElement->end_handle << "]";
|
||||
return ss.str();
|
||||
std::string res;
|
||||
char val[6];
|
||||
res += "[uuid: " + BLEUUID(pGATTCServiceElement->uuid).toString() + ", start_handle: ";
|
||||
snprintf(val, sizeof(val), "%d", pGATTCServiceElement->start_handle);
|
||||
res += val;
|
||||
res += " 0x";
|
||||
snprintf(val, sizeof(val), "%04x", pGATTCServiceElement->start_handle);
|
||||
res += val;
|
||||
res += ", end_handle: ";
|
||||
snprintf(val, sizeof(val), "%d", pGATTCServiceElement->end_handle);
|
||||
res += val;
|
||||
res += " 0x";
|
||||
snprintf(val, sizeof(val), "%04x", pGATTCServiceElement->end_handle);
|
||||
res += val;
|
||||
res += "]";
|
||||
return res;
|
||||
} // gattcServiceElementToString
|
||||
|
||||
|
||||
|
@ -78,6 +78,38 @@ uint32_t FreeRTOS::Semaphore::wait(std::string owner) {
|
||||
return m_value;
|
||||
} // wait
|
||||
|
||||
/**
|
||||
* @brief Wait for a semaphore to be released in a given period of time by trying to take it and
|
||||
* then releasing it again. The value associated with the semaphore can be taken by value() call after return
|
||||
* @param [in] owner A debug tag.
|
||||
* @param [in] timeoutMs timeout to wait in ms.
|
||||
* @return True if we took the semaphore within timeframe.
|
||||
*/
|
||||
bool FreeRTOS::Semaphore::timedWait(std::string owner, uint32_t timeoutMs) {
|
||||
log_v(">> wait: Semaphore waiting: %s for %s", toString().c_str(), owner.c_str());
|
||||
|
||||
if (m_usePthreads && timeoutMs != portMAX_DELAY) {
|
||||
assert(false); // We apparently don't have a timed wait for pthreads.
|
||||
}
|
||||
|
||||
auto ret = pdTRUE;
|
||||
|
||||
if (m_usePthreads) {
|
||||
pthread_mutex_lock(&m_pthread_mutex);
|
||||
} else {
|
||||
ret = xSemaphoreTake(m_semaphore, timeoutMs);
|
||||
}
|
||||
|
||||
if (m_usePthreads) {
|
||||
pthread_mutex_unlock(&m_pthread_mutex);
|
||||
} else {
|
||||
xSemaphoreGive(m_semaphore);
|
||||
}
|
||||
|
||||
log_v("<< wait: Semaphore %s released: %d", toString().c_str(), ret);
|
||||
return ret;
|
||||
} // wait
|
||||
|
||||
|
||||
FreeRTOS::Semaphore::Semaphore(std::string name) {
|
||||
m_usePthreads = false; // Are we using pThreads or FreeRTOS?
|
||||
@ -202,9 +234,12 @@ bool FreeRTOS::Semaphore::take(uint32_t timeoutMs, std::string owner) {
|
||||
* @return A string representation of the semaphore.
|
||||
*/
|
||||
std::string FreeRTOS::Semaphore::toString() {
|
||||
std::stringstream stringStream;
|
||||
stringStream << "name: "<< m_name << " (0x" << std::hex << std::setfill('0') << (uint32_t)m_semaphore << "), owner: " << m_owner;
|
||||
return stringStream.str();
|
||||
char hex[9];
|
||||
std::string res = "name: " + m_name + " (0x";
|
||||
snprintf(hex, sizeof(hex), "%08x", (uint32_t)m_semaphore);
|
||||
res += hex;
|
||||
res += "), owner: " + m_owner;
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
|
||||
|
@ -40,6 +40,8 @@ public:
|
||||
bool take(uint32_t timeoutMs, std::string owner = "<Unknown>");
|
||||
std::string toString();
|
||||
uint32_t wait(std::string owner = "<Unknown>");
|
||||
bool timedWait(std::string owner = "<Unknown>", uint32_t timeoutMs = portMAX_DELAY);
|
||||
uint32_t value(){ return m_value; };
|
||||
|
||||
private:
|
||||
SemaphoreHandle_t m_semaphore;
|
||||
|
@ -104,11 +104,10 @@ bool GeneralUtils::base64Encode(const std::string& in, std::string* out) {
|
||||
* * Amount of free RAM
|
||||
*/
|
||||
void GeneralUtils::dumpInfo() {
|
||||
size_t freeHeap = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
esp_chip_info_t chipInfo;
|
||||
esp_chip_info(&chipInfo);
|
||||
log_v("--- dumpInfo ---");
|
||||
log_v("Free heap: %d", freeHeap);
|
||||
log_v("Free heap: %d", heap_caps_get_free_size(MALLOC_CAP_8BIT));
|
||||
log_v("Chip Info: Model: %d, cores: %d, revision: %d", chipInfo.model, chipInfo.cores, chipInfo.revision);
|
||||
log_v("ESP-IDF version: %s", esp_get_idf_version());
|
||||
log_v("---");
|
||||
@ -332,9 +331,12 @@ void GeneralUtils::hexDump(const uint8_t* pData, uint32_t length) {
|
||||
* @return A string representation of the IP address.
|
||||
*/
|
||||
std::string GeneralUtils::ipToString(uint8_t *ip) {
|
||||
std::stringstream s;
|
||||
s << (int) ip[0] << '.' << (int) ip[1] << '.' << (int) ip[2] << '.' << (int) ip[3];
|
||||
return s.str();
|
||||
auto size = 16;
|
||||
char *val = (char*)malloc(size);
|
||||
snprintf(val, size, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
|
||||
std::string res(val);
|
||||
free(val);
|
||||
return res;
|
||||
} // ipToString
|
||||
|
||||
|
||||
@ -347,11 +349,14 @@ std::string GeneralUtils::ipToString(uint8_t *ip) {
|
||||
std::vector<std::string> GeneralUtils::split(std::string source, char delimiter) {
|
||||
// See also: https://stackoverflow.com/questions/5167625/splitting-a-c-stdstring-using-tokens-e-g
|
||||
std::vector<std::string> strings;
|
||||
std::istringstream iss(source);
|
||||
std::string s;
|
||||
while (std::getline(iss, s, delimiter)) {
|
||||
strings.push_back(trim(s));
|
||||
std::size_t current, previous = 0;
|
||||
current = source.find(delimiter);
|
||||
while (current != std::string::npos) {
|
||||
strings.push_back(trim(source.substr(previous, current - previous)));
|
||||
previous = current + 1;
|
||||
current = source.find(delimiter, previous);
|
||||
}
|
||||
strings.push_back(trim(source.substr(previous, current - previous)));
|
||||
return strings;
|
||||
} // split
|
||||
|
||||
|
@ -0,0 +1,56 @@
|
||||
//This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
//By Victor Tchistiak - 2019
|
||||
//
|
||||
//This example demostrates master mode bluetooth connection and pin
|
||||
//it creates a bridge between Serial and Classical Bluetooth (SPP)
|
||||
//this is an extention of the SerialToSerialBT example by Evandro Copercini - 2018
|
||||
//
|
||||
|
||||
#include "BluetoothSerial.h"
|
||||
|
||||
BluetoothSerial SerialBT;
|
||||
|
||||
String MACadd = "AA:BB:CC:11:22:33";
|
||||
uint8_t address[6] = {0xAA, 0xBB, 0xCC, 0x11, 0x22, 0x33};
|
||||
//uint8_t address[6] = {0x00, 0x1D, 0xA5, 0x02, 0xC3, 0x22};
|
||||
String name = "OBDII";
|
||||
char *pin = "1234"; //<- standard pin would be provided by default
|
||||
bool connected;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
//SerialBT.setPin(pin);
|
||||
SerialBT.begin("ESP32test", true);
|
||||
//SerialBT.setPin(pin);
|
||||
Serial.println("The device started in master mode, make sure remote BT device is on!");
|
||||
|
||||
// connect(address) is fast (upto 10 secs max), connect(name) is slow (upto 30 secs max) as it needs
|
||||
// to resolve name to address first, but it allows to connect to different devices with the same name.
|
||||
// Set CoreDebugLevel to Info to view devices bluetooth address and device names
|
||||
connected = SerialBT.connect(name);
|
||||
//connected = SerialBT.connect(address);
|
||||
|
||||
if(connected) {
|
||||
Serial.println("Connected Succesfully!");
|
||||
} else {
|
||||
while(!SerialBT.connected(10000)) {
|
||||
Serial.println("Failed to connect. Make sure remote device is available and in range, then restart app.");
|
||||
}
|
||||
}
|
||||
// disconnect() may take upto 10 secs max
|
||||
if (SerialBT.disconnect()) {
|
||||
Serial.println("Disconnected Succesfully!");
|
||||
}
|
||||
// this would reconnect to the name(will use address, if resolved) or address used with connect(name/address).
|
||||
SerialBT.connect();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (Serial.available()) {
|
||||
SerialBT.write(Serial.read());
|
||||
}
|
||||
if (SerialBT.available()) {
|
||||
Serial.write(SerialBT.read());
|
||||
}
|
||||
delay(20);
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
//This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
//By Victor Tchistiak - 2019
|
||||
//
|
||||
//This example demonstrates reading and removing paired devices stored on the ESP32 flash memory
|
||||
//Sometimes you may find your ESP32 device could not connect to the remote device despite
|
||||
//many successful connections earlier. This is most likely a result of client replacing your paired
|
||||
//device info with new one from other device. The BT clients store connection info for paired devices,
|
||||
//but it is limited to a few devices only. When new device pairs and number of stored devices is exceeded,
|
||||
//one of the previously paired devices would be replaced with new one.
|
||||
//The only remedy is to delete this saved bound device from your device flash memory
|
||||
//and pair with the other device again.
|
||||
//
|
||||
#include "esp_bt_main.h"
|
||||
#include "esp_bt_device.h"
|
||||
#include"esp_gap_bt_api.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#define REMOVE_BONDED_DEVICES 0 // <- Set to 0 to view all bonded devices addresses, set to 1 to remove
|
||||
|
||||
#define PAIR_MAX_DEVICES 20
|
||||
uint8_t pairedDeviceBtAddr[PAIR_MAX_DEVICES][6];
|
||||
char bda_str[18];
|
||||
|
||||
bool initBluetooth()
|
||||
{
|
||||
if(!btStart()) {
|
||||
Serial.println("Failed to initialize controller");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(esp_bluedroid_init() != ESP_OK) {
|
||||
Serial.println("Failed to initialize bluedroid");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(esp_bluedroid_enable() != ESP_OK) {
|
||||
Serial.println("Failed to enable bluedroid");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
char *bda2str(const uint8_t* bda, char *str, size_t size)
|
||||
{
|
||||
if (bda == NULL || str == NULL || size < 18) {
|
||||
return NULL;
|
||||
}
|
||||
sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
|
||||
return str;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
initBluetooth();
|
||||
Serial.print("ESP32 bluetooth address: "); Serial.println(bda2str(esp_bt_dev_get_address(), bda_str, 18));
|
||||
// Get the numbers of bonded/paired devices in the BT module
|
||||
int count = esp_bt_gap_get_bond_device_num();
|
||||
if(!count) {
|
||||
Serial.println("No bonded device found.");
|
||||
} else {
|
||||
Serial.print("Bonded device count: "); Serial.println(count);
|
||||
if(PAIR_MAX_DEVICES < count) {
|
||||
count = PAIR_MAX_DEVICES;
|
||||
Serial.print("Reset bonded device count: "); Serial.println(count);
|
||||
}
|
||||
esp_err_t tError = esp_bt_gap_get_bond_device_list(&count, pairedDeviceBtAddr);
|
||||
if(ESP_OK == tError) {
|
||||
for(int i = 0; i < count; i++) {
|
||||
Serial.print("Found bonded device # "); Serial.print(i); Serial.print(" -> ");
|
||||
Serial.println(bda2str(pairedDeviceBtAddr[i], bda_str, 18));
|
||||
if(REMOVE_BONDED_DEVICES) {
|
||||
esp_err_t tError = esp_bt_gap_remove_bond_device(pairedDeviceBtAddr[i]);
|
||||
if(ESP_OK == tError) {
|
||||
Serial.print("Removed bonded device # ");
|
||||
} else {
|
||||
Serial.print("Failed to remove bonded device # ");
|
||||
}
|
||||
Serial.println(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {}
|
360
libraries/BluetoothSerial/src/BluetoothSerial.cpp
Normal file → Executable file
360
libraries/BluetoothSerial/src/BluetoothSerial.cpp
Normal file → Executable file
@ -53,15 +53,80 @@ static EventGroupHandle_t _spp_event_group = NULL;
|
||||
static boolean secondConnectionAttempt;
|
||||
static esp_spp_cb_t * custom_spp_callback = NULL;
|
||||
|
||||
#define INQ_LEN 0x10
|
||||
#define INQ_NUM_RSPS 20
|
||||
#define READY_TIMEOUT (10 * 1000)
|
||||
#define SCAN_TIMEOUT (INQ_LEN * 2 * 1000)
|
||||
static esp_bd_addr_t _peer_bd_addr;
|
||||
static char _remote_name[ESP_BT_GAP_MAX_BDNAME_LEN + 1];
|
||||
static bool _isRemoteAddressSet;
|
||||
static bool _isMaster;
|
||||
static esp_bt_pin_code_t _pin_code;
|
||||
static int _pin_len;
|
||||
static bool _isPinSet;
|
||||
static bool _enableSSP;
|
||||
|
||||
#define SPP_RUNNING 0x01
|
||||
#define SPP_CONNECTED 0x02
|
||||
#define SPP_CONGESTED 0x04
|
||||
#define SPP_DISCONNECTED 0x08
|
||||
|
||||
typedef struct {
|
||||
size_t len;
|
||||
uint8_t data[];
|
||||
} spp_packet_t;
|
||||
|
||||
static char *bda2str(esp_bd_addr_t bda, char *str, size_t size)
|
||||
{
|
||||
if (bda == NULL || str == NULL || size < 18) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t *p = bda;
|
||||
sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
p[0], p[1], p[2], p[3], p[4], p[5]);
|
||||
return str;
|
||||
}
|
||||
|
||||
static bool get_name_from_eir(uint8_t *eir, char *bdname, uint8_t *bdname_len)
|
||||
{
|
||||
if (!eir || !bdname || !bdname_len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t *rmt_bdname, rmt_bdname_len;
|
||||
*bdname = *bdname_len = rmt_bdname_len = 0;
|
||||
|
||||
rmt_bdname = esp_bt_gap_resolve_eir_data(eir, ESP_BT_EIR_TYPE_CMPL_LOCAL_NAME, &rmt_bdname_len);
|
||||
if (!rmt_bdname) {
|
||||
rmt_bdname = esp_bt_gap_resolve_eir_data(eir, ESP_BT_EIR_TYPE_SHORT_LOCAL_NAME, &rmt_bdname_len);
|
||||
}
|
||||
if (rmt_bdname) {
|
||||
rmt_bdname_len = rmt_bdname_len > ESP_BT_GAP_MAX_BDNAME_LEN ? ESP_BT_GAP_MAX_BDNAME_LEN : rmt_bdname_len;
|
||||
memcpy(bdname, rmt_bdname, rmt_bdname_len);
|
||||
bdname[rmt_bdname_len] = 0;
|
||||
*bdname_len = rmt_bdname_len;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool btSetPin() {
|
||||
esp_bt_pin_type_t pin_type;
|
||||
if (_isPinSet) {
|
||||
if (_pin_len) {
|
||||
log_i("pin set");
|
||||
pin_type = ESP_BT_PIN_TYPE_FIXED;
|
||||
} else {
|
||||
_isPinSet = false;
|
||||
log_i("pin reset");
|
||||
pin_type = ESP_BT_PIN_TYPE_VARIABLE; // pin_code would be ignored (default)
|
||||
}
|
||||
return (esp_bt_gap_set_pin(pin_type, _pin_len, _pin_code) == ESP_OK);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static esp_err_t _spp_queue_packet(uint8_t *data, size_t len){
|
||||
if(!data || !len){
|
||||
log_w("No data provided");
|
||||
@ -136,12 +201,12 @@ static void _spp_tx_task(void * arg){
|
||||
if(len){
|
||||
memcpy(_spp_tx_buffer, data, len);
|
||||
_spp_tx_buffer_len += len;
|
||||
free(packet);
|
||||
packet = NULL;
|
||||
if(uxQueueMessagesWaiting(_spp_tx_queue) == 0){
|
||||
_spp_send_buffer();
|
||||
}
|
||||
}
|
||||
free(packet);
|
||||
packet = NULL;
|
||||
}
|
||||
} else {
|
||||
log_e("Something went horribly wrong");
|
||||
@ -159,29 +224,34 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
|
||||
case ESP_SPP_INIT_EVT:
|
||||
log_i("ESP_SPP_INIT_EVT");
|
||||
esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
|
||||
esp_spp_start_srv(ESP_SPP_SEC_NONE, ESP_SPP_ROLE_SLAVE, 0, _spp_server_name);
|
||||
if (!_isMaster) {
|
||||
log_i("ESP_SPP_INIT_EVT: slave: start");
|
||||
esp_spp_start_srv(ESP_SPP_SEC_NONE, ESP_SPP_ROLE_SLAVE, 0, _spp_server_name);
|
||||
}
|
||||
xEventGroupSetBits(_spp_event_group, SPP_RUNNING);
|
||||
break;
|
||||
|
||||
case ESP_SPP_SRV_OPEN_EVT://Server connection open
|
||||
log_i("ESP_SPP_SRV_OPEN_EVT");
|
||||
if (!_spp_client){
|
||||
_spp_client = param->open.handle;
|
||||
} else {
|
||||
secondConnectionAttempt = true;
|
||||
esp_spp_disconnect(param->open.handle);
|
||||
}
|
||||
xEventGroupClearBits(_spp_event_group, SPP_DISCONNECTED);
|
||||
xEventGroupSetBits(_spp_event_group, SPP_CONNECTED);
|
||||
log_i("ESP_SPP_SRV_OPEN_EVT");
|
||||
break;
|
||||
|
||||
case ESP_SPP_CLOSE_EVT://Client connection closed
|
||||
log_i("ESP_SPP_CLOSE_EVT");
|
||||
if(secondConnectionAttempt) {
|
||||
secondConnectionAttempt = false;
|
||||
} else {
|
||||
_spp_client = 0;
|
||||
}
|
||||
xEventGroupSetBits(_spp_event_group, SPP_DISCONNECTED);
|
||||
}
|
||||
xEventGroupClearBits(_spp_event_group, SPP_CONNECTED);
|
||||
log_i("ESP_SPP_CLOSE_EVT");
|
||||
break;
|
||||
|
||||
case ESP_SPP_CONG_EVT://connection congestion status changed
|
||||
@ -216,25 +286,149 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
|
||||
}
|
||||
break;
|
||||
|
||||
//should maybe delete those.
|
||||
case ESP_SPP_DISCOVERY_COMP_EVT://discovery complete
|
||||
log_i("ESP_SPP_DISCOVERY_COMP_EVT");
|
||||
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);
|
||||
}
|
||||
break;
|
||||
|
||||
case ESP_SPP_OPEN_EVT://Client connection open
|
||||
log_i("ESP_SPP_OPEN_EVT");
|
||||
if (!_spp_client){
|
||||
_spp_client = param->open.handle;
|
||||
} else {
|
||||
secondConnectionAttempt = true;
|
||||
esp_spp_disconnect(param->open.handle);
|
||||
}
|
||||
xEventGroupClearBits(_spp_event_group, SPP_DISCONNECTED);
|
||||
xEventGroupSetBits(_spp_event_group, SPP_CONNECTED);
|
||||
break;
|
||||
|
||||
case ESP_SPP_START_EVT://server started
|
||||
log_i("ESP_SPP_START_EVT");
|
||||
break;
|
||||
|
||||
case ESP_SPP_CL_INIT_EVT://client initiated a connection
|
||||
log_i("ESP_SPP_CL_INIT_EVT");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(custom_spp_callback)(*custom_spp_callback)(event, param);
|
||||
}
|
||||
|
||||
static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param)
|
||||
{
|
||||
switch(event){
|
||||
case ESP_BT_GAP_DISC_RES_EVT:
|
||||
log_i("ESP_BT_GAP_DISC_RES_EVT");
|
||||
char bda_str[18];
|
||||
log_i("Scanned device: %s", bda2str(param->disc_res.bda, bda_str, 18));
|
||||
for (int i = 0; i < param->disc_res.num_prop; i++) {
|
||||
uint8_t peer_bdname_len;
|
||||
char peer_bdname[ESP_BT_GAP_MAX_BDNAME_LEN + 1];
|
||||
switch(param->disc_res.prop[i].type) {
|
||||
case ESP_BT_GAP_DEV_PROP_EIR:
|
||||
if (get_name_from_eir((uint8_t*)param->disc_res.prop[i].val, peer_bdname, &peer_bdname_len)) {
|
||||
log_i("ESP_BT_GAP_DISC_RES_EVT : EIR : %s : %d", peer_bdname, peer_bdname_len);
|
||||
if (strlen(_remote_name) == peer_bdname_len
|
||||
&& strncmp(peer_bdname, _remote_name, peer_bdname_len) == 0) {
|
||||
log_v("ESP_BT_GAP_DISC_RES_EVT : SPP_START_DISCOVERY_EIR : %s", peer_bdname, peer_bdname_len);
|
||||
_isRemoteAddressSet = true;
|
||||
memcpy(_peer_bd_addr, param->disc_res.bda, ESP_BD_ADDR_LEN);
|
||||
esp_bt_gap_cancel_discovery();
|
||||
esp_spp_start_discovery(_peer_bd_addr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ESP_BT_GAP_DEV_PROP_BDNAME:
|
||||
peer_bdname_len = param->disc_res.prop[i].len;
|
||||
memcpy(peer_bdname, param->disc_res.prop[i].val, peer_bdname_len);
|
||||
peer_bdname_len--; // len includes 0 terminator
|
||||
log_v("ESP_BT_GAP_DISC_RES_EVT : BDNAME : %s : %d", peer_bdname, peer_bdname_len);
|
||||
if (strlen(_remote_name) == peer_bdname_len
|
||||
&& strncmp(peer_bdname, _remote_name, peer_bdname_len) == 0) {
|
||||
log_i("ESP_BT_GAP_DISC_RES_EVT : SPP_START_DISCOVERY_BDNAME : %s", peer_bdname);
|
||||
_isRemoteAddressSet = true;
|
||||
memcpy(_peer_bd_addr, param->disc_res.bda, ESP_BD_ADDR_LEN);
|
||||
esp_bt_gap_cancel_discovery();
|
||||
esp_spp_start_discovery(_peer_bd_addr);
|
||||
}
|
||||
break;
|
||||
|
||||
case ESP_BT_GAP_DEV_PROP_COD:
|
||||
//log_i("ESP_BT_GAP_DEV_PROP_COD");
|
||||
break;
|
||||
|
||||
case ESP_BT_GAP_DEV_PROP_RSSI:
|
||||
//log_i("ESP_BT_GAP_DEV_PROP_RSSI");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (_isRemoteAddressSet)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ESP_BT_GAP_DISC_STATE_CHANGED_EVT:
|
||||
log_i("ESP_BT_GAP_DISC_STATE_CHANGED_EVT");
|
||||
break;
|
||||
|
||||
case ESP_BT_GAP_RMT_SRVCS_EVT:
|
||||
log_i( "ESP_BT_GAP_RMT_SRVCS_EVT");
|
||||
break;
|
||||
|
||||
case ESP_BT_GAP_RMT_SRVC_REC_EVT:
|
||||
log_i("ESP_BT_GAP_RMT_SRVC_REC_EVT");
|
||||
break;
|
||||
|
||||
case ESP_BT_GAP_AUTH_CMPL_EVT:
|
||||
if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) {
|
||||
log_v("authentication success: %s", param->auth_cmpl.device_name);
|
||||
} else {
|
||||
log_e("authentication failed, status:%d", param->auth_cmpl.stat);
|
||||
}
|
||||
break;
|
||||
|
||||
case ESP_BT_GAP_PIN_REQ_EVT:
|
||||
// default pairing pins
|
||||
log_i("ESP_BT_GAP_PIN_REQ_EVT min_16_digit:%d", param->pin_req.min_16_digit);
|
||||
if (param->pin_req.min_16_digit) {
|
||||
log_i("Input pin code: 0000 0000 0000 0000");
|
||||
esp_bt_pin_code_t pin_code;
|
||||
memset(pin_code, '0', ESP_BT_PIN_CODE_LEN);
|
||||
esp_bt_gap_pin_reply(param->pin_req.bda, true, 16, pin_code);
|
||||
} else {
|
||||
log_i("Input pin code: 1234");
|
||||
esp_bt_pin_code_t pin_code;
|
||||
memcpy(pin_code, "1234", 4);
|
||||
esp_bt_gap_pin_reply(param->pin_req.bda, true, 4, pin_code);
|
||||
}
|
||||
break;
|
||||
|
||||
case ESP_BT_GAP_CFM_REQ_EVT:
|
||||
log_i("ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val);
|
||||
esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true);
|
||||
break;
|
||||
|
||||
case ESP_BT_GAP_KEY_NOTIF_EVT:
|
||||
log_i("ESP_BT_GAP_KEY_NOTIF_EVT passkey:%d", param->key_notif.passkey);
|
||||
break;
|
||||
|
||||
case ESP_BT_GAP_KEY_REQ_EVT:
|
||||
log_i("ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool _init_bt(const char *deviceName)
|
||||
{
|
||||
if(!_spp_event_group){
|
||||
@ -245,6 +439,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);
|
||||
}
|
||||
if (_spp_rx_queue == NULL){
|
||||
_spp_rx_queue = xQueueCreate(RX_QUEUE_SIZE, sizeof(uint8_t)); //initialize the queue
|
||||
@ -297,6 +492,11 @@ static bool _init_bt(const char *deviceName)
|
||||
}
|
||||
}
|
||||
|
||||
if (_isMaster && esp_bt_gap_register_callback(esp_bt_gap_cb) != ESP_OK) {
|
||||
log_e("gap register failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (esp_spp_register_callback(esp_spp_cb) != ESP_OK){
|
||||
log_e("spp register failed");
|
||||
return false;
|
||||
@ -307,8 +507,20 @@ static bool _init_bt(const char *deviceName)
|
||||
return false;
|
||||
}
|
||||
|
||||
log_i("device name set");
|
||||
esp_bt_dev_set_device_name(deviceName);
|
||||
|
||||
if (_isPinSet) {
|
||||
btSetPin();
|
||||
}
|
||||
|
||||
if (_enableSSP) {
|
||||
log_i("Simple Secure Pairing");
|
||||
esp_bt_sp_param_t param_type = ESP_BT_SP_IOCAP_MODE;
|
||||
esp_bt_io_cap_t iocap = ESP_BT_IO_CAP_IO;
|
||||
esp_bt_gap_set_security_param(param_type, &iocap, sizeof(uint8_t));
|
||||
}
|
||||
|
||||
// the default BTA_DM_COD_LOUDSPEAKER does not work with the macOS BT stack
|
||||
esp_bt_cod_t cod;
|
||||
cod.major = 0b00001;
|
||||
@ -318,7 +530,6 @@ static bool _init_bt(const char *deviceName)
|
||||
log_e("set cod failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -361,6 +572,11 @@ static bool _stop_bt()
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool waitForConnect(int timeout) {
|
||||
TickType_t xTicksToWait = timeout / portTICK_PERIOD_MS;
|
||||
return (xEventGroupWaitBits(_spp_event_group, SPP_CONNECTED, pdFALSE, pdTRUE, xTicksToWait) != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Serial Bluetooth Arduino
|
||||
*
|
||||
@ -376,8 +592,9 @@ BluetoothSerial::~BluetoothSerial(void)
|
||||
_stop_bt();
|
||||
}
|
||||
|
||||
bool BluetoothSerial::begin(String localName)
|
||||
bool BluetoothSerial::begin(String localName, bool isMaster)
|
||||
{
|
||||
_isMaster = isMaster;
|
||||
if (localName.length()){
|
||||
local_name = localName;
|
||||
}
|
||||
@ -445,4 +662,129 @@ esp_err_t BluetoothSerial::register_callback(esp_spp_cb_t * callback)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
//Simple Secure Pairing
|
||||
void BluetoothSerial::enableSSP() {
|
||||
_enableSSP = true;
|
||||
}
|
||||
/*
|
||||
* Set default parameters for Legacy Pairing
|
||||
* Use fixed pin code
|
||||
*/
|
||||
bool BluetoothSerial::setPin(const char *pin) {
|
||||
bool isEmpty = !(pin && *pin);
|
||||
if (isEmpty && !_isPinSet) {
|
||||
return true; // nothing to do
|
||||
} else if (!isEmpty){
|
||||
_pin_len = strlen(pin);
|
||||
memcpy(_pin_code, pin, _pin_len);
|
||||
} else {
|
||||
_pin_len = 0; // resetting pin to none (default)
|
||||
}
|
||||
_pin_code[_pin_len] = 0;
|
||||
_isPinSet = true;
|
||||
if (isReady(false, READY_TIMEOUT)) {
|
||||
btSetPin();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BluetoothSerial::connect(String remoteName)
|
||||
{
|
||||
if (!isReady(true, READY_TIMEOUT)) return false;
|
||||
if (remoteName && remoteName.length() < 1) {
|
||||
log_e("No remote name is provided");
|
||||
return false;
|
||||
}
|
||||
disconnect();
|
||||
_isRemoteAddressSet = false;
|
||||
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");
|
||||
// will first resolve name to address
|
||||
esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
|
||||
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[])
|
||||
{
|
||||
if (!isReady(true, READY_TIMEOUT)) return false;
|
||||
if (!remoteAddress) {
|
||||
log_e("No remote address is provided");
|
||||
return false;
|
||||
}
|
||||
disconnect();
|
||||
_remote_name[0] = 0;
|
||||
_isRemoteAddressSet = true;
|
||||
memcpy(_peer_bd_addr, remoteAddress, ESP_BD_ADDR_LEN);
|
||||
log_i("master : remoteAddress");
|
||||
if (esp_spp_start_discovery(_peer_bd_addr) == ESP_OK) {
|
||||
return waitForConnect(READY_TIMEOUT);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BluetoothSerial::connect()
|
||||
{
|
||||
if (!isReady(true, READY_TIMEOUT)) return false;
|
||||
if (_isRemoteAddressSet){
|
||||
disconnect();
|
||||
// use resolved or set address first
|
||||
log_i("master : remoteAddress");
|
||||
if (esp_spp_start_discovery(_peer_bd_addr) == ESP_OK) {
|
||||
return waitForConnect(READY_TIMEOUT);
|
||||
}
|
||||
return false;
|
||||
} else if (_remote_name[0]) {
|
||||
disconnect();
|
||||
log_i("master : remoteName");
|
||||
// will resolve name to address first - it may take a while
|
||||
esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
|
||||
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;
|
||||
}
|
||||
log_e("Neither Remote name nor address was provided");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BluetoothSerial::disconnect() {
|
||||
if (_spp_client) {
|
||||
flush();
|
||||
log_i("disconnecting");
|
||||
if (esp_spp_disconnect(_spp_client) == ESP_OK) {
|
||||
TickType_t xTicksToWait = READY_TIMEOUT / portTICK_PERIOD_MS;
|
||||
return (xEventGroupWaitBits(_spp_event_group, SPP_DISCONNECTED, pdFALSE, pdTRUE, xTicksToWait) != 0);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BluetoothSerial::unpairDevice(uint8_t remoteAddress[]) {
|
||||
if (isReady(false, READY_TIMEOUT)) {
|
||||
log_i("removing bonded device");
|
||||
return (esp_bt_gap_remove_bond_device(remoteAddress) == ESP_OK);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BluetoothSerial::connected(int timeout) {
|
||||
return waitForConnect(timeout);
|
||||
}
|
||||
|
||||
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");
|
||||
return false;
|
||||
}
|
||||
if (!btStarted()) {
|
||||
log_e("BT is not initialized. Call begin() first");
|
||||
return false;
|
||||
}
|
||||
TickType_t xTicksToWait = timeout / portTICK_PERIOD_MS;
|
||||
return (xEventGroupWaitBits(_spp_event_group, SPP_RUNNING, pdFALSE, pdTRUE, xTicksToWait) != 0);
|
||||
}
|
||||
#endif
|
||||
|
12
libraries/BluetoothSerial/src/BluetoothSerial.h
Normal file → Executable file
12
libraries/BluetoothSerial/src/BluetoothSerial.h
Normal file → Executable file
@ -30,7 +30,7 @@ class BluetoothSerial: public Stream
|
||||
BluetoothSerial(void);
|
||||
~BluetoothSerial(void);
|
||||
|
||||
bool begin(String localName=String());
|
||||
bool begin(String localName=String(), bool isMaster=false);
|
||||
int available(void);
|
||||
int peek(void);
|
||||
bool hasClient(void);
|
||||
@ -41,6 +41,16 @@ class BluetoothSerial: public Stream
|
||||
void end(void);
|
||||
esp_err_t register_callback(esp_spp_cb_t * callback);
|
||||
|
||||
void enableSSP();
|
||||
bool setPin(const char *pin);
|
||||
bool connect(String remoteName);
|
||||
bool connect(uint8_t remoteAddress[]);
|
||||
bool connect();
|
||||
bool connected(int timeout=0);
|
||||
bool isReady(bool checkMaster=false, int timeout=0);
|
||||
bool disconnect();
|
||||
bool unpairDevice(uint8_t remoteAddress[]);
|
||||
|
||||
private:
|
||||
String local_name;
|
||||
|
||||
|
@ -1,37 +1,21 @@
|
||||
/*
|
||||
ESP32 eeprom_class example with EEPROM library
|
||||
|
||||
This simple example demonstrates using EEPROM library to store different data in
|
||||
ESP32 Flash memory in a multiple user-defined EEPROM partition (0x1000 or 4KB max size or less).
|
||||
ESP32 Flash memory in a multiple user-defined EEPROM class objects.
|
||||
|
||||
Install 'ESP32 Partiton Manager' ONCE from https://github.com/francis94c/ESP32Partitions
|
||||
And generate different partitions with 'partition_name'
|
||||
Usage: EEPROMClass ANY_OBJECT_NAME("partition_name", size);
|
||||
|
||||
Generated partition that would work perfectly with this example
|
||||
#Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x5000,
|
||||
otadata, data, ota, 0xe000, 0x2000,
|
||||
app0, app, ota_0, 0x10000, 0x140000,
|
||||
app1, app, ota_1, 0x150000, 0x140000,
|
||||
eeprom0, data, 0x99, 0x290000, 0x1000,
|
||||
eeprom1, data, 0x9a, 0x291000, 0x500,
|
||||
eeprom2, data, 0x9b, 0x292000, 0x100,
|
||||
spiffs, data, spiffs, 0x293000, 0x16d000,
|
||||
|
||||
Created for arduino-esp32 on 25 Dec, 2017
|
||||
by Elochukwu Ifediora (fedy0)
|
||||
converted to nvs by lbernstone - 06/22/2019
|
||||
*/
|
||||
|
||||
#include "EEPROM.h"
|
||||
|
||||
// Instantiate eeprom objects with parameter/argument names and size same as in the partition table
|
||||
// Instantiate eeprom objects with parameter/argument names and sizes
|
||||
EEPROMClass NAMES("eeprom0", 0x500);
|
||||
EEPROMClass HEIGHT("eeprom1", 0x200);
|
||||
EEPROMClass AGE("eeprom2", 0x100);
|
||||
|
||||
void setup() {
|
||||
// put your setup code here, to run once:
|
||||
Serial.begin(115200);
|
||||
Serial.println("Testing EEPROMClass\n");
|
||||
if (!NAMES.begin(NAMES.length())) {
|
||||
@ -53,11 +37,12 @@ void setup() {
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
char* name = "Teo Swee Ann";
|
||||
const char* name = "Teo Swee Ann";
|
||||
char rname[32];
|
||||
double height = 5.8;
|
||||
uint32_t age = 47;
|
||||
|
||||
// Write: Variables ---> EEPROM partitions
|
||||
// Write: Variables ---> EEPROM stores
|
||||
NAMES.put(0, name);
|
||||
HEIGHT.put(0, height);
|
||||
AGE.put(0, age);
|
||||
@ -75,11 +60,11 @@ void setup() {
|
||||
Serial.print("age: "); Serial.println(age);
|
||||
Serial.println("------------------------------------\n");
|
||||
|
||||
// Read: Variables <--- EEPROM partitions
|
||||
NAMES.get(0, name);
|
||||
// Read: Variables <--- EEPROM stores
|
||||
NAMES.get(0, rname);
|
||||
HEIGHT.get(0, height);
|
||||
AGE.get(0, age);
|
||||
Serial.print("name: "); Serial.println(name);
|
||||
Serial.print("name: "); Serial.println(rname);
|
||||
Serial.print("height: "); Serial.println(height);
|
||||
Serial.print("age: "); Serial.println(age);
|
||||
|
||||
@ -87,6 +72,5 @@ void setup() {
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// put your main code here, to run repeatedly:
|
||||
|
||||
delay(0xFFFFFFFF);
|
||||
}
|
||||
|
@ -49,11 +49,11 @@ void setup() {
|
||||
EEPROM.writeULong(address, 4294967295); // Same as writeUInt and readUInt
|
||||
address += sizeof(unsigned long);
|
||||
|
||||
int64_t value = -9223372036854775808; // -2^63
|
||||
int64_t value = -1223372036854775808LL; // -2^63
|
||||
EEPROM.writeLong64(address, value);
|
||||
address += sizeof(int64_t);
|
||||
|
||||
uint64_t Value = 18446744073709551615; // 2^64 - 1
|
||||
uint64_t Value = 18446744073709551615ULL; // 2^64 - 1
|
||||
EEPROM.writeULong64(address, Value);
|
||||
address += sizeof(uint64_t);
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
name=EEPROM
|
||||
version=1.0
|
||||
version=1.0.3
|
||||
author=Ivan Grokhotkov
|
||||
maintainer=Paolo Becchi <pbecchi@aerobusiness.it>
|
||||
sentence=Enables reading and writing data to the permanent FLASH storage, up to 4kb.
|
||||
sentence=Enables reading and writing data a sequential, addressable FLASH storage
|
||||
paragraph=
|
||||
category=Data Storage
|
||||
url=http://arduino.cc/en/Reference/EEPROM
|
||||
architectures=esp32
|
||||
architectures=esp32
|
||||
|
@ -25,10 +25,11 @@
|
||||
|
||||
#include "EEPROM.h"
|
||||
#include <nvs.h>
|
||||
#include <esp_partition.h>
|
||||
#include <esp_log.h>
|
||||
|
||||
EEPROMClass::EEPROMClass(void)
|
||||
: _handle(NULL)
|
||||
: _handle(0)
|
||||
, _data(0)
|
||||
, _size(0)
|
||||
, _dirty(false)
|
||||
@ -39,7 +40,7 @@ EEPROMClass::EEPROMClass(void)
|
||||
|
||||
EEPROMClass::EEPROMClass(uint32_t sector)
|
||||
// Only for compatiility, no sectors in nvs!
|
||||
: _handle(NULL)
|
||||
: _handle(0)
|
||||
, _data(0)
|
||||
, _size(0)
|
||||
, _dirty(false)
|
||||
@ -49,7 +50,7 @@ EEPROMClass::EEPROMClass(uint32_t sector)
|
||||
}
|
||||
|
||||
EEPROMClass::EEPROMClass(const char* name, uint32_t user_defined_size)
|
||||
: _handle(NULL)
|
||||
: _handle(0)
|
||||
, _data(0)
|
||||
, _size(0)
|
||||
, _dirty(false)
|
||||
@ -59,7 +60,7 @@ EEPROMClass::EEPROMClass(const char* name, uint32_t user_defined_size)
|
||||
}
|
||||
|
||||
EEPROMClass::~EEPROMClass() {
|
||||
// end();
|
||||
end();
|
||||
}
|
||||
|
||||
bool EEPROMClass::begin(size_t size) {
|
||||
@ -111,7 +112,7 @@ bool EEPROMClass::begin(size_t size) {
|
||||
log_e("Not enough memory to expand EEPROM!");
|
||||
return false;
|
||||
}
|
||||
memset(key_data, 0, size);
|
||||
memset(key_data, 0xFF, size);
|
||||
if(key_size) {
|
||||
log_i("Expanding EEPROM from %d to %d", key_size, size);
|
||||
// hold data while key is deleted
|
||||
@ -151,6 +152,9 @@ void EEPROMClass::end() {
|
||||
}
|
||||
_data = 0;
|
||||
_size = 0;
|
||||
|
||||
nvs_close(_handle);
|
||||
_handle = 0;
|
||||
}
|
||||
|
||||
uint8_t EEPROMClass::read(int address) {
|
||||
@ -214,6 +218,67 @@ uint16_t EEPROMClass::length ()
|
||||
return _user_defined_size;
|
||||
}
|
||||
|
||||
/*
|
||||
Convert EEPROM partition into nvs blob
|
||||
Call convert before you call begin
|
||||
*/
|
||||
uint16_t EEPROMClass::convert (bool clear, const char* EEPROMname, const char* nvsname)
|
||||
{
|
||||
uint16_t result = 0;
|
||||
const esp_partition_t* mypart = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, EEPROMname);
|
||||
if (mypart == NULL) {
|
||||
log_i("EEPROM partition not found for conversion");
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t size = mypart->size;
|
||||
uint8_t* data = (uint8_t*) malloc(size);
|
||||
if (!data) {
|
||||
log_e("Not enough memory to convert EEPROM!");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (esp_partition_read (mypart, 0, (void *) data, size) != ESP_OK) {
|
||||
log_e("Unable to read EEPROM partition");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
bool empty;
|
||||
empty = true;
|
||||
for (int x=0; x<size; x++) {
|
||||
if (data[x] != 0xFF) {
|
||||
empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (empty) {
|
||||
log_i("EEPROM partition is empty, will not convert");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
nvs_handle handle;
|
||||
if (nvs_open(nvsname, NVS_READWRITE, &handle) != ESP_OK) {
|
||||
log_e("Unable to open NVS");
|
||||
goto exit;
|
||||
}
|
||||
esp_err_t err;
|
||||
err = nvs_set_blob(handle, nvsname, data, size);
|
||||
if (err != ESP_OK) {
|
||||
log_e("Unable to add EEPROM data to NVS: %s", esp_err_to_name(err));
|
||||
goto exit;
|
||||
}
|
||||
result = size;
|
||||
|
||||
if (clear) {
|
||||
if (esp_partition_erase_range (mypart, 0, size) != ESP_OK) {
|
||||
log_w("Unable to clear EEPROM partition");
|
||||
}
|
||||
}
|
||||
exit:
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
Read 'value' from 'address'
|
||||
*/
|
||||
|
@ -47,6 +47,7 @@ class EEPROMClass {
|
||||
void end();
|
||||
|
||||
uint8_t * getDataPtr();
|
||||
uint16_t convert(bool clear, const char* EEPROMname = "eeprom", const char* nvsname = "eeprom");
|
||||
|
||||
template<typename T>
|
||||
T &get(int address, T &t) {
|
||||
|
@ -229,6 +229,7 @@ static esp_err_t capture_handler(httpd_req_t *req){
|
||||
|
||||
httpd_resp_set_type(req, "image/jpeg");
|
||||
httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg");
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
size_t out_len, out_width, out_height;
|
||||
uint8_t * out_buf;
|
||||
@ -282,6 +283,7 @@ static esp_err_t capture_handler(httpd_req_t *req){
|
||||
face_id = run_face_recognition(image_matrix, net_boxes);
|
||||
}
|
||||
draw_face_boxes(image_matrix, net_boxes, face_id);
|
||||
free(net_boxes->score);
|
||||
free(net_boxes->box);
|
||||
free(net_boxes->landmark);
|
||||
free(net_boxes);
|
||||
@ -325,6 +327,8 @@ static esp_err_t stream_handler(httpd_req_t *req){
|
||||
return res;
|
||||
}
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
while(true){
|
||||
detected = false;
|
||||
face_id = 0;
|
||||
@ -378,6 +382,7 @@ static esp_err_t stream_handler(httpd_req_t *req){
|
||||
}
|
||||
fr_recognize = esp_timer_get_time();
|
||||
draw_face_boxes(image_matrix, net_boxes, face_id);
|
||||
free(net_boxes->score);
|
||||
free(net_boxes->box);
|
||||
free(net_boxes->landmark);
|
||||
free(net_boxes);
|
||||
@ -624,15 +629,18 @@ void startCameraServer(){
|
||||
|
||||
ra_filter_init(&ra_filter, 20);
|
||||
|
||||
mtmn_config.type = FAST;
|
||||
mtmn_config.min_face = 80;
|
||||
mtmn_config.pyramid = 0.7;
|
||||
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 = 4;
|
||||
mtmn_config.r_threshold.candidate_number = 10;
|
||||
mtmn_config.o_threshold.score = 0.7;
|
||||
mtmn_config.o_threshold.nms = 0.4;
|
||||
mtmn_config.o_threshold.nms = 0.7;
|
||||
mtmn_config.o_threshold.candidate_number = 1;
|
||||
|
||||
face_id_init(&id_list, FACE_ID_SAVE_NUMBER, ENROLL_CONFIRM_TIMES);
|
||||
|
@ -19,7 +19,7 @@ Author:
|
||||
Pranav Cherukupalli <cherukupallip@gmail.com>
|
||||
*/
|
||||
|
||||
#define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */
|
||||
#define uS_TO_S_FACTOR 1000000ULL /* Conversion factor for micro seconds to seconds */
|
||||
#define TIME_TO_SLEEP 5 /* Time ESP32 will go to sleep (in seconds) */
|
||||
|
||||
RTC_DATA_ATTR int bootCount = 0;
|
||||
|
@ -40,8 +40,6 @@ Method to print the touchpad by which ESP32
|
||||
has been awaken from sleep
|
||||
*/
|
||||
void print_wakeup_touchpad(){
|
||||
touch_pad_t pin;
|
||||
|
||||
touchPin = esp_sleep_get_touchpad_wakeup_status();
|
||||
|
||||
switch(touchPin)
|
||||
|
@ -88,7 +88,7 @@ void ScanForSlave() {
|
||||
Serial.print(i + 1); Serial.print(": "); Serial.print(SSID); Serial.print(" ["); Serial.print(BSSIDstr); Serial.print("]"); Serial.print(" ("); Serial.print(RSSI); Serial.print(")"); Serial.println("");
|
||||
// Get BSSID => Mac Address of the Slave
|
||||
int mac[6];
|
||||
if ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x%c", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5] ) ) {
|
||||
if ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5] ) ) {
|
||||
for (int ii = 0; ii < 6; ++ii ) {
|
||||
slave.peer_addr[ii] = (uint8_t) mac[ii];
|
||||
}
|
||||
@ -124,17 +124,15 @@ bool manageSlave() {
|
||||
}
|
||||
|
||||
Serial.print("Slave Status: ");
|
||||
const esp_now_peer_info_t *peer = &slave;
|
||||
const uint8_t *peer_addr = slave.peer_addr;
|
||||
// check if the peer exists
|
||||
bool exists = esp_now_is_peer_exist(peer_addr);
|
||||
bool exists = esp_now_is_peer_exist(slave.peer_addr);
|
||||
if ( exists) {
|
||||
// Slave already paired.
|
||||
Serial.println("Already Paired");
|
||||
return true;
|
||||
} else {
|
||||
// Slave not paired, attempt pair
|
||||
esp_err_t addStatus = esp_now_add_peer(peer);
|
||||
esp_err_t addStatus = esp_now_add_peer(&slave);
|
||||
if (addStatus == ESP_OK) {
|
||||
// Pair success
|
||||
Serial.println("Pair success");
|
||||
@ -168,9 +166,7 @@ bool manageSlave() {
|
||||
}
|
||||
|
||||
void deletePeer() {
|
||||
const esp_now_peer_info_t *peer = &slave;
|
||||
const uint8_t *peer_addr = slave.peer_addr;
|
||||
esp_err_t delStatus = esp_now_del_peer(peer_addr);
|
||||
esp_err_t delStatus = esp_now_del_peer(slave.peer_addr);
|
||||
Serial.print("Slave Delete Status: ");
|
||||
if (delStatus == ESP_OK) {
|
||||
// Delete success
|
||||
|
@ -100,7 +100,7 @@ void ScanForSlave() {
|
||||
// Get BSSID => Mac Address of the Slave
|
||||
int mac[6];
|
||||
|
||||
if ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x%c", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5] ) ) {
|
||||
if ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5] ) ) {
|
||||
for (int ii = 0; ii < 6; ++ii ) {
|
||||
slaves[SlaveCnt].peer_addr[ii] = (uint8_t) mac[ii];
|
||||
}
|
||||
@ -127,8 +127,6 @@ void ScanForSlave() {
|
||||
void manageSlave() {
|
||||
if (SlaveCnt > 0) {
|
||||
for (int i = 0; i < SlaveCnt; i++) {
|
||||
const esp_now_peer_info_t *peer = &slaves[i];
|
||||
const uint8_t *peer_addr = slaves[i].peer_addr;
|
||||
Serial.print("Processing: ");
|
||||
for (int ii = 0; ii < 6; ++ii ) {
|
||||
Serial.print((uint8_t) slaves[i].peer_addr[ii], HEX);
|
||||
@ -136,13 +134,13 @@ void manageSlave() {
|
||||
}
|
||||
Serial.print(" Status: ");
|
||||
// check if the peer exists
|
||||
bool exists = esp_now_is_peer_exist(peer_addr);
|
||||
bool exists = esp_now_is_peer_exist(slaves[i].peer_addr);
|
||||
if (exists) {
|
||||
// Slave already paired.
|
||||
Serial.println("Already Paired");
|
||||
} else {
|
||||
// Slave not paired, attempt pair
|
||||
esp_err_t addStatus = esp_now_add_peer(peer);
|
||||
esp_err_t addStatus = esp_now_add_peer(&slaves[i]);
|
||||
if (addStatus == ESP_OK) {
|
||||
// Pair success
|
||||
Serial.println("Pair success");
|
||||
|
@ -52,7 +52,7 @@ void loop()
|
||||
// Printout the received data plus the original values
|
||||
for (i=0; i<60; i++)
|
||||
{
|
||||
Serial.printf("%08x=%08x ", my_data[i], data[i] );
|
||||
Serial.printf("%08x=%08x ", my_data[i].val, data[i].val );
|
||||
if (!((i+1)%4)) Serial.println("\n");
|
||||
}
|
||||
Serial.println("\n");
|
||||
|
@ -141,7 +141,6 @@ static bool xjtReceiveBit(size_t index, bool bit){
|
||||
}
|
||||
|
||||
void parseRmt(rmt_data_t* items, size_t len, uint32_t* channels){
|
||||
size_t chan = 0;
|
||||
bool valid = true;
|
||||
rmt_data_t* it = NULL;
|
||||
|
||||
|
@ -62,7 +62,7 @@ void loop()
|
||||
for (led=0; led<NR_OF_LEDS; led++) {
|
||||
for (col=0; col<3; col++ ) {
|
||||
for (bit=0; bit<8; bit++){
|
||||
if ( (color[col] & (1<<(8-bit))) && (led == led_index) ) {
|
||||
if ( (color[col] & (1<<(7-bit))) && (led == led_index) ) {
|
||||
led_data[i].level0 = 1;
|
||||
led_data[i].duration0 = 8;
|
||||
led_data[i].level1 = 0;
|
||||
|
@ -96,7 +96,6 @@ void loop(void)
|
||||
req = req.substring(addr_start + 1, addr_end);
|
||||
Serial.print("Request: ");
|
||||
Serial.println(req);
|
||||
client.flush();
|
||||
|
||||
String s;
|
||||
if (req == "/")
|
||||
@ -115,6 +114,7 @@ void loop(void)
|
||||
}
|
||||
client.print(s);
|
||||
|
||||
client.stop();
|
||||
Serial.println("Done with client");
|
||||
}
|
||||
|
||||
|
@ -165,8 +165,8 @@ void setup(){
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.printf("Total space: %10lu\n", FFat.totalBytes());
|
||||
Serial.printf("Free space: %10lu\n", FFat.freeBytes());
|
||||
Serial.printf("Total space: %10u\n", FFat.totalBytes());
|
||||
Serial.printf("Free space: %10u\n", FFat.freeBytes());
|
||||
listDir(FFat, "/", 0);
|
||||
writeFile(FFat, "/hello.txt", "Hello ");
|
||||
appendFile(FFat, "/hello.txt", "World!\r\n");
|
||||
@ -175,7 +175,7 @@ void setup(){
|
||||
readFile(FFat, "/foo.txt");
|
||||
deleteFile(FFat, "/foo.txt");
|
||||
testFileIO(FFat, "/test.txt");
|
||||
Serial.printf("Free space: %10lu\n", FFat.freeBytes());
|
||||
Serial.printf("Free space: %10u\n", FFat.freeBytes());
|
||||
deleteFile(FFat, "/test.txt");
|
||||
Serial.println( "Test complete" );
|
||||
}
|
||||
|
177
libraries/FFat/examples/FFat_time/FFat_time.ino
Normal file
177
libraries/FFat/examples/FFat_time/FFat_time.ino
Normal file
@ -0,0 +1,177 @@
|
||||
#include "FS.h"
|
||||
#include "FFat.h"
|
||||
#include <time.h>
|
||||
#include <WiFi.h>
|
||||
|
||||
const char* ssid = "your-ssid";
|
||||
const char* password = "your-password";
|
||||
|
||||
long timezone = 1;
|
||||
byte daysavetime = 1;
|
||||
|
||||
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
|
||||
Serial.printf("Listing directory: %s\n", dirname);
|
||||
|
||||
File root = fs.open(dirname);
|
||||
if(!root){
|
||||
Serial.println("Failed to open directory");
|
||||
return;
|
||||
}
|
||||
if(!root.isDirectory()){
|
||||
Serial.println("Not a directory");
|
||||
return;
|
||||
}
|
||||
|
||||
File file = root.openNextFile();
|
||||
while(file){
|
||||
if(file.isDirectory()){
|
||||
Serial.print(" DIR : ");
|
||||
Serial.print (file.name());
|
||||
time_t t= file.getLastWrite();
|
||||
struct tm * tmstruct = localtime(&t);
|
||||
Serial.printf(" LAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n",(tmstruct->tm_year)+1900,( tmstruct->tm_mon)+1, tmstruct->tm_mday,tmstruct->tm_hour , tmstruct->tm_min, tmstruct->tm_sec);
|
||||
if(levels){
|
||||
listDir(fs, file.name(), levels -1);
|
||||
}
|
||||
} else {
|
||||
Serial.print(" FILE: ");
|
||||
Serial.print(file.name());
|
||||
Serial.print(" SIZE: ");
|
||||
Serial.print(file.size());
|
||||
time_t t= file.getLastWrite();
|
||||
struct tm * tmstruct = localtime(&t);
|
||||
Serial.printf(" LAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n",(tmstruct->tm_year)+1900,( tmstruct->tm_mon)+1, tmstruct->tm_mday,tmstruct->tm_hour , tmstruct->tm_min, tmstruct->tm_sec);
|
||||
}
|
||||
file = root.openNextFile();
|
||||
}
|
||||
}
|
||||
|
||||
void createDir(fs::FS &fs, const char * path){
|
||||
Serial.printf("Creating Dir: %s\n", path);
|
||||
if(fs.mkdir(path)){
|
||||
Serial.println("Dir created");
|
||||
} else {
|
||||
Serial.println("mkdir failed");
|
||||
}
|
||||
}
|
||||
|
||||
void removeDir(fs::FS &fs, const char * path){
|
||||
Serial.printf("Removing Dir: %s\n", path);
|
||||
if(fs.rmdir(path)){
|
||||
Serial.println("Dir removed");
|
||||
} else {
|
||||
Serial.println("rmdir failed");
|
||||
}
|
||||
}
|
||||
|
||||
void readFile(fs::FS &fs, const char * path){
|
||||
Serial.printf("Reading file: %s\n", path);
|
||||
|
||||
File file = fs.open(path);
|
||||
if(!file){
|
||||
Serial.println("Failed to open file for reading");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.print("Read from file: ");
|
||||
while(file.available()){
|
||||
Serial.write(file.read());
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
void writeFile(fs::FS &fs, const char * path, const char * message){
|
||||
Serial.printf("Writing file: %s\n", path);
|
||||
|
||||
File file = fs.open(path, FILE_WRITE);
|
||||
if(!file){
|
||||
Serial.println("Failed to open file for writing");
|
||||
return;
|
||||
}
|
||||
if(file.print(message)){
|
||||
Serial.println("File written");
|
||||
} else {
|
||||
Serial.println("Write failed");
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
void appendFile(fs::FS &fs, const char * path, const char * message){
|
||||
Serial.printf("Appending to file: %s\n", path);
|
||||
|
||||
File file = fs.open(path, FILE_APPEND);
|
||||
if(!file){
|
||||
Serial.println("Failed to open file for appending");
|
||||
return;
|
||||
}
|
||||
if(file.print(message)){
|
||||
Serial.println("Message appended");
|
||||
} else {
|
||||
Serial.println("Append failed");
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
void renameFile(fs::FS &fs, const char * path1, const char * path2){
|
||||
Serial.printf("Renaming file %s to %s\n", path1, path2);
|
||||
if (fs.rename(path1, path2)) {
|
||||
Serial.println("File renamed");
|
||||
} else {
|
||||
Serial.println("Rename failed");
|
||||
}
|
||||
}
|
||||
|
||||
void deleteFile(fs::FS &fs, const char * path){
|
||||
Serial.printf("Deleting file: %s\n", path);
|
||||
if(fs.remove(path)){
|
||||
Serial.println("File deleted");
|
||||
} else {
|
||||
Serial.println("Delete failed");
|
||||
}
|
||||
}
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200);
|
||||
// We start by connecting to a WiFi network
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
Serial.print("Connecting to ");
|
||||
Serial.println(ssid);
|
||||
|
||||
WiFi.begin(ssid, password);
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("WiFi connected");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
Serial.println("Contacting Time Server");
|
||||
configTime(3600*timezone, daysavetime*3600, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
|
||||
struct tm tmstruct ;
|
||||
delay(2000);
|
||||
tmstruct.tm_year = 0;
|
||||
getLocalTime(&tmstruct, 5000);
|
||||
Serial.printf("\nNow is : %d-%02d-%02d %02d:%02d:%02d\n",(tmstruct.tm_year)+1900,( tmstruct.tm_mon)+1, tmstruct.tm_mday,tmstruct.tm_hour , tmstruct.tm_min, tmstruct.tm_sec);
|
||||
Serial.println("");
|
||||
|
||||
if(!FFat.begin(true)){
|
||||
Serial.println("FFat Mount Failed");
|
||||
return;
|
||||
}
|
||||
|
||||
listDir(FFat, "/", 0);
|
||||
removeDir(FFat, "/mydir");
|
||||
createDir(FFat, "/mydir");
|
||||
deleteFile(FFat, "/hello.txt");
|
||||
writeFile(FFat, "/hello.txt", "Hello ");
|
||||
appendFile(FFat, "/hello.txt", "World!\n");
|
||||
listDir(FFat, "/", 0);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
|
||||
}
|
||||
|
||||
|
@ -40,20 +40,26 @@ const esp_partition_t *check_ffat_partition(const char* label)
|
||||
|
||||
bool F_Fat::begin(bool formatOnFail, const char * basePath, uint8_t maxOpenFiles, const char * partitionLabel)
|
||||
{
|
||||
if(_wl_handle){
|
||||
if(_wl_handle != WL_INVALID_HANDLE){
|
||||
log_w("Already Mounted!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!check_ffat_partition(partitionLabel)) return false;
|
||||
if (!check_ffat_partition(partitionLabel)){
|
||||
log_e("No fat partition found on flash");
|
||||
return false;
|
||||
}
|
||||
|
||||
esp_vfs_fat_mount_config_t conf = {
|
||||
.format_if_mount_failed = formatOnFail,
|
||||
.max_files = maxOpenFiles
|
||||
.max_files = maxOpenFiles,
|
||||
.allocation_unit_size = CONFIG_WL_SECTOR_SIZE
|
||||
};
|
||||
esp_err_t err = esp_vfs_fat_spiflash_mount(basePath, partitionLabel, &conf, &_wl_handle);
|
||||
if(err){
|
||||
log_e("Mounting FFat partition failed! Error: %d", err);
|
||||
esp_vfs_fat_spiflash_unmount(basePath, _wl_handle);
|
||||
_wl_handle = WL_INVALID_HANDLE;
|
||||
return false;
|
||||
}
|
||||
_impl->mountpoint(basePath);
|
||||
@ -62,13 +68,13 @@ bool F_Fat::begin(bool formatOnFail, const char * basePath, uint8_t maxOpenFiles
|
||||
|
||||
void F_Fat::end()
|
||||
{
|
||||
if(_wl_handle){
|
||||
if(_wl_handle != WL_INVALID_HANDLE){
|
||||
esp_err_t err = esp_vfs_fat_spiflash_unmount(_impl->mountpoint(), _wl_handle);
|
||||
if(err){
|
||||
log_e("Unmounting FFat partition failed! Error: %d", err);
|
||||
return;
|
||||
}
|
||||
_wl_handle = NULL;
|
||||
_wl_handle = WL_INVALID_HANDLE;
|
||||
_impl->mountpoint(NULL);
|
||||
}
|
||||
}
|
||||
@ -76,14 +82,18 @@ void F_Fat::end()
|
||||
bool F_Fat::format(bool full_wipe, char* partitionLabel)
|
||||
{
|
||||
esp_err_t result;
|
||||
if(_wl_handle){
|
||||
bool res = true;
|
||||
if(_wl_handle != WL_INVALID_HANDLE){
|
||||
log_w("Already Mounted!");
|
||||
return false;
|
||||
}
|
||||
wl_handle_t temp_handle;
|
||||
// Attempt to mount to see if there is already data
|
||||
const esp_partition_t *ffat_partition = check_ffat_partition(partitionLabel);
|
||||
if (!ffat_partition) return false;
|
||||
if (!ffat_partition){
|
||||
log_w("No partition!");
|
||||
return false;
|
||||
}
|
||||
result = wl_mount(ffat_partition, &temp_handle);
|
||||
|
||||
if (result == ESP_OK) {
|
||||
@ -91,15 +101,23 @@ bool F_Fat::format(bool full_wipe, char* partitionLabel)
|
||||
uint32_t wipe_size = full_wipe ? wl_size(temp_handle) : 16384;
|
||||
wl_erase_range(temp_handle, 0, wipe_size);
|
||||
wl_unmount(temp_handle);
|
||||
} else {
|
||||
res = false;
|
||||
log_w("wl_mount failed!");
|
||||
}
|
||||
// Now do a mount with format_if_fail (which it will)
|
||||
esp_vfs_fat_mount_config_t conf = {
|
||||
.format_if_mount_failed = true,
|
||||
.max_files = 1
|
||||
.max_files = 1,
|
||||
.allocation_unit_size = CONFIG_WL_SECTOR_SIZE
|
||||
};
|
||||
result = esp_vfs_fat_spiflash_mount("/format_ffat", partitionLabel, &conf, &temp_handle);
|
||||
esp_vfs_fat_spiflash_unmount("/format_ffat", temp_handle);
|
||||
return result;
|
||||
if (result != ESP_OK){
|
||||
res = false;
|
||||
log_w("esp_vfs_fat_spiflash_mount failed!");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
size_t F_Fat::totalBytes()
|
||||
@ -109,7 +127,9 @@ size_t F_Fat::totalBytes()
|
||||
|
||||
BYTE pdrv = ff_diskio_get_pdrv_wl(_wl_handle);
|
||||
char drv[3] = {(char)(48+pdrv), ':', 0};
|
||||
FRESULT res = f_getfree(drv, &free_clust, &fs);
|
||||
if ( f_getfree(drv, &free_clust, &fs) != FR_OK){
|
||||
return 0;
|
||||
}
|
||||
tot_sect = (fs->n_fatent - 2) * fs->csize;
|
||||
sect_size = CONFIG_WL_SECTOR_SIZE;
|
||||
return tot_sect * sect_size;
|
||||
@ -123,7 +143,9 @@ size_t F_Fat::freeBytes()
|
||||
|
||||
BYTE pdrv = ff_diskio_get_pdrv_wl(_wl_handle);
|
||||
char drv[3] = {(char)(48+pdrv), ':', 0};
|
||||
FRESULT res = f_getfree(drv, &free_clust, &fs);
|
||||
if ( f_getfree(drv, &free_clust, &fs) != FR_OK){
|
||||
return 0;
|
||||
}
|
||||
free_sect = free_clust * fs->csize;
|
||||
sect_size = CONFIG_WL_SECTOR_SIZE;
|
||||
return free_sect * sect_size;
|
||||
|
@ -37,7 +37,7 @@ public:
|
||||
bool exists(const String& path);
|
||||
|
||||
private:
|
||||
wl_handle_t _wl_handle;
|
||||
wl_handle_t _wl_handle = WL_INVALID_HANDLE;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ name=HTTPClient
|
||||
version=1.2
|
||||
author=Markus Sattler
|
||||
maintainer=Markus Sattler
|
||||
sentence=http Client for ESP32
|
||||
sentence=HTTP Client for ESP32
|
||||
paragraph=
|
||||
category=Communication
|
||||
url=https://github.com/Links2004/Arduino/tree/libraries/ESP8266HTTPClient
|
||||
url=https://github.com/espressif/arduino-esp32/tree/master/libraries/HTTPClient
|
||||
architectures=esp32
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <HardwareSerial.h>
|
||||
/**
|
||||
* HTTPClient.cpp
|
||||
*
|
||||
@ -195,6 +196,11 @@ bool HTTPClient::begin(String url, const char* CAcert)
|
||||
}
|
||||
_secure = true;
|
||||
_transportTraits = TransportTraitsPtr(new TLSTraits(CAcert));
|
||||
if(!_transportTraits) {
|
||||
log_e("could not create transport traits");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -215,6 +221,11 @@ bool HTTPClient::begin(String url)
|
||||
return begin(url, (const char*)NULL);
|
||||
}
|
||||
_transportTraits = TransportTraitsPtr(new TransportTraits());
|
||||
if(!_transportTraits) {
|
||||
log_e("could not create transport traits");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // HTTPCLIENT_1_1_COMPATIBLE
|
||||
@ -333,7 +344,8 @@ bool HTTPClient::begin(String host, uint16_t port, String uri, const char* CAcer
|
||||
*/
|
||||
void HTTPClient::end(void)
|
||||
{
|
||||
disconnect();
|
||||
disconnect(false);
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
@ -342,7 +354,7 @@ void HTTPClient::end(void)
|
||||
* disconnect
|
||||
* close the TCP socket
|
||||
*/
|
||||
void HTTPClient::disconnect()
|
||||
void HTTPClient::disconnect(bool preserveClient)
|
||||
{
|
||||
if(connected()) {
|
||||
if(_client->available() > 0) {
|
||||
@ -357,7 +369,9 @@ void HTTPClient::disconnect()
|
||||
} else {
|
||||
log_d("tcp stop\n");
|
||||
_client->stop();
|
||||
_client = nullptr;
|
||||
if(!preserveClient) {
|
||||
_client = nullptr;
|
||||
}
|
||||
#ifdef HTTPCLIENT_1_1_COMPATIBLE
|
||||
if(_tcpDeprecated) {
|
||||
_transportTraits.reset(nullptr);
|
||||
@ -456,6 +470,7 @@ void HTTPClient::setTimeout(uint16_t timeout)
|
||||
void HTTPClient::useHTTP10(bool useHTTP10)
|
||||
{
|
||||
_useHTTP10 = useHTTP10;
|
||||
_reuse = !useHTTP10;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -816,7 +831,8 @@ int HTTPClient::writeToStream(Stream * stream)
|
||||
return returnError(HTTPC_ERROR_ENCODING);
|
||||
}
|
||||
|
||||
end();
|
||||
// end();
|
||||
disconnect(true);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -970,9 +986,12 @@ bool HTTPClient::hasHeader(const char* name)
|
||||
*/
|
||||
bool HTTPClient::connect(void)
|
||||
{
|
||||
|
||||
if(connected()) {
|
||||
log_d("already connected, try reuse!");
|
||||
if(_reuse) {
|
||||
log_d("already connected, reusing connection");
|
||||
} else {
|
||||
log_d("already connected, try reuse!");
|
||||
}
|
||||
while(_client->available() > 0) {
|
||||
_client->read();
|
||||
}
|
||||
@ -980,8 +999,12 @@ bool HTTPClient::connect(void)
|
||||
}
|
||||
|
||||
#ifdef HTTPCLIENT_1_1_COMPATIBLE
|
||||
if(!_client) {
|
||||
if(_transportTraits && !_client) {
|
||||
_tcpDeprecated = _transportTraits->create();
|
||||
if(!_tcpDeprecated) {
|
||||
log_e("failed to create client");
|
||||
return false;
|
||||
}
|
||||
_client = _tcpDeprecated.get();
|
||||
}
|
||||
#endif
|
||||
@ -1080,9 +1103,12 @@ int HTTPClient::handleHeaderResponse()
|
||||
return HTTPC_ERROR_NOT_CONNECTED;
|
||||
}
|
||||
|
||||
clear();
|
||||
|
||||
_canReuse = _reuse;
|
||||
|
||||
String transferEncoding;
|
||||
_returnCode = -1;
|
||||
_size = -1;
|
||||
|
||||
_transferEncoding = HTTPC_TE_IDENTITY;
|
||||
unsigned long lastDataTime = millis();
|
||||
|
||||
@ -1097,6 +1123,9 @@ int HTTPClient::handleHeaderResponse()
|
||||
log_v("RX: '%s'", headerLine.c_str());
|
||||
|
||||
if(headerLine.startsWith("HTTP/1.")) {
|
||||
if(_canReuse) {
|
||||
_canReuse = (headerLine[sizeof "HTTP/1." - 1] != '0');
|
||||
}
|
||||
_returnCode = headerLine.substring(9, headerLine.indexOf(' ', 9)).toInt();
|
||||
} else if(headerLine.indexOf(':')) {
|
||||
String headerName = headerLine.substring(0, headerLine.indexOf(':'));
|
||||
@ -1107,8 +1136,10 @@ int HTTPClient::handleHeaderResponse()
|
||||
_size = headerValue.toInt();
|
||||
}
|
||||
|
||||
if(headerName.equalsIgnoreCase("Connection")) {
|
||||
_canReuse = headerValue.equalsIgnoreCase("keep-alive");
|
||||
if(_canReuse && headerName.equalsIgnoreCase("Connection")) {
|
||||
if(headerValue.indexOf("close") >= 0 && headerValue.indexOf("keep-alive") < 0) {
|
||||
_canReuse = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(headerName.equalsIgnoreCase("Transfer-Encoding")) {
|
||||
|
@ -197,7 +197,7 @@ protected:
|
||||
};
|
||||
|
||||
bool beginInternal(String url, const char* expectedProtocol);
|
||||
void disconnect();
|
||||
void disconnect(bool preserveClient = false);
|
||||
void clear();
|
||||
int returnError(int error);
|
||||
bool connect(void);
|
||||
@ -217,7 +217,7 @@ protected:
|
||||
String _host;
|
||||
uint16_t _port = 0;
|
||||
int32_t _connectTimeout = -1;
|
||||
bool _reuse = false;
|
||||
bool _reuse = true;
|
||||
uint16_t _tcpTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT;
|
||||
bool _useHTTP10 = false;
|
||||
bool _secure = false;
|
||||
|
@ -96,7 +96,7 @@ void loop() {
|
||||
client.setCACert(rootCACertificate);
|
||||
|
||||
// Reading data over SSL may be slow, use an adequate timeout
|
||||
client.setTimeout(12000);
|
||||
client.setTimeout(12000 / 1000); // timeout argument is defined in seconds for setTimeout
|
||||
|
||||
// The line below is optional. It can be used to blink the LED on the board during flashing
|
||||
// The LED will be on during download of one buffer of data from the network. The LED will
|
||||
|
@ -204,7 +204,7 @@ void SPIClass::transferBits(uint32_t data, uint32_t * out, uint8_t bits)
|
||||
* @param data uint8_t *
|
||||
* @param size uint32_t
|
||||
*/
|
||||
void SPIClass::writeBytes(uint8_t * data, uint32_t size)
|
||||
void SPIClass::writeBytes(const uint8_t * data, uint32_t size)
|
||||
{
|
||||
if(_inTransaction){
|
||||
return spiWriteNL(_spi, data, size);
|
||||
|
@ -76,7 +76,7 @@ public:
|
||||
void write(uint8_t data);
|
||||
void write16(uint16_t data);
|
||||
void write32(uint32_t data);
|
||||
void writeBytes(uint8_t * data, uint32_t size);
|
||||
void writeBytes(const uint8_t * data, uint32_t size);
|
||||
void writePixels(const void * data, uint32_t size);//ili9341 compatible
|
||||
void writePattern(uint8_t * data, uint8_t size, uint32_t repeat);
|
||||
|
||||
|
@ -20,13 +20,33 @@ extern "C" {
|
||||
#include <dirent.h>
|
||||
#include "esp_spiffs.h"
|
||||
}
|
||||
|
||||
#include "SPIFFS.h"
|
||||
|
||||
using namespace fs;
|
||||
|
||||
SPIFFSFS::SPIFFSFS(FSImplPtr impl)
|
||||
: FS(impl)
|
||||
{}
|
||||
class SPIFFSImpl : public VFSImpl
|
||||
{
|
||||
public:
|
||||
SPIFFSImpl();
|
||||
virtual ~SPIFFSImpl() { }
|
||||
virtual bool exists(const char* path);
|
||||
};
|
||||
|
||||
SPIFFSImpl::SPIFFSImpl()
|
||||
{
|
||||
}
|
||||
|
||||
bool SPIFFSImpl::exists(const char* path)
|
||||
{
|
||||
File f = open(path, "r");
|
||||
return (f == true) && !f.isDirectory();
|
||||
}
|
||||
|
||||
SPIFFSFS::SPIFFSFS() : FS(FSImplPtr(new SPIFFSImpl()))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool SPIFFSFS::begin(bool formatOnFail, const char * basePath, uint8_t maxOpenFiles)
|
||||
{
|
||||
@ -98,16 +118,5 @@ size_t SPIFFSFS::usedBytes()
|
||||
return used;
|
||||
}
|
||||
|
||||
bool SPIFFSFS::exists(const char* path)
|
||||
{
|
||||
File f = open(path, "r");
|
||||
return (f == true) && !f.isDirectory();
|
||||
}
|
||||
SPIFFSFS SPIFFS;
|
||||
|
||||
bool SPIFFSFS::exists(const String& path)
|
||||
{
|
||||
return exists(path.c_str());
|
||||
}
|
||||
|
||||
|
||||
SPIFFSFS SPIFFS = SPIFFSFS(FSImplPtr(new VFSImpl()));
|
||||
|
@ -22,18 +22,17 @@ namespace fs
|
||||
class SPIFFSFS : public FS
|
||||
{
|
||||
public:
|
||||
SPIFFSFS(FSImplPtr impl);
|
||||
SPIFFSFS();
|
||||
bool begin(bool formatOnFail=false, const char * basePath="/spiffs", uint8_t maxOpenFiles=10);
|
||||
bool format();
|
||||
size_t totalBytes();
|
||||
size_t usedBytes();
|
||||
void end();
|
||||
bool exists(const char* path);
|
||||
bool exists(const String& path);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
extern fs::SPIFFSFS SPIFFS;
|
||||
|
||||
#endif /* _SPIFFS_H_ */
|
||||
|
||||
#endif
|
||||
|
@ -43,9 +43,9 @@ void Ticker::_attach_ms(uint32_t milliseconds, bool repeat, callback_with_arg_t
|
||||
}
|
||||
esp_timer_create(&_timerConfig, &_timer);
|
||||
if (repeat) {
|
||||
esp_timer_start_periodic(_timer, milliseconds * 1000);
|
||||
esp_timer_start_periodic(_timer, milliseconds * 1000ULL);
|
||||
} else {
|
||||
esp_timer_start_once(_timer, milliseconds * 1000);
|
||||
esp_timer_start_once(_timer, milliseconds * 1000ULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ class UpdateClass {
|
||||
If all bytes are written
|
||||
this call will write the config to eboot
|
||||
and return true
|
||||
If there is already an update running but is not finished and !evenIfRemainanig
|
||||
If there is already an update running but is not finished and !evenIfRemaining
|
||||
or there is an error
|
||||
this will clear everything and return false
|
||||
the last error is available through getError()
|
||||
@ -80,6 +80,8 @@ class UpdateClass {
|
||||
*/
|
||||
void printError(Stream &out);
|
||||
|
||||
const char * errorString();
|
||||
|
||||
/*
|
||||
sets the expected MD5 for the firmware (hexString)
|
||||
*/
|
||||
|
@ -189,6 +189,9 @@ bool UpdateClass::_writeBuffer(){
|
||||
//this ensures that partially written firmware will not be bootable
|
||||
_buffer[0] = 0xFF;
|
||||
}
|
||||
if (!_progress && _progress_callback) {
|
||||
_progress_callback(0, _size);
|
||||
}
|
||||
if(!ESP.flashEraseSector((_partition->address + _progress)/SPI_FLASH_SEC_SIZE)){
|
||||
_abort(UPDATE_ERROR_ERASE);
|
||||
return false;
|
||||
@ -204,6 +207,9 @@ bool UpdateClass::_writeBuffer(){
|
||||
_md5.add(_buffer, _bufferLen);
|
||||
_progress += _bufferLen;
|
||||
_bufferLen = 0;
|
||||
if (_progress_callback) {
|
||||
_progress_callback(_progress, _size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -319,9 +325,6 @@ size_t UpdateClass::writeStream(Stream &data) {
|
||||
_reset();
|
||||
return 0;
|
||||
}
|
||||
if (_progress_callback) {
|
||||
_progress_callback(0, _size);
|
||||
}
|
||||
|
||||
if(_ledPin != -1) {
|
||||
pinMode(_ledPin, OUTPUT);
|
||||
@ -352,12 +355,6 @@ size_t UpdateClass::writeStream(Stream &data) {
|
||||
if((_bufferLen == remaining() || _bufferLen == SPI_FLASH_SEC_SIZE) && !_writeBuffer())
|
||||
return written;
|
||||
written += toRead;
|
||||
if(_progress_callback) {
|
||||
_progress_callback(_progress, _size);
|
||||
}
|
||||
}
|
||||
if(_progress_callback) {
|
||||
_progress_callback(_size, _size);
|
||||
}
|
||||
return written;
|
||||
}
|
||||
@ -366,4 +363,8 @@ void UpdateClass::printError(Stream &out){
|
||||
out.println(_err2str(_error));
|
||||
}
|
||||
|
||||
const char * UpdateClass::errorString(){
|
||||
return _err2str(_error);
|
||||
}
|
||||
|
||||
UpdateClass Update;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user