Split the README into docs/ pages, add web UI screenshots

- README is the overview; web UI, pages, Home Assistant, how it works,
  wiring, Nano over WiFi and the recovery app have their own page in docs/.
- docs/web-ui.md has a screenshot of every tab, made with headless Edge by
  tools/make_webui_screenshots.py.
- The web UI opens a page in the editor with #pages/<name>. Version 2.7.2.
- The reply wire is fitted (flashing the Nano over WiFi works).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mangavalkandClaude Opus 5.5 committed 2026-10-15 22:42:46 +02:00
1 parent e991210ce6
commit 58a7cb03c2
23 files changed
+532 -273

No files matched your search

+91
View File
@@ -0,0 +1,91 @@
"""Saves screenshots of the web UI tabs in Pictures/web-ui/, with Microsoft Edge (or Chrome)
in headless mode.
python tools/make_webui_screenshots.py [ESP32 address, default 10.1.1.198]
Each tab is opened by its address (http://<ESP32>/#settings); the page editor with
#pages/<page name>. Edge runs with its own temporary profile. Only the Python standard
library is used.
"""
import json
import os
import shutil
import subprocess
import sys
import tempfile
import urllib.parse
import urllib.request
ESP = 'http://' + (sys.argv[1] if len(sys.argv) > 1 else '10.1.1.198')
OUT = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'Pictures', 'web-ui')
BROWSERS = [
r'C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe',
r'C:\Program Files\Microsoft\Edge\Application\msedge.exe',
r'C:\Program Files\Google\Chrome\Application\chrome.exe',
'microsoft-edge', 'google-chrome', 'chromium',
]
WIDTH = 1000
# File name, address part, window height
SHOTS = [
('show', 'show', 2150),
('pages', 'pages/Weer', 3000), # the page list and the editor (tall: nothing has to scroll)
('schedule', 'schedule', 1150),
('stopwatch', 'stopwatch', 560),
('bitmaps', 'bitmaps', 1600),
('draw', 'draw', 820),
('settings', 'settings', 1550),
('home-assistant', 'ha', 780),
('system', 'system', 1080),
]
def browser():
for b in BROWSERS:
path = shutil.which(b) or (b if os.path.exists(b) else None)
if path:
return path
sys.exit('No Edge or Chrome found')
def read_ha_values():
"""Reads the Home Assistant values of all pages, so the previews show them"""
with urllib.request.urlopen(ESP + '/api/pages', timeout=20) as r:
pages = json.loads(r.read())['pages']
for entity in {(e['entity'], e.get('attribute', '')) for p in pages for e in p['page']['elements'] if e.get('entity')}:
query = urllib.parse.urlencode({'entity': entity[0], 'attribute': entity[1]})
try:
urllib.request.urlopen(ESP + '/api/ha/value?' + query, timeout=10).read()
except Exception:
pass
def shoot(exe, profile, path, address, height):
for attempt in range(3):
try:
subprocess.run([exe, '--headless=new', '--disable-gpu', '--hide-scrollbars', '--user-data-dir=' + profile,
'--window-size=%d,%d' % (WIDTH, height), '--virtual-time-budget=20000',
'--screenshot=' + path, address],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=90)
return True
except subprocess.TimeoutExpired:
pass # the browser hung: try again
return False
def main():
exe = browser()
read_ha_values()
os.makedirs(OUT, exist_ok=True)
profile = tempfile.mkdtemp(prefix='flipdot-edge-')
try:
for name, hash_part, height in SHOTS:
path = os.path.join(OUT, name + '.png')
ok = shoot(exe, profile, path, ESP + '/#' + hash_part, height)
print(name, os.path.getsize(path) if ok and os.path.exists(path) else 'failed')
finally:
shutil.rmtree(profile, ignore_errors=True)
if __name__ == '__main__':
main()