From 59006050eed22e3ca4aabb8b5ae72e0ee3608e72 Mon Sep 17 00:00:00 2001 From: HuggeK <48095810+HuggeK@users.noreply.github.com> Date: Thu, 25 Jun 2026 09:18:42 +0200 Subject: [PATCH] fix: launch Windows desktop app on double-click; drop the .bat launcher MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The released Windows executable is built with `-H windowsgui` (no console) and the `--desktop` flag defaulted to false, so double-clicking `device-simulator.exe` started a hidden HTTP server with no window — the app appeared to do nothing. A generated `Device-Simulator.bat` existed only to pass `--desktop`, which is fragile (antivirus false-positives, console flash, easy to misplace). Gate the `--desktop` default on the `desktop` build tag (new `desktop_mode_on.go` / `desktop_mode_off.go`): desktop release builds (macOS/Linux/Windows, built with `-tags desktop,production`) now default to desktop mode, so launching the executable opens the native window. Server and Docker builds omit the tag and stay headless. `WAILS_DESKTOP` now also accepts `0` to force headless, mirroring `1`. Remove the generated `Device-Simulator.bat` from CI and document running headless with `device-simulator.exe --desktop=false` (web dashboard at http://localhost:8762) in the README, release notes, and CLAUDE.md. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/build.yml | 17 ++++++++++------- CLAUDE.md | 19 ++++++++++++------- README.md | 4 +++- cmd/simulator/desktop_mode_off.go | 11 +++++++++++ cmd/simulator/desktop_mode_on.go | 12 ++++++++++++ cmd/simulator/main.go | 13 ++++++++++--- 6 files changed, 58 insertions(+), 18 deletions(-) create mode 100644 cmd/simulator/desktop_mode_off.go create mode 100644 cmd/simulator/desktop_mode_on.go diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9a8cb03..1737985 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -412,17 +412,14 @@ jobs: New-Item -ItemType Directory -Force -Path build\windows $env:CGO_ENABLED = "1" + # Built with the "desktop" tag so the executable defaults to desktop + # mode: double-clicking device-simulator.exe opens the native window + # (no launcher .bat needed). Run with --desktop=false for headless mode. go build -tags "desktop,production" ` -ldflags "-s -w -H windowsgui -X main.Version=$env:VERSION" ` -o build\windows\device-simulator.exe ` .\cmd\simulator\ - # Create launcher batch file - @" - @echo off - start "" "%~dp0device-simulator.exe" --desktop %* - "@ | Out-File -FilePath build\windows\Device-Simulator.bat -Encoding ASCII - # Create zip (use consistent naming for selfupdate compatibility) Compress-Archive -Path build\windows\* -DestinationPath build\device-simulator_windows_amd64.zip @@ -483,5 +480,11 @@ jobs: ``` ### Windows - 1. Unzip and run `Device-Simulator.bat` or `device-simulator.exe --desktop` + 1. Unzip and double-click `device-simulator.exe` 2. WebView2 will auto-install if needed + + To run headless (HTTP server only, no window), open a terminal and run + `device-simulator.exe --desktop=false`, then browse to http://localhost:8762 + Note: the released `.exe` is a GUI build, so it produces no console output and + Ctrl+C will not stop it — control it from the web dashboard, or use the Docker + image / `make build-windows-server` if you need console logs. diff --git a/CLAUDE.md b/CLAUDE.md index 98cc62d..1c9660f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -59,9 +59,9 @@ go test ./... ``` device-simulator -├── Mode Selection (--desktop flag or WAILS_DESKTOP=1) -│ ├── Desktop Mode: Wails window + HTTP API on :8762 -│ └── Server Mode: HTTP-only on :80 (Docker default) +├── Mode Selection (--desktop flag, build tag default, or WAILS_DESKTOP) +│ ├── Desktop Mode: Wails window + HTTP API on :8762 (default for desktop builds) +│ └── Server Mode: HTTP-only on :80 (default for server/Docker builds) ├── HTTP API Server (unified dashboard + REST API) ├── Modbus TCP Servers (:5000+) ├── MQTT Brokers (:1883+) @@ -70,12 +70,17 @@ device-simulator ### Dual-Mode Operation -The app supports two modes controlled by the `--desktop` flag: +The app supports two modes controlled by the `--desktop` flag. The flag's +**default depends on the build tag**: builds compiled with the `desktop` tag +(the released macOS/Linux/Windows apps) default to desktop mode, so launching +the executable directly opens the native window. Server/Docker builds omit the +tag and default to headless. The default is defined in +`cmd/simulator/desktop_mode_on.go` / `desktop_mode_off.go`. | Mode | Trigger | UI | Use Case | |------|---------|-----|----------| -| Desktop | `--desktop` or `WAILS_DESKTOP=1` | Native Wails window | End users | -| Server | Default (no flag) | Browser at HTTP port | Docker, development | +| Desktop | `--desktop`, `WAILS_DESKTOP=1`, or a `desktop`-tagged build | Native Wails window | End users | +| Server | `--desktop=false`, `WAILS_DESKTOP=0`, or an untagged build | Browser at HTTP port | Docker, development | ### Go Backend (`cmd/simulator/`, `internal/`) @@ -203,7 +208,7 @@ func (a *App) CheckForUpdate() (*UpdateInfo, error) | MQTT_BASE_PORT | 1883 | First MQTT port | | OCPP_BASE_PORT | 9000 | First OCPP port | | HTTP_PORT | 80 (Docker) / 8762 (Desktop) | Web dashboard port | -| WAILS_DESKTOP | 0 | Set to 1 to force desktop mode | +| WAILS_DESKTOP | build-tag default | Set to 1 to force desktop mode, 0 to force headless (overrides --desktop) | | HOST_IP | auto-detected | Override displayed host IP | ## CI/CD (GitHub Actions) diff --git a/README.md b/README.md index 5a01c63..6f2c912 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,9 @@ sudo apt install libgtk-3-0 libwebkit2gtk-4.0-37 # Debian/Ubuntu ./linux/device-simulator.sh ``` -**Windows:** Unzip and run `device-simulator.exe --desktop` +**Windows:** Unzip and double-click `device-simulator.exe` — the desktop window opens automatically (WebView2 auto-installs if needed). + +> **Run headless on Windows?** Open a terminal and run `device-simulator.exe --desktop=false`, then browse to . (The released `.exe` is a GUI build, so it does not print to the console; the web dashboard is the interface. For console logs, use Docker or `make build-windows-server`.) The app auto-updates when new versions are available. diff --git a/cmd/simulator/desktop_mode_off.go b/cmd/simulator/desktop_mode_off.go new file mode 100644 index 0000000..8d7e40d --- /dev/null +++ b/cmd/simulator/desktop_mode_off.go @@ -0,0 +1,11 @@ +//go:build !desktop + +package main + +// defaultDesktopMode is the default for the --desktop flag. +// +// Server/Docker builds omit the "desktop" build tag (e.g. the Docker image and +// the `*-server` Makefile targets). They have no display and default to the +// headless HTTP-only server. Pass --desktop (or set WAILS_DESKTOP=1) to force +// the native window. +const defaultDesktopMode = false diff --git a/cmd/simulator/desktop_mode_on.go b/cmd/simulator/desktop_mode_on.go new file mode 100644 index 0000000..e031fa3 --- /dev/null +++ b/cmd/simulator/desktop_mode_on.go @@ -0,0 +1,12 @@ +//go:build desktop + +package main + +// defaultDesktopMode is the default for the --desktop flag. +// +// Desktop release builds are compiled with the "desktop" build tag (see the +// `-tags "desktop,production"` builds for macOS, Linux and Windows). For those +// builds the app should open the native Wails window when launched with no +// arguments, so double-clicking the executable "just works". Pass +// --desktop=false (or set WAILS_DESKTOP=0) to run those builds headless. +const defaultDesktopMode = true diff --git a/cmd/simulator/main.go b/cmd/simulator/main.go index 257552f..0a88bc0 100644 --- a/cmd/simulator/main.go +++ b/cmd/simulator/main.go @@ -188,7 +188,11 @@ func main() { mqttBasePort := flag.Int("mqtt-base", 1883, "Base port for MQTT brokers") ocppBasePort := flag.Int("ocpp-base", 9000, "Base port for OCPP servers") httpPort := flag.Int("http", 8762, "HTTP server port") - desktopMode := flag.Bool("desktop", false, "Run in desktop mode (Wails)") + // Default depends on the build: desktop release builds (compiled with the + // "desktop" tag) open the native window so double-clicking the executable + // works; server/Docker builds default to headless. Use --desktop=false to + // force headless on a desktop build. + desktopMode := flag.Bool("desktop", defaultDesktopMode, "Run in desktop mode (Wails window); use --desktop=false for headless server mode") flag.Parse() // Load settings from config file (applies before env var overrides) @@ -226,9 +230,12 @@ func main() { *httpPort = n } } - // WAILS_DESKTOP env var overrides flag - if os.Getenv("WAILS_DESKTOP") == "1" { + // WAILS_DESKTOP env var overrides flag/default (1 = desktop, 0 = headless) + switch os.Getenv("WAILS_DESKTOP") { + case "1": *desktopMode = true + case "0": + *desktopMode = false } // Display offsets (used for UI port display)