Created
March 3, 2019 22:23
-
-
Save ShawnHymel/3d124f79aee95fb274876f491a91dcf4 to your computer and use it in GitHub Desktop.
ESP32 WebSocket Host
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <WiFi.h> | |
#include <SPIFFS.h> | |
#include <ESPAsyncWebServer.h> | |
#include <WebSocketsServer.h> | |
// Constants | |
const char *ssid = "ESP32-AP"; | |
const char *password = "LetMeInPlz"; | |
const char *msg_toggle_led = "toggleLED"; | |
const char *msg_get_led = "getLEDState"; | |
const int dns_port = 53; | |
const int http_port = 80; | |
const int ws_port = 1337; | |
const int led_pin = 15; | |
// Globals | |
AsyncWebServer server(80); | |
WebSocketsServer webSocket = WebSocketsServer(1337); | |
char msg_buf[10]; | |
int led_state = 0; | |
/*********************************************************** | |
* Functions | |
*/ | |
// Callback: receiving any WebSocket message | |
void onWebSocketEvent(uint8_t client_num, | |
WStype_t type, | |
uint8_t * payload, | |
size_t length) { | |
// Figure out the type of WebSocket event | |
switch(type) { | |
// Client has disconnected | |
case WStype_DISCONNECTED: | |
Serial.printf("[%u] Disconnected!\n", client_num); | |
break; | |
// New client has connected | |
case WStype_CONNECTED: | |
{ | |
IPAddress ip = webSocket.remoteIP(client_num); | |
Serial.printf("[%u] Connection from ", client_num); | |
Serial.println(ip.toString()); | |
} | |
break; | |
// Handle text messages from client | |
case WStype_TEXT: | |
// Print out raw message | |
Serial.printf("[%u] Received text: %s\n", client_num, payload); | |
// Toggle LED | |
if ( strcmp((char *)payload, "toggleLED") == 0 ) { | |
led_state = led_state ? 0 : 1; | |
Serial.printf("Toggling LED to %u\n", led_state); | |
digitalWrite(led_pin, led_state); | |
// Report the state of the LED | |
} else if ( strcmp((char *)payload, "getLEDState") == 0 ) { | |
sprintf(msg_buf, "%d", led_state); | |
Serial.printf("Sending to [%u]: %s\n", client_num, msg_buf); | |
webSocket.sendTXT(client_num, msg_buf); | |
// Message not recognized | |
} else { | |
Serial.println("[%u] Message not recognized"); | |
} | |
break; | |
// For everything else: do nothing | |
case WStype_BIN: | |
case WStype_ERROR: | |
case WStype_FRAGMENT_TEXT_START: | |
case WStype_FRAGMENT_BIN_START: | |
case WStype_FRAGMENT: | |
case WStype_FRAGMENT_FIN: | |
default: | |
break; | |
} | |
} | |
// Callback: send homepage | |
void onIndexRequest(AsyncWebServerRequest *request) { | |
IPAddress remote_ip = request->client()->remoteIP(); | |
Serial.println("[" + remote_ip.toString() + | |
"] HTTP GET request of " + request->url()); | |
request->send(SPIFFS, "/index.html", "text/html"); | |
} | |
// Callback: send style sheet | |
void onCSSRequest(AsyncWebServerRequest *request) { | |
IPAddress remote_ip = request->client()->remoteIP(); | |
Serial.println("[" + remote_ip.toString() + | |
"] HTTP GET request of " + request->url()); | |
request->send(SPIFFS, "/style.css", "text/css"); | |
} | |
// Callback: send 404 if requested file does not exist | |
void onPageNotFound(AsyncWebServerRequest *request) { | |
IPAddress remote_ip = request->client()->remoteIP(); | |
Serial.println("[" + remote_ip.toString() + | |
"] HTTP GET request of " + request->url()); | |
request->send(404, "text/plain", "Not found"); | |
} | |
/*********************************************************** | |
* Main | |
*/ | |
void setup(){ | |
// Init LED and turn off | |
pinMode(led_pin, OUTPUT); | |
digitalWrite(led_pin, LOW); | |
// Start Serial port | |
Serial.begin(115200); | |
// Make sure we can read the file system | |
if( !SPIFFS.begin()){ | |
Serial.println("Error mounting SPIFFS"); | |
while(1); | |
} | |
// Start access point | |
WiFi.softAP(ssid, password); | |
// Print our IP address | |
Serial.println(); | |
Serial.println("AP running"); | |
Serial.print("My IP address: "); | |
Serial.println(WiFi.softAPIP()); | |
// On HTTP request for root, provide index.html file | |
server.on("/", HTTP_GET, onIndexRequest); | |
// On HTTP request for style sheet, provide style.css | |
server.on("/style.css", HTTP_GET, onCSSRequest); | |
// Handle requests for pages that do not exist | |
server.onNotFound(onPageNotFound); | |
// Start web server | |
server.begin(); | |
// Start WebSocket server and assign callback | |
webSocket.begin(); | |
webSocket.onEvent(onWebSocketEvent); | |
} | |
void loop() { | |
// Look for and handle WebSocket data | |
webSocket.loop(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8" /> | |
<title>WebSocket Test</title> | |
<script language="javascript" type="text/javascript"> | |
var url = "ws://192.168.4.1:1337/"; | |
var output; | |
var button; | |
var canvas; | |
var context; | |
// This is called when the page finishes loading | |
function init() { | |
// Assign page elements to variables | |
button = document.getElementById("toggleButton"); | |
output = document.getElementById("output"); | |
canvas = document.getElementById("led"); | |
// Draw circle in canvas | |
context = canvas.getContext("2d"); | |
context.arc(25, 25, 15, 0, Math.PI * 2, false); | |
context.lineWidth = 3; | |
context.strokeStyle = "black"; | |
context.stroke(); | |
context.fillStyle = "black"; | |
context.fill(); | |
// Connect to WebSocket server | |
wsConnect(url); | |
} | |
// Call this to connect to the WebSocket server | |
function wsConnect(url) { | |
// Connect to WebSocket server | |
websocket = new WebSocket(url); | |
// Assign callbacks | |
websocket.onopen = function(evt) { onOpen(evt) }; | |
websocket.onclose = function(evt) { onClose(evt) }; | |
websocket.onmessage = function(evt) { onMessage(evt) }; | |
websocket.onerror = function(evt) { onError(evt) }; | |
} | |
// Called when a WebSocket connection is established with the server | |
function onOpen(evt) { | |
// Log connection state | |
console.log("Connected"); | |
// Enable button | |
button.disabled = false; | |
// Get the current state of the LED | |
doSend("getLEDState"); | |
} | |
// Called when the WebSocket connection is closed | |
function onClose(evt) { | |
// Log disconnection state | |
console.log("Disconnected"); | |
// Disable button | |
button.disabled = true; | |
// Try to reconnect after a few seconds | |
setTimeout(function() { wsConnect(url) }, 2000); | |
} | |
// Called when a message is received from the server | |
function onMessage(evt) { | |
// Print out our received message | |
console.log("Received: " + evt.data); | |
// Update circle graphic with LED state | |
switch(evt.data) { | |
case "0": | |
console.log("LED is off"); | |
context.fillStyle = "black"; | |
context.fill(); | |
break; | |
case "1": | |
console.log("LED is on"); | |
context.fillStyle = "red"; | |
context.fill(); | |
break; | |
default: | |
break; | |
} | |
} | |
// Called when a WebSocket error occurs | |
function onError(evt) { | |
console.log("ERROR: " + evt.data); | |
} | |
// Sends a message to the server (and prints it to the console) | |
function doSend(message) { | |
console.log("Sending: " + message); | |
websocket.send(message); | |
} | |
// Called whenever the HTML button is pressed | |
function onPress() { | |
doSend("toggleLED"); | |
doSend("getLEDState"); | |
} | |
// Call the init function as soon as the page loads | |
window.addEventListener("load", init, false); | |
</script> | |
<h2>LED Control</h2> | |
<table> | |
<tr> | |
<td><button id="toggleButton" onclick="onPress()" disabled>Toggle LED</button></td> | |
<td><canvas id="led" width="50" height="50"></canvas></td> | |
</tr> | |
</table> | |
<div id="output"></div> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment