Files
geutebruck-api/specs/001-surveillance-api/quickstart.md
Geutebruck API Developer dd2278b39a Complete Phase 0 and Phase 1 design documentation
- Add comprehensive research.md with SDK integration decisions
- Add complete data-model.md with 7 entities and relationships
- Add OpenAPI 3.0 specification (contracts/openapi.yaml)
- Add developer quickstart.md guide
- Add comprehensive tasks.md with 215 tasks organized by user story
- Update plan.md with complete technical context
- Add SDK_INTEGRATION_LESSONS.md capturing critical knowledge
- Add .gitignore for Python and C# projects
- Include GeViScopeConfigReader and GeViSoftConfigReader tools

Phase 1 Design Complete:
 Architecture: Python FastAPI + C# gRPC Bridge + GeViScope SDK
 10 user stories mapped to tasks (MVP = US1-4)
 Complete API contract with 17 endpoints
 Data model with User, Camera, Stream, Event, Recording, Analytics
 TDD approach enforced with 80+ test tasks

Ready for Phase 2: Implementation

🤖 Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-09 07:39:55 +01:00

16 KiB

Quick Start Guide

Geutebruck Surveillance API - REST API for GeViScope/GeViSoft video surveillance systems


Overview

This API provides RESTful access to Geutebruck surveillance systems, enabling:

  • Camera Management: List cameras, get status, control PTZ
  • Live Streaming: Start/stop video streams with token authentication
  • Event Monitoring: Subscribe to real-time surveillance events (motion, alarms, analytics)
  • Recording Access: Query and export recorded video segments
  • Analytics Configuration: Configure video analytics (VMD, NPR, object tracking)

Architecture: Python FastAPI + C# gRPC SDK Bridge + GeViScope SDK


Prerequisites

System Requirements

  • Operating System: Windows 10/11 or Windows Server 2016+
  • GeViSoft Installation: Full GeViSoft application + SDK
  • Visual C++ 2010 Redistributable (x86): Required for SDK
  • Python: 3.11+ (for API server)
  • .NET Framework: 4.8 (for SDK bridge)
  • Redis: 6.0+ (for session management and pub/sub)

GeViSoft SDK Setup

CRITICAL: Install in this exact order:

  1. Install Visual C++ 2010 Redistributable (x86)

    # Download and install
    Invoke-WebRequest -Uri 'https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x86.exe' -OutFile 'vcredist_x86_2010.exe'
    Start-Process -FilePath 'vcredist_x86_2010.exe' -ArgumentList '/install', '/quiet', '/norestart' -Wait
    
  2. Install GeViSoft Full Application

    • Download from Geutebruck
    • Run installer
    • Complete setup wizard
  3. Install GeViSoft SDK

    • Download SDK installer
    • Run SDK setup
    • Verify installation in C:\Program Files (x86)\GeViScopeSDK\
  4. Start GeViServer

    cd C:\GEVISOFT
    GeViServer.exe console
    

Verification:

# Check GeViServer is running
netstat -an | findstr "7700 7701 7703"
# Should show LISTENING on these ports

See SDK_INTEGRATION_LESSONS.md for complete deployment details.


Installation

1. Clone Repository

git clone https://github.com/your-org/geutebruck-api.git
cd geutebruck-api

2. Install Dependencies

Python API Server:

cd src/api
python -m venv venv
venv\Scripts\activate
pip install -r requirements.txt

C# SDK Bridge:

cd src/sdk-bridge
dotnet restore
dotnet build --configuration Release

3. Install Redis

Using Chocolatey:

choco install redis-64
redis-server

Or download from: https://redis.io/download


Configuration

Environment Variables

Create .env file in src/api/:

# API Configuration
API_HOST=0.0.0.0
API_PORT=8000
API_TITLE=Geutebruck Surveillance API
API_VERSION=1.0.0

# GeViScope Connection
GEVISCOPE_HOST=localhost
GEVISCOPE_USERNAME=sysadmin
GEVISCOPE_PASSWORD=masterkey

# SDK Bridge gRPC
SDK_BRIDGE_HOST=localhost
SDK_BRIDGE_PORT=50051

# Redis Configuration
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_DB=0
REDIS_PASSWORD=

# JWT Authentication
JWT_SECRET_KEY=your-secret-key-change-in-production
JWT_ALGORITHM=HS256
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=60
JWT_REFRESH_TOKEN_EXPIRE_DAYS=7

# Stream URLs
STREAM_BASE_URL=rtsp://localhost:8554
STREAM_TOKEN_EXPIRE_MINUTES=15

# Logging
LOG_LEVEL=INFO
LOG_FORMAT=json

Security Note: Change JWT_SECRET_KEY and GEVISCOPE_PASSWORD in production!

Database Migrations

cd src/api
alembic upgrade head

Starting the Services

1. Start GeViServer

cd C:\GEVISOFT
GeViServer.exe console

2. Start Redis

redis-server

3. Start SDK Bridge

cd src/sdk-bridge
dotnet run --configuration Release

4. Start API Server

cd src/api
uvicorn main:app --host 0.0.0.0 --port 8000 --reload

Verify Services:


First API Call

1. Authenticate

Request:

curl -X POST "http://localhost:8000/api/v1/auth/login" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "sysadmin",
    "password": "masterkey"
  }'

Response:

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer",
  "expires_in": 3600
}

Save the access token - you'll need it for all subsequent requests.

2. List Cameras

Request:

curl -X GET "http://localhost:8000/api/v1/cameras" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response:

{
  "total": 2,
  "page": 1,
  "page_size": 50,
  "cameras": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440001",
      "channel": 1,
      "name": "Front Entrance",
      "description": "Main entrance camera",
      "status": "online",
      "capabilities": {
        "ptz": true,
        "audio": false,
        "analytics": ["motion_detection", "people_counting"]
      },
      "resolutions": [
        {"width": 1920, "height": 1080, "fps": 30},
        {"width": 1280, "height": 720, "fps": 60}
      ]
    }
  ]
}

3. Start Video Stream

Request:

curl -X POST "http://localhost:8000/api/v1/cameras/550e8400-e29b-41d4-a716-446655440001/stream" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "resolution": {"width": 1920, "height": 1080, "fps": 30},
    "format": "h264"
  }'

Response:

{
  "stream_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "camera_id": "550e8400-e29b-41d4-a716-446655440001",
  "url": "rtsp://localhost:8554/stream/7c9e6679?token=eyJhbGc...",
  "format": "h264",
  "resolution": {"width": 1920, "height": 1080, "fps": 30},
  "started_at": "2025-12-08T15:30:00Z",
  "expires_at": "2025-12-08T15:45:00Z"
}

Use the stream URL in your video player (VLC, ffplay, etc.):

ffplay "rtsp://localhost:8554/stream/7c9e6679?token=eyJhbGc..."

Common Use Cases

Python SDK Example

import requests
from typing import Dict, Any

class GeutebruckAPI:
    def __init__(self, base_url: str = "http://localhost:8000"):
        self.base_url = base_url
        self.access_token = None

    def login(self, username: str, password: str) -> Dict[str, Any]:
        """Authenticate and get access token"""
        response = requests.post(
            f"{self.base_url}/api/v1/auth/login",
            json={"username": username, "password": password}
        )
        response.raise_for_status()
        data = response.json()
        self.access_token = data["access_token"]
        return data

    def get_cameras(self) -> Dict[str, Any]:
        """List all cameras"""
        response = requests.get(
            f"{self.base_url}/api/v1/cameras",
            headers={"Authorization": f"Bearer {self.access_token}"}
        )
        response.raise_for_status()
        return response.json()

    def start_stream(self, camera_id: str, width: int = 1920, height: int = 1080) -> Dict[str, Any]:
        """Start video stream from camera"""
        response = requests.post(
            f"{self.base_url}/api/v1/cameras/{camera_id}/stream",
            headers={"Authorization": f"Bearer {self.access_token}"},
            json={
                "resolution": {"width": width, "height": height, "fps": 30},
                "format": "h264"
            }
        )
        response.raise_for_status()
        return response.json()

# Usage
api = GeutebruckAPI()
api.login("sysadmin", "masterkey")
cameras = api.get_cameras()
stream = api.start_stream(cameras["cameras"][0]["id"])
print(f"Stream URL: {stream['url']}")

WebSocket Event Monitoring

import asyncio
import websockets
import json

async def monitor_events(access_token: str):
    """Subscribe to real-time surveillance events"""
    uri = f"ws://localhost:8000/api/v1/events/stream?token={access_token}"

    async with websockets.connect(uri) as websocket:
        # Subscribe to specific event types
        await websocket.send(json.dumps({
            "action": "subscribe",
            "filters": {
                "event_types": ["motion_detected", "alarm_triggered"],
                "camera_ids": ["550e8400-e29b-41d4-a716-446655440001"]
            }
        }))

        # Receive events
        while True:
            message = await websocket.recv()
            event = json.loads(message)
            print(f"Event: {event['event_type']} on camera {event['camera_id']}")
            print(f"  Timestamp: {event['timestamp']}")
            print(f"  Details: {event['details']}")

# Run
asyncio.run(monitor_events("YOUR_ACCESS_TOKEN"))

PTZ Camera Control

# Move camera to preset position
curl -X POST "http://localhost:8000/api/v1/cameras/550e8400-e29b-41d4-a716-446655440001/ptz" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "command": "goto_preset",
    "preset": 1
  }'

# Pan/tilt/zoom control
curl -X POST "http://localhost:8000/api/v1/cameras/550e8400-e29b-41d4-a716-446655440001/ptz" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "command": "move",
    "pan": 50,
    "tilt": 30,
    "zoom": 2.5,
    "speed": 50
  }'

Query Recordings

import requests
from datetime import datetime, timedelta

def get_recordings(camera_id: str, access_token: str):
    """Get recordings from last 24 hours"""
    end_time = datetime.utcnow()
    start_time = end_time - timedelta(hours=24)

    response = requests.get(
        "http://localhost:8000/api/v1/recordings",
        headers={"Authorization": f"Bearer {access_token}"},
        params={
            "camera_id": camera_id,
            "start_time": start_time.isoformat() + "Z",
            "end_time": end_time.isoformat() + "Z",
            "event_type": "motion_detected"
        }
    )
    response.raise_for_status()
    return response.json()

# Usage
recordings = get_recordings("550e8400-e29b-41d4-a716-446655440001", "YOUR_ACCESS_TOKEN")
for rec in recordings["recordings"]:
    print(f"Recording: {rec['start_time']} - {rec['end_time']}")
    print(f"  Size: {rec['size_bytes'] / 1024 / 1024:.2f} MB")
    print(f"  Export URL: {rec['export_url']}")

Configure Video Analytics

# Enable motion detection
curl -X POST "http://localhost:8000/api/v1/analytics/550e8400-e29b-41d4-a716-446655440001" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "motion_detection",
    "enabled": true,
    "configuration": {
      "sensitivity": 75,
      "regions": [
        {
          "name": "entrance",
          "points": [
            {"x": 100, "y": 100},
            {"x": 500, "y": 100},
            {"x": 500, "y": 400},
            {"x": 100, "y": 400}
          ]
        }
      ],
      "schedule": {
        "enabled": true,
        "start_time": "18:00:00",
        "end_time": "06:00:00",
        "days": [1, 2, 3, 4, 5, 6, 7]
      }
    }
  }'

Testing

Run Unit Tests

cd src/api
pytest tests/unit -v --cov=app --cov-report=html

Run Integration Tests

# Requires running GeViServer and SDK Bridge
pytest tests/integration -v

Test Coverage

Minimum 80% coverage enforced. View coverage report:

# Open coverage report
start htmlcov/index.html  # Windows
open htmlcov/index.html   # macOS

API Documentation

Interactive Docs

Once the API is running, visit:

Complete API Reference

See contracts/openapi.yaml for the complete OpenAPI 3.0 specification.

Data Model

See data-model.md for entity schemas, relationships, and validation rules.

Architecture

See research.md for:

  • System architecture decisions
  • SDK integration patterns
  • Performance considerations
  • Security implementation

Troubleshooting

Common Issues

1. "Could not load file or assembly 'GeViProcAPINET_4_0.dll'"

Solution: Install Visual C++ 2010 Redistributable (x86):

Invoke-WebRequest -Uri 'https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x86.exe' -OutFile 'vcredist_x86_2010.exe'
Start-Process -FilePath 'vcredist_x86_2010.exe' -ArgumentList '/install', '/quiet', '/norestart' -Wait

2. "Connection refused to GeViServer"

Solution: Ensure GeViServer is running:

cd C:\GEVISOFT
GeViServer.exe console

Check ports: netstat -an | findstr "7700 7701 7703"

3. "Redis connection failed"

Solution: Start Redis server:

redis-server

4. "SDK Bridge gRPC not responding"

Solution: Check SDK Bridge logs and restart:

cd src/sdk-bridge
dotnet run --configuration Release

5. "401 Unauthorized" on API calls

Solution: Check your access token hasn't expired (1 hour lifetime). Use refresh token to get new access token:

curl -X POST "http://localhost:8000/api/v1/auth/refresh" \
  -H "Content-Type: application/json" \
  -d '{
    "refresh_token": "YOUR_REFRESH_TOKEN"
  }'

Debug Mode

Enable debug logging:

LOG_LEVEL=DEBUG

View logs:

# API logs
tail -f logs/api.log

# SDK Bridge logs
tail -f src/sdk-bridge/logs/bridge.log

Health Check

# API health
curl http://localhost:8000/api/v1/health

# Expected response
{
  "status": "healthy",
  "timestamp": "2025-12-08T15:30:00Z",
  "version": "1.0.0",
  "dependencies": {
    "sdk_bridge": "connected",
    "redis": "connected",
    "database": "connected"
  }
}

Performance Tuning

Response Time Optimization

Target: <200ms for most endpoints

# Connection pooling
SDK_BRIDGE_POOL_SIZE=10
SDK_BRIDGE_MAX_OVERFLOW=20

# Redis connection pool
REDIS_MAX_CONNECTIONS=50

# Async workers
UVICORN_WORKERS=4

WebSocket Scaling

Target: 1000+ concurrent connections

# Redis pub/sub
REDIS_PUBSUB_MAX_CONNECTIONS=100

# WebSocket timeouts
WEBSOCKET_PING_INTERVAL=30
WEBSOCKET_PING_TIMEOUT=10

Stream URL Caching

Stream URLs are cached for token lifetime (15 minutes) to reduce SDK bridge calls.


Security Considerations

Production Deployment

CRITICAL: Before deploying to production:

  1. Change default credentials:

    GEVISCOPE_PASSWORD=your-secure-password-here
    JWT_SECRET_KEY=generate-with-openssl-rand-hex-32
    REDIS_PASSWORD=your-redis-password
    
  2. Enable HTTPS:

    • Use reverse proxy (nginx/Caddy) with SSL certificates
    • Redirect HTTP to HTTPS
  3. Network security:

    • GeViServer should NOT be exposed to internet
    • API should be behind firewall/VPN
    • Use internal network for SDK Bridge ↔ GeViServer communication
  4. Rate limiting:

    RATE_LIMIT_PER_MINUTE=60
    RATE_LIMIT_BURST=10
    
  5. Audit logging:

    AUDIT_LOG_ENABLED=true
    AUDIT_LOG_PATH=/var/log/geutebruck-api/audit.log
    

See security.md for complete security guidelines.


Next Steps

  1. Read the Architecture: research.md - Understanding system design decisions
  2. Explore Data Model: data-model.md - Entity schemas and relationships
  3. API Reference: contracts/openapi.yaml - Complete endpoint documentation
  4. SDK Integration: ../../SDK_INTEGRATION_LESSONS.md - Deep dive into SDK usage
  5. Join Development: CONTRIBUTING.md - Contributing guidelines

Support


Version: 1.0.0 Last Updated: 2025-12-08