Skip to content

Latest commit

 

History

History
 
 

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.md

Shelly Manager API

REST API server for Shelly Manager built with Litestar.

Features

  • HTTP REST API for device management
  • OpenAPI documentation at /docs
  • Request/response validation
  • Health monitoring endpoint
  • CORS support for web integration
  • Docker deployment ready

Quick Start

Docker

# Run API server
docker run -p 8000:8000 \
  -v ./config.json:/app/config.json:ro \
  ghcr.io/jfmlima/shelly-manager-api:latest

# Visit API documentation
open http://localhost:8000/docs

Local Development

# Install dependencies (from project root)
uv sync --package shelly-manager-api --extra dev

# Start development server
uv run --package shelly-manager-api python -m api.main

# API available at http://localhost:8000
# Docs available at http://localhost:8000/docs

API Endpoints

Health & Status

GET /api/health                    # Service health check

Device Discovery

GET /api/devices/scan              # Scan network for devices
  ?start_ip=192.168.1.1            # Start IP address
  &end_ip=192.168.1.254            # End IP address
  &use_predefined=true             # Use predefined ranges
  &use_mdns=false                  # Use mDNS discovery
  &timeout=3.0                     # Timeout per device
  &max_workers=50                  # Concurrent workers

Device Operations

GET /api/devices/{ip}/status       # Get device status
  ?include_updates=true            # Include update information

POST /api/devices/{ip}/update      # Update device firmware
  ?channel=stable                  # Update channel (stable/beta)

POST /api/devices/{ip}/reboot      # Reboot device

POST /api/devices/bulk/update      # Bulk firmware updates
  # Body: {"device_ips": ["192.168.1.100", "192.168.1.101"], "channel": "stable"}

# Component Actions
GET /api/devices/{ip}/components/actions           # Discover available actions
POST /api/devices/{ip}/components/{id}/action      # Execute component action

Component Actions

The Component Actions system provides dynamic action discovery and execution for individual device components.

Discovery

GET /api/devices/{ip}/components/actions    # Get all available actions for device

Execute Component Action

POST /api/devices/{ip}/components/{component_id}/action

Monitoring

GET /api/health

Examples

Device Scan

curl "http://localhost:8000/api/devices/scan?start_ip=192.168.1.1&end_ip=192.168.1.10"

Response:

[
  {
    "ip": "192.168.1.100",
    "status": "online",
    "device_type": "shelly1pm",
    "device_name": "Living Room Light",
    "firmware_version": "20230913-112003",
    "response_time": 0.123,
    "last_seen": "2024-01-15T10:30:00Z"
  }
]

Device Update

curl -X POST "http://localhost:8000/api/devices/192.168.1.100/update?channel=stable"

Response:

{
  "ip": "192.168.1.100",
  "success": true,
  "message": "Firmware update initiated",
  "action_type": "firmware_update"
}

Component Actions Examples

Discover Device Actions

curl "http://localhost:8000/api/devices/192.168.1.100/components/actions"

Response Example:

{
  "device_ip": "192.168.1.100",
  "components": [
    {
      "component_id": "switch:0",
      "component_type": "switch",
      "available_actions": [
        {
          "action": "toggle",
          "description": "Toggle switch state",
          "parameters": {}
        },
        {
          "action": "turn_on",
          "description": "Turn switch on",
          "parameters": {}
        }
      ]
    }
  ]
}

Toggle a Switch

curl -X POST "http://localhost:8000/api/devices/192.168.1.100/components/switch:0/action" \
  -H "Content-Type: application/json" \
  -d '{"action": "toggle", "params": {}}'

Request Body:

{
  "action": "toggle",
  "params": {}
}

Response:

{
  "ip": "192.168.1.100",
  "component_id": "switch:0",
  "action": "toggle",
  "success": true,
  "result": {
    "new_state": "on"
  }
}

Open a Cover

curl -X POST "http://localhost:8000/api/devices/192.168.1.100/components/cover:0/action" \
  -H "Content-Type: application/json" \
  -d '{"action": "open", "params": {}}'

Error Response

{
  "detail": "Device not reachable",
  "status_code": 404,
  "ip": "192.168.1.100"
}

Configuration

Environment Variables

Variable Default Description
HOST 127.0.0.1 API server host
PORT 8000 API server port
DEBUG false Enable debug mode
SHELLY_CONFIG_FILE config.json Path to configuration file

Configuration File

Create a config.json file:

{
  "device_ips": ["192.168.1.100", "192.168.1.101"],
  "predefined_ranges": [
    {
      "start": "192.168.1.1",
      "end": "192.168.1.254"
    }
  ],
  "timeout": 3.0,
  "max_workers": 50
}

Docker Deployment

Basic Deployment

docker run -d \
  --name shelly-manager-api \
  -p 8000:8000 \
  -v ./config.json:/app/config.json:ro \
  -e HOST=0.0.0.0 \
  -e PORT=8000 \
  ghcr.io/jfmlima/shelly-manager-api:latest

Docker Compose

services:
  api:
    image: ghcr.io/jfmlima/shelly-manager-api:latest
    ports:
      - "8000:8000"
    volumes:
      - ./config.json:/app/config.json:ro
    environment:
      - HOST=0.0.0.0
      - PORT=8000
      - DEBUG=false
    restart: unless-stopped

Health Check

healthcheck:
  test: ["CMD-SHELL", "curl -f http://localhost:8000/api/health || exit 1"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 40s

Development

Local Development Setup

# From project root
cd shelly-manager

# Install with development dependencies
uv sync --package shelly-manager-api --extra dev

# Run with auto-reload
uv run --package shelly-manager-api python -m api.main

# Run tests
uv run --package shelly-manager-api pytest packages/api/tests/ -v

# Run linting
uv run ruff check packages/api/
uv run mypy packages/api/src/api

API Documentation Development

The API uses Litestar's built-in OpenAPI generation:

Adding New Endpoints

  1. Create Controller: Add to packages/api/src/api/controllers/
  2. Define DTOs: Add request/response models to packages/api/src/api/presentation/dto/
  3. Add Route: Register controller in packages/api/src/api/main.py
  4. Add Tests: Create tests in packages/api/tests/

Example controller:

from litestar import Controller, get
from api.presentation.dto.responses import DeviceResponse

class DeviceController(Controller):
    path = "/devices"

    @get("/{device_ip:str}/status")
    async def get_device_status(self, device_ip: str) -> DeviceResponse:
        # Implementation here
        pass

Testing

# Run all API tests
make test-api

# Run specific test files
uv run --package shelly-manager-api pytest packages/api/tests/unit/controllers/ -v

# Run with coverage
uv run --package shelly-manager-api pytest packages/api/tests/ --cov=api --cov-report=html

Architecture

The API follows Clean Architecture principles:

packages/api/src/api/
├── controllers/           # HTTP request handlers
├── dependencies/          # Dependency injection container
├── main.py               # Application entry point
└── presentation/
    ├── dto/              # Data Transfer Objects
    └── serializers/      # Response serialization

Dependencies

  • Litestar: Modern async web framework
  • Pydantic: Data validation and serialization
  • uvicorn: ASGI server
  • Core Package: Business logic and domain models

Troubleshooting

Common Issues

  1. Port already in use: Change PORT environment variable
  2. Config file not found: Ensure config.json exists and is mounted
  3. CORS errors: Configure CORS settings for your web UI domain
  4. Health check failures: Verify API is responding on configured port

Debug Mode

Enable debug mode for detailed error messages:

docker run -p 8000:8000 \
  -e DEBUG=true \
  ghcr.io/jfmlima/shelly-manager-api:latest

Logs

# View container logs
docker logs shelly-manager-api

# Follow logs in real-time
docker logs -f shelly-manager-api

Additional Resources