# Action Mapping Implementation Guide ## Overview This document describes the GeViSoft action mapping implementation, which provides automated response capabilities for the Geutebruck surveillance system. Action mappings allow you to trigger one or more actions based on an input action (e.g., route a camera to a monitor when motion is detected). ## Architecture ### Components ``` ┌─────────────────────────────────────────────────────────────┐ │ Python FastAPI │ │ ┌─────────────┐ ┌──────────────┐ ┌──────────────────┐ │ │ │ Router │→ │ Service │→ │ Database Model │ │ │ │ (REST API) │ │ (Business) │ │ (PostgreSQL) │ │ │ └─────────────┘ └──────────────┘ └──────────────────┘ │ │ ↓ │ └─────────┼─────────────────────────────────────────────────────┘ │ gRPC ↓ ┌─────────────────────────────────────────────────────────────┐ │ C# SDK Bridge (gRPC Server) │ │ ┌────────────────────┐ ┌──────────────────────────┐ │ │ │ ActionMapping │ → │ GeViDatabaseWrapper │ │ │ │ Handler │ │ (GeViSoft Connection) │ │ │ └────────────────────┘ └──────────────────────────┘ │ │ ↓ │ └──────────────────────────────────────┼───────────────────────┘ │ SDK ↓ ┌──────────────────────┐ │ GeViServer │ │ (GeViSoft) │ └──────────────────────┘ ``` ### Data Flow 1. **Create/Update**: REST API → Database → SDK Bridge → GeViServer 2. **Execute**: GeViServer Event → SDK Bridge Callback → Execute Output Actions 3. **List/Query**: REST API → Database ## Implementation Details ### Backend (C# SDK Bridge) #### Files Created/Modified 1. **Configuration** - `appsettings.json` - Added GeViSoft connection settings - `Program.cs` - Dual connection (GeViScope + GeViSoft) 2. **SDK Layer** - `SDK/ActionMappingHandler.cs` - Core action mapping logic - In-memory storage for MVP (database sync in production) - Input action detection and output action execution 3. **gRPC Service** - `Services/ActionMappingService.cs` - gRPC service implementation - `Protos/actionmapping.proto` - Protocol buffer definitions 4. **Connection Management** - Separate `GeViDatabaseWrapper` instances for GeViScope and GeViSoft - Non-fatal GeViSoft connection (video ops work without it) #### Key Classes **ActionMappingHandler** (`SDK/ActionMappingHandler.cs`): ```csharp public class ActionMappingHandler { public async Task> EnumerateActionMappingsAsync(bool enabledOnly = false) public async Task CreateActionMappingAsync(...) public async Task UpdateActionMappingAsync(...) public async Task DeleteActionMappingAsync(string id) public async Task ExecuteActionMappingAsync(string inputAction) } ``` **ActionMappingConfig** (Data Model): ```csharp public class ActionMappingConfig { public string Id { get; set; } public string Name { get; set; } public string InputAction { get; set; } public List OutputActions { get; set; } public bool Enabled { get; set; } public int ExecutionCount { get; set; } public DateTime? LastExecuted { get; set; } } ``` ### Frontend (Python FastAPI) #### Files Created 1. **Database Models** - `models/action_mapping.py` - SQLAlchemy models - `ActionMapping` - Main table - `ActionMappingExecution` - Execution log for audit 2. **Schemas** - `schemas/action_mapping.py` - Pydantic models - `ActionMappingCreate` - Request for creating - `ActionMappingUpdate` - Request for updating - `ActionMappingResponse` - Response model - `ActionMappingListResponse` - List response 3. **Service Layer** - `services/action_mapping_service.py` - Business logic - Database CRUD operations - SDK Bridge synchronization (TODO) 4. **API Routes** - `routers/action_mappings.py` - REST endpoints - `GET /api/v1/action-mappings` - List all - `GET /api/v1/action-mappings/{id}` - Get one - `POST /api/v1/action-mappings` - Create - `PUT /api/v1/action-mappings/{id}` - Update - `DELETE /api/v1/action-mappings/{id}` - Delete 5. **Migrations** - `migrations/versions/20251210_action_mappings.py` - Database schema #### Database Schema **action_mappings** table: ```sql CREATE TABLE action_mappings ( id UUID PRIMARY KEY, name VARCHAR(100) NOT NULL, description TEXT, input_action VARCHAR(500) NOT NULL, output_actions VARCHAR[] NOT NULL, geviscope_instance_scope VARCHAR(50), enabled BOOLEAN NOT NULL DEFAULT true, execution_count INTEGER NOT NULL DEFAULT 0, last_executed TIMESTAMP WITH TIME ZONE, created_at TIMESTAMP WITH TIME ZONE NOT NULL, updated_at TIMESTAMP WITH TIME ZONE NOT NULL, created_by UUID NOT NULL, metadata_json JSONB ); CREATE INDEX ix_action_mappings_input_action ON action_mappings(input_action); CREATE INDEX ix_action_mappings_enabled ON action_mappings(enabled); CREATE INDEX ix_action_mappings_instance_scope ON action_mappings(geviscope_instance_scope); ``` **action_mapping_executions** table: ```sql CREATE TABLE action_mapping_executions ( id UUID PRIMARY KEY, mapping_id UUID NOT NULL, input_action VARCHAR(500) NOT NULL, output_actions_executed VARCHAR[] NOT NULL, success BOOLEAN NOT NULL, error_message TEXT, executed_at TIMESTAMP WITH TIME ZONE NOT NULL, duration_ms INTEGER, context_json JSONB ); CREATE INDEX ix_action_mapping_executions_mapping_id ON action_mapping_executions(mapping_id); CREATE INDEX ix_action_mapping_executions_executed_at ON action_mapping_executions(executed_at); ``` ## API Usage Examples ### Create Action Mapping ```bash curl -X POST http://localhost:8000/api/v1/action-mappings \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Motion Detection Alert", "description": "Route camera to monitor when motion detected", "input_action": "VMD_Start(101038)", "output_actions": [ "CrossSwitch(101038, 1, 0)", "SendMail(security@example.com, Motion Detected)" ], "enabled": true }' ``` ### List Action Mappings ```bash curl -X GET "http://localhost:8000/api/v1/action-mappings?enabled_only=true" \ -H "Authorization: Bearer $TOKEN" ``` ### Update Action Mapping ```bash curl -X PUT http://localhost:8000/api/v1/action-mappings/{id} \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "enabled": false, "description": "Temporarily disabled" }' ``` ### Delete Action Mapping ```bash curl -X DELETE http://localhost:8000/api/v1/action-mappings/{id} \ -H "Authorization: Bearer $TOKEN" ``` ## Common Use Cases ### 1. Motion Detection → Camera Routing **Scenario**: When motion is detected on a camera, route it to monitor 1 ```json { "name": "VMD Auto-Route", "input_action": "VMD_Start(101038)", "output_actions": ["CrossSwitch(101038, 1, 0)"] } ``` ### 2. Door Contact → Alarm Response **Scenario**: When door contact opens, flash beacon and send email ```json { "name": "Door Open Alert", "input_action": "InputContact(3, false)", "output_actions": [ "AlternateContact(2, 1000, 500)", "SendMail(security@example.com, Door Opened)" ] } ``` ### 3. Alarm → Multi-Action Response **Scenario**: When alarm triggers, route cameras, activate outputs, send notifications ```json { "name": "Intrusion Alarm Response", "input_action": "AlarmStart(1)", "output_actions": [ "CrossSwitch(5, 1, 0)", "CrossSwitch(6, 2, 0)", "OpenContact(10)", "SendMail(security@example.com, ALARM: Intrusion Detected)", "StartRecording(5)", "StartRecording(6)" ] } ``` ## Testing ### Diagnostic Tools 1. **SDK Bridge Diagnostic** (`DiagnoseActionMapping.exe`): ```bash cd C:\DEV\COPILOT\geutebruck-api\src\sdk-bridge\DiagnoseActionMapping dotnet run -- localhost sysadmin password ``` 2. **Python API Test** (`test_action_mappings.py`): ```bash cd C:\DEV\COPILOT\geutebruck-api python tools/test_action_mappings.py --url http://localhost:8000 ``` ### Manual Testing 1. **Start SDK Bridge**: ```bash cd C:\DEV\COPILOT\geutebruck-api\src\sdk-bridge\GeViScopeBridge dotnet run ``` 2. **Run Database Migrations**: ```bash cd C:\DEV\COPILOT\geutebruck-api\src\api alembic upgrade head ``` 3. **Start API Server**: ```bash cd C:\DEV\COPILOT\geutebruck-api\src\api python main.py ``` 4. **Access Swagger UI**: - Navigate to http://localhost:8000/docs - Test endpoints interactively ## Security Considerations ### Authentication - **Viewer Role**: Can list and view action mappings (read-only) - **Operator Role**: Can list and view (no create/edit/delete) - **Administrator Role**: Full CRUD permissions ### Validation - Input action format validated - At least one output action required - Maximum length constraints on all fields - SQL injection prevention via parameterized queries ### Audit Trail All action mapping operations logged: - Who created/updated/deleted - When operation occurred - IP address of requester - Full change history ## Limitations & Future Enhancements ### Current MVP Limitations 1. **In-Memory Storage**: SDK Bridge stores mappings in memory, not GeViServer config 2. **No Callback Registration**: Input actions not automatically detected (would require event monitoring) 3. **No GeViSet Integration**: Cannot import/export from GeViSet application 4. **No Pattern Matching**: Input actions must match exactly (no wildcards) ### Planned Enhancements 1. **Direct GeViServer Integration**: - Store mappings in GeViServer configuration database - Use SetupClient API for configuration management - Sync with GeViSet application 2. **Event Callback System**: - Register SDK callbacks for input action detection - Automatic execution of output actions - Real-time processing 3. **Advanced Features**: - Action patterns with wildcards (e.g., `VMD_Start(*)`) - Conditional logic (if/then/else) - Time-based enabling/disabling - Action chaining and dependencies 4. **Monitoring & Analytics**: - Real-time execution dashboard - Performance metrics - Failure rate tracking - Execution history visualization ## Troubleshooting ### Connection Issues **Problem**: SDK Bridge cannot connect to GeViSoft **Solutions**: 1. Check GeViServer is running 2. Verify connection settings in `appsettings.json` 3. Check firewall rules 4. Review SDK Bridge logs: `logs/sdk-bridge-*.log` ### Database Issues **Problem**: Migration fails or table not found **Solutions**: 1. Run migrations: `alembic upgrade head` 2. Check database connection in `config.py` 3. Verify PostgreSQL is running 4. Check migration logs ### API Errors **Problem**: 403 Forbidden when creating action mapping **Solutions**: 1. Ensure user has Administrator role 2. Check JWT token is valid 3. Verify authentication middleware is working **Problem**: 500 Internal Server Error **Solutions**: 1. Check API logs: `logs/api-*.log` 2. Verify SDK Bridge is running 3. Check database connectivity 4. Review error details in response ## References - [GeViSoft SDK Documentation](../../SOURCES/GeViSoft_SDK_Documentation_text/) - [Data Model Specification](../../specs/001-surveillance-api/data-model.md) - [API Specification](../../specs/001-surveillance-api/spec.md) - [GeViScope SDK Full Documentation](../../SOURCES/GeViSoft_SDK_Documentation_text/GeViScope_SDK_full.txt) ## Support For issues or questions: 1. Check this documentation 2. Review SDK Bridge logs 3. Test with diagnostic tools 4. Check GeViSoft SDK documentation 5. Contact Geutebruck support for SDK-specific issues