diff --git a/platformio.ini b/platformio.ini index 7d72a23c298ddf5fb310c5bbebad12e399908089..b8f71df7a07e842b90e3e9a222fc647f0e6225d9 100644 --- a/platformio.ini +++ b/platformio.ini @@ -15,6 +15,7 @@ framework = arduino upload_port = COM8 monitor_port = COM8 monitor_speed = 115200 +monitor_filters = esp32_exception_decoder board_build.filesystem = littlefs lib_deps = https://github.com/ayushsharma82/ESPConnect.git @@ -22,6 +23,7 @@ lib_deps = https://github.com/me-no-dev/ESPAsyncWebServer.git https://github.com/PlummersSoftwareLLC/SmartMatrix.git https://github.com/sstaub/TickTwo.git + https://github.com/LennartHennigs/ESPTelnet.git [env:esp32dev_ota] extends = env:esp32dev diff --git a/src/display.cpp b/src/display.cpp index 974f632139be920c504091d350b4edd08691f28c..84f59653851a9aedea93a4aedb3def4227016609 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -2,6 +2,7 @@ #include "gameoflife.h" #include "display.h" #include "network.h" +#include "utils.h" #define COLOR_DEPTH 24 // known working: 24, 48 - If the sketch uses type `rgb24` directly, COLOR_DEPTH must be 24 const uint8_t kMatrixWidth = 64; // known working: 32, 64, 96, 128 @@ -54,12 +55,12 @@ void showEndScreen(int ticks) void fadeOutGame(int brightness) { - char msg[38]; + char msg[64]; sprintf(msg, "Setting game layer brightness to: %d", brightness); - sendEvent("display", msg); + logLine(msg); brightness = lightPowerMap8bit[brightness]; backgroundLayer.setBrightness(brightness); - // backgroundLayer.swapBuffers(false); + //backgroundLayer.swapBuffers(false); } void showEvolutions(int ticks) @@ -71,12 +72,12 @@ void showEvolutions(int ticks) indexedLayer.drawString((matrix.getScreenWidth() / 2) - (strlen(msg) * 4) / 2, (matrix.getScreenHeight() / 2) - 2 - 5, 1, msg); indexedLayer.drawString((matrix.getScreenWidth() / 2) - (strlen(evolutions) * 4) / 2, (matrix.getScreenHeight() / 2) + 2, 1, evolutions); indexedLayer.swapBuffers(); - indexedLayer.fillScreen(0); } void clearDisplay() { - indexedLayer.swapBuffers(false); + indexedLayer.fillScreen(0); + indexedLayer.swapBuffers(); backgroundLayer.fillScreen({0, 0, 0}); backgroundLayer.setBrightness(255); backgroundLayer.swapBuffers(false); diff --git a/src/gameoflife.cpp b/src/gameoflife.cpp index f90f80a67daafff10d3572bf5dc07caecd09f15d..89846b787d8c50e6a4948efa7c47640721c157ee 100644 --- a/src/gameoflife.cpp +++ b/src/gameoflife.cpp @@ -2,6 +2,7 @@ #include "display.h" #include "gameoflife.h" #include "network.h" +#include "utils.h" // https://github.com/Stavrosfil/game-of-life-esp32 @@ -13,6 +14,7 @@ bool gameOver = false; int currentTick; int finalTicks; +int cellsAliveNow; int cellsAliveBefore; int noEvolutionTicks; @@ -32,7 +34,7 @@ void setupGameOfLife() { addGlider(random(SCREEN_HEIGHT), random(SCREEN_WIDTH), g); } - sendEvent("game", "Game of Life has been initialized"); + logLine("Game of Life has been initialized"); } void createRandomMatrix(int (&a)[SCREEN_HEIGHT][SCREEN_WIDTH]) @@ -48,9 +50,8 @@ void createRandomMatrix(int (&a)[SCREEN_HEIGHT][SCREEN_WIDTH]) void gameOfLife(int (&a)[SCREEN_HEIGHT][SCREEN_WIDTH]) { + cellsAliveNow = 0; currentTick++; - int cellsAliveNow = 0; - for (int i = 0; i < SCREEN_HEIGHT; i++) { for (int j = 0; j < SCREEN_WIDTH; j++) @@ -91,41 +92,6 @@ void gameOfLife(int (&a)[SCREEN_HEIGHT][SCREEN_WIDTH]) a[i][j] = arrayCopy[i][j]; } } - - if (currentTick % 2) - { - cellsAliveBefore = cellsAliveNow; - char msg[50]; - sprintf(msg, "Cells alive now: %d, Cells alive before: %d", cellsAliveNow, cellsAliveBefore); - sendEvent("game", msg); - } - - if (cellsAliveNow >= cellsAliveBefore - 3 && - cellsAliveNow <= cellsAliveBefore + 3) - { - noEvolutionTicks++; - } - else - { - noEvolutionTicks = 0; - } - - if (noEvolutionTicks > noEvolutionTicksLimit) - { - if (!gameOver) - { - finalTicks = currentTick - noEvolutionTicksLimit; - currentMillis = millis(); - showEndScreen(finalTicks); - gameOver = true; - sendEvent("game", "No Evolution detected anymore, ending Game of Life"); - } - else - { - int brightness = 255 * (1 - ((millis() - currentMillis) / scoreScreenTimeout)); - fadeOutGame(brightness); - } - } } void addGlider(int i1, int j1, int (&a)[SCREEN_HEIGHT][SCREEN_WIDTH]) @@ -145,17 +111,60 @@ void addGlider(int i1, int j1, int (&a)[SCREEN_HEIGHT][SCREEN_WIDTH]) void gameLoop() { - if (runGame) + if (runGame == false) { - gameOfLife(g); - if (gameOver) + return; + } + + gameOfLife(g); + + if (gameOver) + { + + if (millis() - currentMillis > scoreScreenTimeout) + { + resetGame(); + } + + if (noEvolutionTicks > noEvolutionTicksLimit) { - if (millis() - currentMillis > scoreScreenTimeout) + if (gameOver) { - resetGame(); + int brightness = 255 * (1 - ((millis() - currentMillis) / scoreScreenTimeout)); + fadeOutGame(brightness); } } } + else + { + + if (currentTick % 2) + { + char msg[61]; + sprintf(msg, "Cells alive now: %4d, before: %4d - No evolution since: %3d", cellsAliveNow, cellsAliveBefore, noEvolutionTicks); + logLine(msg); + cellsAliveBefore = cellsAliveNow; + } + + if (cellsAliveNow >= cellsAliveBefore - 3 && + cellsAliveNow <= cellsAliveBefore + 3) + { + noEvolutionTicks++; + } + else + { + noEvolutionTicks = 0; + } + + if (noEvolutionTicks > noEvolutionTicksLimit) + { + finalTicks = currentTick - noEvolutionTicksLimit; + currentMillis = millis(); + showEndScreen(finalTicks); + gameOver = true; + logLine("No Evolution detected anymore, ending Game of Life"); + } + } } void resetGame() diff --git a/src/network.cpp b/src/network.cpp index 54c8d7203c17bee33369ff51a39b8b2da2e4eaf8..02d57e10c240f39d96b9b00130c9ccb2b75fbe63 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -1,17 +1,22 @@ #include <Arduino.h> +#include <ESPTelnet.h> #include "config.h" #include "utils.h" #include "network.h" MDNSResponder mdns; AsyncWebServer server(80); -AsyncEventSource events("/events"); +ESPTelnet telnet; +IPAddress ip; + +uint16_t telnetPort = 23; void setupNetwork() { setupWifi(); setupMDNS(); setupOTA(); + setupTelnet(); setupWebserver(); } @@ -20,6 +25,7 @@ void setupWifi() ESPConnect.autoConnect(HOSTNAME); if (ESPConnect.begin(&server)) { + ip = WiFi.localIP(); logLine("Connected to WiFi: ", false); logLine(WiFi.localIP().toString()); } @@ -45,32 +51,53 @@ void setupMDNS() void setupOTA() { ArduinoOTA.onStart([]() - { events.send("Update Start", "ota"); }); + { + runGame = false; + logLine("Update Start"); }); ArduinoOTA.onEnd([]() - { events.send("Update End", "ota"); }); + { + runGame = true; + logLine("Update End"); }); ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { char p[32]; sprintf(p, "Progress: %u%%\n", (progress/(total/100))); - events.send(p, "ota"); }); + logLine(p); }); ArduinoOTA.onError([](ota_error_t error) { - if(error == OTA_AUTH_ERROR) events.send("Auth Failed", "ota"); - else if(error == OTA_BEGIN_ERROR) events.send("Begin Failed", "ota"); - else if(error == OTA_CONNECT_ERROR) events.send("Connect Failed", "ota"); - else if(error == OTA_RECEIVE_ERROR) events.send("Receive Failed", "ota"); - else if(error == OTA_END_ERROR) events.send("End Failed", "ota"); }); + 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"); + 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(telnetPort)) + { + Serial.println("running"); + } + else + { + Serial.println("error."); + } +} + void setupWebserver() { LittleFS.begin(); server.serveStatic("/", LittleFS, "/"); - events.onConnect([](AsyncEventSourceClient *client) - { client->send("hello!", NULL, millis(), 1000); }); - server.addHandler(&events); server.onNotFound([](AsyncWebServerRequest *request) { request->send(404); }); server.begin(); @@ -79,8 +106,56 @@ void setupWebserver() void networkLoop() { ArduinoOTA.handle(); + if (runGame) + { + telnet.loop(); + } } -void sendEvent(const char *tag, const char *msg) { - events.send(msg, tag); +// (optional) callback functions for telnet events +void onTelnetConnect(String ip) +{ + Serial.print("- Telnet: "); + Serial.print(ip); + Serial.println(" connected"); + + telnet.println("\nWelcome " + telnet.getIP()); + telnet.println("Use CTRL+q 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) +{ + // checks for a certain command + if (str == "ping") + { + telnet.println("> pong"); + Serial.println("- Telnet: pong"); + // disconnect the client + } + else if (str == "quit") + { + telnet.println("> disconnecting you..."); + telnet.disconnectClient(); + } } diff --git a/src/network.h b/src/network.h index e77c7c7bc6cccf4718b22dc248169f5fb3e583c3..ae38bd386f77a11a75c8e2b1afcd61755e9a24c0 100644 --- a/src/network.h +++ b/src/network.h @@ -17,8 +17,13 @@ void setupNetwork(); void setupMDNS(); void setupWifi(); void setupOTA(); +void setupTelnet(); void setupWebserver(); void networkLoop(); -void sendEvent(const char *tag, const char *msg); +void onTelnetConnect(String ip); +void onTelnetDisconnect(String ip); +void onTelnetReconnect(String ip); +void onTelnetConnectionAttempt(String ip); +void onTelnetInput(String str); #endif diff --git a/src/utils.cpp b/src/utils.cpp index 469daaeb28c72444af7f87065805a5a6740fd3b0..ee717d1fdb6dd2df29ec23b37ff685367336a4ff 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1,11 +1,14 @@ #include <Arduino.h> +#include <ESPTelnet.h> #include "utils.h" void logLine(String line, bool newline) { Serial.print(line); + telnet.print(line); if (newline) { Serial.println(); + telnet.println(); } } diff --git a/src/utils.h b/src/utils.h index 185eab8bcbc6295b0cc22081d82867d6cb4254a6..80c497e2e70c6215174c419ef5baea0211c1e36c 100644 --- a/src/utils.h +++ b/src/utils.h @@ -2,6 +2,10 @@ #define UTILS_H #include <Arduino.h> +#include <ESPTelnet.h> + void logLine(String line, bool newline = true); +extern ESPTelnet telnet; + #endif