v2 host: portable desktop app (tray + FastAPI + WebView2 panel), unified config, HA control
Fold the Windows tray/daemon into one self-contained Clawdmeter.exe with a settings UI, and wire the host side of the watch features: - config.py: single %LOCALAPPDATA%\Clawdmeter\config.json (ha/buttons/settings), atomic writes, auto-migration from the old ha_config.json. - server.py: local FastAPI (127.0.0.1:8723) — GET/PUT /api/config (token masked), POST /api/ha/test, GET /api/ha/entities, GET /api/status. - web/index.html: brand-styled settings panel (Status/HA/Buttons/Settings tabs). - panel.py: pywebview/WebView2 window, launched as its own process (pywebview and pystray both want the main thread); tray "Settings" opens it via --panel. - daemon: HA command dispatch (toggle/bri/ct), dynamic button labels + index→ action mapping, watch-battery low warning toast, and the dimmer "dim" snapshot (dimreq → light_snapshot of the first entity) so the watch dial seeds from HA. - clawdmeter.spec / requirements: bundle fastapi+uvicorn+pywebview+webview backend. - build-exe.ps1: ASCII-only (Windows PowerShell 5.1 mangles em-dashes under cp1251). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+21
-2
@@ -21,18 +21,37 @@
|
||||
|
||||
from PyInstaller.utils.hooks import collect_all
|
||||
|
||||
datas = [('firmware/src/logo.h', 'firmware/src')] # tray icon parsed at runtime
|
||||
datas = [
|
||||
('firmware/src/logo.h', 'firmware/src'), # tray icon parsed at runtime
|
||||
('daemon/web', 'daemon/web'), # Phase 7 control-panel UI (server._web_dir)
|
||||
]
|
||||
binaries = []
|
||||
hiddenimports = [
|
||||
# Imported lazily inside tray_windows.main(), so name them explicitly.
|
||||
'daemon.claude_usage_daemon_windows',
|
||||
'daemon.autostart_windows',
|
||||
'daemon.icon_assets',
|
||||
# Phase 7 control panel (lazy string-imports inside tray_windows / server).
|
||||
'daemon.config',
|
||||
'daemon.server',
|
||||
'daemon.panel',
|
||||
'daemon.ha_client',
|
||||
# The exact winrt media modules read_now_playing() pulls in.
|
||||
'winrt.windows.media',
|
||||
'winrt.windows.media.control',
|
||||
# pywebview's Windows backend + pythonnet bridge load these dynamically.
|
||||
'webview.platforms.edgechromium',
|
||||
'clr',
|
||||
]
|
||||
for _pkg in ('winrt', 'bleak', 'pystray', 'PIL'):
|
||||
# Phase 7 adds the FastAPI control panel + the pywebview WebView2 window. uvicorn
|
||||
# and pywebview both import their submodules (loop/protocol pickers; the
|
||||
# edgechromium backend + bundled WebView2 DLLs) dynamically, which PyInstaller's
|
||||
# static analysis misses — collect_all pulls submodules, binaries and data files.
|
||||
# clr_loader/pythonnet ship the .NET runtime-config JSON pywebview's WinForms host
|
||||
# needs. If a package is absent the build fails loudly (better than a silent
|
||||
# blank window at runtime).
|
||||
for _pkg in ('winrt', 'bleak', 'pystray', 'PIL',
|
||||
'fastapi', 'uvicorn', 'webview', 'clr_loader', 'pythonnet'):
|
||||
_d, _b, _h = collect_all(_pkg)
|
||||
datas += _d
|
||||
binaries += _b
|
||||
|
||||
Reference in New Issue
Block a user