blueprint: name: Hydro-Québec Crédits Hivernaux (Événements de calendrier) description: | # Gestion automatisée des Crédits Hivernaux (D+CPC). Ce blueprint déclenche des automatisations à heures fixes pour les périodes de pointe et d'ancrage, puis vérifie le calendrier Hydro-Québec pour déterminer si c'est une pointe critique ou régulière et exécute les actions appropriées. **Fonctionnement** : - Déclencheurs à heures fixes pour ancrage et pointes (01h, 04h, 06h, 10h, 12h, 14h, 16h, 20h) - Déclencheurs calendrier avec offset pour pré-chauffage (par défaut -01:45:00 avant pointes critiques) - Vérifie automatiquement si un événement critique existe dans le calendrier - Exécute les actions critiques (si événement calendrier) ou régulières (horaire quotidien) - Le pré-chauffage se déclenche automatiquement via les événements calendrier (pointes critiques uniquement) **Prérequis** : Vous devez avoir configuré un calendrier dans les options de votre intégration Hydro-Québec D+CPC (Crédits Hivernaux). ## Configuration ### Sélection du calendrier Sélectionnez le calendrier configuré dans l'intégration Hydro-Québec. Le calendrier contient uniquement les pointes **critiques** annoncées par Hydro-Québec. ### Pré-chauffage (pointes critiques seulement) Configurez le délai avant les pointes critiques pour commencer le pré-chauffage. Utilise les événements du calendrier avec un offset. - Par défaut : -01:45:00 (1h45 avant le début de la pointe critique) - Le pré-chauffage se déclenche automatiquement UNIQUEMENT pour les événements critiques dans le calendrier ### Horaire quotidien (pointes régulières) Les pointes régulières suivent un horaire fixe pendant la saison hivernale (1er décembre au 31 mars) : - **Ancrage matin** : 01h-04h (établit consommation de référence) - **Pointe matin** : 06h-10h - **Ancrage soir** : 12h-14h (établit consommation de référence) - **Pointe soir** : 16h-20h ### Pointes critiques Hydro-Québec annonce les pointes critiques vers midi la veille. Ces événements apparaissent dans votre calendrier et remplacent les actions régulières pour cette journée. ### Actions Définissez vos actions pour chaque période. Le blueprint choisit automatiquement entre actions critiques et régulières selon la présence d'un événement calendrier. **Important** : Pour éviter qu'une erreur bloque l'exécution, utilisez des actions en parallèle (`parallel:`). **Pré-chauffage** : Pour pré-chauffer avant les pointes critiques, ajoutez la logique dans l'action "début pointe critique" ou créez une automatisation séparée. ### Création manuelle d'événements Si l'intégration ne crée pas automatiquement les événements, vous pouvez les créer manuellement : 1. Créez un événement le jour de la pointe critique (6h-10h ou 16h-20h) 2. Titre: contient "pointe" (ex: "🔴 Pointe critique") 3. Description (optionnel): `Tarif: DCPC` et `Critique: Oui` Plus de détails sur les [crédits hivernaux](https://hydroqc.ca/fr/docs/tarification-dynamique/). domain: automation input: hydroqc_calendar: name: Calendrier Hydro-Québec description: Sélectionnez le calendrier configuré dans l'intégration Hydro-Québec pour les événements de pointe selector: entity: domain: calendar multiple: false preheat_offset_morning: name: Délai de pré-chauffage (matin) description: "Temps avant le début de la pointe du matin pour commencer le pré-chauffage (format -HH:MM:SS, ex: -02:00:00 pour 2 heures avant, -01:45:00 pour 1h45 avant)" default: "-01:45:00" selector: text: type: text preheat_offset_evening: name: Délai de pré-chauffage (soir) description: "Temps avant le début de la pointe du soir pour commencer le pré-chauffage (format -HH:MM:SS, ex: -02:00:00 pour 2 heures avant, -01:45:00 pour 1h45 avant)" default: "-01:45:00" selector: text: type: text # ===== ACTIONS ESSENTIELLES ===== # Actions pour les pointes CRITIQUES (prioritaires) critical_preheat_morning_action: name: "[Critique] Action pré-chauffage (matin)" description: 'Actions pour pointes CRITIQUES - pré-chauffage avant pointe matin. Ex: Maximisez chauffage pour atteindre température élevée. Ne se déclenche QUE si un événement critique existe dans le calendrier pour aujourd''hui.' default: - parallel: - action: persistent_notification.create data: title: "🔥 Pré-chauffage Crédits hivernaux (matin)" message: "Début du pré-chauffage avant pointe critique du matin. Augmentez le chauffage maintenant." selector: action: {} critical_preheat_evening_action: name: "[Critique] Action pré-chauffage (soir)" description: 'Actions pour pointes CRITIQUES - pré-chauffage avant pointe soir. Ex: Maximisez chauffage pour atteindre température élevée. Ne se déclenche QUE si un événement critique existe dans le calendrier pour aujourd''hui.' default: - parallel: - action: persistent_notification.create data: title: "🔥 Pré-chauffage Crédits hivernaux (soir)" message: "Début du pré-chauffage avant pointe critique du soir. Augmentez le chauffage maintenant." selector: action: {} critical_peak_start_action: name: "[Critique] Action début pointe" description: 'Actions pour pointes CRITIQUES - début pointe (6h/16h). Ex: Réduction agressive - fermez chauffe-eau, minimisez CVAC. Le pré-chauffage est géré séparément via les actions de pré-chauffage configurables.' default: - parallel: - action: persistent_notification.create data: title: "🔴 Pointe critique Crédits hivernaux" message: "Début de la pointe critique. Réduisez votre consommation maintenant." selector: action: {} critical_peak_end_action: name: "[Critique] Action fin pointe" description: | Actions pour pointes CRITIQUES - fin pointe (10h/20h). Ex: Rétablissez tous appareils à opération normale. **Délai aléatoire par défaut (30 sec - 5 min)** : Évite une surcharge du réseau électrique causée par le redémarrage simultané de milliers d'appareils à la fin de la pointe. Si vous avez plusieurs actions de reprise, ajoutez un délai aléatoire similaire entre chacune pour étaler la consommation. default: - delay: seconds: "{{ range(30, 300)|random|int }}" alias: Délai aléatoire 30 sec - 5 minutes - parallel: - action: persistent_notification.create data: title: "✅ Fin pointe critique Crédits hivernaux" message: "Fin de la pointe critique. Vous pouvez rétablir votre consommation normale." selector: action: {} # ===== ACTIONS OPTIONNELLES ===== # Actions pour les pointes RÉGULIÈRES (non-critiques) regular_peak_actions: name: "⚪ Actions pointes régulières" description: "Actions exécutées lors des pointes quotidiennes RÉGULIÈRES (6h-10h et 16h-20h) quand AUCUN événement critique n'est présent dans le calendrier. Ces actions s'exécutent automatiquement selon l'horaire fixe hivernal." collapsed: true input: regular_peak_start_action: name: "[Régulière] Début pointe" description: 'Pointes RÉGULIÈRES - début pointe (6h/16h). Notification désactivée par défaut - retirez le mode `enabled: false` pour activer.' default: - enabled: false parallel: - action: persistent_notification.create data: title: "⚪ Pointe régulière Crédits hivernaux" message: "Début de la pointe régulière. Réduction optionnelle de consommation." selector: action: {} regular_peak_end_action: name: "[Régulière] Fin pointe" description: 'Pointes RÉGULIÈRES - fin pointe (10h/20h). Notification désactivée par défaut - retirez le mode `enabled: false` pour activer.' default: - enabled: false parallel: - action: persistent_notification.create data: title: "✅ Fin pointe régulière Crédits hivernaux" message: "Fin de la pointe régulière." selector: action: {} # ===== ACTIONS OPTIONNELLES (ANCRAGE) ===== # Période d'ancrage - permet d'établir une consommation de référence anchor_actions: name: "⚙️ Actions d'ancrage (optionnel)" description: "Les actions d'ancrage permettent d'établir une consommation de référence avant les pointes. Ces actions sont optionnelles." collapsed: true input: critical_anchor_start_morning_action: name: "[Critique] Début ancrage matin" description: 'Pointes CRITIQUES - 5h avant pointe matin (1h). Notification désactivée par défaut - retirez le mode `enabled: false` pour activer.' default: - enabled: false parallel: - action: persistent_notification.create data: title: "🔴 Ancrage critique matin Crédits hivernaux" message: "Début de l'ancrage critique du matin. Maintenez votre consommation normale pour établir une référence." selector: action: {} critical_anchor_start_evening_action: name: "[Critique] Début ancrage soir" description: 'Pointes CRITIQUES - 4h avant pointe soir (12h). Notification désactivée par défaut - retirez le mode `enabled: false` pour activer.' default: - enabled: false parallel: - action: persistent_notification.create data: title: "🔴 Ancrage critique soir Crédits hivernaux" message: "Début de l'ancrage critique du soir. Maintenez votre consommation normale pour établir une référence." selector: action: {} critical_anchor_end_morning_action: name: "[Critique] Fin ancrage matin" description: | Pointes CRITIQUES - 2h avant pointe matin (4h). Fin ancrage. **⚠️ Attention** : Si votre délai de pré-chauffage est <= -02:00:00, il y aura chevauchement avec cette action. La fin d'ancrage se déclenche à 4h pour une pointe à 6h. Notification désactivée par défaut - retirez le mode `enabled: false` pour activer. default: - enabled: false parallel: - action: persistent_notification.create data: title: "✅ Fin ancrage critique matin Crédits hivernaux" message: "Fin de l'ancrage critique du matin. Préparez-vous pour le pré-chauffage." selector: action: {} critical_anchor_end_evening_action: name: "[Critique] Fin ancrage soir" description: | Pointes CRITIQUES - 2h avant pointe soir (14h). Fin ancrage. **⚠️ Attention** : Si votre délai de pré-chauffage est <= -02:00:00, il y aura chevauchement avec cette action. La fin d'ancrage se déclenche à 14h pour une pointe à 16h. Notification désactivée par défaut - retirez le mode `enabled: false` pour activer. default: - enabled: false parallel: - action: persistent_notification.create data: title: "✅ Fin ancrage critique soir Crédits hivernaux" message: "Fin de l'ancrage critique du soir. Préparez-vous pour le pré-chauffage." selector: action: {} regular_anchor_start_morning_action: name: "[Régulière] Début ancrage matin" description: 'Pointes RÉGULIÈRES - 5h avant pointe matin (1h). Notification désactivée par défaut - retirez le mode `enabled: false` pour activer.' default: - enabled: false parallel: - action: persistent_notification.create data: title: "⚙️ Ancrage matin Crédits hivernaux" message: "Début de l'ancrage du matin. Maintenez votre consommation normale." selector: action: {} regular_anchor_start_evening_action: name: "[Régulière] Début ancrage soir" description: 'Pointes RÉGULIÈRES - 4h avant pointe soir (12h). Notification désactivée par défaut - retirez le mode `enabled: false` pour activer.' default: - enabled: false parallel: - action: persistent_notification.create data: title: "⚙️ Ancrage soir Crédits hivernaux" message: "Début de l'ancrage du soir. Maintenez votre consommation normale." selector: action: {} regular_anchor_end_morning_action: name: "[Régulière] Fin ancrage matin" description: 'Pointes RÉGULIÈRES - 2h avant pointe matin (4h). Notification désactivée par défaut - retirez le mode `enabled: false` pour activer.' default: - enabled: false parallel: - action: persistent_notification.create data: title: "✅ Fin ancrage matin Crédits hivernaux" message: "Fin de l'ancrage du matin." selector: action: {} regular_anchor_end_evening_action: name: "[Régulière] Fin ancrage soir" description: 'Pointes RÉGULIÈRES - 2h avant pointe soir (14h). Notification désactivée par défaut - retirez le mode `enabled: false` pour activer.' default: - enabled: false parallel: - action: persistent_notification.create data: title: "✅ Fin ancrage soir Crédits hivernaux" message: "Fin de l'ancrage du soir." selector: action: {} source_url: https://github.com/hydroqc/hydroqc-ha/blob/main/blueprints/winter-credits-calendar.yaml mode: single max_exceeded: silent trigger: # === CALENDAR TRIGGERS (Critical peaks only - with offsets) === # Morning preheat (configurable offset before morning peak) - platform: calendar entity_id: !input hydroqc_calendar event: start offset: !input preheat_offset_morning id: preheat_morning # Evening preheat (configurable offset before evening peak) - platform: calendar entity_id: !input hydroqc_calendar event: start offset: !input preheat_offset_evening id: preheat_evening # === TIME TRIGGERS (Fixed daily schedule) === # Morning anchor start (1h) - platform: time at: "01:00:00" id: anchor_start_morning # Morning anchor end (4h) - platform: time at: "04:00:00" id: anchor_end_morning # Morning peak start (6h) - platform: time at: "06:00:00" id: peak_start_morning # Morning peak end (10h) - platform: time at: "10:00:00" id: peak_end_morning # Evening anchor start (12h) - platform: time at: "12:00:00" id: anchor_start_evening # Evening anchor end (14h) - platform: time at: "14:00:00" id: anchor_end_evening # Evening peak start (16h) - platform: time at: "16:00:00" id: peak_start_evening # Evening peak end (20h) - platform: time at: "20:00:00" id: peak_end_evening # Season condition: only run during winter (Dec 1 - Mar 31) # Calendar events: filter for DCPC peak events only (for multi-tariff calendars) condition: - condition: template value_template: "{{ now().month == 12 or now().month <= 3 }}" - condition: or conditions: # Allow time-based triggers (non-calendar) - condition: template value_template: "{{ trigger.platform != 'calendar' }}" # For calendar triggers: validate DCPC tariff and peak event - condition: and conditions: - condition: template value_template: "{{ 'pointe' in trigger.calendar_event.summary | lower }}" - condition: template value_template: "{{ 'Tarif: DCPC' in trigger.calendar_event.description }}" variables: calendar_entity: !input hydroqc_calendar action: # Fetch today's calendar events to determine if peaks are critical or regular - action: calendar.get_events target: entity_id: !input hydroqc_calendar data: start_date_time: "{{ now().replace(hour=0, minute=0, second=0, microsecond=0).isoformat() }}" end_date_time: "{{ now().replace(hour=23, minute=59, second=59, microsecond=0).isoformat() }}" response_variable: calendar_events - variables: # Check if there's a critical morning peak (starting at 6h) today morning_peak_critical: > {{ calendar_events[calendar_entity].events | selectattr('summary', 'search', '[Pp]ointe') | selectattr('description', 'search', 'Tarif: DCPC') | selectattr('start', 'search', now().strftime('%Y-%m-%dT06:')) | list | length > 0 }} # Check if there's a critical evening peak (starting at 16h) today evening_peak_critical: > {{ calendar_events[calendar_entity].events | selectattr('summary', 'search', '[Pp]ointe') | selectattr('description', 'search', 'Tarif: DCPC') | selectattr('start', 'search', now().strftime('%Y-%m-%dT16:')) | list | length > 0 }} - choose: # ============================================ # MORNING ANCHOR START (01:00) # ============================================ - conditions: - condition: trigger id: anchor_start_morning - condition: template value_template: "{{ morning_peak_critical }}" sequence: !input critical_anchor_start_morning_action - conditions: - condition: trigger id: anchor_start_morning - condition: template value_template: "{{ not morning_peak_critical }}" sequence: !input regular_anchor_start_morning_action # ============================================ # MORNING ANCHOR END (04:00) # ============================================ - conditions: - condition: trigger id: anchor_end_morning - condition: template value_template: "{{ morning_peak_critical }}" sequence: !input critical_anchor_end_morning_action - conditions: - condition: trigger id: anchor_end_morning - condition: template value_template: "{{ not morning_peak_critical }}" sequence: !input regular_anchor_end_morning_action # ============================================ # MORNING PREHEAT (calendar trigger with offset, critical only) # ============================================ - conditions: - condition: trigger id: preheat_morning - condition: template value_template: "{{ as_timestamp(trigger.calendar_event.start) | timestamp_custom('%H') | int < 12 }}" sequence: !input critical_preheat_morning_action # ============================================ # MORNING PEAK START (06:00) # ============================================ - conditions: - condition: trigger id: peak_start_morning - condition: template value_template: "{{ morning_peak_critical }}" sequence: !input critical_peak_start_action - conditions: - condition: trigger id: peak_start_morning - condition: template value_template: "{{ not morning_peak_critical }}" sequence: !input regular_peak_start_action # ============================================ # MORNING PEAK END (10:00) # ============================================ - conditions: - condition: trigger id: peak_end_morning - condition: template value_template: "{{ morning_peak_critical }}" sequence: !input critical_peak_end_action - conditions: - condition: trigger id: peak_end_morning - condition: template value_template: "{{ not morning_peak_critical }}" sequence: !input regular_peak_end_action # ============================================ # EVENING ANCHOR START (12:00) # ============================================ - conditions: - condition: trigger id: anchor_start_evening - condition: template value_template: "{{ evening_peak_critical }}" sequence: !input critical_anchor_start_evening_action - conditions: - condition: trigger id: anchor_start_evening - condition: template value_template: "{{ not evening_peak_critical }}" sequence: !input regular_anchor_start_evening_action # ============================================ # EVENING ANCHOR END (14:00) # ============================================ - conditions: - condition: trigger id: anchor_end_evening - condition: template value_template: "{{ evening_peak_critical }}" sequence: !input critical_anchor_end_evening_action - conditions: - condition: trigger id: anchor_end_evening - condition: template value_template: "{{ not evening_peak_critical }}" sequence: !input regular_anchor_end_evening_action # ============================================ # EVENING PREHEAT (calendar trigger with offset, critical only) # ============================================ - conditions: - condition: trigger id: preheat_evening - condition: template value_template: "{{ as_timestamp(trigger.calendar_event.start) | timestamp_custom('%H') | int >= 12 }}" sequence: !input critical_preheat_evening_action # ============================================ # EVENING PEAK START (16:00) # ============================================ - conditions: - condition: trigger id: peak_start_evening - condition: template value_template: "{{ evening_peak_critical }}" sequence: !input critical_peak_start_action - conditions: - condition: trigger id: peak_start_evening - condition: template value_template: "{{ not evening_peak_critical }}" sequence: !input regular_peak_start_action # ============================================ # EVENING PEAK END (20:00) # ============================================ - conditions: - condition: trigger id: peak_end_evening - condition: template value_template: "{{ evening_peak_critical }}" sequence: !input critical_peak_end_action - conditions: - condition: trigger id: peak_end_evening - condition: template value_template: "{{ not evening_peak_critical }}" sequence: !input regular_peak_end_action