Expand Glitch operations hub, cabinet authoring, deployment, and RFID support

Operator hub
- Introduce Escape Gallery branding and Glitch: the Dark Machine room views
- Add cabinet illustrations, Pac-Man marquee/gameplay artwork, and waiting states
- Add device feedback panels with RFID readings, input/output states, and stale status
- Add logged operator hardware interventions with request deduplication

Room and cabinet authoring
- Add a visual custom-PCB connection editor with per-cabinet device inventory
- Support device IDs, bindings, wiring notes, input polarity, and validation
- Add physical-room label/dimension toggles and editable doorway annotations
- Preserve doorway changes through undo, save, and revert
- Expand cabinet profiles, room layout, and Glitch scenario resources

Scenarios and gameplay
- Add per-assignment game configuration and runtime feature validation
- Add timed test wins and Frogger individual-home objectives
- Add the three-cabinet timed/score/Frogger test scenario
- Add Cabinet 1 Pac-Man RFID credits, credit sound, and CREDIT 0/1 display
- Require physical Start after an accepted scan and prevent duplicate credits

Pi hardware and deployment
- Add GPIO feedback sampling and a separate multiplexed RFID helper
- Validate reader pin ownership and input/output conflicts
- Add SSH cabinet startup and Pi desktop-session service support
- Add master packaging, site setup, SSH enrollment, and staged cabinet releases
- Verify deployment manifests and support explicit activation/status/log commands

Documentation and verification
- Consolidate the root README around the current architecture and setup workflow
- Add the complete master/Pi/RFID export and deployment walkthrough
- Document network isolation, credentials, card identification, and rollback
- Add PCB, room-editor, feedback, credit, deployment, and controller tests
- Isolate protocol tests from designer-edited cabinet configurations

Known limitations
- RFID helper compilation and physical Pi commissioning remain unverified
- Fleet provisioning does not yet configure RFID-only installations completely
- Broader Pac-Man tests retain a ghost-capture assertion failure
- Staged exports must be rebuilt and checked before deploying runtime 2.3
This commit is contained in:
Jeff Luke committed 2026-10-17 14:53:54 -07:00
1 parent 705ec31e0b
commit c1b2195834
90 files changed
+4969 -456

No files matched your search

+118
View File
@@ -0,0 +1,118 @@
# Start the Pi cabinets from the controller PC
After one-time setup, your usual command starts the Windows controller, opens the browser, and asks each configured Pi to start its cabinet service:
```powershell
.\Start-Arcade.ps1 -Mode controller -Browser
```
The Pi service runs the existing cabinet launcher, which starts its GPIO bridge when enabled and then the managed game. SSH disconnects after the start request; the service stays running on the Pi. Already-running services are not restarted. Starting the apps does not automatically prepare or start a scenario; continue doing that in the operator.
The Pis must be powered on, reachable, and logged into their graphical desktop. This is remote application startup, not remote power-on. Desktop autologin is useful for cabinets; configure it on each Pi if desired.
## 1. Install the cabinet service on each Pi
Copy the updated `tools/launch/` scripts to the Pi's deployment folder. Stop the manually running cabinet launcher with Ctrl+C first so it releases the GPIO bridge port.
From a terminal **on the Pi desktop**, as the normal account that runs the game (without sudo):
```sh
python3 tools/launch/pi_service.py install --config tools/launch/launcher.ini
```
Use your actual INI filename, such as `launcher-pi.ini`, if different. It must contain that Pi's executable path, cabinet ID, controller URL/token (or blank URL/token to use its existing Godot CFG), and GPIO settings. The installer records the absolute config path; rerun it if the deployment/config moves.
This creates:
- `~/.config/systemd/user/arcade-cabinet.service`: runs your existing managed launcher as the desktop user.
- `~/.config/autostart/arcade-cabinet-display.desktop`: refreshes display settings at each desktop login, without launching the game.
- A temporary display environment file under the user's runtime directory, refreshed immediately during installation.
The installer does not start the game, enable boot startup, configure SSH, or change OS autologin. It captures only display-related variables, not application tokens. The service clears inherited `ARCADE_*` credential/URL overrides, so keep its intended settings in the configured INI or Godot CFG rather than relying on a terminal's environment.
Test locally:
```sh
systemctl --user start arcade-cabinet.service
systemctl --user status arcade-cabinet.service
```
Confirm the game appears on the cabinet monitor and becomes ONLINE. To stop it:
```sh
systemctl --user stop arcade-cabinet.service
```
If display settings change, run `python3 tools/launch/pi_service.py refresh-session` from the current Pi desktop terminal before starting it again.
## 2. Set up SSH access from Windows
SSH must be enabled on each Pi. Use the same SSH username as the desktop account where you installed the service.
These are **SSH keys**, separate from the 16-character application tokens in the cabinet setup guide. The tokens cannot authenticate SSH.
Generate a dedicated key on the PC (do not overwrite an existing one):
```powershell
ssh-keygen -t ed25519 -f "$env:USERPROFILE\.ssh\arcade_cabinets" -C "arcade-controller"
```
If you use a passphrase, load the key into your SSH agent before launching the room. Automated startup uses batch mode and cannot ask for passwords or passphrases.
For each Pi, first connect interactively and verify its host fingerprint before trusting it:
```powershell
ssh PI_USER@PI_HOST
```
Log out with `exit`. To authorize the public key on that Pi, run from PowerShell (substitute its real user and host):
```powershell
Get-Content "$env:USERPROFILE\.ssh\arcade_cabinets.pub" | ssh PI_USER@PI_HOST 'umask 077; mkdir -p ~/.ssh; cat >> ~/.ssh/authorized_keys'
```
Only copy the `.pub` key; the private key stays on the PC. Test unattended access:
```powershell
ssh -i "$env:USERPROFILE\.ssh\arcade_cabinets" -o BatchMode=yes -o StrictHostKeyChecking=yes PI_USER@PI_HOST "systemctl --user status arcade-cabinet.service"
```
An inactive service may return a nonzero status; confirm SSH succeeded and systemd found the installed unit. The launcher keeps host-key checking enabled and never automatically accepts a new or changed host key.
## 3. Add the Pi list to the PC launcher INI
Merge this into the controller INI you actually launch with. Replace each host and username:
```ini
[remote]
enabled = true
cabinets = [{"id":"cabinet_01","host":"PI_1_HOST","user":"PI_USER","identity_file":"~/.ssh/arcade_cabinets"},{"id":"cabinet_02","host":"PI_2_HOST","user":"PI_USER","identity_file":"~/.ssh/arcade_cabinets"},{"id":"cabinet_03","host":"PI_3_HOST","user":"PI_USER","identity_file":"~/.ssh/arcade_cabinets"}]
```
`identity_file` is optional if your default SSH identity or agent is already configured. `port` is optional and defaults to 22. Each ID must exist in the controller catalog and its cabinet-token map. The Pi's own launcher must use the same cabinet ID; this list does not remotely rewrite its identity or credentials.
Validate, then launch:
```powershell
.\Start-Arcade.ps1 -Mode controller -Check
.\Start-Arcade.ps1 -Mode controller -Browser
```
Use `-Config tools/launch/launcher-pc.ini` if that is your actual config filename. `-Check` validates local settings only; it does not contact or start a Pi.
The controller starts first. The launcher sends the SSH requests concurrently, then checks controller heartbeats. It prints separate **SSH OK/FAILED** and **ONLINE/OFFLINE** results, so a successful service command is not mistaken for a working game connection. A failed/offline Pi leaves the controller running for troubleshooting.
## Operating behavior
- Starting the controller again leaves active Pi services running; it does not interrupt their games with `restart`.
- Closing the browser or stopping the PC controller leaves the Pi services running. They reconnect when the controller returns.
- Closing the Pi game with Escape stops that Pi's launcher/bridge. It will not restart automatically; the next controller launch can start it again.
- A crash is not automatically restarted, avoiding unexpected game resets during a room session.
- Use `ssh PI_USER@PI_HOST "systemctl --user stop arcade-cabinet.service"` for an intentional remote stop.
- Application logs remain in the Pi launcher's configured log folder. Service startup errors are available through `journalctl --user -u arcade-cabinet.service -n 60 --no-pager`.
- If the PC launches before the Pi desktop is ready, startup can fail. Wait for desktop login and launch the controller again, or issue the same `systemctl --user start` command over SSH. There is no automatic power-on or infinite retry loop.
- After a desktop restart/logout, confirm the display helper has run before starting games. If your desktop does not honor XDG autostart entries, run `pi_service.py refresh-session` locally and check the desktop's startup configuration.
The service can be removed by stopping it, removing the two managed files listed above, and running `systemctl --user daemon-reload`. Game resources, saved control mappings, tokens, and GPIO ledger are unaffected.
Implementation references: [OpenSSH client configuration](https://man.openbsd.org/ssh_config), [systemd execution environment](https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html), and [systemd desktop integration](https://github.com/systemd/systemd/blob/main/docs/DESKTOP_ENVIRONMENTS.md).