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
This commit is contained in:
1
HAMLET
Submodule
1
HAMLET
Submodule
Submodule HAMLET added at 22a03a4097
55
README.md
Normal file
55
README.md
Normal file
@@ -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
|
||||||
76
TODO.md
Normal file
76
TODO.md
Normal file
@@ -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 |
|
||||||
14
config/map-init-patch.js
Normal file
14
config/map-init-patch.js
Normal file
@@ -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: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
||||||
|
maxZoom: 19,
|
||||||
|
});
|
||||||
|
tileLayer.addTo(leafletMap);
|
||||||
|
}
|
||||||
90
docs/architecture.md
Normal file
90
docs/architecture.md
Normal file
@@ -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 |
|
||||||
210
docs/concepts.md
Normal file
210
docs/concepts.md
Normal file
@@ -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
|
||||||
143
docs/deployment.md
Normal file
143
docs/deployment.md
Normal file
@@ -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é
|
||||||
BIN
docs/elaad_flexibility_protocols.pdf
Normal file
BIN
docs/elaad_flexibility_protocols.pdf
Normal file
Binary file not shown.
76
docs/flex_ready_standard.md
Normal file
76
docs/flex_ready_standard.md
Normal file
@@ -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
|
||||||
115
docs/lem_rd_tools.md
Normal file
115
docs/lem_rd_tools.md
Normal file
@@ -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/
|
||||||
66
docs/s2_architecture.md
Normal file
66
docs/s2_architecture.md
Normal file
@@ -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
|
||||||
22
scripts/check_auth.py
Normal file
22
scripts/check_auth.py
Normal file
@@ -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]}")
|
||||||
13
scripts/gen_pw.py
Normal file
13
scripts/gen_pw.py
Normal file
@@ -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}")
|
||||||
79
scripts/init_flexmeasures_db.py
Normal file
79
scripts/init_flexmeasures_db.py
Normal file
@@ -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))
|
||||||
96
scripts/relocate_assets.py
Normal file
96
scripts/relocate_assets.py
Normal file
@@ -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!")
|
||||||
101
scripts/relocate_land.py
Normal file
101
scripts/relocate_land.py
Normal file
@@ -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")
|
||||||
29
scripts/test_connection.py
Normal file
29
scripts/test_connection.py
Normal file
@@ -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}")
|
||||||
43
scripts/test_fm_api.py
Normal file
43
scripts/test_fm_api.py
Normal file
@@ -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())
|
||||||
Reference in New Issue
Block a user