Skip to content

Commit d694505

Browse files
committed
feat: add G Hub WebSocket explorer script for LED discovery
1 parent 379940e commit d694505

File tree

1 file changed

+186
-0
lines changed

1 file changed

+186
-0
lines changed

tools/ghub_websocket_test.ps1

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
# G Hub WebSocket Explorer - FFBArcadePlugin
2+
# Connects to lghub_agent.exe WebSocket and explores available commands
3+
# Requires: G Hub running, PowerShell 5.1+
4+
5+
Add-Type -AssemblyName System.Net.WebSockets
6+
7+
$ws = New-Object System.Net.WebSockets.ClientWebSocket
8+
$ws.Options.AddSubProtocol("json")
9+
10+
$uri = [Uri]"ws://localhost:9010"
11+
$cts = New-Object System.Threading.CancellationTokenSource
12+
13+
Write-Host ""
14+
Write-Host "=== G Hub WebSocket Explorer ==="
15+
Write-Host "Connecting to $uri..."
16+
Write-Host ""
17+
18+
try {
19+
$task = $ws.ConnectAsync($uri, $cts.Token)
20+
if (-not $task.Wait(5000)) {
21+
Write-Host "ERROR: Connection timeout (5s)"
22+
Read-Host "Appuie sur Entree"
23+
exit 1
24+
}
25+
if ($task.IsFaulted) { throw $task.Exception }
26+
Write-Host "Connected! State: $($ws.State)"
27+
} catch {
28+
Write-Host "Connection failed: $_"
29+
Write-Host ""
30+
Write-Host "G Hub is running? Check if lghub_agent.exe is in Task Manager."
31+
Read-Host "Appuie sur Entree"
32+
exit 1
33+
}
34+
35+
function Send-WS($json) {
36+
$bytes = [System.Text.Encoding]::UTF8.GetBytes($json)
37+
$segment = New-Object System.ArraySegment[byte](,$bytes)
38+
$task = $ws.SendAsync($segment, [System.Net.WebSockets.WebSocketMessageType]::Text, $true, $cts.Token)
39+
$task.Wait(3000) | Out-Null
40+
}
41+
42+
function Recv-WS {
43+
$buffer = New-Object byte[] 131072
44+
$result = ""
45+
$timeoutCts = New-Object System.Threading.CancellationTokenSource
46+
$timeoutCts.CancelAfter(3000) # 3s timeout per receive
47+
48+
try {
49+
do {
50+
$segment = New-Object System.ArraySegment[byte](,$buffer)
51+
$task = $ws.ReceiveAsync($segment, $timeoutCts.Token)
52+
$task.Wait() | Out-Null
53+
$recv = $task.Result
54+
$result += [System.Text.Encoding]::UTF8.GetString($buffer, 0, $recv.Count)
55+
} while (-not $recv.EndOfMessage)
56+
return $result
57+
} catch {
58+
if ($result.Length -gt 0) { return $result }
59+
return $null
60+
}
61+
}
62+
63+
function Test-Endpoint($id, $verb, $path, $payload) {
64+
Write-Host "--- [$id] $verb $path ---"
65+
66+
$msg = @{ msgId = "$id"; verb = $verb; path = $path }
67+
if ($payload) { $msg.payload = $payload }
68+
$json = $msg | ConvertTo-Json -Compress -Depth 5
69+
70+
Send-WS $json
71+
$resp = Recv-WS
72+
73+
if ($resp) {
74+
Write-Host $resp
75+
} else {
76+
Write-Host " (no response / timeout)"
77+
}
78+
Write-Host ""
79+
}
80+
81+
$id = 1
82+
83+
# ============================================================
84+
# PHASE 1: Device discovery
85+
# ============================================================
86+
Write-Host ""
87+
Write-Host "========================================"
88+
Write-Host "PHASE 1: Device Discovery"
89+
Write-Host "========================================"
90+
Write-Host ""
91+
92+
Test-Endpoint ($id++) "GET" "/devices/list" $null
93+
Test-Endpoint ($id++) "GET" "/devices/state" $null
94+
Test-Endpoint ($id++) "GET" "/api/v1/devices/list" $null
95+
96+
# ============================================================
97+
# PHASE 2: Integration registration
98+
# ============================================================
99+
Write-Host "========================================"
100+
Write-Host "PHASE 2: Integration Registration"
101+
Write-Host "========================================"
102+
Write-Host ""
103+
104+
$regPayload = @{
105+
integrationIdentifier = "ffb_arcade_plugin"
106+
name = "FFB Arcade Plugin"
107+
author = "FFBArcade"
108+
description = "LED control for racing wheels"
109+
manualRegistration = $true
110+
}
111+
Test-Endpoint ($id++) "SET" "/api/v1/integration/register" $regPayload
112+
113+
# Try activation with different SDK types
114+
$sdkTypes = @("ACTION", "LED", "LIGHTSYNC", "STEERING", "WHEEL", "LIGHTING", "SCREEN_SAMPLER")
115+
foreach ($st in $sdkTypes) {
116+
$actPayload = @{
117+
integrationIdentifier = "ffb_arcade_plugin"
118+
sdkType = $st
119+
}
120+
Test-Endpoint ($id++) "SET" "/api/v1/integration/activate" $actPayload
121+
}
122+
123+
# ============================================================
124+
# PHASE 3: Explore lighting/LED endpoints
125+
# ============================================================
126+
Write-Host "========================================"
127+
Write-Host "PHASE 3: Lighting Endpoints"
128+
Write-Host "========================================"
129+
Write-Host ""
130+
131+
$lightingPaths = @(
132+
@("GET", "/lighting/state"),
133+
@("GET", "/lighting/devices"),
134+
@("GET", "/lighting/effects"),
135+
@("GET", "/api/v1/lighting/state"),
136+
@("GET", "/api/v1/lighting/devices"),
137+
@("GET", "/lightsync/state"),
138+
@("GET", "/lightsync/devices"),
139+
@("GET", "/profiles/current"),
140+
@("GET", "/profiles/list"),
141+
@("GET", "/api/v1/profiles/current"),
142+
@("GET", "/api/v1/profiles/list"),
143+
@("GET", "/features/list"),
144+
@("GET", "/api/v1/features/list"),
145+
@("GET", "/steering/state"),
146+
@("GET", "/wheel/state"),
147+
@("GET", "/sdk/state"),
148+
@("GET", "/api/v1/sdk/state")
149+
)
150+
151+
foreach ($ep in $lightingPaths) {
152+
Test-Endpoint ($id++) $ep[0] $ep[1] $null
153+
}
154+
155+
# ============================================================
156+
# PHASE 4: Try SET commands for LED control
157+
# ============================================================
158+
Write-Host "========================================"
159+
Write-Host "PHASE 4: LED Control Attempts"
160+
Write-Host "========================================"
161+
Write-Host ""
162+
163+
# Try setting lighting on various paths
164+
$ledPayload = @{ red = 0; green = 100; blue = 0 }
165+
Test-Endpoint ($id++) "SET" "/lighting/color" $ledPayload
166+
Test-Endpoint ($id++) "SET" "/api/v1/lighting/color" $ledPayload
167+
168+
$zonePayload = @{ deviceType = "steering_wheel"; zone = 0; red = 0; green = 100; blue = 0 }
169+
Test-Endpoint ($id++) "SET" "/lighting/zone" $zonePayload
170+
171+
$ledPayload2 = @{ leds = 31; device = "steering_wheel" }
172+
Test-Endpoint ($id++) "SET" "/steering/leds" $ledPayload2
173+
Test-Endpoint ($id++) "SET" "/wheel/leds" $ledPayload2
174+
175+
# ============================================================
176+
# Cleanup
177+
# ============================================================
178+
Write-Host "========================================"
179+
Write-Host "Done! Copy-paste ALL output above."
180+
Write-Host "========================================"
181+
182+
try {
183+
$ws.CloseAsync([System.Net.WebSockets.WebSocketCloseStatus]::NormalClosure, "done", $cts.Token).Wait(3000) | Out-Null
184+
} catch { }
185+
186+
Read-Host "Appuie sur Entree pour fermer"

0 commit comments

Comments
 (0)