{"id":2862,"date":"2022-05-31T09:48:35","date_gmt":"2022-05-31T07:48:35","guid":{"rendered":"https:\/\/domo.rem81.com\/?p=1544"},"modified":"2024-04-02T09:11:31","modified_gmt":"2024-04-02T07:11:31","slug":"ha-addon-appdaemon-programme-python-2","status":"publish","type":"post","link":"https:\/\/domo.rem81.com\/index.php\/2022\/05\/31\/ha-addon-appdaemon-programme-python-2\/","title":{"rendered":"HA-Addon APPDaemon-Programme Python"},"content":{"rendered":"\n\n\n\n<h1 class=\"wp-block-heading\">Intro<\/h1>\n\n\n\n<p>Dans mes publications, je fais de plus en plus r\u00e9f\u00e9rence \u00e0 des applications \u00e9crites en python dans l&rsquo;addon \u00ab\u00a0Appdaemon\u00a0\u00bb.<\/p>\n\n\n\n<p>Il me semblait utile de d\u00e9tailler simplement son installation dans un article.<\/p>\n\n\n\n<p>Cet Addon, pour ceux qui ne connaissent pas, vient compl\u00e9ter HA en permettant d&rsquo;\u00e9crire et utiliser des programmes en Python tr\u00e8s \u00e9labor\u00e9s, voir impossibles \u00e0 r\u00e9aliser avec l&rsquo;automatisme de base de HA.<\/p>\n\n\n\n<p>Il permet \u00e9galement de d\u00e9velopper un tableau de bord, mais ce n&rsquo;est pas son point fort, j&rsquo;ai test\u00e9 mais je ne suis pas fan, trop long \u00e0 mettre en oeuvre \u00e0 mon gout.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Mise \u00e0 jour<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Du 23 Novembre 2023:<\/h2>\n\n\n\n<p>Depuis la version 0.15.0 le dossier APPDAEMON \u00e0 migr\u00e9 (automatiquement avec la mise \u00e0 jour) du \u00ab\u00a0\/root\/config\/appdaemon\u00a0\u00bb vers \u00ab\u00a0\/root\/addon_configs\/a0d7b954_appdaemon\/\u00a0\u00bb<\/p>\n\n\n\n<p>C&rsquo;est accessible avec Visual Studio avec la commande \u00ab\u00a0Open Folder\u00a0\u00bb.<\/p>\n\n\n\n<p>Pour ceux qui avait d\u00e9j\u00e0 install\u00e9 l&rsquo;addon, vous vous rendrez compte que suite \u00e0 la mise \u00e0 jour, il ne fonctionne plus. Pour le rendre de nouveau op\u00e9rationnel, il faut  modifier le fichier \u00ab\u00a0appdaemon.yaml\u00a0\u00bb en rempla\u00e7ant les directives  \u00ab\u00a0secrets: \/config\/secrets.yaml\u00a0\u00bb par   \u00ab\u00a0secrets: \/homeassistant\/secrets.yaml\u00a0\u00bb et celles des fichiers log: \u00ab\u00a0filename: \/config\/log\/&#8230;&#8230;.log par \u00ab\u00a0filename: \/homeassistant\/log\/&#8230;&#8230;.log\u00a0\u00bb et tout rentre dans l&rsquo;ordre.<\/p>\n\n\n\n<p>Pour plus d&rsquo;info, consulter:  <a href=\"https:\/\/github.com\/hassio-addons\/addon-appdaemon\/releases\">https:\/\/github.com\/hassio-addons\/addon-appdaemon\/releases<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Du 1 juin 2022:<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ajout de l&rsquo;application \u00ab\u00a0Alerte meteo\u00a0\u00bb<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">Installation<\/h1>\n\n\n\n<p>l&rsquo;installation de l&rsquo;Addon est simple en tout cas avec HASS, il suffit de le chercher dans la boutique des modules compl\u00e9mentaires et de l&rsquo;installer. Pour les autres configurations, il faut se reporter \u00e0 la <a rel=\"noreferrer noopener\" href=\"https:\/\/appdaemon.readthedocs.io\/en\/latest\/\" data-type=\"URL\" data-id=\"https:\/\/appdaemon.readthedocs.io\/en\/latest\/\" target=\"_blank\">documentation<\/a> de l&rsquo;addon.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"600\" src=\"https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/02\/image-1-2-1024x600.png\" alt=\"\" class=\"wp-image-1548\" srcset=\"https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/02\/image-1-2-1024x600.png 1024w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/02\/image-1-2-300x176.png 300w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/02\/image-1-2-768x450.png 768w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/02\/image-1-2.png 1237w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"181\" height=\"343\" src=\"https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/01\/image-29.png\" alt=\"\" class=\"wp-image-1467\" srcset=\"https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/01\/image-29.png 181w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/01\/image-29-158x300.png 158w\" sizes=\"auto, (max-width: 181px) 100vw, 181px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"http:\/\/192.168.0.211\/wp-content\/uploads\/2022\/02\/image-2-1.png\" alt=\"\" class=\"wp-image-1548\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"http:\/\/192.168.0.211\/wp-content\/uploads\/2022\/02\/image-11-1024x478.png\" alt=\"\" class=\"wp-image-1567\"\/><\/figure>\n\n\n\n<p>Classiquement dans un Addon, vous avez acc\u00e8s aux informations, \u00e0 la documentation, la configuration et le journal.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"493\" src=\"http:\/\/192.168.0.211\/wp-content\/uploads\/2022\/01\/image-31-1024x493.png\" alt=\"\" class=\"wp-image-1471\" srcset=\"https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/01\/image-31-1024x493.png 1024w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/01\/image-31-300x145.png 300w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/01\/image-31-768x370.png 768w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/01\/image-31.png 1177w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Dans un premier temps vous laissez la configuration par d\u00e9faut, vous pourrez toujours y revenir par la suite. Veuillez noter le port 5050 qui vous permettra d&rsquo;acc\u00e9der \u00e0 l&rsquo;UI de AppDaeamon.<\/p>\n\n\n\n<p>Si tout va bien vous devez visualiser un journal qui ressemble \u00e0 minima celui-ci:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"http:\/\/192.168.0.211\/wp-content\/uploads\/2023\/11\/image-2-1.png\" alt=\"\" class=\"wp-image-2827\"\/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">Configuration<\/h1>\n\n\n\n<p>Apr\u00e8s installation, nous devons configurer AppDaemon, pour cela vous trouverez  un dossier \/root\/addon_configs\/a0d7b954_appdaemon\/\u00a0\u00bb contenant plusieurs sous-dossiers:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"http:\/\/192.168.0.211\/wp-content\/uploads\/2023\/11\/image-1.png\" alt=\"\" class=\"wp-image-2818\"\/><\/figure>\n\n\n\n<p>Pour y acceder vous pouvez utiliser Visual Studio Visual Studio avec la commande \u00ab\u00a0Open Folder\u00a0\u00bb, cliquez sur \u00ab\u00a0addon_configs\u00a0\u00bb<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"http:\/\/192.168.0.211\/wp-content\/uploads\/2023\/11\/image-1-2.png\" alt=\"\" class=\"wp-image-2821\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">AppDaemon.yaml<\/h2>\n\n\n\n<p>Le premier fichier qui nous interresse est le  \u00ab\u00a0\/addon_configs\/a0d7b954_appdaemon\/appdaemon.yaml\u00a0\u00bb, il est install\u00e9 par d\u00e9faut avec l&rsquo;Addon, mais il n\u00e9cessite d\u2019\u00eatre personnalis\u00e9.<\/p>\n\n\n\n<p>Commen\u00e7ons par les coordonn\u00e9es g\u00e9ographiques permettent de d\u00e9terminer la date et l&rsquo;heure locale, vous pouvez utiliser le fichier \u00ab\u00a0secrets.yaml\u00a0\u00bb d\u00e9clar\u00e9 dans votre HA.<\/p>\n\n\n\n<p>Ensuite nous redirigeons les journaux dans un dossier sp\u00e9cifique \u00ab\u00a0\/homeassistant\/<strong>log<\/strong>\/..\u00a0\u00bb pr\u00e9c\u00e9demment cr\u00e9\u00e9. Par d\u00e9faut les \u00ab\u00a0logs\u00a0\u00bb sont envoy\u00e9s dans le \u00ab\u00a0main_log\u00a0\u00bb de l&rsquo;addon.<\/p>\n\n\n\n<p>Pour ma part je cr\u00e9\u00e9 un fichier sp\u00e9cifique \u00e0 chacune de mes applications, c&rsquo;est plus facile de s&rsquo;y retrouver, par exemple:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>piscine_log: <\/strong>#Nom du log que vous utilisez dans le programme python\n<ul class=\"wp-block-list\">\n<li><strong>name: PiscineLog<\/strong> # Nom obligatoire cr\u00e9\u00e9 par l&rsquo;utilisateur<\/li>\n\n\n\n<li><strong>filename: \/homeassistant\/log\/piscine.log<\/strong> # chemin et nom des fichiers logs<\/li>\n\n\n\n<li><strong>log_generations: 3<\/strong> #nombre de fichier logs maximum (les anciens sont \u00e9cras\u00e9s)<\/li>\n\n\n\n<li><strong>log_size: 100000<\/strong> # Taille des fichiers logs quasiment \u00e9gales au nombre de caract\u00e8res(Par d\u00e9faut ils font 1 000 0000 de caract\u00e8res)<\/li>\n\n\n\n<li>Vous pouvez aussi personnaliser le format, se reporter \u00e0 la documentation de l&rsquo;addon.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>La derni\u00e8re version de mon fichier \u00ab\u00a0appdaemon.yaml\u00a0\u00bb est t\u00e9l\u00e9chargeable <a href=\"https:\/\/github.com\/remycrochon\/home-assistant\/blob\/master\/appdaemon\/appdaemon.yaml\" data-type=\"URL\" data-id=\"https:\/\/github.com\/remycrochon\/home-assistant\/blob\/master\/appdaemon\/appdaemon.yaml\" target=\"_blank\" rel=\"noreferrer noopener\">ici<\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>---\nsecrets: \/homeassistant\/secrets.yaml\nappdaemon:\n  latitude: !secret latitude\n  longitude: !secret longitude\n  elevation: 220\n  time_zone: Europe\/Paris\n  plugins:\n    HASS:\n      type: hass\nhttp:\n  url: http:\/\/192.168.0.37:5050\nadmin:\napi:\nhadashboard:\n\nlogs:\n  main_log:\n    filename: \/homeassistant\/log\/appdaemon.log\n    \n  access_log:\n    filename: \/homeassistant\/log\/access.log\n\n  error_log:\n    filename: \/homeassistant\/log\/error.log\n\n  diag_log:\n    filename: \/homeassistant\/log\/diag.log\n    format: \"{asctime} {levelname:&lt;8} {appname:&lt;10}: {message}\"\n\n  piscine_log:\n    name: PiscineLog\n    filename: \/homeassistant\/log\/piscine.log\n    log_generations: 3\n    log_size: 200000\n\n  linky_log:\n    name: LinkyLog\n    filename: \/homeassistant\/log\/linky.log\n    log_generations: 3\n    log_size: 100000\n\n  surveille_log:\n    name: SurveilleLog\n    filename: \/homeassistant\/log\/surveille_log.log\n    log_generations: 3\n    log_size: 100000\n\n  groupealerte_log:\n    name: GroupeAlertLog\n    filename: \/homeassistant\/log\/groupealerte_log.log\n    log_generations: 3\n    log_size: 100000\n\n  fin_certificats_log:\n    name: fincertificats\n    filename: \/homeassistant\/log\/fin_certificats_log.log\n    log_generations: 3\n    log_size: 100000\n\n  test_log:\n    name: TestLog\n    filename: \/homeassistant\/log\/test_log.log\n    log_generations: 3\n    log_size: 100000\n<\/code><\/pre>\n\n\n\n<p>Il ne vous reste qu&rsquo;a personnaliser vos log si vous le souhaitez.<\/p>\n\n\n\n<p>Nota: Apr\u00e8s chaque modification du fichier \u00ab\u00a0.yaml\u00a0\u00bb, il faut red\u00e9marrer l&rsquo;addon depuis son interface:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"http:\/\/192.168.0.211\/wp-content\/uploads\/2022\/02\/image-10-1024x478.png\" alt=\"\" class=\"wp-image-1566\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Code des fichiers python<\/h2>\n\n\n\n<p>Nos fichiers d\u2019applications \u00e9crits en python sont stock\u00e9s dans le fichier \u00ab\u00a0\/config\/appdaemon\/apps\u00a0\u00bb<\/p>\n\n\n\n<p>Chaque application comprends deux fichiers:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Fichier \u00a0\u00bb <strong>.yaml<\/strong>\u00a0\u00bb dans lequel nous d\u00e9clarons les appels vers le fichier python \u00ab\u00a0<strong>.py<\/strong>\u00a0\u00bb associ\u00e9 et les entit\u00e9s HA utilis\u00e9es dans le programme.<\/li>\n\n\n\n<li> Fichier \u00ab\u00a0<strong>.py<\/strong>\u00ab\u00a0: C&rsquo;est le fichier programme python principal d\u00e9clar\u00e9 dans le .\u00a0\u00bbyaml.\u00a0\u00bb Je ne vais pas en d\u00e9tailler le contenu car d&rsquo;une part la <a rel=\"noreferrer noopener\" href=\"https:\/\/appdaemon.readthedocs.io\/en\/latest\/\" target=\"_blank\">documentation<\/a> de l&rsquo;addon est tr\u00e8s compl\u00e8te et d&rsquo;autre part il existe de nombreux sites expliquant la programmation en python.<\/li>\n<\/ul>\n\n\n\n<p>Par d\u00e9faut, un seul fichier \u00ab\u00a0.yaml\u00a0\u00bb peut regrouper les d\u00e9clarations de toutes les applications \u00ab\u00a0.py\u00a0\u00bb, mais afin d&rsquo;am\u00e9liorer la visibilit\u00e9, je pr\u00e9f\u00e8re le s\u00e9parer par application.<\/p>\n\n\n\n<p>Apr\u00e8s modification d&rsquo;un de ces fichiers, <strong>toutes<\/strong> les applications sont automatiquement r\u00e9initialis\u00e9es.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Exemple d&rsquo;applications AppDaemon:<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"> Surveille l&rsquo;activit\u00e9 d&rsquo;une entit\u00e9<\/h3>\n\n\n\n<p>Cette application permet de \u00ab\u00a0surveiller\u00a0\u00bb le changement d&rsquo;\u00e9tat d&rsquo;une variable dans un temps donn\u00e9, une fois le temps \u00e9coul\u00e9, si la variable n&rsquo;a pas \u00e9volu\u00e9, une notification et une action sont d\u00e9clench\u00e9es.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Fichier appdaemon.yaml<\/h4>\n\n\n\n<p>Ajout du log correspondant:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  surveille_log:\n    name: SurveilleLog\n    filename: \/homeassistant\/log\/surveille_log.log\n    log_generations: 3\n    log_size: 100000\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Fichier \u00ab\u00a0Surveille_activite.yaml\u00a0\u00bb<\/h4>\n\n\n\n<p>La configuration minimale est:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>surveille_com_linky: # nom du module que vous retrouvez dans AppDaemon\n<ul class=\"wp-block-list\">\n<li>module: surveille_activite \u00a0\u00bb Nom du fichier \u00ab\u00a0.py\u00a0\u00bb associ\u00e9<\/li>\n\n\n\n<li>class: SurveilleActivite # Class \u00e0 d\u00e9clarer dans le fichier \u00ab\u00a0.py\u00a0\u00bb<\/li>\n\n\n\n<li>entite: sensor.linky_papp # L&rsquo;entit\u00e9 HA surveill\u00e9e<\/li>\n\n\n\n<li>tempo: 3600 # Tempo de surveillance en secondes<\/li>\n\n\n\n<li>activite_ok: input_boolean.com_linky # l&rsquo;entit\u00e9 HA actionn\u00e9e si d\u00e9passement<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>En quelques lignes, vous pouvez faire appel plusieurs fois \u00e0 une m\u00eame instance, dans mon cas je surveille les communications entre HA et mon compteur Linky et ma centrale M\u00e9t\u00e9o.<\/p>\n\n\n\n<p>La derni\u00e8re version du fichier est t\u00e9l\u00e9chargeable <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/remycrochon\/home-assistant\/blob\/master\/appdaemon\/apps\/surveille_activite.yaml\" data-type=\"URL\" data-id=\"https:\/\/github.com\/remycrochon\/home-assistant\/blob\/master\/appdaemon\/apps\/surveille_activite.yaml\" target=\"_blank\">ici<\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>surveille_com_linky:\n  module: surveille_activite\n  class: SurveilleActivite\n  entite: sensor.linky_umoy #sensor.linky_i_inst # sensor.linky_papp #sensor.linky_umoy #\n  #entite: input_text.linky_test_status\n  tempo: 3600 # Tempo de surveillance en secondes\n  activite_ok: input_boolean.com_linky #switch.test_com_out\n\nsurveille_com_vp2:\n  module: surveille_activite\n  class: SurveilleActivite\n  entite: sensor.vp2_datetime\n  tempo: 360 # Tempo de surveillance en secondes\n  activite_ok: input_boolean.com_vp2\n\nsurveille_alim_tablette:\n  module: surveille_activite\n  class: SurveilleActivite\n  entite: sensor.tablette_niveau_charge\n  tempo: 600 # Tempo de surveillance en secondes\n  activite_ok: input_boolean.alim_tablette_ok  <\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Fichier \u00ab\u00a0Surveille_activite.py\u00a0\u00bb<\/h4>\n\n\n\n<p>Dans les grandes lignes, vous avez:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>les class python \u00e0 importer: \u00e0 minima \u00ab\u00a0import hassapi as hass\u00a0\u00bb <\/li>\n\n\n\n<li>la class d\u00e9clar\u00e9e dans le fichier \u00ab\u00a0.yaml\u00a0\u00bb<\/li>\n\n\n\n<li>Une fonction initialisation obligatoire<\/li>\n\n\n\n<li>Une fonction appel\u00e9e sur changement d&rsquo;\u00e9tat<\/li>\n\n\n\n<li>Une fonction de notification<\/li>\n<\/ul>\n\n\n\n<p>La derni\u00e8re version du fichier est t\u00e9l\u00e9chargeable <a href=\"https:\/\/github.com\/remycrochon\/home-assistant\/blob\/master\/appdaemon\/apps\/surveille_activite.py\" data-type=\"URL\" data-id=\"https:\/\/github.com\/remycrochon\/home-assistant\/blob\/master\/appdaemon\/apps\/surveille_activite.py\" target=\"_blank\" rel=\"noreferrer noopener\">ici<\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import hassapi as hass\n\nclass SurveilleActivite(hass.Hass):\n    def initialize(self):\n        self.listen_state(self.change,self.args&#091;\"entite\"])\n        nom_entit\u00e9 = self.get_state(self.args&#091;\"entite\"],attribute=\"entity_id\")\n        duree_tempo=int(self.args&#091;\"tempo\"])\n        self.turn_on(self.args&#091;\"activite_ok\"])\n        self.tempo=self.run_in(self.notification, duree_tempo,entit\u00e9=nom_entit\u00e9,temps=duree_tempo)\n        self.log(f'Initialisation de: {nom_entit\u00e9} pour {duree_tempo}s et {self.tempo}.', log=\"surveille_log\")\n\n    def change(self, entity, attribute, old, new, kwargs):\n        heure = str(self.time())&#091;:8]\n        duree_tempo=int(self.args&#091;\"tempo\"])\n        tempo_on = str(entity)\n        nom_entit\u00e9 = str(entity)\n        nouvelle_valeur = new\n        # Mise \u00e0 on de Com_Ok\n        self.turn_on(self.args&#091;\"activite_ok\"])\n        self.log(f'Nouvelle valeur de {entity}: {nouvelle_valeur}-Tempo={duree_tempo}', log=\"surveille_log\")\n        cle_tempo = self.tempo\n        if cle_tempo != None:\n            self.tempo = self.cancel_timer(cle_tempo) \n            #self.log(f'Info tempo: {self.info_timer(cle_tempo)}', log=\"surveille_log\")\n            #self.log(f'Fin tempo {cle_tempo}', log=\"surveille_log\")\n\n        self.tempo = self.run_in(self.notification, duree_tempo,entit\u00e9=nom_entit\u00e9,temps=duree_tempo)\n\n    def notification(self, kwargs):\n        heure = str(self.time())&#091;:8]\n        nom_entit\u00e9 = kwargs&#091;\"entit\u00e9\"]\n        duree_temps= kwargs&#091;\"temps\"]\n        # Mise \u00e0 off de Com_Ok\n        self.turn_off(self.args&#091;\"activite_ok\"])\n        self.log(f'Alerte! {nom_entit\u00e9} est out depuis {duree_temps} sec.', log=\"surveille_log\")\n        message_notification=format(heure)+\"Alerte!\"+ format(nom_entit\u00e9)+\"est out depuis: \"+format(duree_temps)+\" sec.\"\n        self.call_service('notify\/telegram', message_notification)\n        self.call_service('dwains_dashboard\/notification_create', message=message_notification)<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Surveille le d\u00e9lai de validit\u00e9 d&rsquo;un certificat Lets<\/h3>\n\n\n\n<p>L&rsquo;int\u00e9gration \u00ab\u00a0Expiration du certificat\u00a0\u00bb permet de surveiller l&rsquo;\u00e9tat d&rsquo;un certificat \u00ab\u00a0Lest&rsquo;enscript\u00a0\u00bb. Les miens sont g\u00e9r\u00e9s par mon NAS OpenMediaVault.<\/p>\n\n\n\n<p>Le but de cette application \u00ab\u00a0AppDaemon\u00a0\u00bb est de notifier que le d\u00e9lai du certificat expire dans un nombre de jours param\u00e9trables ou si le certificat est devenu invalide.<\/p>\n\n\n\n<p>La notification sera relanc\u00e9e chaque jour \u00e0 00:00 tant le certificat n&rsquo;aura pas \u00e9t\u00e9 renouvel\u00e9.<\/p>\n\n\n\n<p>Le \u00ab\u00a0state\u00a0\u00bb indique la date-time \u00e0 laquelle le certificat expire, l&rsquo;attribut \u00ab\u00a0is_valid\u00a0\u00bb indique si le certificat est encore valide.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"http:\/\/192.168.0.211\/wp-content\/uploads\/2022\/02\/image-17-1.png\" alt=\"\" class=\"wp-image-1650\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Fichier appdaemon.yaml<\/h4>\n\n\n\n<p>Ajout du log correspondant:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  fin_certificats_log:\n    name: fincertificats\n    filename: \/homeassistant\/log\/fin_certificats_log.log\n    log_generations: 3\n    log_size: 100000\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Fichier \u00ab\u00a0alerte_fin_certificats.yaml\u00a0\u00bb<\/h4>\n\n\n\n<p>D\u00e9claration des entit\u00e9s \u00e0 surveiller et du seuil bas en nombre de Jours en dessous duquel la notification est activ\u00e9e.<\/p>\n\n\n\n<p>La derni\u00e8re version du fichier est t\u00e9l\u00e9chargeable <a href=\"https:\/\/github.com\/remycrochon\/home-assistant\/blob\/master\/appdaemon\/apps\/alerte_fin_certificats.yaml\" data-type=\"URL\" data-id=\"https:\/\/github.com\/remycrochon\/home-assistant\/blob\/master\/appdaemon\/apps\/alerte_fin_certificats.yaml\" target=\"_blank\" rel=\"noreferrer noopener\">ici<\/a>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>alert_fin_certificats:\n  class: AlerteFinCertificats\n  module: alerte_fin_certificats\n  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\n  seuil_bas: 25 # En Jours\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Fichier \u00ab\u00a0alerte_fin_certificats.py\u00a0\u00bb<\/h4>\n\n\n\n<p>Le programme python correspondant:<\/p>\n\n\n\n<p>La derni\u00e8re version du fichier est t\u00e9l\u00e9chargeable <a href=\"https:\/\/github.com\/remycrochon\/home-assistant\/blob\/master\/appdaemon\/apps\/alerte_fin_certificats.py\" data-type=\"URL\" data-id=\"https:\/\/github.com\/remycrochon\/home-assistant\/blob\/master\/appdaemon\/apps\/alerte_fin_certificats.py\" target=\"_blank\" rel=\"noreferrer noopener\">ici<\/a>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import hassapi as hass\nimport datetime\nfrom datetime import datetime\nfrom datetime import timedelta\nimport time\n\n#  Niveau de JOURNALISATION (log): 0=rien ou 1 =info ou 2=debug \nJOURNAL=2 \n\nclass AlerteFinCertificats(hass.Hass):\n    def initialize(self):\n        if \"certif\" in self.args:\n            for certif in self.split_device_list(self.args&#091;\"certif\"]):\n                self.notification('Surveillance de:'+certif,2,\"\")\n        tempo_j = self.run_daily(self.bilan_jour, \"00:05:00\")\n        self.bilan_jour(self)\n        #tempo_j = self.run_every(self.bilan_jour, \"now\", 1 * 60)\n        self.log(\"Initialisation Alert_fin_certificat.py\", log=\"fin_certificats_log\")\n        self.log(\"Initialisation Alert_fin_certificat.py\", log=\"error_log\")\n            \n    def bilan_jour(self,kwargs):\n        s_bas= int(self.args&#091;\"seuil_bas\"])\n        tousvalides=1 # Indicateur que tous les certificats sont valables\n        for certif in self.split_device_list(self.args&#091;\"certif\"]):\n            self.notification('Lecture de:'+certif,2,\"\")\n            nom_entit\u00e9 =  self.friendly_name(certif)\n            \n            etat = self.get_state(certif, attribute=\"state\")\n            validit\u00e9 = self.get_state(certif,attribute=\"is_valid\")\n            self.notification(\"Friendly_name= \"+nom_entit\u00e9,2,\"\")\n            self.notification(\"Etat= \"+etat,2,\"\")\n            # V\u00e9rifie si le certificat est valide\n            if etat !=\"unknown\" and validit\u00e9 == True:\n                # Cr\u00e9ation entit\u00e9s dans HA\n                binarysensorname=\"binary_sensor.cert_\"+certif&#091;29:]+\"_validite\"  #binary_sensor.certificat_ha\n                #binarysensorname=\"binary_sensor.cert_\"+nom_entit\u00e9+\"_validite\"  #binary_sensor.certificat_ha\n                self.set_state(binarysensorname, state=\"on\", replace=True, attributes= {\"icon\": \"mdi:check\",\"device_class\": \"connectivity\"})\n                self.notification(\"Binary_SensorName:\" + binarysensorname,2,\"\")\n                ce_jour=datetime.strptime(time.strftime('%Y:%m:%d', time.localtime()),'%Y:%m:%d')\n                self.notification(\"ce Jour:\" + str(ce_jour),2,\"\")\n                date_de_fin=datetime.strptime(etat&#091;:10],'%Y-%m-%d')\n                self.notification(\"Date de Fin:\" + str(date_de_fin),2,\"\")\n                if date_de_fin&lt;ce_jour:\n                    nb_jour=(date_de_fin-ce_jour).days\n                    self.notification(\"nb Jour negatifs:\" + str(nb_jour),2,\"\")\n                else:\n                    nb_jour=(date_de_fin-ce_jour).days\n                    self.notification(\"nb Jour:\" + str(nb_jour),2,\"\")\n                    sensorname=\"sensor.cert_\"+certif&#091;29:]+\"_fin\"\n                    #sensorname=\"sensor.cert_\"+nom_entit\u00e9+\"_fin\"\n                    self.notification(\"SensorName:\" + sensorname,2,\"\")\n\n                    # V\u00e9rifie si le nombre de jours est inf\u00e9rieur au seuil bas\n                    if nb_jour &lt; s_bas:\n                        # Mise \u00e0 jour entit\u00e9s HA\n                        message_notification= \"Attention: Fin du certificat &lt;\"+ format(nom_entit\u00e9)+\"&gt; dans \"+ format(nb_jour)+\" J.\"\n                        self.set_state(sensorname, state=nb_jour, replace=True, attributes= {\"icon\": \"mdi:alert-octagram\", \"unit_of_measurement\": \"J\"})\n                        self.notification(message_notification,0,\"teleg\")\n                    else:\n                        # Mise \u00e0 jour entit\u00e9s HA\n                        message_notification= \"Le certificat &lt;\"+ format(nom_entit\u00e9)+\"&gt; est encore valable \"+ format(nb_jour)+\" J.\"\n                        self.set_state(sensorname, state=nb_jour, replace=True, attributes= {\"icon\": \"mdi:check\", \"unit_of_measurement\": \"J\"})\n                        self.notification(message_notification,2,\"\")\n            else:\n                tousvalides=0 # Indicateur qu'au moins un certificat n'est plus valable\n                # Mise \u00e0 jour entit\u00e9 HA\n                binarysensorname=\"binary_sensor.cert_\"+nom_entit\u00e9+\"_validite\"\n                self.set_state(binarysensorname, state=\"off\", replace=True, attributes= {\"icon\": \"mdi:alert-octagram\",\"device_class\": \"connectivity\"})\n                message_notification= \" Attention: Le certificat &lt;\"+ format(nom_entit\u00e9)+\"&gt; n'est plus valide.\"\n                self.notification(message_notification,0,\"teleg\")\n\n        #  mise \u00e0 jour dans HA de l'indicateur synth\u00e8se que les certificats sont valables\n        if tousvalides==1:\n            self.set_state(\"binary_sensor.certificat_tous_valides\",state=\"on\", replace=True, attributes= {\"icon\": \"mdi:check\",\"device_class\": \"connectivity\"})\n        else:\n            self.set_state(\"binary_sensor.certificat_tous_valides\",state=\"off\", replace=True, attributes= {\"icon\": \"mdi:alert-octagram\",\"device_class\": \"connectivity\"})\n\n\n\n                \n    # Fonction Notification\n    # message =  Texte \u00e0 afficher\n    # niveau = niveau de journalisation 0,1,2\n    # si notif == \"teleg\" on notifie aussi sur T\u00e9l\u00e9gram\n    def notification(self,texte_message,niveau,notif):\n        global JOURNAL\n        heure = str(self.time())&#091;:8]\n        if niveau &lt;= JOURNAL:\n            message_notification= format(heure)+\": \"+ texte_message\n            self.log(message_notification, log=\"fin_certificats_log\")\n            if notif==\"teleg\":\n                self.call_service('notify\/telegram', message=message_notification)\n                self.call_service('persistent_notification\/create', message=message_notification)\n                self.call_service('dwains_dashboard\/notification_create', message=message_notification)\n    <\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Affichage du r\u00e9sultat<\/h4>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"427\" height=\"476\" src=\"http:\/\/192.168.0.211\/wp-content\/uploads\/2022\/04\/image-3.png\" alt=\"\" class=\"wp-image-1883\" srcset=\"https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/04\/image-3.png 427w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/04\/image-3-269x300.png 269w\" sizes=\"auto, (max-width: 427px) 100vw, 427px\" \/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">Interface Utilisateur Web<\/h1>\n\n\n\n<p>Vous y avez acc\u00e8s via le port de \u00ab\u00a05050\u00a0\u00bb de HA (par exemple http:\/\/192.168.0.37:5050\/). le port \u00ab\u00a05050\u00a0\u00bb est celui d\u00e9clar\u00e9 dans la configuration de l&rsquo;Addon:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"493\" src=\"http:\/\/192.168.0.211\/wp-content\/uploads\/2022\/01\/image-31-1024x493.png\" alt=\"\" class=\"wp-image-1471\" srcset=\"https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/01\/image-31-1024x493.png 1024w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/01\/image-31-300x145.png 300w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/01\/image-31-768x370.png 768w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/01\/image-31.png 1177w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Vous retrouverez dans l&rsquo;UI de AppDaemon l&rsquo;etat, les logs etc&#8230; <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"428\" height=\"475\" src=\"http:\/\/192.168.0.211\/wp-content\/uploads\/2022\/01\/image-32.png\" alt=\"\" class=\"wp-image-1474\" srcset=\"https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/01\/image-32.png 428w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/01\/image-32-270x300.png 270w\" sizes=\"auto, (max-width: 428px) 100vw, 428px\" \/><\/figure>\n\n\n\n<p>Dans l&rsquo; onglet \u00ab\u00a0State\u00a0\u00bb, vous retrouvez vos applications App, le nom correspond \u00e0 celui de la class de votre fichier \u00ab\u00a0*.py\u00a0\u00bb.<\/p>\n\n\n\n<p> \u00ab\u00a0State Idle\u00a0\u00bb signifie que tout va bien. \u00ab\u00a0compile error\u00a0\u00bb signifi\u00e9 que votre programme fonctionne pas, dans ce cas v\u00e9rifiez le programme python.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"544\" src=\"http:\/\/192.168.0.211\/wp-content\/uploads\/2022\/02\/image-4-1024x544.png\" alt=\"\" class=\"wp-image-1556\" srcset=\"https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/02\/image-4-1024x544.png 1024w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/02\/image-4-300x159.png 300w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/02\/image-4-768x408.png 768w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2022\/02\/image-4.png 1268w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>L&rsquo;onglet \u00ab\u00a0log\u00a0\u00bb vous permet de s\u00e9lectionner votre fichier log pr\u00e9c\u00e9demment d\u00e9clar\u00e9 le \u00ab\u00a0.yaml\u00a0\u00bb<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"http:\/\/192.168.0.211\/wp-content\/uploads\/2022\/02\/image-5-1024x351.png\" alt=\"\" class=\"wp-image-1557\"\/><\/figure>\n\n\n\n<p>Le log \u00ab\u00a0main_log\u00a0\u00bb est commun \u00e0 toutes les applications, c&rsquo;est aussi le log par d\u00e9faut.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"http:\/\/192.168.0.211\/wp-content\/uploads\/2022\/02\/image-8.png\" alt=\"\" class=\"wp-image-1563\"\/><\/figure>\n\n\n\n<p>Dans le log \u00ab\u00a0error_log\u00a0\u00bb, vous retrouverez les erreurs de programmation, fonctionnement, etc..<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"http:\/\/192.168.0.211\/wp-content\/uploads\/2022\/02\/image-9-1.png\" alt=\"\" class=\"wp-image-1564\"\/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">Conclusion<\/h1>\n\n\n\n<p>J&rsquo;ai fait le plus simple et le plus d\u00e9taill\u00e9 possible dans l&rsquo;installation et l&rsquo;utilisation de AppDaemon.<\/p>\n\n\n\n<p>Vous l&rsquo;avez compris, \u00e0 travers cet Addon et sa puissance de feu, vous offrez de nombreuses fonctionnalit\u00e9s \u00e0 votre HA.<\/p>\n\n\n\n<p>N&rsquo;h\u00e9sitez pas \u00e0 commenter, vos critiques positives et n\u00e9gatives constructrices seront les bienvenues.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Publication en lien avec cet article:<\/h1>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/domo.rem81.com\/index.php\/2022\/01\/03\/ha-teleinformation-linky-mode-historique\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/domo.rem81.com\/index.php\/2022\/01\/03\/ha-teleinformation-linky-mode-historique\/<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/domo.rem81.com\/index.php\/2022\/02\/02\/ha-gestion-piscine-1-filtration-avec-appdaemon-2\/\">https:\/\/domo.rem81.com\/index.php\/2022\/02\/02\/ha-gestion-piscine-1-filtration-avec-appdaemon-2\/<\/a><\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">R\u00e9f\u00e9rences<\/h1>\n\n\n\n<p>Voici quelques liens qui m&rsquo;ont aid\u00e9 dans la d\u00e9couverte de Appdaemon:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/hassio-addons\/addon-appdaemon\" target=\"_blank\">https:\/\/github.com\/hassio-addons\/addon-appdaemon<\/a><\/li>\n\n\n\n<li><a rel=\"noreferrer noopener\" href=\"https:\/\/appdaemon.readthedocs.io\/en\/latest\/\" target=\"_blank\">https:\/\/appdaemon.readthedocs.io\/en\/latest\/<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/AppDaemon\/appdaemon\/tree\/dev\/conf\/example_apps\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/AppDaemon\/appdaemon\/tree\/dev\/conf\/example_apps<\/a><\/li>\n\n\n\n<li><a rel=\"noreferrer noopener\" href=\"https:\/\/wltd.org\/posts\/how-to-make-complex-automations-with-appdaemon-easily\" target=\"_blank\">https:\/\/wltd.org\/posts\/how-to-make-complex-automations-with-appdaemon-easily<\/a><\/li>\n\n\n\n<li><a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/ReneTode\/My-AppDaemon\/tree\/master\/AppDaemon_for_Beginner\" target=\"_blank\">https:\/\/github.com\/ReneTode\/My-AppDaemon\/tree\/master\/AppDaemon_for_Beginner<\/a><\/li>\n\n\n\n<li><a rel=\"noreferrer noopener\" href=\"https:\/\/appdaemon.readthedocs.io\/en\/latest\/HASS_API_REFERENCE.html#app-creation\" target=\"_blank\">https:\/\/appdaemon.readthedocs.io\/en\/latest\/HASS_API_REFERENCE.html#app-creation<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Intro Dans mes publications, je fais de plus en plus r\u00e9f\u00e9rence \u00e0 des applications \u00e9crites en python dans l&rsquo;addon \u00ab\u00a0Appdaemon\u00a0\u00bb. Il me semblait utile de d\u00e9tailler simplement son installation dans &hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[8,22,33],"class_list":["post-2862","post","type-post","status-publish","format-standard","hentry","category-homeassistant","tag-appdaemon","tag-linky","tag-piscine"],"_links":{"self":[{"href":"https:\/\/domo.rem81.com\/index.php\/wp-json\/wp\/v2\/posts\/2862","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/domo.rem81.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/domo.rem81.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/domo.rem81.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/domo.rem81.com\/index.php\/wp-json\/wp\/v2\/comments?post=2862"}],"version-history":[{"count":3,"href":"https:\/\/domo.rem81.com\/index.php\/wp-json\/wp\/v2\/posts\/2862\/revisions"}],"predecessor-version":[{"id":3127,"href":"https:\/\/domo.rem81.com\/index.php\/wp-json\/wp\/v2\/posts\/2862\/revisions\/3127"}],"wp:attachment":[{"href":"https:\/\/domo.rem81.com\/index.php\/wp-json\/wp\/v2\/media?parent=2862"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/domo.rem81.com\/index.php\/wp-json\/wp\/v2\/categories?post=2862"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/domo.rem81.com\/index.php\/wp-json\/wp\/v2\/tags?post=2862"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}