Compare commits

...

47 Commits
2.4.0 ... 2.7.0

Author SHA1 Message Date
Links2004
6eee4c6dc6 clang-format 2025-08-13 19:24:49 +02:00
Links2004
a804e8e5e8 bump version to 2.7.0 2025-08-13 19:23:49 +02:00
Moritz Ulmer
8a261ade21 Allow definition of custom network interfaces (#921)
* Allow definition of custom network interfaces

* Create network client interface class

* Change to PIMPL approach

* Add example for custom network clients

Why:

- Show users how to use multiple network interfaces

This change addresses the need by:

- Adding an example PIO project to use Wi-Fi and GSM/LTE

* Add WebSockets prefix to normal and secure client

Why:

- Avoid name collision
- Fix broken reconnect change

This change addresses the need by:

- Adding WebSockets prefix to all custom clients
- Marking custom client as secure in clientDisconnect()
  - Remove broken fix for reconnecting
2025-08-13 13:39:38 +02:00
Akashdeep Deb
1789a18ddb Update README.md (#927)
* Update README.md

Updating README to include ESP32 support in client mode

* Update README.md

---------

Co-authored-by: Markus <974709+Links2004@users.noreply.github.com>
2024-12-29 10:25:08 +01:00
Markus
ca8026e550 Merge pull request #917 from omarcostahamido/patch-2
fix typos in WebSocketClientSocketIOack.ino
2024-11-17 09:48:25 +01:00
OCH
daf04b0560 Update WebSocketClientSocketIOack.ino
- fix some typos
2024-11-16 18:47:10 +00:00
Markus
8cdcf47fc5 Merge pull request #913 from Links2004/dependabot/github_actions/arduino/arduino-lint-action-2
Bump arduino/arduino-lint-action from 1 to 2
2024-10-15 09:02:54 +02:00
dependabot[bot]
1bea689694 Bump arduino/arduino-lint-action from 1 to 2
Bumps [arduino/arduino-lint-action](https://github.com/arduino/arduino-lint-action) from 1 to 2.
- [Release notes](https://github.com/arduino/arduino-lint-action/releases)
- [Commits](https://github.com/arduino/arduino-lint-action/compare/v1...v2)

---
updated-dependencies:
- dependency-name: arduino/arduino-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-14 11:00:40 +00:00
Links2004
7a4c416082 bump version to 2.6.1 2024-09-06 20:22:33 +02:00
Links2004
87b23a48e9 fix #907 use corect random source for newer ESP32 models 2024-09-06 20:21:38 +02:00
Links2004
bd011d8fd8 clang 2024-09-06 20:20:30 +02:00
Markus
af17970256 Merge pull request #906 from omarcostahamido/patch-1
Update WebSocketServer.ino
2024-08-28 19:26:45 +02:00
OCH
66f69c3b20 Update WebSocketServer.ino
- fixed weird indentations
2024-08-28 11:59:46 +01:00
Links2004
d41d65ccdc bump version 2.6.0 2024-08-25 18:35:45 +02:00
Markus
2e54e8b9c6 Merge pull request #903 from Links2004/dependabot/github_actions/actions/cache-4
Bump actions/cache from 3 to 4
2024-08-24 12:29:39 +02:00
Markus
2059fc5c3b Merge pull request #904 from Links2004/dependabot/github_actions/actions/checkout-4
Bump actions/checkout from 2 to 4
2024-08-24 12:29:18 +02:00
dependabot[bot]
b60be0e3c5 Bump actions/checkout from 2 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-24 10:08:09 +00:00
dependabot[bot]
e8006439a2 Bump actions/cache from 3 to 4
Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-24 10:08:07 +00:00
Markus
0980b209ba Create dependabot.yml 2024-08-24 12:07:31 +02:00
Aruna Tennakoon
899cfbdbe7 feat: Support Nano 33 IoT, MKR WIFI 1010, XIAO, Wio Terminal (#901) 2024-08-24 12:01:45 +02:00
Aruna Tennakoon
dcfb0df665 feat: Support Arduino Nano 33 IoT, MKR WIFI 1010 (#898) 2024-08-11 09:09:47 +02:00
Links2004
dc6fd04a98 fix #896 ESP32 Arduino changed setCACertBundle args 2024-08-04 09:40:01 +02:00
Links2004
7da1dc5c6e bump version 2.5.2 2024-07-29 13:07:27 +02:00
Aruna Tennakoon
d6d4c516b3 Support Arduino UNO WIFI 4 (#894)
feat: Arduino UNO R4 WiFi support
2024-07-29 10:11:12 +02:00
Links2004
e364e66884 go back to arduino-cli 0.35.3 since 1.0.0 is buggy
see: https://github.com/arduino/arduino-cli/issues/2643
2024-06-17 17:07:09 +02:00
Links2004
d5f0d3c4b5 remove broken rp2040 2024-06-17 16:47:41 +02:00
Links2004
0e127c9a76 update arduino-cli to 1.0.0 2024-06-17 16:28:59 +02:00
Links2004
11cf06897c update arduino-cli 2024-06-17 16:27:43 +02:00
Links2004
af1b0256b9 bump version to 2.4.2 2024-06-17 16:27:08 +02:00
Moritz Ulmer
c5e7a5eb08 Add support for CA bundles (#885)
Why:

- Allow CA cert bundles to be used

This change addresses the need by:

- Adding a constructor that takes a pointer to the bundle
- Setting the WiFiClientSecure to use the bundle
- Adding an example
2024-06-17 13:09:37 +02:00
Links2004
93707d455f fix build_sketch_cli result handling 2024-01-05 17:28:16 +01:00
Hasenradball
8d193b176d [Prevent unwanted Compiler Warnings]: Issue #772 - wrong format specifier in line 754 (#773)
* [Prevent unwanted Compiler Warnings]: Issue #772
2024-01-05 17:25:57 +01:00
Hasenradball
503105a9fe Remove compiler warnings (#854)
* [Prevent unwanted Compiler Warnings]: Issue #772
2024-01-05 17:24:45 +01:00
Links2004
6a26f74f95 code style 2024-01-05 15:27:49 +01:00
Links2004
be9fd8e267 fix getSocketNumber for ESP 2024-01-05 15:26:59 +01:00
Links2004
313f2e0170 update actions/cache@v3 2024-01-05 15:26:26 +01:00
Lukas Runge
3b143bc6f3 🐛 removed default values from *.cpp file 2024-01-05 15:20:03 +01:00
Shreyansh Jain
aed167bee0 updated the header file for the same changes 2024-01-05 15:20:03 +01:00
Shreyansh Jain
4acc33589a added option arguments in socket io being, for pingInterval, pongTimeout, and disconnectTimeoutCount 2024-01-05 15:20:03 +01:00
patrick
3352c833b8 - Fix memory leak by calling delete _server in the WebSocketsServer destructor.
- Improve performance by looking for match to existing socket before creating a new one
2024-01-05 15:17:42 +01:00
Links2004
241c73a806 use ARDUINO_BOARD_MANAGER_ADDITIONAL_URLS env for setting board URLs 2024-01-05 15:06:30 +01:00
Links2004
437c0252f1 fix cli download URL 2024-01-05 15:01:53 +01:00
Links2004
92480b8987 IDE_VERSION --> CLI_VERSION 2024-01-05 15:00:16 +01:00
Links2004
da7efc789e update github actions to arduino-cli for build tests 2024-01-05 14:57:05 +01:00
matth-x
30d5e13666 set minimum bufsize for base64 encode 2023-08-19 21:16:37 +02:00
mavyfaby
751cf87b6c feat(socketio): add disconnect function 2023-05-23 18:03:07 +02:00
Links
a215cca4fe bump version 2.4.1 2023-05-01 15:02:36 +02:00
50 changed files with 5733 additions and 171 deletions

11
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

10
.github/workflows/arduino-lint.yaml vendored Normal file
View File

@@ -0,0 +1,10 @@
name: Arduino library compliance (Lint)
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: arduino/arduino-lint-action@v2
with:
library-manager: update

View File

@@ -0,0 +1,69 @@
name: Compile Arduino WiFiNINA Examples
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
on:
push:
paths:
- ".github/workflows/compile-arduino_wifinina-examples.yaml"
- "examples/arduino_wifinina/**"
- "src/**"
pull_request:
paths:
- ".github/workflows/compile-arduino_wifinina-examples.yaml"
- "examples/arduino_wifinina/**"
- "src/**"
schedule:
# Run every Tuesday at 8 AM UTC to catch breakage caused by changes to external resources (libraries, platforms).
- cron: "0 8 * * TUE"
workflow_dispatch:
repository_dispatch:
jobs:
build:
name: ${{ matrix.board.fqbn }}
runs-on: ubuntu-latest
env:
SKETCHES_REPORTS_PATH: sketches-reports
strategy:
fail-fast: false
matrix:
board:
- fqbn: arduino:samd:mkrwifi1010
platforms: |
- name: arduino:samd
artifact-name-suffix: arduino-samd-mkrwifi1010
libraries: |
- name: WiFiNINA
- fqbn: arduino:samd:nano_33_iot
platforms: |
- name: arduino:samd
artifact-name-suffix: arduino-samd-nano_33_iot
libraries: |
- name: WiFiNINA
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Compile examples
uses: arduino/compile-sketches@v1
with:
fqbn: ${{ matrix.board.fqbn }}
platforms: ${{ matrix.board.platforms }}
libraries: |
# Install the library from the local path.
- source-path: ./
${{ matrix.board.libraries }}
sketch-paths: |
- examples/arduino_wifinina/arduino_wifinina.ino
enable-deltas-report: true
sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }}
- name: Save sketches report as workflow artifact
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
path: ${{ env.SKETCHES_REPORTS_PATH }}
name: sketches-report-${{ matrix.board.artifact-name-suffix }}

View File

@@ -0,0 +1,81 @@
name: Compile SeedStudio Examples
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
on:
push:
paths:
- ".github/workflows/compile-seeed-studio-examples.yaml"
- "examples/seeed-studio/**"
- "src/**"
pull_request:
paths:
- ".github/workflows/compile-seeed-studio-examples.yaml"
- "examples/seeed-studio/**"
- "src/**"
schedule:
# Run every Tuesday at 8 AM UTC to catch breakage caused by changes to external resources (libraries, platforms).
- cron: "0 8 * * TUE"
workflow_dispatch:
repository_dispatch:
jobs:
build:
name: ${{ matrix.board.fqbn }}
runs-on: ubuntu-latest
env:
SKETCHES_REPORTS_PATH: sketches-reports
strategy:
fail-fast: false
matrix:
board:
- fqbn: Seeeduino:samd:seeed_XIAO_m0:usbstack=arduino,debug=off
platforms: |
- name: Seeeduino:samd
source-url: https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json
libraries: |
- name: Seeed Arduino rpcWiFi
- name: Seeed Arduino rpcUnified
- name: Seeed_Arduino_mbedtls
- name: Seeed Arduino FS
- name: Seeed Arduino SFUD
artifact-name-suffix: seeeduino-xia0
- fqbn: Seeeduino:samd:seeed_wio_terminal
platforms: |
- name: Seeeduino:samd
source-url: https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json
libraries: |
- name: Seeed Arduino rpcWiFi
- name: Seeed Arduino rpcUnified
- name: Seeed_Arduino_mbedtls
- name: Seeed Arduino FS
- name: Seeed Arduino SFUD
artifact-name-suffix: seeeduino-wio_terminal
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Compile examples
uses: arduino/compile-sketches@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
fqbn: ${{ matrix.board.fqbn }}
platforms: ${{ matrix.board.platforms }}
libraries: |
# Install the library from the local path.
- source-path: ./
${{ matrix.board.libraries }}
sketch-paths: |
- examples/seeed-studio/xio-wio-terminal/WebSocketClient
enable-deltas-report: true
sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }}
- name: Save sketches report as workflow artifact
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
path: ${{ env.SKETCHES_REPORTS_PATH }}
name: sketches-report-${{ matrix.board.artifact-name-suffix }}

View File

@@ -0,0 +1,60 @@
name: Compile Arduino UNO R4 WiFi Examples
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
on:
push:
paths:
- ".github/workflows/compile-unor4wifi-examples.yaml"
- "examples/arduino_renesas/**"
- "src/**"
pull_request:
paths:
- ".github/workflows/compile-unor4wifi-examples.yaml"
- "examples/arduino_renesas/**"
- "src/**"
schedule:
# Run every Tuesday at 8 AM UTC to catch breakage caused by changes to external resources (libraries, platforms).
- cron: "0 8 * * TUE"
workflow_dispatch:
repository_dispatch:
jobs:
build:
name: ${{ matrix.board.fqbn }}
runs-on: ubuntu-latest
env:
SKETCHES_REPORTS_PATH: sketches-reports
strategy:
fail-fast: false
matrix:
board:
- fqbn: arduino:renesas_uno:unor4wifi
platforms: |
- name: arduino:renesas_uno
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Compile examples
uses: arduino/compile-sketches@v1
with:
fqbn: ${{ matrix.board.fqbn }}
platforms: ${{ matrix.board.platforms }}
libraries: |
# Install the library from the local path.
- source-path: ./
sketch-paths: |
- examples/arduino_renesas/arduino_uno_r4_wifi
enable-deltas-report: true
sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }}
- name: Save sketches report as workflow artifact
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
path: ${{ env.SKETCHES_REPORTS_PATH }}
name: sketches-report-${{ matrix.board.artifact-name-suffix }}

View File

@@ -17,7 +17,7 @@ jobs:
check_version_files:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: check version
run: |
@@ -26,7 +26,7 @@ jobs:
prepare_example_json:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: generate examples
id: set-matrix
@@ -37,13 +37,13 @@ jobs:
echo -en "matrix=" >> $GITHUB_OUTPUT
echo -en "[" >> $GITHUB_OUTPUT
get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp8266_pico esp8266 1.8.19 esp8266com:esp8266:generic:xtal=80,vt=flash,exception=disabled,stacksmash=disabled,ssl=all,mmu=3232,non32xfer=fast,ResetMethod=nodemcu,CrystalFreq=26,FlashFreq=80,FlashMode=qio,eesz=4M2M,led=2,sdk=nonosdk_190703,ip=lm2f,dbg=Serial1,lvl=SSL,wipe=none,baud=115200 >> $GITHUB_OUTPUT
get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp8266_pico esp8266 0.35.3 esp8266:esp8266:generic:xtal=80,vt=flash,exception=disabled,stacksmash=disabled,ssl=all,mmu=3232,non32xfer=fast,ResetMethod=nodemcu,CrystalFreq=26,FlashFreq=80,FlashMode=qio,eesz=4M2M,led=2,sdk=nonosdk_190703,ip=lm2f,dbg=Serial1,lvl=SSL,wipe=none,baud=115200 >> $GITHUB_OUTPUT
echo -en "," >> $GITHUB_OUTPUT
get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp8266_pico esp8266 1.8.19 esp8266com:esp8266:generic:xtal=80,vt=flash,exception=disabled,stacksmash=disabled,ssl=all,mmu=3232,non32xfer=fast,ResetMethod=nodemcu,CrystalFreq=26,FlashFreq=80,FlashMode=qio,eesz=4M2M,led=2,sdk=nonosdk_190703,ip=lm2f,dbg=Disabled,lvl=None____,wipe=none,baud=115200 >> $GITHUB_OUTPUT
get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp8266_pico esp8266 0.35.3 esp8266:esp8266:generic:xtal=80,vt=flash,exception=disabled,stacksmash=disabled,ssl=all,mmu=3232,non32xfer=fast,ResetMethod=nodemcu,CrystalFreq=26,FlashFreq=80,FlashMode=qio,eesz=4M2M,led=2,sdk=nonosdk_190703,ip=lm2f,dbg=Disabled,lvl=None____,wipe=none,baud=115200 >> $GITHUB_OUTPUT
echo -en "," >> $GITHUB_OUTPUT
get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp32 esp32 1.8.19 espressif:esp32:esp32:FlashFreq=80 >> $GITHUB_OUTPUT
get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp32 esp32 0.35.3 esp32:esp32:esp32:FlashFreq=80 >> $GITHUB_OUTPUT
echo -en "]" >> $GITHUB_OUTPUT
echo >> $GITHUB_OUTPUT
@@ -55,33 +55,35 @@ jobs:
strategy:
fail-fast: false
matrix:
IDE_VERSION: [1.8.19]
CLI_VERSION: [0.35.3]
env:
IDE_VERSION: ${{ matrix.IDE_VERSION }}
CLI_VERSION: ${{ matrix.CLI_VERSION }}
ARDUINO_DIRECTORIES_DATA: /home/runner/arduino_ide
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Get Date
id: get-date
- name: Get hash
id: get-hash
run: |
echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT
echo "hash=$(/bin/date -u "+%Y%m%d")-$(md5sum ".github/workflows/main.yml" | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT
shell: bash
- uses: actions/cache@v2
- uses: actions/cache@v4
id: cache_all
with:
path: |
/home/runner/arduino_ide
/home/runner/Arduino
key: ${{ runner.os }}-${{ steps.get-date.outputs.date }}-${{ matrix.IDE_VERSION }}
key: ${{ runner.os }}-${{ steps.get-hash.outputs.hash }}-${{ matrix.CLI_VERSION }}-cli
- name: download IDE
if: steps.cache_all.outputs.cache-hit != 'true'
run: |
wget http://downloads.arduino.cc/arduino-$IDE_VERSION-linux64.tar.xz -q
tar xf arduino-$IDE_VERSION-linux64.tar.xz
mv arduino-$IDE_VERSION $HOME/arduino_ide
wget https://github.com/arduino/arduino-cli/releases/download/v${CLI_VERSION}/arduino-cli_${CLI_VERSION}_Linux_64bit.tar.gz -q
tar xf arduino-cli_${CLI_VERSION}_Linux_64bit.tar.gz
mkdir -p $ARDUINO_DIRECTORIES_DATA
mv arduino-cli $ARDUINO_DIRECTORIES_DATA/
- name: download ArduinoJson
if: steps.cache_all.outputs.cache-hit != 'true'
@@ -91,17 +93,12 @@ jobs:
unzip 6.x.zip
mv ArduinoJson-6.x $HOME/Arduino/libraries/ArduinoJson
- name: download esp8266
- name: download cores
if: steps.cache_all.outputs.cache-hit != 'true'
run: |
export PATH="$ARDUINO_DIRECTORIES_DATA:$PATH"
source $GITHUB_WORKSPACE/travis/common.sh
get_core esp8266
- name: download esp32
if: steps.cache_all.outputs.cache-hit != 'true'
run: |
source $GITHUB_WORKSPACE/travis/common.sh
get_core esp32
get_core_cli
build:
needs: [prepare_ide, prepare_example_json]
@@ -113,30 +110,31 @@ jobs:
env:
CPU: ${{ matrix.cpu }}
BOARD: ${{ matrix.board }}
IDE_VERSION: ${{ matrix.ideversion }}
CLI_VERSION: ${{ matrix.cliversion }}
SKETCH: ${{ matrix.sketch }}
ARDUINO_DIRECTORIES_DATA: /home/runner/arduino_ide
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: install libgtk2.0-0
run: |
sudo apt-get install -y libgtk2.0-0
- name: Get Date
id: get-date
- name: Get hash
id: get-hash
run: |
echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT
echo "hash=$(/bin/date -u "+%Y%m%d")-$(md5sum ".github/workflows/main.yml" | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT
shell: bash
- uses: actions/cache@v2
- uses: actions/cache@v4
id: cache_all
with:
path: |
/home/runner/arduino_ide
/home/runner/Arduino
key: ${{ runner.os }}-${{ steps.get-date.outputs.date }}-${{ matrix.ideversion }}
key: ${{ runner.os }}-${{ steps.get-hash.outputs.hash }}-${{ matrix.cliversion }}-cli
- name: install python serial
if: matrix.cpu == 'esp32'
@@ -145,41 +143,24 @@ jobs:
sudo pip install pyserial
# sudo apt install python-is-python3
- name: start DISPLAY
run: |
/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16
export DISPLAY=:1.0
sleep 3
- name: test IDE
run: |
export PATH="$HOME/arduino_ide:$PATH"
which arduino
export PATH="$ARDUINO_DIRECTORIES_DATA:$PATH"
which arduino-cli
- name: copy code
run: |
mkdir -p $HOME/Arduino/libraries/
cp -r $GITHUB_WORKSPACE $HOME/Arduino/libraries/arduinoWebSockets
- name: config IDE
run: |
set +x
export DISPLAY=:1.0
export PATH="$HOME/arduino_ide:$PATH"
arduino --board $BOARD --save-prefs
arduino --pref update.check=false --pref build.verbose=false --pref cache.enable=true --pref compiler.cache_core=true --pref compiler.warning_level=default --save-prefs
arduino --get-pref sketchbook.path
arduino --get-pref
- name: build example
timeout-minutes: 20
run: |
set -ex
export DISPLAY=:1.0
export PATH="$HOME/arduino_ide:$PATH"
source $GITHUB_WORKSPACE/travis/common.sh
cd $GITHUB_WORKSPACE
build_sketch arduino $SKETCH
build_sketch_cli "$SKETCH" "$BOARD"
done:
needs: [prepare_ide, prepare_example_json, build, check_version_files]

View File

@@ -1,4 +1,4 @@
WebSocket Server and Client for Arduino [![Build Status](https://github.com/Links2004/arduinoWebSockets/workflows/CI/badge.svg?branch=master)](https://github.com/Links2004/arduinoWebSockets/actions?query=workflow%3ACI+branch%3Amaster)
WebSocket Server and Client for Arduino [![Build Status](https://github.com/Links2004/arduinoWebSockets/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/Links2004/arduinoWebSockets/actions?query=branch%3Amaster)
===========================================
a WebSocket Server and Client for Arduino based on RFC6455.
@@ -32,6 +32,9 @@ a WebSocket Server and Client for Arduino based on RFC6455.
- ATmega328 with enc28j60 (ATmega branch)
- ATmega2560 with Ethernet Shield (ATmega branch)
- ATmega2560 with enc28j60 (ATmega branch)
- Arduino UNO [R4 WiFi](https://github.com/arduino/ArduinoCore-renesas)
- Arduino Nano 33 IoT, MKR WIFI 1010 (requires [WiFiNINA](https://github.com/arduino-libraries/WiFiNINA/) library)
- Seeeduino XIAO, Seeeduino Wio Terminal (requires [rpcWiFi](https://github.com/Seeed-Studio/Seeed_Arduino_rpcWiFi) library)
###### Note: ######
@@ -44,10 +47,21 @@ a WebSocket Server and Client for Arduino based on RFC6455.
### wss / SSL ###
supported for:
- wss client on the ESP8266
- wss / SSL for ESP32 in client mode
- wss / SSL is not natively supported in WebSocketsServer however it is possible to achieve secure websockets
by running the device behind an SSL proxy. See [Nginx](examples/Nginx/esp8266.ssl.reverse.proxy.conf) for a
sample Nginx server configuration file to enable this.
### Root CA Cert Bundles for SSL/TLS connections ###
Secure connections require the certificate of the server to be verified. One option is to provide a single certificate in the chain of trust. However, for flexibility and robustness, a certificate bundle is recommended. If a server changes the root CA from which it derives its certificates, this will not be a problem. With a single CA cert it will not connect.
- For [technical details](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/protocols/esp_crt_bundle.html)
- For a [PlatformIO setup](https://github.com/Duckle29/esp32-certBundle/)
- For an [example](examples/esp32/WebSocketClientSSLBundle/)
Including a bundle with all CA certs will use 77.2 kB but this list can be reduced to 16.5 kB for the 41 most common. This results in 90% absolute usage coverage and 99% market share coverage according to [W3Techs](https://w3techs.com/technologies/overview/ssl_certificate). The bundle is inserted into the compiled firmware. The bundle is not loaded into RAM, only its index.
### ESP Async TCP ###
This libary can run in Async TCP mode on the ESP.
@@ -63,19 +77,19 @@ The mode can be activated in the ```WebSockets.h``` (see WEBSOCKETS_NETWORK_TYPE
```c++
void begin(const char *host, uint16_t port, const char * url = "/", const char * protocol = "arduino");
void begin(String host, uint16_t port, String url = "/", String protocol = "arduino");
```
```
- `onEvent`: Callback to handle for websocket events
```c++
```c++
void onEvent(WebSocketClientEvent cbEvent);
```
```
- `WebSocketClientEvent`: Handler for websocket events
```c++
```c++
void (*WebSocketClientEvent)(WStype_t type, uint8_t * payload, size_t length)
```
```
Where `WStype_t type` is defined as:
```c++
```c++
typedef enum {
WStype_ERROR,
WStype_DISCONNECTED,
@@ -89,13 +103,11 @@ Where `WStype_t type` is defined as:
WStype_PING,
WStype_PONG,
} WStype_t;
```
```
### Issues ###
Submit issues to: https://github.com/Links2004/arduinoWebSockets/issues
[![Join the chat at https://gitter.im/Links2004/arduinoWebSockets](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Links2004/arduinoWebSockets?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
### License and credits ###
The library is licensed under [LGPLv2.1](https://github.com/Links2004/arduinoWebSockets/blob/master/LICENSE)

View File

@@ -0,0 +1,109 @@
#include <Arduino.h>
#include <stdarg.h>
#include <stdio.h>
#include "WiFiS3.h"
#include <WebSocketsClient.h>
#define WIFI_SSID ""
#define WIFI_PASS ""
WebSocketsClient webSocket;
void webSocketEvent(WStype_t type, uint8_t *payload, size_t length) {
switch (type) {
case WStype_DISCONNECTED:
Serial.println("[WSc] Disconnected!");
break;
case WStype_CONNECTED:
Serial.println("[WSc] Connected!");
// send message to server when Connected
webSocket.sendTXT("Connected");
break;
case WStype_TEXT:
Serial.print("[WSc] get text:");
Serial.println((char *)payload);
// send message to server
// webSocket.sendTXT("message here");
break;
case WStype_BIN:
// send data to server
// webSocket.sendBIN(payload, length);
break;
case WStype_ERROR:
case WStype_FRAGMENT_TEXT_START:
case WStype_FRAGMENT_BIN_START:
case WStype_FRAGMENT:
case WStype_FRAGMENT_FIN:
break;
}
}
void setup() {
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println();
Serial.println();
Serial.println();
for (uint8_t t = 4; t > 0; t--) {
Serial.println("[SETUP] BOOT WAIT ...");
Serial.flush();
delay(1000);
}
// check for the WiFi module:
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("Communication with WiFi module failed!");
// don't continue
while (true)
;
}
String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
Serial.println("Please upgrade the firmware");
}
Serial.println("[Wifi]: Connecting");
int status = WL_IDLE_STATUS;
// attempt to connect to WiFi network:
while (status != WL_CONNECTED) {
Serial.print("[Wifi]: Attempting to connect to SSID: ");
Serial.println(WIFI_SSID);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(WIFI_SSID, WIFI_PASS);
delay(1000);
}
Serial.println("Connected!");
// print your board's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// server address, port and URL
webSocket.begin("192.168.0.123", 8011);
// event handler
webSocket.onEvent(webSocketEvent);
// try ever 5000 again if connection has failed
webSocket.setReconnectInterval(5000);
}
void loop() {
webSocket.loop();
}

View File

@@ -0,0 +1,100 @@
#include <Arduino.h>
#include <SPI.h>
#include <WiFiNINA.h>
#include <WebSocketsClient.h>
#define WIFI_SSID ""
#define WIFI_PASS ""
int status = WL_IDLE_STATUS;
WiFiClient client;
WebSocketsClient webSocket;
void webSocketEvent(WStype_t type, uint8_t *payload, size_t length) {
switch (type) {
case WStype_DISCONNECTED:
Serial.println("[WSc] Disconnected!");
break;
case WStype_CONNECTED:
Serial.println("[WSc] Connected!");
// send message to server when Connected
webSocket.sendTXT("Connected");
break;
case WStype_TEXT:
Serial.print("[WSc] get text:");
Serial.println((char *)payload);
// send message to server
// webSocket.sendTXT("message here");
break;
case WStype_BIN:
// send data to server
// webSocket.sendBIN(payload, length);
break;
case WStype_ERROR:
case WStype_FRAGMENT_TEXT_START:
case WStype_FRAGMENT_BIN_START:
case WStype_FRAGMENT:
case WStype_PING:
case WStype_PONG:
case WStype_FRAGMENT_FIN:
break;
}
}
void setup() {
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println();
Serial.println();
Serial.println();
// check for the WiFi module:
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("Communication with WiFi module failed!");
// don't continue
while (true);
}
String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
Serial.println("Please upgrade the firmware");
}
// attempt to connect to WiFi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(WIFI_SSID);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(WIFI_SSID, WIFI_PASS);
// wait 10 seconds for connection:
delay(10000);
}
Serial.println("Connected to WiFi");
// print your board's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// server address, port and URL
webSocket.begin("192.168.0.123", 8011);
// event handler
webSocket.onEvent(webSocketEvent);
// try ever 5000 again if connection has failed
webSocket.setReconnectInterval(5000);
}
void loop() {
webSocket.loop();
}

View File

@@ -0,0 +1,135 @@
/*
* main.cpp
*
* Created on: 15.06.2024
*
*/
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <WebSocketsClient.h>
// Use the incbin library to embedd the cert binary
// extern const uint8_t rootca_crt_bundle_start[] asm(
// "_binary_data_cert_x509_crt_bundle_bin_start");
WiFiMulti wifiMulti;
WebSocketsClient webSocket;
#define USE_SERIAL Serial
void setClock() {
configTime(0, 0, "pool.ntp.org", "time.nist.gov");
USE_SERIAL.print(F("Waiting for NTP time sync: "));
time_t nowSecs = time(nullptr);
while(nowSecs < 8 * 3600 * 2) {
delay(500);
USE_SERIAL.print(F("."));
yield();
nowSecs = time(nullptr);
}
USE_SERIAL.println();
struct tm timeinfo;
gmtime_r(&nowSecs, &timeinfo);
USE_SERIAL.print(F("Current time: "));
USE_SERIAL.print(asctime(&timeinfo));
}
void hexdump(const void * mem, uint32_t len, uint8_t cols = 16) {
const uint8_t * src = (const uint8_t *)mem;
USE_SERIAL.printf("\n[HEXDUMP] Address: 0x%08X len: 0x%X (%d)", (ptrdiff_t)src, len, len);
for(uint32_t i = 0; i < len; i++) {
if(i % cols == 0) {
USE_SERIAL.printf("\n[0x%08X] 0x%08X: ", (ptrdiff_t)src, i);
}
USE_SERIAL.printf("%02X ", *src);
src++;
}
USE_SERIAL.printf("\n");
}
void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
switch(type) {
case WStype_DISCONNECTED:
USE_SERIAL.printf("[WSc] Disconnected!\n");
break;
case WStype_CONNECTED:
USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload);
// send message to server when Connected
webSocket.sendTXT("Connected");
break;
case WStype_TEXT:
USE_SERIAL.printf("[WSc] get text: %s\n", payload);
// send message to server
// webSocket.sendTXT("message here");
break;
case WStype_BIN:
USE_SERIAL.printf("[WSc] get binary length: %u\n", length);
hexdump(payload, length);
// send data to server
// webSocket.sendBIN(payload, length);
break;
case WStype_ERROR:
case WStype_FRAGMENT_TEXT_START:
case WStype_FRAGMENT_BIN_START:
case WStype_FRAGMENT:
case WStype_FRAGMENT_FIN:
break;
}
}
void setup() {
USE_SERIAL.begin(115200);
USE_SERIAL.setDebugOutput(true);
USE_SERIAL.println();
USE_SERIAL.println();
USE_SERIAL.println();
for(uint8_t t = 4; t > 0; t--) {
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
USE_SERIAL.flush();
delay(1000);
}
wifiMulti.addAP("SSID", "WIFI_PASSPHRASE");
// WiFi.disconnect();
while(wifiMulti.run() != WL_CONNECTED) {
delay(100);
}
setClock();
// server address, port and URL. This server can be flakey.
// Expected response: Request served by 0123456789abcdef
// webSocket.beginSslWithBundle("echo.websocket.org", 443, "/", rootca_crt_bundle_start, "");
// ESP32 3.0.4 or higher needs the size of the bundle
// webSocket.beginSslWithBundle("echo.websocket.org", 443, "/", rootca_crt_bundle_start, sizeof(rootca_crt_bundle_start), "");
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 4)
webSocket.beginSslWithBundle("echo.websocket.org", 443, "/", NULL, 0, "");
#else
webSocket.beginSslWithBundle("echo.websocket.org", 443, "/", NULL, "");
#endif
// event handler
webSocket.onEvent(webSocketEvent);
// use HTTP Basic Authorization this is optional enable if needed
// webSocket.setAuthorization("user", "Password");
// try ever 5000 again if connection has failed
webSocket.setReconnectInterval(5000);
}
void loop() {
webSocket.loop();
}

View File

@@ -54,7 +54,7 @@ void socketIOEvent(socketIOmessageType_t type, uint8_t * payload, size_t length)
// Message Includes a ID for a ACK (callback)
if(id) {
// creat JSON message for Socket.IO (ack)
// create JSON message for Socket.IO (ack)
DynamicJsonDocument docOut(1024);
JsonArray array = docOut.to<JsonArray>();
@@ -130,11 +130,11 @@ void loop() {
if(now - messageTimestamp > 2000) {
messageTimestamp = now;
// creat JSON message for Socket.IO (event)
// create JSON message for Socket.IO (event)
DynamicJsonDocument doc(1024);
JsonArray array = doc.to<JsonArray>();
// add evnet name
// add event name
// Hint: socket.on('event_name', ....
array.add("event_name");
@@ -142,7 +142,7 @@ void loop() {
JsonObject param1 = array.createNestedObject();
param1["now"] = (uint32_t) now;
// JSON to String (serializion)
// JSON to String (serialization)
String output;
serializeJson(doc, output);

View File

@@ -42,8 +42,8 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length
IPAddress ip = webSocket.remoteIP(num);
USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);
// send message to client
webSocket.sendTXT(num, "Connected");
// send message to client
webSocket.sendTXT(num, "Connected");
}
break;
case WStype_TEXT:
@@ -62,12 +62,12 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length
// send message to client
// webSocket.sendBIN(num, payload, length);
break;
case WStype_ERROR:
case WStype_FRAGMENT_TEXT_START:
case WStype_FRAGMENT_BIN_START:
case WStype_FRAGMENT:
case WStype_FRAGMENT_FIN:
break;
case WStype_ERROR:
case WStype_FRAGMENT_TEXT_START:
case WStype_FRAGMENT_BIN_START:
case WStype_FRAGMENT:
case WStype_FRAGMENT_FIN:
break;
}
}

View File

@@ -0,0 +1 @@
BasedOnStyle: Google

View File

@@ -0,0 +1,2 @@
.pio
.vscode

View File

@@ -0,0 +1,25 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp32dev]
platform = espressif32@6.11.0
board = esp32dev
framework = arduino
monitor_speed = 115200
upload_speed = 921600
build_flags =
-DCORE_DEBUG_LEVEL=5
-D WEBSOCKETS_NETWORK_TYPE=10
-D TINY_GSM_MODEM_SIM7600
lib_deps =
digitaldragon/SSLClient@^1.3.2
vshymanskyy/StreamDebugger@^1.0.1
vshymanskyy/TinyGSM@^0.12.0
symlink://../../..

View File

@@ -0,0 +1,3 @@
This example project shows how to use a custom NetworkClient class to switch between two underlying network interfaces.
In this case it shows how a board can support Wi-Fi as well as GSM/LTE connectivity. It uses a shim to switch between the two network interfaces, thereby allowing a single binary to handle both interfaces without needing to reboot. This example can be extended to cover other network interfaces that conform to the Client() class interface.

View File

@@ -0,0 +1,126 @@
/*
* main.cpp
*
* Created on: 15.06.2024
*
*/
#include <Arduino.h>
#include <WebSocketsClient.h>
#include <WiFiMulti.h>
#include "network_client_impl.h"
WiFiMulti wifiMulti;
WebSocketsClient webSocket;
#define USE_SERIAL Serial
void setClock() {
configTime(0, 0, "pool.ntp.org", "time.nist.gov");
USE_SERIAL.print(F("Waiting for NTP time sync: "));
time_t nowSecs = time(nullptr);
while (nowSecs < 8 * 3600 * 2) {
delay(500);
USE_SERIAL.print(F("."));
yield();
nowSecs = time(nullptr);
}
USE_SERIAL.println();
struct tm timeinfo;
gmtime_r(&nowSecs, &timeinfo);
USE_SERIAL.print(F("Current time: "));
USE_SERIAL.print(asctime(&timeinfo));
}
void hexdump(const void *mem, uint32_t len, uint8_t cols = 16) {
const uint8_t *src = (const uint8_t *)mem;
USE_SERIAL.printf("\n[HEXDUMP] Address: 0x%08X len: 0x%X (%d)",
(ptrdiff_t)src, len, len);
for (uint32_t i = 0; i < len; i++) {
if (i % cols == 0) {
USE_SERIAL.printf("\n[0x%08X] 0x%08X: ", (ptrdiff_t)src, i);
}
USE_SERIAL.printf("%02X ", *src);
src++;
}
USE_SERIAL.printf("\n");
}
void webSocketEvent(WStype_t type, uint8_t *payload, size_t length) {
switch (type) {
case WStype_DISCONNECTED:
USE_SERIAL.printf("[WSc] Disconnected!\n");
break;
case WStype_CONNECTED:
USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload);
// send message to server when Connected
webSocket.sendTXT("Connected");
break;
case WStype_TEXT:
USE_SERIAL.printf("[WSc] get text: %s\n", payload);
// send message to server
// webSocket.sendTXT("message here");
break;
case WStype_BIN:
USE_SERIAL.printf("[WSc] get binary length: %u\n", length);
hexdump(payload, length);
// send data to server
// webSocket.sendBIN(payload, length);
break;
case WStype_ERROR:
case WStype_FRAGMENT_TEXT_START:
case WStype_FRAGMENT_BIN_START:
case WStype_FRAGMENT:
case WStype_FRAGMENT_FIN:
break;
}
}
void setup() {
USE_SERIAL.begin(115200);
USE_SERIAL.setDebugOutput(true);
USE_SERIAL.println();
USE_SERIAL.println();
USE_SERIAL.println();
for (uint8_t t = 4; t > 0; t--) {
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
USE_SERIAL.flush();
delay(1000);
}
wifiMulti.addAP("Berge", "BlauerHimmel!");
// WiFi.disconnect();
while (wifiMulti.run() != WL_CONNECTED) {
delay(100);
}
// Call to enable WiFi interface to be used by the webSocketClient
WebSocketsNetworkClient::Impl::enableWifi();
setClock();
// server address, port and URL. This server can be flakey.
// Expected response: Request served by 0123456789abcdef
webSocket.beginSSL("echo.websocket.org", 443, "/");
// event handler
webSocket.onEvent(webSocketEvent);
// use HTTP Basic Authorization this is optional enable if needed
// webSocket.setAuthorization("user", "Password");
// try ever 5000 again if connection has failed
webSocket.setReconnectInterval(5000);
}
void loop() { webSocket.loop(); }

View File

@@ -0,0 +1,148 @@
#include "network_client_impl.h"
WebSocketsNetworkClient::WebSocketsNetworkClient()
: _impl(new WebSocketsNetworkClient::Impl()) {}
WebSocketsNetworkClient::WebSocketsNetworkClient(WiFiClient wifi_client)
: _impl(new WebSocketsNetworkClient::Impl()) {}
WebSocketsNetworkClient::~WebSocketsNetworkClient() {}
int WebSocketsNetworkClient::connect(IPAddress ip, uint16_t port) {
if (_impl->gsm_client_) {
return _impl->gsm_client_->connect(ip, port);
} else if (_impl->wifi_client_) {
return _impl->wifi_client_->connect(ip, port);
}
Serial.println(_impl->no_interface_error_);
return 0;
}
int WebSocketsNetworkClient::connect(const char *host, uint16_t port) {
if (_impl->gsm_client_) {
return _impl->gsm_client_->connect(host, port);
} else if (_impl->wifi_client_) {
return _impl->wifi_client_->connect(host, port);
}
Serial.println(_impl->no_interface_error_);
return 0;
}
int WebSocketsNetworkClient::connect(const char *host, uint16_t port,
int32_t timeout_ms) {
if (_impl->gsm_client_) {
return _impl->gsm_client_->connect(host, port, timeout_ms);
} else if (_impl->wifi_client_) {
return _impl->wifi_client_->connect(host, port, timeout_ms);
}
Serial.println(_impl->no_interface_error_);
return 0;
}
size_t WebSocketsNetworkClient::write(uint8_t data) {
if (_impl->gsm_client_) {
return _impl->gsm_client_->write(data);
} else if (_impl->wifi_client_) {
return _impl->wifi_client_->write(data);
}
Serial.println(_impl->no_interface_error_);
return 0;
}
size_t WebSocketsNetworkClient::write(const uint8_t *buf, size_t size) {
Serial.printf("Send_: %zu\n", size);
if (_impl->gsm_client_) {
return _impl->gsm_client_->write(buf, size);
} else if (_impl->wifi_client_) {
return _impl->wifi_client_->write(buf, size);
}
Serial.println(_impl->no_interface_error_);
return 0;
}
size_t WebSocketsNetworkClient::write(const char *str) {
const int size = strlen(str);
Serial.printf("Send: %zu\n", size);
if (_impl->gsm_client_) {
return _impl->gsm_client_->write((const uint8_t *)str, size);
} else if (_impl->wifi_client_) {
return _impl->wifi_client_->write((const uint8_t *)str, size);
}
Serial.println(_impl->no_interface_error_);
return 0;
}
int WebSocketsNetworkClient::available() {
if (_impl->gsm_client_) {
return _impl->gsm_client_->available();
} else if (_impl->wifi_client_) {
return _impl->wifi_client_->available();
}
Serial.println(_impl->no_interface_error_);
return 0;
}
int WebSocketsNetworkClient::read() {
if (_impl->gsm_client_) {
return _impl->gsm_client_->read();
} else if (_impl->wifi_client_) {
return _impl->wifi_client_->read();
}
Serial.println(_impl->no_interface_error_);
return 0;
}
int WebSocketsNetworkClient::read(uint8_t *buf, size_t size) {
if (_impl->gsm_client_) {
return _impl->gsm_client_->read(buf, size);
} else if (_impl->wifi_client_) {
return _impl->wifi_client_->read(buf, size);
}
Serial.println(_impl->no_interface_error_);
return 0;
}
int WebSocketsNetworkClient::peek() {
if (_impl->gsm_client_) {
return _impl->gsm_client_->peek();
} else if (_impl->wifi_client_) {
return _impl->wifi_client_->peek();
}
Serial.println(_impl->no_interface_error_);
return 0;
}
void WebSocketsNetworkClient::flush() {
if (_impl->gsm_client_) {
return _impl->gsm_client_->flush();
} else if (_impl->wifi_client_) {
return _impl->wifi_client_->flush();
}
Serial.println(_impl->no_interface_error_);
}
void WebSocketsNetworkClient::stop() {
if (_impl->gsm_client_) {
return _impl->gsm_client_->stop();
} else if (_impl->wifi_client_) {
return _impl->wifi_client_->stop();
}
Serial.println(_impl->no_interface_error_);
}
uint8_t WebSocketsNetworkClient::connected() {
if (_impl->gsm_client_) {
return _impl->gsm_client_->connected();
} else if (_impl->wifi_client_) {
return _impl->wifi_client_->connected();
}
Serial.println(_impl->no_interface_error_);
return 0;
}
WebSocketsNetworkClient::operator bool() {
if (_impl->gsm_client_) {
return _impl->gsm_client_->operator bool();
} else if (_impl->wifi_client_) {
return _impl->wifi_client_->operator bool();
}
Serial.println(_impl->no_interface_error_);
return 0;
}

View File

@@ -0,0 +1,8 @@
#include "network_client_impl.h"
std::unique_ptr<WiFiClient> WebSocketsNetworkClient::Impl::wifi_client_ = nullptr;
std::unique_ptr<WiFiClientSecure> WebSocketsNetworkClient::Impl::wifi_client_secure_ =
nullptr;
std::unique_ptr<TinyGsmClient> WebSocketsNetworkClient::Impl::gsm_client_ = nullptr;
std::unique_ptr<SSLClient> WebSocketsNetworkClient::Impl::gsm_client_secure_ = nullptr;
const char *WebSocketsNetworkClient::Impl::no_interface_error_ = "No interface";

View File

@@ -0,0 +1,45 @@
#pragma once
#include <SSLClient.h>
#include <TinyGSM.h>
#include <WebSocketsNetworkClientSecure.h>
#include <WiFiClientSecure.h>
struct WebSocketsNetworkClient::Impl {
static void enableWifi() {
// Do nothing if already enabled
if (wifi_client_ && wifi_client_secure_) {
return;
}
wifi_client_ = std::unique_ptr<WiFiClient>(new WiFiClient());
wifi_client_secure_ =
std::unique_ptr<WiFiClientSecure>(new WiFiClientSecure());
}
static void disableWifi() {
wifi_client_ = nullptr;
wifi_client_secure_ = nullptr;
}
static void enableGsm(TinyGsm* tiny_gsm) {
// Do nothing if already enabled
if (gsm_client_ && gsm_client_secure_) {
return;
}
gsm_client_ = std::unique_ptr<TinyGsmClient>(new TinyGsmClient(*tiny_gsm));
gsm_client_secure_ =
std::unique_ptr<SSLClient>(new SSLClient(gsm_client_.get()));
}
static void disableGsm() {
if (gsm_client_secure_) {
gsm_client_secure_->stop();
}
gsm_client_secure_ = nullptr;
gsm_client_ = nullptr;
}
static std::unique_ptr<WiFiClient> wifi_client_;
static std::unique_ptr<WiFiClientSecure> wifi_client_secure_;
static std::unique_ptr<TinyGsmClient> gsm_client_;
static std::unique_ptr<SSLClient> gsm_client_secure_;
static const char* no_interface_error_;
};

View File

@@ -0,0 +1,191 @@
#include "network_client_impl.h"
WebSocketsNetworkClientSecure::WebSocketsNetworkClientSecure() {}
WebSocketsNetworkClientSecure::WebSocketsNetworkClientSecure(
WiFiClient wifi_client) {}
WebSocketsNetworkClientSecure::~WebSocketsNetworkClientSecure() {
if (_impl->gsm_client_secure_) {
_impl->gsm_client_secure_->stop();
}
}
int WebSocketsNetworkClientSecure::connect(IPAddress ip, uint16_t port) {
if (_impl->gsm_client_secure_) {
return _impl->gsm_client_secure_->connect(ip, port);
} else if (_impl->wifi_client_secure_) {
return _impl->wifi_client_secure_->connect(ip, port);
}
Serial.println(_impl->no_interface_error_);
return 0;
}
int WebSocketsNetworkClientSecure::connect(const char *host, uint16_t port) {
if (_impl->gsm_client_secure_) {
return _impl->gsm_client_secure_->connect(host, port);
} else if (_impl->wifi_client_secure_) {
return _impl->wifi_client_secure_->connect(host, port);
}
Serial.println(_impl->no_interface_error_);
return 0;
}
int WebSocketsNetworkClientSecure::connect(const char *host, uint16_t port,
int32_t timeout_ms) {
if (_impl->gsm_client_secure_) {
// Ignore timeout as will cause read() to block for specified time
return _impl->gsm_client_secure_->connect(host, port);
} else if (_impl->wifi_client_secure_) {
return _impl->wifi_client_secure_->connect(host, port, timeout_ms);
}
Serial.println(_impl->no_interface_error_);
return 0;
}
size_t WebSocketsNetworkClientSecure::write(uint8_t data) {
if (_impl->gsm_client_secure_) {
return _impl->gsm_client_secure_->write(data);
} else if (_impl->wifi_client_secure_) {
return _impl->wifi_client_secure_->write(data);
}
Serial.println(_impl->no_interface_error_);
return 0;
}
size_t WebSocketsNetworkClientSecure::write(const uint8_t *buf, size_t size) {
if (_impl->gsm_client_secure_) {
return _impl->gsm_client_secure_->write(buf, size);
} else if (_impl->wifi_client_secure_) {
return _impl->wifi_client_secure_->write(buf, size);
}
Serial.println(_impl->no_interface_error_);
return 0;
}
size_t WebSocketsNetworkClientSecure::write(const char *str) {
const int size = strlen(str);
if (_impl->gsm_client_secure_) {
return _impl->gsm_client_secure_->write((const uint8_t *)str, size);
} else if (_impl->wifi_client_secure_) {
return _impl->wifi_client_secure_->write((const uint8_t *)str, size);
}
Serial.println(_impl->no_interface_error_);
return 0;
}
int WebSocketsNetworkClientSecure::available() {
if (_impl->gsm_client_secure_) {
return _impl->gsm_client_secure_->available();
} else if (_impl->wifi_client_secure_) {
return _impl->wifi_client_secure_->available();
}
Serial.println(_impl->no_interface_error_);
return 0;
}
int WebSocketsNetworkClientSecure::read() {
if (_impl->gsm_client_secure_) {
return _impl->gsm_client_secure_->read();
} else if (_impl->wifi_client_secure_) {
return _impl->wifi_client_secure_->read();
}
Serial.println(_impl->no_interface_error_);
return 0;
}
int WebSocketsNetworkClientSecure::read(uint8_t *buf, size_t size) {
if (_impl->gsm_client_secure_) {
return _impl->gsm_client_secure_->read(buf, size);
} else if (_impl->wifi_client_secure_) {
return _impl->wifi_client_secure_->read(buf, size);
}
Serial.println(_impl->no_interface_error_);
return 0;
}
int WebSocketsNetworkClientSecure::peek() {
if (_impl->gsm_client_secure_) {
return _impl->gsm_client_secure_->peek();
} else if (_impl->wifi_client_secure_) {
return _impl->wifi_client_secure_->peek();
}
Serial.println(_impl->no_interface_error_);
return 0;
}
void WebSocketsNetworkClientSecure::flush() {
if (_impl->gsm_client_secure_) {
return _impl->gsm_client_secure_->flush();
} else if (_impl->wifi_client_secure_) {
return _impl->wifi_client_secure_->flush();
}
Serial.println(_impl->no_interface_error_);
}
void WebSocketsNetworkClientSecure::stop() {
if (_impl->gsm_client_secure_) {
return _impl->gsm_client_secure_->stop();
} else if (_impl->wifi_client_secure_) {
return _impl->wifi_client_secure_->stop();
}
Serial.println(_impl->no_interface_error_);
}
uint8_t WebSocketsNetworkClientSecure::connected() {
if (_impl->gsm_client_secure_) {
return _impl->gsm_client_secure_->connected();
} else if (_impl->wifi_client_secure_) {
return _impl->wifi_client_secure_->connected();
}
Serial.println(_impl->no_interface_error_);
return 0;
}
WebSocketsNetworkClientSecure::operator bool() {
if (_impl->gsm_client_secure_) {
return _impl->gsm_client_secure_->operator bool();
} else if (_impl->wifi_client_secure_) {
return _impl->wifi_client_secure_->operator bool();
}
Serial.println(_impl->no_interface_error_);
return 0;
}
void WebSocketsNetworkClientSecure::setCACert(const char *rootCA) {
if (_impl->gsm_client_secure_) {
return _impl->gsm_client_secure_->setCertificate(rootCA);
} else if (_impl->wifi_client_secure_) {
return _impl->wifi_client_secure_->setCACert(rootCA);
}
Serial.println(_impl->no_interface_error_);
}
void WebSocketsNetworkClientSecure::setCACertBundle(const uint8_t *bundle) {
if (_impl->gsm_client_secure_) {
return _impl->gsm_client_secure_->setCACertBundle(bundle);
} else if (_impl->wifi_client_secure_) {
return _impl->wifi_client_secure_->setCACertBundle(bundle);
}
Serial.println(_impl->no_interface_error_);
}
void WebSocketsNetworkClientSecure::setInsecure() {
if (_impl->gsm_client_secure_) {
_impl->gsm_client_secure_->setInsecure();
} else if (_impl->wifi_client_secure_) {
_impl->wifi_client_secure_->setInsecure();
}
Serial.println(_impl->no_interface_error_);
}
bool WebSocketsNetworkClientSecure::verify(const char *fingerprint,
const char *domain_name) {
if (_impl->gsm_client_secure_) {
// Simply calling SSLClient::verify() will break TLS handshake
// Can be skipped as verification is done by SSLClient itself,
// ArduinoWebSockets need not call it
return true;
} else if (_impl->wifi_client_secure_) {
return _impl->wifi_client_secure_->verify(fingerprint, domain_name);
}
Serial.println(_impl->no_interface_error_);
return false;
}

View File

@@ -0,0 +1,8 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
*secret*
!*secrets.hpp.template
*x509_crt_bundle.bin

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
Owner,Common Name or Certificate Name
Amazon Trust Services,Amazon Root CA 1
Amazon Trust Services,Amazon Root CA 2
Amazon Trust Services,Amazon Root CA 3
Amazon Trust Services,Amazon Root CA 4
Amazon Trust Services,Starfield Services Root Certificate Authority - G2
DigiCert,Baltimore CyberTrust Root
DigiCert,Cybertrust Global Root
DigiCert,DigiCert Assured ID Root CA
DigiCert,DigiCert Assured ID Root G2
DigiCert,DigiCert Assured ID Root G3
DigiCert,DigiCert Global Root CA
DigiCert,DigiCert Global Root G2
DigiCert,DigiCert Global Root G3
DigiCert,DigiCert High Assurance EV Root CA
DigiCert,DigiCert Trusted Root G4
GlobalSign,GlobalSign ECC Root CA - R5
GlobalSign,GlobalSign Root CA - R3
GlobalSign,GlobalSign Root CA - R6
GlobalSign,GlobalSign Root CA
GoDaddy,Go Daddy Class 2 CA
GoDaddy,Go Daddy Root Certificate Authority - G2
GoDaddy,Starfield Class 2 CA
GoDaddy,Starfield Root Certificate Authority - G2
Google Trust Services LLC (GTS),GlobalSign ECC Root CA - R4
Google Trust Services LLC (GTS),GlobalSign Root CA - R2
Google Trust Services LLC (GTS),GTS Root R1
Google Trust Services LLC (GTS),GTS Root R2
Google Trust Services LLC (GTS),GTS Root R3
Google Trust Services LLC (GTS),GTS Root R4
"IdenTrust Services, LLC",DST Root CA X3
"IdenTrust Services, LLC",IdenTrust Commercial Root CA 1
"IdenTrust Services, LLC",IdenTrust Public Sector Root CA 1
Sectigo,Comodo AAA Services root
Sectigo,COMODO Certification Authority
Sectigo,COMODO ECC Certification Authority
Sectigo,COMODO RSA Certification Authority
Sectigo,USERTrust ECC Certification Authority
Sectigo,USERTrust RSA Certification Authority
1 Owner Common Name or Certificate Name
2 Amazon Trust Services Amazon Root CA 1
3 Amazon Trust Services Amazon Root CA 2
4 Amazon Trust Services Amazon Root CA 3
5 Amazon Trust Services Amazon Root CA 4
6 Amazon Trust Services Starfield Services Root Certificate Authority - G2
7 DigiCert Baltimore CyberTrust Root
8 DigiCert Cybertrust Global Root
9 DigiCert DigiCert Assured ID Root CA
10 DigiCert DigiCert Assured ID Root G2
11 DigiCert DigiCert Assured ID Root G3
12 DigiCert DigiCert Global Root CA
13 DigiCert DigiCert Global Root G2
14 DigiCert DigiCert Global Root G3
15 DigiCert DigiCert High Assurance EV Root CA
16 DigiCert DigiCert Trusted Root G4
17 GlobalSign GlobalSign ECC Root CA - R5
18 GlobalSign GlobalSign Root CA - R3
19 GlobalSign GlobalSign Root CA - R6
20 GlobalSign GlobalSign Root CA
21 GoDaddy Go Daddy Class 2 CA
22 GoDaddy Go Daddy Root Certificate Authority - G2
23 GoDaddy Starfield Class 2 CA
24 GoDaddy Starfield Root Certificate Authority - G2
25 Google Trust Services LLC (GTS) GlobalSign ECC Root CA - R4
26 Google Trust Services LLC (GTS) GlobalSign Root CA - R2
27 Google Trust Services LLC (GTS) GTS Root R1
28 Google Trust Services LLC (GTS) GTS Root R2
29 Google Trust Services LLC (GTS) GTS Root R3
30 Google Trust Services LLC (GTS) GTS Root R4
31 IdenTrust Services, LLC DST Root CA X3
32 IdenTrust Services, LLC IdenTrust Commercial Root CA 1
33 IdenTrust Services, LLC IdenTrust Public Sector Root CA 1
34 Sectigo Comodo AAA Services root
35 Sectigo COMODO Certification Authority
36 Sectigo COMODO ECC Certification Authority
37 Sectigo COMODO RSA Certification Authority
38 Sectigo USERTrust ECC Certification Authority
39 Sectigo USERTrust RSA Certification Authority

View File

@@ -0,0 +1,227 @@
#!/usr/bin/env python
#
# ESP32 x509 certificate bundle generation utility
#
# Converts PEM and DER certificates to a custom bundle format which stores just the
# subject name and public key to reduce space
#
# The bundle will have the format: number of certificates; crt 1 subject name length; crt 1 public key length;
# crt 1 subject name; crt 1 public key; crt 2...
#
# Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http:#www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import with_statement
import argparse
import csv
import os
import re
import struct
import sys
from io import open
try:
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
except ImportError:
print('The cryptography package is not installed.'
'Please refer to the Get Started section of the ESP-IDF Programming Guide for '
'setting up the required packages.')
raise
ca_bundle_bin_file = 'x509_crt_bundle'
quiet = False
def status(msg):
""" Print status message to stderr """
if not quiet:
critical(msg)
def critical(msg):
""" Print critical message to stderr """
sys.stderr.write('gen_crt_bundle.py: ')
sys.stderr.write(msg)
sys.stderr.write('\n')
class CertificateBundle:
def __init__(self):
self.certificates = []
self.compressed_crts = []
if os.path.isfile(ca_bundle_bin_file):
os.remove(ca_bundle_bin_file)
def add_from_path(self, crts_path):
found = False
for file_path in os.listdir(crts_path):
found |= self.add_from_file(os.path.join(crts_path, file_path))
if found is False:
raise InputError('No valid x509 certificates found in %s' % crts_path)
def add_from_file(self, file_path):
try:
if file_path.endswith('.pem'):
status('Parsing certificates from %s' % file_path)
with open(file_path, 'r', encoding='utf-8') as f:
crt_str = f.read()
self.add_from_pem(crt_str)
return True
elif file_path.endswith('.der'):
status('Parsing certificates from %s' % file_path)
with open(file_path, 'rb') as f:
crt_str = f.read()
self.add_from_der(crt_str)
return True
except ValueError:
critical('Invalid certificate in %s' % file_path)
raise InputError('Invalid certificate')
return False
def add_from_pem(self, crt_str):
""" A single PEM file may have multiple certificates """
crt = ''
count = 0
start = False
for strg in crt_str.splitlines(True):
if strg == '-----BEGIN CERTIFICATE-----\n' and start is False:
crt = ''
start = True
elif strg == '-----END CERTIFICATE-----\n' and start is True:
crt += strg + '\n'
start = False
self.certificates.append(x509.load_pem_x509_certificate(crt.encode(), default_backend()))
count += 1
if start is True:
crt += strg
if(count == 0):
raise InputError('No certificate found')
status('Successfully added %d certificates' % count)
def add_from_der(self, crt_str):
self.certificates.append(x509.load_der_x509_certificate(crt_str, default_backend()))
status('Successfully added 1 certificate')
def create_bundle(self):
# Sort certificates in order to do binary search when looking up certificates
self.certificates = sorted(self.certificates, key=lambda cert: cert.subject.public_bytes(default_backend()))
bundle = struct.pack('>H', len(self.certificates))
for crt in self.certificates:
""" Read the public key as DER format """
pub_key = crt.public_key()
pub_key_der = pub_key.public_bytes(serialization.Encoding.DER, serialization.PublicFormat.SubjectPublicKeyInfo)
""" Read the subject name as DER format """
sub_name_der = crt.subject.public_bytes(default_backend())
name_len = len(sub_name_der)
key_len = len(pub_key_der)
len_data = struct.pack('>HH', name_len, key_len)
bundle += len_data
bundle += sub_name_der
bundle += pub_key_der
return bundle
def add_with_filter(self, crts_path, filter_path):
filter_set = set()
with open(filter_path, 'r', encoding='utf-8') as f:
csv_reader = csv.reader(f, delimiter=',')
# Skip header
next(csv_reader)
for row in csv_reader:
filter_set.add(row[1])
status('Parsing certificates from %s' % crts_path)
crt_str = []
with open(crts_path, 'r', encoding='utf-8') as f:
crt_str = f.read()
# Split all certs into a list of (name, certificate string) tuples
pem_crts = re.findall(r'(^.+?)\n(=+\n[\s\S]+?END CERTIFICATE-----\n)', crt_str, re.MULTILINE)
filtered_crts = ''
for name, crt in pem_crts:
if name in filter_set:
filtered_crts += crt
self.add_from_pem(filtered_crts)
class InputError(RuntimeError):
def __init__(self, e):
super(InputError, self).__init__(e)
def main():
global quiet
parser = argparse.ArgumentParser(description='ESP-IDF x509 certificate bundle utility')
parser.add_argument('--quiet', '-q', help="Don't print non-critical status messages to stderr", action='store_true')
parser.add_argument('--input', '-i', nargs='+', required=True,
help='Paths to the custom certificate folders or files to parse, parses all .pem or .der files')
parser.add_argument('--filter', '-f', help='Path to CSV-file where the second columns contains the name of the certificates \
that should be included from cacrt_all.pem')
args = parser.parse_args()
quiet = args.quiet
bundle = CertificateBundle()
for path in args.input:
if os.path.isfile(path):
if os.path.basename(path) == 'cacrt_all.pem' and args.filter:
bundle.add_with_filter(path, args.filter)
else:
bundle.add_from_file(path)
elif os.path.isdir(path):
bundle.add_from_path(path)
else:
raise InputError('Invalid --input=%s, is neither file nor folder' % args.input)
status('Successfully added %d certificates in total' % len(bundle.certificates))
crt_bundle = bundle.create_bundle()
with open(ca_bundle_bin_file, 'wb') as f:
f.write(crt_bundle)
if __name__ == '__main__':
try:
main()
except InputError as e:
print(e)
sys.exit(2)

View File

@@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in a an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

View File

@@ -0,0 +1,25 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
upload_speed = 921600
build_flags =
-DCORE_DEBUG_LEVEL=5
lib_deps = ../../../src
extra_scripts =
pre:run_gen_script.py
board_build.embed_txtfiles =
data/cert/x509_crt_bundle.bin

View File

@@ -0,0 +1,12 @@
This is a PlatformIO project that uses a modified WiFiClientSecure library (in `lib`) to
implement proper SSL support using root certificates as discussed
[here](https://github.com/espressif/arduino-esp32/issues/3646#issuecomment-648292677)
It is based on the work by [meltdonw03](https://github.com/meltdown03) in that thread, and the
[BasicHttpsClient example](https://github.com/espressif/arduino-esp32/blob/1.0.4/libraries/HTTPClient/examples/BasicHttpsClient/BasicHttpsClient.ino) from the arduino-esp32 project.
Just copy `include/secrets.hpp.template` to `include/secrets.hpp` and fill in your WiFi details.
Then it should be pretty much ready to go. The local WiFiClientSecure library should take priority.
Debug is set to verbose, so you'll see a lot of noise, but there should also be this readme on success :)
To get a current CA cert bundle download it from [curl's website](https://curl.se/docs/caextract.html).

View File

@@ -0,0 +1,6 @@
Import("env")
env.Execute("$PYTHONEXE -m pip install cryptography")
env.Execute("$PYTHONEXE gen_crt_bundle.py --input cacrt_all.pem")
env.Execute("mkdir -p data/cert")
env.Execute("mv -f x509_crt_bundle data/cert/x509_crt_bundle.bin")

View File

@@ -0,0 +1,127 @@
/*
* main.cpp
*
* Created on: 15.06.2024
*
*/
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <WebSocketsClient.h>
extern const uint8_t rootca_crt_bundle_start[] asm(
"_binary_data_cert_x509_crt_bundle_bin_start");
WiFiMulti wifiMulti;
WebSocketsClient webSocket;
#define USE_SERIAL Serial
void setClock() {
configTime(0, 0, "pool.ntp.org", "time.nist.gov");
USE_SERIAL.print(F("Waiting for NTP time sync: "));
time_t nowSecs = time(nullptr);
while(nowSecs < 8 * 3600 * 2) {
delay(500);
USE_SERIAL.print(F("."));
yield();
nowSecs = time(nullptr);
}
USE_SERIAL.println();
struct tm timeinfo;
gmtime_r(&nowSecs, &timeinfo);
USE_SERIAL.print(F("Current time: "));
USE_SERIAL.print(asctime(&timeinfo));
}
void hexdump(const void * mem, uint32_t len, uint8_t cols = 16) {
const uint8_t * src = (const uint8_t *)mem;
USE_SERIAL.printf("\n[HEXDUMP] Address: 0x%08X len: 0x%X (%d)", (ptrdiff_t)src, len, len);
for(uint32_t i = 0; i < len; i++) {
if(i % cols == 0) {
USE_SERIAL.printf("\n[0x%08X] 0x%08X: ", (ptrdiff_t)src, i);
}
USE_SERIAL.printf("%02X ", *src);
src++;
}
USE_SERIAL.printf("\n");
}
void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
switch(type) {
case WStype_DISCONNECTED:
USE_SERIAL.printf("[WSc] Disconnected!\n");
break;
case WStype_CONNECTED:
USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload);
// send message to server when Connected
webSocket.sendTXT("Connected");
break;
case WStype_TEXT:
USE_SERIAL.printf("[WSc] get text: %s\n", payload);
// send message to server
// webSocket.sendTXT("message here");
break;
case WStype_BIN:
USE_SERIAL.printf("[WSc] get binary length: %u\n", length);
hexdump(payload, length);
// send data to server
// webSocket.sendBIN(payload, length);
break;
case WStype_ERROR:
case WStype_FRAGMENT_TEXT_START:
case WStype_FRAGMENT_BIN_START:
case WStype_FRAGMENT:
case WStype_FRAGMENT_FIN:
break;
}
}
void setup() {
USE_SERIAL.begin(115200);
USE_SERIAL.setDebugOutput(true);
USE_SERIAL.println();
USE_SERIAL.println();
USE_SERIAL.println();
for(uint8_t t = 4; t > 0; t--) {
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
USE_SERIAL.flush();
delay(1000);
}
wifiMulti.addAP("SSID", "WIFI_PASSPHRASE");
// WiFi.disconnect();
while(wifiMulti.run() != WL_CONNECTED) {
delay(100);
}
setClock();
// server address, port and URL. This server can be flakey.
// Expected response: Request served by 0123456789abcdef
webSocket.beginSslWithBundle("echo.websocket.org", 443, "/", rootca_crt_bundle_start, "");
// event handler
webSocket.onEvent(webSocketEvent);
// use HTTP Basic Authorization this is optional enable if needed
// webSocket.setAuthorization("user", "Password");
// try ever 5000 again if connection has failed
webSocket.setReconnectInterval(5000);
}
void loop() {
webSocket.loop();
}

View File

@@ -0,0 +1,105 @@
/*
* WebSocketClient.ino
*
* Created on: 10.08.2024
*
*/
#include <Arduino.h>
#include <rpcWiFi.h>
#include <WiFiMulti.h>
#include <WebSocketsClient.h>
WebSocketsClient webSocket;
WiFiMulti wifiMulti;
#define USE_SERIAL Serial
void hexdump(const void *mem, uint32_t len, uint8_t cols = 16) {
const uint8_t* src = (const uint8_t*) mem;
USE_SERIAL.printf("\n[HEXDUMP] Address: 0x%08X len: 0x%X (%d)", (ptrdiff_t)src, len, len);
for(uint32_t i = 0; i < len; i++) {
if(i % cols == 0) {
USE_SERIAL.printf("\n[0x%08X] 0x%08X: ", (ptrdiff_t)src, i);
}
USE_SERIAL.printf("%02X ", *src);
src++;
}
USE_SERIAL.printf("\n");
}
void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
switch(type) {
case WStype_DISCONNECTED:
USE_SERIAL.printf("[WSc] Disconnected!\n");
break;
case WStype_CONNECTED:
USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload);
// send message to server when Connected
webSocket.sendTXT("Connected");
break;
case WStype_TEXT:
USE_SERIAL.printf("[WSc] get text: %s\n", payload);
// send message to server
// webSocket.sendTXT("message here");
break;
case WStype_BIN:
USE_SERIAL.printf("[WSc] get binary length: %u\n", length);
hexdump(payload, length);
// send data to server
// webSocket.sendBIN(payload, length);
break;
case WStype_ERROR:
case WStype_FRAGMENT_TEXT_START:
case WStype_FRAGMENT_BIN_START:
case WStype_FRAGMENT:
case WStype_PONG:
case WStype_PING:
case WStype_FRAGMENT_FIN:
break;
}
}
void setup() {
// USE_SERIAL.begin(921600);
USE_SERIAL.begin(115200);
USE_SERIAL.println();
USE_SERIAL.println();
USE_SERIAL.println();
for(uint8_t t = 4; t > 0; t--) {
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
USE_SERIAL.flush();
delay(1000);
}
wifiMulti.addAP("SSID", "passpasspass");
//WiFi.disconnect();
while(wifiMulti.run() != WL_CONNECTED) {
delay(100);
}
// server address, port and URL
webSocket.begin("192.168.0.123", 81, "/");
// event handler
webSocket.onEvent(webSocketEvent);
// use HTTP Basic Authorization this is optional remove if not needed
webSocket.setAuthorization("user", "Password");
// try ever 5000 again if connection has failed
webSocket.setReconnectInterval(5000);
}
void loop() {
webSocket.loop();
}

View File

@@ -16,10 +16,10 @@
"keywords": "wifi, http, web, server, client, websocket",
"license": "LGPL-2.1",
"name": "WebSockets",
"platforms": "atmelavr, espressif8266, espressif32, raspberrypi",
"platforms": "*",
"repository": {
"type": "git",
"url": "https://github.com/Links2004/arduinoWebSockets.git"
},
"version": "2.4.0"
"version": "2.7.0"
}

View File

@@ -1,5 +1,5 @@
name=WebSockets
version=2.4.0
version=2.7.0
author=Markus Sattler
maintainer=Markus Sattler
sentence=WebSockets for Arduino (Server + Client)

View File

@@ -15,39 +15,39 @@ SocketIOclient::SocketIOclient() {
SocketIOclient::~SocketIOclient() {
}
void SocketIOclient::begin(const char * host, uint16_t port, const char * url, const char * protocol) {
void SocketIOclient::begin(const char * host, uint16_t port, const char * url, const char * protocol, uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount) {
WebSocketsClient::beginSocketIO(host, port, url, protocol);
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
WebSocketsClient::enableHeartbeat(pingInterval, pongTimeout, disconnectTimeoutCount);
initClient();
}
void SocketIOclient::begin(String host, uint16_t port, String url, String protocol) {
void SocketIOclient::begin(String host, uint16_t port, String url, String protocol, uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount) {
WebSocketsClient::beginSocketIO(host, port, url, protocol);
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
WebSocketsClient::enableHeartbeat(pingInterval, pongTimeout, disconnectTimeoutCount);
initClient();
}
#if defined(HAS_SSL)
void SocketIOclient::beginSSL(const char * host, uint16_t port, const char * url, const char * protocol) {
void SocketIOclient::beginSSL(const char * host, uint16_t port, const char * url, const char * protocol, uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount) {
WebSocketsClient::beginSocketIOSSL(host, port, url, protocol);
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
WebSocketsClient::enableHeartbeat(pingInterval, pongTimeout, disconnectTimeoutCount);
initClient();
}
void SocketIOclient::beginSSL(String host, uint16_t port, String url, String protocol) {
void SocketIOclient::beginSSL(String host, uint16_t port, String url, String protocol, uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount) {
WebSocketsClient::beginSocketIOSSL(host, port, url, protocol);
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
WebSocketsClient::enableHeartbeat(pingInterval, pongTimeout, disconnectTimeoutCount);
initClient();
}
#if defined(SSL_BARESSL)
void SocketIOclient::beginSSLWithCA(const char * host, uint16_t port, const char * url, const char * CA_cert, const char * protocol) {
void SocketIOclient::beginSSLWithCA(const char * host, uint16_t port, const char * url, const char * CA_cert, const char * protocol, uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount) {
WebSocketsClient::beginSocketIOSSLWithCA(host, port, url, CA_cert, protocol);
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
WebSocketsClient::enableHeartbeat(pingInterval, pongTimeout, disconnectTimeoutCount);
initClient();
}
void SocketIOclient::beginSSLWithCA(const char * host, uint16_t port, const char * url, BearSSL::X509List * CA_cert, const char * protocol) {
void SocketIOclient::beginSSLWithCA(const char * host, uint16_t port, const char * url, BearSSL::X509List * CA_cert, const char * protocol, uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount) {
WebSocketsClient::beginSocketIOSSLWithCA(host, port, url, CA_cert, protocol);
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
WebSocketsClient::enableHeartbeat(pingInterval, pongTimeout, disconnectTimeoutCount);
initClient();
}
@@ -93,6 +93,10 @@ void SocketIOclient::setReconnectInterval(unsigned long time) {
return WebSocketsClient::setReconnectInterval(time);
}
void SocketIOclient::disconnect(void) {
WebSocketsClient::disconnect();
}
/**
* send text data to client
* @param num uint8_t client id
@@ -257,4 +261,4 @@ void SocketIOclient::handleCbEvent(WStype_t type, uint8_t * payload, size_t leng
case WStype_PONG:
break;
}
}
}

View File

@@ -47,22 +47,25 @@ class SocketIOclient : protected WebSocketsClient {
SocketIOclient(void);
virtual ~SocketIOclient(void);
void begin(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino");
void begin(String host, uint16_t port, String url = "/socket.io/?EIO=3", String protocol = "arduino");
void begin(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino", uint32_t pingInterval = 60 * 1000, uint32_t pongTimeout = 90 * 1000, uint8_t disconnectTimeoutCount = 5);
void begin(String host, uint16_t port, String url = "/socket.io/?EIO=3", String protocol = "arduino", uint32_t pingInterval = 60 * 1000, uint32_t pongTimeout = 90 * 1000, uint8_t disconnectTimeoutCount = 5);
#ifdef HAS_SSL
void beginSSL(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino");
void beginSSL(String host, uint16_t port, String url = "/socket.io/?EIO=3", String protocol = "arduino");
void beginSSL(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino", uint32_t pingInterval = 60 * 1000, uint32_t pongTimeout = 90 * 1000, uint8_t disconnectTimeoutCount = 5);
void beginSSL(String host, uint16_t port, String url = "/socket.io/?EIO=3", String protocol = "arduino", uint32_t pingInterval = 60 * 1000, uint32_t pongTimeout = 90 * 1000, uint8_t disconnectTimeoutCount = 5);
#ifndef SSL_AXTLS
void beginSSLWithCA(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * CA_cert = NULL, const char * protocol = "arduino");
void beginSSLWithCA(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", BearSSL::X509List * CA_cert = NULL, const char * protocol = "arduino");
void beginSSLWithCA(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * CA_cert = NULL, const char * protocol = "arduino", uint32_t pingInterval = 60 * 1000, uint32_t pongTimeout = 90 * 1000, uint8_t disconnectTimeoutCount = 5);
void setSSLClientCertKey(const char * clientCert = NULL, const char * clientPrivateKey = NULL);
#if defined(SSL_BARESSL)
void beginSSLWithCA(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", BearSSL::X509List * CA_cert = NULL, const char * protocol = "arduino", uint32_t pingInterval = 60 * 1000, uint32_t pongTimeout = 90 * 1000, uint8_t disconnectTimeoutCount = 5);
void setSSLClientCertKey(BearSSL::X509List * clientCert = NULL, BearSSL::PrivateKey * clientPrivateKey = NULL);
#endif
#endif
#endif
bool isConnected(void);
void onEvent(SocketIOclientEvent cbEvent);
void disconnect(void);
bool sendEVENT(uint8_t * payload, size_t length = 0, bool headerToPayload = false);
bool sendEVENT(const uint8_t * payload, size_t length = 0);

View File

@@ -42,7 +42,7 @@ extern "C" {
#include <esp_system.h>
#if ESP_IDF_VERSION_MAJOR >= 4
#if(ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(1, 0, 6))
#if (ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(1, 0, 6))
#include "sha/sha_parallel_engine.h"
#else
#include <esp32/sha.h>
@@ -328,7 +328,7 @@ void WebSockets::headerDone(WSclient_t * client) {
client->status = WSC_CONNECTED;
client->cWsRXsize = 0;
DEBUG_WEBSOCKETS("[WS][%d][headerDone] Header Handling Done.\n", client->num);
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
client->cHttpLine = "";
handleWebsocket(client);
#endif
@@ -525,7 +525,7 @@ void WebSockets::handleWebsocketPayloadCb(WSclient_t * client, bool ok, uint8_t
// reset input
client->cWsRXsize = 0;
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
// register callback for next message
handleWebsocketWaitFor(client, 2);
#endif
@@ -571,6 +571,7 @@ String WebSockets::acceptKey(String & clientKey) {
*/
String WebSockets::base64_encode(uint8_t * data, size_t length) {
size_t size = ((length * 1.6f) + 1);
size = std::max(size, (size_t)5); // minimum buffer size
char * buffer = (char *)malloc(size);
if(buffer) {
base64_encodestate _state;
@@ -593,7 +594,7 @@ String WebSockets::base64_encode(uint8_t * data, size_t length) {
* @return true if ok
*/
bool WebSockets::readCb(WSclient_t * client, uint8_t * out, size_t n, WSreadWaitCb cb) {
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
if(!client->tcp || !client->tcp->connected()) {
return false;
}
@@ -749,7 +750,7 @@ void WebSockets::handleHBTimeout(WSclient_t * client) {
client->pongTimeoutCount++;
client->lastPing = millis() - client->pingInterval - 500; // force ping on the next run
DEBUG_WEBSOCKETS("[HBtimeout] pong TIMEOUT! lp=%d millis=%d pi=%d count=%d\n", client->lastPing, millis(), pi, client->pongTimeoutCount);
DEBUG_WEBSOCKETS("[HBtimeout] pong TIMEOUT! lp=%d millis=%lu pi=%d count=%d\n", client->lastPing, millis(), pi, client->pongTimeoutCount);
if(client->disconnectTimeoutCount && client->pongTimeoutCount >= client->disconnectTimeoutCount) {
DEBUG_WEBSOCKETS("[HBtimeout] count=%d, DISCONNECTING\n", client->pongTimeoutCount);

View File

@@ -93,6 +93,24 @@
#define WEBSOCKETS_YIELD() yield()
#define WEBSOCKETS_YIELD_MORE() delay(1)
#elif defined(ARDUINO_UNOWIFIR4)
#define WEBSOCKETS_MAX_DATA_SIZE (15 * 1024)
#define WEBSOCKETS_YIELD() yield()
#define WEBSOCKETS_YIELD_MORE() delay(1)
#elif defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT)
#define WEBSOCKETS_MAX_DATA_SIZE (15 * 1024)
#define WEBSOCKETS_YIELD() yield()
#define WEBSOCKETS_YIELD_MORE() delay(1)
#elif defined(WIO_TERMINAL) || defined(SEEED_XIAO_M0)
#define WEBSOCKETS_MAX_DATA_SIZE (15 * 1024)
#define WEBSOCKETS_YIELD() yield()
#define WEBSOCKETS_YIELD_MORE() delay(1)
#else
// atmega328p has only 2KB ram!
@@ -114,6 +132,10 @@
#define NETWORK_ESP32 (4)
#define NETWORK_ESP32_ETH (5)
#define NETWORK_RP2040 (6)
#define NETWORK_UNOWIFIR4 (7)
#define NETWORK_WIFI_NINA (8)
#define NETWORK_SAMD_SEED (9)
#define NETWORK_CUSTOM (10)
// max size of the WS Message Header
#define WEBSOCKETS_MAX_HEADER_SIZE (14)
@@ -132,6 +154,15 @@
#elif defined(ARDUINO_ARCH_RP2040)
#define WEBSOCKETS_NETWORK_TYPE NETWORK_RP2040
#elif defined(ARDUINO_UNOWIFIR4)
#define WEBSOCKETS_NETWORK_TYPE NETWORK_UNOWIFIR4
#elif defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT)
#define WEBSOCKETS_NETWORK_TYPE NETWORK_WIFI_NINA
#elif defined(WIO_TERMINAL) || defined(SEEED_XIAO_M0)
#define WEBSOCKETS_NETWORK_TYPE NETWORK_SAMD_SEED
#else
#define WEBSOCKETS_NETWORK_TYPE NETWORK_W5100
@@ -139,7 +170,7 @@
#endif
// Includes and defined based on Network Type
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
// Note:
// No SSL/WSS support for client in Async mode
@@ -162,7 +193,7 @@
#define WEBSOCKETS_NETWORK_CLASS AsyncTCPbuffer
#define WEBSOCKETS_NETWORK_SERVER_CLASS AsyncServer
#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
#if !defined(ESP8266) && !defined(ESP31B)
#error "network type ESP8266 only possible on the ESP mcu!"
@@ -182,7 +213,7 @@
#define WEBSOCKETS_NETWORK_SSL_CLASS WiFiClientSecure
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_W5100)
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_W5100)
#ifdef STM32_DEVICE
#define WEBSOCKETS_NETWORK_CLASS TCPClient
@@ -194,13 +225,13 @@
#define WEBSOCKETS_NETWORK_SERVER_CLASS EthernetServer
#endif
#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_ENC28J60)
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ENC28J60)
#include <UIPEthernet.h>
#define WEBSOCKETS_NETWORK_CLASS UIPClient
#define WEBSOCKETS_NETWORK_SERVER_CLASS UIPServer
#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
#include <WiFi.h>
#include <WiFiClientSecure.h>
@@ -209,13 +240,13 @@
#define WEBSOCKETS_NETWORK_SSL_CLASS WiFiClientSecure
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32_ETH)
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32_ETH)
#include <ETH.h>
#define WEBSOCKETS_NETWORK_CLASS WiFiClient
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
#include <WiFi.h>
#include <WiFiClientSecure.h>
@@ -224,6 +255,46 @@
#define WEBSOCKETS_NETWORK_SSL_CLASS WiFiClientSecure
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_UNOWIFIR4)
#include <WiFiS3.h>
#define WEBSOCKETS_NETWORK_CLASS WiFiClient
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_WIFI_NINA)
#if __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#else
#error "Please install WiFiNINA library!"
#endif
#define WEBSOCKETS_NETWORK_CLASS WiFiClient
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
#define WEBSOCKETS_NETWORK_SSL_CLASS WiFiSSLClient
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_SAMD_SEED)
#if __has_include(<rpcWiFi.h>) && __has_include(<rpcWiFiClientSecure.h>)
#include <rpcWiFi.h>
#include <rpcWiFiClientSecure.h>
#else
#error "Please install rpcWiFi library!"
#endif
#define WEBSOCKETS_NETWORK_CLASS WiFiClient
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
#define WEBSOCKETS_NETWORK_SSL_CLASS WiFiClientSecure
#define WEBSOCKETS_NETWORK_CLASS WiFiClient
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_CUSTOM)
#include <WebSocketsNetworkClientSecure.h>
#include <WiFiServer.h>
#define SSL_AXTLS
#define WEBSOCKETS_NETWORK_CLASS WebSocketsNetworkClient
#define WEBSOCKETS_NETWORK_SSL_CLASS WebSocketsNetworkClientSecure
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
#else
#error "no network type selected!"
#endif
@@ -305,8 +376,8 @@ typedef struct {
bool isSocketIO = false; ///< client for socket.io server
#if defined(HAS_SSL)
bool isSSL = false; ///< run in ssl mode
WEBSOCKETS_NETWORK_SSL_CLASS * ssl;
bool isSSL = false; ///< run in ssl mode
WEBSOCKETS_NETWORK_SSL_CLASS * ssl = nullptr;
#endif
String cUrl; ///< http url
@@ -342,7 +413,7 @@ typedef struct {
uint8_t disconnectTimeoutCount = 0; // after how many subsequent pong timeouts discconnect will happen, 0 means "do not disconnect"
uint8_t pongTimeoutCount = 0; // current pong timeout count
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
String cHttpLine; ///< HTTP header lines
#endif

View File

@@ -28,7 +28,7 @@
#include <WebSocketsServer.h>
#include <ESP8266WebServer.h>
#if((WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)) && WEBSERVER_HAS_HOOK
#if ((WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)) && WEBSERVER_HAS_HOOK
class WebSockets4WebServer : public WebSocketsServerCore {
#if defined(ESP8266)

View File

@@ -48,6 +48,12 @@ void WebSocketsClient::begin(const char * host, uint16_t port, const char * url,
#if defined(HAS_SSL)
_fingerprint = SSL_FINGERPRINT_NULL;
_CA_cert = NULL;
#ifdef ESP32
_CA_bundle = NULL;
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 4)
_CA_bundle_size = 0;
#endif
#endif
#endif
_client.num = 0;
@@ -82,7 +88,7 @@ void WebSocketsClient::begin(const char * host, uint16_t port, const char * url,
// todo find better seed
randomSeed(millis());
#endif
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
asyncConnect();
#endif
@@ -107,6 +113,7 @@ void WebSocketsClient::beginSSL(const char * host, uint16_t port, const char * u
_client.isSSL = true;
_fingerprint = fingerprint;
_CA_cert = NULL;
_CA_bundle = NULL;
}
void WebSocketsClient::beginSSL(String host, uint16_t port, String url, String fingerprint, String protocol) {
@@ -118,7 +125,28 @@ void WebSocketsClient::beginSslWithCA(const char * host, uint16_t port, const ch
_client.isSSL = true;
_fingerprint = SSL_FINGERPRINT_NULL;
_CA_cert = CA_cert;
_CA_bundle = NULL;
}
#if defined(ESP32) && ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 4)
void WebSocketsClient::beginSslWithBundle(const char * host, uint16_t port, const char * url, const uint8_t * CA_bundle, size_t CA_bundle_size, const char * protocol) {
begin(host, port, url, protocol);
_client.isSSL = true;
_fingerprint = SSL_FINGERPRINT_NULL;
_CA_cert = NULL;
_CA_bundle = CA_bundle;
_CA_bundle_size = CA_bundle_size;
}
#else
void WebSocketsClient::beginSslWithBundle(const char * host, uint16_t port, const char * url, const uint8_t * CA_bundle, const char * protocol) {
begin(host, port, url, protocol);
_client.isSSL = true;
_fingerprint = SSL_FINGERPRINT_NULL;
_CA_cert = NULL;
_CA_bundle = CA_bundle;
}
#endif
#else
void WebSocketsClient::beginSSL(const char * host, uint16_t port, const char * url, const uint8_t * fingerprint, const char * protocol) {
begin(host, port, url, protocol);
@@ -127,6 +155,7 @@ void WebSocketsClient::beginSSL(const char * host, uint16_t port, const char * u
_CA_cert = NULL;
}
#if defined(SSL_BARESSL)
void WebSocketsClient::beginSslWithCA(const char * host, uint16_t port, const char * url, BearSSL::X509List * CA_cert, const char * protocol) {
begin(host, port, url, protocol);
_client.isSSL = true;
@@ -138,14 +167,15 @@ void WebSocketsClient::beginSslWithCA(const char * host, uint16_t port, const ch
beginSslWithCA(host, port, url, new BearSSL::X509List(CA_cert), protocol);
}
void WebSocketsClient::setSSLClientCertKey(const char * clientCert, const char * clientPrivateKey) {
setSSLClientCertKey(new BearSSL::X509List(clientCert), new BearSSL::PrivateKey(clientPrivateKey));
}
void WebSocketsClient::setSSLClientCertKey(BearSSL::X509List * clientCert, BearSSL::PrivateKey * clientPrivateKey) {
_client_cert = clientCert;
_client_key = clientPrivateKey;
}
void WebSocketsClient::setSSLClientCertKey(const char * clientCert, const char * clientPrivateKey) {
setSSLClientCertKey(new BearSSL::X509List(clientCert), new BearSSL::PrivateKey(clientPrivateKey));
}
#endif // SSL_BARESSL
#endif // SSL_AXTLS
#endif // HAS_SSL
@@ -195,7 +225,7 @@ void WebSocketsClient::beginSocketIOSSLWithCA(const char * host, uint16_t port,
#endif
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
/**
* called in arduino loop
*/
@@ -214,7 +244,12 @@ void WebSocketsClient::loop(void) {
if(_client.isSSL) {
DEBUG_WEBSOCKETS("[WS-Client] connect wss...\n");
if(_client.ssl) {
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_WIFI_NINA) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_SAMD_SEED) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_UNOWIFIR4)
// does not support delete (no destructor)
#else
delete _client.ssl;
#endif
_client.ssl = NULL;
_client.tcp = NULL;
}
@@ -226,12 +261,23 @@ void WebSocketsClient::loop(void) {
_client.ssl->setCACert(_CA_cert);
#elif defined(ESP8266) && defined(SSL_AXTLS)
_client.ssl->setCACert((const uint8_t *)_CA_cert, strlen(_CA_cert) + 1);
#elif(defined(ESP8266) || defined(ARDUINO_ARCH_RP2040)) && defined(SSL_BARESSL)
#elif (defined(ESP8266) || defined(ARDUINO_ARCH_RP2040)) && defined(SSL_BARESSL)
_client.ssl->setTrustAnchors(_CA_cert);
#elif defined(WIO_TERMINAL) || defined(SEEED_XIAO_M0)
_client.ssl->setCACert(_CA_cert);
#elif defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT)
// no setCACert
#else
#error setCACert not implemented
#endif
#if defined(ESP32)
} else if(_CA_bundle) {
DEBUG_WEBSOCKETS("[WS-Client] setting CA bundle");
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 4)
_client.ssl->setCACertBundle(_CA_bundle, _CA_bundle_size);
#else
_client.ssl->setCACertBundle(_CA_bundle);
#endif
} else if(!SSL_FINGERPRINT_IS_SET) {
_client.ssl->setInsecure();
#elif defined(SSL_BARESSL)
@@ -248,7 +294,11 @@ void WebSocketsClient::loop(void) {
} else {
DEBUG_WEBSOCKETS("[WS-Client] connect ws...\n");
if(_client.tcp) {
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_WIFI_NINA) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_SAMD_SEED) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_UNOWIFIR4)
// does not support delete (no destructor)
#else
delete _client.tcp;
#endif
_client.tcp = NULL;
}
_client.tcp = new WEBSOCKETS_NETWORK_CLASS();
@@ -475,7 +525,7 @@ void WebSocketsClient::messageReceived(WSclient_t * client, WSopcode_t opcode, u
void WebSocketsClient::clientDisconnect(WSclient_t * client) {
bool event = false;
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
#ifdef HAS_SSL
if(client->isSSL && client->ssl) {
if(client->ssl->connected()) {
client->ssl->flush();
@@ -490,16 +540,20 @@ void WebSocketsClient::clientDisconnect(WSclient_t * client) {
if(client->tcp) {
if(client->tcp->connected()) {
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
client->tcp->flush();
#endif
client->tcp->stop();
}
event = true;
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
client->status = WSC_NOT_CONNECTED;
#else
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_WIFI_NINA) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_SAMD_SEED) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_UNOWIFIR4)
// does not support delete (no destructor)
#else
delete client->tcp;
#endif
#endif
client->tcp = NULL;
}
@@ -551,7 +605,7 @@ bool WebSocketsClient::clientIsConnected(WSclient_t * client) {
return false;
}
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
/**
* Handel incomming data from Client
*/
@@ -672,7 +726,7 @@ void WebSocketsClient::sendHeader(WSclient_t * client) {
DEBUG_WEBSOCKETS("[WS-Client][sendHeader] handshake %s", (uint8_t *)handshake.c_str());
write(client, (uint8_t *)handshake.c_str(), handshake.length());
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsClient::handleHeader, this, client, &(client->cHttpLine)));
#endif
@@ -747,7 +801,7 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
}
(*headerLine) = "";
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsClient::handleHeader, this, client, &(client->cHttpLine)));
#endif
} else {
@@ -817,7 +871,7 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
headerDone(client);
runCbEvent(WStype_CONNECTED, (uint8_t *)client->cUrl.c_str(), client->cUrl.length());
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
} else if(client->isSocketIO) {
if(client->cSessionId.length() > 0) {
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] found cSessionId\n");
@@ -845,7 +899,7 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
void WebSocketsClient::connectedCb() {
DEBUG_WEBSOCKETS("[WS-Client] connected to %s:%u.\n", _host.c_str(), _port);
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
_client.tcp->onDisconnect(std::bind([](WebSocketsClient * c, AsyncTCPbuffer * obj, WSclient_t * client) -> bool {
DEBUG_WEBSOCKETS("[WS-Server][%d] Disconnect client\n", client->num);
client->status = WSC_NOT_CONNECTED;
@@ -861,12 +915,12 @@ void WebSocketsClient::connectedCb() {
_client.status = WSC_HEADER;
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
// set Timeout for readBytesUntil and readStringUntil
_client.tcp->setTimeout(WEBSOCKETS_TCP_TIMEOUT);
#endif
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
_client.tcp->setNoDelay(true);
#endif
@@ -896,7 +950,7 @@ void WebSocketsClient::connectFailedCb() {
DEBUG_WEBSOCKETS("[WS-Client] connection to %s:%u Failed\n", _host.c_str(), _port);
}
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
void WebSocketsClient::asyncConnect() {
DEBUG_WEBSOCKETS("[WS-Client] asyncConnect...\n");

View File

@@ -48,11 +48,20 @@ class WebSocketsClient : protected WebSockets {
void beginSSL(String host, uint16_t port, String url = "/", String fingerprint = "", String protocol = "arduino");
#else
void beginSSL(const char * host, uint16_t port, const char * url = "/", const uint8_t * fingerprint = NULL, const char * protocol = "arduino");
#if defined(SSL_BARESSL)
void beginSslWithCA(const char * host, uint16_t port, const char * url = "/", BearSSL::X509List * CA_cert = NULL, const char * protocol = "arduino");
void setSSLClientCertKey(BearSSL::X509List * clientCert = NULL, BearSSL::PrivateKey * clientPrivateKey = NULL);
#endif
void setSSLClientCertKey(const char * clientCert = NULL, const char * clientPrivateKey = NULL);
#endif
void beginSslWithCA(const char * host, uint16_t port, const char * url = "/", const char * CA_cert = NULL, const char * protocol = "arduino");
#ifdef ESP32
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 4)
void beginSslWithBundle(const char * host, uint16_t port, const char * url = "/", const uint8_t * CA_bundle = NULL, size_t CA_bundle_size = 0, const char * protocol = "arduino");
#else
void beginSslWithBundle(const char * host, uint16_t port, const char * url = "/", const uint8_t * CA_bundle = NULL, const char * protocol = "arduino");
#endif
#endif
#endif
void beginSocketIO(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino");
@@ -68,7 +77,7 @@ class WebSocketsClient : protected WebSockets {
#endif
#endif
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
void loop(void);
#else
// Async interface not need a loop call
@@ -112,17 +121,30 @@ class WebSocketsClient : protected WebSockets {
#ifdef SSL_AXTLS
String _fingerprint;
const char * _CA_cert;
const uint8_t * _CA_bundle;
#if defined(ESP32)
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 4)
size_t _CA_bundle_size;
#endif
#endif
#define SSL_FINGERPRINT_IS_SET (_fingerprint.length())
#define SSL_FINGERPRINT_NULL ""
#else
const uint8_t * _fingerprint;
#if defined(SSL_BARESSL)
BearSSL::X509List * _CA_cert;
BearSSL::X509List * _client_cert;
BearSSL::PrivateKey * _client_key;
#endif
#define SSL_FINGERPRINT_IS_SET (_fingerprint != NULL)
#define SSL_FINGERPRINT_NULL NULL
#endif
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_SAMD_SEED) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_WIFI_NINA)
const char * _CA_cert;
const uint8_t * _CA_bundle;
#endif
#endif
WSclient_t _client;
@@ -137,7 +159,7 @@ class WebSocketsClient : protected WebSockets {
void clientDisconnect(WSclient_t * client);
bool clientIsConnected(WSclient_t * client);
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
void handleClientData(void);
#endif
@@ -149,7 +171,7 @@ class WebSocketsClient : protected WebSockets {
void handleHBPing(); // send ping in specified intervals
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
void asyncConnect();
#endif

View File

@@ -0,0 +1,29 @@
#pragma once
#include <Client.h>
#include <WiFiClient.h>
class WebSocketsNetworkClient : public Client {
public:
struct Impl;
std::unique_ptr<Impl> _impl;
WebSocketsNetworkClient();
WebSocketsNetworkClient(WiFiClient wifi_client);
virtual ~WebSocketsNetworkClient();
virtual int connect(IPAddress ip, uint16_t port);
virtual int connect(const char * host, uint16_t port);
virtual int connect(const char * host, uint16_t port, int32_t timeout);
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t * buf, size_t size);
virtual size_t write(const char * str);
virtual int available();
virtual int read();
virtual int read(uint8_t * buf, size_t size);
virtual int peek();
virtual void flush();
virtual void stop();
virtual uint8_t connected();
virtual operator bool();
};

View File

@@ -0,0 +1,30 @@
#pragma once
#include <WebSocketsNetworkClient.h>
class WebSocketsNetworkClientSecure : public WebSocketsNetworkClient {
public:
WebSocketsNetworkClientSecure();
WebSocketsNetworkClientSecure(WiFiClient wifi_client);
virtual ~WebSocketsNetworkClientSecure();
int connect(IPAddress ip, uint16_t port) override;
int connect(const char * host, uint16_t port) override;
int connect(const char * host, uint16_t port, int32_t timeout) override;
size_t write(uint8_t) override;
size_t write(const uint8_t * buf, size_t size) override;
size_t write(const char * str) override;
int available() override;
int read() override;
int read(uint8_t * buf, size_t size) override;
int peek() override;
void flush() override;
void stop() override;
uint8_t connected() override;
operator bool() override;
void setCACert(const char * rootCA);
void setCACertBundle(const uint8_t * bundle);
void setInsecure();
bool verify(const char * fingerprint, const char * domain_name);
};

View File

@@ -25,6 +25,14 @@
#include "WebSockets.h"
#include "WebSocketsServer.h"
#ifdef ESP32
#if defined __has_include
#if __has_include("soc/wdev_reg.h")
#include "soc/wdev_reg.h"
#endif // __has_include
#endif // defined __has_include
#endif
WebSocketsServerCore::WebSocketsServerCore(const String & origin, const String & protocol) {
_origin = origin;
_protocol = protocol;
@@ -46,7 +54,7 @@ WebSocketsServer::WebSocketsServer(uint16_t port, const String & origin, const S
_server = new WEBSOCKETS_NETWORK_SERVER_CLASS(port);
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
_server->onClient([](void * s, AsyncClient * c) {
((WebSocketsServerCore *)s)->newClient(new AsyncTCPbuffer(c));
},
@@ -65,6 +73,11 @@ WebSocketsServerCore::~WebSocketsServerCore() {
}
WebSocketsServer::~WebSocketsServer() {
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_WIFI_NINA) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_SAMD_SEED)
// does not support delete (no destructor)
#else
delete _server;
#endif
}
/**
@@ -82,6 +95,8 @@ void WebSocketsServerCore::begin(void) {
#ifdef ESP8266
randomSeed(RANDOM_REG32);
#elif defined(ESP32) && defined(WDEV_RND_REG)
randomSeed(REG_READ(WDEV_RND_REG));
#elif defined(ESP32)
#define DR_REG_RNG_BASE 0x3ff75144
randomSeed(READ_PERI_REG(DR_REG_RNG_BASE));
@@ -396,7 +411,7 @@ bool WebSocketsServerCore::clientIsConnected(uint8_t num) {
return clientIsConnected(client);
}
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
/**
* get an IP for a client
* @param num uint8_t client id
@@ -428,20 +443,28 @@ WSclient_t * WebSocketsServerCore::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclien
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
client = &_clients[i];
// state is not connected or tcp connection is lost
if(!clientIsConnected(client)) {
// look for match to existing socket before creating a new one
if(clientIsConnected(client)) {
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_W5100)
// Check to see if it is the same socket - if so, return it
if(client->tcp->getSocketNumber() == TCPclient->getSocketNumber()) {
return client;
}
#endif
} else {
// state is not connected or tcp connection is lost
client->tcp = TCPclient;
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
client->isSSL = false;
client->tcp->setNoDelay(true);
#endif
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
// set Timeout for readBytesUntil and readStringUntil
client->tcp->setTimeout(WEBSOCKETS_TCP_TIMEOUT);
#endif
client->status = WSC_HEADER;
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
#ifndef NODEBUG_WEBSOCKETS
IPAddress ip = client->tcp->remoteIP();
#endif
@@ -450,7 +473,7 @@ WSclient_t * WebSocketsServerCore::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclien
DEBUG_WEBSOCKETS("[WS-Server][%d] new client\n", client->num);
#endif
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
client->tcp->onDisconnect(std::bind([](WebSocketsServerCore * server, AsyncTCPbuffer * obj, WSclient_t * client) -> bool {
DEBUG_WEBSOCKETS("[WS-Server][%d] Disconnect client\n", client->num);
@@ -523,13 +546,15 @@ void WebSocketsServerCore::dropNativeClient(WSclient_t * client) {
}
if(client->tcp) {
if(client->tcp->connected()) {
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) && (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP32) && (WEBSOCKETS_NETWORK_TYPE != NETWORK_RP2040)
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) && (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP32) && (WEBSOCKETS_NETWORK_TYPE != NETWORK_RP2040)
client->tcp->flush();
#endif
client->tcp->stop();
}
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
client->status = WSC_NOT_CONNECTED;
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_WIFI_NINA) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_SAMD_SEED)
// does not support delete (no destructor)
#else
delete client->tcp;
#endif
@@ -542,7 +567,7 @@ void WebSocketsServerCore::dropNativeClient(WSclient_t * client) {
* @param client WSclient_t * ptr to the client struct
*/
void WebSocketsServerCore::clientDisconnect(WSclient_t * client) {
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
if(client->isSSL && client->ssl) {
if(client->ssl->connected()) {
client->ssl->flush();
@@ -565,7 +590,7 @@ void WebSocketsServerCore::clientDisconnect(WSclient_t * client) {
client->cWsRXsize = 0;
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
client->cHttpLine = "";
#endif
@@ -607,7 +632,7 @@ bool WebSocketsServerCore::clientIsConnected(WSclient_t * client) {
return false;
}
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
/**
* Handle incoming Connection Request
*/
@@ -616,7 +641,7 @@ WSclient_t * WebSocketsServerCore::handleNewClient(WEBSOCKETS_NETWORK_CLASS * tc
if(!client) {
// no free space to handle client
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
#ifndef NODEBUG_WEBSOCKETS
IPAddress ip = tcpClient->remoteIP();
#endif
@@ -641,12 +666,17 @@ WSclient_t * WebSocketsServerCore::handleNewClient(WEBSOCKETS_NETWORK_CLASS * tc
* Handle incoming Connection Request
*/
void WebSocketsServer::handleNewClients(void) {
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
while(_server->hasClient()) {
#endif
// store new connection
// store new connection
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_WIFI_NINA)
WEBSOCKETS_NETWORK_CLASS * tcpClient = new WEBSOCKETS_NETWORK_CLASS(_server->available());
#else
WEBSOCKETS_NETWORK_CLASS * tcpClient = new WEBSOCKETS_NETWORK_CLASS(_server->accept());
#endif
if(!tcpClient) {
DEBUG_WEBSOCKETS("[WS-Client] creating Network class failed!");
return;
@@ -654,7 +684,7 @@ void WebSocketsServer::handleNewClients(void) {
handleNewClient(tcpClient);
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
}
#endif
}
@@ -768,7 +798,7 @@ void WebSocketsServerCore::handleHeader(WSclient_t * client, String * headerLine
}
(*headerLine) = "";
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsServerCore::handleHeader, this, client, &(client->cHttpLine)));
#endif
} else {
@@ -925,16 +955,16 @@ void WebSocketsServer::begin(void) {
void WebSocketsServer::close(void) {
WebSocketsServerCore::close();
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
_server->close();
#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
_server->end();
#else
// TODO how to close server?
#endif
}
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
/**
* called in arduino loop
*/

View File

@@ -90,11 +90,11 @@ class WebSocketsServerCore : protected WebSockets {
void enableHeartbeat(uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount);
void disableHeartbeat();
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
IPAddress remoteIP(uint8_t num);
#endif
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
void loop(void); // handle client data only
#endif
@@ -123,7 +123,7 @@ class WebSocketsServerCore : protected WebSockets {
void clientDisconnect(WSclient_t * client);
bool clientIsConnected(WSclient_t * client);
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
void handleClientData(void);
#endif
@@ -199,7 +199,7 @@ class WebSocketsServerCore : protected WebSockets {
return true;
}
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
WSclient_t * handleNewClient(WEBSOCKETS_NETWORK_CLASS * tcpClient);
#endif
@@ -224,7 +224,7 @@ class WebSocketsServer : public WebSocketsServerCore {
void begin(void);
void close(void);
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
void loop(void); // handle incoming client and client data
#else
// Async interface not need a loop call
@@ -232,7 +232,7 @@ class WebSocketsServer : public WebSocketsServerCore {
#endif
protected:
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
void handleNewClients(void);
#endif

View File

@@ -1,6 +1,6 @@
/**
* @file WebSocketsVersion.h
* @date 01.05.2023
* @date 13.08.2025
* @author Markus Sattler
*
* Copyright (c) 2015 Markus Sattler. All rights reserved.
@@ -25,12 +25,12 @@
#ifndef WEBSOCKETSVERSION_H_
#define WEBSOCKETSVERSION_H_
#define WEBSOCKETS_VERSION "2.4.0"
#define WEBSOCKETS_VERSION "2.7.0"
#define WEBSOCKETS_VERSION_MAJOR 2
#define WEBSOCKETS_VERSION_MINOR 4
#define WEBSOCKETS_VERSION_MINOR 7
#define WEBSOCKETS_VERSION_PATCH 0
#define WEBSOCKETS_VERSION_INT 2004000
#define WEBSOCKETS_VERSION_INT 2007000
#endif /* WEBSOCKETSVERSION_H_ */

View File

@@ -9,7 +9,7 @@ For details, see http://sourceforge.net/projects/libb64
#include <core_esp8266_features.h>
#endif
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(WIO_TERMINAL) || defined(SEEED_XIAO_M0)
#define CORE_HAS_LIBB64
#endif

View File

@@ -9,7 +9,7 @@ For details, see http://sourceforge.net/projects/libb64
#include <core_esp8266_features.h>
#endif
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(WIO_TERMINAL) || defined(SEEED_XIAO_M0)
#define CORE_HAS_LIBB64
#endif

View File

@@ -1,6 +1,5 @@
#!/bin/bash
set -x
set -e
function build_sketches()
{
@@ -29,6 +28,23 @@ function build_sketches()
done
}
function build_sketch_cli()
{
local sketch=$1
local board=$2
arduino-cli --log --log-level info compile -b "$board" "$sketch"
result=$?
if [ $result -ne 0 ]; then
echo "Build failed ($sketch) build verbose..."
arduino-cli --log --log-level debug compile -b "$board" "$sketch"
result=$?
fi
if [ $result -ne 0 ]; then
echo "Build failed ($1) $sketch"
return $result
fi
}
function build_sketch()
{
local arduino=$1
@@ -72,7 +88,7 @@ function get_sketches_json_matrix()
local arduino=$1
local srcpath=$2
local platform=$3
local ideversion=$4
local cliversion=$4
local board=$5
local sketches=($(find $srcpath -name *.ino))
for sketch in "${sketches[@]}" ; do
@@ -81,18 +97,27 @@ function get_sketches_json_matrix()
if [[ -f "$sketchdir/.$platform.skip" ]]; then
continue
fi
echo -en "{\"name\":\"$sketchname\",\"board\":\"$board\",\"ideversion\":\"$ideversion\",\"cpu\":\"$platform\",\"sketch\":\"$sketch\"}"
echo -en "{\"name\":\"$sketchname\",\"board\":\"$board\",\"cliversion\":\"$cliversion\",\"cpu\":\"$platform\",\"sketch\":\"$sketch\"}"
if [[ $sketch != ${sketches[-1]} ]] ; then
echo -en ","
fi
done
}
function get_core_cli() {
export ARDUINO_BOARD_MANAGER_ADDITIONAL_URLS="https://arduino.esp8266.com/stable/package_esp8266com_index.json https://espressif.github.io/arduino-esp32/package_esp32_index.json https://github.com/earlephilhower/arduino-pico/releases/download/3.9.2/package_rp2040_index.json"
arduino-cli core update-index
arduino-cli core install esp8266:esp8266
arduino-cli core install esp32:esp32
arduino-cli core install rp2040:rp2040
}
function get_core()
{
echo Setup core for $1
cd $HOME/arduino_ide/hardware
mkdir -p $HOME/arduino_ide/packages/hardware
cd $HOME/arduino_ide/packages/hardware
if [ "$1" = "esp8266" ] ; then
mkdir esp8266com

View File

@@ -73,7 +73,7 @@ def get_library_json_version():
def get_header_versions():
data = {}
define = re.compile('^#define WEBSOCKETS_VERSION_?(.*) "?([0-9\.]*)"?$')
define = re.compile('^#define WEBSOCKETS_VERSION_?(.*) "?([0-9\\.]*)"?$')
with open(f'{base_dir}/src/WebSocketsVersion.h', 'r') as f:
for line in f:
m = define.match(line)