﻿<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Catégorie Tutoriels - Constellation</title>
	<atom:link href="https://developer.myconstellation.io/tutorials/feed/" rel="self" type="application/rss+xml" />
	<link>https://developer.myconstellation.io/tutorials/</link>
	<description>Votre plateforme d&#039;interconnexion</description>
	<lastBuildDate>Sun, 29 Jul 2018 05:49:22 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.0.11</generator>

<image>
	<url>https://developer.myconstellation.io/wp-content/uploads/2016/02/256x256-e1457476015859.png</url>
	<title>Catégorie Tutoriels - Constellation</title>
	<link>https://developer.myconstellation.io/tutorials/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>FriendLeaf : la serre connectée grâce à Constellation</title>
		<link>https://developer.myconstellation.io/tutorials/friendleaf-la-serre-connectee-grace-a-constellation/</link>
					<comments>https://developer.myconstellation.io/tutorials/friendleaf-la-serre-connectee-grace-a-constellation/#respond</comments>
		
		<dc:creator><![CDATA[Sebastien Warin]]></dc:creator>
		<pubDate>Tue, 17 Jul 2018 09:40:50 +0000</pubDate>
				<category><![CDATA[Tutoriels]]></category>
		<category><![CDATA[IoT]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[Saga]]></category>
		<category><![CDATA[Relais]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[smartphone]]></category>
		<category><![CDATA[PushBullet]]></category>
		<category><![CDATA[Notification]]></category>
		<category><![CDATA[AngularJS]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Mobile]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=6084</guid>

					<description><![CDATA[<p>Plus besoin de disposer d&#8217;un espace extérieur pour faire pousser vos propres herbes aromatiques, salades et fleurs. Grâce à la serre connectée FriendLeaf, vous pouvez faire pousser plusieurs plantes et vous en occuper facilement. Projet réalisé par Théo DELOOSE, Clara</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/tutorials/friendleaf-la-serre-connectee-grace-a-constellation/">FriendLeaf : la serre connectée grâce à Constellation</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><i>Plus besoin de disposer d&rsquo;un espace extérieur pour faire pousser vos propres herbes aromatiques, salades et fleurs. Grâce à la serre connectée FriendLeaf, vous pouvez faire pousser plusieurs plantes et vous en occuper facilement.</i></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure1.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title=" FriendLeaf : la serre connectée grâce à Constellation" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure1_thumb.png" alt="FriendLeaf : la serre connectée grâce à Constellation" width="354" height="266" border="0" /></a></p>
<p>Projet réalisé par Théo DELOOSE, Clara BOMY, Clément NOUGÉ, Mathieu GABRIEL, Marine DAEL et Thaï-Son DANG.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure2.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="L'équipe FriendLeaf" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure2_thumb.png" alt="L'équipe FriendLeaf" width="254" height="208" border="0" /></a></p>
<p><span id="more-6084"></span></p>

<h3>Introduction</h3>
<p>Nous sommes six étudiants en troisième année à l’ISEN Lille. Dans le cadre de notre projet de fin d’année, nous avons conçu une serre connectée dédiée à un usage en intérieur. Celle-ci est équipée d’un système d’éclairage intelligent, d’une pompe d’arrosage automatique et d’un brumisateur intégré afin de garantir la bonne croissance des plantes, rassemblant les conditions nécessaires à leur développement. Pour une plus grande facilité d&rsquo;utilisation, notre serre est associée à une application mobile simple et ludique permettant de suivre en temps réel les données de l’environnement de la serre et de contrôler celle-ci à distance.</p>
<p>En réalisant ce projet, notre but était de proposer une solution de serre connectée à un prix raisonnable et possédant une interface attrayante pour améliorer l’expérience de l’utilisateur.</p>
<p>De plus nous voulions que la serre puisse être intégrée dans différents systèmes facilement pour que l’utilisateur puisse utiliser les données à sa guise.</p>
<h3>Fonctionnement général</h3>
<p>Nous avons pensé<i> FriendLeaf </i>comme un système de monitoring et de pilotage. Il propose en effet de gérer automatiquement l’arrosage, l’humidité et la luminosité de la serre, ou bien de les activer manuellement à notre guise. Il synchronise les données récupérées par les différents capteurs grâce à la plateforme Constellation et active, par le biais d’un relais, les actionneurs. Enfin, <i>FriendLeaf </i>alerte l’utilisateur lorsque le réservoir d’eau est vide. Tout est synchronisé en temps réel comme par magie grâce à Constellation.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure3.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Communication" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure3_thumb.png" alt="Communication" width="400" height="150" border="0" /></a></p>
<p>Nous avons donc ajouté dans la serre les capteurs permettant de relever les informations sur l’humidité de l’air et du sol, sur la température et sur la luminosité.  L’équipement installé comporte aussi une guirlande lumineuse ayant pour but d’éclairer et d’afficher les alertes, une pompe pour le système d’arrosage et un brumisateur permettant d’humidifier l’air.</p>
<p align="center"> <a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure4.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Schéma général de la serre " src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure4_thumb.png" alt="Schéma général de la serre " width="450" height="244" border="0" /></a></p>
<h3>Matériel utilisé</h3>
<p>Pour réaliser notre projet, nous nous sommes servis des composants suivants :</p>
<p>Pour la Serre :</p>
<ul>
<li><u><a href="https://www.ikea.com/fr/fr/catalog/products/70186603/">Serre SOCKER Ikea</a></u> (12,99€), Ikea</li>
<li>Bac pour le terreau (1,50€), Jardinerie</li>
<li><u><a href="https://www.amazon.fr/Raspberry-Pi-3-Mod%C3%A8le-B-Carte-m%C3%A8re/dp/B07BDR5PDW/ref=sr_1_cc_3?s=aps&amp;ie=UTF8&amp;qid=1528895423&amp;sr=1-3-catcorr&amp;keywords=raspberry+pi+3B">Carte Raspberry Pi 3B </a></u>(40,80€), Amazon</li>
<li><u><a href="https://www.amazon.fr/Elegoo-Optocoupleur-Continu-Arduino-Raspberry/dp/B06XKST8XC/ref=sr_1_1?s=computers&amp;ie=UTF8&amp;qid=1528792288&amp;sr=1-1&amp;keywords=4%2Bcanaux%2B250V&amp;th=1">Relais 4 canaux</a></u> supportant jusqu’à 5A et 250V (AC) et 30V (DC) (9,99€), Amazon</li>
<li>Câbles de connexion</li>
<li>Boîte de dérivation</li>
</ul>
<p>Pour les capteurs :</p>
<ul>
<li>Humidité et température air : <u><a href="https://www.amazon.fr/SODIAL-Humidite-Numerique-Temperature-Arduino/dp/B00K67XRFC/ref=sr_1_1?ie=UTF8&amp;qid=1529502640&amp;sr=8-1&amp;keywords=dht+11">DHT11</a></u> (1,31€), Amazon</li>
<li>Luminosité : <u><a href="https://www.gotronic.fr/art-capteur-de-luminosite-tsl2561-19569.htm">TSL2561</a></u> (6,95€), Gotronic</li>
<li>Humidité sol : <u><a href="https://www.gotronic.fr/art-capteur-d-humidite-gt110-26091.htm#complte_desc">GT110</a></u> (2,40€), Gotronic</li>
<li>Niveau d’eau : <u><a href="https://www.gotronic.fr/art-detecteur-de-niveau-gravity-sen0205-25296.htm">Gravity SEN0205</a></u> (10,50€), Gotronic</li>
</ul>
<p>Pour le brumisateur :</p>
<ul>
<li>Un <u><a href="https://www.amazon.fr/Ultrasons-Shineus-Humidificateur-Fontaine-Atomisation/dp/B077HSKYN8/ref=sr_1_4?ie=UTF8&amp;qid=1528895226&amp;sr=8-4&amp;keywords=mist+maker">émetteur à ultrasons</a></u> (9,89€), Amazon</li>
<li>Une alimentation pour le brumisateur (24V DC, 1A) (25€), Derotronic, Lille</li>
<li>Un bol</li>
</ul>
<p>Pour le système d’arrosage :</p>
<ul>
<li>Une <u><a href="https://www.amazon.fr/Gugutogo-submersible-%C3%A9lectrique-silencieux-m%C3%A9canique/dp/B07BXJTND4/ref=sr_1_3?s=electronics&amp;ie=UTF8&amp;qid=1529927406&amp;sr=1-3&amp;keywords=pompe+%C3%A0+eau+12v">pompe à eau</a></u> (5,48€), Amazon</li>
<li>Une alimentation 12V 600mA (12€), Derotronic, Lille</li>
<li>Un jerrican (environ 10€)</li>
<li>Un tuyau (ø7mm -ø10mm), Diall</li>
</ul>
<p>Pour l’éclairage :</p>
<ul>
<li>2m de <u><a href="http://www.blachere-illumination-store.com/fr/nos-creations/326-fil-lumiere-blanc-8m-3587880017658.html">guirlandes lumineuses</a></u> (1m LED et 1m incandescent), Blachère</li>
<li>Une alimentation pour fil lumière, Blachère</li>
<li>Colliers de serrage</li>
</ul>
<h3>Conception de la serre</h3>
<h4>Étape 1 : Préparation de la serre</h4>
<p>Dans la serre, nous avons disposé les capteurs, le pot et un bol pour le brumisateur. Nous avons également percé des trous pour pouvoir faire passer tous les capteurs et le tuyau d’arrosage.</p>
<p>Pour ce qui est de la guirlande lumineuse, il nous a fallu percer quelques trous supplémentaires dans les montants de la serre pour y glisser les colliers de serrage.</p>
<p align="center"> <a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure5.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="La serre &quot;nue&quot; " src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure5_thumb.png" alt="La serre &quot;nue&quot; " width="354" height="266" border="0" /></a></p>
<h4>Étape 2 : Branchement du relais</h4>
<p align="center"> <a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure6.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Les relais" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure6_thumb.png" alt="Les relais" width="240" height="240" border="0" /></a></p>
<p>Afin de pouvoir contrôler les actionneurs, nous avons branché le relais quatre canaux à une carte Raspberry Pi.</p>
<p>Celui-ci est analogue à un interrupteur. Pour chaque canal, une alimentation est nécessaire et chacun d’entre eux peut être piloté individuellement grâces aux différents pins dont dispose le relais. Il faut également prévoir une masse que l’on branche sur le pin “Gnd” du relais.</p>
<p>Par défaut, lorsque les pins d’entrée ne sont pas alimentés, les canaux du relais délivrent la tension d’alimentation correspondante sur la sortie NC (“Normally Closed”) ou sur la sortie NO (“Normally Open”) dans le cas contraire.</p>
<h4>Etape 3 : Éclairage de la serre</h4>
<p>Pour l’éclairage de notre serre, nous avons percé des trous dans la structure et fixé la guirlande avec des colliers de serrage. Celle-ci doit être alimentée par une tension de 230V (<i>tension secteur</i>) et est composée d’un mètre de LEDs rouge et d’un mètre incandescent jaune.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure7.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Les LEDs" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure7_thumb.png" alt="Les LEDs" width="244" height="160" border="0" /></a></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure7bis.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Les LEDs" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure7bis_thumb.png" alt="Les LEDs" width="244" height="184" border="0" /></a></p>
<p>Elle est connectée au relais par la phase et le neutre, chacun branchés sur un canal différent, afin d’isoler totalement la guirlande du secteur et ainsi éviter tout problème avec le reste des composants.</p>
<h4>Etape 4 : Installation du brumisateur</h4>
<p align="center"> <a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure8.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Le relais avec les LEDs et le brumisateur " src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure8_thumb.png" alt="Le relais avec les LEDs et le brumisateur " width="244" height="324" border="0" /></a></p>
<p>Pour augmenter l’humidité de l’air dans la serre, nous avons installé un brumisateur fonctionnant par émissions d’ultrasons. Il nécessite une alimentation de 24V/1A maximum. On le relie ensuite au relais. La masse est directement connectée à l’adaptateur secteur par le biais d’un domino.</p>
<h4>Etape 5 : Installation du système d’arrosage</h4>
<h4 align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure9.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Installation du système d’arrosage" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure9_thumb.png" alt="Installation du système d’arrosage" width="184" height="244" border="0" /></a></h4>
<p>En ce qui concerne l’arrosage, nous disposons d’une pompe submersible qui nécessite une alimentation de 12V et 400mA. Elle est branchée en sortie à un tuyau percé pour un arrosage homogène. Nous la connectons ensuite à un des canaux du relais.</p>
<p align="center"> <a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure10.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Le reservoir" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure10_thumb.png" alt="Le reservoir" width="184" height="244" border="0" /></a></p>
<p>Pour le réservoir, nous avons récupéré un bidon de vinaigre de 5L sur lequel nous avons fait un trou pour le capteur de niveau d’eau et une ouverture pour le remplir et y faire passer la pompe.</p>
<h4>Pour résumer&#8230;</h4>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure11.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Schéma du relais et de la Raspberry" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure11_thumb.png" alt="Schéma du relais et de la Raspberry" width="404" height="301" border="0" /></a></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure12.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Rendu dans la boite " src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure12_thumb.png" alt="Rendu dans la boite " width="185" height="244" border="0" /></a></p>
<h4>Étape 6 : Mise en place des capteurs et paramétrage de la carte Arduino</h4>
<p>Nous installons à présent les capteurs d’humidité/température de l’air, d’humidité du sol, de de luminosité et de niveau d’eau. Nous branchons tous ces capteurs aux pins de la Raspberry ou de l’Arduino en faisant attention au fait que :</p>
<ul>
<li>Les capteurs d’humidité du sol et de niveau d’eau se branchent sur du 5V.</li>
<li>Les capteurs d’humidité/température de l’air et de luminosité sont alimentés en 3,3V.</li>
</ul>
<h5>Étape 6.1 : Capteur d’humidité et de température de l’air</h5>
<p>Le capteur d’humidité et de température de l’air fournissant des données numériques, nous le relions directement à notre Raspberry Pi comme montré sur le schéma ci-dessous :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure13.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Capteur d'humidité/température " src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure13_thumb.png" alt="Capteur d'humidité/température " width="350" height="134" border="0" /></a></p>
<h5>Étape 6.2 : Capteurs de luminosité, d’humidité du sol et de niveau d’eau</h5>
<p><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure14.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; margin-right: auto; border-width: 0px;" title=" Capteurs et Arduino sur la Raspberry " src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure14_thumb.png" alt=" Capteurs et Arduino sur la Raspberry " width="350" height="274" border="0" /></a></p>
<p>Ces capteurs fournissant des données analogiques, nous les avons branchés à une carte Arduino nano qui permet de lire ces données, contrairement à la Raspberry. Elle est reliée directement par USB à la Raspberry Pi comme montré ci-après :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure15.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Arduino et ses capteurs" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure15_thumb.png" alt="Arduino et ses capteurs" width="244" height="184" border="0" /></a><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure16.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Arduino et ses capteurs" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure16_thumb.png" alt="Arduino et ses capteurs" width="244" height="185" border="0" /></a></p>
<h5>Étape 6.3 : Programmation de la carte Arduino</h5>
<p>Dans l’IDE Arduino, nous avons donc commencé par programmer la carte.</p>
<p>Nous ajoutons tout d’abord les librairies d’Adafruit pour pouvoir initialiser le capteur de luminosité et régler le temps d’intégration des données. Dans le gestionnaire de bibliothèque (menu<i> Croquis &gt; Inclure une bibliothèque</i>), nous avons installé les librairies suivantes :</p>
<ul>
<li>Adafruit Unified Sensor</li>
<li>Adafruit TSL2561</li>
</ul>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure17.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Les librairies Arduino " src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure17_thumb.png" alt="Les librairies Arduino " width="350" height="76" border="0" /></a></p>
<p>Au démarrage, dans la méthode “setup()”, nous configurons les pins utilisés. Nous décidons d’utiliser les pins analogiques A0 et A1, respectivement pour le capteur d’humidité du sol et du niveau d’eau et les pins A4 et A5 pour le capteur de luminosité :</p>
<p></p><pre class="crayon-plain-tag">void setup(void) 
{
  Serial.begin(9600);
 
  /*Réglage du capteur de luminosité*/
  if(!tsl.begin()) //Initialisation du capteur
  {
    //S'il y a un problème pour détecter le capteur, vérifier votre connexion
    Serial.print("Ooops, pas de capteur détecté... Vérifier votre connexion!");
    while(1);
  }
  
    //Configuration du gain du capteur et du temps d'intégration
    tsl.enableAutoRange(true);          
    tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS);    
 
}</pre><p></p>
<p>Dans la méthode “loop()”, nous recueillons ensuite les valeurs des capteurs et les faisons afficher sur le Monitor Série en utilisant les commandes analogRead() et Serial.print()  :</p>
<p></p><pre class="crayon-plain-tag">void loop(void) 
{  
  /*Pour recevoir une nouvelle donnée par le capteur de luminosité*/ 
  sensors_event_t event;
  tsl.getEvent(&amp;event);
 
  //Lecture des pins analogiques pour les données des capteurs d'humidité du sol et de niveau d'eau
  Hum_value = analogRead(A0);
  Liquid_value=analogRead(A1);
 
  //Affichage des valeurs sur le Moniteur série
  Serial.print(event.light,0);
  Serial.print(',');
  Serial.print(map(Hum_value,0,1024,0,100)); //Le capteur d'humidité renvoie une valeur en pourcentage 
  Serial.print(',');
  Serial.println(map(Liquid_value,0,512,0,1)); //Le capteur de niveau d'eau retourne la valeur 1 quand il est en contact avec l'eau, 0 sinon
  delay(5000); //Retard de 5s pour éviter de surcharger le buffer de la Raspberry 
}</pre><p></p>
<p>Nous récupèrerons ensuite les données des différents capteurs à l’aide de la carte Raspberry Pi.</p>
<h3>La programmation vers Constellation</h3>
<p>La programmation vers Constellation est divisée en deux packages : le premier correspond à la récupération des données des capteurs et à l’activation des actionneurs, le second a été créé pour gérer le stockage des données en vue de créer des graphiques sur notre application.</p>
<h4>Etape 1 : Package relatif aux capteurs et actionneurs</h4>
<h5>Etape 1.1 : Acquisition des données des capteurs</h5>
<p>Pour récupérer les données des différents capteurs cités précédemment, nous avons utilisé la librairie “Adafruit_DHT” pour Raspberry Pi et la librairie “serial” qui permet de faire le lien entre l’Arduino-Nano et la Raspberry Pi. Ces valeurs vont nous permettre de décider s’il faut activer ou non les actionneurs tels que la pompe, le brumisateur ou les LED.</p>
<p>La fonction ci-après permet de récupérer les valeurs des différents capteurs.</p>
<p></p><pre class="crayon-plain-tag">def getCapteur():
    humiditeAir, temperature = Adafruit_DHT.read_retry(11,4)
    lux, humiditeSol, eau = ser.readline()[:-2].split(",")</pre><p></p>
<p>Nous avons ensuite créé un State Object rassemblant les valeurs d’humidité du sol, d’humidité de l’air, de température et de luminosité ambiante pour pouvoir les publier sur notre Constellation.</p>
<p></p><pre class="crayon-plain-tag">Constellation.PushStateObject("Capteurs", {"HumiditeSol": int(self.humiditeSol), "HumiditeAir": int(self.humiditeAir), "Temperature": int(self.temperature), "Luminosite": int(self.lux)}, "CapteursInfos")</pre><p></p>
<p align="center"> <a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure18.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title=" Le State Object des capteurs " src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure18_thumb.png" alt=" Le State Object des capteurs " width="350" height="169" border="0" /></a></p>
<h5>Etape 1.2 : Activation et désactivation des différents actionneurs (brumisateur, guirlande lumineuse et pompe à eau)</h5>
<p>Comme mentionné précédemment, les actionneurs sont reliés à la Raspberry Pi via un relais quatre canaux. Cela simplifie grandement la programmation : il nous suffit simplement de gérer l’ouverture et la fermeture des relais.</p>
<p>Nous avons donc fait en sorte que chaque actionneur soit associé à son relais grâce à la librairie GPIO de la Raspberry Pi. Ainsi, le code diffère seulement au niveau des numéros des pins utilisés par les actionneurs.</p>
<p>Voici un exemple du code de l’activation et de la désactivation de notre pompe :</p>
<p></p><pre class="crayon-plain-tag">GPIO.setmode(GPIO.BOARD)
GPIO.setup(12,GPIO.OUT)
GPIO.output(12,0)</pre><p></p>
<p>Le pin 12 de la Raspberry est celui relié au relais contrôlant la pompe.</p>
<h5>Etape 1.3 : Automatisation des actionneurs</h5>
<p>Pour réaliser la fonction d’automatisation, nous nous sommes tout d’abord renseignés sur les conditions propices à la bonne croissance des plantes au niveau de l’humidité du sol et de l’air, de la luminosité et de la température de l’air.</p>
<p>Pour le brumisateur, nous avons choisi de l’activer si l’humidité est inférieure à 35% et de le désactiver si l’humidité remonte au dessus de 37%.</p>
<p></p><pre class="crayon-plain-tag">if humiditeAir &gt; 37 and brumisateur:
    DesactiverBrumisateur()
elif humiditeAir &lt; 35 and not brumisateur:
    ActiverBrumisateur()
    time.sleep(1)</pre><p></p>
<p>Pour la pompe, le fonctionnement est différent. Puisque la diffusion de l’eau dans la terre est plus lente, nous activons la pompe pendant 5s avant de la désactiver pendant 30s pour laisser le temps au capteur de ressentir les changements.</p>
<p></p><pre class="crayon-plain-tag">if humiditeSol &lt; 30 and not pompe:
    if self.ticks == 0:
            if self.next_water == 0:
                    ActiverPompe()
            self.next_water = 15
        else:
                    self.next_water -= 1
        elif humiditeSol &gt; 30:
                    self.next_water = 0
    elif pompe:
            self.ticks += 1
               if self.ticks &gt;= 3:
                    DesactiverPompe()
                       self.ticks = 0
time.sleep(1)</pre><p></p>
<p>Ces différentes fonctions sont exécutées dans des threads séparés pour ne pas que le code soit bloquant.</p>
<p>Maintenant, il ne reste plus qu&rsquo;à sécuriser notre système d’arrosage via le capteur de niveau d’eau. Connecté à la carte Arduino nano, ce capteur va nous renvoyer 1 s’il y a de l’eau dans le réservoir, 0 sinon.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure19.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Package PushBullet" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure19_thumb.png" alt="Package PushBullet" width="354" height="163" border="0" /></a></p>
<p>Les données du capteur de niveau d’eau nous permettent d’arrêter le système d’arrosage lorsque le réservoir est presque vide et d’informer l’utilisateur via un PushBullet et l’allumage des LEDs qu’il faut remplir le réservoir.</p>
<p></p><pre class="crayon-plain-tag">Constellation.SendMessage("PushBullet", "PushNote", [ "FriendLead", "Le reservoir d'eau est vide"], Constellation.MessageScope.package)</pre><p></p>
<div align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure20.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Notification sur smartphone" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure20_thumb.png" alt="Notification sur smartphone" width="184" height="364" border="0" /></a></div>
<h4>Étape 2 : Package relatif au stockage des données</h4>
<p>Afin d’historiser les valeurs des capteurs stockées dans un des State Objects du premier package, nous en avons créé un autre que l’on a déployé sur le même serveur que Constellation.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure21.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Enregistrement CSV" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure21_thumb.png" alt="Enregistrement CSV" width="177" height="244" border="0" /></a></p>
<p>Ce package génère une base de données dans un fichier .csv qui est mis à jour toutes les minutes avec les nouvelles données.</p>
<p>Chaque ligne contient la date, l’heure, l’humidité du sol, l’humidité de l’air, la température et la luminosité.</p>
<p></p><pre class="crayon-plain-tag">@Constellation.StateObjectLink(package = "FriendLeafCapteurs", name = "Capteurs")
def RecupValue(stateObject):
    humiditeSol = stateObject.Value.HumiditeSol
    humiditeAir = stateObject.Value.HumiditeAir
    temperature = stateObject.Value.Temperature</pre><p></p>
<p>Nous avons ensuite créé un message callback qui permet de visualiser le fichier CSV dans notre Constellation.</p>
<p></p><pre class="crayon-plain-tag">@Constellation.MessageCallback()
def LireBDD():
'''
: return string : La base de données 
'''
    file = open('BDD.csv','r')
    lines = file.readlines()
    return lines</pre><p></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure22.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="La saga du Message Callback " src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure22_thumb.png" alt="La saga du Message Callback " width="350" height="203" border="0" /></a></p>
<h3>L’interface utilisateur : l’application mobile de monitoring et de pilotage de la serre</h3>
<h4>Étape 1 : Le noyau de l’application</h4>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure23.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="L'application Cordova" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure23_thumb.png" alt="L'application Cordova" width="184" height="364" border="0" /></a></p>
<p>Pour développer l’application mobile nous nous sommes aidés de Cordova, un Framework permettant de créer des application Android et iOS avec des technologies web.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure24.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Cordova" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure24_thumb.png" alt="Cordova" width="240" height="98" border="0" /></a></p>
<p>Nous avons également utilisé jQuery et AngularJS pour faciliter l’interaction entre Javascript et HTML.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure27.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="AngularJS" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure27_thumb.png" alt="AngularJS" width="240" height="143" border="0" /></a></p>
<p>De plus, pour gérer certaines fonctionnalités comme le traitement du CSV ou l’affichage des graphiques, nous avons utilisé des librairies externes comme PapaParser et Chartist. Finalement, pour embellir le CSS, nous avons utilisé le Framework SemanticUI qui ressemble en certain points à Bootstrap.</p>
<h4>Étape 2 : Connexion à Constellation, State Object et Messages Callback</h4>
<p>Pour nous connecter à Constellation avec AngularJS, nous avons utilisé ces lignes de codes :</p>
<p></p><pre class="crayon-plain-tag">Constellation.initializeClient(url_port, sha, "FriendLeaf");

Constellation.onConnectionStateChanged(function (change) {
   //suite
});</pre><p></p>
<p>et une ligne de ce type pour chaque State Object :</p>
<p></p><pre class="crayon-plain-tag">Constellation.registerStateObjectLink("*", "FriendLeafCapteurs", "Actionneurs", "*", function (so) {
    //suite
});</pre><p></p>
<p>Quant aux messages Callback, ils sont envoyés comme suit :</p>
<p></p><pre class="crayon-plain-tag">Constellation.sendMessage({ Scope: 'Package', Args: ['FriendLeafCapteurs'] }, 'DesactiverBrumisateur');</pre><p></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure28.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Page de configuration" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure28_thumb.png" alt="Page de configuration" width="184" height="364" border="0" /></a></p>
<p>Pour que l’application soit utilisable sur n’importe quelle Constellation, nous avons créé un page de configuration où l’utilisateur rentre l’adresse de sa constellation, le port, et des identifiants.</p>
<p>Une fois tout cela rempli, le nom d’utilisateur et le mot de passe sont hachés en SHA1 grâce à une librairie externe et la connexion à Constellation commence.</p>
<p>Lorsque l’application se lance pour la première fois, l&rsquo;utilisateur est directement redirigé vers cette page pour entrer les informations nécessaires.</p>
<h4>Étape 3 : Affichage des données en temps réel</h4>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure29.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Le tableau de bord " src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure29_thumb.png" alt="Le tableau de bord" width="184" height="364" border="0" /></a></p>
<p>Pour l’affichage des données en temps réel nous avons utilisé des images SVG car elles sont très flexibles et nous voulions réaliser des barres de progression en arc de cercle. Pour les valeurs numériques on affiche un scope AngularJS dans lequel sont stockés les valeurs des capteurs.</p>
<p>Le code JS :</p>
<p></p><pre class="crayon-plain-tag">//Stockage des valeurs des capteurs dans la variable capteur
scope.capteurs["humiditeAir"] = so.Value.HumiditeAir;
scope.$apply(); //Applications des modifications du scope

//Pour changer le remplissage de la jauge 
$("#h_air_gauge").css("stroke-dasharray",(so.Value.HumiditeAir*18)/100 + " 18 0");</pre><p></p>
<p>SVG en HTML :</p>
<p></p><pre class="crayon-plain-tag">&lt;svg viewbox="0 0.5 10 8"&gt;
    &lt;defs&gt;
    &lt;linearGradient id="linear" x1="0%" y1="0%" x2="100%" y2="0%"&gt;
        &lt;stop offset="0%" stop-color="#00ee4f"/&gt;
        &lt;stop offset="66%" stop-color="#eeae00"/&gt;
        &lt;stop offset="100%" stop-color="#ee0000"/&gt;
    &lt;/linearGradient&gt;
    &lt;/defs&gt;
    &lt;text x="50%" y="50%" id="h_air_value" text-anchor="middle"  alignment-baseline="middle" fill="#00ee4f"&gt;
        {{Math.round(capteurs["humiditeAir"])}}%
    &lt;/text&gt;
    &lt;path d="M2 8 A 4 4 0 1 1 8 8" fill="none" stroke-width="0.78" stroke="#E8F6FD" /&gt;
    &lt;path class="loader" id="h_air_gauge" d="M2 8 A 4 4 0 1 1 8 8" fill="none" stroke-width="0.8" 
stroke="url(#linear)" /&gt;
&lt;/svg&gt;</pre><p></p>
<h4>Étape 4 : Contrôler sa serre</h4>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure32.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Page de contrôle" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure32_thumb.png" alt="Page de contrôle" width="124" height="244" border="0" /></a><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure30.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Page de contrôle" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure30_thumb.png" alt="Page de contrôle" width="124" height="244" border="0" /></a><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure31.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Page de contrôle" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure31_thumb.png" alt="Page de contrôle" width="124" height="244" border="0" /></a></p>
<p>Nous avons également prévu dans l’application de pouvoir gérer les différents actionneurs de la serre.</p>
<p>Pour gérer le côté automatique du package responsable des capteurs nous avons utilisés des sliders qui lorsqu’activés, vont envoyer un Message Callback comme décrit ci-dessus. On va également suivre l’évolution du State Object indiquant si l’automatisation est activée pour tel ou tel actionneur et ainsi bloqué ou non le bouton d’activation manuel. Car oui, il est également possible d’activer manuellement chaque actionneur grâce à un bouton.</p>
<h4>Étape 5 : Les graphiques</h4>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure33.png"><img class="colorbox-6084"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Graphiques" src="https://developer.myconstellation.io/wp-content/uploads/2018/07/figure33_thumb.png" alt="Graphiques" width="184" height="361" border="0" /></a></p>
<p>Pour ce qui est des graphiques nous avons utilisé une librairie externe que nous avons modifié pour la rendre compatible sur mobile. Cette librairie s’appelle Chartist. Grâce à elle nous avons pu faire de superbes graphiques.</p>
<h3>Conclusion</h3>
<p>Voilà qui conclut les grandes étapes de la réalisation de FriendLeaf. Comme vous avez pu le voir, la serre remplit complètement son rôle. C’est un projet ludique, simple à réaliser et facilement transposable sur d’autres installations grâce aux State Objects et aux messages Callback. C’est également un bon point de départ pour prendre en main la plateforme Constellation. Nous espérons vraiment qu’il vous a plu et que vous allez réaliser votre propre serre.</p>
<p>Nous tenons également à remercier Léa, le jardin de Théo et les parents de Marine qui nous ont fourni quelques accessoires nécessaires à la serre.</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/tutorials/friendleaf-la-serre-connectee-grace-a-constellation/">FriendLeaf : la serre connectée grâce à Constellation</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://developer.myconstellation.io/tutorials/friendleaf-la-serre-connectee-grace-a-constellation/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Créer un boitier connecté « Mix box » permettant de contrôler votre ordinateur</title>
		<link>https://developer.myconstellation.io/tutorials/creer-un-boitier-connecte-mix-box-permettant-de-controler-votre-ordinateur/</link>
					<comments>https://developer.myconstellation.io/tutorials/creer-un-boitier-connecte-mix-box-permettant-de-controler-votre-ordinateur/#respond</comments>
		
		<dc:creator><![CDATA[Sebastien Warin]]></dc:creator>
		<pubDate>Wed, 16 May 2018 14:24:43 +0000</pubDate>
				<category><![CDATA[Tutoriels]]></category>
		<category><![CDATA[tutoriel]]></category>
		<category><![CDATA[MessageCallback]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[ESP8266]]></category>
		<category><![CDATA[Pression]]></category>
		<category><![CDATA[WindowsControl]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=5991</guid>

					<description><![CDATA[<p>Tutoriel proposé par Marc-Antoine DUVAL, Joël GUILLEM et Quentin LEVERT. Dans ce tutoriel, nous allons créer un boitier qui est relié à un ou plusieurs ordinateurs de la maison grâce à un ESP8266 connecté à constellation. Des LEDs permettent à</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/tutorials/creer-un-boitier-connecte-mix-box-permettant-de-controler-votre-ordinateur/">Créer un boitier connecté « Mix box » permettant de contrôler votre ordinateur</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><em>Tutoriel proposé par Marc-Antoine DUVAL, Joël GUILLEM et Quentin LEVERT.</em></p>

<p>Dans ce tutoriel, nous allons créer un boitier qui est relié à un ou plusieurs ordinateurs de la maison grâce à un ESP8266 connecté à constellation. Des LEDs permettent à l’utilisateur de suivre le résultat des commandes en temps réel. Le boitier permet de commander à distance le lecteur de vidéo VLC media player à travers différentes fonctionnalités. Il gère :</p>
<ul>
<li>Le volume</li>
<li>La marche avant / marche arrière au cours d’un visionnage</li>
<li>La mise en lecture / pause d’une vidéo</li>
<li>La fermeture de VLC</li>
</ul>
<h2>Prérequis</h2>
<ul>
<li>Un ESP8266, nous utilisons un D1-mini</li>
<li>6 boutons poussoirs tactiles blancs</li>
<li>2 LEDs RGB</li>
<li>Une plaque de plexiglas noire</li>
<li>Une imprimante laser</li>
<li>Un serveur constellation</li>
<li>Le package « Windows Control » déployé sur une ou plusieurs sentinelles</li>
</ul>
<h2>Etape 1 : Réaliser le montage des boutons et LEDs</h2>
<p>Dans un premier temps, nous allons réaliser le montage électronique des composants. Tout d’abord il est nécessaire de brancher l’ESP8266 à la breadboard et de l’alimenter en le connectant en mini-USB à une source d&rsquo;alimentation. Il faut ensuite brancher la masse de l’ESP à la colonne de masse de la breadboard.</p>
<p>Pour les besoins de l’explication du montage, tous les autres composants seront connectés à la breadboard, cependant il est tout à fait possible de les connecter une fois insérés dans le boitier (voir Etape 2). Le schéma global est présenté ci-après.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/05/Cablage.png"><img class="colorbox-5991"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Cablage" src="https://developer.myconstellation.io/wp-content/uploads/2018/05/Cablage_thumb.png" alt="Cablage" width="354" height="357" border="0" /></a></p>
<p>&nbsp;</p>
<p>Ici nous avons choisi 2 LEDs RGB afin d’améliorer l’effet visuel pour obtenir une LED de couleur jaune. La première LED verte pourra être connectée directement au pin D8 de l’ESP. Quant à la seconde LED RGB, il suffit de connecter les pattes correspondant aux LEDs rouge et verte à la même ligne, puis de lier cette ligne au pin D7 de l’ESP.</p>
<p>Les boutons poussoirs sont à connecter avec les broches 1 et 3 d’un côté et les broches 2 et 4 de l’autre. Le branchement est classique, à savoir les pin D1 à D6 connectés directement sur la patte 1 de chaque bouton, puis retour à la masse sur la patte 3 des boutons. Lorsque l’on appuie sur le bouton, le pin correspondant passera donc en état bas (LOW) et est en état haut (HIGH) tant que l’on n’appuie pas.</p>
<p>Une fois le câblage terminé, nous allons passer à la réalisation du boitier qui contiendra à l’intérieur l’ESP et la breadboard.</p>
<h2>Etape 2 : Réaliser le boitier</h2>
<p>Dans un second temps, il nous faut un boitier que nous pourrons ouvrir pour mettre notre ESP. Le design de la face de devant doit aussi correspondre au nombre de boutons et LED que l’on souhaite mettre en place.</p>
<p>Afin de résoudre cette problématique, nous avons décidé d’imprimer le boitier grâce à une imprimante laser. Nous avons utilisé une plaque de plexiglas noir d’une épaisseur de 3mm.</p>
<p>Tout d’abord, nous avons créé le fond de la boite sans le couvercle. Nous avons utilisé le site : <a href="http://carrefour-numerique.cite-sciences.fr/fablab/wiki/doku.php?id=projets:generateur_de_boites">http://carrefour-numerique.cite-sciences.fr/fablab/wiki/doku.php?id=projets:generateur_de_boites</a> qui permet de générer automatique le fichier .svg qui sera reconnu et utilisé pour l’impression laser. Il suffit d’entrer les dimensions voulues.</p>
<p>Ensuite nous avons utilisé SolidWorks afin de créer notre face avant personnalisée. Nous avons choisi percer 2 trous pour les LEDs et 6 pour les boutons carrés. Après la réalisation de la pièce, plusieurs étapes sont alors nécessaires pour exporter le fichier SolidWorks en fichier .svg.</p>
<ul>
<li>Sélectionner la vue correspondant à la pièce à réaliser</li>
<li>Enregistrer le fichier SolidWorks au format .DXF.</li>
<li>Sélectionner la vue à exporter. Ici, on sélectionne la vue en cours.</li>
</ul>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/05/face_avant.png"><img class="colorbox-5991"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Choix de la face à sauvegarder" src="https://developer.myconstellation.io/wp-content/uploads/2018/05/face_avant_thumb.png" alt="Choix de la face à sauvegarder" width="354" height="194" border="0" /></a></p>
<ul>
<li>Installer Inkscape, ce logiciel permettra de créer le fichier pour l’imprimante laser.</li>
<li>Importer le fichier dans Inkscape. Il faut désactiver mise à l’échelle automatique.</li>
<li>Sauvegarder le fichier qui sera utilisé pour l’impression laser.</li>
</ul>
<p>Enfin, nous avons assemblé toutes les pièces du boitier :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/05/Boitier.jpg"><img class="colorbox-5991"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Boitier" src="https://developer.myconstellation.io/wp-content/uploads/2018/05/Boitier_thumb.jpg" alt="Boitier" width="254" height="316" border="0" /></a></p>
<h2>Etape 3 : Programmation</h2>
<p>Dans un premier temps, il faut vous assurer que votre ESP8266 soit connecté à votre constellation, si vous ne savez pas comment vous y prendre, je vous invite donc à suivre le tutoriel réalisé par Sébastien Warin : <a href="https://developer.myconstellation.io/getting-started/connecter-un-arduino-ou-un-esp8266-constellation/">https://developer.myconstellation.io/getting-started/connecter-un-arduino-ou-un-esp8266-constellation/</a> .</p>
<p>Pour commencer, il faut déclarer le matériel dans la méthode setup de notre ESP8266, conformément à <b>l&rsquo;étape 1, </b>nous avons choisi les pin 1 à 6 en mode PULLUP pour les boutons et les pins 7 &amp; 8 pour les LEDs :</p>
<p></p><pre class="crayon-plain-tag">pinMode(D1,INPUT_PULLUP);
  pinMode(D2,INPUT_PULLUP);
  pinMode(D3,INPUT_PULLUP);
  pinMode(D4,INPUT_PULLUP);
  pinMode(D5,INPUT_PULLUP);
  pinMode(D6,INPUT_PULLUP);
  pinMode(D7,OUTPUT);
  pinMode(D8,OUTPUT);
  digitalWrite(D7,LOW);
  digitalWrite(D8,LOW);</pre><p></p>
<p>Nous avons associé à chaque bouton un messageCallback avec les paramètres permettant d&rsquo;effectuer l&rsquo;action voulu. Pour faire cela, nous avons réalisé une fonction « checkButtonState » qui permet de gérer les évènements d&rsquo;appuie sur les boutons et d&rsquo;appeler le messageCallback correspondant au bouton. Juste avant l&rsquo;appel du messageCallback, la led cablée au pin D7 est allumée pour une période de 2 secondes afin de montrer à l&rsquo;utilisateur que l&rsquo;ESP8266 a bien réalisé l&rsquo;action. Cela permettra en cas de disfonctionnement, que l&rsquo;utilisateur puisse savoir si c&rsquo;est le hardware ou la transmission Wifi/Constellation qui est défectueux.</p>
<p>Le tableau ci-dessous récapitule les actions, messageCallback et pins qui sont associés ensemble :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/05/image-8.png"><img class="colorbox-5991"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="image" src="https://developer.myconstellation.io/wp-content/uploads/2018/05/image_thumb-6.png" alt="image" width="450" height="109" border="0" /></a></p>
<p>Ci-dessous le code de la fonction checkButtonState :</p>
<p></p><pre class="crayon-plain-tag">void checkButtonState(){
  
  static int lastButtonStateD1 = HIGH;
  static int lastButtonStateD2 = HIGH;
  static int lastButtonStateD3 = HIGH;
  static int lastButtonStateD4 = HIGH;
  static int lastButtonStateD5 = HIGH;
  static int lastButtonStateD6 = HIGH;
  static long led1TimeLitUP = 0;
  // If the led is lit up for 2 secondes, we shut off the led
  if(millis() - led1TimeLitUP &gt;2000){
      digitalWrite(D7, LOW);
    }
  // We retrieve the pin value
  int reading = digitalRead(D1);
// If pin value has changed
  if (reading != lastButtonStateD1){
   // And if pin value is high which mean button is pushed, then we make the associated action
    if (reading == HIGH){
      // We lit up the led in order to show to the user that the messageCallback is sending
       digitalWrite(D7,HIGH);
       // "led1TimeLitUp" take the value of the moment when it has been litted up
       led1TimeLitUP = millis();
       // we use the messageCallback to do the wanted action
       constellation.sendMessage(Package, "WindowsControl", "VolumeUp","{}");
     
      }
      lastButtonStateD1 = reading ;
     
      return;
  }
  reading = digitalRead(D2);
  if (reading != lastButtonStateD2){
     if (reading == HIGH){
        digitalWrite(D7,HIGH); 
        led1TimeLitUP = millis();
        constellation.sendMessage(Package, "WindowsControl", "VolumeDown", "{}"); 
        
      }
      lastButtonStateD2 = reading;
      return;
    }
  reading = digitalRead(D3);
  if (reading != lastButtonStateD3){
     if (reading == HIGH){
        digitalWrite(D7,HIGH); 
        led1TimeLitUP = millis();
        constellation.sendMessage(Package, "WindowsControl", "SendKey", "SpaceBar");
       
      }
      lastButtonStateD3 = reading;
      return;
    }
    
  reading = digitalRead(D4);
  if (reading != lastButtonStateD4){
     if (reading == HIGH){
        digitalWrite(D7,HIGH); 
        led1TimeLitUP = millis();
        constellation.sendMessage(Package, "WindowsControl", "SendCombinationOfKey", "['ALT', 'Left']");
        
      }
      lastButtonStateD4 = reading;
      return;
    }
   reading = digitalRead(D5);
    if (reading != lastButtonStateD5){
     if (reading == HIGH){
        digitalWrite(D7,HIGH); 
        led1TimeLitUP = millis();
        constellation.sendMessage(Package, "WindowsControl", "SendCombinationOfKey", "['ALT', 'Right']");
      
      }
      lastButtonStateD5 = reading;
      return;
    }
    reading = digitalRead(D6);
    if (reading != lastButtonStateD6){
     if (reading == HIGH){
        digitalWrite(D7,HIGH); 
        led1TimeLitUP = millis();
        constellation.sendMessage(Package, "WindowsControl", "SendCombinationOfKey", "['CTRL', 'Q']");
        
      }
      lastButtonStateD6 = reading;
      return;
    }  
  }</pre><p></p>
<p>Et voilà notre boitier de contrôle est opérationnel. Il ne reste plus qu’à l’alimenter et vous avons à notre disposition des boutons physiques pour piloter notre Windows facilement.</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/tutorials/creer-un-boitier-connecte-mix-box-permettant-de-controler-votre-ordinateur/">Créer un boitier connecté « Mix box » permettant de contrôler votre ordinateur</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://developer.myconstellation.io/tutorials/creer-un-boitier-connecte-mix-box-permettant-de-controler-votre-ordinateur/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Créer une serrure connectée à Constellation</title>
		<link>https://developer.myconstellation.io/tutorials/creer-une-serrure-connectee-constellation/</link>
					<comments>https://developer.myconstellation.io/tutorials/creer-une-serrure-connectee-constellation/#respond</comments>
		
		<dc:creator><![CDATA[Sebastien Warin]]></dc:creator>
		<pubDate>Wed, 16 May 2018 14:05:31 +0000</pubDate>
				<category><![CDATA[Tutoriels]]></category>
		<category><![CDATA[ESP8266]]></category>
		<category><![CDATA[Serrure]]></category>
		<category><![CDATA[tutoriel]]></category>
		<category><![CDATA[MessageCallback]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Constellation]]></category>
		<category><![CDATA[AngularJS]]></category>
		<category><![CDATA[Arduino]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=5979</guid>

					<description><![CDATA[<p>Article proposé par Olivier MOUILLOT, Mohammed TAHRI JOUTEI HASSANI et Gaëtan DELABY Vous attendez quelqu’un chez vous mais vous êtes occupé à faire autre chose. Cette serrure connectée vous permettra de contrôler l’ouverture de la porte d’entrée depuis n’importe quelle</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/tutorials/creer-une-serrure-connectee-constellation/">Créer une serrure connectée à Constellation</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><em>Article proposé par Olivier MOUILLOT, Mohammed TAHRI JOUTEI HASSANI et Gaëtan DELABY</em></p>
<p>Vous attendez quelqu’un chez vous mais vous êtes occupé à faire autre chose. Cette serrure connectée vous permettra de contrôler l’ouverture de la porte d’entrée depuis n’importe quelle pièce de votre domicile, et cela en un clic grâce à votre smartphone. Nous allons voir pas à pas comment la mettre en place simplement.</p>

<h2>Prérequis</h2>
<p>Pour réaliser ce projet, il vous faut :</p>
<ul>
<li>Une gâche électrique 12V / 500 A</li>
<li>Un ESP8266</li>
<li>Un régulateur de tension LM1117</li>
<li>Un transistor NPN TIP 110</li>
<li>Une résistance 5,6 KΩ</li>
<li>Deux condensateurs 0,1 µF et 0,33 µF</li>
<li>Du fil électrique</li>
<li>Une batterie 12V</li>
<li>Un serveur Constellation (Un ordinateur pourra faire l’affaire)</li>
</ul>
<h2>Etape 1 : réaliser une serrure connectée</h2>
<p>Dans un premier temps, il nous a fallu trouver une serrure adaptée au développement du projet sur laquelle nous pouvions brancher nos fils électriques. Nous avons donc opté pour la serrure suivante que vous pourrez vous procurer via <a href="https://www.amazon.fr/Extel-90301-3-%C3%A9lectrique-passage-serrure/dp/B002LS6OTA/ref=sr_1_2?ie=UTF8&amp;qid=1511196788&amp;sr=8-2&amp;keywords=g%C3%A2che+%C3%A9lectrique&amp;dpID=31-7q-yaD0L&amp;preST=_SX300_QL70_&amp;dpSrc=srch">ce lien </a>.</p>
<p align="center"><a href="https://www.amazon.fr/Extel-90301-3-%C3%A9lectrique-passage-serrure/dp/B002LS6OTA/ref=sr_1_2?ie=UTF8&amp;qid=1511196788&amp;sr=8-2&amp;keywords=g%C3%A2che+%C3%A9lectrique&amp;dpID=31-7q-yaD0L&amp;preST=_SX300_QL70_&amp;dpSrc=srch"><img class="colorbox-5979"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Extel Weca 90301.3 Gâche électrique sans passage de serrure" src="https://developer.myconstellation.io/wp-content/uploads/2018/05/image.png" alt="Extel Weca 90301.3 Gâche électrique sans passage de serrure" width="146" height="331" border="0" /></a></p>
<p>Pour de plus amples informations techniques sur la gâchette, vous pouvez également regarder <a href="http://www.produktinfo.conrad.com/datenblaetter/75000-99999/094195-an-01-ml-gache_elec_de_en_fr_nl.pdf">ici</a>.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/05/image-1.png"><img class="colorbox-5979"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="serrure de dessus" src="https://developer.myconstellation.io/wp-content/uploads/2018/05/image_thumb.png" alt="serrure de dessus " width="354" height="266" border="0" /></a></p>
<p>Il faut ensuite créer le câblage nécessaire au fonctionnement de la serrure. Notre principal problème a été de convertir l’alimentation indispensable de 12V pour la serrure en une alimentation de 3,3V nécessaire à l’utilisation de notre ESP. A l’aide du régulateur de tension, nous avons réalisé le montage suivant en entrée de l’ESP.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/05/image-2.png"><img class="colorbox-5979"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title=" régulateur de tension" src="https://developer.myconstellation.io/wp-content/uploads/2018/05/image_thumb-1.png" alt=" régulateur de tension" width="400" height="138" border="0" /></a></p>
<p>Afin de laisser passer le courant et de faire fonctionner la gâchette, le transistor TIP110 en série avec une résistance 5,6kΩ se placent en sortie GPIO de l’ESP. Une LED peut être également placée à cette même sortie afin de visualiser l’état de la serrure.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/05/image-3.png"><img class="colorbox-5979"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="sortie ESP" src="https://developer.myconstellation.io/wp-content/uploads/2018/05/image_thumb-2.png" alt="sortie ESP" width="350" height="232" border="0" /></a></p>
<p>Enfin, voici le montage final reprenant tous les composants :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/05/image-4.png"><img class="colorbox-5979"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Schéma global du circuit" src="https://developer.myconstellation.io/wp-content/uploads/2018/05/image_thumb-3.png" alt="Schéma global du circuit" width="350" height="184" border="0" /></a></p>
<h2>Etape 2 : Programmation</h2>
<p>Vous avez fait la moitié du travail, voyons ensemble comment coder notre ESP8266.</p>
<p>La fonction de base de la gâche électrique est assez simple : couper le courant à travers la serrure pour la fermer ou le laisser passer le courant afin d’ouvrir la serrure. En premier lieu, nous avons développé le code Arduino servant à faire faire passer du courant ou non dans la gâche. Pour cela nous devons dans un premier temps connecter notre ESP8266 à Constellation. Pour découvrir comment connecter votre ESP à Constellation, <a href="https://developer.myconstellation.io/getting-started/connecter-un-arduino-ou-un-esp8266-constellation/">suivez ce guide</a>.</p>
<p>En ce qui concerne le code Arduino permettant de contrôler la serrure, vous en trouverez ci-dessous l’intégralité.</p>
<p></p><pre class="crayon-plain-tag">#include &lt;Constellation.h&gt;

// ESP8266 Wifi
#include &lt;ESP8266WiFi.h&gt;
char ssid[] = "MY-WIFI";
char password[] = "xxxxxxxx";

define LOCK_PIN D3

// Constellation client
Constellation&lt;WiFiClient&gt; constellation("172.20.10.2", 8088, "d1mini", "demoisen", "xxxxxxxx");

void setup(void) {
  Serial.begin(115200);  delay(10);

  //SET I/O 
  pinMode(LOCK_PIN, OUTPUT);
  // INITIAL mode
  digitalWrite(LOCK_PIN , LOW);

  // Set Wifi mode
  if (WiFi.getMode() != WIFI_STA) {
    WiFi.mode(WIFI_STA);
    delay(10);
  }
  
  // Connecting to Wifi  
  Serial.print("Connecting to ");
  Serial.println(ssid);  
  WiFi.begin(ssid, password);  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("WiFi connected. IP: ");
  Serial.println(WiFi.localIP());

  constellation.pushStateObject("State", false);
  
  constellation.registerMessageCallback("OpenDoor", MessageCallbackDescriptor().setDescription("Ouvres la porte"),
      [](JsonObject&amp; message) {
            digitalWrite(LOCK_PIN, HIGH);
            constellation.pushStateObject("State", true);
            delay(4000);
            digitalWrite(LOCK_PIN, LOW);   
            constellation.pushStateObject("State", false);    
      });
  
  // Declare the package descriptor
  constellation.declarePackageDescriptor();

  // WriteLog info
  constellation.writeInfo("Virtual Package on '%s' is started !", constellation.getSentinelName());  
}

void loop(void) {
  constellation.loop();
}</pre><p></p>
<p>L’étape suivante a été d’utiliser la librairie Constellation <a href="https://developer.myconstellation.io/client-api/arduino-esp-api/recevoir-des-messages-et-exposer-des-methodes-messagecallback-sur-arduino-esp/">pour ajouter un « MessageCallback</a> » afin de contrôler le GPIO de la gâchette, <a href="https://developer.myconstellation.io/client-api/arduino-esp-api/produire-des-stateobjects-depuis-arduino-esp/">couplé à un « StateObject</a> » permettant de maintenir l’état de la serrure dans Constellation :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/05/image-5.png"><img class="colorbox-5979"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="StateObject" src="https://developer.myconstellation.io/wp-content/uploads/2018/05/image_thumb-4.png" alt="StateObject" width="354" height="258" border="0" /></a></p>
<p>Constellation va aller garder en permanence l’état de la serrure grâce au StateObject « State ».</p>
<p>Dorénavant, n’importe qui connecté au serveur peut se servir du MessageCallback « OpenDoor» exposé par l’ESP que nous avons utilisé pour faire permuter l’ouverture et la fermeture automatique de la serrure. Un délai de 4 secondes est programmé avant que la serrure ne se referme après ouverture de la gâche. Nous avons ajouté cette fonctionnalité afin d’ajouter une partie sécurité à notre dispositif.</p>
<p align="center"><img class="colorbox-5979"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="MessageCallback" src="https://developer.myconstellation.io/wp-content/uploads/2018/05/image-6.png" alt="MessageCallback" width="350" height="73" border="0" /></p>
<p>&nbsp;</p>
<p>On obtient alors simplement le pilotage de notre gâchette avec Constellation, dont l’état pourra être contrôlé grâce à une page Web qu’on vous présente dans la partie suivante.</p>
<h2>Etape 3 : Piloter sa serrure à l’aide d’une page web</h2>
<p>Pour cette dernière étape qui consiste à piloter notre serrure connectée grâce à une page Web. Il s’agit principalement de l’interface via laquelle vous pourrez facilement décider de l’ouverture ou la fermeture de la serrure.</p>
<p>Voici le code HTML que nous avons mis en place :</p>
<p></p><pre class="crayon-plain-tag">&lt;!DOCTYPE html&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml" ng-app="MyDemoApp"&gt;
&lt;head&gt;
    &lt;link rel="stylesheet" href="bruh.css" /&gt;
    &lt;title&gt;Serrure connectée&lt;/title&gt;
    &lt;link rel="stylesheet" href="style.css" /&gt;
    &lt;script type="text/javascript" src="https://code.jquery.com/jquery-2.2.4.min.js"&gt;&lt;/script&gt;
    &lt;script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/signalr/jquery.signalr-2.2.2.min.js"&gt;&lt;/script&gt;
    &lt;script type="text/javascript" src="https://cdn.myconstellation.io/js/Constellation-1.8.2.min.js"&gt;&lt;/script&gt;
    &lt;script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"&gt;&lt;/script&gt;
    &lt;script type="text/javascript" src="https://cdn.myconstellation.io/js/ngConstellation-1.8.2.min.js"&gt;&lt;/script&gt;
    
    &lt;script&gt;
        var myDemoApp = angular.module('MyDemoApp', ['ngConstellation']);
        myDemoApp.controller('MyController', ['$scope',  'constellationConsumer', function ($scope, constellation) {
  
          constellation.initializeClient("http://172.20.10.2:8088", "xxxxxxxxxx", "WebPage");
          constellation.onConnectionStateChanged(function (change) {
            if (change.newState === $.signalR.connectionState.connected) {
                console.log("Je suis connecté !");
                constellation.requestSubscribeStateObjects("*", "DoorLock", "*", "*");
                }
            });

          constellation.onUpdateStateObject(function (stateObject) {
              console.log(stateObject);
              $scope[stateObject.Name] = stateObject.Value;
              $scope.$apply();
          });
          
          $scope.openDoor = function(){
                constellation.sendMessage({Scope: 'Package', Args: ['DoorLock']}, 'OpenDoor');
            };

            
          constellation.connect();

                }]);
    &lt;/script&gt;
 
&lt;/head&gt;

&lt;body ng-controller="MyController"&gt;
        
    &lt;button ng-click="openDoor()"&gt; OPEN &lt;/button&gt;

&lt;/body&gt;
&lt;/html&gt;</pre><p></p>
<p>Avec quelques lignes de CSS, le rendu final de notre page est le suivant et on ne peut plus simple d’utilisation pour le pilotage :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/05/image-7.png"><img class="colorbox-5979"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Page Web" src="https://developer.myconstellation.io/wp-content/uploads/2018/05/image_thumb-5.png" alt="Page web" width="354" height="169" border="0" /></a></p>
<p>Pour la suite il suffit d’héberger cette page HTML sur un serveur Web quelconque et vous pourrez ouvrir votre porte depuis un PC, un smartphone, une table ou autre.</p>
<p>Et comme l’ouverture de la porte est exposer comme un <a href="https://developer.myconstellation.io/concepts/messaging-message-scope-messagecallback-saga/">MessageCallback</a>, vous pourrez l’ouvrir depusi un code <a href="https://developer.myconstellation.io/client-api/net-package-api/envoyer-des-messages-invoquer-des-messagecallbacks/">C#,</a> <a href="https://developer.myconstellation.io/client-api/python-api/envoyer-des-messages-et-invoquer-des-messagecallbacks-en-python/">Python</a>, <a href="https://developer.myconstellation.io/client-api/arduino-esp-api/envoyer-des-messages-et-invoquer-des-messagecallbacks-depuis-arduino-esp/">Arduino</a> ou même un simple <a href="https://developer.myconstellation.io/client-api/rest-api/interface-rest-consumer/#Envoyer_des_messages">appel HTTP</a> à l’API Constellation. N’hésitez pas à utiliser le “<a href="https://developer.myconstellation.io/constellation-platform/constellation-console/messagecallbacks-explorer/">Code Generator</a>” de la console Constellation.</p>
<p>Au final avec une gâche électrique, un ESP8266, une Constellation et quelques lignes d’Arduino, on est capable d’ouvrir une porte depuis tous type d’application.</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/tutorials/creer-une-serrure-connectee-constellation/">Créer une serrure connectée à Constellation</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://developer.myconstellation.io/tutorials/creer-une-serrure-connectee-constellation/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Créer une prise connectée avec un ESP8266</title>
		<link>https://developer.myconstellation.io/tutorials/creer-une-prise-connectee-avec-un-esp8266/</link>
					<comments>https://developer.myconstellation.io/tutorials/creer-une-prise-connectee-avec-un-esp8266/#respond</comments>
		
		<dc:creator><![CDATA[Lucas]]></dc:creator>
		<pubDate>Tue, 31 Oct 2017 11:29:46 +0000</pubDate>
				<category><![CDATA[Tutoriels]]></category>
		<category><![CDATA[Relais]]></category>
		<category><![CDATA[XBMC]]></category>
		<category><![CDATA[Kodi]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[MessageCallback]]></category>
		<category><![CDATA[Switch]]></category>
		<category><![CDATA[StateObjectLink]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[ESP8266]]></category>
		<category><![CDATA[ESP]]></category>
		<category><![CDATA[Domotique]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=5668</guid>

					<description><![CDATA[<p>Par Lucas Dupuis La prise connectée est un élément phare de la domotique de la maison. Il permet d&#8217;allumer ou d&#8217;éteindre un équipement branché dessus ou encore de connaitre sa consommation en énergie. Dans mon cas, j&#8217;avais besoin d&#8217;allumer ou</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/tutorials/creer-une-prise-connectee-avec-un-esp8266/">Créer une prise connectée avec un ESP8266</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><em>Par Lucas Dupuis</em></p>
<p>La prise connectée est un élément phare de la domotique de la maison. Il permet d&rsquo;allumer ou d&rsquo;éteindre un équipement branché dessus ou encore de connaitre sa consommation en énergie. Dans mon cas, j&rsquo;avais besoin d&rsquo;allumer ou d&rsquo;éteindre les enceintes de mon média center automatiquement lorsque ce dernier était démarré.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/10/2016-08-08-16.32.30.jpg"><img class="colorbox-5668"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Prise connectée" src="https://developer.myconstellation.io/wp-content/uploads/2017/10/2016-08-08-16.32.30_thumb.jpg" alt="Prise connectée" width="404" height="304" border="0" /></a></p>
<p align="left">Découvrons ensemble comment créer sa prise connectée avec un ESP8266.</p>
<p><span id="more-5668"></span></p>
<h2>Prérequis</h2>
<p>Pour ce tutoriel, il vous faut :</p>
<ul>
<li>Un bloc prise avec un interrupteur</li>
<li>Un transformateur AC/DC 5v</li>
<li>Un ESP-01 (ESP8266)</li>
<li>Un régulateur de tension 3.3v</li>
<li>Un relais 220V pilotable en 5v</li>
<li>Un transistor, des résistances, des leds, une diode, des condensateurs</li>
<li>Du fil électrique</li>
<li>Un pistolet à colle et une drémel</li>
<li>Un serveur Constellation</li>
</ul>
<h2>Etape 1 : Construire la prise</h2>
<p>Dans un premier temps, il nous faut un boitier abordable que nous pourrons ouvrir pour insérer notre ESP à l&rsquo;intérieur. Après quelques recherches, j&rsquo;ai opté pour le <a href="http://www.conrad.fr/ce/fr/product/778994/Prise-intermdiaire-commutable-Renkforce-778994-1-ple-argent">boitier Renkforce disponible chez Conrad</a> pour 3€ environ.</p>
<p>On commence donc par l’ouvrir pour la vider littéralement :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/10/2016-11-10-22.38.32.jpg"><img class="colorbox-5668"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Prise Renkforce" src="https://developer.myconstellation.io/wp-content/uploads/2017/10/2016-11-10-22.38.20_thumb.jpg" alt="Prise Renkforce" width="204" height="271" border="0" /><img class="colorbox-5668"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Prise Renkforce" src="https://developer.myconstellation.io/wp-content/uploads/2017/10/2016-11-10-22.38.32_thumb.jpg" alt="Prise Renkforce" width="204" height="271" border="0" /></a></p>
<p align="center"><img class="colorbox-5668"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Démontage" src="https://developer.myconstellation.io/wp-content/uploads/2017/10/2016-11-10-22.41.28_thumb.jpg" alt="Démontage" width="244" height="184" border="0" /><a href="https://developer.myconstellation.io/wp-content/uploads/2017/10/2016-11-10-22.41.28.jpg"><img class="colorbox-5668"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Prise démontée" src="https://developer.myconstellation.io/wp-content/uploads/2017/10/2016-11-10-22.44.15_thumb.jpg" alt="Prise démontée" width="244" height="184" border="0" /></a></p>
<p>Puis tous les supports plastique à l&rsquo;intérieur doivent être cassés pour libérer un maximum de place. Je les ai cassés avec une pince coupante et j&rsquo;ai fini de retirer le maximum de plastique avec un dremel. Sur cette photo j&rsquo;avais retiré une partie du fond de la prise pour un autre projet.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/10/2016-12-18-11.25.15.jpg"><img class="colorbox-5668"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Usinage" src="https://developer.myconstellation.io/wp-content/uploads/2017/10/2016-12-18-11.25.15_thumb.jpg" alt="Usinage" width="354" height="266" border="0" /></a></p>
<p>Il faut ensuite préparer un câblage avec le relais pour qu&rsquo;il s&rsquo;intercale entre l&rsquo;arrivée de la phase (mur) et la phase distribuée à l&rsquo;élément branché sur la prise. Mais il faut également garder en tête que l&rsquo;alimentation de l&rsquo;ESP doit être permanente :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/10/2016-08-10-22.52.19.jpg"><img class="colorbox-5668"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Schéma" src="https://developer.myconstellation.io/wp-content/uploads/2017/10/2016-08-10-22.52.19_thumb.jpg" alt="Schéma" width="354" height="266" border="0" /></a></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/10/Schma-relais.png"><img class="colorbox-5668"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Schéma" src="https://developer.myconstellation.io/wp-content/uploads/2017/10/Schma-relais_thumb.png" alt="Schéma" width="350" height="321" border="0" /></a></p>
<p>Mon principal problème dans ce tutoriel a été de tout faire rentrer dans la prise. En effet, l&rsquo;alimentation + le relais prennent beaucoup de place et tout est rentré au chausse-pied, avec le câblage noyé dans la colle chaude afin d&rsquo;assurer l&rsquo;isolation.</p>
<p>Le transformateur alimente donc en 5v un régulateur de tension LM1117 3.3V avec deux condensateurs pour lisser du 3.3v pour l&rsquo;ESP01.</p>
<p>Il alimente également directement la bobine du relais dont le circuit est interrompu par un transistor NPN BC547 dont la base sera pilotée en saturation par un GPIO de l&rsquo;ESP.</p>
<p>L&rsquo;ESP pilote deux leds de statut : une rouge et une verte et possède également son dernier GPIO en input pour un bouton physique placé sur le dessus du boitier. Si vous avez suivi jusque-là et que vous connaissez l&rsquo;ESP01, vous aurez compris qu&rsquo;il est impossible de le programmer directement dans la prise, deux des 4 GPIO devant normalement être utilisés pour la communication série.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/10/2016-08-07-16.00.46.jpg"><img class="colorbox-5668"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="2016-08-07 16.00.46" src="https://developer.myconstellation.io/wp-content/uploads/2017/10/2016-08-07-16.00.46_thumb.jpg" alt="2016-08-07 16.00.46" width="454" height="342" border="0" /></a></p>
<p>Pour combler le « trou » du bouton physique original, j&rsquo;ai choisi de coller par l&rsquo;intérieur du boitier un petit bout de plexiglas translucide. Je l&rsquo;ai ensuite percé pour faire passer les deux leds rouge et verte.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/10/2016-12-18-18.27.32.jpg"><img class="colorbox-5668"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="2016-12-18 18.27.32" src="https://developer.myconstellation.io/wp-content/uploads/2017/10/2016-12-18-18.27.32_thumb.jpg" alt="2016-12-18 18.27.32" width="244" height="184" border="0" /></a><a href="https://developer.myconstellation.io/wp-content/uploads/2017/10/2016-08-22-23.08.43.jpg"><img class="colorbox-5668"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="2016-08-22 23.08.43" src="https://developer.myconstellation.io/wp-content/uploads/2017/10/2016-08-22-23.08.43_thumb.jpg" alt="2016-08-22 23.08.43" width="244" height="184" border="0" /></a></p>
<p align="left">Et voilà, on obtient une prise connectée par Wifi avec un ESP8266 avec un bouton poussoir et deux LEDs, reste plus qu’à le programmer !</p>
<h2>Etape 2 : la programmation</h2>
<p>La fonction de base de la prise est assez simple : couper le courant ou le laisser passer. Dans un premier temps, j&rsquo;ai uploadé un sketch de base Constellation avec Arduino sur l&rsquo;ESP01 à l&rsquo;extérieur de la prise. Je l&rsquo;ai ensuite branché dans la prise que j&rsquo;ai enfiché dans le mur. Bazinga, le régulateur 3.3v fait son job, l&rsquo;ESP boote, se connecte à mon réseau wifi et envoie un « hello world » dans la console Constellation. Pour découvrir comment connecter un ESP8266 à Constellation, <a href="https://developer.myconstellation.io/getting-started/connecter-un-arduino-ou-un-esp8266-constellation/">suivez ce guide</a>.</p>
<p>Ensuite, j&rsquo;ai utilisé la librairie Constellation <a href="https://developer.myconstellation.io/client-api/arduino-esp-api/recevoir-des-messages-et-exposer-des-methodes-messagecallback-sur-arduino-esp/">pour ajouter un MessageCallback</a> pour activer ou désactiver le GPIO de la prise, <a href="https://developer.myconstellation.io/client-api/arduino-esp-api/produire-des-stateobjects-depuis-arduino-esp/">couplé à un StateObject</a> pour maintenir l’état de la prise dans Constellation :</p>
<p></p><pre class="crayon-plain-tag">constellation.registerMessageCallback("Switch", MessageCallbackDescriptor().setDescription("Switch le statut du relais."),
  [](JsonObject &amp; json) {
    statutRelais = !statutRelais;
    digitalWrite(gpioRelais, statutRelais);
    constellation.pushStateObject("Status", stringFormat("{ 'IsActivated':%s }", statutRelais ? "true" : "false" ));
  });</pre><p></p>
<p align="left">Ainsi Constellation a toujours connaissance de l’état de la prise via le StateObject nommé “Status” :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/10/StateObject.png"><img class="colorbox-5668"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="StateObject de l'état de la prise" src="https://developer.myconstellation.io/wp-content/uploads/2017/10/StateObject_thumb.png" alt="StateObject de l'état de la prise" width="354" height="259" border="0" /></a></p>
<p align="left">Et tout le monde peut maintenant découvrir et utiliser le MessageCallback “Switch” exposé par notre ESP pour permuter l’état de notre prise :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/10/MessageCallback2-002.png"><img class="colorbox-5668"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="MessageCallback" src="https://developer.myconstellation.io/wp-content/uploads/2017/10/MessageCallback2-002_thumb.png" alt="MessageCallback" width="354" height="115" border="0" /></a></p>
<p align="left">Bingo, on a donc une prise 220V connectée à Constellation qu’on pourra piloter depuis une page Web, un programme Python ou autre.</p>
<p align="left">Pour vous donnez quelques idées, n’hésitez pas à relire ce tutoriel : <a href="https://developer.myconstellation.io/tutorials/creer-un-relais-connecte/">Créer un relais connecté</a>.</p>
<h2 align="left">Etape 3 : Lier sa prise connectée à l’état de son média-center</h2>
<p align="left">Dans ma Constellation, je dispose d&rsquo;un package « brain » développé en C# avec Visual Studio qui contient l’ensemble des règles de la maison (gestion du chauffages, lumières, volets, etc..).</p>
<p align="left">Je l’ai enrichi pour faire en sorte que si Kodi est en train de lire un média (audio ou vidéo) et que la prise n’est pas allumée, alors il invoque le MessageCallback pour allumer la prise. Et inversement pour l&rsquo;éteindre !</p>
<p align="left">J’ai donc dans une classe C#, ajouté <a href="https://developer.myconstellation.io/client-api/net-package-api/consommer-des-stateobjects/#Les_StateObjectLink">deux StateObjectLinks</a>, c’est à dire que j’ai deux propriétés de mon code C# qui sont liées à mes StateObjets représentant l’état de mon media-center de l’état de ma prise !</p>
<p align="left">Il me reste plus qu’à ajouter un handler sur le changement d’état du State Object de Kodi, afin d’ajouter deux conditions “if” :</p>
<ul>
<li>
<div align="left">Si la prise est éteinte alors que Kodi joue quelque chose (PlayerState différent de null) alors on allume la prise</div>
</li>
<li>
<div align="left">Si la prise est allumée alors que Kodi joue rien (PlayerState null) alors on éteint la prise</div>
</li>
</ul>
<p align="left">Pour allumer ou éteindre la prise, il suffit d’invoquer le MessageCallback “Switch” exposé par notre code Arduino <a href="https://developer.myconstellation.io/client-api/net-package-api/envoyer-des-messages-invoquer-des-messagecallbacks/">en créant un proxy vers notre package.</a></p>
<p></p><pre class="crayon-plain-tag">public class KodiDemo
{
    /// &lt;summary&gt;
    /// StateObject XBMC. Permet de connaitre les infos de lecture.
    /// &lt;/summary&gt;
    [StateObjectLink(Package = "Xbmc", Name = "Kodi Salon NUC")]
    public StateObjectNotifier KodiNotifier { get; set; }

    /// &lt;summary&gt;
    /// StateObject de l'ESP controlant le relais d'activation. Permet de synchroniser les infos de lecture avec la valeur du relais.
    /// &lt;/summary&gt;
    [StateObjectLink(Sentinel = "ESP8266-01-001", Package = "ESP_Relay_Button", Name = "Status")]
    public StateObjectNotifier PriseKodi { get; set; }

    public void Start()
    {
        this.KodiNotifier.ValueChanged += (s, e) =&gt;
        {
            if (this.PriseKodi.DynamicValue.Status == false
                &amp;&amp; e.IsNew == false
                &amp;&amp; e.OldState.DynamicValue.PlayerState == null
                &amp;&amp; e.NewState.DynamicValue.PlayerState != null)
            {
                // démarrage.
                PackageHost.WriteInfo("Activation de la prise.");
                PackageHost.CreateMessageProxy("ESP8266_01_002/ESP_Relay_Button").Switch();
            }

            if (this.PriseKodi.DynamicValue.Status == true
                &amp;&amp; e.IsNew == false
                &amp;&amp; e.OldState.DynamicValue.PlayerState != null
                &amp;&amp; e.NewState.DynamicValue.PlayerState == null)
            {
                PackageHost.WriteInfo($"Arret de la prise.");
                PackageHost.CreateMessageProxy("ESP8266_01_002/ESP_Relay_Button").Switch();
            }
        };
    }
}</pre><p></p>
<p>Et voilà comment en quelques lignes de C# et grâce à Constellation, mes enceintes seront automatiquement allumées ou éteintes selon que mon media-center diffuse ou non un média vidéo ou audio !</p>
<h2>Pour aller plus loin</h2>
<p>Pour aller plus loin, j&rsquo;ai ajouté quelques fonctionnalités intéressantes :</p>
<ul>
<li>J&rsquo;ai pluggé le bouton poussoir ajouté sur le dessus de la prise pour qu&rsquo;il change l&rsquo;état du relais et mette à jour le state objet en conséquence.</li>
<li>J&rsquo;ai ajouté la possibilité d&rsquo;associer les leds de façade au fonctionnement de la prise en m&rsquo;inspirant de ce qui existe sur les prises connectées du marché. La led rouge indique le statut de fonctionnement (power on / connexion au wifi en clignotant), la led verte indique l&rsquo;état du relais.</li>
<li>J&rsquo;ai ajouté également un mode « blind », je trouve que c&rsquo;est une fonctionnalité intéressante mais qui est absente des prises sur le marché : Quand il fait noir dans une pièce et que la prise se reconnecte au wifi, cela peut être gênant de la voir clignoter. Un package de « brain » peut alors gérer les leds directement en <a href="https://developer.myconstellation.io/showcases/connecter-volets-constellation-arduino-raspberry/">fonction de mes volets</a> <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></li>
<li>Ensuite, en cas de déconnection du wifi ou de coupure de courant, j&rsquo;ai prévu un bout de code permettant, au démarrage de l&rsquo;ESP, de requêter son propre StateObject. Cela permet à la prise de revenir à l&rsquo;état dans lequel elle était avant la coupure.</li>
<li>J&rsquo;ai également fait intervenir <a href="https://developer.myconstellation.io/tutorials/connecter-un-video-projecteur-dans-constellation/">l&rsquo;activation de mon projecteur</a>. Ce dernier push un StateObject. Si le média center est éteint, il envoie un paquet WOL via <a href="https://developer.myconstellation.io/package-library/networktools/">le package networktools</a> pour l&rsquo;allumer et envoie une notification de fermeture des volets du salon. Le démarrage de la lecture du média sur kodi pilote la prise d&rsquo;allumage des enceintes sans action manuelle. Ainsi, le démarrage du projecteur et la lecture sur kodi lancent l&rsquo;ambiance parfaite pour profiter de mes séries en un seul geste.</li>
</ul>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/tutorials/creer-une-prise-connectee-avec-un-esp8266/">Créer une prise connectée avec un ESP8266</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://developer.myconstellation.io/tutorials/creer-une-prise-connectee-avec-un-esp8266/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Connecter un vidéo projecteur standard à Constellation et synchroniser les volets</title>
		<link>https://developer.myconstellation.io/tutorials/connecter-un-video-projecteur-dans-constellation/</link>
					<comments>https://developer.myconstellation.io/tutorials/connecter-un-video-projecteur-dans-constellation/#respond</comments>
		
		<dc:creator><![CDATA[Lucas]]></dc:creator>
		<pubDate>Tue, 16 May 2017 10:23:36 +0000</pubDate>
				<category><![CDATA[Tutoriels]]></category>
		<category><![CDATA[Domotique]]></category>
		<category><![CDATA[Volet]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[Projecteur]]></category>
		<category><![CDATA[IoT]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[ESP8266]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=4888</guid>

					<description><![CDATA[<p>Par Lucas Dupuis Ayant fait récemment l&#8217;acquisition d&#8217;un vidéo-projecteur pour mes soirées films, je me suis vite rendu compte qu&#8217;avec les jours qui rallongent, j&#8217;ai besoin de fermer les volets de mon salon afin de rester dans une certaine pénombre.</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/tutorials/connecter-un-video-projecteur-dans-constellation/">Connecter un vidéo projecteur standard à Constellation et synchroniser les volets</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><em>Par Lucas Dupuis</em></p>
<p>Ayant fait récemment l&rsquo;acquisition d&rsquo;un vidéo-projecteur pour mes soirées films, je me suis vite rendu compte qu&rsquo;avec les jours qui rallongent, j&rsquo;ai besoin de fermer les volets de mon salon afin de rester dans une certaine pénombre.</p>
<p>La présentation de mon système de pilotage de volets n&rsquo;est plus à faire, <a href="/showcases/connecter-volets-constellation-arduino-raspberry/">vous la retrouverez ici</a>. Vous pouvez aussi utiliser des modules Z-Wave comme le FGR-211 qu&rsquo;on connectera à Constellation via le package <a href="/package-library/vera/">Vera</a> ou <a href="/package-library/jeedom/">Jeedom</a>. Dans tous les cas, nous disposons un <a href="/concepts/messaging-message-scope-messagecallback-saga/">MessageCallback </a>pour ouvrir ou fermer nos volets !</p>
<p>La problématique qui se pose est la suivante : comment savoir que le projecteur est allumé et que je m&rsquo;apprête à regarder un film ?</p>
<p>J&rsquo;ai réfléchi à plusieurs solutions :</p>
<ul>
<li>Monitorer la consommation de la prise électrique afin de déduire que le projecteur est allumé
<ul>
<li>Avantages :
<ul>
<li>Permet d&rsquo;exposer un booléen indiquant que le projecteur est allumé et d&rsquo;ouvrir/fermer les volets en conséquence</li>
<li>Permet de monitorer la consommation en temps réel</li>
<li>Permet de monitorer la durée d&rsquo;utilisation de la lampe du vidéo-projecteur</li>
</ul>
</li>
<li>Inconvénients :
<ul>
<li>Nécessite une prise connectée avec conso-mètre (à fabriquer ou à acheter)</li>
<li>C&rsquo;est potentiellement complexe et coûteux</li>
</ul>
</li>
</ul>
</li>
<li>Surveiller le StateObject de mon médiacenter Kodi (exposé par le package <a href="/package-library/xbmc/">xbmc</a>)
<ul>
<li>Avantages :
<ul>
<li>J&rsquo;ai déjà une routine surveillant le stateobject pour allumer et éteindre le système de son lorsqu&rsquo;un média est joué</li>
<li>Il n&rsquo;y a que du code à mettre en place dans le package « cerveau » de la maison</li>
</ul>
</li>
<li>Inconvénients :
<ul>
<li>Il n&rsquo;y a pas de lien direct entre l&rsquo;allumage du projecteur et une action sur les volets</li>
<li>La sélection du film ou du média sur l&rsquo;écran se fait volets ouverts, et donc c&rsquo;est potentiellement gênant en cas de luminosité importante</li>
<li>Cela ne tient pas compte des autres sources branchées sur le projecteur (TV, console, &#8230;)</li>
</ul>
</li>
</ul>
</li>
<li>Utiliser un déclencheur sur le projecteur
<ul>
<li>Avantages :
<ul>
<li>Montage simple</li>
<li>Peu d&rsquo;investissement</li>
<li>Système embarqué trivial</li>
</ul>
</li>
<li>Inconvénients :
<ul>
<li>Pas de monitoring de consommation</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>J&rsquo;ai retenu la seconde et la troisième option : la seconde option, consistant à surveiller le stateobject de <a href="/package-library/xbmc/">kodi</a> permet l&rsquo;allumage du système de son lorsqu&rsquo;un média est lu, que ce soit un film ou un morceau de musique et la troisième option pour déclencher la fermeture des volets à l&rsquo;allumage du vidéo projecteur.</p>
<h3>Prerequis</h3>
<ul>
<li>Un serveur Constellation</li>
<li>Un vidéo-projecteur avec une sortie 12V</li>
<li>Un ESP8266 (ou Arduino connecté) avec un régulateur de tension</li>
<li>Le SDK Visual Studio</li>
</ul>
<h3>Etape 1 : connecter le vidéo projecteur dans Constellation</h3>
<p>En regardant les caractéristiques de mon projecteur, je me suis rendu compte qu&rsquo;il existait une sortie 12V permettant de déclencher un moteur pour une toile de projection.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/2017-05-03-21.19.35.jpg"><img class="colorbox-4888"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Le projecteur vidéo" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/2017-05-03-21.19.35_thumb.jpg" alt="Le projecteur vidéo" width="454" height="342" border="0" /></a></p>
<p>À la maison je projette sur un mur blanc, je n&rsquo;ai donc pas besoin de cette sortie. Il s&rsquo;agit d&rsquo;un connecteur jack mono que vous trouverez rapidement chez vous dans votre boite de récup&rsquo; ou bien directement sur le net pour quelques centimes.</p>
<p>Il suffit donc d&rsquo;un ESP8266 (par exemple un ESP-01, très petit et peu cher) et d&rsquo;un régulateur de tension 3.3v (ex. LD1117v33) acceptant en entrée une tension entre 5 et 15V et le tour est joué !</p>
<p>En effet, le projecteur envoie du 12v sur la sortie dès qu&rsquo;il est sous tension et du 0v lorsqu&rsquo;il est éteint. Ainsi notre ESP-01 sera alimenté par cette sortie. Lorsqu&rsquo;on allume le vidéo-projecteur, l&rsquo;ESP-01 sera démarré et lorsqu&rsquo;on éteint le vidéo projecteur, il sera éteint car plus d&rsquo;alimentation !</p>
<p>Aussi simple que cela !</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/2017-05-16-10.27.17.jpg"><img class="colorbox-4888"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Schéma du montage avec l'ESP8266" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/2017-05-16-10.27.17_thumb.jpg" alt="Schéma du montage avec l'ESP8266" width="454" height="193" border="0" /></a></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/2017-05-06-15.37.28.jpg"><img class="colorbox-4888"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Le vidéo projecteur avec l'ESP8266" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/2017-05-06-15.37.28_thumb.jpg" alt="Le vidéo projecteur avec l'ESP8266" width="454" height="342" border="0" /></a></p>
<p>L&rsquo;ESP, de son côté, publie simplement toutes les secondes un StateObject ayant une durée de vie de 5 secondes pour indiquer que le projecteur est allumé.</p>
<p>Pour connecter un ESP8266 (ou un Arduino) <a href="/getting-started/connecter-un-arduino-ou-un-esp8266-constellation/">suivez ce guide</a> ! Une fois connecté dans ma Constellation, je <a href="/client-api/arduino-esp-api/produire-des-stateobjects-depuis-arduino-esp/">publie le StateObject</a> dans la boucle principale <em>loop()</em></p>
<p></p><pre class="crayon-plain-tag">void loop() {
  constellation.loop();
 
  if(((millis() - lastTime) &gt; 1000) 
    || (millis() &lt; lastTime))
  {
    constellation.pushStateObject("Uptime",  millis(), 5);
    lastTime = millis();
  } 
}</pre><p></p>
<p>On a donc dans les StateObjects de notre Constellation, un StateObject « Uptime » publié dans mon cas par le package (virtuel)  « ESP01_Projector » qui contient l&rsquo;uptime de mon projecteur :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/Screenshot-SO.png"><img class="colorbox-4888"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Le StateObject de l'uptime du projecteur" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/Screenshot-SO_thumb.png" alt="Le StateObject de l'uptime du projecteur" width="457" height="332" border="0" /></a></p>
<p style="text-align: left;" align="center">Ce StateObject est mis à jour par l&rsquo;ESP toutes les secondes avec une durée de vie de 5 secondes ! Ainsi je n&rsquo;ai pas besoin de connaitre la valeur du StateObject, il me suffit juste de vérifier que le StateObject est « Valide » et non « Expiré » !</p>
<p style="text-align: left;" align="center">Si il est valide c&rsquo;est que dans les 5 dernières secondes il y a bien publié son Uptime, donc l&rsquo; ESP est démarré ce qui implique que mon vidéo projecteur est bien démarré (pour alimenter l&rsquo;ESP) !</p>
<p style="text-align: left;" align="center">En revanche si ce StateObject est expiré, c&rsquo;est à dire que le StateObject n&rsquo;a pas été mis à jour durant les 5 dernières secondes or l&rsquo;ESP est censé le faire à chaque seconde ! L&rsquo;ESP-01 est donc déconnecté ce qui impliquerai que le vidéo projecteur est arrêté !</p>
<h3 style="text-align: left;" align="center">Etape 2 : synchroniser le vidéo projecteur avec mes volets</h3>
<p style="text-align: left;" align="center">Maintenant, dans mon package « cerveau » de Constellation, il suffit de surveiller ce StateObject et son état expiré ou non pour savoir quelle commande envoyer aux volets.</p>
<p style="text-align: left;" align="center">J&rsquo;ai donc créé un package « cerveau » en C#.</p>
<p style="text-align: left;" align="center">Dans ma classe, je crée un <a href="/client-api/net-package-api/consommer-des-stateobjects/">StateObjectLink </a>pour lier le StateObject de l&rsquo;ESP dans une propriété .NET de mon code :</p>
<p></p><pre class="crayon-plain-tag">/// &lt;summary&gt;
/// StateObject du projecteur. Permet de connaitre l'uptime du projecteur.
/// &lt;/summary&gt;
[StateObjectLink("ESP01_Projector", "Uptime")]
public StateObjectNotifier ProjectorUptime { get; set; }</pre><p></p>
<p>Maintenant au démarrage de mon package, j&rsquo;attache un « handler » sur l&rsquo;événement « <em>ValueChanged</em> » permettant d&rsquo;ajouter du code en cas de mise à jour du StateObject.</p>
<p>Ici je vérifie que mon StateObjectLink est bien lié au StateObject (<em>HasValue</em>) et que ce StateObject n&rsquo;est pas expiré (<em>IsExpired</em>).</p>
<p>Si la condition est vrai, c&rsquo;est que mon projecteur est allumé, alors je peux fermer mes volets autrement je restaure les volets dans leurs positions précédentes.</p>
<p></p><pre class="crayon-plain-tag">this.ProjectorUptime.ValueChanged += (s, e) =&gt;
{
    // Projecteur allumé ?
    if (this.ProjectorUptime.HasValue == true &amp;&amp; this.ProjectorUptime.Value.IsExpired == false)
    {
        // Si projecteur est allumé, on ferme les volets.
        foreach (var volet in this.voletConfig)
        {
            if (this.ShowDebug)
            {
                PackageHost.WriteWarn($"Fermeture du volet {volet.Name} à 100%.");
            }
            
            // On enregistre au passage la position de départ pour la restaurer à la fin.
            volet.PreviousPosition = volet.CurrentPosition; 
            
            // Ordre de fermeture (100%).
            PackageHost.CreateMessageScope("ESP_Shutters").ChangePercent(volet.Name, 100);
        }
    }
    else
    {
        // Si projecteur est éteint, on rouvre les volets.
        foreach (var volet in this.voletConfig)
        {
            if (this.ShowDebug)
            {
                PackageHost.WriteWarn($"Ouverture du volet {volet.Name} à l'ancienne position, {Convert.ToInt32(volet.Percent * 100.0)}-&gt;{volet.PreviousPosition}% après {this.tempoReouvertureVolets} secs d'inactivité.");
            }

            // Pour chaque volet, on revient à la position initiale
            PackageHost.CreateMessageScope("ESP_Shutters").ChangePercent(volet.Name, volet.PreviousPosition);
        }
    }
};</pre><p></p>
<h3>Conclusion</h3>
<p>Une demi-heure de prototypage et de soudure, un petit quart d&rsquo;heure de développement, et le challenge est relevé !</p>
<p>L&rsquo;allumage du projecteur ferme les volets de mon salon selon une consigne, il déclenche également un scénario prédéfini pour les lampes Hue et active la prise du système de son. Le clic sur le bouton de la télécommande rend l&rsquo;expérience du film beaucoup plus profitable avec Constellation !</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/tutorials/connecter-un-video-projecteur-dans-constellation/">Connecter un vidéo projecteur standard à Constellation et synchroniser les volets</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://developer.myconstellation.io/tutorials/connecter-un-video-projecteur-dans-constellation/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Synchroniser un interrupteur mural avec des ampoules connectées et contrôler l&#8217;ambiance lumineuse de votre pièce</title>
		<link>https://developer.myconstellation.io/tutorials/synchroniser-interrupteur-mural-ampoules-connectee/</link>
					<comments>https://developer.myconstellation.io/tutorials/synchroniser-interrupteur-mural-ampoules-connectee/#comments</comments>
		
		<dc:creator><![CDATA[Sebastien Warin]]></dc:creator>
		<pubDate>Mon, 15 May 2017 23:12:13 +0000</pubDate>
				<category><![CDATA[Tutoriels]]></category>
		<category><![CDATA[Z-Wave]]></category>
		<category><![CDATA[Hue]]></category>
		<category><![CDATA[Lampe]]></category>
		<category><![CDATA[Fibaro]]></category>
		<category><![CDATA[Ampoules]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Package]]></category>
		<category><![CDATA[Vera]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=4853</guid>

					<description><![CDATA[<p>Dans cet article nous allons découvrir comment contrôler l&#8217;ambiance lumineuse d&#8217;une pièce équipée d&#8217;ampoules connectées avec un simple interrupteur mural. L&#8217;idée est à la fois de pouvoir allumer ou éteindre toutes les ampoules de la pièce à partir de l’interrupteur</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/tutorials/synchroniser-interrupteur-mural-ampoules-connectee/">Synchroniser un interrupteur mural avec des ampoules connectées et contrôler l&rsquo;ambiance lumineuse de votre pièce</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Dans cet article nous allons découvrir comment contrôler l&rsquo;ambiance lumineuse d&rsquo;une pièce équipée d&rsquo;ampoules connectées avec un simple interrupteur mural.</p>
<p>L&rsquo;idée est à la fois de pouvoir allumer ou éteindre toutes les ampoules de la pièce à partir de l’interrupteur mais également de pouvoir sélectionner une ambiance lumineuse en fonction des circonstances, par exemple pour un salon : ambiance « réception », ambiance « soirée », ambiance « Ciné », ambiance « Feu de cheminée », etc&#8230;</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/Hue1.gif"><img class="colorbox-4853"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Hue1" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/Hue1_thumb-gap.jpg" data-gif="https://developer.myconstellation.io/wp-content/uploads/2017/05/Hue1_thumb.gif" alt="Hue1" width="150" height="266" border="0" /></a></p>
<h3>Prérequis</h3>
<ul>
<li>Un serveur Constellation</li>
<li>Des lampes ou ampoules connectées, ici des Philips Hue</li>
<li>Un interrupteur mural connecté, ici un interrupteur Legrand relié à un module Z-Wave Fibaro FGS-211</li>
<li>Le SDK Constellation pour Visual Studio</li>
</ul>
<h3>Etape 1 : connecter un interrupteur mural</h3>
<p>La première étape consiste donc à intégrer un interrupteur dans Constellation. Avec la polyvalence de la plateforme Constellation, il y a mille et une manière d&rsquo;y parvenir.</p>
<p>Pour ma part, j&rsquo;ai conservé les interrupteurs existants de la gamme Mosaic Legrand. Il s&rsquo;agit pour être exacte d&rsquo;un double bouton poussoir.</p>
<p>Pour le rendre connecté, j&rsquo;ai ajouté un micro-module de la marque Fibaro spécialement conçu pour être intégré dans la boite d&rsquo;encastrement juste derrière l’interrupteur.</p>
<p>Ce module Fibaro est un FGS-211 connecté en Z-Wave et disposant de deux relais en sortie pilotant des charges jusqu&rsquo;à 1500W et de deux entrées. Dans mon cas, il n&rsquo;y a aucune charge connectée sur ce module, il me sert juste de »capteur ».</p>
<p>Je rappelle aussi que les ampoules Philips Hue doivent être constamment alimentées en 220v de façon à être pilotable même après avoir fermé les lumières !</p>
<p>Le module Fibaro est simplement connecté sur le réseau électrique 220v pour son alimentation et aux deux boutons poussoir Legrand de la façon suivante :</p>
<p style="text-align: center;"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-87.png"><img loading="lazy" class="alignnone colorbox-4853" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Connexion du FGS-211" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-86.png" alt="Connexion du FGS-211" width="450" height="321" border="0" /></a></p>
<p>Cela permettant d&rsquo;avoir deux boutons connectés sur le même interrupteur : l&rsquo;un servira pour allumer ou éteindre toutes les lumières du salon et l&rsquo;autre permettra de changer la configuration lumineuse de la pièce.</p>
<p style="text-align: center;"><img loading="lazy" class="aligncenter colorbox-4853" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-86.png" alt="image" width="240" height="232" border="0" /></p>
<p style="text-align: left;">Ce module Fibaro a été appairé sur mon contrôleur Z-Wave qui est une Vera Lite. Après avoir déployé le package <a href="/package-library/vera/">Vera </a>sur une des sentinelles de ma Constellation, on obtient différents StateObjects représentant l&rsquo;état en temps réel de chaque device Z-Wave et des MessageCallbacks permettant de les piloter.</p>
<p style="text-align: left;">Les deux relais du FGS-221 sont considérés comme deux devices distincts de type « Switchs » (On ou Off). On a donc deux StateObjects dans Constellation pour représenter l&rsquo;état de ces deux relais. Chacun de ces StateObjects contient la propriété « Status », un booléen indiquant si le relais est ouvert ou fermé.</p>
<p style="text-align: center;" align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-89.png"><img loading="lazy" class="aligncenter colorbox-4853" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="StateObject du FGS-211" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-88.png" alt="StateObject du FGS-211" width="354" height="293" border="0" /></a></p>
<p style="text-align: left;">On peut permuter l&rsquo;état du relais informatiquement parlant par la Vera (ou par Constellation via le MessageCallback « <em>SetSwitchState</em> » du package Vera) ou directement en appuyant sur les boutons poussoirs.</p>
<p>Ainsi dès lors que l&rsquo;utilisateur va appuyer sur l&rsquo;un des boutons poussoirs, l&rsquo;état du relais changera et donc le StateObject le représentant sera également mis à jour dans votre Constellation. On pourra donc s&rsquo;abonner à ces deux StateObjects via l&rsquo;API.NET, Python, Arduino ou autre pour réagir à ces changements d&rsquo;état, par exemple pour allumer ou éteindre les ampoules Hue.</p>
<h3>Etape 2 : connecter des lampes</h3>
<p>Deuxième étape pour mener à bien notre projet : connecter des lampes dans Constellation. Il y a différentes solutions comme nous avons pu le découvrir dans <a href="/tutorials/synchroniser-lampe-bureau-avec-session-windows/#Etape_1_piloter_une_lampe_par_Constellation">cet autre tutoriel</a> : solutions DIY, prises connectées en Wifi, RF, en Z-Wave, lampes ou ampoules connectées en Wifi, en ZeeBee, etc.. etc..</p>
<p>Dans mon cas, j&rsquo;ai équipé les huit appliques de mon salon avec des ampoules Philips Hue.</p>
<p style="text-align: center;"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/hue.jpg"><img loading="lazy" class="aligncenter colorbox-4853" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="hue" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/hue_thumb.jpg" alt="hue" width="400" height="210" border="0" /></a></p>
<p style="text-align: left;">Toutes les ampoules communiquent en ZeeBee à un pont Ethernet, nommé le bridge (à gauche de la photo ci-dessus). Grace au package <a href="/package-library/hue/">Hue</a>, vous disposez de différents MessageCallbacks pour contrôler chaque lampes Hue (état, intensité lumineuse, couleur, effet, etc..) et d&rsquo;un StateObject par luminaire représentant son état en temps réel.</p>
<p style="text-align: center;" align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-90.png"><img class="colorbox-4853"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="StateObject d'une ampoule Hue" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-89.png" alt="StateObject d'une ampoule Hue" width="354" height="258" border="0" /></a></p>
<p style="text-align: center;" align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-91.png"><img class="colorbox-4853"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="MessageCallbacks du package Hue" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-90.png" alt="MessageCallbacks du package Hue" width="354" height="358" border="0" /></a></p>
<h3>Etape 3 : synchroniser l’interrupteur avec les lampes</h3>
<p>Passons au chose sérieuse, nous avons d’un côté deux StateObjects nous indiquant l&rsquo;état des deux relais qu&rsquo;on contrôle par les boutons poussoirs et de l&rsquo;autre des MessageCallbacks nous permettant de contrôler les ampoules Hue du salon, reste juste à faire le lien !</p>
<p>Pour cela nous allons <a href="https://developer.myconstellation.io/getting-started/creez-votre-premier-package-constellation-en-csharp/">créer un package .NET en C#</a> depuis Visual Studio.</p>
<p>Dans la classe principale (<em>Program</em>), nous allons ajouter deux <a href="https://developer.myconstellation.io/client-api/net-package-api/consommer-des-stateobjects/">StateObjectLinks</a>, c’est à dire des propriétés dans notre code liées aux StateObjects représentant les états des interrupteurs :</p>
<p></p><pre class="crayon-plain-tag">[StateObjectLink("Vera", "Interrupteur Hue 1")]
public StateObjectNotifier InterrupteurHue1 { get; set; }

[StateObjectLink("Vera", "Interrupteur Hue 2")]
public StateObjectNotifier InterrupteurHue2 { get; set; }</pre><p></p>
<p>Nous allons commencer par le bouton de gauche, c&rsquo;est à dire l&rsquo;interrupteur n°1 qui se chargera d&rsquo;allumer ou d’éteindre toutes les ampoules du salon.</p>
<p>Pour cela nous allons attacher un « handler » qui réagira à la mise à jour du StateObject « Interrupteur Hue 1 ». Le handler commencera par vérifier que l&rsquo;état à bien changé, c&rsquo;est à dire que la propriété « Status » du « OldState » versus le « NewState » est bien différente (le StateObject peut être mis à jour par exemple dans le cas d&rsquo;un « poll » Z-Wave à intervalle régulier sans pour autant que son Status ait changé !).</p>
<p>Ensuite on invoque simplement le MessageCallback « <em>SetState</em> » du package Hue. Le 1er argument est le n° de la lampe, 0 indiquant « toutes les lampes » et le 2ème argument est l&rsquo;état (On ou Off) de la lampe. Ici on passera l&rsquo;état du relais (propriété du Status).</p>
<p></p><pre class="crayon-plain-tag">this.InterrupteurHue1.ValueChanged += (s, e) =&gt;
{
    if ((bool)e.OldState.DynamicValue.Status != (bool)e.NewState.DynamicValue.Status)
    {
        PackageHost.CreateMessageProxy("Hue").SetState(0, (bool)e.NewState.DynamicValue.Status);
    }
};</pre><p></p>
<p>Ainsi dès que vous appuyez sur le bouton poussoir de gauche, le relais change d&rsquo;état donc le code ci-dessus est invoqué ce qui allumera ou éteindra toutes vos lampes Hue !</p>
<p>Et voilà comment en quelques lignes on peut synchroniser des choses ensembles ! Au final, on obtient un interrupteur connecté pilotant plusieurs ampoules connectées.</p>
<p>Une fois votre package testé et validé, vous pouvez <a href="/constellation-platform/constellation-sdk/publier-package-visual-studio/">le publier</a> dans votre Constellation et le déployer sur une de vos sentinelles (<a href="/getting-started/creez-votre-premier-package-constellation-en-csharp/#Publier_son_package_dans_Constellation">voir le guide</a>). Simple et efficace !</p>
<h3>Etape 4 : contrôler les ambiances lumineuses</h3>
<p>Ce que nous avons fait jusqu&rsquo;à présent est relativement simple : on synchronise simplement l&rsquo;état du relais Fibaro (piloté par l’interrupteur) à l&rsquo;état (state On/Off) des lampes Hue.</p>
<p>Le MessageCallback « <em>SetState</em> » allume ou éteint des lampes Hue. Dans le cas d&rsquo;un allumage, les lampes reprendront leurs dernières configurations en terme de couleur et d&rsquo;intensité.</p>
<p style="text-align: left;">Il existe d&rsquo;autre MC sur ce package comme le <em>SetColor</em>, <em>SetBrightness</em>, ou le <em>Set</em> qui combine les 3 en un en prenant en paramètre à la fois l&rsquo;état, la couleur et l&rsquo;intensité.</p>
<p style="text-align: left;">Nous allons donc perfectionner notre package en utilisant <a href="/client-api/net-package-api/settings/">un setting au format JSON</a> pour décrire nos différentes ambiances lumineuses. L’interrupteur de gauche ne se contentera plus de faire un simple <em>SetState</em> sur chaque lampe mais appliquera la configuration dite par défaut que nous pourrons à tout moment mettre à jour dans les settings depuis la Console.</p>
<p style="text-align: left;">L&rsquo;interrupteur n°2 quant à lui, celui de droite, servira pour appliquer la configuration suivante de façon cyclique (arrivé à la dernière, on revient au début).</p>
<p align="center"><img class="colorbox-4853"  loading="lazy" title="Hue2" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/Hue2_thumb-gap.jpg" data-gif="https://developer.myconstellation.io/wp-content/uploads/2017/05/Hue2_thumb.gif" alt="Hue2" width="150" height="266" border="0" /></p>
<p style="text-align: left;" align="center">Commençons d&rsquo;abord par définir nos configurations lumineuses dans un setting JSON.</p>
<h4>Créer des « configurations lumineuses »</h4>
<p>Pour cela je vous propose de créer une page Web pour générer le setting de configuration sur base de l&rsquo;état actuelle de vos lampes.</p>
<p>En clair, avec l&rsquo;application officielle Hue, réglez vos lampes pour créer l&rsquo;ambiance lumineuse souhaitée et en temps réel notre page Web générera l&rsquo;objet JSON représentant votre configuration.</p>
<p>Nous allons simplement créer un simple page HTML en y ajoutant le module Constellation / AngularJS <a href="/client-api/javascript-api/consommer-constellation-angular-js/">comme vu ici</a>.</p>
<p>Lorsque nous sommes connecté, on enregistre un StateObjectLink sur tous les StateObjects du type « <em>Q42.HueApi.Light</em> » du package Hue. Pour chaque lampe Hue, on stocke la valeur du StateObject dans une variable de scope nommée « lights » :</p>
<p></p><pre class="crayon-plain-tag">constellation.registerStateObjectLink("*", "Hue", "*", "Q42.HueApi.Light", function (stateObject) { 
    $scope.$apply(function () {
        $scope.lights[stateObject.Name] = stateObject.Value;
    });
});</pre><p></p>
<p>Ainsi l&rsquo;état de chacune de nos lampes sera synchronisée en temps réel dans cette variable Javascript.</p>
<p>Maintenant dans le code HTML, générons une liste pour afficher le nom de chaque lampe, son ID, son état (on/off), sa couleur (Hue et Saturation) et son intensité (bri) avec un « ng-repeat » Angular :</p>
<p></p><pre class="crayon-plain-tag">&lt;ul&gt;
    &lt;li ng-repeat="(name, value) in lights" title="{{value}}"&gt;{{name}} = #{{value.id}} On:{{value.state.on}} Hue:{{value.state.hue}} Sat:{{value.state.sat}} Bri:{{value.state.bri}}&lt;/li&gt;
&lt;/ul&gt;</pre><p></p>
<p>C&rsquo;est aussi simple que cela !</p>
<p>Maintenant ajoutons une méthode « <em>ExportCurrentConfig</em> » qu&rsquo;on appellera dans notre StateObjectLink dès qu&rsquo;un StateObject est mis à jour :</p>
<p></p><pre class="crayon-plain-tag">$scope.ExportCurrentConfig = function() {
    var config = { ConfigName: "MyConfig", Lights: []};
    for(var name in $scope.lights) {
        var value = $scope.lights[name];
        config.Lights.push({ id: value.id, state: value.state.on, hue: value.state.hue, sat:value.state.sat, bri:value.state.bri });
    }
    $scope.strConfigs = JSON.stringify([ config ]).replace(/"/g, "'");
};</pre><p></p>
<p>On crée un objet avec une propriété « <em>ConfigName</em> » pour nommer notre configuration et un tableau « <em>Lights</em> » qu&rsquo;on remplit avec l&rsquo;état connu de chaque lampe. Pour finir on « <em>stringify</em> » notre objet en JSON qu&rsquo;on affichera ensuite dans un « <em>textarea</em> » sur la page :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-88.png"><img class="colorbox-4853"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-87.png" alt="image" width="454" height="274" border="0" /></a></p>
<p style="text-align: left;" align="center">Il ne reste plus qu&rsquo;à générer différentes configurations notre « extracteur » pour la suite de notre tutoriel.</p>
<p style="text-align: left;" align="center">Le code complet de la page :</p>
<p></p><pre class="crayon-plain-tag">&lt;!DOCTYPE html&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml" ng-app="hue"&gt;
&lt;head&gt;
    &lt;title&gt;Hue Configuration&lt;/title&gt;
        
    &lt;script type="text/javascript" src="/Scripts/jquery-2.1.3.min.js"&gt;&lt;/script&gt;
    &lt;script type="text/javascript" src="/Scripts/angular.min.js"&gt;&lt;/script&gt;
    &lt;script type="text/javascript" src="/Scripts/jquery.signalR-2.2.0.min.js"&gt;&lt;/script&gt;
    &lt;script type="text/javascript" src="/Scripts/Constellation-1.8.1.js"&gt;&lt;/script&gt;
    &lt;script type="text/javascript" src="/Scripts/ngConstellation-1.8.1.js"&gt;&lt;/script&gt; 
    
    &lt;script&gt;
        var hue = angular.module('hue',  ['ngConstellation'])
            .controller('HueController', ['$scope', 'constellationConsumer', function ($scope, constellation) {
                $scope.lights = {};
                $scope.strConfigs = "";
            
                constellation.initializeClient("http://xxxxxxx:8088/", "demo123", "Hue Configurator");
                
                $scope.ExportCurrentConfig = function() {
                    var config = { ConfigName: "MyConfig", Lights: []};
                    for(var name in $scope.lights) {
                        var value = $scope.lights[name];
                        config.Lights.push({ id: value.id, state: value.state.on, hue: value.state.hue, sat:value.state.sat, bri:value.state.bri });
                    }
                    $scope.strConfigs = JSON.stringify([ config ]).replace(/"/g, "'");
                };

                constellation.onConnectionStateChanged(function (change) {
                    if (change.newState === $.signalR.connectionState.connected) {
                        console.log("Connected");
                        constellation.registerStateObjectLink("*", "Hue", "*", "Q42.HueApi.Light", function (stateObject) {  
                            $scope.$apply(function () {
                                $scope.lights[stateObject.Name] = stateObject.Value;    
                                $scope.ExportCurrentConfig();
                            });
                        });                        
                    }
                    else if (change.newState === $.signalR.connectionState.disconnected) {    
                        constellation.connect();
                    }
                });
                
                constellation.connect();
            }]);
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;ul&gt;
        &lt;li ng-repeat="(name, value) in lights" title="{{value}}"&gt;{{name}} = #{{value.id}} On:{{value.state.on}} Hue:{{value.state.hue}} Sat:{{value.state.sat}} Bri:{{value.state.bri}}&lt;/li&gt;
    &lt;/ul&gt;
    &lt;hr/&gt;
    &lt;p&gt;Current configuration :&lt;/p&gt;
    &lt;textarea rows="40" cols="50"&gt;{{strConfigs}}&lt;/textarea&gt;
    
&lt;/body&gt;
&lt;/html&gt;</pre><p></p>
<h4>Activer les configurations depuis interrupteur</h4>
<p>Premièrement nous allons déclarer dans le <a href="/concepts/package-manifest/">manifeste de notre package</a> (<em>PackageInfo.xml</em>) le setting « <em>Hue.Configuration</em> » par la ligne :</p>
<p></p><pre class="crayon-plain-tag">&lt;Setting name="Hue.Configurations" type="JsonObject" isRequired="true" description="Configurations lumineuses" /&gt;</pre><p></p>
<p>Le contenu de ce setting sera un tableau des différentes configurations générées par notre extracteur ci-dessus.</p>
<p>Pour ma part voici mes configurations à titre d&rsquo;exemple :</p>
<p></p><pre class="crayon-plain-tag">[
   {
      'ConfigName':'Blanc chaud',
      'DefaultConfig':true,
      'Lights':[
         {
            'id':'1',
            'state':true,
            'hue':6479,
            'sat':252,
            'bri':254
         },
         {
            'id':'2',
            'state':true,
            'hue':13907,
            'sat':187,
            'bri':179
         },
         {
            'id':'3',
            'state':true,
            'hue':13907,
            'sat':187,
            'bri':254
         },
         {
            'id':'4',
            'state':true,
            'hue':14101,
            'sat':180,
            'bri':141
         },
         {
            'id':'5',
            'state':true,
            'hue':14101,
            'sat':180,
            'bri':254
         },
         {
            'id':'6',
            'state':true,
            'hue':14101,
            'sat':180,
            'bri':161
         },
         {
            'id':'7',
            'state':true,
            'hue':12778,
            'sat':219,
            'bri':120
         },
         {
            'id':'8',
            'state':true,
            'hue':12778,
            'sat':219,
            'bri':254
         }
      ]
   },
   {
      'ConfigName':'Film du soir',
      'Lights':[
         {
            'id':'1',
            'state':true,
            'hue':7157,
            'sat':243,
            'bri':104
         },
         {
            'id':'2',
            'state':false,
            'hue':13907,
            'sat':187,
            'bri':179
         },
         {
            'id':'3',
            'state':true,
            'hue':13122,
            'sat':211,
            'bri':80
         },
         {
            'id':'4',
            'state':true,
            'hue':12778,
            'sat':219,
            'bri':142
         },
         {
            'id':'5',
            'state':true,
            'hue':13122,
            'sat':211,
            'bri':80
         },
         {
            'id':'6',
            'state':false,
            'hue':14101,
            'sat':180,
            'bri':161
         },
         {
            'id':'7',
            'state':false,
            'hue':13122,
            'sat':211,
            'bri':120
         },
         {
            'id':'8',
            'state':false,
            'hue':4712,
            'sat':241,
            'bri':254
         }
      ]
   },
   {
      'ConfigName':'Cheminée',
      'Lights':[
         {
            'id':'2',
            'state':false,
            'hue':7980,
            'sat':252,
            'bri':79
         },
         {
            'id':'8',
            'state':true,
            'hue':4712,
            'sat':241,
            'bri':254
         },
         {
            'id':'5',
            'state':true,
            'hue':13122,
            'sat':211,
            'bri':91
         },
         {
            'id':'4',
            'state':false,
            'hue':7862,
            'sat':252,
            'bri':53
         },
         {
            'id':'3',
            'state':true,
            'hue':13122,
            'sat':211,
            'bri':91
         },
         {
            'id':'6',
            'state':true,
            'hue':8774,
            'sat':252,
            'bri':56
         },
         {
            'id':'7',
            'state':true,
            'hue':13122,
            'sat':211,
            'bri':120
         },
         {
            'id':'1',
            'state':true,
            'hue':6196,
            'sat':247,
            'bri':104
         }
      ]
   },
   {
      'ConfigName':'Tout éteind',
      'OffConfig':true,
      'Lights':[
         {
            'id':'1',
            'state':false,
            'hue':7157,
            'sat':243,
            'bri':104
         },
         {
            'id':'2',
            'state':false,
            'hue':13907,
            'sat':187,
            'bri':179
         },
         {
            'id':'3',
            'state':false,
            'hue':3584,
            'sat':252,
            'bri':254
         },
         {
            'id':'4',
            'state':false,
            'hue':12778,
            'sat':219,
            'bri':142
         },
         {
            'id':'5',
            'state':false,
            'hue':13122,
            'sat':211,
            'bri':80
         },
         {
            'id':'6',
            'state':false,
            'hue':14101,
            'sat':180,
            'bri':161
         },
         {
            'id':'7',
            'state':false,
            'hue':12778,
            'sat':219,
            'bri':120
         },
         {
            'id':'8',
            'state':false,
            'hue':12778,
            'sat':219,
            'bri':254
         }
      ]
   }
]</pre><p></p>
<p>Vous remarquerez que j&rsquo;ai ajouté sur la première configuration la propriété « <em>DefaultConfig = true</em> » et « <em>OffConfig =true</em> » sur la dernière.  On se servira de ces deux propriétés pour savoir quelles sont les configurations à appliquer en cas de « On » et de « Off » sur notre interrupteur n°1.</p>
<p>Le setting est de type « JsonObject », on aura donc un bel éditeur dans la Console Constellation pour le déclarer ou le modifier. Pour vos développements vous pouvez aussi utiliser le <a href="/client-api/net-package-api/settings/">fichier App.config</a>.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-92.png"><img class="colorbox-4853"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Configuration du setting" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-91.png" alt="Configuration du setting" width="454" height="278" border="0" /></a></p>
<p>Pour revenir à notre code C#, nous allons tout d&rsquo;abord déclarer les variables privées suivantes :</p>
<p></p><pre class="crayon-plain-tag">private int currentConfigurationId = 0, defaultConfigurationId = 0, offConfigurationId = 0;
private List&lt;dynamic&gt; hueConfiguration = new List&lt;dynamic&gt;();</pre><p></p>
<p>Dans la méthode démarrage (<em>OnStart</em>) on charge notre setting JSON dans la variable « <em>hueConfiguration</em> » avec la méthode « <em>GetSettingAsJson</em> » puis on récupère dans ce tableau l&rsquo;index de la configuration « Default » et « Off » par la méthode .NET « <em>FindIndex</em> » :</p>
<p></p><pre class="crayon-plain-tag">hueConfiguration = new List&lt;dynamic&gt;(PackageHost.GetSettingAsJsonObject("Hue.Configurations"));
defaultConfigurationId = this.hueConfiguration.FindIndex(c =&gt; c.DefaultConfig == true);
offConfigurationId = this.hueConfiguration.FindIndex(c =&gt; c.OffConfig == true);</pre><p></p>
<p>Créons maintenant la méthode « <em>ApplyHueConfiguration</em> » qui se chargera d&rsquo;appliquer la configuration sur nos lampes Hue.</p>
<p>En quelques mots elle itère sur chaque « <em>Light</em> » de la configuration spécifiée par son index puis invoque le MessageCallback « <em>Set</em> » du package Hue en passant l&rsquo;ID de la lampe avec son état (state, hue/sat et brightness). La configuration courante est sauvegardée dans la variable « <em>currentConfigurationId</em>« .</p>
<p>Il est aussi possible de spécifier optionnellement l&rsquo;index de la configuration à exclure ce qui aura pour action d&rsquo;appliquer automatique la configuration suivante.</p>
<p></p><pre class="crayon-plain-tag">private int ApplyHueConfigration(List&lt;dynamic&gt; configurationList, int configIdx, int configToExclude = -1)
{
    // Si la config selectionnée est à exclure ...
    if (configToExclude &gt;= 0 &amp;&amp; configIdx == configToExclude)
    {
        // On passe à la configuration suivante :
        return this.ApplyHueConfigration(configurationList, (configIdx + 1) % configurationList.Count, configToExclude);
    }
    else
    {
        // On récupere la configuration à partir de son Index
        var config = configurationList[configIdx];
        PackageHost.WriteInfo("Applying Hue configuration '{0}'", config.ConfigName);
        // On applique la configuration en invoquant le MC "Set" à chaque lampe
        this.currentConfigurationId = configIdx;
        foreach (dynamic hue in config.Lights)
        {
            PackageHost.CreateMessageProxy("Hue").Set(hue.id, hue.state, hue.hue, hue.sat, hue.bri);
            Thread.Sleep(100);
        }
        // On retourne l'Index de la configuration appliquée
        return configIdx;
    }
}</pre><p></p>
<p>Maintenant modifions notre handler sur le StateObjectLink « InterrupteurHue1 » que nous avons créé précédemment.</p>
<p>Dès que cet interrupteur change d&rsquo;état on applique la configuration « Default » ou « Off » en fonction de l&rsquo;état du relais FGS-211 correspondant. On prendra garde de ne rien faire si l&rsquo;interrupteur change à « On » alors que l&rsquo;état des lampes n&rsquo;est pas éteint et inversement, on ne fera rien si l&rsquo;interrupteur change à « Off » alors que les lampes sont déjà éteintes.</p>
<p></p><pre class="crayon-plain-tag">this.InterrupteurHue1.ValueChanged += (s, e) =&gt;
{
    // Si InterrupteurHue1 change d'état
    if ((bool)e.OldState.DynamicValue.Status != (bool)e.NewState.DynamicValue.Status)
    {
        if ((bool)e.NewState.DynamicValue.Status &amp;&amp; this.currentConfigurationId != offConfigurationId)
        {
            // Ne rien faire si InterrupteurHue1 = ON et que la configuration actuelle n'est pas "tout eteint" !
            return;
        }
        else if ((bool)e.NewState.DynamicValue.Status == false &amp;&amp; this.currentConfigurationId == offConfigurationId)
        {
            // Ne rien faire si InterrupteurHue1 = OFF et que la configuration actuelle est déjà "tout eteint" !
            return;
        }
        else
        {
            // Autrement on applique la configuration "default" si InterrupteurHue1 = ON ou "off" si InterrupteurHue1 = Off
            this.ApplyHueConfigration(hueConfiguration, (bool)e.NewState.DynamicValue.Status ? defaultConfigurationId : offConfigurationId);
        }
    }
};</pre><p></p>
<p>Maintenant pour le deuxième interrupteur, dès qu&rsquo;il changera d&rsquo;état, deux cas :</p>
<ul>
<li>Si l&rsquo;interrupteur n°1 n&rsquo;est pas allumé, on invoque le MC « <em>SetSwitchState</em> » du package Vera pour l&rsquo;allumer. Ainsi son SO sera mis à jour et donc le code ci-dessus sera invoqué pour appliquer la configuration « Default » (synchronisation parfaite entre l&rsquo;état du relais Fibaro et nos lampes)</li>
<li>Si l&rsquo;interrupteur n°1 est déjà allumé, on appelle notre méthode « <em>ApplyHueConfiguration</em> » en spécifiant l&rsquo;index de la prochaine configuration et en excluant la configuration « tout éteint » (Off)</li>
</ul>
<p></p><pre class="crayon-plain-tag">// On permute les configurations avec InterrupteurHue2
this.InterrupteurHue2.ValueChanged += (s, e) =&gt;
{
    // Si InterrupteurHue2 change d'état
    if ((bool)e.OldState.DynamicValue.Status != (bool)e.NewState.DynamicValue.Status)
    {
        // Si InterrupteurHue1 = OFF, on l'allume pour garder InterrupteurHue1 syncrhonisé !
        if ((bool)this.InterrupteurHue1.DynamicValue.Status == false)
        {
            // Cela déclenchera le handler ci-dessus ce qui appliquera la configuration "default".
            PackageHost.CreateMessageProxy("Vera").SetSwitchState(new { DeviceID = (int)this.InterrupteurHue1.DynamicValue.Id, State = true });
        }
        else // Si InterrupteurHue1 est déjà ON
        {
            // ON applique la configuration suivante de facon cyclique en excluant la configuration " tout éteint"
            this.ApplyHueConfigration(hueConfiguration, (this.currentConfigurationId + 1) % hueConfiguration.Count, configToExclude: offConfigurationId);
        }
    }
};</pre><p></p>
<p>Ainsi on a bien l&rsquo;interrupteur n°1 qui contrôle le relais n° 1 du Fibaro, lui même parfaitement synchronisé avec nos lampes. Si le relais est éteint, on applique la configuration « OffConfig » de notre setting et si le relais est allumé, on applique la configuration « DefaultConfig ».</p>
<p>Quand on appuie sur l&rsquo;interrupteur n°2, on permute l&rsquo;état du relais n° 2 du Fibaro ce qui applique donc, de manière cyclique, les différentes configurations de notre setting sur nos lampes Hue.</p>
<p>On peut modifier comme bon nous semble le setting depuis la Console Constellation pour changer la configuration par défaut, ajouter ou supprimer de nouvelles ambiances ou modifier celles existantes ! De même, si ajoutez des lampes dans votre pièce vous n&rsquo;aurez qu&rsquo;à les déclarer dans votre JSON;</p>
<p>De plus, avec n&rsquo;importe quelle application ou contrôleur Z-Wave comme un Minimote par exemple, vous pouvez contrôler l&rsquo;interrupteur n°1 qui se synchronisera parfaitement avec vos lampes Hue !</p>
<h4>Pour aller plus loin</h4>
<p>Ajoutons une dernière méthode nommée « <em>ApplyHueConfiguration</em> » qui accepte en paramètre le nom de la configuration à appliquer. On l&rsquo;invoque avec le nom de la configuration (et non l&rsquo;index) et elle se chargera d&rsquo;appliquer cette configuration si elle existe bien dans votre setting.</p>
<p>Une fois n&rsquo;est pas coutume, on enverra des messages au package Vera pour synchroniser l&rsquo;état du relais n°1 si nécessaire.</p>
<p></p><pre class="crayon-plain-tag">[MessageCallback]
public int ApplyHueConfigration(string configName)
{
    // On récupere l'ID de la configuration à partir de son nom
    int configId = this.hueConfiguration.FindIndex(c =&gt; c.ConfigName == configName);
    if (configId &gt;= 0)
    {
        // On synchronise l'interrupteur Fibaro avec les lampes (sens Hue -&gt; Fibaro)
        if (configId != offConfigurationId &amp;&amp; (bool)this.InterrupteurHue1.DynamicValue.State == false)
        {
            PackageHost.CreateMessageProxy("Vera").SetSwitchState(new { DeviceID = (int)this.InterrupteurHue1.DynamicValue.Id, State = true });
        }
        else if (configId == offConfigurationId &amp;&amp; (bool)this.InterrupteurHue1.DynamicValue.State == true)
        {
            PackageHost.CreateMessageProxy("Vera").SetSwitchState(new { DeviceID = (int)this.InterrupteurHue1.DynamicValue.Id, State = false });
        }

        // On applique la configuration
        return this.ApplyHueConfigration(hueConfiguration, configId);
    }
    else
    {
        return configId;
    }
}</pre><p></p>
<p>Vous remarquerez que nous avons ajouté l&rsquo;attribut <em>[MessageCallback]</em> sur cette méthode ce qui veut dire que votre package exposera cette méthode, que l&rsquo;on nomme <em>MessageCallback</em>, pour toute votre Constellation.</p>
<p>C&rsquo;est à dire que n&rsquo;importe quel autre package C#, Python, un script Powershell ou Bash, un Arduino ou ESP8266, une page Web, etc&#8230; Tous pourront envoyer un message à votre package pour appliquer des configurations lumineuses sur vos lampes Hue en fonction des configurations que nous avez configuré dans votre setting !</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/tutorials/synchroniser-interrupteur-mural-ampoules-connectee/">Synchroniser un interrupteur mural avec des ampoules connectées et contrôler l&rsquo;ambiance lumineuse de votre pièce</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://developer.myconstellation.io/tutorials/synchroniser-interrupteur-mural-ampoules-connectee/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Synchroniser la lampe du bureau avec sa session Windows</title>
		<link>https://developer.myconstellation.io/tutorials/synchroniser-lampe-bureau-avec-session-windows/</link>
					<comments>https://developer.myconstellation.io/tutorials/synchroniser-lampe-bureau-avec-session-windows/#respond</comments>
		
		<dc:creator><![CDATA[Sebastien Warin]]></dc:creator>
		<pubDate>Sun, 14 May 2017 12:35:00 +0000</pubDate>
				<category><![CDATA[Tutoriels]]></category>
		<category><![CDATA[Vera]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Z-Wave]]></category>
		<category><![CDATA[WindowsControl]]></category>
		<category><![CDATA[Lux]]></category>
		<category><![CDATA[LightSensor]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[IA]]></category>
		<category><![CDATA[Package]]></category>
		<category><![CDATA[StateObjectLink]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=4829</guid>

					<description><![CDATA[<p>L&#8217;un des avantages de Constellation est qu&#8217;il est très facile de faire « parler » des objets/systèmes entre eux. Dans ce tutoriel, nous allons lier notre lampe du bureau à notre session Windows. L&#8217;idée est très simple : lorsque vous déverrouillez (ou ouvrez) votre</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/tutorials/synchroniser-lampe-bureau-avec-session-windows/">Synchroniser la lampe du bureau avec sa session Windows</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>L&rsquo;un des avantages de Constellation est qu&rsquo;il est très facile de faire « parler » des objets/systèmes entre eux. Dans ce tutoriel, nous allons lier notre lampe du bureau à notre session Windows.</p>
<p>L&rsquo;idée est très simple : lorsque vous déverrouillez (ou ouvrez) votre session Windows on allumera automatiquement la lampe du bureau et lorsque vous verrouillez (ou fermez) votre session, la lampe s&rsquo;éteindra automatiquement.</p>
<p align="center"><img loading="lazy" class="aligncenter wp-image-4833 size-full colorbox-4829" title="Demo" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/WindowsControl-gap.jpg" data-gif="https://developer.myconstellation.io/wp-content/uploads/2017/05/WindowsControl.gif" alt="Demo" width="450" height="253" /></p>
<p>On peut même aller plus loin si vous avez un capteur de luminosité connecté pour n&rsquo;allumer la lampe que lorsqu&rsquo;il fait trop sombre.</p>
<h3>Prérequis</h3>
<ul>
<li>Un serveur Constellation</li>
<li>Une lampe pilotable par Constellation</li>
<li>Le package <a href="/package-library/windowscontrol/">WindowsControl</a> déployé sur la sentinelle de l&rsquo;ordinateur Windows à synchroniser avec la lampe</li>
<li>Optionnellement un capteur de luminosité connecté dans Constellation</li>
<li>Le SDK Constellation pour Visual Studio</li>
</ul>
<h3>Etape 1 : piloter une lampe par Constellation</h3>
<p>Bien entendu il faut d&rsquo;abord pouvoir piloter une lampe par Constellation pour réaliser ce tutoriel !</p>
<p>Vous pouvez par exemple piloter un relais depuis un Raspberry en créant un package Python ou bien depuis un Arduino ou un ESP8266 comme vu <a href="/tutorials/creer-un-relais-connecte/">dans ce tutoriel</a>. Il suffit de créer une fonction pilotant un relais (simple manipulation d&rsquo;une sortie digitale) et d&rsquo;exposer cette fonction comme <a href="/concepts/messaging-message-scope-messagecallback-saga/">MessageCallback</a>. On pourra ainsi invoquer votre méthode pour ouvrir et fermer le relais et donc piloter une lampe depuis n&rsquo;importe quel système connecté dans votre Constellation.</p>
<p align="center"><img loading="lazy" class="alignnone size-full wp-image-4599 colorbox-4829" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-58.png" alt="" width="350" height="198" srcset="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-58.png 454w, https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-58-300x170.png 300w" sizes="(max-width: 350px) 100vw, 350px" /></p>
<p>Autre solution utiliser une carte de relais connectée par USB qu&rsquo;on pilotera avec le package <a href="/package-library/relayboard/">RelayBoard</a>. Ce package expose des MC permettant d&rsquo;ouvrir ou fermer les relais et publie l&rsquo;état de chacun d&rsquo;entre eux comme StateObject. Il ne reste plus qu&rsquo;à connecter une lampe sur l&rsquo;un des relais.</p>
<p align="center"><img loading="lazy" class="alignnone size-full wp-image-3530 colorbox-4829" title="RelayBoard" src="https://developer.myconstellation.io/wp-content/uploads/2016/10/image-143.png" alt="RelayBoard" width="176" height="180" /></p>
<p>On peut aussi utiliser des prises Wifi Belkin Wemo qu&rsquo;on connectera à Constellation avec le package <a href="/package-library/wemo/">Wemo</a>. Encore une fois ce package expose des MC permettant d&rsquo;allumer ou d’éteindre la charge connectée dessus et publie son état en tant que StateObject. Il suffit d&rsquo;y brancher une lampe !</p>
<p align="center"><img class="colorbox-4829"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Prise Wemo Insight" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/wemo.jpg" alt="Prise Wemo Insight" width="200" height="200" border="0" /></p>
<p>Dans la même idée, on peut utiliser des prises Somfy qu&rsquo;on connectera à Constellation avec le package <a href="/package-library/rfxcom/">RFXCOM </a>nécessitant une passerelle RFXcom connectée en USB. Le package expose un MessageCallback permettant d&rsquo;envoyer des ordres par radiofréquences aux équipements RTS (protocole Somfy) pour piloter par exemple des prises. Il n&rsquo;y a pas de retour d&rsquo;état sur ce protocole, donc il ne sera pas possible de récupérer son état mais on pourra allumer ou éteindre la prise et donc une lampe !</p>
<p align="center"><img class="colorbox-4829"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Prise Somfy" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/prise-telecommandee-interieure-variateur-100-w-rts-2401092-somfy.jpg" alt="Prise Somfy" width="200" height="200" border="0" /></p>
<p>Encore une autre possibilité, utiliser des prises ou des modules Z-Wave. Il faut pour cela un contrôleur Z-Wave qu&rsquo;on connectera à Constellation. Vous pouvez soit utiliser le package <a href="/package-library/jeedom/">Jeedom </a>ou soit le package <a href="/package-library/vera/">Vera</a>.</p>
<p align="center"><img class="colorbox-4829"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Prise Z-Wave AN158" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/an158.jpg" alt="Prise Z-Wave AN158" width="200" height="200" border="0" /></p>
<p>On pourrait également utiliser des lampes ou des ampoules connectées de la gamme Phillips Hue qu&rsquo;on connectera à Constellation grâce au package <a href="/package-library/hue/">Hue</a>.</p>
<p style="text-align: center;"><img loading="lazy" class="alignnone size-full wp-image-3598 colorbox-4829" src="https://developer.myconstellation.io/wp-content/uploads/2016/10/image-166.png" alt="" width="350" height="175" srcset="https://developer.myconstellation.io/wp-content/uploads/2016/10/image-166.png 350w, https://developer.myconstellation.io/wp-content/uploads/2016/10/image-166-300x150.png 300w" sizes="(max-width: 350px) 100vw, 350px" /></p>
<p>Pour ma part la lampe de mon bureau est contrôlée par une prise Z-Wave AN158 appairée sur une Vera Lite. Ce contrôleur Z-Wave est connecté à Constellation grâce au package <a href="/package-library/vera/">Vera</a>.</p>
<p>J&rsquo;ai donc dans ma Constellation des StateObjets pour chaque périphérique Z-Wave et des MessageCallbacks pour envoyer des ordres Z-Wave. Par exemple depuis le <a href="/constellation-platform/constellation-console/messagecallbacks-explorer/">MessageCallbacks Explorer</a>, on retrouve le MC « <em>SetSwitchState</em> » permettant de définir l&rsquo;état d&rsquo;un switch (On/Off) Z-Wave.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-85.png"><img class="colorbox-4829"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="MessageCallbacks Explorer" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-85.png" alt="MessageCallbacks Explorer" width="454" height="169" border="0" /></a></p>
<p style="text-align: left;" align="center">Depuis l&rsquo;API.net il me suffit d&rsquo;invoquer le code suivant pour allumer le device #42 :</p>
<p></p><pre class="crayon-plain-tag">PackageHost.CreateMessageProxy("Vera").SetSwitchState(new { DeviceID = 42, State = true });</pre><p></p>
<p>Vous pouvez appuyer sur le bouton <img loading="lazy" class="alignnone size-full wp-image-2961 colorbox-4829" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/image_thumb-112.png" alt="" width="25" height="22" /> pour obtenir les exemples de code pour chaque MessageCallback. Par exemple toujours pour allumer le device Z-Wave #42 depuis un Arduino :</p>
<p></p><pre class="crayon-plain-tag">constellation.sendMessage(Package, "Vera", "SetSwitchState", "{ 'DeviceID':42, 'State':true }");</pre><p></p>
<p>Bref il existe différente méthode de piloter une lampe (ou n&rsquo;importe quelle charge) depuis Constellation, soit en mode DIY en créant vous-même votre package réel (C#, Python, &#8230;) ou virtuel (Arduino, ESP8266, Gadgeteer, &#8230;) ou bien en utilisant des technologies telles RTS de Somfy, le Z-Wave, les lampes et ampoules Philips, les prises Wifi de Belkin, etc&#8230; avec les packages déjà disponibles dans le <a href="/plateforme/package-repository/">catalogue en ligne</a>.</p>
<p>Et quand bien même il n&rsquo;existe pas de connecteur Constellation pour piloter votre lampe, libre à vous de créer votre propre package créant ainsi la passerelle, le connecteur entre Constellation et votre lampe.</p>
<h3>Etape 2 : connaitre l&rsquo;état de la session avec le package WindowsControl</h3>
<p>Maintenant que nous avons un MessageCallback pour piloter la lampe du bureau, faut-il encore savoir si la session est ouverte ou non.</p>
<p>Pour cela vous avez dans le catalogue en ligne, le package <a href="/package-library/windowscontrol/">WindowsControl</a> qui expose différent MessageCallbacks pour verrouiller ou fermer une session, pour arrêter ou redémarrer l&rsquo;ordinateur, pour contrôler le volume ou la luminosité (comme vu <a href="/tutorials/potentiometre-connecte-pour-controler-le-volume-ou-la-luminosite/">dans ce tutoriel</a>).</p>
<p>Ce package produit également un StateObject nommé « SessionLocked » de type booléen qui indique si la session est verrouillée (ou fermée) ou non.</p>
<p>Il suffit donc de <a href="/getting-started/telecharger-et-deployer-des-packages-sur-vos-sentinelles/">déployer ce package</a> depuis la <a href="/constellation-platform/constellation-console/package-repository/">Console Constellation</a> sur la sentinelle UI du PC à synchroniser avec votre lampe. On suivra ainsi ce StateObject pour savoir quel est l&rsquo;état de votre session et réagir tout changement d&rsquo;état.</p>
<h3>Etape 3 : synchroniser la lampe avec la session en C#</h3>
<p>Passons au chose sérieuse, nous avons d&rsquo;un côté un StateObject nous indiquant si la session est ouverte ou non et un MessageCallback nous permettant d&rsquo;allumer ou d&rsquo;éteindre la lampe du bureau, reste juste à créer le lien.</p>
<p>Pour cela nous allons <a href="/getting-started/creez-votre-premier-package-constellation-en-csharp/">créer un package .NET en C#</a> depuis Visual Studio.</p>
<p>Dans la classe principale (<em>Program</em>), nous allons ajouter un <a href="/client-api/net-package-api/consommer-des-stateobjects/">StateObjectLink</a>, c&rsquo;est à dire une propriété dans notre code liée au StateObject représentant l&rsquo;état de la session en ajoutant les lignes :</p>
<p></p><pre class="crayon-plain-tag">[StateObjectLink("WindowsControl", "SessionLocked")]
public StateObjectNotifier SessionLocked { get; set; }</pre><p></p>
<p>Prenez garde toutefois, si vous avez déployé le package WindowsControl sur plusieurs sentinelles de votre Constellation, le StateObjectLink ci-dessus sera lié à plusieurs StateObjects et non au StateObject de votre ordinateur à scruter. L’unicité d’un StateObject est obtenu par le triplet : “Sentinel + Package + Nom” car un nom de StateObject est unique pour une <a href="https://developer.myconstellation.io/concepts/instance-package-versioning-et-resolution/#Sentinel_Package_Instance_de_package">instance de package</a> (couple Sentinel / Package), de même qu’un package est unique pour une sentinelle et qu’une sentinelle est unique dans une Constellation.</p>
<p>De ce fait pour lier la propriété « <em>SessionLocked</em> » au StateObject « <em>SessionLocked</em> » de votre ordinateur on écrira :</p>
<p></p><pre class="crayon-plain-tag">[StateObjectLink("PC-SEB_UI", "WindowsControl", "SessionLocked")]
public StateObjectNotifier Session { get; set; }</pre><p></p>
<p>Dans l&rsquo;exemple ci-dessus, la machine est nommée « PC-SEB » et donc le nom de sa sentinelle « PC-SEB_UI » étant donné que le package WindowsControl est déployé sur la Sentinelle UI d&rsquo;où le suffixe « _UI » dans le nom de la sentinelle. Vous pouvez bien entendu vérifier le nom exacte de votre sentinelle sur la Console Constellation.</p>
<p>Maintenant que l&rsquo;état de la session de notre PC est synchronisé dans cette propriété .NET de notre code C#, nous allons ajouter un « handler » pour réagir au changement d&rsquo;état :</p>
<p></p><pre class="crayon-plain-tag">this.SessionLocked.ValueChanged += (s, e) =&gt;
{
    if ((bool)this.SessionLocked.DynamicValue)
    {
        PackageHost.WriteInfo("Verrouillage de la session : fermeture de la lampe");
    }
    else
    {
        PackageHost.WriteInfo("Session déverrouillée : allumage de la lampe");
    }
};</pre><p></p>
<p>Maintenant pour allumer la lumière, il suffit d&rsquo;envoyer un message pour déclencher le MessageCallback permettant de contrôler votre lampe. Comme expliqué ci-dessus, dans mon cas, la lampe sur mon bureau est contrôlée par une prise Z-Wave AN158 pilotable par le package Vera via le MessageCallback « <em>SetSwitchState</em>« .</p>
<p>On crée donc <a href="/client-api/net-package-api/envoyer-des-messages-invoquer-des-messagecallbacks/">un proxy dynamique vers le package</a> Vera et on invoque le MC comme on invoquerait une méthode .NET en passant en paramètre un objet contenant l&rsquo;ID du device Z-Wave et l&rsquo;état souhaité :</p>
<p></p><pre class="crayon-plain-tag">PackageHost.CreateMessageProxy("Vera").SetSwitchState(new { DeviceID = 42, State = true });</pre><p></p>
<p>Pour connaitre l&rsquo;ID du device Z-Wave on peut soit le rechercher dans le StateObjects Explorer et l&rsquo;écrire en dur dans notre code C#, ou soit ajouter un autre StateObjectLink afin de récupérer dynamiquement son Id (car contenu dans le StateObject du device).</p>
<p>Le code de notre package sera donc :</p>
<p></p><pre class="crayon-plain-tag">public class Program : PackageBase
{
    [StateObjectLink("Vera", "Lampe Bureau Seb")]
    public StateObjectNotifier LampeBureau { get; set; }

    [StateObjectLink("PC-SEB_UI", "WindowsControl", "SessionLocked")]
    public StateObjectNotifier SessionLocked { get; set; }

    static void Main(string[] args)
    {
        PackageHost.Start&lt;Program&gt;(args);
    }

    public override void OnStart()
    {
        this.SessionLocked.ValueChanged += (s, e) =&gt;
        {
            if ((bool)this.SessionLocked.DynamicValue)
            {
                PackageHost.WriteInfo("Verrouillage de la session : fermeture de la lampe");
                PackageHost.CreateMessageProxy("Vera").SetSwitchState(new { DeviceID = (int)this.LampeBureau.DynamicValue.Id, State = false });
            }
            else
            {
                PackageHost.WriteInfo("Session déverrouillée : allumage de la lampe");
                PackageHost.CreateMessageProxy("Vera").SetSwitchState(new { DeviceID = (int)this.LampeBureau.DynamicValue.Id, State = true });
            }
        };
    }
}</pre><p></p>
<p>On peut maintenant lancer notre package en mode « Debug On Constellation » pour le tester depuis Visual Studio tout en le connectant dans votre Constellation :</p>
<p><img loading="lazy" class="alignnone size-full wp-image-1675 aligncenter colorbox-4829" src="https://developer.myconstellation.io/wp-content/uploads/2016/03/image-196.png" alt="" width="104" height="34" /></p>
<p>Vous pouvez tester le fonctionnel de votre package : on verrouille la session, la lampe s&rsquo;éteint, on la déverrouille, la lampe s&rsquo;allume !</p>
<p>Une fois votre package testé et validé, vous pouvez <a href="/constellation-platform/constellation-sdk/publier-package-visual-studio/">le publier</a> dans votre Constellation et le déployer sur une de vos sentinelles (<a href="/getting-started/creez-votre-premier-package-constellation-en-csharp/#Publier_son_package_dans_Constellation">voir le guide</a>).</p>
<h3>Etape 4 : ajouter un capteur de luminosité</h3>
<p>Jusqu&rsquo;à présent dès que la session est déverrouillée la lampe du bureau s&rsquo;allume et dès qu&rsquo;on la ferme elle s’éteint. Seulement en pleine journée ce n&rsquo;est peut être pas très judicieux d&rsquo;allumer la lumière !</p>
<p>Pour cela nous pouvons ajouter une condition supplémentaire basée sur la luminosité ambiante.</p>
<p>On pourrait utiliser un capteur sans fil du marché comme le Chacon DIO54783 connecté via le package RFXcom ou bien un capteur Z-Wave via le package Vera ou Jeedom. On peut aussi concevoir son propre capteur avec un Arduino ou un ESP8266 <a href="/tutorials/creer-un-capteur-de-luminosite-dans-une-prise-220v/">comme vu dans ce tutoriel</a> ou avec un Raspberry Pi <a href="/tutorials/un-capteur-de-luminosite-exterieur-pilote-par-raspberry/">comme vu ici</a>.</p>
<p style="text-align: center;"><a href="/tutorials/creer-un-capteur-de-luminosite-dans-une-prise-220v/"><img loading="lazy" class="alignnone wp-image-4818 colorbox-4829" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-84.png" alt="" width="351" height="312" srcset="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-84.png 454w, https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-84-300x266.png 300w" sizes="(max-width: 351px) 100vw, 351px" /></a></p>
<p style="text-align: center;"><a href="/tutorials/un-capteur-de-luminosite-exterieur-pilote-par-raspberry/"><img loading="lazy" class="alignnone wp-image-4749 size-full colorbox-4829" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1170883_thumb-1.jpg" alt="" width="354" height="227" srcset="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1170883_thumb-1.jpg 354w, https://developer.myconstellation.io/wp-content/uploads/2017/05/P1170883_thumb-1-300x192.jpg 300w" sizes="(max-width: 354px) 100vw, 354px" /></a></p>
<p>Dans notre article, prenons par exemple l&rsquo;un des deux capteurs ci-dessus qui publient chacun un StateObject nommé « Lux » composé de 3 propriétés : Broadband, IR et Lux.</p>
<p>Pour intégrer cette « information » dans notre code C#, ajoutons un StateObjectLink vers le StateObject « Lux » :</p>
<p></p><pre class="crayon-plain-tag">[StateObjectLink("LightSensor", "Lux")]
public StateObjectNotifier LuxSensor { get; set; }</pre><p></p>
<p>On peut maintenant modifier la condition d&rsquo;allumage avec un « else if » qui vérifiera que la luminosité est inférieure à un seuil qu&rsquo;on <a href="/client-api/net-package-api/settings/">va déclarer dans les settings</a> Constellation de façon à pouvoir modifier cette valeur à la volée depuis la Console Constellation :</p>
<p></p><pre class="crayon-plain-tag">else if (this.LuxSensor.DynamicValue.Lux &lt; PackageHost.GetSettingValue&lt;int&gt;("DaylightThreshold"))</pre><p></p>
<p>Bien entendu comme tout setting, il est vivement recommandé de le déclarer dans le <a href="/concepts/package-manifest/">manifeste du package</a> (le fichier <em>PackageInfo.xml</em>). De plus on pourra y définir la valeur par défaut ici fixée à 50 (lux) :</p>
<p></p><pre class="crayon-plain-tag">&lt;Settings&gt;
  &lt;Setting name="DaylightThreshold" type="Int32" defaultValue="50" description="Seuil de luminosité minimale pour l'allumage de la lampe du bureau" /&gt;
&lt;/Settings&gt;</pre><p></p>
<p>Pour finir, prenons le cas où la session est déjà déverrouillée et la soirée arrivant, la luminosité passe en dessous du seuil : il faut alors allumer la lumière bien que l&rsquo;état de la session n&rsquo;a pas changé !</p>
<p>Pour cela nous allons ajouter un « handler » pour réagir à chaque mise à jour du StateObject « Lux » du capteur de luminosité. A chaque nouvelle mesure, si la valeur est inférieure au seuil défini dans les settings et que la session est bien déverrouillée, on allumera la lumière :</p>
<p></p><pre class="crayon-plain-tag">this.LuxSensor.ValueChanged += (s, e) =&gt;
{
    if (e.NewState.DynamicValue.Lux &lt; PackageHost.GetSettingValue&lt;int&gt;("DaylightThreshold") &amp;&amp; (bool) this.SessionLocked.DynamicValue == false)
    {
        PackageHost.WriteInfo("Session déverrouillée à la tombée de la nuit : allumage de la lampe");
        PackageHost.CreateMessageProxy("Vera").SetSwitchState(new { DeviceID = (int)this.LampeBureau.DynamicValue.Id, State = true });
    }
};</pre><p></p>
<p>Ainsi notre lumière de bureau est maintenant synchronisée à notre session et ne s&rsquo;allumera que si la luminosité est faible. Elle sera donc éteinte dès qu&rsquo;on ferme ou verrouille la session et s&rsquo;allumera si la luminosité baisse sous le seuil défini dans les settings alors que la session est déjà déverrouillée ou vient d&rsquo;être déverrouillée.</p>
<h3>Etape 5 : fermer la lampe en cas de déconnexion du PC</h3>
<p>Pour vraiment aller au fond des choses il y a encore un cas à gérer : que faire si le PC s’arrête proprement ou brutalement. En somme l&rsquo;idée est de fermer la lampe si le PC est déconnecté de Constellation, que ce soit suite à un arrêt de l&rsquo;ordinateur, un crash, une déconnexion quelconque, etc..</p>
<p>Pour savoir si le PC est bien connecté on va surveiller l&rsquo;état de la sentinelle UI de votre PC. Pour cela il faut se connecter sur le hub de contrôle.</p>
<p>L&rsquo;utilisation du hub de contrôle depuis un package C# est expliqué en détail <a href="/client-api/net-package-api/controlmanager/">dans cet article </a>que je vous recommande de lire.</p>
<p>La première étape consiste donc à déclarer dans le <a href="/concepts/package-manifest/">manifeste du package</a> (le fichier <em>PackageInfo.xml</em>) l&rsquo;utilisation du hub de contrôle par votre package en ajoutant l&rsquo;attribut suivant sur la balise <em>Package</em> :</p>
<p></p><pre class="crayon-plain-tag">EnableControlHub="true"</pre><p></p>
<p>De plus il faut également, sur votre package, définir une <a href="/constellation-platform/constellation-console/gerer-credentials-avec-la-console-constellation/">clé d&rsquo;accès ayant les droits d&rsquo;accès au hub de contrôle</a>. Vous pouvez vérifier la bonne connexion au hub de contrôle dans votre code par la propriété : « <em>PackageHost.HasControlManager</em>« .</p>
<p>Une fois connecté au hub de contrôle on va demander à recevoir les mises à jour des statuts des sentinelles de notre Constellation par la ligne :</p>
<p></p><pre class="crayon-plain-tag">PackageHost.ControlManager.RequestSentinelUpdates();</pre><p></p>
<p>Cela nous permet ensuite d&rsquo;attacher un « handler » qu&rsquo;on filtrera sur notre sentinelle (ici nommée « PC-SEB_UI »). On stockera dans la variable « pcConnected » un booléen indiquant si la sentinelle de notre PC est connectée ou non. Si notre sentinelle n&rsquo;est pas/plus connectée, on fermera immédiatement la lampe du bureau.</p>
<p></p><pre class="crayon-plain-tag">PackageHost.ControlManager.SentinelUpdated += (s, e) =&gt;
{
    if (e.Sentinel.Description.SentinelName == "PC-SEB_UI")
    {
        this.pcConnected = e.Sentinel.IsConnected;
        PackageHost.WriteInfo("Le PC de Seb est '{0}'", e.Sentinel.IsConnected ? "connecté" : "déconnecté");
        if (!this.pcConnected)
        {
            // Éteindre la lampe si le PC est déconnecté !
            PackageHost.CreateMessageProxy("Vera").SetSwitchState(new { DeviceID = (int)this.LampeBureau.DynamicValue.Id, State = false });
        }
    }
};</pre><p></p>
<p>De plus, dans la condition d&rsquo;allumage, on rajoutera le fait de vérifier que le PC est bien connecté avant de prendre la décision d&rsquo;allumer la lampe :</p>
<p></p><pre class="crayon-plain-tag">else if (this.pcConnected &amp;&amp; this.LuxSensor.DynamicValue.Lux &lt; PackageHost.GetSettingValue&lt;int&gt;("DaylightThreshold"))</pre><p></p>
<p>Et voilà, notre package est opérationnel ! La lampe est parfaitement synchronisée avec l&rsquo;état de notre session Windows en tenant compte de la luminosité ambiante et des différents cas de figure pouvant apparaître, comme le redémarrage, l’arrêt ou le crash de notre PC !</p>
<p>Le code final est :</p>
<p></p><pre class="crayon-plain-tag">public class Program : PackageBase
{
    // Nom de la sentinelle Windows à syncrhoniser avec la lampe
    private const string SEB_PC_SENTINEL_NAME = "PC-SEB_UI";
    
    // PC Connecté? oui ou non !
    private bool pcConnected = false;

    // Lien vers le SO de la lampe du bureau
    [StateObjectLink("Vera", "Lampe Bureau Seb")]
    public StateObjectNotifier LampeBureau { get; set; }

    // Lien vers l'état de la session Windows
    [StateObjectLink(SEB_PC_SENTINEL_NAME, "WindowsControl", "SessionLocked")]
    public StateObjectNotifier SessionLocked { get; set; }

    // Lien vers le capteur de luminosité
    [StateObjectLink("LightSensor", "Lux")]
    public StateObjectNotifier LuxSensor { get; set; }

    // Démarrage du package
    static void Main(string[] args)
    {
        PackageHost.Start&lt;Program&gt;(args);
    }

    // Méthode de démarrage de notre package
    public override void OnStart()
    {
        // Si accès au ControlHub
        if (PackageHost.HasControlManager)
        {
            // Demande de reception des mise à jour des sentinelles
            PackageHost.ControlManager.RequestSentinelUpdates();
            // En cas de mise à jour de l'état d'une sentinelle
            PackageHost.ControlManager.SentinelUpdated += (s, e) =&gt;
            {
                // Si cela concerne notre sentinelle
                if (e.Sentinel.Description.SentinelName == SEB_PC_SENTINEL_NAME)
                {
                    // On stocke dans la variable "pcConnected" l'état connecté ou déconnecté de notre PC
                    this.pcConnected = e.Sentinel.IsConnected;
                    PackageHost.WriteInfo("Le PC de Seb est '{0}'", e.Sentinel.IsConnected ? "connecté" : "déconnecté");
                    // Si le PC est maintenant déconnecté, on ferme la lampe !
                    if (!this.pcConnected)
                    {
                        SetLight(false);
                    }
                }
            };
        }
        else
        {
            // Pas d'accès au COntrolHub, on log une erreur ! Vérifiez votre clé d'accès !
            PackageHost.WriteError("Accès au ControlHub impossible !");
        }

        // En cas de mise à jour du StateObject "Lux" du package "LightSensor"
        this.LuxSensor.ValueChanged += (s, e) =&gt;
        {
            // Si le PC est connecté, que la luminosité actuelle est inférieure au seuil défini dans les settings et que la session est bien dévérouillée
            if (this.pcConnected &amp;&amp; e.NewState.DynamicValue.Lux &lt; PackageHost.GetSettingValue&lt;int&gt;("DaylightThreshold") &amp;&amp; (bool) this.SessionLocked.DynamicValue == false)
            {
                // On allume la lampe !
                SetLight(true);
                PackageHost.WriteInfo("Session dévérouillée à la tombée de la nuit : allumage de la lampe");
            }
        };

        // En cas de mise à jour du StateObject "SessionLocked" du package "WindowsControl"
        this.SessionLocked.ValueChanged += (s, e) =&gt;
        {
            // Si la session est vérouillée (ou fermée)
            if ((bool)this.SessionLocked.DynamicValue)
            {
                // On eteint la lampe
                SetLight(false);
                PackageHost.WriteInfo("Verrouillage de la session : fermeture de la lampe");
            }
            // Si le PC est connecté, que la luminosité actuelle est inférieure au seuil défini dans les settings et que la session est donc dévérouillée
            else if (this.pcConnected &amp;&amp; this.LuxSensor.DynamicValue.Lux &lt; PackageHost.GetSettingValue&lt;int&gt;("DaylightThreshold"))
            {
                // On allume la lampe !
                SetLight(true);
                PackageHost.WriteInfo("Session déverrouillée avec luminosité faible : allumage de la lampe");
            }
        };
    }

    private void SetLight(bool state)
    {
        // Pour allumer la lumière, on invoque le MC "SetSwitchState" du package "Vera" en passant l'ID de la lampe (récupérée par son StateObjet)
        PackageHost.CreateMessageProxy("Vera").SetSwitchState(new { DeviceID = (int)this.LampeBureau.DynamicValue.Id, State = state });
    }
}</pre><p></p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/tutorials/synchroniser-lampe-bureau-avec-session-windows/">Synchroniser la lampe du bureau avec sa session Windows</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://developer.myconstellation.io/tutorials/synchroniser-lampe-bureau-avec-session-windows/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Créer un capteur de luminosité dans une prise 220v avec un ESP8266</title>
		<link>https://developer.myconstellation.io/tutorials/creer-un-capteur-de-luminosite-dans-une-prise-220v/</link>
					<comments>https://developer.myconstellation.io/tutorials/creer-un-capteur-de-luminosite-dans-une-prise-220v/#comments</comments>
		
		<dc:creator><![CDATA[Sebastien Warin]]></dc:creator>
		<pubDate>Sat, 13 May 2017 13:35:14 +0000</pubDate>
				<category><![CDATA[Tutoriels]]></category>
		<category><![CDATA[IoT]]></category>
		<category><![CDATA[ESP8266]]></category>
		<category><![CDATA[Lux]]></category>
		<category><![CDATA[TSL2561]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=4819</guid>

					<description><![CDATA[<p>Ce tutoriel est sur le principe identique à celui-ci : Créer un capteur de température, humidité et luminosité connecté sauf que nous allons utiliser un ESP-01 beaucoup plus petit et moins cher qu&#8217;un D1 Mini Pro. Nous assemblerons l&#8217;ESP8266 et le capteur de</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/tutorials/creer-un-capteur-de-luminosite-dans-une-prise-220v/">Créer un capteur de luminosité dans une prise 220v avec un ESP8266</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Ce tutoriel est sur le principe identique à celui-ci : <a href="/tutorials/creer-un-capteur-de-temperature-humidite-et-luminosite-connecte/">Créer un capteur de température, humidité et luminosité connecté</a> sauf que nous allons utiliser un ESP-01 beaucoup plus petit et moins cher qu&rsquo;un D1 Mini Pro.</p>
<p>Nous assemblerons l&rsquo;ESP8266 et le capteur de luminosité TSL2561 dans une prise 220v avec un convertisseur 220v -&gt; 3v3.</p>
<h3>Prérequis</h3>
<ul>
<li>Un serveur Constellation</li>
<li>Un ESP8266 comme l&rsquo;ESP-01 (entre 1,5€ et 2€)</li>
<li>Un capteur de luminosité TSL2561 (environ 2€)</li>
<li>Un convertisseur 220v -&gt; 3v3 (environ 2€)</li>
<li>Un boitier/prise 220v (entre 5 et 15 €)</li>
</ul>
<h3>Le montage</h3>
<p>Le capteur TSL2561 se connecte en I²C, il suffit donc de l&rsquo;alimenter en 3v3 et de connecter les deux GPIO de l&rsquo;ESP-01 (GPIO-0 et GPIO-2) aux pins SCL et SDA du capteur.</p>
<p>Le schéma de connexion est donc le suivant :</p>
<p style="text-align: center;"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/Fig-1.png"><img class="colorbox-4819"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Lux Sensor" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/Fig-1_thumb.png" alt="Lux Sensor" width="450" height="285" border="0" /></a></p>
<p>Sur le bornier 220v de notre prise nous allons souder deux fils (la phase et le neutre) vers l&rsquo;entrée convertisseur 220v AC. En sortie du convertisseur, on a une tension de 3v3 DC que nous connecterons à l&rsquo;ESP-01 ainsi qu&rsquo;au TSL2561.</p>
<p>N&rsquo;oubliez pas également de relier le port « CH_PD » de l&rsquo;ESP-01 au 3v3 pour activer le Wifi.</p>
<p>Pour plus d’information, je vous invite <a href="https://sebastien.warin.fr/2016/07/12/4138-decouverte-des-esp8266-le-microcontroleur-connecte-par-wifi-pour-2-au-potentiel-phenomenal-avec-constellation/" target="_blank" rel="noopener noreferrer">à lire cet article</a>.</p>
<p style="text-align: center;"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-84.png"><img class="colorbox-4819"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Lux Sensor" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-84.png" alt="Lux Sensor" width="454" height="403" border="0" /></a></p>
<p>Disposez les différents composants dans le boitier en prenant soin d&rsquo;isoler les parties 220v (avec de la colle thermofusibles ou du ruban isolant).</p>
<h3>Le code</h3>
<p>L&rsquo;ESP-01 ne dispose pas comme le D1 Mini Pro vu dans<a href="/tutorials/creer-un-capteur-de-temperature-humidite-et-luminosite-connecte/"> ce tutoriel</a> d&rsquo;une interface USB intégrée. Il vous faudra donc une interface USB/FTDI pour le programmer. Pour plus d’information, je vous invite <a href="https://sebastien.warin.fr/2016/07/12/4138-decouverte-des-esp8266-le-microcontroleur-connecte-par-wifi-pour-2-au-potentiel-phenomenal-avec-constellation/" target="_blank" rel="noopener noreferrer">à lire cet article</a>.</p>
<p>A l&rsquo;inverse du <a href="/tutorials/creer-un-capteur-de-temperature-humidite-et-luminosite-connecte/">tutoriel précédent</a>, ce code utilise la libraire <a href="https://github.com/adafruit/TSL2561-Arduino-Library" data-pjax="#js-repo-pjax-container">TSL2561-Arduino-Library</a> et non la « Unifed Sensor Library » afin de nous permettre de récupérer le Broadband et l&rsquo;IR en plus des Lux.</p>
<p>Il faudra donc installer la libraire « <em>TSL2561-Arduino-Library</em> » depuis le Gestionnaire de bibliothèque. De plus on utilise ici « ArduinoThread » pour ordonner les mesures à intervalle régulier. Vous devrez également installer cette librairie.</p>
<p><strong>Attention</strong> : si tout cela est nouveau pour vous, je vous recommande <a href="https://developer.myconstellation.io/getting-started/connecter-un-arduino-ou-un-esp8266-constellation/">de suivre ce guide d’introduction à l’API Constellation pour Arduino/ESP8266</a>.</p>
<p>Le code complet est :</p>
<p></p><pre class="crayon-plain-tag">#include &lt;ESP8266WiFi.h&gt;
const char* ssid     = "MON SSID";
const char* password = "lacléeWifi!!!!";

#include &lt;Constellation.h&gt;
Constellation&lt;WiFiClient&gt; constellation("IP ou DNS du serveur Constellation", 8088, "ESP-LightSensorSalon", "LightSensor", "123456789");

#include &lt;Wire.h&gt;
#include &lt;TSL2561.h&gt;
TSL2561 tsl(TSL2561_ADDR_FLOAT); 

#include &lt;Thread.h&gt;
Thread thrPushLux = Thread();

void pushLuxOnConstellation() {  
  uint32_t lum = tsl.getFullLuminosity();
  uint16_t ir, full;
  ir = lum &gt;&gt; 16;
  full = lum &amp; 0xFFFF;
  uint32_t lux = tsl.calculateLux(full, ir);
  
  constellation.pushStateObject("Lux", stringFormat("{ 'Lux':%d, 'Broadband':%d, 'IR':%d }", lux, full, ir), "LightSensor.Lux", 300);
}

void setup(void) {
  Serial.begin(115200);  delay(10);

  if (tsl.begin()) {
    Serial.println("Found sensor");
  } else {
    Serial.println("No sensor?");
    while (1);
  }
  
  // You can change the gain on the fly, to adapt to brighter/dimmer light situations
  //tsl.setGain(TSL2561_GAIN_0X);         // set no gain (for bright situtations)
  tsl.setGain(TSL2561_GAIN_16X);      // set 16x gain (for dim situations)  
  // Changing the integration time gives you a longer time over which to sense light
  // longer timelines are slower, but are good in very low light situtations!
  //tsl.setTiming(TSL2561_INTEGRATIONTIME_13MS);  // shortest integration time (bright light)
  //tsl.setTiming(TSL2561_INTEGRATIONTIME_101MS);  // medium integration time (medium light)
  tsl.setTiming(TSL2561_INTEGRATIONTIME_402MS);  // longest integration time (dim light)

  // Set Wifi mode
  if (WiFi.getMode() != WIFI_STA) {
    WiFi.mode(WIFI_STA);
    delay(10);
  }
  
  // Connect to Wifi  
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("WiFi connected. IP: ");
  Serial.println(WiFi.localIP());
  Serial.println(constellation.getSentinelName());
  
  JsonObject&amp; settings = constellation.getSettings();
  int interval = 10000; //ms
  if(settings.containsKey("Interval")) {
    interval = settings["Interval"].as&lt;int&gt;();
  }

  thrPushLux.onRun(pushLuxOnConstellation);
  thrPushLux.setInterval(interval);

  constellation.addStateObjectType("LightSensor.Lux", TypeDescriptor().setDescription("Lux data informations").addProperty("Broadband", "System.Int32").addProperty("IR", "System.Int32").addProperty("Lux", "System.Int32"));
  constellation.declarePackageDescriptor();
  
  constellation.writeInfo("ESP LightSensor '%s' is started (Push interval: %d sec)", constellation.getSentinelName(), interval);  
}

void loop(void) {
  if(thrPushLux.shouldRun()){
    thrPushLux.run();
  }
}</pre><p></p>
<p>Pour démarrer vous devez dans Constellation déclarer une sentinelle associée à une clé d’accès et un package virtuel. Ici notre ESP8266 est représenté par la sentinelle nommée “ESP-LightSensorSalon” et le package virtuel se nomme “LightSensor”.</p>
<p>Ensuite il faut définir le nom de notre réseau Wifi (SSID) ainsi que sa clé d’accès puis nous configurerons le client Constellation en spécifiant l’identité de notre package virtuel, sa clé d’accès et l’adresse/port de notre serveur Constellation.</p>
<p>Dans la méthode « <em>setup()</em>« , on initialise le capteur TSL puis on se connecte au Wifi et enfin on déclare l&rsquo;intervalle de temps entre chaque mesure, par défaut de 10 secondes qu&rsquo;on peut modifier en ajoutant un setting « Interval » sur notre package virtuel.</p>
<p>On configure ensuite un « thread » qui exécutera à l&rsquo;intervalle de temps spécifié la méthode « <em>pushLuxOnConstellation</em>« . Pour finir on déclare la description du StateObject par la méthode « <em>constellation.addStateObjectType</em> » et on affiche un log. Dans la <em>loop()</em>, on déclenche le thread.</p>
<p>La méthode « <em>pushLuxOnConstellation</em> » récupère les données du capteur et publie le StateObject « Lux » avec les trois propriétés :</p>
<p></p><pre class="crayon-plain-tag">constellation.pushStateObject("Lux", stringFormat("{ 'Lux':%d, 'Broadband':%d, 'IR':%d }", lux, full, ir), "LightSensor.Lux", 300);</pre><p></p>
<p>Une fois le programme téléversé, votre prise publiera le StateObject à l&rsquo;intervalle régulier la luminosité ambiante.</p>
<h3>Exploiter le capteur</h3>
<p>Comme vous le savez, une fois les données mesurées publiées dans un StateObject n&rsquo;importe quel système connecté dans Constellation peut récupérer ou s&rsquo;abonner en temps réel au StateObject.</p>
<p>On peut donc écrire des pages Web, des scripts, des packages .NET ou Python, Arduino, etc… qui exploiteront ces mesures en temps réel.</p>
<p>Je vous renvoie sur <a href="/tutorials/un-capteur-de-luminosite-exterieur-pilote-par-raspberry/#Exploitez_les_donnees">cette page</a> ou<a href="/tutorials/creer-un-capteur-de-temperature-humidite-et-luminosite-connecte/#Etape_3_Une_page_Web_pour_afficher_votre_capteur_en_temps_reel"> cette autre page</a> pour avoir quelques idées.</p>
<p>Pour ma part ce capteur installé dans le salon est affiché en temps réel sur <a href="https://sebastien.warin.fr/2015/07/15/3033-s-panel-une-interface-domotique-et-iot-multi-plateforme-avec-cordova-angularjs-et-constellation-ou-comment-crer-son-dashboard-domotique-mural/">un dashboard Web</a>,  stocké dans ElasticSearch et Cacti et exploité dans un package .NET nommé « MyBrain » car cette information sur la luminosité ambiante sert dans beaucoup de scénario : gestion des éclairages ou des volets.</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/tutorials/creer-un-capteur-de-luminosite-dans-une-prise-220v/">Créer un capteur de luminosité dans une prise 220v avec un ESP8266</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://developer.myconstellation.io/tutorials/creer-un-capteur-de-luminosite-dans-une-prise-220v/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Un capteur de luminosité extérieur piloté par un Raspberry avec un package Python</title>
		<link>https://developer.myconstellation.io/tutorials/un-capteur-de-luminosite-exterieur-pilote-par-raspberry/</link>
					<comments>https://developer.myconstellation.io/tutorials/un-capteur-de-luminosite-exterieur-pilote-par-raspberry/#respond</comments>
		
		<dc:creator><![CDATA[Sebastien Warin]]></dc:creator>
		<pubDate>Sat, 13 May 2017 12:46:15 +0000</pubDate>
				<category><![CDATA[Tutoriels]]></category>
		<category><![CDATA[Raspberry]]></category>
		<category><![CDATA[Lux]]></category>
		<category><![CDATA[Luminosité]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=4730</guid>

					<description><![CDATA[<p>Dans un précédent tutoriel, nous avons découvert comment créer un capteur de luminosité avec un ESP8266 connecté par Wifi. Ici je vous propose de créer un capteur extérieur piloté par un Raspberry Pi. Pour être exact, le Raspberry Pi sera</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/tutorials/un-capteur-de-luminosite-exterieur-pilote-par-raspberry/">Un capteur de luminosité extérieur piloté par un Raspberry avec un package Python</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Dans un précédent tutoriel, nous avons découvert comment créer un <a href="/tutorials/creer-un-capteur-de-temperature-humidite-et-luminosite-connecte/">capteur de luminosité avec un ESP8266</a> connecté par Wifi. Ici je vous propose de créer un capteur extérieur piloté par un Raspberry Pi.</p>
<p>Pour être exact, le Raspberry Pi sera installé en intérieur, connecté au réseau filaire Ethernet et relié par un câble à un boitier étanche installé sur le toit qui contiendra une photorésistance et/ou un capteur TSL2561.</p>
<p>Nous allons utiliser un <a href="/constellation-platform/constellation-sentinel/constellation-raspberry-pi/">Raspberry B+ version 1</a> sur lequel <a href="/getting-started/ajouter-des-sentinelles/">nous installerons une sentinelle</a> pour pouvoir déployer notre package depuis Visual Studio. Le package d’acquisition des données sera <a href="/getting-started/creez-votre-premier-package-constellation-en-python/">écrit en Python</a>.</p>
<h3>Prérequis</h3>
<ul>
<li>Un serveur Constellation</li>
<li>Un <a href="/constellation-platform/constellation-sentinel/constellation-raspberry-pi/">Raspberry Pi </a>sur lequel <a href="/getting-started/ajouter-des-sentinelles/">nous installerons une sentinelle</a></li>
<li>Une photorésistance avec un condensateur 1uF et/ou un capteur TSL2561</li>
<li>Visual Studio avec le SDK Constellation</li>
</ul>
<h3>Mesurer la luminosité ambiante avec une photorésistance</h3>
<h4>Le montage</h4>
<p>Tout d&rsquo;abord, il nous faut un boitier étanche avec un couvercle transparent (pour mesurer la luminosité c&rsquo;est mieux !) :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1160386-1.jpg"><img class="colorbox-4730"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Boite étanche" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1160386_thumb-1.jpg" alt="Boite étanche" width="379" height="243" border="0" /></a></p>
<p>Sur une plaque epoxy, soudons la photorésistance avec un condensateur 1uF.</p>
<p>Une des deux pattes de la photorésistance sera reliée sur la pin « 3v3 » du Raspberry et la deuxième sera reliée à une entrée du Raspberry, disons la pin n°12 (soit la GPIO #18). Toujours sur cette 2ème patte, on soudera le pole « + » du condensateur. L&rsquo;autre pole du condensateur, celle marquée « -« , devra être reliée à la masse, sur l&rsquo;une des pins « GND » du Raspberry.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1160398-1.jpg"><img class="colorbox-4730"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Photorésistance" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1160398_thumb-1.jpg" alt="Photorésistance" width="310" height="298" border="0" /></a></p>
<p>On a donc trois fils connectés entre le Raspberry et notre capteur : le 3V3 et la masse (Gnd) pour l&rsquo;alimentation et un pour le signal (GPIO #18). L&rsquo;idée est donc de « charger » le condensateur et de chronométrer le temps qu&rsquo;il mets à se décharger.</p>
<p>Plus il y a de lumière et moins la résistance est forte, autrement dit le condensateur se déchargera très rapidement. A l&rsquo;inverse, plus il fait sombre et plus la résistance sera forte. Autrement dit, moins il y a de lumière et moins vite se déchargera le condensateur.</p>
<p>On voit sur les photos ci-dessous, le fil Orange pour le 3V3, le fil Bleu pour la GPIO et le fil Blanc pour la masse (Gnd) :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1160424-1.jpg"><img class="colorbox-4730"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Installation dans le boitier" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1160424_thumb-1.jpg" alt="Installation dans le boitier" width="347" height="264" border="0" /></a><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1160435-1.jpg"><img class="colorbox-4730"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Installation dans le boitier" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1160435_thumb-1.jpg" alt="Installation dans le boitier" width="351" height="264" border="0" /></a></p>
<p>Il fois les connexions réalisées, on peut refermer proprement notre boitier en vérifiant soigneusement son étanchéité avant de l&rsquo;installer sur le toit.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1160450-1.jpg"><img class="colorbox-4730"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Installation sur le toit" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1160450_thumb-1.jpg" alt="Installation sur le toit" width="354" height="300" border="0" /></a></p>
<p>Côté intérieur, on relie les 3 fils de notre boitier au Raspberry (3v3, Gnd et GPIO18), le câble Ethernet et l&rsquo;alimentation MicroUSB.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1160442-1.jpg"><img class="colorbox-4730"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Raspberry Pi B" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1160442_thumb-1.jpg" alt="Raspberry Pi B" width="354" height="335" border="0" /></a></p>
<p style="text-align: left;" align="center">Pour l&rsquo;installation du <a href="/constellation-platform/constellation-sentinel/constellation-raspberry-pi/">système sur le Raspberry suivez ce guide</a> puis <a href="/getting-started/ajouter-des-sentinelles/">installez-y une sentinelle</a>. Votre Raspberry est prêt et connecté à Constellation, reste à développer notre package Python.</p>
<h4>Programmation</h4>
<p>Depuis Visual Studio, <a href="/getting-started/creez-votre-premier-package-constellation-en-python/">créons un nouveau projet</a> de type « Constellation Python Package » que nous nommerons “LightSensor”.</p>
<p align="center"><img loading="lazy" class="wp-image-1736 size-medium aligncenter colorbox-4730" src="https://developer.myconstellation.io/wp-content/uploads/2016/04/image_thumb-300x208.png" alt="" width="300" height="208" srcset="https://developer.myconstellation.io/wp-content/uploads/2016/04/image_thumb-300x208.png 300w, https://developer.myconstellation.io/wp-content/uploads/2016/04/image_thumb.png 424w" sizes="(max-width: 300px) 100vw, 300px" /></p>
<p>Renommez le fichier « Demo.py » en « Light.py » et remplacez l’intégralité du contenu par le code suivant :</p>
<p></p><pre class="crayon-plain-tag">import Constellation
import RPi.GPIO as GPIO, time, os      

MAX_READING = 30000
LIGHT_SENSOR_GPIO = 18
MEASURE_INTERVAL = 10

def OnExit():
    GPIO.cleanup()

def RCtime (RCpin):
    reading = 0
    GPIO.setup(RCpin, GPIO.OUT)
    GPIO.output(RCpin, GPIO.LOW)
    time.sleep(0.1) 
    GPIO.setup(RCpin, GPIO.IN)
    # This takes about 1 millisecond per loop cycle
    while (GPIO.input(RCpin) == GPIO.LOW):
        if (reading &gt; MAX_READING):
            break
        reading += 1
    return reading
 
def Start():
    global INTERVAL
    GPIO.setmode(GPIO.BCM)
    Constellation.OnExitCallback = OnExit
    lastSend = 0
    currentValue = 0
    count = 0
    Constellation.WriteInfo("LightSensor is ready !")
    while Constellation.IsRunning:
        currentValue = currentValue + RCtime(LIGHT_SENSOR_GPIO)
        count = count + 1
        ts = int(round(time.time()))
        if ts - lastSend &gt;= int(Constellation.GetSetting("Interval")):
            avg = int(round(currentValue / count))
            Constellation.PushStateObject("Light", avg, "int")
            currentValue = 0
            count = 0
            lastSend = ts
        time.sleep(MEASURE_INTERVAL)

Constellation.Start(Start)</pre><p></p>
<p>N’hésitez pas à <a href="/getting-started/creez-votre-premier-package-constellation-en-python/">relire le guide</a> sur la création de package Python pour bien comprendre les bases d&rsquo;un package Python.</p>
<p>Ici on démarre notre package par la méthode « Start » qui démarre une boucle pour appeler la méthode <em>RCtime</em> toutes les 10 secondes (variable MEASURE_INTERVAL).</p>
<p>La méthode <em>RCtime</em> charge le condensateur (mode output) puis passe l&rsquo;I/O en « input » et incrémente la variable « reading » en continue tant que le condensateur n&rsquo;est pas déchargé (input == « low »). Plus la valeur « reading » est élevée, plus le condensateur a mis du temps à se décharger et donc moins il y a de lumière. On a un garde-fou à « 30.000 » pour ne pas attendre indéfiniment dans le cas où il fait trop sombre.</p>
<p>Bien entendu on ne mesure pas une unité précise. Si vous déployez votre code sur un RPi V1 et V2 (plus puissant), vous n&rsquo;aurez pas la même valeur pour les mêmes conditions.</p>
<p>Chaque mesure incrémente la variable « currentValue », puis dès qu&rsquo;on atteint l&rsquo;intervalle configuré dans les Settings Constellation, on fait la moyenne des mesures on <a href="/getting-started/creez-votre-premier-package-constellation-en-python/#Publier_des_StateObjects">publie un StateObjec</a>t nommé « Light » de type « int ».</p>
<p>Dans le <a href="/concepts/package-manifest/">manifeste du package</a> (<em>PackageInfo.xml</em>), n&rsquo;oubliez pas de déclarer le setting « Interval » en lui spécifiant une valeur par défaut, ici de 10 seconde :</p>
<p></p><pre class="crayon-plain-tag">&lt;Settings&gt;
  &lt;Setting name="Interval" isRequired="false" type="Int32" defaultValue="10" description="Interval to read sensors in second" /&gt;
&lt;/Settings&gt;</pre><p></p>
<p>De même vous pouvez également modifier les informations de compatibilité des plateformes pour exclure la plateforme Windows dans la mesure où le package exploite les GPIO du Raspberry.</p>
<p></p><pre class="crayon-plain-tag">&lt;Platform id="Win32NT" isCompliant="false" /&gt;</pre><p></p>
<p>Et voilà le package est prêt, vous pouvez depuis Visual Studio le <a href="/getting-started/creez-votre-premier-package-constellation-en-python/#Publiez_votre_package">publier</a> dans votre Constellation :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-72.png"><img class="colorbox-4730"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Publication du projet" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-72.png" alt="Publication du projet" width="454" height="283" border="0" /></a></p>
<p>… puis <a href="/getting-started/creez-votre-premier-package-constellation-en-python/#Deployez_votre_package_sur_une_sentinelle">le déployer</a> sur votre sentinelle Raspberry depuis la Console Constellation, en cliquant sur le bouton “Deploy new package” :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-73.png"><img class="colorbox-4730"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Deploiement" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-73.png" alt="Deploiement" width="454" height="291" border="0" /></a></p>
<p>Dans l’assistant de déploiement vous pourrez alors personnaliser le setting “Interval” ou bien laisser la valeur par défaut que nous avons fixé à 10 (secondes) :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-74.png"><img class="colorbox-4730"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Settings" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-74.png" alt="Settings" width="454" height="248" border="0" /></a></p>
<p align="left">Sur la Console Log, le package va être téléchargé et déployé par votre sentinelle Raspberry avant de démarrer :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-75.png"><img class="colorbox-4730"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Console Log" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-75.png" alt="Console Log" width="454" height="252" border="0" /></a></p>
<p align="left">Et en vous rendant dans le StateObjects Explorer, vous verrez votre package “LightSensor” publier un StateObject “Light” avec un entier comme valeur :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-76.png"><img class="colorbox-4730"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="StateObjects Explorer" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-76.png" alt="StateObjects Explorer" width="454" height="160" border="0" /></a></p>
<p>Votre package Python est opérationnel, on peut dés à présent exploiter cette valeur dans une page Web, un script, un programme .NET ou Python, un Arduino, etc… comme nous le verrons dans la suite de cet article.</p>
<h3>Mesurer des lux avec un capteur TSL2561</h3>
<p>Pour obtenir une mesure plus fiable et surtout exploitant une échelle de mesure universelle, nous allons utiliser un capteur de luminosité TSL2561 capable de mesurer des Lux.</p>
<h4>Le montage</h4>
<p>Dans cette deuxième version, j&rsquo;ai conservé la photorésistance et simplement ajouté le capteur TSL2561. Celui-ci est également alimenté en 3V3, j&rsquo;ai donc réutilisé les deux fils (Orange et Blanc) de la photorésistance pour alimenter le capteur également.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1170883-1.jpg"><img class="colorbox-4730"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Ajout d'un capteur TSL2561" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1170883_thumb-1.jpg" alt="Ajout d'un capteur TSL2561" width="354" height="227" border="0" /></a></p>
<p style="text-align: left;" align="center">Le TSL2561 utilise l&rsquo;I²C, j&rsquo;ai donc ajouté deux fils entre le boitier étanche et le Raspberry pour connecter le capteur en i²C (SDA et SCL).</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1170888-1.jpg"><img class="colorbox-4730"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Ajout d'un capteur TSL2561" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1170888_thumb-1.jpg" alt="Ajout d'un capteur TSL2561" width="354" height="201" border="0" /></a></p>
<p style="text-align: left;" align="center">Sur le Raspberry, le SDA est la GPIO#2 et le SCL la GPIO #3, c&rsquo;est à dire juste en dessus de la pin 3v3.</p>
<h4>La programmation</h4>
<p>Le plus simple et le plus fiable pour récupérer les données du capteur TSL2561 depuis un Raspberry est d&rsquo;utiliser un programme natif. Pour cela nous allons utiliser le code publié à cette adresse : <a title="http://dino.ciuffetti.info/2014/03/tsl2561-light-sensor-on-raspberry-pi-in-c/" href="http://dino.ciuffetti.info/2014/03/tsl2561-light-sensor-on-raspberry-pi-in-c/">http://dino.ciuffetti.info/2014/03/tsl2561-light-sensor-on-raspberry-pi-in-c/</a>.</p>
<p>Il suffit récupérer les 3 fichiers C et de les compiler avec GCC pour générer le binaire. Pour vous simplifier la tache, vous pouvez directement récupérer le binaire <a href="https://developer.myconstellation.io/download/resources/tutorials/GetTSL2561">GetTSL2561 ici</a>.</p>
<p>Ajoutez ensuite un deuxième script nommé « Lux.py » dans le répertoire « Scripts » de votre projet et <strong>n&rsquo;oubliez pas</strong> d&rsquo;inclure votre script dans le package en définissant la Build Action à « Content » et en activant la copie du fichier dans le répertoire de sortie :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-77.png"><img class="colorbox-4730"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Inclure les scripts Python dans le package" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-77.png" alt="Inclure les scripts Python dans le package" width="254" height="339" border="0" /></a></p>
<p>Copiez également le binaire <a href="https://developer.myconstellation.io/download/resources/tutorials/GetTSL2561">GetTSL2561</a> dans le répertoire « Scripts » de votre package en l&rsquo;incluant également dans le package (Build Action à Content et Copy if newer).</p>
<p>Le contenu du script « Lux.py » sera :</p>
<p></p><pre class="crayon-plain-tag">import Constellation
import os, re, subprocess, time, stat

# Const
EXECUTABLE_FILENAME = "GetTSL2561"

def DoMeasure():
    # Start process
    process = subprocess.Popen("./" + EXECUTABLE_FILENAME, stdout=subprocess.PIPE)
    # Reading  output
    for line in iter(process.stdout.readline, ''):
        # Parse line
        matchObj = re.match('RC: (\d*)\((.*)\), broadband: (\d*), ir: (\d*), lux: (\d*)', line)
        if matchObj:
            # Reading value
            returnCode = int(matchObj.group(1))
            broadband = int(matchObj.group(3))
            ir = int(matchObj.group(4))
            lux = int(matchObj.group(5))
            # Push StateObject
            if returnCode != 0:
                Constellation.WriteWarn("Unknow return code %s : %s" % (returnCode, line))
            else:
                Constellation.PushStateObject("Lux", { "Broadband": broadband, "IR" : ir, "Lux" : lux }, "LightSensor.Lux")
        else:
            Constellation.WriteError("Unable to parse the output: %s" % line)

def Start():    
    # Make the "GetTSL2561" file as executable
    st = os.stat(EXECUTABLE_FILENAME)
    os.chmod(EXECUTABLE_FILENAME, st.st_mode | stat.S_IEXEC)
    Constellation.WriteInfo("LuxSensor is ready !")
    while Constellation.IsRunning:  
        DoMeasure()
        time.sleep(int(Constellation.GetSetting("Interval")))

Constellation.Start(Start)</pre><p></p>
<p>Comme pour le script « Light.py », on déclare la méthode « <em>Start</em> » comme méthode de démarrage. Celle-ci boucle tant que le package est démarré à l&rsquo;intervalle défini par le setting « Interval » qu&rsquo;on a déclaré à 10 secondes par défaut dans le manifeste.</p>
<p>A chaque itération, on invoque la méthode « <em>DoMeasure</em> » qui démarre le programme « <em>GetTSL2561</em> » et on parse avec une regex le résultat de la sortie du programme (<em>process.stdout</em>) pour extraire le code de retour, le broadband (spectre visible), l&rsquo;infrarouge et le nombre de lux courant mesuré par le capteur.</p>
<p>Si le code de retour est égal à 0 c&rsquo;est que la mesure est correcte, on publie alors un StateObject nommé « Lux » contenant les trois propriétés mesurées : Broadband, IR et Lux.</p>
<p></p><pre class="crayon-plain-tag">Constellation.PushStateObject("Lux", { "Broadband": broadband, "IR" : ir, "Lux" : lux }, "LightSensor.Lux")</pre><p></p>
<p>Attention avant de déployer cette nouvelle version<strong> il faut activer l&rsquo;I²C sur le Raspberry</strong>. Pour cela lancer la commande « <em>sudo raspi-config</em> » puis dans le menu « <em>Advanced Options</em> » activez l&rsquo;I²C et chargez le module par défaut au démarrage.</p>
<p>On peut maintenant publier cette nouvelle version depuis Visual Studio et lancer un « Reload » sur notre package pour déployer cette nouvelle version sur notre Rapsberry.</p>
<p>Désormais nous avons deux StateObjects publiés par ce package : « <em>Light</em> » via la photorésistance et « <em>Lux</em> » via le TSL2561 :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-78.png"><img class="colorbox-4730"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="StateObjects Explorer" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-78.png" alt="StateObjects Explorer" width="454" height="133" border="0" /></a></p>
<p>Notre nouveau StateObject « Lux » est un objet complexe contenant trois propriétés :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-79.png"><img class="colorbox-4730"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Detail du StateObject Lux" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-79.png" alt="Detail du StateObject Lux" width="454" height="330" border="0" /></a></p>
<h3>Exploitez les données</h3>
<p>Notre package Python vit sa vie sur notre Raspberry et publie à intervalle régulier deux StateObjects sur base des mesures réalisées par la photorésistance et/ou le capteur de lux TSL2561.</p>
<p>On peut maintenant écrire des pages Web, des scripts, des packages .NET ou Python, Arduino, etc… qui exploiteront ces mesures en temps réel.</p>
<h4>Un dashboard Web</h4>
<p>Depuis <a href="/getting-started/connectez-vos-pages-web-constellation/">une page Web</a>, il suffit d&rsquo;ajouter un <a href="/client-api/javascript-api/consommer-constellation-angular-js/">StateObjectLink</a>. Vous pouvez vous inspirer <a href="/tutorials/creer-un-capteur-de-temperature-humidite-et-luminosite-connecte/#Etape_3_Une_page_Web_pour_afficher_votre_capteur_en_temps_reel">de ce tutoriel</a> par exemple.</p>
<p></p><pre class="crayon-plain-tag">constellation.registerStateObjectLink("*", "LightSensor", "Lux", "*", function (so) {
  $scope.$apply(function () {
    console.log("Lux = ", so.Value.Lux);
  });
});</pre><p></p>
<p>Par exemple sur le <a href="https://sebastien.warin.fr/2015/07/15/3033-s-panel-une-interface-domotique-et-iot-multi-plateforme-avec-cordova-angularjs-et-constellation-ou-comment-crer-son-dashboard-domotique-mural/" target="_blank" rel="noopener noreferrer">projet S-Panel</a> avec quelques composants Bootstrap :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-80.png"><img class="colorbox-4730"  loading="lazy" title="S-Panel" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-80.png" alt="S-Panel" width="244" height="131" border="0" /></a></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-81.png"><img class="colorbox-4730"  loading="lazy" title="S-Panel" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-81.png" alt="S-Panel" width="354" height="210" border="0" /></a></p>
<h4>Un programme .NET</h4>
<p>Vous pouvez là aussi vous inspirer <a href="/tutorials/creer-un-capteur-de-temperature-humidite-et-luminosite-connecte/#Etape_4_optionnelle_creer_un_package_NET_pour_exploiter_les_donnees_du_capteur">de ce tutoriel</a>. En clair, il suffit dans votre code C# d&rsquo;ajouter des <a href="/client-api/net-package-api/consommer-des-stateobjects/">StateObjectLinks </a>avec l&rsquo;API.NET :</p>
<p></p><pre class="crayon-plain-tag">[StateObjectLink("LightSensor", "Lux")]
public StateObjectNotifier Lux { get; set; }</pre><p></p>
<p>Ainsi la propriété .NET nommée « Lux » ci-dessus sera liée en temps réel au StateObject « Lux » du package « LigthSensor ».</p>
<p>Vous pouvez ajouter des événements dès que la valeur change :</p>
<p></p><pre class="crayon-plain-tag">this.Lux.ValueChanged += (s, e) =&gt;
{
    PackageHost.WriteInfo($"Nouvelle mesure à {this.Lux.Value.LastUpdate} = {this.Lux.DynamicValue.Lux} lux");
};</pre><p></p>
<p><img loading="lazy" class="alignnone size-medium wp-image-4596 aligncenter colorbox-4730" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-57-300x153.png" alt="" width="300" height="153" srcset="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-57-300x153.png 300w, https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-57.png 404w" sizes="(max-width: 300px) 100vw, 300px" /></p>
<p>Vous pouvez ainsi faire ce que bon vous semble avec cette information. Par exemple allumer automatiquement les lumières si la luminosité est trop faible, fermer les volets, enregistrer la valeur des Lux dans un fichier Excel ou une base de données, etc.. etc..</p>
<h4>Historisation avec ElasticSearch / Kibana</h4>
<p>En utilisant le package <a href="/package-library/graylogconnector">Graylog </a>du <a href="/plateforme/package-repository/">catalogue de package</a>, on peut historiser les mesures de notre capteur dans une base ElasticSearch.</p>
<p>Dans la configuration du package Graylog, on aura quelque chose comme :</p>
<p></p><pre class="crayon-plain-tag">&lt;graylogConfiguration xmlns="urn:GraylogConnector" sendPackageLogs="false" sendPackageStates="true" sendSentinelUpdates="true"&gt;
    &lt;subscriptions&gt;
        &lt;subscription package="LightSensor" name="Lux" /&gt;
        &lt;!-- ..... --&gt;
    &lt;/subscriptions&gt;
    &lt;outputs&gt;
        &lt;gelfOutput name="Graylog server UDP" host="graylog.ajsinfo.loc" port="12201" protocol="Udp" /&gt;
    &lt;/outputs&gt;
&lt;/graylogConfiguration&gt;</pre><p></p>
<p>La documentation du package <a href="/package-library/graylogconnector">Graylog</a> est disponible <a href="/package-library/graylogconnector">ici</a>. En résumé on crée ici un abonnement pour la StateObject « Lux » du package « LightSensor » et dans les « outputs » on a déclaré notre serveur Graylog.</p>
<p>De ce fait dès que le StateObject « Lux » est mis à jour par notre package Python, le package Graylog enregistre la nouvelle version du StateObject sur le serveur Graylog qui lui-même utilise ElasticSearch comme base de stockage.</p>
<p>Ainsi on pourra utiliser un outil comme Kibana pour visualiser l&rsquo;évolution de notre StateObject :</p>
<p><img loading="lazy" class="aligncenter colorbox-4730" title="Kibana" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-83.png" alt="Kibana" width="454" height="304" border="0" /></p>
<p>Un article complet sur le sujet <a href="https://sebastien.warin.fr/2015/10/09/3180-creez-votre-home-analytics-analyse-et-reporting-de-votre-domotique-informatique-et-objets-connectes-avec-elasticsearch-graylog-kibana-constellation/" target="_blank" rel="noopener noreferrer">a été publié ici</a>.</p>
<h4>Stats avec Cacti</h4>
<p>On peut également écrire un script pour récupérer notre StateObject « Lux » depuis l&rsquo;<a href="/client-api/rest-api/interface-rest-consumer/">interface REST</a> qu&rsquo;on ajoutera en tant que « <em>Data Input Methods</em> » dans Cacti pour pouvoir créer des graphiques facilement :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-82.png"><img class="colorbox-4730"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Cacti" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-82.png" alt="Cacti" width="454" height="358" border="0" /></a></p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/tutorials/un-capteur-de-luminosite-exterieur-pilote-par-raspberry/">Un capteur de luminosité extérieur piloté par un Raspberry avec un package Python</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://developer.myconstellation.io/tutorials/un-capteur-de-luminosite-exterieur-pilote-par-raspberry/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Pilotez une matrice de LED avec une page Web en temps réel</title>
		<link>https://developer.myconstellation.io/tutorials/pilotez-une-matrice-de-led-avec-une-page-web/</link>
					<comments>https://developer.myconstellation.io/tutorials/pilotez-une-matrice-de-led-avec-une-page-web/#respond</comments>
		
		<dc:creator><![CDATA[Sebastien Warin]]></dc:creator>
		<pubDate>Tue, 09 May 2017 12:48:57 +0000</pubDate>
				<category><![CDATA[Tutoriels]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[ESP8266]]></category>
		<category><![CDATA[LED]]></category>
		<category><![CDATA[Matrix]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Canvas]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=4532</guid>

					<description><![CDATA[<p>Découvrons dans ce tutoriel comment piloter en temps réel une matrice de LED bicolore depuis une page Web en quelque ligne. Pour cela nous allons utiliser une matrice de 8&#215;8 LEDs pilotable en I²C que vous pouvez trouver chez Adafruit</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/tutorials/pilotez-une-matrice-de-led-avec-une-page-web/">Pilotez une matrice de LED avec une page Web en temps réel</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Découvrons dans ce tutoriel comment piloter en temps réel une matrice de LED bicolore depuis une page Web en quelque ligne.</p>
<p align="center"><img class="colorbox-4532"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="ESP Matrix Controller" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/ESPMatrix2-gap.jpg" data-gif="https://developer.myconstellation.io/wp-content/uploads/2017/05/ESPMatrix2.gif" alt="ESP Matrix Controller" width="400" height="225" border="0" /></p>
<p>Pour cela nous allons utiliser une matrice de 8&#215;8 LEDs pilotable en I²C que vous pouvez trouver <a href="https://www.adafruit.com/product/902">chez Adafruit</a> pour environ 15€. Pour piloter cette matrice nous allons utiliser un ESP8266, ici un <a href="https://www.wemos.cc/product/d1-mini-pro.html">D1 Mini Pro</a> (environ 6€).</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1040128.jpg"><img class="colorbox-4532"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="ESP Matrix Controller" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1040128_thumb.jpg" alt="ESP Matrix Controller" width="404" height="304" border="0" /></a></p>
<h3 align="left">Prérequis</h3>
<p align="left">Pour réaliser ce tutoriel, vous aurez besoin :</p>
<ul>
<li>
<div align="left">Un serveur Constellation</div>
</li>
<li>
<div align="left">Un ESP8266</div>
</li>
<li>
<div align="left">Une matrice de LED I²C</div>
</li>
</ul>
<p align="left">Si c’est la première fois que vous utilisez un ESP8266 connecté à Constellation, je vous recommande <a href="/getting-started/connecter-un-arduino-ou-un-esp8266-constellation/">de suivre ce guide d’introduction</a> avant de commencer !</p>
<h3 align="left">Etape 1 : connecter la matrice de LED</h3>
<p align="left">Nous avons ici utilisé un D1 Mini Pro, un ESP8266 intégrant nativement une interface de programmation USB, très pratique pour créer des prototypes rapides.</p>
<p align="left">La matrice de LED se connecte à l’ESP8266 en I²C. Nous avons utilisé les fils Noir et Blanc pour alimenter la matrice depuis les pins “5V” et “GND” du D1 Mini ainsi que les fils Bleu et Vert pour connecter les ports D1 et D2 du D1 Mini aux ports SCL et SDA de la matrice de LED :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1040132.jpg"><img class="colorbox-4532"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="D1 Mini avec un 8x8 LED Matrix" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1040132_thumb.jpg" alt="D1 Mini avec un 8x8 LED Matrix" width="354" height="266" border="0" /></a></p>
<p align="left">Et voilà le montage est déjà fini ! Vous pouvez maintenant connecter votre D1 Mini en USB à votre PC pour le programmer.</p>
<h3 align="left">Etape 2 : programmer l’ESP8266</h3>
<p align="left">Pour démarrer vous devez dans Constellation déclarer une sentinelle associée à une clé d&rsquo;accès et un package virtuel. Ici notre ESP8266 est représenté par la sentinelle nommée « ESP8266 » et le package virtuel se nomme « MatrixController ».</p>
<p align="left">Dans l&rsquo;Arduino IDE, nous créons un nouveau projet à partir du Starter Kit Constellation pour ESP8266 dans lequel nous allons définir le nom de notre réseau Wifi (SSID) ainsi que sa clé d&rsquo;accès  puis nous configurerons le client Constellation en spécifiant l&rsquo;identité de notre package virtuel, sa clé d&rsquo;accès et l&rsquo;adresse/port de notre serveur Constellation :</p>
<p></p><pre class="crayon-plain-tag">// ESP8266 Wifi
#include &lt;ESP8266WiFi.h&gt;
char ssid[] = "MON SSID";
char password[] = "macléWifi!!!!";

// Constellation client
Constellation&lt;WiFiClient&gt; constellation("X.X.X.X", 8088, "ESP8266", "MatrixController", "xxxxxxxxxxxxxxxxx");</pre><p></p>
<p align="left">Encore une fois si tout cela est nouveau pour vous, je vous recommande <a href="/getting-started/connecter-un-arduino-ou-un-esp8266-constellation/">de suivre ce guide d’introduction à l&rsquo;API Constellation pour Arduino/ESP8266</a>.</p>
<p align="left">Maintenant que la coquille de notre package virtuel sur ESP8266 est prête, ajoutons les librairies d&rsquo;Adafruit pour piloter la matrice de LED bicolore.</p>
<p align="left">Dans le gestionnaire de bibliothèque (menu<em> Croquis &gt; Inclure une bibliothèque</em>), installez les librairies suivantes :</p>
<ul>
<li>Adafruit GFX</li>
<li>Adafruit LED Backpack</li>
</ul>
<p>Puis dans votre code, ajoutez ces librairies et déclarez une variable de type « Adafruit_BicolorMatrix » que nous nommerons « matrix » :</p>
<p></p><pre class="crayon-plain-tag">#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"
#include &lt;Wire.h&gt;
Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();</pre><p></p>
<p align="left">Au démarrage, dans la méthode « setup() », initialisez la matrice de LED. Pour rappel nous avons branché la matrice I²C sur les ports D1 et D2 :</p>
<p></p><pre class="crayon-plain-tag">// Init matrix led
Wire.begin(D1, D2);
matrix.begin(0x70);</pre><p></p>
<p align="left">Toujours dans la méthode d&rsquo;initialisation, enregistrons un premier MessageCallback que nous allons nommer « SetPixel ». Ce MessageCallback permettra d&rsquo;allumer ou éteindre un pixel de la matrice.</p>
<p align="left">Nous le déclarons avec 4 paramètres d&rsquo;entrée :</p>
<ul>
<li>x et y pour définir la position du pixel à piloter</li>
<li>state : un boolean indiquant si le pixel doit être allumé ou éteint</li>
<li>clear: un paramètre optionnel de type boolean pour indiquer si il faut effacer la matrice avant (par défaut « true »)</li>
</ul>
<p>Comme vous le constatez ci-dessous, le code de ce MessageCallback commence par effacer la matrice si le dernière paramètre (<em>clear</em>) n&rsquo;est pas défini (car optionnel) ou si il est à « <em>true</em> » en invoquant la méthode « <em>matrix.clear()</em>« .</p>
<p>Ensuite on appelle la méthode « <em>drawPixel</em> » en passant les arguments de notre MC, à savoir le « x », le « y » et le « state ».</p>
<p>Si le paramètre « <em>state</em> » est vrai, on allume le pixel en vert (LED_GREEN) sinon on l&rsquo;éteint (LED_OFF).</p>
<p>Le code est donc :</p>
<p></p><pre class="crayon-plain-tag">// Register SetPixel
constellation.registerMessageCallback("SetPixel",
  MessageCallbackDescriptor().setDescription("Set Pixel On or Off").addParameter&lt;int&gt;("x").addParameter&lt;int&gt;("y").addParameter&lt;bool&gt;("state", "ON or OFF").addOptionalParameter&lt;bool&gt;("clear", true, "Clear matrix before drawn"),
  [](JsonObject&amp; json) {
    if(json["Data"].size() &lt; 4 || json["Data"][3].as&lt;bool&gt;()) {
      matrix.clear();
    }
    matrix.drawPixel(json["Data"][0].as&lt;int&gt;(), json["Data"][1].as&lt;int&gt;(), json["Data"][2].as&lt;bool&gt;() ? LED_GREEN : LED_OFF);  
    matrix.writeDisplay();
 });</pre><p></p>
<p align="left">Comme il s&rsquo;agit d&rsquo;une matrice bicolore, on peut allumer chaque pixel en vert ou en rouge, ou bien en vert ET en rouge ce qui donne du orange.</p>
<p align="left">Nous allons donc ajouter un deuxième MessageCallback que nous nommerons « SetPixelColor » sensiblement identique au premier, sauf que le paramètre « state » est maintenant de type  « int » et se nomme « color ».</p>
<p align="left">D&rsquo;après les constantes de la librairie d&rsquo;Adafruit, LED_GREEN = 2, LED_OFF = 0, le rouge (LED_RED) = 1 et le Orange/Jaune = 2. Le code est donc :</p>
<p></p><pre class="crayon-plain-tag">// Register SetPixelColor
constellation.registerMessageCallback("SetPixelColor",
  MessageCallbackDescriptor().setDescription("Set Pixel On or Off").addParameter&lt;int&gt;("x").addParameter&lt;int&gt;("y").addParameter&lt;int&gt;("color", "0 = Off, 1 = red, 2 = orange, 3 = green").addOptionalParameter&lt;bool&gt;("clear", true, "Clear matrix before drawn"),
  [](JsonObject&amp; json) {
    if(json["Data"].size() &lt; 4 || json["Data"][3].as&lt;bool&gt;()) {
      matrix.clear();
    }
    matrix.drawPixel(json["Data"][0].as&lt;int&gt;(), json["Data"][1].as&lt;int&gt;(), json["Data"][2].as&lt;int&gt;());  
    matrix.writeDisplay();
 });</pre><p></p>
<p align="left">Pour finir, ajoutons un troisième et dernier MessageCallback pour effacer l&rsquo;écran :</p>
<p></p><pre class="crayon-plain-tag">// Register Clear
constellation.registerMessageCallback("Clear",
  MessageCallbackDescriptor().setDescription("Clear matrix"),
  [](JsonObject&amp; json) {
    matrix.clear();
    matrix.writeDisplay();
 });</pre><p></p>
<p align="left">Vous pouvez téléverser le programme puis en vous connectant sur le <a href="/constellation-platform/constellation-console/messagecallbacks-explorer/">MessageCallbacks Explorer</a> de la Console Constellation vous constaterez que les trois MessageCallbacks sont bien référencés dans votre Constellation.</p>
<p align="left">Votre ESP8266 est prêt ! Vous pouvez tester les MC directement depuis la Console pour vous assurer que tout fonctionne correctement :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-48.png"><img class="colorbox-4532"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="MessageCallbacks Explorer" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-48.png" alt="MessageCallbacks Explorer" width="404" height="284" border="0" /></a></p>
<p style="text-align: left;" align="center">Par exemple en invoquant le MessageCallback « SetPixel » avec<em> x=1</em>,<em> y=2</em> et <em>state=true</em>, le résultat est instantanément visible sur la matrice :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1040131-1.jpg"><img class="colorbox-4532"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Test du package virtuel" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/P1040131_thumb-1.jpg" alt="Test du package virtuel" width="404" height="304" border="0" /></a></p>
<h3 align="left">Etape 3 : créer une page Web</h3>
<p align="left">Maintenant que notre matrice connectée est prête, créons une page Web pour pouvoir la piloter.</p>
<p align="left">Pour cela nous allons créer une grille de 8&#215;8 représentant la matrice sur laquelle nous pourrions dessiner à la sourie ou au droit (touch) avec la possibilité de choisir la couleur entre le verte, le roue et le orange. Nous allons utiliser le Canvas HTML5 pour cela.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-49.png"><img class="colorbox-4532"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Page de contrôle en HTML5/JS" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image_thumb-49.png" alt="Page de contrôle en HTML5/JS" width="204" height="278" border="0" /></a></p>
<p align="left">Inutile d&rsquo;utiliser le framework AngularJS pour cela, nous utiliserons la librairie Constellation pour Javascript.</p>
<p align="left">Commençons donc par créer une page HTML classique dans laquelle ajoutons dans l’entête <em>&lt;head&gt;</em> les scripts nécessaires pour <a href="/getting-started/connectez-vos-pages-web-constellation/">connecter la page à Constellation</a> :</p>
<p></p><pre class="crayon-plain-tag">&lt;meta name="viewport" content="width=device-width" /&gt;
&lt;script type="text/javascript" src="https://code.jquery.com/jquery-2.2.4.min.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/signalr/jquery.signalr-2.2.1.min.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="https://cdn.myconstellation.io/js/Constellation-1.8.1.min.js"&gt;&lt;/script&gt;</pre><p></p>
<p>Nous avons également ajouté la meta « viewport » pour adapter proprement notre page sur un mobile.</p>
<p>Dans le corps <em>&lt;body&gt;</em> de notre page ajoutons un canvas pour la grille, la liste des couleurs possibles et un bouton pour effacer l&rsquo;écran :</p>
<p></p><pre class="crayon-plain-tag">&lt;canvas id="canvas" width="400" height="400"&gt;&lt;/canvas&gt;

&lt;ul id="colors"&gt;
    &lt;li&gt;&lt;a href="#" data-colorId="0" data-color="white"&gt;Eraser&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="#" data-colorId="1" data-color="red" class="selected"&gt;Rouge&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="#" data-colorId="2" data-color="orange"&gt;Orange&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="#" data-colorId="3" data-color="green"&gt;Vert&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;button id="clear"&gt;Clear&lt;/button&gt;</pre><p></p>
<p>Vous remarquerez que nous stockons dans des attributs « data- » l&rsquo;ID de la couleur de la matrice de LED (0 à 3) et le nom de la couleur HTML équivalente (ex. red = 1). La couleur sélectionnée est repérée par la classe CSS « selected ».</p>
<p>Pour la mise en page justement, ajoutez le code CSS dans une balise <em>&lt;style&gt;</em> dans la page :</p>
<p></p><pre class="crayon-plain-tag">body {
    text-align:center; 
    background:#e9e9e9
}        
#canvas {
    margin:0 auto 20px auto; 
    display:block; 
    background:#fff; 
    cursor:crosshair
}
#colors {
    list-style:none; 
    margin:0 0 20px 0;
    padding:0
}
#colors li {
    display:inline-block
}
#colors a {
    display:inline-block; 
    width:50px; 
    height:50px; 
    margin-right:10px; 
    text-indent:-4000px; 
    overflow:hidden; 
    border-radius:50%
}
#colors a.selected {
    border:2px solid #000; 
    width:45px; 
    height:45px
}
button {
  border-radius: 8px;
  padding: 10px 20px 10px 20px;
  color: #ffffff;
  font-size: 20px;
  background: #808080;
}</pre><p></p>
<p>Enfin, passons au code Javascript de notre page. Ouvrez une balise &lt;script&gt; pour ajouter le code ci-dessous.</p>
<p>On commence tout d&rsquo;abord par déclarer la taille de notre matrice (8&#215;8) ainsi que le client « consumer » de Constellation en spécifiant l&rsquo;adresse/port de votre serveur Constellation ainsi qu&rsquo;une clé d&rsquo;accès pour pouvoir s&rsquo;y connecter.</p>
<p>Ensuite on déclare les variables globales de notre script.</p>
<p></p><pre class="crayon-plain-tag">// Config
var matrixWidth = 8, matrixHeight = 8;
var constellation = $.signalR.createConstellationConsumer("http://x.x.x.x:8088/", "xxxxxxxxxxxxxx", "WebMatrixController"); 

// Global variables
var pixels = [];
var selectedColor = {};
var mouseDown = false;
var canvas, context;
var boxWidth, boxHeight;</pre><p></p>
<p>On ajoute une fonction « initBoard » pour dessiner notre grille dans le canvas HTML et initialiser le tableau « pixels » qui contiendra l&rsquo;état de la matrice :</p>
<p></p><pre class="crayon-plain-tag">function initBoard() {
    // Init the pixels array
    pixels = [];
    for (var x = 0; x &lt;= matrixWidth; x++) {
        pixels[x] = [];
        for (var y = 0; y &lt;= matrixHeight; y++) {
            pixels[x][y] = 0;
        }
    }
    // Create the vertical lines
    for (var x = 0; x &lt;= matrixWidth; x++) {
        context.moveTo(1 + x * boxWidth, 0);
        context.lineTo(1 + x * boxWidth, canvas.height());
    }
    // Create the horizontal lines
    for (var x = 0; x &lt;= matrixHeight; x++) {
        context.moveTo(0, 1 + x * boxHeight);
        context.lineTo(canvas.width(), 1 + x * boxHeight);
    }
    // Draw lines
    context.lineWidth=1;
    context.strokeStyle = "black";
    context.stroke();
}</pre><p></p>
<p>On déclare ensuite une fonction « setPixel » qui se chargera à la fois de dessiner dans le canvas la couleur sélectionnée du pixel mais également d&rsquo;envoyer un message à notre ESP8266 pour invoquer le MessageCallback « SetPixelColor » en spécifiant la position du pixel et la couleur sélectionnée. Le tableau « pixel » permet de n&rsquo;envoyer le message que si la couleur a changé pour éviter d’envoyer plusieurs fois le même ordre.</p>
<p></p><pre class="crayon-plain-tag">function setPixel(x, y) {
    if(pixels[x][y] != selectedColor.color) {
        // Save pixel
        pixels[x][y] = selectedColor.color;
        // Draw on canvas
        context.fillStyle=selectedColor.color;
        context.fillRect(2 + boxWidth * x, 2 +  boxHeight * y, boxWidth - 2, boxHeight - 2);
        // SetPixelColor on ESP8266
        constellation.server.sendMessage({ Scope: 'Package', Args: ['MatrixDesign'] }, 'SetPixelColor', [ x, y, selectedColor.id ]);  
    }
}</pre><p></p>
<p>Pour l’interaction nous ajoutons trois méthodes :</p>
<ul>
<li>moveStart : lorsque la sourie/le doigt (si touch) est posé sur la grille</li>
<li>move : lorsque la sourie/le doigt (si touch) se déplace sur la grille</li>
<li>moveEnd : lorsque la sourie/le doigt (si touch) « quitte » la grille</li>
</ul>
<p>Dans les deux premières méthodes l&rsquo;idée est de déduire la position du pixel en fonction des arguments de l&rsquo;événement levé afin d&rsquo;invoquer la méthode « setPixel » que nous avons déclarée ci-dessus qui se chargera à son tour de dessiner la bonne couleur dans le canvas tout envoyant le message à notre ESP8266.</p>
<p></p><pre class="crayon-plain-tag">function moveStart(e, mobile, obj) {
    mouseDown = true;
    // Determine the pixel coordinates
    var event = mobile ? e.originalEvent : e;
    var x = Math.trunc((event.pageX - obj.offsetLeft) / boxWidth);
    var y = Math.trunc((event.pageY - obj.offsetTop) / boxHeight);
    // Block mobile event
    if (mobile) {
        e.preventDefault();
    }        
    // Set pixel
    setPixel(x, y);
}

function move(e, mobile, obj) {
    if (mouseDown) {
        // Determine the pixel coordinates
        var pageX = mobile ? e.originalEvent.targetTouches[0].pageX : e.pageX;
        var pageY = mobile ? e.originalEvent.targetTouches[0].pageY : e.pageY;
        var x = Math.trunc((pageX - obj.offsetLeft) / boxWidth);
        var y = Math.trunc((pageY - obj.offsetTop) / boxHeight);
        // Block mobile event                
        if (mobile) {
            e.preventDefault();
        }     
        // Set pixel
        setPixel(x, y);
    }
}

function moveEnd() {
    mouseDown = false;
}</pre><p></p>
<p>Il ne reste plus qu&rsquo;à écrire le code de démarrage de notre page.</p>
<p>On commence par initialiser nos variables globales (instance et taille du canvas, contexte de rendu 2D du canvas). On initialise ensuite la grille par notre méthode « <em>iniBoard</em> » et on se connecte à notre Constellation (<em>constellation.connection.start()</em>).</p>
<p>Pour chaque couleur de notre liste, on affecte la couleur du background définie par son attribut <em>data-color</em> et on ajoute un handler au click de façon à récupéré dans l&rsquo;objet « selectedColor » la couleur sélectionnée par l&rsquo;utilisateur.</p>
<p>On affecte également un handler au click du bouton « Clear » pour effacer le Canvas et invoquer le MessageCallback « <em>clear</em> » sur notre ESP8266 afin de vider la matrice.</p>
<p>Et pour finir on attache des handlers aux événements de la souris (<em>mouseDown</em>, <em>mouseMove</em> et <em>mouseUp</em>) et du tactile (<em>touchStart</em>, <em>touchMove</em> et <em>touchEnd</em>) sur nos tris méthodes ci-dessus pour gérer les interactions avec notre grille.</p>
<p></p><pre class="crayon-plain-tag">// On page load
$(document).ready(function() {
    // Variables
    canvas = $("#canvas");
    context = canvas[0].getContext('2d');
    boxWidth = (canvas.width() - 2) / matrixWidth;
    boxHeight = (canvas.height() - 2) / matrixHeight;
    // Init board
    initBoard();            
    // Constellation connection
    constellation.connection.stateChanged(function (change) {
        if (change.newState === $.signalR.connectionState.connected) {
            console.log("Je suis connecté !");
        }
    });                
    constellation.connection.start();            
    // For each color buttons
    $("#colors a").each(function() {
        // Set background color
        $(this).css("background", $(this).attr("data-color"));
        // Attach handler on click
        $(this).click(function() {
            // Load the selected color
            selectedColor.id = $(this).attr("data-colorId");
            selectedColor.color = $(this).attr("data-color");
            // Set the selected class
            $("#colors a").removeAttr("class", "");
            $(this).attr("class", "selected");
            return false;                    
        });
        // Load the selected color
        if( $(this).attr("class") == "selected") {
            selectedColor.id = $(this).attr("data-colorId");
            selectedColor.color = $(this).attr("data-color");
        }
    });            
    // Clear button
     $("#clear").click(function() {
        // Clear the matrix
        constellation.server.sendMessage({ Scope: 'Package', Args: ['MatrixDesign'] }, 'Clear', {});
        // Clear the canvas
        var s = document.getElementById ("canvas");
        var w = s.width;    
        s.width = 10;
        s.width = w;
        // Redraw the board
        initBoard();                
     });             
     // Attach Touch events
    canvas.bind('touchstart', function(e) { moveStart(e, true, this); });
    canvas.bind('touchmove', function(e) { move(e, true, this); });
    $(this).bind('touchend', function() { moveEnd(); });
    // Attach Mouse events
    canvas.mousedown(function(e) {  moveStart(e, false, this); });
    canvas.mousemove(function(e) { move(e, false, this); });
    $(this).mouseup(function() { moveEnd(); });
});</pre><p></p>
<p>Et voilà notre page HTML est prête ! Lancez-la dans notre navigateur et profitez du résultat.</p>
<h3 align="left">Demos</h3>
<p>Quelques démonstrations animées &#8230;.</p>
<p align="center"><img class="colorbox-4532"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="ESP Matrix Controller" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/ESPMatrix1-gap.jpg" data-gif="https://developer.myconstellation.io/wp-content/uploads/2017/05/ESPMatrix1.gif" alt="ESP Matrix Controller" width="400" height="225" border="0" /></p>
<p align="center"><img class="colorbox-4532"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="ESPMatrix3" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/ESPMatrix3-gap.jpg" data-gif="https://developer.myconstellation.io/wp-content/uploads/2017/05/ESPMatrix3.gif" alt="ESPMatrix3" width="400" height="225" border="0" /></p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/tutorials/pilotez-une-matrice-de-led-avec-une-page-web/">Pilotez une matrice de LED avec une page Web en temps réel</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://developer.myconstellation.io/tutorials/pilotez-une-matrice-de-led-avec-une-page-web/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Mise en cache de page à l’aide de Disk: Enhanced 

Served from: developer.myconstellation.io @ 2026-01-21 02:53:42 by W3 Total Cache
-->