doc: port mapping implementation planning
This commit is contained in:
121
doc/plan/implementation-feature-port-mapping.md
Normal file
121
doc/plan/implementation-feature-port-mapping.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# KVM port configuration and switching
|
||||
|
||||
## Context
|
||||
|
||||
The Belkin OmniView fronts an Avocent KVM switch with up to 16 ports. The legacy web interface at `http://10.3.0.130` allows port naming, hotkey assignment, visibility toggling, and active port switching. Users currently need to visit that interface separately. We want blekin to fully replace it — starting with port management, with a navigation structure that supports adding more settings pages later.
|
||||
|
||||
## Belkin device API (from HTML form inspection)
|
||||
|
||||
**GET /kvm.asp** — returns HTML form with current port config:
|
||||
- `ECG_kvm_nr_ports`: port count (1,2,4,8,12,16,24,32,48,64)
|
||||
- `ECG_key_pause_duration`: ms (default 100)
|
||||
- Per port N (0-indexed): `ECG_kvm_portname_N`, `ECG_kvm_hotkey_N`, `ECG_kvm_show_in_rc_N`
|
||||
- `kvm_active_port_0`: currently selected port
|
||||
|
||||
**POST /kvm.asp** — save port config (same fields + `action_apply=Apply`)
|
||||
|
||||
**POST /home2.asp** — switch active port: `kvm_active_port_0=<0-15>&action_switch_0=Switch`
|
||||
|
||||
All requests require `pp_session_id` cookie.
|
||||
|
||||
## Changes
|
||||
|
||||
### Backend: persist session cookie
|
||||
|
||||
Modify `AppState` in `main.rs` to hold the device session cookie:
|
||||
```rust
|
||||
pub session_cookie: Arc<tokio::sync::RwLock<Option<String>>>,
|
||||
```
|
||||
|
||||
Update `login.rs` to store the cookie into shared state after successful auth.
|
||||
|
||||
### Backend: new REST endpoints (`crates/ericrfb-proxy/src/kvm.rs`)
|
||||
|
||||
| Endpoint | Method | Purpose |
|
||||
|----------|--------|---------|
|
||||
| `/api/kvm/ports` | GET | Fetch port config (scrape kvm.asp, return JSON) |
|
||||
| `/api/kvm/ports` | PUT | Save port config (build form, POST to kvm.asp) |
|
||||
| `/api/kvm/switch` | POST | Switch active port (POST to home2.asp) |
|
||||
|
||||
**GET /api/kvm/ports response:**
|
||||
```json
|
||||
{
|
||||
"port_count": 16,
|
||||
"key_pause_duration": 100,
|
||||
"active_port": 0,
|
||||
"ports": [
|
||||
{ "index": 0, "name": "oolon", "hotkey": "", "show_in_rc": true },
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
HTML scraping: simple string/regex matching on the predictable firmware HTML (extract `value="..."` from named inputs, `selected` from dropdowns, `checked` from checkboxes).
|
||||
|
||||
### Frontend: app shell with navigation (`crates/ericrfb-frontend/src/shell.ts`)
|
||||
|
||||
After login, render a shell layout:
|
||||
```
|
||||
+----------+----------------------------------+
|
||||
| sidebar | content area |
|
||||
| | |
|
||||
| Console | (active page rendered here) |
|
||||
| Ports | |
|
||||
| | |
|
||||
+----------+----------------------------------+
|
||||
```
|
||||
|
||||
Each page module exports `mount(container)` and `unmount()`. The shell swaps them on nav clicks. This pattern supports adding Virtual Media, Users, Device Settings etc. later without restructuring.
|
||||
|
||||
### Frontend: refactor console into page module
|
||||
|
||||
Move `console.ts` logic into a `pages/console.ts` with mount/unmount pattern:
|
||||
- `mount(el, session)`: creates toolbar + canvas, connects WebSocket
|
||||
- `unmount()`: tears down WebSocket, removes event listeners
|
||||
|
||||
Add port switcher `<select>` to the console toolbar (fetches port list from `/api/kvm/ports`, calls `/api/kvm/switch` on change, triggers reconnect).
|
||||
|
||||
### Frontend: port config page (`crates/ericrfb-frontend/src/pages/ports.ts`)
|
||||
|
||||
Editable table of ports with name, hotkey, show-in-console fields. Port count dropdown and key-pause input at the top. Save button PUTs to `/api/kvm/ports`. Each row has a Switch button that POSTs to `/api/kvm/switch`. Active port highlighted.
|
||||
|
||||
## Files
|
||||
|
||||
### New
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `crates/ericrfb-proxy/src/kvm.rs` | GET/PUT ports, POST switch, HTML scraping |
|
||||
| `crates/ericrfb-frontend/src/shell.ts` | App shell, sidebar nav, page routing |
|
||||
| `crates/ericrfb-frontend/src/pages/console.ts` | Console page (refactored from console.ts) |
|
||||
| `crates/ericrfb-frontend/src/pages/ports.ts` | Port configuration page |
|
||||
|
||||
### Modified
|
||||
| File | Changes |
|
||||
|------|---------|
|
||||
| `crates/ericrfb-proxy/src/main.rs` | session_cookie in AppState, new routes, `mod kvm` |
|
||||
| `crates/ericrfb-proxy/src/login.rs` | Store cookie in shared state after auth |
|
||||
| `crates/ericrfb-proxy/Cargo.toml` | Add `regex = "1"` |
|
||||
| `crates/ericrfb-frontend/src/main.ts` | After login → mountShell() instead of startConsole() |
|
||||
| `crates/ericrfb-frontend/src/login.ts` | Success callback → shell mount |
|
||||
| `crates/ericrfb-frontend/src/style.css` | Shell layout, sidebar, ports page styles |
|
||||
| `crates/ericrfb-frontend/src/console.ts` | Delete or re-export from pages/console.ts |
|
||||
|
||||
## Implementation order
|
||||
|
||||
1. Backend: session cookie persistence in AppState + login.rs
|
||||
2. Backend: kvm.rs with three endpoints, test with curl
|
||||
3. Frontend: shell.ts with sidebar navigation
|
||||
4. Frontend: refactor console.ts → pages/console.ts with mount/unmount
|
||||
5. Frontend: pages/ports.ts wired to API
|
||||
6. Frontend: port switcher dropdown in console toolbar
|
||||
|
||||
## Verification
|
||||
|
||||
- `cargo test && cargo clippy` pass
|
||||
- `npx tsc --noEmit` passes
|
||||
- `curl /api/kvm/ports` returns correct JSON matching device state
|
||||
- `curl -X POST /api/kvm/switch -d '{"port":0}'` switches the active port
|
||||
- `curl -X PUT /api/kvm/ports` with config JSON updates port names on device
|
||||
- Frontend: navigate between Console and Ports pages without breaking WebSocket
|
||||
- Frontend: switch port from console toolbar, console reconnects to new port
|
||||
- Frontend: edit port names in Ports page, save, verify on device
|
||||
Reference in New Issue
Block a user