diagram_ph/TACHES_IMPLEMENTATION.md

10 KiB

📋 Tâches d'implémentation - API Diagramme PH

Vue d'ensemble

Implémentation progressive et testable de l'API, étape par étape.


🎯 Phase 1 : Configuration initiale (MAINTENANT)

Tâche 1.1 : Structure de base du projet

Durée estimée : 30 minutes

Actions :

# Créer structure
mkdir -p app/api/v1/endpoints
mkdir -p app/core
mkdir -p app/models
mkdir -p app/services
mkdir -p app/utils
mkdir -p libs/so
mkdir -p tests/test_api
mkdir -p tests/test_core
mkdir -p docker
mkdir -p deployment/scripts

Fichiers à créer :

  • app/__init__.py
  • app/config.py
  • app/main.py
  • requirements.txt
  • .env.example
  • .gitignore

Test : Structure des dossiers existe


Tâche 1.2 : Configuration requirements.txt

Durée estimée : 10 minutes

Créer : requirements.txt

fastapi==0.109.0
uvicorn[standard]==0.27.0
pydantic==2.5.0
pydantic-settings==2.1.0
numpy==1.26.3
pandas==2.2.0
matplotlib==3.8.2
plotly==5.18.0
python-multipart==0.0.6
cachetools==5.3.2
python-json-logger==2.0.7

Test : pip install -r requirements.txt fonctionne


Tâche 1.3 : Configuration de base

Durée estimée : 15 minutes

Créer : app/config.py

from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    APP_NAME: str = "Diagram PH API"
    VERSION: str = "1.0.0"
    ENV: str = "development"
    LOG_LEVEL: str = "DEBUG"
    
    class Config:
        env_file = ".env"

settings = Settings()

Créer : .env.example

ENV=development
LOG_LEVEL=DEBUG

Test : Importer settings fonctionne


Tâche 1.4 : Application FastAPI minimale

Durée estimée : 20 minutes

Créer : app/main.py

from fastapi import FastAPI
from app.config import settings

app = FastAPI(
    title=settings.APP_NAME,
    version=settings.VERSION
)

@app.get("/")
def root():
    return {
        "message": "Diagram PH API",
        "version": settings.VERSION,
        "status": "running"
    }

@app.get("/api/v1/health")
def health():
    return {
        "status": "healthy",
        "version": settings.VERSION
    }

Test :

uvicorn app.main:app --reload
# Visiter http://localhost:8000
# Visiter http://localhost:8000/api/v1/health

Résultat attendu : API démarre, endpoints répondent


🎯 Phase 2 : Intégration bibliothèques .so (ENSUITE)

Tâche 2.1 : Copier bibliothèques .so

Durée estimée : 5 minutes

Actions :

# Copier les fichiers .so
cp IPM_SO/*.so libs/so/

Test : Fichiers existent dans libs/so/


Tâche 2.2 : Wrapper bibliothèque de base

Durée estimée : 45 minutes

Créer : app/core/refrigerant_loader.py

import ctypes
import platform
from pathlib import Path
from typing import Optional

class RefrigerantLoader:
    """Gestionnaire de chargement des bibliothèques .so"""
    
    BASE_DIR = Path(__file__).parent.parent.parent / "libs"
    
    @classmethod
    def get_library_path(cls, refrigerant: str) -> Path:
        """Retourne le chemin de la bibliothèque"""
        system = platform.system()
        
        if system == "Windows":
            return cls.BASE_DIR / "dll" / f"{refrigerant}.dll"
        elif system == "Linux":
            return cls.BASE_DIR / "so" / f"lib{refrigerant}.so"
        else:
            raise OSError(f"Unsupported OS: {system}")
    
    @classmethod
    def load(cls, refrigerant: str):
        """Charge la bibliothèque"""
        lib_path = cls.get_library_path(refrigerant)
        
        if not lib_path.exists():
            raise FileNotFoundError(f"Library not found: {lib_path}")
        
        try:
            return ctypes.CDLL(str(lib_path))
        except OSError as e:
            raise RuntimeError(f"Failed to load {lib_path}: {e}")
    
    @classmethod
    def list_available(cls) -> list:
        """Liste les réfrigérants disponibles"""
        system = platform.system()
        
        if system == "Windows":
            dir_path = cls.BASE_DIR / "dll"
            pattern = "R*.dll"
        else:
            dir_path = cls.BASE_DIR / "so"
            pattern = "libR*.so"
        
        if not dir_path.exists():
            return []
        
        files = list(dir_path.glob(pattern))
        refrigerants = []
        
        for f in files:
            if system == "Windows":
                name = f.stem
            else:
                name = f.stem[3:]  # Remove 'lib' prefix
            refrigerants.append(name)
        
        return sorted(refrigerants)

Test :

# test_loader.py
from app.core.refrigerant_loader import RefrigerantLoader

# Lister disponibles
refrigerants = RefrigerantLoader.list_available()
print(f"Disponibles: {refrigerants}")

# Charger R134a
lib = RefrigerantLoader.load("R134a")
print(f"✅ R134a chargé: {lib}")

Résultat attendu : Liste des réfrigérants + chargement réussi


Tâche 2.3 : Endpoint liste réfrigérants

Durée estimée : 20 minutes

Créer : app/api/v1/endpoints/refrigerants.py

from fastapi import APIRouter
from app.core.refrigerant_loader import RefrigerantLoader

router = APIRouter()

@router.get("/refrigerants")
def list_refrigerants():
    """Liste des réfrigérants disponibles"""
    refrigerants = RefrigerantLoader.list_available()
    
    return {
        "success": True,
        "count": len(refrigerants),
        "refrigerants": refrigerants
    }

Modifier : app/main.py

from app.api.v1.endpoints import refrigerants

app.include_router(
    refrigerants.router,
    prefix="/api/v1",
    tags=["refrigerants"]
)

Test :

curl http://localhost:8000/api/v1/refrigerants

Résultat attendu : JSON avec liste des réfrigérants


🎯 Phase 3 : Calculs thermodynamiques (APRÈS)

Tâche 3.1 : Interface simple_refrig_api.py

Durée estimée : 30 minutes

Copier et adapter : IPM_DLL/simple_refrig_api.pyapp/core/refrig_api.py

Modifications :

  • Adapter paths pour libs/so/
  • Simplifier pour besoins API
  • Ajouter gestion erreurs

Test :

from app.core.refrig_api import Refifc

# Test R134a
refrig = Refifc("R134a")
props = refrig.get_properties_PT(500000, 278.15)
print(f"✅ Propriétés calculées: {props}")

Tâche 3.2 : Endpoint propriétés basiques

Durée estimée : 40 minutes

Créer : app/models/requests.py

from pydantic import BaseModel, Field
from typing import Optional

class PropertyRequest(BaseModel):
    refrigerant: str = Field(..., description="Nom du réfrigérant")
    pressure: float = Field(..., gt=0, description="Pression [Pa]")
    temperature: float = Field(..., description="Température [K]")

Créer : app/api/v1/endpoints/properties.py

from fastapi import APIRouter, HTTPException
from app.models.requests import PropertyRequest
from app.core.refrig_api import Refifc

router = APIRouter()

@router.post("/properties/calculate")
def calculate_properties(request: PropertyRequest):
    """Calcule les propriétés thermodynamiques"""
    try:
        refrig = Refifc(request.refrigerant)
        # TODO: Appeler méthodes DLL
        
        return {
            "success": True,
            "refrigerant": request.refrigerant,
            "properties": {
                "pressure": request.pressure,
                "temperature": request.temperature,
                # TODO: Ajouter propriétés calculées
            }
        }
    except FileNotFoundError:
        raise HTTPException(404, "Refrigerant not found")
    except Exception as e:
        raise HTTPException(500, str(e))

Test :

curl -X POST http://localhost:8000/api/v1/properties/calculate \
  -H "Content-Type: application/json" \
  -d '{
    "refrigerant": "R134a",
    "pressure": 500000,
    "temperature": 278.15
  }'

🎯 Phase 4 : Génération diagrammes (PLUS TARD)

Tâche 4.1 : Courbe de saturation basique

Durée estimée : 1 heure

Créer : app/core/diagram_generator.py

  • Générer courbe saturation
  • Format JSON simple

Tâche 4.2 : Export Plotly JSON

Durée estimée : 1 heure

  • Créer figure Plotly
  • Exporter en JSON
  • Endpoint /diagram/generate

Tâche 4.3 : Export Matplotlib PNG

Durée estimée : 45 minutes

  • Générer image PNG
  • Encoder en base64
  • Option dans endpoint

🎯 Phase 5 : Calculs cycle (ENCORE PLUS TARD)

Tâche 5.1 : Calculs COP basiques

Durée estimée : 1.5 heures


Tâche 5.2 : Endpoint cycle complet

Durée estimée : 1 heure


🎯 Checklist de progression

Maintenant (Session actuelle)

  • Tâche 1.1 : Structure projet
  • Tâche 1.2 : Requirements
  • Tâche 1.3 : Configuration
  • Tâche 1.4 : FastAPI minimal
  • TEST : API démarre et répond

Session suivante

  • Tâche 2.1 : Copier .so
  • Tâche 2.2 : Loader bibliothèques
  • Tâche 2.3 : Endpoint réfrigérants
  • TEST : Liste réfrigérants fonctionne

Après

  • Phase 3 : Calculs propriétés
  • Phase 4 : Diagrammes
  • Phase 5 : Cycles

🧪 Tests à chaque étape

Test 1 : Structure

ls -la app/
ls -la libs/so/

Test 2 : API démarre

uvicorn app.main:app --reload
curl http://localhost:8000/api/v1/health

Test 3 : Bibliothèques

python -c "from app.core.refrigerant_loader import RefrigerantLoader; print(RefrigerantLoader.list_available())"

Test 4 : Endpoint complet

curl http://localhost:8000/api/v1/refrigerants

Critères de succès

Après Phase 1 (aujourd'hui) :

  • API FastAPI fonctionne
  • Endpoint /health répond
  • Documentation auto (/docs)

Après Phase 2 :

  • Bibliothèques .so chargées
  • Liste réfrigérants disponible
  • Aucune erreur au démarrage

🚀 On commence maintenant !

Prochaine action : Basculer en mode Code et créer la structure (Tâche 1.1)

Êtes-vous prêt ?