docs: add project description and server setup instructions to README
This commit is contained in:
98
server/app/coap_bridge.py
Normal file
98
server/app/coap_bridge.py
Normal file
@@ -0,0 +1,98 @@
|
||||
"""
|
||||
Demeter Server — CoAP-to-REST Bridge
|
||||
|
||||
Proxies HTTP requests to CoAP endpoints on ESP devices, allowing
|
||||
the dashboard and external tools to query devices via standard HTTP.
|
||||
|
||||
Routes:
|
||||
GET /api/devices/{device_id}/coap/{resource_path} — proxy CoAP GET
|
||||
PUT /api/devices/{device_id}/coap/{resource_path} — proxy CoAP PUT
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter, HTTPException, Request
|
||||
|
||||
router = APIRouter(prefix="/api", tags=["coap-bridge"])
|
||||
|
||||
|
||||
def _get_store(request: Request):
|
||||
return request.app.state.store
|
||||
|
||||
|
||||
def _get_observer(request: Request):
|
||||
return request.app.state.observer
|
||||
|
||||
|
||||
@router.get("/devices/{device_id}/coap/{resource_path:path}")
|
||||
async def coap_proxy_get(
|
||||
device_id: str,
|
||||
resource_path: str,
|
||||
request: Request,
|
||||
) -> dict[str, Any]:
|
||||
"""
|
||||
Proxy a CoAP GET request to an ESP device.
|
||||
|
||||
Example: GET /api/devices/esp32-plant-01/coap/sensors/temperature
|
||||
→ CoAP GET coap://192.168.1.100:5683/sensors/temperature
|
||||
"""
|
||||
store = _get_store(request)
|
||||
observer = _get_observer(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")
|
||||
|
||||
try:
|
||||
result = await observer.coap_get(
|
||||
device.config.ip, device.config.port, resource_path
|
||||
)
|
||||
return {
|
||||
"device_id": device_id,
|
||||
"resource": resource_path,
|
||||
"method": "GET",
|
||||
"response": result,
|
||||
}
|
||||
except ConnectionError as e:
|
||||
raise HTTPException(status_code=504, detail=str(e))
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=502, detail=str(e))
|
||||
|
||||
|
||||
@router.put("/devices/{device_id}/coap/{resource_path:path}")
|
||||
async def coap_proxy_put(
|
||||
device_id: str,
|
||||
resource_path: str,
|
||||
body: dict[str, Any],
|
||||
request: Request,
|
||||
) -> dict[str, Any]:
|
||||
"""
|
||||
Proxy a CoAP PUT request to an ESP device.
|
||||
|
||||
Example: PUT /api/devices/esp32-plant-01/coap/config/interval
|
||||
Body: {"interval": 10}
|
||||
→ CoAP PUT coap://192.168.1.100:5683/config/interval
|
||||
"""
|
||||
store = _get_store(request)
|
||||
observer = _get_observer(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")
|
||||
|
||||
try:
|
||||
result = await observer.coap_put(
|
||||
device.config.ip, device.config.port, resource_path, body
|
||||
)
|
||||
return {
|
||||
"device_id": device_id,
|
||||
"resource": resource_path,
|
||||
"method": "PUT",
|
||||
"response": result,
|
||||
}
|
||||
except ConnectionError as e:
|
||||
raise HTTPException(status_code=504, detail=str(e))
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=502, detail=str(e))
|
||||
Reference in New Issue
Block a user