2016 lines
169 KiB
Plaintext
Executable File
2016 lines
169 KiB
Plaintext
Executable File
a:6:{s:5:"child";a:1:{s:0:"";a:1:{s:3:"rss";a:1:{i:0;a:6:{s:4:"data";s:4:"
|
|
|
|
";s:7:"attribs";a:1:{s:0:"";a:1:{s:7:"version";s:3:"2.0";}}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:1:{s:0:"";a:1:{s:7:"channel";a:1:{i:0;a:6:{s:4:"data";s:113:"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:4:{s:0:"";a:7:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:12:"My Canaletto";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:0:"";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:20:"http://canaletto.fr/";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"docs";a:1:{i:0;a:5:{s:4:"data";s:41:"http://www.rssboard.org/rss-specification";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:9:"generator";a:1:{i:0;a:5:{s:4:"data";s:22:"BlogEngine.NET 3.3.8.0";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"language";a:1:{i:0;a:5:{s:4:"data";s:5:"en-US";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"item";a:10:{i:0;a:6:{s:4:"data";s:145:"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:7:{s:0:"";a:7:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:39:"AutoDiscover & AutoConfig IMAP/SMTP";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:12491:"<p style="text-align: justify;">En 2020, pour m'occuper pendant le confinement, j'avais écrit <a href="http://canaletto.fr/post/configuration-automatique-pop-imap" target="_blank" rel="noopener">un article</a> sur la configuration automatique des clients POP/IMAP. Ca fonctionnait sur Thunderbird, mais pas sur les clients Microsoft... Bon, les clients Microsoft il y en a de plusieurs sorte (Courrier, Outlook nouveau, ancien, 365, jadis Express et j'en passe) et la chose n'est (volontairement ?) pas simple. On va oublier les versions 365 qui même si elles supportent IMAP le font mal et ne sont pas vraiment destinés à cet usage mais plus à du MAPI.</p>
|
|
<p style="text-align: justify;">Pour cet article j'ai monté un serveur <a href="https://www.cloudron.io/" target="_blank" rel="noopener">Cloudron</a>. Ce projet gère très bien le mail dans sa version de base gratuite. Hélas il ne gère pas la configuration des clients, ce qui est regrettable car il pourrait très facilement intégrer ce qui suit afin d'être totalement dans la philosophie du projet intégré !</p>
|
|
<p style="text-align: justify;">Il existe plusieurs façons de faire de l'AutoDiscovery ou de l'AutoConfig</p>
|
|
<h3 style="text-align: justify;">La méthode RFC 6186</h3>
|
|
<p style="text-align: justify;">Elle se base sur des enregistrements DNS :</p>
|
|
<pre class="language-yaml"><code>_imap._tcp 300 IN SRV 0 0 0 .
|
|
_imaps._tcp 300 IN SRV 0 1 993 mail.domain.tld.
|
|
_pop3._tcp 300 IN SRV 0 0 0 .
|
|
_pop3s._tcp 300 IN SRV 10 1 995 mail.domain.tld.
|
|
_submission._tcp 300 IN SRV 0 0 0 .
|
|
_submissions._tcp 300 IN SRV 0 1 587 mail.domain.tld.</code></pre>
|
|
<p style="text-align: justify;"><a href="https://www.rfc-editor.org/rfc/rfc6186" target="_blank" rel="noopener">Normalisée</a> mais visiblement trop simple est abandonnée. Encore que <a href="https://social.technet.microsoft.com/Forums/en-US/daa5fd1f-883e-4ca9-8ebc-3b25576ced28/autodiscover-for-imap-account-on-outlook-20162019?forum=outlook" target="_blank" rel="noopener">certaines versions d'Outlook</a> utiliseraient ça. Etrange.</p>
|
|
<h3 style="text-align: justify;">La méthode Thunderbird </h3>
|
|
<p style="text-align: justify;">Thunderbird va chercher les paramètres dans un fichier XML sur l'url :<code></code></p>
|
|
<p style="text-align: justify;"><code>http://autoconfig.domain.tld/mail/config-v1.1.xml</code></p>
|
|
<h3 style="text-align: justify;">La méthode Outlook</h3>
|
|
<p style="text-align: justify;">Outlook cherche l’enregistrement DNS de type SRV :</p>
|
|
<p style="text-align: justify;"><code>_autodiscover._tcp.domain.tld 3600 IN SRV 10 10 443 autodiscover.domain.tld.</code></p>
|
|
<p style="text-align: justify;">qui va lui donner l'adresse ou interroger le fichier XML, donc un CNAME qui pointe sur le serveur web qui héberger le fichier XML, ce qui au final donnera une requête sur</p>
|
|
<p style="text-align: justify;"><code>https://autodiscover.domain.tld/AutoDiscover/AutoDiscover.xml</code></p>
|
|
<p style="text-align: justify;">Simple ! Attention à bien respecter la casse du mot AutoDiscover... Et ne pas oublier que dans le cas Microsoft on travaille en HTTPS. Dans certains cas on pourrait faire pointer ça sur n'importe quelle url, mais il semblerait que certaines vers ions d'Outlook (et il y en a !) cherchent une url qui commence par <code>autodiscover</code>...</p>
|
|
<h3 style="text-align: justify;">Un site pour les rassembler</h3>
|
|
<p style="text-align: justify;">Dans la méthode qui va suivre on va utiliser un seul site capable de répondre aux url <code>autoconfig</code> et <code>autodiscover</code>, on renseignera donc ces enregistrement dans le dns :</p>
|
|
<pre class="language-yaml"><code>_autodiscover._tcp.domain.tld 1800 IN SRV 10 10 443 autodiscover.domain.tld.
|
|
autoconfig 1800 IN CNAME web_server.domain.tld.
|
|
autodiscover 1080 IN CNAME web_server.domain.tld.</code></pre>
|
|
<p style="text-align: justify;">Ensuite on crée un site web capable de répondre à ces deux url pour l'ensemble des domaines de messagerie pour lesquels on souhaite proposer ce service. Le site doit répondre en HTTP et HTTPS, <span style="text-decoration: underline;">mais surtout sans redirection automatique HTTP vers HTTPS</span>. Pour cet exemple j'ai utilisé un serveur web NGINX avec du PHP.</p>
|
|
<p style="text-align: justify;">On va utiliser ce code que j'ai trouvé <a href="https://david.mercereau.info/autoconfig-thunderbird-autodiscover-outlook-sur-messagerie-heberge-ispconfig/" target="_blank" rel="noopener">ici</a>, je l'ai utilisé tel que en adaptant les enregistrements DNS et les redirections pour NGINX que l'on verra après le code. On copie donc ce code PHP dans autoconfig-mail.php :</p>
|
|
<pre class="language-php"><code><?php
|
|
|
|
/*
|
|
By David Mercereau
|
|
Licence Beerware
|
|
*/
|
|
|
|
function extract_domain($domain) {
|
|
if(preg_match("/(?P<domain>[a-z0-9][a-z0-9\-]{1,63}\.[a-z\.]{2,6})$/i", $domain, $matches)) {
|
|
return $matches['domain'];
|
|
} else {
|
|
return $domain;
|
|
}
|
|
}
|
|
|
|
$domain = extract_domain($_SERVER['SERVER_NAME']);
|
|
$mailServeur='mail.'.$domain;
|
|
|
|
if (preg_match('/^\/mail\/config-v1\.1\.xml/', $_SERVER['REQUEST_URI'])) {
|
|
header('Content-Type: text/xml');
|
|
header('Content-Type: application/xml');
|
|
?>
|
|
<clientConfig version="1.1">
|
|
<emailProvider id="<?= $domain ?>">
|
|
<domain><?= $domain ?></domain>
|
|
<displayName><?= $domain ?></displayName>
|
|
<displayShortName><?= $domain ?></displayShortName>
|
|
<incomingServer type="imap">
|
|
<hostname><?= $mailServeur ?></hostname>
|
|
<port>143</port>
|
|
<socketType>STARTTLS</socketType>
|
|
<username>%EMAILADDRESS%</username>
|
|
<authentication>password-cleartext</authentication>
|
|
</incomingServer>
|
|
<outgoingServer type="smtp">
|
|
<hostname><?= $mailServeur ?></hostname>
|
|
<port>587</port>
|
|
<socketType>STARTTLS</socketType>
|
|
<username>%EMAILADDRESS%</username>
|
|
<authentication>password-cleartext</authentication>
|
|
</outgoingServer>
|
|
<documentation url="https://webmail.<?= $domain ?>">
|
|
<descr lang="fr">Connexion Webmail</descr>
|
|
<descr lang="en">Webmail connexion</descr>
|
|
</documentation>
|
|
<documentation url="http://projet.retzo.net/projects/hebergement/wiki">
|
|
<descr lang="fr">Documentation</descr>
|
|
<descr lang="en">Generic settings page</descr>
|
|
</documentation>
|
|
</emailProvider>
|
|
</clientConfig>
|
|
<?php
|
|
} else {
|
|
// Outlook
|
|
//get raw POST data so we can extract the email address
|
|
$data = file_get_contents("php://input");
|
|
preg_match("/\<EMailAddress\>(.*?)\<\/EMailAddress\>/", $data, $matches);
|
|
|
|
//set Content-Type
|
|
header('Content-Type: text/xml');
|
|
header('Content-Type: application/xml');
|
|
echo '<?xml version="1.0" encoding="utf-8" ?>';
|
|
?>
|
|
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
|
|
<Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
|
|
<Account>
|
|
<AccountType>email</AccountType>
|
|
<Action>settings</Action>
|
|
<Protocol>
|
|
<Type>IMAP</Type>
|
|
<Server><?= $mailServeur ?></Server>
|
|
<Port>993</Port>
|
|
<DomainRequired>off</DomainRequired>
|
|
<LoginName><?php echo $matches[1]; ?></LoginName>
|
|
<SPA>off</SPA>
|
|
<SSL>on</SSL>
|
|
<AuthRequired>on</AuthRequired>
|
|
</Protocol>
|
|
<Protocol>
|
|
<Type>POP3</Type>
|
|
<Server><?= $mailServeur ?></Server>
|
|
<Port>995</Port>
|
|
<DomainRequired>off</DomainRequired>
|
|
<LoginName><?php echo $matches[1]; ?></LoginName>
|
|
<SPA>off</SPA>
|
|
<SSL>on</SSL>
|
|
<AuthRequired>on</AuthRequired>
|
|
</Protocol>
|
|
<Protocol>
|
|
<Type>SMTP</Type>
|
|
<Server><?= $mailServeur ?></Server>
|
|
<Port>587</Port>
|
|
<DomainRequired>off</DomainRequired>
|
|
<LoginName><?php echo $matches[1]; ?></LoginName>
|
|
<SPA>off</SPA>
|
|
<Encryption>TLS</Encryption>
|
|
<AuthRequired>on</AuthRequired>
|
|
<UsePOPAuth>off</UsePOPAuth>
|
|
<SMTPLast>off</SMTPLast>
|
|
</Protocol>
|
|
</Account>
|
|
</Response>
|
|
</Autodiscover>
|
|
<?php
|
|
}
|
|
|
|
?></code></pre>
|
|
<p style="text-align: justify;">Ensuite dans configuration NGINX on ajoute les redirections suivantes qui va permettre de servir la bonne version XML selon que la requête utilise la méthode Outlook ou Thunderbird (attention à la casse...) :</p>
|
|
<pre class="language-javascript"><code>location /AutoDiscover {
|
|
rewrite ^/AutoDiscover/AutoDiscover.xml /autoconfig-mail.php;
|
|
}
|
|
location /mail {
|
|
rewrite ^/mail/config-v1.1.xml /autoconfig-mail.php;
|
|
}</code></pre>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/enjoy2.jpg" width="250" height="168" /></p>
|
|
<h3 style="text-align: left;">Sources</h3>
|
|
<ul style="list-style-type: circle;">
|
|
<li style="text-align: left;"><a href="https://github.com/cfoellmann/ISPC-resources/tree/master/guides/autodiscover" target="_blank" rel="noopener">https://github.com/cfoellmann/ISPC-resources/tree/master/guides/autodiscover</a></li>
|
|
<li style="text-align: left;"><a href="https://help.directadmin.com/item.php?id=661" target="_blank" rel="noopener">https://help.directadmin.com/item.php?id=661</a></li>
|
|
<li style="text-align: left;"><a href="https://testconnectivity.microsoft.com" target="_blank" rel="noopener">https://testconnectivity.microsoft.com</a></li>
|
|
<li style="text-align: left;"><a href="https://www.howto-outlook.com/howto/autodiscoverconfiguration.htm#cname" target="_blank" rel="noopener">https://www.howto-outlook.com/howto/autodiscoverconfiguration.htm#cname</a></li>
|
|
<li style="text-align: left;">https://www.awsmonster.com/2019/09/how-to-configure-autodiscover.html</li>
|
|
<li style="text-align: left;"><a href="https://learn.microsoft.com/fr-fr/exchange/troubleshoot/outlook-issues/issues-when-using-autodiscover-service" target="_blank" rel="noopener">https://learn.microsoft.com/fr-fr/exchange/troubleshoot/outlook-issues/issues-when-using-autodiscover-service</a></li>
|
|
<li style="text-align: left;"><a href="https://docs.directadmin.com/other-hosting-services/email/autodiscover.html" target="_blank" rel="noopener">https://docs.directadmin.com/other-hosting-services/email/autodiscover.html</a></li>
|
|
<li style="text-align: left;"><a href="https://david.mercereau.info/autoconfig-thunderbird-autodiscover-outlook-sur-messagerie-heberge-ispconfig/" target="_blank" rel="noopener">https://david.mercereau.info/autoconfig-thunderbird-autodiscover-outlook-sur-messagerie-heberge-ispconfig/</a></li>
|
|
<li style="text-align: left;"><a href="https://github.com/wdes/mail-autodiscover-autoconfig" target="_blank" rel="noopener">https://github.com/wdes/mail-autodiscover-autoconfig</a> (Apple inside...)</li>
|
|
<li style="text-align: left;"><a href="https://blog.ebak.fr/2022/03/05/Auto-configuration-des-clients-mails/#Autoconfig-Thunderbird" target="_blank" rel="noopener">https://blog.ebak.fr/2022/03/05/Auto-configuration-des-clients-mails/#Autoconfig-Thunderbird</a> </li>
|
|
</ul>
|
|
<p style="text-align: left;"><br />https://github.com/gronke/email-autodiscover<br />https://github.com/SpicyWeb-de/isp-mailConfig</p>";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:62:"http://canaletto.fr/post/autodiscover-and-autoconfig-imap-smtp";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"comments";a:1:{i:0;a:5:{s:4:"data";s:70:"http://canaletto.fr/post/autodiscover-and-autoconfig-imap-smtp#comment";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post.aspx?id=d03374ea-d6e8-464d-a0e8-80f3ef2a3efe";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:33:"lun., 20 nov. 2023 23:08:00 +0100";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:2:"IT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:34:"https://blogengine.io/schemas/tags";a:1:{s:3:"tag";a:6:{i:0;a:5:{s:4:"data";s:11:"Thunderbird";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:1;a:5:{s:4:"data";s:7:"Outlook";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:2;a:5:{s:4:"data";s:4:"Mail";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:3;a:5:{s:4:"data";s:4:"IMAP";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:4;a:5:{s:4:"data";s:12:"Autodiscover";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:5;a:5:{s:4:"data";s:10:"autoconfig";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:9:"publisher";a:1:{i:0;a:5:{s:4:"data";s:5:"Admin";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:52:"http://madskills.com/public/xml/rss/module/pingback/";a:2:{s:6:"server";a:1:{i:0;a:5:{s:4:"data";s:32:"http://canaletto.fr/pingback.axd";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:6:"target";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post.aspx?id=d03374ea-d6e8-464d-a0e8-80f3ef2a3efe";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:38:"http://purl.org/rss/1.0/modules/slash/";a:1:{s:8:"comments";a:1:{i:0;a:5:{s:4:"data";s:1:"0";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:53:"http://madskills.com/public/xml/rss/module/trackback/";a:1:{s:4:"ping";a:1:{i:0;a:5:{s:4:"data";s:73:"http://canaletto.fr/trackback.axd?id=d03374ea-d6e8-464d-a0e8-80f3ef2a3efe";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:36:"http://wellformedweb.org/CommentAPI/";a:2:{s:7:"comment";a:1:{i:0;a:5:{s:4:"data";s:70:"http://canaletto.fr/post/autodiscover-and-autoconfig-imap-smtp#comment";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:10:"commentRss";a:1:{i:0;a:5:{s:4:"data";s:77:"http://canaletto.fr/syndication.axd?post=d03374ea-d6e8-464d-a0e8-80f3ef2a3efe";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:1;a:6:{s:4:"data";s:152:"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:7:{s:0:"";a:7:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:36:"Home Assistant, Zigbee & Legrand";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:9877:"<p style="text-align: justify;">On m'a demandé récemment d'intégrer des appareils Legrand dans Home Assistant, je l'avais déjà fait pour certains et j'en avais parlé dans <a href="http://canaletto.fr/post/home-assistant-zha-and-legrand" target="_blank" rel="noopener">cet article</a>. Aujourd'hui il s'agit d'intégrer des commandes sans fil vue come des télécommandes dans HA. Vous allez me demander quel est l'intérêt quand un simple bouton Ikea (E1743) à moins de 10 fait le job pour mes volets roulants. C'est purement esthétique, quand on a un logement équipé en Legrand Céliane ou Mosaic, on veut parfois que les commandes des volets soient dans la même collection.</p>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/legrand_vr.jpeg" width="249" height="249" /></p>
|
|
<p style="text-align: justify;">Soit, Legrand propose des commandes en Zigbee, il n'y a plus qu'à !</p>
|
|
<p style="text-align: justify;">Dans la pratique on va voir que ce n'est pas si simple, en tous cas bien moins simple qu'avec mon bouton Ikea à 10 € ! Je précise le prix car les commandes Legrand sont plutôt à 80 €. Mais quand on aime on ne compte pas.</p>
|
|
<p style="text-align: justify;">Il existe plusieurs type d'équipements Zigbee chez Legrand</p>
|
|
<ul style="text-align: justify;">
|
|
<li>Ceux qui sont filaires, j'en ai parlé <a href="http://canaletto.fr/post/home-assistant-zha-and-legrand" target="_blank" rel="noopener">ici</a> (micro modules, contacteur DIN, prise connectée, etc...)</li>
|
|
<li>La gamme des commandes sans fil à pile</li>
|
|
<li>La gamme des commandes sans fil sans piles (gamme Self-e). J'y reviendrait certainement, mais d'après mes infos cette gamme supporte tous les canaux et serait mieux intégrée ZHA/Z2M.</li>
|
|
</ul>
|
|
<p style="text-align: justify;">Je me suis donc penché sur la gamme avec pile.</p>
|
|
<p style="text-align: justify;">Première observation, ces devices sont généralement livrés avec un firmware de niveau 42 qui ne permet que l'utilisation du canal Zigbee 11. Don impossible à faire fonctionner sur mon ZHA qui est en 15. Je l'ai donc appairé sur mon Z2M en 11 et ça fonctionne. Et là je me suis dit que j'allais pouvoir mettre à jour ce firmware en OTA. Mais non, ça ne fonctionne pas et on se retrouve dans la problématique des équipements franco Français qui n'intéressent pas grand monde au niveau international (on pense par exemple à tout ce qui est lié à l'intégration Overkiz...).</p>
|
|
<p style="text-align: justify;">Après moultes lectures des forums de diverses plateformes domotique, la conclusion est que la mise à jour du firmware ne peut se faire qu'au travers d'une passerelle officielle Legrand ! J’ai donc acheté le kit qui comprend :</p>
|
|
<ul style="text-align: justify;">
|
|
<li>La prise Control qui sert de passerelle</li>
|
|
<li>Un inter sans fil</li>
|
|
<li>Une ampoule</li>
|
|
</ul>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/legrand_pack.jpg" width="532" height="532" /></p>
|
|
<p style="text-align: justify;">Il faut bien sur installer l’appli Legrand et ensuite tenter d’associer la prise au WIFI. Facile ? Non, ça m’a pris de plombes car vu que leur process est trop long, le mobile qui se connecte à la prise pour la configurer repasse sur le WIFI normal ou il retrouve Internet, et perd la config en cours. Solution faire ça avec un vieux mobile… Bref, un premier amateurisme car on fait facilement ce genre d'association avec la majorité des objets mobile en WIFI !</p>
|
|
<p style="text-align: justify;">Bon, la logique de l’appli est orientée électricien très grand public, avec une logique d'électricien qui n’est pas nécessairement la notre. C'est un choix, il faut s'y faire, mais n'oublions pas que nous sommes ici uniquement pour faire un mise à jour...</p>
|
|
<p style="text-align: justify;">Ensuite il faut ajouter les inter. Sauf que la il faut comprendre qu’on ne peut pas ajouter un inter seul. Dans la logique Legrand si tu ajoute un inter, en fin de dialogue ça te demande ce que tu veux commander, sans quoi ça bloque et il n’y a plus qu’à forcer le redémarrage de l’appli et recommencer... Je n’avais pas de prise Legrand sous la main, mais au bout d’un moment j’ai fini par penser à appairer l’ampoule. Et la je vois enfin l’inter livré et mon inter de volet roulant qui ne peut rien commander, c’est le même mais avec un firmware différent.</p>
|
|
<p style="text-align: justify;">Mais souvenons nous que nous somme là à jouer avec ce bazar dans le seul but de mettre à jour le firmware de ces putains d’inter qui au delà de couter un rein ne fonctionnent (mal) que sur le canal 11. Hélas il n’y arien pour faire cette mise à jour, mon inter de VR apparait en 42 dans l’appli et en 002a dans z2m, donc identique l’un étant en hexa. D’après ce que j’ai pu lire, la mise à jour se fera, un jour, mais on ne peut pas la forcer. Il faut juste laisser branché, en espérant que mon inter qui n’est pas connecté à un appareil se mette à jour tout seul…</p>
|
|
<p style="text-align: justify;">Donc je laisse branché, la suite pour bientôt…</p>
|
|
<p style="text-align: justify;"><strong>EDIT un peu plus tard :</strong></p>
|
|
<ul style="text-align: justify;">
|
|
<li>L’inter (0 677 73N) est passé de 50 à 70</li>
|
|
<li>L’inter VR (0 777 48LA) n’a pas bougé…</li>
|
|
<li>Je testerais si on peut l’appairer hors du canal 11 mais je commence à douter…</li>
|
|
</ul>
|
|
<p style="text-align: justify;"><strong>EDIT le lendemain :</strong></p>
|
|
<ul style="text-align: justify;">
|
|
<li>L’inter s’appaire bien sur un autre canal après sa mise à jour. Testé en ZHA sur 15, mais ZHA ne le supporte pas et rien ne bouge, aucun event.</li>
|
|
<li>L’inter VR ne s’est toujours pas mis à jour. Un peu comme s’il lui fallait une charge...</li>
|
|
</ul>
|
|
<p style="text-align: justify;"><strong>EDIT le lendemain soir :</strong></p>
|
|
<ul style="text-align: justify;">
|
|
<li>L’inter VR est bien passé de 42 à 70, mon ZHA qui est sur le canal 15 le voit mais n’en fait rien. Quand à Z2M il n’en veut plus ! Pire ça me fait planter Z2M…</li>
|
|
</ul>
|
|
<p style="text-align: justify;"><strong>EDIT le sur lendemain midi :</strong></p>
|
|
<ul style="text-align: justify;">
|
|
<li>L’inter VR qui ne veut toujours pas de ZHA ou Z2M s’est appairé correctement sur deconz en canal 15, il retourne dans les event les valeurs suivantes :</li>
|
|
</ul>
|
|
<blockquote>
|
|
<p>Montée : <code>1002</code> / Montée puis relâché : <code>1002/3002</code><br />Descente : <code>2002</code> / Descente puis relâché : <code>2002/3003</code><br />Stop (Les deux en même temps) : <code>3003</code></p>
|
|
</blockquote>
|
|
<p style="text-align: justify;">Ce comportement est identique à ce qu’il était sous Z2M et contrairement à d'autres télécommandes (le on/off Ikea (E1743 par exemple) il manque le fait qu’un second appui bref provoque un stop. Il faut donc bien appuyer au milieu pour faire un « stop » et ce n’est pas toujours pris en compte (problème physique).</p>
|
|
<p style="text-align: justify;">Qu’il ne soit pas supporté sur ZHA est un fait, il faudrait développer un quirk et ça me dépasse. Je ne sais pas pourquoi il ne veut plus s’appairer sur Z2M, mais c’est peut être lié à mon installation, ma clé, que sais-je...</p>
|
|
<p style="text-align: justify;">Il y a des chances que l’aventure Legrand va prendre fin et je que je retourne fissa ce Kit à Amazon !</p>
|
|
<h3 style="text-align: justify;">Homekit</h3>
|
|
<p style="text-align: justify;">A signaler toutefois que cette passerelle est Homekit. Ce qui veut dire que ses équipements remontent dans Home Assistant. Mais ne rêvez pas trop, si l’ampoule remonte bien, et certainement tous les actionneurs connectés (prises, modules DIN), pas les inter ! Mais j’avais déjà remarqué ça avec les télécommandes Tuya qui ne remontent pas via une passerelle Tuya Homekit. Il y a une forme de logique, Homekit sert à commander un équipement, comme une télécommande, hors on ne commande pas une télécommande…</p>
|
|
<p style="text-align: justify;">Par contre ça veut dire que les équipements reconnus par Legrand vont remonter dans Homekit, ce qui peut être une solution de contrôle facile pour des produit pas reconnus par HA (Profalux, Bubendorf, Aldes, etc…).</p>
|
|
<h3 style="text-align: justify;">La suite</h3>
|
|
<p style="text-align: justify;">Je vous propose de poursuivre <a href="https://forum.hacf.fr/t/interrupteur-legrand-volet-roulant-celiane-mosaic/9137/24" target="_blank" rel="noopener">ici</a> et que chacun y apporte ses retours.</p>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/ThatsAllFolks.jpg" width="275" height="275" /></p>";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:58:"http://canaletto.fr/post/home-assistant-zigbee-and-legrand";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"comments";a:1:{i:0;a:5:{s:4:"data";s:66:"http://canaletto.fr/post/home-assistant-zigbee-and-legrand#comment";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post.aspx?id=c9296c49-547e-42ae-b4be-7a9cedd65947";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:33:"dim., 19 nov. 2023 17:14:00 +0100";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:9:"Domotique";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:34:"https://blogengine.io/schemas/tags";a:1:{s:3:"tag";a:7:{i:0;a:5:{s:4:"data";s:14:"Home Assistant";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:1;a:5:{s:4:"data";s:4:"HASS";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:2;a:5:{s:4:"data";s:7:"Legrand";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:3;a:5:{s:4:"data";s:6:"zigbee";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:4;a:5:{s:4:"data";s:3:"Z2M";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:5;a:5:{s:4:"data";s:3:"ZHA";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:6;a:5:{s:4:"data";s:11:"zigbee2mqtt";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:9:"publisher";a:1:{i:0;a:5:{s:4:"data";s:5:"Admin";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:52:"http://madskills.com/public/xml/rss/module/pingback/";a:2:{s:6:"server";a:1:{i:0;a:5:{s:4:"data";s:32:"http://canaletto.fr/pingback.axd";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:6:"target";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post.aspx?id=c9296c49-547e-42ae-b4be-7a9cedd65947";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:38:"http://purl.org/rss/1.0/modules/slash/";a:1:{s:8:"comments";a:1:{i:0;a:5:{s:4:"data";s:1:"5";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:53:"http://madskills.com/public/xml/rss/module/trackback/";a:1:{s:4:"ping";a:1:{i:0;a:5:{s:4:"data";s:73:"http://canaletto.fr/trackback.axd?id=c9296c49-547e-42ae-b4be-7a9cedd65947";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:36:"http://wellformedweb.org/CommentAPI/";a:2:{s:7:"comment";a:1:{i:0;a:5:{s:4:"data";s:66:"http://canaletto.fr/post/home-assistant-zigbee-and-legrand#comment";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:10:"commentRss";a:1:{i:0;a:5:{s:4:"data";s:77:"http://canaletto.fr/syndication.axd?post=c9296c49-547e-42ae-b4be-7a9cedd65947";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:2;a:6:{s:4:"data";s:159:"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:7:{s:0:"";a:7:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:29:"Home Assistant & Mi Boxer";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:14571:"<p style="text-align: justify;">J'avais <a href="https://amzn.to/46hQBZR" target="_blank" rel="noopener">acheté cette télécommande Mi Boxer</a> il y a quelques mois afin de gérer les éclairages de mon séjour, en me disant que les curseurs seraient plus pratiques que mon <a href="https://fr.aliexpress.com/item/1005002219929565.html" target="_blank" rel="noopener">Opple</a> avec ses 6 boutons actuelle. Hélas elle n'était reconnue nulle part et avait terminé sa course dans le tiroir aux oubliettes du Zigbee...</p>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/MiBoxer2.jpg" width="397" height="369" /></p>
|
|
<p style="text-align: justify;">C'était sans compter sur la ténacité de quelques amateurs de reverse engineering sur lesquels je suis tombé il y a quelques semaines et qui on <a href="https://github.com/Koenkk/zigbee2mqtt/issues/10708" target="_blank" rel="noopener">fait un travail formidable</a> qui a aboutit à <a href="https://www.zigbee2mqtt.io/devices/FUT089Z.html#exposing-the-controls" target="_blank" rel="noopener">une extension</a> pour Zigbee2MQTT, ce qui rend cette télécommande enfin utilisable, tout au moins partiellement pour l'instant. Mais l'essentiel est là !</p>
|
|
<p style="text-align: justify;"><strong>Ce qui fonctionne :</strong></p>
|
|
<ul style="text-align: justify;">
|
|
<li>7 boutons avec ON et OFF (deux actions et non un toggle). Celui du bas à droite n'est pas actif et je vous déconseille de l'utiliser...</li>
|
|
<li>1 bouton avec ON et OFF (en haut)</li>
|
|
<li>1 bouton W (si on veut bricoler...)</li>
|
|
<li>La barre de réglage de la luminosité</li>
|
|
<li>La remontée de l'état de la batterie</li>
|
|
</ul>
|
|
<p style="text-align: justify;"><strong>Ce qui ne fonctionne pas (pour l'instant) :</strong></p>
|
|
<ul style="text-align: justify;">
|
|
<li>La barre de réglage des couleurs</li>
|
|
<li>La barre de réglage de la température du blanc</li>
|
|
<li>Les touches RGB</li>
|
|
<li>Les touches de temporisation (en bas à droite)</li>
|
|
</ul>
|
|
<p style="text-align: justify;">Une fois la télécommande reconnue sous Z2M on peut commencer à créer des actions. On remarque tout de suite que l'affaire va manquer de <code>sensor:</code> et que certains ne fonctionnent pas. Pas de panique, il y a une solution comme je vais vous le démonter avec l'<code>automation:</code> qui suit. </p>
|
|
<p style="text-align: justify;">J'ai fait un mélange de <code>choose:</code> / <code>conditions:</code> / <code>trigger.id</code> . C'est un peu long, mais je la colle en entier ce qui vous évitera une fastidieuse saisie. Il faudra tout de même y coller vous <code>id:</code> et <code>entity:</code> ! Ah j'allais oublier, il faut aussi ajouter un petit <code>input_select:</code> ...</p>
|
|
<p style="text-align: justify;">J'ai tenté de faire ça avec ControllerX que j'adore et qui me sert pour toutes mes télécommandes, mais pour l'instant c'est un échec !</p>
|
|
<pre class="language-yaml"><code>alias: GUI - Mi Boxer
|
|
description: ""
|
|
trigger:
|
|
- platform: state
|
|
entity_id:
|
|
- sensor.mi_boxeur_brightness
|
|
id: bright
|
|
- platform: device
|
|
domain: mqtt
|
|
device_id: 86c1403c24491ce021ac3ee081a86308
|
|
type: button_short_press
|
|
subtype: button_group_1_on
|
|
discovery_id: 0x003c84fffec29c71_zone_1_button_on
|
|
id: 1on
|
|
- platform: device
|
|
domain: mqtt
|
|
device_id: 86c1403c24491ce021ac3ee081a86308
|
|
type: button_short_press
|
|
subtype: button_group_1_off
|
|
discovery_id: 0x003c84fffec29c71_zone_1_button_off
|
|
id: 1off
|
|
- platform: device
|
|
domain: mqtt
|
|
device_id: 86c1403c24491ce021ac3ee081a86308
|
|
type: button_short_press
|
|
subtype: button_group_2_on
|
|
discovery_id: 0x003c84fffec29c71_zone_2_button_on
|
|
id: 2on
|
|
- platform: device
|
|
domain: mqtt
|
|
device_id: 86c1403c24491ce021ac3ee081a86308
|
|
type: button_short_press
|
|
subtype: button_group_2_off
|
|
discovery_id: 0x003c84fffec29c71_zone_2_button_off
|
|
id: 2off
|
|
- platform: device
|
|
domain: mqtt
|
|
device_id: 86c1403c24491ce021ac3ee081a86308
|
|
type: button_short_press
|
|
subtype: button_group_3_on
|
|
discovery_id: 0x003c84fffec29c71_zone_3_button_on
|
|
id: 3on
|
|
- platform: device
|
|
domain: mqtt
|
|
device_id: 86c1403c24491ce021ac3ee081a86308
|
|
type: button_short_press
|
|
subtype: button_group_3_off
|
|
discovery_id: 0x003c84fffec29c71_zone_3_button_off
|
|
id: 3off
|
|
- platform: device
|
|
domain: mqtt
|
|
device_id: 86c1403c24491ce021ac3ee081a86308
|
|
type: button_short_press
|
|
subtype: button_group_4_on
|
|
discovery_id: 0x003c84fffec29c71_zone_4_button_on
|
|
id: 4on
|
|
- platform: device
|
|
domain: mqtt
|
|
device_id: 86c1403c24491ce021ac3ee081a86308
|
|
type: button_short_press
|
|
subtype: button_group_4_off
|
|
discovery_id: 0x003c84fffec29c71_zone_4_button_off
|
|
id: 4off
|
|
- platform: device
|
|
domain: mqtt
|
|
device_id: 86c1403c24491ce021ac3ee081a86308
|
|
type: button_short_press
|
|
subtype: button_group_5_on
|
|
discovery_id: 0x003c84fffec29c71_zone_5_button_on
|
|
id: 5on
|
|
- platform: device
|
|
domain: mqtt
|
|
device_id: 86c1403c24491ce021ac3ee081a86308
|
|
type: button_short_press
|
|
subtype: button_group_5_off
|
|
discovery_id: 0x003c84fffec29c71_zone_5_button_off
|
|
id: 5off
|
|
- platform: device
|
|
domain: mqtt
|
|
device_id: 86c1403c24491ce021ac3ee081a86308
|
|
type: button_short_press
|
|
subtype: button_group_6_on
|
|
discovery_id: 0x003c84fffec29c71_zone_6_button_on
|
|
id: 6on
|
|
- platform: device
|
|
domain: mqtt
|
|
device_id: 86c1403c24491ce021ac3ee081a86308
|
|
type: button_short_press
|
|
subtype: button_group_6_off
|
|
discovery_id: 0x003c84fffec29c71_zone_6_button_off
|
|
id: 6off
|
|
- platform: device
|
|
domain: mqtt
|
|
device_id: 86c1403c24491ce021ac3ee081a86308
|
|
type: button_short_press
|
|
subtype: button_group_7_on
|
|
discovery_id: 0x003c84fffec29c71_zone_7_button_on
|
|
id: 7on
|
|
- platform: device
|
|
domain: mqtt
|
|
device_id: 86c1403c24491ce021ac3ee081a86308
|
|
type: button_short_press
|
|
subtype: button_group_7_off
|
|
discovery_id: 0x003c84fffec29c71_zone_7_button_off
|
|
id: 7off
|
|
- platform: device
|
|
domain: mqtt
|
|
device_id: 86c1403c24491ce021ac3ee081a86308
|
|
type: button_short_press
|
|
subtype: button_group_8_on
|
|
discovery_id: 0x003c84fffec29c71_zone_8_button_on
|
|
id: 8on
|
|
- platform: device
|
|
domain: mqtt
|
|
device_id: 86c1403c24491ce021ac3ee081a86308
|
|
type: button_short_press
|
|
subtype: button_group_8_off
|
|
discovery_id: 0x003c84fffec29c71_zone_8_button_off
|
|
id: 8off
|
|
|
|
condition: []
|
|
action:
|
|
- choose:
|
|
- conditions: "{{ trigger.id in ['1on'] }}"
|
|
sequence:
|
|
- service: light.turn_on
|
|
data: {}
|
|
target:
|
|
entity_id: light.shellydimmer_f3d426
|
|
- service: input_select.select_option
|
|
data:
|
|
option: "1"
|
|
target:
|
|
entity_id: input_select.mi_boxer_select
|
|
- conditions: "{{ trigger.id in ['1off'] }}"
|
|
sequence:
|
|
- service: light.turn_off
|
|
data: {}
|
|
target:
|
|
entity_id: light.shellydimmer_f3d426
|
|
|
|
- conditions: "{{ trigger.id in ['2on'] }}"
|
|
sequence:
|
|
- service: light.turn_on
|
|
data: {}
|
|
target:
|
|
entity_id: light.shellydimmer_d3e57c
|
|
- service: input_select.select_option
|
|
data:
|
|
option: "2"
|
|
target:
|
|
entity_id: input_select.mi_boxer_select
|
|
- conditions: "{{ trigger.id in ['2off'] }}"
|
|
sequence:
|
|
- service: light.turn_off
|
|
data: {}
|
|
target:
|
|
entity_id: light.shellydimmer_d3e57c
|
|
|
|
- conditions: "{{ trigger.id in ['3on'] }}"
|
|
sequence:
|
|
- service: light.turn_on
|
|
data: {}
|
|
target:
|
|
entity_id: light.ikea_e27_tv
|
|
- service: input_select.select_option
|
|
data:
|
|
option: "3"
|
|
target:
|
|
entity_id: input_select.mi_boxer_select
|
|
- conditions: "{{ trigger.id in ['3off'] }}"
|
|
sequence:
|
|
- service: light.turn_off
|
|
data: {}
|
|
target:
|
|
entity_id: light.ikea_e27_tv
|
|
|
|
- conditions: "{{ trigger.id in ['4on'] }}"
|
|
sequence:
|
|
- service: light.turn_on
|
|
data: {}
|
|
target:
|
|
entity_id: light.lidl_led_stand
|
|
- service: input_select.select_option
|
|
data:
|
|
option: "4"
|
|
target:
|
|
entity_id: input_select.mi_boxer_select
|
|
- conditions: "{{ trigger.id in ['4off'] }}"
|
|
sequence:
|
|
- service: light.turn_off
|
|
data: {}
|
|
target:
|
|
entity_id: light.lidl_led_stand
|
|
|
|
- conditions: "{{ trigger.id in ['5on'] }}"
|
|
sequence:
|
|
- service: light.turn_on
|
|
data: {}
|
|
target:
|
|
entity_id: light.dimmable_sm309
|
|
- service: input_select.select_option
|
|
data:
|
|
option: "5"
|
|
target:
|
|
entity_id: input_select.mi_boxer_select
|
|
- conditions: "{{ trigger.id in ['5off'] }}"
|
|
sequence:
|
|
- service: light.turn_off
|
|
data: {}
|
|
target:
|
|
entity_id: light.dimmable_sm309
|
|
|
|
- conditions: "{{ trigger.id in ['6on'] }}"
|
|
sequence:
|
|
- service: light.turn_on
|
|
data: {}
|
|
target:
|
|
entity_id: light.shelly_bulb_1
|
|
- service: input_select.select_option
|
|
data:
|
|
option: "6"
|
|
target:
|
|
entity_id: input_select.mi_boxer_select
|
|
- conditions: "{{ trigger.id in ['6off'] }}"
|
|
sequence:
|
|
- service: light.turn_off
|
|
data: {}
|
|
target:
|
|
entity_id: light.shelly_bulb_1
|
|
|
|
- conditions: "{{ trigger.id in ['7on'] }}"
|
|
sequence:
|
|
- service: light.turn_on
|
|
data: {}
|
|
target:
|
|
entity_id: light.led_strip_1
|
|
- service: input_select.select_option
|
|
data:
|
|
option: "7"
|
|
target:
|
|
entity_id: input_select.mi_boxer_select
|
|
- conditions: "{{ trigger.id in ['7off'] }}"
|
|
sequence:
|
|
- service: light.turn_off
|
|
data: {}
|
|
target:
|
|
entity_id: light.led_strip_1
|
|
|
|
- conditions: "{{ trigger.id in ['8on'] }}"
|
|
sequence:
|
|
- service: light.turn_on
|
|
data: {}
|
|
target:
|
|
entity_id:
|
|
- light.shellydimmer_f3d426
|
|
- light.shellydimmer_d3e57c
|
|
- light.ikea_e27_tv
|
|
- light.dimmable_sm309
|
|
- light.shelly_bulb_1
|
|
- light.lidl_led_stand
|
|
- light.plug_tz_10_switch
|
|
- light.led_strip_1
|
|
- service: input_select.select_option
|
|
data:
|
|
option: "8"
|
|
target:
|
|
entity_id: input_select.mi_boxer_select
|
|
- conditions: "{{ trigger.id in ['8off'] }}"
|
|
sequence:
|
|
- service: light.turn_off
|
|
data: {}
|
|
target:
|
|
entity_id:
|
|
- light.shellydimmer_f3d426
|
|
- light.shellydimmer_d3e57c
|
|
- light.ikea_e27_tv
|
|
- light.dimmable_sm309
|
|
- light.shelly_bulb_1
|
|
- light.lidl_led_stand
|
|
- light.plug_tz_10_switch
|
|
- light.led_strip_1
|
|
|
|
- conditions: >-
|
|
{{ is_state('input_select.mi_boxer_select', '1') and trigger.id in ['bright'] }}
|
|
sequence:
|
|
- service: light.turn_on
|
|
data:
|
|
brightness_pct: "{{ trigger.to_state.state }}"
|
|
transition: 0.2
|
|
target:
|
|
entity_id: light.shellydimmer_f3d426
|
|
enabled: true
|
|
|
|
- conditions: >-
|
|
{{ is_state('input_select.mi_boxer_select', '2') and trigger.id in ['bright'] }}
|
|
sequence:
|
|
- service: light.turn_on
|
|
data:
|
|
brightness_pct: "{{ trigger.to_state.state }}"
|
|
transition: 0.2
|
|
target:
|
|
device_id: 1ff4112785e14b8b8cba18d45fec3b11
|
|
enabled: true
|
|
|
|
- conditions: >-
|
|
{{ is_state('input_select.mi_boxer_select', '3') and trigger.id in ['bright'] }}
|
|
sequence:
|
|
- service: light.turn_on
|
|
data:
|
|
brightness_pct: "{{ trigger.to_state.state }}"
|
|
transition: 0.2
|
|
target:
|
|
entity_id: light.ikea_e27_tv
|
|
enabled: true
|
|
|
|
- conditions: >-
|
|
{{ is_state('input_select.mi_boxer_select', '4') and trigger.id in ['bright'] }}
|
|
sequence:
|
|
- service: light.turn_on
|
|
data:
|
|
brightness_pct: "{{ trigger.to_state.state }}"
|
|
transition: 0.2
|
|
target:
|
|
entity_id: light.lidl_led_stand
|
|
enabled: true
|
|
|
|
- conditions: >-
|
|
{{ is_state('input_select.mi_boxer_select', '5') and trigger.id in ['bright'] }}
|
|
sequence:
|
|
- service: light.turn_on
|
|
data:
|
|
brightness_pct: "{{ trigger.to_state.state }}"
|
|
transition: 0.2
|
|
target:
|
|
entity_id: light.dimmable_sm309
|
|
enabled: true
|
|
|
|
- conditions: >-
|
|
{{ is_state('input_select.mi_boxer_select', '6') and trigger.id in ['bright'] }}
|
|
sequence:
|
|
- service: light.turn_on
|
|
data:
|
|
brightness_pct: "{{ trigger.to_state.state }}"
|
|
transition: 0.2
|
|
target:
|
|
entity_id: light.shelly_bulb_1
|
|
enabled: true
|
|
|
|
- conditions: >-
|
|
{{ is_state('input_select.mi_boxer_select', '7') and trigger.id in ['bright'] }}
|
|
sequence:
|
|
- service: light.turn_on
|
|
data:
|
|
brightness_pct: "{{ trigger.to_state.state }}"
|
|
transition: 0.2
|
|
target:
|
|
entity_id: light.led_strip_1
|
|
enabled: true
|
|
mode: restart</code></pre>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/enjoy2.jpg" width="269" height="180" /></p>";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:52:"http://canaletto.fr/post/home-assistant-and-mi-boxer";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"comments";a:1:{i:0;a:5:{s:4:"data";s:60:"http://canaletto.fr/post/home-assistant-and-mi-boxer#comment";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post.aspx?id=569246a8-f03b-4657-90f7-6b063e6def16";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:33:"jeu., 16 nov. 2023 21:29:00 +0100";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:9:"Domotique";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:34:"https://blogengine.io/schemas/tags";a:1:{s:3:"tag";a:8:{i:0;a:5:{s:4:"data";s:14:"Home Assistant";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:1;a:5:{s:4:"data";s:4:"HASS";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:2;a:5:{s:4:"data";s:6:"Hassio";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:3;a:5:{s:4:"data";s:6:"zigbee";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:4;a:5:{s:4:"data";s:11:"zigbee2mqtt";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:5;a:5:{s:4:"data";s:3:"Z2M";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:6;a:5:{s:4:"data";s:8:"Mi Boxer";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:7;a:5:{s:4:"data";s:6:"Remote";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:9:"publisher";a:1:{i:0;a:5:{s:4:"data";s:5:"Admin";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:52:"http://madskills.com/public/xml/rss/module/pingback/";a:2:{s:6:"server";a:1:{i:0;a:5:{s:4:"data";s:32:"http://canaletto.fr/pingback.axd";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:6:"target";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post.aspx?id=569246a8-f03b-4657-90f7-6b063e6def16";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:38:"http://purl.org/rss/1.0/modules/slash/";a:1:{s:8:"comments";a:1:{i:0;a:5:{s:4:"data";s:1:"0";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:53:"http://madskills.com/public/xml/rss/module/trackback/";a:1:{s:4:"ping";a:1:{i:0;a:5:{s:4:"data";s:73:"http://canaletto.fr/trackback.axd?id=569246a8-f03b-4657-90f7-6b063e6def16";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:36:"http://wellformedweb.org/CommentAPI/";a:2:{s:7:"comment";a:1:{i:0;a:5:{s:4:"data";s:60:"http://canaletto.fr/post/home-assistant-and-mi-boxer#comment";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:10:"commentRss";a:1:{i:0;a:5:{s:4:"data";s:77:"http://canaletto.fr/syndication.axd?post=569246a8-f03b-4657-90f7-6b063e6def16";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:3;a:6:{s:4:"data";s:138:"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:7:{s:0:"";a:7:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:8:"RustDesk";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:15848:"<p style="text-align: justify;">Au fil des ans TeamViewer s’est imposé dans l'IT. Au départ pseudo gratuit ce produit offre maintenant de plus en plus de fonctionnalités (souvent inutiles) et son cout augmente d’années en années. On pourrait imaginer le remplacer par AnyDesk, mais hélas leur politique est quasiment identique et ce serait reculer pour mieux sauter.</p>
|
|
<p style="text-align: justify;">Pendant le confinement certains en ont eu assez de se faire “raquetter”. Si le mot vous parait fort, constatez simplement les augmentations successives dont la dernière de 20% que rien ne justifie à mes yeux, l'éditeur se justifiant quant à lui par l'ajout de fonctionnalités qui me sont inutiles. Entendons nous bien, tout a un prix et tout travail ou service mérite une rémunération, mais tout doit rester dans la nuance, même quand on se retrouve dans une position de domination, ce qui est d'ailleurs le cas pour d'autres, comme Microsoft et ses dernières augmentations au niveau 365 ou Azure...</p>
|
|
<p style="text-align: center;"><img style="text-align: center;" src="http://canaletto.fr/image.axd?picture=/images/rustedesk_000.png" /></p>
|
|
<p style="text-align: justify;">Bref, c'est donc ainsi qu'une petite équipe de développeurs a créé <a href="https://rustdesk.com/" target="_blank" rel="noopener">RustDesk</a>. RustDesk offre les mêmes fonctionnalités de base dans le cadre de l’open source. Je teste Rustdesk depuis près d’un an et j’estime que l’heure est venue de franchir le pas.</p>
|
|
<p style="text-align: justify;">RustDesk est <a href="https://github.com/rustdesk/rustdesk/releases" target="_blank" rel="noopener">disponible</a> sous différentes distributions Linux, MacOS, Windows, Android et IOS.</p>
|
|
<h2 style="text-align: justify;">Il existe plusieurs façons d’utiliser RustDesk :</h2>
|
|
<h3 style="text-align: justify;">Version isolée sans serveur</h3>
|
|
<p style="text-align: justify;">La plus simple et totalement gratuite, mais qui présente quelques inconvénients :</p>
|
|
<ul style="text-align: justify;">
|
|
<li>Pas de chiffrement, cela veut dire que toutes les infos circulent en clair (pas sécure pour les clients, mauvaise pratique).</li>
|
|
<li>Lenteurs possibles car ça utilise les serveurs publics, ce qui reste limité.</li>
|
|
<li>Pas de carnet d’adresse synchronisé entre les devices clients. Et là ça bloque car comme beaucoup de monde j'utilise un PC fixe au bureau et un laptop quand je me déplace, sur lequel je souhaite retrouver mon environnement de travail. Ils auraient pu envisager une synchronisation de type "drive", mais cela aurait posé des questions de sécurité car en plus de synchroniser les identifiants il faut stocker des mots de passe.</li>
|
|
</ul>
|
|
<h3 style="text-align: justify;">Version gratuite avec serveur</h3>
|
|
<p style="text-align: justify;">Toujours gratuit (en dehors du cout d'un serveur VPS (qui peut être mutualisé)), et on résous la question du chiffrement :</p>
|
|
<ul style="text-align: justify;">
|
|
<li>Le serveur sert de relais (amélioration de la vitesse) et de serveur de chiffrement afin de sécuriser les liens.</li>
|
|
</ul>
|
|
<h3 style="text-align: justify;">Version payante avec serveur privé</h3>
|
|
<p style="text-align: justify;">La totale qui va <a href="https://rustdesk.com/pricing.html">couter quelques euros</a> (10 € / mois pour deux utilisateurs, ou 20 € /mois pour 20 utilisateurs + le serveur), mais à mon sens indispensable dans un cadre professionnel</p>
|
|
<ul style="text-align: justify;">
|
|
<li>Le serveur offre une console qui permet de lister les clients installés et éventuellement les partager
|
|
<ul>
|
|
<li>Seul l’admin peut activer les partages à ce stade. Partager fait remonter les ID pour un autre utilisateur, mais le mot de passe associé au device reste nécessaire.</li>
|
|
</ul>
|
|
</li>
|
|
<li>Avoir des logs, qui se connecte à quoi (dispo pour chaque utilisateur), transferts de fichiers.</li>
|
|
<li>Changer l’ID d’un client</li>
|
|
<li>Utiliser un carnet d’adresse qui sera synchronisé entre les clients de chaque utilisateur, mais non accessible à l’admin.</li>
|
|
<li>Appliquer des stratégies</li>
|
|
<li>Et d'autres fonctionnalités à venir car le projet est en constante évolution....</li>
|
|
</ul>
|
|
<p>Il n'existe pour l'instant pas de version Cloud et je n'ai pas le sentiment que ce soit dans l'ordre des priorités de l'équipe.</p>
|
|
<h2 style="text-align: justify;">Installation</h2>
|
|
<p style="text-align: justify;">Je me place ici dans le cadre de la version serveur après avoir acquis une licence.</p>
|
|
<p style="text-align: justify;">L'installation du serveur se fait sous Linux ou dans un container Docker. La procédure est décrite <a href="https://rustdesk.com/docs/en/self-host/rustdesk-server-pro/" target="_blank" rel="noopener">ici</a> et je ne vais pas la reprendre. J'ai choisit Docker pour la facilité d'un Compose...</p>
|
|
<p style="text-align: justify;">Coté client, contrairement à TeamViewer qui fonctionne uniquement avec une infrastructure cloud, RustDesk fonctionne avec une infrastructure privée si l’on veut disposer de toutes ses fonctionnalités. Quand on installe le client il va donc falloir configurer les informations liées au serveur. Ce device sera alors uniquement accessible par des clients également configurés pour ce serveur (tout au moins pour l’instant car il y a des évolutions en cours).</p>
|
|
<p style="text-align: justify;">Pour configurer le client afin qu’il soit reconnu par le serveur on a plusieurs solutions :</p>
|
|
<ul style="text-align: justify;">
|
|
<li>Soit on installe l’exe normalement et on copie la config dans ID / Relay server</li>
|
|
</ul>
|
|
<blockquote><code class="language-powershell">Qfi0TWlxGWrUdfqdsfVENxxxxxxxxxxxxxxxxxxxxxxxqfsqdfN3boJye
|
|
</code></blockquote>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/rustedesk_01.png" width="500" /></p>
|
|
<ul style="text-align: justify;">
|
|
<li>Soit on renomme l’exe d’installation afin d’y intégrer la clé, ce qui va donner quelque chose du genre:</li>
|
|
</ul>
|
|
<blockquote><code class="language-powershell">rustdesk-licensed-Qfi0TWlxGWrUkR5Vxxxxxxxdfsdfsdfsdfye.exe
|
|
</code></blockquote>
|
|
<ul style="text-align: justify;">
|
|
<li>Soit on crée un script de déploiement et ainsi appliquer la configuration après l’installation dans le cadre d’un script PowerShell, on dispose alors de ces trois commandes, et on verra plus bas ce à quoi peut ressembler un script de déploiement :<br /><br /></li>
|
|
</ul>
|
|
<h3 style="text-align: justify;">Se connecter</h3>
|
|
<p style="text-align: justify;">En général quand on utilise ce genre de produit, souvent pour de l'assistance client ou de la gestion de serveurs, il y a deux types d'installations :</p>
|
|
<ul>
|
|
<li style="text-align: center;">Le device client, le mien, sur lequel après avoir configuré le serveur (chapitre précédent), je vais me connecter avec l'identifiant fournit par l'administrateur du serveur : <br /><img src="http://canaletto.fr/image.axd?picture=/images/rustedesk_02.png" width="500" /></li>
|
|
<li style="text-align: justify;">Le device distant auquel on va affecter (ou pas) un utilisateur</li>
|
|
</ul>
|
|
<h3 style="text-align: justify;">Affecter un device à un utilisateur</h3>
|
|
<p style="text-align: justify;">Si on affecte un device à un utilisateur, cet utilisateur (et uniquement lui) verra ce device distant monter dans son logiciel client. Il pourra également l’ajouter à son carnet d’adresse personnel. Si on ne l'affecte pas, tous les utilisateurs le verront, pourront l'ajouter à leur carnet d'adresse et s'y connecter (sous réserve de disposer du mot de passe préalablement défini).</p>
|
|
<p style="text-align: justify;">Des fonctionnalités de groupe et de partage de groupe sont également prévues. Il est ainsi possible de partager les devises affectés à un groupe à un autre utilisateur. A noter que pour l'instant <code>groupe = utilisateur</code> et que l'on ne peut pas directement affecter des devices à un groupe isolé. La solution consiste donc à créer un utilisateur virtuel qui partagera ses devices avec d'autres utilisateurs. Par exemple j'ai créé un utilisateur virtuel <em>Société A</em> qui partage ses devices avec les deux personnes chargés de la maintenance de <em>Société A.</em> Ca consomme une licence utilisateur mais je n'ai pas trouvé mieux pour l'instant.</p>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/rustedesk_03.png" /></p>
|
|
<p style="text-align: justify;">Il existe plusieurs façons pour y parvenir :</p>
|
|
<ul style="text-align: justify;">
|
|
<li>En se connectant avec son user/password (mais c’est une très mauvaise idée que de faire ça sur le PC d’un client)</li>
|
|
<li>En l’associant dans l’interface d’administrateur (mais seul l’admin peut le faire)</li>
|
|
<li>En utilisant l’API sur le client dans le cadre d’un déploiement vie un script</li>
|
|
</ul>
|
|
<p style="text-align: justify;">Pour ça il faut un token. Les tokens qui permettent l’accès à l’API sont délivrés par l’admin.</p>
|
|
<pre class="language-powershell"><code>PS C:\Program Files\RustDesk>.\RustDesk.exe –assign –token "rapi_xxxxxxxxdyw==" –user_name “admin” | more</code></pre>
|
|
<h3 style="text-align: justify;">La console</h3>
|
|
<p style="text-align: justify;">Chaque utilisateur peut voir la liste de ses devices, l’état de la connexion ainsi que diverses infos (par exemple :</p>
|
|
<blockquote>
|
|
<p style="text-align: justify;"><code>ip: <a href="http://82.65.xxx.xxx">82.65.xxx.xxx</a>;<br /> version: 1.2.3;<br /> cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz, 2.53GHz, 4/4 cores; mem: 8GB</code></p>
|
|
</blockquote>
|
|
<p style="text-align: justify;">Un log est également disponible tant pour les connections que pour les transferts de fichiers. Cette console est destinée à évoluer pour plus de fonctionnalités.</p>
|
|
<p style="text-align: justify;">L'administrateur peut quant à lui, outre gérer utilisateurs et devices, affecter des stratégies aux utilisateurs et devices :</p>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/rustedesk_04.png" /></p>
|
|
<h3 style="text-align: justify;">Script PowerShell d’installation</h3>
|
|
<p style="text-align: justify;">On ne dispose pour l'instant pas de .msi et ce script est un peu simpliste (il en existe pour d'autres O/S <a href="https://rustdesk.com/docs/en/self-host/client-deployment/" target="_blank" rel="noopener">ici</a>). Pour faire simple je conseille d’ouvrir une session PS en mode admin. Mais il est également possible de faire une élévation dans le script (voir à la fin). Pour l’instant attention à indiquer la version de l'exe sur la bonne ligne…</p>
|
|
<pre class="language-yaml"><code>################################# VARIABLES #######################################
|
|
$rustdesk_pw="PasswordPermanent" # Celui du device distant
|
|
$rustdesk_token="MonTocken"
|
|
$rustdesk_cfg="Qfi0TWlxxxxxxxxxxxxxxxxxxxxxxxxxxN3boJye" # Clé de configuration
|
|
$ErrorActionPreference= 'silentlycontinue'
|
|
################################### SCRIPT ########################################
|
|
|
|
If (!(Test-Path C:\Temp))
|
|
{
|
|
New-Item -ItemType Directory -Force -Path C:\Temp > null
|
|
}
|
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
|
cd C:\Temp
|
|
Invoke-WebRequest "https://github.com/rustdesk/rustdesk/releases/download/1.2.3/rustdesk-1.2.3-x86_64.exe" -Outfile "rustdesk.exe" # Changer la version le cas échéant
|
|
|
|
Start-Process .\rustdesk.exe --silent-install # -wait
|
|
$ServiceName = 'Rustdesk'
|
|
$arrService = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
|
|
|
|
if ($arrService -eq $null)
|
|
{
|
|
Start-Sleep -seconds 20
|
|
}
|
|
cd $env:ProgramFiles\RustDesk\
|
|
$rustdesk_id = (.\RustDesk.exe --get-id | out-host)
|
|
|
|
.\RustDesk.exe --config $rustdesk_cfg | out-host
|
|
.\RustDesk.exe --password $rustdesk_pw | out-host
|
|
Start-Sleep -Seconds 5
|
|
.\RustDesk.exe --assign --token $rustdesk_token --user_name manu | out-host</code></pre>
|
|
<p style="text-align: justify;"><strong>Elévation</strong> (le cas échéant à ajouter au début du script)</p>
|
|
<pre class="language-powershell"><code>if (-Not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
|
|
if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
|
|
Start-Process PowerShell -Verb RunAs -ArgumentList "-NoProfile -ExecutionPolicy Bypass -Command `"cd '$pwd'; & '$PSCommandPath';`"";
|
|
Exit;
|
|
}
|
|
}</code></pre>
|
|
<h3 style="text-align: justify;">Le cas des serveurs Windows et du RDP</h3>
|
|
<p style="text-align: justify;">Si on installe RustDesk sur un serveur Windows va se retrouver face à deux possibilités, activer ou pas le partage de session RDP (une problématique identique existe avec TeamViewer qui a choisit de fournir deux ID, cela concerne principalement les administrateurs de serveurs, qu’ils soient premise ou cloud) :</p>
|
|
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://canaletto.fr/image.axd?picture=/images/rustedesk_05.png" /></p>
|
|
<ul style="text-align: justify;">
|
|
<li><strong>Non activé :</strong> RustDesk va proposer une ouverture de session, il est possible d’enregistrer le mot de passe dans le client, et cette ouverture de session déconnectera l’éventuel utilisateur connecté en RDP.</li>
|
|
<li><strong>Activé :</strong> Dans ce cas RustDesk partage la connexion RDP active et si on déconnecte la session RDP ça déconnecte la session RustDesk (qui peut toutefois se reconnecter s’il dispose des identifiants Windows.
|
|
<ul>
|
|
<li>Il existe toutefois un problème, dans ce mode rien ne permet actuellement de choisir la session sur laquelle va s’opérer le partage, il y a donc un risque de se concerter sur la session d’un utilisateur actif dans le cas d’un serveur de bureaux virtuels. (<a href="https://github.com/rustdesk/rustdesk-server-pro/issues/132" target="_blank" rel="noopener">ticket ouvert</a> en cours).</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
<p style="text-align: justify;"><!-- notionvc: e35aebc7-b0a2-4f1b-b7d6-44dd44071be6 --></p>
|
|
<h2 style="text-align: justify;">Conclusion</h2>
|
|
<p style="text-align: justify;">RustDesk est constante évolution et j'y reviendrait certainement ici. En attendant j'ai déployé une trentaine de devices sans observer de problèmes particulier si je compare à mon classique TeamViewer.</p>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/enjoyit.png" width="258" height="258" /></p>";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:33:"http://canaletto.fr/post/rustdesk";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"comments";a:1:{i:0;a:5:{s:4:"data";s:41:"http://canaletto.fr/post/rustdesk#comment";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post.aspx?id=e5d7b70a-11e0-4cc0-affb-00e324cf8389";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:33:"lun., 23 oct. 2023 16:13:00 +0100";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:2:{i:0;a:5:{s:4:"data";s:7:"IP & Co";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:1;a:5:{s:4:"data";s:2:"IT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:34:"https://blogengine.io/schemas/tags";a:1:{s:3:"tag";a:4:{i:0;a:5:{s:4:"data";s:10:"TeamViewer";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:1;a:5:{s:4:"data";s:7:"AnuDesk";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:2;a:5:{s:4:"data";s:9:"Rustedesk";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:3;a:5:{s:4:"data";s:3:"RDP";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:9:"publisher";a:1:{i:0;a:5:{s:4:"data";s:5:"Admin";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:52:"http://madskills.com/public/xml/rss/module/pingback/";a:2:{s:6:"server";a:1:{i:0;a:5:{s:4:"data";s:32:"http://canaletto.fr/pingback.axd";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:6:"target";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post.aspx?id=e5d7b70a-11e0-4cc0-affb-00e324cf8389";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:38:"http://purl.org/rss/1.0/modules/slash/";a:1:{s:8:"comments";a:1:{i:0;a:5:{s:4:"data";s:1:"0";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:53:"http://madskills.com/public/xml/rss/module/trackback/";a:1:{s:4:"ping";a:1:{i:0;a:5:{s:4:"data";s:73:"http://canaletto.fr/trackback.axd?id=e5d7b70a-11e0-4cc0-affb-00e324cf8389";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:36:"http://wellformedweb.org/CommentAPI/";a:2:{s:7:"comment";a:1:{i:0;a:5:{s:4:"data";s:41:"http://canaletto.fr/post/rustdesk#comment";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:10:"commentRss";a:1:{i:0;a:5:{s:4:"data";s:77:"http://canaletto.fr/syndication.axd?post=e5d7b70a-11e0-4cc0-affb-00e324cf8389";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:4;a:6:{s:4:"data";s:159:"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:7:{s:0:"";a:7:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:19:"RDP & Guacamole";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:13329:"<p style="text-align: justify;">Et non, je ne suis hélas pas parti en vacances au Mexique déguster du guacamole arrosé de téquila ! Mais j'ai trouvé la solution que je cherchait depuis longtemps pour sécuriser les accès RDP. Comme chacun le sait il n'est vraiment pas conseillé de laisser ouvert sur internet le port RDP qui est plutôt vulnérable. Hélas pensant le confinement beaucoup de clients ont du mettre en place des solutions dans l'urgence et dans bien des cas il était impossible de verrouiller au minimum ce port sur une IP fixe....</p>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/gua10.png" width="800" /></p>
|
|
<p style="text-align: justify;">Bien sur Microsoft a une solution (RDP Gateway), couteuse et complexe, donc pas adaptée à de petites entreprises dont les couts IT explosent déjà. Je restait donc en éveil à la recherche d'une solution quand je suis tombé sur le projet open-source Guacamole en HTML5. Et surprise, celui ci fonctionne vraiment bien ! Le principe est simple et reprends celui des autres projets, une machine va servir de proxy afin d'exposer le RDP (mais aussi SSH, Telnet et VNC).</p>
|
|
<h3 style="text-align: justify;">Installation</h3>
|
|
<p style="text-align: justify;"><span style="text-align: justify;">S'il est possible d'installer Guacamole en natif comme c'est très bien expliqué ici, après avoir testé différentes options, par facilité je vais faire ça sous Docker en utilisant ce </span><a style="text-align: justify;" href="https://github.com/boschkundendienst/guacamole-docker-compose" target="_blank" rel="noopener">projet</a><span style="text-align: justify;">.</span></p>
|
|
<p style="text-align: justify;"><span style="text-align: justify;">Je vais donc monter une VM Linux Ubuntu et y configurer Docker et Docker Compose. Pour cette partie je vous laisse chercher, d'autres expliquent mieux que moi.</span></p>
|
|
<p><img style="text-align: justify; display: block; margin-left: auto; margin-right: auto;" src="http://canaletto.fr/image.axd?picture=/images/gua07.png" width="600" /></p>
|
|
<p style="text-align: justify;">Pour déployer Guacamole on a besoin de 3 services :</p>
|
|
<ul style="text-align: justify;">
|
|
<li>GUACD : Le cœur de Guacamole qui va servir à connecter les différents services (RDP, SSH, etc...)</li>
|
|
<li>PostgreSQL : Une base de donnée (qui peut être également MySQL ou encore l'utilisation d'une base externe)</li>
|
|
<li>Guacamole : Le composant FrontEnd qui va gérer les connections, les services et les utilisateurs.</li>
|
|
</ul>
|
|
<p style="text-align: justify;"><strong>Docker Compose</strong></p>
|
|
<p style="text-align: justify;">L'auteur de l'intégration a eu la bonne idée de nous fournir un script d'installation. On va donc l'utiliser et on se servira de Docker Compose plus tard afin d'ajuster la configuration.</p>
|
|
<pre class="language-javascript"><code>sudo git clone "https://github.com/boschkundendienst/guacamole-docker-compose.git"
|
|
cd guacamole-docker-compose
|
|
./prepare.sh
|
|
sudo docker-compose up -d</code></pre>
|
|
<p style="text-align: justify;">Si tout se passe bien on peut se connecter sur <code>https://ip_serveur:8443/guacamole</code>. Le nom d'utilisateur par défaut est <code>guacadmin</code> avec mot de passe <code>guacadmin</code>. La première chose à faire est bien sur de le changer.</p>
|
|
<p style="text-align: justify;">On pourra facilement configurer un serveur RDP et s'y connecter pour avoir les premières impressions. Je trouve que le rendu RDP en HTML5 est fluide, même en regardant des vidéos sur YouTube à une bonne résolution. Attention à ne pas perdre de vue que c'est le serveur Guacamole qui doit encaisser le trafic entrant et sortant. Selon l'usage et le nombre de clients il faudra donc le dimensionner correctement.</p>
|
|
<p style="text-align: justify;">Je ne vais pas m'étendre sur les différentes options, l'interface et claire, la documentation également et d'autres en parlent très bien.</p>
|
|
<h3 style="text-align: justify;">Sécurisation</h3>
|
|
<p style="text-align: justify;">Il n'est bien sur pas question d'exposer ce serveur directement sur internet et je vais tester deux solutions de reverse proxy, je commence par éditer le fichier <code>docker-compose.yml</code> afin de supprimer le proxy Nginx préinstallé histoire de ne pas empiler les proxys. J'ajuste également en <code>8080:8080</code> pour une utilisation en direct et <code>REMOTE_IP_VALVE_ENABLED: 'true'</code> pour activer le proxy externe et <code>WEBAPP_CONTEXT: 'ROOT'</code> afin que Guacamole soit accessible en racine :</p>
|
|
<pre class="language-yaml"><code>version: '2.0'
|
|
networks:
|
|
guacnetwork_compose:
|
|
driver: bridge
|
|
|
|
services:
|
|
# guacd
|
|
guacd:
|
|
container_name: guacd_compose
|
|
image: guacamole/guacd
|
|
networks:
|
|
guacnetwork_compose:
|
|
restart: always
|
|
volumes:
|
|
- ./drive:/drive:rw
|
|
- ./record:/record:rw
|
|
# postgres
|
|
postgres:
|
|
container_name: postgres_guacamole_compose
|
|
environment:
|
|
PGDATA: /var/lib/postgresql/data/guacamole
|
|
POSTGRES_DB: guacamole_db
|
|
POSTGRES_PASSWORD: 'ChooseYourOwnPasswordHere1234'
|
|
POSTGRES_USER: guacamole_user
|
|
image: postgres:15.2-alpine
|
|
networks:
|
|
guacnetwork_compose:
|
|
restart: always
|
|
volumes:
|
|
- ./init:/docker-entrypoint-initdb.d:z
|
|
- ./data:/var/lib/postgresql/data:Z
|
|
|
|
guacamole:
|
|
container_name: guacamole_compose
|
|
depends_on:
|
|
- guacd
|
|
- postgres
|
|
environment:
|
|
REMOTE_IP_VALVE_ENABLED: 'true' # On active ici l'utilisation via un proxy externe
|
|
WEBAPP_CONTEXT: 'ROOT'
|
|
GUACD_HOSTNAME: guacd
|
|
POSTGRES_DATABASE: guacamole_db
|
|
POSTGRES_HOSTNAME: postgres
|
|
POSTGRES_PASSWORD: 'ChooseYourOwnPasswordHere1234'
|
|
POSTGRES_USER: guacamole_user
|
|
image: guacamole/guacamole
|
|
volumes:
|
|
- ./custom/server.xml:/home/administrator/guacamole-docker-compose/server.xml
|
|
links:
|
|
- guacd
|
|
networks:
|
|
guacnetwork_compose:
|
|
ports:
|
|
- 8080:8080
|
|
restart: always</code></pre>
|
|
<p style="text-align: justify;">Je relance docker :</p>
|
|
<pre class="language-powershell"><code>administrator@guacamole:~/guacamole-docker-compose$ sudo docker-compose up -d</code></pre>
|
|
<p style="text-align: justify;">En local je me connecte maintenant en <code>http://ip_serveur:8080</code> sans SSL car le SSL sera géré par le proxy.</p>
|
|
<h4 style="text-align: justify;">Option 1 : pfsense</h4>
|
|
<p style="text-align: justify;">J'ai un pfsense installé avec HAProxy et Acme pour gérer les certificats Lets'Encrypt, je vais donc me servir de ca pour publier le service. Sur HAProxy on configure le BackEnd et le FronteEnd qui lui utilisera le certificat préalablement créé avec Acme. Dans ma configuration je partage l'IP avec plusieurs sites et ce qui est important c'est d'activer l'option <code>forwardfor</code> qui permettra de transférer les adresses sources à Guacamole.</p>
|
|
<p style="text-align: justify;">Je mets ici le code de configuration qui sera utile à ceux qui n'utilisent pas HAProxy sous pfsense qui lui dispose d'une interface graphique. Comme on peut le constater le HTTP to HTTPS se fait au niveau du HAProxy et c'est lui également qui redirigera les requetés HTTTP vers HTTPS et mon serveur sera accessible sur <code>https://guacamole.mondomaine.tld</code> :</p>
|
|
<pre class="language-markup"><code>global
|
|
maxconn 10000
|
|
stats socket /tmp/haproxy.socket level admin expose-fd listeners
|
|
uid 80
|
|
gid 80
|
|
nbproc 1
|
|
nbthread 1
|
|
hard-stop-after 15m
|
|
chroot /tmp/haproxy_chroot
|
|
daemon
|
|
tune.ssl.default-dh-param 1024
|
|
server-state-file /tmp/haproxy_server_state
|
|
|
|
listen HAProxyLocalStats
|
|
bind 127.0.0.1:2200 name localstats
|
|
mode http
|
|
stats enable
|
|
stats admin if TRUE
|
|
stats show-legends
|
|
stats uri /haproxy/haproxy_stats.php?haproxystats=1
|
|
timeout client 5000
|
|
timeout connect 5000
|
|
timeout server 5000
|
|
|
|
frontend Shared_WAN-merged
|
|
bind x.x.x.x:443 (IP WAN) name x.x.x.x:443 (IP WAN) ssl crt-list /var/etc/haproxy/Shared_WAN.crt_list
|
|
mode http
|
|
log global
|
|
option http-keep-alive
|
|
option forwardfor
|
|
acl https ssl_fc
|
|
http-request set-header X-Forwarded-Proto http if !https
|
|
http-request set-header X-Forwarded-Proto https if https
|
|
timeout client 30000
|
|
acl Admin var(txn.txnhost) -m str -i admin.domain.tld
|
|
acl guacamole var(txn.txnhost) -m str -i guacamole.domain.tld
|
|
http-request set-var(txn.txnhost) hdr(host)
|
|
use_backend Admin_ipvANY if Admin
|
|
use_backend Guacamole_8443_ipvANY if guacamole
|
|
|
|
frontend http-to-https
|
|
bind x.x.x.x:80 (IP WAN) name x.x.x.x:80 (IP WAN)
|
|
mode http
|
|
log global
|
|
option http-keep-alive
|
|
timeout client 30000
|
|
http-request redirect code 301 location https://%[hdr(host)]%[path]
|
|
|
|
backend Admin_ipvANY
|
|
mode http
|
|
id 100
|
|
log global
|
|
timeout connect 30000
|
|
timeout server 30000
|
|
retries 3
|
|
server admin 192.168.55.44:80 id 101
|
|
|
|
backend Guacamole_8443_ipvANY
|
|
mode http
|
|
id 102
|
|
log global
|
|
timeout connect 30000
|
|
timeout server 30000
|
|
retries 3
|
|
server guacamole 192.168.66.55:8080 id 101</code></pre>
|
|
<h4 style="text-align: justify;">Option 2 : CloudFlared</h4>
|
|
<p style="text-align: justify;">Cette option est encore plus simple pour ceux qui disposent d'un domaine chez Cloudflare. On va utiliser les possibilités offertes gratuitement par Cloudflared et ajouter une couche de sécurité supplémentaire.</p>
|
|
<p style="text-align: justify;">On commence par créer un tunnel CloudFlared avec une instance Docker supplémentaire (le code est fournit par le site de configuration Zero Trust de Cloudflare)</p>
|
|
<pre class="language-yaml"><code>docker run cloudflare/cloudflared:latest tunnel --no-autoupdate run --token eyJhIjoiZjk0YjdkZTBiMzFmYWNkNjZlshhsgfhsfghsgfhgfhssgfhsfgzRiMC00MmNlLWJjMghsfghsghsgfhsgfhsgfhsgmpaR00tyyretu(-yenebybvewWXpGaUxUazVNell0TnpRek56WXhNMlkxWXpFeiJ9</code></pre>
|
|
<p style="text-align: justify;">Ensuite une fois que le tunnel est monté</p>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/gua01.png" alt="" width="800" height="338" /></p>
|
|
<p style="text-align: justify;">On va publier et pointant sur l'ip privée et le port de notre serveur, cela va automatiquement créer l'entrée DNS dans CloudFlare et gérer la problématique du certificat. Ll sera accessible en SSL. :</p>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/gua02.png" width="800" /></p>
|
|
<p style="text-align: justify;">Ensuite on va ajouter une couche de sécurité supplémentaire en créant une application de type SelfHosted à laquelle on affecte une policie qui impose un code supplémentaire lors d'une connexion. Ce code sera envoyé sur le mail de l'utilisateur sur une adresse individuelle ou un domaine spécifique. Ce n'est pas tout à fait du MFA, mais on considère que si l'utilisateur reçoit bien le code sur son mail professionnel, il s'agit bien de lui et on peut lui permettre de saisir son login / password pour accéder au service :</p>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/gua03.png" width="600" /></p>
|
|
<p style="text-align: justify;">C'est la méthode la plus simple et de nombreuses option sont exploitables, de même qu'il est possible d'utiliser de nombreux providers externes d'authentification :</p>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/gua04.png" width="600" /></p>
|
|
<p style="text-align: justify;">Lorsqu'il souhaite se connecter, l'utilisateur tombe sur un portail que l'on peu personnaliser aux couleurs de l'entreprise.</p>
|
|
<p style="text-align: justify;">Voilà, et surtout maintenant on retrouve bien les IP publiques dans le log de Guacamole :</p>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/gua05.png" width="800" /></p>
|
|
<p style="text-align: justify;">Il n'y a plus qu'a ajuster les différentes options de Guacamole et pour ça la <a href="https://guacamole.apache.org/doc/gug/introduction.html" target="_blank" rel="noopener">documentation</a> est très bien faite. Et bien sur si on se sert de Guacamole pour exposer des serveurs RDP accessibles sur l'internet on prendra soin de restreindre leur usage à l'IP publique du serveur Guacamole, ou mieux de faire transiter ce flux par un tunnel (Wireguard, Tailscale ou Zerotier par exemple que l'on peu facilement installer sur les deux serveurs).</p>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/ThatsAllFolks.jpg" width="439" height="439" /></p>";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:42:"http://canaletto.fr/post/rdp-and-guacamole";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"comments";a:1:{i:0;a:5:{s:4:"data";s:50:"http://canaletto.fr/post/rdp-and-guacamole#comment";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post.aspx?id=07488d65-ada0-4c38-95a7-d5dc8f054d2c";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:33:"ven., 30 juin 2023 15:04:00 +0100";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:2:{i:0;a:5:{s:4:"data";s:7:"IP & Co";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:1;a:5:{s:4:"data";s:2:"IT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:34:"https://blogengine.io/schemas/tags";a:1:{s:3:"tag";a:7:{i:0;a:5:{s:4:"data";s:10:"Cloudflare";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:1;a:5:{s:4:"data";s:11:"CloudFlared";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:2;a:5:{s:4:"data";s:9:"Guacamole";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:3;a:5:{s:4:"data";s:3:"RDP";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:4;a:5:{s:4:"data";s:3:"SSH";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:5;a:5:{s:4:"data";s:5:"Proxy";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:6;a:5:{s:4:"data";s:13:"Reverse Proxy";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:9:"publisher";a:1:{i:0;a:5:{s:4:"data";s:5:"Admin";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:52:"http://madskills.com/public/xml/rss/module/pingback/";a:2:{s:6:"server";a:1:{i:0;a:5:{s:4:"data";s:32:"http://canaletto.fr/pingback.axd";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:6:"target";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post.aspx?id=07488d65-ada0-4c38-95a7-d5dc8f054d2c";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:38:"http://purl.org/rss/1.0/modules/slash/";a:1:{s:8:"comments";a:1:{i:0;a:5:{s:4:"data";s:1:"1";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:53:"http://madskills.com/public/xml/rss/module/trackback/";a:1:{s:4:"ping";a:1:{i:0;a:5:{s:4:"data";s:73:"http://canaletto.fr/trackback.axd?id=07488d65-ada0-4c38-95a7-d5dc8f054d2c";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:36:"http://wellformedweb.org/CommentAPI/";a:2:{s:7:"comment";a:1:{i:0;a:5:{s:4:"data";s:50:"http://canaletto.fr/post/rdp-and-guacamole#comment";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:10:"commentRss";a:1:{i:0;a:5:{s:4:"data";s:77:"http://canaletto.fr/syndication.axd?post=07488d65-ada0-4c38-95a7-d5dc8f054d2c";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:5;a:6:{s:4:"data";s:145:"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:7:{s:0:"";a:7:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:29:"Home Assistant & Arrosage";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:14191:"<p style="text-align: justify;">Je n'ai pas vraiment la main verte et et mon jardin ressemble souvent à un no man's land, mais au printemps dernier une amie m'a convaincu de créer un carré d'herbes aromatiques, l'idée à fait son chemin et au centre on a même planté des plants de tomates qui produisent bien cet été ! Bon, vous imaginez bien que je ne vais pas ici vous conter ma vie privée mais plutôt la part domotique de cette réalisation !</p>
|
|
<p style="text-align: justify;">En Provence, si on veut un peu de verdure et espérer manger ses propres tomates, il n'y a pas de secret, il faut arroser ! J'ai donc commencé par disposer un tuyau poreux sur mon carré. Ensuite j'ai acheté un robinet Zigbee et préparé un petit scheduler qui me permet facilement d'activer ou pas la plage journalière d'arrosage. J'ai fait quelque chose de simple en m'inspirant de ce que j'avais fait pour <a href="http://canaletto.fr/post/home-assistant-and-ecs" target="_blank" rel="noopener">mon chauffe eau</a>. Je publie ici le code suite à quelques demandes, même si ça n'a pas une grande valeur ajoutée.</p>
|
|
<p><img style="text-align: center; display: block; margin-left: auto; margin-right: auto;" src="http://canaletto.fr/image.axd?picture=/images/arrosage_1.png" width="400" /></p>
|
|
<p style="text-align: justify;">Pour l'instant ça ne prends pas en compte les valeurs remontés sur les capteurs de plantes car je n'en suis pas satisfait.</p>
|
|
<p style="text-align: justify;">L'offre en matière de capteurs de plantes n'est pas énorme :</p>
|
|
<ul style="text-align: justify;">
|
|
<li><strong>Le capteur Xiaomi</strong> (ou ses copies) qui fonctionnent en Bluetooth et que l'on trouve sur <a href="https://amzn.to/3r3MPV4" target="_blank" rel="noopener">Amazon</a> ou Ali Express : C'est ce qui fonctionne le "mieux", mais cela nécessite un <a href="http://canaletto.fr/post/home-assistant-and-ble-proxy" target="_blank" rel="noopener">proxy BLE</a> à l'extérieur que l'on peut facilement se bricoler avec un ESP sous ESPHome.</li>
|
|
<li><strong>Le capteur Rehent</strong> en Zigbee que j'ai acheté chez Domadoo : Et là c'est la déconvenue. Il est un peu encombrant mais ne pose pas de soucis particulier pour l'appairer en ZHA ou Z2M (ou sur une passerelle Tuya), sauf que si ce capteur remonte parfaitement la température du sol, l'humidité du sol reste invariablement entre 75% et 85% (voir les sources au bas de cet article). Et bien sur chez Domadoo on est pas chez Amazon, le client a tort et l'éventuel retour est à votre charge. Bref capteur et fournisseur à éviter ! Il semblerait qu'autres séries de ce capteur que l'on trouve chez AliExpress fonctionnent, mais là il faudra aussi oublier le retour...</li>
|
|
</ul>
|
|
<p style="text-align: justify;">J'utilise une vanne Zigbee <a href="https://amzn.to/45QexEA" target="_blank" rel="noopener">Woox</a> qui alimente le tuyaux poreux (que je devrais remplacer par un un goute à goute). Pour avoir un réseau Zigbee fiable à l'extérieur, j'ai installé sous la toiture de la terrasse des prises Zigbee dont le relais est HS mais qui continuent à remplir parfaitement leur rôle de routeur Zigbee.</p>
|
|
<p style="text-align: justify;">Tout cela reste très expérimental... Coté intégration j'utilise <a href="https://github.com/Olen/homeassistant-plant" target="_blank" rel="noopener">Home Assistant Plant</a> et la <a href="https://github.com/Olen/lovelace-flower-card" target="_blank" rel="noopener">carte</a> qui va avec.</p>
|
|
<h3 style="text-align: justify;">Automation</h3>
|
|
<p style="text-align: justify;">Une automation de schedule simple et visuelle :</p>
|
|
<pre class="language-yaml"><code>input_datetime:
|
|
watering_start:
|
|
has_date: false
|
|
has_time: true
|
|
watering_stop:
|
|
has_date: false
|
|
has_time: true
|
|
|
|
input_boolean:
|
|
watering_day_monday:
|
|
name: "WATERING : Lundi"
|
|
icon: mdi:toggle-switch
|
|
watering_day_tuesday:
|
|
name: "WATERING : Mardi"
|
|
icon: mdi:toggle-switch
|
|
watering_day_wednesday:
|
|
name: "WATERING : Mercredi"
|
|
icon: mdi:toggle-switch
|
|
watering_day_thursday:
|
|
name: "WATERING : Jeudi"
|
|
icon: mdi:toggle-switch
|
|
watering_day_friday:
|
|
name: "WATERING : Vendredi"
|
|
icon: mdi:toggle-switch
|
|
watering_day_saturday:
|
|
name: "WATERING : Samedi"
|
|
icon: mdi:toggle-switch
|
|
watering_day_sunday:
|
|
name: "WATERING : Dimanche"
|
|
icon: mdi:toggle-switch
|
|
|
|
automation:
|
|
|
|
- id: 'xx8d0e1-fcb6-4412-abvxx-99c4d37be5xx'
|
|
alias: 'WATERING ON'
|
|
trigger:
|
|
- platform: template
|
|
value_template: '{{ states.sensor.time.state == states.input_datetime.watering_start.state[0:5] }}'
|
|
condition:
|
|
condition: or
|
|
conditions:
|
|
- '{{ (now().strftime("%a") == "Mon") and is_state("input_boolean.watering_day_monday", "on") }}'
|
|
- '{{ (now().strftime("%a") == "Tue") and is_state("input_boolean.watering_day_tuesday", "on") }}'
|
|
- '{{ (now().strftime("%a") == "Wed") and is_state("input_boolean.watering_day_wednesday", "on") }}'
|
|
- '{{ (now().strftime("%a") == "Thu") and is_state("input_boolean.watering_day_thursday", "on") }}'
|
|
- '{{ (now().strftime("%a") == "Fri") and is_state("input_boolean.watering_day_friday", "on") }}'
|
|
- '{{ (now().strftime("%a") == "Sat") and is_state("input_boolean.watering_day_saturday", "on") }}'
|
|
- '{{ (now().strftime("%a") == "Sun") and is_state("input_boolean.watering_day_sunday", "on")}}'
|
|
action:
|
|
- service: switch.turn_on
|
|
entity_id: switch.vanne_woox_switch
|
|
- service: notify.slack_hass_canaletto
|
|
data:
|
|
message: "{{now().strftime('%d/%m/%Y, %H:%M')}} > WATERING | START | Soil : {{ states.sensor.soil_01_soil_moisture.state }}%"
|
|
|
|
|
|
- id: 'zz9csdfsef-76dd-4fdd-9dzz-40bfsdq158zz'
|
|
alias: 'WATERING OFF'
|
|
trigger:
|
|
- platform: template
|
|
value_template: '{{ states.sensor.time.state == states.input_datetime.watering_stop.state[0:5] }}'
|
|
action:
|
|
- service: switch.turn_off
|
|
entity_id: switch.vanne_woox_switch
|
|
- service: notify.slack_hass_canaletto
|
|
data:
|
|
message: "{{now().strftime('%d/%m/%Y, %H:%M')}} > WATERING | STOP | Soil : {{ states.sensor.soil_01_soil_moisture.state }}%" </code></pre>
|
|
<p style="text-align: justify;">La carte Lovelace :</p>
|
|
<pre class="language-yaml"><code>type: vertical-stack
|
|
cards:
|
|
- type: entities
|
|
entities:
|
|
- entities:
|
|
- entity: automation.watering_on
|
|
name: false
|
|
- entity: sensor.energy_total_yearly_1pm_watering
|
|
name: false
|
|
unit: kWh
|
|
format: precision2
|
|
- entity: sensor.soil_01_soil_moisture
|
|
name: false
|
|
entity: switch.vanne_woox_switch
|
|
name: Arrosage
|
|
icon: mdi:watering-can-outline
|
|
show_state: false
|
|
state_color: true
|
|
type: custom:multiple-entity-row
|
|
- type: horizontal-stack
|
|
cards:
|
|
- type: custom:button-card
|
|
color_type: card
|
|
entity: input_boolean.watering_day_monday
|
|
name: Lundi
|
|
show_last_changed: false
|
|
show_state: false
|
|
tap_action:
|
|
action: toggle
|
|
state:
|
|
- value: 'on'
|
|
color: green
|
|
icon: mdi:water-boiler
|
|
- value: 'off'
|
|
color: grey
|
|
icon: mdi:water-boiler-off
|
|
styles:
|
|
card:
|
|
- height: 60px
|
|
- border-radius: 5px
|
|
- font-size: 12px
|
|
- type: custom:button-card
|
|
color_type: card
|
|
entity: input_boolean.watering_day_tuesday
|
|
name: Mardi
|
|
show_last_changed: false
|
|
show_state: false
|
|
tap_action:
|
|
action: toggle
|
|
state:
|
|
- value: 'on'
|
|
color: green
|
|
icon: mdi:water-boiler
|
|
- value: 'off'
|
|
color: grey
|
|
icon: mdi:water-boiler-off
|
|
styles:
|
|
card:
|
|
- height: 60px
|
|
- border-radius: 5px
|
|
- font-size: 12px
|
|
- type: custom:button-card
|
|
color_type: card
|
|
entity: input_boolean.watering_day_wednesday
|
|
name: Mercredi
|
|
show_last_changed: false
|
|
show_state: false
|
|
tap_action:
|
|
action: toggle
|
|
state:
|
|
- value: 'on'
|
|
color: green
|
|
icon: mdi:water-boiler
|
|
- value: 'off'
|
|
color: grey
|
|
icon: mdi:water-boiler-off
|
|
styles:
|
|
card:
|
|
- height: 60px
|
|
- border-radius: 5px
|
|
- font-size: 12px
|
|
- type: custom:button-card
|
|
color_type: card
|
|
entity: input_boolean.watering_day_thursday
|
|
name: Jeudi
|
|
show_last_changed: false
|
|
show_state: false
|
|
tap_action:
|
|
action: toggle
|
|
state:
|
|
- value: 'on'
|
|
color: green
|
|
icon: mdi:water-boiler
|
|
- value: 'off'
|
|
color: grey
|
|
icon: mdi:water-boiler-off
|
|
styles:
|
|
card:
|
|
- height: 60px
|
|
- border-radius: 5px
|
|
- font-size: 12px
|
|
- type: custom:button-card
|
|
color_type: card
|
|
entity: input_boolean.watering_day_friday
|
|
name: Vendredi
|
|
show_last_changed: false
|
|
show_state: false
|
|
tap_action:
|
|
action: toggle
|
|
state:
|
|
- value: 'on'
|
|
color: green
|
|
icon: mdi:water-boiler
|
|
- value: 'off'
|
|
color: grey
|
|
icon: mdi:water-boiler-off
|
|
styles:
|
|
card:
|
|
- height: 60px
|
|
- border-radius: 5px
|
|
- font-size: 12px
|
|
- type: custom:button-card
|
|
color_type: card
|
|
entity: input_boolean.watering_day_saturday
|
|
name: Samedi
|
|
show_last_changed: false
|
|
show_state: false
|
|
tap_action:
|
|
action: toggle
|
|
state:
|
|
- value: 'on'
|
|
color: green
|
|
icon: mdi:water-boiler
|
|
- value: 'off'
|
|
color: grey
|
|
icon: mdi:water-boiler-off
|
|
styles:
|
|
card:
|
|
- height: 60px
|
|
- border-radius: 5px
|
|
- font-size: 12px
|
|
- type: custom:button-card
|
|
color_type: card
|
|
entity: input_boolean.watering_day_sunday
|
|
name: Dimanche
|
|
show_last_changed: false
|
|
show_state: false
|
|
tap_action:
|
|
action: toggle
|
|
state:
|
|
- value: 'on'
|
|
color: green
|
|
icon: mdi:water-boiler
|
|
- value: 'off'
|
|
color: grey
|
|
icon: mdi:water-boiler-off
|
|
styles:
|
|
card:
|
|
- height: 60px
|
|
- border-radius: 5px
|
|
- font-size: 12px
|
|
- type: conditional
|
|
conditions:
|
|
- entity: automation.watering_on
|
|
state: 'on'
|
|
card:
|
|
type: custom:vertical-stack-in-card
|
|
cards:
|
|
- type: horizontal-stack
|
|
cards:
|
|
- type: markdown
|
|
content: '#### <center> Heure de début'
|
|
- type: markdown
|
|
content: '#### <center> Arrosage'
|
|
- type: markdown
|
|
content: '#### <center> Heure de Fin'
|
|
- type: horizontal-stack
|
|
cards:
|
|
- entity: input_datetime.watering_start
|
|
type: custom:time-picker-card
|
|
name: Début
|
|
layout:
|
|
align_controls: center
|
|
embedded: true
|
|
hide:
|
|
name: true
|
|
icon: true
|
|
- type: glance
|
|
show_state: true
|
|
show_name: false
|
|
entities:
|
|
- switch.vanne_woox_switch
|
|
- entity: input_datetime.watering_stop
|
|
type: custom:time-picker-card
|
|
layout:
|
|
align_controls: center
|
|
embedded: true
|
|
hide:
|
|
name: true
|
|
icon: true
|
|
- color_thresholds:
|
|
- color: '#039BE5'
|
|
value: 0
|
|
- color: '#0da035'
|
|
value: 19
|
|
- color: '#e0b400'
|
|
value: 25
|
|
- color: '#e45e65'
|
|
value: 2400
|
|
color_thresholds_transition: hard
|
|
entities:
|
|
- entity: sensor.plant_01_moisture
|
|
name: Humidité du sol
|
|
- entity: sensor.plant_01_temperature
|
|
name: Températire du sol
|
|
- color: rgba(0,0,255,1)
|
|
entity: binary_sensor.night_reworked
|
|
name: Nuit
|
|
show_line: false
|
|
y_axis: secondary
|
|
group: false
|
|
hour24: true
|
|
hours_to_show: 24
|
|
line_width: 2
|
|
name: Humidité et température du sol
|
|
points_per_hour: 4
|
|
show:
|
|
extrema: true
|
|
fill: fade
|
|
icon: true
|
|
labels: false
|
|
name: true
|
|
state: true
|
|
state_map:
|
|
- label: Day
|
|
value: 'off'
|
|
- label: Night
|
|
value: 'on'
|
|
type: custom:mini-graph-card
|
|
- type: custom:flower-card
|
|
entity: plant.jardin
|
|
show_bars:
|
|
- illuminance
|
|
- humidity
|
|
- moisture
|
|
- conductivity
|
|
- temperature
|
|
- dli
|
|
battery_sensor: sensor.demo_battery</code></pre>
|
|
<h3>Souces</h3>
|
|
<h4>Capteur Rehent</h4>
|
|
<ul>
|
|
<li><a href="https://smarthomescene.com/reviews/tuya-zigbee-plant-soil-sensor-gxm-01-review/">https://smarthomescene.com/reviews/tuya-zigbee-plant-soil-sensor-gxm-01-review/</a></li>
|
|
<li><a href="https://community.home-assistant.io/t/tze200-myd45weu-ts0601-with-zha-error-tuya-model/550381">https://community.home-assistant.io/t/tze200-myd45weu-ts0601-with-zha-error-tuya-model/550381</a></li>
|
|
<li><a href="https://community.jeedom.com/t/capteur-humidite-du-sol-en-zigbee/105716">https://community.jeedom.com/t/capteur-humidite-du-sol-en-zigbee/105716</a></li>
|
|
<li><a href="https://community.jeedom.com/t/demande-ajout-module-capteur-humidite-sol-tuya/101614/24">https://community.jeedom.com/t/demande-ajout-module-capteur-humidite-sol-tuya/101614/24</a></li>
|
|
</ul>
|
|
<p> </p>";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:52:"http://canaletto.fr/post/home-assistant-and-arrosage";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"comments";a:1:{i:0;a:5:{s:4:"data";s:60:"http://canaletto.fr/post/home-assistant-and-arrosage#comment";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post.aspx?id=73d63065-74d4-46d9-a913-740f09593ea0";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:32:"mer., 7 juin 2023 20:21:00 +0100";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:9:"Domotique";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:34:"https://blogengine.io/schemas/tags";a:1:{s:3:"tag";a:6:{i:0;a:5:{s:4:"data";s:14:"Home Assistant";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:1;a:5:{s:4:"data";s:4:"HASS";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:2;a:5:{s:4:"data";s:5:"Plant";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:3;a:5:{s:4:"data";s:4:"Soil";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:4;a:5:{s:4:"data";s:8:"Arrosage";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:5;a:5:{s:4:"data";s:8:"Watering";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:9:"publisher";a:1:{i:0;a:5:{s:4:"data";s:5:"Admin";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:52:"http://madskills.com/public/xml/rss/module/pingback/";a:2:{s:6:"server";a:1:{i:0;a:5:{s:4:"data";s:32:"http://canaletto.fr/pingback.axd";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:6:"target";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post.aspx?id=73d63065-74d4-46d9-a913-740f09593ea0";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:38:"http://purl.org/rss/1.0/modules/slash/";a:1:{s:8:"comments";a:1:{i:0;a:5:{s:4:"data";s:1:"1";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:53:"http://madskills.com/public/xml/rss/module/trackback/";a:1:{s:4:"ping";a:1:{i:0;a:5:{s:4:"data";s:73:"http://canaletto.fr/trackback.axd?id=73d63065-74d4-46d9-a913-740f09593ea0";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:36:"http://wellformedweb.org/CommentAPI/";a:2:{s:7:"comment";a:1:{i:0;a:5:{s:4:"data";s:60:"http://canaletto.fr/post/home-assistant-and-arrosage#comment";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:10:"commentRss";a:1:{i:0;a:5:{s:4:"data";s:77:"http://canaletto.fr/syndication.axd?post=73d63065-74d4-46d9-a913-740f09593ea0";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:6;a:6:{s:4:"data";s:131:"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:7:{s:0:"";a:7:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:34:"Home Assistant & Plug Security";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:6180:"<p style="text-align: justify;">On utilise souvent des prises commandées uniquement pour mesurer la consommation de certains appareils. Ces prises sont toujours en position ON. Ces prises, si elles ne sont pas de trop mauvaise qualité un mécanisme de sécurité intégré qui les passent OFF en cas de surtension ou de surcharge. Et dans la pratique ça arrive parfois et on constate plus tard que le lave linge ou le lave vaisselle s'est arrêté, ou pire dans le cas d'un congélateur.</p>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/blitzwolf_bw_shp13_small.jpg" width="290" height="220" /></p>
|
|
<p style="text-align: justify;">Pour palier à cet inconvénient on va créer une automation qui va réarmer la prise après quelques minutes en OFF. Jusque là c'est simple, mais il se peut également que le problème soit plus grave et qu'il ne faille pas forcer indéfiniment ce réarmement automatique. Etant donné qu'on ne dispose généralement pas d'information sur la cause de ce passage en sécurité on va considérer qu'au bout de "n" tentatives sur un temps donné on ne réarme plus. Pour ça on va utiliser des compteurs (à créer avec un minimum à 0 et un maximum à 10) et on fera un reset de ceux-ci toutes les nuits...</p>
|
|
<p style="text-align: justify;">J'ai fixé ici arbitrairement à 5 le nombre de réarmements possibles.</p>
|
|
<p style="text-align: justify;"><span style="background-color: #f8cac6;"><strong>Attention :</strong> Je vous explique ici comment j'ai fait, mais un risque existe toujours et la mise en œuvre de cette solution est à vos risques (et périls). Je me dégage ainsi de toute responsabilité.</span></p>
|
|
<p style="text-align: justify;">On va faire ça avec une seule automation que j'ai voulue la plus concise et qui servira également à notifier :</p>
|
|
<pre class="language-yaml"><code>automation:
|
|
- id: '2bd0ertyyf-2687-45f98f-aed0-to-off'
|
|
alias: "Notify Plug Off"
|
|
description: "Notification mise en sécurité des prises"
|
|
mode: single
|
|
trigger:
|
|
- platform: state
|
|
entity_id: switch.bw_1
|
|
to: "off"
|
|
id: "Lave Vaisselle"
|
|
- platform: state
|
|
entity_id: switch.bw_2
|
|
to: "off"
|
|
id: "Lave Linge"
|
|
- platform: state
|
|
entity_id: switch.bw_3
|
|
to: "off"
|
|
id: "Seche Linge"
|
|
- platform: state
|
|
entity_id: switch.bw_4
|
|
to: "off"
|
|
id: "Congelateur"
|
|
- platform: time
|
|
at: "00:05:00"
|
|
id: "Reset"
|
|
condition: []
|
|
action:
|
|
- delay:
|
|
hours: 0
|
|
minutes: 5
|
|
seconds: 0
|
|
milliseconds: 0
|
|
- choose:
|
|
- conditions: "{{ trigger.id in ['Lave Vaisselle'] and states('counter.plug_bw_1') | int < 5 }}"
|
|
sequence:
|
|
- service: switch.turn_on
|
|
target:
|
|
entity_id: switch.bw_1
|
|
- service: counter.increment
|
|
target:
|
|
entity_id: counter.plug_bw_1
|
|
- service: notify.slack_hass_mondon
|
|
data:
|
|
message: "{{now().strftime('%d/%m/%Y, %H:%M:%S')}} > Réarmement n°{{ states('counter.plug_bw_1')}} du {{ trigger.id }}"
|
|
|
|
- conditions: "{{ trigger.id in ['Lave Linge'] and states('counter.plug_bw_2') | int < 5 }}"
|
|
sequence:
|
|
- service: switch.turn_on
|
|
target:
|
|
entity_id: switch.bw_2
|
|
- service: counter.increment
|
|
target:
|
|
entity_id: counter.plug_bw_2
|
|
- service: notify.slack_hass_mondon
|
|
data:
|
|
message: "{{now().strftime('%d/%m/%Y, %H:%M:%S')}} > Réarmement n°{{ states('counter.plug_bw_2')}} du {{ trigger.id }}"
|
|
|
|
- conditions: "{{ trigger.id in ['Seche Linge'] and states('counter.plug_bw_3') | int < 5 }}"
|
|
sequence:
|
|
- service: switch.turn_on
|
|
target:
|
|
entity_id: switch.bw_3
|
|
- service: counter.increment
|
|
target:
|
|
entity_id: counter.plug_bw_3
|
|
- service: notify.slack_hass_mondon
|
|
data:
|
|
message: "{{now().strftime('%d/%m/%Y, %H:%M:%S')}} > Réarmement n°{{ states('counter.plug_bw_3')}} du {{ trigger.id }}"
|
|
|
|
- conditions: "{{ trigger.id in ['Congelateur'] and states('counter.plug_bw_4') | int < 5 }}"
|
|
sequence:
|
|
- service: switch.turn_on
|
|
target:
|
|
entity_id: switch.bw_4
|
|
- service: counter.increment
|
|
target:
|
|
entity_id: counter.plug_bw_3
|
|
- service: notify.slack_hass_mondon
|
|
data:
|
|
message: "{{now().strftime('%d/%m/%Y, %H:%M:%S')}} > Réarmement n°{{ states('counter.plug_bw_4')}} du {{ trigger.id }}"
|
|
|
|
- conditions:
|
|
- condition: or
|
|
conditions:
|
|
- "{{ trigger.id in ['Lave Vaisselle'] and states('counter.plug_bw_1') | int >= 5 }}"
|
|
- "{{ trigger.id in ['Lave Linge'] and states('counter.plug_bw_2') | int >= 5 }}"
|
|
- "{{ trigger.id in ['Seche Linge'] and states('counter.plug_bw_3') | int >= 5 }}"
|
|
- "{{ trigger.id in ['Congelateur'] and states('counter.plug_bw_4') | int >= 5 }}"
|
|
sequence:
|
|
- service: notify.slack_hass_mondon
|
|
data:
|
|
message: "{{now().strftime('%d/%m/%Y, %H:%M:%S')}} > Problème avec le {{ trigger.id }}. On ne réarme plus, une vérification s'impose."
|
|
|
|
- conditions: "{{ trigger.id in ['Reset'] }}"
|
|
sequence:
|
|
- service: counter.reset
|
|
target:
|
|
entity_id:
|
|
- counter.plug_bw_1
|
|
- counter.plug_bw_2
|
|
- counter.plug_bw_3
|
|
- counter.plug_bw_4</code></pre>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/enjoy2.jpg" width="302" height="202" /></p>";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:57:"http://canaletto.fr/post/home-assistant-and-plug-security";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"comments";a:1:{i:0;a:5:{s:4:"data";s:65:"http://canaletto.fr/post/home-assistant-and-plug-security#comment";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post.aspx?id=3b6db46a-58aa-41b8-a651-23fda8859b7a";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:32:"dim., 4 juin 2023 17:03:00 +0100";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:9:"Domotique";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:34:"https://blogengine.io/schemas/tags";a:1:{s:3:"tag";a:4:{i:0;a:5:{s:4:"data";s:4:"HASS";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:1;a:5:{s:4:"data";s:14:"Home Assistant";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:2;a:5:{s:4:"data";s:6:"Prises";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:3;a:5:{s:4:"data";s:5:"Plug ";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:9:"publisher";a:1:{i:0;a:5:{s:4:"data";s:5:"Admin";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:52:"http://madskills.com/public/xml/rss/module/pingback/";a:2:{s:6:"server";a:1:{i:0;a:5:{s:4:"data";s:32:"http://canaletto.fr/pingback.axd";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:6:"target";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post.aspx?id=3b6db46a-58aa-41b8-a651-23fda8859b7a";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:38:"http://purl.org/rss/1.0/modules/slash/";a:1:{s:8:"comments";a:1:{i:0;a:5:{s:4:"data";s:1:"0";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:53:"http://madskills.com/public/xml/rss/module/trackback/";a:1:{s:4:"ping";a:1:{i:0;a:5:{s:4:"data";s:73:"http://canaletto.fr/trackback.axd?id=3b6db46a-58aa-41b8-a651-23fda8859b7a";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:36:"http://wellformedweb.org/CommentAPI/";a:2:{s:7:"comment";a:1:{i:0;a:5:{s:4:"data";s:65:"http://canaletto.fr/post/home-assistant-and-plug-security#comment";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:10:"commentRss";a:1:{i:0;a:5:{s:4:"data";s:77:"http://canaletto.fr/syndication.axd?post=3b6db46a-58aa-41b8-a651-23fda8859b7a";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:7;a:6:{s:4:"data";s:131:"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:7:{s:0:"";a:7:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:25:"Tailscale Access Controls";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:5420:"<p style="text-align: justify;">J'ai souvent parlé de Zerotier que j'utilise au quotidien, mais qui dans sa version gratuite comporte quelques limitations en terme de contrôle d'accès dans un environnement mixant du site-to-site et des clients isolés. J'ai donc voulut voir ce que proposait <a href="https://tailscale.com/" target="_blank" rel="noopener">Tailscale</a>, qui est un VPN managé relativement similaire reposant sur Wireguard. Tous deux offrent des fonctionnalités gratuites et payantes. Si payer ne doit pas être un problème dans un environnement de production, c'est un peu différent en mode home lab.... d'autant plus que certaines fonctionnalités de la version gratuite ne se retrouvent que dans la <a href="https://tailscale.com/pricing/" target="_blank" rel="noopener">version Premium</a> à $18 /mois/utilisateur.</p>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/tailscale.png" width="250" height="51" /></p>
|
|
<p style="text-align: justify;">La version gratuite des Tailscale est plutôt généreuse, elle propose 100 nodes et 3 utilisateurs (à condition de disposer d'un "custom domain" (je vais utiliser des comptes Microsoft 365, mais plusieurs autres possibilités sont disponibles : <a href="https://tailscale.com/kb/1013/sso-providers/" target="_blank" rel="noopener">SSO Identity Providers</a>). On peut donc disposer de 3 comptes sur un même domaine. Je parle de comptes car nativement (et normalement) le contrôle d'accès se fait sur l'utilisateur. Manque de chance j'ai besoin de gérer 4 utilisateurs, et je ne suis pas prêt à payer 4 x $18, ce qui me ferait plus de $ 800 par an !</p>
|
|
<p style="text-align: justify;">J'ai donc cherché à contourner et je vais finalement gérer mes autorisations à partir des machines Tailscale que j'ai approuvées (mode NFS pour ceux qui se souviennent). Dans cet usage je ne cherche pas faire communiquer les clients Tailscale entre eux mais à leur permettre d'accéder à des ressources situées sur différents subnets sur lesquels je souhaite restreindre les possibilités.</p>
|
|
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://canaletto.fr/image.axd?picture=/images/tailscale-subnet.png" width="698" height="445" /></p>
|
|
<p style="text-align: justify;">Pour la suite on considère que le réseaux Tailscale est configuré avec les nodes qui servent à joindre les subnets.</p>
|
|
<p style="text-align: justify;">Je vais créer deux utilisateurs :</p>
|
|
<pre class="language-yaml"><code>admin@canaletto.fr
|
|
user@canaletto.fr</code></pre>
|
|
<p style="text-align: justify;">Le premier compte qui sera également le mien va également me permettre de configurer et approuver les machines clientes.</p>
|
|
<p style="text-align: justify;">Le second servira à connecter mes utilisateurs et je pourrais approuver leurs machines. Ce compte étant protégé en MFA, il nécessitera une validation de ma part. Une fois la machine connectée, je désactive l'expiration de la clé et on passe au contrôle s'accès :</p>
|
|
<pre class="language-yaml"><code>{
|
|
"acls": [
|
|
{"action": "accept", "src": ["admin@canaletto.fr"], "dst": ["*:*"]}, // Ici l'admin dispose de tous les droits
|
|
|
|
// Autorisation par machines
|
|
{
|
|
"action": "accept",
|
|
"src": ["azura", "lydia"], // Ici deux clients Tailscale
|
|
"dst": [
|
|
"pipa:25,53", // On autorise le host qui supporte le DNS si on veut utiliser les noms courts...
|
|
"mixa:80,443,445,3389",
|
|
"nona:80,443,445,1443,3389", // Ports autorisés
|
|
|
|
"lab-1:*",
|
|
|
|
"192.168.2.12:80,443,9100,5001,3389", // Par IP + ports
|
|
"192.168.6.0/24:*", // Par subnet
|
|
],
|
|
},
|
|
],
|
|
"hosts": {
|
|
"azura": "100.1.2.3", // Client Tailscale
|
|
"lydia": "100.5.2.3", // Client Tailscale
|
|
|
|
"mixa": "192.168.1.4", // Host on subnet
|
|
"nona": "192.168.2.8", // Host on subnet
|
|
"pipa": "192.168.2.1", // Host on subnet
|
|
|
|
"lab-1": "192.168.6.0/24", // subnet
|
|
},
|
|
|
|
}</code></pre>
|
|
<p style="text-align: justify;"><strong>Dans l'ordre :</strong></p>
|
|
<ol style="text-align: justify;">
|
|
<li>J'autorise l'admin à tout voir.</li>
|
|
<li>Ensuite j'autorise les machines <code>azura</code> et <code>lydia</code> à accéder uniquement aux hosts que j'aurais défini avec une restriction sur certains ports. C'est possible en définissant les hosts plus loin ou en se servant directement des adresses IP. L'ICMP (ping) est ouvert automatiquement vers les destinations autorisées.</li>
|
|
<li>Je défini les clients et serveurs.</li>
|
|
</ol>
|
|
<p>Voilà. Je n'ai pas creusé toutes les possibilité offertes par le contrôle d'accès proposé par Tailscale, la liste est longue et le <a href="https://tailscale.com/kb/" target="_blank" rel="noopener">documentation</a> plutôt bien faire. Idées bienvenues !</p>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/enjoy2.jpg" width="285" height="191" /></p>";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:50:"http://canaletto.fr/post/tailscale-access-controls";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"comments";a:1:{i:0;a:5:{s:4:"data";s:58:"http://canaletto.fr/post/tailscale-access-controls#comment";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post.aspx?id=41efab1a-c669-47a9-9b5f-5f67128e8eb2";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:31:"mar., 2 mai 2023 20:24:00 +0100";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:2:{i:0;a:5:{s:4:"data";s:7:"IP & Co";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:1;a:5:{s:4:"data";s:2:"IT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:34:"https://blogengine.io/schemas/tags";a:1:{s:3:"tag";a:3:{i:0;a:5:{s:4:"data";s:3:"vpn";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:1;a:5:{s:4:"data";s:9:"TailScale";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:2;a:5:{s:4:"data";s:9:"WireGuard";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:9:"publisher";a:1:{i:0;a:5:{s:4:"data";s:5:"Admin";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:52:"http://madskills.com/public/xml/rss/module/pingback/";a:2:{s:6:"server";a:1:{i:0;a:5:{s:4:"data";s:32:"http://canaletto.fr/pingback.axd";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:6:"target";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post.aspx?id=41efab1a-c669-47a9-9b5f-5f67128e8eb2";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:38:"http://purl.org/rss/1.0/modules/slash/";a:1:{s:8:"comments";a:1:{i:0;a:5:{s:4:"data";s:1:"0";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:53:"http://madskills.com/public/xml/rss/module/trackback/";a:1:{s:4:"ping";a:1:{i:0;a:5:{s:4:"data";s:73:"http://canaletto.fr/trackback.axd?id=41efab1a-c669-47a9-9b5f-5f67128e8eb2";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:36:"http://wellformedweb.org/CommentAPI/";a:2:{s:7:"comment";a:1:{i:0;a:5:{s:4:"data";s:58:"http://canaletto.fr/post/tailscale-access-controls#comment";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:10:"commentRss";a:1:{i:0;a:5:{s:4:"data";s:77:"http://canaletto.fr/syndication.axd?post=41efab1a-c669-47a9-9b5f-5f67128e8eb2";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:8;a:6:{s:4:"data";s:138:"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:7:{s:0:"";a:7:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:37:"Home Assistant & Alarm, encore...";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:26973:"<p style="text-align: justify;">J'ai souvent parlé d'alarme ici, de télécommandes, de claviers et de sirènes. Je pense cette fois être parvenu à quelque chose de fonctionnel et je vais vous en parler. Pour faire face aux différentes contraintes, notamment la gestion bizarre des télécommandes sous ZHA, il va falloir un peu ruser. Avant que vous me demandiez pourquoi je m'obstine sous ZHA alors que ces mêmes télécommandes sont bien gérées sous Z2M, je vous répondrait que mon objectif est la simplification et donc d'éviter le plus possible les adons qui complexifient une installation, pas forcément pour moi ou je dispose de toutes les passerelles possibles, mais sur des installations que je gère à distance ou je me dois de faire simple et fiable.</p>
|
|
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://canaletto.fr/image.axd?picture=/images/Alarm_07.png" /></p>
|
|
<p style="text-align: justify;"><span style="background-color: #f8cac6;"><strong>Attention :</strong> on parle ici d'un système de sécurité DIY, donc non agrée par les assurances et autres... Ca ne veut pas dire que ça ne fonctionne pas, juste que ça ne répond pas aux normes NF en vigueur dans ce domaine</span></p>
|
|
<p style="text-align: justify;">Afin de gérer toutes les contraintes, je vais principalement m'appuyer sur deux <code>automations:</code>, quelques <code>scripts:</code> et un <code>alarm_control_panel:</code> virtuel.</p>
|
|
<p style="text-align: justify;"><strong>L'objectif est de gérer :</strong></p>
|
|
<ul style="text-align: justify;">
|
|
<li>Un mode absent (away) (avec une variable pour simuler un peu de présence).</li>
|
|
<li>Un mode présent/nuit armé (home) (plus ou moins utile mais mais ça fait partie de tout système d'alarme face au home jacking.</li>
|
|
<li>Un mode alerte (emergency) qui va permettre de déclencher une action d'urgence en appuyant sur un bouton de télécommande ou médaillon (je pense à mes vieux jours).</li>
|
|
</ul>
|
|
<p style="text-align: justify;"><strong>De l'armement / désarmement vont également découler :</strong></p>
|
|
<ul style="text-align: justify;">
|
|
<li>La fermeture complète ou partielle des volets roulants, leur réouverture cohérente avec la programmation en cours et éventuellement le passage en manuel des volets des chambres des enfants / invités s'ils sont présents.</li>
|
|
<li>La gestion du climatiseur et des convecteurs avec passage en mode éco ou absent en fonction du type d'armement).</li>
|
|
<li>La gestion du chauffe eau en cas d'absence de longue durée.</li>
|
|
<li>La gestion des éclairages et la mise en veille des écrans et ordinateurs.</li>
|
|
<li>...</li>
|
|
</ul>
|
|
<p style="text-align: justify;">Etant donné que j'ai deux systèmes d'alarme qui fonctionnent en parallèle (Alarmo et Visonic), j'ai commencé par créer une alarme virtuelle et je me servirait d'elle pour les différentes actions.</p>
|
|
<pre class="language-yaml"><code>alarm_control_panel:
|
|
- platform: manual
|
|
name: Home Alarm Command
|
|
code: 1234
|
|
code_arm_required: false
|
|
disarm_after_trigger: false
|
|
arming_time: 0
|
|
delay_time: 0
|
|
trigger_time: 600
|
|
disarmed:
|
|
trigger_time: 0
|
|
armed_home:
|
|
arming_time: 0
|
|
delay_time: 0</code></pre>
|
|
<h3 style="text-align: justify;">L'Armement / Désarmement</h3>
|
|
<p style="text-align: justify;">L'armement / désarmement va pouvoir se faire de plusieurs façons :</p>
|
|
<ul style="text-align: justify;">
|
|
<li>Clavier à code</li>
|
|
<li>Télécommande dédiée</li>
|
|
<li>Application mobile</li>
|
|
<li>Tag RFID (pour désarmer dans mon cas)</li>
|
|
</ul>
|
|
<p style="text-align: justify;">J'ai volontairement écarté les télécommandes radio en 433 Mhz dont j'avais parlé ici, d'une part parce qu'elles sont facilement piratables, et d'autre part parce qu'elles ne permettent pas de savoir qui a désarmé le système.</p>
|
|
<p style="text-align: justify;">Je vais utiliser deux automations et les découper ce dessous/</p>
|
|
<ul style="text-align: justify;">
|
|
<li>La première pour gérer les armements / désarmements</li>
|
|
<li>La seconde pour gérer le désarmement des télécommandes, claviers à code afin d'intégrer les particularités ZHA (en attendant une amélioration de la part des développeurs de Home Assistant qui pour l'instant font la sourde oreille, parfois plus concentrés sur les nouveautés que l'affinage de l'existant).</li>
|
|
</ul>
|
|
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://canaletto.fr/image.axd?picture=/images/Alarm_10_panel.png" width="500" /></p>
|
|
<h3>Gestion de l'armement / désarmement et des boutons d'urgence</h3>
|
|
<p style="text-align: justify;"><strong>Les déclencheurs</strong> : Ici on va empiler nos déclencheurs d'armement, qu'ils soient gérés par ZHA, Z2M ou toute autre source. 3 par fonction, <code>armed_away, armed_home, triggered</code>, mais cela peut également être un bouton virtuel pour Lovelace, voire n'importe quelle télécommande ou bouton poussoir.</p>
|
|
<pre class="language-yaml"><code>- id: 078fsdg412-3545-4f37-ba02-bccsfds5646sf
|
|
alias: "Alarm : Global ON/OFF"
|
|
mode: restart
|
|
trigger:
|
|
- platform: device
|
|
device_id: c036b6547a0347878dcc6d06152267ab
|
|
domain: alarm_control_panel
|
|
entity_id: alarm_control_panel.lk_zb_keypad
|
|
type: armed_away
|
|
id: "KeyPad Away"
|
|
- platform: device
|
|
device_id: c036b6547a0347878dcc6d06152267ab
|
|
domain: alarm_control_panel
|
|
entity_id: alarm_control_panel.lk_zb_keypad
|
|
type: armed_home
|
|
id: "KeyPad Home"
|
|
- platform: device
|
|
device_id: c036b6547a0347878dcc6d06152267ab
|
|
domain: alarm_control_panel
|
|
entity_id: alarm_control_panel.lk_zb_keypad
|
|
type: triggered
|
|
id: "KeyPad Triggered"
|
|
- platform: state
|
|
entity_id: input_button.arm_alarm_away
|
|
id: "Push Button Away"</code></pre>
|
|
<p style="text-align: justify;">Et un déclencheur de désarmement activé par une seconde automation que l'on verra plus loin :</p>
|
|
<pre class="language-yaml"><code> - platform: state
|
|
entity_id:
|
|
- alarm_control_panel.home_alarm_command
|
|
to: disarmed
|
|
id: "Remote or Keypad"</code></pre>
|
|
<p style="text-align: justify;"><strong>Les conditions</strong> : Dans mon cas je n'en ai pas utilisé. Chacun adaptera.</p>
|
|
<pre class="language-yaml"><code> condition:</code></pre>
|
|
<p style="text-align: justify;"><strong>Les actions</strong> : </p>
|
|
<p style="text-align: justify;">Je commence par arrêter les éventuels scripts en cours. Cela est principalement utile quand on a fermé la porte, armé le système et que l'on doit rapidement désarmer car on a oublié quelque chose dans la maison.</p>
|
|
<pre class="language-yaml"><code> action:
|
|
- service: homeassistant.turn_off
|
|
target:
|
|
entity_id:
|
|
- script.privacy_on
|
|
- script.privacy_off
|
|
- script.alarmo_after_arm
|
|
- script.alarmo_after_disarm
|
|
- script.alarm_actions_on_leave_common_tasks
|
|
- script.alarm_actions_on_return_common_tasks</code></pre>
|
|
<p style="text-align: justify;">Ensuite on va utiliser <code>chose:</code> pour exécuter les différentes actions en fonction de la source et de l'état.</p>
|
|
<p style="text-align: justify;">On commence par l'armement en mode absent :</p>
|
|
<ul style="text-align: justify;">
|
|
<li style="text-align: justify;">On envoie les bips d'armement sur la sirène. En MQTT pour l'instant car elle aussi est très mal gérée sous ZHA</li>
|
|
<li style="text-align: justify;">On arme Alarmo</li>
|
|
<li style="text-align: justify;">On arme Visonic (en mode Home sans les PIR qui déraillent).</li>
|
|
<li style="text-align: justify;">On arme notre panneau d'alarme virtuel qui nous servira au désarmement</li>
|
|
<li style="text-align: justify;">On arme également le clavier, ça ne change rien à l'usage mais quand on se présentera pour désarmé il apparaitra comme étant armé. Dans la pratique ça relance de fait l'automation avec la même automation, et donc ça fausse le message, j'ai donc retiré cette option pour l'instant. (D'ailleurs si vous êtes sous Z2M il le développeur d'Alarmo a fait <a href="https://community.home-assistant.io/t/zigbee2mqtt-control-alarmo-via-keypad/420016" target="_blank" rel="noopener">un joli travail</a> pour ce clavier).</li>
|
|
<li style="text-align: justify;">On inscrit un message texte dans un <code>input_text:</code> que l'on affiche dans Lovelace et qui nous permet de savoir qui fait quoi. A terme je remplacerait les <code>id:</code> par le prénom de l'utilisateur pour plus de lisibilité.</li>
|
|
</ul>
|
|
<pre class="language-yaml"><code> - choose:
|
|
- conditions: "{{ trigger.id in ['KeyPad Away', 'Heiman RC1 Away', 'Heiman RC2 Away', 'Woox RC1 Away'] }}"
|
|
sequence:
|
|
- service: mqtt.publish
|
|
data:
|
|
topic: zigbee2mqtt/Sirène SMaBiT/set
|
|
payload: >-
|
|
{"squawk": {"state": "system_is_armed", "level": "veryhigh", "strobe": "true"}}
|
|
- service: alarm_control_panel.alarm_arm_away # ALARMO Away
|
|
data:
|
|
code: !secret alarm_code
|
|
entity_id: alarm_control_panel.alarmo
|
|
- service: alarm_control_panel.alarm_arm_home # VISONIC Home (ne jamais armer AWAY à cause des détecteurs HS)
|
|
data:
|
|
code: !secret alarm_code_visonic
|
|
entity_id: alarm_control_panel.visonic_alarm
|
|
- service: script.alarm_actions_on_leave_common_tasks
|
|
- service: alarm_control_panel.alarm_arm_away # FAKE ALARM PANEL Away
|
|
target:
|
|
entity_id: alarm_control_panel.home_alarm_command
|
|
- service: alarm_control_panel.alarm_arm_away # On arme le clavier afin qu'il apparaisse armé
|
|
data:
|
|
code: !secret alarm_code_zha
|
|
target:
|
|
entity_id:
|
|
- alarm_control_panel.lk_zb_keypad
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: input_text.last_arm
|
|
data:
|
|
value: "{{now().strftime('%d/%m/%Y, %H:%M:%S')}} > Arm Away by : {{ trigger.id }}" </code></pre>
|
|
<p style="text-align: justify;">On fait la même chose pour le mode home. Je fais l'impasse sur Visonic, par contre j'émet un son de confirmation sur un buzzer (on verra plus loin l'utilisation possible d'un TTS sur une enceinte.</p>
|
|
<pre class="language-yaml"><code> - conditions: "{{ trigger.id in ['KeyPad Home', 'Heiman RC1 Home', 'Heiman RC2 Home', 'Woox RC1 Home'] }}"
|
|
sequence:
|
|
- service: alarm_control_panel.alarm_arm_home # ALARMO Home
|
|
data:
|
|
code: !secret alarm_code
|
|
entity_id: alarm_control_panel.alarmo
|
|
- service: alarm_control_panel.alarm_arm_home # FAKE ALARM PANEL Home
|
|
target:
|
|
entity_id: alarm_control_panel.home_alarm_command
|
|
- service: alarm_control_panel.alarm_arm_home # On arme le clavier afin qu'il apparaisse armé
|
|
data:
|
|
code: !secret alarm_code_zha
|
|
target:
|
|
entity_id:
|
|
- alarm_control_panel.lk_zb_keypad
|
|
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.up_chime_play_buzzer
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: input_text.last_arm
|
|
data:
|
|
value: "{{now().strftime('%d/%m/%Y, %H:%M:%S')}} > Arm Home by : {{ trigger.id }}" </code></pre>
|
|
<p style="text-align: justify;">Ensuite on passe au désarmement du mode absent. On remarque que l'on écrit pas d'<code>input_text:</code> car ici on ne sait pas qui a fait quoi car l'ordre vient de la seconde automation que l'on verra plus loi. C'est donc elle qui écrira. Par contre on émet le son de désarmement sur la sirène.</p>
|
|
<pre class="language-yaml"><code> - conditions: "{{ trigger.id in ['Remote or Keypad'] and is_state('alarm_control_panel.alarmo', 'armed_away') }}"
|
|
sequence:
|
|
- service: alarm_control_panel.alarm_disarm
|
|
data:
|
|
code: !secret alarm_code
|
|
entity_id:
|
|
- alarm_control_panel.alarmo
|
|
- alarm_control_panel.visonic_alarm
|
|
- service: mqtt.publish
|
|
data:
|
|
topic: zigbee2mqtt/Sirène SMaBiT/set
|
|
payload: >-
|
|
{"squawk": {"state": "system_is_disarmed", "level": "veryhigh", "strobe": "true"}} </code></pre>
|
|
<p style="text-align: justify;">Pareil pour le mode Home. Ici on joue un son sur le buzzer.</p>
|
|
<pre class="language-yaml"><code> - conditions:
|
|
- "{{ trigger.id in ['Push Button'] }}"
|
|
- "{{ is_state('alarm_control_panel.alarmo', 'armed_home') }}"
|
|
sequence:
|
|
- service: alarm_control_panel.alarm_disarm
|
|
data:
|
|
code: !secret alarm_code
|
|
entity_id:
|
|
- alarm_control_panel.alarmo
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.up_chime_play_buzzer</code></pre>
|
|
<p style="text-align: justify;">On continue avec la gestion du bouton d'urgence :</p>
|
|
<ul style="text-align: justify;">
|
|
<li style="text-align: justify;">On joue un son pour confirmer</li>
|
|
<li style="text-align: justify;">On arme notre panneau d'alarme virtuel dans un mode inutilisé (Nuit) pour ensuite pouvoir désarmer.</li>
|
|
<li style="text-align: justify;">On envoie un SMS d'Au Secours, ou toute autre action à imaginer.</li>
|
|
<li style="text-align: justify;">On écrit un <code>input_text:</code> pour avoir une trace.</li>
|
|
</ul>
|
|
<pre class="language-yaml"><code> - conditions: "{{ trigger.id in ['KeyPad Triggered', 'Heiman RC1 Triggered', 'Heiman RC2 Triggered', 'Woox RC1 Triggered'] and is_state('alarm_control_panel.alarmo', 'disarmed') }}"
|
|
sequence:
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.up_chime_play_chime
|
|
- service: alarm_control_panel.alarm_arm_night # FAKE ALARM PANEL Night pour pouvoir désarmer
|
|
target:
|
|
entity_id: alarm_control_panel.home_alarm_command
|
|
- service: notify.free_mobile_andre
|
|
data:
|
|
message: "{{ states.sensor.date_time.state}} > TEST Alerte au secours par télécommande TEST"
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: input_text.last_arm
|
|
data:
|
|
value: "{{now().strftime('%d/%m/%Y, %H:%M:%S')}} > Triggered by : {{ trigger.id }}" </code></pre>
|
|
<p style="text-align: justify;">Enfin, on désarme cette alerte. A ce stade on peut aussi envoyer un SMS pour dire que c'était une fausse alerte... Je vais me contenter de jouer du buzzer...</p>
|
|
<pre class="language-yaml"><code> - conditions:
|
|
- "{{ trigger.id in ['Remote or Keypad'] and is_state('alarm_control_panel.alarmo', 'disarmed') }}"
|
|
sequence:
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.up_chime_play_buzzer</code></pre>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/Alarm_09.png" width="500" /></p>
|
|
<h3 style="text-align: justify;">Gestion des commandes de désarmement</h3>
|
|
<p style="text-align: justify;">Au risque de me répéter, cette partie aurait pu être intégrée à la première automation, si ZHA ne posait pas problème... Je le ferait probablement, mais pour l'exemple on va pour l'instant scinder cette partie.</p>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/Alarm_01_remote.png" width="395" height="287" /></p>
|
|
<p style="text-align: justify;">Donc, pour les télécommandes d'alarme sous ZHA on va devoir écouter un <code>event:</code>, s'en servir pour désarmer nos système d'alarme mais également pour la désarmer et désarmer ses copines ainsi que le clavier. Simple ! J'avais exploré dans <a href="http://canaletto.fr/post/home-assistant-and-remote-alarm" target="_blank" rel="noopener">un précédent article plusieurs pistes</a> afin de ne prendre en compte qu'un seul de ses "<em>events</em>" (en + elle en envoie 3 ou 4 identiques selon l'humeur et le modèle). J'ai un peu avancé et on ne va pas les écouter dans l'automation, mais se servir de l'état temporaire d'un <code>binary_sensor:</code> que l'on va pouvoir temporiser et ainsi ne prendre en compte qu'un seul <code>event:</code></p>
|
|
<pre class="language-yaml"><code>template:
|
|
- trigger:
|
|
- platform: event
|
|
event_type: zha_event
|
|
event_data:
|
|
device_ieee: a4:c1:38:96:0b:cf:c9:61 # Woox RC1
|
|
command: 'arm'
|
|
args:
|
|
arm_mode: 0
|
|
arm_mode_description: 'Disarm'
|
|
code: ''
|
|
zone_id: 0
|
|
binary_sensor:
|
|
name: Woox RC1 to Disarmed
|
|
icon: "{{ (trigger.platform == 'event') | iif('mdi:remote-off', 'mdi:remote') }}"
|
|
state: "{{ trigger.platform == 'event' }}"
|
|
auto_off:
|
|
seconds: 5</code></pre>
|
|
<p style="text-align: justify;"><strong>Les déclencheurs</strong> : Ici on va écouter des actions de désarmement, que cela provienne d'un clavier, une télécommande (via leur <code>binary_sensor:</code>), ou en direct pour une source classique (tag RFID, MQTT, ...).</p>
|
|
<pre class="language-yaml"><code>- id: '2bd0ertyyf-43fa-45f98f-aed0-disarm'
|
|
alias: "Alarm @ Remote Disarm"
|
|
description: 'Disarm Remote Control panel'
|
|
mode: single
|
|
trigger:
|
|
- platform: state
|
|
entity_id: binary_sensor.heiman_rc1_to_disarmed
|
|
to: "on"
|
|
id: "Heiman RC 1"
|
|
- platform: tag
|
|
tag_id: 2b855225-c999-4b5558123-6c7d12345641
|
|
id: "TAG Jaune"
|
|
- platform: device
|
|
domain: mqtt
|
|
device_id: 139eb4ce27246465b0d5aa7560a953601
|
|
type: action
|
|
subtype: disarm
|
|
discovery_id: 0x84fd27fffe915905 action_disarm
|
|
id: "Heiman RC2"</code></pre>
|
|
<p style="text-align: justify;"><strong>Les conditions</strong> : Aucune, mais on pourrait imagine un flag de blocage activé à distance après une alerte...</p>
|
|
<pre class="language-yaml"><code>condition:</code></pre>
|
|
<p style="text-align: justify;"><strong>Les actions</strong> : On utilise un chose: et on commence par :</p>
|
|
<ul style="text-align: justify;">
|
|
<li style="text-align: justify;">Désarmer le panneau d'alarme virtuel, ce qui déclenchera l'action idoine dans la première automation.</li>
|
|
<li style="text-align: justify;">Désarmer les télécommandes et claviers qui sont également des panneaux d'alarme, avec cette particularité ZHA qui fait qu'il faut un code pour désarmer une télécommande...</li>
|
|
<li style="text-align: justify;">Ecrire un <code>input_text:</code> afin de savoir qui a désarmé.</li>
|
|
<li style="text-align: justify;">J'envoie un message dans Slack qui me sert de log. Ca va également m'informer à distance que quelqu'un est arrivé et a désarmé </li>
|
|
</ul>
|
|
<pre class="language-yaml"><code> action:
|
|
- choose: # DISARM
|
|
- conditions: "{{ trigger.id in ['Push Button', 'KeyPad', 'Linkind RC', 'Heiman RC 1', 'Woox RC 1', 'TAG Porte', 'TAG Jaune', 'TAG Clé', 'TAG Carte', 'Heiman RC2' ] }}"
|
|
sequence:
|
|
- service: alarm_control_panel.alarm_disarm # FAKE ALARM PANEL to Command
|
|
data:
|
|
code: "1234"
|
|
target:
|
|
entity_id: alarm_control_panel.home_alarm_command
|
|
- service: alarm_control_panel.alarm_disarm
|
|
data:
|
|
code: !secret alarm_code_zha
|
|
target:
|
|
entity_id:
|
|
- alarm_control_panel.lk_zb_keypad
|
|
- alarm_control_panel.lk_zb_remote
|
|
- alarm_control_panel.heiman_remote
|
|
- alarm_control_panel.woox_01
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: input_text.last_disarm
|
|
data:
|
|
value: "{{now().strftime('%d/%m/%Y, %H:%M:%S')}} > Disarm by : {{ trigger.id }}"
|
|
- service: notify.slack_hass_canaletto
|
|
data:
|
|
message: "{{now().strftime('%d/%m/%Y, %H:%M:%S')}} > Disarmed by : {{ trigger.id }}" </code></pre>
|
|
<p style="text-align: justify;">On peut également faire une place à une fonctionnalité détournée du clavier. En effet au delà de l'amenée Home, Away et Emergency, on peut également lui faire avaler n'importe quel code et effectuer une action précise en fonction de celui ci. Ici si je saisit 33 et valide je vais allumer les projecteurs.</p>
|
|
<pre class="language-yaml"><code> - choose:
|
|
- conditions: "{{ trigger.id in ['KeyPad 33'] }}"
|
|
sequence:
|
|
- service: light.turn_off
|
|
target:
|
|
entity_id:
|
|
- light.groupe_de_projecteurs
|
|
</code></pre>
|
|
<p style="text-align: justify;">Enfin j'ai quelques actions par défaut, comme éteindre les sirènes au cas ou... (ça sent le debug...).</p>
|
|
<pre class="language-yaml"><code> - service: mqtt.publish
|
|
data:
|
|
topic: zigbee2mqtt/Sirène SMaBiT/set
|
|
payload: >-
|
|
{"warning": {"mode": "stop"}}
|
|
- service: siren.turn_off
|
|
target:
|
|
entity_id:
|
|
- siren.heiman_sirene_1
|
|
- siren.heiman_sirene_2
|
|
- siren.sirene_terrasse
|
|
</code></pre>
|
|
<p style="text-align: justify;"><span style="text-decoration: line-through;">Et surtout <span style="background-color: #fbeeb8;">on ajoute un délai</span> car ces télécommandes ont la fâcheuse idée d'envoyer 3 ou 4 <code>event:</code> identique pour chaque appui. Donc combiné au <code>mode: single</code> de cette automation, on va en capturer qu'un seul. Ce délais est bien sur à ajuster plus ou moins au pif...</span> Maintenant que je passe par des <code>binary_sensor:</code> temporisés, je pense que ce délai est devenu inutile.</p>
|
|
<pre class="language-yaml"><code> - delay : '00:00:08'</code></pre>
|
|
<h3 style="text-align: justify;">Les actions POST Armement / Désarmement</h3>
|
|
<p style="text-align: justify;">On va utiliser deux scripts qui seront exécutés par Alarmo après l'armement et après le désarmement. Chez moi ils vont servir à :</p>
|
|
<ul style="text-align: justify;">
|
|
<li style="text-align: justify;">Jouer une annonce vocale en TTS sur une enceinte extérieure pour annoncer l'état armé ou désarmé.</li>
|
|
<li style="text-align: justify;">Activer ou désactiver la vidéo surveillance.</li>
|
|
<li style="text-align: justify;">Passer les volets en mode manuel et automatique au retour (voir l'automatisation des volets).</li>
|
|
<li style="text-align: justify;">Gérer le mode ECO/Absent du climatiseur et des convecteurs.</li>
|
|
<li style="text-align: justify;">Gérer les éclairages et le mode veille de mon PC.</li>
|
|
<li style="text-align: justify;">Et plus encore selon votre imagination....</li>
|
|
</ul>
|
|
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://canaletto.fr/image.axd?picture=/images/Alarm_08.png" /></p>
|
|
<h3 style="text-align: justify;">Les notifications d'alarme et sirènes</h3>
|
|
<ul style="text-align: justify;">
|
|
<li style="text-align: justify;">Notifications SMS pour l'intrusion, la détection incendie ou fuite d'eau. (notifications gérées par Alarmo).</li>
|
|
<li style="text-align: justify;">Sirènes et projecteurs en cas d'intrusion :
|
|
<ul>
|
|
<li>la législation autorise au maximum 3 minutes pour chaque lancement de sirène.</li>
|
|
<li>Pas de limite pour les projecteurs. Et éclairer comme en plein jour peut également faire fuir et permettra d'avoir des images bien nettes sur les caméras.</li>
|
|
<li>Si vous avez un système audio multi room bien puissant, vous pouvez également envoyer une bonne salve d'AC-DC, ça peu perturber... ou inciter les voisins à appeler la maréchaussée.</li>
|
|
<li>Les armes, explosifs et autres gaz toxiques sont à proscrire.</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
<p style="text-align: justify;">Pour cela on va utiliser des scripts: qui seront lancés par Alarmo selon les conditions choisies (voir <a href="http://canaletto.fr/post/home-assistant-and-sirenes" target="_blank" rel="noopener">ici</a>).</p>
|
|
<p style="text-align: justify;">Etant donné que j'ai des détecteurs d'ouverture sur mes volets roulants, je peux également imaginer l'éclairage extérieur avant de déclencher l'alarme si un de ces volets est touché. Il faut être prévenant et éclairer l'intrus. Cela peut se gréer dans une partition secondaire d'Alarmo, ou simple une automation. Les caméras Unifi Protect (G4) font également de la détection de personne qui remonte dans Home Assistant.</p>
|
|
<p style="text-align: justify;">Voilà, ce n'est pas exhaustif, vos idées son les bienvenues, ici ou sur <a href="https://forum.hacf.fr/t/alarme-encore/21838" target="_blank" rel="noopener">HACF</a>.</p>
|
|
<p style="text-align: justify;"> </p>
|
|
<p style="text-align: justify;"> </p>";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:56:"http://canaletto.fr/post/home-assistant-and-alarm-encore";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"comments";a:1:{i:0;a:5:{s:4:"data";s:64:"http://canaletto.fr/post/home-assistant-and-alarm-encore#comment";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post.aspx?id=9217dc3a-beac-408d-9078-45b874365a1a";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:33:"lun., 13 mars 2023 00:01:00 +0100";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:9:"Domotique";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:34:"https://blogengine.io/schemas/tags";a:1:{s:3:"tag";a:5:{i:0;a:5:{s:4:"data";s:4:"HASS";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:1;a:5:{s:4:"data";s:6:"Hassio";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:2;a:5:{s:4:"data";s:6:"Alarme";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:3;a:5:{s:4:"data";s:6:"Alarmo";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:4;a:5:{s:4:"data";s:6:"Remote";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:9:"publisher";a:1:{i:0;a:5:{s:4:"data";s:5:"Admin";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:52:"http://madskills.com/public/xml/rss/module/pingback/";a:2:{s:6:"server";a:1:{i:0;a:5:{s:4:"data";s:32:"http://canaletto.fr/pingback.axd";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:6:"target";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post.aspx?id=9217dc3a-beac-408d-9078-45b874365a1a";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:38:"http://purl.org/rss/1.0/modules/slash/";a:1:{s:8:"comments";a:1:{i:0;a:5:{s:4:"data";s:1:"5";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:53:"http://madskills.com/public/xml/rss/module/trackback/";a:1:{s:4:"ping";a:1:{i:0;a:5:{s:4:"data";s:73:"http://canaletto.fr/trackback.axd?id=9217dc3a-beac-408d-9078-45b874365a1a";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:36:"http://wellformedweb.org/CommentAPI/";a:2:{s:7:"comment";a:1:{i:0;a:5:{s:4:"data";s:64:"http://canaletto.fr/post/home-assistant-and-alarm-encore#comment";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:10:"commentRss";a:1:{i:0;a:5:{s:4:"data";s:77:"http://canaletto.fr/syndication.axd?post=9217dc3a-beac-408d-9078-45b874365a1a";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}i:9;a:6:{s:4:"data";s:166:"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";s:5:"child";a:7:{s:0:"";a:7:{s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:43:"VMWare ESXi sur Nuc 9 & SSD firmware...";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:11:"description";a:1:{i:0;a:5:{s:4:"data";s:10810:"<p style="text-align: justify;">Comme je vous en avait parlé <a href="http://canaletto.fr/post/vmware-esxi-nuc-9" target="_blank" rel="noopener">ici</a>, j'ai remplacé mon serveur ESXi HP ML350p par un Nuc 9. Depuis plus de 6 mois ça fonctionne très bien.</p>
|
|
<p style="text-align: justify;">Dans ce Nuc j'ai installé deux SSD NVMe Samsung 980 Pro. Les performance sont au top, mais voilà que plusieurs utilisateurs se plaignent que leurs SSD s'usent prématurément et finissent par passer en R/O. C'est d'autant plus fâcheux que sous ESX on ne dispose de rien pour surveiller les disques sur un NUC, celui ci ne remontant pas de données IPML comme le ferait un vrai serveur. Après avoir fait un peu la sourde oreille, Samsung a fini par sortir <a href="https://semiconductor.samsung.com/consumer-storage/support/tools/" target="_blank" rel="noopener">la mise à jour</a> idoine.</p>
|
|
<p style="text-align: center;"><img src="http://canaletto.fr/image.axd?picture=/images/nuc_ssd_updat_05.png" width="600" /></p>
|
|
<p style="text-align: justify;">Sous Windows il est très facile de mettre à jour (ou de migrer) un SSD, il suffit de lancer Samsung Magician et le tour est joué ! Sous VMWare ESXi rien de tout ça et il va falloir le faire à la mano. Heureusement pour cela Samsung fournit également les firmawares sous la forme d'une ISO, il suffit, en principe, de le griller sur une clé USB et de booter avec et de faire la mise à jour. Mais ça c'est la théorie. Dans la pratique j'ai appris à mes dépends que cette clé basée sur un vieux Linux était incapable de booter sur du matériel moderne, et quand elle boote certains disent même qu'elle ne reconnait que les claviers PS2... Allons donc !</p>
|
|
<p style="text-align: justify;">Après quelques recherches j'ai découvert qu'il existait un contournement possible mis en pratique par la communauté Linux, mais nullement supportée par Samsung qui doit considérer que ses SSD sont destinés uniquement à l'environnement Windows, tout comme VMWare qui a sa liste de hardware supporté...</p>
|
|
<p style="text-align: justify;">L'astuce consiste à booter sous Linux, un Live CD Ubuntu. Facile, non pas si simple car ce live CD ne voulait lui non plus pas booter. Le bios de ce Nuc n'étant pas de toute fraicheur j'en profite pour le mettre à jour sans plus de succès.</p>
|
|
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://canaletto.fr/image.axd?picture=/images/nuc_ssd_updat_01.png" width="600" /></p>
|
|
<p style="text-align: justify;">J'ai fini par trouver que pour booter sous Ubuntu il fallait désactiver TPM et SGX. Ca ne s'invente pas mais j'ai fini par pouvoir booter mon Ubuntu Live.</p>
|
|
<p style="text-align: justify;">Une fois sur le desktop de mon Ubuntu je copie l'ISO de mise à jour (<code>Samsung_SSD_980_PRO_5B2QGXA7.iso</code>) que j'ai au préalable préparée sur une autre clé USB vers le répertoire Home et je monte le volume. Ensuite toujours depuis l'interface graphique j'extrait le fichier <code>initrd</code> un répertoire (<code>/home/samsung</code> par exemple). Ensuite je vais jusqu'à <code>/home/samsung/initrd/root/fumagician</code> et je peux lancer la mise à jour de mes SSD :</p>
|
|
<pre class="language-yaml"><code>sudo ./fumagicien</code></pre>
|
|
<p style="text-align: justify;">Je fais la mise à jour de mes deux SSD et je relance le Nuc. Attention, le bon numéro de version n'apparaitra qu'âpres le prochain redémarrage. Donc même si c'est un peu fastidieux, je vous conseille de relancer le Live CD pour vérifier. De même si vous avez d'autres machines à mettre à jour, vous pouvez sauvegarder <code>fumagician</code> sur une clé pour éviter l'étape de l'extraction. </p>
|
|
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://canaletto.fr/image.axd?picture=/images/nuc_ssd_updat_02.png" width="600" /></p>
|
|
<p style="text-align: justify;">Il existe une autre méthode en CLI pour les barbus, elle demandera toutefois de connecter le Live CE au réseau si on veut éviter l'étape de la clé USB, mais in fine ça revient au même :</p>
|
|
<pre class="language-yaml"><code>wget https://semiconductor.samsung.com/resources/software-resources/Samsung_SSD_980_PRO_5B2QGXA7.iso
|
|
apt-get -y install gzip unzip wget cpio
|
|
mkdir /mnt/iso
|
|
sudo mount -o loop ./Samsung_SSD_980_PRO_5B2QGXA7.iso /mnt/iso/
|
|
mkdir /tmp/fwupdate
|
|
cd /tmp/fwupdate
|
|
gzip -dc /mnt/iso/initrd | cpio -idv --no-absolute-filenames
|
|
cd root/fumagician/
|
|
sudo ./fumagician</code></pre>
|
|
<p style="text-align: justify;">Voilà comment occuper (perdre) un après-midi d'hiver !</p>
|
|
<p style="text-align: justify;">Attention toutefois, si vous avez créé un volume RAID, ce qui est discutable avec des SSD, il semblerait que vous ne puissiez les voir sans repasser le bios en AHCI.</p>
|
|
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://canaletto.fr/image.axd?picture=/images/enjoyit.png" width="206" height="206" /></p>
|
|
<h3 style="text-align: left;">Sources</h3>
|
|
<ul>
|
|
<li style="text-align: left;"><span style="font-size: 10pt;"><a href="https://askubuntu.com/questions/1405963/ubuntu-22-04-failed-to-boot-on-intel-nuc-nuc9i9qnx-out-of-memory" target="_blank" rel="noopener">https://askubuntu.com/questions/1405963/ubuntu-22-04-failed-to-boot-on-intel-nuc-nuc9i9qnx-out-of-memory</a></span></li>
|
|
<li style="text-align: left;"><span style="font-size: 10pt;"><a href="https://www.phonandroid.com/samsung-ne-trouve-pas-de-solution-contre-la-degradation-rapide-de-ses-ssd-les-plus-performants.html" target="_blank" rel="noopener">https://www.phonandroid.com/samsung-ne-trouve-pas-de-solution-contre-la-degradation-rapide-de-ses-ssd-les-plus-performants.html</a></span></li>
|
|
<li style="text-align: left;"><span style="font-size: 10pt;"><a href="https://www.clubic.com/pro/entreprises/samsung/actualite-455880-samsung-publie-enfin-un-correctif-pour-ses-ssd-980-pro.html" target="_blank" rel="noopener">https://www.clubic.com/pro/entreprises/samsung/actualite-455880-samsung-publie-enfin-un-correctif-pour-ses-ssd-980-pro.html</a></span></li>
|
|
<li style="text-align: left;"><span style="font-size: 10pt;"><a href="https://semiconductor.samsung.com/resources/software-resources/Samsung_SSD_Firmware_Update_Utility_User_Manual_English.pdf" target="_blank" rel="noopener">https://semiconductor.samsung.com/resources/software-resources/Samsung_SSD_Firmware_Update_Utility_User_Manual_English.pdf</a></span></li>
|
|
<li style="text-align: left;"><span style="font-size: 10pt;"><a href="https://www.malekal.com/mettre-a-jour-firmware-ssd/" target="_blank" rel="noopener">https://www.malekal.com/mettre-a-jour-firmware-ssd/</a></span></li>
|
|
<li style="text-align: left;"><span style="font-size: 10pt;"><a href="https://semiconductor.samsung.com/consumer-storage/support/tools/" target="_blank" rel="noopener">https://semiconductor.samsung.com/consumer-storage/support/tools/</a></span></li>
|
|
<li style="text-align: left;"><span style="font-size: 10pt;"><a href="https://askubuntu.com/questions/1263336/unable-to-install-20-04-lts-on-intel-nuc-10i3fnh" target="_blank" rel="noopener">https://askubuntu.com/questions/1263336/unable-to-install-20-04-lts-on-intel-nuc-10i3fnh</a></span></li>
|
|
<li style="text-align: left;"><span style="font-size: 10pt;"><a href="https://help.ubuntu.com/rst/" target="_blank" rel="noopener">https://help.ubuntu.com/rst/</a></span></li>
|
|
<li style="text-align: left;"><span style="font-size: 10pt;"><a href="https://www.nextinpact.com/article/68212/nuc-9-pro-nuc9vxqnx-quartz-canyon-dintel-on-y-a-installe-deux-ssd-et-geforce" target="_blank" rel="noopener">https://www.nextinpact.com/article/68212/nuc-9-pro-nuc9vxqnx-quartz-canyon-dintel-on-y-a-installe-deux-ssd-et-geforce</a></span></li>
|
|
<li style="text-align: left;"><span style="font-size: 10pt;"><a href="https://www.storagereview.com/review/intel-nuc-9-pro-as-an-esxi-server" target="_blank" rel="noopener">https://www.storagereview.com/review/intel-nuc-9-pro-as-an-esxi-server</a></span></li>
|
|
<li style="text-align: left;"><span style="font-size: 10pt;"><a href="https://www.ubackup.com/enterprise-backup/esxi-recovery-mode.html" target="_blank" rel="noopener">https://www.ubackup.com/enterprise-backup/esxi-recovery-mode.html</a></span></li>
|
|
<li style="text-align: left;"><span style="font-size: 10pt;"><a href="https://bytespeed.com/nuc-bios-uefi-shell-update/" target="_blank" rel="noopener">https://bytespeed.com/nuc-bios-uefi-shell-update/</a></span></li>
|
|
<li style="text-align: left;"><span style="font-size: 10pt;"><a href="https://www.reddit.com/r/zfs/comments/fuqgoi/script_to_update_samsung_ssd_firmware/" target="_blank" rel="noopener">https://www.reddit.com/r/zfs/comments/fuqgoi/script_to_update_samsung_ssd_firmware/</a></span></li>
|
|
<li style="text-align: left;"><span style="font-size: 10pt;"><a href="https://apple.stackexchange.com/questions/387414/ssd-firmware-upgrade-requires-iso-on-a-pendrive-how-to-make-that-bootable" target="_blank" rel="noopener">https://apple.stackexchange.com/questions/387414/ssd-firmware-upgrade-requires-iso-on-a-pendrive-how-to-make-that-bootable</a></span></li>
|
|
<li style="text-align: left;"><span style="font-size: 10pt;"><a href="https://www.malekal.com/mettre-a-jour-firmware-ssd/" target="_blank" rel="noopener">https://www.malekal.com/mettre-a-jour-firmware-ssd/</a></span></li>
|
|
<li style="text-align: left;"><span style="font-size: 10pt;"><a href="https://blog.quindorian.org/2021/05/firmware-update-samsung-ssd-in-linux.html/" target="_blank" rel="noopener">https://blog.quindorian.org/2021/05/firmware-update-samsung-ssd-in-linux.html/</a></span></li>
|
|
<li style="text-align: left;"><span style="font-size: 10pt;"><a href="https://askubuntu.com/questions/1348219/how-to-update-samsung-ssd-firmware-from-ubuntu" target="_blank" rel="noopener">https://askubuntu.com/questions/1348219/how-to-update-samsung-ssd-firmware-from-ubuntu</a></span></li>
|
|
<li style="text-align: left;"><span style="font-size: 10pt;"><a href="https://www.youtube.com/watch?v=mAPWugrTO5Q" target="_blank" rel="noopener">https://www.youtube.com/watch?v=mAPWugrTO5Q</a></span></li>
|
|
<li style="text-align: left;"><span style="font-size: 10pt;"><a href="https://github.com/ventoy/Ventoy/issues/550" target="_blank" rel="noopener">https://github.com/ventoy/Ventoy/issues/550</a></span></li>
|
|
</ul>
|
|
<p> </p>";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"link";a:1:{i:0;a:5:{s:4:"data";s:61:"http://canaletto.fr/post/vmware-esxi-nuc9-update-ssd-firmware";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"comments";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post/vmware-esxi-nuc9-update-ssd-firmware#comment";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"guid";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post.aspx?id=9efc2b9d-524d-442f-8beb-9d9b6e866358";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:7:"pubDate";a:1:{i:0;a:5:{s:4:"data";s:35:"dim., 12 févr. 2023 22:46:00 +0100";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:8:"category";a:1:{i:0;a:5:{s:4:"data";s:2:"IT";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:34:"https://blogengine.io/schemas/tags";a:1:{s:3:"tag";a:9:{i:0;a:5:{s:4:"data";s:7:"Samsung";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:1;a:5:{s:4:"data";s:3:"SSD";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:2;a:5:{s:4:"data";s:4:"NVMe";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:3;a:5:{s:4:"data";s:3:"ESX";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:4;a:5:{s:4:"data";s:4:"ESXi";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:5;a:5:{s:4:"data";s:6:"VMWare";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:6;a:5:{s:4:"data";s:5:"Linux";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:7;a:5:{s:4:"data";s:8:"Firmware";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}i:8;a:5:{s:4:"data";s:5:"NUC 9";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:1:{s:9:"publisher";a:1:{i:0;a:5:{s:4:"data";s:5:"Admin";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:52:"http://madskills.com/public/xml/rss/module/pingback/";a:2:{s:6:"server";a:1:{i:0;a:5:{s:4:"data";s:32:"http://canaletto.fr/pingback.axd";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:6:"target";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post.aspx?id=9efc2b9d-524d-442f-8beb-9d9b6e866358";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:38:"http://purl.org/rss/1.0/modules/slash/";a:1:{s:8:"comments";a:1:{i:0;a:5:{s:4:"data";s:1:"0";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:53:"http://madskills.com/public/xml/rss/module/trackback/";a:1:{s:4:"ping";a:1:{i:0;a:5:{s:4:"data";s:73:"http://canaletto.fr/trackback.axd?id=9efc2b9d-524d-442f-8beb-9d9b6e866358";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:36:"http://wellformedweb.org/CommentAPI/";a:2:{s:7:"comment";a:1:{i:0;a:5:{s:4:"data";s:69:"http://canaletto.fr/post/vmware-esxi-nuc9-update-ssd-firmware#comment";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:10:"commentRss";a:1:{i:0;a:5:{s:4:"data";s:77:"http://canaletto.fr/syndication.axd?post=9efc2b9d-524d-442f-8beb-9d9b6e866358";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}}}s:45:"http://backend.userland.com/blogChannelModule";a:2:{s:8:"blogRoll";a:1:{i:0;a:5:{s:4:"data";s:28:"http://canaletto.fr/opml.axd";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:5:"blink";a:1:{i:0;a:5:{s:4:"data";s:36:"https://canaletto.fr/syndication.axd";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:32:"http://purl.org/dc/elements/1.1/";a:2:{s:7:"creator";a:1:{i:0;a:5:{s:4:"data";s:7:"My name";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:5:"title";a:1:{i:0;a:5:{s:4:"data";s:12:"My Canaletto";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}s:40:"http://www.w3.org/2003/01/geo/wgs84_pos#";a:2:{s:3:"lat";a:1:{i:0;a:5:{s:4:"data";s:8:"0.000000";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}s:4:"long";a:1:{i:0;a:5:{s:4:"data";s:8:"0.000000";s:7:"attribs";a:0:{}s:8:"xml_base";s:0:"";s:17:"xml_base_explicit";b:0;s:8:"xml_lang";s:0:"";}}}}}}}}}}}}s:4:"type";i:128;s:7:"headers";a:14:{s:4:"date";s:29:"Sun, 26 Nov 2023 10:04:50 GMT";s:12:"content-type";s:19:"application/rss+xml";s:13:"cache-control";s:6:"public";s:13:"last-modified";s:29:"Mon, 20 Nov 2023 23:56:40 GMT";s:4:"etag";s:22:"W/"638361250000000000"";s:19:"content-disposition";s:24:"inline; filename=rss.xml";s:12:"x-powered-by";s:7:"ASP.NET";s:15:"cf-cache-status";s:7:"DYNAMIC";s:9:"report-to";s:233:"{endpoints:[{url:https:\/\/a.nel.cloudflare.com\/report\/v3?s=aZZVj5znwMVrqU%2Bn32L8cfd4HVN4ZOcLEhpiJsiXo7ELCb1ZG6QgG5YV8AsKh%2BNuq5djk8r4Y%2Bxd%2FGSGjoWnNStVjm7REaGbdNOUxu01aoD%2BaMKWHF9cOvqiwXkxpzk%3D}],group:cf-nel,max_age:604800}";s:3:"nel";s:52:"{success_fraction:0,report_to:cf-nel,max_age:604800}";s:6:"server";s:10:"cloudflare";s:6:"cf-ray";s:20:"82c14f401cb012b4-MRS";s:16:"content-encoding";s:2:"br";s:7:"alt-svc";s:17:"h3=:443; ma=86400";}s:5:"build";s:14:"20230304122624";s:5:"mtime";i:1700993090;s:3:"md5";s:32:"5aee2bbdb1d87fbc5607ccb26c505eb4";} |