enedis-client
Récupère la courbe de charge de ton compteur Linky via la passerelle MyElectricalData, et l'exporte en JSON et en CSV.
Première brique d'une future intégration Home Assistant : toute la logique d'accès aux données vit ici, pour être réutilisée telle quelle ensuite.
Démarrage
make setup # venv + dépendances
make demo # essaie tout, sans token ni réseau
make demo fait tourner la chaîne complète — découpage en fenêtres, parsing,
agrégation, export — sur des données simulées. C'est le moyen le plus rapide de
voir ce que produit l'outil sans toucher à ton quota Enedis.
Pour de vraies données :
cp .env.example .env # puis renseigne ENEDIS_PDL et ENEDIS_TOKEN
make check # vérifie le consentement et le quota restant
make daily # consommation quotidienne en kWh -> dumps/
make fetch # courbe de charge (nécessite la collecte horaire)
Commence par make daily. La consommation quotidienne ne dépend que du
consentement et fonctionne immédiatement. La courbe de charge, elle, exige en
plus que la collecte horaire soit activée chez Enedis — voir En cas de
problème.
Commandes
| Commande | Effet |
|---|---|
enedis check |
Valide le .env, l'état du consentement Enedis et le quota d'appels |
enedis daily --days 30 |
Consommation quotidienne en kWh — marche sans la collecte horaire |
enedis fetch --days 30 |
Courbe de charge au pas du compteur |
enedis fetch --start 2026-01-01 --end 2026-02-01 |
Une période précise (--end est exclue) |
enedis demo --days 20 |
La courbe de charge sur des données simulées |
enedis cache-clear |
Efface les données que la passerelle a mises en cache |
Options communes : --format json|csv|both, --out <dossier>, --no-cache,
-y/--yes, -v pour le détail, --env-file pour un .env alternatif.
--end est exclue : --end 2026-02-01 s'arrête au 31 janvier inclus. Les
périodes impossibles (inversées, futures, au-delà de 24 mois) sont refusées avec
un message et le code de sortie 2, avant le moindre appel réseau.
Le binaire s'appelle enedis une fois le projet installé ; python -m enedis_client
fonctionne aussi.
Le cache stocke tes données chez un tiers
Les endpoints en /cache font stocker tes données chiffrées, pendant 30 jours,
sur les serveurs de MyElectricalData. C'est un compromis : le cache épargne le
quota Enedis, qui est serré.
Le cache est actif par défaut, et chaque commande le rappelle à l'écran.
--no-cache va chercher la donnée directement chez Enedis sans rien y laisser,
au prix d'un appel de quota. enedis cache-clear efface ce qui y est déjà.
Ce que couvre le client
| Endpoint | Méthode | Donnée |
|---|---|---|
consumption_load_curve |
consumption_load_curve() |
Puissance moyenne en W, au pas du compteur |
production_load_curve |
production_load_curve() |
Idem, en production (photovoltaïque) |
daily_consumption |
daily_consumption() |
Énergie en Wh, par journée |
daily_production |
daily_production() |
Idem, en production |
contracts |
contracts() |
Puissance souscrite, option tarifaire |
valid_access |
valid_access() |
Consentement, quota, réinitialisation |
*/cache (DELETE) |
clear_cache() |
Purge du cache de la passerelle |
identity, contact et addresses existent aussi côté passerelle mais ne sont
pas exposés : ce sont des données personnelles sans rapport avec la consommation.
En bibliothèque
from datetime import date, timedelta
from enedis_client import MyElectricalDataClient, Settings, fetch_daily, fetch_load_curve
today = date.today()
with MyElectricalDataClient(Settings.from_env()) as client:
# Quotidien : une énergie en Wh par journée.
series = fetch_daily(client, today - timedelta(days=30), today)
print(f"{series.total_energy_kwh:.1f} kWh sur {len(series)} jours")
# Courbe de charge : une puissance moyenne en W par intervalle.
curve = fetch_load_curve(client, today - timedelta(days=7), today)
for reading in curve.readings[:3]:
print(reading.start, "->", reading.end, reading.power_w, "W", reading.energy_wh, "Wh")
DailySeries et LoadCurve sont deux types distincts, volontairement : le
quotidien porte des Wh d'énergie, la courbe de charge des W de puissance. Passer
l'un au parseur de l'autre lève une ParseError explicite plutôt que de produire
des chiffres faux d'un facteur deux.
Ce que le format Enedis a de piégeux
Trois détails cassent silencieusement les calculs si on les rate. Ils sont traités dans models.py et couverts par des tests.
dateest la fin de l'intervalle, pas son début.IntervalReadingexpose les deux (startetend).valueest une puissance moyenne en watts, pas une énergie.energy_whfait la conversion avec la vraie durée de l'intervalle.- Le pas de mesure n'est pas toujours 30 minutes : Enedis livre du
PT10M,PT30MouPT60Mselon le compteur. Il est lu dans chaque mesure.
À quoi s'ajoute le changement d'heure : en octobre, l'heure 02:00–03:00 est
vécue deux fois et Enedis renvoie deux fois les mêmes horodatages. Ils sont
désambiguïsés par l'ordre d'arrivée. Pour comparer ou soustraire deux mesures,
utilise end_utc — entre deux datetime qui partagent le même fuseau, Python
soustrait les valeurs naïves et ignore le décalage.
Limites de l'API
- Courbe de charge : 7 jours maximum par appel, 24 mois d'historique.
- Quotidien : 1095 jours par appel, 36 mois d'historique. Enedis le dit lui-même — « Il est possible de recevoir au maximun 1095j de données consécutives ».
- Rien pour la journée en cours : les bornes sont ramenées automatiquement dans
la fenêtre servable, et
fetch/dailydécoupent et recollent les périodes plus longues. - Une plage longue est annoncée avant d'être lancée. Le nombre d'appels
s'affiche en tête, et au-delà de 20 la commande demande confirmation — deux ans
d'historique, c'est 105 appels pour un quota de l'ordre de 50 par jour.
--yespasse outre. - Deux quotas, pas un.
enedis checkaffiche le compteur de la passerelle (appels/quota), mais Enedis applique en plus son propre throttling, qui peut refuser un appel alors que ce compteur est à zéro. Dans ce cas la réponse indique l'heure de réouverture, etenedis fetchla relaie telle quelle. Ce refus n'est jamais réessayé : l'accès ne rouvre pas avant plusieurs heures. - Le cache de la passerelle est utilisé par défaut ;
--no-cacheforce un vrai appel chez Enedis. - La collecte de la courbe de charge doit être activée chez Enedis, et se réactive chaque année à la date anniversaire. Sans ça, les réponses sont vides.
En cas de problème
| Message | Cause | Quoi faire |
|---|---|---|
aucune mesure entre … la collecte horaire doit etre activee |
La passerelle répond 404 no measure found. Le consentement peut être valide sans que la collecte horaire le soit : c'est une option distincte, à activer sur le compte Enedis (Je souhaite accéder à mes données horaires). |
L'activer, puis attendre : elle passe par En cours d'activation et le premier relevé arrive sous quelques jours. Rien n'est rétroactif. En attendant, enedis daily fonctionne. |
quota d'appels Enedis atteint … Acces rouvert le … |
Throttling Enedis, indépendant du compteur affiché par enedis check. |
Attendre l'heure indiquée. Le cache de la passerelle évite d'y revenir. |
token refuse par la passerelle (403 Le point de livraison ne correspond au token fourni) |
ENEDIS_TOKEN invalide, ou lié à un autre PDL. Refaire un consentement invalide le token précédent. |
Reprendre le token affiché sur myelectricaldata.fr et le remettre dans .env. |
consentement Enedis absent ou expire |
Le consentement a une date de fin. | Le renouveler sur myelectricaldata.fr. |
enedis check répond aux trois derniers cas sans consommer de quota Enedis.
Intégration Home Assistant
Le dossier custom_components/enedis_med/ contient une intégration installable via HACS en dépôt personnalisé (catégorie Integration), puis ajoutée depuis Paramètres → Appareils et services.
La configuration se fait entièrement par l'interface : point de livraison et token. Le couple est validé auprès de la passerelle avant que l'entrée soit créée, donc une erreur de saisie se voit tout de suite.
La consommation apparaît dans le dashboard Energy sous Consommation du
réseau, au nom Enedis <pdl> consommation. Ce n'est pas une entité mais une
statistique externe : c'est la seule façon d'injecter de l'historique passé,
ce qu'un capteur classique ne permet pas.
Ce qu'il faut savoir
- Le token est stocké en clair dans
.storage/core.config_entries. C'est le fonctionnement normal de Home Assistant pour toutes les intégrations. - Refaire un consentement sur myelectricaldata.fr invalide le token précédent. Home Assistant le détecte et ouvre un formulaire de ré-authentification qui ne redemande que le token.
- Le rattrapage est étalé. Un appel couvre 7 jours et le quota est de 50 appels par jour : après une longue coupure, le dashboard se remplit sur plusieurs cycles plutôt que d'un bloc. Le cycle est de 12 heures.
- Les mesures impossibles sont écartées. Tout intervalle dépassant la puissance souscrite lue dans ton contrat est ignoré et journalisé. Sur des données réelles, un point à 20 822 W pour 9 kVA souscrits ramenait l'erreur totale de 5,75 % à 1,31 % face aux index quotidiens.
Développement
make test # aucun appel réseau : respx simule la passerelle
make lint # style ruff
L'environnement exige Python 3.14, imposé par
pytest-homeassistant-custom-component. make setup l'installe via uv.
Pour figer le format exact renvoyé par ton propre compteur :
python scripts/capture_fixture.py --day 2026-09-01
Un seul appel, sur une seule journée ; le PDL est remplacé et les puissances bruitées, donc la fixture produite est commitable.
Structure
| Fichier | Rôle |
|---|---|
| config.py | Lecture et validation du .env, masquage du token |
| client.py | Appels HTTP, retries, traduction des erreurs |
| models.py | Parsing, fuseau horaire, énergie ; LoadCurve et DailySeries |
| windows.py | Découpage en fenêtres (7 jours horaire, 1095 quotidien) |
| loadcurve.py | Enchaînement des fenêtres et recollement |
| export.py | Écriture JSON et CSV |
| demo.py | Fausse passerelle pour le mode démo |
| errors.py | Une exception par cause traitable |
| cli.py | Commandes check, fetch, demo |
| demo.py | Fausse passerelle pour le mode démo |
Metadata
Release files for enedis-client 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| enedis_client-1.0.0.tar.gz | 44.3 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| enedis_client-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 79.5 kB
Release files / enedis_client-1.0.0.tar.gz
| Download URL | enedis_client-1.0.0.tar.gz |
|---|---|
| Size | 44.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2a8b9916be751ff3b5edd15409f6047dbd6a53062751614f13d3f059440799c3
|
|
BLAKE2b-256 checksum How to use checksums |
b8a1c11070a08cc7aa205d89fc71f1ee9e5edc76bce75d05541c385ceb0b36ec
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / enedis_client-1.0.0-py3-none-any.whl
| Download URL | enedis_client-1.0.0-py3-none-any.whl |
|---|---|
| Size | 35.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
75540bff1765ca18e47b5701a3c646529bc8e6b97e7b15b2b50cb32432b892c2
|
|
BLAKE2b-256 checksum How to use checksums |
93aec9d198a1fd300039cad9654383093ccedbcee767b638171ed4d1fce6d62f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for enedis-client 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.