Compare commits

..

33 Commits

Author SHA1 Message Date
dependabot[bot]
24f36a78d1 Bump actions/checkout from 4 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [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/v4...v6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-24 11:09:31 +00:00
Razvan Grigore
84f379474d add client disconnect reason text in events (#957) 2025-10-24 16:28:16 +02:00
Razvan Grigore
6801736f98 add getUrl method (#955) 2025-10-17 17:22:47 +02:00
Moritz Ulmer
3af6593a00 Support Arduino >=3.x for custom network client (#954)
Support Arduino >=3.x for custom network client
2025-10-02 17:18:44 +02:00
Links2004
6eee4c6dc6 clang-format 2025-08-13 19:24:49 +02:00
Links2004
a804e8e5e8 bump version to 2.7.0 2025-08-13 19:23:49 +02:00
Moritz Ulmer
8a261ade21 Allow definition of custom network interfaces (#921)
* Allow definition of custom network interfaces

* Create network client interface class

* Change to PIMPL approach

* Add example for custom network clients

Why:

- Show users how to use multiple network interfaces

This change addresses the need by:

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

* Add WebSockets prefix to normal and secure client

Why:

- Avoid name collision
- Fix broken reconnect change

This change addresses the need by:

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

Updating README to include ESP32 support in client mode

* Update README.md

---------

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

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

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

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-24 10:08:07 +00:00
Markus
0980b209ba Create dependabot.yml 2024-08-24 12:07:31 +02:00
Aruna Tennakoon
899cfbdbe7 feat: Support Nano 33 IoT, MKR WIFI 1010, XIAO, Wio Terminal (#901) 2024-08-24 12:01:45 +02:00
Aruna Tennakoon
dcfb0df665 feat: Support Arduino Nano 33 IoT, MKR WIFI 1010 (#898) 2024-08-11 09:09:47 +02:00
Links2004
dc6fd04a98 fix #896 ESP32 Arduino changed setCACertBundle args 2024-08-04 09:40:01 +02:00
Links2004
7da1dc5c6e bump version 2.5.2 2024-07-29 13:07:27 +02:00
Aruna Tennakoon
d6d4c516b3 Support Arduino UNO WIFI 4 (#894)
feat: Arduino UNO R4 WiFi support
2024-07-29 10:11:12 +02:00
Links2004
e364e66884 go back to arduino-cli 0.35.3 since 1.0.0 is buggy
see: https://github.com/arduino/arduino-cli/issues/2643
2024-06-17 17:07:09 +02:00
Links2004
d5f0d3c4b5 remove broken rp2040 2024-06-17 16:47:41 +02:00
Links2004
0e127c9a76 update arduino-cli to 1.0.0 2024-06-17 16:28:59 +02:00
Links2004
11cf06897c update arduino-cli 2024-06-17 16:27:43 +02:00
Links2004
af1b0256b9 bump version to 2.4.2 2024-06-17 16:27:08 +02:00
41 changed files with 1479 additions and 130 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@v6
- 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@v6
- 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@v6
- 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@v6
- 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@v6
- name: check version - name: check version
run: | run: |
@@ -26,7 +26,7 @@ jobs:
prepare_example_json: prepare_example_json:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v6
- name: generate examples - name: generate examples
id: set-matrix id: set-matrix
@@ -37,13 +37,13 @@ jobs:
echo -en "matrix=" >> $GITHUB_OUTPUT echo -en "matrix=" >> $GITHUB_OUTPUT
echo -en "[" >> $GITHUB_OUTPUT echo -en "[" >> $GITHUB_OUTPUT
get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp8266_pico esp8266 0.35.0 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 get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp8266_pico esp8266 0.35.3 esp8266:esp8266:generic:xtal=80,vt=flash,exception=disabled,stacksmash=disabled,ssl=all,mmu=3232,non32xfer=fast,ResetMethod=nodemcu,CrystalFreq=26,FlashFreq=80,FlashMode=qio,eesz=4M2M,led=2,sdk=nonosdk_190703,ip=lm2f,dbg=Serial1,lvl=SSL,wipe=none,baud=115200 >> $GITHUB_OUTPUT
echo -en "," >> $GITHUB_OUTPUT echo -en "," >> $GITHUB_OUTPUT
get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp8266_pico esp8266 0.35.0 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 get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp8266_pico esp8266 0.35.3 esp8266:esp8266:generic:xtal=80,vt=flash,exception=disabled,stacksmash=disabled,ssl=all,mmu=3232,non32xfer=fast,ResetMethod=nodemcu,CrystalFreq=26,FlashFreq=80,FlashMode=qio,eesz=4M2M,led=2,sdk=nonosdk_190703,ip=lm2f,dbg=Disabled,lvl=None____,wipe=none,baud=115200 >> $GITHUB_OUTPUT
echo -en "," >> $GITHUB_OUTPUT echo -en "," >> $GITHUB_OUTPUT
get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp32 esp32 0.35.0 esp32:esp32:esp32:FlashFreq=80 >> $GITHUB_OUTPUT get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp32 esp32 0.35.3 esp32:esp32:esp32:FlashFreq=80 >> $GITHUB_OUTPUT
echo -en "]" >> $GITHUB_OUTPUT echo -en "]" >> $GITHUB_OUTPUT
echo >> $GITHUB_OUTPUT echo >> $GITHUB_OUTPUT
@@ -55,27 +55,27 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
CLI_VERSION: [0.35.0] CLI_VERSION: [0.35.3]
env: env:
CLI_VERSION: ${{ matrix.CLI_VERSION }} CLI_VERSION: ${{ matrix.CLI_VERSION }}
ARDUINO_DIRECTORIES_DATA: /home/runner/arduino_ide ARDUINO_DIRECTORIES_DATA: /home/runner/arduino_ide
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v6
- name: Get Date - name: Get hash
id: get-date id: get-hash
run: | run: |
echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT echo "hash=$(/bin/date -u "+%Y%m%d")-$(md5sum ".github/workflows/main.yml" | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT
shell: bash shell: bash
- uses: actions/cache@v3 - 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.CLI_VERSION }}-cli 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'
@@ -116,25 +116,25 @@ jobs:
# 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@v6
- 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 "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT echo "hash=$(/bin/date -u "+%Y%m%d")-$(md5sum ".github/workflows/main.yml" | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT
shell: bash shell: bash
- uses: actions/cache@v3 - 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.cliversion }}-cli 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'

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.
@@ -32,6 +32,9 @@ a WebSocket Server and Client for Arduino based on RFC6455.
- 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: ######
@@ -44,6 +47,7 @@ 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.
@@ -104,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

@@ -112,7 +112,13 @@ void setup() {
// server address, port and URL. This server can be flakey. // server address, port and URL. This server can be flakey.
// Expected response: Request served by 0123456789abcdef // Expected response: Request served by 0123456789abcdef
// webSocket.beginSslWithBundle("echo.websocket.org", 443, "/", rootca_crt_bundle_start, ""); // 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, ""); webSocket.beginSslWithBundle("echo.websocket.org", 443, "/", NULL, "");
#endif
// event handler // event handler
webSocket.onEvent(webSocketEvent); webSocket.onEvent(webSocketEvent);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,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, raspberrypi", "platforms": "*",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/Links2004/arduinoWebSockets.git" "url": "https://github.com/Links2004/arduinoWebSockets.git"
}, },
"version": "2.4.1" "version": "2.7.1"
} }

View File

@@ -1,5 +1,5 @@
name=WebSockets name=WebSockets
version=2.4.1 version=2.7.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

@@ -55,10 +55,12 @@ class SocketIOclient : protected WebSocketsClient {
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); 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", 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", 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", uint32_t pingInterval = 60 * 1000, uint32_t pongTimeout = 90 * 1000, uint8_t disconnectTimeoutCount = 5);
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);

View File

@@ -93,6 +93,24 @@
#define WEBSOCKETS_YIELD() yield() #define WEBSOCKETS_YIELD() yield()
#define WEBSOCKETS_YIELD_MORE() delay(1) #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!
@@ -114,6 +132,10 @@
#define NETWORK_ESP32 (4) #define NETWORK_ESP32 (4)
#define NETWORK_ESP32_ETH (5) #define NETWORK_ESP32_ETH (5)
#define NETWORK_RP2040 (6) #define NETWORK_RP2040 (6)
#define NETWORK_UNOWIFIR4 (7)
#define NETWORK_WIFI_NINA (8)
#define NETWORK_SAMD_SEED (9)
#define NETWORK_CUSTOM (10)
// max size of the WS Message Header // max size of the WS Message Header
#define WEBSOCKETS_MAX_HEADER_SIZE (14) #define WEBSOCKETS_MAX_HEADER_SIZE (14)
@@ -132,6 +154,15 @@
#elif defined(ARDUINO_ARCH_RP2040) #elif defined(ARDUINO_ARCH_RP2040)
#define WEBSOCKETS_NETWORK_TYPE NETWORK_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
@@ -224,6 +255,46 @@
#define WEBSOCKETS_NETWORK_SSL_CLASS WiFiClientSecure #define WEBSOCKETS_NETWORK_SSL_CLASS WiFiClientSecure
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer #define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_UNOWIFIR4)
#include <WiFiS3.h>
#define WEBSOCKETS_NETWORK_CLASS WiFiClient
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_WIFI_NINA)
#if __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#else
#error "Please install WiFiNINA library!"
#endif
#define WEBSOCKETS_NETWORK_CLASS WiFiClient
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
#define WEBSOCKETS_NETWORK_SSL_CLASS WiFiSSLClient
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_SAMD_SEED)
#if __has_include(<rpcWiFi.h>) && __has_include(<rpcWiFiClientSecure.h>)
#include <rpcWiFi.h>
#include <rpcWiFiClientSecure.h>
#else
#error "Please install rpcWiFi library!"
#endif
#define WEBSOCKETS_NETWORK_CLASS WiFiClient
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
#define WEBSOCKETS_NETWORK_SSL_CLASS WiFiClientSecure
#define WEBSOCKETS_NETWORK_CLASS WiFiClient
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_CUSTOM)
#include <WebSocketsNetworkClientSecure.h>
#include <WiFiServer.h>
#define SSL_AXTLS
#define WEBSOCKETS_NETWORK_CLASS WebSocketsNetworkClient
#define WEBSOCKETS_NETWORK_SSL_CLASS WebSocketsNetworkClientSecure
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
#else #else
#error "no network type selected!" #error "no network type selected!"
#endif #endif
@@ -306,7 +377,7 @@ typedef struct {
#if defined(HAS_SSL) #if defined(HAS_SSL)
bool isSSL = false; ///< run in ssl mode bool isSSL = false; ///< run in ssl mode
WEBSOCKETS_NETWORK_SSL_CLASS * ssl; WEBSOCKETS_NETWORK_SSL_CLASS * ssl = nullptr;
#endif #endif
String cUrl; ///< http url String cUrl; ///< http url

View File

@@ -50,6 +50,9 @@ void WebSocketsClient::begin(const char * host, uint16_t port, const char * url,
_CA_cert = NULL; _CA_cert = NULL;
#ifdef ESP32 #ifdef ESP32
_CA_bundle = NULL; _CA_bundle = NULL;
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 4)
_CA_bundle_size = 0;
#endif
#endif #endif
#endif #endif
@@ -124,6 +127,17 @@ void WebSocketsClient::beginSslWithCA(const char * host, uint16_t port, const ch
_CA_cert = CA_cert; _CA_cert = CA_cert;
_CA_bundle = NULL; _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) { 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); begin(host, port, url, protocol);
_client.isSSL = true; _client.isSSL = true;
@@ -131,6 +145,7 @@ void WebSocketsClient::beginSslWithBundle(const char * host, uint16_t port, cons
_CA_cert = NULL; _CA_cert = NULL;
_CA_bundle = CA_bundle; _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) {
@@ -140,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;
@@ -151,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
@@ -227,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;
} }
@@ -241,15 +263,21 @@ void WebSocketsClient::loop(void) {
_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(ARDUINO_ARCH_RP2040)) && 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) { } else if(_CA_bundle) {
DEBUG_WEBSOCKETS("[WS-Client] setting 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); _client.ssl->setCACertBundle(_CA_bundle);
#endif #endif
#if defined(ESP32)
} 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)
@@ -266,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();
@@ -446,6 +478,19 @@ bool WebSocketsClient::isConnected(void) {
return (_client.status == WSC_CONNECTED); return (_client.status == WSC_CONNECTED);
} }
/**
* RFC 6455
* get the full URL/URI of the connection
*/
String WebSocketsClient::getUrl(void) {
#if defined(HAS_SSL)
String protocol = (_client.isSSL) ? WEBSOCKETS_STRING("wss://") : WEBSOCKETS_STRING("ws://");
#else
String protocol = WEBSOCKETS_STRING("ws://");
#endif
return protocol + _host + ":" + String(_port) + _client.cUrl;
}
// ################################################################################# // #################################################################################
// ################################################################################# // #################################################################################
// ################################################################################# // #################################################################################
@@ -487,13 +532,14 @@ void WebSocketsClient::messageReceived(WSclient_t * client, WSopcode_t opcode, u
} }
/** /**
* Disconnect an client * Disconnect a client
* @param client WSclient_t * ptr to the client struct * @param client WSclient_t * ptr to the client struct
* @param reason const char * disconnect reason (optional, defaults to NULL)
*/ */
void WebSocketsClient::clientDisconnect(WSclient_t * client) { void WebSocketsClient::clientDisconnect(WSclient_t * client, const char * reason) {
bool event = false; bool event = false;
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040) #ifdef HAS_SSL
if(client->isSSL && client->ssl) { if(client->isSSL && client->ssl) {
if(client->ssl->connected()) { if(client->ssl->connected()) {
client->ssl->flush(); client->ssl->flush();
@@ -516,8 +562,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;
} }
@@ -535,9 +585,13 @@ void WebSocketsClient::clientDisconnect(WSclient_t * client) {
DEBUG_WEBSOCKETS("[WS-Client] client disconnected.\n"); DEBUG_WEBSOCKETS("[WS-Client] client disconnected.\n");
if(event) { if(event) {
if(reason && strlen(reason) > 0) {
runCbEvent(WStype_DISCONNECTED, (uint8_t *)reason, strlen(reason));
} else {
runCbEvent(WStype_DISCONNECTED, NULL, 0); runCbEvent(WStype_DISCONNECTED, NULL, 0);
} }
} }
}
/** /**
* get client state * get client state
@@ -558,13 +612,13 @@ bool WebSocketsClient::clientIsConnected(WSclient_t * client) {
if(client->status != WSC_NOT_CONNECTED) { if(client->status != WSC_NOT_CONNECTED) {
DEBUG_WEBSOCKETS("[WS-Client] connection lost.\n"); DEBUG_WEBSOCKETS("[WS-Client] connection lost.\n");
// do cleanup // do cleanup
clientDisconnect(client); clientDisconnect(client, "Connection lost");
} }
} }
if(client->tcp) { if(client->tcp) {
// do cleanup // do cleanup
clientDisconnect(client); clientDisconnect(client, "TCP connection cleanup");
} }
return false; return false;
@@ -576,7 +630,7 @@ bool WebSocketsClient::clientIsConnected(WSclient_t * client) {
void WebSocketsClient::handleClientData(void) { void WebSocketsClient::handleClientData(void) {
if((_client.status == WSC_HEADER || _client.status == WSC_BODY) && _lastHeaderSent + WEBSOCKETS_TCP_TIMEOUT < millis()) { if((_client.status == WSC_HEADER || _client.status == WSC_BODY) && _lastHeaderSent + WEBSOCKETS_TCP_TIMEOUT < millis()) {
DEBUG_WEBSOCKETS("[WS-Client][handleClientData] header response timeout.. disconnecting!\n"); DEBUG_WEBSOCKETS("[WS-Client][handleClientData] header response timeout.. disconnecting!\n");
clientDisconnect(&_client); clientDisconnect(&_client, "Header response timeout");
WEBSOCKETS_YIELD(); WEBSOCKETS_YIELD();
return; return;
} }
@@ -811,7 +865,9 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
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);
clientDisconnect(client); // Create disconnect reason with HTTP status code
String reason = "HTTP " + String(client->cCode);
clientDisconnect(client, reason.c_str());
_lastConnectionFail = millis(); _lastConnectionFail = millis();
break; break;
} }
@@ -855,7 +911,11 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
if(clientIsConnected(client)) { if(clientIsConnected(client)) {
write(client, "This is a webSocket client!"); write(client, "This is a webSocket client!");
} }
clientDisconnect(client); String reason = "WebSocket handshake failed";
if(client->cCode > 0) {
reason += " - HTTP " + String(client->cCode);
}
clientDisconnect(client, reason.c_str());
} }
} }
} }

View File

@@ -48,14 +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 #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"); 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 #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");
@@ -106,6 +112,7 @@ class WebSocketsClient : protected WebSockets {
void disableHeartbeat(); void disableHeartbeat();
bool isConnected(void); bool isConnected(void);
String getUrl(void);
protected: protected:
String _host; String _host;
@@ -116,17 +123,29 @@ class WebSocketsClient : protected WebSockets {
String _fingerprint; String _fingerprint;
const char * _CA_cert; const char * _CA_cert;
const uint8_t * _CA_bundle; 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;
@@ -138,7 +157,10 @@ class WebSocketsClient : protected WebSockets {
void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin); void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin);
void clientDisconnect(WSclient_t * client); void clientDisconnect(WSclient_t * client) {
clientDisconnect(client, NULL);
}
void clientDisconnect(WSclient_t * client, const char * reason = NULL);
bool clientIsConnected(WSclient_t * client); bool clientIsConnected(WSclient_t * client);
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) #if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)

View File

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

View File

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

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,7 +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; delete _server;
#endif
} }
/** /**
@@ -83,6 +95,8 @@ 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));
@@ -539,6 +553,8 @@ void WebSocketsServerCore::dropNativeClient(WSclient_t * client) {
} }
#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
@@ -655,7 +671,12 @@ void WebSocketsServer::handleNewClients(void) {
#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());
#else
WEBSOCKETS_NETWORK_CLASS * tcpClient = new WEBSOCKETS_NETWORK_CLASS(_server->accept()); 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;

View File

@@ -1,6 +1,6 @@
/** /**
* @file WebSocketsVersion.h * @file WebSocketsVersion.h
* @date 01.05.2023 * @date 13.08.2025
* @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.4.1" #define WEBSOCKETS_VERSION "2.7.1"
#define WEBSOCKETS_VERSION_MAJOR 2 #define WEBSOCKETS_VERSION_MAJOR 2
#define WEBSOCKETS_VERSION_MINOR 4 #define WEBSOCKETS_VERSION_MINOR 7
#define WEBSOCKETS_VERSION_PATCH 1 #define WEBSOCKETS_VERSION_PATCH 1
#define WEBSOCKETS_VERSION_INT 2004001 #define WEBSOCKETS_VERSION_INT 2007001
#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) || defined(ARDUINO_ARCH_RP2040) #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) || defined(ARDUINO_ARCH_RP2040) #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,6 +1,5 @@
#!/bin/bash #!/bin/bash
set -e
set -x
function build_sketches() function build_sketches()
{ {
@@ -106,11 +105,11 @@ function get_sketches_json_matrix()
} }
function get_core_cli() { 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/global/package_rp2040_index.json" 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 update-index
arduino-cli core install esp8266:esp8266 arduino-cli core install esp8266:esp8266
arduino-cli core install esp32:esp32 arduino-cli core install esp32:esp32
arduino-cli core install arduino:mbed_rp2040 arduino-cli core install rp2040:rp2040
} }
function get_core() function get_core()

View File

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