Arduino Core 3 (#407)
* Add and remove libs and components for Arduino Core 3 * Arduino Core 3 * Add back Solo1 * Change ESP32-S3 to 4MB build * Update README.md * Fix retain and number of retries * Fix rolling log * Fix defaults * Fix BleScanner on Solo1 * Export settings * Import settings * Fix HA Battery voltage * Change submodule * Update espMqttClient and AsyncTCP * Webserial and MQTT/Network reconnecting * Update nuki_ble --------- Co-authored-by: iranl <iranl@github.com>
This commit is contained in:
35
lib/AsyncTCP/.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
35
lib/AsyncTCP/.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[BUG]"
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Please make sure to go through the recommendations before opening a bug report:**
|
||||
|
||||
[https://github.com/mathieucarbou/AsyncTCP?tab=readme-ov-file#important-recommendations](https://github.com/mathieucarbou/AsyncTCP?tab=readme-ov-file#important-recommendations)
|
||||
|
||||
**Description**
|
||||
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**Board**
|
||||
|
||||
esp32dev, esp32s3, etc
|
||||
|
||||
**Ethernet adapter used ?**
|
||||
|
||||
If yes, please specify which one
|
||||
|
||||
**Stack trace**
|
||||
|
||||
Please provide the stack trace here taken with `monitor_filters = esp32_exception_decoder`.
|
||||
**Any issue opened with a non readable stack trace will be ignored because not helpful at all.**
|
||||
|
||||
As an alternative, you can use [https://maximeborges.github.io/esp-stacktrace-decoder/](https://maximeborges.github.io/esp-stacktrace-decoder/).
|
||||
|
||||
**Additional notes**
|
||||
|
||||
Add any other context about the problem here.
|
||||
10
lib/AsyncTCP/.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
10
lib/AsyncTCP/.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: Question
|
||||
about: Describe your question
|
||||
title: "[Q]"
|
||||
labels: question
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
|
||||
10
lib/AsyncTCP/.github/dependabot.yml
vendored
Normal file
10
lib/AsyncTCP/.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# Set update schedule for GitHub Actions
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
# Check for updates to GitHub Actions every week
|
||||
interval: "weekly"
|
||||
@@ -1,36 +0,0 @@
|
||||
#!/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
|
||||
220
lib/AsyncTCP/.github/scripts/install-arduino-ide.sh
vendored
220
lib/AsyncTCP/.github/scripts/install-arduino-ide.sh
vendored
@@ -1,220 +0,0 @@
|
||||
#!/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"
|
||||
elif [ "$OS_IS_WINDOWS" == "1" ]; then
|
||||
export ARDUINO_IDE_PATH="$HOME/arduino_ide"
|
||||
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
|
||||
}
|
||||
133
lib/AsyncTCP/.github/scripts/install-platformio.sh
vendored
133
lib/AsyncTCP/.github/scripts/install-platformio.sh
vendored
@@ -1,133 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "Installing Python Wheel ..."
|
||||
pip install wheel > /dev/null 2>&1
|
||||
|
||||
echo "Installing PlatformIO ..."
|
||||
pip install -U platformio > /dev/null 2>&1
|
||||
|
||||
echo "PlatformIO 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 -l '.' --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
|
||||
}
|
||||
64
lib/AsyncTCP/.github/scripts/on-push.sh
vendored
64
lib/AsyncTCP/.github/scripts/on-push.sh
vendored
@@ -1,64 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ ! -z "$TRAVIS_BUILD_DIR" ]; then
|
||||
export GITHUB_WORKSPACE="$TRAVIS_BUILD_DIR"
|
||||
export GITHUB_REPOSITORY="$TRAVIS_REPO_SLUG"
|
||||
elif [ -z "$GITHUB_WORKSPACE" ]; then
|
||||
export GITHUB_WORKSPACE="$PWD"
|
||||
export GITHUB_REPOSITORY="me-no-dev/AsyncTCP"
|
||||
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
|
||||
|
||||
if [ "$BUILD_PIO" -eq 0 ]; then
|
||||
# ArduinoIDE Test
|
||||
source ./.github/scripts/install-arduino-ide.sh
|
||||
source ./.github/scripts/install-arduino-core-esp32.sh
|
||||
|
||||
echo "Installing AsyncTCP ..."
|
||||
cp -rf "$GITHUB_WORKSPACE" "$ARDUINO_USR_PATH/libraries/AsyncTCP"
|
||||
|
||||
FQBN="espressif:esp32:esp32:PSRAM=enabled,PartitionScheme=huge_app"
|
||||
build_sketches "$FQBN" "$GITHUB_WORKSPACE/examples"
|
||||
if [ ! "$OS_IS_WINDOWS" == "1" ]; then
|
||||
echo "Installing ESPAsyncWebServer ..."
|
||||
git clone https://github.com/me-no-dev/ESPAsyncWebServer "$ARDUINO_USR_PATH/libraries/ESPAsyncWebServer" > /dev/null 2>&1
|
||||
|
||||
echo "Installing ArduinoJson ..."
|
||||
git clone https://github.com/bblanchon/ArduinoJson "$ARDUINO_USR_PATH/libraries/ArduinoJson" > /dev/null 2>&1
|
||||
|
||||
build_sketches "$FQBN" "$ARDUINO_USR_PATH/libraries/ESPAsyncWebServer/examples"
|
||||
fi
|
||||
else
|
||||
# PlatformIO Test
|
||||
source ./.github/scripts/install-platformio.sh
|
||||
|
||||
echo "Installing AsyncTCP ..."
|
||||
python -m platformio lib --storage-dir "$GITHUB_WORKSPACE" install
|
||||
|
||||
BOARD="esp32dev"
|
||||
build_pio_sketches "$BOARD" "$GITHUB_WORKSPACE/examples"
|
||||
|
||||
if [[ "$OSTYPE" != "cygwin" ]] && [[ "$OSTYPE" != "msys" ]] && [[ "$OSTYPE" != "win32" ]]; then
|
||||
echo "Installing ESPAsyncWebServer ..."
|
||||
python -m platformio lib -g install https://github.com/me-no-dev/ESPAsyncWebServer.git > /dev/null 2>&1
|
||||
git clone https://github.com/me-no-dev/ESPAsyncWebServer "$HOME/ESPAsyncWebServer" > /dev/null 2>&1
|
||||
|
||||
echo "Installing ArduinoJson ..."
|
||||
python -m platformio lib -g install https://github.com/bblanchon/ArduinoJson.git > /dev/null 2>&1
|
||||
|
||||
build_pio_sketches "$BOARD" "$HOME/ESPAsyncWebServer/examples"
|
||||
fi
|
||||
fi
|
||||
52
lib/AsyncTCP/.github/workflows/push.yml
vendored
52
lib/AsyncTCP/.github/workflows/push.yml
vendored
@@ -2,31 +2,51 @@ name: Async TCP CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release/*
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
||||
build-arduino:
|
||||
name: Arduino on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: ${{ matrix.config }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macOS-latest]
|
||||
config: [arduino-cli.yaml, arduino-cli-dev.yaml]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Build Tests
|
||||
run: bash ./.github/scripts/on-push.sh 0 1
|
||||
- uses: actions/checkout@v4
|
||||
- uses: arduino/setup-arduino-cli@v1
|
||||
- name: Download board
|
||||
run: |
|
||||
arduino-cli --config-file ${{ matrix.config }} core update-index
|
||||
arduino-cli --config-file ${{ matrix.config }} board listall
|
||||
arduino-cli --config-file ${{ matrix.config }} core install esp32:esp32
|
||||
- name: Compile Sketch
|
||||
run: arduino-cli --config-file ${{ matrix.config }} --library ./src/ compile --fqbn esp32:esp32:esp32 ./examples/ClientServer/Client/Client.ino
|
||||
- name: Compile Sketch with IPv6
|
||||
env:
|
||||
LWIP_IPV6: true
|
||||
run: arduino-cli --config-file ${{ matrix.config }} --library ./src/ compile --fqbn esp32:esp32:esp32 ./examples/ClientServer/Client/Client.ino
|
||||
|
||||
build-pio:
|
||||
name: PlatformIO on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: ${{ matrix.board }} ${{ matrix.env }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macOS-latest]
|
||||
board: [esp32dev, esp32-s3-devkitc-1]
|
||||
env: [arduino-2, arduino-3]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Build Tests
|
||||
run: bash ./.github/scripts/on-push.sh 1 1
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.platformio
|
||||
~/.cache/pip
|
||||
key: ${{ matrix.env }}
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- run: pip install platformio
|
||||
- run: sed -i -e 's/esp32dev/${{ matrix.board }}/g' platformio.ini
|
||||
- run: pio run -e ${{ matrix.env }}
|
||||
|
||||
6
lib/AsyncTCP/.gitignore
vendored
6
lib/AsyncTCP/.gitignore
vendored
@@ -1,2 +1,6 @@
|
||||
|
||||
.DS_Store
|
||||
.lh
|
||||
/.pio
|
||||
/.vscode/*
|
||||
!/.vscode/settings.json
|
||||
/logs
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
sudo: false
|
||||
language: python
|
||||
os:
|
||||
- linux
|
||||
|
||||
git:
|
||||
depth: false
|
||||
|
||||
stages:
|
||||
- build
|
||||
|
||||
jobs:
|
||||
include:
|
||||
|
||||
- name: "Arduino Build"
|
||||
if: tag IS blank AND (type = pull_request OR (type = push AND branch = master))
|
||||
stage: build
|
||||
script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh
|
||||
|
||||
- name: "PlatformIO Build"
|
||||
if: tag IS blank AND (type = pull_request OR (type = push AND branch = master))
|
||||
stage: build
|
||||
script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 1 1
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: change
|
||||
on_failure: change
|
||||
webhooks:
|
||||
urls:
|
||||
- https://webhooks.gitter.im/e/60e65d0c78ea0a920347
|
||||
on_success: change # options: [always|never|change] default: always
|
||||
on_failure: always # options: [always|never|change] default: always
|
||||
on_start: false # default: false
|
||||
@@ -1,13 +1,52 @@
|
||||
# AsyncTCP
|
||||
[](https://travis-ci.org/me-no-dev/AsyncTCP)  [](https://www.codacy.com/manual/me-no-dev/AsyncTCP?utm_source=github.com&utm_medium=referral&utm_content=me-no-dev/AsyncTCP&utm_campaign=Badge_Grade)
|
||||
# AsyncTCP
|
||||
|
||||
[](https://opensource.org/license/lgpl-3-0/)
|
||||
[](https://github.com/mathieucarbou/AsyncTCP/actions/workflows/push.yml)
|
||||
[](https://registry.platformio.org/libraries/mathieucarbou/Async%20TCP)
|
||||
|
||||
A fork of the [AsyncTCP](https://github.com/me-no-dev/AsyncTCP) library by [@me-no-dev](https://github.com/me-no-dev) for [ESPHome](https://esphome.io).
|
||||
|
||||
### Async TCP Library for ESP32 Arduino
|
||||
|
||||
[](https://gitter.im/me-no-dev/ESPAsyncWebServer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
This is a fully asynchronous TCP library, aimed at enabling trouble-free, multi-connection network environment for Espressif's ESP32 MCUs.
|
||||
|
||||
This library is the base for [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer)
|
||||
This library is the base for [ESPAsyncWebServer](https://github.com/mathieucarbou/ESPAsyncWebServer)
|
||||
|
||||
## AsyncClient and AsyncServer
|
||||
|
||||
The base classes on which everything else is built. They expose all possible scenarios, but are really raw and require more skills to use.
|
||||
|
||||
## Changes in this fork
|
||||
|
||||
- All improvements from [ESPHome fork](https://github.com/esphome/AsyncTCP)
|
||||
- Reverted back `library.properties` for Arduino IDE users
|
||||
- Arduino 3 / ESP-IDF 5 compatibility
|
||||
- Changed lib name: `AsyncTCP` -> `Async TCP`
|
||||
- Point to `mathieucarbou/Async TCP @ ^3.1.4`
|
||||
- IPv6 support
|
||||
|
||||
## Important recommendations
|
||||
|
||||
Most of the crashes are caused by improper configuration of the library for the project.
|
||||
Here are some recommendations to avoid them.
|
||||
|
||||
1. Set the running core to be on the same core of your application (usually core 1) `-D CONFIG_ASYNC_TCP_RUNNING_CORE=1`
|
||||
2. Set the stack size appropriately with `-D CONFIG_ASYNC_TCP_STACK_SIZE=16384`.
|
||||
The default value of `16384` might be too much for your project.
|
||||
You can look at the [MycilaTaskMonitor](https://oss.carbou.me/MycilaTaskMonitor) project to monitor the stack usage.
|
||||
3. You can change **if you know what you are doing** the task priority with `-D CONFIG_ASYNC_TCP_PRIORITY=10`.
|
||||
Default is `10`.
|
||||
4. You can increase the queue size with `-D CONFIG_ASYNC_TCP_QUEUE_SIZE=128`.
|
||||
Default is `64`.
|
||||
5. You can decrease the maximum ack time `-D CONFIG_ASYNC_TCP_MAX_ACK_TIME=3000`.
|
||||
Default is `5000`.
|
||||
|
||||
I personally use the following configuration in my projects:
|
||||
|
||||
```c++
|
||||
-D CONFIG_ASYNC_TCP_MAX_ACK_TIME=3000
|
||||
-D CONFIG_ASYNC_TCP_PRIORITY=10
|
||||
-D CONFIG_ASYNC_TCP_QUEUE_SIZE=128
|
||||
-D CONFIG_ASYNC_TCP_RUNNING_CORE=1
|
||||
-D CONFIG_ASYNC_TCP_STACK_SIZE=4096
|
||||
```
|
||||
|
||||
25
lib/AsyncTCP/arduino-cli-dev.yaml
Normal file
25
lib/AsyncTCP/arduino-cli-dev.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
board_manager:
|
||||
additional_urls:
|
||||
- https://espressif.github.io/arduino-esp32/package_esp32_dev_index.json
|
||||
directories:
|
||||
builtin.libraries: ./src/
|
||||
build_cache:
|
||||
compilations_before_purge: 10
|
||||
ttl: 720h0m0s
|
||||
daemon:
|
||||
port: "50051"
|
||||
library:
|
||||
enable_unsafe_install: false
|
||||
logging:
|
||||
file: ""
|
||||
format: text
|
||||
level: info
|
||||
metrics:
|
||||
addr: :9090
|
||||
enabled: true
|
||||
output:
|
||||
no_color: false
|
||||
sketch:
|
||||
always_export_binaries: false
|
||||
updater:
|
||||
enable_notification: true
|
||||
25
lib/AsyncTCP/arduino-cli.yaml
Normal file
25
lib/AsyncTCP/arduino-cli.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
board_manager:
|
||||
additional_urls:
|
||||
- https://espressif.github.io/arduino-esp32/package_esp32_index.json
|
||||
directories:
|
||||
builtin.libraries: ./src/
|
||||
build_cache:
|
||||
compilations_before_purge: 10
|
||||
ttl: 720h0m0s
|
||||
daemon:
|
||||
port: "50051"
|
||||
library:
|
||||
enable_unsafe_install: false
|
||||
logging:
|
||||
file: ""
|
||||
format: text
|
||||
level: info
|
||||
metrics:
|
||||
addr: :9090
|
||||
enabled: true
|
||||
output:
|
||||
no_color: false
|
||||
sketch:
|
||||
always_export_binaries: false
|
||||
updater:
|
||||
enable_notification: true
|
||||
42
lib/AsyncTCP/examples/ClientServer/Client/Client.ino
Normal file
42
lib/AsyncTCP/examples/ClientServer/Client/Client.ino
Normal file
@@ -0,0 +1,42 @@
|
||||
#include <AsyncTCP.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
static void replyToServer(void* arg) {
|
||||
AsyncClient* client = reinterpret_cast<AsyncClient*>(arg);
|
||||
|
||||
// send reply
|
||||
if (client->space() > 32 && client->canSend()) {
|
||||
char message[32];
|
||||
client->add(message, strlen(message));
|
||||
client->send();
|
||||
}
|
||||
}
|
||||
|
||||
/* event callbacks */
|
||||
static void handleData(void* arg, AsyncClient* client, void *data, size_t len) {
|
||||
Serial.printf("\n data received from %s \n", client->remoteIP().toString().c_str());
|
||||
Serial.write((uint8_t*)data, len);
|
||||
|
||||
}
|
||||
|
||||
void onConnect(void* arg, AsyncClient* client) {
|
||||
Serial.printf("\n client has been connected to %s on port %d \n", SERVER_HOST_NAME, TCP_PORT);
|
||||
replyToServer(client);
|
||||
}
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(20);
|
||||
|
||||
AsyncClient* client = new AsyncClient;
|
||||
client->onData(&handleData, client);
|
||||
client->onConnect(&onConnect, client);
|
||||
client->connect(SERVER_HOST_NAME, TCP_PORT);
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
}
|
||||
23
lib/AsyncTCP/examples/ClientServer/Client/config.h
Normal file
23
lib/AsyncTCP/examples/ClientServer/Client/config.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
/*
|
||||
* This example demonstrate how to use asynchronous client & server APIs
|
||||
* in order to establish tcp socket connections in client server manner.
|
||||
* server is running (on port 7050) on one ESP, acts as AP, and other clients running on
|
||||
* remaining ESPs acts as STAs. after connection establishment between server and clients
|
||||
* there is a simple message transfer in every 2s. clients connect to server via it's host name
|
||||
* (in this case 'esp_server') with help of DNS service running on server side.
|
||||
*
|
||||
* Note: default MSS for ESPAsyncTCP is 536 byte and defualt ACK timeout is 5s.
|
||||
*/
|
||||
|
||||
#define SSID "ESP-TEST"
|
||||
#define PASSWORD "123456789"
|
||||
|
||||
#define SERVER_HOST_NAME "esp_server"
|
||||
|
||||
#define TCP_PORT 7050
|
||||
#define DNS_PORT 53
|
||||
|
||||
#endif // CONFIG_H
|
||||
@@ -1,22 +1,38 @@
|
||||
{
|
||||
"name":"AsyncTCP",
|
||||
"description":"Asynchronous TCP Library for ESP32",
|
||||
"keywords":"async,tcp",
|
||||
"authors":
|
||||
{
|
||||
"name": "Hristo Gochkov",
|
||||
"maintainer": true
|
||||
},
|
||||
"repository":
|
||||
{
|
||||
"name": "Async TCP",
|
||||
"version": "3.1.4",
|
||||
"description": "Asynchronous TCP Library for ESP32",
|
||||
"keywords": "async,tcp",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/me-no-dev/AsyncTCP.git"
|
||||
"url": "https://github.com/mathieucarbou/AsyncTCP.git"
|
||||
},
|
||||
"version": "1.1.1",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Hristo Gochkov"
|
||||
},
|
||||
{
|
||||
"name": "Mathieu Carbou",
|
||||
"maintainer": true
|
||||
}
|
||||
],
|
||||
"license": "LGPL-3.0",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "espressif32",
|
||||
"platforms": [
|
||||
"espressif32",
|
||||
"libretiny"
|
||||
],
|
||||
"build": {
|
||||
"libCompatMode": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"export": {
|
||||
"include": [
|
||||
"examples",
|
||||
"src",
|
||||
"library.json",
|
||||
"library.properties",
|
||||
"LICENSE",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
name=AsyncTCP
|
||||
version=1.1.1
|
||||
name=Async TCP
|
||||
version=3.1.4
|
||||
author=Me-No-Dev
|
||||
maintainer=Me-No-Dev
|
||||
maintainer=Mathieu Carbou <mathieu.carbou@gmail.com>
|
||||
sentence=Async TCP Library for ESP32
|
||||
paragraph=Async TCP Library for ESP32
|
||||
category=Other
|
||||
url=https://github.com/me-no-dev/AsyncTCP
|
||||
url=https://github.com/mathieucarbou/AsyncTCP.git
|
||||
architectures=*
|
||||
|
||||
28
lib/AsyncTCP/platformio.ini
Normal file
28
lib/AsyncTCP/platformio.ini
Normal file
@@ -0,0 +1,28 @@
|
||||
[env]
|
||||
framework = arduino
|
||||
build_flags =
|
||||
-Wall -Wextra
|
||||
-D CONFIG_ARDUHAL_LOG_COLORS
|
||||
-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||
upload_protocol = esptool
|
||||
monitor_speed = 115200
|
||||
monitor_filters = esp32_exception_decoder, log2file
|
||||
|
||||
[platformio]
|
||||
lib_dir = .
|
||||
src_dir = examples/ClientServer/Client
|
||||
|
||||
[env:arduino]
|
||||
platform = espressif32
|
||||
board = esp32dev
|
||||
|
||||
[env:arduino-2]
|
||||
platform = espressif32@6.7.0
|
||||
board = esp32dev
|
||||
|
||||
[env:arduino-3]
|
||||
platform = espressif32
|
||||
platform_packages=
|
||||
platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.2
|
||||
platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.2/esp32-arduino-libs-3.0.2.zip
|
||||
board = esp32dev
|
||||
@@ -29,7 +29,9 @@ extern "C"{
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/err.h"
|
||||
}
|
||||
#if CONFIG_ASYNC_TCP_USE_WDT
|
||||
#include "esp_task_wdt.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TCP/IP Event Task
|
||||
@@ -44,7 +46,7 @@ typedef struct {
|
||||
void *arg;
|
||||
union {
|
||||
struct {
|
||||
void * pcb;
|
||||
tcp_pcb * pcb;
|
||||
int8_t err;
|
||||
} connected;
|
||||
struct {
|
||||
@@ -76,7 +78,7 @@ typedef struct {
|
||||
};
|
||||
} lwip_event_packet_t;
|
||||
|
||||
static xQueueHandle _async_queue;
|
||||
static QueueHandle_t _async_queue;
|
||||
static TaskHandle_t _async_service_task_handle = NULL;
|
||||
|
||||
|
||||
@@ -95,7 +97,7 @@ static uint32_t _closed_index = []() {
|
||||
|
||||
static inline bool _init_async_event_queue(){
|
||||
if(!_async_queue){
|
||||
_async_queue = xQueueCreate(32, sizeof(lwip_event_packet_t *));
|
||||
_async_queue = xQueueCreate(CONFIG_ASYNC_TCP_QUEUE_SIZE, sizeof(lwip_event_packet_t *));
|
||||
if(!_async_queue){
|
||||
return false;
|
||||
}
|
||||
@@ -213,12 +215,32 @@ static void _stop_async_task(){
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
static bool customTaskCreateUniversal(
|
||||
TaskFunction_t pxTaskCode,
|
||||
const char * const pcName,
|
||||
const uint32_t usStackDepth,
|
||||
void * const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
TaskHandle_t * const pxCreatedTask,
|
||||
const BaseType_t xCoreID) {
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
if(xCoreID >= 0 && xCoreID < 2) {
|
||||
return xTaskCreatePinnedToCore(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, xCoreID);
|
||||
} else {
|
||||
#endif
|
||||
return xTaskCreate(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask);
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool _start_async_task(){
|
||||
if(!_init_async_event_queue()){
|
||||
return false;
|
||||
}
|
||||
if(!_async_service_task_handle){
|
||||
xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 * 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE);
|
||||
customTaskCreateUniversal(_async_service_task, "async_tcp", CONFIG_ASYNC_TCP_STACK_SIZE, NULL, CONFIG_ASYNC_TCP_PRIORITY, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE);
|
||||
if(!_async_service_task_handle){
|
||||
return false;
|
||||
}
|
||||
@@ -555,12 +577,11 @@ AsyncClient::AsyncClient(tcp_pcb* pcb)
|
||||
, _pb_cb_arg(0)
|
||||
, _timeout_cb(0)
|
||||
, _timeout_cb_arg(0)
|
||||
, _pcb_busy(false)
|
||||
, _pcb_sent_at(0)
|
||||
, _ack_pcb(true)
|
||||
, _rx_last_packet(0)
|
||||
, _rx_since_timeout(0)
|
||||
, _ack_timeout(ASYNC_MAX_ACK_TIME)
|
||||
, _tx_last_packet(0)
|
||||
, _rx_timeout(0)
|
||||
, _rx_last_ack(0)
|
||||
, _ack_timeout(CONFIG_ASYNC_TCP_MAX_ACK_TIME)
|
||||
, _connect_port(0)
|
||||
, prev(NULL)
|
||||
, next(NULL)
|
||||
@@ -568,13 +589,15 @@ AsyncClient::AsyncClient(tcp_pcb* pcb)
|
||||
_pcb = pcb;
|
||||
_closed_slot = -1;
|
||||
if(_pcb){
|
||||
_allocate_closed_slot();
|
||||
_rx_last_packet = millis();
|
||||
tcp_arg(_pcb, this);
|
||||
tcp_recv(_pcb, &_tcp_recv);
|
||||
tcp_sent(_pcb, &_tcp_sent);
|
||||
tcp_err(_pcb, &_tcp_error);
|
||||
tcp_poll(_pcb, &_tcp_poll, 1);
|
||||
if(!_allocate_closed_slot()) {
|
||||
_close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -674,9 +697,9 @@ void AsyncClient::onPoll(AcConnectHandler cb, void* arg){
|
||||
* Main Public Methods
|
||||
* */
|
||||
|
||||
bool AsyncClient::connect(IPAddress ip, uint16_t port){
|
||||
bool AsyncClient::_connect(ip_addr_t addr, uint16_t port){
|
||||
if (_pcb){
|
||||
log_w("already connected, state %d", _pcb->state);
|
||||
log_d("already connected, state %d", _pcb->state);
|
||||
return false;
|
||||
}
|
||||
if(!_start_async_task()){
|
||||
@@ -684,11 +707,12 @@ bool AsyncClient::connect(IPAddress ip, uint16_t port){
|
||||
return false;
|
||||
}
|
||||
|
||||
ip_addr_t addr;
|
||||
addr.type = IPADDR_TYPE_V4;
|
||||
addr.u_addr.ip4.addr = ip;
|
||||
if(!_allocate_closed_slot()) {
|
||||
log_e("failed to allocate: closed slot full");
|
||||
return false;
|
||||
}
|
||||
|
||||
tcp_pcb* pcb = tcp_new_ip_type(IPADDR_TYPE_V4);
|
||||
tcp_pcb* pcb = tcp_new_ip_type(addr.type);
|
||||
if (!pcb){
|
||||
log_e("pcb == NULL");
|
||||
return false;
|
||||
@@ -699,27 +723,59 @@ bool AsyncClient::connect(IPAddress ip, uint16_t port){
|
||||
tcp_recv(pcb, &_tcp_recv);
|
||||
tcp_sent(pcb, &_tcp_sent);
|
||||
tcp_poll(pcb, &_tcp_poll, 1);
|
||||
//_tcp_connect(pcb, &addr, port,(tcp_connected_fn)&_s_connected);
|
||||
_tcp_connect(pcb, _closed_slot, &addr, port,(tcp_connected_fn)&_tcp_connected);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AsyncClient::connect(const IPAddress& ip, uint16_t port){
|
||||
ip_addr_t addr;
|
||||
#if ESP_IDF_VERSION_MAJOR < 5
|
||||
addr.u_addr.ip4.addr = ip;
|
||||
addr.type = IPADDR_TYPE_V4;
|
||||
#else
|
||||
ip.to_ip_addr_t(&addr);
|
||||
#endif
|
||||
|
||||
return _connect(addr, port);
|
||||
}
|
||||
|
||||
#if LWIP_IPV6 && ESP_IDF_VERSION_MAJOR < 5
|
||||
bool AsyncClient::connect(const IPv6Address& ip, uint16_t port){
|
||||
ip_addr_t addr;
|
||||
addr.type = IPADDR_TYPE_V6;
|
||||
memcpy(addr.u_addr.ip6.addr, static_cast<const uint32_t*>(ip), sizeof(uint32_t) * 4);
|
||||
|
||||
return _connect(addr, port);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool AsyncClient::connect(const char* host, uint16_t port){
|
||||
ip_addr_t addr;
|
||||
|
||||
|
||||
if(!_start_async_task()){
|
||||
log_e("failed to start task");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
err_t err = dns_gethostbyname(host, &addr, (dns_found_callback)&_tcp_dns_found, this);
|
||||
if(err == ERR_OK) {
|
||||
#if ESP_IDF_VERSION_MAJOR < 5
|
||||
#if LWIP_IPV6
|
||||
if(addr.type == IPADDR_TYPE_V6) {
|
||||
return connect(IPv6Address(addr.u_addr.ip6.addr), port);
|
||||
}
|
||||
return connect(IPAddress(addr.u_addr.ip4.addr), port);
|
||||
#else
|
||||
return connect(IPAddress(addr.addr), port);
|
||||
#endif
|
||||
#else
|
||||
return _connect(addr, port);
|
||||
#endif
|
||||
} else if(err == ERR_INPROGRESS) {
|
||||
_connect_port = port;
|
||||
return true;
|
||||
}
|
||||
log_e("error: %d", err);
|
||||
log_d("error: %d", err);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -763,13 +819,12 @@ size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) {
|
||||
}
|
||||
|
||||
bool AsyncClient::send(){
|
||||
int8_t err = ERR_OK;
|
||||
err = _tcp_output(_pcb, _closed_slot);
|
||||
if(err == ERR_OK){
|
||||
_pcb_busy = true;
|
||||
_pcb_sent_at = millis();
|
||||
auto backup = _tx_last_packet;
|
||||
_tx_last_packet = millis();
|
||||
if (_tcp_output(_pcb, _closed_slot) == ERR_OK) {
|
||||
return true;
|
||||
}
|
||||
_tx_last_packet = backup;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -799,7 +854,6 @@ int8_t AsyncClient::_close(){
|
||||
//ets_printf("X: 0x%08x\n", (uint32_t)this);
|
||||
int8_t err = ERR_OK;
|
||||
if(_pcb) {
|
||||
//log_i("");
|
||||
tcp_arg(_pcb, NULL);
|
||||
tcp_sent(_pcb, NULL);
|
||||
tcp_recv(_pcb, NULL);
|
||||
@@ -810,6 +864,7 @@ int8_t AsyncClient::_close(){
|
||||
if(err != ERR_OK) {
|
||||
err = abort();
|
||||
}
|
||||
_free_closed_slot();
|
||||
_pcb = NULL;
|
||||
if(_discard_cb) {
|
||||
_discard_cb(_discard_cb_arg, this);
|
||||
@@ -818,7 +873,10 @@ int8_t AsyncClient::_close(){
|
||||
return err;
|
||||
}
|
||||
|
||||
void AsyncClient::_allocate_closed_slot(){
|
||||
bool AsyncClient::_allocate_closed_slot(){
|
||||
if (_closed_slot != -1) {
|
||||
return true;
|
||||
}
|
||||
xSemaphoreTake(_slots_lock, portMAX_DELAY);
|
||||
uint32_t closed_slot_min_index = 0;
|
||||
for (int i = 0; i < _number_of_closed_slots; ++ i) {
|
||||
@@ -831,28 +889,27 @@ void AsyncClient::_allocate_closed_slot(){
|
||||
_closed_slots[_closed_slot] = 0;
|
||||
}
|
||||
xSemaphoreGive(_slots_lock);
|
||||
return (_closed_slot != -1);
|
||||
}
|
||||
|
||||
void AsyncClient::_free_closed_slot(){
|
||||
xSemaphoreTake(_slots_lock, portMAX_DELAY);
|
||||
if (_closed_slot != -1) {
|
||||
_closed_slots[_closed_slot] = _closed_index;
|
||||
_closed_slot = -1;
|
||||
++ _closed_index;
|
||||
}
|
||||
xSemaphoreGive(_slots_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Private Callbacks
|
||||
* */
|
||||
|
||||
int8_t AsyncClient::_connected(void* pcb, int8_t err){
|
||||
int8_t AsyncClient::_connected(tcp_pcb* pcb, int8_t err){
|
||||
_pcb = reinterpret_cast<tcp_pcb*>(pcb);
|
||||
if(_pcb){
|
||||
_rx_last_packet = millis();
|
||||
_pcb_busy = false;
|
||||
// tcp_recv(_pcb, &_tcp_recv);
|
||||
// tcp_sent(_pcb, &_tcp_sent);
|
||||
// tcp_poll(_pcb, &_tcp_poll, 1);
|
||||
}
|
||||
if(_connect_cb) {
|
||||
_connect_cb(_connect_cb_arg, this);
|
||||
@@ -869,6 +926,7 @@ void AsyncClient::_error(int8_t err) {
|
||||
tcp_err(_pcb, NULL);
|
||||
tcp_poll(_pcb, NULL, 0);
|
||||
}
|
||||
_free_closed_slot();
|
||||
_pcb = NULL;
|
||||
}
|
||||
if(_error_cb) {
|
||||
@@ -882,7 +940,7 @@ void AsyncClient::_error(int8_t err) {
|
||||
//In LwIP Thread
|
||||
int8_t AsyncClient::_lwip_fin(tcp_pcb* pcb, int8_t err) {
|
||||
if(!_pcb || pcb != _pcb){
|
||||
log_e("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb);
|
||||
log_d("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb);
|
||||
return ERR_OK;
|
||||
}
|
||||
tcp_arg(_pcb, NULL);
|
||||
@@ -910,23 +968,27 @@ int8_t AsyncClient::_fin(tcp_pcb* pcb, int8_t err) {
|
||||
}
|
||||
|
||||
int8_t AsyncClient::_sent(tcp_pcb* pcb, uint16_t len) {
|
||||
_rx_last_packet = millis();
|
||||
//log_i("%u", len);
|
||||
_pcb_busy = false;
|
||||
_rx_last_ack = _rx_last_packet = millis();
|
||||
if(_sent_cb) {
|
||||
_sent_cb(_sent_cb_arg, this, len, (millis() - _pcb_sent_at));
|
||||
_sent_cb(_sent_cb_arg, this, len, (_rx_last_packet - _tx_last_packet));
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) {
|
||||
while(pb != NULL) {
|
||||
if(!_pcb || pcb != _pcb){
|
||||
log_d("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb);
|
||||
return ERR_OK;
|
||||
}
|
||||
size_t total = 0;
|
||||
while((pb != NULL) && (ERR_OK == err)) {
|
||||
_rx_last_packet = millis();
|
||||
//we should not ack before we assimilate the data
|
||||
_ack_pcb = true;
|
||||
pbuf *b = pb;
|
||||
pb = b->next;
|
||||
b->next = NULL;
|
||||
total += b->len;
|
||||
if(_pb_cb){
|
||||
_pb_cb(_pb_cb_arg, this, b);
|
||||
} else {
|
||||
@@ -935,38 +997,39 @@ int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) {
|
||||
}
|
||||
if(!_ack_pcb) {
|
||||
_rx_ack_len += b->len;
|
||||
} else if(_pcb) {
|
||||
_tcp_recved(_pcb, _closed_slot, b->len);
|
||||
}
|
||||
pbuf_free(b);
|
||||
}
|
||||
pbuf_free(b);
|
||||
}
|
||||
return ERR_OK;
|
||||
return _tcp_recved(pcb, _closed_slot, total);
|
||||
}
|
||||
|
||||
int8_t AsyncClient::_poll(tcp_pcb* pcb){
|
||||
if(!_pcb){
|
||||
log_w("pcb is NULL");
|
||||
log_d("pcb is NULL");
|
||||
return ERR_OK;
|
||||
}
|
||||
if(pcb != _pcb){
|
||||
log_e("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb);
|
||||
log_d("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
uint32_t now = millis();
|
||||
|
||||
// ACK Timeout
|
||||
if(_pcb_busy && _ack_timeout && (now - _pcb_sent_at) >= _ack_timeout){
|
||||
_pcb_busy = false;
|
||||
log_w("ack timeout %d", pcb->state);
|
||||
if(_timeout_cb)
|
||||
_timeout_cb(_timeout_cb_arg, this, (now - _pcb_sent_at));
|
||||
return ERR_OK;
|
||||
if(_ack_timeout){
|
||||
const uint32_t one_day = 86400000;
|
||||
bool last_tx_is_after_last_ack = (_rx_last_ack - _tx_last_packet + one_day) < one_day;
|
||||
if(last_tx_is_after_last_ack && (now - _tx_last_packet) >= _ack_timeout) {
|
||||
log_d("ack timeout %d", pcb->state);
|
||||
if(_timeout_cb)
|
||||
_timeout_cb(_timeout_cb_arg, this, (now - _tx_last_packet));
|
||||
return ERR_OK;
|
||||
}
|
||||
}
|
||||
// RX Timeout
|
||||
if(_rx_since_timeout && (now - _rx_last_packet) >= (_rx_since_timeout * 1000)){
|
||||
log_w("rx timeout %d", pcb->state);
|
||||
if(_rx_timeout && (now - _rx_last_packet) >= (_rx_timeout * 1000)) {
|
||||
log_d("rx timeout %d", pcb->state);
|
||||
_close();
|
||||
return ERR_OK;
|
||||
}
|
||||
@@ -978,8 +1041,19 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){
|
||||
}
|
||||
|
||||
void AsyncClient::_dns_found(struct ip_addr *ipaddr){
|
||||
if(ipaddr && ipaddr->u_addr.ip4.addr){
|
||||
connect(IPAddress(ipaddr->u_addr.ip4.addr), _connect_port);
|
||||
#if ESP_IDF_VERSION_MAJOR < 5
|
||||
if(ipaddr && IP_IS_V4(ipaddr)){
|
||||
connect(IPAddress(ip_addr_get_ip4_u32(ipaddr)), _connect_port);
|
||||
#if LWIP_IPV6
|
||||
} else if(ipaddr && ipaddr->u_addr.ip6.addr){
|
||||
connect(IPv6Address(ipaddr->u_addr.ip6.addr), _connect_port);
|
||||
#endif
|
||||
#else
|
||||
if(ipaddr) {
|
||||
IPAddress ip;
|
||||
ip.from_ip_addr_t(ipaddr);
|
||||
connect(ip, _connect_port);
|
||||
#endif
|
||||
} else {
|
||||
if(_error_cb) {
|
||||
_error_cb(_error_cb_arg, this, -55);
|
||||
@@ -1017,18 +1091,21 @@ size_t AsyncClient::write(const char* data) {
|
||||
|
||||
size_t AsyncClient::write(const char* data, size_t size, uint8_t apiflags) {
|
||||
size_t will_send = add(data, size, apiflags);
|
||||
if(!will_send || !send()) {
|
||||
if(!will_send) {
|
||||
return 0;
|
||||
}
|
||||
while (connected() && !send()) {
|
||||
taskYIELD();
|
||||
}
|
||||
return will_send;
|
||||
}
|
||||
|
||||
void AsyncClient::setRxTimeout(uint32_t timeout){
|
||||
_rx_since_timeout = timeout;
|
||||
_rx_timeout = timeout;
|
||||
}
|
||||
|
||||
uint32_t AsyncClient::getRxTimeout(){
|
||||
return _rx_since_timeout;
|
||||
return _rx_timeout;
|
||||
}
|
||||
|
||||
uint32_t AsyncClient::getAckTimeout(){
|
||||
@@ -1057,6 +1134,18 @@ bool AsyncClient::getNoDelay(){
|
||||
return tcp_nagle_disabled(_pcb);
|
||||
}
|
||||
|
||||
void AsyncClient::setKeepAlive(uint32_t ms, uint8_t cnt){
|
||||
if(ms!=0) {
|
||||
_pcb->so_options |= SOF_KEEPALIVE; //Turn on TCP Keepalive for the given pcb
|
||||
// Set the time between keepalive messages in milli-seconds
|
||||
_pcb->keep_idle = ms;
|
||||
_pcb->keep_intvl = ms;
|
||||
_pcb->keep_cnt = cnt; //The number of unanswered probes required to force closure of the socket
|
||||
} else {
|
||||
_pcb->so_options &= ~SOF_KEEPALIVE; //Turn off TCP Keepalive for the given pcb
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t AsyncClient::getMss(){
|
||||
if(!_pcb) {
|
||||
return 0;
|
||||
@@ -1068,9 +1157,60 @@ uint32_t AsyncClient::getRemoteAddress() {
|
||||
if(!_pcb) {
|
||||
return 0;
|
||||
}
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
return _pcb->remote_ip.u_addr.ip4.addr;
|
||||
#else
|
||||
return _pcb->remote_ip.addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
ip6_addr_t AsyncClient::getRemoteAddress6() {
|
||||
if(!_pcb) {
|
||||
ip6_addr_t nulladdr;
|
||||
ip6_addr_set_zero(&nulladdr);
|
||||
return nulladdr;
|
||||
}
|
||||
return _pcb->remote_ip.u_addr.ip6;
|
||||
}
|
||||
|
||||
ip6_addr_t AsyncClient::getLocalAddress6() {
|
||||
if(!_pcb) {
|
||||
ip6_addr_t nulladdr;
|
||||
ip6_addr_set_zero(&nulladdr);
|
||||
return nulladdr;
|
||||
}
|
||||
return _pcb->local_ip.u_addr.ip6;
|
||||
}
|
||||
#if ESP_IDF_VERSION_MAJOR < 5
|
||||
IPv6Address AsyncClient::remoteIP6() {
|
||||
return IPv6Address(getRemoteAddress6().addr);
|
||||
}
|
||||
|
||||
IPv6Address AsyncClient::localIP6() {
|
||||
return IPv6Address(getLocalAddress6().addr);
|
||||
}
|
||||
#else
|
||||
IPAddress AsyncClient::remoteIP6() {
|
||||
if (!_pcb) {
|
||||
return IPAddress(IPType::IPv6);
|
||||
}
|
||||
IPAddress ip;
|
||||
ip.from_ip_addr_t(&(_pcb->remote_ip));
|
||||
return ip;
|
||||
}
|
||||
|
||||
IPAddress AsyncClient::localIP6() {
|
||||
if (!_pcb) {
|
||||
return IPAddress(IPType::IPv6);
|
||||
}
|
||||
IPAddress ip;
|
||||
ip.from_ip_addr_t(&(_pcb->local_ip));
|
||||
return ip;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uint16_t AsyncClient::getRemotePort() {
|
||||
if(!_pcb) {
|
||||
return 0;
|
||||
@@ -1082,7 +1222,11 @@ uint32_t AsyncClient::getLocalAddress() {
|
||||
if(!_pcb) {
|
||||
return 0;
|
||||
}
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
return _pcb->local_ip.u_addr.ip4.addr;
|
||||
#else
|
||||
return _pcb->local_ip.addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t AsyncClient::getLocalPort() {
|
||||
@@ -1093,7 +1237,16 @@ uint16_t AsyncClient::getLocalPort() {
|
||||
}
|
||||
|
||||
IPAddress AsyncClient::remoteIP() {
|
||||
#if ESP_IDF_VERSION_MAJOR < 5
|
||||
return IPAddress(getRemoteAddress());
|
||||
#else
|
||||
if (!_pcb) {
|
||||
return IPAddress();
|
||||
}
|
||||
IPAddress ip;
|
||||
ip.from_ip_addr_t(&(_pcb->remote_ip));
|
||||
return ip;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t AsyncClient::remotePort() {
|
||||
@@ -1101,9 +1254,19 @@ uint16_t AsyncClient::remotePort() {
|
||||
}
|
||||
|
||||
IPAddress AsyncClient::localIP() {
|
||||
#if ESP_IDF_VERSION_MAJOR < 5
|
||||
return IPAddress(getLocalAddress());
|
||||
#else
|
||||
if (!_pcb) {
|
||||
return IPAddress();
|
||||
}
|
||||
IPAddress ip;
|
||||
ip.from_ip_addr_t(&(_pcb->local_ip));
|
||||
return ip;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
uint16_t AsyncClient::localPort() {
|
||||
return getLocalPort();
|
||||
}
|
||||
@@ -1226,7 +1389,7 @@ void AsyncClient::_s_error(void * arg, int8_t err) {
|
||||
reinterpret_cast<AsyncClient*>(arg)->_error(err);
|
||||
}
|
||||
|
||||
int8_t AsyncClient::_s_connected(void * arg, void * pcb, int8_t err){
|
||||
int8_t AsyncClient::_s_connected(void * arg, struct tcp_pcb * pcb, int8_t err){
|
||||
return reinterpret_cast<AsyncClient*>(arg)->_connected(pcb, err);
|
||||
}
|
||||
|
||||
@@ -1236,6 +1399,13 @@ int8_t AsyncClient::_s_connected(void * arg, void * pcb, int8_t err){
|
||||
|
||||
AsyncServer::AsyncServer(IPAddress addr, uint16_t port)
|
||||
: _port(port)
|
||||
#if ESP_IDF_VERSION_MAJOR < 5
|
||||
, _bind4(true)
|
||||
, _bind6(false)
|
||||
#else
|
||||
, _bind4(addr.type() != IPType::IPv6)
|
||||
, _bind6(addr.type() == IPType::IPv6)
|
||||
#endif
|
||||
, _addr(addr)
|
||||
, _noDelay(false)
|
||||
, _pcb(0)
|
||||
@@ -1243,9 +1413,27 @@ AsyncServer::AsyncServer(IPAddress addr, uint16_t port)
|
||||
, _connect_cb_arg(0)
|
||||
{}
|
||||
|
||||
#if ESP_IDF_VERSION_MAJOR < 5
|
||||
AsyncServer::AsyncServer(IPv6Address addr, uint16_t port)
|
||||
: _port(port)
|
||||
, _bind4(false)
|
||||
, _bind6(true)
|
||||
, _addr6(addr)
|
||||
, _noDelay(false)
|
||||
, _pcb(0)
|
||||
, _connect_cb(0)
|
||||
, _connect_cb_arg(0)
|
||||
{}
|
||||
#endif
|
||||
|
||||
AsyncServer::AsyncServer(uint16_t port)
|
||||
: _port(port)
|
||||
, _bind4(true)
|
||||
, _bind6(false)
|
||||
, _addr((uint32_t) IPADDR_ANY)
|
||||
#if ESP_IDF_VERSION_MAJOR < 5
|
||||
, _addr6()
|
||||
#endif
|
||||
, _noDelay(false)
|
||||
, _pcb(0)
|
||||
, _connect_cb(0)
|
||||
@@ -1271,15 +1459,24 @@ void AsyncServer::begin(){
|
||||
return;
|
||||
}
|
||||
int8_t err;
|
||||
_pcb = tcp_new_ip_type(IPADDR_TYPE_V4);
|
||||
_pcb = tcp_new_ip_type(_bind4 && _bind6 ? IPADDR_TYPE_ANY : (_bind6 ? IPADDR_TYPE_V6 : IPADDR_TYPE_V4));
|
||||
if (!_pcb){
|
||||
log_e("_pcb == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
ip_addr_t local_addr;
|
||||
local_addr.type = IPADDR_TYPE_V4;
|
||||
local_addr.u_addr.ip4.addr = (uint32_t) _addr;
|
||||
#if ESP_IDF_VERSION_MAJOR < 5
|
||||
if (_bind6) { // _bind6 && _bind4 both at the same time is not supported on Arduino 2 in this lib API
|
||||
local_addr.type = IPADDR_TYPE_V6;
|
||||
memcpy(local_addr.u_addr.ip6.addr, static_cast<const uint32_t*>(_addr6), sizeof(uint32_t) * 4);
|
||||
} else {
|
||||
local_addr.type = IPADDR_TYPE_V4;
|
||||
local_addr.u_addr.ip4.addr = _addr;
|
||||
}
|
||||
#else
|
||||
_addr.to_ip_addr_t(&local_addr);
|
||||
#endif
|
||||
err = _tcp_bind(_pcb, &local_addr, _port);
|
||||
|
||||
if (err != ERR_OK) {
|
||||
@@ -1322,7 +1519,7 @@ int8_t AsyncServer::_accept(tcp_pcb* pcb, int8_t err){
|
||||
if(tcp_close(pcb) != ERR_OK){
|
||||
tcp_abort(pcb);
|
||||
}
|
||||
log_e("FAIL");
|
||||
log_d("FAIL");
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,13 +22,34 @@
|
||||
#ifndef ASYNCTCP_H_
|
||||
#define ASYNCTCP_H_
|
||||
|
||||
#define ASYNCTCP_VERSION "3.1.4"
|
||||
#define ASYNCTCP_VERSION_MAJOR 3
|
||||
#define ASYNCTCP_VERSION_MINOR 1
|
||||
#define ASYNCTCP_VERSION_REVISION 4
|
||||
#define ASYNCTCP_FORK_mathieucarbou
|
||||
|
||||
#include "IPAddress.h"
|
||||
#include "sdkconfig.h"
|
||||
#if ESP_IDF_VERSION_MAJOR < 5
|
||||
#include "IPv6Address.h"
|
||||
#endif
|
||||
#include <functional>
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
|
||||
#ifndef LIBRETINY
|
||||
#include "sdkconfig.h"
|
||||
extern "C" {
|
||||
#include "freertos/semphr.h"
|
||||
#include "lwip/pbuf.h"
|
||||
}
|
||||
#else
|
||||
extern "C" {
|
||||
#include <semphr.h>
|
||||
#include <lwip/pbuf.h>
|
||||
}
|
||||
#define CONFIG_ASYNC_TCP_RUNNING_CORE -1 //any available core
|
||||
#define CONFIG_ASYNC_TCP_USE_WDT 0
|
||||
#endif
|
||||
|
||||
//If core is not defined, then we are running in Arduino or PIO
|
||||
#ifndef CONFIG_ASYNC_TCP_RUNNING_CORE
|
||||
@@ -36,9 +57,24 @@ extern "C" {
|
||||
#define CONFIG_ASYNC_TCP_USE_WDT 1 //if enabled, adds between 33us and 200us per event
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_ASYNC_TCP_STACK_SIZE
|
||||
#define CONFIG_ASYNC_TCP_STACK_SIZE 8192 * 2
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_ASYNC_TCP_PRIORITY
|
||||
#define CONFIG_ASYNC_TCP_PRIORITY 10
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_ASYNC_TCP_QUEUE_SIZE
|
||||
#define CONFIG_ASYNC_TCP_QUEUE_SIZE 64
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_ASYNC_TCP_MAX_ACK_TIME
|
||||
#define CONFIG_ASYNC_TCP_MAX_ACK_TIME 5000
|
||||
#endif
|
||||
|
||||
class AsyncClient;
|
||||
|
||||
#define ASYNC_MAX_ACK_TIME 5000
|
||||
#define ASYNC_WRITE_FLAG_COPY 0x01 //will allocate new buffer to hold the data while sending (else will hold reference to the data given)
|
||||
#define ASYNC_WRITE_FLAG_MORE 0x02 //will not send PSH flag, meaning that there should be more data to be sent before the application should react.
|
||||
|
||||
@@ -65,8 +101,11 @@ class AsyncClient {
|
||||
bool operator!=(const AsyncClient &other) {
|
||||
return !(*this == other);
|
||||
}
|
||||
bool connect(IPAddress ip, uint16_t port);
|
||||
bool connect(const char* host, uint16_t port);
|
||||
bool connect(const IPAddress& ip, uint16_t port);
|
||||
#if ESP_IDF_VERSION_MAJOR < 5
|
||||
bool connect(const IPv6Address& ip, uint16_t port);
|
||||
#endif
|
||||
bool connect(const char *host, uint16_t port);
|
||||
void close(bool now = false);
|
||||
void stop();
|
||||
int8_t abort();
|
||||
@@ -99,16 +138,29 @@ class AsyncClient {
|
||||
void setNoDelay(bool nodelay);
|
||||
bool getNoDelay();
|
||||
|
||||
void setKeepAlive(uint32_t ms, uint8_t cnt);
|
||||
|
||||
uint32_t getRemoteAddress();
|
||||
uint16_t getRemotePort();
|
||||
uint32_t getLocalAddress();
|
||||
uint16_t getLocalPort();
|
||||
#if LWIP_IPV6
|
||||
ip6_addr_t getRemoteAddress6();
|
||||
ip6_addr_t getLocalAddress6();
|
||||
#if ESP_IDF_VERSION_MAJOR < 5
|
||||
IPv6Address remoteIP6();
|
||||
IPv6Address localIP6();
|
||||
#else
|
||||
IPAddress remoteIP6();
|
||||
IPAddress localIP6();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//compatibility
|
||||
IPAddress remoteIP();
|
||||
uint16_t remotePort();
|
||||
uint16_t remotePort();
|
||||
IPAddress localIP();
|
||||
uint16_t localPort();
|
||||
uint16_t localPort();
|
||||
|
||||
void onConnect(AcConnectHandler cb, void* arg = 0); //on successful connect
|
||||
void onDisconnect(AcConnectHandler cb, void* arg = 0); //disconnected
|
||||
@@ -133,13 +185,15 @@ class AsyncClient {
|
||||
static int8_t _s_lwip_fin(void *arg, struct tcp_pcb *tpcb, int8_t err);
|
||||
static void _s_error(void *arg, int8_t err);
|
||||
static int8_t _s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len);
|
||||
static int8_t _s_connected(void* arg, void* tpcb, int8_t err);
|
||||
static int8_t _s_connected(void* arg, struct tcp_pcb *tpcb, int8_t err);
|
||||
static void _s_dns_found(const char *name, struct ip_addr *ipaddr, void *arg);
|
||||
|
||||
int8_t _recv(tcp_pcb* pcb, pbuf* pb, int8_t err);
|
||||
tcp_pcb * pcb(){ return _pcb; }
|
||||
|
||||
protected:
|
||||
bool _connect(ip_addr_t addr, uint16_t port);
|
||||
|
||||
tcp_pcb* _pcb;
|
||||
int8_t _closed_slot;
|
||||
|
||||
@@ -160,19 +214,19 @@ class AsyncClient {
|
||||
AcConnectHandler _poll_cb;
|
||||
void* _poll_cb_arg;
|
||||
|
||||
bool _pcb_busy;
|
||||
uint32_t _pcb_sent_at;
|
||||
bool _ack_pcb;
|
||||
uint32_t _tx_last_packet;
|
||||
uint32_t _rx_ack_len;
|
||||
uint32_t _rx_last_packet;
|
||||
uint32_t _rx_since_timeout;
|
||||
uint32_t _rx_timeout;
|
||||
uint32_t _rx_last_ack;
|
||||
uint32_t _ack_timeout;
|
||||
uint16_t _connect_port;
|
||||
|
||||
int8_t _close();
|
||||
void _free_closed_slot();
|
||||
void _allocate_closed_slot();
|
||||
int8_t _connected(void* pcb, int8_t err);
|
||||
bool _allocate_closed_slot();
|
||||
int8_t _connected(tcp_pcb* pcb, int8_t err);
|
||||
void _error(int8_t err);
|
||||
int8_t _poll(tcp_pcb* pcb);
|
||||
int8_t _sent(tcp_pcb* pcb, uint16_t len);
|
||||
@@ -188,6 +242,9 @@ class AsyncClient {
|
||||
class AsyncServer {
|
||||
public:
|
||||
AsyncServer(IPAddress addr, uint16_t port);
|
||||
#if ESP_IDF_VERSION_MAJOR < 5
|
||||
AsyncServer(IPv6Address addr, uint16_t port);
|
||||
#endif
|
||||
AsyncServer(uint16_t port);
|
||||
~AsyncServer();
|
||||
void onClient(AcConnectHandler cb, void* arg);
|
||||
@@ -203,7 +260,12 @@ class AsyncServer {
|
||||
|
||||
protected:
|
||||
uint16_t _port;
|
||||
bool _bind4 = false;
|
||||
bool _bind6 = false;
|
||||
IPAddress _addr;
|
||||
#if ESP_IDF_VERSION_MAJOR < 5
|
||||
IPv6Address _addr6;
|
||||
#endif
|
||||
bool _noDelay;
|
||||
tcp_pcb* _pcb;
|
||||
AcConnectHandler _connect_cb;
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
IPv6Address.cpp - Base class that provides IPv6Address
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <IPv6Address.h>
|
||||
#include <Print.h>
|
||||
|
||||
IPv6Address::IPv6Address()
|
||||
{
|
||||
memset(_address.bytes, 0, sizeof(_address.bytes));
|
||||
}
|
||||
|
||||
IPv6Address::IPv6Address(const uint8_t *address)
|
||||
{
|
||||
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||
}
|
||||
|
||||
IPv6Address::IPv6Address(const uint32_t *address)
|
||||
{
|
||||
memcpy(_address.bytes, (const uint8_t *)address, sizeof(_address.bytes));
|
||||
}
|
||||
|
||||
IPv6Address& IPv6Address::operator=(const uint8_t *address)
|
||||
{
|
||||
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool IPv6Address::operator==(const uint8_t* addr) const
|
||||
{
|
||||
return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
|
||||
}
|
||||
|
||||
size_t IPv6Address::printTo(Print& p) const
|
||||
{
|
||||
size_t n = 0;
|
||||
for(int i = 0; i < 16; i+=2) {
|
||||
if(i){
|
||||
n += p.print(':');
|
||||
}
|
||||
n += p.printf("%02x", _address.bytes[i]);
|
||||
n += p.printf("%02x", _address.bytes[i+1]);
|
||||
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
String IPv6Address::toString() const
|
||||
{
|
||||
char szRet[40];
|
||||
sprintf(szRet,"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
|
||||
_address.bytes[0], _address.bytes[1], _address.bytes[2], _address.bytes[3],
|
||||
_address.bytes[4], _address.bytes[5], _address.bytes[6], _address.bytes[7],
|
||||
_address.bytes[8], _address.bytes[9], _address.bytes[10], _address.bytes[11],
|
||||
_address.bytes[12], _address.bytes[13], _address.bytes[14], _address.bytes[15]);
|
||||
return String(szRet);
|
||||
}
|
||||
|
||||
bool IPv6Address::fromString(const char *address)
|
||||
{
|
||||
//format 0011:2233:4455:6677:8899:aabb:ccdd:eeff
|
||||
if(strlen(address) != 39){
|
||||
return false;
|
||||
}
|
||||
char * pos = (char *)address;
|
||||
size_t i = 0;
|
||||
for(i = 0; i < 16; i+=2) {
|
||||
if(!sscanf(pos, "%2hhx", &_address.bytes[i]) || !sscanf(pos+2, "%2hhx", &_address.bytes[i+1])){
|
||||
return false;
|
||||
}
|
||||
pos += 5;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
IPv6Address.h - Base class that provides IPv6Address
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef IPv6Address_h
|
||||
#define IPv6Address_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <WString.h>
|
||||
#include <Printable.h>
|
||||
|
||||
// A class to make it easier to handle and pass around IP addresses
|
||||
|
||||
class IPv6Address: public Printable
|
||||
{
|
||||
private:
|
||||
union {
|
||||
uint8_t bytes[16]; // IPv4 address
|
||||
uint32_t dword[4];
|
||||
} _address;
|
||||
|
||||
// Access the raw byte array containing the address. Because this returns a pointer
|
||||
// to the internal structure rather than a copy of the address this function should only
|
||||
// be used when you know that the usage of the returned uint8_t* will be transient and not
|
||||
// stored.
|
||||
uint8_t* raw_address()
|
||||
{
|
||||
return _address.bytes;
|
||||
}
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
IPv6Address();
|
||||
IPv6Address(const uint8_t *address);
|
||||
IPv6Address(const uint32_t *address);
|
||||
virtual ~IPv6Address() {}
|
||||
|
||||
bool fromString(const char *address);
|
||||
bool fromString(const String &address) { return fromString(address.c_str()); }
|
||||
|
||||
operator const uint8_t*() const
|
||||
{
|
||||
return _address.bytes;
|
||||
}
|
||||
operator const uint32_t*() const
|
||||
{
|
||||
return _address.dword;
|
||||
}
|
||||
bool operator==(const IPv6Address& addr) const
|
||||
{
|
||||
return (_address.dword[0] == addr._address.dword[0])
|
||||
&& (_address.dword[1] == addr._address.dword[1])
|
||||
&& (_address.dword[2] == addr._address.dword[2])
|
||||
&& (_address.dword[3] == addr._address.dword[3]);
|
||||
}
|
||||
bool operator==(const uint8_t* addr) const;
|
||||
|
||||
// Overloaded index operator to allow getting and setting individual octets of the address
|
||||
uint8_t operator[](int index) const
|
||||
{
|
||||
return _address.bytes[index];
|
||||
}
|
||||
uint8_t& operator[](int index)
|
||||
{
|
||||
return _address.bytes[index];
|
||||
}
|
||||
|
||||
// Overloaded copy operators to allow initialisation of IPv6Address objects from other types
|
||||
IPv6Address& operator=(const uint8_t *address);
|
||||
|
||||
virtual size_t printTo(Print& p) const;
|
||||
String toString() const;
|
||||
|
||||
friend class UDP;
|
||||
friend class Client;
|
||||
friend class Server;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user