diff --git a/data/favicon.ico b/data/favicon.ico index 71b25fe6ee6012a4c26602977262d217af885520..e625327072d434ecf199703b86f1ac812a4030c2 100644 Binary files a/data/favicon.ico and b/data/favicon.ico differ diff --git a/data/index.html b/data/index.html index f167d3a3847638315026c4c4dce29a8a5f8c1ac9..53830e4ed5bf15a7d443606a8581f9c6ff696fd7 100644 --- a/data/index.html +++ b/data/index.html @@ -1,81 +1,42 @@ -<!DOCTYPE html> -<html> - <head> - <meta http-equiv="Content-type" content="text/html; charset=utf-8"> - <title>WebSocketTester</title> - <style type="text/css" media="screen"> - body { - margin:0; - padding:0; - background-color: black; - } +<!doctype html> +<html lang="en"> - #dbg, #input_div, #input_el { - font-family: monaco; - font-size: 12px; - line-height: 13px; - color: #AAA; - } +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>Matrix of Life</title> + <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous"> + <link href="styles.css" rel="stylesheet"> +</head> - #dbg, #input_div { - margin:0; - padding:0; - padding-left:4px; - } +<body class="w-100 h-100 d-flex align-items-center"> + + <div class="container justify-content-center"> + + <div class="col-lg-6 offset-lg-3"> + + <div class="row mb-3"> + <label for="rangeBrightness" class="col-form-label">Brightness</label> + <input type="range" class="form-range" id="rangeBrightness" data-name="brightness" min="8" max="255" steps="1"> + </div> + <div class="row mb-3"> + <label for="rangeSpeed" class="col-form-label">Speed</label> + <input type="range" class="form-range" id="rangeSpeed" data-name="interval" min="10" max="1000" steps="10"> + </div> + <button type="button" class="btn btn-primary" id="btnGlider">Add Glider</button> + + <pre id="dbg"></pre> + <div id="input_div"> + $<input type="text" value="" id="input_el"> + </div> - #input_el { - width:98%; - background-color: rgba(0,0,0,0); - border: 0px; - } - #input_el:focus { - outline: none; - } - </style> - <script type="text/javascript"> - var ws = null; - function ge(s){ return document.getElementById(s);} - function ce(s){ return document.createElement(s);} - function stb(){ window.scrollTo(0, document.body.scrollHeight || document.documentElement.scrollHeight); } - function addMessage(m){ - var msg = ce("div"); - msg.innerText = m; - ge("dbg").appendChild(msg); - stb(); - } - function startSocket(){ - ws = new WebSocket('ws://'+document.location.host+'/ws',['arduino']); - ws.onopen = function(e){ - addMessage("Connected"); - }; - ws.onclose = function(e){ - addMessage("Disconnected"); - }; - ws.onerror = function(e){ - console.log("ws error", e); - addMessage("Error"); - }; - ws.onmessage = function(e){ - var msg = "> "+e.data; - addMessage(msg); - }; - ge("input_el").onkeydown = function(e){ - stb(); - if(e.keyCode == 13 && ge("input_el").value != ""){ - ws.send(ge("input_el").value); - ge("input_el").value = ""; - } - } - } - function onBodyLoad(){ - startSocket(); - } - </script> - </head> - <body id="body" onload="onBodyLoad()"> - <pre id="dbg"></pre> - <div id="input_div"> - $<input type="text" value="" id="input_el"> </div> - </body> + + </div> + + <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script> + <script src="https://code.jquery.com/jquery-3.7.0.slim.min.js" integrity="sha256-tG5mcZUtJsZvyKAxYLVXrmjKBVLd6VpVccqz/r4ypFE=" crossorigin="anonymous"></script> + <script src="main.js"></script> +</body> + </html> diff --git a/data/main.js b/data/main.js new file mode 100644 index 0000000000000000000000000000000000000000..8540a25cdb74ff7027db3ec758ffab2ad0c38e9e --- /dev/null +++ b/data/main.js @@ -0,0 +1,70 @@ +var ws = null; +function ge(s) { return document.getElementById(s); } +function ce(s) { return document.createElement(s); } +function addMessage(m) { + var msg = ce("div"); + msg.innerText = m; + ge("dbg").appendChild(msg); +} + +var config = { + brightness: 0, + interval: 0, +}; + +$(document).ready(function() { + startSocket(); +}); + +$(document).on('input change', '#rangeBrightness, #rangeSpeed', function() { + config[$(this).data('name')] = $(this).val(); + var payload = { + config: config + }; + ws.send(JSON.stringify(payload)); +}); + +$('#btnGlider').on('click', function() { + var payload = { + action: "addGlider" + }; + ws.send(JSON.stringify(payload)); +}) + +function startSocket() { + ws = new WebSocket('ws://' + document.location.host + '/ws', ['arduino']); + ws.onopen = function (e) { + addMessage("Connected"); + }; + ws.onclose = function (e) { + addMessage("Disconnected"); + }; + ws.onerror = function (e) { + console.log("ws error", e); + addMessage("Error"); + }; + ws.onmessage = function (e) { + var msg = "> " + e.data; + addMessage(msg); + var data = jQuery.parseJSON(e.data); + console.log(data); + if(data.config) { + loadConfig(data.config); + } else { + console.log("no config"); + } + }; + ge("input_el").onkeydown = function (e) { + if (e.keyCode == 13 && ge("input_el").value != "") { + ws.send(ge("input_el").value); + ge("input_el").value = ""; + } + } +} + +function loadConfig(data) { + config.brightness = data.brightness; + config.interval = data.interval; + $('#rangeBrightness').val(data.brightness); + $('#rangeSpeed').val(data.interval); +} diff --git a/data/styles.css b/data/styles.css new file mode 100644 index 0000000000000000000000000000000000000000..3bee0465785fd6c068be7522eaf6cf89483d3d82 --- /dev/null +++ b/data/styles.css @@ -0,0 +1,24 @@ +html { + width: 100%; + height: 100%; +} + +#dbg, #input_div, #input_el { + font-family: monaco; +} + +#dbg, #input_div { + margin:0; + padding:0; + padding-left:4px; +} + +#input_el { + width:98%; + background-color: rgba(0,0,0,0); + border: 0px; +} + +#input_el:focus { + outline: none; +} diff --git a/src/gameoflife.cpp b/src/gameoflife.cpp index fde43972b1d44103462320eeb9b5f4785a6960c7..d5d57e2c3bd51890df5c9667a327770823b515dd 100644 --- a/src/gameoflife.cpp +++ b/src/gameoflife.cpp @@ -34,7 +34,7 @@ void setupGameOfLife() createRandomMatrix(g); for (int i = 0; i < 10; i++) { - addGlider(random(SCREEN_HEIGHT), random(SCREEN_WIDTH), g); + addGlider(); } logLine("Starting Game " + String(gameEra)); } @@ -96,7 +96,7 @@ void gameOfLife(int (&a)[SCREEN_HEIGHT][SCREEN_WIDTH]) } } -void addGlider(int i1, int j1, int (&a)[SCREEN_HEIGHT][SCREEN_WIDTH]) +void createGlider(int i1, int j1, int (&a)[SCREEN_HEIGHT][SCREEN_WIDTH]) { // 010 // 001 @@ -111,6 +111,10 @@ void addGlider(int i1, int j1, int (&a)[SCREEN_HEIGHT][SCREEN_WIDTH]) } } +void addGlider() { + createGlider(random(SCREEN_HEIGHT), random(SCREEN_WIDTH), g); +} + void gameLoop() { if (runGame == false) diff --git a/src/gameoflife.h b/src/gameoflife.h index 2e0e14c8412616beb080b0df1d464b641bf36f1c..2af799f335e033ec3a929d1ed25c176cfa7d0240 100644 --- a/src/gameoflife.h +++ b/src/gameoflife.h @@ -16,7 +16,8 @@ extern int defaultBrightness; void setupGameOfLife(); void createRandomMatrix(int (&a)[SCREEN_HEIGHT][SCREEN_WIDTH]); void gameOfLife(int (&a)[SCREEN_HEIGHT][SCREEN_WIDTH]); -void addGlider(int i1, int j1, int (&a)[SCREEN_HEIGHT][SCREEN_WIDTH]); +void createGlider(int i1, int j1, int (&a)[SCREEN_HEIGHT][SCREEN_WIDTH]); +void addGlider(); void gameLoop(); void endGame(); void resetGame(); diff --git a/src/network.cpp b/src/network.cpp index fc1d8b13576222c4e42a7a924b441d1f073abf14..a13222bfabb358245b2153ee03c5f3ddd1f8ddda 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -4,6 +4,7 @@ #include "utils.h" #include "network.h" #include "display.h" +#include "gameoflife.h" MDNSResponder mdns; AsyncWebServer server(80); @@ -62,6 +63,7 @@ void setupOTA() clearDisplay(); }); ArduinoOTA.onEnd([]() { + otaProgress = 0; runGame = true; logLine("Update End"); clearDisplay(); }); @@ -85,6 +87,7 @@ void setupOTA() 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(); @@ -244,6 +247,18 @@ void handleJson(uint8_t *data) { updateConfig(doc); } + + if (doc.containsKey("action")) + { + if (doc["action"] == "addGlider") + { + addGlider(); + } + else if (doc["action"] == "reboot") + { + ESP.restart(); + } + } } void updateConfig(StaticJsonDocument<200U> doc)