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 %}