Select Git revision
network.cpp
network.cpp 6.21 KiB
#include <Arduino.h>
#include <ESPTelnet.h>
#include "config.h"
#include "utils.h"
#include "network.h"
#include "display.h"
#include "gameoflife.h"
MDNSResponder mdns;
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");
ESPTelnet telnet;
IPAddress ip;
int otaProgress = 0;
void setupNetwork()
{
setupWifi();
setupMDNS();
setupOTA();
setupTelnet();
setupWebserver();
}
void setupWifi()
{
ESPConnect.autoConnect(HOSTNAME);
if (ESPConnect.begin(&server))
{
ip = WiFi.localIP();
logLine("Connected to WiFi: ", false);
logLine(WiFi.localIP().toString());
}
else
{
logLine("Failed to connect to WiFi");
}
}
void setupMDNS()
{
if (mdns.begin(HOSTNAME))
{
logLine("MDNS responder started");
mdns.addService("http", "tcp", 80);
}
else
{
logLine("MDNS.begin failed");
}
}
void setupOTA()
{
ArduinoOTA.onStart([]()
{
runGame = false;
ws.enable(false);
ws.textAll("OTA Update Started");
ws.closeAll();
logLine("Update Start");
clearDisplay(); });
ArduinoOTA.onEnd([]()
{
otaProgress = 0;
runGame = true;
logLine("Update End");
clearDisplay(); });
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total)
{
int percent = ceil(progress/(total/100));
if (percent > otaProgress) {
char msg[10];
sprintf(msg, "OTA:%3d%%", percent);
showMessage(msg);
logLine("OTA: ", false);
logLine((String)percent, false);
logLine("%");
otaProgress = percent;
} });
ArduinoOTA.onError([](ota_error_t error)
{
if(error == OTA_AUTH_ERROR) logLine("OTA Auth Failed");
else if(error == OTA_BEGIN_ERROR) logLine("OTA Begin Failed");
else if(error == OTA_CONNECT_ERROR) logLine("OTA Connect Failed");
else if(error == OTA_RECEIVE_ERROR) logLine("OTA Receive Failed");
else if(error == OTA_END_ERROR) logLine("OTA End Failed");
clearDisplay();
otaProgress = 0;
runGame = true; });
ArduinoOTA.setHostname(HOSTNAME);
ArduinoOTA.begin();
}
void setupTelnet()
{
telnet.onConnect(onTelnetConnect);
telnet.onConnectionAttempt(onTelnetConnectionAttempt);
telnet.onReconnect(onTelnetReconnect);
telnet.onDisconnect(onTelnetDisconnect);
telnet.onInputReceived(onTelnetInput);
Serial.print("- Telnet: ");
if (telnet.begin())
{
Serial.println("running");
}
else
{
Serial.println("error.");
}
}
void setupWebserver()
{
LittleFS.begin();
ws.onEvent(onEvent);
server.addHandler(&ws);
server.on("/heap", HTTP_GET, [](AsyncWebServerRequest *request)
{ request->send(200, "text/plain", String(ESP.getFreeHeap())); });
server.onNotFound([](AsyncWebServerRequest *request)
{ request->send(404); });
server.serveStatic("/", LittleFS, "/").setDefaultFile("index.html");
server.begin();
}
void networkLoop()
{
ArduinoOTA.handle();
telnet.loop();
}
void onTelnetConnect(String ip)
{
Serial.print("- Telnet: ");
Serial.print(ip);
Serial.println(" connected");
telnet.println("\nWelcome " + telnet.getIP());
telnet.println("Use 'CTRL+Q, ENTER' to disconnect.\n");
}
void onTelnetDisconnect(String ip)
{
Serial.print("- Telnet: ");
Serial.print(ip);
Serial.println(" disconnected");
}
void onTelnetReconnect(String ip)
{
Serial.print("- Telnet: ");
Serial.print(ip);
Serial.println(" reconnected");
}
void onTelnetConnectionAttempt(String ip)
{
Serial.print("- Telnet: ");
Serial.print(ip);
Serial.println(" tried to connected");
}
void onTelnetInput(String str)
{
if (str == "ping")
{
telnet.println("> pong");
Serial.println("- Telnet: pong");
}
else if (str == "quit" || str == "exit")
{
telnet.println("> disconnecting...");
telnet.disconnectClient();
}
else if (str == "reboot" || str == "reset")
{
telnet.println("> rebooting...");
ESP.restart();
}
}
DynamicJsonDocument getConfigJson()
{
DynamicJsonDocument doc(200);
JsonObject config = doc.createNestedObject("config");
config["brightness"] = defaultBrightness;
config["interval"] = gameInterval;
return doc;
}
void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len)
{
if (type == WS_EVT_CONNECT)
{
// client connected
logLine("WS<< connect");
logLine("WS>> ping");
client->ping();
DynamicJsonDocument doc = getConfigJson();
size_t strsize = measureJson(doc) + 1;
char json[strsize];
serializeJson(doc, json, strsize);
logLine("WS>> ", false);
logLine(json);
ws.text(client->id(), json);
}
else if (type == WS_EVT_DISCONNECT)
{
logLine("WS<< disconnect");
}
else if (type == WS_EVT_ERROR)
{
// error was received from the other end
char msg[64];
snprintf_P(msg, sizeof(msg), PSTR("WS[%u] error(%u): %s"), client->id(), *((uint16_t *)arg), (char *)data);
logLine(msg);
}
else if (type == WS_EVT_PONG)
{
// pong message was received (in response to a ping request maybe)
logLine("WS<< pong");
}
else if (type == WS_EVT_DATA)
{
// data packet
data[len] = 0;
logLine("WS<< ", false);
logLine((char *)data);
handleJson(data);
}
}
void handleJson(uint8_t *data)
{
StaticJsonDocument<200> doc;
DeserializationError error = deserializeJson(doc, (char *)data);
if (error)
{
logLine("deserializeJson() failed: ", false);
logLine(error.c_str());
return;
}
if (doc.containsKey("config"))
{
updateConfig(doc);
}
if (doc.containsKey("action"))
{
if (doc["action"] == "addGlider")
{
addGlider();
}
else if (doc["action"] == "reboot")
{
ESP.restart();
}
}
}
void updateConfig(StaticJsonDocument<200U> doc)
{
gameInterval = doc["config"]["interval"];
defaultBrightness = doc["config"]["brightness"];
displayBrightness(defaultBrightness);
}