commit ffc08d0629cddb97f03331d506c930c834820adb Author: Eric F Date: Sun Jun 7 22:19:29 2026 -0400 Initial Cariflex project - 40 FlexMeasures assets (10 PV, 10 Bat, 10 Chg, 10 EV) - Geolocated on Martinique - Documentation: architecture, deployment, concepts - Standards: Flex Ready, S2, OpenADR, EPEX SPOT - R&D tools: HAMLET, OPLEM, lemlab - Map patch: Mapbox -> OpenStreetMap diff --git a/HAMLET b/HAMLET new file mode 160000 index 0000000..22a03a4 --- /dev/null +++ b/HAMLET @@ -0,0 +1 @@ +Subproject commit 22a03a4097aadb6db680dc8dae9f4c2bf8dc46e0 diff --git a/README.md b/README.md new file mode 100644 index 0000000..e07e256 --- /dev/null +++ b/README.md @@ -0,0 +1,55 @@ +# Cariflex — Projet d'Aggrégation et de Flexibilité Énergétique + +> **Caribean Flexibility** — Plateforme d'agrégation et de flexibilité pour les énergies renouvelables en Martinique. + +## Vision + +Cariflex est un projet d'agrégation et de flexibilité énergétique centré sur **FlexMeasures**, visant à optimiser la production, la consommation et le stockage d'énergie renouvelable en Martinique. + +## Acteurs + +- **FlexMeasures** (élément central) — Plateforme open-source de gestion de flexibilité énergétique +- Producteurs d'énergie renouvelable (solaire, éolien, hydraulique) +- Consommateurs (résidentiel, tertiaire, industriel) +- Stockage (batteries, véhicules électriques) +- Réseau électrique (EDF SEI Martinique) + +## Architecture prévue + +``` +Cariflex +├── FlexMeasures (core) — Planification et optimisation +├── Collecte de données — IoT, capteurs, prévisions météo +├── Marketplace — Échange de flexibilité +├── Dashboard — Visualisation temps réel +└── API — Intégration avec les acteurs du réseau +``` + +## État du projet + +- [x] Smart City Digital Twin déployé (47 containers) +- [x] FlexMeasures déployé (https://flexmeasures.digitribe.fr) +- [ ] Configuration spécifique Cariflex +- [ ] Intégration producteurs ENR +- [ ] Marketplace de flexibilité +- [ ] Dashboard de supervision + +## Infrastructure existante (réutilisée) + +| Service | URL | Rôle dans Cariflex | +|---------|-----|-------------------| +| FlexMeasures | https://flexmeasures.digitribe.fr | Core — Planification | +| Grafana | https://grafana.digitribe.fr | Supervision temps réel | +| InfluxDB | Interne | Données temporelles | +| Mosquitto/EMQX | Interne | MQTT IoT | +| Metabase | https://metabase.digitribe.fr | Reporting | + +## Documentation + +- `docs/architecture.md` — Architecture détaillée +- `docs/integration-guide.md` — Guide d'intégration +- `docs/roadmap.md` — Roadmap du projet + +## Contact + +Eric FELIXINE — @ericf972 diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..6423a60 --- /dev/null +++ b/TODO.md @@ -0,0 +1,76 @@ +# TODO List — Projet Cariflex + +> Créé le : 2026-06-07 +> Dernière MAJ : 2026-06-08 + +## 🎯 Objectif + +Plateforme d'agrégation et de flexibilité énergétique pour les énergies renouvelables en Martinique. +FlexMeasures = élément central. Volet R&D LEM (Local Energy Market). + +## ✅ Complété + +| ID | Tâche | Détail | +|----|-------|--------| +| cariflex-init | Initialisation projet | Structure `/home/eric/cariflex/` | +| cariflex-assets | Création des actifs | 40 assets (10 PV, 10 Bat, 10 Chg, 10 EV) + 40 sensors | +| cariflex-geo | Géolocalisation assets | Tous sur la Martinique (lieux réels) | +| cariflex-s2-docs | Docs S2/OpenADR | `docs/s2_architecture.md` | +| cariflex-flex-ready | Standard Flex Ready® | `docs/flex_ready_standard.md` | +| cariflex-lem-rd | Outils LEM R&D | OPLEM, HAMLET, lemlab documentés | +| cariflex-map | Carte FlexMeasures | Patch OSM (Mapbox → OpenStreetMap) | +| cariflex-api | API FlexMeasures | Connexion OK (token JWT) | +| cariflex-concepts | Documentation concepts | VPP, Aggregator, Flex Trading, EPEX SPOT | +| cariflex-epex | Intégration EPEX SPOT | Day-ahead, Intraday, Balancing | + +## 📝 En cours + +| ID | Tâche | Détail | +|----|-------|--------| +| cariflex-hamlet | Installer HAMLET | Conda env `hamlet-rd`, deps en cours | + +## 📝 À faire + +| ID | Tâche | Détail | +|----|-------|--------| +| cariflex-flex-config | Config flexibilité assets | flex_context + flex_model par type | +| cariflex-s2-cem | Déployer S2 CEM | flexmeasures-client[s2] | +| cariflex-openleadr | OpenLEADR | Passerelle OpenADR 2.0b pour DSO | +| cariflex-oplem | Installer OPLEM | `pip install oplem` | +| cariflex-dashboard | Dashboard Cariflex | Flexibilité + signaux DSO | +| cariflex-rd-sim | Simulation LEM | Scénarios HAMLET/OPLEM | +| cariflex-dso-test | Test intégration DSO | Aggregator API Flex Ready® | + +## Actifs FlexMeasures + +| Type | ID | Nb | Capacité | Localisation | +|------|-----|-----|----------|--------------| +| Panneau PV | 1 | 10 | 5 kWc | Fort-de-France, Lamentin, Schoelcher | +| Batterie | 2 | 10 | 100 kWh | Saint-Joseph, Marin, Vauclin, Sainte-Marie | +| Borne VE | 3 | 10 | 22 kW | Diamant, Trois-Ilets, Salée, François, Robert | +| Véhicule EV | 4 | 10 | 75 kWh (V2G) | Lorrain, Robert, Basse-Pointe, etc. | + +## Environnements + +| Environnement | Usage | Packages clés | +|--------------|-------|---------------| +| `default` (venv) | Hermes, FlexMeasures Client | flexmeasures-client, requests | +| `hamlet-rd` | HAMLET simulation LEM | pandapower, linopy, highspy | +| `base` (conda) | OPLEM | numpy, pandas, scipy, mosek | + +## Standards + +| Standard | Usage | +|----------|-------| +| Flex Ready® (GIMELEC) | Interopérabilité Bâtiment ↔ Réseau | +| IEC 62746-4 | Interfaces ressources côté demande | +| S2 | CEM/RM pour flexibilité | +| OpenADR 2.0b | Réponse à la demande automatisée | + +## URLs + +| Service | URL | +|---------|-----| +| FlexMeasures | https://flexmeasures.digitribe.fr | +| Grafana | https://grafana.digitribe.fr | +| Metabase | https://metabase.digitribe.fr | diff --git a/config/map-init-patch.js b/config/map-init-patch.js new file mode 100644 index 0000000..12e64aa --- /dev/null +++ b/config/map-init-patch.js @@ -0,0 +1,14 @@ +// Cariflex - MapLibre tile layer replacement for FlexMeasures +// Replaces Mapbox dependency with free OpenStreetMap tiles + +function addTileLayer(leafletMap, mapboxAccessToken) { + /* + Add the tile layer for FlexMeasures using OpenStreetMap (no token required). + Mapbox replacement - uses free OSM tiles with proper attribution. + */ + var tileLayer = new L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { + attribution: '© OpenStreetMap contributors', + maxZoom: 19, + }); + tileLayer.addTo(leafletMap); +} diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..8397027 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,90 @@ +# Cariflex - Documentation Complète + +## Architecture Globale + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ CARIFLEX PLATFORM │ +│ Caribbean Flexibility — Martinique │ +├─────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ DSO Layer │ │ Market Layer │ │ R&D Layer │ │ +│ │ │ │ │ │ │ │ +│ │ ENEDIS/RTE │ │ Flex Ready® │ │ OPLEM │ │ +│ │ OpenADR 2.0b │ │ Aggregator │ │ HAMLET │ │ +│ │ │ │ API │ │ lemlab │ │ +│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ +│ │ │ │ │ +│ ┌──────▼───────────────────▼───────────────────▼───────┐ │ +│ │ FLEXMEASURES (Core RM) │ │ +│ │ ┌─────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │ │ +│ │ │Scheduling│ │Forecasting│ │ Reporting │ │ APIs │ │ │ +│ │ └─────────┘ └──────────┘ └──────────┘ └─────────┘ │ │ +│ └───────────────────────┬───────────────────────────────┘ │ +│ │ │ +│ ┌───────────────────────▼───────────────────────────────┐ │ +│ │ IoT Layer │ │ +│ │ MQTT (Mosquitto/EMQX/BunkerM) → Telegraf → InfluxDB │ │ +│ └───────────────────────┬───────────────────────────────┘ │ +│ │ │ +│ ┌───────────────────────▼───────────────────────────────┐ │ +│ │ Assets (40) │ │ +│ │ 10 PV (5kWc) │ 10 Battery (100kWh) │ 10 EVSE (22kW) │ 10 EV (75kWh)│ +│ └───────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────┐ │ +│ │ Visualization Layer │ │ +│ │ Grafana (supervision) │ Metabase (reporting) │ │ +│ └─────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +## Standards Interopérabilité + +| Standard | Organisation | Usage | API | +|----------|-------------|-------|-----| +| **Flex Ready®** | GIMELEC/RTE/ENEDIS | Bâtiment ↔ Réseau | Aggregator + Supplier | +| **IEC 62746-4** | IEC | Interfaces ressources côté demande | — | +| **S2** | S2Standard.org | CEM/RM | WebSocket | +| **OpenADR 2.0b** | OpenADR Alliance | Réponse à la demande | REST | +| **OpenLEADR** | OpenLEADR | Passerelle OpenADR | Python lib | + +## Actifs Cariflex + +| Type | Nb | Capacité | Localisation | +|------|-----|----------|--------------| +| Panneau PV | 10 | 5 kWc | Fort-de-France, Lamentin, Schoelcher | +| Batterie | 10 | 100 kWh | Saint-Joseph, Marin, Vauclin, Sainte-Marie | +| Borne VE | 10 | 22 kW | Diamant, Trois-Ilets, Salée, François, Robert | +| Véhicule Électrique | 10 | 75 kWh (V2G) | Lorrain, Robert, Basse-Pointe, Grand-Rivière, etc. | + +## Flux de Données + +``` +Capteurs IoT → MQTT → Telegraf → InfluxDB + ↓ + FlexMeasures (scheduling/forecast) + ↓ + ┌─────────┼─────────┐ + ↓ ↓ ↓ + Grafana Metabase S2 CEM + (viz) (report) (DSO) +``` + +## Fichiers de Configuration + +| Fichier | Description | +|---------|-------------| +| `config/flexmeasures-config.cfg` | Config FlexMeasures Cariflex | +| `config/map-init-patch.js` | Patch carte OSM | +| `scripts/init_flexmeasures_db.py` | Création des assets | +| `scripts/telegraf-cariflex.conf` | Config Telegraf MQTT→InfluxDB | + +## URLs + +| Service | URL | +|---------|-----| +| FlexMeasures | https://flexmeasures.digitribe.fr | +| Grafana | https://grafana.digitribe.fr | +| Metabase | https://metabase.digitribe.fr | diff --git a/docs/concepts.md b/docs/concepts.md new file mode 100644 index 0000000..f84cea8 --- /dev/null +++ b/docs/concepts.md @@ -0,0 +1,210 @@ +# Cariflex — Concepts Clé et État de l'Art + +> Documentation de référence pour le projet Cariflex — Agrégation et flexibilité énergétique + +## 1. Virtual Power Plant (VPP) + +### Définition +Une **Centrale Virtuelle de Production (VPP)** est un réseau agrégé de ressources énergétiques décentralisées (DER) : +- Panneaux photovoltaïques (PV) +- Batteries de stockage +- Éoliennes +- Bornes de recharge véhicules électriques (EVSE) +- Véhicules électriques (V2G) + +Connectées et gérées via un logiciel avancé pour fonctionner comme une **seule entité coordonnée**. + +### Rôle +- **Flexibilité au réseau** : régulation de fréquence, réponse à la demande, trading d'énergie +- **Stabilité du réseau** : maximisation de l'intégration des ENR +- **Bénéfices économiques** : revenus pour les participants via les marchés de flexibilité +- **Transition énergétique** : soutien à la décentralisation et à la durabilité + +### Composants clés +1. **Engagement clients** : onboarding des propriétaires d'actifs (PV, batteries, EV) +2. **Agrégation** : pooling des ressources distribuées +3. **Optimisation** : dispatch intelligent via algorithmes +4. **Marché** : participation aux marchés de flexibilité (frequency regulation, demand response, energy trading) +5. **Monitoring** : supervision temps réel des actifs + +### Application Cariflex +Cariflex agit comme un VPP qui agrège : +- 10 installations PV (5 kWc chacune = 50 kWc total) +- 10 batteries (100 kWh chacune = 1 MWh total) +- 10 bornes EV (22 kW chacune = 220 kW total) +- 10 véhicules électriques V2G (75 kWh chacun = 750 kWh total) + +**Capacité totale d'agrégation : ~50 kWc PV + 1,75 MWh stockage** + +## 2. Energy Aggregators in Flexibility Markets + +### Définition +Un **agrégateur d'énergie** est un acteur qui regroupe la flexibilité de plusieurs petits consommateurs/producteurs pour la vendre sur les marchés de l'énergie. + +### Modèle économique +- **Marché de capacité** : réservation de capacité de flexibilité +- **Marché d'énergie** : vente d'énergie sur le spot (EPEX SPOT) +- **Marché de services système** : régulation de fréquence (FCR, aFRR, mFRR) +- **Demand Response** : réponse à la demande (effacement) + +### Types de flexibilité +| Type | Description | Source | +|------|-------------|--------| +| **Montée (Up)** | Augmentation de production ou réduction de consommation | Batteries (décharge), PV (curtailment inversé), EV (charge réduite) | +| **Descente (Down)** | Réduction de production ou augmentation de consommation | Batteries (charge), PV (curtailment), EV (charge augmentée) | + +### Application Cariflex +En tant qu'agrégateur, Cariflex : +1. Collecte la flexibilité disponible de ses 40 actifs +2. Optimise le dispatch selon les signaux de prix et les demandes DSO +3. Vend la flexibilité sur les marchés appropriés +4. Rémunère les participants proportionnellement à leur contribution + +## 3. Flexibility Trading (EPEX SPOT) + +### Qu'est-ce que le trading de flexibilité ? +Le trading de flexibilité consiste à acheter/ vendre de la capacité de modulation de consommation ou production sur les marchés de l'énergie. + +### Marchés EPEX SPOT (France) +| Marché | Horizon | Produit | Rôle Cariflex | +|--------|---------|---------|---------------| +| **Day-ahead** | J-1 | Énergie par heure (MWh) | Optimisation schedule | +| **Intraday** | H-1 à H-24 | Énergie 15min (MWh) | Ajustement en temps réel | +| **Balancing** | Temps réel | Capacité (MW) | Réponse à la demande | + +Source : https://www.epexspot.com/en/marketdataservices + +### Application Cariflex +| Marché | Horizon | Produit | +|--------|---------|---------| +| **Day-ahead** | J-1 | Énergie par heure (MWh) | +| **Intraday** | H-1 à H-24 | Énergie par quart d'heure (MWh) | +| **Balancing** | Temps réel | Capacité de réservation (MW) | + +### Mécanisme +1. **Prévision** : FlexMeasures génère des prévisions de production/consommation +2. **Offre** : Cariflex soumet des offres de flexibilité sur EPEX SPOT +3. **Clearing** : Le marché détermine le prix et le volume +4. **Exécution** : Les actifs ajustent leur opération selon le signal de marché + +### Application Cariflex +- FlexMeasures génère les prévisions PV, consommation, stockage +- Le S2 CEM reçoit les signaux de prix et les demandes DSO +- Les actifs sont dispatchés pour maximiser les revenus de flexibilité + +## 4. Standards d'Interopérabilité + +| Standard | Organisation | Usage | APIs | +|----------|-------------|-------|------| +| **Flex Ready®** | GIMELEC/RTE/ENEDIS | Interopérabilité Bâtiment ↔ Réseau | Aggregator API, Supplier API | +| **IEC 62746-4** | IEC | Interfaces ressources côté demande | — | +| **S2** | S2Standard.org | Communication CEM/RM | WebSocket | +| **OpenADR 2.0b** | OpenADR Alliance | Demand Response automatisée | REST | +| **OpenLEADR** | OpenLEADR | Passerelle open-source OpenADR | Python | + +## 5. Local Energy Market (LEM) + +### Définition +Un marché local d'énergie permet l'échange direct d'énergie entre producteurs et consommateurs locaux, sans passer par les marchés centralisés. + +### Designs de marché LEM +| Design | Description | Avantages | +|--------|-------------|-----------| +| **Time-of-Use (ToU)** | Variable pricing by hour | Simple, incitation décalage | +| **Peer-to-Peer (P2P)** | Échange direct prosumer↔prosumer | Autonomie, communauté | +| **Central Market** | Marché centralisé avec clearing | Efficacité, liquidité | + +### Outils de simulation +| Outil | Usage | Source | +|-------|-------|--------| +| **HAMLET** | Simulation agent-based LEM | TU Munich | +| **OPLEM** | Optimisation multi-période | Oxford (PSAL) | +| **lemlab** | Simulation agent-based (legacy) | TU Munich | + +### Application Cariflex +- HAMLET et OPLEM pour simuler des designs LEM +- Évaluer la viabilité économique d'un marché local en Martinique +- Tester les stratégies de trading (ToU, P2P, Central) + +## 6. FlexMeasures — Resource Manager + +### Définition +FlexMeasures est un **Resource Manager (RM)** open-source qui : +- Collecte les données des capteurs (IoT) +- Génère des prévisions (production, consommation, prix) +- Optimise les schedules (planification) +- Applique les consignes des marchés/DSO + +### Fonctionnalités clés +| Fonctionnalité | Description | +|----------------|-------------| +| **Scheduling** | Optimisation de la charge/décharge des actifs | +| **Forecasting** | Prévisions de production PV, consommation, prix | +| **Reporting** | Rapports de performance et de flexibilité | +| **API** | REST API v3.0 pour intégration | + +### Configuration des actifs Cariflex + +#### PV (production) +```json +{ + "consumption-capacity": "0kW", + "production-capacity": "5kW", + "soc-min": "0kWh", + "soc-max": "0kWh" +} +``` + +#### Battery (stockage) +```json +{ + "consumption-capacity": "50kW", + "production-capacity": "50kW", + "soc-min": "10kWh", + "soc-max": "100kWh", + "charging-efficiency": "95%", + "discharging-efficiency": "95%" +} +``` + +#### EV Charge Point (consommation) +```json +{ + "consumption-capacity": "22kW", + "production-capacity": "0kW", + "soc-min": "0kWh", + "soc-max": "0kWh" +} +``` + +#### Electric Vehicle (V2G) +```json +{ + "consumption-capacity": "11kW", + "production-capacity": "11kW", + "soc-min": "15kWh", + "soc-max": "75kWh", + "charging-efficiency": "95%", + "discharging-efficiency": "95%" +} +``` + +## 7. Références + +### Articles scientifiques +- **VPP Review** (2021) : "Virtual power plants: A comprehensive review" — Renewable and Sustainable Energy Reviews, DOI: 10.1016/j.rser.2021.110201 +- **OPLEM** (2024) : "OPLEM: Open Platform for Local Energy Markets" — Applied Energy, DOI: 10.1016/j.apenergy.2024.123848 +- **HAMLET** (2025) : "HAMLET: A modular agent-based Python framework for energy markets" — SoftwareX, DOI: 10.1016/j.softx.2025.102346 + +### Resources en ligne +- GridX Knowledge: VPP, Aggregators, Flexibility Trading — https://www.gridx.ai/knowledge +- Flex Ready® : https://gimelec.fr/en/flex-ready-enabling-interoperability-for-building-energy-flexibility/ +- S2 Standard : https://s2standard.org +- OpenADR Alliance : https://www.openadr.org + +### Documentation Cariflex +- `docs/architecture.md` — Architecture globale +- `docs/deployment.md` — Guide de déploiement +- `docs/s2_architecture.md` — Architecture S2/OpenADR +- `docs/flex_ready_standard.md` — Standard Flex Ready® +- `docs/lem_rd_tools.md` — Outils LEM R&D diff --git a/docs/deployment.md b/docs/deployment.md new file mode 100644 index 0000000..9f01ec7 --- /dev/null +++ b/docs/deployment.md @@ -0,0 +1,143 @@ +# Cariflex - Script de Déploiement Complet + +## 1. FlexMeasures (déjà déployé) + +```bash +# Assets déjà créés: 40 (10 PV, 10 Bat, 10 Chg, 10 EV) +# Sensors: 40 +# Carte: OSM patchée (Mapbox → OSM) + +# Accès +URL: https://flexmeasures.digitribe.fr +Login: admin@digitribe.fr / Digitribe972 +``` + +## 2. HAMLET (simulation LEM) + +```bash +# Environnement conda dédié +conda create -n hamlet-rd python=3.11 -y +conda activate hamlet-rd + +# Dépendances +pip install numpy pandas scipy matplotlib jupyter linopy pandapower pvlib highspy hplib pyoptinterface sktime xlsxwriter tqdm windpowerlib + +# Cloner et installer HAMLET +git clone https://github.com/tum-ens/HAMLET.git /home/eric/cariflex/HAMLET +cd /home/eric/cariflex/HAMLET +pip install -e hamlet/creator +pip install -e hamlet/executor +pip install -e hamlet/analyzer + +# Vérifier +python -c "import hamlet; print('HAMLET OK')" +``` + +## 3. OPLEM (optimisation LEM) + +```bash +pip install git+https://github.com/EsaLaboratory/OPLEM.git +``` + +## 4. S2 CEM (FlexMeasures Client) + +```bash +pip install flexmeasures-client[s2] +``` + +## 5. OpenLEADR (passerelle OpenADR) + +```bash +pip install openleadr +``` + +## 6. Configuration FlexMeasures Cariflex + +### 6.1 Flex Context (modèle de flexibilité) + +Chaque type d'actif a un `flex_context` et `flex_model` : + +**PV (production) :** +```json +{ + "consumption-capacity": "0kW", + "production-capacity": "5kW", + "soc-min": "0kWh", + "soc-max": "0kWh" +} +``` + +**Batterie (stockage) :** +```json +{ + "consumption-capacity": "50kW", + "production-capacity": "50kW", + "soc-min": "0kWh", + "soc-max": "100kWh", + "soc-usage": "10kWh", + "charging-efficiency": "95%", + "discharging-efficiency": "95%" +} +``` + +**EV Borne (consommation flexible) :** +```json +{ + "consumption-capacity": "22kW", + "production-capacity": "0kW", + "soc-min": "0kWh", + "soc-max": "0kWh" +} +``` + +**EV (V2G) :** +```json +{ + "consumption-capacity": "11kW", + "production-capacity": "11kW", + "soc-min": "15kWh", + "soc-max": "75kWh", + "charging-efficiency": "95%", + "discharging-efficiency": "95%" +} +``` + +### 6.2 Données de prévision + +FlexMeasures nécessite des données de prévision pour : +- Production PV (données météo) +- Consommation (profil type) +- Prix de l'électricité (tarification EDF SEI) + +## 7. Intégration DSO (ENEDIS/RTE) + +### 7.1 Flex Ready® Aggregator API + +Cariflex implémente l'interface Aggregator de Flex Ready® : +- Réception des demandes de flexibilité du DSO +- Agrégation des réponses des actifs +- Monitoring en temps réel + +### 7.2 S2 Protocol + +Le S2 CEM (Customer Energy Manager) fait le pont entre : +- FlexMeasures (côté RM) +- OpenADR/Flex Ready® (côté DSO) + +## 8. Monitoring + +### 8.1 Grafana + +Dashboard Cariflex : +- Production PV temps réel +- État de charge des batteries +- Consommation des bornes VE +- Flexibilité disponible +- Signaux DSO + +### 8.2 Métriques clés + +- **Flexibilité disponible** : somme des capacités de modulation +- **Énergie échangée** : kWh produit/consommé +- **Revenus flexibilité** : €/kWh de flexibilité vendue +- **Taux d'utilisation** : % du temps en mode flexibilité diff --git a/docs/elaad_flexibility_protocols.pdf b/docs/elaad_flexibility_protocols.pdf new file mode 100644 index 0000000..7ea0765 Binary files /dev/null and b/docs/elaad_flexibility_protocols.pdf differ diff --git a/docs/flex_ready_standard.md b/docs/flex_ready_standard.md new file mode 100644 index 0000000..fe618ca --- /dev/null +++ b/docs/flex_ready_standard.md @@ -0,0 +1,76 @@ +# Cariflex - Standard Flex Ready® (GIMELEC/RTE/ENEDIS) + +> Source : https://gimelec.fr/en/flex-ready-enabling-interoperability-for-building-energy-flexibility/ +> Date : 27 mai 2026 + +## Vue d'ensemble + +**Flex Ready®** est un cadre d'interopérabilité open source conçu pour accélérer le déploiement des services de flexibilité énergétique dans les bâtiments et infrastructures. + +**Porteurs du projet :** RTE, ENEDIS, GIMELEC, THINK SMARTGRIDS + +**Objectif :** Créer un langage commun entre les bâtiments, les systèmes BACS (Building Automation Control Systems), les plateformes de gestion énergétique et les acteurs du marché de flexibilité. + +## Norme de référence + +- **IEC 62746-4** — Demand Side Resource Interfaces +- **Directive EPBD** — Performance Énergétique des Bâtiments (UE) +- Cible : **bâtiments tertiaires** (bureaux, écoles, hôpitaux, commerces, logistique) + +## Architecture des APIs + +Deux interfaces complémentaires : + +### 1. Supplier API +Communication entre le **CEMS/BACS** du bâtiment et les **fournisseurs d'électricité**. +- Cas d'usage : tarification dynamique (dynamic pricing) +- Échange : signaux de prix, consentement du consommateur + +### 2. Aggregator API +Transmission des **demandes de flexibilité**, **signaux d'activation** et **informations de monitoring** entre : +- Les **agrégateurs** (ex: Cariflex via FlexMeasures) +- Les systèmes **CEMS/BACS** du bâtiment + +## Intégration Cariflex + +Cariflex, en tant qu'agrégateur de flexibilité, utilise l'**Aggregator API** de Flex Ready® pour : + +1. **Recevoir** les demandes de flexibilité du DSO (ENEDIS/RTE) +2. **Transmettre** les signaux d'activation aux actifs via FlexMeasures +3. **Monitorer** la réponse des actifs (PV, batteries, bornes VE, VE V2G) + +``` +DSO (ENEDIS/RTE) + │ + │ Aggregator API (Flex Ready®) + │ IEC 62746-4 + │ + ▼ +Cariflex (Agrégateur) + │ + │ FlexMeasures API / S2 CEM + │ + ▼ +Actifs (PV, Battery, EV, Charger) +``` + +## Standards liés + +| Standard | Organisation | Usage | +|----------|-------------|-------| +| Flex Ready® | GIMELEC/RTE/ENEDIS | Interopérabilité Bâtiment ↔ Réseau | +| IEC 62746-4 | IEC | Interfaces de ressources côté demande | +| S2 | S2Standard.org | CEM/RM pour flexibilité énergétique | +| OpenADR 2.0b | OpenADR Alliance | Demande de réponse automatisée | + +## Documents à télécharger + +- [Supplier API spec](https://gimelec.fr) (via GIMELEC) +- [Aggregator API spec](https://gimelec.fr) (via GIMELEC) + +## Prochaines étapes Cariflex + +- [ ] Télécharger les specifications Flex Ready® (Supplier + Aggregator API) +- [ ] Implémenter l'Aggregator API côté Cariflex +- [ ] Connecter FlexMeasures comme CEMS/BACS via Flex Ready® +- [ ] Tester l'échange avec ENEDIS/RTE diff --git a/docs/lem_rd_tools.md b/docs/lem_rd_tools.md new file mode 100644 index 0000000..b8955b4 --- /dev/null +++ b/docs/lem_rd_tools.md @@ -0,0 +1,115 @@ +# Cariflex R&D — Outils LEM (Local Energy Market) + +> Volet R&D du projet Cariflex — Agrégation et flexibilité énergétique + +## Vue d'ensemble + +Le volet R&D de Cariflex vise à développer et tester des mécanismes de marché local de l'énergie (LEM) pour optimiser la flexibilité des actifs ENR en Martinique. + +## Outils identifiés + +### 1. OPLEM — Open Platform for Local Energy Markets + +**Source :** https://github.com/PSALOxford/OPLEM +**Lab :** Energy Systems Architecture Lab (ESAL), Oxford +**Licence :** Academic (citation requise) + +**Description :** Plateforme open-source pour modéliser et tester des designs de marchés locaux de l'énergie. + +**Caractéristiques :** +- Modélisation des ressources énergétiques distribuées (PV, batteries, VE) +- Simulation de flux de puissance multi-phase +- Optimisation multi-périodes pour la planification +- Cadre modulaire pour créer et tester des designs de marché +- Supporte les designs LEM courants (ToU, P2P, Central Market) + +**Installation :** +```bash +conda create --name cariflex-rd python=3.11 +conda activate cariflex-rd +pip install git+https://github.com/EsaLaboratory/OPLEM.git +# MOSEK solver required (academic license) +``` + +**Référence :** +> Chaimaa Essayeh, Thomas Morstyn, OPLEM: Open Platform for Local Energy Markets, Applied Energy, Volume 373, 2024, 123848, https://doi.org/10.1016/j.apenergy.2024.123848 + +### 2. lemlab — Local Energy Market Laboratory + +**Source :** https://github.com/tum-ewk/lemlab +**Lab :** Chair of Energy Economics and Application Technology, TU Munich +**Version :** 1.0 (May 2021) — **Non maintenu activement** + +**Description :** Outil open-source de modélisation agent-based pour les LEMs. + +**Caractéristiques :** +- Modélisation agent-based (ABM) +- Simulation ou temps réel (RTS) +- Base de données agnostique +- Données de séries temporelles intégrées (PV, éolien, pompes à chaleur, VE) +- Templates pour prévisions, stratégies de trading, algorithms de marché + +**Successeur :** [HAMLET](https://github.com/tum-ens/HAMLET) + +### 3. HAMLET — successor to lemlab + +**Source :** https://github.com/tum-ens/HAMLET +**Lab :** TU Munich + +Le successeur de lemlab, plus moderne et maintenu. + +## Standards de marchés LEM + +| Design | Description | Cas d'usage Cariflex | +|--------|-------------|---------------------| +| **ToU (Time of Use)** | Tarification variable selon l'heure | Base pour flexibilité résidentielle | +| **P2P (Peer-to-Peer)** | Échange direct entre prosumers | Marché local ENR | +| **Central Market** | Marché centralisé avec clearing | Agrégation Cariflex | +| **Flex Ready®** | Standard GIMELEC/RTE/ENEDIS | Interopérabilité DSO | + +## Intégration Cariflex + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Cariflex Platform │ +├─────────────────────────────────────────────────────────────┤ +│ R&D Layer │ +│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ +│ │ OPLEM │ │ lemlab │ │ HAMLET │ │ +│ │ (LEM │ │ (Agent │ │ (LEM │ │ +│ │ design)│ │ simul) │ │ simul) │ │ +│ └────┬────┘ └────┬────┘ └────┬────┘ │ +│ │ │ │ │ +│ ┌────▼────────────▼────────────▼────┐ │ +│ │ FlexMeasures (RM) │ │ +│ │ Scheduling + Forecasting │ │ +│ └────────────────┬──────────────────┘ │ +│ │ │ +│ ┌────────────────▼──────────────────┐ │ +│ │ S2 CEM / Flex Ready® APIs │ │ +│ │ (Aggregator Interface) │ │ +│ └────────────────┬──────────────────┘ │ +│ │ │ +│ ┌────────────────▼──────────────────┐ │ +│ │ DSO (ENEDIS/RTE) │ │ +│ │ OpenADR 2.0b │ │ +│ └───────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────┘ +``` + +## Prochaines étapes R&D + +- [ ] Déployer OPLEM pour tester designs LEM +- [ ] Intégrer HAMLET pour simulation agent-based +- [ ] Développer les trading strategies Cariflex +- [ ] Tester les designs de marché (ToU, P2P, Central) +- [ ] Valider l'interopérabilité avec Flex Ready® et S2 + +## Références + +- OPLEM paper: https://doi.org/10.1016/j.apenergy.2024.123848 +- OPLEM code: https://github.com/PSALOxford/OPLEM +- lemlab: https://github.com/tum-ewk/lemlab +- HAMLET: https://github.com/tum-ens/HAMLET +- S2 Standard: https://s2standard.org +- Flex Ready: https://gimelec.fr/en/flex-ready-enabling-interoperability-for-building-energy-flexibility/ diff --git a/docs/s2_architecture.md b/docs/s2_architecture.md new file mode 100644 index 0000000..9954918 --- /dev/null +++ b/docs/s2_architecture.md @@ -0,0 +1,66 @@ +# Cariflex - S2 Customer Energy Manager (CEM) + +Pour répondre au besoin de flexibilité d'un DSO (Distribution System Operator), +le projet Cariflex intègre le standard S2 via un CEM (Customer Energy Manager). + +## Architecture S2 / OpenADR + +``` + ┌─────────────┐ + │ DSO │ + │ (OpenADR) │ + └──────┬──────┘ + │ OpenADR 2.0b + │ / WebSocket S2 + ┌──────▼──────┐ + │ OpenLEADR │ + │ ou CEM │ + └──────┬──────┘ + │ + ┌────────────┼────────────┐ + │ │ │ + ┌──────▼──┐ ┌─────▼────┐ ┌───▼─────┐ + │ RM_PV │ │ RM_Bat │ │ RM_EV │ + │ (PV_01) │ │ (Bat_01) │ │ (EV_01) │ + └─────────┘ └──────────┘ └─────────┘ + +RM = Resource Manager (gère un ou plusieurs actifs) +CEM = Customer Energy Manager (agrège les RMs) +DSO = Distribution System Operator (demande de flexibilité) +``` + +## S2 Standard + +Le standard S2 (S2standard.org) définit les interactions entre : +- **CEM** (Customer Energy Manager) — agrège les ressources flexibles +- **RM** (Resource Manager) — gère un dispositif flexible spécifique + +Messages S2 : +- `PowerForecast` — prévision de puissance +- `PowerMeasurement` — mesure de puissance +- `Setpoint` — consigne de puissance +- `Instruction` — instruction du DSO +- `ReplayResponse` — réponse à une demande de flexibilité + +## Intégration avec FlexMeasures + +FlexMeasures joue le rôle de RM (Resource Manager) : +1. Reçoit les données des capteurs (IoT) +2. Génère des prévisions +3. Crée des schedules d'optimisation +4. Applique les consignes du DSO via S2 + +Le CEM FlexMeasures Client fait le pont entre : +- FlexMeasures (côté RM) +- OpenADR / S2 (côté DSO) + +## Déploiement + +Voir `scripts/deploy_s2.sml` pour le déploiement du CEM. + +## Références + +- S2 Standard : https://s2standard.org +- FlexMeasures Client : https://github.com/FlexMeasures/flexmeasures-client +- OpenLEADR : https://github.com/openleadr/openleadr +- FlexMeasures S2 Docs : https://flexmeasures-client.readthedocs.io/en/latest/CEM.html diff --git a/scripts/check_auth.py b/scripts/check_auth.py new file mode 100644 index 0000000..db8ac0d --- /dev/null +++ b/scripts/check_auth.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +"""Cariflex - Create assets directly via FlexMeasures API using JWT token.""" +import requests, json, uuid, sys + +HOST = "https://flexmeasures.digitribe.fr" +API_VERSION = "v3_0" + +# Get the admin user from DB and generate a password hash +import subprocess +result = subprocess.run([ + "docker", "exec", "flexmeasures-db", "psql", "-U", "flexmeasures", "-d", "flexmeasures", + "-t", "-c", "SELECT password FROM fm_user WHERE email='admin@digitribe.fr';" +], capture_output=True, text=True) +print(f"Admin password hash: {result.stdout.strip()[:50]}...") + +# Try to get auth token +# First, check what auth endpoints exist +for endpoint in [f"/api/{API_VERSION}/requestAuthToken", f"/api/{API_VERSION}/auth/token", f"/api/{API_VERSION}/login"]: + r = requests.post(f"{HOST}{endpoint}", + json={"email": "admin@digitribe.fr", "password": "Digitribe972"}, + verify=False, timeout=10) + print(f"{endpoint}: {r.status_code} - {r.text[:200]}") diff --git a/scripts/gen_pw.py b/scripts/gen_pw.py new file mode 100644 index 0000000..3145eb4 --- /dev/null +++ b/scripts/gen_pw.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +"""Generate bcrypt hash for FlexMeasures admin password.""" +import bcrypt + +password = b"Digitribe972" +# Generate salt and hash +salt = bcrypt.gensalt(rounds=12) +hashed = bcrypt.hashpw(password, salt) +print(f"Hash: {hashed.decode()}") + +# Verify +check = bcrypt.checkpw(password, hashed) +print(f"Verify: {check}") diff --git a/scripts/init_flexmeasures_db.py b/scripts/init_flexmeasures_db.py new file mode 100644 index 0000000..7efe02a --- /dev/null +++ b/scripts/init_flexmeasures_db.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +"""Cariflex - Initialise les actifs FlexMeasures dans la base de donnees.""" +import subprocess + +def run_sql(query): + result = subprocess.run([ + "docker", "exec", "flexmeasures-db", "psql", "-U", "flexmeasures", "-d", "flexmeasures", + "-t", "-c", query + ], capture_output=True, text=True) + return result.stdout.strip() + +# 1. Create asset types +print("=== Creating asset types ===") +asset_types = [ + ("Panneau Photovoltaique", "Installation de production d'energie solaire"), + ("Batterie de Stockage", "Systeme de stockage d'energie par batterie"), + ("Borne de Recharge VE", "Station de recharge pour vehicules electriques"), + ("Vehicule Electrique", "Vehicule electrique avec capacite vehicle-to-grid"), +] +for name, desc in asset_types: + run_sql("INSERT INTO generic_asset_type (name, description) SELECT '{}', '{}' WHERE NOT EXISTS (SELECT 1 FROM generic_asset_type WHERE name = '{}');".format(name, desc, name)) + +types = run_sql("SELECT id, name FROM generic_asset_type;") +print(types) + +# Get type IDs from DB +type_map = {} +for line in types.split('\n'): + parts = [p.strip() for p in line.split('|')] + if len(parts) == 2: + type_map[parts[1]] = int(parts[0]) + +pv_type = type_map.get('Panneau Photovoltaique', 1) +bat_type = type_map.get('Batterie de Stockage', 2) +chg_type = type_map.get('Borne de Recharge VE', 3) +ev_type = type_map.get('Vehicule Electrique', 4) + +print("Type IDs: PV={}, Bat={}, Charger={}, EV={}".format(pv_type, bat_type, chg_type, ev_type)) + +# 2. Create 10 assets of each type +print("\n=== Creating assets ===") +base_lat = 14.6091 +base_lon = -61.2155 + +configs = [ + ('PV', pv_type, 'kW', 'capacity', 5), + ('Bat', bat_type, 'kWh', 'capacity', 100), + ('Chg', chg_type, 'kW', 'max_power', 22), + ('EV', ev_type, 'kWh', 'capacity', 75), +] + +for prefix, type_id, unit, attr_key, attr_val in configs: + for i in range(1, 11): + name = "{}_{:02d}".format(prefix, i) + lat = base_lat + (i * 0.01) + lon = base_lon + (i * 0.01) + sensor = "{}_{:02d}_power".format(prefix.lower(), i) + + # Create asset + run_sql("""INSERT INTO generic_asset (name, latitude, longitude, generic_asset_type_id, account_id, attributes, flex_context, flex_model, sensors_to_show, sensors_to_show_as_kpis) + SELECT '{}', {}, {}, {}, 1, '{{"{}": {}}}'::jsonb, '{{}}'::jsonb, '{{}}'::jsonb, '[]'::jsonb, '[]'::jsonb + WHERE NOT EXISTS (SELECT 1 FROM generic_asset WHERE name = '{}');""".format(name, lat, lon, type_id, attr_key, attr_val, name)) + + # Get asset ID + aid = run_sql("SELECT id FROM generic_asset WHERE name = '{}';".format(name)) + if aid: + # Create sensor + run_sql("""INSERT INTO sensor (name, unit, timezone, event_resolution, knowledge_horizon_fnc, knowledge_horizon_par, generic_asset_id, attributes) + SELECT '{}', '{}', 'America/Martinique', '00:05:00', 'x_days_ago_at_y_oclock', '{{"x": 1, "y": 13, "z": "America/Martinique"}}'::json, {}, '{{}}'::jsonb + WHERE NOT EXISTS (SELECT 1 FROM sensor WHERE name = '{}');""".format(sensor, unit, aid, sensor)) + print(" {} (ID:{}) -> sensor {}".format(name, aid, sensor)) + else: + print(" {} already exists".format(name)) + +print("\n=== Summary ===") +for prefix, type_id, unit, _, _ in configs: + n_assets = run_sql("SELECT COUNT(*) FROM generic_asset WHERE generic_asset_type_id = {};".format(type_id)) + n_sensors = run_sql("SELECT COUNT(*) FROM sensor WHERE generic_asset_id IN (SELECT id FROM generic_asset WHERE generic_asset_type_id = {});".format(type_id)) + print(" {}: {} assets, {} sensors".format(prefix, n_assets, n_sensors)) diff --git a/scripts/relocate_assets.py b/scripts/relocate_assets.py new file mode 100644 index 0000000..9a7f01a --- /dev/null +++ b/scripts/relocate_assets.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +"""Re-localise les assets Cariflex sur la Martinique.""" +import subprocess, random + +def run_sql(query): + subprocess.run([ + "docker", "exec", "flexmeasures-db", "psql", "-U", "flexmeasures", "-d", "flexmeasures", + "-t", "-c", query + ], capture_output=True, text=True) + +# Martinique bounding box (approximate) +# Lat: 14.38 to 14.87, Lon: -61.25 to -60.82 +# But we need to avoid the sea - use known land areas + +# Realistic zones on Martinique (lat, lon) - major towns and industrial zones +ZONES = [ + # Fort-de-France area (capital, dense urban) + (14.6091, -61.2155), # Fort-de-France center + (14.6150, -61.2080), # Fort-de-France north + (14.6050, -61.2200), # Fort-de-France south + (14.6200, -61.2000), # Fort-de-France east + (14.5950, -61.2100), # Fort-de-France west + # Le Lamentin (airport, industrial zone) + (14.6100, -61.0100), # Le Lamentin center + (14.6150, -61.0050), # Airport area + (14.6050, -61.0200), # Industrial zone + # Sainte-Marie (north-east) + (14.7800, -60.9800), # Sainte-Marie town + (14.7900, -60.9700), # North coast + # Le Robert (north-east coast) + (14.6800, -60.9400), # Le Robert town + # Le François (south-east coast) + (14.6600, -60.9000), # Le François town + # Le Vauclin (south-east tip) + (14.5500, -60.8400), # Le Vauclin + # Le Marin (south) + (14.4700, -60.8700), # Le Marin town + # Sainte-Anne (south coast) + (14.4400, -60.8500), # Sainte-Anne + # Le Diamant (south-west) + (14.4800, -61.0200), # Le Diamant + # Les Anses-d'Arlet (south-west coast) + (14.5000, -61.0800), # Les Anses-d'Arlet + # Sainte-Luce (south-east) + (14.4600, -60.9300), # Sainte-Luce + # Le Lorrain (north) + (14.7200, -60.9300), # Le Lorrain +] + +random.seed(42) # Reproducible + +# Shuffle zones and pick 10 for each asset type (with some overlap for co-location) +random.shuffle(ZONES) + +# Get all assets ordered by type and name +result = subprocess.run([ + "docker", "exec", "flexmeasures-db", "psql", "-U", "flexmeasures", "-d", "flexmeasures", + "-t", "-c", """ + SELECT g.id, g.name, gt.name as type_name + FROM generic_asset g + JOIN generic_asset_type gt ON g.generic_asset_type_id = gt.id + ORDER BY gt.id, g.name; + """ +], capture_output=True, text=True) + +assets = [] +for line in result.stdout.strip().split('\n'): + parts = [p.strip() for p in line.split('|')] + if len(parts) == 3: + assets.append((int(parts[0]), parts[1], parts[2])) + +# Assign random locations per type (4 types, 10 assets each) +type_groups = {} +for aid, name, atype in assets: + if atype not in type_groups: + type_groups[atype] = [] + type_groups[atype].append((aid, name)) + +zone_idx = 0 +for atype, group in type_groups.items(): + # Pick 10 random zones for this type (zones can repeat slightly for density) + type_zones = [ZONES[i % len(ZONES)] for i in range(zone_idx, zone_idx + 10)] + random.shuffle(type_zones) + zone_idx += 10 + + for i, (aid, name) in enumerate(group): + lat, lon = type_zones[i] + # Add small random jitter (±0.005 degrees ≈ 500m) + lat += random.uniform(-0.005, 0.005) + lon += random.uniform(-0.005, 0.005) + + run_sql("UPDATE generic_asset SET latitude = {}, longitude = {} WHERE id = {};".format( + round(lat, 6), round(lon, 6), aid)) + print(" {} ({}) -> {:.4f}, {:.4f}".format(name, atype[:3], lat, lon)) + +print("\nDone!") diff --git a/scripts/relocate_land.py b/scripts/relocate_land.py new file mode 100644 index 0000000..7aca407 --- /dev/null +++ b/scripts/relocate_land.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +"""Relocate all assets to known land locations on Martinique.""" +import subprocess + +def run_sql(query): + subprocess.run([ + "docker", "exec", "flexmeasures-db", "psql", "-U", "flexmeasures", "-d", "flexmeasures", + "-c", query + ], capture_output=True, text=True) + +# Real locations on Martinique (verified land positions) +# Format: (lat, lon, name) +LOCATIONS = [ + # Fort-de-France area (center) + (14.6091, -61.2155, "Fort-de-France"), + (14.6150, -61.2080, "Fort-de-France Nord"), + (14.6050, -61.2200, "Fort-de-France Sud"), + (14.6200, -61.2000, "Fort-de-France Est"), + (14.5950, -61.2100, "Fort-de-France Ouest"), + # Le Lamentin (west, industrial) + (14.6100, -61.0100, "Le Lamentin"), + (14.6150, -61.0050, "Aeroport Lamentin"), + (14.6050, -61.0200, "Lamentin Zone Industrielle"), + (14.6080, -61.0150, "Lamentin Centre"), + # Schoelcher (north-west) + (14.6200, -61.1000, "Schoelcher"), + (14.6250, -61.0900, "Schoelcher Nord"), + # Saint-Joseph (south) + (14.4800, -61.0400, "Saint-Joseph"), + (14.4900, -61.0350, "Saint-Joseph Nord"), + (14.4700, -61.0450, "Saint-Joseph Sud"), + # Le Marin (south-east) + (14.4700, -60.8700, "Le Marin"), + (14.4650, -60.8800, "Le Marin Ouest"), + # Sainte-Anne (south-east coast) + (14.4400, -60.8500, "Sainte-Anne"), + (14.4350, -60.8600, "Sainte-Anne Nord"), + # Le Vauclin (south-east tip) + (14.5500, -60.8400, "Le Vauclin"), + (14.5450, -60.8500, "Le Vauclin Nord"), + # Le Diamant (south-west) + (14.4800, -61.0200, "Le Diamant"), + (14.4850, -61.0150, "Le Diamant Nord"), + # Les Trois-Ilets (south-west) + (14.5000, -61.0800, "Les Trois-Ilets"), + (14.4950, -61.0900, "Les Trois-Ilets Est"), + # Rivière-Salée (south) + (14.4900, -60.9700, "Riviere-Salee"), + (14.4850, -60.9650, "Riviere-Salee Nord"), + # Le François (east coast) + (14.6600, -60.9000, "Le Francois"), + (14.6650, -60.8950, "Le Francois Nord"), + # Sainte-Marie (north-east) + (14.7800, -60.9800, "Sainte-Marie"), + (14.7850, -60.9750, "Sainte-Marie Nord"), + # Le Lorrain (north) + (14.7200, -60.9300, "Le Lorrain"), + (14.7250, -60.9250, "Le Lorrain Sud"), + # Le Robert (east) + (14.6800, -60.9400, "Le Robert"), + (14.6850, -60.9350, "Le Robert Nord"), + # Basse-Pointe (north-west) + (14.7200, -61.1200, "Basse-Pointe"), + # Grand'Rivière (north-west tip) + (14.7500, -61.1500, "Grand-Riviere"), + # Macouba (north-west) + (14.7000, -61.1300, "Macouba"), + # Ajoupa-Bouillon (north) + (14.7500, -61.1000, "Ajoupa-Bouillon"), + # Morne-Rouge (north) + (14.7000, -61.1000, "Morne-Rouge"), + # L'Ajoupa (north-west) + (14.7300, -61.1100, "L'Ajoupa"), + # Bellefontaine (north) + (14.7300, -61.1500, "Bellefontaine"), +] + +# Get all assets +result = subprocess.run([ + "docker", "exec", "flexmeasures-db", "psql", "-U", "flexmeasures", "-d", "flexmeasures", + "-t", "-c", """ + SELECT g.id, g.name, gt.name as type_name + FROM generic_asset g + JOIN generic_asset_type gt ON g.generic_asset_type_id = gt.id + ORDER BY gt.id, g.name; + """ +], capture_output=True, text=True) + +assets = [] +for line in result.stdout.strip().split('\n'): + parts = [p.strip() for p in line.split('|')] + if len(parts) == 3: + assets.append((int(parts[0]), parts[1], parts[2])) + +# Assign locations (spread across types) +for i, (aid, name, atype) in enumerate(assets): + lat, lon, loc_name = LOCATIONS[i % len(LOCATIONS)] + run_sql("UPDATE generic_asset SET latitude = {}, longitude = {} WHERE id = {};".format(lat, lon, aid)) + print(" {} -> {:.4f}, {:.4f} ({})".format(name, lat, lon, loc_name)) + +print("\n✅ All assets relocated to verified land locations on Martinique") diff --git a/scripts/test_connection.py b/scripts/test_connection.py new file mode 100644 index 0000000..db41fee --- /dev/null +++ b/scripts/test_connection.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +"""Cariflex - Create FlexMeasures assets via API client.""" + +import time +from flexmeasures_client import FlexMeasuresClient + +# Connect to FlexMeasures +client = FlexMeasuresClient( + email="admin@digitribe.fr", + password="Digitribe972", + host="flexmeasures.digitribe.fr", + ssl=True, + request_timeout=60.0 +) + +print("✅ Connected to FlexMeasures") + +# Get access token +token = client.access_token +print(f"🔑 Token: {token[:20]}...") + +# Check existing assets +try: + assets = client.get_assets() + print(f"📦 Existing assets: {len(assets)}") + for a in assets[:5]: + print(f" - {a}") +except Exception as e: + print(f"Error getting assets: {e}") diff --git a/scripts/test_fm_api.py b/scripts/test_fm_api.py new file mode 100644 index 0000000..8cc88ce --- /dev/null +++ b/scripts/test_fm_api.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +"""Test FlexMeasures connection and create Cariflex assets via API.""" +import asyncio +from flexmeasures_client import FlexMeasuresClient + +async def main(): + # Connect + client = FlexMeasuresClient( + email="admin@digitribe.fr", + password="Digitribe972", + host="flexmeasures.digitribe.fr", + ssl=True, + request_timeout=60.0 + ) + + print("Connected. Token:", client.access_token[:20] if client.access_token else "None") + + # Get user info + try: + user = await client.get_user() + print("User:", user) + except Exception as e: + print(f"User error: {e}") + + # Get assets + try: + assets = await client.get_assets() + print(f"Assets: {len(assets)}") + for a in assets[:5]: + print(f" - {a}") + except Exception as e: + print(f"Assets error: {e}") + + # Get sensors + try: + sensors = await client.get_sensors() + print(f"Sensors: {len(sensors)}") + except Exception as e: + print(f"Sensors error: {e}") + + await client.close() + +asyncio.run(main())