feat: add API endpoint to get devices list

This commit is contained in:
Alexis Fourmaux 2026-05-12 21:59:24 +02:00
parent 0cb5706ed7
commit f4b7daabd3
9 changed files with 66 additions and 1 deletions

View file

@ -0,0 +1,10 @@
from pydantic import BaseModel
from domain.entities import Device
class DeviceResponseSchema(BaseModel):
device_eui: str
@classmethod
def from_domain(cls, device: Device) -> "DeviceResponseSchema":
return cls(device_eui=device.device_eui)

View file

@ -0,0 +1,12 @@
from fastapi import APIRouter, Depends
from services.devices_service import DeviceService
from dependencies import get_device_service
from ._devices_schemas import DeviceResponseSchema
devices_router = APIRouter(prefix="/devices", tags=["devices"])
@devices_router.get("", response_model=list[DeviceResponseSchema])
def list_devices(service: DeviceService = Depends(get_device_service)):
return [DeviceResponseSchema.from_domain(d) for d in service.get_all_devices()]

View file

@ -1,6 +1,7 @@
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from .readings import readings_router from .readings import readings_router
from .devices import devices_router
app = FastAPI(title="SimuGazAPI", version="1.0.0") app = FastAPI(title="SimuGazAPI", version="1.0.0")
@ -12,6 +13,7 @@ app.add_middleware(
) )
app.include_router(readings_router) app.include_router(readings_router)
app.include_router(devices_router)
@app.get("/health") @app.get("/health")
def health(): def health():

View file

@ -5,6 +5,7 @@ import psycopg2
from ports import DeviceRepository from ports import DeviceRepository
from domain.exceptions import DatabaseError from domain.exceptions import DatabaseError
from infrastructure.db import get_conn from infrastructure.db import get_conn
from domain.entities import Device
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -28,3 +29,15 @@ class PgDeviceRepository(DeviceRepository):
return str(cur.fetchone()[0]) # type: ignore return str(cur.fetchone()[0]) # type: ignore
except psycopg2.DatabaseError as e: except psycopg2.DatabaseError as e:
raise DatabaseError(f"Erreur de création du device {dev_eui}") from e raise DatabaseError(f"Erreur de création du device {dev_eui}") from e
def get_all(self) -> list[Device]:
query = "SELECT device_id, device_eui FROM device ORDER BY device_eui ASC"
try:
with get_conn() as conn:
with conn.cursor() as cur:
cur.execute(query)
rows = cur.fetchall()
except psycopg2.DatabaseError as e:
raise DatabaseError(f"Erreur d'accès aux devices : {e}") from e
return [Device(device_id=r[0], device_eui=r[1]) for r in rows]

View file

@ -4,6 +4,7 @@ from adapters.postgres import PgDeviceRepository, PgReadingRepository, PgReading
from adapters.mqtt import PahoMqttBroker from adapters.mqtt import PahoMqttBroker
from services.uplink_service import UplinkService from services.uplink_service import UplinkService
from services.consumption_service import ConsumptionService from services.consumption_service import ConsumptionService
from services.devices_service import DeviceService
MQTT_HOST = os.getenv("MQTT_HOST", "mosquitto") MQTT_HOST = os.getenv("MQTT_HOST", "mosquitto")
MQTT_PORT = int(os.getenv("MQTT_PORT", 1883)) MQTT_PORT = int(os.getenv("MQTT_PORT", 1883))
@ -28,6 +29,9 @@ def get_uplink_service() -> UplinkService:
def get_consumption_service() -> ConsumptionService: def get_consumption_service() -> ConsumptionService:
return ConsumptionService(get_query_repo()) return ConsumptionService(get_query_repo())
def get_device_service() -> DeviceService:
return DeviceService(get_device_repo())
## Adapters ## Adapters
def get_mqtt_broker() -> PahoMqttBroker: def get_mqtt_broker() -> PahoMqttBroker:

View file

@ -1,4 +1,5 @@
from .uplink_event import UplinkEvent from .uplink_event import UplinkEvent
from .consumption_point import ConsumptionPoint, ConsumptionResponse from .consumption_point import ConsumptionPoint, ConsumptionResponse
from .device import Device
__all__ = ["UplinkEvent", "ConsumptionPoint", "ConsumptionResponse"] __all__ = ["UplinkEvent", "ConsumptionPoint", "ConsumptionResponse", "Device"]

View file

@ -0,0 +1,6 @@
from dataclasses import dataclass
@dataclass
class Device:
device_id: int
device_eui: str

View file

@ -1,7 +1,14 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from domain.entities import Device
class DeviceRepository(ABC): class DeviceRepository(ABC):
@abstractmethod @abstractmethod
def get_or_create_device_id(self, dev_eui: str) -> str: def get_or_create_device_id(self, dev_eui: str) -> str:
"""Retourne le device_id, crée le device s'il est inconnu""" """Retourne le device_id, crée le device s'il est inconnu"""
...
@abstractmethod
def get_all(self) -> list[Device]:
"""Retourne l'ensemble des devices existants"""
... ...

View file

@ -0,0 +1,10 @@
from domain.entities import Device
from adapters.postgres.device_repository import DeviceRepository
class DeviceService:
def __init__(self, device_repo: DeviceRepository) -> None:
self._device_repo = device_repo
def get_all_devices(self) -> list[Device]:
return self._device_repo.get_all()