# API Diagramme PH - Spécifications Techniques ## Vue d'ensemble API REST pour générer des diagrammes Pression-Enthalpie (PH) de réfrigérants et effectuer des calculs thermodynamiques frigorifiques avancés. --- ## Architecture Technique ### Stack Technologique - **Framework**: FastAPI (Python 3.12+) - **Bibliothèques thermodynamiques**: DLL/SO personnalisées (IPM_DLL) - **Visualisation**: Matplotlib, Plotly - **Déploiement**: Docker + AWS Elastic Beanstalk - **Format de réponse**: JSON + images base64 ### Réfrigérants supportés R12, R22, R32, R134a, R290, R404A, R410A, R452A, R454A, R454B, R502, R507A, R513A, R515B, R744 (CO2), R1233zd, R1234ze --- ## Endpoints API ### 1. GET /api/v1/health **Description**: Vérification de l'état de l'API **Réponse**: ```json { "status": "healthy", "version": "1.0.0", "available_refrigerants": ["R134a", "R410A", ...] } ``` --- ### 2. GET /api/v1/refrigerants **Description**: Liste des réfrigérants disponibles **Réponse**: ```json { "refrigerants": [ { "name": "R134a", "description": "HFC Refrigerant", "pressure_range": {"min": 51325, "max": 4059280, "unit": "Pa"}, "temperature_range": {"min": -103.3, "max": 101.1, "unit": "°C"} }, ... ] } ``` --- ### 3. POST /api/v1/diagram/generate **Description**: Génération d'un diagramme PH **Request Body**: ```json { "refrigerant": "R134a", "output_format": "plotly_json", // "matplotlib_png", "plotly_json", "plotly_html" "points": [ { "type": "PT", // "PT", "PX", "PH", "TSX" "pressure": 500000, // Pa "temperature": 5, // °C "label": "Point 1", "order": 1 }, { "type": "PX", "pressure": 1500000, // Pa "quality": 1.0, "label": "Point 2", "order": 2 } ], "diagram_options": { "show_isotherms": true, "isotherm_step": 10, // °C "show_saturation_lines": true, "title": "Custom Title (optional)", "width": 1000, "height": 800 } } ``` **Réponse (format plotly_json)**: ```json { "success": true, "refrigerant": "R134a", "diagram_type": "PH", "output_format": "plotly_json", "data": { "plotly_figure": { "data": [...], // Plotly traces "layout": {...} // Plotly layout }, "points_calculated": [ { "label": "Point 1", "order": 1, "pressure": 500000, "temperature": 5, "enthalpy": 250000, "quality": 0.0, "entropy": 1200, "density": 1250 } ] }, "metadata": { "generated_at": "2025-10-18T12:30:00Z", "computation_time_ms": 245 } } ``` **Réponse (format matplotlib_png)**: ```json { "success": true, "refrigerant": "R134a", "diagram_type": "PH", "output_format": "matplotlib_png", "data": { "image_base64": "iVBORw0KGgoAAAANSUhEUgAA...", "mime_type": "image/png", "points_calculated": [...] }, "metadata": {...} } ``` --- ### 4. POST /api/v1/calculations/cycle **Description**: Calculs de cycle frigorifique complet (COP, puissance, rendement) **Request Body**: ```json { "refrigerant": "R134a", "cycle_type": "standard", // "standard", "economizer", "two_stage" "points": { "evaporator_outlet": { "type": "PT", "pressure": 200000, "temperature": -10, "superheat": 5 // °C (optionnel) }, "compressor_outlet": { "type": "PT", "pressure": 1500000, "temperature": 80 }, "condenser_outlet": { "type": "PT", "pressure": 1500000, "temperature": 40, "subcooling": 5 // °C (optionnel) }, "expansion_valve_outlet": { "type": "PX", "pressure": 200000, "quality": 0.25 } }, "operating_conditions": { "mass_flow_rate": 0.05, // kg/s "volumetric_efficiency": 0.85, "isentropic_efficiency": 0.75, "mechanical_efficiency": 0.95 }, "economizer": { // Optionnel pour cycle avec économiseur "enabled": false, "intermediate_pressure": 600000, "subcooling_gain": 10 } } ``` **Réponse**: ```json { "success": true, "refrigerant": "R134a", "cycle_type": "standard", "results": { "cop": { "cop_cooling": 3.85, "cop_heating": 4.85, "carnot_cop": 5.2, "carnot_efficiency": 0.74 }, "capacities": { "cooling_capacity": 12500, // W "heating_capacity": 15750, // W "compressor_power": 3250 // W }, "energies": { "evaporator_heat": 250000, // J/kg "condenser_heat": 315000, // J/kg "compressor_work": 65000 // J/kg }, "efficiencies": { "volumetric_efficiency": 0.85, "isentropic_efficiency": 0.75, "mechanical_efficiency": 0.95, "overall_efficiency": 0.606 }, "mass_flow": { "refrigerant_mass_flow": 0.05, // kg/s "volume_flow_rate": 0.04 // m³/s }, "cycle_points": [ { "point_name": "evaporator_outlet", "order": 1, "pressure": 200000, "temperature": -5, "enthalpy": 390000, "entropy": 1750, "quality": 1.0, "density": 8.5 }, { "point_name": "compressor_outlet", "order": 2, "pressure": 1500000, "temperature": 80, "enthalpy": 455000, "entropy": 1820, "quality": null, "density": 45.2 } ] }, "diagram_data": { "plotly_json": {...} // Diagramme PH du cycle }, "metadata": { "generated_at": "2025-10-18T12:30:00Z", "computation_time_ms": 185 } } ``` --- ### 5. POST /api/v1/calculations/power **Description**: Calcul de puissance entre deux points avec débit massique **Request Body**: ```json { "refrigerant": "R134a", "point_1": { "type": "PT", "pressure": 500000, "temperature": 5 }, "point_2": { "type": "PT", "pressure": 1500000, "temperature": 80 }, "mass_flow_rate": 0.05, // kg/s "process_type": "compression" // "compression", "expansion", "heat_exchange" } ``` **Réponse**: ```json { "success": true, "refrigerant": "R134a", "results": { "power": 3250, // W "enthalpy_difference": 65000, // J/kg "entropy_difference": 70, // J/(kg·K) "point_1": { "pressure": 500000, "temperature": 5, "enthalpy": 390000, "entropy": 1750 }, "point_2": { "pressure": 1500000, "temperature": 80, "enthalpy": 455000, "entropy": 1820 }, "mass_flow_rate": 0.05 } } ``` --- ### 6. POST /api/v1/properties/calculate **Description**: Calcul des propriétés thermodynamiques à un point **Request Body**: ```json { "refrigerant": "R134a", "point": { "type": "PT", // "PT", "PX", "PH", "TX" "pressure": 500000, "temperature": 5 } } ``` **Réponse**: ```json { "success": true, "refrigerant": "R134a", "properties": { "pressure": 500000, // Pa "temperature": 5, // °C "enthalpy": 390000, // J/kg "entropy": 1750, // J/(kg·K) "density": 1250, // kg/m³ "quality": 1.0, // 0-1 (null si surchauffe/sous-refroidissement) "specific_volume": 0.0008, // m³/kg "cp": 1050, // J/(kg·K) "cv": 850, // J/(kg·K) "viscosity": 0.00012, // Pa·s "thermal_conductivity": 0.015, // W/(m·K) "sound_velocity": 250, // m/s "saturation_temperature": -10, // °C "phase": "superheated_vapor" // "subcooled_liquid", "two_phase", "superheated_vapor" } } ``` --- ### 7. POST /api/v1/calculations/economizer **Description**: Calculs spécifiques pour cycles avec économiseur **Request Body**: ```json { "refrigerant": "R134a", "main_cycle": { "evaporator_pressure": 200000, "condenser_pressure": 1500000, "evaporator_superheat": 5, "condenser_subcooling": 5 }, "economizer": { "intermediate_pressure": 600000, "flash_gas_quality": 0.3, "subcooling_effectiveness": 0.8 }, "mass_flow_rate": 0.05, "efficiencies": { "isentropic_low_stage": 0.75, "isentropic_high_stage": 0.75, "volumetric": 0.85 } } ``` **Réponse**: ```json { "success": true, "refrigerant": "R134a", "results": { "performance": { "cop": 4.2, "cop_improvement": 9.1, // % vs standard cycle "cooling_capacity": 13500, "total_compressor_power": 3214 }, "mass_flows": { "evaporator_flow": 0.05, "economizer_flash_gas": 0.008, "high_stage_flow": 0.058 }, "economizer_benefit": { "subcooling_increase": 8, // °C "enthalpy_reduction": 12000, // J/kg "capacity_increase": 8.0 // % }, "cycle_points": [...] } } ``` --- ### 8. POST /api/v1/batch/calculate **Description**: Calculs en batch pour plusieurs points ou configurations **Request Body**: ```json { "refrigerant": "R134a", "calculations": [ { "id": "calc_1", "type": "properties", "point": {"type": "PT", "pressure": 500000, "temperature": 5} }, { "id": "calc_2", "type": "power", "point_1": {"type": "PT", "pressure": 500000, "temperature": 5}, "point_2": {"type": "PT", "pressure": 1500000, "temperature": 80}, "mass_flow_rate": 0.05 } ] } ``` --- ## Codes d'erreur | Code | Description | |------|-------------| | 400 | Requête invalide (paramètres manquants ou invalides) | | 404 | Réfrigérant non trouvé | | 422 | Point thermodynamique hors limites | | 500 | Erreur serveur (DLL, calcul) | | 503 | Service temporairement indisponible | **Format d'erreur**: ```json { "success": false, "error": { "code": "INVALID_REFRIGERANT", "message": "Refrigerant R999 not found", "details": { "available_refrigerants": ["R134a", "R410A", ...] } } } ``` --- ## Limites et Contraintes ### Rate Limiting - 100 requêtes/minute par IP - 1000 requêtes/heure par IP ### Taille des requêtes - Max 100 points par diagramme - Max 50 calculs par batch - Timeout: 30 secondes par requête ### Précision des calculs - Pression: ±0.1% - Température: ±0.1 K - Enthalpie: ±0.5% --- ## Exemples d'utilisation ### Python ```python import requests # Générer un diagramme PH response = requests.post( "https://api.diagramph.com/api/v1/diagram/generate", json={ "refrigerant": "R134a", "output_format": "plotly_json", "points": [ {"type": "PT", "pressure": 500000, "temperature": 5, "order": 1}, {"type": "PT", "pressure": 1500000, "temperature": 80, "order": 2} ] } ) data = response.json() ``` ### JavaScript/React ```javascript const response = await fetch('https://api.diagramph.com/api/v1/diagram/generate', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ refrigerant: 'R134a', output_format: 'plotly_json', points: [...] }) }); const data = await response.json(); // Utiliser Plotly.react() pour afficher le graphique ``` ### cURL ```bash curl -X POST https://api.diagramph.com/api/v1/diagram/generate \ -H "Content-Type: application/json" \ -d '{ "refrigerant": "R134a", "output_format": "matplotlib_png", "points": [ {"type": "PT", "pressure": 500000, "temperature": 5} ] }' ``` --- ## Changelog ### Version 1.0.0 (2025-10) - Endpoints de base pour diagrammes PH - Calculs de cycles frigorifiques - Support économiseur - 17 réfrigérants supportés