From db478460be8b707cdd7a2eac8f1efc3c2a062c5b Mon Sep 17 00:00:00 2001 From: root Date: Tue, 16 Jun 2026 18:25:28 +0200 Subject: [PATCH] audit: nettoyage et corrections juin 2026 --- .gitignore | 16 + automations.yaml | 1272 ++++++++++++++++++++++++++++++++++++++++++++++ notify.yaml | 10 + scenes.yaml | 65 +++ scripts.yaml | 124 +++++ secrets.yaml | 12 + sensors.yaml | 14 + template.yaml | 349 +++++++++++++ 8 files changed, 1862 insertions(+) create mode 100644 .gitignore create mode 100644 automations.yaml create mode 100644 notify.yaml create mode 100644 scenes.yaml create mode 100644 scripts.yaml create mode 100644 secrets.yaml create mode 100644 sensors.yaml create mode 100644 template.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ce9add1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +.HA_VERSION +.cache/ +.ha_run.lock +.shopping_list.json +.storage/ +*.log +*.log.* +*.db +*.db-shm +*.db-wal +*.db.corrupt* +home-assistant_v2* +alexa_media* +tts/ +image/ +zigbee.db diff --git a/automations.yaml b/automations.yaml new file mode 100644 index 0000000..3a36415 --- /dev/null +++ b/automations.yaml @@ -0,0 +1,1272 @@ +- id: '1749315801894' + alias: "\U0001F4C5 Notif - Calendrier" + description: Envoie une notification Gotify à chaque déclenchement d'un événement + calendrier (bestioles, maison, poubelles, jardin). + triggers: + - entity_id: + - calendar.bestioles + - calendar.mashome + - calendar.garbage + - calendar.garden + to: 'on' + trigger: state + conditions: [] + actions: + - action: script.notif_gotify + data: + title: "\U0001F4C5 {{ state_attr(trigger.entity_id, 'friendly_name') }}" + message: '{{ state_attr(trigger.entity_id, ''message'') }}' + priority: 5 + mode: single +- id: '1751221338548' + alias: "\U0001F680 Système - Home Assistant (MAJ + démarrage + arrêt)" + description: Notifie les mises à jour disponibles (Core, OS, Supervisor) et les + événements de cycle de vie de HA (démarrage / arrêt). + triggers: + - entity_id: + - update.home_assistant_core_update + - update.home_assistant_operating_system_update + - update.home_assistant_supervisor_update + to: 'on' + id: update + trigger: state + - event: start + id: start + trigger: homeassistant + - event: shutdown + id: stop + trigger: homeassistant + actions: + - choose: + - conditions: + - condition: trigger + id: update + sequence: + - data: + title: "\U0001F680 MAJ {{ trigger.to_state.name }}" + message: Version {{ trigger.to_state.attributes.latest_version }} disponible + priority: 5 + action: script.notif_gotify + - conditions: + - condition: trigger + id: start + sequence: + - data: + title: ✅ Gérald + message: Démarrage réussi + priority: 4 + action: script.notif_gotify + - conditions: + - condition: trigger + id: stop + sequence: + - data: + title: ⏹️ Gérald + message: Arrêt en cours + priority: 4 + action: script.notif_gotify + mode: single +- id: '1752652068313' + alias: "\U0001F3D6️ Simulation Présence" + description: 'Simule une présence réaliste pendant les vacances : ouverture progressive + des volets le matin, fermeture au coucher du soleil, allumage/extinction aléatoire + des lumières en soirée.' + triggers: + - minutes: /30 + trigger: time_pattern + conditions: + - condition: state + entity_id: input_boolean.vacance + state: 'on' + actions: + - choose: + - conditions: + - condition: sun + after: sunrise + after_offset: +00:30:00 + - condition: time + before: '10:00:00' + sequence: + - action: cover.set_cover_position + target: + entity_id: + - cover.bibliotheque + - cover.cuisine + - cover.salle_a_manger + - cover.salon + data: + position: '{{ range(80, 100) | random }}' + - choose: + - conditions: + - condition: sun + after: sunset + after_offset: -00:30:00 + sequence: + - action: cover.close_cover + target: + entity_id: + - cover.bibliotheque + - cover.cuisine + - cover.salle_a_manger + - cover.salon + data: {} + - choose: + - conditions: + - condition: time + after: '18:00:00' + before: '23:30:00' + - condition: sun + after: sunset + sequence: + - action: light.turn_on + target: + entity_id: '{{ [''light.interrupteur_veranda_l1'', ''light.bar'', ''light.plafonnier'', + ''light.halogene''] | random }}' + data: + brightness_pct: '{{ range(40, 80) | random }}' + transition: 2 + - delay: + minutes: '{{ range(15, 45) | random }}' + - action: light.turn_off + target: + entity_id: '{{ expand(''light.lumieres'') | selectattr(''state'', ''eq'', + ''on'') | map(attribute=''entity_id'') | list | random }}' + data: + transition: 2 + mode: queued + max: 3 +- id: '1755537503205' + alias: "\U0001FA9F Volets - Gestion complète" + description: Ferme les volets en mode canicule (temp >24°C, hors 20h-6h, si volets + ouverts). Ouvre les volets au lever du soleil si le mode maison est 'absent'. + triggers: + - entity_id: input_select.maison_mode + trigger: state + id: mode_change + - entity_id: sensor.mont_cauvaire_temperature + above: 24 + trigger: numeric_state + id: temp_canicule + - trigger: sun + event: sunrise + id: sunrise + conditions: [] + actions: + - choose: + - conditions: + - condition: trigger + id: temp_canicule + - condition: not + conditions: + - condition: time + after: '20:00:00' + before: 06:00:00 + - condition: numeric_state + entity_id: sensor.mont_cauvaire_temperature + above: 24 + - condition: state + entity_id: cover.volets + state: open + sequence: + - action: scene.turn_on + target: + entity_id: scene.volets_chaleur + - conditions: + - condition: trigger + id: sunrise + - condition: state + entity_id: input_select.maison_mode + state: absent + sequence: + - action: cover.open_cover + target: + entity_id: cover.volets + mode: restart +- id: '1755633804919' + alias: "\U0001F9F9 Doris - Gestion complète" + description: Rappel de vidage du réservoir si ≥5 cycles (11h et 19h). Incrémente + le compteur et notifie à chaque fin de nettoyage. + triggers: + - trigger: time + at: '11:00:00' + id: notification_matin + - trigger: time + at: '19:00:00' + id: notification_soir + - trigger: state + entity_id: + - vacuum.doris + from: + - returning + to: + - docked + id: nettoyage_termine + conditions: [] + actions: + - choose: + - conditions: + - condition: trigger + id: + - notification_matin + - notification_soir + - condition: numeric_state + entity_id: counter.cycle_doris + above: 5 + sequence: + - action: script.notif_gotify + data: + title: "\U0001F9F9 Doris" + message: 'Réservoir à vider : {{ states(''counter.cycle_doris'') }} cycles + effectués' + priority: 6 + - conditions: + - condition: trigger + id: nettoyage_termine + sequence: + - action: counter.increment + target: + entity_id: counter.cycle_doris + - action: script.notif_gotify + data: + title: "\U0001F9F9 Doris" + message: Nettoyage terminé ({{ states('counter.cycle_doris') }} cycles) + priority: 3 + mode: queued + max: 3 +- id: '1755637169948' + alias: ⏱️ Timer Unifié - TV Chambre et Home Cinéma + description: 'Gestion centralisée des timers d''extinction : TV chambre (durée configurable + via input_number) et home cinéma (fixe 1h30). Notifie au démarrage, à l''extinction + et en cas d''annulation.' + triggers: + - entity_id: input_boolean.etat_minuteur_chambre + to: 'on' + trigger: state + id: timer_chambre + - entity_id: input_boolean.minuteur_salon + to: 'on' + trigger: state + id: timer_salon + - trigger: state + entity_id: + - input_boolean.etat_minuteur_chambre + to: + - 'off' + id: cancel_chambre + conditions: [] + actions: + - choose: + - conditions: + - condition: trigger + id: + - timer_chambre + sequence: + - variables: + delay_minutes: '{{ states(''input_number.timer_ch'') | int(30) }}' + - action: script.notif_gotify + data: + title: ⏱️ Timer TV Chambre + message: Extinction dans {{ delay_minutes }} minutes + priority: 3 + - delay: + minutes: '{{ delay_minutes }}' + - condition: state + entity_id: input_boolean.etat_minuteur_chambre + state: 'on' + - action: switch.turn_off + target: + entity_id: + - switch.tele_chambre + - action: input_boolean.turn_off + target: + entity_id: input_boolean.etat_minuteur_chambre + - action: script.notif_gotify + data: + title: ✅ Timer terminé + message: TV chambre éteinte + priority: 2 + - conditions: + - condition: trigger + id: + - timer_salon + sequence: + - action: script.notif_gotify + data: + title: ⏱️ Timer Home Cinéma + message: Extinction dans 1h30 + priority: 3 + - delay: + hours: 1 + minutes: 30 + - condition: state + entity_id: input_boolean.minuteur_salon + state: 'on' + - action: switch.turn_off + target: + entity_id: switch.home_cinema_prise + - action: input_boolean.turn_off + target: + entity_id: input_boolean.minuteur_salon + - action: script.notif_gotify + data: + title: ✅ Timer terminé + message: Home cinéma éteint + priority: 2 + - conditions: + - condition: trigger + id: + - cancel_chambre + sequence: + - action: script.notif_gotify + data: + title: ❌ Timer annulé + message: Timer chambre annulé + priority: 2 + mode: parallel + max: 2 +- id: '1758057240516' + alias: "\U0001F4FA Home Cinéma - Gestion complète" + description: Synchronise la Bbox, la prise home cinéma et le plafonnier. Gère l'allumage/extinction + de nuit (lumière ambiante) et adapte le comportement selon l'origine du déclenchement + (prise ou Bbox). + triggers: + - entity_id: switch.home_cinema_prise + trigger: state + to: 'on' + for: + seconds: 3 + id: TVON + - entity_id: switch.home_cinema_prise + trigger: state + to: 'off' + id: TVOFF + - type: turned_on + device_id: 3b837fd4e120ab9b973f31ce99017ef5 + entity_id: 34b78481039c1e06821015a0e6bed72d + domain: remote + trigger: device + for: + seconds: 3 + id: bbox_on + - trigger: sun + event: sunset + id: Coucher_soleil + conditions: [] + actions: + - choose: + - conditions: + - condition: trigger + id: TVON + - condition: sun + after: sunset + before: sunrise + sequence: + - action: remote.turn_on + target: + entity_id: remote.bboxtv + - action: light.turn_on + data: + color_temp_kelvin: 2000 + brightness_pct: 50 + target: + entity_id: light.plafonnier + - conditions: + - condition: trigger + id: TVON + - condition: sun + before: sunset + after: sunrise + sequence: + - action: remote.turn_on + target: + entity_id: remote.bboxtv + - conditions: + - condition: trigger + id: bbox_on + - condition: sun + after: sunset + before: sunrise + sequence: + - action: switch.turn_on + target: + entity_id: switch.home_cinema_prise + - action: light.turn_on + data: + color_temp_kelvin: 2000 + brightness_pct: 50 + target: + entity_id: light.plafonnier + - conditions: + - condition: trigger + id: bbox_on + - condition: sun + before: sunset + after: sunrise + sequence: + - action: switch.turn_on + target: + entity_id: switch.home_cinema_prise + - conditions: + - condition: trigger + id: Coucher_soleil + - condition: state + entity_id: switch.home_cinema_prise + state: 'on' + sequence: + - action: light.turn_on + data: + color_temp_kelvin: 2000 + brightness_pct: 50 + target: + entity_id: light.plafonnier + - conditions: + - condition: trigger + id: TVOFF + sequence: + - action: remote.turn_off + target: + entity_id: remote.bboxtv + device_id: + - 3b837fd4e120ab9b973f31ce99017ef5 + - e40a5194622be081af6b905eaa6675c6 + area_id: salon + data: {} + - action: light.turn_off + target: + entity_id: light.plafonnier + mode: restart +- id: '1763205350889' + alias: "\U0001FA9F Radiateurs + Fenêtres" + description: Coupe le radiateur chambre si la fenêtre reste ouverte >10s, le rallume + 2min après fermeture. Même logique pour le radiateur bureau via le capteur de + verrou. + triggers: + - entity_id: + - binary_sensor.fenetre_chambre + - binary_sensor.verrou_fenetre_bureau + trigger: state + for: + seconds: 10 + conditions: [] + actions: + - choose: + - conditions: + - condition: template + value_template: '{{ trigger.entity_id == ''binary_sensor.fenetre_chambre'' + }}' + - condition: state + entity_id: binary_sensor.fenetre_chambre + state: 'on' + - condition: template + value_template: '{{ states(''climate.radiateur_chambre'') != ''off'' }}' + sequence: + - action: climate.set_hvac_mode + target: + device_id: f8576af3693e3b54af895631c64538fb + data: + hvac_mode: 'off' + - action: script.notif_gotify + data: + title: "\U0001FA9F Fenêtre chambre" + message: Radiateur coupé (fenêtre ouverte) + priority: 4 + enabled: false + - conditions: + - condition: template + value_template: '{{ trigger.entity_id == ''binary_sensor.fenetre_chambre'' + }}' + - condition: state + entity_id: binary_sensor.fenetre_chambre + state: 'off' + for: + seconds: 5 + - condition: template + value_template: '{{ states(''climate.radiateur_chambre'') == ''off'' }}' + sequence: + - delay: + minutes: 2 + - condition: state + entity_id: binary_sensor.fenetre_chambre + state: 'off' + - condition: template + value_template: '{{ states(''climate.radiateur_chambre'') == ''off'' }}' + - action: climate.set_hvac_mode + target: + device_id: f8576af3693e3b54af895631c64538fb + data: + hvac_mode: heat + - action: script.notif_gotify + data: + title: "\U0001FA9F Fenêtre chambre" + message: Radiateur rallumé (fenêtre fermée) + priority: 3 + enabled: false + - choose: + - conditions: + - condition: template + value_template: '{{ trigger.entity_id == ''binary_sensor.verrou_fenetre_bureau'' + }}' + - condition: state + entity_id: binary_sensor.verrou_fenetre_bureau + state: 'on' + - condition: state + entity_id: switch.radiateur_bureau + state: 'on' + sequence: + - action: switch.turn_off + target: + entity_id: switch.radiateur_bureau + - action: script.notif_gotify + data: + title: "\U0001FA9F Fenêtre bureau" + message: Radiateur coupé (fenêtre ouverte) + priority: 4 + enabled: false + - conditions: + - condition: template + value_template: '{{ trigger.entity_id == ''binary_sensor.verrou_fenetre_bureau'' + }}' + - condition: state + entity_id: binary_sensor.verrou_fenetre_bureau + state: 'off' + for: + seconds: 5 + - condition: state + entity_id: switch.radiateur_bureau + state: 'off' + sequence: + - delay: + minutes: 2 + - condition: state + entity_id: binary_sensor.verrou_fenetre_bureau + state: 'off' + - condition: state + entity_id: switch.radiateur_bureau + state: 'off' + - action: switch.turn_on + target: + entity_id: switch.radiateur_bureau + - action: script.notif_gotify + data: + title: "\U0001FA9F Fenêtre bureau" + message: Radiateur rallumé (fenêtre fermée) + priority: 3 + enabled: false + mode: queued + max: 5 +- id: '1766170300000' + alias: "\U0001F527 Maintenance et Surveillance" + description: Surveille les appareils hors ligne (10min), les erreurs Doris (5min), + les batteries critiques (<10%, heure ouvrable). Rapport batteries faibles (<20%) + tous les dimanches à 10h. + triggers: + - entity_id: + - vacuum.doris + - switch.radiateur_bureau + - switch.home_cinema_prise + - cover.volets + - climate.radiateur_chambre + to: unavailable + trigger: state + for: + minutes: 10 + id: appareil_offline + - entity_id: vacuum.doris + to: error + trigger: state + for: + minutes: 5 + id: doris_erreur + - trigger: numeric_state + entity_id: + - sensor.doris_battery_level + - sensor.porte_bibliotheque + - sensor.porte_veranda + - sensor.fenetre_chambre + - sensor.verrou_fenetre_bureau + below: 10 + id: batterie_critique + for: + hours: 1 + - trigger: state + entity_id: sensor.litiere_etat_batterie + to: low + id: batterie_litiere + for: + hours: 1 + - trigger: time + at: '10:00:00' + id: rappel_hebdo + conditions: [] + actions: + - choose: + - conditions: + - condition: trigger + id: appareil_offline + sequence: + - action: script.notif_gotify + data: + title: "\U0001F50C Appareil hors ligne" + message: '{{ trigger.to_state.attributes.friendly_name }} indisponible' + priority: 8 + - conditions: + - condition: trigger + id: doris_erreur + sequence: + - action: script.notif_gotify + data: + title: "\U0001F9F9 Doris - Erreur" + message: Doris en erreur depuis 5min + priority: 8 + - conditions: + - condition: trigger + id: batterie_critique + - condition: template + value_template: '{{ now().hour >= 8 and now().hour < 22 }}' + sequence: + - action: script.notif_gotify + data: + title: "\U0001F50B Batterie critique" + message: '{{ trigger.to_state.attributes.friendly_name }} à {{ trigger.to_state.state + }}%' + priority: 8 + - conditions: + - condition: trigger + id: batterie_litiere + sequence: + - action: script.notif_gotify + data: + title: "\U0001F50B Batterie litière" + message: Batterie du capteur PIR litière faible + priority: 8 + - conditions: + - condition: trigger + id: rappel_hebdo + - condition: time + weekday: + - sun + sequence: + - variables: + batteries_faibles: "{% set ns = namespace(liste=[]) %} {% for entity in + [\n 'sensor.doris_battery_level',\n 'sensor.porte_veranda',\n 'sensor.porte_bibliotheque',\n + \ 'sensor.fenetre_chambre',\n 'sensor.verrou_fenetre_bureau'\n] %}\n + \ {% set niveau = states(entity) | int(100) %}\n {% if niveau < 20 %}\n + \ {% set nom = state_attr(entity, 'friendly_name') %}\n {% set ns.liste + = ns.liste + [nom ~ ' (' ~ niveau ~ '%)'] %}\n {% endif %}\n{% endfor + %} {{ ns.liste | join(', ') }}" + - condition: template + value_template: '{{ batteries_faibles != "" }}' + - action: script.notif_gotify + data: + title: "\U0001F50B Rappel batteries" + message: 'À surveiller : {{ batteries_faibles }}' + priority: 5 + mode: queued + max: 5 +- id: '1766170300001' + alias: "\U0001F326️ Météo - Gestion complète" + description: Alerte en cas de pluie, orage ou neige (après 15min de stabilisation). + Alerte gel entre 17h et 21h si température <3°C depuis 15min. + triggers: + - entity_id: + - sensor.mont_cauvaire_original_condition + trigger: state + id: condition_change + for: + hours: 0 + minutes: 15 + seconds: 0 + - entity_id: + - sensor.mont_cauvaire_temperature + below: 3 + trigger: numeric_state + id: risque_gel + for: + hours: 0 + minutes: 15 + seconds: 0 + conditions: [] + actions: + - choose: + - conditions: + - condition: trigger + id: + - condition_change + - condition: template + value_template: '{{ trigger.to_state.state in [''pluie'', ''orage'', ''neige''] + }}' + - condition: template + value_template: '{{ trigger.from_state.state not in [''pluie'', ''orage'', + ''neige''] }}' + sequence: + - choose: + - conditions: + - condition: template + value_template: '{{ trigger.to_state.state == ''orage'' }}' + sequence: + - action: script.notif_gotify + data: + title: ⛈️ Alerte orage + message: Rentrer mobilier jardin et fermer fenêtres ! + priority: 8 + default: + - action: script.notif_gotify + data: + title: "\U0001F326️ Alerte météo" + message: '{{ trigger.to_state.state | capitalize }}' + priority: 6 + - conditions: + - condition: trigger + id: + - risque_gel + - condition: time + after: '17:00:00' + before: '21:00:00' + sequence: + - action: script.notif_gotify + data: + title: "\U0001F331 Protection plantes" + message: Gel prévu ({{ states('sensor.mont_cauvaire_temperature') }}°C) + - Protéger plantes ! + priority: 7 + mode: queued + max: 3 +- id: '1766573335939' + alias: "\U0001F431 Litière - Utilisation et notifications" + description: Détecte chaque passage de Mojo (filtre 15s), incrémente le compteur + et notifie sur mobile. Déclenche un rappel nettoyage au seuil configuré, et un + rappel grand nettoyage au seuil de nettoyages cumulés. Reset manuel via input_button. + triggers: + - entity_id: + - binary_sensor.litiere_mouvement + to: + - 'on' + trigger: state + id: utilisation + for: + seconds: '{{ states(''input_number.duree_detection_litiere'') | int(15) }}' + - entity_id: counter.compteur_litiere + trigger: state + id: check_nettoyage + - entity_id: counter.nettoyages_litiere + trigger: state + id: check_gros_nettoyage + - entity_id: input_button.litiere_reset + trigger: state + id: reset + conditions: [] + actions: + - choose: + - conditions: + - condition: trigger + id: + - utilisation + sequence: + - action: counter.increment + target: + entity_id: counter.compteur_litiere + - action: notify.mobile_app_arthas + data: + title: "\U0001F431 Litière" + message: Mojo a chié. + - conditions: + - condition: trigger + id: + - check_nettoyage + - condition: template + value_template: "{{ states('counter.compteur_litiere') | int >= \n states('input_number.seuil_nettoyage_litiere') + | int }}" + sequence: + - action: script.notif_gotify + data: + title: "\U0001F9F9 Litière à nettoyer" + message: Mojo a utilisé la litière {{ states('counter.compteur_litiere') + }} fois. Il est temps de retirer les crottes ! + priority: 6 + - action: counter.reset + target: + entity_id: counter.compteur_litiere + - conditions: + - condition: trigger + id: + - check_gros_nettoyage + - condition: template + value_template: "{{ states('counter.nettoyages_litiere') | int >= \n states('input_number.seuil_gros_nettoyage') + | int }}" + sequence: + - action: script.notif_gotify + data: + title: "\U0001F9FC GROS NETTOYAGE litière" + message: '{{ states(''counter.nettoyages_litiere'') }} nettoyages effectués + ! Il est temps de faire le gros nettoyage complet de la litière (changement + total).' + priority: 8 + - action: counter.reset + target: + entity_id: counter.nettoyages_litiere + - action: counter.reset + target: + entity_id: counter.compteur_litiere + - conditions: + - condition: trigger + id: + - reset + sequence: + - action: counter.reset + target: + entity_id: counter.compteur_litiere + mode: queued + max: 3 +- id: '1771693177609' + alias: "\U0001F4A1 Lumières - Gestion complète" + description: Allume la véranda et le bar à l'arrivée d'un habitant après le coucher + du soleil (extinction véranda après 5min). Allume l'allée si une ouverture est + détectée de nuit. + triggers: + - entity_id: + - person.morgane + - person.seb + zone: zone.home + event: enter + id: arrivee + trigger: zone + - entity_id: + - binary_sensor.fenetre_bibliotheque + - binary_sensor.porte_veranda + to: 'on' + id: ouverture + trigger: state + conditions: [] + actions: + - choose: + - conditions: + - condition: trigger + id: arrivee + - condition: sun + after: sunset + sequence: + - target: + entity_id: + - light.bar + - light.interrupteur_veranda_l1 + data: + brightness_pct: 100 + action: light.turn_on + - delay: 00:05:00 + - target: + entity_id: light.interrupteur_veranda_l1 + action: light.turn_off + data: {} + - conditions: + - condition: trigger + id: ouverture + - condition: state + entity_id: sun.sun + state: below_horizon + sequence: + - target: + entity_id: switch.allee + action: switch.turn_on + data: {} + - delay: 00:05:00 + - target: + entity_id: switch.allee + action: switch.turn_off + data: {} + mode: restart +- id: '1777000000001' + alias: "\U0001F3E0 Mode Maison - Gestion complète" + description: Met à jour input_select.maison_mode selon la présence de Morgane et + Seb et l'état du mode vacances. Désactive automatiquement les vacances au retour + d'un habitant. + triggers: + - entity_id: person.morgane + zone: zone.home + event: enter + trigger: zone + id: morgane_enter + - entity_id: person.morgane + zone: zone.home + event: leave + trigger: zone + id: morgane_leave + - entity_id: person.seb + zone: zone.home + event: enter + trigger: zone + id: seb_enter + - entity_id: person.seb + zone: zone.home + event: leave + trigger: zone + id: seb_leave + - entity_id: input_boolean.vacance + trigger: state + id: vacance_toggle + conditions: [] + actions: + - choose: + - alias: Retour maison pendant vacances → désactive vacances + conditions: + - condition: or + conditions: + - condition: trigger + id: morgane_enter + - condition: trigger + id: seb_enter + - condition: state + entity_id: input_boolean.vacance + state: 'on' + sequence: + - action: input_boolean.turn_off + target: + entity_id: input_boolean.vacance + - action: alarmo.disarm + data: + code: '4212' + - alias: Vacances activées → mode vacances + armer Alarmo + conditions: + - condition: trigger + id: vacance_toggle + - condition: state + entity_id: input_boolean.vacance + state: 'on' + sequence: + - action: input_select.select_option + target: + entity_id: input_select.maison_mode + data: + option: vacances + - action: alarmo.arm + data: + mode: vacation + code: '4212' + - alias: Vacances OFF + quelqu'un à la maison → mode maison + désarmer + conditions: + - condition: or + conditions: + - condition: trigger + id: morgane_enter + - condition: trigger + id: seb_enter + - condition: state + entity_id: input_boolean.vacance + state: 'off' + - condition: template + value_template: '{{ is_state(''person.morgane'', ''home'') or is_state(''person.seb'', + ''home'') }}' + sequence: + - action: input_select.select_option + target: + entity_id: input_select.maison_mode + data: + option: maison + - action: alarmo.disarm + data: + code: '4212' + - alias: Vacances OFF + tout le monde absent → mode absent + armer + conditions: + - condition: or + conditions: + - condition: trigger + id: morgane_leave + - condition: trigger + id: seb_leave + - condition: state + entity_id: input_boolean.vacance + state: 'off' + - condition: template + value_template: '{{ is_state(''person.morgane'', ''not_home'') and is_state(''person.seb'', + ''not_home'') }}' + sequence: + - action: input_select.select_option + target: + entity_id: input_select.maison_mode + data: + option: absent + - action: alarmo.arm + data: + mode: away + code: '4212' + mode: restart +- id: '1781010467486' + alias: "\U0001F33F Marcelino - Gestion complète" + description: 'Notifie les erreurs, la batterie faible et le bilan du soir (19h15 + : retour en cours, erreur ou non en charge). Confirme le retour en base après + 19h15.' + triggers: + - id: erreur_change + entity_id: sensor.marcelino_erreur + trigger: state + - id: batterie_basse + entity_id: + - sensor.marcelino_batterie + below: 3 + trigger: numeric_state + - id: soir + at: '19:15:00' + trigger: time + - id: docked + entity_id: lawn_mower.marcelino + from: returning + to: docked + for: + seconds: 15 + trigger: state + actions: + - choose: + - conditions: + - condition: trigger + id: erreur_change + - condition: template + value_template: '{{ erreur != ''no_error'' }}' + sequence: + - data: + title: "\U0001F33F Marcelino" + message: '❌ Erreur : {{ erreur }}' + priority: 9 + action: script.notif_gotify + - conditions: + - condition: trigger + id: batterie_basse + sequence: + - data: + title: "\U0001F33F Marcelino" + message: "\U0001F50B Batterie faible : {{ states('sensor.marcelino_batterie') + }}%" + priority: 7 + action: script.notif_gotify + - conditions: + - condition: trigger + id: soir + - condition: not + conditions: + - condition: state + entity_id: lawn_mower.marcelino + state: docked + sequence: + - choose: + - conditions: + - condition: state + entity_id: lawn_mower.marcelino + state: returning + sequence: + - data: + title: "\U0001F33F Marcelino" + message: "\U0001F3E0 Marcelino est sur le chemin du retour" + priority: 5 + action: script.notif_gotify + - conditions: + - condition: template + value_template: '{{ erreur != ''no_error'' }}' + sequence: + - data: + title: "\U0001F33F Marcelino" + message: '❌ Erreur soir : {{ erreur }}' + priority: 9 + action: script.notif_gotify + - conditions: + - condition: template + value_template: '{{ tension < 25 }}' + sequence: + - data: + title: "\U0001F33F Marcelino" + message: ⚠️ Non en charge + priority: 7 + action: script.notif_gotify + - conditions: + - condition: trigger + id: docked + - condition: time + after: '19:15:00' + sequence: + - data: + title: "\U0001F33F Marcelino" + message: ✅ Marcelino est rentré à la maison + priority: 5 + action: script.notif_gotify + variables: + erreur: '{{ states(''sensor.marcelino_erreur'') }}' + tension: '{{ states(''sensor.marcelino_batterie'') | float(0) }}' + mode: restart +- id: '1781032426339' + alias: "\U0001F37D️ Mealie - Sync menus semaine" + description: Synchronise les menus Mealie — utilise la date de référence si définie + triggers: + - trigger: time + at: 06:00:00 + - trigger: homeassistant + event: start + - trigger: state + entity_id: input_datetime.mealie_semaine_ref + conditions: [] + actions: + - variables: + ref_date: "{% set ref = states('input_datetime.mealie_semaine_ref') %} {% if + ref not in ['unknown','unavailable',''] %}\n {% set d = strptime(ref, '%Y-%m-%d') + %}\n {{ (d.date() - timedelta(days=d.weekday())).strftime('%Y-%m-%d') }}\n{% + else %}\n {{ (now().date() - timedelta(days=now().weekday())).strftime('%Y-%m-%d') + }}\n{% endif %}" + - repeat: + for_each: + - nom: lundi + offset: 0 + - nom: mardi + offset: 1 + - nom: mercredi + offset: 2 + - nom: jeudi + offset: 3 + - nom: vendredi + offset: 4 + - nom: samedi + offset: 5 + - nom: dimanche + offset: 6 + sequence: + - variables: + jour_nom: '{{ repeat.item.nom }}' + jour_date: '{{ (strptime(ref_date, ''%Y-%m-%d'').date() + timedelta(days=repeat.item.offset)).strftime(''%Y-%m-%d'') + }}' + - repeat: + for_each: + - nom: petit_dejeuner + entity: calendar.mealie_petit_dejeuner + - nom: dejeuner + entity: calendar.mealie_dejeuner + - nom: accompagnement + entity: calendar.mealie_accompagnement + - nom: collation + entity: calendar.mealie_collation + - nom: dessert + entity: calendar.mealie_dessert + - nom: diner + entity: calendar.mealie_diner + sequence: + - action: calendar.get_events + target: + entity_id: '{{ repeat.item.entity }}' + data: + start_date_time: '{{ jour_date }}T00:00:00' + end_date_time: '{{ jour_date }}T23:59:59' + response_variable: events + - action: input_text.set_value + target: + entity_id: input_text.mealie_{{ jour_nom }}_{{ repeat.item.nom }} + data: + value: "{% set cal = repeat.item.entity %} {% if events[cal] is defined + and events[cal].events | length > 0 %}\n {{ events[cal].events[0].summary + }}\n{% else %}\n \n{% endif %}\n" + mode: single +- id: '1781126730091' + alias: Alarmo - Alertes Alexa simples + triggers: + - entity_id: alarm_control_panel.alarmo + to: armed_away + id: armed + trigger: state + - entity_id: alarm_control_panel.alarmo + to: disarmed + id: disarmed + trigger: state + - entity_id: alarm_control_panel.alarmo + to: triggered + id: triggered + trigger: state + actions: + - choose: + - conditions: + - condition: trigger + id: armed + sequence: + - data: + target: + - media_player.echo_chambre + - media_player.echo_bureau + - media_player.echo_salon + message: Système armé. + data: + type: announce + action: notify.alexa_media + - conditions: + - condition: trigger + id: disarmed + sequence: + - data: + target: + - media_player.echo_chambre + - media_player.echo_bureau + - media_player.echo_salon + message: Système désarmé. + data: + type: announce + action: notify.alexa_media + - conditions: + - condition: trigger + id: triggered + sequence: + - data: + target: + - media_player.echo_chambre + - media_player.echo_bureau + - media_player.echo_salon + message: Alerte intrusion. Alarme déclenchée. + data: + type: announce + action: notify.alexa_media + enabled: true + - action: notify.mobile_app_tablette + metadata: {} + data: + message: Intrusion détectée + title: "\U0001F6A8 Alarme" + mode: single +- id: '1781519588436' + alias: "\U0001F514 Michelle - Gestion minuteur" + description: Capture la source et notifie en boucle jusqu'à confirmation + triggers: + - event_type: assist_pipeline_run + id: capture_source + trigger: event + - event_type: timer.finished + id: timer_fini + trigger: event + actions: + - choose: + - conditions: + - condition: trigger + id: capture_source + sequence: + - action: input_text.set_value + target: + entity_id: input_text.timer_source_device + data: + value: '{{ trigger.event.data.device_id }}' + - conditions: + - condition: trigger + id: timer_fini + sequence: + - action: input_boolean.turn_on + target: + entity_id: input_boolean.timer_actif + - repeat: + while: + - condition: state + entity_id: input_boolean.timer_actif + state: 'on' + sequence: + - action: 'notify.{{ states(''input_text.timer_source_device'') }} + + ' + data: + title: ⏰ Minuteur terminé ! + message: Dis Okay Nabu, arrête le minuteur + data: + channel: timer + importance: high + ttl: 0 + priority: high + persistent: true + tag: timer_alert + - delay: + seconds: 30 diff --git a/notify.yaml b/notify.yaml new file mode 100644 index 0000000..3a4b1db --- /dev/null +++ b/notify.yaml @@ -0,0 +1,10 @@ +- platform: rest + name: gotify_notify + resource: http://192.168.42.10:7631/message + method: POST + headers: + X-Gotify-Key: "AIeuHYDyRvlAYxe" + message_param_name: message + title_param_name: title + data: + priority: 5 diff --git a/scenes.yaml b/scenes.yaml new file mode 100644 index 0000000..aaf3bd4 --- /dev/null +++ b/scenes.yaml @@ -0,0 +1,65 @@ +- id: '1755628384512' + name: "\U0001F319 Nuit" + entities: + light.lumieres: + state: 'off' + cover.volets: + state: closed + current_position: 0 + media_player.echo_bureau: + volume_level: 0.4 + is_volume_muted: false + source: Local Speaker + state: paused + media_player.echo_salon: + volume_level: 0.2 + is_volume_muted: false + source: Local Speaker + state: idle + switch.home_cinema_prise: + state: 'off' + remote.bboxtv: + state: 'off' + switch.allee: + state: 'off' + switch.entree_veranda: + state: 'off' + icon: mdi:weather-night + metadata: + switch.allee: + entity_only: true + switch.entree_veranda: + entity_only: true +- id: '1755628647672' + name: Volets - Chaleur + entities: + cover.volets: + state: open + current_position: 37 + icon: mdi:sun-thermometer-outline +- id: '1755628991599' + name: Cinéma + entities: + cover.volets: + state: closed + current_position: 0 + switch.home_cinema_prise: + device_class: outlet + icon: mdi:toggle-switch-variant + friendly_name: Home cinema + state: 'on' + light.halogene: + state: 'off' + icon: mdi:movie + metadata: + light.halogene: + entity_only: true +- id: '1766314080516' + name: "\U0001F3E0 Départ" + entities: + light.lumieres: + state: 'off' + cover.volets: + state: open + current_position: 100 + icon: mdi:home-export-outline diff --git a/scripts.yaml b/scripts.yaml new file mode 100644 index 0000000..c628a89 --- /dev/null +++ b/scripts.yaml @@ -0,0 +1,124 @@ +notif_gotify: + alias: "\U0001F4E2 Notification Gotify" + description: + Envoie une notification via Gotify avec cooldown anti-spam global 10min + (bypass si priorité ≥ 8) + fields: + title: + description: Titre de la notification + example: Doris + message: + description: Contenu du message + example: Le réservoir doit être vidé + priority: + description: Priorité (1-10) + example: 5 + default: 5 + sequence: + - condition: template + value_template: + "{{ (priority | default(5) | int) >= 8\n or (as_timestamp(now()) + - as_timestamp(states('input_datetime.last_notification'))) > 600 }}\n" + - action: notify.gotify_notify + data: + title: "{{ title | default('Home Assistant') }}" + message: "{{ message }}" + data: + priority: "{{ priority | default(5) }}" + - action: input_datetime.set_datetime + target: + entity_id: input_datetime.last_notification + data: + datetime: "{{ now() }}" +incrementer_cycle_doris: + alias: Incrémenter cycle Doris + sequence: + - action: counter.increment + data: {} + target: + entity_id: counter.cycle_doris + description: "" +reinitialiser_compteur_doris: + alias: "\U0001F9F9 Réinitialiser compteur Doris" + description: Remet le compteur à zéro après vidange du réservoir + sequence: + - action: counter.reset + target: + entity_id: counter.cycle_doris + - action: script.notif_gotify + data: + title: "\U0001F9F9 Doris" + message: Compteur remis à zéro après vidange + priority: 3 + icon: mdi:refresh +mealie_semaine_precedente: + alias: Mealie - Semaine précédente + sequence: + - action: input_datetime.set_datetime + target: + entity_id: input_datetime.mealie_semaine_ref + data: + date: + "{% set ref = states('input_datetime.mealie_semaine_ref') %} {% set + d = strptime(ref, '%Y-%m-%d') %} {{ (d.date() - timedelta(days=7)).strftime('%Y-%m-%d') + }} + + " + - action: automation.trigger + target: + entity_id: automation.mealie_sync_menus_semaine + data: + skip_condition: true + mode: single + description: "" +mealie_cette_semaine: + alias: Mealie - Cette semaine + sequence: + - action: input_datetime.set_datetime + target: + entity_id: input_datetime.mealie_semaine_ref + data: + date: + "{{ (now().date() - timedelta(days=now().weekday())).strftime('%Y-%m-%d') + }} + + " + - action: automation.trigger + target: + entity_id: automation.mealie_sync_menus_semaine + data: + skip_condition: true + mode: single + description: "" +mealie_semaine_suivante: + alias: Mealie - Semaine suivante + sequence: + - action: input_datetime.set_datetime + target: + entity_id: input_datetime.mealie_semaine_ref + data: + date: + "{% set ref = states('input_datetime.mealie_semaine_ref') %} {% set + d = strptime(ref, '%Y-%m-%d') %} {{ (d.date() + timedelta(days=7)).strftime('%Y-%m-%d') + }} + + " + - action: automation.trigger + target: + entity_id: automation.mealie_sync_menus_semaine + data: + skip_condition: true + mode: single + description: "" +arreter_le_minuteur: + alias: Arrêter le minuteur + sequence: + - action: input_boolean.turn_off + target: + entity_id: input_boolean.timer_actif + - action: notify.mobile_app_tablette + data: + message: clear_notification + data: + tag: timer_alert + description: "" diff --git a/secrets.yaml b/secrets.yaml new file mode 100644 index 0000000..0c9cef9 --- /dev/null +++ b/secrets.yaml @@ -0,0 +1,12 @@ +# Use this file to store secrets like usernames and passwords. +# Learn more at https://www.home-assistant.io/docs/configuration/secrets/ +some_password: welcome + +#Synology Chat +syno_chat_res: https://192.168.42.12:5001/webapi/entry.cgi?api=SYNO.Chat.External&method=incoming&version=2&token=%22Vt6mzBxZ9cyyLEmB4KnymbTOPM37GJsarAq807u4OVFvX1YpiA4i9ZH0ejXPViN1%22 + +#Synology calendrier +calendar_pwd-moe: Berg@motte + +# Mealie +mealie_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb25nX3Rva2VuIjp0cnVlLCJpZCI6IjA3YWZiMjJkLWRlN2QtNDJiNC1hZWMzLTNkYTVkZjUyNDJkNSIsIm5hbWUiOiJHZXJhbGQiLCJpbnRlZ3JhdGlvbl9pZCI6ImdlbmVyaWMiLCJleHAiOjE5Mzg3MTA4Mzh9.C6TglhK9vx-db7bRicDBI1CDlFJUSlbUkCpYdAotUak" \ No newline at end of file diff --git a/sensors.yaml b/sensors.yaml new file mode 100644 index 0000000..106d6a2 --- /dev/null +++ b/sensors.yaml @@ -0,0 +1,14 @@ +- platform: rest + name: "Mealie Meal Plan" + unique_id: mealie_meal_plan + resource: "http://192.168.42.10:7670/api/groups/mealplans?orderBy=date&orderDirection=asc&perPage=20" + headers: + Authorization: "Bearer !secret mealie_token" + value_template: "{{ value_json.items | length }} repas planifiés" + json_attributes_path: "$.items" + json_attributes: + - date + - entryType + - title + - recipe + scan_interval: 3600 diff --git a/template.yaml b/template.yaml new file mode 100644 index 0000000..5d52534 --- /dev/null +++ b/template.yaml @@ -0,0 +1,349 @@ +- sensor: + - name: "timer_ch_duration" + state: "{{ (states('input_number.timer_ch') | int * 60) | int }}" + unit_of_measurement: "seconds" + + - name: "Grocy Chores Weekly" + unique_id: grocy_chores_weekly + state: > + {{ state_attr('sensor.grocy_chores', 'chores') + | selectattr('period_type', 'equalto', 'weekly') + | list | count }} + attributes: + chores: > + {{ state_attr('sensor.grocy_chores', 'chores') + | selectattr('period_type', 'equalto', 'weekly') + | list }} + + - name: "Grocy Chores Monthly" + unique_id: grocy_chores_monthly + state: > + {{ state_attr('sensor.grocy_chores', 'chores') + | selectattr('period_type', 'equalto', 'monthly') + | list | count }} + attributes: + chores: > + {{ state_attr('sensor.grocy_chores', 'chores') + | selectattr('period_type', 'equalto', 'monthly') + | list }} + + - name: "Grocy Chores Adaptive" + unique_id: grocy_chores_adaptive + state: > + {{ state_attr('sensor.grocy_chores', 'chores') + | selectattr('period_type', 'equalto', 'adaptive') + | list | count }} + attributes: + chores: > + {{ state_attr('sensor.grocy_chores', 'chores') + | selectattr('period_type', 'equalto', 'adaptive') + | list }} + + - name: "Lumieres Allumees" + unique_id: lumieres_allumees + state: > + {{ expand('light.lumieres') + | selectattr('state', 'eq', 'on') | list | count }} + unit_of_measurement: "allumée(s)" + + - name: "Volets Ouverts" + unique_id: volets_ouverts + state: > + {{ expand('cover.volets') + | selectattr('state', 'eq', 'open') | list | count }} + unit_of_measurement: "ouvert(s)" + + - name: "Prises Actives" + unique_id: prises_actives + state: > + {{ expand('switch.prises') + | selectattr('state', 'eq', 'on') | list | count }} + unit_of_measurement: "active(s)" + + - name: "Ouvertures Ouvertes" + unique_id: ouvertures_ouvertes + state: > + {{ expand('binary_sensor.ouvrants') + | selectattr('state', 'eq', 'on') | list | count }} + unit_of_measurement: "ouvert(s)" + + - name: "Watchman Missing" + unique_id: watchman_missing + state: > + {{ state_attr("sensor.watchman_missing_entities", "entities") + | selectattr('state', 'eq', 'missing') | list | count }} + icon: mdi:alert-circle + + - name: "Watchman Unavail" + unique_id: watchman_unavail + state: > + {{ state_attr("sensor.watchman_missing_entities", "entities") + | selectattr('state', 'eq', 'unavail') | list | count }} + icon: mdi:alert-circle-outline + + - name: "HACS Intégrations count" + unique_id: hacs_integrations_count + state: > + {{ integration_entities('hacs') | list | count }} + icon: mdi:package-variant + + - name: "Grocy - Corvées hebdo réalisées" + unique_id: grocy_weekly_done + unit_of_measurement: "corvées" + icon: mdi:check-circle + state: > + {% set chores = state_attr('sensor.grocy_chores_weekly', 'chores') %} + {% if chores %} + {% set week_start = now().replace(hour=0, minute=0, second=0, microsecond=0) - timedelta(days=now().weekday()) %} + {{ chores | selectattr('last_tracked_time', 'ne', None) + | selectattr('last_tracked_time', 'ge', week_start.isoformat()) + | list | count }} + {% else %} + 0 + {% endif %} + + - name: "Grocy - Corvées hebdo restantes" + unique_id: grocy_weekly_remaining + unit_of_measurement: "corvées" + icon: mdi:clock-alert + state: > + {% set chores = state_attr('sensor.grocy_chores_weekly', 'chores') %} + {% if chores %} + {% set dow = now().weekday() %} + {% set days_to_friday = (4 - dow) % 7 %} + {% set friday_end = (now().replace(hour=23, minute=59, second=59, microsecond=0) + timedelta(days=days_to_friday)).isoformat() %} + {{ chores | selectattr('next_estimated_execution_time', 'ne', None) + | selectattr('next_estimated_execution_time', 'le', friday_end) + | list | count }} + {% else %} + 0 + {% endif %} + + - name: "Grocy - Corvées mensuelles réalisées" + unique_id: grocy_monthly_done + unit_of_measurement: "corvées" + icon: mdi:check-circle + state: > + {% set chores = state_attr('sensor.grocy_chores_monthly', 'chores') %} + {% if chores %} + {% set week_start = now().replace(hour=0, minute=0, second=0, microsecond=0) - timedelta(days=now().weekday()) %} + {{ chores | selectattr('last_tracked_time', 'ne', None) + | selectattr('last_tracked_time', 'ge', week_start.isoformat()) + | list | count }} + {% else %} + 0 + {% endif %} + + - name: "Grocy - Corvées mensuelles restantes" + unique_id: grocy_monthly_remaining + unit_of_measurement: "corvées" + icon: mdi:clock-alert + state: > + {% set chores = state_attr('sensor.grocy_chores_monthly', 'chores') %} + {% if chores %} + {% set dow = now().weekday() %} + {% set days_to_friday = (4 - dow) % 7 %} + {% set friday_end = (now().replace(hour=23, minute=59, second=59, microsecond=0) + timedelta(days=days_to_friday)).isoformat() %} + {{ chores | selectattr('next_estimated_execution_time', 'ne', None) + | selectattr('next_estimated_execution_time', 'le', friday_end) + | list | count }} + {% else %} + 0 + {% endif %} + + - name: "Grocy - Corvées adaptatives réalisées" + unique_id: grocy_adaptive_done + unit_of_measurement: "corvées" + icon: mdi:check-circle + state: > + {% set chores = state_attr('sensor.grocy_chores_adaptive', 'chores') %} + {% if chores %} + {% set week_start = now().replace(hour=0, minute=0, second=0, microsecond=0) - timedelta(days=now().weekday()) %} + {{ chores | selectattr('last_tracked_time', 'ne', None) + | selectattr('last_tracked_time', 'ge', week_start.isoformat()) + | list | count }} + {% else %} + 0 + {% endif %} + + - name: "Grocy - Corvées adaptatives restantes" + unique_id: grocy_adaptive_remaining + unit_of_measurement: "corvées" + icon: mdi:clock-alert + state: > + {% set chores = state_attr('sensor.grocy_chores_adaptive', 'chores') %} + {% if chores %} + {% set dow = now().weekday() %} + {% set days_to_friday = (4 - dow) % 7 %} + {% set friday_end = (now().replace(hour=23, minute=59, second=59, microsecond=0) + timedelta(days=days_to_friday)).isoformat() %} + {{ chores | selectattr('next_estimated_execution_time', 'ne', None) + | selectattr('next_estimated_execution_time', 'le', friday_end) + | list | count }} + {% else %} + 0 + {% endif %} + + - name: "Calendrier Mashome prochain" + unique_id: calendar_mashome_next + state: > + {% set next = state_attr('calendar.mashome', 'start_time') %} + {% if next %} + {% set diff = (as_local(as_datetime(next)) - now()).days %} + {{ diff <= 6 and diff >= 0 }} + {% else %} + false + {% endif %} + + - name: "Calendrier Garbage prochain" + unique_id: calendar_garbage_next + state: > + {% set next = state_attr('calendar.garbage', 'start_time') %} + {% if next %} + {% set diff = (as_local(as_datetime(next)) - now()).days %} + {{ diff <= 6 and diff >= 0 }} + {% else %} + false + {% endif %} + + - name: "Calendrier Garden prochain" + unique_id: calendar_garden_next + state: > + {% set next = state_attr('calendar.garden', 'start_time') %} + {% if next %} + {% set diff = (as_local(as_datetime(next)) - now()).days %} + {{ diff <= 6 and diff >= 0 }} + {% else %} + false + {% endif %} + + - name: "Calendrier Bestioles prochain" + unique_id: calendar_bestioles_next + state: > + {% set next = state_attr('calendar.bestioles', 'start_time') %} + {% if next %} + {% set diff = (as_local(as_datetime(next)) - now()).days %} + {{ diff <= 30 and diff >= 0 }} + {% else %} + false + {% endif %} + +- sensor: + - name: mojo_delai_repas + unique_id: mojo_delai_repas + state: > + {% set last = states.sensor.nutri_mojo_dernier_montant.last_changed %} + {% set diff = (now() - last).total_seconds() | int %} + {% set h = (diff // 3600) | int %} + {% set m = ((diff % 3600) // 60) | int %} + {% if h == 0 %}il y a {{ m }}min + {% elif h < 2 %}il y a {{ h }}h{{ '%02d' | format(m) }} + {% else %}il y a {{ h }}h + {% endif %} + attributes: + secondes: > + {{ (now() - states.sensor.nutri_mojo_dernier_montant.last_changed).total_seconds() | int }} + + - name: mojo_delai_litiere + unique_id: mojo_delai_litiere + state: > + {% set last = states.counter.compteur_litiere.last_changed %} + {% set diff = (now() - last).total_seconds() | int %} + {% set h = (diff // 3600) | int %} + {% set m = ((diff % 3600) // 60) | int %} + {% if h == 0 %}il y a {{ m }}min + {% elif h < 2 %}il y a {{ h }}h{{ '%02d' | format(m) }} + {% else %}il y a {{ h }}h + {% endif %} + attributes: + secondes: > + {{ (now() - states.counter.compteur_litiere.last_changed).total_seconds() | int }} + + - name: mojo_indice_confort + unique_id: mojo_indice_confort + unit_of_measurement: "/10" + state: > + {% set seuil = states('input_number.seuil_nettoyage_litiere') | float %} + {% set passages = states('counter.compteur_litiere') | int %} + {% set delai_repas = (now() - states.sensor.nutri_mojo_dernier_montant.last_changed).total_seconds() / 3600 %} + {% set score_litiere = [10 - ((passages / seuil) * 10) | round(0), 0] | max %} + {% set score_repas = [10 - ((delai_repas / 8) * 10) | round(0), 0] | max %} + {{ ((score_litiere * 0.5) + (score_repas * 0.5)) | round(1) }} + + - name: mojo_humeur + unique_id: mojo_humeur + state: > + {% set seuil = states('input_number.seuil_nettoyage_litiere') | float %} + {% set passages = states('counter.compteur_litiere') | int %} + {% set delai_repas = (now() - states.sensor.nutri_mojo_dernier_montant.last_changed).total_seconds() / 3600 %} + {% set litiere_ok = passages < seuil * 0.5 %} + {% set litiere_sale = passages > seuil * 0.8 %} + {% set repas_recent = delai_repas < 2 %} + {% set affame = delai_repas > 6 %} + {% if affame and litiere_sale %}Affamé et en colère + {% elif affame %}Affamé + {% elif litiere_sale %}Grognon + {% elif repas_recent and litiere_ok %}Roi du monde + {% elif repas_recent %}Content + {% else %}Neutre + {% endif %} + attributes: + icone: > + {% set h = states('sensor.mojo_humeur') %} + {% if h == 'Affamé et en colère' %}😾🍽️ + {% elif h == 'Affamé' %}🍽️😿 + {% elif h == 'Grognon' %}😾 + {% elif h == 'Roi du monde' %}👑😸 + {% elif h == 'Content' %}😸 + {% else %}🐱 + {% endif %} + citation: > + {% set h = states('sensor.mojo_humeur') %} + {% if h == 'Affamé et en colère' %}Tu pourrais faire un effort sur les deux fronts non ?! + {% elif h == 'Affamé' %}Je vois des croquettes partout... des croquettes imaginaires... + {% elif h == 'Grognon' %}Cette litière est une insulte à ma dignité féline. + {% elif h == 'Roi du monde' %}La vie est belle. Je règne sur tout ce que je vois. + {% elif h == 'Content' %}Zzz... bien mangé, bien fait... zzz... + {% else %}J'observe. J'attends. Je suis un chat. + {% endif %} + + - name: mojo_barre_faim + unique_id: mojo_barre_faim + unit_of_measurement: "%" + state: > + {% set repas_s = state_attr('sensor.mojo_delai_repas', 'secondes') | int(0) %} + {{ [[((1 - repas_s / 28800) * 100) | round, 0] | max, 100] | min }} + + - name: mojo_barre_hygiene + unique_id: mojo_barre_hygiene + unit_of_measurement: "%" + state: > + {% set passages = states('counter.compteur_litiere') | int %} + {% set seuil = states('input_number.seuil_nettoyage_litiere') | float(10) %} + {{ [[((1 - passages / seuil) * 100) | round, 0] | max, 100] | min }} + + - name: mojo_barre_energie + unique_id: mojo_barre_energie + unit_of_measurement: "%" + state: > + {% set h = now().hour %} + {% if h >= 6 and h <= 9 %}90 + {% elif h >= 17 and h <= 20 %}85 + {% elif h >= 13 and h <= 15 %}15 + {% elif h >= 22 or h < 5 %}10 + {% else %}55{% endif %} + + - name: mojo_barre_calins + unique_id: mojo_barre_calins + unit_of_measurement: "%" + state: > + {{ ((now().minute * 7 + now().hour * 13) % 50) + 30 }} + + - name: mojo_barre_capteur + unique_id: mojo_barre_capteur + unit_of_measurement: "%" + state: > + {% set b = states('sensor.litiere_etat_batterie') %} + {% if b == 'high' %}90 + {% elif b == 'middle' %}50 + {% elif b == 'low' %}15 + {% else %}0{% endif %}