# 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)**
   ```powershell
   # 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**
   ```cmd
   cd C:\GEVISOFT
   GeViServer.exe console
   ```

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

See [SDK_INTEGRATION_LESSONS.md](../../SDK_INTEGRATION_LESSONS.md) for complete deployment details.

---

## Installation

### 1. Clone Repository

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

### 2. Install Dependencies

**Python API Server**:
```bash
cd src/api
python -m venv venv
venv\Scripts\activate
pip install -r requirements.txt
```

**C# SDK Bridge**:
```bash
cd src/sdk-bridge
dotnet restore
dotnet build --configuration Release
```

### 3. Install Redis

**Using Chocolatey**:
```powershell
choco install redis-64
redis-server
```

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

---

## Configuration

### Environment Variables

Create `.env` file in `src/api/`:

```env
# 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

```bash
cd src/api
alembic upgrade head
```

---

## Starting the Services

### 1. Start GeViServer
```cmd
cd C:\GEVISOFT
GeViServer.exe console
```

### 2. Start Redis
```bash
redis-server
```

### 3. Start SDK Bridge
```bash
cd src/sdk-bridge
dotnet run --configuration Release
```

### 4. Start API Server
```bash
cd src/api
uvicorn main:app --host 0.0.0.0 --port 8000 --reload
```

**Verify Services**:
- API: http://localhost:8000/api/v1/health
- API Docs: http://localhost:8000/docs
- SDK Bridge: gRPC on localhost:50051

---

## First API Call

### 1. Authenticate

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

**Response**:
```json
{
  "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**:
```bash
curl -X GET "http://localhost:8000/api/v1/cameras" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

**Response**:
```json
{
  "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**:
```bash
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**:
```json
{
  "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.):
```bash
ffplay "rtsp://localhost:8554/stream/7c9e6679?token=eyJhbGc..."
```

---

## Common Use Cases

### Python SDK Example

```python
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

```python
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

```bash
# 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

```python
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

```bash
# 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

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

### Run Integration Tests

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

### Test Coverage

Minimum 80% coverage enforced. View coverage report:
```bash
# Open coverage report
start htmlcov/index.html  # Windows
open htmlcov/index.html   # macOS
```

---

## API Documentation

### Interactive Docs

Once the API is running, visit:

- **Swagger UI**: http://localhost:8000/docs
- **ReDoc**: http://localhost:8000/redoc
- **OpenAPI JSON**: http://localhost:8000/openapi.json

### Complete API Reference

See [contracts/openapi.yaml](./contracts/openapi.yaml) for the complete OpenAPI 3.0 specification.

### Data Model

See [data-model.md](./data-model.md) for entity schemas, relationships, and validation rules.

### Architecture

See [research.md](./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):
```powershell
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:
```cmd
cd C:\GEVISOFT
GeViServer.exe console
```
Check ports: `netstat -an | findstr "7700 7701 7703"`

**3. "Redis connection failed"**

**Solution**: Start Redis server:
```bash
redis-server
```

**4. "SDK Bridge gRPC not responding"**

**Solution**: Check SDK Bridge logs and restart:
```bash
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:
```bash
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:
```env
LOG_LEVEL=DEBUG
```

View logs:
```bash
# API logs
tail -f logs/api.log

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

### Health Check

```bash
# 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

```env
# 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

```env
# 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**:
   ```env
   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**:
   ```env
   RATE_LIMIT_PER_MINUTE=60
   RATE_LIMIT_BURST=10
   ```

5. **Audit logging**:
   ```env
   AUDIT_LOG_ENABLED=true
   AUDIT_LOG_PATH=/var/log/geutebruck-api/audit.log
   ```

See [security.md](./security.md) for complete security guidelines.

---

## Next Steps

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

---

## Support

- **Issues**: https://github.com/your-org/geutebruck-api/issues
- **Documentation**: https://docs.geutebruck-api.example.com
- **GeViScope SDK**: See `C:\GEVISOFT\Documentation\`

---

**Version**: 1.0.0
**Last Updated**: 2025-12-08
