Contents
- 1 Intro
- 2 Mise à jour
- 3 Installation
- 4 Configuration
- 5 Interface Utilisateur Web
- 6 Conclusion
- 7 Publication en lien avec cet article:
- 8 Références
Intro
Dans mes publications, je fais de plus en plus référence à des applications écrites en python dans l’addon « Appdaemon ».
Il me semblait utile de détailler simplement son installation dans un article.
Cet Addon, pour ceux qui ne connaissent pas, vient compléter HA en permettant d’écrire et utiliser des programmes en Python très élaborés, voir impossibles à réaliser avec l’automatisme de base de HA.
Il permet également de développer un tableau de bord, mais ce n’est pas son point fort, j’ai testé mais je ne suis pas fan, trop long à mettre en oeuvre à mon gout.
Mise à jour
Du 23 Novembre 2023:
Depuis la version 0.15.0 le dossier APPDAEMON à migré (automatiquement avec la mise à jour) du « /root/config/appdaemon » vers « /root/addon_configs/a0d7b954_appdaemon/ »
C’est accessible avec Visual Studio avec la commande « Open Folder ».
Pour ceux qui avait déjà installé l’addon, vous vous rendrez compte que suite à la mise à jour, il ne fonctionne plus. Pour le rendre de nouveau opérationnel, il faut modifier le fichier « appdaemon.yaml » en remplaçant les directives « secrets: /config/secrets.yaml » par « secrets: /homeassistant/secrets.yaml » et celles des fichiers log: « filename: /config/log/…….log par « filename: /homeassistant/log/…….log » et tout rentre dans l’ordre.
Pour plus d’info, consulter: https://github.com/hassio-addons/addon-appdaemon/releases
Du 1 juin 2022:
- Ajout de l’application « Alerte meteo »
Installation
l’installation de l’Addon est simple en tout cas avec HASS, il suffit de le chercher dans la boutique des modules complémentaires et de l’installer. Pour les autres configurations, il faut se reporter à la documentation de l’addon.
Classiquement dans un Addon, vous avez accès aux informations, à la documentation, la configuration et le journal.
Dans un premier temps vous laissez la configuration par défaut, vous pourrez toujours y revenir par la suite. Veuillez noter le port 5050 qui vous permettra d’accéder à l’UI de AppDaeamon.
Si tout va bien vous devez visualiser un journal qui ressemble à minima celui-ci:
Configuration
Après installation, nous devons configurer AppDaemon, pour cela vous trouverez un dossier /root/addon_configs/a0d7b954_appdaemon/ » contenant plusieurs sous-dossiers:
Pour y acceder vous pouvez utiliser Visual Studio Visual Studio avec la commande « Open Folder », cliquez sur « addon_configs »
AppDaemon.yaml
Le premier fichier qui nous interresse est le « /addon_configs/a0d7b954_appdaemon/appdaemon.yaml », il est installé par défaut avec l’Addon, mais il nécessite d’être personnalisé.
Commençons par les coordonnées géographiques permettent de déterminer la date et l’heure locale, vous pouvez utiliser le fichier « secrets.yaml » déclaré dans votre HA.
Ensuite nous redirigeons les journaux dans un dossier spécifique « /homeassistant/log/.. » précédemment créé. Par défaut les « logs » sont envoyés dans le « main_log » de l’addon.
Pour ma part je créé un fichier spécifique à chacune de mes applications, c’est plus facile de s’y retrouver, par exemple:
- piscine_log: #Nom du log que vous utilisez dans le programme python
- name: PiscineLog # Nom obligatoire créé par l’utilisateur
- filename: /homeassistant/log/piscine.log # chemin et nom des fichiers logs
- log_generations: 3 #nombre de fichier logs maximum (les anciens sont écrasés)
- log_size: 100000 # Taille des fichiers logs quasiment égales au nombre de caractères(Par défaut ils font 1 000 0000 de caractères)
- Vous pouvez aussi personnaliser le format, se reporter à la documentation de l’addon.
La dernière version de mon fichier « appdaemon.yaml » est téléchargeable ici.
---
secrets: /homeassistant/secrets.yaml
appdaemon:
latitude: !secret latitude
longitude: !secret longitude
elevation: 220
time_zone: Europe/Paris
plugins:
HASS:
type: hass
http:
url: http://192.168.0.37:5050
admin:
api:
hadashboard:
logs:
main_log:
filename: /homeassistant/log/appdaemon.log
access_log:
filename: /homeassistant/log/access.log
error_log:
filename: /homeassistant/log/error.log
diag_log:
filename: /homeassistant/log/diag.log
format: "{asctime} {levelname:<8} {appname:<10}: {message}"
piscine_log:
name: PiscineLog
filename: /homeassistant/log/piscine.log
log_generations: 3
log_size: 200000
linky_log:
name: LinkyLog
filename: /homeassistant/log/linky.log
log_generations: 3
log_size: 100000
surveille_log:
name: SurveilleLog
filename: /homeassistant/log/surveille_log.log
log_generations: 3
log_size: 100000
groupealerte_log:
name: GroupeAlertLog
filename: /homeassistant/log/groupealerte_log.log
log_generations: 3
log_size: 100000
fin_certificats_log:
name: fincertificats
filename: /homeassistant/log/fin_certificats_log.log
log_generations: 3
log_size: 100000
test_log:
name: TestLog
filename: /homeassistant/log/test_log.log
log_generations: 3
log_size: 100000
Il ne vous reste qu’a personnaliser vos log si vous le souhaitez.
Nota: Après chaque modification du fichier « .yaml », il faut redémarrer l’addon depuis son interface:
Code des fichiers python
Nos fichiers d’applications écrits en python sont stockés dans le fichier « /config/appdaemon/apps »
Chaque application comprends deux fichiers:
- Fichier » .yaml » dans lequel nous déclarons les appels vers le fichier python « .py » associé et les entités HA utilisées dans le programme.
- Fichier « .py« : C’est le fichier programme python principal déclaré dans le . »yaml. » Je ne vais pas en détailler le contenu car d’une part la documentation de l’addon est très complète et d’autre part il existe de nombreux sites expliquant la programmation en python.
Par défaut, un seul fichier « .yaml » peut regrouper les déclarations de toutes les applications « .py », mais afin d’améliorer la visibilité, je préfère le séparer par application.
Après modification d’un de ces fichiers, toutes les applications sont automatiquement réinitialisées.
Exemple d’applications AppDaemon:
Surveille l’activité d’une entité
Cette application permet de « surveiller » le changement d’état d’une variable dans un temps donné, une fois le temps écoulé, si la variable n’a pas évolué, une notification et une action sont déclenchées.
Fichier appdaemon.yaml
Ajout du log correspondant:
surveille_log:
name: SurveilleLog
filename: /homeassistant/log/surveille_log.log
log_generations: 3
log_size: 100000
Fichier « Surveille_activite.yaml »
La configuration minimale est:
- surveille_com_linky: # nom du module que vous retrouvez dans AppDaemon
- module: surveille_activite » Nom du fichier « .py » associé
- class: SurveilleActivite # Class à déclarer dans le fichier « .py »
- entite: sensor.linky_papp # L’entité HA surveillée
- tempo: 3600 # Tempo de surveillance en secondes
- activite_ok: input_boolean.com_linky # l’entité HA actionnée si dépassement
En quelques lignes, vous pouvez faire appel plusieurs fois à une même instance, dans mon cas je surveille les communications entre HA et mon compteur Linky et ma centrale Météo.
La dernière version du fichier est téléchargeable ici.
surveille_com_linky:
module: surveille_activite
class: SurveilleActivite
entite: sensor.linky_umoy #sensor.linky_i_inst # sensor.linky_papp #sensor.linky_umoy #
#entite: input_text.linky_test_status
tempo: 3600 # Tempo de surveillance en secondes
activite_ok: input_boolean.com_linky #switch.test_com_out
surveille_com_vp2:
module: surveille_activite
class: SurveilleActivite
entite: sensor.vp2_datetime
tempo: 360 # Tempo de surveillance en secondes
activite_ok: input_boolean.com_vp2
surveille_alim_tablette:
module: surveille_activite
class: SurveilleActivite
entite: sensor.tablette_niveau_charge
tempo: 600 # Tempo de surveillance en secondes
activite_ok: input_boolean.alim_tablette_ok
Fichier « Surveille_activite.py »
Dans les grandes lignes, vous avez:
- les class python à importer: à minima « import hassapi as hass »
- la class déclarée dans le fichier « .yaml »
- Une fonction initialisation obligatoire
- Une fonction appelée sur changement d’état
- Une fonction de notification
La dernière version du fichier est téléchargeable ici.
import hassapi as hass
class SurveilleActivite(hass.Hass):
def initialize(self):
self.listen_state(self.change,self.args["entite"])
nom_entité = self.get_state(self.args["entite"],attribute="entity_id")
duree_tempo=int(self.args["tempo"])
self.turn_on(self.args["activite_ok"])
self.tempo=self.run_in(self.notification, duree_tempo,entité=nom_entité,temps=duree_tempo)
self.log(f'Initialisation de: {nom_entité} pour {duree_tempo}s et {self.tempo}.', log="surveille_log")
def change(self, entity, attribute, old, new, kwargs):
heure = str(self.time())[:8]
duree_tempo=int(self.args["tempo"])
tempo_on = str(entity)
nom_entité = str(entity)
nouvelle_valeur = new
# Mise à on de Com_Ok
self.turn_on(self.args["activite_ok"])
self.log(f'Nouvelle valeur de {entity}: {nouvelle_valeur}-Tempo={duree_tempo}', log="surveille_log")
cle_tempo = self.tempo
if cle_tempo != None:
self.tempo = self.cancel_timer(cle_tempo)
#self.log(f'Info tempo: {self.info_timer(cle_tempo)}', log="surveille_log")
#self.log(f'Fin tempo {cle_tempo}', log="surveille_log")
self.tempo = self.run_in(self.notification, duree_tempo,entité=nom_entité,temps=duree_tempo)
def notification(self, kwargs):
heure = str(self.time())[:8]
nom_entité = kwargs["entité"]
duree_temps= kwargs["temps"]
# Mise à off de Com_Ok
self.turn_off(self.args["activite_ok"])
self.log(f'Alerte! {nom_entité} est out depuis {duree_temps} sec.', log="surveille_log")
message_notification=format(heure)+"Alerte!"+ format(nom_entité)+"est out depuis: "+format(duree_temps)+" sec."
self.call_service('notify/telegram', message_notification)
self.call_service('dwains_dashboard/notification_create', message=message_notification)
Surveille le délai de validité d’un certificat Lets
L’intégration « Expiration du certificat » permet de surveiller l’état d’un certificat « Lest’enscript ». Les miens sont gérés par mon NAS OpenMediaVault.
Le but de cette application « AppDaemon » est de notifier que le délai du certificat expire dans un nombre de jours paramétrables ou si le certificat est devenu invalide.
La notification sera relancée chaque jour à 00:00 tant le certificat n’aura pas été renouvelé.
Le « state » indique la date-time à laquelle le certificat expire, l’attribut « is_valid » indique si le certificat est encore valide.
Fichier appdaemon.yaml
Ajout du log correspondant:
fin_certificats_log:
name: fincertificats
filename: /homeassistant/log/fin_certificats_log.log
log_generations: 3
log_size: 100000
Fichier « alerte_fin_certificats.yaml »
Déclaration des entités à surveiller et du seuil bas en nombre de Jours en dessous duquel la notification est activée.
La dernière version du fichier est téléchargeable ici:
alert_fin_certificats:
class: AlerteFinCertificats
module: alerte_fin_certificats
certif: sensor.cert_expiry_timestamp_domo_rem81_com,sensor.cert_expiry_timestamp_meteo_rem81_com,sensor.cert_expiry_timestamp_motioneye_rem81_com,sensor.cert_expiry_timestamp_ha_rem81_com,sensor.cert_expiry_timestamp_nextcloud_rem81_com,sensor.cert_expiry_timestamp_matamo_rem81_com
seuil_bas: 25 # En Jours
Fichier « alerte_fin_certificats.py »
Le programme python correspondant:
La dernière version du fichier est téléchargeable ici:
import hassapi as hass
import datetime
from datetime import datetime
from datetime import timedelta
import time
# Niveau de JOURNALISATION (log): 0=rien ou 1 =info ou 2=debug
JOURNAL=2
class AlerteFinCertificats(hass.Hass):
def initialize(self):
if "certif" in self.args:
for certif in self.split_device_list(self.args["certif"]):
self.notification('Surveillance de:'+certif,2,"")
tempo_j = self.run_daily(self.bilan_jour, "00:05:00")
self.bilan_jour(self)
#tempo_j = self.run_every(self.bilan_jour, "now", 1 * 60)
self.log("Initialisation Alert_fin_certificat.py", log="fin_certificats_log")
self.log("Initialisation Alert_fin_certificat.py", log="error_log")
def bilan_jour(self,kwargs):
s_bas= int(self.args["seuil_bas"])
tousvalides=1 # Indicateur que tous les certificats sont valables
for certif in self.split_device_list(self.args["certif"]):
self.notification('Lecture de:'+certif,2,"")
nom_entité = self.friendly_name(certif)
etat = self.get_state(certif, attribute="state")
validité = self.get_state(certif,attribute="is_valid")
self.notification("Friendly_name= "+nom_entité,2,"")
self.notification("Etat= "+etat,2,"")
# Vérifie si le certificat est valide
if etat !="unknown" and validité == True:
# Création entités dans HA
binarysensorname="binary_sensor.cert_"+certif[29:]+"_validite" #binary_sensor.certificat_ha
#binarysensorname="binary_sensor.cert_"+nom_entité+"_validite" #binary_sensor.certificat_ha
self.set_state(binarysensorname, state="on", replace=True, attributes= {"icon": "mdi:check","device_class": "connectivity"})
self.notification("Binary_SensorName:" + binarysensorname,2,"")
ce_jour=datetime.strptime(time.strftime('%Y:%m:%d', time.localtime()),'%Y:%m:%d')
self.notification("ce Jour:" + str(ce_jour),2,"")
date_de_fin=datetime.strptime(etat[:10],'%Y-%m-%d')
self.notification("Date de Fin:" + str(date_de_fin),2,"")
if date_de_fin<ce_jour:
nb_jour=(date_de_fin-ce_jour).days
self.notification("nb Jour negatifs:" + str(nb_jour),2,"")
else:
nb_jour=(date_de_fin-ce_jour).days
self.notification("nb Jour:" + str(nb_jour),2,"")
sensorname="sensor.cert_"+certif[29:]+"_fin"
#sensorname="sensor.cert_"+nom_entité+"_fin"
self.notification("SensorName:" + sensorname,2,"")
# Vérifie si le nombre de jours est inférieur au seuil bas
if nb_jour < s_bas:
# Mise à jour entités HA
message_notification= "Attention: Fin du certificat <"+ format(nom_entité)+"> dans "+ format(nb_jour)+" J."
self.set_state(sensorname, state=nb_jour, replace=True, attributes= {"icon": "mdi:alert-octagram", "unit_of_measurement": "J"})
self.notification(message_notification,0,"teleg")
else:
# Mise à jour entités HA
message_notification= "Le certificat <"+ format(nom_entité)+"> est encore valable "+ format(nb_jour)+" J."
self.set_state(sensorname, state=nb_jour, replace=True, attributes= {"icon": "mdi:check", "unit_of_measurement": "J"})
self.notification(message_notification,2,"")
else:
tousvalides=0 # Indicateur qu'au moins un certificat n'est plus valable
# Mise à jour entité HA
binarysensorname="binary_sensor.cert_"+nom_entité+"_validite"
self.set_state(binarysensorname, state="off", replace=True, attributes= {"icon": "mdi:alert-octagram","device_class": "connectivity"})
message_notification= " Attention: Le certificat <"+ format(nom_entité)+"> n'est plus valide."
self.notification(message_notification,0,"teleg")
# mise à jour dans HA de l'indicateur synthèse que les certificats sont valables
if tousvalides==1:
self.set_state("binary_sensor.certificat_tous_valides",state="on", replace=True, attributes= {"icon": "mdi:check","device_class": "connectivity"})
else:
self.set_state("binary_sensor.certificat_tous_valides",state="off", replace=True, attributes= {"icon": "mdi:alert-octagram","device_class": "connectivity"})
# Fonction Notification
# message = Texte à afficher
# niveau = niveau de journalisation 0,1,2
# si notif == "teleg" on notifie aussi sur Télégram
def notification(self,texte_message,niveau,notif):
global JOURNAL
heure = str(self.time())[:8]
if niveau <= JOURNAL:
message_notification= format(heure)+": "+ texte_message
self.log(message_notification, log="fin_certificats_log")
if notif=="teleg":
self.call_service('notify/telegram', message=message_notification)
self.call_service('persistent_notification/create', message=message_notification)
self.call_service('dwains_dashboard/notification_create', message=message_notification)
Affichage du résultat
Interface Utilisateur Web
Vous y avez accès via le port de « 5050 » de HA (par exemple http://192.168.0.37:5050/). le port « 5050 » est celui déclaré dans la configuration de l’Addon:
Vous retrouverez dans l’UI de AppDaemon l’etat, les logs etc…
Dans l’ onglet « State », vous retrouvez vos applications App, le nom correspond à celui de la class de votre fichier « *.py ».
« State Idle » signifie que tout va bien. « compile error » signifié que votre programme fonctionne pas, dans ce cas vérifiez le programme python.
L’onglet « log » vous permet de sélectionner votre fichier log précédemment déclaré le « .yaml »
Le log « main_log » est commun à toutes les applications, c’est aussi le log par défaut.
Dans le log « error_log », vous retrouverez les erreurs de programmation, fonctionnement, etc..
Conclusion
J’ai fait le plus simple et le plus détaillé possible dans l’installation et l’utilisation de AppDaemon.
Vous l’avez compris, à travers cet Addon et sa puissance de feu, vous offrez de nombreuses fonctionnalités à votre HA.
N’hésitez pas à commenter, vos critiques positives et négatives constructrices seront les bienvenues.
Publication en lien avec cet article:
- https://domo.rem81.com/index.php/2022/01/03/ha-teleinformation-linky-mode-historique/
- https://domo.rem81.com/index.php/2022/02/02/ha-gestion-piscine-1-filtration-avec-appdaemon-2/
Références
Voici quelques liens qui m’ont aidé dans la découverte de Appdaemon:
- https://github.com/hassio-addons/addon-appdaemon
- https://appdaemon.readthedocs.io/en/latest/
- https://github.com/AppDaemon/appdaemon/tree/dev/conf/example_apps
- https://wltd.org/posts/how-to-make-complex-automations-with-appdaemon-easily
- https://github.com/ReneTode/My-AppDaemon/tree/master/AppDaemon_for_Beginner
- https://appdaemon.readthedocs.io/en/latest/HASS_API_REFERENCE.html#app-creation
Bonjour rem81
Un grand merci pour cet article relativement précis qui pourrait bien m’être utile pour une tâche particulière que je cherche à faire : fermer une app de mon smartphone (avec une notification command_launch_app mais command_close_app n’existe pas).
Les logs semblent corrects, je m’attendais donc à trouver une entité ou un service me permettant à l’exécution de la commande de fermer mon app, mais je ne vois aucune entité ou service en rapport avec ma programmation 🙁
Est-ce que je loupe quelque chose dans le raisonnement ?
Bonjour désolé mais je ne sais pas t’aider.
Je viens de passer 1 heure à comprendre pourquoi plus rien ne marchait. Bien sûr ça venait du appdaemon.yaml. Merci Rem pour ton update du 23 novembre, j’aurais jamais trouvé!! Ouf!
Bonjour,
Les liens vers le github des addon de appdaemon ne sont pas disponibles
Merci
Bonjour, il faut utiliser les codes de l’article, j’ai supprimer les liens de téléchargement devenu obsoletes suite à la réorganisation de APPDAEMON
Cdlt
Bonjour,
Voici les logs « piscine », je ne sais pas si les fichiers de cette page sont ceux qui sont dans le github ?
Merci
2024-06-26 08:35:46.066604 WARNING AppDaemon: Logged an error to /homeassistant/log/error.log
2024-06-26 08:35:46.058769 INFO AppDaemon: App initialization complete
2024-06-26 08:35:46.054677 WARNING Piscine: Piscine: Entity input_boolean.mem_delestage not found in namespace default
2024-06-26 08:35:46.052770 WARNING Piscine: Piscine: Entity input_select.mode_fonctionnement_piscine not found in namespace default
2024-06-26 08:35:46.050089 INFO AppDaemon: Calling initialize() for Piscine
2024-06-26 08:35:46.049655 INFO hello_world: You are now ready to run Apps!
2024-06-26 08:35:46.049263 INFO hello_world: Hello from AppDaemon
2024-06-26 08:35:46.028186 INFO AppDaemon: Calling initialize() for hello_world
2024-06-26 08:35:46.027464 INFO AppDaemon: Loading app Piscine using class FiltrationPiscine from module filtration_piscine
Bonjour, il faut utiliser les codes de l’article, j’ai supprimer les liens de téléchargement devenu obsoletes suite à la réorganisation de APPDAEMON
les deux entités en warning sont déclarées dans un fichier .yaml de HA
cdlt
Bonjour,
Merci pour tes reponses, ne connaissant pas HA…
J’ai cherché en vain
# voir le « input select » dans « config/helpers »
ceci etant la declaration du fichier piscine.yaml
»
# selection du mode de fonctionnement de la filtration
# voir le « input select » dans « config/helpers »
input_select:
# sert aux tests AppDaemon
mode_fonctionnement_piscine_test:
name: Mode Fonct Piscine
options:
– « Auto »
– « Ma F »
– « At F »
icon: mdi:pool
«
Bonjour, dans le piscine.yaml il y a aussi la déclaration du « input_select.mode_fonctionnement_piscine », sinon tu peux aussi le déclarer dans « parametres » (menu de gauche ds HA), puis « appareils et services », puis « entrées ». @+