316 lines
7.5 KiB
C++
316 lines
7.5 KiB
C++
/*********
|
|
Rui Santos
|
|
Complete project details at https://RandomNerdTutorials.com/esp32-websocket-server-arduino/
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
*********/
|
|
//Libraries
|
|
#include <SPI.h> //https://www.arduino.cc/en/reference/SPI
|
|
#include <MFRC522.h> //https://github.com/miguelbalboa/rfid
|
|
//Constants
|
|
#define SS_PIN 5
|
|
#define RST_PIN 0
|
|
//Parameters
|
|
const int ipaddress[4] = { 103, 97, 67, 25 };
|
|
//Variables
|
|
byte nuidPICC[4] = { 0, 0, 0, 0 };
|
|
MFRC522::MIFARE_Key key;
|
|
MFRC522 rfid = MFRC522(SS_PIN, RST_PIN);
|
|
|
|
// Import required libraries
|
|
#include <WiFi.h>
|
|
#include <AsyncTCP.h>
|
|
#include <ESPAsyncWebServer.h>
|
|
|
|
// Replace with your network credentials
|
|
const char *ssid = "Orcon-Wireless";
|
|
const char *password = "140313502555";
|
|
|
|
bool ledState = 0;
|
|
const int ledPin = 2;
|
|
|
|
// Create AsyncWebServer object on port 80
|
|
AsyncWebServer server(80);
|
|
AsyncWebSocket ws("/ws");
|
|
|
|
const char index_html[] PROGMEM = R"rawliteral(
|
|
<!DOCTYPE HTML><html>
|
|
<head>
|
|
<title>ESP Web Server</title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<link rel="icon" href="data:,">
|
|
<style>
|
|
html {
|
|
font-family: Arial, Helvetica, sans-serif;
|
|
text-align: center;
|
|
}
|
|
h1 {
|
|
font-size: 1.8rem;
|
|
color: white;
|
|
}
|
|
h2{
|
|
font-size: 1.5rem;
|
|
font-weight: bold;
|
|
color: #143642;
|
|
}
|
|
.topnav {
|
|
overflow: hidden;
|
|
background-color: #143642;
|
|
}
|
|
body {
|
|
margin: 0;
|
|
}
|
|
.content {
|
|
padding: 30px;
|
|
max-width: 600px;
|
|
margin: 0 auto;
|
|
}
|
|
.card {
|
|
background-color: #F8F7F9;;
|
|
box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);
|
|
padding-top:10px;
|
|
padding-bottom:20px;
|
|
}
|
|
.button {
|
|
padding: 15px 50px;
|
|
font-size: 24px;
|
|
text-align: center;
|
|
outline: none;
|
|
color: #fff;
|
|
background-color: #0f8b8d;
|
|
border: none;
|
|
border-radius: 5px;
|
|
-webkit-touch-callout: none;
|
|
-webkit-user-select: none;
|
|
-khtml-user-select: none;
|
|
-moz-user-select: none;
|
|
-ms-user-select: none;
|
|
user-select: none;
|
|
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
|
}
|
|
/*.button:hover {background-color: #0f8b8d}*/
|
|
.button:active {
|
|
background-color: #0f8b8d;
|
|
box-shadow: 2 2px #CDCDCD;
|
|
transform: translateY(2px);
|
|
}
|
|
.state {
|
|
font-size: 1.5rem;
|
|
color:#8c8c8c;
|
|
font-weight: bold;
|
|
}
|
|
</style>
|
|
<title>ESP Web Server</title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<link rel="icon" href="data:,">
|
|
</head>
|
|
<body>
|
|
<div class="topnav">
|
|
<h1>ESP WebSocket Server</h1>
|
|
</div>
|
|
<div class="content">
|
|
<div class="card">
|
|
<h2>Output - GPIO 2</h2>
|
|
<p class="state">state: <span id="state">%STATE%</span></p>
|
|
<p><button id="button" class="button">Toggle</button></p>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
var gateway = `ws://${window.location.hostname}/ws`;
|
|
var websocket;
|
|
window.addEventListener('load', onLoad);
|
|
function initWebSocket() {
|
|
console.log('Trying to open a WebSocket connection...');
|
|
websocket = new WebSocket(gateway);
|
|
websocket.onopen = onOpen;
|
|
websocket.onclose = onClose;
|
|
websocket.onmessage = onMessage; // <-- add this line
|
|
}
|
|
function onOpen(event) {
|
|
console.log('Connection opened');
|
|
}
|
|
function onClose(event) {
|
|
console.log('Connection closed');
|
|
setTimeout(initWebSocket, 2000);
|
|
}
|
|
function onMessage(event) {
|
|
console.log(event.data)
|
|
console.log("--")
|
|
console.log(consistentRandomNumber(42, 100))
|
|
var state;
|
|
if (event.data == "1"){
|
|
state = "ON";
|
|
}
|
|
else{
|
|
state = "OFF";
|
|
}
|
|
document.getElementById('state').innerHTML = state;
|
|
}
|
|
function consistentRandomNumber(inputNumber, max) {
|
|
const randomNumber = seededRandom(inputNumber);
|
|
return Math.floor(randomNumber * max) + 1;
|
|
}
|
|
function seededRandom(seed) {
|
|
seed = (seed * 16807) % 2147483647;
|
|
return (seed - 1) / 2147483646;
|
|
}
|
|
function onLoad(event) {
|
|
initWebSocket();
|
|
initButton();
|
|
}
|
|
function initButton() {
|
|
document.getElementById('button').addEventListener('click', toggle);
|
|
}
|
|
function toggle(){
|
|
websocket.send('toggle');
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|
|
)rawliteral";
|
|
|
|
void notifyClients() {
|
|
ws.textAll(String(ledState));
|
|
}
|
|
|
|
void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {
|
|
AwsFrameInfo *info = (AwsFrameInfo *)arg;
|
|
if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
|
|
data[len] = 0;
|
|
if (strcmp((char *)data, "toggle") == 0) {
|
|
ledState = !ledState;
|
|
notifyClients();
|
|
}
|
|
}
|
|
}
|
|
|
|
void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type,
|
|
void *arg, uint8_t *data, size_t len) {
|
|
switch (type) {
|
|
case WS_EVT_CONNECT:
|
|
Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
|
|
break;
|
|
case WS_EVT_DISCONNECT:
|
|
Serial.printf("WebSocket client #%u disconnected\n", client->id());
|
|
break;
|
|
case WS_EVT_DATA:
|
|
handleWebSocketMessage(arg, data, len);
|
|
break;
|
|
case WS_EVT_PONG:
|
|
case WS_EVT_ERROR:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void initWebSocket() {
|
|
ws.onEvent(onEvent);
|
|
server.addHandler(&ws);
|
|
}
|
|
|
|
String processor(const String &var) {
|
|
Serial.println(var);
|
|
if (var == "STATE") {
|
|
if (ledState) {
|
|
return "ON";
|
|
} else {
|
|
return "OFF";
|
|
}
|
|
}
|
|
return String();
|
|
}
|
|
|
|
void setup() {
|
|
// Serial port for debugging purposes
|
|
Serial.begin(115200);
|
|
|
|
pinMode(ledPin, OUTPUT);
|
|
digitalWrite(ledPin, LOW);
|
|
|
|
// Connect to Wi-Fi
|
|
WiFi.begin(ssid, password);
|
|
while (WiFi.status() != WL_CONNECTED) {
|
|
delay(1000);
|
|
Serial.println("Connecting to WiFi..");
|
|
}
|
|
|
|
// Print ESP Local IP Address
|
|
Serial.println(WiFi.localIP());
|
|
|
|
initWebSocket();
|
|
|
|
// Route for root / web page
|
|
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
|
|
request->send_P(200, "text/html", index_html, processor);
|
|
});
|
|
|
|
// Start server
|
|
server.begin();
|
|
|
|
//Init Serial USB
|
|
Serial.begin(115200);
|
|
Serial.println(F("Initialize System"));
|
|
//init rfid D8,D5,D6,D7
|
|
SPI.begin();
|
|
rfid.PCD_Init();
|
|
Serial.print(F("Reader :"));
|
|
rfid.PCD_DumpVersionToSerial();
|
|
}
|
|
|
|
void loop() {
|
|
ws.cleanupClients();
|
|
digitalWrite(ledPin, ledState);
|
|
readRFID();
|
|
}
|
|
|
|
void readRFID(void) { /* function readRFID */
|
|
////Read RFID card
|
|
for (byte i = 0; i < 6; i++) {
|
|
key.keyByte[i] = 0xFF;
|
|
}
|
|
// Look for new 1 cards
|
|
if (!rfid.PICC_IsNewCardPresent())
|
|
return;
|
|
// Verify if the NUID has been readed
|
|
if (!rfid.PICC_ReadCardSerial())
|
|
return;
|
|
// Store NUID into nuidPICC array
|
|
for (byte i = 0; i < 4; i++) {
|
|
nuidPICC[i] = rfid.uid.uidByte[i];
|
|
}
|
|
Serial.print(F("RFID In dec: "));
|
|
printDec(rfid.uid.uidByte, rfid.uid.size);
|
|
// printHex(rfid.uid.uidByte, rfid.uid.size);
|
|
Serial.println();
|
|
// Halt PICC
|
|
rfid.PICC_HaltA();
|
|
// Stop encryption on PCD
|
|
rfid.PCD_StopCrypto1();
|
|
}
|
|
/**
|
|
Helper routine to dump a byte array as hex values to Serial.
|
|
*/
|
|
void printHex(byte *buffer, byte bufferSize) {
|
|
for (byte i = 0; i < bufferSize; i++) {
|
|
Serial.print(buffer[i] < 0x10 ? " 0" : " ");
|
|
Serial.print(buffer[i], HEX);
|
|
}
|
|
// ws.textAll(str);
|
|
}
|
|
/**
|
|
Helper routine to dump a byte array as dec values to Serial.
|
|
*/
|
|
void printDec(byte *buffer, byte bufferSize) {
|
|
for (byte i = 0; i < bufferSize; i++) {
|
|
Serial.print(buffer[i] < 0x10 ? " 0" : " ");
|
|
Serial.print(buffer[i], DEC);
|
|
}
|
|
String str = "";
|
|
str += nuidPICC[0];
|
|
str += nuidPICC[1];
|
|
str += nuidPICC[2];
|
|
str += nuidPICC[3];
|
|
Serial.println();
|
|
Serial.print(str);
|
|
Serial.println();
|
|
ws.textAll(str);
|
|
} |