Files
geutebruck/ACTION_MAPPING_CRUD_SUMMARY.md
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

270 lines
7.3 KiB
Markdown

# 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
```python
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
```python
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
```python
# 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
```python
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
1. **ActionMappingManager.cs** (`C:\DEV\COPILOT\geutebruck-api\src\sdk-bridge\GeViScopeBridge\Services\`)
- Added complete filter/field structure
- Set secondary flag to 100
- Made `CreateOutputFolder` public for reuse in UPDATE
2. **ConfigurationServiceImplementation.cs**
- Implemented CREATE using FolderTreeParser/Writer
- Implemented UPDATE to modify existing mappings in folder tree
- Implemented DELETE to remove mappings from folder tree
3. **configuration.proto**
- Added `video_input` field to ActionMappingInput
### Folder Tree Approach
All operations use the **FolderTreeParser** and **FolderTreeWriter** classes to:
1. Parse binary .set file into hierarchical folder structure
2. Navigate to MappingRules folder
3. Modify the folder tree (add/update/delete)
4. Serialize back to binary
5. Write to GeViServer
This approach maintains the complete configuration structure and ensures proper binary serialization.
## Testing
### Run Comprehensive CRUD Test
```bash
# 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:
1. Reconnect to GeViSet
2. Navigate to action mappings
3. 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 (`VideoInput` with 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):
```python
# 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:
1. Secondary flag is 100
2. `.VideoInput` filter is set to true
3. `VideoInput` field has valid camera ID
4. 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.