chat py
This commit is contained in:
+151
@@ -0,0 +1,151 @@
|
||||
from flask import Flask, request, jsonify, Response
|
||||
import threading
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
# Shared state — written by Flask thread, read by main loop
|
||||
state = {
|
||||
'brightness': 100,
|
||||
'program_top_text_enabled': True,
|
||||
'program_bottom_text_enabled': True,
|
||||
'program_vehicles_enabled': True,
|
||||
}
|
||||
_lock = threading.Lock()
|
||||
|
||||
INDEX_HTML = """<!DOCTYPE HTML><html>
|
||||
<head>
|
||||
<title>LED Panel Control</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body { font-family: Arial, sans-serif; background: #1a1a2e; color: #eee; padding: 20px; }
|
||||
h1 { text-align: center; margin-bottom: 30px; font-size: 1.5em; }
|
||||
.container { max-width: 400px; margin: 0 auto; }
|
||||
.card { background: #16213e; border-radius: 12px; padding: 16px 20px; margin-bottom: 12px;
|
||||
display: flex; align-items: center; justify-content: space-between; }
|
||||
.card-label { font-size: 1em; }
|
||||
.card-label small { display: block; color: #888; font-size: 0.75em; margin-top: 2px; }
|
||||
.toggle { position: relative; width: 52px; height: 28px; flex-shrink: 0; }
|
||||
.toggle input { opacity: 0; width: 0; height: 0; }
|
||||
.toggle .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0;
|
||||
background: #444; border-radius: 28px; transition: 0.3s; }
|
||||
.toggle .slider:before { content: ""; position: absolute; height: 22px; width: 22px;
|
||||
left: 3px; bottom: 3px; background: #fff; border-radius: 50%; transition: 0.3s; }
|
||||
.toggle input:checked + .slider { background: #4CAF50; }
|
||||
.toggle input:checked + .slider:before { transform: translateX(24px); }
|
||||
.brightness-card { background: #16213e; border-radius: 12px; padding: 16px 20px; margin-bottom: 12px; }
|
||||
.brightness-card label { font-size: 1em; display: block; margin-bottom: 8px; }
|
||||
.brightness-row { display: flex; align-items: center; gap: 12px; }
|
||||
.brightness-row input[type=range] { flex: 1; accent-color: #4CAF50; }
|
||||
.brightness-row span { min-width: 32px; text-align: right; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>LED Panel Control</h1>
|
||||
<div class="card">
|
||||
<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>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-label">Bottom Text<small>School programs</small></div>
|
||||
<label class="toggle"><input type="checkbox" id="bottom_text" checked onchange="toggle('bottom_text', this.checked)"><span class="slider"></span></label>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-label">Vehicles<small>Vehicle interruptions</small></div>
|
||||
<label class="toggle"><input type="checkbox" id="vehicles" checked onchange="toggle('vehicles', this.checked)"><span class="slider"></span></label>
|
||||
</div>
|
||||
<div class="brightness-card">
|
||||
<label>Brightness</label>
|
||||
<div class="brightness-row">
|
||||
<input type="range" id="brightness" min="0" max="100" value="100" oninput="updateBrightnessLabel()" onchange="sendBrightness()">
|
||||
<span id="brightnessValue">100</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function toggle(program, enabled) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "/toggle-program", true);
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
xhr.send("program=" + program + "&enabled=" + (enabled ? "true" : "false"));
|
||||
}
|
||||
function updateBrightnessLabel() {
|
||||
document.getElementById("brightnessValue").innerText = document.getElementById("brightness").value;
|
||||
}
|
||||
function sendBrightness() {
|
||||
var val = document.getElementById("brightness").value;
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "/brightness", true);
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
xhr.send("value=" + val);
|
||||
}
|
||||
function fetchStatus() {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "/program-status", true);
|
||||
xhr.onload = function() {
|
||||
if (xhr.status === 200) {
|
||||
var s = JSON.parse(xhr.responseText);
|
||||
document.getElementById("top_text").checked = s.top_text;
|
||||
document.getElementById("bottom_text").checked = s.bottom_text;
|
||||
document.getElementById("vehicles").checked = s.vehicles;
|
||||
document.getElementById("brightness").value = s.brightness;
|
||||
document.getElementById("brightnessValue").innerText = s.brightness;
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
}
|
||||
window.onload = fetchStatus;
|
||||
</script>
|
||||
</body>
|
||||
</html>"""
|
||||
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
return Response(INDEX_HTML, mimetype='text/html')
|
||||
|
||||
|
||||
@app.route('/brightness', methods=['POST'])
|
||||
def handle_brightness():
|
||||
value = request.form.get('value')
|
||||
if value is not None:
|
||||
with _lock:
|
||||
state['brightness'] = max(0, min(100, int(value)))
|
||||
return 'OK'
|
||||
|
||||
|
||||
@app.route('/toggle-program', methods=['POST'])
|
||||
def handle_toggle():
|
||||
program = request.form.get('program')
|
||||
enabled_str = request.form.get('enabled')
|
||||
if not program or enabled_str is None:
|
||||
return 'Missing program or enabled parameter', 400
|
||||
enabled = enabled_str.lower() == 'true'
|
||||
key_map = {
|
||||
'top_text': 'program_top_text_enabled',
|
||||
'bottom_text': 'program_bottom_text_enabled',
|
||||
'vehicles': 'program_vehicles_enabled',
|
||||
}
|
||||
if program not in key_map:
|
||||
return 'Unknown program', 400
|
||||
with _lock:
|
||||
state[key_map[program]] = enabled
|
||||
return 'OK'
|
||||
|
||||
|
||||
@app.route('/program-status', methods=['GET'])
|
||||
def handle_status():
|
||||
with _lock:
|
||||
s = dict(state)
|
||||
return jsonify({
|
||||
'top_text': s['program_top_text_enabled'],
|
||||
'bottom_text': s['program_bottom_text_enabled'],
|
||||
'vehicles': s['program_vehicles_enabled'],
|
||||
'brightness': s['brightness'],
|
||||
})
|
||||
|
||||
|
||||
def start_server(host='0.0.0.0', port=80):
|
||||
t = threading.Thread(target=lambda: app.run(host=host, port=port, use_reloader=False), daemon=True)
|
||||
t.start()
|
||||
Reference in New Issue
Block a user