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.3 KiB
Action Mapping CRUD Operations - Implementation Summary
Overview
Successfully implemented CREATE, READ, UPDATE, and DELETE operations for GeViSoft action mappings via gRPC API. Mappings created through the API are fully visible and editable in GeViSet.
Critical Discovery: The Secondary Flag
The breakthrough finding: GeViSet requires the secondary flag (@@) to be set to 100 for mappings to be visible in the UI.
Without @@ = 100, mappings exist in the configuration but are filtered out by GeViSet's display logic.
Complete Mapping Structure (for VideoInput mappings)
MappingRules/
{rule_id}/
# FILTERS (control which fields are active)
.SwitchMode = false (bool)
.VideoInput = true (bool)
.VideoOutput = false (bool)
# CAPTION AND FLAGS
@ = "Mapping Name" (string)
@! = 0 (int32) # Primary flag
@@ = 100 (int32) # Secondary flag - CRITICAL FOR VISIBILITY!
# OUTPUT ACTIONS
Rules/
0/
@ = "Action Name"
@! = 0
@@ = 0
GCoreAction = "ActionType" (or GscAction)
GCoreServer = "" (or GscServer)
1/
...
# FIELD VALUES (after Rules)
SwitchMode = 0 (int32)
VideoInput = 101027 (int32)
VideoOutput = 0 (int32)
API Operations
1. CREATE - Create New Action Mapping
import grpc
from protos import configuration_pb2, configuration_pb2_grpc
channel = grpc.insecure_channel('localhost:50051')
stub = configuration_pb2_grpc.ConfigurationServiceStub(channel)
# Define output actions
output1 = configuration_pb2.ActionDefinition(action="GCoreDataBase")
output2 = configuration_pb2.ActionDefinition(action="GscMail")
# Create mapping
mapping = configuration_pb2.ActionMappingInput(
name="My New Mapping",
video_input=101027, # Camera ID
output_actions=[output1, output2]
)
request = configuration_pb2.CreateActionMappingRequest(mapping=mapping)
response = stub.CreateActionMapping(request)
print(f"Success: {response.success}")
print(f"Message: {response.message}")
2. READ - List All Action Mappings
request = configuration_pb2.ReadActionMappingsRequest()
response = stub.ReadActionMappings(request)
print(f"Total mappings: {response.total_count}")
for mapping in response.mappings:
print(f" - {mapping.name}")
print(f" Input actions: {len(mapping.input_actions)}")
print(f" Output actions: {len(mapping.output_actions)}")
3. UPDATE - Modify Existing Mapping
# Update mapping ID 66 (1-based index)
updated_output = configuration_pb2.ActionDefinition(action="UpdatedAction")
update_mapping = configuration_pb2.ActionMappingInput(
name="Updated Name",
video_input=101028, # Changed camera
output_actions=[updated_output]
)
request = configuration_pb2.UpdateActionMappingRequest(
mapping_id=66,
mapping=update_mapping
)
response = stub.UpdateActionMapping(request)
print(f"Success: {response.success}")
4. DELETE - Remove Action Mapping
request = configuration_pb2.DeleteActionMappingRequest(mapping_id=66)
response = stub.DeleteActionMapping(request)
print(f"Success: {response.success}")
print(f"Message: {response.message}")
Key Implementation Details
Files Modified
-
ActionMappingManager.cs (
C:\DEV\COPILOT\geutebruck-api\src\sdk-bridge\GeViScopeBridge\Services\)- Added complete filter/field structure
- Set secondary flag to 100
- Made
CreateOutputFolderpublic for reuse in UPDATE
-
ConfigurationServiceImplementation.cs
- Implemented CREATE using FolderTreeParser/Writer
- Implemented UPDATE to modify existing mappings in folder tree
- Implemented DELETE to remove mappings from folder tree
-
configuration.proto
- Added
video_inputfield to ActionMappingInput
- Added
Folder Tree Approach
All operations use the FolderTreeParser and FolderTreeWriter classes to:
- Parse binary .set file into hierarchical folder structure
- Navigate to MappingRules folder
- Modify the folder tree (add/update/delete)
- Serialize back to binary
- Write to GeViServer
This approach maintains the complete configuration structure and ensures proper binary serialization.
Testing
Run Comprehensive CRUD Test
# 1. Disconnect from GeViSet
# 2. Start SDK bridge:
cd geutebruck-api/src/sdk-bridge/GeViScopeBridge
dotnet run
# 3. In another terminal:
python test_crud_operations.py
The test will:
- CREATE a new mapping
- READ and verify it exists
- UPDATE the mapping (change name and VideoInput)
- READ and verify the update
- DELETE the mapping
- READ and verify deletion
Verify in GeViSet
After CREATE/UPDATE operations:
- Reconnect to GeViSet
- Navigate to action mappings
- Verify the mapping is visible and editable
Connection Management
IMPORTANT: GeViSoft only allows ONE connection at a time.
- GeViSet connected = SDK bridge cannot connect
- SDK bridge connected = GeViSet cannot connect
Always disconnect from GeViSet before running SDK bridge operations.
GeViSet Display Requirements
For a mapping to be visible in GeViSet:
✅ Required:
- Secondary flag (
@@) = 100 - Caption (
@) with non-empty name - At least one filter enabled (
.VideoInput = true) - Corresponding field value (
VideoInputwith camera ID)
❌ Without these:
- Mapping exists in configuration
- API can read it
- But GeViSet filters it out (invisible in UI)
Performance Notes
- CREATE: Adds ~200-300 bytes to configuration
- UPDATE: Size change depends on what's modified
- DELETE: Reduces configuration size
- All operations write full configuration (~280KB)
Bulk Operations
For bulk creation (thousands of mappings):
# Read configuration once
response = stub.ReadActionMappings(configuration_pb2.ReadActionMappingsRequest())
initial_count = len(response.mappings)
# Create multiple mappings
for i in range(1000):
mapping = configuration_pb2.ActionMappingInput(
name=f"Bulk Mapping {i}",
video_input=101000 + i,
output_actions=[output1, output2]
)
request = configuration_pb2.CreateActionMappingRequest(mapping=mapping)
response = stub.CreateActionMapping(request)
if i % 100 == 0:
print(f"Created {i} mappings...")
Troubleshooting
Mapping not visible in GeViSet
Check:
- Secondary flag is 100
.VideoInputfilter is set to trueVideoInputfield has valid camera ID- Caption (
@) is non-empty
Connection refused
- Ensure GeViSet is disconnected
- Check GeViServer is running
- Verify port 50051 is available
Write operation succeeds but changes not persisted
- This is normal - GeViSoft may cache configuration
- Restart GeViSet to force reload
- Or use GeViSet's refresh functionality
Next Steps
Potential enhancements:
- Add input action support (for trigger conditions)
- Support for other filter/field types (beyond VideoInput)
- Batch operations endpoint
- Transaction support (create multiple mappings atomically)
- Validation of camera IDs and action names
Summary
All CRUD operations are now fully functional:
- ✅ CREATE - Add new mappings visible in GeViSet
- ✅ READ - List all mappings with full details
- ✅ UPDATE - Modify existing mappings
- ✅ DELETE - Remove mappings
The key breakthrough was discovering that @@ = 100 (secondary flag) is required for GeViSet visibility.