docs: add project description and server setup instructions to README

This commit is contained in:
2026-03-21 18:25:35 +00:00
parent c81815a83d
commit 6115a065c7
36 changed files with 4003 additions and 0 deletions

90
server/app/devices_api.py Normal file
View File

@@ -0,0 +1,90 @@
"""
Demeter Server — REST API Endpoints
Provides JSON endpoints for querying device metadata and sensor
readings from the in-memory store.
Routes:
GET /api/devices — list all devices + latest readings
GET /api/devices/{device_id} — single device detail
GET /api/devices/{device_id}/readings — sensor readings only
GET /api/status — server status summary
"""
from __future__ import annotations
import time
from typing import Any
from fastapi import APIRouter, HTTPException, Request
router = APIRouter(prefix="/api", tags=["devices"])
def _get_store(request: Request):
"""Retrieve the DeviceStore from app state."""
return request.app.state.store
def _get_observer(request: Request):
"""Retrieve the CoapObserverClient from app state."""
return request.app.state.observer
@router.get("/devices")
async def list_devices(request: Request) -> dict[str, Any]:
"""List all registered devices with their latest readings."""
store = _get_store(request)
snapshot = await store.snapshot()
return {
"devices": list(snapshot.values()),
"count": len(snapshot),
"timestamp": time.time(),
}
@router.get("/devices/{device_id}")
async def get_device(device_id: str, request: Request) -> dict[str, Any]:
"""Get a single device's full state."""
store = _get_store(request)
device = await store.get_device(device_id)
if device is None:
raise HTTPException(status_code=404, detail=f"Device {device_id!r} not found")
return device.to_dict()
@router.get("/devices/{device_id}/readings")
async def get_readings(device_id: str, request: Request) -> dict[str, Any]:
"""Get sensor readings for a specific device."""
store = _get_store(request)
device = await store.get_device(device_id)
if device is None:
raise HTTPException(status_code=404, detail=f"Device {device_id!r} not found")
return {
"device_id": device_id,
"online": device.online,
"readings": {
uri: reading.to_dict()
for uri, reading in device.readings.items()
},
}
@router.get("/status")
async def server_status(request: Request) -> dict[str, Any]:
"""Server status: subscription count, device overview."""
store = _get_store(request)
observer = _get_observer(request)
devices = await store.get_all_devices()
online = sum(1 for d in devices if d.online)
return {
"server": "demeter",
"version": request.app.state.settings.app_version,
"devices_total": len(devices),
"devices_online": online,
"active_subscriptions": observer.active_subscriptions,
"subscriptions": observer.subscription_status(),
"timestamp": time.time(),
}