Compare commits

...

76 Commits

Author SHA1 Message Date
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
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
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
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
7a4c416082 bump version to 2.6.1 2024-09-06 20:22:33 +02:00
87b23a48e9 fix #907 use corect random source for newer ESP32 models 2024-09-06 20:21:38 +02:00
bd011d8fd8 clang 2024-09-06 20:20:30 +02:00
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
d41d65ccdc bump version 2.6.0 2024-08-25 18:35:45 +02:00
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
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
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
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
0980b209ba Create dependabot.yml 2024-08-24 12:07:31 +02:00
899cfbdbe7 feat: Support Nano 33 IoT, MKR WIFI 1010, XIAO, Wio Terminal (#901) 2024-08-24 12:01:45 +02:00
dcfb0df665 feat: Support Arduino Nano 33 IoT, MKR WIFI 1010 (#898) 2024-08-11 09:09:47 +02:00
dc6fd04a98 fix #896 ESP32 Arduino changed setCACertBundle args 2024-08-04 09:40:01 +02:00
7da1dc5c6e bump version 2.5.2 2024-07-29 13:07:27 +02:00
d6d4c516b3 Support Arduino UNO WIFI 4 (#894)
feat: Arduino UNO R4 WiFi support
2024-07-29 10:11:12 +02:00
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
d5f0d3c4b5 remove broken rp2040 2024-06-17 16:47:41 +02:00
0e127c9a76 update arduino-cli to 1.0.0 2024-06-17 16:28:59 +02:00
11cf06897c update arduino-cli 2024-06-17 16:27:43 +02:00
af1b0256b9 bump version to 2.4.2 2024-06-17 16:27:08 +02:00
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
93707d455f fix build_sketch_cli result handling 2024-01-05 17:28:16 +01:00
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
503105a9fe Remove compiler warnings (#854)
* [Prevent unwanted Compiler Warnings]: Issue #772
2024-01-05 17:24:45 +01:00
6a26f74f95 code style 2024-01-05 15:27:49 +01:00
be9fd8e267 fix getSocketNumber for ESP 2024-01-05 15:26:59 +01:00
313f2e0170 update actions/cache@v3 2024-01-05 15:26:26 +01:00
3b143bc6f3 🐛 removed default values from *.cpp file 2024-01-05 15:20:03 +01:00
aed167bee0 updated the header file for the same changes 2024-01-05 15:20:03 +01:00
4acc33589a added option arguments in socket io being, for pingInterval, pongTimeout, and disconnectTimeoutCount 2024-01-05 15:20:03 +01:00
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
241c73a806 use ARDUINO_BOARD_MANAGER_ADDITIONAL_URLS env for setting board URLs 2024-01-05 15:06:30 +01:00
437c0252f1 fix cli download URL 2024-01-05 15:01:53 +01:00
92480b8987 IDE_VERSION --> CLI_VERSION 2024-01-05 15:00:16 +01:00
da7efc789e update github actions to arduino-cli for build tests 2024-01-05 14:57:05 +01:00
30d5e13666 set minimum bufsize for base64 encode 2023-08-19 21:16:37 +02:00
751cf87b6c feat(socketio): add disconnect function 2023-05-23 18:03:07 +02:00
a215cca4fe bump version 2.4.1 2023-05-01 15:02:36 +02:00
bb900a77b6 GITHUB_STATE --> GITHUB_OUTPUT 2023-05-01 14:53:30 +02:00
7eda34f345 add RP2040 as supported and bump version 2023-05-01 14:51:36 +02:00
22dff6598f make OTA work with ArduinoJson 6.x 2023-05-01 14:48:18 +02:00
a4f13a1410 clang-format 2023-05-01 14:36:26 +02:00
4115a87c16 set-output command is deprecated 2023-05-01 14:36:07 +02:00
82c357c036 fix OTA example build and build tests for esp8266 examples 2023-05-01 14:30:20 +02:00
d9a5c629f0 Port to Raspberry Pi Pico W core
Add support for the onboard WiFi chip on the Raspberry Pi Pico W
(RP2040 based ) board using the arduino-pico Arduino core at
https://github.com/earlephilhower/arduino-pico

The PicoW WiFi stack is a mashup of the ESP8266 and ESP32 cores, so
only minimal changes were required.  Defines a new NETWORK_TYPE for
the PicoW.

ESP8266 examples renames to ESP8266_PICO because they all work unmodified
(except for OTA which is handled differently on the Pico)
2023-05-01 08:50:01 +02:00
323592f622 Add possibility to change WEBSOCKETS_TCP_TIMEOUT 2022-08-22 14:28:19 +02:00
f1ffaede0b Fix Typo 2022-08-22 14:22:00 +02:00
94a531c464 Use async sleep, increase chunk size 2022-08-22 14:22:00 +02:00
ccdba4ed8a Fix response type prefix (LoadProhibitedCause) 2022-08-22 14:22:00 +02:00
2b0e8f6fe9 Fix async run 2022-08-22 14:22:00 +02:00
dd8675c6a9 don't update cSessionId on unwanted Set-Cookie 2022-06-24 10:57:33 +02:00
2110ad0a10 more debug 2022-06-24 10:54:26 +02:00
04249a9b62 more debug 2022-06-24 10:54:26 +02:00
1fb67c8868 esp8266 build, change config options 2022-06-24 10:54:26 +02:00
3073c156b1 Fix compiler warning "function may return address of local variable" 2022-06-24 10:26:43 +02:00
5881a99a30 bump version to 2.3.7 2022-04-05 20:07:59 +02:00
52b3aa8ea4 enable debug for CI 2022-04-05 19:40:57 +02:00
28c0cf3094 fix #728 dropNativeClient null ptr 2022-04-05 19:11:11 +02:00
ab9af162b2 fix code style 2022-04-05 19:10:57 +02:00
8d76469e90 update to Arduino IDE 1.8.19 for testing and dropped testing with 1.6.13 2022-04-05 19:03:19 +02:00
61ea44942e Suppress esp32/sha.h warning 2022-04-05 18:55:48 +02:00
28ed615145 Add minimal example for ESP OTA 2021-12-11 11:40:24 +01:00
108090e8cf Update WebSocketsServer.cpp
Created a dummy client in order to be able to drop the TCP Client.
2021-09-10 22:55:37 +02:00
46b2ae1c97 fix #695, #696 2021-07-14 19:28:25 +02:00
27f86a10ad allow access to setExtraHeaders and setReconnectInterval for SocketIOclient
fix: #690
2021-07-09 17:17:42 +02:00
860ac9da69 Prevent Compiler Warning: --> add // falls through
prevent Compiler warning by adding // falls through to imform compiler.
2021-06-20 09:22:41 +02:00
c897f60567 update arduino IDE from 1.8.13 to 1.8.15 2021-06-17 20:04:28 +02:00
b242882ac5 add git submodule update --init to esp8266 build 2021-06-17 19:56:45 +02:00
f8da05aa87 add Socket.IO example for ESP32 2021-06-17 19:43:15 +02:00
72aae52655 set EIO to version 4 in SocketIO examples
see #682
2021-06-17 19:42:09 +02:00
56 changed files with 5894 additions and 199 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: check_version_files:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: check version - name: check version
run: | run: |
@ -26,28 +26,27 @@ jobs:
prepare_example_json: prepare_example_json:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: generate examples - name: generate examples
id: set-matrix id: set-matrix
run: | run: |
source $GITHUB_WORKSPACE/travis/common.sh source $GITHUB_WORKSPACE/travis/common.sh
cd $GITHUB_WORKSPACE cd $GITHUB_WORKSPACE
echo -en "::set-output name=matrix::"
echo -en "["
get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp8266 esp8266 1.6.13 esp8266com:esp8266:generic:xtal=80 echo -en "matrix=" >> $GITHUB_OUTPUT
echo -en "," echo -en "[" >> $GITHUB_OUTPUT
get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp8266 esp8266 1.6.13 esp8266com:esp8266:generic:xtal=80,dbg=Serial1 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 "," echo -en "," >> $GITHUB_OUTPUT
get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp8266 esp8266 1.8.13 esp8266com:esp8266:generic:xtal=80,eesz=1M,FlashMode=qio,FlashFreq=80 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 "," echo -en "," >> $GITHUB_OUTPUT
get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp32 esp32 1.8.13 espressif:esp32:esp32:FlashFreq=80 get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp32 esp32 0.35.3 esp32:esp32:esp32:FlashFreq=80 >> $GITHUB_OUTPUT
echo -en "]" echo -en "]" >> $GITHUB_OUTPUT
echo >> $GITHUB_OUTPUT
outputs: outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }} matrix: ${{ steps.set-matrix.outputs.matrix }}
@ -56,33 +55,35 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
IDE_VERSION: [1.8.13, 1.6.13] CLI_VERSION: [0.35.3]
env: env:
IDE_VERSION: ${{ matrix.IDE_VERSION }} CLI_VERSION: ${{ matrix.CLI_VERSION }}
ARDUINO_DIRECTORIES_DATA: /home/runner/arduino_ide
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: Get Date - name: Get hash
id: get-date id: get-hash
run: | run: |
echo "::set-output name=date::$(/bin/date -u "+%Y%m%d")" echo "hash=$(/bin/date -u "+%Y%m%d")-$(md5sum ".github/workflows/main.yml" | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT
shell: bash shell: bash
- uses: actions/cache@v2 - uses: actions/cache@v4
id: cache_all id: cache_all
with: with:
path: | path: |
/home/runner/arduino_ide /home/runner/arduino_ide
/home/runner/Arduino /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 - name: download IDE
if: steps.cache_all.outputs.cache-hit != 'true' if: steps.cache_all.outputs.cache-hit != 'true'
run: | run: |
wget http://downloads.arduino.cc/arduino-$IDE_VERSION-linux64.tar.xz -q wget https://github.com/arduino/arduino-cli/releases/download/v${CLI_VERSION}/arduino-cli_${CLI_VERSION}_Linux_64bit.tar.gz -q
tar xf arduino-$IDE_VERSION-linux64.tar.xz tar xf arduino-cli_${CLI_VERSION}_Linux_64bit.tar.gz
mv arduino-$IDE_VERSION $HOME/arduino_ide mkdir -p $ARDUINO_DIRECTORIES_DATA
mv arduino-cli $ARDUINO_DIRECTORIES_DATA/
- name: download ArduinoJson - name: download ArduinoJson
if: steps.cache_all.outputs.cache-hit != 'true' if: steps.cache_all.outputs.cache-hit != 'true'
@ -92,17 +93,12 @@ jobs:
unzip 6.x.zip unzip 6.x.zip
mv ArduinoJson-6.x $HOME/Arduino/libraries/ArduinoJson mv ArduinoJson-6.x $HOME/Arduino/libraries/ArduinoJson
- name: download esp8266 - name: download cores
if: steps.cache_all.outputs.cache-hit != 'true' if: steps.cache_all.outputs.cache-hit != 'true'
run: | run: |
export PATH="$ARDUINO_DIRECTORIES_DATA:$PATH"
source $GITHUB_WORKSPACE/travis/common.sh source $GITHUB_WORKSPACE/travis/common.sh
get_core esp8266 get_core_cli
- name: download esp32
if: steps.cache_all.outputs.cache-hit != 'true' && matrix.IDE_VERSION != '1.6.13'
run: |
source $GITHUB_WORKSPACE/travis/common.sh
get_core esp32
build: build:
needs: [prepare_ide, prepare_example_json] needs: [prepare_ide, prepare_example_json]
@ -114,30 +110,31 @@ jobs:
env: env:
CPU: ${{ matrix.cpu }} CPU: ${{ matrix.cpu }}
BOARD: ${{ matrix.board }} BOARD: ${{ matrix.board }}
IDE_VERSION: ${{ matrix.ideversion }} CLI_VERSION: ${{ matrix.cliversion }}
SKETCH: ${{ matrix.sketch }} 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 represent a sequence of tasks that will be executed as part of the job
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: install libgtk2.0-0 - name: install libgtk2.0-0
run: | run: |
sudo apt-get install -y libgtk2.0-0 sudo apt-get install -y libgtk2.0-0
- name: Get Date - name: Get hash
id: get-date id: get-hash
run: | run: |
echo "::set-output name=date::$(/bin/date -u "+%Y%m%d")" echo "hash=$(/bin/date -u "+%Y%m%d")-$(md5sum ".github/workflows/main.yml" | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT
shell: bash shell: bash
- uses: actions/cache@v2 - uses: actions/cache@v4
id: cache_all id: cache_all
with: with:
path: | path: |
/home/runner/arduino_ide /home/runner/arduino_ide
/home/runner/Arduino /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 - name: install python serial
if: matrix.cpu == 'esp32' if: matrix.cpu == 'esp32'
@ -146,38 +143,24 @@ jobs:
sudo pip install pyserial sudo pip install pyserial
# sudo apt install python-is-python3 # 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 - name: test IDE
run: | run: |
export PATH="$HOME/arduino_ide:$PATH" export PATH="$ARDUINO_DIRECTORIES_DATA:$PATH"
which arduino which arduino-cli
- name: copy code - name: copy code
run: | run: |
mkdir -p $HOME/Arduino/libraries/ mkdir -p $HOME/Arduino/libraries/
cp -r $GITHUB_WORKSPACE $HOME/Arduino/libraries/arduinoWebSockets cp -r $GITHUB_WORKSPACE $HOME/Arduino/libraries/arduinoWebSockets
- name: config IDE
run: |
export DISPLAY=:1.0
export PATH="$HOME/arduino_ide:$PATH"
arduino --board $BOARD --save-prefs
arduino --get-pref sketchbook.path
arduino --pref update.check=false
- name: build example - name: build example
timeout-minutes: 20 timeout-minutes: 20
run: | run: |
export DISPLAY=:1.0 set -ex
export PATH="$HOME/arduino_ide:$PATH" export PATH="$HOME/arduino_ide:$PATH"
source $GITHUB_WORKSPACE/travis/common.sh source $GITHUB_WORKSPACE/travis/common.sh
cd $GITHUB_WORKSPACE cd $GITHUB_WORKSPACE
build_sketch arduino $SKETCH build_sketch_cli "$SKETCH" "$BOARD"
done: done:
needs: [prepare_ide, prepare_example_json, build, check_version_files] 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. a WebSocket Server and Client for Arduino based on RFC6455.
@ -26,11 +26,15 @@ a WebSocket Server and Client for Arduino based on RFC6455.
- ESP8266 [Arduino for ESP8266](https://github.com/esp8266/Arduino/) - ESP8266 [Arduino for ESP8266](https://github.com/esp8266/Arduino/)
- ESP32 [Arduino for ESP32](https://github.com/espressif/arduino-esp32) - ESP32 [Arduino for ESP32](https://github.com/espressif/arduino-esp32)
- ESP31B - ESP31B
- Raspberry Pi Pico W [Arduino for Pico](https://github.com/earlephilhower/arduino-pico)
- Particle with STM32 ARM Cortex M3 - Particle with STM32 ARM Cortex M3
- ATmega328 with Ethernet Shield (ATmega branch) - ATmega328 with Ethernet Shield (ATmega branch)
- ATmega328 with enc28j60 (ATmega branch) - ATmega328 with enc28j60 (ATmega branch)
- ATmega2560 with Ethernet Shield (ATmega branch) - ATmega2560 with Ethernet Shield (ATmega branch)
- ATmega2560 with enc28j60 (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: ###### ###### Note: ######
@ -43,10 +47,21 @@ a WebSocket Server and Client for Arduino based on RFC6455.
### wss / SSL ### ### wss / SSL ###
supported for: supported for:
- wss client on the ESP8266 - 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 - 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 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. 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 ### ### ESP Async TCP ###
This libary can run in Async TCP mode on the ESP. This libary can run in Async TCP mode on the ESP.
@ -93,8 +108,6 @@ Where `WStype_t type` is defined as:
### Issues ### ### Issues ###
Submit issues to: https://github.com/Links2004/arduinoWebSockets/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 ### ### License and credits ###
The library is licensed under [LGPLv2.1](https://github.com/Links2004/arduinoWebSockets/blob/master/LICENSE) 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

@ -0,0 +1,155 @@
/*
* WebSocketClientSocketIOack.ino
*
* Created on: 20.07.2019
*
*/
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>
#include <WebSocketsClient.h>
#include <SocketIOclient.h>
WiFiMulti WiFiMulti;
SocketIOclient socketIO;
#define USE_SERIAL Serial
void socketIOEvent(socketIOmessageType_t type, uint8_t * payload, size_t length) {
switch(type) {
case sIOtype_DISCONNECT:
USE_SERIAL.printf("[IOc] Disconnected!\n");
break;
case sIOtype_CONNECT:
USE_SERIAL.printf("[IOc] Connected to url: %s\n", payload);
// join default namespace (no auto join in Socket.IO V3)
socketIO.send(sIOtype_CONNECT, "/");
break;
case sIOtype_EVENT:
{
char * sptr = NULL;
int id = strtol((char *)payload, &sptr, 10);
USE_SERIAL.printf("[IOc] get event: %s id: %d\n", payload, id);
if(id) {
payload = (uint8_t *)sptr;
}
DynamicJsonDocument doc(1024);
DeserializationError error = deserializeJson(doc, payload, length);
if(error) {
USE_SERIAL.print(F("deserializeJson() failed: "));
USE_SERIAL.println(error.c_str());
return;
}
String eventName = doc[0];
USE_SERIAL.printf("[IOc] event name: %s\n", eventName.c_str());
// Message Includes a ID for a ACK (callback)
if(id) {
// create JSON message for Socket.IO (ack)
DynamicJsonDocument docOut(1024);
JsonArray array = docOut.to<JsonArray>();
// add payload (parameters) for the ack (callback function)
JsonObject param1 = array.createNestedObject();
param1["now"] = millis();
// JSON to String (serializion)
String output;
output += id;
serializeJson(docOut, output);
// Send event
socketIO.send(sIOtype_ACK, output);
}
}
break;
case sIOtype_ACK:
USE_SERIAL.printf("[IOc] get ack: %u\n", length);
break;
case sIOtype_ERROR:
USE_SERIAL.printf("[IOc] get error: %u\n", length);
break;
case sIOtype_BINARY_EVENT:
USE_SERIAL.printf("[IOc] get binary: %u\n", length);
break;
case sIOtype_BINARY_ACK:
USE_SERIAL.printf("[IOc] get binary ack: %u\n", length);
break;
}
}
void setup() {
//USE_SERIAL.begin(921600);
USE_SERIAL.begin(115200);
//Serial.setDebugOutput(true);
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", "passpasspass");
//WiFi.disconnect();
while(WiFiMulti.run() != WL_CONNECTED) {
delay(100);
}
String ip = WiFi.localIP().toString();
USE_SERIAL.printf("[SETUP] WiFi Connected %s\n", ip.c_str());
// server address, port and URL
socketIO.begin("10.11.100.100", 8880, "/socket.io/?EIO=4");
// event handler
socketIO.onEvent(socketIOEvent);
}
unsigned long messageTimestamp = 0;
void loop() {
socketIO.loop();
uint64_t now = millis();
if(now - messageTimestamp > 2000) {
messageTimestamp = now;
// create JSON message for Socket.IO (event)
DynamicJsonDocument doc(1024);
JsonArray array = doc.to<JsonArray>();
// add event name
// Hint: socket.on('event_name', ....
array.add("event_name");
// add payload (parameters) for the event
JsonObject param1 = array.createNestedObject();
param1["now"] = (uint32_t) now;
// JSON to String (serialization)
String output;
serializeJson(doc, output);
// Send event
socketIO.sendEVENT(output);
// Print JSON for debugging
USE_SERIAL.println(output);
}
}

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,27 @@
## Minimal example of WebsocketClientOTA and Python server
Take this as small example, how achieve OTA update on ESP8266 and ESP32.
Python server was wrote from train so take it only as bare example.
It's working, but it's not mean to run in production.
### Usage:
Start server:
```bash
cd python_ota_server
python3 -m venv .venv
source .venv/bin/activate
pip3 install -r requirements.txt
python3 main.py
```
Flash ESP with example sketch and start it.
Change version inside example sketch to higher and compile it and save it to bin file.
Rename it to `mydevice-1.0.1-esp8266.bin` and place it inside new folder firmware (server create it).
When the ESP connect to server, it check if version flashed is equal to fw in firmware folder. If higher FW version is present,
start the flash process.

View File

@ -0,0 +1,264 @@
/*
* WebSocketClientOTA.ino
*
* Created on: 25.10.2021
*
*/
#include <Arduino.h>
#include <ArduinoJson.h>
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266mDNS.h>
#include <Updater.h>
#include <Hash.h>
ESP8266WiFiMulti WiFiMulti;
#elif defined(ESP32)
#include <WiFi.h>
#include <WiFiMulti.h>
#include "ESPmDNS.h"
#include <Update.h>
WiFiMulti WiFiMulti;
#else
#error Unsupported device
#endif
#include <WiFiUdp.h>
#include <WebSocketsClient.h>
WebSocketsClient webSocket;
#define USE_SERIAL Serial
// Variables:
// Settable:
const char *version = "1.0.0";
const char *name = "mydevice";
// Others:
#ifdef ESP8266
const char *chip = "esp8266";
#endif
#ifdef ESP32
const char *chip = "esp32";
#endif
uint32_t maxSketchSpace = 0;
int SketchSize = 0;
bool ws_conn = false;
void greetings_(){
StaticJsonDocument<200> doc;
doc["type"] = "greetings";
doc["mac"] = WiFi.macAddress().c_str();
doc["ip"] = WiFi.localIP().toString().c_str();
doc["version"] = version;
doc["name"] = name;
doc["chip"] = chip;
char data[200];
serializeJson(doc, data);
webSocket.sendTXT(data);
}
void register_(){
StaticJsonDocument<200> doc;
doc["type"] = "register";
doc["mac"] = WiFi.macAddress().c_str();
char data[200];
serializeJson(doc, data);
webSocket.sendTXT(data);
ws_conn = true;
}
typedef void (*CALLBACK_FUNCTION)(JsonDocument &msg);
typedef struct {
char type[50];
CALLBACK_FUNCTION func;
} RESPONSES_STRUCT;
void OTA_RESPONSES(JsonDocument &msg){
USE_SERIAL.print(F("[WSc] OTA mode: "));
String val = msg["value"];
if(val == "go") {
USE_SERIAL.print(F("go\n"));
SketchSize = int(msg["size"]);
maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
USE_SERIAL.printf("[WSc] Max sketch size: %u\n", maxSketchSpace);
USE_SERIAL.printf("[WSc] Sketch size: %d\n", SketchSize);
USE_SERIAL.setDebugOutput(true);
if (!Update.begin(maxSketchSpace)) { //start with max available size
Update.printError(Serial);
ESP.restart();
}
} else if (val == "ok") {
USE_SERIAL.print(F("OK\n"));
register_();
} else {
USE_SERIAL.print(F("unknown value : "));
USE_SERIAL.print(val);
USE_SERIAL.print(F("\n"));
}
}
void STA_RESPONSES(JsonDocument &msg){
// Do something with message
}
// Count of responses handled by RESPONSES_STRUCT
// increase increase if another response handler is added
const int nrOfResponses = 2;
RESPONSES_STRUCT responses[nrOfResponses] = {
{"ota", OTA_RESPONSES},
{"state", STA_RESPONSES},
};
void text(uint8_t * payload, size_t length){
// Convert message to something usable
char msgch[length];
for (unsigned int i = 0; i < length; i++)
{
USE_SERIAL.print((char)payload[i]);
msgch[i] = ((char)payload[i]);
}
msgch[length] = '\0';
// Parse Json
StaticJsonDocument<200> doc_in;
DeserializationError error = deserializeJson(doc_in, msgch);
if (error) {
USE_SERIAL.print(F("deserializeJson() failed: "));
USE_SERIAL.println(error.c_str());
return;
}
// Handle each TYPE of message
int b = 0;
String t = doc_in["type"];
for( b=0 ; b<nrOfResponses ; b++ )
{
if(t == responses[b].type) {
responses[b].func(doc_in);
}
}
}
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");
greetings_();
}
break;
case WStype_TEXT:
USE_SERIAL.printf("[WSc] get text: %s\n", payload);
// send message to server
// webSocket.sendTXT("message here");
text(payload, length);
break;
case WStype_BIN:
USE_SERIAL.printf("[WSc] get binary length: %u\n", length);
// hexdump(payload, length);
if (Update.write(payload, length) != length) {
Update.printError(Serial);
ESP.restart();
}
yield();
SketchSize -= length;
USE_SERIAL.printf("[WSc] Sketch size left: %u\n", SketchSize);
if (SketchSize < 1){
if (Update.end(true)) { //true to set the size to the current progress
USE_SERIAL.printf("Update Success: \nRebooting...\n");
delay(5);
yield();
ESP.restart();
} else {
Update.printError(USE_SERIAL);
ESP.restart();
}
USE_SERIAL.setDebugOutput(false);
}
// send data to server
// webSocket.sendBIN(payload, length);
break;
case WStype_PING:
// pong will be send automatically
USE_SERIAL.printf("[WSc] get ping\n");
break;
case WStype_PONG:
// answer to a ping we send
USE_SERIAL.printf("[WSc] get pong\n");
break;
}
}
void setup() {
// USE_SERIAL.begin(921600);
USE_SERIAL.begin(115200);
//Serial.setDebugOutput(true);
USE_SERIAL.setDebugOutput(true);
USE_SERIAL.print(F("\nMAC: "));
USE_SERIAL.println(WiFi.macAddress());
USE_SERIAL.print(F("\nDevice: "));
USE_SERIAL.println(name);
USE_SERIAL.printf("\nVersion: %s\n", version);
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", "PASS");
//WiFi.disconnect();
while(WiFiMulti.run() != WL_CONNECTED) {
delay(100);
}
// server address, port and URL
webSocket.begin("10.0.1.5", 8081, "/");
// event handler
webSocket.onEvent(webSocketEvent);
// use HTTP Basic Authorization this is optional remove if not needed
// webSocket.setAuthorization("USER", "PASS");
// try ever 5000 again if connection has failed
webSocket.setReconnectInterval(5000);
// start heartbeat (optional)
// ping server every 15000 ms
// expect pong from server within 3000 ms
// consider connection disconnected if pong is not received 2 times
webSocket.enableHeartbeat(15000, 3000, 2);
}
void loop() {
webSocket.loop();
}

View File

@ -0,0 +1,235 @@
"""Minimal example of Python websocket server
handling OTA updates for ESP32 amd ESP8266
Check and upload of firmware works.
Register and state function are jus for example.
"""
# pylint: disable=W0703,E1101
import asyncio
import copy
import json
import logging
import subprocess
import threading
import time
from os import listdir
from os.path import join as join_pth
from pathlib import Path
import websockets
from packaging import version
# Logger settings
logging.basicConfig(filename="ws_server.log")
Logger = logging.getLogger('WS-OTA')
Logger.addHandler(logging.StreamHandler())
Logger.setLevel(logging.INFO)
# Path to directory with FW
fw_path = join_pth(Path().absolute(), "firmware")
def create_path(path: str) -> None:
"""Check if path exist or create it"""
Path(path).mkdir(parents=True, exist_ok=True)
def shell(command):
"""Handle execution of shell commands"""
with subprocess.Popen(command, shell=True,
stdout=subprocess.PIPE,
universal_newlines=True
) as process:
for stdout_line in iter(process.stdout.readline, ""):
Logger.debug(stdout_line)
process.stdout.close()
return_code = process.wait()
Logger.debug("Shell returned: %s", return_code)
return process.returncode
return None
async def binary_send(websocket, fw_file):
"""Read firmware file, divide it to chunks and send them"""
with open(fw_file, "rb") as binaryfile:
while True:
chunk = binaryfile.read(4096)
if not chunk:
break
try:
await websocket.send(chunk)
except Exception as exception:
Logger.exception(exception)
return False
asyncio.sleep(0.2)
def version_checker(name, vdev, vapp):
"""Parse and compare FW version"""
if version.parse(vdev) < version.parse(vapp):
Logger.info("Client(%s) version %s is smaller than %s: Go for update", name, vdev, vapp)
return True
Logger.info("Client(%s) version %s is greater or equal to %s: Not updating", name, vdev, vapp)
return False
class WsOtaHandler (threading.Thread):
"""Thread handling ota update
Running ota directly from message would kill WS
as message bus would timeout.
"""
def __init__(self, name, message, websocket):
threading.Thread.__init__(self, daemon=True)
self.name = name
self.msg = message
self.websocket = websocket
def run(self, ):
try:
asyncio.run(self.start_())
except Exception as exception:
Logger.exception(exception)
finally:
pass
async def start_(self):
"""Start _ota se asyncio future"""
msg_task = asyncio.ensure_future(
self._ota())
done, pending = await asyncio.wait(
[msg_task],
return_when=asyncio.FIRST_COMPLETED,
)
Logger.info("WS Ota Handler done: %s", done)
for task in pending:
task.cancel()
async def _ota(self):
"""Check for new fw and update or pass"""
device_name = self.msg['name']
device_chip = self.msg['chip']
device_version = self.msg['version']
fw_version = ''
fw_name = ''
fw_device = ''
for filename in listdir(fw_path):
fw_info = filename.split("-")
fw_device = fw_info[0]
if fw_device == device_name:
fw_version = fw_info[1]
fw_name = filename
break
if not fw_version:
Logger.info("Client(%s): No fw found!", device_name)
msg = '{"type": "ota", "value":"ok"}'
await self.websocket.send(msg)
return
if not version_checker(device_name, device_version, fw_version):
return
fw_file = join_pth(fw_path, fw_name)
if device_chip == 'esp8266' and not fw_file.endswith('.gz'):
# We can compress fw to make it smaller for upload
fw_cpress = fw_file
fw_file = fw_cpress + ".gz"
cpress = f"gzip -9 {fw_cpress}"
cstate = shell(cpress)
if cstate:
Logger.error("Cannot compress firmware: %s", fw_name)
return
# Get size of fw
size = Path(fw_file).stat().st_size
# Request ota mode
msg = '{"type": "ota", "value":"go", "size":' + str(size) + '}'
await self.websocket.send(msg)
# send file by chunks trough websocket
await binary_send(self.websocket, fw_file)
async def _register(websocket, message):
mac = message.get('mac')
name = message.get('name')
Logger.info("Client(%s) mac: %s", name, mac)
# Some code
response = {'type': 'registry', 'state': 'ok'}
await websocket.send(json.dumps(response))
async def _state(websocket, message):
mac = message.get('mac')
name = message.get('name')
Logger.info("Client(%s) mac: %s", name, mac)
# Some code
response = {'type': 'state', 'state': 'ok'}
await websocket.send(json.dumps(response))
async def _unhandled(websocket, msg):
Logger.info("Unhandled message from device: %s", str(msg))
response = {'type': 'response', 'state': 'nok'}
await websocket.send(json.dumps(response))
async def _greetings(websocket, message):
WsOtaHandler('thread_ota', copy.deepcopy(message), websocket).start()
async def message_received(websocket, message) -> None:
"""Handle incoming messages
Check if message contain json and run waned function
"""
switcher = {"greetings": _greetings,
"register": _register,
"state": _state
}
if message[0:1] == "{":
try:
msg_json = json.loads(message)
except Exception as exception:
Logger.error(exception)
return
type_ = msg_json.get('type')
name = msg_json.get('name')
func = switcher.get(type_, _unhandled)
Logger.debug("Client(%s)said: %s", name, type_)
try:
await func(websocket, msg_json)
except Exception as exception:
Logger.error(exception)
# pylint: disable=W0613
async def ws_server(websocket, path) -> None:
"""Run in cycle and wait for new messages"""
async for message in websocket:
await message_received(websocket, message)
async def main():
"""Server starter
Normal user can bind only port numbers greater than 1024
"""
async with websockets.serve(ws_server, "10.0.1.5", 8081):
await asyncio.Future() # run forever
create_path(fw_path)
asyncio.run(main())

View File

@ -0,0 +1,2 @@
packaging
websockets

View File

@ -88,7 +88,7 @@ void setup() {
USE_SERIAL.printf("[SETUP] WiFi Connected %s\n", ip.c_str()); USE_SERIAL.printf("[SETUP] WiFi Connected %s\n", ip.c_str());
// server address, port and URL // server address, port and URL
socketIO.begin("10.11.100.100", 8880); socketIO.begin("10.11.100.100", 8880, "/socket.io/?EIO=4");
// event handler // event handler
socketIO.onEvent(socketIOEvent); socketIO.onEvent(socketIOEvent);

View File

@ -125,7 +125,7 @@ void setup() {
USE_SERIAL.printf("[SETUP] WiFi Connected %s\n", ip.c_str()); USE_SERIAL.printf("[SETUP] WiFi Connected %s\n", ip.c_str());
// server address, port and URL // server address, port and URL
socketIO.begin("10.11.100.100", 8880); socketIO.begin("10.11.100.100", 8880, "/socket.io/?EIO=4");
// event handler // event handler
socketIO.onEvent(socketIOEvent); socketIO.onEvent(socketIOEvent);

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", "keywords": "wifi, http, web, server, client, websocket",
"license": "LGPL-2.1", "license": "LGPL-2.1",
"name": "WebSockets", "name": "WebSockets",
"platforms": "atmelavr, espressif8266, espressif32", "platforms": "*",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/Links2004/arduinoWebSockets.git" "url": "https://github.com/Links2004/arduinoWebSockets.git"
}, },
"version": "2.3.6" "version": "2.6.1"
} }

View File

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

View File

@ -15,39 +15,39 @@ SocketIOclient::SocketIOclient() {
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::beginSocketIO(host, port, url, protocol);
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5); WebSocketsClient::enableHeartbeat(pingInterval, pongTimeout, disconnectTimeoutCount);
initClient(); 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::beginSocketIO(host, port, url, protocol);
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5); WebSocketsClient::enableHeartbeat(pingInterval, pongTimeout, disconnectTimeoutCount);
initClient(); initClient();
} }
#if defined(HAS_SSL) #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::beginSocketIOSSL(host, port, url, protocol);
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5); WebSocketsClient::enableHeartbeat(pingInterval, pongTimeout, disconnectTimeoutCount);
initClient(); 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::beginSocketIOSSL(host, port, url, protocol);
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5); WebSocketsClient::enableHeartbeat(pingInterval, pongTimeout, disconnectTimeoutCount);
initClient(); initClient();
} }
#if defined(SSL_BARESSL) #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::beginSocketIOSSLWithCA(host, port, url, CA_cert, protocol);
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5); WebSocketsClient::enableHeartbeat(pingInterval, pongTimeout, disconnectTimeoutCount);
initClient(); 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::beginSocketIOSSLWithCA(host, port, url, CA_cert, protocol);
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5); WebSocketsClient::enableHeartbeat(pingInterval, pongTimeout, disconnectTimeoutCount);
initClient(); initClient();
} }
@ -85,6 +85,18 @@ bool SocketIOclient::isConnected(void) {
return WebSocketsClient::isConnected(); return WebSocketsClient::isConnected();
} }
void SocketIOclient::setExtraHeaders(const char * extraHeaders) {
return WebSocketsClient::setExtraHeaders(extraHeaders);
}
void SocketIOclient::setReconnectInterval(unsigned long time) {
return WebSocketsClient::setReconnectInterval(time);
}
void SocketIOclient::disconnect(void) {
WebSocketsClient::disconnect();
}
/** /**
* send text data to client * send text data to client
* @param num uint8_t client id * @param num uint8_t client id

View File

@ -9,6 +9,7 @@
#define SOCKETIOCLIENT_H_ #define SOCKETIOCLIENT_H_
#include "WebSockets.h" #include "WebSockets.h"
#include "WebSocketsClient.h"
#define EIO_HEARTBEAT_INTERVAL 20000 #define EIO_HEARTBEAT_INTERVAL 20000
@ -46,22 +47,25 @@ class SocketIOclient : protected WebSocketsClient {
SocketIOclient(void); SocketIOclient(void);
virtual ~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(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"); 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 #ifdef HAS_SSL
void beginSSL(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * 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"); 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 #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", const char * CA_cert = NULL, const char * protocol = "arduino", uint32_t pingInterval = 60 * 1000, uint32_t pongTimeout = 90 * 1000, uint8_t disconnectTimeoutCount = 5);
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 setSSLClientCertKey(const char * clientCert = NULL, const char * clientPrivateKey = NULL); 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); void setSSLClientCertKey(BearSSL::X509List * clientCert = NULL, BearSSL::PrivateKey * clientPrivateKey = NULL);
#endif #endif
#endif
#endif #endif
bool isConnected(void); bool isConnected(void);
void onEvent(SocketIOclientEvent cbEvent); void onEvent(SocketIOclientEvent cbEvent);
void disconnect(void);
bool sendEVENT(uint8_t * payload, size_t length = 0, bool headerToPayload = false); bool sendEVENT(uint8_t * payload, size_t length = 0, bool headerToPayload = false);
bool sendEVENT(const uint8_t * payload, size_t length = 0); bool sendEVENT(const uint8_t * payload, size_t length = 0);
@ -75,6 +79,9 @@ class SocketIOclient : protected WebSocketsClient {
bool send(socketIOmessageType_t type, const char * payload, size_t length = 0); bool send(socketIOmessageType_t type, const char * payload, size_t length = 0);
bool send(socketIOmessageType_t type, String & payload); bool send(socketIOmessageType_t type, String & payload);
void setExtraHeaders(const char * extraHeaders = NULL);
void setReconnectInterval(unsigned long time);
void loop(void); void loop(void);
void configureEIOping(bool disableHeartbeat = false); void configureEIOping(bool disableHeartbeat = false);

View File

@ -42,7 +42,11 @@ extern "C" {
#include <esp_system.h> #include <esp_system.h>
#if ESP_IDF_VERSION_MAJOR >= 4 #if ESP_IDF_VERSION_MAJOR >= 4
#if(ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(1, 0, 6))
#include "sha/sha_parallel_engine.h"
#else
#include <esp32/sha.h> #include <esp32/sha.h>
#endif
#else #else
#include <hwcrypto/sha.h> #include <hwcrypto/sha.h>
#endif #endif
@ -478,7 +482,7 @@ void WebSockets::handleWebsocketPayloadCb(WSclient_t * client, bool ok, uint8_t
switch(header->opCode) { switch(header->opCode) {
case WSop_text: case WSop_text:
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] text: %s\n", client->num, payload); DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] text: %s\n", client->num, payload);
// no break here! // fallthrough
case WSop_binary: case WSop_binary:
case WSop_continuation: case WSop_continuation:
messageReceived(client, header->opCode, payload, header->payloadLen, header->fin); messageReceived(client, header->opCode, payload, header->payloadLen, header->fin);
@ -567,6 +571,7 @@ String WebSockets::acceptKey(String & clientKey) {
*/ */
String WebSockets::base64_encode(uint8_t * data, size_t length) { String WebSockets::base64_encode(uint8_t * data, size_t length) {
size_t size = ((length * 1.6f) + 1); size_t size = ((length * 1.6f) + 1);
size = std::max(size, (size_t)5); // minimum buffer size
char * buffer = (char *)malloc(size); char * buffer = (char *)malloc(size);
if(buffer) { if(buffer) {
base64_encodestate _state; base64_encodestate _state;
@ -745,7 +750,7 @@ void WebSockets::handleHBTimeout(WSclient_t * client) {
client->pongTimeoutCount++; client->pongTimeoutCount++;
client->lastPing = millis() - client->pingInterval - 500; // force ping on the next run 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) { if(client->disconnectTimeoutCount && client->pongTimeoutCount >= client->disconnectTimeoutCount) {
DEBUG_WEBSOCKETS("[HBtimeout] count=%d, DISCONNECTING\n", client->pongTimeoutCount); DEBUG_WEBSOCKETS("[HBtimeout] count=%d, DISCONNECTING\n", client->pongTimeoutCount);

View File

@ -84,6 +84,33 @@
#define GET_FREE_HEAP System.freeMemory() #define GET_FREE_HEAP System.freeMemory()
#define WEBSOCKETS_YIELD() #define WEBSOCKETS_YIELD()
#define WEBSOCKETS_YIELD_MORE() #define WEBSOCKETS_YIELD_MORE()
#elif defined(ARDUINO_ARCH_RP2040)
#define WEBSOCKETS_MAX_DATA_SIZE (15 * 1024)
#define WEBSOCKETS_USE_BIG_MEM
#define GET_FREE_HEAP rp2040.getFreeHeap()
#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 #else
// atmega328p has only 2KB ram! // atmega328p has only 2KB ram!
@ -94,7 +121,9 @@
#define WEBSOCKETS_YIELD_MORE() #define WEBSOCKETS_YIELD_MORE()
#endif #endif
#ifndef WEBSOCKETS_TCP_TIMEOUT
#define WEBSOCKETS_TCP_TIMEOUT (5000) #define WEBSOCKETS_TCP_TIMEOUT (5000)
#endif
#define NETWORK_ESP8266_ASYNC (0) #define NETWORK_ESP8266_ASYNC (0)
#define NETWORK_ESP8266 (1) #define NETWORK_ESP8266 (1)
@ -102,6 +131,10 @@
#define NETWORK_ENC28J60 (3) #define NETWORK_ENC28J60 (3)
#define NETWORK_ESP32 (4) #define NETWORK_ESP32 (4)
#define NETWORK_ESP32_ETH (5) #define NETWORK_ESP32_ETH (5)
#define NETWORK_RP2040 (6)
#define NETWORK_UNOWIFIR4 (7)
#define NETWORK_WIFI_NINA (8)
#define NETWORK_SAMD_SEED (9)
// max size of the WS Message Header // max size of the WS Message Header
#define WEBSOCKETS_MAX_HEADER_SIZE (14) #define WEBSOCKETS_MAX_HEADER_SIZE (14)
@ -116,6 +149,19 @@
#elif defined(ESP32) #elif defined(ESP32)
#define WEBSOCKETS_NETWORK_TYPE NETWORK_ESP32 #define WEBSOCKETS_NETWORK_TYPE NETWORK_ESP32
// #define WEBSOCKETS_NETWORK_TYPE NETWORK_ESP32_ETH // #define WEBSOCKETS_NETWORK_TYPE NETWORK_ESP32_ETH
#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 #else
#define WEBSOCKETS_NETWORK_TYPE NETWORK_W5100 #define WEBSOCKETS_NETWORK_TYPE NETWORK_W5100
@ -199,6 +245,47 @@
#define WEBSOCKETS_NETWORK_CLASS WiFiClient #define WEBSOCKETS_NETWORK_CLASS WiFiClient
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer #define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
#include <WiFi.h>
#include <WiFiClientSecure.h>
#define SSL_BARESSL
#define WEBSOCKETS_NETWORK_CLASS WiFiClient
#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
#else #else
#error "no network type selected!" #error "no network type selected!"
#endif #endif

View File

@ -28,23 +28,29 @@
#include <WebSocketsServer.h> #include <WebSocketsServer.h>
#include <ESP8266WebServer.h> #include <ESP8266WebServer.h>
#if WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266 && WEBSERVER_HAS_HOOK #if((WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)) && WEBSERVER_HAS_HOOK
class WebSockets4WebServer : public WebSocketsServerCore { class WebSockets4WebServer : public WebSocketsServerCore {
#if defined(ESP8266)
using WebServerClass = ESP8266WebServer;
#else
using WebServerClass = WebServer;
#endif
public: public:
WebSockets4WebServer(const String & origin = "", const String & protocol = "arduino") WebSockets4WebServer(const String & origin = "", const String & protocol = "arduino")
: WebSocketsServerCore(origin, protocol) { : WebSocketsServerCore(origin, protocol) {
begin(); begin();
} }
ESP8266WebServer::HookFunction hookForWebserver(const String & wsRootDir, WebSocketServerEvent event) { WebServerClass::HookFunction hookForWebserver(const String & wsRootDir, WebSocketServerEvent event) {
onEvent(event); onEvent(event);
return [&, wsRootDir](const String & method, const String & url, WiFiClient * tcpClient, ESP8266WebServer::ContentTypeFunction contentType) { return [&, wsRootDir](const String & method, const String & url, WiFiClient * tcpClient, WebServerClass::ContentTypeFunction contentType) {
(void)contentType; (void)contentType;
if(!(method == "GET" && url.indexOf(wsRootDir) == 0)) { if(!(method == "GET" && url.indexOf(wsRootDir) == 0)) {
return ESP8266WebServer::CLIENT_REQUEST_CAN_CONTINUE; return WebServerClass::CLIENT_REQUEST_CAN_CONTINUE;
} }
// allocate a WiFiClient copy (like in WebSocketsServer::handleNewClients()) // allocate a WiFiClient copy (like in WebSocketsServer::handleNewClients())
@ -63,7 +69,7 @@ class WebSockets4WebServer : public WebSocketsServerCore {
} }
// tell webserver to not close but forget about this client // tell webserver to not close but forget about this client
return ESP8266WebServer::CLIENT_IS_GIVEN; return WebServerClass::CLIENT_IS_GIVEN;
}; };
} }
}; };

View File

@ -48,6 +48,12 @@ void WebSocketsClient::begin(const char * host, uint16_t port, const char * url,
#if defined(HAS_SSL) #if defined(HAS_SSL)
_fingerprint = SSL_FINGERPRINT_NULL; _fingerprint = SSL_FINGERPRINT_NULL;
_CA_cert = 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 #endif
_client.num = 0; _client.num = 0;
@ -76,6 +82,8 @@ void WebSocketsClient::begin(const char * host, uint16_t port, const char * url,
#ifdef ESP8266 #ifdef ESP8266
randomSeed(RANDOM_REG32); randomSeed(RANDOM_REG32);
#elif defined(ARDUINO_ARCH_RP2040)
randomSeed(rp2040.hwrand32());
#else #else
// todo find better seed // todo find better seed
randomSeed(millis()); randomSeed(millis());
@ -105,6 +113,7 @@ void WebSocketsClient::beginSSL(const char * host, uint16_t port, const char * u
_client.isSSL = true; _client.isSSL = true;
_fingerprint = fingerprint; _fingerprint = fingerprint;
_CA_cert = NULL; _CA_cert = NULL;
_CA_bundle = NULL;
} }
void WebSocketsClient::beginSSL(String host, uint16_t port, String url, String fingerprint, String protocol) { void WebSocketsClient::beginSSL(String host, uint16_t port, String url, String fingerprint, String protocol) {
@ -116,7 +125,28 @@ void WebSocketsClient::beginSslWithCA(const char * host, uint16_t port, const ch
_client.isSSL = true; _client.isSSL = true;
_fingerprint = SSL_FINGERPRINT_NULL; _fingerprint = SSL_FINGERPRINT_NULL;
_CA_cert = CA_cert; _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 #else
void WebSocketsClient::beginSSL(const char * host, uint16_t port, const char * url, const uint8_t * fingerprint, const char * protocol) { void WebSocketsClient::beginSSL(const char * host, uint16_t port, const char * url, const uint8_t * fingerprint, const char * protocol) {
begin(host, port, url, protocol); begin(host, port, url, protocol);
@ -125,6 +155,7 @@ void WebSocketsClient::beginSSL(const char * host, uint16_t port, const char * u
_CA_cert = NULL; _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) { void WebSocketsClient::beginSslWithCA(const char * host, uint16_t port, const char * url, BearSSL::X509List * CA_cert, const char * protocol) {
begin(host, port, url, protocol); begin(host, port, url, protocol);
_client.isSSL = true; _client.isSSL = true;
@ -136,14 +167,15 @@ void WebSocketsClient::beginSslWithCA(const char * host, uint16_t port, const ch
beginSslWithCA(host, port, url, new BearSSL::X509List(CA_cert), protocol); 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) { void WebSocketsClient::setSSLClientCertKey(BearSSL::X509List * clientCert, BearSSL::PrivateKey * clientPrivateKey) {
_client_cert = clientCert; _client_cert = clientCert;
_client_key = clientPrivateKey; _client_key = clientPrivateKey;
} }
#endif // SSL_BARESSL
void WebSocketsClient::setSSLClientCertKey(const char * clientCert, const char * clientPrivateKey) {
setSSLClientCertKey(new BearSSL::X509List(clientCert), new BearSSL::PrivateKey(clientPrivateKey));
}
#endif // SSL_AXTLS #endif // SSL_AXTLS
#endif // HAS_SSL #endif // HAS_SSL
@ -212,7 +244,12 @@ void WebSocketsClient::loop(void) {
if(_client.isSSL) { if(_client.isSSL) {
DEBUG_WEBSOCKETS("[WS-Client] connect wss...\n"); DEBUG_WEBSOCKETS("[WS-Client] connect wss...\n");
if(_client.ssl) { 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; delete _client.ssl;
#endif
_client.ssl = NULL; _client.ssl = NULL;
_client.tcp = NULL; _client.tcp = NULL;
} }
@ -224,12 +261,23 @@ void WebSocketsClient::loop(void) {
_client.ssl->setCACert(_CA_cert); _client.ssl->setCACert(_CA_cert);
#elif defined(ESP8266) && defined(SSL_AXTLS) #elif defined(ESP8266) && defined(SSL_AXTLS)
_client.ssl->setCACert((const uint8_t *)_CA_cert, strlen(_CA_cert) + 1); _client.ssl->setCACert((const uint8_t *)_CA_cert, strlen(_CA_cert) + 1);
#elif defined(ESP8266) && defined(SSL_BARESSL) #elif(defined(ESP8266) || defined(ARDUINO_ARCH_RP2040)) && defined(SSL_BARESSL)
_client.ssl->setTrustAnchors(_CA_cert); _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 #else
#error setCACert not implemented #error setCACert not implemented
#endif #endif
#if defined(ESP32) #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) { } else if(!SSL_FINGERPRINT_IS_SET) {
_client.ssl->setInsecure(); _client.ssl->setInsecure();
#elif defined(SSL_BARESSL) #elif defined(SSL_BARESSL)
@ -246,7 +294,11 @@ void WebSocketsClient::loop(void) {
} else { } else {
DEBUG_WEBSOCKETS("[WS-Client] connect ws...\n"); DEBUG_WEBSOCKETS("[WS-Client] connect ws...\n");
if(_client.tcp) { 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; delete _client.tcp;
#endif
_client.tcp = NULL; _client.tcp = NULL;
} }
_client.tcp = new WEBSOCKETS_NETWORK_CLASS(); _client.tcp = new WEBSOCKETS_NETWORK_CLASS();
@ -473,7 +525,7 @@ void WebSocketsClient::messageReceived(WSclient_t * client, WSopcode_t opcode, u
void WebSocketsClient::clientDisconnect(WSclient_t * client) { void WebSocketsClient::clientDisconnect(WSclient_t * client) {
bool event = false; bool event = false;
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
if(client->isSSL && client->ssl) { if(client->isSSL && client->ssl) {
if(client->ssl->connected()) { if(client->ssl->connected()) {
client->ssl->flush(); client->ssl->flush();
@ -496,8 +548,12 @@ void WebSocketsClient::clientDisconnect(WSclient_t * client) {
event = true; event = true;
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
client->status = WSC_NOT_CONNECTED; 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 #else
delete client->tcp; delete client->tcp;
#endif
#endif #endif
client->tcp = NULL; client->tcp = NULL;
} }
@ -733,7 +789,7 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
client->cExtensions = headerValue; client->cExtensions = headerValue;
} else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Version"))) { } else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Version"))) {
client->cVersion = headerValue.toInt(); client->cVersion = headerValue.toInt();
} else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Set-Cookie"))) { } else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Set-Cookie")) && headerValue.indexOf(" io=") > -1) {
if(headerValue.indexOf(';') > -1) { if(headerValue.indexOf(';') > -1) {
client->cSessionId = headerValue.substring(headerValue.indexOf('=') + 1, headerValue.indexOf(";")); client->cSessionId = headerValue.substring(headerValue.indexOf('=') + 1, headerValue.indexOf(";"));
} else { } else {
@ -784,8 +840,10 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
if(client->isSocketIO) { if(client->isSocketIO) {
break; break;
} }
// falls through
case 403: ///< Forbidden case 403: ///< Forbidden
// todo handle login // todo handle login
// falls through
default: ///< Server dont unterstand requrst default: ///< Server dont unterstand requrst
ok = false; ok = false;
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] serverCode is not 101 (%d)\n", client->cCode); DEBUG_WEBSOCKETS("[WS-Client][handleHeader] serverCode is not 101 (%d)\n", client->cCode);
@ -862,7 +920,7 @@ void WebSocketsClient::connectedCb() {
_client.tcp->setTimeout(WEBSOCKETS_TCP_TIMEOUT); _client.tcp->setTimeout(WEBSOCKETS_TCP_TIMEOUT);
#endif #endif
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
_client.tcp->setNoDelay(true); _client.tcp->setNoDelay(true);
#endif #endif

View File

@ -48,11 +48,20 @@ class WebSocketsClient : protected WebSockets {
void beginSSL(String host, uint16_t port, String url = "/", String fingerprint = "", String protocol = "arduino"); void beginSSL(String host, uint16_t port, String url = "/", String fingerprint = "", String protocol = "arduino");
#else #else
void beginSSL(const char * host, uint16_t port, const char * url = "/", const uint8_t * fingerprint = NULL, const char * protocol = "arduino"); 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 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); void setSSLClientCertKey(BearSSL::X509List * clientCert = NULL, BearSSL::PrivateKey * clientPrivateKey = NULL);
#endif
void setSSLClientCertKey(const char * clientCert = NULL, const char * clientPrivateKey = NULL); void setSSLClientCertKey(const char * clientCert = NULL, const char * clientPrivateKey = NULL);
#endif #endif
void beginSslWithCA(const char * host, uint16_t port, const char * url = "/", const char * CA_cert = NULL, const char * protocol = "arduino"); 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 #endif
void beginSocketIO(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino"); void beginSocketIO(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino");
@ -112,17 +121,30 @@ class WebSocketsClient : protected WebSockets {
#ifdef SSL_AXTLS #ifdef SSL_AXTLS
String _fingerprint; String _fingerprint;
const char * _CA_cert; 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_IS_SET (_fingerprint.length())
#define SSL_FINGERPRINT_NULL "" #define SSL_FINGERPRINT_NULL ""
#else #else
const uint8_t * _fingerprint; const uint8_t * _fingerprint;
#if defined(SSL_BARESSL)
BearSSL::X509List * _CA_cert; BearSSL::X509List * _CA_cert;
BearSSL::X509List * _client_cert; BearSSL::X509List * _client_cert;
BearSSL::PrivateKey * _client_key; BearSSL::PrivateKey * _client_key;
#endif
#define SSL_FINGERPRINT_IS_SET (_fingerprint != NULL) #define SSL_FINGERPRINT_IS_SET (_fingerprint != NULL)
#define SSL_FINGERPRINT_NULL NULL #define SSL_FINGERPRINT_NULL NULL
#endif #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 #endif
WSclient_t _client; WSclient_t _client;

View File

@ -25,6 +25,14 @@
#include "WebSockets.h" #include "WebSockets.h"
#include "WebSocketsServer.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) { WebSocketsServerCore::WebSocketsServerCore(const String & origin, const String & protocol) {
_origin = origin; _origin = origin;
_protocol = protocol; _protocol = protocol;
@ -65,6 +73,11 @@ WebSocketsServerCore::~WebSocketsServerCore() {
} }
WebSocketsServer::~WebSocketsServer() { 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,9 +95,13 @@ void WebSocketsServerCore::begin(void) {
#ifdef ESP8266 #ifdef ESP8266
randomSeed(RANDOM_REG32); randomSeed(RANDOM_REG32);
#elif defined(ESP32) && defined(WDEV_RND_REG)
randomSeed(REG_READ(WDEV_RND_REG));
#elif defined(ESP32) #elif defined(ESP32)
#define DR_REG_RNG_BASE 0x3ff75144 #define DR_REG_RNG_BASE 0x3ff75144
randomSeed(READ_PERI_REG(DR_REG_RNG_BASE)); randomSeed(READ_PERI_REG(DR_REG_RNG_BASE));
#elif defined(ARDUINO_ARCH_RP2040)
randomSeed(rp2040.hwrand32());
#else #else
// TODO find better seed // TODO find better seed
randomSeed(millis()); randomSeed(millis());
@ -394,7 +411,7 @@ bool WebSocketsServerCore::clientIsConnected(uint8_t num) {
return clientIsConnected(client); return clientIsConnected(client);
} }
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) #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 * get an IP for a client
* @param num uint8_t client id * @param num uint8_t client id
@ -426,8 +443,16 @@ WSclient_t * WebSocketsServerCore::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclien
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) { for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
client = &_clients[i]; client = &_clients[i];
// 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 // state is not connected or tcp connection is lost
if(!clientIsConnected(client)) {
client->tcp = TCPclient; 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)
@ -439,7 +464,7 @@ WSclient_t * WebSocketsServerCore::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclien
client->tcp->setTimeout(WEBSOCKETS_TCP_TIMEOUT); client->tcp->setTimeout(WEBSOCKETS_TCP_TIMEOUT);
#endif #endif
client->status = WSC_HEADER; client->status = WSC_HEADER;
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) #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 #ifndef NODEBUG_WEBSOCKETS
IPAddress ip = client->tcp->remoteIP(); IPAddress ip = client->tcp->remoteIP();
#endif #endif
@ -516,15 +541,20 @@ void WebSocketsServerCore::messageReceived(WSclient_t * client, WSopcode_t opcod
* @param client WSclient_t * ptr to the client struct contaning the native client "->tcp" * @param client WSclient_t * ptr to the client struct contaning the native client "->tcp"
*/ */
void WebSocketsServerCore::dropNativeClient(WSclient_t * client) { void WebSocketsServerCore::dropNativeClient(WSclient_t * client) {
if(!client) {
return;
}
if(client->tcp) { if(client->tcp) {
if(client->tcp->connected()) { if(client->tcp->connected()) {
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) && (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP32) #if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) && (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP32) && (WEBSOCKETS_NETWORK_TYPE != NETWORK_RP2040)
client->tcp->flush(); client->tcp->flush();
#endif #endif
client->tcp->stop(); client->tcp->stop();
} }
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
client->status = WSC_NOT_CONNECTED; 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 #else
delete client->tcp; delete client->tcp;
#endif #endif
@ -537,7 +567,7 @@ void WebSocketsServerCore::dropNativeClient(WSclient_t * client) {
* @param client WSclient_t * ptr to the client struct * @param client WSclient_t * ptr to the client struct
*/ */
void WebSocketsServerCore::clientDisconnect(WSclient_t * client) { void WebSocketsServerCore::clientDisconnect(WSclient_t * client) {
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
if(client->isSSL && client->ssl) { if(client->isSSL && client->ssl) {
if(client->ssl->connected()) { if(client->ssl->connected()) {
client->ssl->flush(); client->ssl->flush();
@ -611,7 +641,7 @@ WSclient_t * WebSocketsServerCore::handleNewClient(WEBSOCKETS_NETWORK_CLASS * tc
if(!client) { if(!client) {
// no free space to handle client // no free space to handle client
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
#ifndef NODEBUG_WEBSOCKETS #ifndef NODEBUG_WEBSOCKETS
IPAddress ip = tcpClient->remoteIP(); IPAddress ip = tcpClient->remoteIP();
#endif #endif
@ -619,7 +649,12 @@ WSclient_t * WebSocketsServerCore::handleNewClient(WEBSOCKETS_NETWORK_CLASS * tc
#else #else
DEBUG_WEBSOCKETS("[WS-Server] no free space new client\n"); DEBUG_WEBSOCKETS("[WS-Server] no free space new client\n");
#endif #endif
// no client! => create dummy!
WSclient_t dummy = WSclient_t();
client = &dummy;
client->tcp = tcpClient;
dropNativeClient(client); dropNativeClient(client);
return nullptr;
} }
WEBSOCKETS_YIELD(); WEBSOCKETS_YIELD();
@ -631,12 +666,17 @@ WSclient_t * WebSocketsServerCore::handleNewClient(WEBSOCKETS_NETWORK_CLASS * tc
* Handle incoming Connection Request * Handle incoming Connection Request
*/ */
void WebSocketsServer::handleNewClients(void) { void WebSocketsServer::handleNewClients(void) {
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
while(_server->hasClient()) { while(_server->hasClient()) {
#endif #endif
// store new connection // store new connection
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_WIFI_NINA)
WEBSOCKETS_NETWORK_CLASS * tcpClient = new WEBSOCKETS_NETWORK_CLASS(_server->available()); WEBSOCKETS_NETWORK_CLASS * tcpClient = new WEBSOCKETS_NETWORK_CLASS(_server->available());
#else
WEBSOCKETS_NETWORK_CLASS * tcpClient = new WEBSOCKETS_NETWORK_CLASS(_server->accept());
#endif
if(!tcpClient) { if(!tcpClient) {
DEBUG_WEBSOCKETS("[WS-Client] creating Network class failed!"); DEBUG_WEBSOCKETS("[WS-Client] creating Network class failed!");
return; return;
@ -644,7 +684,7 @@ void WebSocketsServer::handleNewClients(void) {
handleNewClient(tcpClient); handleNewClient(tcpClient);
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
} }
#endif #endif
} }
@ -915,7 +955,7 @@ void WebSocketsServer::begin(void) {
void WebSocketsServer::close(void) { void WebSocketsServer::close(void) {
WebSocketsServerCore::close(); WebSocketsServerCore::close();
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
_server->close(); _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(); _server->end();

View File

@ -90,7 +90,7 @@ class WebSocketsServerCore : protected WebSockets {
void enableHeartbeat(uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount); void enableHeartbeat(uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount);
void disableHeartbeat(); void disableHeartbeat();
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) #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); IPAddress remoteIP(uint8_t num);
#endif #endif

View File

@ -1,6 +1,6 @@
/** /**
* @file WebSocketsVersion.h * @file WebSocketsVersion.h
* @date 08.03.2021 * @date 06.09.2024
* @author Markus Sattler * @author Markus Sattler
* *
* Copyright (c) 2015 Markus Sattler. All rights reserved. * Copyright (c) 2015 Markus Sattler. All rights reserved.
@ -25,12 +25,12 @@
#ifndef WEBSOCKETSVERSION_H_ #ifndef WEBSOCKETSVERSION_H_
#define WEBSOCKETSVERSION_H_ #define WEBSOCKETSVERSION_H_
#define WEBSOCKETS_VERSION "2.3.6" #define WEBSOCKETS_VERSION "2.6.1"
#define WEBSOCKETS_VERSION_MAJOR 2 #define WEBSOCKETS_VERSION_MAJOR 2
#define WEBSOCKETS_VERSION_MINOR 3 #define WEBSOCKETS_VERSION_MINOR 6
#define WEBSOCKETS_VERSION_PATCH 6 #define WEBSOCKETS_VERSION_PATCH 1
#define WEBSOCKETS_VERSION_INT 2003006 #define WEBSOCKETS_VERSION_INT 2006001
#endif /* WEBSOCKETSVERSION_H_ */ #endif /* WEBSOCKETSVERSION_H_ */

View File

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

View File

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

View File

@ -1,4 +1,5 @@
#!/bin/bash #!/bin/bash
set -e
function build_sketches() function build_sketches()
{ {
@ -27,11 +28,28 @@ function build_sketches()
done 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() function build_sketch()
{ {
local arduino=$1 local arduino=$1
local sketch=$2 local sketch=$2
$arduino --verify $sketch; $arduino --verify --verbose $sketch;
local result=$? local result=$?
if [ $result -ne 0 ]; then if [ $result -ne 0 ]; then
echo "Build failed ($sketch) build verbose..." echo "Build failed ($sketch) build verbose..."
@ -70,7 +88,7 @@ function get_sketches_json_matrix()
local arduino=$1 local arduino=$1
local srcpath=$2 local srcpath=$2
local platform=$3 local platform=$3
local ideversion=$4 local cliversion=$4
local board=$5 local board=$5
local sketches=($(find $srcpath -name *.ino)) local sketches=($(find $srcpath -name *.ino))
for sketch in "${sketches[@]}" ; do for sketch in "${sketches[@]}" ; do
@ -79,24 +97,34 @@ function get_sketches_json_matrix()
if [[ -f "$sketchdir/.$platform.skip" ]]; then if [[ -f "$sketchdir/.$platform.skip" ]]; then
continue continue
fi 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 if [[ $sketch != ${sketches[-1]} ]] ; then
echo -en "," echo -en ","
fi fi
done 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() function get_core()
{ {
echo Setup core for $1 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 if [ "$1" = "esp8266" ] ; then
mkdir esp8266com mkdir esp8266com
cd esp8266com cd esp8266com
git clone --depth 1 https://github.com/esp8266/Arduino.git esp8266 git clone --depth 1 https://github.com/esp8266/Arduino.git esp8266
cd esp8266/ cd esp8266/
git submodule update --init
rm -rf .git rm -rf .git
cd tools cd tools
python get.py python get.py