# REST API Endpoints - Data Sources Explained ## Overview This document explains where each REST API endpoint gets its data and how the flow works. --- ## 🎥 Camera Endpoints ### GET /api/v1/cameras **Data Source**: GeViServer Camera Manager (real-time, in-memory) **Flow**: ``` Client → FastAPI → gRPC (CameraService) → StateQueryHandler → SDK → GeViServer Camera Manager ``` **Code Path**: 1. `routers/cameras.py` - REST endpoint 2. `services/camera_service.py` - Business logic 3. `clients/sdk_bridge_client.py` - gRPC client 4. `Services/CameraService.cs` (C#) - gRPC service 5. `SDK/StateQueryHandler.cs` (C#) - SDK wrapper 6. `CSQGetFirstVideoInput()` + `CSQGetNextVideoInput()` - SDK enumeration **What You Get**: ```json [ { "channel": 1, "name": "Front Door Camera", "description": "Main entrance", "has_ptz": true, "has_video_sensor": true, "status": "online" } ] ``` **Data Characteristics**: - ✅ Real-time camera list - ✅ Current connection status - ✅ Live from GeViServer memory - ❌ NOT stored in TestMKS.set - 🔄 Changes when cameras connect/disconnect --- ## 📺 Monitor Endpoints ### GET /api/v1/monitors **Data Source**: GeViServer Monitor Manager (real-time, in-memory) **Flow**: ``` Client → FastAPI → gRPC (MonitorService) → StateQueryHandler → SDK → GeViServer Monitor Manager ``` **Code Path**: 1. `routers/monitors.py` 2. `services/monitor_service.py` 3. `clients/sdk_bridge_client.py` 4. `Services/MonitorService.cs` (C#) 5. `SDK/StateQueryHandler.cs` (C#) 6. `CSQGetFirstVideoOutput()` + `CSQGetNextVideoOutput()` **What You Get**: ```json [ { "channel": 1, "name": "Main Monitor", "is_active": true, "current_camera_id": 7 } ] ``` **Data Characteristics**: - ✅ Real-time monitor/viewer list - ✅ Current routing state (which camera is shown) - ✅ GSCView client status - ❌ NOT in TestMKS.set - 🔄 Changes when monitors connect/disconnect --- ## 🔀 CrossSwitch Endpoints ### POST /api/v1/crossswitch **Action**: Routes camera to monitor (sends command to GeViServer) **Flow**: ``` Client → FastAPI → gRPC (CrossSwitchService) → ActionDispatcher → SDK → GeViServer Action Engine ``` **Request**: ```json { "camera_id": 7, "monitor_id": 3, "mode": 0 } ``` **Code Path**: 1. `routers/crossswitch.py` 2. `services/crossswitch_service.py` 3. `Services/CrossSwitchService.cs` (C#) 4. `SDK/ActionDispatcher.cs` (C#) 5. `SendAction("CrossSwitch", ...)` - SDK action **What Happens**: - GeViServer routes video from Camera 7 to Monitor 3 - Monitor immediately shows the camera feed - Routing state updated in GeViServer memory ### DELETE /api/v1/monitors/{id} **Action**: Clears monitor (stops video display) **Code Path**: Similar to CrossSwitch but calls `ClearVideoOutput` action --- ## ⚙️ Configuration Endpoints (✅ IMPLEMENTED) ### GET /api/v1/configuration/servers **Data Source**: TestMKS.set file (persistent binary configuration) **Flow**: ``` Client → FastAPI → gRPC (ConfigurationService) → SetupClient.Download() → Parse .set file → Extract GeViGCoreServer folder → Return servers ``` **Code Path**: 1. `routers/configuration.py` 2. `services/configuration_service.py` 3. `clients/sdk_bridge_client.py` 4. `Services/ConfigurationService.cs` (C#) - gRPC service 5. `SDK/GeViSetupClientWrapper.cs` (C#) - Download config 6. `Services/FolderTreeParser.cs` (C#) - Parse binary .set 7. Navigate to "GeViGCoreServer" folder 8. Extract all server nodes **What You Get**: ```json [ { "id": "1", "alias": "Remote Server 1", "host": "192.168.1.100", "user": "admin", "enabled": true, "deactivate_echo": false, "deactivate_live_check": false }, { "id": "2", "alias": "Remote Server 2", ... } ] ``` **Data Characteristics**: - ✅ Persistent in TestMKS.set file - ✅ Survives GeViServer restart - ✅ Visible in GeViSet UI - 💾 Binary format, parsed on-demand - 🔒 Requires SetupClient download --- ### POST /api/v1/configuration/servers **Action**: Creates new G-Core server in configuration **Flow**: ``` Client → FastAPI → gRPC → SetupClient.Download() → Parse .set → Auto-increment ID → Create server node → Write tree → SetupClient.Upload() ``` **Request**: ```json { "alias": "New Remote Server", "host": "192.168.1.200", "user": "admin", "password": "secret", "enabled": true } ``` **What Happens**: 1. Downloads current TestMKS.set file 2. Parses binary format into folder tree 3. Finds GeViGCoreServer folder 4. Calculates new ID (max existing ID + 1) 5. Creates new server node with all fields 6. Writes modified tree back to binary 7. Uploads to GeViServer 8. GeViServer saves and reloads config **Response**: ```json { "id": "14", "alias": "New Remote Server", "host": "192.168.1.200", ... } ``` --- ### PUT /api/v1/configuration/servers/{server_id} **Status**: ⚠️ KNOWN BUG - "Server ID is required" **Intended Flow**: Download → Parse → Find server → Update fields → Upload **Workaround**: Use DELETE + POST to replace server --- ### DELETE /api/v1/configuration/servers/{server_id} **Action**: Removes server from configuration **Flow**: ``` Client → FastAPI → gRPC → Download .set → Parse → Find server node by ID → Remove node → Upload ``` **Critical Note**: When deleting multiple servers, always delete in **REVERSE ORDER** (highest ID first) to prevent ID shifting! --- ### GET /api/v1/configuration/action-mappings **Data Source**: TestMKS.set file → ActionMapping folder **Flow**: Same as servers, but navigates to "ActionMapping" folder **What You Get**: ```json [ { "id": 1, "name": "Door Contact Mapping", "input_action": "GeVi DoorContact_101001", "output_action": "GeVi PanLeft_101027", "enabled": true } ] ``` **Data Characteristics**: - ID is 1-based index in MappingRules list - Each mapping links input action → output action - Used for automation (e.g., door opens → camera pans) --- ### POST /api/v1/configuration/action-mappings **Action**: Creates new action mapping **Flow**: Download → Parse → Add to MappingRules list → Upload **Request**: ```json { "name": "VMD Trigger", "input_action": "GeVi VideoMotionDetection_7", "output_action": "GeVi StartRecording_7", "enabled": true } ``` --- ### PUT /api/v1/configuration/action-mappings/{mapping_id} **Action**: Updates existing action mapping **Flow**: Download → Parse → Find by ID → Update fields → Upload **Status**: ✅ WORKING (all CRUD operations functional) --- ### DELETE /api/v1/configuration/action-mappings/{mapping_id} **Action**: Removes action mapping **Flow**: Download → Parse → Remove from list → Upload **⚠️ CRITICAL**: When deleting multiple mappings, always delete in **REVERSE ORDER**! **Why?** Mappings use 1-based indices. Deleting mapping #5 shifts all subsequent mappings down by 1 index. **Example Bug**: ``` Original: [#1, #2, #3, #4, #5, #6] Delete #4 → [#1, #2, #3, #5→4, #6→5] Delete #5 (which is now actually #6!) → WRONG MAPPING DELETED! ``` **Solution**: ```python # Sort by ID descending mappings_sorted = sorted(mappings, key=lambda x: x['id'], reverse=True) for mapping in mappings_sorted: delete_action_mapping(mapping['id']) # Delete from highest to lowest ``` --- ## 🔐 Authentication Endpoints ### POST /api/v1/auth/login **Data Source**: PostgreSQL database (user credentials) **Flow**: FastAPI → AuthService → Database query → JWT generation **Not fully implemented yet** - authentication is stubbed out --- ## ❤️ Health Endpoint ### GET /api/v1/health **Data Source**: Real-time component checks **Checks**: 1. **Database**: PostgreSQL connection test 2. **Redis**: Cache connectivity 3. **SDK Bridge**: gRPC connection test (calls ping) **Response**: ```json { "status": "healthy", "version": "1.0.0", "components": { "database": "healthy", "redis": "healthy", "sdk_bridge": "healthy" }, "timestamp": "2025-12-16T21:15:00Z" } ``` --- ## 🔍 Data Source Summary | Endpoint Pattern | Data Source | Access Method | Persistent? | |------------------|-------------|---------------|-------------| | `/cameras` | GeViServer memory | SDK State Query | ❌ Real-time | | `/monitors` | GeViServer memory | SDK State Query | ❌ Real-time | | `/crossswitch` | GeViServer actions | SDK Action Dispatch | ❌ Command | | `/configuration/servers` | TestMKS.set | SetupClient + Parser | ✅ Persistent | | `/configuration/action-mappings` | TestMKS.set | SetupClient + Parser | ✅ Persistent | | `/auth/*` | PostgreSQL | Database query | ✅ Persistent | | `/health` | Component checks | Direct probe | ❌ Real-time | --- ## 🎯 Testing the API ### Using Swagger UI 1. Open http://localhost:8000/docs 2. All endpoints are documented with schemas 3. Click "Try it out" to test ### Using curl ```bash # List cameras curl http://localhost:8000/api/v1/cameras # List servers curl http://localhost:8000/api/v1/configuration/servers # Get specific server curl http://localhost:8000/api/v1/configuration/servers/1 # Create server curl -X POST http://localhost:8000/api/v1/configuration/servers \ -H "Content-Type: application/json" \ -d '{ "alias": "Test Server", "host": "192.168.1.50", "user": "admin", "password": "test123", "enabled": true }' # Delete server curl -X DELETE http://localhost:8000/api/v1/configuration/servers/14 ``` ### Using Python ```python import requests # List cameras response = requests.get("http://localhost:8000/api/v1/cameras") cameras = response.json() print(f"Found {len(cameras)} cameras") # Get all servers response = requests.get("http://localhost:8000/api/v1/configuration/servers") servers = response.json() print(f"Found {len(servers)} servers") # Create server new_server = { "alias": "Python Test Server", "host": "192.168.1.99", "user": "admin", "password": "secret", "enabled": True } response = requests.post( "http://localhost:8000/api/v1/configuration/servers", json=new_server ) created = response.json() print(f"Created server with ID: {created['id']}") ``` --- ## 🐛 Common Issues ### 1. Empty Camera List **Cause**: No cameras configured in GeViServer **Solution**: Add IP cameras in GeViSet or camera configuration ### 2. Configuration Endpoints Return Error **Cause**: SetupClient cannot connect to GeViServer **Possible reasons**: - GeViSet is connected (blocks SetupClient port) - GeViServer not running - Port 7702 not available **Solution**: - Close GeViSet - Ensure GeViServer is running - Check `status-services.ps1` ### 3. CrossSwitch Fails **Cause**: Invalid camera or monitor ID **Solution**: First call `/cameras` and `/monitors` to get valid IDs --- ## 📚 Next Steps 1. **Test each endpoint** with Swagger UI 2. **Verify data sources** match expectations 3. **Check logs** for any errors 4. **Use test scripts** in repository root: - `comprehensive_crud_test.py` - Full CRUD test - `verify_config_via_grpc.py` - Config verification --- **Last Updated**: 2025-12-16 **Version**: 1.0