Merge remote-tracking branch 'origin/dev' into feat/endpoint-sites-current
# Conflicts: # apps/backend/app/repositories/reading.py # apps/backend/openapi.json # docs/architecture/20-backend.md
This commit is contained in:
@@ -1314,6 +1314,217 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/readings": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"readings"
|
||||
],
|
||||
"summary": "Liste l'historique des lectures",
|
||||
"operationId": "list_readings_api_v1_readings_get",
|
||||
"security": [
|
||||
{
|
||||
"Jeton d'accès": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "site_id",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Site Id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "start",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Start"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "end",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "End"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"maximum": 2000,
|
||||
"minimum": 1,
|
||||
"default": 500,
|
||||
"title": "Limit"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "offset",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"default": 0,
|
||||
"title": "Offset"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ReadingResponse"
|
||||
},
|
||||
"title": "Response List Readings Api V1 Readings Get"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Erreur interne. `correlation` identifie la trace côté serveur, qui n'est pas renvoyée au client.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/InternalErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Jeton absent, illisible, périmé, ou rendu caduc par un changement de rôle ou une désactivation. L'en-tête `WWW-Authenticate` porte la cause dans `error=`.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Mot de passe provisoire à changer (`detail` vaut `password_change_required`).",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Corps invalide. Le détail nomme le champ fautif et le type d'erreur, jamais la valeur envoyée.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ValidationErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Fenêtre temporelle invalide : `start` postérieur ou égal à `end`, ou écart entre les deux supérieur à 90 jours.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/sensors/status": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"sensors"
|
||||
],
|
||||
"summary": "État de santé des capteurs par site",
|
||||
"operationId": "get_status_api_v1_sensors_status_get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/SensorStatusResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Erreur interne. `correlation` identifie la trace côté serveur, qui n'est pas renvoyée au client.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/InternalErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Jeton absent, illisible, périmé, ou rendu caduc par un changement de rôle ou une désactivation. L'en-tête `WWW-Authenticate` porte la cause dans `error=`.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Droits insuffisants, ou mot de passe provisoire à changer quand `detail` vaut `password_change_required`.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Jeton d'accès": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
@@ -1611,6 +1822,225 @@
|
||||
],
|
||||
"title": "ReadinessStatus"
|
||||
},
|
||||
"ReadingDataQuality": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"good",
|
||||
"partial",
|
||||
"degraded",
|
||||
"critical"
|
||||
],
|
||||
"title": "ReadingDataQuality"
|
||||
},
|
||||
"ReadingResponse": {
|
||||
"properties": {
|
||||
"reading_id": {
|
||||
"type": "integer",
|
||||
"title": "Reading Id"
|
||||
},
|
||||
"site_id": {
|
||||
"type": "string",
|
||||
"title": "Site Id"
|
||||
},
|
||||
"timestamp": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"title": "Timestamp"
|
||||
},
|
||||
"source": {
|
||||
"$ref": "#/components/schemas/ReadingSource"
|
||||
},
|
||||
"consumption_kw": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Consumption Kw"
|
||||
},
|
||||
"consumption_kwh": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Consumption Kwh"
|
||||
},
|
||||
"consumption_euros": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Consumption Euros"
|
||||
},
|
||||
"voltage_v": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Voltage V"
|
||||
},
|
||||
"current_a": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Current A"
|
||||
},
|
||||
"power_factor": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Power Factor"
|
||||
},
|
||||
"temperature_celsius": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Temperature Celsius"
|
||||
},
|
||||
"humidity_percent": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Humidity Percent"
|
||||
},
|
||||
"solar_irradiance_wm2": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Solar Irradiance Wm2"
|
||||
},
|
||||
"is_working_hours": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Is Working Hours"
|
||||
},
|
||||
"data_quality": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/ReadingDataQuality"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"null_reasons": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Null Reasons"
|
||||
},
|
||||
"imputed_values": {
|
||||
"anyOf": [
|
||||
{
|
||||
"additionalProperties": true,
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Imputed Values"
|
||||
},
|
||||
"imputation_method": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Imputation Method"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"reading_id",
|
||||
"site_id",
|
||||
"timestamp",
|
||||
"source",
|
||||
"consumption_kw",
|
||||
"consumption_kwh",
|
||||
"consumption_euros",
|
||||
"voltage_v",
|
||||
"current_a",
|
||||
"power_factor",
|
||||
"temperature_celsius",
|
||||
"humidity_percent",
|
||||
"solar_irradiance_wm2",
|
||||
"is_working_hours",
|
||||
"data_quality",
|
||||
"null_reasons",
|
||||
"imputed_values",
|
||||
"imputation_method"
|
||||
],
|
||||
"title": "ReadingResponse"
|
||||
},
|
||||
"ReadingSource": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"csv",
|
||||
"api_current",
|
||||
"api_history"
|
||||
],
|
||||
"title": "ReadingSource"
|
||||
},
|
||||
"RecommendationResponse": {
|
||||
"properties": {
|
||||
"recommendation_id": {
|
||||
@@ -1659,6 +2089,59 @@
|
||||
],
|
||||
"title": "Role"
|
||||
},
|
||||
"SensorDiagnosticResponse": {
|
||||
"properties": {
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"ok",
|
||||
"failing"
|
||||
],
|
||||
"title": "Status"
|
||||
},
|
||||
"since": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Since",
|
||||
"description": "Horodatage de la dernière lecture reçue pour ce site. Ce n'est pas le début de la panne : l'historique ne permet pas de le dater sans requête supplémentaire."
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"status",
|
||||
"since"
|
||||
],
|
||||
"title": "SensorDiagnosticResponse"
|
||||
},
|
||||
"SensorStatusResponse": {
|
||||
"properties": {
|
||||
"timestamp": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"title": "Timestamp"
|
||||
},
|
||||
"sites": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/SiteSensorStatusResponse"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "Sites"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"timestamp",
|
||||
"sites"
|
||||
],
|
||||
"title": "SensorStatusResponse"
|
||||
},
|
||||
"SiteCurrentResponse": {
|
||||
"properties": {
|
||||
"timestamp": {
|
||||
@@ -1852,6 +2335,66 @@
|
||||
],
|
||||
"title": "SiteResponse"
|
||||
},
|
||||
"SiteSensorStatusResponse": {
|
||||
"properties": {
|
||||
"site_id": {
|
||||
"type": "string",
|
||||
"title": "Site Id"
|
||||
},
|
||||
"site_name": {
|
||||
"type": "string",
|
||||
"title": "Site Name"
|
||||
},
|
||||
"sensors": {
|
||||
"$ref": "#/components/schemas/SiteSensorsResponse"
|
||||
},
|
||||
"overall": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"ok",
|
||||
"degraded",
|
||||
"critical"
|
||||
],
|
||||
"title": "Overall"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"site_id",
|
||||
"site_name",
|
||||
"sensors",
|
||||
"overall"
|
||||
],
|
||||
"title": "SiteSensorStatusResponse"
|
||||
},
|
||||
"SiteSensorsResponse": {
|
||||
"properties": {
|
||||
"consumption": {
|
||||
"$ref": "#/components/schemas/SensorDiagnosticResponse"
|
||||
},
|
||||
"electrical": {
|
||||
"$ref": "#/components/schemas/SensorDiagnosticResponse"
|
||||
},
|
||||
"temperature": {
|
||||
"$ref": "#/components/schemas/SensorDiagnosticResponse"
|
||||
},
|
||||
"humidity": {
|
||||
"$ref": "#/components/schemas/SensorDiagnosticResponse"
|
||||
},
|
||||
"network": {
|
||||
"$ref": "#/components/schemas/SensorDiagnosticResponse"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"consumption",
|
||||
"electrical",
|
||||
"temperature",
|
||||
"humidity",
|
||||
"network"
|
||||
],
|
||||
"title": "SiteSensorsResponse"
|
||||
},
|
||||
"SiteSummaryResponse": {
|
||||
"properties": {
|
||||
"site_id": {
|
||||
@@ -2180,6 +2723,14 @@
|
||||
{
|
||||
"name": "stats",
|
||||
"description": "Statistiques agrégées de consommation. Accessible à partir du rôle `lecteur`."
|
||||
},
|
||||
{
|
||||
"name": "readings",
|
||||
"description": "Historique des lectures de consommation. Fenêtre temporelle plafonnée à 90 jours, 24 dernières heures par défaut si `start`/`end` sont omis. Accessible à partir du rôle `lecteur`."
|
||||
},
|
||||
{
|
||||
"name": "sensors",
|
||||
"description": "État de santé des capteurs par site. Réservé au rôle `admin`."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user