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>
7.1 KiB
7.1 KiB
Action Mapping Binary Structure - Complete Guide
Summary
Based on analysis of TestMKS_original.set vs TestMKS_added_mapping.set, this document explains how action mappings are stored and how to programmatically add thousands of them.
Binary Structure
Overall Format
MARKER SECTION:
├─ 'ules' (4 bytes) - Action mapping marker
├─ Length (4 bytes, little-endian) - Length of marker name/data section
└─ Marker Name/Data Section (variable length)
├─ Metadata bytes
├─ Properties (optional, multiple)
│ └─ Each property: 01 <len> <.name> <value_marker> <value>
└─ Additional metadata
ACTION SECTION (follows marker section):
├─ Action Entry 1
│ ├─ Entry number (01 for first, 02 for second, etc.)
│ ├─ Metadata: 05 00 00 00
│ ├─ Action data: 07 01 40 <len_u16_LE> <action_string>
│ └─ Additional metadata (varies)
├─ Action Entry 2
│ └─ (same structure)
└─ ...
NEXT MARKER:
└─ 05 'Rules' or next 'ules' marker
Example 1: Simple Mapping (No Parameters)
Hex Dump (offset 0x41433):
75 6C 65 73 - 'ules' marker
02 00 00 00 - Length: 2 bytes
00 01 - Marker data (2 bytes)
31 05 00 00 00 - Action entry #1 metadata
07 01 40 - Action marker
0B 00 - Length: 11 bytes (little-endian)
47 53 43 20 50 61 6E 4C 65 66 74 - "GSC PanLeft"
...
Example 2: Mapping with Parameters
Hex Dump (offset 0x3D90D):
75 6C 65 73 - 'ules' marker
40 00 00 00 - Length: 64 bytes
00 01 - Start of marker data
# Properties within marker data:
01 - Property marker
0B - Name length: 11
2E 53 77 69 74 63 68 4D 6F 64 65 - ".SwitchMode"
00 - Value type: null
01 - Property marker
0C - Name length: 12
2E 56 69 64 65 6F 4F 75 74 70 75 74 - ".VideoOutput"
00 - Value type: null
# Then actions follow...
Property Value Types
| Marker | Type | Structure |
|---|---|---|
0x01 |
Boolean | 01 <value> where value is 00 or 01 |
0x04 |
Integer | 04 <int32_LE> (4 bytes, little-endian) |
0x00 |
Null | Just 00 |
0x07 |
String | 07 <len> <string_bytes> |
Action Entry Format
Each action entry consists of:
<entry_number> - 01, 02, 03, etc. (sequential)
05 00 00 00 - Metadata (always this sequence)
07 01 40 - Action marker (always this sequence)
<length> - 2 bytes, little-endian (length of action string)
<action_name> - UTF-8 encoded action name
04 02 40 21 00 00 00 00 - Additional metadata
04 02 40 40 <4 bytes> - More metadata (varies)
Key Findings
1. File Reorganization
When you add a mapping using GeViSoft GUI:
- The entire .set file is reorganized
- All offsets change
- Mappings may be reordered
- Net result: +1 mapping but many bytes change
This means you cannot simply append to the end of the file!
2. Insertion Strategy
To programmatically add mappings:
Option A: Parse → Modify → Rebuild
- Parse the entire .set file
- Add new mapping to internal structure
- Regenerate the entire file
- Write back to disk
Option B: Use GeViSoft API (if available)
- Use SetupClient API to modify configuration
- Let GeViSoft handle file format
Option C: Template-Based (recommended for bulk)
- Create template mappings in GUI
- Export configuration
- Use find/replace to duplicate with new IDs
- Import back
3. Complexity Factors
- Offsets must be recalculated
- File structure is tightly packed
- No obvious "free space" to insert data
- Dependencies between sections unknown
- Checksum or validation may exist
Programmatic Approach
Step 1: Create Mapping Binary Data
def create_action_mapping(actions, parameters=None):
"""
Generate binary data for an action mapping
Args:
actions: List of action strings
parameters: Dict of parameter_name -> value (optional)
Returns:
bytes: Complete mapping binary data
"""
import struct
# Build marker name/data section
marker_data = bytearray()
marker_data.extend(b'\x00\x01') # Base metadata
# Add parameters if any
if parameters:
for name, value in parameters.items():
# Property marker
marker_data.append(0x01)
# Name with leading dot
name_with_dot = f".{name}"
name_bytes = name_with_dot.encode('utf-8')
marker_data.append(len(name_bytes))
marker_data.extend(name_bytes)
# Value
if value is None:
marker_data.append(0x00)
elif isinstance(value, bool):
marker_data.append(0x01)
marker_data.append(0x01 if value else 0x00)
elif isinstance(value, int):
marker_data.append(0x04)
marker_data.extend(struct.pack('<i', value))
# Build complete marker section
result = bytearray()
result.extend(b'ules') # Marker
result.extend(struct.pack('<I', len(marker_data))) # Length
result.extend(marker_data) # Data
# Add actions
for i, action in enumerate(actions, 1):
# Entry number
result.append(i)
# Metadata
result.extend(b'\x05\x00\x00\x00')
# Action marker
result.extend(b'\x07\x01\x40')
# Action length and string
action_bytes = action.encode('utf-8')
result.extend(struct.pack('<H', len(action_bytes)))
result.extend(action_bytes)
# Additional metadata (simplified)
result.extend(b'\x04\x02\x40\x21\x00\x00\x00\x00')
result.extend(b'\x04\x02\x40\x40\x00\x10\x00\x00')
return bytes(result)
Step 2: Insert into Configuration
The recommended approach is to:
- Read entire configuration using existing parser
- Add new mapping to internal structure
- Regenerate file using configuration writer
Practical Recommendations
For Adding Thousands of Mappings
Best Approach:
-
Use C# SDK + Configuration API
// Pseudo-code var config = parser.Parse(file); for (int i = 0; i < 1000; i++) { var mapping = new ActionMapping { Actions = new[] { $"Action_{i}" }, Parameters = new Dictionary<string, object>() }; config.AddMapping(mapping); } writer.Write(config, outputFile); -
Batch Process via GUI Templates
- Create 1 mapping template in GUI
- Export configuration as JSON/XML (if supported)
- Programmatically duplicate + modify
- Import back
-
Direct Binary Manipulation (risky!)
- Parse existing file completely
- Understand all section dependencies
- Insert mappings
- Rebuild file with correct offsets
Next Steps
For your use case (adding thousands of mappings), I recommend:
- Extend C# Parser to support WRITING (currently read-only)
- Create AddActionMapping() method in ConfigurationService
- Batch add via gRPC/REST API
- Write back to .set file
Would you like me to:
- Create C# writer for .set files
- Build Python script for bulk mapping creation
- Extend the gRPC API to support CREATE operations
- Create a bulk import tool (CSV → action mappings)