Files
geutebruck/test_geviset_parser.py
Administrator 14893e62a5 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>
2025-12-31 18:10:54 +01:00

202 lines
5.8 KiB
Python

#!/usr/bin/env python3
"""
Test and example script for GeViSet parser
This script demonstrates how to:
1. Parse a .set configuration file
2. Extract specific settings
3. Modify configuration
4. Generate a new .set file
"""
import sys
import json
from pathlib import Path
from geviset_parser import GeViSetParser, GeViSetGenerator
def test_parse(set_file_path):
"""Test parsing a .set file"""
print("=" * 80)
print("TEST 1: Parsing .set file")
print("=" * 80)
print()
parser = GeViSetParser()
config = parser.parse_file(set_file_path)
print("\nParsing Results:")
print(f" Top-level sections: {len(config)}")
print(f" Section names:")
for section_name in config.keys():
print(f" - {section_name}")
return config
def test_extract_users(config):
"""Test extracting user information"""
print("\n" + "=" * 80)
print("TEST 2: Extracting User Information")
print("=" * 80)
print()
if 'Users' not in config:
print(" No Users section found")
return
users_section = config['Users']
print(f" Users section metadata: {users_section.get('_metadata', {})}")
print(f"\n Users found:")
for key, value in users_section.items():
if key == '_metadata':
continue
if isinstance(value, dict):
print(f"\n User: {key}")
for prop_name, prop_value in value.items():
if prop_name == '_metadata':
print(f" Metadata: {prop_value}")
elif prop_name == 'Password':
# Truncate password hash for display
print(f" {prop_name}: {str(prop_value)[:16]}...")
else:
print(f" {prop_name}: {prop_value}")
def test_extract_network_settings(config):
"""Test extracting network settings"""
print("\n" + "=" * 80)
print("TEST 3: Extracting Network Settings")
print("=" * 80)
print()
# Look for GETAS section (network/TCP settings)
if 'GeViSoft Parameters' in config:
params = config['GeViSoft Parameters']
if 'GETAS' in params:
getas = params['GETAS']
print(" GETAS Configuration:")
for key, value in getas.items():
if key == '_metadata':
continue
print(f" {key}: {value}")
else:
print(" No GETAS section found")
else:
print(" No GeViSoft Parameters section found")
def test_modify_and_save(config, output_path):
"""Test modifying configuration and saving"""
print("\n" + "=" * 80)
print("TEST 4: Modifying and Saving Configuration")
print("=" * 80)
print()
# Create a copy to avoid modifying original
import copy
modified_config = copy.deepcopy(config)
# Example modification: Change GETAS TCP port
if 'GeViSoft Parameters' in modified_config:
if 'GETAS' in modified_config['GeViSoft Parameters']:
old_port = modified_config['GeViSoft Parameters']['GETAS'].get('TCPPort', 'N/A')
modified_config['GeViSoft Parameters']['GETAS']['TCPPort'] = 9999
print(f" Changed GETAS TCPPort: {old_port} -> 9999")
# Save modified configuration
generator = GeViSetGenerator()
generator.generate_file(modified_config, output_path)
print(f"\n Modified configuration saved to: {output_path}")
# Verify by re-parsing
print("\n Verifying modified file...")
parser2 = GeViSetParser()
verified_config = parser2.parse_file(output_path)
if 'GeViSoft Parameters' in verified_config:
if 'GETAS' in verified_config['GeViSoft Parameters']:
new_port = verified_config['GeViSoft Parameters']['GETAS'].get('TCPPort', 'N/A')
print(f" Verified TCPPort in new file: {new_port}")
if new_port == 9999:
print(" ✓ Modification successful!")
else:
print(" ✗ Modification failed!")
else:
print(" ✗ GETAS section missing in regenerated file")
else:
print(" ✗ GeViSoft Parameters missing in regenerated file")
def test_json_export(config, json_path):
"""Test exporting to JSON"""
print("\n" + "=" * 80)
print("TEST 5: Exporting to JSON")
print("=" * 80)
print()
# Convert to JSON
with open(json_path, 'w', encoding='utf-8') as f:
json.dump(config, f, indent=2, ensure_ascii=False)
print(f" Configuration exported to: {json_path}")
# Show file size
json_size = Path(json_path).stat().st_size
print(f" JSON file size: {json_size:,} bytes")
def main():
"""Main test function"""
if len(sys.argv) < 2:
print("Usage: python3 test_geviset_parser.py <path_to_config.set>")
print()
print("Example: python3 test_geviset_parser.py GeViSoft.set")
sys.exit(1)
set_file = Path(sys.argv[1])
if not set_file.exists():
print(f"Error: File not found: {set_file}")
sys.exit(1)
print(f"\nTesting GeViSet Parser with file: {set_file}")
print(f"File size: {set_file.stat().st_size:,} bytes")
print()
# Test 1: Parse
config = test_parse(set_file)
# Test 2: Extract users
test_extract_users(config)
# Test 3: Extract network settings
test_extract_network_settings(config)
# Test 4: Modify and save
output_file = set_file.parent / f"{set_file.stem}_modified{set_file.suffix}"
test_modify_and_save(config, output_file)
# Test 5: Export to JSON
json_file = set_file.parent / f"{set_file.stem}.json"
test_json_export(config, json_file)
print("\n" + "=" * 80)
print("ALL TESTS COMPLETE")
print("=" * 80)
print()
print("Generated files:")
print(f" - {output_file} (modified .set file)")
print(f" - {json_file} (JSON export)")
print()
if __name__ == '__main__':
main()