{"id":4004,"date":"2025-06-02T08:00:00","date_gmt":"2025-06-02T06:00:00","guid":{"rendered":"https:\/\/domo.rem81.com\/?p=4004"},"modified":"2026-03-24T08:58:22","modified_gmt":"2026-03-24T07:58:22","slug":"routeur-solaire-photovoltaique-avec-esphome-une-solution-diy-pour-optimiser-votre-autoconsommation","status":"publish","type":"post","link":"https:\/\/domo.rem81.com\/index.php\/2025\/06\/02\/routeur-solaire-photovoltaique-avec-esphome-une-solution-diy-pour-optimiser-votre-autoconsommation\/","title":{"rendered":"HA-Routeur Solaire Photovolta\u00efque avec ESPHome V2"},"content":{"rendered":"\n\n\n\n<h1 class=\"wp-block-heading\">Intro<\/h1>\n\n\n\n<p>Dans un<a href=\"https:\/\/domo.rem81.com\/index.php\/2023\/07\/18\/pv-routeur-solaire\/\" target=\"_blank\" rel=\"noreferrer noopener\"> article pr\u00e9c\u00e9dent<\/a>, je d\u00e9crivais une deuxieme version de routeur PV d\u00e9velopp\u00e9 sous ESP Home donc compl\u00e8tement int\u00e9gr\u00e9 \u00e0 HA.<\/p>\n\n\n\n<p>Dans cette version le programme a \u00e9t\u00e9 totalement refondu avec un principe de r\u00e9gulation in\u00e9dit.<\/p>\n\n\n\n<p>Vous pouvez que aussi consulter cet <a href=\"https:\/\/domo.rem81.com\/index.php\/2023\/04\/14\/ha-routeur-solaire\/\" data-type=\"link\" data-id=\"https:\/\/domo.rem81.com\/index.php\/2023\/04\/14\/ha-routeur-solaire\/\" target=\"_blank\" rel=\"noreferrer noopener\">article<\/a> d\u00e9crivant une premi\u00e8re version de routeur solaire, vous y trouverez le mat\u00e9riel utilis\u00e9.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Upgrade:<\/h1>\n\n\n\n<ul class=\"wp-block-list\">\n<li>15\/10\/2025: Refonte d&rsquo;une partie du code avec int\u00e9gration des notifications Telegram et s\u00e9paration de la table \u00e9talonnage.<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">Pourquoi un Routeur Solaire ?<\/h1>\n\n\n\n<p>Depuis l\u2019installation de mes panneaux photovolta\u00efques, je cherchais une solution pour maximiser l\u2019utilisation de l\u2019\u00e9nergie produite, plut\u00f4t que de l\u2019injecter dans le r\u00e9seau \u00e0 un tarif d\u00e9risoire (environ 0,10 \u20ac\/kWh en France). Mon objectif : rediriger le surplus d\u2019\u00e9nergie vers mon chauffe-eau \u00e9lectrique pour chauffer l\u2019eau gratuitement. C\u2019est ainsi que j\u2019ai con\u00e7u un <strong>routeur solaire photovolta\u00efque<\/strong> bas\u00e9 sur <strong>ESPHome<\/strong>, un ESP32, et un gradateur AC, qui ajuste pr\u00e9cis\u00e9ment la puissance envoy\u00e9e \u00e0 l\u2019ECS (eau chaude sanitaire). Dans cet article, je vous d\u00e9taille la configuration de mon syst\u00e8me solaire, le fonctionnement du programme ESPHome, les quatre modes de r\u00e9gulation, le calcul de la puissance disponible, et comment l\u2019ECS est aliment\u00e9 en amont sur le grid de l\u2019onduleur.<\/p>\n\n\n\n<p>Un <strong>routeur solaire<\/strong> est un dispositif intelligent qui d\u00e9tecte l\u2019exc\u00e9dent d\u2019\u00e9nergie produit par vos panneaux photovolta\u00efques et le redirige vers un appareil consommateur, comme un chauffe-eau, pour optimiser l\u2019autoconsommation. Avec des tarifs de rachat d\u2019\u00e9lectricit\u00e9 solaire peu attractifs, utiliser directement l\u2019\u00e9nergie produite est bien plus rentable.<\/p>\n\n\n\n<p>Mon routeur solaire, surnomm\u00e9 <strong>esp176_routeur<\/strong>, utilise un ESP32 programm\u00e9 avec ESPHome pour :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Monitorer<\/strong> la production solaire, la consommation domestique, et l\u2019\u00e9tat des batteries via MQTT.<\/li>\n\n\n\n<li><strong>R\u00e9guler<\/strong> la puissance envoy\u00e9e au chauffe-eau en fonction du surplus disponible.<\/li>\n\n\n\n<li><strong>Garantir la s\u00e9curit\u00e9<\/strong> avec des contr\u00f4les de temp\u00e9rature, de production minimale, et d\u2019\u00e9tat de charge.<\/li>\n\n\n\n<li><strong>S\u2019int\u00e9grer \u00e0 Home Assistant<\/strong> pour un suivi en temps r\u00e9el, des r\u00e9glages personnalis\u00e9s, et des notifications Telegram.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Configuration Solaire<\/h1>\n\n\n\n<p>Mon installation photovolta\u00efque est con\u00e7ue pour couvrir une partie de ma consommation domestique tout en stockant l\u2019\u00e9nergie dans des batteries pour une utilisation ult\u00e9rieure. Voici les d\u00e9tails :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Panneaux solaires<\/strong> : Puissance cr\u00eate totale de <strong>7.2 kWc<\/strong>.<\/li>\n\n\n\n<li><strong>Onduleur<\/strong> : Un <strong>Victron MultiPlus II 48\/5000<\/strong>, qui g\u00e8re la conversion DC\/AC, la charge des batteries, et l\u2019injection\/soutirage sur le r\u00e9seau. L\u2019onduleur est connect\u00e9 \u00e0 un <strong>Cerbo GX<\/strong> pour le monitoring et la publication des donn\u00e9es via MQTT.<\/li>\n\n\n\n<li><strong>Batteries<\/strong> : D&rsquo;une capacit\u00e9 totale de <strong>12 kWh<\/strong>, elles permettent de stocker l\u2019exc\u00e9dent pour les p\u00e9riodes sans soleil.<\/li>\n\n\n\n<li><strong>Chauffe-eau (ECS)<\/strong> : Un chauffe-eau \u00e9lectrique de 300 L avec une r\u00e9sistance de <strong>3 kW<\/strong>, aliment\u00e9 <strong>en amont sur le grid de l\u2019onduleur<\/strong> (c\u00f4t\u00e9 r\u00e9seau AC, avant l\u2019onduleur). Cela signifie que l\u2019ECS consomme soit l\u2019\u00e9nergie solaire exc\u00e9dentaire, soit l\u2019\u00e9nergie du r\u00e9seau si n\u00e9cessaire, sous le contr\u00f4le du routeur.<\/li>\n<\/ul>\n\n\n\n<p>Le Cerbo GX publie les donn\u00e9es de l\u2019onduleur (production, consommation, \u00e9tat des batteries) sur un broker MQTT, que l\u2019ESP32 r\u00e9cup\u00e8re pour calculer la puissance \u00e0 injecter dans l\u2019ECS.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Mat\u00e9riel du Routeur Solaire<\/h2>\n\n\n\n<p>Le routeur est construit autour d\u2019un <strong>ESP32 DevKit<\/strong>, choisi pour sa puissance, ses multiples GPIO, et sa compatibilit\u00e9 avec ESPHome. Voici les composants principaux :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Gradateur AC (dimmer)<\/strong> : Pilot\u00e9 via les broches GPIO33 (gate) et GPIO34 (zero-cross), il ajuste la puissance envoy\u00e9e \u00e0 l\u2019ECS de 0 \u00e0 3 kW.<\/li>\n\n\n\n<li><strong>Sonde de temp\u00e9rature Dallas DS18B20<\/strong> : Connect\u00e9e \u00e0 GPIO27, elle mesure la temp\u00e9rature du radiateur pour \u00e9viter la surchauffe.<\/li>\n\n\n\n<li><strong>\u00c9cran LCD 20&#215;4 (PCF8574)<\/strong> : Reli\u00e9 via I2C (GPIO21\/SDA, GPIO22\/SCL), il affiche la puissance r\u00e9seau, la sortie triac, la temp\u00e9rature, et le mode.<\/li>\n\n\n\n<li><strong>Relais<\/strong> : Connect\u00e9 \u00e0 GPIO5, il s\u2019active en cas de surplus important pour alimenter un autre appareil (par exemple, une pompe \u00e0 chaleur).<\/li>\n\n\n\n<li><strong>LEDs<\/strong> : Une LED jaune (GPIO26) indique l\u2019\u00e9tat du routeur, une LED rouge (GPIO25) signale une injection r\u00e9seau.<\/li>\n\n\n\n<li><strong>Alimentation 5V<\/strong> : Alimente l\u2019ESP32 et les composants.<\/li>\n<\/ul>\n\n\n\n<p>Le tout est install\u00e9 dans un bo\u00eetier DIN dans mon tableau \u00e9lectrique, avec une connexion Wi-Fi pour l\u2019int\u00e9gration \u00e0 Home Assistant.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Programme ESPHome : Une R\u00e9gulation Intelligente<\/h1>\n\n\n\n<p>Le c\u0153ur du routeur est un programme <strong>ESPHome<\/strong> qui g\u00e8re la r\u00e9gulation, l\u2019affichage, les logs, et l\u2019int\u00e9gration domotique. Voici une explication d\u00e9taill\u00e9e des \u00e9l\u00e9ments cl\u00e9s.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Les Quatre Modes de Fonctionnement<\/h2>\n\n\n\n<p>Le routeur propose quatre modes, s\u00e9lectionnables via un s\u00e9lecteur dans Home Assistant (<code>select.esp176_mode_fonctionnement_routeur<\/code>) :<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Mode Auto<\/strong> :\n<ul class=\"wp-block-list\">\n<li><strong>Description<\/strong> : Le routeur r\u00e9gule automatiquement la puissance envoy\u00e9e \u00e0 l\u2019ECS en fonction du surplus solaire, tout en respectant des conditions de s\u00e9curit\u00e9 :\n<ul class=\"wp-block-list\">\n<li>Production solaire sup\u00e9rieure au seuil (<code>seuil_prod<\/code>, par exemple 100 W).<\/li>\n\n\n\n<li>\u00c9tat de charge des batteries (SOC) sup\u00e9rieur au seuil (<code>seuil_soc<\/code>, par exemple 50 %).<\/li>\n\n\n\n<li>Temp\u00e9rature du radiateur inf\u00e9rieure au maximum (<code>tmax<\/code>, par exemple 75 \u00b0C).<\/li>\n\n\n\n<li>Routeur valid\u00e9 (<code>switch.esp176_valid_routeur<\/code> activ\u00e9).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Comportement<\/strong> : Si toutes les conditions sont remplies, le script <code>regulation_interpolation<\/code> calcule la puissance disponible (<code>p_dispo<\/code>) et ajuste la sortie du triac (<code>striac<\/code>) via le gradateur. Sinon, le triac est d\u00e9sactiv\u00e9 (<code>striac = 0<\/code>).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Mode Manuel<\/strong> :\n<ul class=\"wp-block-list\">\n<li><strong>Description<\/strong> : Permet de fixer manuellement la sortie du triac (de 0 \u00e0 100 %) via un r\u00e9glage dans Home Assistant (<code>number.esp176_consigne_triac_en_manu<\/code>).<\/li>\n\n\n\n<li><strong>Comportement<\/strong> : Le triac prend la valeur d\u00e9finie, ind\u00e9pendamment de la production ou de l\u2019\u00e9tat des batteries. Utile pour des tests ou pour forcer une chauffe. Le routeur reste s\u00e9curis\u00e9 par la validation (<code>validrouteur<\/code>).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Mode Arr\u00eat<\/strong> :\n<ul class=\"wp-block-list\">\n<li><strong>Description<\/strong> : D\u00e9sactive compl\u00e8tement le routeur.<\/li>\n\n\n\n<li><strong>Comportement<\/strong> : Le triac est mis \u00e0 0, le gradateur est \u00e9teint, et aucune puissance n\u2019est envoy\u00e9e \u00e0 l\u2019ECS. Le mode est publi\u00e9 comme \u00ab OFF \u00bb (<code>text_sensor.esp176_mode_regulation<\/code>).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Mode \u00c9talonnage<\/strong> :\n<ul class=\"wp-block-list\">\n<li><strong>Description<\/strong> : Utilis\u00e9 pour \u00e9tablir une table de correspondance entre la sortie du triac (0 \u00e0 100 %) et la puissance consomm\u00e9e par l\u2019ECS (<code>puecs<\/code>).<\/li>\n\n\n\n<li><strong>Comportement<\/strong> : Le script <code><strong>etalonnage_striac<\/strong><\/code> incr\u00e9mente la sortie du triac par pas de 1 % toutes les 10 secondes, mesure la puissance ECS, et enregistre les donn\u00e9es via l&rsquo;int\u00e9gration \u00ab\u00a0files\u00a0\u00bb de HA. Ces donn\u00e9es alimenteront la table <strong>t<code>able<\/code>_puissanc<\/strong>e pour une r\u00e9gulation pr\u00e9cise.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Calcul de la Puissance Disponible<\/h2>\n\n\n\n<p>Le calcul de la puissance disponible (table_puissance) d\u00e9pend de l\u2019\u00e9tat de charge des batteries, d\u00e9termin\u00e9 par l\u2019\u00e9tat du bus VE (<code>etatbus_ve<\/code>, publi\u00e9 via MQTT) :<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Mode Bulk (etatbus_ve = 3)<\/strong> :\n<ul class=\"wp-block-list\">\n<li>Les batteries sont en charge rapide, et une partie du surplus doit leur \u00eatre r\u00e9serv\u00e9e.<\/li>\n\n\n\n<li>Formule :<code>p_dispo = pu_prod - conso_maison - res_pubatt<\/code>\n<ul class=\"wp-block-list\">\n<li><code>pu_prod<\/code> : Puissance produite par les panneaux solaires (par exemple, 2000 W).<\/li>\n\n\n\n<li><code>conso_maison<\/code> : Consommation domestique (par exemple, 800 W).<\/li>\n\n\n\n<li><code>res_pubatt<\/code> : R\u00e9serve pour les batteries, configurable dans Home Assistant (<code>number.esp176_reserve_charge_batteries<\/code>, par exemple 500 W).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Exemple : Si <code>pu_prod = 2000 W<\/code>, <code>conso_maison = 800 W<\/code>, <code>res_pubatt = 500 W<\/code>, alors <code>p_dispo = 2000 - 800 - 500 = 700 W<\/code>.<\/li>\n\n\n\n<li>La r\u00e9serve (<code>res_pubatt<\/code>) est publi\u00e9e comme consigne de charge (<code>sensor.esp176_cons_batt_en_cours<\/code>).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Mode Absorption (etatbus_ve = 4) ou Float (etatbus_ve = 5)<\/strong> :\n<ul class=\"wp-block-list\">\n<li>Les batteries sont presque pleines ou pleines, et la puissance des batteries (<code>pu_batteries<\/code>) peut \u00eatre n\u00e9gative (d\u00e9charge) ou positive (charge lente).<\/li>\n\n\n\n<li>Formule :<code>p_dispo = pu_prod - conso_maison + pu_batteries<\/code>\n<ul class=\"wp-block-list\">\n<li><code>pu_batteries<\/code> : Puissance des batteries, n\u00e9gative en d\u00e9charge (par exemple, -200 W si les batteries soutiennent la maison).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Exemple : Si <code>pu_prod = 2000 W<\/code>, <code>conso_maison = 800 W<\/code>, <code>pu_batteries = -200 W<\/code>, alors <code>p_dispo = 2000 - 800 + (-200) = 1000 W<\/code>.<\/li>\n\n\n\n<li>La puissance des batteries (n\u00e9gative) est publi\u00e9e comme <code>sensor.esp176_cons_batt_en_cours<\/code>.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Autres \u00e9tats<\/strong> :\n<ul class=\"wp-block-list\">\n<li>Si <code>etatbus_ve<\/code> n\u2019est ni 3, 4, ni 5, alors <code>p_dispo = 0<\/code>, et aucune puissance n\u2019est envoy\u00e9e \u00e0 l\u2019ECS.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<p>La puissance disponible est limit\u00e9e par la puissance maximale du triac (<code>pmax<\/code>, par exemple 3000 W) et convertie en pourcentage de sortie triac (<code>striac<\/code>) via une table de correspondance \u00e9tablie en mode \u00c9talonnage. Une interpolation lin\u00e9aire entre les valeurs de la table (<code>p_dispo_table<\/code>) garantit une r\u00e9gulation pr\u00e9cise.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">S\u00e9curit\u00e9 et Contr\u00f4les<\/h2>\n\n\n\n<p>Le routeur inclut plusieurs s\u00e9curit\u00e9s :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Temp\u00e9rature<\/strong> : La sonde Dallas surveille la temp\u00e9rature du radiateur. Si elle d\u00e9passe <code>tmax<\/code> (par exemple, 75 \u00b0C), le triac est d\u00e9sactiv\u00e9 (<code>temperatureok = false<\/code>).<\/li>\n\n\n\n<li><strong>Production minimale<\/strong> : Le routeur ne s\u2019active que si <code>pu_prod &gt; seuil_prod<\/code> (par exemple, 100 W).<\/li>\n\n\n\n<li><strong>\u00c9tat de charge (SOC)<\/strong> : Un seuil minimal (<code>seuil_soc<\/code>, par exemple 50 %) avec une hyst\u00e9r\u00e9sis de 2 % prot\u00e8ge les batteries.<\/li>\n\n\n\n<li><strong>Relais de surproduction<\/strong> : Si le triac est \u00e0 90 % et que l\u2019ECS consomme moins de 100 W pendant 5 minutes, un relais s\u2019active pour alimenter un autre appareil.<\/li>\n\n\n\n<li><strong>Validation<\/strong> : Le routeur ne fonctionne que si <code>validrouteur<\/code> est activ\u00e9.<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">Affichage LCD<\/h1>\n\n\n\n<p>Un \u00e9cran LCD 20&#215;4 affiche :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Ligne 1<\/strong> : Puissance r\u00e9seau (<code>pureseau1<\/code>) et ECS (<code>puecs<\/code>).<\/li>\n\n\n\n<li><strong>Ligne 2<\/strong> : Sortie triac (<code>striac<\/code>) et \u00e9tat du routeur (<code>validrouteur<\/code> : OK\/NOK).<\/li>\n\n\n\n<li><strong>Ligne 3<\/strong> : Temp\u00e9rature du radiateur (<code>temp_triac<\/code>) et \u00e9tat de la temp\u00e9rature (<code>temperatureok<\/code> : OK\/NOK).<\/li>\n\n\n\n<li><strong>Ligne 4<\/strong> : Mode de fonctionnement (<code>Auto<\/code>, <code>Manu<\/code>, <code>Arret<\/code>, <code>Etalonnage<\/code>).<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">Int\u00e9gration Home Assistant<\/h1>\n\n\n\n<p>Les entit\u00e9s sont expos\u00e9es dans Home Assistant via l\u2019API ESPHome :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Capteurs<\/strong> : <code>sensor.esp176_pu_disponible<\/code>, <code>sensor.esp176_sortie_triac<\/code>, <code>sensor.esp176_pu_reseau<\/code>.<\/li>\n\n\n\n<li><strong>S\u00e9lecteurs<\/strong> : <code>select.esp176_mode_fonctionnement_routeur<\/code>.<\/li>\n\n\n\n<li><strong>Nombres<\/strong> : <code>number.esp176_puissance_max_triac<\/code>, <code>number.esp176_seuil_soc<\/code>.<\/li>\n\n\n\n<li><strong>Interrupteurs<\/strong> : <code>switch.esp176_valid_routeur<\/code>, <code>switch.esp176_relais<\/code>.<\/li>\n<\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Configuration du fichier log:<\/h2>\n\n\n\n<p>Il faut cr\u00e9er une entr\u00e9e dans l\u2019int\u00e9gration \u00ab\u00a0file\u00a0\u00bb, par exemple\u00a0\u00bb\/config\/fichiers\/etalonnage_routeur.csv\u00a0\u00bb<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"945\" height=\"630\" src=\"https:\/\/domo.rem81.com\/wp-content\/uploads\/2025\/06\/image-6.png\" alt=\"\" class=\"wp-image-4160\" srcset=\"https:\/\/domo.rem81.com\/wp-content\/uploads\/2025\/06\/image-6.png 945w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2025\/06\/image-6-300x200.png 300w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2025\/06\/image-6-768x512.png 768w\" sizes=\"auto, (max-width: 945px) 100vw, 945px\" \/><\/figure>\n\n\n\n<p>Vous renommer son id \u00ab\u00a0notify.etalonnage_routeur\u00a0\u00bb<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"493\" height=\"643\" src=\"https:\/\/domo.rem81.com\/wp-content\/uploads\/2025\/06\/image-7.png\" alt=\"\" class=\"wp-image-4161\" srcset=\"https:\/\/domo.rem81.com\/wp-content\/uploads\/2025\/06\/image-7.png 493w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2025\/06\/image-7-230x300.png 230w\" sizes=\"auto, (max-width: 493px) 100vw, 493px\" \/><\/figure>\n\n\n\n<p>Apres etalonnage vous pourrez visualiser le r\u00e9sultat dans le fichier \u00ab\u00a0etalonnage_routeur.csv\u00a0\u00bb et le copier\/coller dans le fichier \u00ab\u00a0table_pu.yaml\u00a0\u00bb.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"523\" height=\"354\" src=\"https:\/\/domo.rem81.com\/wp-content\/uploads\/2025\/06\/image-8.png\" alt=\"\" class=\"wp-image-4162\" srcset=\"https:\/\/domo.rem81.com\/wp-content\/uploads\/2025\/06\/image-8.png 523w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2025\/06\/image-8-300x203.png 300w\" sizes=\"auto, (max-width: 523px) 100vw, 523px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Vue Synoptique de r\u00e9gulation<\/h2>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"416\" height=\"304\" src=\"https:\/\/domo.rem81.com\/wp-content\/uploads\/2025\/06\/image-1.png\" alt=\"\" class=\"wp-image-4023\" srcset=\"https:\/\/domo.rem81.com\/wp-content\/uploads\/2025\/06\/image-1.png 416w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2025\/06\/image-1-300x219.png 300w\" sizes=\"auto, (max-width: 416px) 100vw, 416px\" \/><\/figure>\n\n\n\n<p>Code: <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>type: picture-elements\nelements:\n  - entity: sensor.esp176_esp32_routeur_1r_mode_regulation\n    prefix: \"Regul \"\n    style:\n      background: null\n      color: white\n      font-size: 120%\n      left: 5%\n      top: 5%\n      transform: none\n    type: state-label\n  - entity: sensor.mp2_affichage_status_bus_ve\n    prefix: \"Bus Ve= \"\n    style:\n      background: null\n      color: white\n      font-size: 120%\n      left: 60%\n      top: 5%\n      transform: none\n    type: state-label\n  - entity: sensor.esp176_esp32_routeur_1r_pu_disponible\n    style:\n      background: none\n      color: white\n      font-size: 100%\n      left: 47%\n      top: 31%\n      transform: none\n    type: state-label\n    prefix: \"P= \"\n  - entity: sensor.esp176_esp32_routeur_1r_cons_batt_en_cours\n    prefix: \"Bat= \"\n    style:\n      background: null\n      color: white\n      font-size: 100%\n      left: 0%\n      top: 46%\n      transform: none\n    type: state-label\n  - entity: sensor.esp176_routeur_sortie_triac\n    prefix: \"\"\n    style:\n      background: null\n      color: white\n      font-size: 100%\n      left: 85%\n      top: 31%\n      transform: none\n    type: state-label\n  - entity: sensor.esp176_esp32_routeur_1r_p_ecs_jsymk\n    prefix: \"ECS: \"\n    type: state-label\n    style:\n      background: null\n      color: white\n      font-size: 100%\n      left: 47%\n      top: 48%\n      transform: none\n  - entity: sensor.mp2_prod_totale_mqtt\n    prefix: \"Prod= \"\n    type: state-label\n    style:\n      background: null\n      color: white\n      font-size: 100%\n      left: 0%\n      top: 26%\n      transform: none\n  - entity: sensor.mp2_conso_out1_mqtt\n    prefix: \"Mais= \"\n    type: state-label\n    style:\n      background: null\n      color: white\n      font-size: 100%\n      left: 0%\n      top: 36%\n      transform: none\n  - entity: sensor.esp176_routeur_temp_triac\n    prefix: \"T\u00b0 Triac= \"\n    type: state-label\n    style:\n      background: null\n      color: white\n      font-size: 100%\n      left: 70%\n      top: 60%\n      transform: none\n  - entity: sensor.esp126_temp_ecs\n    prefix: \"T\u00b0 ECS= \"\n    type: state-label\n    style:\n      background: null\n      color: white\n      font-size: 100%\n      left: 70%\n      top: 70%\n      transform: none\nimage: \/local\/images\/pid_routeur_v4.png<\/code><\/pre>\n\n\n\n<p>Fichier image: <a href=\"https:\/\/github.com\/remycrochon\/home-assistant\/tree\/master\/www\/images\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/remycrochon\/home-assistant\/tree\/master\/www\/images<\/a><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Alimentation de l\u2019ECS<\/h1>\n\n\n\n<p>L\u2019ECS est aliment\u00e9 <strong>en amont sur le grid de l\u2019onduleur<\/strong>, c\u2019est-\u00e0-dire sur le r\u00e9seau AC avant l\u2019entr\u00e9e de l\u2019onduleur MultiPlus II. Cela signifie que :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>L\u2019ECS peut consommer l\u2019\u00e9nergie solaire exc\u00e9dentaire g\u00e9r\u00e9e par le routeur.<\/li>\n\n\n\n<li>Si le surplus solaire est insuffisant, l\u2019ECS tire l\u2019\u00e9nergie du r\u00e9seau public.<\/li>\n\n\n\n<li>Le routeur ajuste la puissance via le gradateur pour minimiser le soutirage r\u00e9seau, en s\u2019appuyant sur les donn\u00e9es de l\u2019onduleur (publi\u00e9es via MQTT).<\/li>\n<\/ul>\n\n\n\n<p>Cette configuration garantit une int\u00e9gration fluide avec l\u2019onduleur, qui priorise l\u2019alimentation de la maison et des batteries avant de laisser le surplus \u00e0 l\u2019ECS.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Installation et Mise en Route<\/h1>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Assemblage<\/strong> : Connectez l\u2019ESP32, le gradateur, la sonde Dallas, l\u2019\u00e9cran LCD, et le relais dans un bo\u00eetier DIN.<\/li>\n\n\n\n<li><strong>C\u00e2blage<\/strong> : Branchez le gradateur \u00e0 l\u2019ECS, la sonde au radiateur, et le relais \u00e0 un consommateur secondaire. Assurez-vous que l\u2019ECS est connect\u00e9e en amont de l\u2019onduleur.<\/li>\n\n\n\n<li><strong>Firmware<\/strong> : Flashez l\u2019ESP32 avec le YAML ESPHome, en ajustant les secrets (Wi-Fi, MQTT) et l\u2019IP statique (par ex 192.168.0.176).<\/li>\n\n\n\n<li><strong>Configuration Home Assistant<\/strong> : Ajoutez l\u2019appareil ESPHome et r\u00e9glez les seuils (<code>pmax<\/code>, <code>tmax<\/code>, <code>seuil_soc<\/code>, <code>seuil_prod<\/code>, <code>res_pubatt<\/code>).<\/li>\n\n\n\n<li><strong>\u00c9talonnage<\/strong> : Lancez le mode \u00c9talonnage pour g\u00e9n\u00e9rer la table de correspondance, puis passez en mode Auto.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">R\u00e9sultats et Perspectives<\/h1>\n\n\n\n<p>Depuis son installation, le routeur a boost\u00e9 mon autoconsommation. Par une belle journ\u00e9e, je redirige jusqu\u2019\u00e0 <strong>3 kW<\/strong> de surplus vers l\u2019ECS, r\u00e9duisant l\u2019injection r\u00e9seau \u00e0 presque z\u00e9ro. Le relais de surproduction s\u2019active occasionnellement il n&rsquo;est pas utilis\u00e9 actuellement.<\/p>\n\n\n\n<p>Voici une vue Graphana, vous pouvez constater la r\u00e9activit\u00e9 du routeur: la puissance ECS suit de tr\u00e8s pr\u00eat la puissance disponible!<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1010\" height=\"450\" src=\"https:\/\/domo.rem81.com\/wp-content\/uploads\/2025\/06\/image-9.png\" alt=\"\" class=\"wp-image-4164\" srcset=\"https:\/\/domo.rem81.com\/wp-content\/uploads\/2025\/06\/image-9.png 1010w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2025\/06\/image-9-300x134.png 300w, https:\/\/domo.rem81.com\/wp-content\/uploads\/2025\/06\/image-9-768x342.png 768w\" sizes=\"auto, (max-width: 1010px) 100vw, 1010px\" \/><\/figure>\n\n\n\n<p>Quelques id\u00e9es d\u2019am\u00e9lioration :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ajouter un capteur de temp\u00e9rature d\u2019eau pour arr\u00eater le routeur quand l\u2019ECS est chaude.<\/li>\n\n\n\n<li>Int\u00e9grer des pr\u00e9visions m\u00e9t\u00e9o pour anticiper la production.<\/li>\n\n\n\n<li>Ajouter un second gradateur pour un autre appareil.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Conclusion<\/h1>\n\n\n\n<p>Ce routeur solaire DIY, bas\u00e9 sur ESPHome et un ESP32, est une solution puissante pour maximiser l\u2019autoconsommation photovolta\u00efque. Avec ses quatre modes de fonctionnement, ses s\u00e9curit\u00e9s, et son int\u00e9gration \u00e0 Home Assistant, il offre une flexibilit\u00e9 et une efficacit\u00e9 remarquables. Si vous avez une installation solaire avec un onduleur Victron et un chauffe-eau, ce projet est parfait pour vous !<\/p>\n\n\n\n<p>Partagez vos retours ou vos propres projets dans les commentaires ou sur le forum Home Assistant. <\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Annexes :<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Codes ESPHome:<\/h2>\n\n\n\n<p>Le dernier code \u00e0 jour est disponibles ici: <a href=\"https:\/\/github.com\/remycrochon\/home-assistant\/blob\/master\/esphome\/esp176-routeur.yaml\">https:\/\/github.com\/remycrochon\/home-assistant\/blob\/master\/esphome\/esp176-routeur.yaml<\/a><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>substitutions:\n  device_name: \"esp176_routeur\"\n  friendly_name: esp176\n  adress_ip: \"192.168.0.176\"\n  time_timezone: \"Europe\/Paris\"\n  # Affectation des GPIO\n  GPIO_onewire: \"GPIO27\"\n  GPIO_sda: \"GPIO21\"\n  GPIO_scl: \"GPIO22\"\n  GPIO_tx: \"GPIO17\"\n  GPIO_rx: \"GPIO16\"  \n  GPIO_Led_jaune: \"GPIO26\"\n  GPIO_Led_rouge: \"GPIO25\"\n  GPIO_Led_status: \"GPIO32\"\n  GPIO_Relais: \"GPIO5\"\n  # Dimmer\n  GPIO_Gate_pin: \"GPIO33\"\n  GPIO_ZC_pin: \"GPIO34\"\n\n\npackages:\n  jsk: !include pack_esp176\/jsk.yaml\n  table_pu: !include pack_esp176\/table_pu.yaml\n\nesphome:\n  name: ${device_name}\n  on_boot:\n    priority: -100\n    # Force mode auto et tempok au demarrage\n    then: \n      - binary_sensor.template.publish:\n          id: temperatureok\n          state: ON\n\nesp32:\n  board: esp32dev\n  framework:\n    type: arduino\n    \nwifi:\n  networks:\n    - ssid: !secret wifi_esp\n      password: !secret mdpwifi_esp\n  reboot_timeout: 5min\n\n  manual_ip:\n    static_ip: ${adress_ip}\n    gateway: 192.168.0.254\n    subnet: 255.255.255.0\n    dns1: !secret dns1\n    dns2: !secret dns2\n    \n    \n# Utilisez la LED bleue de l'appareil comme LED d'\u00e9tat, qui clignotera s'il y a des avertissements (lent) ou des erreurs (rapide)\nstatus_led:\n  pin:\n    number: ${GPIO_Led_status} # led jaune\n    inverted: true\n\n# Enable logging\nlogger:\n  baud_rate: 0\n  level: info\n\n#    modbus.component: INFO\n# Enable Home Assistant API\napi:\n\nota:\n  platform: esphome\nweb_server:\n  port: 80\n  version: 3\n\ntime:\n  - platform: sntp\n    id: sntp_time\n    timezone: Europe\/Paris\n    servers:\n     - 0.pool.ntp.org\n     - 1.pool.ntp.org\n     - 2.pool.ntp.org  \n\n# Protocole I2C\ni2c:\n  sda: ${GPIO_sda}\n  scl: ${GPIO_scl}\n  scan: True\n  id: bus_a\n  frequency: 400kHz\n\n# Mosquitto Proxmox\nmqtt:\n  broker: 192.168.0.37\n  username: !secret mqtt_ha_name\n  password: !secret mqtt_ha_pw\n  #internal_mqtt_default: internal\n\nglobals:\n  - id: p_dispo\n    type: float\n    restore_value: no\n    initial_value: '0'\n  - id: regul\n    type: std::string\n    restore_value: no\n    initial_value: '\"Pas de r\u00e9gulation\"'\n  - id: striac\n    type: float\n    restore_value: no\n    initial_value: '0'\n\n  # stocke temporairement le message \u00e0 envoyer \u00e0 telegram\n  - id: telegram_msg_buffer\n    type: std::string\n    restore_value: no\n    initial_value: '\"\"'\n\n#\u00a0Sonde Temperature Dallas\none_wire:\n  - platform: gpio  \n    pin: ${GPIO_onewire}\n\n# d\u00e9claration des modes de fonctionnement dans des \"input select\"\nselect:\n  - platform: template\n    name: \"Mode_Fonctionnement_routeur\"\n    optimistic: true\n    restore_value: true\n    options:\n      - Auto\n      - Manu\n      - Arret\n      - Etalonnage\n    id: _Mode_Fonctionnement_routeur\n    on_value: \n      then:\n        - lambda: |-\n            char mess&#091;128];\n            snprintf(mess, sizeof(mess), \"Mode Fonctionnement Routeur: %s\", id(_Mode_Fonctionnement_routeur).state.c_str());\n            ESP_LOGI(\"fichier\", \"Message: %s\", mess);\n            id(_log_fichier).execute(mess);  \/\/ Appelle le script _log_fichier avec le param\u00e8tre mess      \n        # Passage en mode \u00e9talonnage\n        - if:\n            condition:\n              - lambda: 'return id(_Mode_Fonctionnement_routeur).state == \"Etalonnage\";'\n            then:\n              - script.execute: etalonnage_striac\n        # Passage en mode Manu on remet \u00e0 Zero le valid Routeur et la consigne Manu\n        - if:\n            condition:\n              - lambda: 'return id(_Mode_Fonctionnement_routeur).state == \"Manu\";'\n            then:\n              - lambda: |-\n                  id(ctriac_manu).publish_state(0);\n              - switch.turn_off: validrouteur\n        # Passage dans tous les modes on met \u00e0 z\u00e9ro le triac\n        - lambda: |-\n            id(striac) = 0;\n        - light.turn_off:\n            id: gradateur\n        - script.execute: calcul_injection        \n\nbinary_sensor:\n  #Etat de la connection\n    - platform: status\n      name: \"Status\"\n  \n    - platform: template\n      name: \"Temp Ok\"\n      id: temperatureok\n  \n    - platform: template\n      name: \"Seuil Prod Ok\"\n      id: seuil_prod_ok\n\n    - platform: template\n      name: \"Seuil SOC Ok\"\n      id: seuil_soc_ok\n  \n# Input Number\nnumber:\n  # seuil SOC validation routeur\n  - platform: template\n    name: \"Consigne Triac en manu\"\n    id: ctriac_manu\n    optimistic: true\n    restore_value: true\n    mode: box\n    min_value: 0\n    max_value: 100\n    unit_of_measurement: \"%\"\n    step: 1\n    icon: mdi:arrow-collapse-vertical\n\n  # Max sortie triac\n  - platform: template\n    name: \"Puissance Max Triac\"\n    id: pmax\n    optimistic: true\n    restore_value: true\n    mode: box\n    min_value: 10\n    max_value: 3000\n    unit_of_measurement: \"W\"\n    step: 1\n    icon: mdi:arrow-collapse-vertical\n\n  # Seuil MAX temperature\n  - platform: template\n    name: \"T Max\"\n    id: tmax\n    optimistic: true\n    restore_value: true\n    mode: box\n    min_value: 0\n    max_value: 75\n    unit_of_measurement: \"C\u00b0\"\n    step: 0.1\n    icon: mdi:arrow-collapse-vertical\n\n  # Consigne R\u00e9gul sur Puissance Batteries en mode Bulk\n  - platform: template\n    name: \"Reserve Charge Batteries\"\n    id: res_pubatt\n    optimistic: true\n    restore_value: true\n    mode: box\n    min_value: 0\n    max_value: 2500\n    unit_of_measurement: \"W\"\n    step: 1\n    icon: mdi:arrow-collapse-vertical\n\n  # seuil SOC validation routeur\n  - platform: template\n    name: \"Seuil SOC\"\n    id: seuil_soc\n    optimistic: true\n    restore_value: true\n    mode: box\n    min_value: 0\n    max_value: 100\n    unit_of_measurement: \"%\"\n    step: 1\n    icon: mdi:arrow-collapse-vertical\n\n  # seuil Production Photovoltaique de validation routeur \n  - platform: template\n    name: \"Seuil Production Val Routeur\"\n    id: seuil_prod\n    optimistic: true\n    restore_value: true\n    mode: box\n    min_value: 100\n    max_value: 3000\n    unit_of_measurement: \"W\"\n    step: 1\n    icon: mdi:arrow-collapse-vertical\n\nsensor:\n  - platform: wifi_signal # Reports the WiFi signal strength\/RSSI in dB\n    name: \"WiFi Signal dB\"\n    id: wifi_signal_db\n    update_interval: 60s\n    entity_category: \"diagnostic\"\n\n  - platform: copy # Reports the WiFi signal strength in %\n    source_id: wifi_signal_db\n    name: \"WiFi Signal Percent\"\n    filters:\n      - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);\n    unit_of_measurement: \"Signal %\"\n    entity_category: \"diagnostic\"\n    device_class: \"\"\n    \n  ############### TEMPLATE  ######################\"\n  # Affichage dans HA et sur l'afficheur\n  # Puissance lue par le JSk- N\u00e9gative en injection\/Positive en soutirage\n  - platform: template\n    name: \"Pu Reseau\"\n    id: pureseau1\n    unit_of_measurement: \"W\"\n    state_class: \"measurement\"\n    accuracy_decimals: 0\n  # Sortie triac de 0\u00e0100%\n  - platform: template\n    name: \"Sortie Triac\"\n    id: afstriac\n    unit_of_measurement: \"%\"\n    state_class: \"measurement\"  \n    accuracy_decimals: 2\n  # Pu disponible\n  - platform: template\n    name: \"Pu Disponible\"\n    id: afpdispo\n    unit_of_measurement: \"W\"\n    state_class: \"measurement\"\n    accuracy_decimals: 0\n\n  # Sensor Intermediaire pour synoptique\n  - platform: template\n    name: \"Cons batt en Cours\"\n    id: cons_batt_cours\n    state_class: \"measurement\"\n    unit_of_measurement: \"W\"\n    accuracy_decimals: 0\n\n  # Les MQTT sont d\u00e9clar\u00e9s dans le Node Red du Cerbo GX\n  # https:\/\/venus.local:1881\/#flow\/dbd727f16cbe7b5f\n\n  - platform: mqtt_subscribe\n    name: \"Conso Maison\"\n    id: conso_maison\n    topic: mp2\/multiplus2\/conso_out1\n    unit_of_measurement: \"W\"\n    state_class: \"measurement\"  \n    accuracy_decimals: 2\n    filters:\n      - sliding_window_moving_average:\n          window_size: 10\n          send_every: 1\n\n  - platform: mqtt_subscribe\n    name: \"Pu batterie\"\n    id: pu_batteries\n    topic: mp2\/batteries\/puissance\n    unit_of_measurement: \"W\"\n    state_class: \"measurement\"  \n    accuracy_decimals: 2\n    filters:\n      - sliding_window_moving_average:\n          window_size: 10\n          send_every: 1\n        \n  - platform: mqtt_subscribe\n    name: \"Pu Produite\"\n    id: pu_prod\n    topic: mp2\/multiplus2\/prod_totale\n    unit_of_measurement: \"W\"\n    state_class: \"measurement\"  \n    accuracy_decimals: 2\n    filters:\n      - sliding_window_moving_average:\n          window_size: 10\n          send_every: 1\n\n  - platform: mqtt_subscribe\n    name: \"Soc\"\n    id: soc\n    topic: mp2\/batteries\/soc\n    unit_of_measurement: \"%\"\n    state_class: \"measurement\"  \n    accuracy_decimals: 2\n    filters:\n      - sliding_window_moving_average:\n          window_size: 10\n          send_every: 1\n          \n  - platform: mqtt_subscribe\n    name: \"Etat Bus VE\"\n    id: etatbus_ve\n    topic: mp2\/multiplus2\/etatbusve\n    accuracy_decimals: 0\n\n  # lecture sensor Home Assistant\n  - platform: homeassistant\n    name: \"Status Bus VE\"\n    entity_id: sensor.mp2_status_bus_ve\n    id: statusbusve\n\n  - platform: homeassistant\n    name: \"Tarif Num\"\n    entity_id: sensor.linky_n_tarif\n    id: hc\n  - platform: homeassistant\n    name: \"Pu Clim\"\n    entity_id: sensor.ecocompteur_clim\n    id: pu_clim\n\n  # Sonde Temperature radiateur\n  - platform: dallas_temp\n    address: 0xeb012112e461b128\n    name: \"Temp triac\"\n    id: temp_triac\n    update_interval: 60s\n    filters:\n      - filter_out: NAN\n \n# d\u00e9claration des \"text_sensors\"\ntext_sensor:\n  - platform: template\n    name: \"Mode Regulation\"\n    id: moderegul\n      \nswitch:\n  - platform: gpio\n    name: \"Relais\"\n    pin: ${GPIO_Relais}\n    id: relais\n\n  - platform: template\n    name: \"Valid Routeur\"    \n    id: validrouteur\n    optimistic: true\n    restore_mode: always_on\n\n  - platform: restart\n    name: \"Restart\"\n\noutput:\n  #LEDS --------------------------------------\n  - id: led_jaune\n    platform: gpio\n    pin: ${GPIO_Led_jaune} \n\n  - id: led_rouge\n    platform: gpio\n    pin: ${GPIO_Led_rouge}\n\n  # Pilotage du Dimmer\n  - platform: ac_dimmer\n    id: ecs\n    gate_pin: ${GPIO_Gate_pin}\n    method: leading\n    zero_cross_pin:\n      number: ${GPIO_ZC_pin} \n      mode:\n        input: true\n      inverted: yes\n    min_power: 5%\n\nlight:\n  - platform: monochromatic\n    name: \"STriac\"\n    output: ecs\n    id: gradateur\n    default_transition_length: 50ms\n\n  # Affichage\ndisplay:\n  - platform: lcd_pcf8574\n    dimensions: 20x4\n    address: 0x27\n    update_interval: 20s  # Plus espac\u00e9 pour all\u00e9ger la charge CPU\n    lambda: |-\n      char ligne0&#091;21];\n      char ligne1&#091;21];\n      char ligne2&#091;21];\n      char ligne3&#091;21];\n\n      snprintf(ligne0, sizeof(ligne0), \"Pr=%0.0fW Pe=%0.0fW\", id(pureseau1).state, id(puecs).state);\n      snprintf(ligne1, sizeof(ligne1), \"Tr=%0.1f%% V:%s\", id(striac), id(validrouteur).state ? \"OK\" : \"NOK\");\n      snprintf(ligne2, sizeof(ligne2), \"Tp=%0.1fc E:%s\", id(temp_triac), id(temperatureok).state ? \"OK\" : \"NOK\");\n      snprintf(ligne3, sizeof(ligne3), \"Mode:%s\", id(_Mode_Fonctionnement_routeur).state.c_str());\n\n      it.print(0, 0, ligne0);\n      it.print(0, 1, ligne1);\n      it.print(0, 2, ligne2);\n      it.print(0, 3, ligne3);\n\ninterval:\n  - interval: 1s\n    then:\n      - script.execute: calcul_injection\n \n  - interval: 5s\n    then:      \n      - script.execute: etat_production\n      - script.execute: calcul_relais_surprod      \n\n ########################################################################\"\"\nscript:\n  # Calcul du niveau de puissance \u00e0 injecter dans le triac pilotant l'ECS\n  # En Auto: Conditions Initales de D\u00e9marrage:\n                                              # Mode de Fct=Auto\n                                              # Seuil Prod Ok\n                                              # Seuil SOC Ok\n                                              # temp Triac Ok\n                                              # Routeur Valid\u00e9\n  - id: calcul_injection\n    mode: single\n    then:\n      - lambda: |-\n          \/\/  Pu production > Seuil de production\n          id(seuil_prod_ok).publish_state(id(pu_prod).state > id(seuil_prod).state);\n\n          \/\/ # Seuil de SOC (avec hysteresis de 2 %)\n          if (id(soc).state >= id(seuil_soc).state) {\n            id(seuil_soc_ok).publish_state(true);\n          } else if (id(soc).state &lt; (id(seuil_soc).state - 2)) {\n            id(seuil_soc_ok).publish_state(false);\n          }\n\n          \/\/ Surveille temp\u00e9rature triac\n          if (id(temp_triac).state &lt; (id(tmax).state - 2)) {\n            id(temperatureok).publish_state(true);\n          } else if (id(temp_triac).state >= id(tmax).state) {\n            id(temperatureok).publish_state(false);\n          }\n          \/\/ Log de d\u00e9bug\n          \/\/ ESP_LOGI(\"regulp\", \"P Prod; %.0f Seuil: %.2f\",id(pu_prod).state,id(seuil_prod).state);\n\n      # Si conditions non Ok alors RAZ du Triac\n      - if:\n          condition:\n            or:\n              # Cas 1 : Mode Arret ==> OFF\n              - lambda: 'return id(_Mode_Fonctionnement_routeur).state == \"Arret\";'\n\n              # Cas 2 : Mode auto avec conditions NOK => OFF\n              - and:\n                  - lambda: 'return id(_Mode_Fonctionnement_routeur).state == \"Auto\";'\n                  - or:\n                      - switch.is_off: validrouteur\n                      - binary_sensor.is_off: temperatureok\n                      - binary_sensor.is_off: seuil_prod_ok\n                      - binary_sensor.is_off: seuil_soc_ok\n          then:\n            - lambda: |-\n                id(striac) = 0;\n                id(moderegul).publish_state(\"OFF\");\n                id(afpdispo).publish_state(0);\n                id(cons_batt_cours).publish_state(0);\n                \n            - light.turn_off: gradateur\n            - logger.log:\n                format: \"R\u00e9gulation OFF - Mode: %s - Striac: %.1f\"\n                args: &#091;'id(moderegul).state.c_str()', 'id(striac)']\n                level: DEBUG\n      # Si toutes les conditions OK alors on calcule la S triac\n      - if:\n          condition:\n            and:\n              # Cas 3 : Mode auto + toutes les conditions OK => PID actif\n              - lambda: 'return id(_Mode_Fonctionnement_routeur).state == \"Auto\";'\n              - switch.is_on: validrouteur\n              - binary_sensor.is_on: seuil_prod_ok\n              - binary_sensor.is_on: temperatureok\n              - binary_sensor.is_on: seuil_soc_ok\n          then:\n            # Vers script de r\u00e9gulation\n            - script.execute: regulation_interpolation\n\n            - light.turn_on:\n                id: gradateur\n                brightness: !lambda |-\n                  return id(striac) \/ 100;\n              \n      # Mode Manuel\n      - if:\n          condition:\n            and:\n              - lambda: 'return id(_Mode_Fonctionnement_routeur).state == \"Manu\";'\n              - switch.is_on: validrouteur\n\n          then:\n            - lambda: |-\n                \/\/ Application de striac avec s\u00e9curit\u00e9\n                id(striac) = id(ctriac_manu).state;\n\n                \/\/ Publication des \u00e9tats\n                id(afpdispo).publish_state(0);\n                id(moderegul).publish_state(\"Manu\");\n                id(cons_batt_cours).publish_state(0);\n\n            - light.turn_on:\n                id: gradateur\n                brightness: !lambda |-\n                  return id(striac) \/ 100;\n\n      # Affichage STriac\n      - lambda: |-\n            id(afstriac).publish_state( id(striac)) ;\n  \n  ########################################################################\"\"\n  # Principe de la r\u00e9gulation:\n  # Si Bus Ve en Bulk:, on partage le surplus entre la batterie (cons_batt) et l'ECS\n  #   P Dispo= Prod-Conso Maison-Reserve batteries\n  # Si Bus Ve en Absortion ou Float, cela signifie que la batterie est charg\u00e9e, alors:\n  #  P Dispo= Prod-Conso Maison-Pu batteries (Negative en d\u00e9charge)\n  # Sinon:\n  #   P Dispo = 0\n  # La sortie triac est calcul\u00e9e en fonction de la P_Dispo en recherchant sa valeur dans la table de correspondance \u00e9tablie en mode \u00e9talonnage\n  - id: regulation_interpolation\n    mode: single\n    then:\n       - lambda: |-\n          float result = 0.0;\n\n          \/\/ S\u00e9lection de Consigne et Mesure\n          if (id(etatbus_ve).state == 3) {\n            id(p_dispo) = id(pu_prod).state - id(conso_maison).state - id(pu_clim).state - id(res_pubatt).state;\n            if (id(p_dispo) &lt; 0.0) id(p_dispo) = 0.0;\n            id(cons_batt_cours).publish_state(id(res_pubatt).state);\n            id(regul) = \"Sur Pu batteries Bulk\";\n          } else if ((id(etatbus_ve).state == 4) || (id(etatbus_ve).state == 5)) {\n            id(p_dispo) = id(pu_prod).state - id(conso_maison).state - id(pu_clim).state + id(pu_batteries).state;\n            if (id(p_dispo) &lt; 0.0) id(p_dispo) = 0.0;\n            id(cons_batt_cours).publish_state(id(pu_batteries).state * -1);\n            id(regul) = \"Sur P Batt Absord\/Float\";\n          } else {\n            id(regul) = \"Pas de r\u00e9gulation\";\n            id(cons_batt_cours).publish_state(0);\n            id(p_dispo) = 0;\n          }\n\n          \/\/ Limite P dispo\n          id(p_dispo) = constrain(id(p_dispo), 0.0f, id(pmax).state);\n\n          \/\/ Interpolation dans la table\n          float striac_f = 0.0f;\n\n          for (size_t i = 1; i &lt; id(table_puissance).size(); i++) {\n            float x0 = id(table_puissance)&#091;i-1].first;   \/\/ % Triac\n            float y0 = id(table_puissance)&#091;i-1].second;  \/\/ Puissance\n            float x1 = id(table_puissance)&#091;i].first;\n            float y1 = id(table_puissance)&#091;i].second;\n\n            if (id(p_dispo) &lt;= y1) {\n              striac_f = x0 + (id(p_dispo) - y0) * (x1 - x0) \/ (y1 - y0);\n              break;\n            }\n            striac_f = x1;\n          }\n\n          \/\/ S\u00e9curit\u00e9\n          if (isnan(striac_f)) striac_f = 0.0;\n          id(striac) = constrain(striac_f, 0.0f, 100.0f);\n\n          \/\/ Publication\n          id(afpdispo).publish_state(id(p_dispo));\n          id(moderegul).publish_state(id(regul));\n\n          ESP_LOGI(\"regul\", \"p_dispo: %.2f, pu_prod: %.2f, conso_maison: %.2f, pu_clim: %.2f, pu_batt: %.2f, STriac: %.2f\",\n            id(p_dispo), id(pu_prod).state, id(conso_maison).state, id(pu_clim).state, id(cons_batt_cours).state, id(striac));\n  ########################################################################\"\"\n    # Mode Etalonnage Increment S Triac toutes les 20 s pour laisser du temps \u00e0 la puissance pour se stabiliser\n  - id: etalonnage_striac\n    mode: restart  \n    then:\n\n      - lambda: |-\n          id(striac) = 0.0;\n      - while:\n          condition:\n            lambda: 'return id(striac) &lt; 100.0;'  # S'arr\u00eate apr\u00e8s striac = 100\n          then:\n            - lambda: |-\n                id(striac) += 1.0; \/\/ Incr\u00e9mente striac\n                ESP_LOGI(\"striac\", \"Valeur striac: %.2f\", id(striac));\n            - light.turn_on:\n                id: gradateur\n                brightness: !lambda 'return id(striac) \/ 100.0;'  # Normalise entre 0.0 et 1.0\n\n            - delay: 20s  # Temporisation\n\n            - lambda: |-\n                ESP_LOGI(\"striac\", \"Valeur striac: %.2f Pu ECS %.0f\", id(striac), id(puecs).state);            \n\n            - lambda: |-\n                std::string mess = \"{\";\n                mess += std::to_string(id(striac)) + \",\";\n                mess += std::to_string(id(puecs).state)+\"}\";\n                ESP_LOGI(\"fichier\", \"Message: %s\", mess.c_str());\n                id(_log_etalonnage).execute(mess);  \/\/ Appelle le script _log_message avec le param\u00e8tre mess\n\n      - lambda: |-\n          ESP_LOGI(\"striac\", \"Fin de l'\u00e9talonnage, striac = %.2f\", id(striac));\n\n  ########################################################################\"\"\n    # ------------  Pilotage led\n  - id: etat_production\n    mode: single\n    then:\n      - if: \n          condition:\n            sensor.in_range:\n              id: pureseau1\n              below: -50\n          then:\n            - output.turn_on: led_rouge\n          else:\n            - output.turn_off: led_rouge\n            \n      - if: \n          condition:\n            switch.is_on: validrouteur\n          then:\n            - output.turn_on: led_jaune\n          else:\n            - output.turn_off: led_jaune\n \n ########################################################################\"\"\n  - id: calcul_relais_surprod\n    mode: single\n    then:\n     # Si sortie triac > 20 et Pu ECS >10, signifie que le triac est sans effet, pendant plus de 60s et que\n     # la temp\u00e9rature de l'ECS a atteint son max (Thermostat de l'ECS d\u00e9clench\u00e9)\n     # alors on active le relais\n     # si Pu ECS > 10 alors on desactive le relais\n      - if: \n          condition:\n            - lambda: 'return (id(striac)>=90 &amp;&amp; id(puecs).state&lt;10);'\n          then:\n            - delay: 300s\n            - switch.turn_on: relais\n            - logger.log: \"Relais Activ\u00e9\"\n\n      - if: \n          condition:\n            - lambda: 'return id(puecs).state >= 10;'\n          then:\n            - switch.turn_off: relais\n            - logger.log: \"Relais D\u00e9sactiv\u00e9\"\n \n ########################################################################\"\"\n  - id: _log_fichier\n    parameters:\n      mess1: std::string  # Type explicite pour ESPHome\n    then:\n      - lambda: |-\n          std::string mess = mess1;  \/\/ Utilise directement mess1 sans horodatage\n          id(telegram_msg_buffer) = mess;\n          ESP_LOGI(\"log_message\", \"Telegram buffer: %s\", id(telegram_msg_buffer).c_str());\n      - homeassistant.service:                \n          action: notify.send_message\n          data:\n            entity_id: notify.log_esp176\n            message: !lambda 'return id(telegram_msg_buffer).c_str();'\n########################################################################\"\"\n  - id: _log_etalonnage\n    parameters:\n      mess1: std::string  # Type explicite pour ESPHome\n    then:\n      - lambda: |-\n          std::string mess = mess1;  \/\/ Utilise directement mess1 sans horodatage\n          id(telegram_msg_buffer) = mess;\n          ESP_LOGI(\"log_message\", \"Telegram buffer: %s\", id(telegram_msg_buffer).c_str());\n      - homeassistant.service:                \n          action: notify.send_message\n          data:\n            entity_id: notify.etalonnage_routeur\n            message: !lambda 'return id(telegram_msg_buffer).c_str();'            <\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Code du fichier \u00ab\u00a0jsk.yaml\u00a0\u00bb<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code># Protocole du JSK\nuart:\n  id: mod_bus\n  tx_pin: ${GPIO_tx} #17\n  rx_pin: ${GPIO_rx} #16\n  baud_rate: 38400\n  stop_bits: 1\n#  debug:\n#    direction: BOTH\n#    dummy_receiver: false\n#    after:\n#      timeout: 150ms\n#    sequence:\n#      - lambda: |-\n#          UARTDebug::log_string(direction, bytes);\n\nmodbus:\n#flow_control_pin: 5\n  #send_wait_time: 200ms\n  id: modbus1\n\nmodbus_controller:\n  - id: jsymk\n    ## the Modbus device addr\n    address: 0x1\n    modbus_id: modbus1\n    update_interval: 0.75s\n    command_throttle: 50ms\n    # setup_priority: -10\n\nsensor:  \n  # tension de l'alimentation\n  - platform: modbus_controller\n    modbus_controller_id: jsymk\n    id: Tension\n    #name: \"Tension JSYMK\"\n    address: 0x0048\n    unit_of_measurement: \"V\"\n    register_type: holding\n    value_type: U_DWORD\n    accuracy_decimals: 1\n    filters:\n      - multiply: 0.0001\n    register_count: 1\n    response_size: 4\n\n    # Intensit\u00e9 traversant le tore\n  - platform: modbus_controller\n    modbus_controller_id: jsymk\n    id: Itore\n    name: \"I_ECS JSYMK\"\n    address: 0x0049\n    unit_of_measurement: \"A\"\n    register_type: holding\n    value_type: U_DWORD\n    accuracy_decimals: 1\n    filters:\n      - multiply: 0.0001\n    register_count: 1\n    response_size: 4\n    state_class: measurement\n\n  # Puissance traversant le tore\n  - platform: modbus_controller\n    modbus_controller_id: jsymk\n    id: puecs\n    name: \"P_ECS JSYMK\"\n    address: 0x004A\n    unit_of_measurement: \"W\"\n    register_type: holding\n    value_type: U_DWORD\n    accuracy_decimals: 1\n    filters:\n      - multiply: 0.0001\n      - sliding_window_moving_average:\n          window_size: 10\n          send_every: 1\n    register_count: 1\n    response_size: 4\n    state_class: measurement\n\n  # Energie lue dans le tore\n  - platform: modbus_controller\n    modbus_controller_id: jsymk\n    id: energietore\n    name: \"Energie ECS JSYMK\"\n    address: 0x004B\n    unit_of_measurement: \"kWh\"\n    register_type: holding\n    value_type: U_DWORD\n    accuracy_decimals: 1\n    filters:\n      - multiply: 0.0001\n    register_count: 1\n    response_size: 4\n    state_class: total\n\n  # Energie lue dans le tore\n  - platform: modbus_controller\n    modbus_controller_id: jsymk\n    id: fptore\n    #name: \"FP Tore JSYMK\"\n    address: 0x004C\n    register_type: holding\n    value_type: U_DWORD\n    accuracy_decimals: 1\n    filters:\n      - multiply: 0.0001\n    register_count: 1\n    response_size: 4\n\n  # Energie NEG lue dans le tore\n  - platform: modbus_controller\n    modbus_controller_id: jsymk\n    id: energietoren\n    name: \"Energie ECS Neg JSYMK\"\n    address: 0x004D\n    unit_of_measurement: \"kWh\"\n    register_type: holding\n    value_type: U_DWORD\n    accuracy_decimals: 1\n    filters:\n      - multiply: 0.0001     \n    register_count: 1\n    response_size: 4 \n    state_class: total\n    \n  # Sens du courant dans la pince\n  - platform: modbus_controller\n    modbus_controller_id: jsymk\n    id: senspince\n    #name: \"Sens_Pince JSYMK\"\n    address: 0x004E\n    register_type: holding\n    value_type: U_DWORD\n    bitmask: 0X00010000\n    filters:\n      - multiply: 1\n    register_count: 1\n    response_size: 4\n\n  # Sens du courant dans le tore\n  - platform: modbus_controller\n    modbus_controller_id: jsymk\n    id: senstor\n    #name: \"Sens_Tore JSYMK\"\n    address: 0x004E\n    register_type: holding\n    value_type: U_DWORD\n    accuracy_decimals: 0\n    bitmask: 0X01000000\n    filters:\n      - multiply: 1\n    register_count: 1\n    response_size: 4\n\n  # Fr\u00e9quence de l'alimentation  \n  - platform: modbus_controller\n    modbus_controller_id: jsymk\n    id: frequence\n    #name: \"Frequence JSYMK\"\n    address: 0x004F\n    unit_of_measurement: \"hz\"    \n    register_type: holding\n    value_type: U_DWORD\n    accuracy_decimals: 1\n    filters:\n      - multiply: 0.01\n    register_count: 1\n    response_size: 4\n\n  # tension de l'alimentation\n  - platform: modbus_controller\n    modbus_controller_id: jsymk\n    id: Tension2\n    #name: \"U_Reseau JSYMK\"\n    address: 0x0050\n    unit_of_measurement: \"V\"\n    register_type: holding\n    value_type: U_DWORD\n    accuracy_decimals: 1\n    filters:\n      - multiply: 0.0001\n    register_count: 1\n    response_size: 4\n    \n  # Intensit\u00e9 lue dans la pince\n  - platform: modbus_controller\n    modbus_controller_id: jsymk\n    id: Ireseau\n    #name: \"I_Reseau JSYMK\"\n    address: 0x0051\n    unit_of_measurement: \"A\"\n    register_type: holding\n    value_type: U_DWORD\n    accuracy_decimals: 1\n    filters:\n      - multiply: 0.0001\n    register_count: 1\n    response_size: 4\n\n  # puissance lue dans la pince\n  - platform: modbus_controller\n    modbus_controller_id: jsymk\n    id: pureseau\n    #name: \"P_Reseau JSYMK\"\n    address: 0x0052\n    unit_of_measurement: \"W\"\n    register_type: holding\n    value_type: U_DWORD\n    accuracy_decimals: 1\n    filters:\n      - multiply: 0.0001\n    register_count: 1\n    response_size: 4 \n    on_value:\n      then:\n        - lambda: |-\n            if ( id(senspince).state == 1 ) {\n              id(pureseau1).publish_state( id(pureseau).state *-1);\n            } else {\n              id(pureseau1).publish_state( id(pureseau).state );\n            }\n    \n  # Energie lue dans la pince\n  - platform: modbus_controller\n    modbus_controller_id: jsymk\n    id: energiepince\n    #name: \"Energie Reseau JSYMK\"\n    address: 0x0053\n    unit_of_measurement: \"kWh\"\n    register_type: holding\n    value_type: U_DWORD\n    accuracy_decimals: 1\n    filters:\n      - multiply: 0.0001\n    register_count: 1\n    response_size: 4\n\n  # Energie lue dans le tore\n  - platform: modbus_controller\n    modbus_controller_id: jsymk\n    id: fppince\n    #name: \"FP Pince JSYMK\"\n    address: 0x0054\n    register_type: holding\n    value_type: U_DWORD\n    accuracy_decimals: 1\n    filters:\n      - multiply: 0.0001\n    register_count: 1\n    response_size: 4\n\n  # Energie NEG lue dans le tore\n  - platform: modbus_controller\n    modbus_controller_id: jsymk\n    id: energienegpince\n    #name: \"Energie ECS Neg JSYMK\"\n    address: 0x0055\n    unit_of_measurement: \"kWh\"\n    register_type: holding\n    value_type: U_DWORD\n    accuracy_decimals: 1\n    filters:\n      - multiply: 0.0001     \n    register_count: 1\n    response_size: 4 <\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Code du fichier \u00ab\u00a0table_pu.yaml\u00a0\u00bb<\/h3>\n\n\n\n<p>Contient le r\u00e9sultat de votre etalonnage<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>globals:\n  - id: table_puissance\n    type: std::vector&lt;std::pair&lt;float, float>>\n    restore_value: no\n    initial_value: |-\n      {{\n        {0.0, 5.0},\n        {1.0, 14.661659},\n        {2.0, 15.560880},\n        {3.0, 15.927020},\n        {4.0, 16.568291},\n        {5.0, 18.303759},\n        {6.0, 19.157148},\n        {7.0, 20.944599},\n        {8.0, 22.596100},\n        {9.0, 23.025951},\n        {10.0, 25.903030},\n        {11.0, 28.434729},\n        {12.0, 30.524710},\n        {13.0, 31.625759},\n        {14.0, 34.235725},\n        {15.0, 36.901440},\n        {16.0, 40.163738},\n        {17.0, 44.019341},\n        {18.0, 44.768658},\n        {19.0, 49.555248},\n        {20.0, 56.278118},\n        {21.0, 59.905346},\n        {22.0, 64.042496},\n        {23.0, 69.965248},\n        {24.0, 77.182022},\n        {25.0, 81.073914},\n        {26.0, 89.339218},\n        {27.0, 96.296753},\n        {28.0, 100.722771},\n        {29.0, 108.025780},\n        {30.0, 115.575485},\n        {31.0, 122.833633},\n        {32.0, 133.766602},\n        {33.0, 144.135086},\n        {34.0, 159.488968},\n        {35.0, 166.558502},\n        {36.0, 178.282349},\n        {37.0, 189.092865},\n        {38.0, 202.196732},\n        {39.0, 212.861603},\n        {40.0, 234.333084},\n        {41.0, 248.347321},\n        {42.0, 262.094543},\n        {43.0, 283.565796},\n        {44.0, 301.493713},\n        {45.0, 322.728455},\n        {46.0, 344.373596},\n        {47.0, 365.494080},\n        {48.0, 381.928162},\n        {49.0, 415.564850},\n        {50.0, 441.482819},\n        {51.0, 468.173431},\n        {52.0, 501.893982},\n        {53.0, 521.712341},\n        {54.0, 550.043701},\n        {55.0, 586.746399},\n        {56.0, 627.726074},\n        {57.0, 661.966309},\n        {58.0, 703.051208},\n        {59.0, 730.505554},\n        {60.0, 761.137329},\n        {61.0, 804.480469},\n        {62.0, 847.356140},\n        {63.0, 878.056946},\n        {64.0, 941.720215},\n        {65.0, 993.722656},\n        {66.0, 1061.685303},\n        {67.0, 1101.080322},\n        {68.0, 1135.102417},\n        {69.0, 1196.311035},\n        {70.0, 1233.961548},\n        {71.0, 1294.063599},\n        {72.0, 1352.521729},\n        {73.0, 1392.430054},\n        {74.0, 1460.270386},\n        {75.0, 1512.882202},\n        {76.0, 1609.747437},\n        {77.0, 1674.149170},\n        {78.0, 1696.517944},\n        {79.0, 1770.225342},\n        {80.0, 1833.700928},\n        {81.0, 1901.670288},\n        {82.0, 1970.877197},\n        {83.0, 2023.935547},\n        {84.0, 2094.105469},\n        {85.0, 2165.517334},\n        {86.0, 2248.448242},\n        {87.0, 2357.001465},\n        {88.0, 2456.213135},\n        {89.0, 2539.881348},\n        {90.0, 2570.754395},\n        {91.0, 2631.065918},\n        {92.0, 2691.585938},\n        {93.0, 2750.663086},\n        {94.0, 2817.201172},\n        {95.0, 2895.280762},\n        {96.0, 2941.024902},\n        {97.0, 3038.455322},\n        {98.0, 3106.765137},\n        {99.0, 3144.267822},\n        {100.0, 3183.569824}\n      }}\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Intro Dans un article pr\u00e9c\u00e9dent, je d\u00e9crivais une deuxieme version de routeur PV d\u00e9velopp\u00e9 sous ESP Home donc compl\u00e8tement int\u00e9gr\u00e9 \u00e0 HA. Dans cette version le programme a \u00e9t\u00e9 totalement &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,6],"tags":[15,17,83],"class_list":["post-4004","post","type-post","status-publish","format-standard","hentry","category-homeassistant","category-photovoltaique","tag-esp32","tag-esphome","tag-routeur-solaire"],"_links":{"self":[{"href":"https:\/\/domo.rem81.com\/index.php\/wp-json\/wp\/v2\/posts\/4004","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=4004"}],"version-history":[{"count":26,"href":"https:\/\/domo.rem81.com\/index.php\/wp-json\/wp\/v2\/posts\/4004\/revisions"}],"predecessor-version":[{"id":4165,"href":"https:\/\/domo.rem81.com\/index.php\/wp-json\/wp\/v2\/posts\/4004\/revisions\/4165"}],"wp:attachment":[{"href":"https:\/\/domo.rem81.com\/index.php\/wp-json\/wp\/v2\/media?parent=4004"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/domo.rem81.com\/index.php\/wp-json\/wp\/v2\/categories?post=4004"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/domo.rem81.com\/index.php\/wp-json\/wp\/v2\/tags?post=4004"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}