Public Access
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:
1 parent
e991210ce6
commit
58a7cb03c2
23 files changed
+532
-273
No files matched your search
@@ -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()
|
||||
Reference in new issue
Block a user