feat: add ue_scene websocket integration

This commit is contained in:
opencode
2026-05-09 11:32:07 +08:00
parent 61baee00f6
commit 8f67d8d108
12 changed files with 2684 additions and 49 deletions

View File

@@ -0,0 +1,134 @@
param(
[string]$BaseUrl = "http://localhost:8000",
[string]$Username,
[string]$Password,
[int]$ReadMessageCount = 5
)
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
if ([string]::IsNullOrWhiteSpace($Username) -or [string]::IsNullOrWhiteSpace($Password)) {
throw "Missing username/password. Pass -Username and -Password."
}
Add-Type -AssemblyName System.Net.Http
function Read-WebSocketMessage {
param(
[System.Net.WebSockets.ClientWebSocket]$Socket
)
$buffer = New-Object byte[] 8192
$segment = [System.ArraySegment[byte]]::new($buffer)
$builder = New-Object System.Text.StringBuilder
do {
$result = $Socket.ReceiveAsync($segment, [Threading.CancellationToken]::None).GetAwaiter().GetResult()
if ($result.MessageType -eq [System.Net.WebSockets.WebSocketMessageType]::Close) {
return $null
}
$builder.Append([System.Text.Encoding]::UTF8.GetString($buffer, 0, $result.Count)) | Out-Null
} while (-not $result.EndOfMessage)
return $builder.ToString()
}
$loginUri = "$BaseUrl/api/v1/auth/login"
$loginBody = "username=$([uri]::EscapeDataString($Username))&password=$([uri]::EscapeDataString($Password))"
Write-Host "Requesting access token from $loginUri ..."
$tokenResponse = Invoke-RestMethod `
-Method Post `
-Uri $loginUri `
-ContentType "application/x-www-form-urlencoded" `
-Body $loginBody
if (-not $tokenResponse.access_token) {
throw "Login succeeded but access_token missing."
}
$accessToken = [string]$tokenResponse.access_token
Write-Host "Token acquired. Expires in: $($tokenResponse.expires_in)"
$wsBase = $BaseUrl -replace "^http", "ws"
$wsUri = "$wsBase/ws?token=$accessToken"
$socket = [System.Net.WebSockets.ClientWebSocket]::new()
$socket.Options.KeepAliveInterval = [TimeSpan]::FromSeconds(20)
Write-Host "Connecting WebSocket: $wsUri"
$socket.ConnectAsync([Uri]$wsUri, [Threading.CancellationToken]::None).GetAwaiter().GetResult()
Write-Host "WebSocket connected."
try {
$initial = Read-WebSocketMessage -Socket $socket
if ($null -ne $initial) {
Write-Host ""
Write-Host "=== connection_established ==="
Write-Host $initial
}
$subscribeFrame = @{
type = "subscribe"
data = @{
channels = @("ue_scene")
}
} | ConvertTo-Json -Depth 8 -Compress
$subscribeBytes = [System.Text.Encoding]::UTF8.GetBytes($subscribeFrame)
$subscribeSegment = [System.ArraySegment[byte]]::new($subscribeBytes)
$socket.SendAsync(
$subscribeSegment,
[System.Net.WebSockets.WebSocketMessageType]::Text,
$true,
[Threading.CancellationToken]::None
).GetAwaiter().GetResult()
$subAck = Read-WebSocketMessage -Socket $socket
if ($null -ne $subAck) {
Write-Host ""
Write-Host "=== subscription_confirmed ==="
Write-Host $subAck
}
$syncFrame = @{
type = "sync_request"
data = @{
channel = "ue_scene"
reason = "initial_connect"
last_sequence = $null
}
} | ConvertTo-Json -Depth 8 -Compress
$syncBytes = [System.Text.Encoding]::UTF8.GetBytes($syncFrame)
$syncSegment = [System.ArraySegment[byte]]::new($syncBytes)
$socket.SendAsync(
$syncSegment,
[System.Net.WebSockets.WebSocketMessageType]::Text,
$true,
[Threading.CancellationToken]::None
).GetAwaiter().GetResult()
for ($i = 1; $i -le $ReadMessageCount; $i++) {
$message = Read-WebSocketMessage -Socket $socket
if ($null -eq $message) {
break
}
Write-Host ""
Write-Host "=== message $i ==="
Write-Host $message
}
}
finally {
if ($socket.State -eq [System.Net.WebSockets.WebSocketState]::Open) {
$socket.CloseAsync(
[System.Net.WebSockets.WebSocketCloseStatus]::NormalClosure,
"done",
[Threading.CancellationToken]::None
).GetAwaiter().GetResult()
}
$socket.Dispose()
}