feat: Geutebruck GeViScope/GeViSoft Action Mapping System - MVP
This MVP release provides a complete full-stack solution for managing action mappings in Geutebruck's GeViScope and GeViSoft video surveillance systems. ## Features ### Flutter Web Application (Port 8081) - Modern, responsive UI for managing action mappings - Action picker dialog with full parameter configuration - Support for both GSC (GeViScope) and G-Core server actions - Consistent UI for input and output actions with edit/delete capabilities - Real-time action mapping creation, editing, and deletion - Server categorization (GSC: prefix for GeViScope, G-Core: prefix for G-Core servers) ### FastAPI REST Backend (Port 8000) - RESTful API for action mapping CRUD operations - Action template service with comprehensive action catalog (247 actions) - Server management (G-Core and GeViScope servers) - Configuration tree reading and writing - JWT authentication with role-based access control - PostgreSQL database integration ### C# SDK Bridge (gRPC, Port 50051) - Native integration with GeViSoft SDK (GeViProcAPINET_4_0.dll) - Action mapping creation with correct binary format - Support for GSC and G-Core action types - Proper Camera parameter inclusion in action strings (fixes CrossSwitch bug) - Action ID lookup table with server-specific action IDs - Configuration reading/writing via SetupClient ## Bug Fixes - **CrossSwitch Bug**: GSC and G-Core actions now correctly display camera/PTZ head parameters in GeViSet - Action strings now include Camera parameter: `@ PanLeft (Comment: "", Camera: 101028)` - Proper filter flags and VideoInput=0 for action mappings - Correct action ID assignment (4198 for GSC, 9294 for G-Core PanLeft) ## Technical Stack - **Frontend**: Flutter Web, Dart, Dio HTTP client - **Backend**: Python FastAPI, PostgreSQL, Redis - **SDK Bridge**: C# .NET 8.0, gRPC, GeViSoft SDK - **Authentication**: JWT tokens - **Configuration**: GeViSoft .set files (binary format) ## Credentials - GeViSoft/GeViScope: username=sysadmin, password=masterkey - Default admin: username=admin, password=admin123 ## Deployment All services run on localhost: - Flutter Web: http://localhost:8081 - FastAPI: http://localhost:8000 - SDK Bridge gRPC: localhost:50051 - GeViServer: localhost (default port) Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
206
Parse-GeViSet-Simple.ps1
Normal file
206
Parse-GeViSet-Simple.ps1
Normal file
@@ -0,0 +1,206 @@
|
||||
# Simple GeViSet parser - reads and displays configuration structure
|
||||
|
||||
param(
|
||||
[string]$FilePath = "C:\Users\Administrator\Desktop\GeViSoft.set",
|
||||
[string]$OutputJson = ""
|
||||
)
|
||||
|
||||
$data = [System.IO.File]::ReadAllBytes($FilePath)
|
||||
$pos = 0
|
||||
$config = [ordered]@{}
|
||||
|
||||
function Read-Byte {
|
||||
if ($script:pos -ge $script:data.Length) { throw "EOF" }
|
||||
$b = $script:data[$script:pos]
|
||||
$script:pos++
|
||||
return $b
|
||||
}
|
||||
|
||||
function Read-UInt16 {
|
||||
$bytes = $script:data[$script:pos..($script:pos+1)]
|
||||
$script:pos += 2
|
||||
return [BitConverter]::ToUInt16($bytes, 0)
|
||||
}
|
||||
|
||||
function Read-UInt32 {
|
||||
$bytes = $script:data[$script:pos..($script:pos+3)]
|
||||
$script:pos += 4
|
||||
return [BitConverter]::ToUInt32($bytes, 0)
|
||||
}
|
||||
|
||||
function Read-UInt64 {
|
||||
$bytes = $script:data[$script:pos..($script:pos+7)]
|
||||
$script:pos += 8
|
||||
return [BitConverter]::ToUInt64($bytes, 0)
|
||||
}
|
||||
|
||||
function Read-String {
|
||||
param([int]$lengthBytes)
|
||||
|
||||
if ($lengthBytes -eq 1) {
|
||||
$length = Read-Byte
|
||||
} else {
|
||||
$length = Read-UInt16
|
||||
}
|
||||
|
||||
if ($length -eq 0) { return "" }
|
||||
|
||||
$stringData = $script:data[$script:pos..($script:pos + $length - 1)]
|
||||
$script:pos += $length
|
||||
|
||||
try {
|
||||
return [System.Text.Encoding]::UTF8.GetString($stringData)
|
||||
} catch {
|
||||
return [System.Text.Encoding]::GetEncoding("ISO-8859-1").GetString($stringData)
|
||||
}
|
||||
}
|
||||
|
||||
function Read-Value {
|
||||
param([byte]$type)
|
||||
|
||||
switch ($type) {
|
||||
0x01 { return [bool](Read-Byte) }
|
||||
0x04 { return Read-UInt32 }
|
||||
0x02 { return Read-UInt64 }
|
||||
0x08 { return Read-String -lengthBytes 2 }
|
||||
default { throw "Unknown type: 0x$($type.ToString('X2'))" }
|
||||
}
|
||||
}
|
||||
|
||||
function Read-Section {
|
||||
param([string]$name, [int]$indent = 0)
|
||||
|
||||
$section = [ordered]@{}
|
||||
$prefix = " " * $indent
|
||||
|
||||
# Read metadata (int32 + byte)
|
||||
try {
|
||||
$metaInt = Read-UInt32
|
||||
$metaByte = Read-Byte
|
||||
$section['_meta'] = @{value=$metaInt; flags=$metaByte}
|
||||
Write-Host "$prefix [Metadata: value=$metaInt, flags=$metaByte]" -ForegroundColor DarkGray
|
||||
} catch {
|
||||
Write-Warning "Failed to read metadata for section '$name'"
|
||||
return $section
|
||||
}
|
||||
|
||||
$maxIterations = 10000
|
||||
$iterations = 0
|
||||
|
||||
while ($script:pos -lt $script:data.Length -and $iterations -lt $maxIterations) {
|
||||
$iterations++
|
||||
|
||||
try {
|
||||
$typeMarker = $script:data[$script:pos]
|
||||
} catch {
|
||||
break
|
||||
}
|
||||
|
||||
if ($typeMarker -eq 0x00) {
|
||||
# Section
|
||||
Read-Byte | Out-Null
|
||||
$subName = Read-String -lengthBytes 1
|
||||
|
||||
if ([string]::IsNullOrEmpty($subName)) {
|
||||
# End of section
|
||||
if ($script:pos + 3 -lt $script:data.Length) {
|
||||
$script:pos += 4
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
Write-Host "$prefix [$subName]" -ForegroundColor Cyan
|
||||
$section[$subName] = Read-Section -name $subName -indent ($indent + 1)
|
||||
|
||||
} elseif ($typeMarker -eq 0x07) {
|
||||
# Property
|
||||
Read-Byte | Out-Null
|
||||
$propName = Read-String -lengthBytes 1
|
||||
|
||||
if ([string]::IsNullOrEmpty($propName)) {
|
||||
continue
|
||||
}
|
||||
|
||||
try {
|
||||
$valueType = Read-Byte
|
||||
$value = Read-Value -type $valueType
|
||||
$section[$propName] = $value
|
||||
|
||||
$valueStr = if ($value -is [string] -and $value.Length -gt 50) {
|
||||
$value.Substring(0, 47) + "..."
|
||||
} else {
|
||||
$value
|
||||
}
|
||||
|
||||
Write-Host "$prefix $propName = $valueStr" -ForegroundColor Green
|
||||
} catch {
|
||||
Write-Warning "$prefix Failed to read property: $propName"
|
||||
break
|
||||
}
|
||||
|
||||
} else {
|
||||
# Unknown or end
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if ($iterations -ge $maxIterations) {
|
||||
Write-Warning "Max iterations reached in section '$name'"
|
||||
}
|
||||
|
||||
return $section
|
||||
}
|
||||
|
||||
Write-Host "=" * 80 -ForegroundColor Yellow
|
||||
Write-Host "Parsing GeViSet Configuration File" -ForegroundColor Yellow
|
||||
Write-Host "=" * 80 -ForegroundColor Yellow
|
||||
Write-Host "File: $FilePath"
|
||||
Write-Host "Size: $($data.Length) bytes"
|
||||
Write-Host ""
|
||||
|
||||
$topLevelSections = 0
|
||||
|
||||
while ($pos -lt $data.Length) {
|
||||
try {
|
||||
$typeMarker = $data[$pos]
|
||||
|
||||
if ($typeMarker -eq 0x00) {
|
||||
Read-Byte | Out-Null
|
||||
$sectionName = Read-String -lengthBytes 1
|
||||
|
||||
if ([string]::IsNullOrEmpty($sectionName)) {
|
||||
if ($pos -ge $data.Length - 10) { break }
|
||||
continue
|
||||
}
|
||||
|
||||
$topLevelSections++
|
||||
Write-Host ""
|
||||
Write-Host "[$sectionName]" -ForegroundColor Yellow
|
||||
$config[$sectionName] = Read-Section -name $sectionName -indent 0
|
||||
|
||||
} else {
|
||||
if ($pos -ge $data.Length - 10) { break }
|
||||
$pos++
|
||||
}
|
||||
} catch {
|
||||
if ($_.Exception.Message -ne "EOF") {
|
||||
Write-Warning "Error at position $pos : $_"
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "=" * 80 -ForegroundColor Yellow
|
||||
Write-Host "Parsing Complete" -ForegroundColor Green
|
||||
Write-Host "Top-level sections: $topLevelSections" -ForegroundColor Green
|
||||
Write-Host "=" * 80 -ForegroundColor Yellow
|
||||
|
||||
if ($OutputJson) {
|
||||
Write-Host ""
|
||||
Write-Host "Exporting to JSON: $OutputJson" -ForegroundColor Cyan
|
||||
$config | ConvertTo-Json -Depth 100 | Set-Content -Path $OutputJson -Encoding UTF8
|
||||
Write-Host "JSON export complete." -ForegroundColor Green
|
||||
}
|
||||
|
||||
return $config
|
||||
Reference in New Issue
Block a user