Add architecture v2 with OCPI and GIREVE integration
This commit is contained in:
BIN
docs/architecture_cariflex_v2.pdf
Normal file
BIN
docs/architecture_cariflex_v2.pdf
Normal file
Binary file not shown.
BIN
docs/architecture_cariflex_v2.png
Normal file
BIN
docs/architecture_cariflex_v2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 310 KiB |
248
docs/architecture_diagrams_v2.md
Normal file
248
docs/architecture_diagrams_v2.md
Normal file
@@ -0,0 +1,248 @@
|
||||
# Cariflex - Diagrammes d'Architecture v2
|
||||
|
||||
> Mise à jour avec OCPI et GIREVE
|
||||
|
||||
## 1. Architecture Générale
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph EXTERNAL["External Layer"]
|
||||
EPEX["EPEX SPOT<br/>Day-ahead Prices"]
|
||||
ENTSOE["ENTSO-E<br/>CO2/Prices"]
|
||||
WEATHER["Weather API<br/>Solcast/Météo"]
|
||||
DSO["DSO/TSO<br/>OpenADR/S2"]
|
||||
end
|
||||
|
||||
subgraph INTEROP["Interoperability Layer"]
|
||||
OCPI["OCPI Gateway<br/>━━━━━━━━━━━━━━<br/>• Tarifs • Sessions<br/>• CDRs • Roaming<br/>• Commands"]
|
||||
GIREVE["GIREVE Connector<br/>━━━━━━━━━━━━━━<br/>• Session data<br/>• Roaming hub<br/>• Billing<br/>• PNIRE"]
|
||||
end
|
||||
|
||||
subgraph INTEGRATION["Integration Layer"]
|
||||
FM["FlexMeasures EMS<br/>━━━━━━━━━━━━━━<br/>• Ingestion<br/>• Forecasting<br/>• Scheduling<br/>• Reporting"]
|
||||
|
||||
CITRINEOS["CitrineOS<br/>CSMS<br/>━━━━━━━━━━━━━━<br/>• OCPP 2.0.1<br/>• Charge Points<br/>• Transactions"]
|
||||
|
||||
EVEREST["EVerest<br/>Middleware<br/>━━━━━━━━━━━━━━<br/>• ISO 15118<br/>• Smart Charging<br/>• Power Mgmt"]
|
||||
|
||||
OPENLEADR["OpenLEADR<br/>VEN Client<br/>━━━━━━━━━━━━━━<br/>• OpenADR 2.0b<br/>• DSO Signals<br/>• Flexibility"]
|
||||
end
|
||||
|
||||
subgraph MARKET["Market Layer (R&D)"]
|
||||
GSY["Grid Singularity<br/>gsy-e<br/>━━━━━━━━━━━━━━<br/>• P2P Trading<br/>• Market Clearing"]
|
||||
|
||||
OPLEM["OPLEM<br/>━━━━━━━━━━━━━━<br/>• Local Market<br/>• Prosumer Opt."]
|
||||
|
||||
HAMLET["HAMLET<br/>━━━━━━━━━━━━━━<br/>• Multi-agent<br/>• Simulation"]
|
||||
end
|
||||
|
||||
subgraph DEVICES["Device Layer"]
|
||||
PV["10 PV Panels<br/>5kWc"]
|
||||
BAT["10 Batteries<br/>100kWh"]
|
||||
EV["10 EVs<br/>75kWh V2G"]
|
||||
CHG["10 EV Chargers<br/>22kW"]
|
||||
end
|
||||
|
||||
subgraph VIZ["Visualization"]
|
||||
GRAFANA["Grafana<br/>Dashboards"]
|
||||
METABASE["Metabase<br/>Analytics"]
|
||||
CARIFLEX_UI["Cariflex UI<br/>FM Frontend"]
|
||||
end
|
||||
|
||||
%% External to Interop
|
||||
DSO -->|"Flex Requests"| OPENLEADR
|
||||
EPEX -->|"Prices"| FM
|
||||
ENTSOE -->|"CO2/Prices"| FM
|
||||
WEATHER -->|"Irradiance"| FM
|
||||
|
||||
%% Interop layer
|
||||
OCPI <-->|"OCPI 2.2"| OtherCPOs["Other CPOs<br/>(Roaming)"]
|
||||
GIREVE <-->|"eMSP API"| GIREVEPlatform["GIREVE Platform"]
|
||||
OCPI -->|"Session data"| FM
|
||||
GIREVE -->|"CDRs/Sessions"| FM
|
||||
|
||||
%% Integration to FM
|
||||
CITRINEOS -->|"OCPP/REST"| FM
|
||||
EVEREST -->|"OCPP"| CITRINEOS
|
||||
OPENLEADR -->|"REST API"| FM
|
||||
|
||||
%% Market to FM
|
||||
GSY <-.->|"gsy-e-sdk"| FM
|
||||
OPLEM <-.->|"sensor data"| FM
|
||||
HAMLET <-.->|"forecasts"| FM
|
||||
|
||||
%% Devices
|
||||
PV -->|"Modbus"| FM
|
||||
BAT -->|"Modbus"| FM
|
||||
EV -->|"ISO 15118"| EVEREST
|
||||
CHG -->|"OCPP 2.0.1"| CITRINEOS
|
||||
|
||||
%% FM to Viz
|
||||
FM -->|"PostgreSQL"| GRAFANA
|
||||
FM -->|"PostgreSQL"| METABASE
|
||||
FM -->|"REST API"| CARIFLEX_UI
|
||||
|
||||
style FM fill:#2196F3,stroke:#1565C0,color:#fff
|
||||
style OCPI fill:#E91E63,stroke:#C2185B,color:#fff
|
||||
style GIREVE fill:#795548,stroke:#5D4037,color:#fff
|
||||
style CITRINEOS fill:#4CAF50,stroke:#388E3C,color:#fff
|
||||
style EVEREST fill:#FF9800,stroke:#F57C00,color:#fff
|
||||
style OPENLEADR fill:#9C27B0,stroke:#7B1FA2,color:#fff
|
||||
style GSY fill:#00BCD4,stroke:#0097A7,color:#fff
|
||||
```
|
||||
|
||||
## 2. Flux OCPI - Session de Recharge
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant EV as EV Driver
|
||||
participant CP as Charge Point
|
||||
participant CitrineOS as CitrineOS CSMS
|
||||
participant FM as FlexMeasures
|
||||
participant OCPI as OCPI Gateway
|
||||
participant OtherCPO as Other CPO
|
||||
|
||||
%% Session start
|
||||
EV->>CP: Plug in (RFID/App)
|
||||
CP->>CitrineOS: StartTransaction
|
||||
CitrineOS->>FM: POST /sensors/{id}/data (power)
|
||||
FM->>OCPI: Check roaming rights
|
||||
OCPI->>OtherCPO: POST /cdrs (session start)
|
||||
OtherCPO-->>OCPI: 200 OK
|
||||
OCPI-->>FM: Authorized
|
||||
|
||||
%% Charging loop
|
||||
loop Every 30s
|
||||
CitrineOS->>FM: Power readings
|
||||
FM->>OCPI: Update session
|
||||
OCPI->>OtherCPO: PATCH /sessions/{id}
|
||||
end
|
||||
|
||||
%% Session end
|
||||
EV->>CP: Unplug
|
||||
CP->>CitrineOS: StopTransaction
|
||||
CitrineOS->>FM: Final readings
|
||||
FM->>OCPI: Generate CDR
|
||||
OCPI->>OtherCPO: POST /cdrs
|
||||
OtherCPO-->>OCPI: CDR accepted
|
||||
```
|
||||
|
||||
## 3. Flux GIREVE - Session de Recharge
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant EV as EV Driver
|
||||
participant CP as Charge Point
|
||||
participant CitrineOS as CitrineOS CSMS
|
||||
participant FM as FlexMeasures
|
||||
participant GIREVE as GIREVE Platform
|
||||
|
||||
%% Session start
|
||||
EV->>CP: Start charging
|
||||
CP->>CitrineOS: StartTransaction
|
||||
CitrineOS->>FM: POST /sensors/{id}/data
|
||||
FM->>GIREVE: POST /session (session start)
|
||||
GIREVE-->>FM: Session acknowledged
|
||||
|
||||
%% Charging loop
|
||||
loop Every 30s
|
||||
CitrineOS->>FM: Power readings
|
||||
FM->>GIREVE: PATCH /session/{id} (consumption)
|
||||
end
|
||||
|
||||
%% Session end
|
||||
EV->>CP: Stop charging
|
||||
CP->>CitrineOS: StopTransaction
|
||||
CitrineOS->>FM: Final readings
|
||||
FM->>GIREVE: POST /cdr (final CDR)
|
||||
GIREVE-->>FM: CDR accepted
|
||||
```
|
||||
|
||||
## 4. Intégration Complète - Tous les Composants
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant GIREVE as GIREVE
|
||||
participant OCPI as OCPI Gateway
|
||||
participant FM as FlexMeasures
|
||||
participant OpenLEADR as OpenLEADR
|
||||
participant CitrineOS as CitrineOS
|
||||
participant EVEREST as EVerest
|
||||
participant EV as EV
|
||||
participant BAT as Battery
|
||||
participant PV as Panel
|
||||
|
||||
%% Data ingestion
|
||||
PV->>FM: Power readings (30s)
|
||||
BAT->>FM: SOC readings (30s)
|
||||
EVEREST->>CitrineOS: OCPP
|
||||
CitrineOS->>FM: EV power readings
|
||||
|
||||
%% Interoperability
|
||||
FM->>GIREVE: Sessions + CDRs
|
||||
FM->>OCPI: Tariffs + Sessions
|
||||
OCPI->>OtherCPOs: Roaming
|
||||
|
||||
%% Forecasting
|
||||
FM->>FM: TrainPredictPipeline (daily)
|
||||
FM->>DB: Save forecasts
|
||||
|
||||
%% Scheduling (triggered by OpenADR)
|
||||
DSO->>OpenLEADR: Flexibility request
|
||||
OpenLEADR->>FM: POST /schedules/trigger
|
||||
FM->>FM: StorageScheduler optimize
|
||||
FM->>DB: Save schedule
|
||||
FM->>CitrineOS: Charging profile
|
||||
CitrineOS->>EVEREST: OCPP commands
|
||||
EVEREST->>EV: Start/stop charging
|
||||
```
|
||||
|
||||
## 5. Architecture Réseau Docker
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph Docker["Docker Network: cariflex-internal"]
|
||||
FM_SRV["flexmeasures-server:5000"]
|
||||
FM_WRK["flexmeasures-worker:5000"]
|
||||
FM_DB["flexmeasures-db:5432"]
|
||||
FM_REDIS["flexmeasures-redis:6379"]
|
||||
|
||||
CITRINEOS["citrineos-server:8080"]
|
||||
EVEREST["everest:8080"]
|
||||
OCPI_GW["ocpi-gateway:8081"]
|
||||
GIREVE_CONN["gireve-connector:8082"]
|
||||
GSY["gsy-e:8080"]
|
||||
end
|
||||
|
||||
subgraph Traefik["Traefik (websecure)"]
|
||||
ROUTER_FM["Router: cariflex.digitribe.fr"]
|
||||
ROUTER_OCPI["Router: ocpi.cariflex.digitribe.fr"]
|
||||
end
|
||||
|
||||
ROUTER_FM -->|"HTTPS"| FM_SRV
|
||||
ROUTER_OCPI -->|"HTTPS"| OCPI_GW
|
||||
FM_SRV -->|"REST"| FM_WRK
|
||||
FM_WRK -->|"RQ"| FM_REDIS
|
||||
FM_WRK -->|"SQL"| FM_DB
|
||||
FM_SRV -->|"SQL"| FM_DB
|
||||
|
||||
CITRINEOS -->|"REST"| FM_SRV
|
||||
EVEREST -->|"OCPP"| CITRINEOS
|
||||
OCPI_GW -->|"REST"| FM_SRV
|
||||
GIREVE_CONN -->|"REST"| FM_SRV
|
||||
GSY -->|"REST"| FM_SRV
|
||||
```
|
||||
|
||||
## 6. TODO - Intégrations
|
||||
|
||||
| Intégration | Priorité | Complexité | Statut |
|
||||
|-------------|----------|------------|--------|
|
||||
| **OCPI Gateway** | Haute | Élevée | 📋 À faire |
|
||||
| **GIREVE Connector** | Haute | Moyenne | 📋 À faire |
|
||||
| **CitrineOS ↔ FM** | Haute | Moyenne | ⏳ À faire |
|
||||
| **EVerest ↔ CitrineOS** | Haute | Moyenne | ⏳ À faire |
|
||||
| **OpenLEADR ↔ FM** | Haute | Faible | ⏳ À faire |
|
||||
| **Grid Singularity ↔ FM** | Moyenne | Élevée | ⏳ À faire |
|
||||
| **OPLEM ↔ FM** | Moyenne | Moyenne | ⏳ À faire |
|
||||
| **HAMLET ↔ FM** | Basse | Élevée | ⏳ À faire |
|
||||
| **MQTT Brokers Cariflex** | Haute | Moyenne | ⏳ À faire |
|
||||
420
docs/architecture_v2.md
Normal file
420
docs/architecture_v2.md
Normal file
@@ -0,0 +1,420 @@
|
||||
# Cariflex - Architecture d'Intégration EMS v2
|
||||
|
||||
> Documentation de l'architecture Cariflex - Plateforme d'Energy Management System
|
||||
> **Mise à jour :** Intégration OCPI et GIREVE
|
||||
|
||||
---
|
||||
|
||||
## 1. Vue d'Ensemble
|
||||
|
||||
Cariflex est une plateforme EMS (Energy Management System) pour la Martinique, intégrant :
|
||||
|
||||
### Composants Principaux
|
||||
| Composant | Rôle | Protocole | Statut |
|
||||
|-----------|------|-----------|--------|
|
||||
| **FlexMeasures** | Moteur central EMS | REST API | ✅ Installé |
|
||||
| **CitrineOS** | CSMS (Charge Station Management) | OCPP 2.0.1 | ✅ Extrait |
|
||||
| **EVerest** | Middleware EV charging | OCPP/ISO 15118 | ✅ Extrait |
|
||||
| **OpenLEADR** | Communication DSO | OpenADR 2.0b | ✅ Installé |
|
||||
| **Grid Singularity** | Marché P2P | gsy-e-sdk | ✅ Extrait |
|
||||
| **OPLEM** | Marché local | Python | ✅ Installé |
|
||||
| **HAMLET** | Simulation LEM | Agent-based | ✅ Extrait |
|
||||
| **OCPI** | Interopérabilité EV | OCPI 2.2 | 📋 À intégrer |
|
||||
| **GIREVE** | Plateforme interop GIREVE | eMSP API | 📋 À intégrer |
|
||||
|
||||
### Glossaire
|
||||
- **OCPI** : Open Charge Point Interface - Protocole d'échange entre opérateurs de bornes
|
||||
- **GIREVE** : Plateforme d'interopérabilité pour la mobilité électrique
|
||||
- **eMSP** : E-Mobility Service Provider
|
||||
- **CPO** : Charge Point Operator
|
||||
- **CSMS** : Charge Station Management System
|
||||
- **OCPP** : Open Charge Point Protocol
|
||||
|
||||
---
|
||||
|
||||
## 2. Architecture Fonctionnelle Complète
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ CARIFLEX EMS - ARCHITECTURE v2 │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ EXTERNAL LAYER │ │
|
||||
│ │ │ │
|
||||
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
|
||||
│ │ │ EPEX SPOT │ │ ENTSO-E │ │ Weather API │ │ DSO/TSO │ │ │
|
||||
│ │ │ (Day-ahead) │ │ (Prices, │ │ (Solcast, │ │ (OpenADR/ │ │ │
|
||||
│ │ │ Localflex) │ │ CO2) │ │ Météo) │ │ S2) │ │ │
|
||||
│ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ └─────────────────┴─────────────────┴─────────────────┘ │ │
|
||||
│ │ │ │ │
|
||||
│ │ ┌──────────────────────────────────────────────────────┼───────────────────────────┐ │ │
|
||||
│ │ │ INTEROPERABILITY LAYER │ │ │ │
|
||||
│ │ │ ▼ │ │ │
|
||||
│ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │
|
||||
│ │ │ │ OCPI │ │ GIREVE │ │ OpenLEADR │ │ │ │
|
||||
│ │ │ │ (eMSP/CPO) │ │ (Platform) │ │ (VEN) │ │ │ │
|
||||
│ │ │ │ │ │ │ │ │ │ │ │
|
||||
│ │ │ │ • Tarifs │ │ • Session │ │ • Flex │ │ │ │
|
||||
│ │ │ │ • Sessions │ │ data │ │ requests │ │ │ │
|
||||
│ │ │ │ • CDRs │ │ • Roaming │ │ • Events │ │ │ │
|
||||
│ │ │ │ • Roaming │ │ • Billing │ │ • Reports │ │ │ │
|
||||
│ │ │ │ • Commands │ │ • CDRs │ │ │ │ │ │
|
||||
│ │ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │ │
|
||||
│ │ │ │ │ │ │ │ │
|
||||
│ │ └─────────┼─────────────────┼─────────────────┼────────────────────────────────────┘ │ │
|
||||
│ │ │ │ │ │ │
|
||||
│ │ ▼ ▼ ▼ │ │
|
||||
│ │ ┌──────────────────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ FLEXMEASURES EMS │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │
|
||||
│ │ │ │ INGESTION │ │ FORECAST │ │ SCHEDULING │ │ REPORTING │ │ │ │
|
||||
│ │ │ │ │ │ │ │ │ │ │ │ │ │
|
||||
│ │ │ │ • Sensors │ │ • PV │ │ • Batteries │ │ • Assets │ │ │ │
|
||||
│ │ │ │ • Assets │ │ • Load │ │ • EVs │ │ • Schedules │ │ │ │
|
||||
│ │ │ │ • Beliefs │ │ • Prices │ │ • Grid │ │ • Forecasts │ │ │ │
|
||||
│ │ │ │ • OCPI CDRs │ │ • CO2 │ │ services │ │ • OCPI CDRs │ │ │ │
|
||||
│ │ │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ ┌─────────────────────────────────────────────────────────────────────────┐ │ │ │
|
||||
│ │ │ │ DATA MODEL │ │ │ │
|
||||
│ │ │ │ Accounts ──► Assets ──► Sensors ──► Beliefs (timed data) │ │ │ │
|
||||
│ │ │ └─────────────────────────────────────────────────────────────────────────┘ │ │ │
|
||||
│ │ └──────────────────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ ┌──────────────────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ DEVICE LAYER │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ ┌────────────────────┐ ┌────────────────────┐ ┌────────────────────┐ │ │ │
|
||||
│ │ │ │ CITRINEOS │ │ EVEREST │ │ _grid SINGULARITY │ │ │ │
|
||||
│ │ │ │ (CSMS) │ │ (Middleware) │ │ (Market) │ │ │ │
|
||||
│ │ │ │ │ │ │ │ │ │ │ │
|
||||
│ │ │ │ • OCPP 2.0.1 │ │ • ISO 15118-2 │ │ • P2P trading │ │ │ │
|
||||
│ │ │ │ • Charge Points │ │ • OCPP proxy │ │ • Market clearing │ │ │ │
|
||||
│ │ │ │ • Transactions │ │ • Smart Charging │ │ • Price discovery │ │ │ │
|
||||
│ │ │ │ • Remote control │ │ • V2G │ │ │ │ │ │
|
||||
│ │ │ │ │ │ │ │ │ │ │ │
|
||||
│ │ │ │ ← OCPP │ │ ← ISO 15118 │ │ ← gsy-e-sdk │ │ │ │
|
||||
│ │ │ │ → FM API │ → CitrineOS OCPP │ │ → FM API │ │ │ │
|
||||
│ │ │ └────────────────────┘ └────────────────────┘ └────────────────────┘ │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ ┌─────────────────────────────────────────────────────────────────────────┐ │ │ │
|
||||
│ │ │ │ DEVICES │ │ │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ │ │ 10 PV Panels (5kWc) │ Modbus TCP │ │ │ │
|
||||
│ │ │ │ 10 Batteries (100kWh) │ Modbus TCP │ │ │ │
|
||||
│ │ │ │ 10 EV Chargers (22kW) │ OCPP 2.0.1 │ │ │ │
|
||||
│ │ │ │ 10 EVs (75kWh V2G) │ ISO 15118 │ │ │ │
|
||||
│ │ │ └─────────────────────────────────────────────────────────────────────────┘ │ │ │
|
||||
│ │ └──────────────────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ ┌──────────────────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ MARKET LAYER (R&D) │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ ┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐ │ │ │
|
||||
│ │ │ │ OPLEM │ │ HAMLET │ │ EPEX LOCALFLEX │ │ │ │
|
||||
│ │ │ │ (Local Market) │ │ (Agent-based LEM) │ │ (Flexibility) │ │ │ │
|
||||
│ │ │ │ │ │ │ │ │ │ │ │
|
||||
│ │ │ │ • Prosumer optim. │ │ • Multi-agent sim │ │ • Local flex market │ │ │ │
|
||||
│ │ │ │ • Battery agents │ │ • Battery agents │ │ • Price signals │ │ │ │
|
||||
│ │ │ │ • EV agents │ │ • EV agents │ │ • Flex bidding │ │ │ │
|
||||
│ │ │ └──────────────────────┘ └──────────────────────┘ └──────────────────────┘ │ │ │
|
||||
│ │ └──────────────────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ ┌──────────────────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ VISUALIZATION LAYER │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ ┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐ │ │ │
|
||||
│ │ │ │ GRAFANA │ │ METABASE │ │ CARIFLEX UI │ │ │ │
|
||||
│ │ │ │ (Port 3001) │ │ (Analytics) │ │ (Port 5000) │ │ │ │
|
||||
│ │ │ │ │ │ │ │ │ │ │ │
|
||||
│ │ │ │ • Timeseries │ │ • SQL queries │ │ • Asset map │ │ │ │
|
||||
│ │ │ │ • Asset table │ │ • Reporting │ │ • Schedules │ │ │ │
|
||||
│ │ │ │ • OCPI CDRs │ │ • Data exploration │ │ • Forecasts │ │ │ │
|
||||
│ │ │ │ • Flexibility KPIs │ │ • Billing │ │ • OCPI sessions │ │ │ │
|
||||
│ │ │ └──────────────────────┘ └──────────────────────┘ └──────────────────────┘ │ │ │
|
||||
│ │ └──────────────────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ └─────────────────────────────────────────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Intégration OCPI
|
||||
|
||||
### 3.1 Qu'est-ce qu'OCPI ?
|
||||
|
||||
**OCPI (Open Charge Point Interface)** est un protocole standard pour l'interopérabilité entre opérateurs de bornes de recharge EV. Il permet :
|
||||
|
||||
- **Tarification** : Échange des tarifs entre opérateurs
|
||||
- **Sessions** : Suivi des sessions de recharge en temps réel
|
||||
- **CDRs** (Call Detail Records) : Facturation inter-opérateurs
|
||||
- **Roaming** : Accès aux bornes d'autres opérateurs
|
||||
- **Commands** : Démarrage/arrêt à distance
|
||||
|
||||
### 3.2 Architecture OCPI dans Cariflex
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ OCPI INTEGRATION │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ OTHER │◄───────►│ CARIFLEX │◄───────►│ CITRINEOS │ │
|
||||
│ │ CPOs │ OCPI │ OCPI │ OCPP │ (CSMS) │ │
|
||||
│ │ │ 2.2 │ GATEWAY │ 2.0.1 │ │ │
|
||||
│ └──────────────┘ └──────┬───────┘ └──────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌──────────────┐ │
|
||||
│ │ FLEXMEASURES │ │
|
||||
│ │ EMS │ │
|
||||
│ │ │ │
|
||||
│ │ • CDRs │ │
|
||||
│ │ • Sessions │ │
|
||||
│ │ • Tariffs │ │
|
||||
│ │ • Roaming │ │
|
||||
│ └──────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3.3 Flux de Données OCPI
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant EV as EV Driver
|
||||
participant OtherCPO as Other CPO
|
||||
participant OCPI as Cariflex OCPI Gateway
|
||||
participant FM as FlexMeasures
|
||||
participant CitrineOS as CitrineOS CSMS
|
||||
participant CP as Cariflex Charge Point
|
||||
|
||||
%% Roaming in (EV driver from other CPO)
|
||||
EV->>CP: Plug in (RFID/App)
|
||||
CP->>CitrineOS: StartTransaction
|
||||
CitrineOS->>FM: POST /sensors/{id}/data (power)
|
||||
|
||||
FM->>OCPI: Check roaming rights
|
||||
OCPI->>OtherCPO: POST /cdrs (session start)
|
||||
OtherCPO-->>OCPI: 200 OK
|
||||
OCPI-->>FM: Authorized
|
||||
|
||||
%% Charging loop
|
||||
loop Every 30s
|
||||
CitrineOS->>FM: Power readings
|
||||
FM->>OCPI: Update session
|
||||
OCPI->>OtherCPO: PATCH /sessions/{id}
|
||||
end
|
||||
|
||||
%% Session end
|
||||
EV->>CP: Unplug
|
||||
CP->>CitrineOS: StopTransaction
|
||||
CitrineOS->>FM: Final readings
|
||||
FM->>OCPI: Generate CDR
|
||||
OCPI->>OtherCPO: POST /cdrs
|
||||
OtherCPO-->>OCPI: CDR accepted
|
||||
```
|
||||
|
||||
### 3.4 Modules OCPI à Développer
|
||||
|
||||
| Module | Endpoint | Description |
|
||||
|--------|----------|-------------|
|
||||
| `ocpi_versions` | `GET /ocpi/2.2` | Version negotiation |
|
||||
| `ocpi_credentials` | `POST /ocpi/2.2/credentials` | Auth tokens |
|
||||
| `ocpi_locations` | `GET /ocpi/2.2/locations` | Bornes Cariflex |
|
||||
| `ocpi_sessions` | `GET/POST /ocpi/2.2/sessions` | Sessions de recharge |
|
||||
| `ocpi_cdrs` | `POST /ocpi/2.2/cdrs` | Facturation |
|
||||
| `ocpi_tariffs` | `GET /ocpi/2.2/tariffs` | Tarifs Cariflex |
|
||||
| `ocpi_commands` | `POST /ocpi/2.2/commands` | Remote control |
|
||||
|
||||
---
|
||||
|
||||
## 4. Intégration GIREVE
|
||||
|
||||
### 4.1 Qu'est-ce que GIREVE ?
|
||||
|
||||
**GIREVE** (Gestion des Itinéraires de Recharge des Véhicules Electriques) est une plateforme d'interopérabilité française pour la mobilité électrique :
|
||||
|
||||
- **Agrégation** : Centralise les données de multiples CPOs et eMSPs
|
||||
- **Roaming** : Facilite l'itinérance de recharge
|
||||
- **Données** : Session data, CDRs, tarifs, disponibilité
|
||||
- **Billing** : Facturation inter-opérateurs
|
||||
- **PNIRE** : Point d'Intersection au Réseau d'Information
|
||||
|
||||
### 4.2 Architecture GIREVE dans Cariflex
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ GIREVE INTEGRATION │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ GIREVE │◄───────►│ CARIFLEX │◄───────►│ FLEXMEASURES│ │
|
||||
│ │ PLATFORM │ eMSP │ GIREVE │ REST │ EMS │ │
|
||||
│ │ │ API │ CONNECTOR │ API │ │ │
|
||||
│ │ │ │ │ │ • CDRs │ │
|
||||
│ │ • Sessions │ │ • Tarifs │ │ • Sessions │ │
|
||||
│ │ • CDRs │ │ • Sessions │ │ • Billing │ │
|
||||
│ │ • Tarifs │ │ • CDRs │ │ • Reporting │ │
|
||||
│ │ • Roaming │ │ • Billing │ │ │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ GIREVE SERVICES │ │
|
||||
│ │ │ │
|
||||
│ │ • PNIRE (Point d'Intersection au Réseau d'Information) │ │
|
||||
│ │ • Roaming hub (inter-CPO) │ │
|
||||
│ │ • Data aggregation (sessions, CDRs) │ │
|
||||
│ │ • Billing reconciliation │ │
|
||||
│ │ • Availability dissemination │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 4.3 Flux de Données GIREVE
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant EV as EV Driver
|
||||
participant CP as Charge Point
|
||||
participant CitrineOS as CitrineOS CSMS
|
||||
participant FM as FlexMeasures
|
||||
participant GIREVE as GIREVE Platform
|
||||
participant OtherCPO as Other CPO
|
||||
|
||||
%% Session start
|
||||
EV->>CP: Start charging
|
||||
CP->>CitrineOS: StartTransaction
|
||||
CitrineOS->>FM: POST /sensors/{id}/data
|
||||
FM->>GIREVE: POST /session (session start)
|
||||
GIREVE-->>FM: Session acknowledged
|
||||
|
||||
%% Charging loop
|
||||
loop Every 30s
|
||||
CitrineOS->>FM: Power readings
|
||||
FM->>GIREVE: PATCH /session/{id} (consumption)
|
||||
end
|
||||
|
||||
%% Session end
|
||||
EV->>CP: Stop charging
|
||||
CP->>CitrineOS: StopTransaction
|
||||
CitrineOS->>FM: Final readings
|
||||
FM->>GIREVE: POST /cdr (final CDR)
|
||||
GIREVE-->>FM: CDR accepted
|
||||
|
||||
%% Roaming
|
||||
OtherCPO->>GIREVE: GET /tariffs (Cariflex tariffs)
|
||||
GIREVE-->>OtherCPO: Tariff data
|
||||
OtherCPO->>GIREVE: POST /session (roaming session)
|
||||
GIREVE->>FM: Validate roaming
|
||||
FM-->>GIREVE: Authorized
|
||||
```
|
||||
|
||||
### 4.4 Services GIREVE à Développer
|
||||
|
||||
| Service | Endpoint | Description |
|
||||
|---------|----------|-------------|
|
||||
| `gireve_tariffs` | `GET /tariffs` | Diffusion des tarifs Cariflex |
|
||||
| `gireve_sessions` | `POST /sessions` | Envoi des sessions |
|
||||
| `gireve_cdrs` | `POST /cdrs` | Envoi des CDRs |
|
||||
| `gireve_locations` | `GET /locations` | Disponibilité des bornes |
|
||||
| `gireve_roaming` | `POST /validate` | Validation roaming entrant |
|
||||
| `gireve_billing` | `GET /reports` | Rapports de facturation |
|
||||
|
||||
---
|
||||
|
||||
## 5. Intégrations à Développer (Mise à Jour)
|
||||
|
||||
| Intégration | Priorité | Complexité | Statut | Description |
|
||||
|-------------|----------|------------|--------|-------------|
|
||||
| **OCPI Gateway** | Haute | Élevée | 📋 À faire | Protocole OCPI 2.2 pour roaming |
|
||||
| **GIREVE Connector** | Haute | Moyenne | 📋 À faire | Connexion plateforme GIREVE |
|
||||
| **CitrineOS ↔ FM** | Haute | Moyenne | ⏳ À faire | OCPP 2.0.1 → FM API |
|
||||
| **EVerest ↔ CitrineOS** | Haute | Moyenne | ⏳ À faire | ISO 15118 → OCPP proxy |
|
||||
| **OpenLEADR ↔ FM** | Haute | Faible | ⏳ À faire | OpenADR 2.0b → FM scheduling |
|
||||
| **Grid Singularity ↔ FM** | Moyenne | Élevée | ⏳ À faire | P2P trading → FM schedules |
|
||||
| **OPLEM ↔ FM** | Moyenne | Moyenne | ⏳ À faire | Local market optimization |
|
||||
| **HAMLET ↔ FM** | Basse | Élevée | ⏳ À faire | Multi-agent simulation |
|
||||
| **MQTT Brokers Cariflex** | Haute | Moyenne | ⏳ À faire | Format compatible FM |
|
||||
|
||||
---
|
||||
|
||||
## 6. Configuration Requise
|
||||
|
||||
### 6.1 FlexMeasures (mise à jour)
|
||||
```yaml
|
||||
# Environment variables
|
||||
FLEXMEASURES_ENV=production
|
||||
FLEXMEASURES_PLATFORM_NAME=Cariflex
|
||||
FLEXMEASURES_MENU_LOGO_PATH=/ui/static/images/cariflex-logo.jpg
|
||||
FLEXMEASURES_REDIS_URL=flexmeasures-redis
|
||||
FLEXMEASURES_REDIS_PORT=6379
|
||||
FLEXMEASURES_REDIS_DB_NR=0
|
||||
FLEXMEASURES_REDIS_PASSWORD=***
|
||||
S...n
|
||||
|
||||
# New: OCPI settings
|
||||
OCPI_ENABLED=true
|
||||
OCPI_VERSION=2.2
|
||||
OCPI_BASE_URL=https://cariflex.digitribe.fr/ocpi
|
||||
OCPI_CPO_IDENTIFIER=FR*CAR
|
||||
|
||||
# New: GIREVE settings
|
||||
GIREVE_ENABLED=true
|
||||
GIREVE_BASE_URL=https://platform.gireve.com
|
||||
GIREVE_CPO_ID=FR_CARIFLEX
|
||||
GIREVE_API_KEY=***
|
||||
```
|
||||
|
||||
### 6.2 Grafana Datasource
|
||||
```json
|
||||
{
|
||||
"name": "PostgreSQL-FlexMeasures",
|
||||
"type": "postgres",
|
||||
"url": "flexmeasures-db:5432",
|
||||
"database": "flexmeasures",
|
||||
"user": "flexmeasures"
|
||||
}
|
||||
```
|
||||
|
||||
### 6.3 Nouvaires Services Docker à Ajouter
|
||||
```yaml
|
||||
# OCPI Gateway
|
||||
cariflex-ocpi:
|
||||
image: cariflex/ocpi-gateway:latest
|
||||
environment:
|
||||
OCPI_VERSION: "2.2"
|
||||
FM_API_URL: "http://flexmeasures-server:5000"
|
||||
CPO_IDENTIFIER: "FR*CAR"
|
||||
ports:
|
||||
- "8081:8080"
|
||||
networks:
|
||||
- cariflex-internal
|
||||
|
||||
# GIREVE Connector
|
||||
cariflex-gireve:
|
||||
image: cariflex/gireve-connector:latest
|
||||
environment:
|
||||
GIREVE_API_URL: "https://platform.gireve.com"
|
||||
FM_API_URL: "http://flexmeasures-server:5000"
|
||||
CPO_ID: "FR_CARIFLEX"
|
||||
networks:
|
||||
- cariflex-internal
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Prochaines Étapes
|
||||
|
||||
1. **Développer OCPI Gateway** : Implémenter les endpoints OCPI 2.2
|
||||
2. **Développer GIREVE Connector** : Connexion à la plateforme GIREVE
|
||||
3. **Intégrer CitrineOS** : Connecter via OCPP 2.0.1 aux bornes EV
|
||||
4. **Intégrer EVerest** : Configurer ISO 15118 pour V2G
|
||||
5. **Intégrer OpenLEADR** : Connecter au DSO pour flexibilité
|
||||
6. **Créer brokers MQTT Cariflex** : Format compatible FM
|
||||
7. **Automatiser forecasting/scheduling** : Cron jobs ou scheduler
|
||||
8. **Intégrer Grid Singularity** : P2P trading
|
||||
9. **Documentation complète** : API, déploiement, fonctionnement
|
||||
93
scripts/generate_architecture_diagram.py
Normal file
93
scripts/generate_architecture_diagram.py
Normal file
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate Cariflex architecture diagrams as PDF."""
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.patches as mpatches
|
||||
from matplotlib.patches import FancyBboxPatch, FancyArrowPatch
|
||||
import matplotlib.patches as patches
|
||||
|
||||
fig, ax = plt.subplots(1, 1, figsize=(20, 14))
|
||||
ax.set_xlim(0, 20)
|
||||
ax.set_ylim(0, 14)
|
||||
ax.axis('off')
|
||||
fig.patch.set_facecolor('#f5f5f5')
|
||||
|
||||
def draw_box(ax, x, y, w, h, text, color='#2196F3', textcolor='white', fontsize=9, alpha=1.0):
|
||||
box = FancyBboxPatch((x, y), w, h, boxstyle="round,pad=0.1",
|
||||
facecolor=color, edgecolor='white', linewidth=2, alpha=alpha)
|
||||
ax.add_patch(box)
|
||||
ax.text(x + w/2, y + h/2, text, ha='center', va='center',
|
||||
fontsize=fontsize, color=textcolor, fontweight='bold', wrap=True)
|
||||
|
||||
def draw_arrow(ax, x1, y1, x2, y2, color='#666', label=''):
|
||||
ax.annotate('', xy=(x2, y2), xytext=(x1, y1),
|
||||
arrowprops=dict(arrowstyle='->', color=color, lw=1.5))
|
||||
if label:
|
||||
mx, my = (x1+x2)/2, (y1+y2)/2
|
||||
ax.text(mx+0.1, my+0.1, label, fontsize=7, color=color)
|
||||
|
||||
# Title
|
||||
ax.text(10, 13.5, 'CARIFLEX EMS - Architecture d\'Intégration',
|
||||
ha='center', fontsize=16, fontweight='bold', color='#1565C0')
|
||||
|
||||
# External Layer
|
||||
ax.text(0.5, 12.5, 'EXTERNAL', fontsize=10, fontweight='bold', color='#666')
|
||||
draw_box(ax, 0.5, 11.5, 4, 0.8, 'EPEX SPOT\nDay-ahead Prices', '#FF9800')
|
||||
draw_box(ax, 5, 11.5, 4, 0.8, 'ENTSO-E\nCO2 / Prices', '#FF9800')
|
||||
draw_box(ax, 9.5, 11.5, 4, 0.8, 'Weather API\nSolcast/Météo', '#FF9800')
|
||||
draw_box(ax, 14, 11.5, 5, 0.8, 'DSO/TSO\nOpenADR / S2', '#FF9800')
|
||||
|
||||
# Arrows to FM
|
||||
draw_arrow(ax, 2.5, 11.5, 5, 10.5, '#666', 'Prices')
|
||||
draw_arrow(ax, 7, 11.5, 7, 10.5, '#666', 'CO2')
|
||||
draw_arrow(ax, 11.5, 11.5, 9, 10.5, '#666', 'Irradiance')
|
||||
draw_arrow(ax, 16.5, 11.5, 15, 10.5, '#666', 'Flex Requests')
|
||||
|
||||
# FlexMeasures EMS (central)
|
||||
draw_box(ax, 3, 8.5, 14, 1.8, '', '#2196F3', alpha=0.2)
|
||||
ax.text(10, 9.8, 'FLEXMEASURES EMS', ha='center', fontsize=12, fontweight='bold', color='#1565C0')
|
||||
draw_box(ax, 3.5, 8.7, 3, 0.8, 'INGESTION\n• Sensors • Assets • Beliefs', '#2196F3', fontsize=7)
|
||||
draw_box(ax, 7, 8.7, 3, 0.8, 'FORECASTING\n• PV • Load • Prices', '#2196F3', fontsize=7)
|
||||
draw_box(ax, 10.5, 8.7, 3, 0.8, 'SCHEDULING\n• Batteries • EVs • Grid', '#2196F3', fontsize=7)
|
||||
draw_box(ax, 14, 8.7, 2.5, 0.8, 'REPORTING\n• Assets • Schedules', '#2196F3', fontsize=7)
|
||||
|
||||
# Device Layer
|
||||
ax.text(0.5, 7.8, 'INTEGRATION', fontsize=10, fontweight='bold', color='#666')
|
||||
draw_box(ax, 0.5, 6.5, 5, 1, 'CITRINEOS (CSMS)\n• OCPP 2.0.1 • Charge Points • Transactions', '#4CAF50', fontsize=8)
|
||||
draw_box(ax, 6, 6.5, 5, 1, 'EVEREST (Middleware)\n• ISO 15118 • Smart Charging • Power Mgmt', '#FF9800', fontsize=8)
|
||||
draw_box(ax, 11.5, 6.5, 5, 1, 'OPENLEADR (VEN)\n• OpenADR 2.0b • DSO Signals • Flexibility', '#9C27B0', fontsize=8)
|
||||
|
||||
# Arrows to devices
|
||||
draw_arrow(ax, 3, 6.5, 3, 5.5, '#4CAF50', 'OCPP')
|
||||
draw_arrow(ax, 8.5, 6.5, 8.5, 5.5, '#FF9800', 'ISO 15118')
|
||||
draw_arrow(ax, 14, 6.5, 14, 5.5, '#9C27B0', 'Commands')
|
||||
|
||||
# Devices
|
||||
ax.text(0.5, 5.8, 'DEVICES', fontsize=10, fontweight='bold', color='#666')
|
||||
draw_box(ax, 0.5, 4.5, 3.5, 1, '10 PV Panels\n5kWc each\nModbus TCP', '#FFC107', fontsize=8, textcolor='#333')
|
||||
draw_box(ax, 4.5, 4.5, 3.5, 1, '10 Batteries\n100kWh each\nModbus TCP', '#FFC107', fontsize=8, textcolor='#333')
|
||||
draw_box(ax, 8.5, 4.5, 3.5, 1, '10 EV Chargers\n22kW each\nOCPP 2.0.1', '#FFC107', fontsize=8, textcolor='#333')
|
||||
draw_box(ax, 12.5, 4.5, 4, 1, '10 EVs\n75kWh V2G\nISO 15118', '#FFC107', fontsize=8, textcolor='#333')
|
||||
|
||||
# Market Layer
|
||||
ax.text(0.5, 3.8, 'MARKET (R&D)', fontsize=10, fontweight='bold', color='#666')
|
||||
draw_box(ax, 0.5, 2.5, 5.5, 1, 'GRID SINGULARITY\ngsy-e (88 stars)\n• P2P Trading • Market Clearing', '#00BCD4', fontsize=8)
|
||||
draw_box(ax, 6.5, 2.5, 5.5, 1, 'OPLEM\npip install oplem\n• Local Market • Prosumer Opt.', '#00BCD4', fontsize=8)
|
||||
draw_box(ax, 12.5, 2.5, 5.5, 1, 'HAMLET\nconda hamlet\n• Multi-agent • Simulation', '#00BCD4', fontsize=8)
|
||||
|
||||
# Visualization Layer
|
||||
ax.text(0.5, 1.8, 'VISUALIZATION', fontsize=10, fontweight='bold', color='#666')
|
||||
draw_box(ax, 0.5, 0.5, 4, 1, 'GRAFANA\n• 4 Timeseries • 1 Table\nPostgreSQL DS', '#E91E63', fontsize=8)
|
||||
draw_box(ax, 5, 0.5, 4, 1, 'METABASE\n• SQL Analytics\n• Reporting', '#E91E63', fontsize=8)
|
||||
draw_box(ax, 9.5, 0.5, 5, 1, 'CARIFLEX UI\n(FM Frontend)\n• Asset Map • Schedules', '#E91E63', fontsize=8)
|
||||
|
||||
# Legend
|
||||
ax.text(15, 1, 'Cariflex - Caribbean Flexibility Platform',
|
||||
ha='center', fontsize=8, fontweight='bold', color='#1565C0',
|
||||
bbox=dict(boxstyle='round', facecolor='white', alpha=0.8))
|
||||
|
||||
plt.tight_layout()
|
||||
plt.savefig('/home/eric/cariflex/docs/architecture_cariflex.pdf', dpi=150, bbox_inches='tight')
|
||||
plt.savefig('/home/eric/cariflex/docs/architecture_cariflex.png', dpi=150, bbox_inches='tight')
|
||||
print("✅ Architecture diagrams generated")
|
||||
print(" - PDF: /home/eric/cariflex/docs/architecture_cariflex.pdf")
|
||||
print(" - PNG: /home/eric/cariflex/docs/architecture_cariflex.png")
|
||||
146
scripts/generate_architecture_v2.py
Normal file
146
scripts/generate_architecture_v2.py
Normal file
@@ -0,0 +1,146 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate Cariflex architecture diagrams v2 (with OCPI and GIREVE) as PDF."""
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.patches as mpatches
|
||||
from matplotlib.patches import FancyBboxPatch
|
||||
import numpy as np
|
||||
|
||||
fig, ax = plt.subplots(1, 1, figsize=(22, 16))
|
||||
ax.set_xlim(0, 22)
|
||||
ax.set_ylim(0, 16)
|
||||
ax.axis('off')
|
||||
fig.patch.set_facecolor('#f8f9fa')
|
||||
|
||||
def draw_box(ax, x, y, w, h, text, color='#2196F3', textcolor='white', fontsize=8, alpha=1.0, border='white'):
|
||||
box = FancyBboxPatch((x, y), w, h, boxstyle="round,pad=0.15",
|
||||
facecolor=color, edgecolor=border, linewidth=1.5, alpha=alpha)
|
||||
ax.add_patch(box)
|
||||
ax.text(x + w/2, y + h/2, text, ha='center', va='center',
|
||||
fontsize=fontsize, color=textcolor, fontweight='bold', wrap=True,
|
||||
multialignment='center')
|
||||
|
||||
def draw_arrow(ax, x1, y1, x2, y2, color='#666', label='', lw=1.2):
|
||||
ax.annotate('', xy=(x2, y2), xytext=(x1, y1),
|
||||
arrowprops=dict(arrowstyle='->', color=color, lw=lw))
|
||||
if label:
|
||||
mx, my = (x1+x2)/2, (y1+y2)/2
|
||||
ax.text(mx+0.1, my+0.1, label, fontsize=6, color=color, style='italic')
|
||||
|
||||
# Title
|
||||
ax.text(11, 15.5, 'CARIFLEX EMS - Architecture d\'Intégration v2',
|
||||
ha='center', fontsize=18, fontweight='bold', color='#1565C0')
|
||||
ax.text(11, 15.1, 'avec OCPI et GIREVE',
|
||||
ha='center', fontsize=12, color='#666')
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
# EXTERNAL LAYER
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
ax.text(0.3, 14.3, 'EXTERNAL', fontsize=9, fontweight='bold', color='#888', style='italic')
|
||||
|
||||
draw_box(ax, 0.3, 13.3, 4.5, 0.8, 'EPEX SPOT\nDay-ahead / Localflex', '#FF9800', fontsize=8)
|
||||
draw_box(ax, 5.3, 13.3, 4.5, 0.8, 'ENTSO-E\nPrices / CO2', '#FF9800', fontsize=8)
|
||||
draw_box(ax, 10.3, 13.3, 4.5, 0.8, 'Weather API\nSolcast / Météo', '#FF9800', fontsize=8)
|
||||
draw_box(ax, 15.3, 13.3, 6, 0.8, 'DSO / TSO\nOpenADR / S2', '#FF9800', fontsize=8)
|
||||
|
||||
# Arrows to interop/integration
|
||||
draw_arrow(ax, 2.5, 13.3, 3, 12.5, '#FF9800', 'prices')
|
||||
draw_arrow(ax, 7.5, 13.3, 8, 12.5, '#FF9800', 'CO2')
|
||||
draw_arrow(ax, 12.5, 13.3, 10, 12.5, '#FF9800', 'weather')
|
||||
draw_arrow(ax, 18.3, 13.3, 17, 12.5, '#FF9800', 'flex')
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
# INTEROPERABILITY LAYER (NEW)
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
ax.text(0.3, 12.7, 'INTEROPERABILITY', fontsize=9, fontweight='bold', color='#888', style='italic')
|
||||
|
||||
draw_box(ax, 0.3, 11.5, 9, 1, 'OCPI Gateway (eMSP/CPO)\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n• Tarifs • Sessions • CDRs • Roaming (in/out) • Commands', '#E91E63', fontsize=7.5)
|
||||
draw_box(ax, 10, 11.5, 9, 1, 'GIREVE Connector\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n• Session data • Roaming hub • Billing • PNIRE • CDRs', '#795548', fontsize=7.5)
|
||||
|
||||
# Arrows from external
|
||||
draw_arrow(ax, 5.3, 11.5, 5.3, 10.8, '#E91E63', 'roaming')
|
||||
draw_arrow(ax, 14.5, 11.5, 12, 10.8, '#795548', 'sessions')
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
# INTEGRATION LAYER
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
ax.text(0.3, 11.0, 'INTEGRATION', fontsize=9, fontweight='bold', color='#888', style='italic')
|
||||
|
||||
# FlexMeasures EMS (central)
|
||||
draw_box(ax, 2, 9.2, 16, 1.5, '', '#2196F3', alpha=0.15)
|
||||
ax.text(10, 10.4, 'FLEXMEASURES EMS', ha='center', fontsize=11, fontweight='bold', color='#1565C0')
|
||||
|
||||
draw_box(ax, 2.3, 9.4, 3.5, 0.9, 'INGESTION\nSensors / Assets\nBeliefs / OCPI CDRs', '#2196F3', fontsize=7)
|
||||
draw_box(ax, 6.2, 9.4, 3.5, 0.9, 'FORECASTING\nPV / Load\nPrices / CO2', '#2196F3', fontsize=7)
|
||||
draw_box(ax, 10.1, 9.4, 3.5, 0.9, 'SCHEDULING\nBatteries / EVs\nGrid services', '#2196F3', fontsize=7)
|
||||
draw_box(ax, 14, 9.4, 3.7, 0.9, 'REPORTING\nAssets / Sched\nForecasts / CDRs', '#2196F3', fontsize=7)
|
||||
|
||||
# Sub-components
|
||||
draw_box(ax, 0.3, 8.2, 5, 0.8, 'CITRINEOS (CSMS)\nOCPP 2.0.1 • Charge Points • Transactions', '#4CAF50', fontsize=7.5)
|
||||
draw_box(ax, 5.8, 8.2, 5, 0.8, 'EVEREST (Middleware)\nISO 15118 • Smart Charging • V2G', '#FF9800', fontsize=7.5)
|
||||
draw_box(ax, 11.3, 8.2, 5, 0.8, 'OPENLEADR (VEN)\nOpenADR 2.0b • DSO • Flexibility', '#9C27B0', fontsize=7.5)
|
||||
|
||||
# Arrows to FM
|
||||
draw_arrow(ax, 2.8, 8.2, 4, 9.2, '#4CAF50', 'REST')
|
||||
draw_arrow(ax, 8.3, 8.2, 8, 9.2, '#FF9800', 'OCPP')
|
||||
draw_arrow(ax, 13.8, 8.2, 12, 9.2, '#9C27B0', 'REST')
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
# DEVICES LAYER
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
ax.text(0.3, 7.5, 'DEVICES', fontsize=9, fontweight='bold', color='#888', style='italic')
|
||||
|
||||
draw_box(ax, 0.3, 6.3, 4.5, 1, '10 PV Panels\n5kWc each\nModbus TCP → FM', '#FFC107', textcolor='#333', fontsize=8)
|
||||
draw_box(ax, 5.3, 6.3, 4.5, 1, '10 Batteries\n100kWh / 50kW\nModbus TCP → FM', '#FFC107', textcolor='#333', fontsize=8)
|
||||
draw_box(ax, 10.3, 6.3, 4.5, 1, '10 EV Chargers\n22kW OCPP 2.0.1\n→ CitrineOS', '#FFC107', textcolor='#333', fontsize=8)
|
||||
draw_box(ax, 15.3, 6.3, 5.5, 1, '10 EVs\n75kWh V2G\nISO 15118 → EVerest', '#FFC107', textcolor='#333', fontsize=8)
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
# MARKET LAYER (R&D)
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
ax.text(0.3, 5.6, 'MARKET (R&D)', fontsize=9, fontweight='bold', color='#888', style='italic')
|
||||
|
||||
draw_box(ax, 0.3, 4.4, 6.5, 1, 'GRID SINGULARITY\ngsy-e • P2P Trading • Market Clearing\nPrice discovery → FM schedules', '#00BCD4', fontsize=7.5)
|
||||
draw_box(ax, 7.3, 4.4, 6.5, 1, 'OPLEM\nLocal Market • Prosumer Opt.\nBattery/EV agents → FM', '#00BCD4', fontsize=7.5)
|
||||
draw_box(ax, 14.3, 4.4, 6.5, 1, 'HAMLET\nMulti-agent Simulation\nStrategy validation → FM', '#00BCD4', fontsize=7.5)
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
# VISUALIZATION LAYER
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
ax.text(0.3, 3.7, 'VISUALIZATION', fontsize=9, fontweight='bold', color='#888', style='italic')
|
||||
|
||||
draw_box(ax, 0.3, 2.5, 6, 1, 'GRAFANA (Port 3001)\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n4 Timeseries + 1 Table\nPostgreSQL-FlexMeasures DS', '#E91E63', fontsize=7.5)
|
||||
draw_box(ax, 6.8, 2.5, 6, 1, 'METABASE\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\nSQL Analytics • Reporting\nBilling • Data exploration', '#E91E63', fontsize=7.5)
|
||||
draw_box(ax, 13.3, 2.5, 7, 1, 'CARIFLEX UI (Port 5000)\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\nAsset Map • Schedules\nForecasts • OCPI Sessions', '#E91E63', fontsize=7.5)
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
# NETWORK LEGEND
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
ax.text(0.3, 1.8, 'PROTOCOLS:', fontsize=8, fontweight='bold', color='#666')
|
||||
|
||||
protocols = [
|
||||
('OCPP 2.0.1', '#4CAF50'),
|
||||
('ISO 15118', '#FF9800'),
|
||||
('OCPI 2.2', '#E91E63'),
|
||||
('OpenADR', '#9C27B0'),
|
||||
('Modbus', '#FFC107'),
|
||||
('REST API', '#2196F3'),
|
||||
('GIREVE', '#795548'),
|
||||
]
|
||||
|
||||
for i, (name, color) in enumerate(protocols):
|
||||
x = 0.3 + i * 2.8
|
||||
rect = plt.Rectangle((x, 1.1), 0.3, 0.4, facecolor=color, edgecolor='white')
|
||||
ax.add_patch(rect)
|
||||
ax.text(x + 0.5, 1.3, name, fontsize=7, color='#333')
|
||||
|
||||
# Footer
|
||||
ax.text(11, 0.5, 'Cariflex - Caribbean Flexibility Platform - 2026',
|
||||
ha='center', fontsize=10, fontweight='bold', color='#1565C0',
|
||||
bbox=dict(boxstyle='round', facecolor='white', alpha=0.8))
|
||||
|
||||
plt.tight_layout()
|
||||
plt.savefig('/home/eric/cariflex/docs/architecture_cariflex_v2.pdf', dpi=150, bbox_inches='tight')
|
||||
plt.savefig('/home/eric/cariflex/docs/architecture_cariflex_v2.png', dpi=150, bbox_inches='tight')
|
||||
print("✅ Architecture v2 diagrams generated")
|
||||
print(" - PDF: /home/eric/cariflex/docs/architecture_cariflex_v2.pdf")
|
||||
print(" - PNG: /home/eric/cariflex/docs/architecture_cariflex_v2.png")
|
||||
Reference in New Issue
Block a user