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

11 KiB

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:

[
  {
    "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:

[
  {
    "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:

{
  "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:

[
  {
    "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:

{
  "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:

{
  "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:

[
  {
    "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:

{
  "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:

# 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:

{
  "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

# 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

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