├── examples ├── PC_Host │ ├── run.sh │ ├── HTTP_Streaming │ │ ├── server │ │ │ ├── run.sh │ │ │ ├── install_libs.sh │ │ │ ├── install_libs.bat │ │ │ ├── run.bat │ │ │ ├── sse_server.py │ │ │ └── Readme.md │ │ └── debug.h │ ├── install_libs.sh │ ├── install_libs.bat │ ├── run.bat │ ├── MQTT │ │ ├── SerialSSLClient.h │ │ ├── debug.h │ │ └── MQTT.ino │ ├── cert │ │ └── Amazon_Root_CA1.pem │ ├── HTTP_GET │ │ ├── debug.h │ │ └── HTTP_GET.ino │ ├── HTTP_POST │ │ ├── debug.h │ │ └── HTTP_POST.ino │ ├── STARTTLS │ │ └── debug.h │ ├── UDP_NTP │ │ └── debug.h │ ├── WebSocket │ │ ├── debug.h │ │ └── WebSocket.ino │ ├── Host_Management │ │ ├── debug.h │ │ └── Host_Management.ino │ ├── Secure_Connection │ │ └── debug.h │ └── Readme.md ├── Device_Host │ ├── Generic_Client │ │ ├── HTTP_Streaming │ │ │ ├── server │ │ │ │ ├── run.sh │ │ │ │ ├── install_libs.sh │ │ │ │ ├── install_libs.bat │ │ │ │ ├── run.bat │ │ │ │ ├── sse_server.py │ │ │ │ └── Readme.md │ │ │ └── debug.h │ │ ├── Host │ │ │ ├── Filesystem.h │ │ │ └── Host.ino │ │ ├── cert │ │ │ └── Amazon_Root_CA1.pem │ │ ├── NeoHWSerial │ │ │ ├── InterruptStream.h │ │ │ ├── debug.h │ │ │ └── NeoHWSerial.ino │ │ ├── MQTT │ │ │ ├── debug.h │ │ │ └── MQTT.ino │ │ ├── UDP_NTP │ │ │ └── debug.h │ │ ├── HTTP_GET │ │ │ ├── debug.h │ │ │ └── HTTP_GET.ino │ │ ├── HTTP_POST │ │ │ ├── debug.h │ │ │ └── HTTP_POST.ino │ │ ├── STARTTLS │ │ │ └── debug.h │ │ ├── WebSocket │ │ │ ├── debug.h │ │ │ └── Websocket.ino │ │ ├── Host_Management │ │ │ ├── debug.h │ │ │ └── Host_Management.ino │ │ └── Secure_Connection │ │ │ └── debug.h │ └── Async_Client │ │ ├── Host │ │ └── Host.ino │ │ └── AsyncTCP_Client │ │ ├── debug.h │ │ └── AsyncTCP_Client.ino └── Readme.md ├── .gitignore ├── src ├── SerialNetworkBridge.h ├── include │ ├── HostReboot.h │ └── HostNVS.h └── SerialHostManager.h ├── library.properties ├── library.json ├── LICENSE ├── .github └── workflows │ └── ci.yml ├── assets ├── diagram_pc.svg ├── diagram.svg └── logo.svg └── keywords.txt /examples/PC_Host/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd "$(dirname "$0")" 3 | python3 serial_bridge.py -------------------------------------------------------------------------------- /examples/PC_Host/HTTP_Streaming/server/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd "$(dirname "$0")" 3 | python3 sse_server.py -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .pio 2 | .vscode/.browse.c_cpp.db* 3 | .vscode/c_cpp_properties.json 4 | .vscode/launch.json 5 | .vscode/ipch 6 | -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/HTTP_Streaming/server/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd "$(dirname "$0")" 3 | python3 sse_server.py -------------------------------------------------------------------------------- /examples/PC_Host/HTTP_Streaming/server/install_libs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if running as root 4 | if [ "$EUID" -ne 0 ]; then 5 | echo "Re-running with sudo..." 6 | exec sudo "$0" "$@" 7 | fi 8 | 9 | cd "$(dirname "$0")" 10 | python3 -m pip install --upgrade pip 11 | python3 -m pip install flask -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/HTTP_Streaming/server/install_libs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if running as root 4 | if [ "$EUID" -ne 0 ]; then 5 | echo "Re-running with sudo..." 6 | exec sudo "$0" "$@" 7 | fi 8 | 9 | cd "$(dirname "$0")" 10 | python3 -m pip install --upgrade pip 11 | python3 -m pip install flask -------------------------------------------------------------------------------- /examples/PC_Host/install_libs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if running as root 4 | if [ "$EUID" -ne 0 ]; then 5 | echo "Re-running with sudo..." 6 | exec sudo "$0" "$@" 7 | fi 8 | 9 | cd "$(dirname "$0")" 10 | python3 -m pip install --upgrade pip 11 | python3 -m pip install pyserial cobs websocket-client colorama pywifi comtypes 12 | -------------------------------------------------------------------------------- /src/SerialNetworkBridge.h: -------------------------------------------------------------------------------- 1 | #ifndef SERIAL_NETWORK_BRIDGE_H 2 | #define SERIAL_NETWORK_BRIDGE_H 3 | 4 | #include 5 | #include "SerialAsyncTCPClient.h" 6 | #include "SerialTCPClient.h" 7 | #include "SerialWebsocketClient.h" 8 | #include "SerialUDPClient.h" 9 | #include "SerialNetworkHost.h" 10 | #include "SerialHostManager.h" 11 | 12 | #endif -------------------------------------------------------------------------------- /examples/PC_Host/HTTP_Streaming/server/install_libs.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | :: Check for admin rights 3 | net session >nul 2>&1 4 | if %errorLevel% == 0 ( 5 | echo Running as Administrator... 6 | ) else ( 7 | echo Requesting Administrator privileges... 8 | powershell -Command "Start-Process '%~f0' -Verb RunAs" 9 | exit /b 10 | ) 11 | 12 | cd /d "%~dp0" 13 | python -m pip install --upgrade pip 14 | python -m pip install flask 15 | -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/HTTP_Streaming/server/install_libs.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | :: Check for admin rights 3 | net session >nul 2>&1 4 | if %errorLevel% == 0 ( 5 | echo Running as Administrator... 6 | ) else ( 7 | echo Requesting Administrator privileges... 8 | powershell -Command "Start-Process '%~f0' -Verb RunAs" 9 | exit /b 10 | ) 11 | 12 | cd /d "%~dp0" 13 | python -m pip install --upgrade pip 14 | python -m pip install flask 15 | -------------------------------------------------------------------------------- /examples/PC_Host/install_libs.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | :: Check for admin rights 3 | net session >nul 2>&1 4 | if %errorLevel% == 0 ( 5 | echo Running as Administrator... 6 | ) else ( 7 | echo Requesting Administrator privileges... 8 | powershell -Command "Start-Process '%~f0' -Verb RunAs" 9 | exit /b 10 | ) 11 | 12 | cd /d "%~dp0" 13 | python -m pip install --upgrade pip 14 | python -m pip install pyserial cobs websocket-client colorama pywifi comtypes 15 | 16 | pause 17 | -------------------------------------------------------------------------------- /examples/PC_Host/run.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | :: Batch file to run Python script in this folder with admin rights 3 | 4 | :: Check for admin rights 5 | net session >nul 2>&1 6 | if %errorLevel% == 0 ( 7 | echo Running as Administrator... 8 | ) else ( 9 | echo Requesting Administrator privileges... 10 | powershell -Command "Start-Process '%~f0' -Verb RunAs" 11 | exit /b 12 | ) 13 | 14 | :: Change to the folder where the batch file is located 15 | cd /d "%~dp0" 16 | 17 | :: Run the Python script (replace script.py with your filename) 18 | python serial_bridge.py 19 | 20 | pause 21 | -------------------------------------------------------------------------------- /examples/PC_Host/HTTP_Streaming/server/run.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | :: Batch file to run Python script in this folder with admin rights 3 | 4 | :: Check for admin rights 5 | net session >nul 2>&1 6 | if %errorLevel% == 0 ( 7 | echo Running as Administrator... 8 | ) else ( 9 | echo Requesting Administrator privileges... 10 | powershell -Command "Start-Process '%~f0' -Verb RunAs" 11 | exit /b 12 | ) 13 | 14 | :: Change to the folder where the batch file is located 15 | cd /d "%~dp0" 16 | 17 | :: Run the Python script (replace script.py with your filename) 18 | python sse_server.py 19 | 20 | pause -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/HTTP_Streaming/server/run.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | :: Batch file to run Python script in this folder with admin rights 3 | 4 | :: Check for admin rights 5 | net session >nul 2>&1 6 | if %errorLevel% == 0 ( 7 | echo Running as Administrator... 8 | ) else ( 9 | echo Requesting Administrator privileges... 10 | powershell -Command "Start-Process '%~f0' -Verb RunAs" 11 | exit /b 12 | ) 13 | 14 | :: Change to the folder where the batch file is located 15 | cd /d "%~dp0" 16 | 17 | :: Run the Python script (replace script.py with your filename) 18 | python sse_server.py 19 | 20 | pause -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=SerialNetworkBridge 2 | version=2.0.0 3 | author=mobizt 4 | maintainer=mobizt 5 | sentence=Bridge TCP, UDP, and WebSocket client communication over serial. 6 | paragraph=Enables non-networked Arduino boards to perform TCP, UDP, and WebSocket client operations. Bridges communication via a WiFi-capable host (ESP32/ESP8266) OR a PC/Raspberry Pi via USB (Python). Features include SSL/TLS support, datagram handling, and async events. 7 | category=Communication 8 | url=https://github.com/mobizt/SerialNetworkBridge 9 | architectures=* 10 | includes=SerialNetworkBridge.h 11 | depends=ArduinoMqttClient,WebSockets -------------------------------------------------------------------------------- /examples/PC_Host/HTTP_Streaming/server/sse_server.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, Response 2 | import time 3 | import json 4 | import random 5 | 6 | app = Flask(__name__) 7 | 8 | def generate_events(): 9 | while True: 10 | # Simulate dynamic data 11 | event_id = random.randint(1, 1000) 12 | news = { 13 | "id": event_id, 14 | "title": f"title {event_id}", 15 | "content": f"content {event_id}" 16 | } 17 | 18 | # Format SSE message 19 | yield f"id: {event_id}\ndata: {json.dumps({'news': [news]})}\n\n" 20 | 21 | time.sleep(2) # send every 2 seconds 22 | 23 | @app.route("/stream") 24 | def stream(): 25 | return Response(generate_events(), mimetype="text/event-stream") 26 | 27 | if __name__ == "__main__": 28 | app.run(debug=True, threaded=True) 29 | -------------------------------------------------------------------------------- /examples/PC_Host/MQTT/SerialSSLClient.h: -------------------------------------------------------------------------------- 1 | #ifndef __SERIAL_SSL_CLIENT_H__ 2 | #define __SERIAL_SSL_CLIENT_H__ 3 | 4 | #include 5 | 6 | // HELPER CLASS TO FORCE SSL 7 | // The ArduinoMqttClient calls connect(host, port) without the 3rd 'ssl' arg. 8 | // This class overrides that behavior to ALWAYS send 'true' (SSL Enabled) to the bridge. 9 | class SerialSSLClient : public SerialTCPClient 10 | { 11 | public: 12 | using SerialTCPClient::SerialTCPClient; // Inherit constructors 13 | 14 | // Override the standard connect method 15 | int connect(const char *host, uint16_t port) override 16 | { 17 | // Force use_ssl = true 18 | return SerialTCPClient::connect(host, port, true); 19 | } 20 | 21 | // Pull in IPAddress overload to avoid hiding it 22 | using SerialTCPClient::connect; 23 | }; 24 | 25 | #endif -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/HTTP_Streaming/server/sse_server.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, Response 2 | import time 3 | import json 4 | import random 5 | 6 | app = Flask(__name__) 7 | 8 | def generate_events(): 9 | while True: 10 | # Simulate dynamic data 11 | event_id = random.randint(1, 1000) 12 | news = { 13 | "id": event_id, 14 | "title": f"title {event_id}", 15 | "content": f"content {event_id}" 16 | } 17 | 18 | # Format SSE message 19 | yield f"id: {event_id}\ndata: {json.dumps({'news': [news]})}\n\n" 20 | 21 | time.sleep(2) # send every 2 seconds 22 | 23 | @app.route("/stream") 24 | def stream(): 25 | return Response(generate_events(), mimetype="text/event-stream") 26 | 27 | if __name__ == "__main__": 28 | app.run(debug=True, threaded=True) 29 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "SerialNetworkBridge", 3 | "version": "2.0.0", 4 | "description": "A serial-to-network bridge allowing non-networked Arduino boards (Uno, Nano, STM32, etc.) to perform TCP, UDP, WebSocket, and SSL/TLS client operations via a WiFi-capable host (ESP32) or a PC/Raspberry Pi (Python).", 5 | "keywords": [ 6 | "TCP", 7 | "UDP", 8 | "WebSocket", 9 | "serial", 10 | "bridge", 11 | "WiFi", 12 | "ESP32", 13 | "ESP8266", 14 | "client", 15 | "SSL", 16 | "TLS", 17 | "python", 18 | "pc-host", 19 | "gateway" 20 | ], 21 | "repository": { 22 | "type": "git", 23 | "url": "https://github.com/mobizt/SerialNetworkBridge" 24 | }, 25 | "authors": [ 26 | { 27 | "name": "mobizt", 28 | "email": "suwatchai@outlook.com", 29 | "maintainer": true 30 | } 31 | ], 32 | "license": "MIT", 33 | "frameworks": "arduino", 34 | "platforms": "*", 35 | "headers": [ 36 | "SerialNetworkBridge.h" 37 | ], 38 | "dependencies": [ 39 | "ArduinoMqttClient","WebSockets" 40 | ] 41 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Suwatchai K. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/Host/Filesystem.h: -------------------------------------------------------------------------------- 1 | #ifndef __FILESYSTEM_H__ 2 | #define __FILESYSTEM_H__ 3 | 4 | // ESP8266 5 | #if defined(ESP8266) 6 | #include 7 | #define __filesystem LittleFS 8 | 9 | // ESP32 10 | #elif defined(ESP32) 11 | #ifdef USE_LITTLEFS 12 | #include 13 | #define __filesystem LittleFS 14 | #else 15 | #include 16 | #define __filesystem SPIFFS 17 | #endif 18 | 19 | // Raspberry Pi Pico W (Earle Philhower Core) 20 | #elif defined(ARDUINO_RASPBERRY_PI_PICO_W) 21 | #include 22 | #define __filesystem LittleFS 23 | 24 | // SAMD (Arduino Zero, MKR) 25 | #elif defined(ARDUINO_ARCH_SAMD) 26 | 27 | 28 | // STM32 29 | #elif defined(ARDUINO_ARCH_STM32) 30 | 31 | 32 | // Teensy 33 | #elif defined(TEENSYDUINO) 34 | #include // requires external flash chip 35 | #define __filesystem LittleFS 36 | 37 | // Renesas RA/RX 38 | #elif defined(__RENESAS_RA__) || defined(__RENESAS_RX__) 39 | #include // vendor-provided 40 | #define __filesystem FatFS 41 | 42 | // AVR (Uno, Mega) 43 | #elif defined(ARDUINO_ARCH_AVR) 44 | 45 | 46 | #else 47 | // #warning "No flash filesystem available for this platform" 48 | #endif 49 | 50 | #endif -------------------------------------------------------------------------------- /examples/PC_Host/cert/Amazon_Root_CA1.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF 3 | ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 4 | b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL 5 | MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv 6 | b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj 7 | ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM 8 | 9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw 9 | IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 10 | VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L 11 | 93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm 12 | jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC 13 | AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA 14 | A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI 15 | U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs 16 | N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv 17 | o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU 18 | 5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy 19 | rqXRfboQnoZsG4q5WTP468SQvvG5 20 | -----END CERTIFICATE----- 21 | -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/cert/Amazon_Root_CA1.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF 3 | ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 4 | b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL 5 | MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv 6 | b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj 7 | ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM 8 | 9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw 9 | IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 10 | VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L 11 | 93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm 12 | jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC 13 | AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA 14 | A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI 15 | U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs 16 | N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv 17 | o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU 18 | 5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy 19 | rqXRfboQnoZsG4q5WTP468SQvvG5 20 | -----END CERTIFICATE----- 21 | -------------------------------------------------------------------------------- /examples/PC_Host/HTTP_Streaming/server/Readme.md: -------------------------------------------------------------------------------- 1 | # Python SSE Server for HTTP Streaming Example 2 | 3 | This folder contains a simple Python Flask server that acts as the target for the **HTTP Streaming (SSE)** example. It simulates a live data stream by sending JSON events every 2 seconds. 4 | 5 | ## 📋 Prerequisites 6 | 7 | * **Python 3.7+** installed on your system. 8 | * **Pip** (Python package manager). 9 | 10 | ## 📦 Installation 11 | 12 | You need to install the `Flask` library. Automatic scripts are provided for convenience. 13 | 14 | ### Windows 15 | Double-click **`install_libs.bat`**. 16 | * This script runs as Administrator to upgrade pip and install `flask`. 17 | 18 | ### Linux / macOS 19 | Open a terminal in this directory and run: 20 | ```bash 21 | chmod +x install_libs.sh 22 | ./install_libs.sh 23 | ``` 24 | * This script uses `sudo` to install dependencies. 25 | 26 | ## 🚀 How to Run 27 | 28 | ### Windows 29 | Double-click **`run.bat`**. 30 | * This launches `sse_server.py` in a new window. 31 | 32 | ### Linux / macOS 33 | Open a terminal in this directory and run: 34 | ```bash 35 | chmod +x run.sh 36 | ./run.sh 37 | ``` 38 | * This executes `python3 sse_server.py`. 39 | 40 | ## 🌐 Server Details 41 | * **URL:** `http://localhost:5000/stream` 42 | * **Method:** `GET` 43 | * **Format:** Server-Sent Events (SSE) 44 | * **Output:** JSON payloads (`{"news": [...]}`) sent every 2 seconds. 45 | 46 | --- 47 | **Note:** Keep this server running **AND** the `serial_bridge.py` (from the parent directory) running simultaneously to allow the Arduino to connect. -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/HTTP_Streaming/server/Readme.md: -------------------------------------------------------------------------------- 1 | # Python SSE Server for HTTP Streaming Example 2 | 3 | This folder contains a simple Python Flask server that acts as the target for the **HTTP Streaming (SSE)** example. It simulates a live data stream by sending JSON events every 2 seconds. 4 | 5 | ## 📋 Prerequisites 6 | 7 | * **Python 3.7+** installed on your system. 8 | * **Pip** (Python package manager). 9 | 10 | ## 📦 Installation 11 | 12 | You need to install the `Flask` library. Automatic scripts are provided for convenience. 13 | 14 | ### Windows 15 | Double-click **`install_libs.bat`**. 16 | * This script runs as Administrator to upgrade pip and install `flask`. 17 | 18 | ### Linux / macOS 19 | Open a terminal in this directory and run: 20 | ```bash 21 | chmod +x install_libs.sh 22 | ./install_libs.sh 23 | ``` 24 | * This script uses `sudo` to install dependencies. 25 | 26 | ## 🚀 How to Run 27 | 28 | ### Windows 29 | Double-click **`run.bat`**. 30 | * This launches `sse_server.py` in a new window. 31 | 32 | ### Linux / macOS 33 | Open a terminal in this directory and run: 34 | ```bash 35 | chmod +x run.sh 36 | ./run.sh 37 | ``` 38 | * This executes `python3 sse_server.py`. 39 | 40 | ## 🌐 Server Details 41 | * **URL:** `http://localhost:5000/stream` 42 | * **Method:** `GET` 43 | * **Format:** Server-Sent Events (SSE) 44 | * **Output:** JSON payloads (`{"news": [...]}`) sent every 2 seconds. 45 | 46 | --- 47 | **Note:** Keep this server running **AND** the `serial_bridge.py` (from the parent directory) running simultaneously to allow the Arduino to connect. -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: PlatformIO CI 2 | 3 | on: 4 | push: 5 | branches: [ "main", "master" ] 6 | pull_request: 7 | branches: [ "main", "master" ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | include: 16 | 17 | - name: "Client - MQTT (ESP32)" 18 | example: "examples/Device_Host/Generic_Client/MQTT/MQTT.ino" 19 | board: esp32dev 20 | lib_deps: "ArduinoMqttClient" 21 | 22 | 23 | - name: "Client - UDP NTP (ESP32)" 24 | example: "examples/Device_Host/Generic_Client/UDP_NTP/UDP_NTP.ino" 25 | board: esp32dev 26 | lib_deps: "" 27 | 28 | - name: "Client - WebSocket (ESP32)" 29 | example: "examples/Device_Host/Generic_Client/WebSocket/WebSocket.ino" 30 | board: esp32dev 31 | lib_deps: "" 32 | 33 | - name: "Host (ESP32)" 34 | example: "examples/Device_Host/Generic_Client/Host/Host.ino" 35 | board: esp32dev 36 | lib_deps: "Links2004/WebSockets" 37 | 38 | 39 | steps: 40 | - name: Checkout Code 41 | uses: actions/checkout@v3 42 | 43 | - name: Set up Python 44 | uses: actions/setup-python@v4 45 | with: 46 | python-version: '3.9' 47 | 48 | - name: Install PlatformIO Core 49 | run: pip install -U platformio 50 | 51 | - name: Build Example 52 | env: 53 | PLATFORMIO_CI_SRC: ${{ matrix.example }} 54 | run: | 55 | if [ -n "${{ matrix.lib_deps }}" ]; then 56 | LIB_DEPS_ARG="--project-option=lib_deps=${{ matrix.lib_deps }}" 57 | else 58 | LIB_DEPS_ARG="" 59 | fi 60 | 61 | echo "Building ${{ matrix.example }} for ${{ matrix.board }}..." 62 | 63 | pio ci "$PLATFORMIO_CI_SRC" \ 64 | --board=${{ matrix.board }} \ 65 | --lib="." \ 66 | $LIB_DEPS_ARG -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/NeoHWSerial/InterruptStream.h: -------------------------------------------------------------------------------- 1 | #ifndef INTERRUPT_STREAM_H 2 | #define INTERRUPT_STREAM_H 3 | 4 | #include 5 | #include 6 | 7 | // Define buffer size (Power of 2 is best for performance) 8 | #define ISR_BUF_SIZE 1024 9 | 10 | class InterruptStream : public Stream { 11 | private: 12 | volatile uint8_t _buffer[ISR_BUF_SIZE]; 13 | volatile uint16_t _head; 14 | volatile uint16_t _tail; 15 | NeoHWSerial *_txPort; // Pointer to the real hardware port for sending data OUT 16 | 17 | public: 18 | // Constructor: Pass the NeoSerial port you want to write to (e.g., NeoSerial1) 19 | InterruptStream(NeoHWSerial &port) : _head(0), _tail(0), _txPort(&port) {} 20 | 21 | // ----------------------------------------------------------------- 22 | // ISR METHOD: Call this inside your NeoHWSerial attachInterrupt function 23 | // ----------------------------------------------------------------- 24 | inline void push(uint8_t c) { 25 | uint16_t next = (_head + 1) % ISR_BUF_SIZE; 26 | 27 | // Only write if buffer is not full 28 | if (next != _tail) { 29 | _buffer[_head] = c; 30 | _head = next; 31 | } 32 | // Else: Buffer overflow - byte dropped (increase ISR_BUF_SIZE if this happens) 33 | } 34 | 35 | // ----------------------------------------------------------------- 36 | // STREAM INTERFACE (Used by SerialNetworkBridge) 37 | // ----------------------------------------------------------------- 38 | virtual int available() { 39 | return (ISR_BUF_SIZE + _head - _tail) % ISR_BUF_SIZE; 40 | } 41 | 42 | virtual int read() { 43 | if (_head == _tail) return -1; 44 | uint8_t c = _buffer[_tail]; 45 | _tail = (_tail + 1) % ISR_BUF_SIZE; 46 | return c; 47 | } 48 | 49 | virtual int peek() { 50 | if (_head == _tail) return -1; 51 | return _buffer[_tail]; 52 | } 53 | 54 | // Pass output data directly to the hardware UART 55 | virtual size_t write(uint8_t c) { 56 | return _txPort->write(c); 57 | } 58 | 59 | // Support for writing buffers 60 | virtual size_t write(const uint8_t *buffer, size_t size) { 61 | return _txPort->write(buffer, size); 62 | } 63 | 64 | virtual void flush() { 65 | _txPort->flush(); 66 | } 67 | }; 68 | 69 | #endif -------------------------------------------------------------------------------- /assets/diagram_pc.svg: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 24 | Arduino (Client) 25 | SerialTCP / UDP / WS 26 | 27 | 28 | PC / RPi Host 29 | Python Script 30 | 31 | 32 | TCP / UDP / WS Server 33 | Internet/Cloud 34 | 35 | 36 | 37 | 38 | USB Serial 39 | Protocol: COBS+CRC 40 | Commands: BEGIN/WRITE/END 41 | 42 | 43 | 44 | 45 | OS Network 46 | Python Socket Lib 47 | WiFi / Ethernet 48 | -------------------------------------------------------------------------------- /examples/Device_Host/Async_Client/Host/Host.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * =============================================== 3 | * Device Host Serial Bridge for AsyncTCP 4 | * =============================================== 5 | * Runs on: ESP32 using AsyncTCP client. 6 | * Purpose: Provide the example to use ESP32's AsyncTCP as a client in ESP32 host device. 7 | * Requirement: Define USE_ASYNC_CLIENT macro to use. 8 | * 9 | * For more Host features, please see examples/Device_Host/Generic_Client/Host 10 | * 11 | * Macros explanation 12 | * 13 | * ENABLE_LOCAL_DEBUG The macro to allow local debug to show on Serial port. 14 | * 15 | * WIFI_SSID The default WiFi AP SSID 16 | * 17 | * WIFI_PASSWORD The default WiFi AP Password 18 | * 19 | * BridgeRate The bridge serial port baud rate. 20 | * Should be matched with client device serial baud rate. 21 | * Should not exceed 115200 for AVR 22 | * 23 | * BridgeSerial The serial port that is connected to the client device serial port. 24 | * 25 | */ 26 | 27 | #define ENABLE_LOCAL_DEBUG 28 | #define USE_ASYNC_CLIENT 29 | 30 | #define WIFI_SSID "ssid" 31 | #define WIFI_PASSWORD "password" 32 | #define BridgeRate 115200 33 | #define BridgeSerial Serial2 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | SerialNetworkHost host(BridgeSerial); 41 | AsyncClient asyncTcpClient; // The AsyncTCP object 42 | 43 | void setup() 44 | { 45 | Serial.begin(115200); 46 | delay(2000); 47 | 48 | BridgeSerial.begin(BridgeRate); 49 | 50 | WiFi.begin(WIFI_SSID, WIFI_PASSWORD); 51 | while (WiFi.status() != WL_CONNECTED) 52 | delay(500); 53 | 54 | // Assign the AsyncClient to Slot 0 55 | host.setAsyncClient(&asyncTcpClient, 0); 56 | 57 | // Connect to WiFi 58 | 59 | Serial.println("[Host] Connecting to WiFi AP: "); 60 | Serial.println(WIFI_SSID); 61 | Serial.println("..."); 62 | 63 | WiFi.begin(WIFI_SSID, WIFI_PASSWORD); 64 | while (WiFi.status() != WL_CONNECTED) 65 | delay(500); 66 | 67 | Serial.println("[Host] WiFi AP connected!"); 68 | 69 | // Notify the client that host is rebooted/ready. 70 | // This resets the client's internal state for a fresh session. 71 | host.notifyBoot(); 72 | 73 | Serial.println("Device Host Serial Bridge started."); 74 | } 75 | 76 | void loop() 77 | { 78 | // Reqouirements for Host operation 79 | host.loop(); 80 | } -------------------------------------------------------------------------------- /assets/diagram.svg: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 24 | Arduino (Client) 25 | SerialTCP / UDP / WS 26 | 27 | 28 | ESP32/ESP8266 Host 29 | SerialNetworkHost 30 | 31 | 32 | TCP / UDP / WS Server 33 | Internet/Cloud 34 | 35 | 36 | 37 | 38 | Serial Link 39 | Protocol: COBS+CRC 40 | Commands: BEGIN/WRITE/END 41 | 42 | 43 | 44 | 45 | WiFi/Ethernet 46 | Native Stack 47 | TCP / UDP / WS 48 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For SerialNetworkBridge 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | SerialTCPClient KEYWORD1 10 | SerialAsyncTCPClient KEYWORD1 11 | SerialUDPClient KEYWORD1 12 | SerialWebsocketClient KEYWORD1 13 | SerialNetworkHost KEYWORD1 14 | SerialHostManager KEYWORD1 15 | SerialNetworkProtocol KEYWORD1 16 | 17 | ####################################### 18 | # Methods and Functions (KEYWORD2) 19 | ####################################### 20 | 21 | setSlot KEYWORD2 22 | pingHost KEYWORD2 23 | setLocalDebugLevel KEYWORD2 24 | setCACert KEYWORD2 25 | startTLS KEYWORD2 26 | isSSL KEYWORD2 27 | availableForWrite KEYWORD2 28 | notifyBoot KEYWORD2 29 | setTCPClient KEYWORD2 30 | setAsyncClient KEYWORD2 31 | setUDPClient KEYWORD2 32 | setWebSocketClient KEYWORD2 33 | setWebSocketCallback KEYWORD2 34 | setStartTLSCallback KEYWORD2 35 | setSetWiFiCallback KEYWORD2 36 | setConnectNetworkCallback KEYWORD2 37 | setRebootCallback KEYWORD2 38 | setPreConnectCallback KEYWORD2 39 | setWiFi KEYWORD2 40 | connectNetwork KEYWORD2 41 | disconnectNetwork KEYWORD2 42 | isNetworkConnected KEYWORD2 43 | rebootHost KEYWORD2 44 | setDebugLevel KEYWORD2 45 | loop KEYWORD2 46 | readChunkSize KEYWORD2 47 | beginPacket KEYWORD2 48 | endPacket KEYWORD2 49 | parsePacket KEYWORD2 50 | remoteIP KEYWORD2 51 | remotePort KEYWORD2 52 | onEvent KEYWORD2 53 | sendText KEYWORD2 54 | sendBinary KEYWORD2 55 | pushWsEvent KEYWORD2 56 | setCACert KEYWORD2 57 | startTLS KEYWORD2 58 | isSSL KEYWORD2 59 | hostPrint KEYWORD2 60 | setFlag KEYWORD2 61 | getFlag KEYWORD2 62 | setInsecure KEYWORD2 63 | setPlainStart KEYWORD2 64 | isSecure KEYWORD2 65 | setBufferSizes KEYWORD2 66 | 67 | # AsyncTCP Specific 68 | ack KEYWORD2 69 | ackPacket KEYWORD2 70 | add KEYWORD2 71 | send KEYWORD2 72 | getMss KEYWORD2 73 | getRxTimeout KEYWORD2 74 | setRxTimeout KEYWORD2 75 | getAckTimeout KEYWORD2 76 | setAckTimeout KEYWORD2 77 | getNoDelay KEYWORD2 78 | setNoDelay KEYWORD2 79 | setKeepAlive KEYWORD2 80 | getRemoteAddress KEYWORD2 81 | getRemotePort KEYWORD2 82 | getLocalAddress KEYWORD2 83 | getLocalPort KEYWORD2 84 | onConnect KEYWORD2 85 | onDisconnect KEYWORD2 86 | onAck KEYWORD2 87 | onError KEYWORD2 88 | onData KEYWORD2 89 | onPacket KEYWORD2 90 | onTimeout KEYWORD2 91 | onPoll KEYWORD2 92 | errorToString KEYWORD2 93 | stateToString KEYWORD2 94 | 95 | ####################################### 96 | # Constants (LITERAL1) 97 | ####################################### 98 | 99 | WSMessageType LITERAL1 100 | WS_EVENT_CONNECTED LITERAL1 101 | WS_EVENT_DISCONNECTED LITERAL1 102 | WS_FRAME_TEXT LITERAL1 103 | WS_FRAME_BINARY LITERAL1 104 | WS_FRAME_PONG LITERAL1 105 | WS_EVENT_ERROR LITERAL1 -------------------------------------------------------------------------------- /src/include/HostReboot.h: -------------------------------------------------------------------------------- 1 | #ifndef __HOST_REBOOT_H__ 2 | #define __HOST_REBOOT_H__ 3 | 4 | #include 5 | 6 | namespace HostUtil 7 | { 8 | 9 | #if defined(ARDUINO_ARCH_AVR) 10 | #include 11 | inline void reboot() 12 | { 13 | wdt_enable(WDTO_15MS); 14 | while (true) 15 | { 16 | } 17 | } 18 | 19 | #elif defined(ESP32) 20 | #include 21 | inline void reboot() { esp_restart(); } 22 | #elif defined(ESP8266) 23 | #include 24 | inline void reboot() { ESP.restart(); } 25 | 26 | #elif defined(TEENSYDUINO) 27 | inline void reboot() { SCB_AIRCR = 0x05FA0004; } 28 | 29 | #elif defined(ARDUINO_ARCH_SAMD) 30 | inline void reboot() { NVIC_SystemReset(); } 31 | 32 | #elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F4) 33 | 34 | #if defined(ARDUINO_ARCH_STM32) 35 | // Official STM32 Core (STM32duino) 36 | inline void reboot() { NVIC_SystemReset(); } 37 | #elif defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F4) 38 | // Legacy Maple Core (Roger Clark) 39 | inline void reboot() { nvic_sys_reset(); } 40 | #endif 41 | 42 | #elif defined(ARDUINO_ARCH_RP2040) 43 | // Differentiate between Official Mbed Core and Earle Philhower Core 44 | #if defined(ARDUINO_ARCH_MBED) 45 | inline void reboot() { NVIC_SystemReset(); } 46 | #elif defined(ARDUINO_RASPBERRY_PI_PICO_W) 47 | // Earle Philhower Core 48 | inline void reboot() { rp2040.reboot(); } 49 | #else 50 | 51 | inline void reboot() 52 | { 53 | watchdog_enable(1000, 1); 54 | while (true) 55 | { 56 | } 57 | } 58 | 59 | #endif 60 | 61 | #elif defined(ARDUINO_ARCH_NRF52) 62 | #include "Arduino.h" 63 | inline void reboot() { NVIC_SystemReset(); } 64 | 65 | #elif defined(__RENESAS_RA__) 66 | #include "cmsis_gcc.h" 67 | inline void reboot() { NVIC_SystemReset(); } 68 | 69 | #elif defined(__RENESAS_RX__) 70 | #include "iodefine.h" 71 | inline void reboot() 72 | { 73 | SYSTEM.PRCR.WORD = 0xA50B; 74 | SYSTEM.SWRSTCR.BIT.SWRST = 1; 75 | while (true) 76 | { 77 | } 78 | } 79 | 80 | #elif defined(__RENESAS_RL78__) 81 | #include 82 | inline void reboot() 83 | { 84 | WDTE = 0x00; // Trigger Watchdog 85 | while (true) 86 | { 87 | } 88 | } 89 | 90 | // Fallback for generic ARM Cortex-M devices not explicitly caught above 91 | #elif defined(__arm__) 92 | #if defined(ARDUINO_ARCH_MBED) 93 | #include "mbed.h" 94 | inline void reboot() { NVIC_SystemReset(); } 95 | #else 96 | // Try standard CMSIS reset 97 | extern "C" void NVIC_SystemReset(); 98 | inline void reboot() 99 | { 100 | NVIC_SystemReset(); 101 | } 102 | #endif 103 | 104 | #else 105 | // Final Fallback: Hang (Safe Fail) 106 | inline void reboot() 107 | { 108 | while (true) 109 | { 110 | } 111 | } 112 | 113 | #endif 114 | } 115 | #endif -------------------------------------------------------------------------------- /src/SerialHostManager.h: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2025 Suwatchai K. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | #ifndef SERIAL_HOST_MANAGER_H 8 | #define SERIAL_HOST_MANAGER_H 9 | 10 | #include "SerialTCPClient.h" 11 | 12 | class SerialHostManager 13 | { 14 | friend class SerialTCPClient; 15 | 16 | public: 17 | SerialHostManager(Stream &sink) 18 | : sink(&sink) { _serial_tcp_client.setSerial(sink); } 19 | 20 | /** 21 | * @brief Sets the WiFi credentials on the host. 22 | */ 23 | bool setWiFi(const char *ssid, const char *password) 24 | { 25 | return _serial_tcp_client.setWiFiImpl(ssid, password); 26 | } 27 | 28 | /** 29 | * @brief Commands the host to connect to the configured WiFi. 30 | */ 31 | bool connectNetwork() 32 | { 33 | return _serial_tcp_client.sendCommand(CMD_C_CONNECT_NET, GLOBAL_SLOT_ID, nullptr, 0, true, SERIAL_TCP_CONNECT_TIMEOUT); 34 | } 35 | 36 | /** 37 | * @brief Commands the host to disconnect from WiFi. 38 | */ 39 | bool disconnectNetwork() 40 | { 41 | return _serial_tcp_client.sendCommand(CMD_C_DISCONNECT_NET, GLOBAL_SLOT_ID, nullptr, 0, true); 42 | } 43 | 44 | /** 45 | * @brief Checks if the host is connected to WiFi. 46 | */ 47 | bool isNetworkConnected() 48 | { 49 | return _serial_tcp_client.sendCommand(CMD_C_IS_NET_CONNECTED, GLOBAL_SLOT_ID, nullptr, 0, true); 50 | } 51 | 52 | /** 53 | * @brief Pings the host to check if it's alive. 54 | */ 55 | bool pingHost(uint32_t timeout = 1000) 56 | { 57 | return _serial_tcp_client.sendCommand(CMD_C_PING_HOST, GLOBAL_SLOT_ID, nullptr, 0, true, timeout); 58 | } 59 | 60 | /** 61 | * @brief Commands the host to reboot. 62 | */ 63 | bool rebootHost() 64 | { 65 | return _serial_tcp_client.sendCommand(CMD_C_REBOOT_HOST, GLOBAL_SLOT_ID, nullptr, 0, true); 66 | } 67 | 68 | /** 69 | * @brief Sets the debug level on the *host*. 70 | */ 71 | bool setDebugLevel(int level) 72 | { 73 | return _serial_tcp_client.setDebugLevelImpl(level); 74 | } 75 | 76 | /** 77 | * @brief Sets the debug level only on the client. 78 | */ 79 | void setLocalDebugLevel(int level) 80 | { 81 | _serial_tcp_client.setLocalDebugLevelImpl(level); 82 | } 83 | 84 | /** 85 | * @brief Printing message to Host Stream (Serial). 86 | * @param info Information to print. 87 | */ 88 | void hostPrint(const char *info) 89 | { 90 | size_t len = strlen(info); 91 | size_t offset = 0; 92 | // Use small chunk size to avoid flooding serial buffer all at once 93 | const size_t CHUNK_SIZE = 64; 94 | 95 | while (offset < len) 96 | { 97 | size_t toSend = len - offset; 98 | if (toSend > CHUNK_SIZE) 99 | toSend = CHUNK_SIZE; 100 | 101 | // wait_for_ack = false: Fire and forget. 102 | // This prevents blocking the Arduino waiting for a response while it might be 103 | // receiving data on another slot, avoiding deadlock. 104 | _serial_tcp_client.sendCommand(CMD_C_DEBUG_INFO, GLOBAL_SLOT_ID, (const uint8_t *)(info + offset), toSend, false); 105 | offset += toSend; 106 | } 107 | } 108 | 109 | /** 110 | * @brief Printing message to Host Stream (Serial). 111 | * @param info Information to print. 112 | */ 113 | void hostPrint(String info) // Overload for String 114 | { 115 | hostPrint(info.c_str()); 116 | } 117 | 118 | private: 119 | Stream *sink = nullptr; 120 | SerialTCPClient _serial_tcp_client; 121 | }; 122 | #endif -------------------------------------------------------------------------------- /src/include/HostNVS.h: -------------------------------------------------------------------------------- 1 | #ifndef __HOST_NVS_H__ 2 | #define __HOST_NVS_H__ 3 | 4 | #include 5 | 6 | #if defined(ESP32) 7 | #include 8 | #define USE_PREFERENCES 9 | #else 10 | #include 11 | #define USE_EEPROM 12 | // Opta and ESP8266 require EEPROM size definition or begin() 13 | #define EEPROM_SIZE 512 14 | #define EEPROM_ADDR 0 // Start address 15 | #endif 16 | 17 | static String _ssid; 18 | static String _password; 19 | 20 | #if defined(USE_PREFERENCES) 21 | static Preferences prefs; 22 | #elif defined(USE_EEPROM) 23 | // Structure required for EEPROM because we cannot save String objects directly 24 | struct WiFiCreds 25 | { 26 | uint8_t magic; // Simple check to verify data validity (0xA5) 27 | char ssid[33]; // Max SSID length is 32 + null terminator 28 | char pass[65]; // Max WPA2 pass length is 64 + null terminator 29 | }; 30 | #endif 31 | 32 | static void saveWiFi(const char *ssid, const char *password) 33 | { 34 | _ssid = ssid; 35 | _password = password; 36 | 37 | #if defined(USE_PREFERENCES) 38 | if (prefs.begin("serialtcp", false)) 39 | { 40 | prefs.putString("ssid", ssid); 41 | prefs.putString("pass", password); 42 | prefs.end(); 43 | Serial.println("[Host] Credentials saved to Preferences."); 44 | } 45 | else 46 | { 47 | Serial.println("[Host] Failed to open Preferences."); 48 | } 49 | 50 | #elif defined(USE_EEPROM) 51 | #if defined(ESP8266) || defined(ARDUINO_OPTA) 52 | EEPROM.begin(EEPROM_SIZE); 53 | #endif 54 | 55 | WiFiCreds creds; 56 | creds.magic = 0xA5; // distinct pattern to indicate valid data 57 | 58 | // Safely copy strings to fixed char arrays 59 | strncpy(creds.ssid, ssid, sizeof(creds.ssid) - 1); 60 | creds.ssid[sizeof(creds.ssid) - 1] = '\0'; // Ensure null termination 61 | 62 | strncpy(creds.pass, password, sizeof(creds.pass) - 1); 63 | creds.pass[sizeof(creds.pass) - 1] = '\0'; 64 | 65 | EEPROM.put(EEPROM_ADDR, creds); 66 | 67 | #if defined(ESP8266) || defined(ARDUINO_OPTA) 68 | // Commit is required for flash-based EEPROM emulation 69 | if (EEPROM.commit()) 70 | { 71 | Serial.println("[Host] Credentials committed to Flash/EEPROM."); 72 | } 73 | else 74 | { 75 | Serial.println("[Host] EEPROM Commit failed."); 76 | } 77 | #else 78 | // AVR writes instantly 79 | Serial.println("[Host] Credentials saved to EEPROM."); 80 | #endif 81 | #endif 82 | } 83 | 84 | static void loadWiFi(const char *default_ssid, const char *default_password) 85 | { 86 | _ssid = default_ssid; 87 | _password = default_password; 88 | 89 | #if defined(USE_PREFERENCES) 90 | if (prefs.begin("serialtcp", true)) 91 | { 92 | if (prefs.isKey("ssid")) 93 | { 94 | _ssid = prefs.getString("ssid"); 95 | _password = prefs.getString("pass"); 96 | Serial.println("[Host] Loaded from Preferences."); 97 | } 98 | else 99 | { 100 | Serial.println("[Host] No saved keys. Using defaults."); 101 | } 102 | prefs.end(); 103 | } 104 | 105 | #elif defined(USE_EEPROM) 106 | #if defined(ESP8266) || defined(ARDUINO_OPTA) 107 | EEPROM.begin(EEPROM_SIZE); 108 | #endif 109 | 110 | WiFiCreds creds; 111 | EEPROM.get(EEPROM_ADDR, creds); 112 | 113 | // Check magic byte to see if this is valid data or empty flash (0xFF) 114 | if (creds.magic == 0xA5) 115 | { 116 | _ssid = String(creds.ssid); 117 | _password = String(creds.pass); 118 | Serial.println("[Host] Loaded from EEPROM."); 119 | } 120 | else 121 | { 122 | Serial.println("[Host] EEPROM empty or invalid. Using defaults."); 123 | } 124 | #endif 125 | } 126 | 127 | #endif -------------------------------------------------------------------------------- /assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Serial ↔ TCP / UDP / WS 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | UNO 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | ESP32 59 | 60 | 61 | 62 | 63 | 64 | 76 | 77 | 78 | 79 | 80 | 81 | SerialNetworkBridge 82 | 83 | 84 | -------------------------------------------------------------------------------- /examples/Readme.md: -------------------------------------------------------------------------------- 1 | # SerialNetworkBridge Examples 2 | 3 | This folder contains example sketches demonstrating how to use the `SerialNetworkBridge` library. The examples are categorized by their connection architecture: **Device Host** and **PC Host**. 4 | 5 | 6 | ## 🚀 Getting Started with PC Host Mode (USB) 7 | 8 | PC Host mode allows your Arduino to access the internet directly through your computer's USB connection using a Python script. This eliminates the need for a separate Arduino device bridge. 9 | 10 | ### 1. Prerequisites 11 | * **Python 3.7+** installed on your computer. 12 | * **Pip** installed. 13 | 14 | ### 2. Installation 15 | Navigate to `examples/PC_Host/` and run the installer script to download required Python libraries (`pyserial`, `cobs`, `websocket-client`, `colorama`, `pywifi`, `flask`, and `comtypes`). 16 | 17 | * **Windows:** Double-click `install_libs.bat`. 18 | * **Linux/macOS:** Run `./install_libs.sh` in a terminal. 19 | 20 | ### 3. Configure the Bridge 21 | Open `examples/PC_Host/serial_bridge.py` in a text editor and update the configuration at the top: 22 | 23 | ```python 24 | SERIAL_PORT = 'COM3' # <-- Update to your Arduino's Port (e.g., COM3 or /dev/ttyUSB0) 25 | BAUD_RATE = 115200 # Must match your Arduino sketch 26 | ``` 27 | 28 | ### 4. Run an Example 29 | 1. **Upload** one of the PC Host sketches (e.g., `examples/Device_Host/Generic_Client/HTTP_GET/HTTP_GET.ino`) to your Arduino. 30 | * *Note:* Ensure `#define ENABLE_LOCAL_DEBUG` is commented out and `HOST_RELAY_DEBUG` is defined in the sketch! 31 | 2. **Close** the Arduino Serial Monitor. 32 | 3. **Run the Bridge:** 33 | * **Windows:** Double-click `run.bat`. 34 | * **Linux/macOS:** Run `./run.sh`. 35 | 36 | --- 37 | 38 | ## 📚 Example Descriptions 39 | 40 | ### 1. Device Host (using other Arduino WiFi/Ethernet capable devices as a bridge host device) 41 | Standard setup using an Arduino Client (e.g., Mega) connected via Serial to an ESP32 Host. 42 | * **HTTP_GET:** Simple data retrieval. 43 | * **HTTP_POST:** Sending JSON data to a server. 44 | * **WebSocket:** Connects to a public echo server (`echo.websocket.org`) with SSL verification disabled for compatibility. 45 | * **MQTT:** Connecting to a broker and publishing messages. 46 | * **HTTP_Streaming:** Reading chunked data (SSE) from a local sse server running on the same PC (`localhost:5000`) using python script (`Server/sse_server.py`). 47 | * **UDP_NTP:** Fetches time from `pool.ntp.org` using UDP packets. 48 | * **Host_Management:** **[Advanced]** Allows the Arduino to reboot the PC script or change the PC's Wi-Fi network. 49 | * **Secure_Connection:** Demonstrates loading a custom Root CA (`cert/Amazon_Root_CA1.pem`) to verify a secure connection. 50 | * **STARTTLS:** Upgrades a plain text email connection to SSL. 51 | 52 | ### 2. PC Host (Direct USB) 53 | Equivalent examples adapted for the Python Bridge. 54 | * **HTTP_GET:** Simple data retrieval. 55 | * **HTTP_POST:** Sending JSON data to a server. 56 | * **WebSocket:** Connects to a public echo server (`echo.websocket.org`) with SSL verification disabled for compatibility. 57 | * **MQTT:** Connecting to a broker and publishing messages. 58 | * **HTTP_Streaming:** Reading chunked data (SSE) from a local sse server running on the same PC (`localhost:5000`) using python script (`Server/sse_server.py`). 59 | * **UDP_NTP:** Fetches time from `pool.ntp.org` using UDP packets. 60 | * **Host_Management:** **[Advanced]** Allows the Arduino to reboot the PC script or change the PC's Wi-Fi network. 61 | * **Secure_Connection:** Demonstrates loading a custom Root CA (`cert/Amazon_Root_CA1.pem`) to verify a secure connection. 62 | * **STARTTLS:** Upgrades a plain text email connection to SSL. 63 | 64 | --- 65 | 66 | ## ⚠️ Critical Notes for PC Host 67 | 1. **Using Relay Debug:** You cannot use `Serial.print()` for debugging in your Arduino sketch because the USB port is used for the network protocol. Use the predefined helper functions (`debug::prnt`, `debug::printRaw`, `debug::printNewLinr`) with `HOST_RELAY_DEBUG` to relay the debug message to PC terminal. 68 | 2. **Bootloader Noise:** All PC Host sketches include `Serial.write(0x00); delay(500);` in `setup()` to clear garbage data caused by the Arduino rebooting. Do not remove this line. 69 | 3. **Admin Privileges:** The `Host_Management` example (controlling Wi-Fi/Reboot) requires running the Python script as Administrator (Windows) or with `sudo` (Linux/macOS). -------------------------------------------------------------------------------- /examples/PC_Host/MQTT/debug.h: -------------------------------------------------------------------------------- 1 | #include "HardwareSerial.h" 2 | #ifndef __DEBUG_H__ 3 | #define __DEBUG_H__ 4 | #include 5 | #include 6 | 7 | // #define BLINK_LED_PIN -1 // GPIO pin used here should not be used by serial port for bridge 8 | #define PULLED_UP_LED 0 // 1 = pull-up, 0 = pull-down 9 | 10 | struct debug 11 | { 12 | static void initBlink() 13 | { 14 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 15 | pinMode(BLINK_LED_PIN, OUTPUT); 16 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 17 | #endif 18 | } 19 | 20 | static void blink(int times, int delayMs) 21 | { 22 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 23 | for (int i = 0; i < times; i++) 24 | { 25 | digitalWrite(BLINK_LED_PIN, !PULLED_UP_LED); 26 | delay(delayMs); 27 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 28 | delay(delayMs); 29 | } 30 | #endif 31 | } 32 | /** 33 | * Print debug information with tag and spaced ident options to the sink object 34 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * @param msg The message to print. 36 | * @param tag Option to prepend with tag i.e. [Client]. 37 | * @param tag Option to prepend with space. 38 | */ 39 | template 40 | static void print(T &sink, const char *msg = "", bool tag = true, bool indent = true) 41 | { 42 | #if defined(HOST_RELAY_DEBUG) 43 | if (indent) 44 | sink.hostPrint(" "); 45 | if (tag) 46 | sink.hostPrint("[Client] "); 47 | sink.hostPrint(msg); 48 | #else 49 | if (tag) 50 | sink.print("[Client] "); 51 | sink.print(msg); 52 | #endif 53 | } 54 | 55 | /** 56 | * Print new line to the sink object 57 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 58 | */ 59 | template 60 | static void printNewLine(T &sink) 61 | { 62 | print(sink, "\r\n", false, false); 63 | } 64 | 65 | /** 66 | * Print debug information to the sink object 67 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 68 | * @param msg The message to print. 69 | */ 70 | template 71 | static void printRaw(T &sink, const char *msg) 72 | { 73 | print(sink, msg, false, false); 74 | } 75 | 76 | /** 77 | * Read data stream from sink object to beffer 78 | * Data will read from stream until the endToken was found or the buffer is full. 79 | * @param source The object to read data e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 80 | * @param buffer The buffer to store the data. 81 | * @param bufferLen The size of buffer. 82 | * @param totalRead The total data that has been read. 83 | * @param endToken The token to terminate the reading. 84 | */ 85 | template 86 | static int readResonse(TSRC &source, TSNK &sink, char *buffer, size_t bufferLen, int &totalRead, const char endToken) 87 | { 88 | size_t pos = 0; 89 | int c; 90 | 91 | unsigned long ms_start = millis(); 92 | unsigned long timeout = 5000; // 5 second timeout 93 | 94 | if (!source.connected() && source.available() == 0 && totalRead == 0) 95 | return -1; // socket closed 96 | 97 | while ((source.connected() || source.available()) && (millis() - ms_start < timeout)) 98 | { 99 | if (!source.available()) 100 | { 101 | delay(1); // avoid busy loop 102 | continue; 103 | } 104 | 105 | c = source.read(); 106 | if (c == -1) 107 | continue; 108 | 109 | buffer[pos++] = (char)c; 110 | totalRead++; 111 | 112 | if (c == endToken || (endToken == 0 && source.available() == 0) || pos >= bufferLen - 1) 113 | { 114 | buffer[pos] = '\0'; 115 | print(sink, buffer, false); // debug 116 | return (int)pos; 117 | } 118 | 119 | ms_start = millis(); // reset idle timeout only after valid read 120 | } 121 | 122 | return millis() - ms_start < timeout ? 0 /* no data available */ : -2 /* timeout */; 123 | } 124 | }; 125 | 126 | #endif -------------------------------------------------------------------------------- /examples/PC_Host/HTTP_GET/debug.h: -------------------------------------------------------------------------------- 1 | #include "HardwareSerial.h" 2 | #ifndef __DEBUG_H__ 3 | #define __DEBUG_H__ 4 | #include 5 | #include 6 | 7 | // #define BLINK_LED_PIN -1 // GPIO pin used here should not be used by serial port for bridge 8 | #define PULLED_UP_LED 0 // 1 = pull-up, 0 = pull-down 9 | 10 | struct debug 11 | { 12 | static void initBlink() 13 | { 14 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 15 | pinMode(BLINK_LED_PIN, OUTPUT); 16 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 17 | #endif 18 | } 19 | 20 | static void blink(int times, int delayMs) 21 | { 22 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 23 | for (int i = 0; i < times; i++) 24 | { 25 | digitalWrite(BLINK_LED_PIN, !PULLED_UP_LED); 26 | delay(delayMs); 27 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 28 | delay(delayMs); 29 | } 30 | #endif 31 | } 32 | /** 33 | * Print debug information with tag and spaced ident options to the sink object 34 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * @param msg The message to print. 36 | * @param tag Option to prepend with tag i.e. [Client]. 37 | * @param tag Option to prepend with space. 38 | */ 39 | template 40 | static void print(T &sink, const char *msg = "", bool tag = true, bool indent = true) 41 | { 42 | #if defined(HOST_RELAY_DEBUG) 43 | if (indent) 44 | sink.hostPrint(" "); 45 | if (tag) 46 | sink.hostPrint("[Client] "); 47 | sink.hostPrint(msg); 48 | #else 49 | if (tag) 50 | sink.print("[Client] "); 51 | sink.print(msg); 52 | #endif 53 | } 54 | 55 | /** 56 | * Print new line to the sink object 57 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 58 | */ 59 | template 60 | static void printNewLine(T &sink) 61 | { 62 | print(sink, "\r\n", false, false); 63 | } 64 | 65 | /** 66 | * Print debug information to the sink object 67 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 68 | * @param msg The message to print. 69 | */ 70 | template 71 | static void printRaw(T &sink, const char *msg) 72 | { 73 | print(sink, msg, false, false); 74 | } 75 | 76 | /** 77 | * Read data stream from sink object to beffer 78 | * Data will read from stream until the endToken was found or the buffer is full. 79 | * @param source The object to read data e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 80 | * @param buffer The buffer to store the data. 81 | * @param bufferLen The size of buffer. 82 | * @param totalRead The total data that has been read. 83 | * @param endToken The token to terminate the reading. 84 | */ 85 | template 86 | static int readResonse(TSRC &source, TSNK &sink, char *buffer, size_t bufferLen, int &totalRead, const char endToken) 87 | { 88 | size_t pos = 0; 89 | int c; 90 | 91 | unsigned long ms_start = millis(); 92 | unsigned long timeout = 5000; // 5 second timeout 93 | 94 | if (!source.connected() && source.available() == 0 && totalRead == 0) 95 | return -1; // socket closed 96 | 97 | while ((source.connected() || source.available()) && (millis() - ms_start < timeout)) 98 | { 99 | if (!source.available()) 100 | { 101 | delay(1); // avoid busy loop 102 | continue; 103 | } 104 | 105 | c = source.read(); 106 | if (c == -1) 107 | continue; 108 | 109 | buffer[pos++] = (char)c; 110 | totalRead++; 111 | 112 | if (c == endToken || (endToken == 0 && source.available() == 0) || pos >= bufferLen - 1) 113 | { 114 | buffer[pos] = '\0'; 115 | print(sink, buffer, false); // debug 116 | return (int)pos; 117 | } 118 | 119 | ms_start = millis(); // reset idle timeout only after valid read 120 | } 121 | 122 | return millis() - ms_start < timeout ? 0 /* no data available */ : -2 /* timeout */; 123 | } 124 | }; 125 | 126 | #endif -------------------------------------------------------------------------------- /examples/PC_Host/HTTP_POST/debug.h: -------------------------------------------------------------------------------- 1 | #include "HardwareSerial.h" 2 | #ifndef __DEBUG_H__ 3 | #define __DEBUG_H__ 4 | #include 5 | #include 6 | 7 | // #define BLINK_LED_PIN -1 // GPIO pin used here should not be used by serial port for bridge 8 | #define PULLED_UP_LED 0 // 1 = pull-up, 0 = pull-down 9 | 10 | struct debug 11 | { 12 | static void initBlink() 13 | { 14 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 15 | pinMode(BLINK_LED_PIN, OUTPUT); 16 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 17 | #endif 18 | } 19 | 20 | static void blink(int times, int delayMs) 21 | { 22 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 23 | for (int i = 0; i < times; i++) 24 | { 25 | digitalWrite(BLINK_LED_PIN, !PULLED_UP_LED); 26 | delay(delayMs); 27 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 28 | delay(delayMs); 29 | } 30 | #endif 31 | } 32 | /** 33 | * Print debug information with tag and spaced ident options to the sink object 34 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * @param msg The message to print. 36 | * @param tag Option to prepend with tag i.e. [Client]. 37 | * @param tag Option to prepend with space. 38 | */ 39 | template 40 | static void print(T &sink, const char *msg = "", bool tag = true, bool indent = true) 41 | { 42 | #if defined(HOST_RELAY_DEBUG) 43 | if (indent) 44 | sink.hostPrint(" "); 45 | if (tag) 46 | sink.hostPrint("[Client] "); 47 | sink.hostPrint(msg); 48 | #else 49 | if (tag) 50 | sink.print("[Client] "); 51 | sink.print(msg); 52 | #endif 53 | } 54 | 55 | /** 56 | * Print new line to the sink object 57 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 58 | */ 59 | template 60 | static void printNewLine(T &sink) 61 | { 62 | print(sink, "\r\n", false, false); 63 | } 64 | 65 | /** 66 | * Print debug information to the sink object 67 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 68 | * @param msg The message to print. 69 | */ 70 | template 71 | static void printRaw(T &sink, const char *msg) 72 | { 73 | print(sink, msg, false, false); 74 | } 75 | 76 | /** 77 | * Read data stream from sink object to beffer 78 | * Data will read from stream until the endToken was found or the buffer is full. 79 | * @param source The object to read data e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 80 | * @param buffer The buffer to store the data. 81 | * @param bufferLen The size of buffer. 82 | * @param totalRead The total data that has been read. 83 | * @param endToken The token to terminate the reading. 84 | */ 85 | template 86 | static int readResonse(TSRC &source, TSNK &sink, char *buffer, size_t bufferLen, int &totalRead, const char endToken) 87 | { 88 | size_t pos = 0; 89 | int c; 90 | 91 | unsigned long ms_start = millis(); 92 | unsigned long timeout = 5000; // 5 second timeout 93 | 94 | if (!source.connected() && source.available() == 0 && totalRead == 0) 95 | return -1; // socket closed 96 | 97 | while ((source.connected() || source.available()) && (millis() - ms_start < timeout)) 98 | { 99 | if (!source.available()) 100 | { 101 | delay(1); // avoid busy loop 102 | continue; 103 | } 104 | 105 | c = source.read(); 106 | if (c == -1) 107 | continue; 108 | 109 | buffer[pos++] = (char)c; 110 | totalRead++; 111 | 112 | if (c == endToken || (endToken == 0 && source.available() == 0) || pos >= bufferLen - 1) 113 | { 114 | buffer[pos] = '\0'; 115 | print(sink, buffer, false); // debug 116 | return (int)pos; 117 | } 118 | 119 | ms_start = millis(); // reset idle timeout only after valid read 120 | } 121 | 122 | return millis() - ms_start < timeout ? 0 /* no data available */ : -2 /* timeout */; 123 | } 124 | }; 125 | 126 | #endif -------------------------------------------------------------------------------- /examples/PC_Host/STARTTLS/debug.h: -------------------------------------------------------------------------------- 1 | #include "HardwareSerial.h" 2 | #ifndef __DEBUG_H__ 3 | #define __DEBUG_H__ 4 | #include 5 | #include 6 | 7 | // #define BLINK_LED_PIN -1 // GPIO pin used here should not be used by serial port for bridge 8 | #define PULLED_UP_LED 0 // 1 = pull-up, 0 = pull-down 9 | 10 | struct debug 11 | { 12 | static void initBlink() 13 | { 14 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 15 | pinMode(BLINK_LED_PIN, OUTPUT); 16 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 17 | #endif 18 | } 19 | 20 | static void blink(int times, int delayMs) 21 | { 22 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 23 | for (int i = 0; i < times; i++) 24 | { 25 | digitalWrite(BLINK_LED_PIN, !PULLED_UP_LED); 26 | delay(delayMs); 27 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 28 | delay(delayMs); 29 | } 30 | #endif 31 | } 32 | /** 33 | * Print debug information with tag and spaced ident options to the sink object 34 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * @param msg The message to print. 36 | * @param tag Option to prepend with tag i.e. [Client]. 37 | * @param tag Option to prepend with space. 38 | */ 39 | template 40 | static void print(T &sink, const char *msg = "", bool tag = true, bool indent = true) 41 | { 42 | #if defined(HOST_RELAY_DEBUG) 43 | if (indent) 44 | sink.hostPrint(" "); 45 | if (tag) 46 | sink.hostPrint("[Client] "); 47 | sink.hostPrint(msg); 48 | #else 49 | if (tag) 50 | sink.print("[Client] "); 51 | sink.print(msg); 52 | #endif 53 | } 54 | 55 | /** 56 | * Print new line to the sink object 57 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 58 | */ 59 | template 60 | static void printNewLine(T &sink) 61 | { 62 | print(sink, "\r\n", false, false); 63 | } 64 | 65 | /** 66 | * Print debug information to the sink object 67 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 68 | * @param msg The message to print. 69 | */ 70 | template 71 | static void printRaw(T &sink, const char *msg) 72 | { 73 | print(sink, msg, false, false); 74 | } 75 | 76 | /** 77 | * Read data stream from sink object to beffer 78 | * Data will read from stream until the endToken was found or the buffer is full. 79 | * @param source The object to read data e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 80 | * @param buffer The buffer to store the data. 81 | * @param bufferLen The size of buffer. 82 | * @param totalRead The total data that has been read. 83 | * @param endToken The token to terminate the reading. 84 | */ 85 | template 86 | static int readResonse(TSRC &source, TSNK &sink, char *buffer, size_t bufferLen, int &totalRead, const char endToken) 87 | { 88 | size_t pos = 0; 89 | int c; 90 | 91 | unsigned long ms_start = millis(); 92 | unsigned long timeout = 5000; // 5 second timeout 93 | 94 | if (!source.connected() && source.available() == 0 && totalRead == 0) 95 | return -1; // socket closed 96 | 97 | while ((source.connected() || source.available()) && (millis() - ms_start < timeout)) 98 | { 99 | if (!source.available()) 100 | { 101 | delay(1); // avoid busy loop 102 | continue; 103 | } 104 | 105 | c = source.read(); 106 | if (c == -1) 107 | continue; 108 | 109 | buffer[pos++] = (char)c; 110 | totalRead++; 111 | 112 | if (c == endToken || (endToken == 0 && source.available() == 0) || pos >= bufferLen - 1) 113 | { 114 | buffer[pos] = '\0'; 115 | print(sink, buffer, false); // debug 116 | return (int)pos; 117 | } 118 | 119 | ms_start = millis(); // reset idle timeout only after valid read 120 | } 121 | 122 | return millis() - ms_start < timeout ? 0 /* no data available */ : -2 /* timeout */; 123 | } 124 | }; 125 | 126 | #endif -------------------------------------------------------------------------------- /examples/PC_Host/UDP_NTP/debug.h: -------------------------------------------------------------------------------- 1 | #include "HardwareSerial.h" 2 | #ifndef __DEBUG_H__ 3 | #define __DEBUG_H__ 4 | #include 5 | #include 6 | 7 | // #define BLINK_LED_PIN -1 // GPIO pin used here should not be used by serial port for bridge 8 | #define PULLED_UP_LED 0 // 1 = pull-up, 0 = pull-down 9 | 10 | struct debug 11 | { 12 | static void initBlink() 13 | { 14 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 15 | pinMode(BLINK_LED_PIN, OUTPUT); 16 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 17 | #endif 18 | } 19 | 20 | static void blink(int times, int delayMs) 21 | { 22 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 23 | for (int i = 0; i < times; i++) 24 | { 25 | digitalWrite(BLINK_LED_PIN, !PULLED_UP_LED); 26 | delay(delayMs); 27 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 28 | delay(delayMs); 29 | } 30 | #endif 31 | } 32 | /** 33 | * Print debug information with tag and spaced ident options to the sink object 34 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * @param msg The message to print. 36 | * @param tag Option to prepend with tag i.e. [Client]. 37 | * @param tag Option to prepend with space. 38 | */ 39 | template 40 | static void print(T &sink, const char *msg = "", bool tag = true, bool indent = true) 41 | { 42 | #if defined(HOST_RELAY_DEBUG) 43 | if (indent) 44 | sink.hostPrint(" "); 45 | if (tag) 46 | sink.hostPrint("[Client] "); 47 | sink.hostPrint(msg); 48 | #else 49 | if (tag) 50 | sink.print("[Client] "); 51 | sink.print(msg); 52 | #endif 53 | } 54 | 55 | /** 56 | * Print new line to the sink object 57 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 58 | */ 59 | template 60 | static void printNewLine(T &sink) 61 | { 62 | print(sink, "\r\n", false, false); 63 | } 64 | 65 | /** 66 | * Print debug information to the sink object 67 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 68 | * @param msg The message to print. 69 | */ 70 | template 71 | static void printRaw(T &sink, const char *msg) 72 | { 73 | print(sink, msg, false, false); 74 | } 75 | 76 | /** 77 | * Read data stream from sink object to beffer 78 | * Data will read from stream until the endToken was found or the buffer is full. 79 | * @param source The object to read data e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 80 | * @param buffer The buffer to store the data. 81 | * @param bufferLen The size of buffer. 82 | * @param totalRead The total data that has been read. 83 | * @param endToken The token to terminate the reading. 84 | */ 85 | template 86 | static int readResonse(TSRC &source, TSNK &sink, char *buffer, size_t bufferLen, int &totalRead, const char endToken) 87 | { 88 | size_t pos = 0; 89 | int c; 90 | 91 | unsigned long ms_start = millis(); 92 | unsigned long timeout = 5000; // 5 second timeout 93 | 94 | if (!source.connected() && source.available() == 0 && totalRead == 0) 95 | return -1; // socket closed 96 | 97 | while ((source.connected() || source.available()) && (millis() - ms_start < timeout)) 98 | { 99 | if (!source.available()) 100 | { 101 | delay(1); // avoid busy loop 102 | continue; 103 | } 104 | 105 | c = source.read(); 106 | if (c == -1) 107 | continue; 108 | 109 | buffer[pos++] = (char)c; 110 | totalRead++; 111 | 112 | if (c == endToken || (endToken == 0 && source.available() == 0) || pos >= bufferLen - 1) 113 | { 114 | buffer[pos] = '\0'; 115 | print(sink, buffer, false); // debug 116 | return (int)pos; 117 | } 118 | 119 | ms_start = millis(); // reset idle timeout only after valid read 120 | } 121 | 122 | return millis() - ms_start < timeout ? 0 /* no data available */ : -2 /* timeout */; 123 | } 124 | }; 125 | 126 | #endif -------------------------------------------------------------------------------- /examples/PC_Host/WebSocket/debug.h: -------------------------------------------------------------------------------- 1 | #include "HardwareSerial.h" 2 | #ifndef __DEBUG_H__ 3 | #define __DEBUG_H__ 4 | #include 5 | #include 6 | 7 | // #define BLINK_LED_PIN -1 // GPIO pin used here should not be used by serial port for bridge 8 | #define PULLED_UP_LED 0 // 1 = pull-up, 0 = pull-down 9 | 10 | struct debug 11 | { 12 | static void initBlink() 13 | { 14 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 15 | pinMode(BLINK_LED_PIN, OUTPUT); 16 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 17 | #endif 18 | } 19 | 20 | static void blink(int times, int delayMs) 21 | { 22 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 23 | for (int i = 0; i < times; i++) 24 | { 25 | digitalWrite(BLINK_LED_PIN, !PULLED_UP_LED); 26 | delay(delayMs); 27 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 28 | delay(delayMs); 29 | } 30 | #endif 31 | } 32 | /** 33 | * Print debug information with tag and spaced ident options to the sink object 34 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * @param msg The message to print. 36 | * @param tag Option to prepend with tag i.e. [Client]. 37 | * @param tag Option to prepend with space. 38 | */ 39 | template 40 | static void print(T &sink, const char *msg = "", bool tag = true, bool indent = true) 41 | { 42 | #if defined(HOST_RELAY_DEBUG) 43 | if (indent) 44 | sink.hostPrint(" "); 45 | if (tag) 46 | sink.hostPrint("[Client] "); 47 | sink.hostPrint(msg); 48 | #else 49 | if (tag) 50 | sink.print("[Client] "); 51 | sink.print(msg); 52 | #endif 53 | } 54 | 55 | /** 56 | * Print new line to the sink object 57 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 58 | */ 59 | template 60 | static void printNewLine(T &sink) 61 | { 62 | print(sink, "\r\n", false, false); 63 | } 64 | 65 | /** 66 | * Print debug information to the sink object 67 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 68 | * @param msg The message to print. 69 | */ 70 | template 71 | static void printRaw(T &sink, const char *msg) 72 | { 73 | print(sink, msg, false, false); 74 | } 75 | 76 | /** 77 | * Read data stream from sink object to beffer 78 | * Data will read from stream until the endToken was found or the buffer is full. 79 | * @param source The object to read data e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 80 | * @param buffer The buffer to store the data. 81 | * @param bufferLen The size of buffer. 82 | * @param totalRead The total data that has been read. 83 | * @param endToken The token to terminate the reading. 84 | */ 85 | template 86 | static int readResonse(TSRC &source, TSNK &sink, char *buffer, size_t bufferLen, int &totalRead, const char endToken) 87 | { 88 | size_t pos = 0; 89 | int c; 90 | 91 | unsigned long ms_start = millis(); 92 | unsigned long timeout = 5000; // 5 second timeout 93 | 94 | if (!source.connected() && source.available() == 0 && totalRead == 0) 95 | return -1; // socket closed 96 | 97 | while ((source.connected() || source.available()) && (millis() - ms_start < timeout)) 98 | { 99 | if (!source.available()) 100 | { 101 | delay(1); // avoid busy loop 102 | continue; 103 | } 104 | 105 | c = source.read(); 106 | if (c == -1) 107 | continue; 108 | 109 | buffer[pos++] = (char)c; 110 | totalRead++; 111 | 112 | if (c == endToken || (endToken == 0 && source.available() == 0) || pos >= bufferLen - 1) 113 | { 114 | buffer[pos] = '\0'; 115 | print(sink, buffer, false); // debug 116 | return (int)pos; 117 | } 118 | 119 | ms_start = millis(); // reset idle timeout only after valid read 120 | } 121 | 122 | return millis() - ms_start < timeout ? 0 /* no data available */ : -2 /* timeout */; 123 | } 124 | }; 125 | 126 | #endif -------------------------------------------------------------------------------- /examples/PC_Host/HTTP_Streaming/debug.h: -------------------------------------------------------------------------------- 1 | #include "HardwareSerial.h" 2 | #ifndef __DEBUG_H__ 3 | #define __DEBUG_H__ 4 | #include 5 | #include 6 | 7 | // #define BLINK_LED_PIN -1 // GPIO pin used here should not be used by serial port for bridge 8 | #define PULLED_UP_LED 0 // 1 = pull-up, 0 = pull-down 9 | 10 | struct debug 11 | { 12 | static void initBlink() 13 | { 14 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 15 | pinMode(BLINK_LED_PIN, OUTPUT); 16 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 17 | #endif 18 | } 19 | 20 | static void blink(int times, int delayMs) 21 | { 22 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 23 | for (int i = 0; i < times; i++) 24 | { 25 | digitalWrite(BLINK_LED_PIN, !PULLED_UP_LED); 26 | delay(delayMs); 27 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 28 | delay(delayMs); 29 | } 30 | #endif 31 | } 32 | /** 33 | * Print debug information with tag and spaced ident options to the sink object 34 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * @param msg The message to print. 36 | * @param tag Option to prepend with tag i.e. [Client]. 37 | * @param tag Option to prepend with space. 38 | */ 39 | template 40 | static void print(T &sink, const char *msg = "", bool tag = true, bool indent = true) 41 | { 42 | #if defined(HOST_RELAY_DEBUG) 43 | if (indent) 44 | sink.hostPrint(" "); 45 | if (tag) 46 | sink.hostPrint("[Client] "); 47 | sink.hostPrint(msg); 48 | #else 49 | if (tag) 50 | sink.print("[Client] "); 51 | sink.print(msg); 52 | #endif 53 | } 54 | 55 | /** 56 | * Print new line to the sink object 57 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 58 | */ 59 | template 60 | static void printNewLine(T &sink) 61 | { 62 | print(sink, "\r\n", false, false); 63 | } 64 | 65 | /** 66 | * Print debug information to the sink object 67 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 68 | * @param msg The message to print. 69 | */ 70 | template 71 | static void printRaw(T &sink, const char *msg) 72 | { 73 | print(sink, msg, false, false); 74 | } 75 | 76 | /** 77 | * Read data stream from sink object to beffer 78 | * Data will read from stream until the endToken was found or the buffer is full. 79 | * @param source The object to read data e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 80 | * @param buffer The buffer to store the data. 81 | * @param bufferLen The size of buffer. 82 | * @param totalRead The total data that has been read. 83 | * @param endToken The token to terminate the reading. 84 | */ 85 | template 86 | static int readResonse(TSRC &source, TSNK &sink, char *buffer, size_t bufferLen, int &totalRead, const char endToken) 87 | { 88 | size_t pos = 0; 89 | int c; 90 | 91 | unsigned long ms_start = millis(); 92 | unsigned long timeout = 5000; // 5 second timeout 93 | 94 | if (!source.connected() && source.available() == 0 && totalRead == 0) 95 | return -1; // socket closed 96 | 97 | while ((source.connected() || source.available()) && (millis() - ms_start < timeout)) 98 | { 99 | if (!source.available()) 100 | { 101 | delay(1); // avoid busy loop 102 | continue; 103 | } 104 | 105 | c = source.read(); 106 | if (c == -1) 107 | continue; 108 | 109 | buffer[pos++] = (char)c; 110 | totalRead++; 111 | 112 | if (c == endToken || (endToken == 0 && source.available() == 0) || pos >= bufferLen - 1) 113 | { 114 | buffer[pos] = '\0'; 115 | print(sink, buffer, false); // debug 116 | return (int)pos; 117 | } 118 | 119 | ms_start = millis(); // reset idle timeout only after valid read 120 | } 121 | 122 | return millis() - ms_start < timeout ? 0 /* no data available */ : -2 /* timeout */; 123 | } 124 | }; 125 | 126 | #endif -------------------------------------------------------------------------------- /examples/PC_Host/Host_Management/debug.h: -------------------------------------------------------------------------------- 1 | #include "HardwareSerial.h" 2 | #ifndef __DEBUG_H__ 3 | #define __DEBUG_H__ 4 | #include 5 | #include 6 | 7 | // #define BLINK_LED_PIN -1 // GPIO pin used here should not be used by serial port for bridge 8 | #define PULLED_UP_LED 0 // 1 = pull-up, 0 = pull-down 9 | 10 | struct debug 11 | { 12 | static void initBlink() 13 | { 14 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 15 | pinMode(BLINK_LED_PIN, OUTPUT); 16 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 17 | #endif 18 | } 19 | 20 | static void blink(int times, int delayMs) 21 | { 22 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 23 | for (int i = 0; i < times; i++) 24 | { 25 | digitalWrite(BLINK_LED_PIN, !PULLED_UP_LED); 26 | delay(delayMs); 27 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 28 | delay(delayMs); 29 | } 30 | #endif 31 | } 32 | /** 33 | * Print debug information with tag and spaced ident options to the sink object 34 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * @param msg The message to print. 36 | * @param tag Option to prepend with tag i.e. [Client]. 37 | * @param tag Option to prepend with space. 38 | */ 39 | template 40 | static void print(T &sink, const char *msg = "", bool tag = true, bool indent = true) 41 | { 42 | #if defined(HOST_RELAY_DEBUG) 43 | if (indent) 44 | sink.hostPrint(" "); 45 | if (tag) 46 | sink.hostPrint("[Client] "); 47 | sink.hostPrint(msg); 48 | #else 49 | if (tag) 50 | sink.print("[Client] "); 51 | sink.print(msg); 52 | #endif 53 | } 54 | 55 | /** 56 | * Print new line to the sink object 57 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 58 | */ 59 | template 60 | static void printNewLine(T &sink) 61 | { 62 | print(sink, "\r\n", false, false); 63 | } 64 | 65 | /** 66 | * Print debug information to the sink object 67 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 68 | * @param msg The message to print. 69 | */ 70 | template 71 | static void printRaw(T &sink, const char *msg) 72 | { 73 | print(sink, msg, false, false); 74 | } 75 | 76 | /** 77 | * Read data stream from sink object to beffer 78 | * Data will read from stream until the endToken was found or the buffer is full. 79 | * @param source The object to read data e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 80 | * @param buffer The buffer to store the data. 81 | * @param bufferLen The size of buffer. 82 | * @param totalRead The total data that has been read. 83 | * @param endToken The token to terminate the reading. 84 | */ 85 | template 86 | static int readResonse(TSRC &source, TSNK &sink, char *buffer, size_t bufferLen, int &totalRead, const char endToken) 87 | { 88 | size_t pos = 0; 89 | int c; 90 | 91 | unsigned long ms_start = millis(); 92 | unsigned long timeout = 5000; // 5 second timeout 93 | 94 | if (!source.connected() && source.available() == 0 && totalRead == 0) 95 | return -1; // socket closed 96 | 97 | while ((source.connected() || source.available()) && (millis() - ms_start < timeout)) 98 | { 99 | if (!source.available()) 100 | { 101 | delay(1); // avoid busy loop 102 | continue; 103 | } 104 | 105 | c = source.read(); 106 | if (c == -1) 107 | continue; 108 | 109 | buffer[pos++] = (char)c; 110 | totalRead++; 111 | 112 | if (c == endToken || (endToken == 0 && source.available() == 0) || pos >= bufferLen - 1) 113 | { 114 | buffer[pos] = '\0'; 115 | print(sink, buffer, false); // debug 116 | return (int)pos; 117 | } 118 | 119 | ms_start = millis(); // reset idle timeout only after valid read 120 | } 121 | 122 | return millis() - ms_start < timeout ? 0 /* no data available */ : -2 /* timeout */; 123 | } 124 | }; 125 | 126 | #endif -------------------------------------------------------------------------------- /examples/PC_Host/Secure_Connection/debug.h: -------------------------------------------------------------------------------- 1 | #include "HardwareSerial.h" 2 | #ifndef __DEBUG_H__ 3 | #define __DEBUG_H__ 4 | #include 5 | #include 6 | 7 | // #define BLINK_LED_PIN -1 // GPIO pin used here should not be used by serial port for bridge 8 | #define PULLED_UP_LED 0 // 1 = pull-up, 0 = pull-down 9 | 10 | struct debug 11 | { 12 | static void initBlink() 13 | { 14 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 15 | pinMode(BLINK_LED_PIN, OUTPUT); 16 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 17 | #endif 18 | } 19 | 20 | static void blink(int times, int delayMs) 21 | { 22 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 23 | for (int i = 0; i < times; i++) 24 | { 25 | digitalWrite(BLINK_LED_PIN, !PULLED_UP_LED); 26 | delay(delayMs); 27 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 28 | delay(delayMs); 29 | } 30 | #endif 31 | } 32 | /** 33 | * Print debug information with tag and spaced ident options to the sink object 34 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * @param msg The message to print. 36 | * @param tag Option to prepend with tag i.e. [Client]. 37 | * @param tag Option to prepend with space. 38 | */ 39 | template 40 | static void print(T &sink, const char *msg = "", bool tag = true, bool indent = true) 41 | { 42 | #if defined(HOST_RELAY_DEBUG) 43 | if (indent) 44 | sink.hostPrint(" "); 45 | if (tag) 46 | sink.hostPrint("[Client] "); 47 | sink.hostPrint(msg); 48 | #else 49 | if (tag) 50 | sink.print("[Client] "); 51 | sink.print(msg); 52 | #endif 53 | } 54 | 55 | /** 56 | * Print new line to the sink object 57 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 58 | */ 59 | template 60 | static void printNewLine(T &sink) 61 | { 62 | print(sink, "\r\n", false, false); 63 | } 64 | 65 | /** 66 | * Print debug information to the sink object 67 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 68 | * @param msg The message to print. 69 | */ 70 | template 71 | static void printRaw(T &sink, const char *msg) 72 | { 73 | print(sink, msg, false, false); 74 | } 75 | 76 | /** 77 | * Read data stream from sink object to beffer 78 | * Data will read from stream until the endToken was found or the buffer is full. 79 | * @param source The object to read data e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 80 | * @param buffer The buffer to store the data. 81 | * @param bufferLen The size of buffer. 82 | * @param totalRead The total data that has been read. 83 | * @param endToken The token to terminate the reading. 84 | */ 85 | template 86 | static int readResonse(TSRC &source, TSNK &sink, char *buffer, size_t bufferLen, int &totalRead, const char endToken) 87 | { 88 | size_t pos = 0; 89 | int c; 90 | 91 | unsigned long ms_start = millis(); 92 | unsigned long timeout = 5000; // 5 second timeout 93 | 94 | if (!source.connected() && source.available() == 0 && totalRead == 0) 95 | return -1; // socket closed 96 | 97 | while ((source.connected() || source.available()) && (millis() - ms_start < timeout)) 98 | { 99 | if (!source.available()) 100 | { 101 | delay(1); // avoid busy loop 102 | continue; 103 | } 104 | 105 | c = source.read(); 106 | if (c == -1) 107 | continue; 108 | 109 | buffer[pos++] = (char)c; 110 | totalRead++; 111 | 112 | if (c == endToken || (endToken == 0 && source.available() == 0) || pos >= bufferLen - 1) 113 | { 114 | buffer[pos] = '\0'; 115 | print(sink, buffer, false); // debug 116 | return (int)pos; 117 | } 118 | 119 | ms_start = millis(); // reset idle timeout only after valid read 120 | } 121 | 122 | return millis() - ms_start < timeout ? 0 /* no data available */ : -2 /* timeout */; 123 | } 124 | }; 125 | 126 | #endif -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/MQTT/debug.h: -------------------------------------------------------------------------------- 1 | #include "HardwareSerial.h" 2 | #ifndef __DEBUG_H__ 3 | #define __DEBUG_H__ 4 | #include 5 | #include 6 | 7 | // #define BLINK_LED_PIN -1 // GPIO pin used here should not be used by serial port for bridge 8 | #define PULLED_UP_LED 0 // 1 = pull-up, 0 = pull-down 9 | 10 | struct debug 11 | { 12 | static void initBlink() 13 | { 14 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 15 | pinMode(BLINK_LED_PIN, OUTPUT); 16 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 17 | #endif 18 | } 19 | 20 | static void blink(int times, int delayMs) 21 | { 22 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 23 | for (int i = 0; i < times; i++) 24 | { 25 | digitalWrite(BLINK_LED_PIN, !PULLED_UP_LED); 26 | delay(delayMs); 27 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 28 | delay(delayMs); 29 | } 30 | #endif 31 | } 32 | /** 33 | * Print debug information with tag and spaced ident options to the sink object 34 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * @param msg The message to print. 36 | * @param tag Option to prepend with tag i.e. [Client]. 37 | * @param tag Option to prepend with space. 38 | */ 39 | template 40 | static void print(T &sink, const char *msg = "", bool tag = true, bool indent = true) 41 | { 42 | #if defined(HOST_RELAY_DEBUG) 43 | if (indent) 44 | sink.hostPrint(" "); 45 | if (tag) 46 | sink.hostPrint("[Client] "); 47 | sink.hostPrint(msg); 48 | #else 49 | if (tag) 50 | sink.print("[Client] "); 51 | sink.print(msg); 52 | #endif 53 | } 54 | 55 | /** 56 | * Print new line to the sink object 57 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 58 | */ 59 | template 60 | static void printNewLine(T &sink) 61 | { 62 | print(sink, "\r\n", false, false); 63 | } 64 | 65 | /** 66 | * Print debug information to the sink object 67 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 68 | * @param msg The message to print. 69 | */ 70 | template 71 | static void printRaw(T &sink, const char *msg) 72 | { 73 | print(sink, msg, false, false); 74 | } 75 | 76 | /** 77 | * Read data stream from sink object to beffer 78 | * Data will read from stream until the endToken was found or the buffer is full. 79 | * @param source The object to read data e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 80 | * @param buffer The buffer to store the data. 81 | * @param bufferLen The size of buffer. 82 | * @param totalRead The total data that has been read. 83 | * @param endToken The token to terminate the reading. 84 | */ 85 | template 86 | static int readResonse(TSRC &source, TSNK &sink, char *buffer, size_t bufferLen, int &totalRead, const char endToken) 87 | { 88 | size_t pos = 0; 89 | int c; 90 | 91 | unsigned long ms_start = millis(); 92 | unsigned long timeout = 5000; // 5 second timeout 93 | 94 | if (!source.connected() && source.available() == 0 && totalRead == 0) 95 | return -1; // socket closed 96 | 97 | while ((source.connected() || source.available()) && (millis() - ms_start < timeout)) 98 | { 99 | if (!source.available()) 100 | { 101 | delay(1); // avoid busy loop 102 | continue; 103 | } 104 | 105 | c = source.read(); 106 | if (c == -1) 107 | continue; 108 | 109 | buffer[pos++] = (char)c; 110 | totalRead++; 111 | 112 | if (c == endToken || (endToken == 0 && source.available() == 0) || pos >= bufferLen - 1) 113 | { 114 | buffer[pos] = '\0'; 115 | print(sink, buffer, false); // debug 116 | return (int)pos; 117 | } 118 | 119 | ms_start = millis(); // reset idle timeout only after valid read 120 | } 121 | 122 | return millis() - ms_start < timeout ? 0 /* no data available */ : -2 /* timeout */; 123 | } 124 | }; 125 | 126 | #endif -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/UDP_NTP/debug.h: -------------------------------------------------------------------------------- 1 | #include "HardwareSerial.h" 2 | #ifndef __DEBUG_H__ 3 | #define __DEBUG_H__ 4 | #include 5 | #include 6 | 7 | // #define BLINK_LED_PIN -1 // GPIO pin used here should not be used by serial port for bridge 8 | #define PULLED_UP_LED 0 // 1 = pull-up, 0 = pull-down 9 | 10 | struct debug 11 | { 12 | static void initBlink() 13 | { 14 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 15 | pinMode(BLINK_LED_PIN, OUTPUT); 16 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 17 | #endif 18 | } 19 | 20 | static void blink(int times, int delayMs) 21 | { 22 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 23 | for (int i = 0; i < times; i++) 24 | { 25 | digitalWrite(BLINK_LED_PIN, !PULLED_UP_LED); 26 | delay(delayMs); 27 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 28 | delay(delayMs); 29 | } 30 | #endif 31 | } 32 | /** 33 | * Print debug information with tag and spaced ident options to the sink object 34 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * @param msg The message to print. 36 | * @param tag Option to prepend with tag i.e. [Client]. 37 | * @param tag Option to prepend with space. 38 | */ 39 | template 40 | static void print(T &sink, const char *msg = "", bool tag = true, bool indent = true) 41 | { 42 | #if defined(HOST_RELAY_DEBUG) 43 | if (indent) 44 | sink.hostPrint(" "); 45 | if (tag) 46 | sink.hostPrint("[Client] "); 47 | sink.hostPrint(msg); 48 | #else 49 | if (tag) 50 | sink.print("[Client] "); 51 | sink.print(msg); 52 | #endif 53 | } 54 | 55 | /** 56 | * Print new line to the sink object 57 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 58 | */ 59 | template 60 | static void printNewLine(T &sink) 61 | { 62 | print(sink, "\r\n", false, false); 63 | } 64 | 65 | /** 66 | * Print debug information to the sink object 67 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 68 | * @param msg The message to print. 69 | */ 70 | template 71 | static void printRaw(T &sink, const char *msg) 72 | { 73 | print(sink, msg, false, false); 74 | } 75 | 76 | /** 77 | * Read data stream from sink object to beffer 78 | * Data will read from stream until the endToken was found or the buffer is full. 79 | * @param source The object to read data e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 80 | * @param buffer The buffer to store the data. 81 | * @param bufferLen The size of buffer. 82 | * @param totalRead The total data that has been read. 83 | * @param endToken The token to terminate the reading. 84 | */ 85 | template 86 | static int readResonse(TSRC &source, TSNK &sink, char *buffer, size_t bufferLen, int &totalRead, const char endToken) 87 | { 88 | size_t pos = 0; 89 | int c; 90 | 91 | unsigned long ms_start = millis(); 92 | unsigned long timeout = 5000; // 5 second timeout 93 | 94 | if (!source.connected() && source.available() == 0 && totalRead == 0) 95 | return -1; // socket closed 96 | 97 | while ((source.connected() || source.available()) && (millis() - ms_start < timeout)) 98 | { 99 | if (!source.available()) 100 | { 101 | delay(1); // avoid busy loop 102 | continue; 103 | } 104 | 105 | c = source.read(); 106 | if (c == -1) 107 | continue; 108 | 109 | buffer[pos++] = (char)c; 110 | totalRead++; 111 | 112 | if (c == endToken || (endToken == 0 && source.available() == 0) || pos >= bufferLen - 1) 113 | { 114 | buffer[pos] = '\0'; 115 | print(sink, buffer, false); // debug 116 | return (int)pos; 117 | } 118 | 119 | ms_start = millis(); // reset idle timeout only after valid read 120 | } 121 | 122 | return millis() - ms_start < timeout ? 0 /* no data available */ : -2 /* timeout */; 123 | } 124 | }; 125 | 126 | #endif -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/HTTP_GET/debug.h: -------------------------------------------------------------------------------- 1 | #include "HardwareSerial.h" 2 | #ifndef __DEBUG_H__ 3 | #define __DEBUG_H__ 4 | #include 5 | #include 6 | 7 | // #define BLINK_LED_PIN -1 // GPIO pin used here should not be used by serial port for bridge 8 | #define PULLED_UP_LED 0 // 1 = pull-up, 0 = pull-down 9 | 10 | struct debug 11 | { 12 | static void initBlink() 13 | { 14 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 15 | pinMode(BLINK_LED_PIN, OUTPUT); 16 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 17 | #endif 18 | } 19 | 20 | static void blink(int times, int delayMs) 21 | { 22 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 23 | for (int i = 0; i < times; i++) 24 | { 25 | digitalWrite(BLINK_LED_PIN, !PULLED_UP_LED); 26 | delay(delayMs); 27 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 28 | delay(delayMs); 29 | } 30 | #endif 31 | } 32 | /** 33 | * Print debug information with tag and spaced ident options to the sink object 34 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * @param msg The message to print. 36 | * @param tag Option to prepend with tag i.e. [Client]. 37 | * @param tag Option to prepend with space. 38 | */ 39 | template 40 | static void print(T &sink, const char *msg = "", bool tag = true, bool indent = true) 41 | { 42 | #if defined(HOST_RELAY_DEBUG) 43 | if (indent) 44 | sink.hostPrint(" "); 45 | if (tag) 46 | sink.hostPrint("[Client] "); 47 | sink.hostPrint(msg); 48 | #else 49 | if (tag) 50 | sink.print("[Client] "); 51 | sink.print(msg); 52 | #endif 53 | } 54 | 55 | /** 56 | * Print new line to the sink object 57 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 58 | */ 59 | template 60 | static void printNewLine(T &sink) 61 | { 62 | print(sink, "\r\n", false, false); 63 | } 64 | 65 | /** 66 | * Print debug information to the sink object 67 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 68 | * @param msg The message to print. 69 | */ 70 | template 71 | static void printRaw(T &sink, const char *msg) 72 | { 73 | print(sink, msg, false, false); 74 | } 75 | 76 | /** 77 | * Read data stream from sink object to beffer 78 | * Data will read from stream until the endToken was found or the buffer is full. 79 | * @param source The object to read data e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 80 | * @param buffer The buffer to store the data. 81 | * @param bufferLen The size of buffer. 82 | * @param totalRead The total data that has been read. 83 | * @param endToken The token to terminate the reading. 84 | */ 85 | template 86 | static int readResonse(TSRC &source, TSNK &sink, char *buffer, size_t bufferLen, int &totalRead, const char endToken) 87 | { 88 | size_t pos = 0; 89 | int c; 90 | 91 | unsigned long ms_start = millis(); 92 | unsigned long timeout = 5000; // 5 second timeout 93 | 94 | if (!source.connected() && source.available() == 0 && totalRead == 0) 95 | return -1; // socket closed 96 | 97 | while ((source.connected() || source.available()) && (millis() - ms_start < timeout)) 98 | { 99 | if (!source.available()) 100 | { 101 | delay(1); // avoid busy loop 102 | continue; 103 | } 104 | 105 | c = source.read(); 106 | if (c == -1) 107 | continue; 108 | 109 | buffer[pos++] = (char)c; 110 | totalRead++; 111 | 112 | if (c == endToken || (endToken == 0 && source.available() == 0) || pos >= bufferLen - 1) 113 | { 114 | buffer[pos] = '\0'; 115 | print(sink, buffer, false); // debug 116 | return (int)pos; 117 | } 118 | 119 | ms_start = millis(); // reset idle timeout only after valid read 120 | } 121 | 122 | return millis() - ms_start < timeout ? 0 /* no data available */ : -2 /* timeout */; 123 | } 124 | }; 125 | 126 | #endif -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/HTTP_POST/debug.h: -------------------------------------------------------------------------------- 1 | #include "HardwareSerial.h" 2 | #ifndef __DEBUG_H__ 3 | #define __DEBUG_H__ 4 | #include 5 | #include 6 | 7 | // #define BLINK_LED_PIN -1 // GPIO pin used here should not be used by serial port for bridge 8 | #define PULLED_UP_LED 0 // 1 = pull-up, 0 = pull-down 9 | 10 | struct debug 11 | { 12 | static void initBlink() 13 | { 14 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 15 | pinMode(BLINK_LED_PIN, OUTPUT); 16 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 17 | #endif 18 | } 19 | 20 | static void blink(int times, int delayMs) 21 | { 22 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 23 | for (int i = 0; i < times; i++) 24 | { 25 | digitalWrite(BLINK_LED_PIN, !PULLED_UP_LED); 26 | delay(delayMs); 27 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 28 | delay(delayMs); 29 | } 30 | #endif 31 | } 32 | /** 33 | * Print debug information with tag and spaced ident options to the sink object 34 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * @param msg The message to print. 36 | * @param tag Option to prepend with tag i.e. [Client]. 37 | * @param tag Option to prepend with space. 38 | */ 39 | template 40 | static void print(T &sink, const char *msg = "", bool tag = true, bool indent = true) 41 | { 42 | #if defined(HOST_RELAY_DEBUG) 43 | if (indent) 44 | sink.hostPrint(" "); 45 | if (tag) 46 | sink.hostPrint("[Client] "); 47 | sink.hostPrint(msg); 48 | #else 49 | if (tag) 50 | sink.print("[Client] "); 51 | sink.print(msg); 52 | #endif 53 | } 54 | 55 | /** 56 | * Print new line to the sink object 57 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 58 | */ 59 | template 60 | static void printNewLine(T &sink) 61 | { 62 | print(sink, "\r\n", false, false); 63 | } 64 | 65 | /** 66 | * Print debug information to the sink object 67 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 68 | * @param msg The message to print. 69 | */ 70 | template 71 | static void printRaw(T &sink, const char *msg) 72 | { 73 | print(sink, msg, false, false); 74 | } 75 | 76 | /** 77 | * Read data stream from sink object to beffer 78 | * Data will read from stream until the endToken was found or the buffer is full. 79 | * @param source The object to read data e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 80 | * @param buffer The buffer to store the data. 81 | * @param bufferLen The size of buffer. 82 | * @param totalRead The total data that has been read. 83 | * @param endToken The token to terminate the reading. 84 | */ 85 | template 86 | static int readResonse(TSRC &source, TSNK &sink, char *buffer, size_t bufferLen, int &totalRead, const char endToken) 87 | { 88 | size_t pos = 0; 89 | int c; 90 | 91 | unsigned long ms_start = millis(); 92 | unsigned long timeout = 5000; // 5 second timeout 93 | 94 | if (!source.connected() && source.available() == 0 && totalRead == 0) 95 | return -1; // socket closed 96 | 97 | while ((source.connected() || source.available()) && (millis() - ms_start < timeout)) 98 | { 99 | if (!source.available()) 100 | { 101 | delay(1); // avoid busy loop 102 | continue; 103 | } 104 | 105 | c = source.read(); 106 | if (c == -1) 107 | continue; 108 | 109 | buffer[pos++] = (char)c; 110 | totalRead++; 111 | 112 | if (c == endToken || (endToken == 0 && source.available() == 0) || pos >= bufferLen - 1) 113 | { 114 | buffer[pos] = '\0'; 115 | print(sink, buffer, false); // debug 116 | return (int)pos; 117 | } 118 | 119 | ms_start = millis(); // reset idle timeout only after valid read 120 | } 121 | 122 | return millis() - ms_start < timeout ? 0 /* no data available */ : -2 /* timeout */; 123 | } 124 | }; 125 | 126 | #endif -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/NeoHWSerial/debug.h: -------------------------------------------------------------------------------- 1 | #include "HardwareSerial.h" 2 | #ifndef __DEBUG_H__ 3 | #define __DEBUG_H__ 4 | #include 5 | #include 6 | 7 | // #define BLINK_LED_PIN -1 // GPIO pin used here should not be used by serial port for bridge 8 | #define PULLED_UP_LED 0 // 1 = pull-up, 0 = pull-down 9 | 10 | struct debug 11 | { 12 | static void initBlink() 13 | { 14 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 15 | pinMode(BLINK_LED_PIN, OUTPUT); 16 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 17 | #endif 18 | } 19 | 20 | static void blink(int times, int delayMs) 21 | { 22 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 23 | for (int i = 0; i < times; i++) 24 | { 25 | digitalWrite(BLINK_LED_PIN, !PULLED_UP_LED); 26 | delay(delayMs); 27 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 28 | delay(delayMs); 29 | } 30 | #endif 31 | } 32 | /** 33 | * Print debug information with tag and spaced ident options to the sink object 34 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * @param msg The message to print. 36 | * @param tag Option to prepend with tag i.e. [Client]. 37 | * @param tag Option to prepend with space. 38 | */ 39 | template 40 | static void print(T &sink, const char *msg = "", bool tag = true, bool indent = true) 41 | { 42 | #if defined(HOST_RELAY_DEBUG) 43 | if (indent) 44 | sink.hostPrint(" "); 45 | if (tag) 46 | sink.hostPrint("[Client] "); 47 | sink.hostPrint(msg); 48 | #else 49 | if (tag) 50 | sink.print("[Client] "); 51 | sink.print(msg); 52 | #endif 53 | } 54 | 55 | /** 56 | * Print new line to the sink object 57 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 58 | */ 59 | template 60 | static void printNewLine(T &sink) 61 | { 62 | print(sink, "\r\n", false, false); 63 | } 64 | 65 | /** 66 | * Print debug information to the sink object 67 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 68 | * @param msg The message to print. 69 | */ 70 | template 71 | static void printRaw(T &sink, const char *msg) 72 | { 73 | print(sink, msg, false, false); 74 | } 75 | 76 | /** 77 | * Read data stream from sink object to beffer 78 | * Data will read from stream until the endToken was found or the buffer is full. 79 | * @param source The object to read data e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 80 | * @param buffer The buffer to store the data. 81 | * @param bufferLen The size of buffer. 82 | * @param totalRead The total data that has been read. 83 | * @param endToken The token to terminate the reading. 84 | */ 85 | template 86 | static int readResonse(TSRC &source, TSNK &sink, char *buffer, size_t bufferLen, int &totalRead, const char endToken) 87 | { 88 | size_t pos = 0; 89 | int c; 90 | 91 | unsigned long ms_start = millis(); 92 | unsigned long timeout = 5000; // 5 second timeout 93 | 94 | if (!source.connected() && source.available() == 0 && totalRead == 0) 95 | return -1; // socket closed 96 | 97 | while ((source.connected() || source.available()) && (millis() - ms_start < timeout)) 98 | { 99 | if (!source.available()) 100 | { 101 | delay(1); // avoid busy loop 102 | continue; 103 | } 104 | 105 | c = source.read(); 106 | if (c == -1) 107 | continue; 108 | 109 | buffer[pos++] = (char)c; 110 | totalRead++; 111 | 112 | if (c == endToken || (endToken == 0 && source.available() == 0) || pos >= bufferLen - 1) 113 | { 114 | buffer[pos] = '\0'; 115 | print(sink, buffer, false); // debug 116 | return (int)pos; 117 | } 118 | 119 | ms_start = millis(); // reset idle timeout only after valid read 120 | } 121 | 122 | return millis() - ms_start < timeout ? 0 /* no data available */ : -2 /* timeout */; 123 | } 124 | }; 125 | 126 | #endif -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/STARTTLS/debug.h: -------------------------------------------------------------------------------- 1 | #include "HardwareSerial.h" 2 | #ifndef __DEBUG_H__ 3 | #define __DEBUG_H__ 4 | #include 5 | #include 6 | 7 | // #define BLINK_LED_PIN -1 // GPIO pin used here should not be used by serial port for bridge 8 | #define PULLED_UP_LED 0 // 1 = pull-up, 0 = pull-down 9 | 10 | struct debug 11 | { 12 | static void initBlink() 13 | { 14 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 15 | pinMode(BLINK_LED_PIN, OUTPUT); 16 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 17 | #endif 18 | } 19 | 20 | static void blink(int times, int delayMs) 21 | { 22 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 23 | for (int i = 0; i < times; i++) 24 | { 25 | digitalWrite(BLINK_LED_PIN, !PULLED_UP_LED); 26 | delay(delayMs); 27 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 28 | delay(delayMs); 29 | } 30 | #endif 31 | } 32 | /** 33 | * Print debug information with tag and spaced ident options to the sink object 34 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * @param msg The message to print. 36 | * @param tag Option to prepend with tag i.e. [Client]. 37 | * @param tag Option to prepend with space. 38 | */ 39 | template 40 | static void print(T &sink, const char *msg = "", bool tag = true, bool indent = true) 41 | { 42 | #if defined(HOST_RELAY_DEBUG) 43 | if (indent) 44 | sink.hostPrint(" "); 45 | if (tag) 46 | sink.hostPrint("[Client] "); 47 | sink.hostPrint(msg); 48 | #else 49 | if (tag) 50 | sink.print("[Client] "); 51 | sink.print(msg); 52 | #endif 53 | } 54 | 55 | /** 56 | * Print new line to the sink object 57 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 58 | */ 59 | template 60 | static void printNewLine(T &sink) 61 | { 62 | print(sink, "\r\n", false, false); 63 | } 64 | 65 | /** 66 | * Print debug information to the sink object 67 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 68 | * @param msg The message to print. 69 | */ 70 | template 71 | static void printRaw(T &sink, const char *msg) 72 | { 73 | print(sink, msg, false, false); 74 | } 75 | 76 | /** 77 | * Read data stream from sink object to beffer 78 | * Data will read from stream until the endToken was found or the buffer is full. 79 | * @param source The object to read data e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 80 | * @param buffer The buffer to store the data. 81 | * @param bufferLen The size of buffer. 82 | * @param totalRead The total data that has been read. 83 | * @param endToken The token to terminate the reading. 84 | */ 85 | template 86 | static int readResonse(TSRC &source, TSNK &sink, char *buffer, size_t bufferLen, int &totalRead, const char endToken) 87 | { 88 | size_t pos = 0; 89 | int c; 90 | 91 | unsigned long ms_start = millis(); 92 | unsigned long timeout = 5000; // 5 second timeout 93 | 94 | if (!source.connected() && source.available() == 0 && totalRead == 0) 95 | return -1; // socket closed 96 | 97 | while ((source.connected() || source.available()) && (millis() - ms_start < timeout)) 98 | { 99 | if (!source.available()) 100 | { 101 | delay(1); // avoid busy loop 102 | continue; 103 | } 104 | 105 | c = source.read(); 106 | if (c == -1) 107 | continue; 108 | 109 | buffer[pos++] = (char)c; 110 | totalRead++; 111 | 112 | if (c == endToken || (endToken == 0 && source.available() == 0) || pos >= bufferLen - 1) 113 | { 114 | buffer[pos] = '\0'; 115 | print(sink, buffer, false); // debug 116 | return (int)pos; 117 | } 118 | 119 | ms_start = millis(); // reset idle timeout only after valid read 120 | } 121 | 122 | return millis() - ms_start < timeout ? 0 /* no data available */ : -2 /* timeout */; 123 | } 124 | }; 125 | 126 | #endif -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/WebSocket/debug.h: -------------------------------------------------------------------------------- 1 | #include "HardwareSerial.h" 2 | #ifndef __DEBUG_H__ 3 | #define __DEBUG_H__ 4 | #include 5 | #include 6 | 7 | // #define BLINK_LED_PIN -1 // GPIO pin used here should not be used by serial port for bridge 8 | #define PULLED_UP_LED 0 // 1 = pull-up, 0 = pull-down 9 | 10 | struct debug 11 | { 12 | static void initBlink() 13 | { 14 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 15 | pinMode(BLINK_LED_PIN, OUTPUT); 16 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 17 | #endif 18 | } 19 | 20 | static void blink(int times, int delayMs) 21 | { 22 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 23 | for (int i = 0; i < times; i++) 24 | { 25 | digitalWrite(BLINK_LED_PIN, !PULLED_UP_LED); 26 | delay(delayMs); 27 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 28 | delay(delayMs); 29 | } 30 | #endif 31 | } 32 | /** 33 | * Print debug information with tag and spaced ident options to the sink object 34 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * @param msg The message to print. 36 | * @param tag Option to prepend with tag i.e. [Client]. 37 | * @param tag Option to prepend with space. 38 | */ 39 | template 40 | static void print(T &sink, const char *msg = "", bool tag = true, bool indent = true) 41 | { 42 | #if defined(HOST_RELAY_DEBUG) 43 | if (indent) 44 | sink.hostPrint(" "); 45 | if (tag) 46 | sink.hostPrint("[Client] "); 47 | sink.hostPrint(msg); 48 | #else 49 | if (tag) 50 | sink.print("[Client] "); 51 | sink.print(msg); 52 | #endif 53 | } 54 | 55 | /** 56 | * Print new line to the sink object 57 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 58 | */ 59 | template 60 | static void printNewLine(T &sink) 61 | { 62 | print(sink, "\r\n", false, false); 63 | } 64 | 65 | /** 66 | * Print debug information to the sink object 67 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 68 | * @param msg The message to print. 69 | */ 70 | template 71 | static void printRaw(T &sink, const char *msg) 72 | { 73 | print(sink, msg, false, false); 74 | } 75 | 76 | /** 77 | * Read data stream from sink object to beffer 78 | * Data will read from stream until the endToken was found or the buffer is full. 79 | * @param source The object to read data e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 80 | * @param buffer The buffer to store the data. 81 | * @param bufferLen The size of buffer. 82 | * @param totalRead The total data that has been read. 83 | * @param endToken The token to terminate the reading. 84 | */ 85 | template 86 | static int readResonse(TSRC &source, TSNK &sink, char *buffer, size_t bufferLen, int &totalRead, const char endToken) 87 | { 88 | size_t pos = 0; 89 | int c; 90 | 91 | unsigned long ms_start = millis(); 92 | unsigned long timeout = 5000; // 5 second timeout 93 | 94 | if (!source.connected() && source.available() == 0 && totalRead == 0) 95 | return -1; // socket closed 96 | 97 | while ((source.connected() || source.available()) && (millis() - ms_start < timeout)) 98 | { 99 | if (!source.available()) 100 | { 101 | delay(1); // avoid busy loop 102 | continue; 103 | } 104 | 105 | c = source.read(); 106 | if (c == -1) 107 | continue; 108 | 109 | buffer[pos++] = (char)c; 110 | totalRead++; 111 | 112 | if (c == endToken || (endToken == 0 && source.available() == 0) || pos >= bufferLen - 1) 113 | { 114 | buffer[pos] = '\0'; 115 | print(sink, buffer, false); // debug 116 | return (int)pos; 117 | } 118 | 119 | ms_start = millis(); // reset idle timeout only after valid read 120 | } 121 | 122 | return millis() - ms_start < timeout ? 0 /* no data available */ : -2 /* timeout */; 123 | } 124 | }; 125 | 126 | #endif -------------------------------------------------------------------------------- /examples/Device_Host/Async_Client/AsyncTCP_Client/debug.h: -------------------------------------------------------------------------------- 1 | #include "HardwareSerial.h" 2 | #ifndef __DEBUG_H__ 3 | #define __DEBUG_H__ 4 | #include 5 | #include 6 | 7 | // #define BLINK_LED_PIN -1 // GPIO pin used here should not be used by serial port for bridge 8 | #define PULLED_UP_LED 0 // 1 = pull-up, 0 = pull-down 9 | 10 | struct debug 11 | { 12 | static void initBlink() 13 | { 14 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 15 | pinMode(BLINK_LED_PIN, OUTPUT); 16 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 17 | #endif 18 | } 19 | 20 | static void blink(int times, int delayMs) 21 | { 22 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 23 | for (int i = 0; i < times; i++) 24 | { 25 | digitalWrite(BLINK_LED_PIN, !PULLED_UP_LED); 26 | delay(delayMs); 27 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 28 | delay(delayMs); 29 | } 30 | #endif 31 | } 32 | /** 33 | * Print debug information with tag and spaced ident options to the sink object 34 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * @param msg The message to print. 36 | * @param tag Option to prepend with tag i.e. [Client]. 37 | * @param tag Option to prepend with space. 38 | */ 39 | template 40 | static void print(T &sink, const char *msg = "", bool tag = true, bool indent = true) 41 | { 42 | #if defined(HOST_RELAY_DEBUG) 43 | if (indent) 44 | sink.hostPrint(" "); 45 | if (tag) 46 | sink.hostPrint("[Client] "); 47 | sink.hostPrint(msg); 48 | #else 49 | if (tag) 50 | sink.print("[Client] "); 51 | sink.print(msg); 52 | #endif 53 | } 54 | 55 | /** 56 | * Print new line to the sink object 57 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 58 | */ 59 | template 60 | static void printNewLine(T &sink) 61 | { 62 | print(sink, "\r\n", false, false); 63 | } 64 | 65 | /** 66 | * Print debug information to the sink object 67 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 68 | * @param msg The message to print. 69 | */ 70 | template 71 | static void printRaw(T &sink, const char *msg) 72 | { 73 | print(sink, msg, false, false); 74 | } 75 | 76 | /** 77 | * Read data stream from sink object to beffer 78 | * Data will read from stream until the endToken was found or the buffer is full. 79 | * @param source The object to read data e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 80 | * @param buffer The buffer to store the data. 81 | * @param bufferLen The size of buffer. 82 | * @param totalRead The total data that has been read. 83 | * @param endToken The token to terminate the reading. 84 | */ 85 | template 86 | static int readResonse(TSRC &source, TSNK &sink, char *buffer, size_t bufferLen, int &totalRead, const char endToken) 87 | { 88 | size_t pos = 0; 89 | int c; 90 | 91 | unsigned long ms_start = millis(); 92 | unsigned long timeout = 5000; // 5 second timeout 93 | 94 | if (!source.connected() && source.available() == 0 && totalRead == 0) 95 | return -1; // socket closed 96 | 97 | while ((source.connected() || source.available()) && (millis() - ms_start < timeout)) 98 | { 99 | if (!source.available()) 100 | { 101 | delay(1); // avoid busy loop 102 | continue; 103 | } 104 | 105 | c = source.read(); 106 | if (c == -1) 107 | continue; 108 | 109 | buffer[pos++] = (char)c; 110 | totalRead++; 111 | 112 | if (c == endToken || (endToken == 0 && source.available() == 0) || pos >= bufferLen - 1) 113 | { 114 | buffer[pos] = '\0'; 115 | print(sink, buffer, false); // debug 116 | return (int)pos; 117 | } 118 | 119 | ms_start = millis(); // reset idle timeout only after valid read 120 | } 121 | 122 | return millis() - ms_start < timeout ? 0 /* no data available */ : -2 /* timeout */; 123 | } 124 | }; 125 | 126 | #endif -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/HTTP_Streaming/debug.h: -------------------------------------------------------------------------------- 1 | #include "HardwareSerial.h" 2 | #ifndef __DEBUG_H__ 3 | #define __DEBUG_H__ 4 | #include 5 | #include 6 | 7 | // #define BLINK_LED_PIN -1 // GPIO pin used here should not be used by serial port for bridge 8 | #define PULLED_UP_LED 0 // 1 = pull-up, 0 = pull-down 9 | 10 | struct debug 11 | { 12 | static void initBlink() 13 | { 14 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 15 | pinMode(BLINK_LED_PIN, OUTPUT); 16 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 17 | #endif 18 | } 19 | 20 | static void blink(int times, int delayMs) 21 | { 22 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 23 | for (int i = 0; i < times; i++) 24 | { 25 | digitalWrite(BLINK_LED_PIN, !PULLED_UP_LED); 26 | delay(delayMs); 27 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 28 | delay(delayMs); 29 | } 30 | #endif 31 | } 32 | /** 33 | * Print debug information with tag and spaced ident options to the sink object 34 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * @param msg The message to print. 36 | * @param tag Option to prepend with tag i.e. [Client]. 37 | * @param tag Option to prepend with space. 38 | */ 39 | template 40 | static void print(T &sink, const char *msg = "", bool tag = true, bool indent = true) 41 | { 42 | #if defined(HOST_RELAY_DEBUG) 43 | if (indent) 44 | sink.hostPrint(" "); 45 | if (tag) 46 | sink.hostPrint("[Client] "); 47 | sink.hostPrint(msg); 48 | #else 49 | if (tag) 50 | sink.print("[Client] "); 51 | sink.print(msg); 52 | #endif 53 | } 54 | 55 | /** 56 | * Print new line to the sink object 57 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 58 | */ 59 | template 60 | static void printNewLine(T &sink) 61 | { 62 | print(sink, "\r\n", false, false); 63 | } 64 | 65 | /** 66 | * Print debug information to the sink object 67 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 68 | * @param msg The message to print. 69 | */ 70 | template 71 | static void printRaw(T &sink, const char *msg) 72 | { 73 | print(sink, msg, false, false); 74 | } 75 | 76 | /** 77 | * Read data stream from sink object to beffer 78 | * Data will read from stream until the endToken was found or the buffer is full. 79 | * @param source The object to read data e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 80 | * @param buffer The buffer to store the data. 81 | * @param bufferLen The size of buffer. 82 | * @param totalRead The total data that has been read. 83 | * @param endToken The token to terminate the reading. 84 | */ 85 | template 86 | static int readResonse(TSRC &source, TSNK &sink, char *buffer, size_t bufferLen, int &totalRead, const char endToken) 87 | { 88 | size_t pos = 0; 89 | int c; 90 | 91 | unsigned long ms_start = millis(); 92 | unsigned long timeout = 5000; // 5 second timeout 93 | 94 | if (!source.connected() && source.available() == 0 && totalRead == 0) 95 | return -1; // socket closed 96 | 97 | while ((source.connected() || source.available()) && (millis() - ms_start < timeout)) 98 | { 99 | if (!source.available()) 100 | { 101 | delay(1); // avoid busy loop 102 | continue; 103 | } 104 | 105 | c = source.read(); 106 | if (c == -1) 107 | continue; 108 | 109 | buffer[pos++] = (char)c; 110 | totalRead++; 111 | 112 | if (c == endToken || (endToken == 0 && source.available() == 0) || pos >= bufferLen - 1) 113 | { 114 | buffer[pos] = '\0'; 115 | print(sink, buffer, false); // debug 116 | return (int)pos; 117 | } 118 | 119 | ms_start = millis(); // reset idle timeout only after valid read 120 | } 121 | 122 | return millis() - ms_start < timeout ? 0 /* no data available */ : -2 /* timeout */; 123 | } 124 | }; 125 | 126 | #endif -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/Host_Management/debug.h: -------------------------------------------------------------------------------- 1 | #include "HardwareSerial.h" 2 | #ifndef __DEBUG_H__ 3 | #define __DEBUG_H__ 4 | #include 5 | #include 6 | 7 | // #define BLINK_LED_PIN -1 // GPIO pin used here should not be used by serial port for bridge 8 | #define PULLED_UP_LED 0 // 1 = pull-up, 0 = pull-down 9 | 10 | struct debug 11 | { 12 | static void initBlink() 13 | { 14 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 15 | pinMode(BLINK_LED_PIN, OUTPUT); 16 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 17 | #endif 18 | } 19 | 20 | static void blink(int times, int delayMs) 21 | { 22 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 23 | for (int i = 0; i < times; i++) 24 | { 25 | digitalWrite(BLINK_LED_PIN, !PULLED_UP_LED); 26 | delay(delayMs); 27 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 28 | delay(delayMs); 29 | } 30 | #endif 31 | } 32 | /** 33 | * Print debug information with tag and spaced ident options to the sink object 34 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * @param msg The message to print. 36 | * @param tag Option to prepend with tag i.e. [Client]. 37 | * @param tag Option to prepend with space. 38 | */ 39 | template 40 | static void print(T &sink, const char *msg = "", bool tag = true, bool indent = true) 41 | { 42 | #if defined(HOST_RELAY_DEBUG) 43 | if (indent) 44 | sink.hostPrint(" "); 45 | if (tag) 46 | sink.hostPrint("[Client] "); 47 | sink.hostPrint(msg); 48 | #else 49 | if (tag) 50 | sink.print("[Client] "); 51 | sink.print(msg); 52 | #endif 53 | } 54 | 55 | /** 56 | * Print new line to the sink object 57 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 58 | */ 59 | template 60 | static void printNewLine(T &sink) 61 | { 62 | print(sink, "\r\n", false, false); 63 | } 64 | 65 | /** 66 | * Print debug information to the sink object 67 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 68 | * @param msg The message to print. 69 | */ 70 | template 71 | static void printRaw(T &sink, const char *msg) 72 | { 73 | print(sink, msg, false, false); 74 | } 75 | 76 | /** 77 | * Read data stream from sink object to beffer 78 | * Data will read from stream until the endToken was found or the buffer is full. 79 | * @param source The object to read data e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 80 | * @param buffer The buffer to store the data. 81 | * @param bufferLen The size of buffer. 82 | * @param totalRead The total data that has been read. 83 | * @param endToken The token to terminate the reading. 84 | */ 85 | template 86 | static int readResonse(TSRC &source, TSNK &sink, char *buffer, size_t bufferLen, int &totalRead, const char endToken) 87 | { 88 | size_t pos = 0; 89 | int c; 90 | 91 | unsigned long ms_start = millis(); 92 | unsigned long timeout = 5000; // 5 second timeout 93 | 94 | if (!source.connected() && source.available() == 0 && totalRead == 0) 95 | return -1; // socket closed 96 | 97 | while ((source.connected() || source.available()) && (millis() - ms_start < timeout)) 98 | { 99 | if (!source.available()) 100 | { 101 | delay(1); // avoid busy loop 102 | continue; 103 | } 104 | 105 | c = source.read(); 106 | if (c == -1) 107 | continue; 108 | 109 | buffer[pos++] = (char)c; 110 | totalRead++; 111 | 112 | if (c == endToken || (endToken == 0 && source.available() == 0) || pos >= bufferLen - 1) 113 | { 114 | buffer[pos] = '\0'; 115 | print(sink, buffer, false); // debug 116 | return (int)pos; 117 | } 118 | 119 | ms_start = millis(); // reset idle timeout only after valid read 120 | } 121 | 122 | return millis() - ms_start < timeout ? 0 /* no data available */ : -2 /* timeout */; 123 | } 124 | }; 125 | 126 | #endif -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/Secure_Connection/debug.h: -------------------------------------------------------------------------------- 1 | #include "HardwareSerial.h" 2 | #ifndef __DEBUG_H__ 3 | #define __DEBUG_H__ 4 | #include 5 | #include 6 | 7 | // #define BLINK_LED_PIN -1 // GPIO pin used here should not be used by serial port for bridge 8 | #define PULLED_UP_LED 0 // 1 = pull-up, 0 = pull-down 9 | 10 | struct debug 11 | { 12 | static void initBlink() 13 | { 14 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 15 | pinMode(BLINK_LED_PIN, OUTPUT); 16 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 17 | #endif 18 | } 19 | 20 | static void blink(int times, int delayMs) 21 | { 22 | #if defined(BLINK_LED_PIN) && BLINK_LED_PIN > -1 23 | for (int i = 0; i < times; i++) 24 | { 25 | digitalWrite(BLINK_LED_PIN, !PULLED_UP_LED); 26 | delay(delayMs); 27 | digitalWrite(BLINK_LED_PIN, PULLED_UP_LED); 28 | delay(delayMs); 29 | } 30 | #endif 31 | } 32 | /** 33 | * Print debug information with tag and spaced ident options to the sink object 34 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * @param msg The message to print. 36 | * @param tag Option to prepend with tag i.e. [Client]. 37 | * @param tag Option to prepend with space. 38 | */ 39 | template 40 | static void print(T &sink, const char *msg = "", bool tag = true, bool indent = true) 41 | { 42 | #if defined(HOST_RELAY_DEBUG) 43 | if (indent) 44 | sink.hostPrint(" "); 45 | if (tag) 46 | sink.hostPrint("[Client] "); 47 | sink.hostPrint(msg); 48 | #else 49 | if (tag) 50 | sink.print("[Client] "); 51 | sink.print(msg); 52 | #endif 53 | } 54 | 55 | /** 56 | * Print new line to the sink object 57 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 58 | */ 59 | template 60 | static void printNewLine(T &sink) 61 | { 62 | print(sink, "\r\n", false, false); 63 | } 64 | 65 | /** 66 | * Print debug information to the sink object 67 | * @param sink The object to print to e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 68 | * @param msg The message to print. 69 | */ 70 | template 71 | static void printRaw(T &sink, const char *msg) 72 | { 73 | print(sink, msg, false, false); 74 | } 75 | 76 | /** 77 | * Read data stream from sink object to beffer 78 | * Data will read from stream until the endToken was found or the buffer is full. 79 | * @param source The object to read data e.g. Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 80 | * @param buffer The buffer to store the data. 81 | * @param bufferLen The size of buffer. 82 | * @param totalRead The total data that has been read. 83 | * @param endToken The token to terminate the reading. 84 | */ 85 | template 86 | static int readResonse(TSRC &source, TSNK &sink, char *buffer, size_t bufferLen, int &totalRead, const char endToken) 87 | { 88 | size_t pos = 0; 89 | int c; 90 | 91 | unsigned long ms_start = millis(); 92 | unsigned long timeout = 5000; // 5 second timeout 93 | 94 | if (!source.connected() && source.available() == 0 && totalRead == 0) 95 | return -1; // socket closed 96 | 97 | while ((source.connected() || source.available()) && (millis() - ms_start < timeout)) 98 | { 99 | if (!source.available()) 100 | { 101 | delay(1); // avoid busy loop 102 | continue; 103 | } 104 | 105 | c = source.read(); 106 | if (c == -1) 107 | continue; 108 | 109 | buffer[pos++] = (char)c; 110 | totalRead++; 111 | 112 | if (c == endToken || (endToken == 0 && source.available() == 0) || pos >= bufferLen - 1) 113 | { 114 | buffer[pos] = '\0'; 115 | print(sink, buffer, false); // debug 116 | return (int)pos; 117 | } 118 | 119 | ms_start = millis(); // reset idle timeout only after valid read 120 | } 121 | 122 | return millis() - ms_start < timeout ? 0 /* no data available */ : -2 /* timeout */; 123 | } 124 | }; 125 | 126 | #endif -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/Host_Management/Host_Management.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================= 3 | * HOST Management Example (for client to work with Device Host) 4 | * ============================================================= 5 | * Runs on: Any Arduino device (as a client). 6 | * Host: Requires "Device_Host/Generic_Client/Host/Host.ino" running on 7 | * other Arduino devices that connected to this device via Serial port. 8 | * Purpose: Demonstrates how to use the "global" 9 | * commands to remotely control the host. 10 | * 11 | * Macros explanation 12 | * 13 | * BridgeRate The bridge serial port baud rate. 14 | * Should be matched with host device serial baud rate. 15 | * Should not exceed 115200 for AVR 16 | * 17 | * BridgeSerial The serial port that is connected to host device serial port. 18 | * 19 | * ENABLE_LOCAL_DEBUG The macro to allow local debug to show on Serial port. 20 | * This macro can be defined only when the Bridge serial port is not a USB Serial port. 21 | * 22 | * HOST_RELAY_DEBUG The macro that should be defined when working with PC host to relay the debug info. 23 | * This macro should be commented out or undefined in this example (debug info is printed locally). 24 | * 25 | * STREAM The sink object to print debug info which is one of the following clients. 26 | * Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 27 | * 28 | * BLINK_LED_PIN The GPIO that is connected to LED which is used for pinging error display. 29 | */ 30 | 31 | #define ENABLE_LOCAL_DEBUG 32 | #define BLINK_LED_PIN -1 33 | 34 | #include 35 | #include 36 | #include "debug.h" 37 | 38 | #define BridgeSlot_0 0 39 | #define BridgeRate 115200 // Change this to match with the host serial baud rate. 40 | #define BridgeSerial Serial2 // Change this to match your hardware. 41 | 42 | SerialHostManager manager(BridgeSerial); 43 | 44 | #if defined(HOST_RELAY_DEBUG) 45 | #define STREAM manager 46 | #else 47 | #define STREAM Serial 48 | #endif 49 | 50 | unsigned long ms = 0; 51 | bool hostReady = false; 52 | 53 | // WiFi Credentials for testing (Update these!) 54 | const char *new_ssid = "SSID"; 55 | const char *new_pass = "Password"; 56 | 57 | void setup() 58 | { 59 | Serial.begin(115200); 60 | delay(1000); 61 | 62 | BridgeSerial.begin(BridgeRate); 63 | 64 | manager.setLocalDebugLevel(1); // Enable debug prints 65 | 66 | // Ping host 67 | debug::print(STREAM, "Pinging host...\r\n"); 68 | if (!manager.pingHost()) 69 | { 70 | Serial.println("No response from host. Check serial port, baud rate and host device..."); 71 | while (1) 72 | delay(100); 73 | } 74 | debug::print(STREAM, "Success\r\n"); 75 | 76 | delay(2000); 77 | 78 | debug::print(STREAM, "Disconnecting Current WiFi...\r\n"); 79 | 80 | // Disconnect from WiFi AP 81 | if (manager.disconnectNetwork()) 82 | debug::print(STREAM, "Success\r\n"); 83 | else 84 | debug::print(STREAM, "Failed\r\n"); 85 | 86 | delay(5000); 87 | 88 | // Checks if host has internet access 89 | debug::print(STREAM, "Checking the network connection...\r\n"); 90 | 91 | if (manager.isNetworkConnected()) 92 | debug::print(STREAM, "WiFi is connected.\r\n"); 93 | else 94 | debug::print(STREAM, "WiFi is disconnected.\r\n"); 95 | 96 | delay(500); 97 | 98 | // Set WiFi credentials 99 | debug::print(STREAM, "Setting the WiFi AP..,\r\n"); 100 | 101 | if (manager.setWiFi(new_ssid, new_pass)) 102 | debug::print(STREAM, "Success\r\n"); 103 | else 104 | debug::print(STREAM, "Failed\r\n"); 105 | 106 | delay(500); 107 | 108 | // Tell host to connect to the new network 109 | debug::print(STREAM, "Connecting to the new WiFi AP...\r\n"); 110 | 111 | if (manager.connectNetwork()) 112 | debug::print(STREAM, "Success\r\n"); 113 | else 114 | debug::print(STREAM, "Failed\r\n"); 115 | 116 | delay(10000); 117 | 118 | // Checks if host has internet access 119 | debug::print(STREAM, "Checking the network connection...\r\n"); 120 | 121 | if (manager.isNetworkConnected()) 122 | debug::print(STREAM, "WiFi is connected.\r\n"); 123 | else 124 | debug::print(STREAM, "WiFi is disconnected.\r\n"); 125 | 126 | delay(5000); 127 | 128 | // Reboot host device 129 | debug::print(STREAM, "Rebooting the host...\r\n"); 130 | if (manager.rebootHost()) 131 | debug::print(STREAM, "Success\r\n"); 132 | else 133 | debug::print(STREAM, "Failed\r\n"); 134 | 135 | debug::print(STREAM, "Test complete.\r\n"); 136 | } 137 | 138 | void loop() 139 | { 140 | } -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/HTTP_GET/HTTP_GET.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * ======================================================= 3 | * HTTP GET Example (for client to work with Device Host) 4 | * ======================================================= 5 | * Runs on: Any Arduino device. 6 | * Host: Requires "Device_Host/Generic_Client/Host/Host.ino" running on 7 | * other Arduino devices that connected to this device via Serial port. 8 | * Purpose: Demonstrates a HTTP GET request. 9 | * 10 | * Macros explanation 11 | * 12 | * BridgeRate The bridge serial port baud rate. 13 | * Should be matched with host device serial baud rate. 14 | * Should not exceed 115200 for AVR 15 | * 16 | * BridgeSerial The serial port that is connected to host device serial port. 17 | * 18 | * BridgeSlot_0 The slot (channel or session) 0 which data will be transferred 19 | * This corresponds to the SSL client assigned on slot 0 of the host device. 20 | * See Host.ino example. 21 | * 22 | * ENABLE_LOCAL_DEBUG The macro to allow local debug to show on Serial port. 23 | * This macro can be defined only when the Bridge serial port is not a USB Serial port. 24 | * 25 | * HOST_RELAY_DEBUG The macro that should be defined when working with PC host to relay the debug info. 26 | * This macro should be commented out or undefined in this example (debug info is printed locally). 27 | * 28 | * STREAM The sink object to print debug info which is one of the following clients. 29 | * Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 30 | * 31 | * CLIENT The client object e.g. SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 32 | * 33 | * BLINK_LED_PIN The GPIO that is connected to LED which is used for pinging error display. 34 | */ 35 | 36 | #define ENABLE_LOCAL_DEBUG 37 | #define BLINK_LED_PIN -1 38 | 39 | #include 40 | #include 41 | #include "debug.h" 42 | 43 | #define BridgeSlot_0 0 44 | #define BridgeRate 115200 // Change this to match with the host serial baud rate. 45 | #define BridgeSerial Serial2 // Change this to match your hardware. 46 | 47 | SerialTCPClient client(BridgeSerial, BridgeSlot_0); 48 | 49 | #if defined(HOST_RELAY_DEBUG) 50 | #define STREAM client 51 | #define CLIENT client 52 | #else 53 | #define STREAM Serial 54 | #define CLIENT client 55 | #endif 56 | 57 | unsigned long ms = 0; 58 | bool hostReady = false; 59 | 60 | void setup() 61 | { 62 | Serial.begin(115200); 63 | delay(1000); 64 | 65 | BridgeSerial.begin(BridgeRate); 66 | 67 | client.setLocalDebugLevel(1); // Enable debug prints 68 | 69 | // Sending Ping request to host; 70 | debug::initBlink(); 71 | while (!hostReady) 72 | { 73 | hostReady = client.pingHost(500); 74 | if (!hostReady) 75 | { 76 | Serial.println("No response from host. Check serial port, baud rate and host device..."); 77 | debug::blink(10, 500); 78 | delay(2000); 79 | } 80 | } 81 | } 82 | 83 | void loop() 84 | { 85 | if (hostReady && (ms == 0 || millis() - ms > 10000)) 86 | { 87 | ms = millis(); 88 | 89 | // This will set SSL I/O buffer (if SSL client on host device is supported) 90 | client.setBufferSizes(2048, 1024); 91 | 92 | // Set this to skip SSL certificate verification on SSL client assigned to slot 0 in host device. 93 | client.setInsecure(); 94 | 95 | debug::print(STREAM, "Connecting to server...\r\n"); 96 | 97 | if (client.connect("httpbin.org", 443)) 98 | { 99 | debug::print(STREAM, "Server connected, sending request...\r\n"); 100 | 101 | client.println("GET /get HTTP/1.1"); 102 | client.println("Host: httpbin.org"); 103 | client.println("Connection: close"); 104 | client.println(); 105 | 106 | debug::print(STREAM, "Waiting for response...\r\n"); 107 | 108 | char buffer[128]; 109 | int ret = 0, totalRead = 0; 110 | char endToken = '\n'; // start by reading lines 111 | do 112 | { 113 | ret = debug::readResonse(CLIENT, STREAM, buffer, 128, totalRead, endToken); 114 | 115 | if (endToken == '\n' && strcmp(buffer, "\r\n") == 0) 116 | { 117 | // Headers done 118 | // read all remaining data without line endings 119 | endToken = '\0'; 120 | } 121 | } while (ret > 0); 122 | 123 | debug::printNewLine(STREAM); 124 | debug::print(STREAM, ret >= 0 ? "Response complete.\r\n" : (ret < -1 ? "Error: Response timeout.\r\n" : "Error: Socket closed.\r\n")); 125 | client.stop(); 126 | } 127 | else 128 | { 129 | debug::print(STREAM, "Unable to connect to server\r\n"); 130 | } 131 | } 132 | } -------------------------------------------------------------------------------- /examples/PC_Host/Host_Management/Host_Management.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * ========================================================= 3 | * Host Management Example (for client to work with PC Host) 4 | * ========================================================= 5 | * Runs on: Any Arduino device (as a client). 6 | * Host: Requires the UPDATED 'serial_bridge.py' script running on your PC. 7 | * Purpose: Demonstrates using "Global Commands" to control the Host PC. 8 | * WARNING: 9 | * The 'rebootHost' command will REBOOT YOUR COMPUTER if running as Administrator/Root. 10 | * The WiFi commands will disconnect/connect your PC's actual Wi-Fi interface. 11 | * Use with caution! 12 | * 13 | * INSTRUCTIONS: 14 | * 1. CRITICAL: Ensure '#define ENABLE_SERIALTCP_DEBUG' is commented out/disabled. 15 | * 2. Upload this sketch to your Arduino. 16 | * 3. Close the Serial Monitor. 17 | * 4. Run 'python serial_bridge.py' on your computer (Admin/Sudo required for WiFi/Reboot). 18 | * 19 | * Macros explanation 20 | * 21 | * BridgeRate The bridge serial port baud rate. 22 | * Should not exceed 115200 for AVR 23 | * 24 | * ENABLE_LOCAL_DEBUG The macro to allow local debug to show on Serial port. 25 | * This macro can be defined only when the Bridge serial port is not a USB Serial port. 26 | * It shiukd not defined in this example. 27 | * 28 | * HOST_RELAY_DEBUG The macro that should be defined when working with PC host to relay the debug info. 29 | * This macro should be defined in this example. 30 | * 31 | * STREAM The sink object to print debug info which is one of the following clients. 32 | * Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 33 | * 34 | * BLINK_LED_PIN The GPIO that is connected to LED which is used for pinging error display. 35 | */ 36 | 37 | #define HOST_RELAY_DEBUG 38 | #define BLINK_LED_PIN -1 39 | 40 | #include 41 | #include 42 | #include "debug.h" 43 | 44 | #define BridgeRate 115200 45 | 46 | SerialHostManager manager(Serial); 47 | 48 | #if defined(HOST_RELAY_DEBUG) 49 | #define STREAM manager 50 | #else 51 | #define STREAM Serial 52 | #endif 53 | 54 | // WiFi Credentials for testing (Update these!) 55 | const char *new_ssid = "SSID"; 56 | const char *new_pass = "Password"; 57 | 58 | void setup() 59 | { 60 | Serial.begin(BridgeRate); 61 | while (!Serial) 62 | ; 63 | 64 | Serial.write(0x00); 65 | delay(500); 66 | 67 | // Ping host 68 | debug::print(STREAM, "Pinging host...\r\n"); 69 | if (!manager.pingHost()) 70 | { 71 | // This debug message will not be unable to send to host PC. 72 | Serial.println("No response from host. Please make sure serial_bridge.py is running..."); 73 | while (1) 74 | delay(100); 75 | } 76 | debug::print(STREAM, "Success\r\n"); 77 | 78 | delay(2000); 79 | 80 | debug::print(STREAM, "Disconnecting Current WiFi...\r\n"); 81 | 82 | // Disconnect from WiFi AP 83 | if (manager.disconnectNetwork()) 84 | debug::print(STREAM, "Success\r\n"); 85 | else 86 | debug::print(STREAM, "Failed\r\n"); 87 | 88 | delay(5000); 89 | 90 | // Checks if host has internet access 91 | debug::print(STREAM, "Checking the network connection...\r\n"); 92 | 93 | if (manager.isNetworkConnected()) 94 | debug::print(STREAM, "WiFi is connected.\r\n"); 95 | else 96 | debug::print(STREAM, "WiFi is disconnected.\r\n"); 97 | 98 | delay(500); 99 | 100 | // Set WiFi credentials 101 | debug::print(STREAM, "Setting the WiFi AP..,\r\n"); 102 | 103 | if (manager.setWiFi(new_ssid, new_pass)) 104 | debug::print(STREAM, "Success\r\n"); 105 | else 106 | debug::print(STREAM, "Failed\r\n"); 107 | 108 | delay(500); 109 | 110 | // Tell host to connect to the new network 111 | debug::print(STREAM, "Connecting to the new WiFi AP...\r\n"); 112 | 113 | if (manager.connectNetwork()) 114 | debug::print(STREAM, "Success\r\n"); 115 | else 116 | debug::print(STREAM, "Failed\r\n"); 117 | 118 | delay(10000); 119 | 120 | // Checks if host has internet access 121 | debug::print(STREAM, "Checking the network connection...\r\n"); 122 | 123 | if (manager.isNetworkConnected()) 124 | debug::print(STREAM, "WiFi is connected.\r\n"); 125 | else 126 | debug::print(STREAM, "WiFi is disconnected.\r\n"); 127 | 128 | delay(5000); 129 | 130 | // Reboot host 131 | debug::print(STREAM, "Rebooting the host...\r\n"); 132 | if (manager.rebootHost()) 133 | debug::print(STREAM, "Success\r\n"); 134 | else 135 | debug::print(STREAM, "Failed\r\n"); 136 | 137 | debug::print(STREAM, "Test complete.\r\n"); 138 | } 139 | 140 | void loop() 141 | { 142 | } -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/WebSocket/Websocket.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * ====================================================== 3 | * WebSocket Example (for client to work with Device Host) 4 | * ====================================================== 5 | * Runs on: Arduino device (e.g., Uno, Nano). 6 | * Host: Requires "Device_Host/Generic_Client/Host/Host.ino" running on 7 | * other Arduino devices that connected to this device via Serial port. 8 | * Purpose: Demonstrates the Websocket client usage. 9 | * 10 | * Macros explanation 11 | * 12 | * BridgeRate The bridge serial port baud rate. 13 | * Should be matched with host device serial baud rate. 14 | * Should not exceed 115200 for AVR 15 | * 16 | * BridgeSerial The serial port that is connected to host device serial port. 17 | * 18 | * BridgeSlot_2 The slot (channel or session) 2 which data will be transferred 19 | * This corresponds to the Websocket client assigned on slot 2 of the host device. 20 | * See Host.ino example. 21 | * 22 | * ENABLE_LOCAL_DEBUG The macro to allow local debug to show on Serial port. 23 | * This macro can be defined only when the Bridge serial port is not a USB Serial port. 24 | * 25 | * HOST_RELAY_DEBUG The macro that should be defined when working with PC host to relay the debug info. 26 | * This macro should be commented out or undefined in this example (debug info is printed locally). 27 | * 28 | * STREAM The sink object to print debug info which is one of the following clients. 29 | * Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 30 | * 31 | * CLIENT The client object e.g. SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 32 | * 33 | * BLINK_LED_PIN The GPIO that is connected to LED which is used for pinging error display. 34 | */ 35 | 36 | #define ENABLE_LOCAL_DEBUG 37 | #define BLINK_LED_PIN -1 38 | 39 | #include 40 | #include 41 | #include "debug.h" 42 | 43 | #define BridgeSlot_2 2 44 | #define BridgeRate 115200 // Change this to match with the host serial baud rate. 45 | #define BridgeSerial Serial2 // Change this to match your hardware. 46 | 47 | SerialWebsocketClient ws(BridgeSerial, BridgeSlot_2); 48 | 49 | #if defined(HOST_RELAY_DEBUG) 50 | #define STREAM ws 51 | #define CLIENT ws 52 | #else 53 | #define STREAM Serial 54 | #define CLIENT ws 55 | #endif 56 | 57 | unsigned long ms = 0; 58 | bool hostReady = false; 59 | 60 | const unsigned long interval = 5000; // Send message every 5 seconds 61 | 62 | // WebSocket Event Callback 63 | void onWsEvent(WSMessageType type, const uint8_t *payload, size_t len) 64 | { 65 | switch (type) 66 | { 67 | case WS_EVENT_CONNECTED: 68 | debug::print(STREAM, "WS Connected!\r\n\r\n"); 69 | break; 70 | case WS_EVENT_DISCONNECTED: 71 | debug::print(STREAM, "Warning: WS Disconnected!\r\n\r\n"); 72 | break; 73 | case WS_FRAME_TEXT: 74 | if (type == WS_FRAME_TEXT) 75 | { 76 | char *msg = (char *)malloc(len + 1); 77 | memcpy(msg, payload, len); 78 | msg[len] = '\0'; 79 | debug::print(STREAM, "Text message received: "); 80 | debug::printRaw(STREAM, msg); 81 | debug::printRaw(STREAM, "\r\n\r\n"); 82 | } 83 | else if (type == WS_FRAME_BINARY) 84 | { 85 | debug::print(STREAM, "Binary message received, Size: "); 86 | debug::printRaw(STREAM, String(len).c_str()); 87 | debug::printRaw(STREAM, "\r\n\r\n"); 88 | } 89 | 90 | break; 91 | } 92 | } 93 | 94 | void setup() 95 | { 96 | Serial.begin(115200); 97 | delay(1000); 98 | 99 | BridgeSerial.begin(BridgeRate); 100 | 101 | ws.setLocalDebugLevel(1); // Enable debug prints 102 | 103 | // Sending Ping request to host; 104 | debug::initBlink(); 105 | while (!hostReady) 106 | { 107 | hostReady = ws.pingHost(500); 108 | if (!hostReady) 109 | { 110 | Serial.println("No response from host. Check serial port, baud rate and host device..."); 111 | debug::blink(10, 500); 112 | delay(2000); 113 | } 114 | } 115 | 116 | // Register the event callback 117 | ws.onEvent(onWsEvent); 118 | 119 | debug::print(STREAM, "Connecting to echo server...\r\n\r\n"); 120 | 121 | // Connect to the public echo server (SSL Enabled) 122 | ws.connect("echo.websocket.org", 443, "/", true); 123 | } 124 | 125 | void loop() 126 | { 127 | // WebSocket is event-driven, so we simply call loop() repeatedly 128 | ws.loop(); 129 | 130 | // Send Periodic Requests 131 | if (ms == 0 || millis() - ms > interval) 132 | { 133 | ms = millis(); 134 | debug::print(STREAM, "Sending message...\r\n\r\n"); 135 | ws.sendText("Hello from Arduino!"); 136 | } 137 | } -------------------------------------------------------------------------------- /examples/PC_Host/HTTP_GET/HTTP_GET.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * ================================================== 3 | * HTTP GET Example (for client to work with PC Host) 4 | * ================================================== 5 | * Runs on: Any Arduino device (as a client). 6 | * Host: Requires the 'serial_bridge.py' script running on your PC. 7 | * Purpose: Demonstrates how to configure your device to connect to 8 | * the 'serial_bridge.py' script running on your computer via the USB cable. 9 | * It pings the bridge and sends an HTTP GET request to httpbin.org. 10 | * INSTRUCTIONS: 11 | * 1. CRITICAL: Ensure '#define ENABLE_SERIALTCP_DEBUG' is commented out/disabled. 12 | * 2. Upload this sketch to your Arduino. 13 | * 3. Close the Serial Monitor (The USB port is used for the bridge). 14 | * 4. Run 'python serial_bridge.py' on your computer. 15 | * 16 | * Macros explanation 17 | * 18 | * BridgeRate The bridge serial port baud rate. 19 | * Should not exceed 115200 for AVR 20 | * 21 | * BridgeSlot_0 The slot (session) 0 which data will be transferred 22 | * This corresponds to the ssl wrapped socket assigned on slot 0 of the python script running on the PC device. 23 | * The implementation on python script is different and flexible. The transport layer does not fix to the slot 24 | * as it is assigned to the host device. 25 | * 26 | * ENABLE_LOCAL_DEBUG The macro to allow local debug to show on Serial port. 27 | * This macro can be defined only when the Bridge serial port is not a USB Serial port. 28 | * It shiukd not defined in this example. 29 | * 30 | * HOST_RELAY_DEBUG The macro that should be defined when working with PC host to relay the debug info. 31 | * This macro should be defined in this example. 32 | * 33 | * STREAM The sink object to print debug info which is one of the following clients. 34 | * Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * 36 | * CLIENT The client object e.g. SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 37 | * 38 | * BLINK_LED_PIN The GPIO that is connected to LED which is used for pinging error display. 39 | */ 40 | 41 | #define HOST_RELAY_DEBUG 42 | #define BLINK_LED_PIN -1 43 | 44 | #include 45 | #include 46 | #include "debug.h" 47 | 48 | #define BridgeSlot_0 0 49 | #define BridgeRate 115200 50 | 51 | SerialTCPClient client(Serial, BridgeSlot_0); 52 | 53 | #if defined(HOST_RELAY_DEBUG) 54 | #define STREAM client 55 | #define CLIENT client 56 | #else 57 | #define STREAM Serial 58 | #define CLIENT client 59 | #endif 60 | 61 | unsigned long ms = 0; 62 | bool hostReady = false; 63 | 64 | void setup() 65 | { 66 | Serial.begin(BridgeRate); 67 | while (!Serial) 68 | ; 69 | 70 | Serial.write(0x00); 71 | delay(500); 72 | 73 | // Sending Ping request to host; 74 | debug::initBlink(); 75 | while (!hostReady) 76 | { 77 | hostReady = client.pingHost(500); 78 | if (!hostReady) 79 | { 80 | Serial.println("No response from host. Please make sure serial_bridge.py is running..."); 81 | debug::blink(10, 500); 82 | delay(2000); 83 | } 84 | } 85 | 86 | client.stop(); 87 | } 88 | 89 | void loop() 90 | { 91 | if (hostReady && (ms == 0 || millis() - ms > 10000)) 92 | { 93 | ms = millis(); 94 | 95 | debug::print(STREAM, "Connecting to server...\r\n"); 96 | 97 | // [CRITICAL] The 3rd parameter 'true' enables SSL/TLS (HTTPS). 98 | // Unlike the Arduino device Host, the PC Host script REQUIRES this flag to know 99 | // it must wrap the socket in SSL. If omitted, it attempts a plain 100 | // TCP connection to port 443, which the server will reject. 101 | if (client.connect("httpbin.org", 443, true)) 102 | { 103 | debug::print(STREAM, "Server connected, sending request...\r\n"); 104 | 105 | client.println("GET /get HTTP/1.1"); 106 | client.println("Host: httpbin.org"); 107 | client.println("Connection: close"); 108 | client.println(); 109 | 110 | debug::print(STREAM, "Waiting for response...\r\n"); 111 | 112 | char buffer[128]; 113 | int ret = 0, totalRead = 0; 114 | char endToken = '\n'; // start by reading lines 115 | do 116 | { 117 | ret = debug::readResonse(CLIENT, STREAM, buffer, 128, totalRead, endToken); 118 | 119 | if (endToken == '\n' && strcmp(buffer, "\r\n") == 0) 120 | { 121 | // Headers done 122 | // read all remaining data without line endings 123 | endToken = '\0'; 124 | } 125 | } while (ret > 0); 126 | 127 | debug::printNewLine(STREAM); 128 | debug::print(STREAM, ret >= 0 ? "Response complete.\r\n" : (ret < -1 ? "Error: Response timeout.\r\n" : "Error: Socket closed.\r\n")); 129 | client.stop(); 130 | } 131 | else 132 | { 133 | debug::print(STREAM, "Unable to connect to server\r\n"); 134 | } 135 | } 136 | } -------------------------------------------------------------------------------- /examples/PC_Host/MQTT/MQTT.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * =============================================== 3 | * MQTT Example (for client to work with PC Host) 4 | * =============================================== 5 | * Runs on: Any Arduino device (as a client). 6 | * Host: Requires the 'serial_bridge.py' script running on your PC. 7 | * Purpose: Connects to broker.hivemq.com on Port 8883 (SSL) via PC Bridge. 8 | * INSTRUCTIONS: 9 | * 1. CRITICAL: Ensure '#define ENABLE_SERIALTCP_DEBUG' is commented out/disabled. 10 | * 2. Upload this sketch. 11 | * 3. Close Serial Monitor. 12 | * 4. Run 'python serial_bridge.py'. 13 | * 14 | * Macros explanation 15 | * 16 | * BridgeRate The bridge serial port baud rate. 17 | * Should not exceed 115200 for AVR 18 | * 19 | * BridgeSlot_0 The slot (session) 0 which data will be transferred 20 | * This corresponds to the ssl wrapped socket assigned on slot 0 of the python script running on the PC device. 21 | * The implementation on python script is different and flexible. The transport layer does not fix to the slot 22 | * as it is assigned to the host device. 23 | * 24 | * ENABLE_LOCAL_DEBUG The macro to allow local debug to show on Serial port. 25 | * This macro can be defined only when the Bridge serial port is not a USB Serial port. 26 | * It shiukd not defined in this example. 27 | * 28 | * HOST_RELAY_DEBUG The macro that should be defined when working with PC host to relay the debug info. 29 | * This macro should be defined in this example. 30 | * 31 | * STREAM The sink object to print debug info which is one of the following clients. 32 | * Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 33 | * 34 | * CLIENT The client object e.g. SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * 36 | * BLINK_LED_PIN The GPIO that is connected to LED which is used for pinging error display. 37 | */ 38 | 39 | #define HOST_RELAY_DEBUG 40 | #define BLINK_LED_PIN -1 41 | 42 | #include 43 | #include 44 | #include "SerialSSLClient.h" 45 | #include "debug.h" 46 | 47 | // This ibrary is required for this example 48 | #include 49 | 50 | #define BridgeSlot_0 0 51 | #define BridgeRate 115200 // Change this to match with the host serial baud rate. 52 | 53 | SerialSSLClient client(Serial, BridgeSlot_0); 54 | MqttClient mqtt(client); 55 | 56 | #if defined(HOST_RELAY_DEBUG) 57 | #define STREAM client 58 | #define CLIENT client 59 | #else 60 | #define STREAM Serial 61 | #define CLIENT client 62 | #endif 63 | 64 | unsigned long ms = 0; 65 | bool hostReady = false; 66 | 67 | // MQTT broker config 68 | const char broker[] = "broker.hivemq.com"; 69 | const int port = 8883; // SSL Port 70 | const char topic[] = "arduino/serialtcp-test"; 71 | 72 | int count = 0; 73 | const long interval = 3000; 74 | 75 | void connectMqt() 76 | { 77 | debug::print(STREAM, "Attempting to connect to the MQTT broker over ssl: "); 78 | debug::print(STREAM, broker, false, false); 79 | debug::printNewLine(STREAM); 80 | 81 | if (!mqtt.connect(broker, port)) 82 | { 83 | debug::print(STREAM, "MQTT connection failed! Error code = "); 84 | debug::printRaw(STREAM, String(mqtt.connectError()).c_str()); 85 | debug::printNewLine(STREAM); 86 | return; 87 | } 88 | 89 | debug::print(STREAM, "You're connected to the MQTT broker!\r\n"); 90 | debug::print(STREAM, "Subscribing to topic: "); 91 | debug::printRaw(STREAM, topic); 92 | debug::printNewLine(STREAM); 93 | 94 | // subscribe to a topic 95 | mqtt.subscribe(topic); 96 | 97 | // topics can be unsubscribed using: 98 | // mqtt.unsubscribe(topic); 99 | 100 | debug::print(STREAM, "Waiting for messages on topic: "); 101 | debug::printRaw(STREAM, topic); 102 | debug::printNewLine(STREAM); 103 | } 104 | 105 | void setup() 106 | { 107 | Serial.begin(115200); 108 | while (!Serial) 109 | ; 110 | 111 | // Flush bootloader noise 112 | Serial.write(0x00); 113 | delay(500); 114 | 115 | // Sending Ping request to host; 116 | debug::initBlink(); 117 | while (!hostReady) 118 | { 119 | hostReady = client.pingHost(500); 120 | if (!hostReady) 121 | { 122 | Serial.println("No response from host. Please make sure serial_bridge.py is running..."); 123 | debug::blink(10, 500); 124 | delay(2000); 125 | } 126 | } 127 | 128 | client.stop(); 129 | 130 | connectMqt(); 131 | } 132 | 133 | void loop() 134 | { 135 | if (!hostReady) 136 | return; 137 | 138 | if (!mqtt.connected()) 139 | { 140 | connectMqt(); 141 | delay(2000); 142 | return; 143 | } 144 | 145 | mqtt.poll(); 146 | 147 | int messageSize = mqtt.parseMessage(); 148 | if (messageSize) 149 | { 150 | debug::print(STREAM, "Message Received: "); 151 | while (mqtt.available()) 152 | { 153 | debug::printRaw(STREAM, String(mqtt.read()).c_str()); 154 | } 155 | 156 | debug::printNewLine(STREAM); 157 | } 158 | 159 | if (ms == 0 || millis() - ms > interval) 160 | { 161 | ms = millis(); 162 | mqtt.beginMessage(topic); 163 | mqtt.print(count); 164 | mqtt.endMessage(); 165 | count++; 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /examples/PC_Host/HTTP_POST/HTTP_POST.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * =================================================== 3 | * HTTP POST Example (for client to work with PC Host) 4 | * =================================================== 5 | * Runs on: Any Arduino device (as a client). 6 | * Host: Requires the 'serial_bridge.py' script running on your PC. 7 | * Purpose: Demonstrates how to configure your device to connect to 8 | * the 'serial_bridge.py' script running on your computer via the USB cable. 9 | * It pings the bridge and sends an HTTP POST request to reqres.in. 10 | * INSTRUCTIONS: 11 | * 1. CRITICAL: Ensure '#define ENABLE_SERIALTCP_DEBUG' is commented out/disabled. 12 | * 2. Upload this sketch to your Arduino. 13 | * 3. Close the Serial Monitor (The USB port is used for the bridge). 14 | * 4. Run 'python serial_bridge.py' on your computer. 15 | * 16 | * Macros explanation 17 | * 18 | * BridgeRate The bridge serial port baud rate. 19 | * Should not exceed 115200 for AVR 20 | * 21 | * BridgeSlot_0 The slot (session) 0 which data will be transferred 22 | * This corresponds to the ssl wrapped socket assigned on slot 0 of the python script running on the PC device. 23 | * The implementation on python script is different and flexible. The transport layer does not fix to the slot 24 | * as it is assigned to the host device. 25 | * 26 | * ENABLE_LOCAL_DEBUG The macro to allow local debug to show on Serial port. 27 | * This macro can be defined only when the Bridge serial port is not a USB Serial port. 28 | * It shiukd not defined in this example. 29 | * 30 | * HOST_RELAY_DEBUG The macro that should be defined when working with PC host to relay the debug info. 31 | * This macro should be defined in this example. 32 | * 33 | * STREAM The sink object to print debug info which is one of the following clients. 34 | * Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * 36 | * CLIENT The client object e.g. SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 37 | * 38 | * BLINK_LED_PIN The GPIO that is connected to LED which is used for pinging error display. 39 | */ 40 | 41 | #define HOST_RELAY_DEBUG 42 | #define BLINK_LED_PIN -1 43 | 44 | #include 45 | #include 46 | #include "debug.h" 47 | 48 | #define BridgeSlot_0 0 49 | #define BridgeRate 115200 // Change this to match with the host serial baud rate. 50 | 51 | SerialTCPClient client(Serial, BridgeSlot_0); 52 | 53 | #if defined(HOST_RELAY_DEBUG) 54 | #define STREAM client 55 | #define CLIENT client 56 | #else 57 | #define STREAM Serial 58 | #define CLIENT client 59 | #endif 60 | 61 | unsigned long ms = 0; 62 | bool hostReady = false; 63 | 64 | void setup() 65 | { 66 | Serial.begin(BridgeRate); 67 | while (!Serial) 68 | ; 69 | 70 | Serial.write(0x00); 71 | delay(500); 72 | 73 | // Sending Ping request to host; 74 | debug::initBlink(); 75 | while (!hostReady) 76 | { 77 | hostReady = client.pingHost(500); 78 | if (!hostReady) 79 | { 80 | Serial.println("No response from host. Please make sure serial_bridge.py is running..."); 81 | debug::blink(10, 500); 82 | delay(2000); 83 | } 84 | } 85 | 86 | client.stop(); 87 | } 88 | 89 | void loop() 90 | { 91 | if (hostReady && (ms == 0 || millis() - ms > 10000)) 92 | { 93 | ms = millis(); 94 | 95 | debug::print(STREAM, "Connecting to server...\r\n"); 96 | 97 | // [CRITICAL] The 3rd parameter 'true' enables SSL/TLS (HTTPS). 98 | // Unlike the Arduino device Host, the PC Host script REQUIRES this flag to know 99 | // it must wrap the socket in SSL. If omitted, it attempts a plain 100 | // TCP connection to port 443, which the server will reject. 101 | if (client.connect("jsonplaceholder.typicode.com", 443)) 102 | { 103 | debug::print(STREAM, "Server connected, sending request...\r\n"); 104 | 105 | const char *request = 106 | "POST /posts HTTP/1.1\r\n" 107 | "Host: jsonplaceholder.typicode.com\r\n" 108 | "Content-Type: application/json\r\n" 109 | "Content-Length: 34\r\n" 110 | "Connection: close\r\n" 111 | "\r\n" 112 | "{\"name\":\"morpheus\",\"job\":\"leader\"}"; 113 | 114 | // Send the request 115 | client.write((const uint8_t *)request, strlen(request)); 116 | 117 | // Wait for response 118 | debug::print(STREAM, "Waiting for response...\r\n"); 119 | 120 | char buffer[128]; 121 | int ret = 0, totalRead = 0; 122 | char endToken = '\n'; // start by reading lines 123 | do 124 | { 125 | ret = debug::readResonse(CLIENT, STREAM, buffer, 128, totalRead, endToken); 126 | 127 | if (endToken == '\n' && strcmp(buffer, "\r\n") == 0) 128 | { 129 | // Headers done 130 | // read all remaining data without line endings 131 | endToken = '\0'; 132 | } 133 | } while (ret > 0); 134 | 135 | debug::printNewLine(STREAM); 136 | debug::print(STREAM, ret >= 0 ? "Response complete.\r\n" : (ret < -1 ? "Error: Response timeout.\r\n" : "Error: Socket closed.\r\n")); 137 | client.stop(); 138 | } 139 | else 140 | { 141 | debug::print(STREAM, "Unable to connect to server\r\n"); 142 | } 143 | } 144 | } -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/HTTP_POST/HTTP_POST.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * ======================================================== 3 | * HTTP POST Example (for client to work with Device Host) 4 | * ======================================================== 5 | * Runs on: Any Arduino device. 6 | * Host: Requires "Device_Host/Generic_Client/Host/Host.ino" running on 7 | * other Arduino devices that connected to this device via Serial port. 8 | * Purpose: Demonstrates a HTTP POST request. 9 | * 10 | * Macros explanation 11 | * 12 | * BridgeRate The bridge serial port baud rate. 13 | * Should be matched with host device serial baud rate. 14 | * Should not exceed 115200 for AVR 15 | * 16 | * BridgeSerial The serial port that is connected to host device serial port. 17 | * 18 | * BridgeSlot_0 The slot (channel or session) 0 which data will be transferred 19 | * This corresponds to the SSL client assigned on slot 0 of the host device. 20 | * See Host.ino example. 21 | * 22 | * ENABLE_LOCAL_DEBUG The macro to allow local debug to show on Serial port. 23 | * This macro can be defined only when the Bridge serial port is not a USB Serial port. 24 | * 25 | * HOST_RELAY_DEBUG The macro that should be defined when working with PC host to relay the debug info. 26 | * This macro should be commented out or undefined in this example (debug info is printed locally). 27 | * 28 | * STREAM The sink object to print debug info which is one of the following clients. 29 | * Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 30 | * 31 | * CLIENT The client object e.g. SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 32 | * 33 | * BLINK_LED_PIN The GPIO that is connected to LED which is used for pinging error display. 34 | */ 35 | 36 | #define ENABLE_LOCAL_DEBUG 37 | #define BLINK_LED_PIN -1 38 | 39 | #include 40 | #include 41 | #include "debug.h" 42 | 43 | #define BridgeSlot_0 0 44 | #define BridgeRate 115200 // Change this to match with the host serial baud rate. 45 | #define BridgeSerial Serial2 // Change this to match your hardware. 46 | 47 | SerialTCPClient client(BridgeSerial, BridgeSlot_0); 48 | 49 | #if defined(HOST_RELAY_DEBUG) 50 | #define STREAM client 51 | #define CLIENT client 52 | #else 53 | #define STREAM Serial 54 | #define CLIENT client 55 | #endif 56 | 57 | unsigned long ms = 0; 58 | bool hostReady = false; 59 | 60 | void setup() 61 | { 62 | Serial.begin(115200); 63 | delay(1000); 64 | 65 | BridgeSerial.begin(BridgeRate); 66 | client.setLocalDebugLevel(1); // Enable debug prints 67 | 68 | // Sending Ping request to host; 69 | debug::initBlink(); 70 | while (!hostReady) 71 | { 72 | hostReady = client.pingHost(500); 73 | if (!hostReady) 74 | { 75 | Serial.println("No response from host. Check serial port, baud rate and host device..."); 76 | debug::blink(10, 500); 77 | delay(2000); 78 | } 79 | } 80 | } 81 | 82 | void loop() 83 | { 84 | if (hostReady && (ms == 0 || millis() - ms > 10000)) 85 | { 86 | ms = millis(); 87 | 88 | // This will set SSL I/O buffer (if SSL client on host device is supported) 89 | client.setBufferSizes(2048, 1024); 90 | 91 | // Set this to skip SSL certificate verification on SSL client assigned to slot 0 in host device. 92 | client.setInsecure(); 93 | 94 | debug::print(STREAM, "Connecting to server...\r\n"); 95 | 96 | // Assume SSL client was set to the host for this CLIENT_SLOT 97 | if (client.connect("jsonplaceholder.typicode.com", 443)) 98 | { 99 | debug::print(STREAM, "Server connected, sending request...\r\n"); 100 | 101 | const char *request = 102 | "POST /posts HTTP/1.1\r\n" 103 | "Host: jsonplaceholder.typicode.com\r\n" 104 | "Content-Type: application/json\r\n" 105 | "Content-Length: 34\r\n" 106 | "Connection: close\r\n" 107 | "\r\n" 108 | "{\"name\":\"morpheus\",\"job\":\"leader\"}"; 109 | 110 | // Send the request 111 | client.write((const uint8_t *)request, strlen(request)); 112 | 113 | // Wait for response 114 | debug::print(STREAM, "Waiting for response...\r\n"); 115 | 116 | char buffer[128]; 117 | int ret = 0, totalRead = 0; 118 | char endToken = '\n'; // start by reading lines 119 | do 120 | { 121 | ret = debug::readResonse(CLIENT, STREAM, buffer, 128, totalRead, endToken); 122 | 123 | if (endToken == '\n' && strcmp(buffer, "\r\n") == 0) 124 | { 125 | // Headers done 126 | // read all remaining data without line endings 127 | endToken = '\0'; 128 | } 129 | } while (ret > 0); 130 | 131 | debug::printNewLine(STREAM); 132 | debug::print(STREAM, ret >= 0 ? "Response complete.\r\n" : (ret < -1 ? "Error: Response timeout.\r\n" : "Error: Socket closed.\r\n")); 133 | client.stop(); 134 | } 135 | else 136 | { 137 | debug::print(STREAM, "Unable to connect to server\r\n"); 138 | } 139 | } 140 | } -------------------------------------------------------------------------------- /examples/PC_Host/WebSocket/WebSocket.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * =================================================== 3 | * WebSocket Example (for client to work with PC Host) 4 | * =================================================== 5 | * Runs on: Any Arduino device (as Client). 6 | * Host: Requires the 'serial_bridge.py' script running on your PC. 7 | * Purpose: Demonstrates how to configure your device to connect to 8 | * the 'serial_bridge.py' script running on your computer via the USB cable. 9 | * It connects to a WebSocket echo server and blinks the LED on events. 10 | * * * INSTRUCTIONS: 11 | * 1. CRITICAL: Ensure '#define ENABLE_SERIALTCP_DEBUG' is commented out/disabled. 12 | * 2. Upload this sketch to your Arduino. 13 | * 3. Close the Serial Monitor (The USB port is used for the bridge). 14 | * 4. Run 'python serial_bridge.py' on your computer. 15 | * 16 | * Macros explanation 17 | * 18 | * BridgeRate The bridge serial port baud rate. 19 | * Should not exceed 115200 for AVR 20 | * 21 | * BridgeSlot_0 The slot (session) 0 which data will be transferred 22 | * This corresponds to the ssl wrapped socket assigned on slot 0 of the python script running on the PC device. 23 | * The implementation on python script is different and flexible. The transport layer does not fix to the slot 24 | * as it is assigned to the host device. 25 | * 26 | * ENABLE_LOCAL_DEBUG The macro to allow local debug to show on Serial port. 27 | * This macro can be defined only when the Bridge serial port is not a USB Serial port. 28 | * It shiukd not defined in this example. 29 | * 30 | * HOST_RELAY_DEBUG The macro that should be defined when working with PC host to relay the debug info. 31 | * This macro should be defined in this example. 32 | * 33 | * STREAM The sink object to print debug info which is one of the following clients. 34 | * Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 35 | * 36 | * CLIENT The client object e.g. SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 37 | * 38 | * BLINK_LED_PIN The GPIO that is connected to LED which is used for pinging error display. 39 | */ 40 | 41 | #define HOST_RELAY_DEBUG 42 | #define BLINK_LED_PIN -1 43 | 44 | #include 45 | #include 46 | #include "debug.h" 47 | 48 | #define BridgeSlot_0 0 49 | #define BridgeRate 115200 50 | 51 | SerialWebsocketClient ws(Serial, BridgeSlot_0); 52 | 53 | #if defined(HOST_RELAY_DEBUG) 54 | #define STREAM ws 55 | #define CLIENT ws 56 | #else 57 | #define STREAM Serial 58 | #define CLIENT ws 59 | #endif 60 | 61 | unsigned long ms = 0; 62 | bool hostReady = false; 63 | 64 | // Use the main USB Serial port (Slot 0) 65 | SerialWebsocketClient ws(Serial, BridgeSlot_0); 66 | 67 | const unsigned long interval = 5000; // Send message every 5 seconds 68 | 69 | // WebSocket Event Callback 70 | void onWsEvent(WSMessageType type, const uint8_t *payload, size_t len) 71 | { 72 | switch (type) 73 | { 74 | case WS_EVENT_CONNECTED: 75 | debug::print(STREAM, "WS Connected!\r\n\r\n"); 76 | break; 77 | case WS_EVENT_DISCONNECTED: 78 | debug::print(STREAM, "Warning: WS Disconnected!\r\n\r\n"); 79 | break; 80 | case WS_FRAME_TEXT: 81 | if (type == WS_FRAME_TEXT) 82 | { 83 | char *msg = (char *)malloc(len + 1); 84 | memcpy(msg, payload, len); 85 | msg[len] = '\0'; 86 | debug::print(STREAM, "Text message received: "); 87 | debug::printRaw(STREAM, msg); 88 | debug::printRaw(STREAM, "\r\n\r\n"); 89 | } 90 | else if (type == WS_FRAME_BINARY) 91 | { 92 | debug::print(STREAM, "Binary message received, Size: "); 93 | debug::printRaw(STREAM, String(len).c_str()); 94 | debug::printRaw(STREAM, "\r\n\r\n"); 95 | } 96 | 97 | break; 98 | } 99 | } 100 | 101 | void setup() 102 | { 103 | Serial.begin(BridgeRate); 104 | while (!Serial) 105 | ; 106 | 107 | // [CRITICAL FIX] Flush bootloader noise so the PC Python script 108 | // doesn't get confused by random bytes on startup. 109 | Serial.write(0x00); 110 | delay(500); 111 | 112 | // Sending Ping request to host; 113 | debug::initBlink(); 114 | while (!hostReady) 115 | { 116 | hostReady = ws.pingHost(500); 117 | if (!hostReady) 118 | { 119 | Serial.println("No response from host. Please make sure serial_bridge.py is running..."); 120 | debug::blink(10, 500); 121 | delay(2000); 122 | } 123 | } 124 | 125 | ws.stop(); 126 | 127 | // Skip SSL certificate verification 128 | ws.setInsecure(); 129 | // Set SSL Client RX/TX buffer sizest 130 | ws.setBufferSizes(2048, 1024); 131 | 132 | // Register the event callback 133 | ws.onEvent(onWsEvent); 134 | 135 | debug::print(STREAM, "Connecting to echo server...\r\n\r\n"); 136 | 137 | // Connect to the public echo server (SSL Enabled) 138 | ws.connect("echo.websocket.org", 443, "/", true); 139 | } 140 | 141 | void loop() 142 | { 143 | // WebSocket is event-driven, so we simply call loop() repeatedly 144 | ws.loop(); 145 | 146 | // Send Periodic Requests 147 | if (ms == 0 || millis() - ms > interval) 148 | { 149 | ms = millis(); 150 | debug::print(STREAM, "Sending message...\r\n\r\n"); 151 | ws.sendText("Hello from Arduino!"); 152 | } 153 | } -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/MQTT/MQTT.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * ================================================== 3 | * MQTT Example (for client to work with Device Host) 4 | * ================================================== 5 | * Runs on: Any Arduino device. 6 | * Host: Requires "Device_Host/Generic_Client/Host/Host.ino" running on 7 | * other Arduino devices that connected to this device via Serial port. 8 | * Purpose: Demonstrates how to use with Arduino Mqtt Client library. 9 | * 10 | * Macros explanation 11 | * 12 | * BridgeRate The bridge serial port baud rate. 13 | * Should be matched with host device serial baud rate. 14 | * Should not exceed 115200 for AVR 15 | * 16 | * BridgeSerial The serial port that is connected to host device serial port. 17 | * 18 | * BridgeSlot_0 The slot (channel or session) 0 which data will be transferred 19 | * This corresponds to the SSL client assigned on slot 0 of the host device. 20 | * See Host.ino example. 21 | * 22 | * ENABLE_LOCAL_DEBUG The default to allow local debug to show on Serial port. 23 | * This macro can be defined only when the Bridge serial port is not a USB Serial port. 24 | * 25 | * HOST_RELAY_DEBUG The macro that should be defined when working with PC host to relay the debug info. 26 | * This macro should be commented out or undefined in this example (debug info is printed locally). 27 | * 28 | * STREAM The sink object to print debug info which is one of the following clients. 29 | * Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 30 | * 31 | * CLIENT The client object e.g. SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 32 | * 33 | * BLINK_LED_PIN The GPIO that is connected to LED which is used for pinging error display. 34 | */ 35 | 36 | #define ENABLE_LOCAL_DEBUG 37 | #define BLINK_LED_PIN -1 38 | 39 | #include 40 | #include 41 | #include "debug.h" 42 | 43 | // This ibrary is required for this example 44 | #include 45 | 46 | #define BridgeSlot_0 0 47 | #define BridgeRate 115200 // Change this to match with the host serial baud rate. 48 | #define BridgeSerial Serial2 // Change this to match your hardware. 49 | 50 | SerialTCPClient client(BridgeSerial, BridgeSlot_0); 51 | MqttClient mqtt(client); 52 | 53 | #if defined(HOST_RELAY_DEBUG) 54 | #define STREAM client 55 | #define CLIENT client 56 | #else 57 | #define STREAM Serial 58 | #define CLIENT client 59 | #endif 60 | 61 | unsigned long ms = 0; 62 | bool hostReady = false; 63 | 64 | const char broker[] = "broker.hivemq.com"; 65 | const int port = 8883; 66 | const char topic[] = "arduino/serialtcp-test"; 67 | 68 | int count = 0; 69 | const long interval = 3000; 70 | 71 | void connectMqt() 72 | { 73 | debug::print(STREAM, "Attempting to connect to the MQTT broker over ssl: "); 74 | debug::print(STREAM, broker, false, false); 75 | debug::printNewLine(STREAM); 76 | 77 | // This will set SSL I/O buffer (if SSL client on host device is supported) 78 | client.setBufferSizes(2048, 1024); 79 | 80 | // Set this to skip SSL certificate verification on SSL client assigned to slot 0 in host device. 81 | client.setInsecure(); 82 | 83 | if (!mqtt.connect(broker, port)) 84 | { 85 | debug::print(STREAM, "MQTT connection failed! Error code = "); 86 | debug::printRaw(STREAM, String(mqtt.connectError()).c_str()); 87 | debug::printNewLine(STREAM); 88 | return; 89 | } 90 | 91 | debug::print(STREAM, "You're connected to the MQTT broker!\r\n"); 92 | debug::print(STREAM, "Subscribing to topic: "); 93 | debug::printRaw(STREAM, topic); 94 | debug::printNewLine(STREAM); 95 | 96 | // subscribe to a topic 97 | mqtt.subscribe(topic); 98 | 99 | // topics can be unsubscribed using: 100 | // mqtt.unsubscribe(topic); 101 | 102 | debug::print(STREAM, "Waiting for messages on topic: "); 103 | debug::printRaw(STREAM, topic); 104 | debug::printNewLine(STREAM); 105 | } 106 | 107 | void setup() 108 | { 109 | Serial.begin(115200); 110 | delay(1000); 111 | 112 | BridgeSerial.begin(BridgeRate); 113 | client.setLocalDebugLevel(1); // Enable debug prints 114 | 115 | // Sending Ping request to host; 116 | debug::initBlink(); 117 | while (!hostReady) 118 | { 119 | hostReady = client.pingHost(500); 120 | if (!hostReady) 121 | { 122 | Serial.println("No response from host. Check serial port, baud rate and host device..."); 123 | debug::blink(10, 500); 124 | delay(2000); 125 | } 126 | } 127 | 128 | connectMqt(); 129 | } 130 | 131 | void loop() 132 | { 133 | if (!hostReady) 134 | return; 135 | 136 | if (!mqtt.connected()) 137 | { 138 | connectMqt(); 139 | delay(2000); 140 | return; 141 | } 142 | 143 | mqtt.poll(); 144 | 145 | int messageSize = mqtt.parseMessage(); 146 | if (messageSize) 147 | { 148 | debug::print(STREAM, "Message Received: "); 149 | while (mqtt.available()) 150 | { 151 | debug::printRaw(STREAM, String(mqtt.read()).c_str()); 152 | } 153 | 154 | debug::printNewLine(STREAM); 155 | } 156 | 157 | if (millis() - ms > interval) 158 | { 159 | ms = millis(); 160 | mqtt.beginMessage(topic); 161 | mqtt.print(count); 162 | mqtt.endMessage(); 163 | count++; 164 | } 165 | } -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/NeoHWSerial/NeoHWSerial.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * ================================================================ 3 | * NeoHWSerial Client Example (for client to work with Device Host) 4 | * ================================================================ 5 | * Runs on: Any Arduino AVR device e.g. mega. 6 | * Host: Requires "Device_Host/Generic_Client/Host/Host.ino" running on 7 | * other Arduino devices that connected to this device via Serial port. 8 | * Purpose: Demonstrates how to use NeoHWSerial and InterruptStream wrapper. 9 | * Macros explanation 10 | * 11 | * BridgeRate The bridge serial port baud rate. 12 | * Should be matched with host device serial baud rate. 13 | * Should not exceed 115200 for AVR 14 | * 15 | * BridgeSerial The serial port that is connected to host device serial port. 16 | * 17 | * BridgeSlot_0 The slot (channel or session) 0 which data will be transferred 18 | * This corresponds to the SSL client assigned on slot 0 of the host device. 19 | * See Host.ino example. 20 | * 21 | * ENABLE_LOCAL_DEBUG The macro to allow local debug to show on Serial port. 22 | * This macro can be defined only when the Bridge serial port is not a USB Serial port. 23 | * 24 | * HOST_RELAY_DEBUG The macro that should be defined when working with PC host to relay the debug info. 25 | * This macro should be commented out or undefined in this example (debug info is printed locally). 26 | * 27 | * STREAM The sink object to print debug info which is one of the following clients. 28 | * Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 29 | * 30 | * CLIENT The client object e.g. SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 31 | * 32 | * BLINK_LED_PIN The GPIO that is connected to LED which is used for pinging error display. 33 | */ 34 | 35 | #define ENABLE_LOCAL_DEBUG 36 | #define BLINK_LED_PIN -1 37 | 38 | #include 39 | #include 40 | #include 41 | #include "debug.h" 42 | #include "InterruptStream.h" // The wrapper class we created earlier 43 | 44 | #define BridgeSlot_0 0 45 | #define BridgeRate 115200 // Change this to match with the host serial baud rate. 46 | // Mega Pin 18 (TX1) -> Host device RX (may use Voltage Divider!) 47 | // Mega Pin 19 (RX1) <- Host device TX (may use Voltage Divider!) 48 | #define BridgeSerial NeoSerial1 49 | 50 | // Initialize the Wrapper 51 | InterruptStream bridgeStream(BridgeSerial); 52 | 53 | // Initialize the Client using the Wrapper 54 | // We pass 'bridgeStream' instead of NeoSerial1 55 | SerialTCPClient client(bridgeStream, 0); 56 | 57 | #if defined(HOST_RELAY_DEBUG) 58 | #define STREAM client 59 | #define CLIENT client 60 | #else 61 | #define STREAM NeoSerial 62 | #define CLIENT client 63 | #endif 64 | 65 | bool hostReady = false; 66 | unsigned long ms = 0; 67 | 68 | // Interrupt service routime for receiving data from Host 69 | static void handleRxChar(uint8_t c) 70 | { 71 | // Push data from the MKR immediately into our buffer 72 | bridgeStream.push(c); 73 | } 74 | 75 | void setup() 76 | { 77 | // Debug Serial (USB to PC) 78 | NeoSerial.begin(115200); 79 | while (!NeoSerial) 80 | ; 81 | 82 | BridgeSerial.begin(BridgeRate); 83 | 84 | // Attach the interrupt for high-performance receiving 85 | BridgeSerial.attachInterrupt(handleRxChar); 86 | 87 | client.setLocalDebugLevel(1); // Enable debug prints 88 | 89 | // Sending Ping request to host; 90 | debug::initBlink(); 91 | while (!hostReady) 92 | { 93 | hostReady = client.pingHost(500); 94 | if (!hostReady) 95 | { 96 | Serial.println("No response from host. Check serial port, baud rate and host device..."); 97 | debug::blink(10, 500); 98 | delay(2000); 99 | } 100 | } 101 | } 102 | 103 | void loop() 104 | { 105 | if (hostReady && (ms == 0 || millis() - ms > 10000)) 106 | { 107 | ms = millis(); 108 | 109 | client.setBufferSizes(2048, 1024); 110 | client.setInsecure(); 111 | 112 | debug::print(STREAM, "Connecting to server...\r\n"); 113 | 114 | if (client.connect("httpbin.org", 443)) 115 | { 116 | debug::print(STREAM, "Server connected, sending request...\r\n"); 117 | 118 | client.println("GET /get HTTP/1.1"); 119 | client.println("Host: httpbin.org"); 120 | client.println("Connection: close"); 121 | client.println(); 122 | 123 | debug::print(STREAM, "Waiting for response...\r\n"); 124 | 125 | char buffer[128]; 126 | int ret = 0, totalRead = 0; 127 | char endToken = '\n'; // start by reading lines 128 | do 129 | { 130 | ret = debug::readResonse(CLIENT, STREAM, buffer, 128, totalRead, endToken); 131 | 132 | if (endToken == '\n' && strcmp(buffer, "\r\n") == 0) 133 | { 134 | // Headers done 135 | // read all remaining data without line endings 136 | endToken = '\0'; 137 | } 138 | } while (ret > 0); 139 | 140 | debug::printNewLine(STREAM); 141 | debug::print(STREAM, ret >= 0 ? "Response complete.\r\n" : (ret < -1 ? "Error: Response timeout.\r\n" : "Error: Socket closed.\r\n")); 142 | client.stop(); 143 | } 144 | else 145 | { 146 | debug::print(STREAM, "Unable to connect to server\r\n"); 147 | } 148 | } 149 | } -------------------------------------------------------------------------------- /examples/PC_Host/Readme.md: -------------------------------------------------------------------------------- 1 | # Serial Network Bridge (PC Host python script) 2 | 3 | This Python script acts as a network bridge for your Arduino device. It listens to the serial port and proxies TCP, UDP, and WebSocket connections from the Arduino to the PC's internet connection. 4 | 5 | ## 📋 Prerequisites 6 | 7 | * **Python 3.7 or newer** installed on your system. 8 | * An Arduino board running the `SerialTCPClient` (or `SerialNetworkBridge`) library. 9 | 10 | --- 11 | 12 | ## 📦 Installation 13 | 14 | You can install the required dependencies automatically using the provided scripts, or manually via the terminal. 15 | 16 | ### Option A: Automatic Installation (Recommended) 17 | 18 | **🪟 Windows:** 19 | Double-click **`install_libs.bat`**. 20 | * This script will automatically request **Administrator privileges**. 21 | * It upgrades `pip` and installs `pyserial`, `cobs`, `websocket-client`, `colorama`, `pywifi`, `flask`, and `comtypes`. 22 | 23 | **🐧 Linux / Raspberry Pi:** 24 | Open a terminal in this folder and run: 25 | ```bash 26 | chmod +x install_libs.sh 27 | ./install_libs.sh 28 | ``` 29 | * This script will prompt for your `sudo` password to install dependencies globally. 30 | 31 | ### Option B: Manual Installation 32 | 33 | It is recommended to use a virtual environment to keep dependencies isolated, though you can install them globally if preferred. 34 | 35 | **1. Create a Virtual Environment (Optional)** 36 | ```powershell 37 | # Windows 38 | python -m venv venv 39 | .\venv\Scripts\activate 40 | 41 | # Linux / Mac 42 | python3 -m venv venv 43 | source venv/bin/activate 44 | ``` 45 | 46 | **2. Install Dependencies** 47 | ```bash 48 | pip install pyserial cobs websocket-client colorama pywifi flask comtypes 49 | ``` 50 | 51 | --- 52 | 53 | ## ⚙️ Configuration 54 | 55 | ### 1. Python Script Setup 56 | 57 | Open `serial_bridge.py` in a text editor and update the constants at the top: 58 | 59 | ```python 60 | SERIAL_PORT = 'COM3' # Windows Example 61 | # SERIAL_PORT = '/dev/ttyUSB0' # Linux/RPi Example 62 | 63 | BAUD_RATE = 115200 # Must match your Arduino sketch! 64 | ``` 65 | 66 | ### 2. Arduino Sketch Setup (CRITICAL) 67 | 68 | When connecting directly to a PC via USB, you **must** follow these two rules in your Arduino sketch: 69 | 70 | 1. **Use `Serial`**: Pass the main `Serial` object to the client constructor. 71 | 2. **Disable System Debug**: You **MUST** remove or comment out `#define ENABLE_LOCAL_DEBUG`. If system debug is enabled, text logs will mix with the binary data, causing CRC errors and connection failure. You can relay debug information to the host terminal by defining `HOST_RELAY_DEBUG` and call `debug::prnt`, `debug::printRaw`, `debug::printNewLinr` that are included in `debug.h` in all client examples. 72 | 73 | **Example Sketch:** 74 | 75 | ```cpp 76 | // 1. DISABLE DEBUG (Comment this line out!) 77 | // #define ENABLE_LOCAL_DEBUG 78 | 79 | #include 80 | 81 | // 2. Relay the debug message to the Host PC/device. 82 | #define HOST_RELAY_DEBUG 83 | #include "debug.h" 84 | 85 | // 3. Use 'Serial' (The USB connection) 86 | SerialTCPClient client(Serial, 0); 87 | 88 | void setup() { 89 | // 4. Start Serial at the SAME baud rate as your Python script 90 | Serial.begin(115200); 91 | 92 | // Wait for Serial to be ready (important for native USB boards like Leonardo/Micro) 93 | while (!Serial); 94 | 95 | debug::print(client /* Stream class object */, "This is the debug message\r\n"); 96 | 97 | // Note: Do NOT use Serial.println() for logs! 98 | // It will break the bridge connection. 99 | } 100 | 101 | void loop() { 102 | // Your network logic here... 103 | } 104 | ``` 105 | 106 | --- 107 | 108 | ## 🚀 How to Run 109 | 110 | ### Option A: Quick Start (Scripts) 111 | 112 | **🪟 Windows:** 113 | Double-click **`run.bat`**. 114 | * This will launch the Python bridge with Administrator privileges (required for some serial port access). 115 | 116 | **🐧 Linux / Raspberry Pi:** 117 | Open a terminal in this folder and run: 118 | ```bash 119 | chmod +x run.sh 120 | ./run.sh 121 | ``` 122 | * This launches the script using `python3`. 123 | 124 | ### Option B: Manual Run 125 | 126 | **🪟 Windows** 127 | 1. Connect your Arduino via USB. 128 | 2. Find your COM port in **Device Manager**. 129 | 3. Update `SERIAL_PORT` in `serial_bridge.py`. 130 | 4. Run the script: 131 | ```powershell 132 | python serial_bridge.py 133 | ``` 134 | 135 | **🐧 Linux / Raspberry Pi** 136 | 1. Connect your Arduino. 137 | 2. Find the port name: `ls /dev/ttyUSB*` or `ls /dev/ttyACM*`. 138 | 3. Update `SERIAL_PORT` in `serial_bridge.py`. 139 | 4. **Permission Setup (One-time only):** 140 | If you get a "Permission denied" error, add your user to the dialout group: 141 | ```bash 142 | sudo usermod -a -G dialout $USER 143 | ``` 144 | *Log out and back in for this to take effect.* 145 | 5. Run the script: 146 | ```bash 147 | python3 serial_bridge.py 148 | ``` 149 | 150 | --- 151 | 152 | ## ❓ Troubleshooting 153 | 154 | **`CRC Mismatch` / `COBS Decode Error`** 155 | * **Cause 1:** You forgot to comment out `#define ENABLE_LOCAL_DEBUG` in the Arduino sketch. The PC is receiving text logs instead of data packets. 156 | * **Cause 2:** The Baud Rate in Python does not match `Serial.begin(...)` in the sketch. 157 | * **Fix:** Disable debug and match the baud rates. 158 | 159 | **`Permission denied: '/dev/ttyUSB0'`** 160 | * This happens on Linux/Pi if your user isn't in the `dialout` group. 161 | * **Fix:** Use the `install_libs.sh` script or run `sudo chmod 666 /dev/ttyUSB0` (temporary fix). 162 | 163 | **`SerialException: could not open port`** 164 | * The port name is wrong, or the port is already open in another program (like the Arduino Serial Monitor). 165 | * **Fix:** Close the Arduino Serial Monitor and double-check the port name. -------------------------------------------------------------------------------- /examples/Device_Host/Async_Client/AsyncTCP_Client/AsyncTCP_Client.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================= 3 | * AsyncTCP Client Example (for client to work with Device Host) 4 | * ============================================================= 5 | * Runs on: Any Arduino device (Client). 6 | * Host: Requires "Device_Host/Async_Client/Host/Host.ino" running on ESP32 7 | * Purpose: Demonstrates a AsyncTCP client usage. 8 | * 9 | * Macros explanation 10 | * 11 | * BridgeRate The bridge serial port baud rate. 12 | * Should be matched with host device serial baud rate. 13 | * Should not exceed 115200 for AVR 14 | * 15 | * BridgeSerial The serial port that is connected to host device serial port. 16 | * 17 | * BridgeSlot_0 The slot (channel or session) 0 which data will be transferred 18 | * This corresponds to the SSL client assigned on slot 0 of the host device. 19 | * See Host.ino example. 20 | * 21 | * ENABLE_LOCAL_DEBUG The macro to allow local debug to show on Serial port. 22 | * This macro can be defined only when the Bridge serial port is not a USB Serial port. 23 | * 24 | * HOST_RELAY_DEBUG The macro that should be defined when working with PC host to relay the debug info. 25 | * This macro should be commented out or undefined in this example (debug info is printed locally). 26 | * 27 | * STREAM The sink object to print debug info which is one of the following clients. 28 | * Serial, SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 29 | * 30 | * CLIENT The client object e.g. SerialTCPClient, SerialUDPClient, SerialWebsocketClient, SerialHostManager 31 | * 32 | * BLINK_LED_PIN The GPIO that is connected to LED which is used for pinging error display. 33 | */ 34 | 35 | #define ENABLE_LOCAL_DEBUG 36 | #define BLINK_LED_PIN -1 37 | 38 | #define BridgeSlot_0 0 39 | #define BridgeRate 115200 // Change this to match with the host serial baud rate. 40 | #define BridgeSerial Serial2 // Change this to match your hardware. 41 | 42 | #include 43 | #include 44 | #include "debug.h" 45 | 46 | SerialAsyncTCPClient asyncClient(BridgeSerial, BridgeSlot_0); 47 | 48 | #if defined(HOST_RELAY_DEBUG) 49 | #define STREAM client 50 | #define CLIENT client 51 | #else 52 | #define STREAM Serial 53 | #define CLIENT client 54 | #endif 55 | 56 | // State tracking 57 | bool hostReady = false; 58 | bool requestSent = false; 59 | 60 | void onConnect(void *arg, SerialAsyncTCPClient *c) 61 | { 62 | debug::print(STREAM, "Event: Connected to Server!\r\n"); 63 | 64 | debug::print(STREAM, "Sending GET request...\r\n"); 65 | 66 | // [FIX] Combine payload into one string to prevent packet dropping 67 | String req = "GET /get HTTP/1.1\r\n"; 68 | req += "Host: httpbin.org\r\n"; 69 | req += "User-Agent: SerialNetworkBridge/2.0\r\n"; 70 | req += "Connection: close\r\n\r\n"; 71 | 72 | c->write(req.c_str()); 73 | 74 | requestSent = true; 75 | } 76 | 77 | void onData(void *arg, SerialAsyncTCPClient *c, void *data, size_t len) 78 | { 79 | debug::print(STREAM, "Event: Data Received ("); 80 | debug::printRaw(STREAM, String(len).c_str()); 81 | debug::printRaw(STREAM, " bytes)\r\n"); 82 | 83 | char *str = (char *)malloc(len + 1); 84 | if (str) 85 | { 86 | memcpy(str, data, len); 87 | str[len] = '\0'; 88 | debug::printRaw(STREAM, str); 89 | debug::printNewLine(STREAM); 90 | free(str); 91 | } 92 | } 93 | 94 | void onDisconnect(void *arg, SerialAsyncTCPClient *c) 95 | { 96 | debug::print(STREAM, "Event: Disconnected.\r\n"); 97 | requestSent = false; 98 | } 99 | 100 | void onError(void *arg, SerialAsyncTCPClient *c, int8_t error) 101 | { 102 | debug::print(STREAM, "Event: Error Code: "); 103 | debug::printRaw(STREAM, String(error).c_str()); 104 | debug::printNewLine(STREAM); 105 | } 106 | 107 | void onTimeout(void *arg, SerialAsyncTCPClient *c, uint32_t time) 108 | { 109 | debug::print(STREAM, "Event: Ack Timeout!\r\n"); 110 | c->close(); 111 | } 112 | 113 | void setup() 114 | { 115 | 116 | Serial.begin(115200); 117 | 118 | delay(2000); 119 | 120 | BridgeSerial.begin(BridgeRate); 121 | 122 | asyncClient.setLocalDebugLevel(1); 123 | 124 | debug::print(STREAM, "Pinging Host...\r\n"); 125 | 126 | // Sending Ping request to host; 127 | debug::initBlink(); 128 | while (!hostReady) 129 | { 130 | hostReady = asyncClient.pingHost(500); 131 | if (!hostReady) 132 | { 133 | Serial.println("No response from host. Check serial port, baud rate and host device3..."); 134 | debug::blink(10, 500); 135 | delay(2000); 136 | } 137 | } 138 | 139 | debug::print(STREAM, "Host is ready\r\n"); 140 | 141 | asyncClient.onConnect(onConnect); 142 | asyncClient.onData(onData); 143 | asyncClient.onDisconnect(onDisconnect); 144 | asyncClient.onError(onError); 145 | asyncClient.onTimeout(onTimeout); 146 | 147 | debug::print(STREAM, "Connecting to httpbin.org...\r\n"); 148 | 149 | if (!asyncClient.connect("httpbin.org", 80)) 150 | { 151 | debug::print(STREAM, "Failed to send connect command.\r\n"); 152 | } 153 | } 154 | 155 | void loop() 156 | { 157 | 158 | asyncClient.loop(); 159 | 160 | static unsigned long lastCheck = 0; 161 | if (millis() - lastCheck > 10000) 162 | { 163 | lastCheck = millis(); 164 | 165 | // Only warn if we expected to be connected 166 | if (requestSent && !asyncClient.connected()) 167 | { 168 | debug::print(STREAM, "Server is not connected.\r\n"); 169 | } 170 | } 171 | } -------------------------------------------------------------------------------- /examples/Device_Host/Generic_Client/Host/Host.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * =============================================== 3 | * Device Host Serial Bridge (with NVS Storage) 4 | * =============================================== 5 | * Runs on: The host device (e.g., ESP8266, ESP32, Raspberry Pi Pico W). 6 | * Purpose: Operating the neccessary tasks on the host. 7 | * 8 | * Macros explanation 9 | * 10 | * MAX_CLIENT_SLOTS Maximum slots (channel or session) 11 | * 12 | * ENABLE_LOCAL_DEBUG The macro to allow local debug to show on Serial port. 13 | * 14 | * USE_UDP The UDP client will be assigned to the host 15 | * 16 | * USE_WEBSOCKET The Websocket client will be assigned to the host 17 | * 18 | * USE_ESP_SSLCLIENT Use ESP_SSLClient for SSL client 19 | * 20 | * USE_LITTLEFS Use LittleFS for local file storage filesystem 21 | * 22 | * WIFI_SSID The default WiFi AP SSID 23 | * 24 | * WIFI_PASSWORD The default WiFi AP Password 25 | * 26 | * BridgeRate The bridge serial port baud rate. 27 | * Should be matched with client device serial baud rate. 28 | * Should not exceed 115200 for AVR 29 | * 30 | * BridgeSerial The serial port that is connected to the client device serial port. 31 | * 32 | * Predefined macros for network class (Optional) 33 | * 34 | * __ssl_client SSL client class that is defined in HostNetwork.h 35 | * WiFiClientSecure or WiFiSSLClient in WiFi capable device. 36 | * ESP_SSLClient for generic or non-WiFi capable device. 37 | * 38 | * __udp_client UDP client class that is defined in HostNetwork.h 39 | * WiFiUDP in WiFi capable device. 40 | * EthernetUDP for non-WiFi capable device. 41 | * 42 | * __ssl_set_network_class Defined in HostNetwork.h where ESP_SSLClient is used. 43 | * If this macro is defined, it means the network client (WiFi/Ethernet) 44 | * is required to use with SSL client object. 45 | * 46 | * __network_class Defined in HostNetwork.h for network client class. 47 | * WiFiClient for WiFi capable device. 48 | * EthernetClient for non-WiFi capable device. 49 | * 50 | */ 51 | 52 | #define MAX_CLIENT_SLOTS 4 53 | #define ENABLE_LOCAL_DEBUG 54 | #define USE_UDP 55 | #define USE_WEBSOCKET 56 | #define WIFI_SSID "ssid" 57 | #define WIFI_PASSWORD "password" 58 | #define BridgeRate 115200 59 | #define BridgeSerial Serial2 60 | 61 | // Optional for external WiFi and SSL client libraries 62 | // #include 63 | // #include 64 | 65 | #include "Filesystem.h" 66 | 67 | #include 68 | 69 | // https://github.com/Links2004/arduinoWebSockets 70 | // This websocket library can't be used with Teensy and Arduino NANO RP2040 71 | // due to compilation error 72 | #include 73 | 74 | SerialNetworkHost host(BridgeSerial); 75 | 76 | 77 | #if defined(__ssl_client) 78 | __ssl_client ssl_client; 79 | #endif 80 | 81 | 82 | #if defined(__udp_client) 83 | __udp_client udp_client; 84 | #endif 85 | 86 | 87 | #if defined(__ssl_set_network_class) && defined(__network_class) 88 | __network_class network_client; 89 | #endif 90 | 91 | #if defined(USE_WEBSOCKET) 92 | WebSocketsClient ws_client; 93 | #endif 94 | 95 | #include "Callback.h" 96 | 97 | void setup() 98 | { 99 | // Start local Serial for debugging 100 | Serial.begin(115200); 101 | delay(1000); 102 | 103 | BridgeSerial.begin(BridgeRate); 104 | 105 | Serial.println("\n[Host] SerialTCP Host Starting..."); 106 | 107 | // Load Credentials from Storage 108 | loadWiFi(WIFI_SSID, WIFI_PASSWORD); 109 | 110 | // Handles WiFi credentials setup 111 | host.setSetWiFiCallback(handle_set_wifi); 112 | 113 | // Handles WiFi connection 114 | host.setConnectNetworkCallback(handle_connect_network); 115 | 116 | // Handles host reboot 117 | host.setRebootCallback(handle_reboot); 118 | 119 | // Callbacks pecific to SSL client in some platforms 120 | 121 | // Handles client side function setCACert() in ESP32's WiFiClientSecure and ESP_SSLClient, 122 | // setTrustAnchors in ESP8266/RPi Pico W's WiFiClientSecure. 123 | host.setSetSSLCertificateCallback(handle_certificate_setup); 124 | 125 | // Handles client side function setBufferSizes() in ESP8266/RPi Pico W's WiFiClientSecure and ESP_SSLClient. 126 | host.setSetBufferSizeCallback(handle_set_buffer_size); 127 | 128 | // Handles the client side function isSecure() in ESP32/ESP8266/RPi Pico W's WiFiClientSecure and ESP_SSLClient. 129 | host.setGetFlagCallback(handle_get_flag); 130 | 131 | // Handles the client side functions setInsecure() in ESP32/ESP8266/RPi Pico W's WiFiClientSecure and ESP_SSLClient 132 | // setPlainStart() in ESP32/ESP8266/RPi Pico W WiFiClientSecure and ESP_SSLClient, 133 | // enableSSL() in ESP_SSLClient. 134 | host.setSetFlagCallback(handle_set_flag); 135 | 136 | // Handles client side function StartTLS() in ESP32' WiFiClientSecure and connectSSL() in ESP_SSLClient. 137 | host.setStartTLSCallback(0 /* slot */, handle_start_tls); 138 | 139 | #if defined(__ssl_set_network_class) && defined(__network_class) 140 | ssl_client.setClient(&network_client); 141 | #endif 142 | 143 | // Assign clients for each slot 144 | // In this example, slot 0 is for TCP client, slot 1 is for UDP and slot 2 is for websocket. 145 | 146 | host.setTCPClient(&ssl_client, 0 /* slot */); 147 | 148 | #if defined(__udp_client) 149 | host.setUDPClient(&udp_client, 1 /* slot */); 150 | #endif 151 | 152 | #if defined(USE_WEBSOCKET) 153 | host.setWebSocketClient(&ws_client, 2 /* slot */); 154 | #endif 155 | 156 | host.setLocalDebugLevel(1); 157 | 158 | // Connect to WiFi 159 | handle_connect_network(); 160 | 161 | // Notify the client that host is rebooted/ready. 162 | // This resets the client's internal state for a fresh session. 163 | host.notifyBoot(); 164 | 165 | Serial.println("Device Host Serial Bridge started."); 166 | } 167 | 168 | void loop() 169 | { 170 | // Reqouirements for Host operation 171 | host.loop(); 172 | } --------------------------------------------------------------------------------