Files
OSIT-AE-App-Native-Electron/README.md
Scott Idem b3f59b7bf5 docs: add onsite deployment guide and device reference table
- Step-by-step SSH deployment instructions (build, copy .app, write seed.json)
- Multi-laptop deployment loop example
- Device reference table: all 19 laptops with IPs and event_device_ids
- Clarify seed.json location, format, and per-event API key workflow
- Document architecture detection (x64 vs arm64) and SSH key setup
2026-04-20 14:26:54 -04:00

237 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Aether Native Launcher (Electron)
The Aether Native Launcher is a specialized Electron-based shell for the Aether Platform. It provides a secure bridge between the SvelteKit web UI and the local operating system, enabling features restricted by browser sandboxing.
## 🚀 Overview
This application serves as the "Native Mode" runtime for Aether podiums and devices. It handles:
- **Local File Orchestration:** Managed cache for presentation files (PPTx, Keynote, PDF).
- **Automation:** Specialized AppleScript handlers for PowerPoint and Keynote.
- **Hardware Telemetry:** Direct access to CPU, RAM, and Network interface data.
- **Remote Control:** Slide navigation and application control via WebSocket intents.
## 🖥️ Onsite Deployment
**Current hardware:** MacBook Air 2018 — Intel x64. All current deployments use `aether_launcher-darwin-x64`.
**Future hardware:** Apple Silicon Macs use `aether_launcher-darwin-arm64`. Windows and Linux builds are planned.
SSH user on all laptops: **`speaker ready`**
IP pattern: `192.168.32.1XX` (XX = zero-padded laptop number, e.g. 03 → `.103`). Find/replace this prefix for other onsite environments.
### Step 1 — Build the app (workstation)
```bash
cd ~/OSIT_dev/aether_app_native_electron
npm run package:mac
# Produces builds/aether_launcher-darwin-x64/aether_launcher.app ← the one to deploy
```
Only rebuild if source code has changed. The `.app` bundle is identical for all Intel laptops —
only `~/seed.json` differs per device.
### Step 2 — Determine target architecture and copy the .app
Check the target Mac's CPU if unsure:
```bash
ssh "speaker ready"@192.168.32.103 "uname -m"
# x86_64 → use aether_launcher-darwin-x64 (MacBook Air 2018 and all current Intel Macs)
# arm64 → use aether_launcher-darwin-arm64 (Apple Silicon M1/M2/M3/M4)
```
Copy from the workstation (replace `103` with the target IP last octet):
```bash
# Intel (current hardware):
scp -r builds/aether_launcher-darwin-x64/aether_launcher.app \
"speaker ready"@192.168.32.103:/Applications/aether_launcher.app
# Apple Silicon (future hardware):
scp -r builds/aether_launcher-darwin-arm64/aether_launcher.app \
"speaker ready"@192.168.32.103:/Applications/aether_launcher.app
```
If `/Applications/aether_launcher.app` already exists, `scp -r` overwrites it. No need to
remove the old version first.
### Step 3 — Write seed.json on the target laptop
The seed file lives at `~/seed.json` (`/Users/speaker ready/seed.json`) on each Mac.
It is intentionally outside the app bundle so it can be updated without redeploying.
```bash
ssh "speaker ready"@192.168.32.103 "cat > ~/seed.json" << 'EOF'
{
"event_device_id": "DEVICE_ID_FOR_THIS_LAPTOP",
"aether_api_key": "YOUR_API_KEY",
"primary_api_base_url": "https://api.oneskyit.com",
"backup_api_base_url": "https://bak-api.oneskyit.com",
"onsite_api_base_url": null
}
EOF
```
`event_device_id` values by laptop — see the **Device Reference** table below.
### Step 4 — Verify
```bash
# Confirm seed.json landed correctly
ssh "speaker ready"@192.168.32.103 "cat ~/seed.json"
# Confirm the .app is present
ssh "speaker ready"@192.168.32.103 "ls /Applications/aether_launcher.app"
```
Then launch the app on the laptop and confirm it connects and shows the correct device name
in the Launcher UI.
### Updating seed.json only (no app reinstall)
If only the device config needs updating (e.g. changing `event_device_id` or `onsite_api_base_url`):
```bash
ssh "speaker ready"@192.168.32.103 "cat > ~/seed.json" << 'EOF'
{ ... }
EOF
```
No need to re-copy the `.app`. Restart the Electron app after writing the new seed.
### Deploy to multiple laptops at once
Repeat Steps 23 for each laptop, or use a loop:
```bash
for OCTET in 103 104 105 106; do
echo "=== Deploying to 192.168.32.$OCTET ==="
scp -r builds/aether_launcher-darwin-x64/aether_launcher.app \
"speaker ready"@192.168.32.$OCTET:/Applications/aether_launcher.app
done
```
`seed.json` must still be written per-device (each has a unique `event_device_id`).
### Adding SSH key to a new laptop (first time only)
```bash
ssh-copy-id "speaker ready"@192.168.32.1XX
```
Run once per laptop before attempting any of the deploy steps above.
---
## 📋 Device Reference
| Laptop | IP Address | event_device_id | Notes |
|--------|------------------|-----------------|--------------------------|
| 01 | 192.168.32.101 | tFLL1fLQfnk | |
| 02 | 192.168.32.102 | rpbfunVPEzw | |
| 03 | 192.168.32.103 | 1EPfPX8kfw8 | |
| 04 | 192.168.32.104 | zvgyLM5yieU | |
| 05 | 192.168.32.105 | QOc046GoeSc | |
| 06 | 192.168.32.106 | 2o8j6eb0L6s | |
| 07 | 192.168.32.107 | Oa1tlxPEVSQ | |
| 08 | 192.168.32.108 | fY4yznpUZ48 | |
| 09 | 192.168.32.109 | YlgGCyjo9bY | |
| 10 | 192.168.32.110 | GcTnFsp1mHI | |
| 11 | 192.168.32.111 | 6z88m9oEZio | |
| 12 | 192.168.32.112 | EggJqL2kWkA | |
| 13 | 192.168.32.113 | O11eckHFdVE | |
| 14 | 192.168.32.114 | reI0SecUEhI | |
| 15 | 192.168.32.115 | crozxT8mA44 | |
| 16 | 192.168.32.116 | 0nP4VZsvr2Q | |
| 17 | 192.168.32.117 | Gm2gNqPGzLA | |
| 19 | 192.168.32.119 | 6tpukvRVugU | (no laptop 18) |
| x20 | 192.168.32.120 | rwLYnKUNd1M | old 04, spare/retired |
`aether_api_key`: all laptops share a single key per event deployment. The key is created in
the Aether admin panel before the show and deleted after. Check `builds/seed.json` for the
current key, or create a new one in Aether (Core → Accounts or Events → Devices API key section)
before each deployment.
---
## ⚙️ Configuration
The application requires a `seed.json` file to identify the device and connect to the Aether API.
### 1. Seed Configuration
**Location: `~/seed.json`** (user's home directory — external to the app bundle by design)
This file is intentionally kept outside the application bundle so it can be edited per-device
without re-signing or repackaging the app. On macOS this is `/Users/speaker ready/seed.json`.
Seed file format:
```json
{
"event_device_id": "tFLL1fLQfnk",
"aether_api_key": "YOUR_API_KEY",
"primary_api_base_url": "https://api.oneskyit.com",
"backup_api_base_url": "https://bak-api.oneskyit.com",
"onsite_api_base_url": null
}
```
`event_device_id` is the `id_random` from the Aether `event_device` record for that physical
laptop — see the Device Reference table above. `aether_api_key` is a shared key created per
event deployment and deleted after the show.
### 2. Development Setup
```bash
npm install
npm start # Compiles TypeScript (tsc) then launches Electron
```
### 3. File Cache Layout
Presentation files are cached locally under `hash_prefix_length`-char subdirectories (default: 2):
```text
[local_file_cache_path]/
4a/
4a228ef8ac1a...sha256hash...file
1d/
1d720916a831...sha256hash...file
```
**Important:** `hash_prefix_length` must be consistent. If it changes, files in old directories
become orphaned and will be re-downloaded. The default is `2` and should not be changed unless
explicitly coordinated across all devices.
## 🌉 The Native Bridge (`aetherNative`)
The bridge is exposed to the renderer via `contextBridge`. It can be accessed in the web UI via `window.aetherNative`.
### Core Methods
| Method | Description |
| --- | --- |
| `list_tools()` | Returns a JSON manifest of all available native functions. |
| `launch_presentation({path, app})` | Launches a presentation with auto-focus and slideshow start. |
| `control_presentation({app, action})` | Sends `next`, `prev`, `start`, or `stop` to active decks. |
| `open_folder(path)` | Opens a local directory in the OS file explorer. |
| `get_device_info()` | Returns hardware metadata (RAM, IPs, Hostname). |
### Example Usage (UI Relay)
```typescript
import * as native from '$lib/electron/electron_relay';
// Launch a file from local cache
await native.launch_presentation({
path: '[tmp]/my_deck.pptx',
app: 'powerpoint'
});
// Navigate slides
await native.control_presentation({
app: 'powerpoint',
action: 'next'
});
```
## 🛠️ Development
- **Preload:** Logic defined in `src/preload/index.ts`.
- **Handlers:** OS-level logic in `src/main/shell_handlers.ts` and `src/main/file_handlers.ts`.
- **Types:** Shared TypeScript interfaces in `src/shared/types.ts`.