add mirroring state onto web server
This commit is contained in:
+60
-3
@@ -1,5 +1,9 @@
|
|||||||
from flask import Flask, request, jsonify, Response
|
from flask import Flask, request, jsonify, Response
|
||||||
import threading
|
import threading
|
||||||
|
import json
|
||||||
|
|
||||||
|
import low_level
|
||||||
|
from config import DISPLAY_MAX_X, DISPLAY_MAX_Y
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
@@ -19,8 +23,12 @@ INDEX_HTML = """<!DOCTYPE HTML><html>
|
|||||||
<style>
|
<style>
|
||||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
body { font-family: Arial, sans-serif; background: #1a1a2e; color: #eee; padding: 20px; }
|
body { font-family: Arial, sans-serif; background: #1a1a2e; color: #eee; padding: 20px; }
|
||||||
h1 { text-align: center; margin-bottom: 30px; font-size: 1.5em; }
|
h1 { text-align: center; margin-bottom: 20px; font-size: 1.5em; }
|
||||||
.container { max-width: 400px; margin: 0 auto; }
|
.container { max-width: 600px; margin: 0 auto; }
|
||||||
|
.display-wrapper { background: #0a0a0a; border-radius: 12px; padding: 12px; margin-bottom: 20px; overflow-x: auto; }
|
||||||
|
.display-grid { display: grid; grid-template-columns: repeat(48, 1fr); gap: 1px; width: 100%; aspect-ratio: 3/1; }
|
||||||
|
.dot { aspect-ratio: 1; border-radius: 50%; background: #111; }
|
||||||
|
.controls { max-width: 400px; margin: 0 auto; }
|
||||||
.card { background: #16213e; border-radius: 12px; padding: 16px 20px; margin-bottom: 12px;
|
.card { background: #16213e; border-radius: 12px; padding: 16px 20px; margin-bottom: 12px;
|
||||||
display: flex; align-items: center; justify-content: space-between; }
|
display: flex; align-items: center; justify-content: space-between; }
|
||||||
.card-label { font-size: 1em; }
|
.card-label { font-size: 1em; }
|
||||||
@@ -43,6 +51,10 @@ INDEX_HTML = """<!DOCTYPE HTML><html>
|
|||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1>LED Panel Control</h1>
|
<h1>LED Panel Control</h1>
|
||||||
|
<div class="display-wrapper">
|
||||||
|
<div class="display-grid" id="grid"></div>
|
||||||
|
</div>
|
||||||
|
<div class="controls">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-label">Top Text<small>Witamy w PTI</small></div>
|
<div class="card-label">Top Text<small>Witamy w PTI</small></div>
|
||||||
<label class="toggle"><input type="checkbox" id="top_text" checked onchange="toggle('top_text', this.checked)"><span class="slider"></span></label>
|
<label class="toggle"><input type="checkbox" id="top_text" checked onchange="toggle('top_text', this.checked)"><span class="slider"></span></label>
|
||||||
@@ -63,7 +75,41 @@ INDEX_HTML = """<!DOCTYPE HTML><html>
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<script>
|
<script>
|
||||||
|
var COLS = 48, ROWS = 16;
|
||||||
|
var dots = [];
|
||||||
|
var grid = document.getElementById("grid");
|
||||||
|
for (var i = 0; i < ROWS * COLS; i++) {
|
||||||
|
var d = document.createElement("div");
|
||||||
|
d.className = "dot";
|
||||||
|
grid.appendChild(d);
|
||||||
|
dots.push(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
function pollDisplay() {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("GET", "/display", true);
|
||||||
|
xhr.onload = function() {
|
||||||
|
if (xhr.status === 200) {
|
||||||
|
var px = JSON.parse(xhr.responseText);
|
||||||
|
for (var y = 0; y < ROWS; y++) {
|
||||||
|
for (var x = 0; x < COLS; x++) {
|
||||||
|
var c = px[y][x];
|
||||||
|
var idx = y * COLS + x;
|
||||||
|
if (c[0] === 0 && c[1] === 0 && c[2] === 0) {
|
||||||
|
dots[idx].style.background = "#111";
|
||||||
|
} else {
|
||||||
|
dots[idx].style.background = "rgb(" + c[0] + "," + c[1] + "," + c[2] + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
setInterval(pollDisplay, 100);
|
||||||
|
|
||||||
function toggle(program, enabled) {
|
function toggle(program, enabled) {
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
xhr.open("POST", "/toggle-program", true);
|
xhr.open("POST", "/toggle-program", true);
|
||||||
@@ -95,7 +141,7 @@ INDEX_HTML = """<!DOCTYPE HTML><html>
|
|||||||
};
|
};
|
||||||
xhr.send();
|
xhr.send();
|
||||||
}
|
}
|
||||||
window.onload = fetchStatus;
|
window.onload = function() { fetchStatus(); pollDisplay(); };
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>"""
|
</html>"""
|
||||||
@@ -106,6 +152,17 @@ def index():
|
|||||||
return Response(INDEX_HTML, mimetype='text/html')
|
return Response(INDEX_HTML, mimetype='text/html')
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/display', methods=['GET'])
|
||||||
|
def handle_display():
|
||||||
|
pixels = []
|
||||||
|
for y in range(DISPLAY_MAX_Y + 1):
|
||||||
|
row = []
|
||||||
|
for x in range(DISPLAY_MAX_X + 1):
|
||||||
|
row.append(low_level.get_pixel_color(x, y))
|
||||||
|
pixels.append(row)
|
||||||
|
return Response(json.dumps(pixels), mimetype='application/json')
|
||||||
|
|
||||||
|
|
||||||
@app.route('/brightness', methods=['POST'])
|
@app.route('/brightness', methods=['POST'])
|
||||||
def handle_brightness():
|
def handle_brightness():
|
||||||
value = request.form.get('value')
|
value = request.form.get('value')
|
||||||
|
|||||||
Reference in New Issue
Block a user