Files
geutebruck/geutebruck-api/docs/api-endpoints-explained.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

494 lines
11 KiB
Markdown

# 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