Support pour Hydro-Québec (Tarif D / Flex D): non basé sur une puissance, modele de consommation par tiers

Salut @pierre-gilles

Je voulais ouvrir un espace de discussion sur GitHub - GladysAssistant/energy-contracts: Gladys Assistant Energy Contracts as JSON · GitHub , mais je ne peux ouvrir que des issues.

Contexte

Je voudrais ajouter les tarifs résidentiels d’Hydro-Québec (fournisseur d’électricité public du Québec, Canada) à ce repo, mais la structure tarifaire ne rentre pas dans le modèle actuel.

Comment fonctionne le modèle actuel

En regardant EDF (contracts/edf/base) et les autres fournisseurs français du repo, le prix est toujours organisé autour d’une puissance souscrite (kVA) :

  • une clé par palier de puissance (3, 6, 9, 12, 15 kVA…)
  • pour chaque palier : un abonnement fixe (annualisé en mensuel) + un prix variable au kWh constant
  • variantes existantes : base, peak-off-peak (heures pleines/creuses), tempo (jour bleu/blanc/rouge)

Pourquoi le Tarif D d’Hydro-Québec ne rentre pas dans ce modèle

Le Tarif D (résidentiel de base) n’a aucune notion de puissance souscrite. Sa structure est :

  • un frais d’accès au réseau fixe par jour, indépendant de la puissance
  • un prix au kWh progressif selon la consommation réelle du jour (pas un choix de palier à l’avance) :
    • jusqu’à 40 kWh/jour : un premier prix
    • au-delà de 40 kWh/jour : un second prix, plus élevé

Grille en vigueur depuis le 1ᵉʳ avril 2026 (source officielle : grille-tarifaire.pdf) :

Composante Valeur
Frais d’accès au réseau 0,46154 $ CAD / jour
Énergie, ≤ 40 kWh/jour 0,07065 $ CAD / kWh
Énergie, > 40 kWh/jour 0,11142 $ CAD / kWh

Il existe aussi une option de tarification dynamique, Flex D, avec un prix hors-pointe réduit en hiver et un prix majoré pendant des événements de pointe critique annoncés 24h à l’avance (chiffres à revérifier précisément sur la grille officielle avant implémentation) :

Composante Valeur (à confirmer)
Frais d’accès au réseau identique au Tarif D
Hors pointe, période hivernale (1ᵉʳ déc.–31 mars) ≈ 0,04886 $ CAD / kWh
Pointe critique (événements ponctuels) ≈ 0,50 $ CAD / kWh
Reste de l’année Tarif D standard

Autres différences structurelles :

  • devise CAD, pas encore utilisée dans le repo (seul eur semble utilisé en pratique)
  • pas de notion de puissance souscrite à choisir par le client

Ce que je propose de discuter

  1. Comment encoder un tarif sans puissance souscrite ? Une clé neutre ("none" / "standard") à la place du palier de kVA, ou une évolution du schéma pour rendre cette dimension optionnelle ?
  2. Comment encoder un barème progressif au kWh (prix qui change selon le volume consommé dans la période, pas selon l’heure ni le jour) ? Rien dans le repo actuel ne semble couvrir ce cas — les variantes existantes (base, peak-off-peak, tempo) sont toutes indépendantes du volume.
  3. Un nouveau type de dossier serait-il pertinent, par ex. tiered-consumption, en complément de base / peak-off-peak / tempo ?
  4. Confirmation que la devise cad est bien supportée/acceptée par le pipeline process.js / le frontend Gladys qui consomme ce JSON.

Je suis preneur de retours avant d’investir du temps (enfin, des tokens :wink:) dans le CSV + convert.js. Une fois le format validé, je peux proposer une PR avec :

  • contracts/hydro-quebec/base (Tarif D)
  • contracts/hydro-quebec/flex (Flex D)

Hello @lmilcent,

Merci pour ce sujet très complet, il tombe à pic ! :raising_hands:

Je suis en train de refondre en profondeur le suivi de l’énergie dans Gladys (je l’ai présenté ici : API : permettre aux intégrations externes de déclarer leurs propres types de contrat énergie - #3 par pierre-gilles ).

Les contrats ne sont plus limités à Base / Heures creuses / Tempo : chaque contrat est décrit par des règles, et ça couvre exactement les points que tu soulèves.

Tarif D : ce sera possible directement

  • Pas de puissance souscrite : ce champ devient facultatif.
  • Paliers de consommation : « les 40 premiers kWh du jour à un prix, le reste à un autre » est géré nativement.
  • Frais d’accès quotidien : un montant fixe par jour.
  • Dollar canadien : chaque contrat a sa propre devise (CAD, USD, EUR…).

Concrètement, avec les prix de ton message, le Tarif D s’écrit comme ça :

{
  "tariff_version": 1,
  "components": [
    {
      "key": "energy",
      "kind": "consumption",
      "rules": [
        { "label": "40 premiers kWh du jour", "when": { "tier": { "cumulative": "day", "from_kwh": 0, "to_kwh": 40 } }, "price": 0.07065 }
      ],
      "fallback": { "label": "Au-delà de 40 kWh", "price": 0.11142 }
    },
    { "key": "acces", "kind": "fixed", "amount": 0.46154, "per": "day" }
  ]
}

Tu pourras le coller dans l’éditeur de contrat de Gladys, et il pourra aussi être ajouté au catalogue communautaire pour que tout le monde l’ait en un clic.

Flex D : le calcul est prévu, il manque la source des pointes critiques

Le calcul lui-même est couvert : période d’hiver du 1er décembre au 31 mars, prix réduit hors pointe, prix élevé pendant les événements de pointe critique. Mais comme les événements sont annoncés la veille, il faut que quelque chose les récupère et les transmette à Gladys.

Ce sera le rôle d’une intégration externe, qui publie les jours de pointe dans un « calendrier » que le contrat utilise. Tout est prévu dans Gladys pour ça, mais cette intégration reste à écrire.

Deux questions pour être sûr de coller à ta facture

  1. Pour le seuil de 40 kWh, Hydro-Québec le calcule-t-il jour par jour, ou comme « 40 kWh × nombre de jours » sur toute la période de facturation ? Ça change légèrement le résultat les jours où tu dépasses 40 kWh.
  2. Pour Flex D, peux-tu me confirmer les plages horaires des événements de pointe, et si les paliers de 40 kWh s’appliquent aussi pendant l’hiver ?

Ce n’est pas encore sorti, c’est en cours de relecture avant une prochaine version.

Cool de voir que tu retravailles le sujet ! :tada:

Seuil de 40 kWh (Tarif D)

Hydro-Québec le calcule de façon cumulative sur toute la période de facturation, pas jour par jour : le premier palier = 40 kWh × nombre de jours de la période, appliqué au total de consommation de la période.

Exemple concret tiré de ma facture : 368 kWh sur 63 jours, seuil = 40 × 63 = 2 520 kWh → tout est facturé au premier prix (368 × 0,07065 $ = 26,00 $), peu importe si un jour individuel a dépassé 40 kWh.

Dans ton exemple JSON, "cumulative": "day" ne correspond donc probablement pas à la méthode réelle, ce serait plutôt un cumul sur toute la période de facturation ("cumulative": "billing_period" ou équivalent), sans réinitialisation quotidienne.

Flex D basé sur la grille officielle 2026 (article 2.72)

Composante Prix
Frais d’accès au réseau, par jour 46,154 ¢
Hiver, hors pointe — jusqu’à 40 kWh/jour 4,886 ¢/kWh
Hiver, hors pointe — reste de l’énergie 9,103 ¢/kWh
Hiver, pendant un événement de pointe 46,463 ¢/kWh (prix unique)
Été (reste de l’année) — jusqu’à 40 kWh/jour 7,065 ¢/kWh
Été (reste de l’année) — reste de l’énergie 11,142 ¢/kWh

Le palier de 40 kWh s’applique bien pendant l’hiver Flex D, hors événement : ce n’est que pendant un événement de pointe qu’un prix unique remplace les paliers.

Événements de pointe : entre 6h-10h et 16h-20h, tous les jours de la semaine (week-ends inclus), maximum 120 heures par hiver, période hivernale du 1er décembre au 31 mars inclusivement. Reste de l’année : Tarif D standard.

Integration Hydro Quebec

Pour l’intégration externe qui publierait les jours de pointe dans un calendrier, mon integration actuelle basée sur le projet hydroqc pourrait le supporter (il faut que j’adapte le module Gladys). Mais ce projet nécessite les identifiants du compte.

Sinon j’ai trouvé que Hydro-Québec publie un portail de données ouvertes officiel (https://donnees.hydroquebec.com) avec un jeu de données evenements-pointe qui liste tous les événements de pointe (Crédit hivernal ET Flex D, filtrable par offre : CPC-D, TPC-DPC, etc.), via une API REST standard (OpenDataSoft), sans compte ni authentification. Le projet Beat-YT/hydropeak-ha (MIT) s’appuie déjà dessus pour Home Assistant, sans jamais toucher aux identifiants du client.

Ça permettrait une intégration externe beaucoup plus simple et plus sûre : un seul flux public partagé pour tous les utilisateurs, au lieu de devoir stocker les identifiants Hydro-Québec de chacun. Bon ca ne change pas au fait que les identifiants restent nécessaires pour récupérer la consommation.

Merci @lmilcent, c’est exactement ce qu’il me fallait ! :folded_hands:

Correction sur le seuil : mon premier JSON appliquait les 40 kWh jour par jour, ce qui est faux. Comme Gladys découpe par mois, j’applique le seuil « 40 kWh × jours du mois » sur le cumul mensuel (1 240 / 1 200 / 1 120 kWh). Sur un exemple, ça donne exactement le calcul d’Hydro-Québec, là où la version « par jour » surestimait de 14 %.

Seule limite : ta période de facturation dure environ 2 mois. Si un mois gourmand est suivi d’un mois léger dans la même période, Gladys comptera un peu trop de kWh au 2ᵉ palier. Février bissextile (2028) est aussi décalé de 40 kWh.

Tarif D

{
  "tariff_version": 1,
  "components": [
    { "key": "energy", "kind": "consumption",
      "rules": [
        { "label": "Palier 1", "when": { "months": [1,3,5,7,8,10,12], "tier": { "cumulative": "month", "from_kwh": 0, "to_kwh": 1240 } }, "price": 0.07065 },
        { "label": "Palier 1", "when": { "months": [4,6,9,11], "tier": { "cumulative": "month", "from_kwh": 0, "to_kwh": 1200 } }, "price": 0.07065 },
        { "label": "Palier 1", "when": { "months": [2], "tier": { "cumulative": "month", "from_kwh": 0, "to_kwh": 1120 } }, "price": 0.07065 }
      ],
      "fallback": { "label": "Palier 2", "price": 0.11142 } },
    { "key": "acces", "kind": "fixed", "amount": 0.46154, "per": "day" }
  ]
}

Flex D

{
  "tariff_version": 1,
  "calendars": ["hq-critical-peaks"],
  "components": [
    { "key": "energy", "kind": "consumption",
      "rules": [
        { "label": "Pointe", "when": { "months": [12,1,2,3], "calendar": { "hq-critical-peaks": "critical-peak" } }, "price": 0.46463 },
        { "label": "Hiver palier 1", "when": { "months": [12,1,3], "tier": { "cumulative": "month", "from_kwh": 0, "to_kwh": 1240 } }, "price": 0.04886 },
        { "label": "Hiver palier 1", "when": { "months": [2], "tier": { "cumulative": "month", "from_kwh": 0, "to_kwh": 1120 } }, "price": 0.04886 },
        { "label": "Hiver palier 2", "when": { "months": [12,1,2,3] }, "price": 0.09103 },
        { "label": "Été palier 1", "when": { "months": [5,7,8,10], "tier": { "cumulative": "month", "from_kwh": 0, "to_kwh": 1240 } }, "price": 0.07065 },
        { "label": "Été palier 1", "when": { "months": [4,6,9,11], "tier": { "cumulative": "month", "from_kwh": 0, "to_kwh": 1200 } }, "price": 0.07065 }
      ],
      "fallback": { "label": "Été palier 2", "price": 0.11142 } },
    { "key": "acces", "kind": "fixed", "amount": 0.46154, "per": "day" }
  ]
}

Pour les pointes, le jeu de données « evenements-pointe » des données ouvertes est parfait : une petite intégration externe peut le lire et publier les créneaux de pointe dans le calendrier hq-critical-peaks, sans aucun identifiant. Comme les créneaux viennent des données, la règle n’a pas besoin des plages 6h–10h / 16h–20h. hydropeak-ha est une bonne base pour la récupération. Si quelqu’un veut s’y lancer, je suis là pour aider !

Dernière question : les kWh consommés pendant une pointe comptent-ils dans le seuil des 40 kWh × jours ? Pour l’instant je les compte.

Ça c’est une bonne question ! J’en avais aucune idée mais Claude m’a bien aidé avec tous les documents que je lui ai donné :grinning_face_with_smiling_eyes:

Pour les kWh de pointe : la grille tarifaire officielle (article 2.72) décrit trois catégories distinctes et mutuellement exclusives :

  • « Jusqu’à 40 kWh d’énergie par jour en dehors des événements de pointe »
  • « Reste de l’énergie consommée en dehors des événements de pointe »
  • « Énergie consommée pendant les événements de pointe »

Le seuil des 40 kWh × jours est explicitement scopé au hors-pointe dans le texte. Rien n’indique que l’énergie de pointe alimente ce même cumul — ce sont deux compteurs séparés. Donc les kWh consommés pendant un événement de pointe ne devraient pas compter dans le seuil du palier hors-pointe.

Ça correspond aussi à la logique du programme : sinon, un client qui ne peut pas effacer sa consommation pendant un événement se ferait pénaliser deux fois (prix de pointe + perte de palier avantageux sur le reste du mois), ce qui va à l’encontre de l’objectif d’un tarif dynamique.

Pour l’implémentation ça voudrait dire : dans la règle « Hiver palier 1 / palier 2 », la fenêtre tier.cumulative: "month" ne devrait comptabiliser que les kWh hors calendar: critical-peak, pas le total mensuel brut.

Salut Louis,

Merci pour l’article 2.72, tu avais complètement raison ! J’ai fait évoluer le moteur de Gladys avec deux ajouts sur les paliers :

  • to_kwh_per_day : le seuil devient « 40 kWh × nombre de jours de la période ». Il est calculé sur le total, et février bissextile est géré.
  • counts_when : on choisit quels kWh alimentent le palier. Les kWh consommés pendant une pointe ne mangent plus ton palier hors pointe.

J’ai vérifié sur quelques cas, au centime près par rapport à la grille :

  • janvier avec des jours irréguliers (1 220 kWh) : 86,19 $ ;
  • février 2028 bissextile : 98,11 $ ;
  • Flex D en janvier avec 20 h de pointe : 116,90 $ (sans la correction, on était à 118,45 $).

Tarif D

{
  "tariff_version": 1,
  "components": [
    { "key": "energy", "kind": "consumption",
      "rules": [
        { "label": "Palier 1", "when": { "tier": { "cumulative": "billing_period", "from_kwh_per_day": 0, "to_kwh_per_day": 40 } }, "price": 0.07065 }
      ],
      "fallback": { "label": "Palier 2", "price": 0.11142 } },
    { "key": "acces", "kind": "fixed", "amount": 0.46154, "per": "day" }
  ]
}

Flex D

{
  "tariff_version": 1,
  "calendars": ["hq-critical-peaks"],
  "components": [
    { "key": "energy", "kind": "consumption",
      "rules": [
        { "label": "Pointe", "when": { "calendar": { "hq-critical-peaks": "critical-peak" } }, "price": 0.46463 },
        { "label": "Hiver palier 1", "when": { "season": { "from": "12-01", "to": "03-31" }, "tier": { "cumulative": "billing_period", "from_kwh_per_day": 0, "to_kwh_per_day": 40, "counts_when": { "not_calendar": { "hq-critical-peaks": "critical-peak" } } } }, "price": 0.04886 },
        { "label": "Hiver palier 2", "when": { "season": { "from": "12-01", "to": "03-31" } }, "price": 0.09103 },
        { "label": "Été palier 1", "when": { "tier": { "cumulative": "billing_period", "from_kwh_per_day": 0, "to_kwh_per_day": 40 } }, "price": 0.07065 }
      ],
      "fallback": { "label": "Été palier 2", "price": 0.11142 } },
    { "key": "acces", "kind": "fixed", "amount": 0.46154, "per": "day" }
  ]
}

Seule limite restante : Gladys découpe la facturation par mois, alors que tes périodes Hydro-Québec font environ 2 mois. L’écart ne joue que si un mois gourmand et un mois léger se retrouvent dans la même période.

Pour que les pointes soient réellement facturées, il reste l’intégration qui lit les événements sur les données ouvertes d’Hydro-Québec.

Excellent ! Tout me semble correct, tant pis pour la petite faille, c’est peu probable (sauf quitter son logement) d’avoir deux mois tres différents sur la consommation pendant l’hiver, vu l’isolation des bâtiments et le type de chauffage ici :rofl:

Quand ça sera sorti, je mettrais a jour mon module pour synchroniser le planning de pointe d’hydro Québec.

Salut @pierre-gilles

Merci pour la refonte des contrats, j’ai lu #3130 et la synchro du SDK. Comme prévu, je vais mettre à jour le module Hydro-Québec pour alimenter le calendrier hq-critical-peaks : les pointes Flex D (TPC-DPC) lues sur les données ouvertes, publiées en créneaux de 30 min, avec les modèles Tarif D et Flex D qu’on a validés ensemble. Tous les événements Flex D publiés depuis décembre 2024 sont à l’heure pile (6 h–9 h, 6 h–10 h, 16 h–20 h), donc l’alignement ne pose aucun souci.

Il me reste en revanche un blocage pour que le coût soit réellement calculé :

  1. Hydro-Québec ne fournit la consommation qu’avec environ un jour de retard (données horaires de la veille). Or le seul chemin prévu pour une intégration, l’index cumulatif, est traité en temps réel : tout l’écart d’index part dans la demi-heure courante, et un état plus ancien que le curseur est ignoré.
  2. La consommation quotidienne ne suffit pas pour Flex D : une journée est tarifée à son début (minuit), donc elle ne tombe jamais dans un créneau de pointe. Et une intégration ne peut pas relier elle-même une paire consommation/coût (energy_parent_id).

Est-ce que tu envisagerais :

  • de laisser une intégration publier une thirty-minutes-consumption datée (created_at dans le passé), dont le cœur dériverait la fonctionnalité de coût comme il le fait pour un index, puis la tarifierait à l’arrivée ?
  • un requestEnergyRecalculation({ from }) daté ? La relance actuelle ne couvre que 48 h, et seulement les contrats qui lisent un calendrier de l’intégration, donc pas le Tarif D seul.

De mon côté, je découperais chaque heure en deux demi-heures égales. Comme les pointes commencent à l’heure pile, rien ne serait mal attribué.

Salut tout le monde !

Ce sujet est désormais en cours de développement.

Une PR a été ouverte pour permettre aux intégrations externes de publier une consommation datée (fournisseurs à données tardives, type Hydro-Québec) :

N’hésitez pas à suivre la PR, à tester (optionnel, surtout pour les petites demandes) et à faire vos retours ici si besoin.

Salut tout le monde !

Ce sujet est désormais en cours de développement.

Une PR a été ouverte pour empêcher le compteur principal de se rattacher à lui-même (et casser le calcul des coûts) :

N’hésitez pas à suivre la PR, à tester (optionnel, surtout pour les petites demandes) et à faire vos retours ici si besoin.

Salut !

Grace à la sortie de Gladys 5.2, la consommation datée correspond exactement au besoin, et le fait que la publication déclenche elle-même le recalcul simplifie beaucoup le module.

La version 0.2.0 de l’intégration Hydro-Québec est disponible et s’appuie dessus (Gladys 5.2 minimum) :

  • Consommation par demi-heure : les relevés horaires d’Hydro-Québec (la veille) sont publiés avec publishEnergyConsumption, chaque heure coupée en deux. Au premier démarrage, l’intégration rattrape la consommation depuis le 1er du mois, pour que les paliers soient comptés en entier.
  • Deux modèles de contrat dans l’assistant : Hydro-Québec – Tarif D et Hydro-Québec – Flex D, avec les grilles du 1er avril 2026 qu’on avait validées ici (paliers « 40 kWh × jours », kWh de pointe exclus du palier hors pointe).
  • Calendrier hq-critical-peaks : les pointes Flex D sont lues sur les données ouvertes d’Hydro-Québec et publiées en créneaux de 30 minutes. Une pointe annulée avant son début redevient normale.
  • Les déclencheurs de scène déjà présents (pointe annoncée, préchauffage, début et fin de pointe) restent à la minute près et complètent le déclencheur natif « Changement de prix de l’électricité ».

Pour l’activer : mettez à jour l’intégration, cliquez sur « Mettre à jour » dans l’onglet Découverte, puis créez un contrat dans Suivi de l’énergie → Contrats avec l’appareil Hydro-Québec comme compteur. Au Crédit hivernal, choisissez le Tarif D : le crédit reste suivi par les fonctionnalités de l’appareil.

:warning: Changement à noter : la consommation quotidienne est remplacée par la consommation par demi-heure, et son historique est supprimé lors de la mise à jour.

Appel aux testeurs : rien de tout ça n’a encore tourné sur un vrai compte. Si vous êtes chez Hydro-Québec, surtout en Flex D ou au Crédit hivernal, vos retours m’intéressent beaucoup : les données horaires arrivent-elles bien, et le coût calculé par Gladys est-il cohérent avec votre facture ?

Merci encore !