Files
clawdmeter/build-exe.ps1
T
wenilandClaude Opus 4.8 1c64386996 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>
2026-07-09 20:20:44 +03:00

49 lines
2.1 KiB
PowerShell

# build-exe.ps1 - build the standalone Clawdmeter.exe (PyInstaller).
#
# Produces dist\Clawdmeter.exe: a single self-contained tray + daemon executable
# that runs on ANY Windows 11 machine with no Python install and no pip. Build it
# on a machine that DOES have Python (e.g. your dev box), then distribute the exe
# via a Gitea release; end users just download and run it (see daemon\README-windows.md).
#
# Usage (from anywhere):
# powershell -ExecutionPolicy Bypass -File build-exe.ps1
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
function Log { param([string]$Msg) Write-Host "[$(Get-Date -Format HH:mm:ss)] $Msg" }
$RepoRoot = $PSScriptRoot
if (-not $RepoRoot) { $RepoRoot = (Get-Location).Path }
Set-Location $RepoRoot
$VenvDir = Join-Path $RepoRoot ".venv"
$PythonExe = Join-Path $VenvDir "Scripts\python.exe"
Log "=== Clawdmeter exe build ==="
# 1. Virtual environment
if (-not (Test-Path $PythonExe)) {
Log "Creating virtual environment at .venv ..."
& python -m venv $VenvDir
if ($LASTEXITCODE -ne 0) { throw "venv creation failed (exit $LASTEXITCODE) - is Python on PATH?" }
}
# 2. Runtime dependencies + PyInstaller (the only build-time extra)
Log "Installing runtime dependencies + PyInstaller ..."
& $PythonExe -m pip install --quiet -r (Join-Path $RepoRoot "daemon\requirements-windows.txt")
if ($LASTEXITCODE -ne 0) { throw "pip install (runtime deps) failed (exit $LASTEXITCODE)" }
& $PythonExe -m pip install --quiet pyinstaller
if ($LASTEXITCODE -ne 0) { throw "pip install pyinstaller failed (exit $LASTEXITCODE)" }
# 3. Build from the committed spec (onefile, windowed)
Log "Building dist\Clawdmeter.exe (this takes a minute) ..."
& $PythonExe -m PyInstaller --noconfirm (Join-Path $RepoRoot "clawdmeter.spec")
if ($LASTEXITCODE -ne 0) { throw "PyInstaller build failed (exit $LASTEXITCODE)" }
$ExePath = Join-Path $RepoRoot "dist\Clawdmeter.exe"
if (-not (Test-Path $ExePath)) { throw "Build reported success but $ExePath is missing" }
$sizeMB = [math]::Round((Get-Item $ExePath).Length / 1MB, 1)
Log "Build complete: $ExePath ($sizeMB MB)"
Log "Distribute this exe via a Gitea release - it is intentionally not committed to git."