﻿<?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>Tag Saga - Constellation</title>
	<atom:link href="https://developer.myconstellation.io/tag/saga/feed/" rel="self" type="application/rss+xml" />
	<link>https://developer.myconstellation.io/tag/saga/</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>Tag Saga - Constellation</title>
	<link>https://developer.myconstellation.io/tag/saga/</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>Nouvelle librairie Constellation pour Arduino / ESP8266 en version 2.0</title>
		<link>https://developer.myconstellation.io/blog/nouvelle-librairie-constellation-pour-arduino-esp8266-en-version-2-0/</link>
					<comments>https://developer.myconstellation.io/blog/nouvelle-librairie-constellation-pour-arduino-esp8266-en-version-2-0/#comments</comments>
		
		<dc:creator><![CDATA[Sebastien Warin]]></dc:creator>
		<pubDate>Tue, 13 Sep 2016 13:20:38 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[MessageCallback]]></category>
		<category><![CDATA[MessageContext]]></category>
		<category><![CDATA[Saga]]></category>
		<category><![CDATA[PurgeStateObject]]></category>
		<category><![CDATA[StateObjectLink]]></category>
		<category><![CDATA[PackageDescriptor]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[Virtuel]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Subscribe]]></category>
		<category><![CDATA[SendMessage]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[PushStateObject]]></category>
		<category><![CDATA[ESP8266]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[ESP]]></category>
		<category><![CDATA[Package]]></category>
		<category><![CDATA[Messaging]]></category>
		<category><![CDATA[Message]]></category>
		<category><![CDATA[Console]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=2546</guid>

					<description><![CDATA[<p>J’ai le plaisir de  vous annoncer l’arrivée de la nouvelle libraire Constellation pour Arduino/ESP en version 2.0. Cette nouvelle version amène beaucoup de nouveautés que je vous propose de découvrir dans cet article. La librairie a été testé avec succès</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/blog/nouvelle-librairie-constellation-pour-arduino-esp8266-en-version-2-0/">Nouvelle librairie Constellation pour Arduino / ESP8266 en version 2.0</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>J’ai le plaisir de  vous annoncer l’arrivée de la nouvelle libraire Constellation pour Arduino/ESP en version 2.0.</p>
<p>Cette nouvelle version amène beaucoup de nouveautés que je vous propose de découvrir dans cet article. La librairie a été testé avec succès sur différentes cartes animées par un ESP8266 (ESP-01, 05, 07 et D1 Mini) ainsi qu’un Arduino/Genuino MKR1000.</p>
<p>Pour la mise à jour, téléchargez la libraire ci-dessous et dézippez les fichiers dans le dossier “Constellation” dans votre répertoire de libraire Arduino.</p>

<p><u>Attention</u> : cette version 2.x de la librairie Constellation pour Arduino/ESP nécessite la version <a href="/constellation-platform/changelog/#05092016_Update_Server_18116249">1.8.1.16249</a> ou plus récente du serveur Constellation pour fonctionner correctement. Pour mettre à jour votre plateforme Constellation, lancez le <a href="/downloads/">Web Platform Installer</a>.</p>
<h3>Réception de message et StateObject “asynchrone”</h3>
<p>Il s’agit d’une grosse évolution par rapport à la version 1.x. Pour “récupérer” du serveur Constellation les messages à destination de votre package virtuel ou les StateObjects pour lequel votre package (virtuel) s’est abonné, il faut invoquer les actions “<a href="/client-api/rest-api/interface-rest-constellation/#Recevoir_des_messages">GetMessages</a>” et “<a href="/client-api/rest-api/interface-rest-constellation/#Subscribe">GetStateObjects</a>” sur l’interface REST.</p>
<p>Ces méthodes supportent le “long-polling” c’est à dire qu’elles mettent en attente la requête tant qu’il n’y a pas de messages ou StateObjects à retourner avec la notion de timeout (par défaut 60 secondes).</p>
<p>Le problème sur les versions 1.x de la libraire Arduino est que le client HTTP est “synchrone”, c’est à dire qu’il envoi la requête HTTP et attend la réponse du serveur pour traitement ce qui est incompatible avec du long-polling car cela bloquerait le code de l’Arduino. De ce fait, les anciennes versions spécifiées le “timeout” de ces requêtes à 1 seconde.</p>
<p>Ainsi jusqu’à maintenant, l’interrogation des messages et SO pouvaient bloquer jusqu’à 2 secondes votre Arduino (1 seconde pour le GetMessage et 1 seconde pour le GetStateObject) et engendrait donc 1 requêtes HTTP toutes les secondes entre votre ESP/Arduino et le serveur Constellation.</p>
<p>Dans cette nouvelle version, la librairie utilisent 3 clients HTTP différents : un pour toutes les requêtes synchrones, un pour la réception de message (<em>GetMessage</em>) et un pour la réception des StateObjects (<em>GetStateObjects</em>).</p>
<p>Le client synchrone est donc toujours disponible et il n’y a aucun blocage, aucune attente pour la réception de message et de SO. De plus il n’y a plus besoin de “poller” ou “flooder” le serveur d’une requête toute les secondes, en réactivant le long-polling le 2ème et 3ème client HTTP, on lance une requête toutes les minutes (60 sec par défaut) dans l’attente de message et SO.</p>
<p>De ce fait, il y a quelques modifications à apporter dans votre code !</p>
<p>Premièrement, vous ne devez plus passer la référence de votre client réseau mais plutôt spécifier le type de votre client dans le template de la classe Constellation. Par exemple, si vous utilisez un ESP8266 ou un Arduino MKR1000, vous utiliserez la classe “WifiClient “” :</p>
<p></p><pre class="crayon-plain-tag">/* Create the Constellation client */
Constellation&lt;WiFiClient&gt; constellation("constellation.monserveur.com", 8088, "MyVirtualSentine", "MyPackage", "MyAccessKey123!");</pre><p></p>
<p>Ensuite, il n’y a plus besoin d’invoquer la méthode “poll” dans votre boucle principale avec un timer, vous devez tout simplement appeler la méthode “loop” autant de fois que vous voulez :</p>
<p></p><pre class="crayon-plain-tag">void loop(void) {
  // Process incoming message &amp; StateObject updates
  constellation.loop();
}</pre><p></p>
<p>Cette méthode vérifie en fait si il y a eu une réponse sur le client utilisé pour la réception de message et sur le client pour la réception de SO afin de les dispatcher dans votre code.</p>
<h3>Support du PackageDescriptor</h3>
<p>Autre nouveauté majeure pour cette version 2, le support du “Package Descriptor”.</p>
<p>Pour rappel le “Package Descriptor” est un objet envoyé par un package au serveur pour décrire ses StateObjects et ses MessageCallbacks exposés par le package.</p>
<p>Le MessageCallback Explorer de la Console Constellation s’appuie sur le “Package Descriptor” de chaque package pour lister chaque MessageCallback avec un formulaire de test. Sans cette description cela serait impossible !</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image.png"><img class="colorbox-2546"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="MessageCallback Explorer" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/image_thumb.png" alt="MessageCallback Explorer" width="350" height="168" border="0" /></a></p>
<p>Les versions 1.x ne supportaient pas “Package Descriptor”, de ce fait il n’était pas possible d’explorer/découvrir les MessageCallbacks d’un package Arduino/ESP. Vous devez nécessairement connaitre par vous même les MC exposés par le package et le type des StateObjects qu’il pouvait publier.</p>
<p>Avec la version 2.0, l’Arduino/ESP envoie au serveur la description des MC exposés et des types utilisés par les SO et arguments des MC.</p>
<p>Dans la suite de cet article, vous découvrirez comment ajouter des types dans la description de votre package, mais n’oubliez jamais d’envoyer votre “Package Descriptor” en invoquant la méthode “declarePackageDescriptor”, typiquement une fois votre code Arduino initialisé (par exemple à la fin de la méthode <em>setup()</em>) :</p>
<p></p><pre class="crayon-plain-tag">// Declare the package descriptor
constellation.declarePackageDescriptor();</pre><p></p>
<h3>Amélioration du PushStateObject</h3>
<p>La méthode “PushStateObject” permet de publier un StateObject sur le serveur Constellation.</p>
<p>Tout d’abord la méthode expose des surcharges vous permettant de spécifier comme “value” de votre SO des int, uint, double, float, long et bool et supporte en paramètre optionnel le “lifetime”, c’st à dire la durée en seconde de “vie” de votre StateObject avant d’être considéré comme expiré.</p>
<p></p><pre class="crayon-plain-tag">// Dummy data
uint16_t lux = 123;

// Push a simple type on Constellation 
constellation.pushStateObject("DemoLux", lux);  

// Push a simple type on Constellation with lifetime of 20 seconds
constellation.pushStateObject("DemoLux", lux, 20);</pre><p></p>
<p>Vous pouvez toujours publier des StateObjects dont la valeur (value) est un objet complexe (formaté en JSON).</p>
<p>Le JSON peut être formaté sous forme d’une chaine de caractère avec la méthode “stringFormat” :</p>
<p></p><pre class="crayon-plain-tag">// Push a complex object on Constellation with stringFormat
constellation.pushStateObject("DemoLux", stringFormat("{ 'Lux':%d, 'Broadband':%d, 'IR':%d }", lux, full, ir));</pre><p></p>
<p>Vous pouvez également définir votre propre type pour ce StateObject, par exemple nommons cet objet “MyLuxData” :</p>
<p></p><pre class="crayon-plain-tag">constellation.pushStateObject("DemoLux", stringFormat("{ 'Lux':%d, 'Broadband':%d, 'IR':%d }", lux, full, ir), "MyLuxData");</pre><p></p>
<p>Sans oublier d’ajouter ce type “personnalisé” dans le “package descriptor”. Par exemple, dans le “setup()” et avant de faire un “declarePackageDescriptor”, on aurait décrit “MyLuxData” de la façon suivante :</p>
<p></p><pre class="crayon-plain-tag">constellation.addStateObjectType("MyLuxData", TypeDescriptor().setDescription("MyLuxData demo").addProperty("Broadband", "System.Int32").addProperty("IR", "System.Int32").addProperty("Lux", "System.Int32"));</pre><p></p>
<p>Pour finir, vous pouvez toujours publier un StateObject en construisant la valeur dans un objet JsonObject de façon suivante :</p>
<p></p><pre class="crayon-plain-tag">// Push a complex object on Constellation with JsonObject
const int BUFFER_SIZE = JSON_OBJECT_SIZE(5);
StaticJsonBuffer&lt;BUFFER_SIZE&gt; jsonBuffer;
JsonObject&amp; myStateObject = jsonBuffer.createObject();
myStateObject["Lux"] = lux;
myStateObject["Broadband"] = full;
myStateObject["IR"] = ir;
constellation.pushStateObject("DemoLux", myStateObject);</pre><p></p>
<p>Dans les surcharges de cette méthode, vous pouvez également spécifier le type de votre StateObject et/ou sa durée de vie :</p>
<p></p><pre class="crayon-plain-tag">constellation.pushStateObject("DemoLux", myStateObject, "MyLuxData", 20);</pre><p></p>
<p>Pour finir, nouveauté de la librairie 2.0, vous pouvez également spécifier des “meta-données” à vos StateObjects. Par exemple :</p>
<p></p><pre class="crayon-plain-tag">// Ajout de metadatas au StateObject
JsonObject&amp; metadatas = jsonBuffer.createObject();
metadatas["ChipId"] = ESP.getChipId();
metadatas["Timestamp"] = millis();
constellation.pushStateObject("DemoLux", myStateObject, "MyStateObject", 20, &amp;metadatas);</pre><p></p>
<h3>Les StateObjectLinks</h3>
<p>En version 1.x de la librairie Arduino, vous pouvez :</p>
<ul>
<li>interroger des StateObjects de la Constellation en invoquant la méthode “requestStateObjects” qui vous retourne les StateObjects à l’instant T correspondant à votre requête :</li>
</ul>
<p></p><pre class="crayon-plain-tag">// Example : print the all SO's value named "/intelcpu/0/load/0" and produced by the "HWMonitor" package (on all sentinels)
JsonArray&amp; cpus = constellation.requestStateObjects("*", "HWMonitor", "/intelcpu/0/load/0");
for(int i=0; i &lt; cpus.size(); i++) { 
  constellation.writeInfo("CPU on %s is currently %d %", cpus[i]["SentinelName"].asString(), cpus[i]["Value"]["Value"].as&lt;float&gt;());
}</pre><p></p>
<ul>
<li>vous abonnez aux mises à jour des StateObjects pour être notifié en temps réel des que les SO changent :</li>
</ul>
<p></p><pre class="crayon-plain-tag">// set a StateObject update callback and subscribe to SO
constellation.setStateObjectUpdateCallback([] (JsonObject&amp; so) {
constellation.writeInfo("StateObject updated ! StateObject name = %s", so["Name"].asString()); 
});
// Subscribe to SO named "/intelcpu/0/load/0" and produced by the "HWMonitor" package (on all sentinels)
constellation.subscribeToStateObjects("*", "HWMonitor", "/intelcpu/0/load/0");</pre><p></p>
<p>Vous pouvez invoquer plusieurs fois la méthode “subscribeToStateObjects” pour ajouter des abonnements à d’autre StateObjects mais il n’y a qu’un seul callback de réception des SO (défini par la méthode setStateObjectUpdateCallback). C’est à vous de “dispatcher” les SO reçus.</p>
<p>La nouveauté en 2.0 vient de l’ajout de la méthode “registerStateObjectLink” qui vous permet d’associer un callback à un abonnement laissant ainsi à la librairie la charge du “dispatch”.</p>
<p>Par exemple, on peut désormais écrire :</p>
<p></p><pre class="crayon-plain-tag">constellation.registerStateObjectLink("*", "HWMonitor", "/intelcpu/0/load/0", [](JsonObject&amp; so) {
  constellation.writeInfo("CPU on %s is currently %d %", so["SentinelName"].asString(), so["Value"]["Value"].as&lt;float&gt;());
});</pre><p></p>
<p>Ici on enregistre un “StateObject Link” sur tous les SO nommés « /intelcpu/0/load/0 » produits par le package “HWMonitor” de toutes les sentinelles de votre Constellation. Dès qu’un de ces StateObjects changent on exécutera le callback associé, qui ici écrit dans le log un message indiquant la nouvelle valeur du CPU.</p>
<p>Vous bien entendu enregistrer autant de StateObjectLink que vous souhaitez.</p>
<h3>Enregistrement des MessageCallbacks</h3>
<p>Le principe est le même que celui décrit ci-dessus pour les abonnements aux StateObjects.</p>
<p>En version 1.x, on devait définir un callback pour réception de message et invoquer la méthode “subscribeToMessage” :</p>
<p></p><pre class="crayon-plain-tag">// Set callback for all incoming messages
 constellation.setMessageReceiveCallback([](JsonObject&amp; json) { 
   constellation.writeInfo("Message receive ! Message key = %s", json["Key"].asString());     
 }); 
 // Subscribe to message
 constellation.subscribeToMessage();</pre><p></p>
<p>C’était donc à votre charge de “dispatcher” les messages reçus en fonction du “MessageKey”.</p>
<p>Désormais avec la version 2.0, vous pouvez enregistrer un callback pour un “MessageKey” donné. Par exemple :</p>
<p></p><pre class="crayon-plain-tag">constellation.registerMessageCallback("HelloWorld",
  [](JsonObject&amp; json) {
    constellation.writeInfo("Hello Constellation !");
 });</pre><p></p>
<p>Dans l’exemple ci-dessous, on ajoute/expose un MessageCallback “HelloWorld” qui écrit dans les logs !</p>
<p>Il n’y donc plus besoin de “dispatcher”, un MessageCallback est donc associé à un “MessageKey” unique et un callback. Il n’y a plus besoin non plus de faire un “subscribeToMessage” (cette méthode est invoquée implicitement par le <em>registerMessageCallback</em>).</p>
<p>De plus cette méthode ajoute implicitement les MessageCallbacks dans le Package Descriptor de sorte que chaque MC soit ainsi référencé dans la Constellation</p>
<p>(console)</p>
<p>Vous pouvez également passer un “MessageCallbackDescriptor” dans l’enregistrement de vos MC pour ajouter une description par exemple :</p>
<p></p><pre class="crayon-plain-tag">constellation.registerMessageCallback("HelloWorld",
  MessageCallbackDescriptor().setDescription("Say Hello to Constellation"),
  [](JsonObject&amp; json) {
    constellation.writeInfo("Hello Constellation !");
 });</pre><p></p>
<p>Et même définir les paramètres de vos MC :</p>
<p></p><pre class="crayon-plain-tag">constellation.registerMessageCallback("SayHello",
  MessageCallbackDescriptor().setDescription("Say hello !").addParameter("FirstName", "System.String").addParameter("LastName", "System.String"),
  [](JsonObject&amp; json) {
    constellation.writeInfo("Hello %s %s", json["Data"][0].asString(), json["Data"][1].asString()); 
 });</pre><p></p>
<p>Ici on déclare un MC nommé “SayHello” prenant deux paramètres de type String avec un texte de description. Dans la code nous verrons :</p>
<p>(console)</p>
<p>Tout comme les StateObjects, les types des arguments des MC peuvent être des types complexes.</p>
<p>Par exemple enregistrons un MC prenant un seul argument de type “SampleUserData” que nous allons décrire avec la méthode “addMessageCallbackType” comme un objet composé de deux propriétés de type String :</p>
<p></p><pre class="crayon-plain-tag">// Expose a MessageCallback with complex parameter :
constellation.registerMessageCallback("SayHello2",
  MessageCallbackDescriptor().setDescription("Say hello with complex object!").addParameter("User", "SampleUserData"),
  [](JsonObject&amp; json) {
    constellation.writeInfo("Hello %s %s", json["Data"][0]["FirstName"].asString(), json["Data"][0]["LastName"].asString()); 
});  
// and describe the complex parameter "SampleUserData"  
constellation.addMessageCallbackType("SampleUserData", TypeDescriptor().setDescription("This is a smaple user data").addProperty("FirstName", "System.String").addProperty("LastName", "System.String"));</pre><p></p>
<p>Enfin la méthode “registerMessageCallback” accepte également des callbacks prenant en paramètre le “MessageContext” :</p>
<p></p><pre class="crayon-plain-tag">constellation.registerMessageCallback("HelloWorld",
  MessageCallbackDescriptor().setDescription("Say Hello to Constellation"),
  [](JsonObject&amp; json, MessageContext ctx) {
    constellation.writeInfo("Message received from %s", ctx.sender.friendlyName);
 });</pre><p></p>
<p>L’objet “MessageContext” est défini de la façon suivante :</p>
<p></p><pre class="crayon-plain-tag">typedef struct {
    const char* sagaId;
    bool isSaga;
    const char* messageKey;
    MessageSender sender;
    ScopeType scope;
} MessageContext;

typedef struct {
    SenderType type;
    const char* friendlyName;
    const char* connectionId;
} MessageSender;</pre><p></p>
<p>Vous pouvez donc récupérer les informations sur l’émetteur (Sender) du message, le scope et l’identifiant de Saga si c’est une saga (isSaga = true).</p>
<h3>Support des Saga (messages avec réponse)</h3>
<p>Une <a href="/concepts/messaging-message-scope-messagecallback-saga/#Les_Sagas">saga</a> est un identifiant unique qu’on affecte à des messages pour les lier entre eux. Cela permet de faire des couples de message “Requête / Réponse”. Une “réponse” étant un message renvoyé à l’émetteur de la requête avec le même identifiant de saga pour que ce dernier puisse l’identifier comme la “réponse” à son message d’origine.</p>
<p>Vous pouvez exposer des MessageCallbacks qui “répondent”, c’est à dire des  MessageCallbacks qui retournent un message de réponse.</p>
<p>Par exemple, exposons un MC pour réaliser des Additions sur un Arduino. Vous enregistrerez un MC “Addition” prenant en parametre deux entiers et qui en retourne un (le résultat) :</p>
<p></p><pre class="crayon-plain-tag">constellation.registerMessageCallback("Addition",
  MessageCallbackDescriptor().setDescription("Do addition on this tiny device").addParameter("a", "System.Int32").addParameter("b", "System.Int32").setReturnType("System.Int32"),
  [](JsonObject&amp; json, MessageContext ctx) {        
    int a = json["Data"][0].as&lt;int&gt;();      
    int b = json["Data"][1].as&lt;int&gt;();
    int result = a + b;
    constellation.writeInfo("Addition %d + %d = %d", a, b, result);      
    if(ctx.isSaga) {
      constellation.writeInfo("Doing additoon for %s (sagaId: %s)", ctx.sender.friendlyName, ctx.sagaId);   
    // Return the result :
      constellation.sendResponse&lt;int&gt;(ctx, result);
    }
    else {
      constellation.writeInfo("No saga, no response !");
    }
 });</pre><p></p>
<p>Vous remarquerez dans le “MessageCallbackDescriptor” l’appel de la méthode “setReturnType” pour spécifier le type de retour (et que le fait qu’il s’agit d’un MC acceptant les sagas).</p>
<p>L’envoi de la réponse étant réalisé par la méthode sendReponse. Cette méthode a plusieurs surcharges :</p>
<p></p><pre class="crayon-plain-tag">template&lt;typename T&gt; bool sendResponse(MessageContext context, T data);
bool sendResponse(MessageContext context, const char* data, ...);
bool sendResponse(MessageContext context, JsonObject&amp; data);</pre><p></p>
<p>Notez aussi que vous devriez faire un “sendResponse” si et seulement le message reçu est associé à une saga, c’est à dire que le champs “isSaga” du contexte (MessageContext) est “vrai”. Sinon ca ne sert à rien de répondre <img class="wlEmoticon wlEmoticon-winkingsmile colorbox-2546" style="border-style: none;" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/wlEmoticon-winkingsmile.png" alt="Clignement d'œil" /></p>
<p>Pour finir, cette nouvelle version supporte également l’envoi de message dans une saga. C’est à dire que vous pouvez envoyer un message qui attend une réponse et donc enregistrer un callback de traitement de la réponse.</p>
<p>Par exemple le package “NetworkTools” expose un MC “Ping” permettant de faire un ping. Le package retourne dans la saga un message contenant le temps en milliseconde du ping. On pourrait alors invoquer cette méthode depuis notre Arduino de la façon suivante :</p>
<p></p><pre class="crayon-plain-tag">const char* ip = "192.168.0.10";
// Send message in a saga and attach a callback for response :
constellation.sendMessageWithSaga([](JsonObject&amp; json) {
  constellation.writeInfo("Ping response in %s ms", json["Data"].asString()); 
}, Package, "NetworkTools", "Ping", "[ '%s' ]", ip);</pre><p></p>
<p>Ici on envoi un message au scope “Package” pour atteindre le(x) package(s) “NetworkTools” afin d’invoquer le MessageCallback “Ping” en passant en argument l’IP à pinger. Vous remarquerez qu’on utilise le formatage implicite des arguments.</p>
<p>La méthode n’est pas la traditionnelle “sendMessage” mais “sendMessageWithSaga” qui prend un argument supplémentaire : le callback de traitement de la réponse.</p>
<p>Ainsi quand le package “NetworkTools” répondra, on executera le callback associé qui ici affichera le temps de réponse de notre ping (Data) dans les logs Constellation (writeInfo).</p>
<p>De ce fait, avec cette nouvelle libraire vos Arduino/ESP peuvent invoquer des MC dans sagas pour exploiter la réponse mais également exposer des MC qui retournent des résultats.</p>
<h3>Autres nouveautés</h3>
<p>En vrac, vous disposez maintenant une méthode “purgeStateObjects” permettant de supprimer des StateObjects de votre package.</p>
<p>De plus la méthode “setDebugMode” accepte en argument l’énumération “DebugMode” composée des valeurs suivantes :</p>
<ul>
<li>“Quiet” (mode silencieux, la libraire ne produit aucune trace dans l’interface Serial)</li>
<li>“Normal” (mode par défaut, écrit quelques informations dans l’interface Serial)</li>
<li>“Verbose” (écrit beaucoup d’information dans l’interface Serial comme par exemple les requêtes et réponse HTTP v ers Constellation)</li>
</ul>
<p>Enfin les exemples fournis dans la libraire ont été complètement revus.</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/blog/nouvelle-librairie-constellation-pour-arduino-esp8266-en-version-2-0/">Nouvelle librairie Constellation pour Arduino / ESP8266 en version 2.0</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://developer.myconstellation.io/blog/nouvelle-librairie-constellation-pour-arduino-esp8266-en-version-2-0/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Le MessageCallbacks Explorer</title>
		<link>https://developer.myconstellation.io/constellation-platform/constellation-console/messagecallbacks-explorer/</link>
					<comments>https://developer.myconstellation.io/constellation-platform/constellation-console/messagecallbacks-explorer/#comments</comments>
		
		<dc:creator><![CDATA[Sebastien Warin]]></dc:creator>
		<pubDate>Fri, 23 Sep 2016 07:33:37 +0000</pubDate>
				<category><![CDATA[Constellation Console]]></category>
		<category><![CDATA[Saga]]></category>
		<category><![CDATA[Message]]></category>
		<category><![CDATA[MessageCallback]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=2712</guid>

					<description><![CDATA[<p>Le MessageCallbacks Explorer permet d’afficher la liste des MessageCallbacks exposés par les packages de votre Constellation. Pour chaque MessageCallback déclaré vous retrouverez une description, la liste des paramètres du MessageCallback avec un formulaire de test et un bouton d’envoi. Il</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/constellation-platform/constellation-console/messagecallbacks-explorer/">Le MessageCallbacks Explorer</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Le MessageCallbacks Explorer permet d’afficher la liste des MessageCallbacks exposés par les packages de votre Constellation.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-44.png"><img class="colorbox-2712"  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/2016/09/image_thumb-43.png" alt="image" width="350" height="172" border="0" /></a></p>
<p align="left">Pour chaque MessageCallback déclaré vous retrouverez une description, la liste des paramètres du MessageCallback avec un formulaire de test et un bouton d’envoi.</p>
<p align="left">Il est ainsi possible de tester directement les MC de vos packages depuis la Console Constellation.</p>
<p align="left">Vous disposez également d’un moteur de recherche :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-45.png"><img class="colorbox-2712"  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/2016/09/image_thumb-44.png" alt="image" width="205" height="114" border="0" /></a></p>
<p align="left">Si le package est déployé sur plusieurs sentinelle le bouton “Invoke” vous proposera d’envoyer votre message à une instance en particulier ou à toutes les instances du package dans votre Constellation :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-51.png"><img class="colorbox-2712"  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/2016/09/image_thumb-50.png" alt="image" width="350" height="130" border="0" /></a></p>
<p align="left">Aussi le MessageCallbacks Explorer dispose d’un générateur de code permettant d’afficher des “code snippets” d’invocation du MC pour chaque API Constellation.</p>
<p align="left">Vous pouvez ouvrir ce générateur de code en cliquant sur le bouton <img class="colorbox-2712"  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/2016/09/image-57.png" alt="image" width="26" height="25" border="0" /> à côté du nom de chaque MessageCallback.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-46.png"><img class="colorbox-2712"  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/2016/09/image_thumb-45.png" alt="image" width="350" height="225" border="0" /></a></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-47.png"><img class="colorbox-2712"  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/2016/09/image_thumb-46.png" alt="image" width="350" height="216" border="0" /></a></p>
<p align="left">Les types personnalisés sont affichés sous forme de lien sur lesquels vous pouvez cliquer pour ouvrir la fenêtre de description de type :</p>
<p align="left"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-53.png"><img class="colorbox-2712"  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: 0px;" title="image" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/image_thumb-52.png" alt="image" width="350" height="102" border="0" /></a></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-54.png"><img class="colorbox-2712"  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/2016/09/image_thumb-53.png" alt="image" width="350" height="187" border="0" /></a></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-55.png"><img class="colorbox-2712"  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/2016/09/image_thumb-54.png" alt="image" width="350" height="172" border="0" /></a></p>
<p align="left">Enfin pour les MessageCallbacks avec message de réponse, vous pouvez les invoquer en envoyant le message dans une saga en cochant la case “With Saga” :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-56.png"><img class="colorbox-2712"  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/2016/09/image_thumb-55.png" alt="image" width="95" height="66" border="0" /></a></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-48.png"><img class="colorbox-2712"  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/2016/09/image_thumb-47.png" alt="image" width="350" height="139" border="0" /></a></p>
<p align="left">Les messages de réponse des sagas apparaissent sous forme de notification dans la barre du haut :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-49.png"><img class="colorbox-2712"  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/2016/09/image_thumb-48.png" alt="image" width="350" height="117" border="0" /></a></p>
<p>En cliquant dessus vous pourrez consulter le message de réponse ainsi que l’ensemble des informations liées à la saga :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-50.png"><img class="colorbox-2712"  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/2016/09/image_thumb-49.png" alt="image" width="350" height="238" border="0" /></a></p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/constellation-platform/constellation-console/messagecallbacks-explorer/">Le MessageCallbacks Explorer</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://developer.myconstellation.io/constellation-platform/constellation-console/messagecallbacks-explorer/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>MessageCallback : Exposer des méthodes Python</title>
		<link>https://developer.myconstellation.io/client-api/python-api/messagecallbacks-exposer-des-methodes-python/</link>
					<comments>https://developer.myconstellation.io/client-api/python-api/messagecallbacks-exposer-des-methodes-python/#respond</comments>
		
		<dc:creator><![CDATA[Sebastien Warin]]></dc:creator>
		<pubDate>Wed, 24 Aug 2016 09:47:40 +0000</pubDate>
				<category><![CDATA[Python API]]></category>
		<category><![CDATA[Package]]></category>
		<category><![CDATA[Message]]></category>
		<category><![CDATA[MessageCallback]]></category>
		<category><![CDATA[Saga]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[MessageContext]]></category>
		<category><![CDATA[PackageDescriptor]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=2511</guid>

					<description><![CDATA[<p>Exposer une méthode Pour exposer une méthode Python dans Constellation vous devez tout simplement ajouter le décorateur “Constellation.MessageCallback” sur votre méthode : [crayon-6972d48e1c175861987860/] Ici nous déclarons le MessageCallback “SimpleMessageCallback” sans paramètre ni documentation. Vous pouvez ajouter un ou plusieurs arguments</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/client-api/python-api/messagecallbacks-exposer-des-methodes-python/">MessageCallback : Exposer des méthodes Python</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h3>Exposer une méthode</h3>
<p>Pour exposer une méthode Python dans Constellation vous devez tout simplement ajouter le décorateur “<em>Constellation.MessageCallback</em>” sur votre méthode :</p>
<p></p><pre class="crayon-plain-tag">@Constellation.MessageCallback()
def SimpleMessageCallback():
    Constellation.WriteInfo('Hello Python !')</pre><p></p>
<p>Ici nous déclarons le MessageCallback “SimpleMessageCallback” sans paramètre ni documentation.</p>
<p>Vous pouvez ajouter un ou plusieurs arguments à votre MC et utiliser la syntaxe de Python pour commenter vos MC :</p>
<p></p><pre class="crayon-plain-tag">@Constellation.MessageCallback()
def DemoArg(data):
    "Ceci est la description du MessageCallback DemoArg avec 1 argument"
    Constellation.WriteInfo('arg = %s', data)

@Constellation.MessageCallback()
def DemoArgs(a, b, c):
    "Ceci est la description du MessageCallback DemoArgs avec 3 arguments"
    Constellation.WriteInfo(a)
    Constellation.WriteInfo(b)
    Constellation.WriteInfo(c)</pre><p></p>
<p>Le ou les paramètres peuvent être des types simples (string, int, bool, etc..) ou des types (objets) complexes :</p>
<p></p><pre class="crayon-plain-tag">@Constellation.MessageCallback()
def ComplexMessageCallback(data):
    "Ceci est la description du MessageCallback ComplexMessageCallback avec un objet complexe en argument"
    Constellation.WriteInfo(data.A)
    Constellation.WriteInfo(data.B)
    Constellation.WriteInfo(data.C)</pre><p></p>
<p>L’ensemble de ces méthodes déclarées “MessageCallbacks” seront alors référencées dans la Constellation. Vous pouvez les découvrir en interrogeant le Package Descriptor de votre package.</p>
<p>Par exemple, lancez la Console Constellation et rendez-vous dans le “MessageCallback Browser”. Vous aurez la liste de vos méthodes avec la possibilité de les invoquer directement depuis l’interface :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/04/image-9.png"><img class="colorbox-2511"  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/2018/04/image_thumb-8.png" alt="MessageCallbacks Explorer" width="484" height="346" border="0" /></a></p>
<h3>Documenter son MessageCallback</h3>
<h4>Description des MessageCallbacks</h4>
<p>Comme vous l’avez remarqué dans les exemples précédents, nous utilisons la documentation des méthodes de Python :</p>
<p></p><pre class="crayon-plain-tag">@Constellation.MessageCallback()
def Demo():
    "Ceci est la description du MessageCallback !"
    pass</pre><p></p>
<p>La documentation de la méthode est utilisée comme description du MessageCallback :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/08/image-72.png"><img class="colorbox-2511"  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/2016/08/image_thumb-61.png" alt="image" width="350" height="109" border="0" /></a></p>
<p>La description de la méthode peut être écrite sur plusieurs lignes :</p>
<p></p><pre class="crayon-plain-tag">@Constellation.MessageCallback()
def Demo():
    '''
    The first line is brief explanation, which may be completed with 
    a longer one. For instance to discuss about its methods.
    '''
    pass</pre><p></p>
<h4>Description des arguments des MessageCallbacks</h4>
<p><u>Note</u> : la description des arguments est disponible depuis l’API Python 1.8.4.x. Pensez à mettre à jour la référence de votre API par Nuget depuis Visual Studio ou en <a href="/client-api/python-api/developper-avec-le-package-tools-cli/#Mise_a_jour_du_template">mettant à jour le template depuis la CLI</a>.</p>
<p>Si vous regardez attentivement les arguments des MC dans le MessageCallback Explorer, ils sont reconnus comme « System.Object » étant donné que les arguments d&rsquo;une fonction en Python ne sont pas typés.</p>
<p>Pour décrire les paramètres utilisez la syntaxe suivante dans la description du MC :</p>
<p></p><pre class="crayon-plain-tag">:param &lt;type&gt; &lt;name&gt; : &lt;description&gt;</pre><p></p>
<p>Par exemple :</p>
<p></p><pre class="crayon-plain-tag">@Constellation.MessageCallback()
def Demo(a, b, c):
    '''
    Ceci est un exemple de MC avec 3 parametres

    :param int a: My int value
    :param bool b: My boolean value
    :param string c: My string value
    '''
    Constellation.WriteInfo("a = %s - type: %s" % (a, type(a)))
    Constellation.WriteInfo("b = %s - type: %s" % (b, type(b)))
    Constellation.WriteInfo("c = %s - type: %s" % (c, type(c)))</pre><p></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/04/image-10.png"><img class="colorbox-2511"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Description des arguments d'un MC en Python" src="https://developer.myconstellation.io/wp-content/uploads/2018/04/image_thumb-9.png" alt="Description des arguments d'un MC en Python" width="484" height="166" border="0" /></a></p>
<p align="left">Ainsi en retournant sur le MC Explorer, chaque argument est correctement typé dans Constellation.</p>
<h4 align="left">Paramètres optionnels avec valeur par défaut</h4>
<p align="left">Vous pouvez également définir que certains paramètres sont optionnels en spécifiant leurs valeurs par défaut avec la syntaxe [default: XXX] :</p>
<p></p><pre class="crayon-plain-tag">@Constellation.MessageCallback()
def DemoOptional(a, b):
    '''
    Ceci est un exemple de MC des paramètres optionnels

    :param int a: My int value [default:10]
    :param bool b: My boolean value [default:true]
    '''
    Constellation.WriteInfo("a = %s" % a)
    Constellation.WriteInfo("b = %s" % b)</pre><p></p>
<p>&nbsp;</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/04/image-11.png"><img class="colorbox-2511"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Arguments optionnels avec valeur par défaut" src="https://developer.myconstellation.io/wp-content/uploads/2018/04/image_thumb-10.png" alt="Arguments optionnels avec valeur par défaut" width="484" height="138" border="0" /></a></p>
<h4>Décrire les arguments de type complexe</h4>
<p>Dans le cas où un MC prend en paramètre un (ou plusieurs) type complexe, il faudra d&rsquo;abord décrie le type dans la méthode « Start ».</p>
<p>Par exemple, enregistrons au démarrage du package (méthode Start), le type “CredentialInfo” :</p>
<p></p><pre class="crayon-plain-tag">Constellation.DescribeMessageCallbackType("CredentialInfo", "Credential information", [
    { 'Name':'Username', 'Type':'string', 'Description': 'The username' },
    { 'Name':'Password', 'Type':'string', 'Description': 'The password' },
])</pre><p></p>
<p>Une fois tous vos types déclarés, il faut publier le “Package Descriptor” de votre package à Constellation par la ligne :</p>
<p></p><pre class="crayon-plain-tag">Constellation.DeclarePackageDescriptor()</pre><p></p>
<p>Nous pouvons maintenant déclarer un MC avec un parametre de type “CredentialInfo”. Par exemple :</p>
<p></p><pre class="crayon-plain-tag">@Constellation.MessageCallback()
def DemoAuth(credential):
    '''
    Demo MC avec avec un paramètre de type complexe

    :param CredentialInfo credential: the credential info
    '''
    Constellation.WriteInfo("User=%s Password=%s" % (credential.Username, credential.Password))</pre><p></p>
<p>Comme vous pourrez le voir dans le MessageCallbacks Explorer, votre méthode Python est correctement décrite ainsi que son paramètre “credential” de type “Credentialnfo”.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/04/image-12.png"><img class="colorbox-2511"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Argument de type complexe" src="https://developer.myconstellation.io/wp-content/uploads/2018/04/image_thumb-11.png" alt="Argument de type complexe" width="484" height="150" border="0" /></a></p>
<p>Notez également que la description du type CredentialInfo est accessible en cliquant sur le type :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/04/image-13.png"><img class="colorbox-2511"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Argument de type complexe" src="https://developer.myconstellation.io/wp-content/uploads/2018/04/image_thumb-12.png" alt="Argument de type complexe" width="484" height="186" border="0" /></a></p>
<h3>Personnaliser le MessageCallback</h3>
<p>Comme pour l’API.NET, par défaut le nom du MessageCallback déclaré dans la Constellation est le nom de votre méthode mais vous pouvez redéfinir le nom exposé dans la Constellation :</p>
<p></p><pre class="crayon-plain-tag">@Constellation.MessageCallback("MySuperName")
def MyInternalMethodName():
    Constellation.WriteInfo("Hello")</pre><p></p>
<p>Aussi vous pouvez “cacher” ce MessageCallback à la Constellation.</p>
<p></p><pre class="crayon-plain-tag">@Constellation.MessageCallback(False)
def HiddenMessageCallback():
    "Hidden message callback"
    Constellation.WriteInfo("I'm here !!")</pre><p></p>
<p>Tous les packages ou consommateurs de votre Constellation pourront envoyer un message “HiddenMessageCallback” à votre package Python et donc invoquer votre méthode mais celle-ci ne sera pas déclarée dans le “Package  Descriptor”.</p>
<h3>Récupérer le contexte</h3>
<p>Comme avec l’API.NET, vous pouvez récupérer le contexte de réception du message en déclarant comme dernier argument de votre MessageCallback, le paramètre “context”.</p>
<p>Par exemple :</p>
<p></p><pre class="crayon-plain-tag">@Constellation.MessageCallback("MaMethode") # méthode renommée !
def DemoSeb5(context):
    "Test du contexte"
    Constellation.WriteInfo("Sender : %s" % context.Sender.FriendlyName)
    Constellation.WriteInfo("test sans parametre")</pre><p></p>
<p>Ou avec des paramètres :</p>
<p></p><pre class="crayon-plain-tag">@Constellation.MessageCallback()
def DemoSeb5(a, b, context):
    "Test du contexte avec parametre"
    Constellation.WriteInfo("Sender : %s" % context.Sender.FriendlyName)
    Constellation.WriteInfo("a = %s et b = %s" % (a, b))</pre><p></p>
<p>Il faut juste que le dernier argument soit nommé “context”. Notez qu’il ne fait pas partie de la signature de votre MessageCallback.</p>
<p>Ci-dessus, le 1er exemple est un MessageCallback caché et sans paramètre et le 2ème n’a que deux paramètres “a” et “b”.</p>
<p>L’objet “context” correspondant à la classe “<em>Constellation.Package.MessageContext</em>”. Vous retrouvez les propriétés suivantes :</p>
<ul>
<li>IsSaga : indique si le message reçu appartient à une Saga</li>
<li>SagaId : identifiant de la Saga (si <em>IsSaga = true</em>)</li>
<li>Scope : scope d’envoi du message reçu
<ul>
<li>Type : type du scope (All, Group, Package, Sentinel, Others)</li>
<li>Args : arguments du scope (ex : nom du groupe, du package ou de la sentinelle)</li>
</ul>
</li>
<li>Sender : représente l’émetteur du message
<ul>
<li>ConnectionId : identifiant de connexion unique de l’émetteur</li>
<li>Type : type de l’émetteur (ConsumerHub, ConstellationHub, ConsumerHttp ou ConstellationHttp)</li>
<li>FriendlyName : nom de l’émetteur</li>
</ul>
</li>
</ul>
<h3>Répondre aux Sagas</h3>
<p>Votre méthode peut également retourner une réponse à l’appelant, c’est ce que l’on appelle <a href="/concepts/messaging-message-scope-messagecallback-saga/">une saga</a>. Pour cela vous pouvez spécifier le type de la valeur de retour dans le décorateur de la façon suivante :</p>
<p></p><pre class="crayon-plain-tag">@Constellation.MessageCallback(returnType='System.Boolean')
def DemoSaga(user, password):
    "Test de saga"
    Constellation.WriteInfo("User=%s Password=%s" % (user, password))
    return user == password</pre><p></p>
<p>Cependant il est recommandé d&rsquo;utiliser la description du MC pour spécifier le type de retour avec la syntaxe</p>
<p></p><pre class="crayon-plain-tag">:return &lt;type&gt;: &lt;description&gt;</pre><p></p>
<p>Par exemple :</p>
<p></p><pre class="crayon-plain-tag">@Constellation.MessageCallback()
def DemoSaga(user, password):
    '''
    Test de saga

    :param string user: The username
    :param string password: The password
    :return bool: if user match
    '''
    Constellation.WriteInfo("User=%s Password=%s" % (user, password))
    return user == password</pre><p></p>
<p>Cela marche également en combinant la récupération du contexte :</p>
<p></p><pre class="crayon-plain-tag">@Constellation.MessageCallback()
def DemoAuth(user, password, context):
    '''
    Test de saga

    :param string user: The username
    :param string password: The password
    :return bool: if user match
    '''
    Constellation.WriteInfo("Sender : %s" % context.Sender.FriendlyName)
    Constellation.WriteInfo("User=%s Password=%s" % (user, password))
    return user == password</pre><p></p>
<p align="left">Par exemple en ouvrant le “Message Callback Explorer” de la Console Constellation vous constaterez que votre MC “DemoAuth” est bien référencé comme retournant un “Booléen” en prenant deux arguments (car l’argument “context” n’est pas pris en compte dans la signature du MC) :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2018/04/image-14.png"><img class="colorbox-2511"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="Saga" src="https://developer.myconstellation.io/wp-content/uploads/2018/04/image_thumb-13.png" alt="Saga" width="484" height="142" border="0" /></a></p>
<p align="left">En invoquant cette méthode depuis la console, vous recevrez alors la réponse du package, ici un booléen :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/08/image-74.png"><img class="colorbox-2511"  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/2016/08/image_thumb-63.png" alt="image" width="350" height="241" border="0" /></a></p>
<p align="left">Dans les logs, on retrouve bien la trace de l’invocation de notre Saga avec le “contexte” :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/08/image-75.png"><img class="colorbox-2511"  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/2016/08/image_thumb-64.png" alt="image" width="350" height="104" border="0" /></a></p>
<p>(le FriendlyName de la Console Constellation est “<em>Consumer/ControlCenter:&lt;user&gt;</em>”).</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/client-api/python-api/messagecallbacks-exposer-des-methodes-python/">MessageCallback : Exposer des méthodes Python</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://developer.myconstellation.io/client-api/python-api/messagecallbacks-exposer-des-methodes-python/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Envoyer des messages et invoquer des MessageCallbacks en Python</title>
		<link>https://developer.myconstellation.io/client-api/python-api/envoyer-des-messages-et-invoquer-des-messagecallbacks-en-python/</link>
					<comments>https://developer.myconstellation.io/client-api/python-api/envoyer-des-messages-et-invoquer-des-messagecallbacks-en-python/#respond</comments>
		
		<dc:creator><![CDATA[Sebastien Warin]]></dc:creator>
		<pubDate>Wed, 24 Aug 2016 09:47:10 +0000</pubDate>
				<category><![CDATA[Python API]]></category>
		<category><![CDATA[Message]]></category>
		<category><![CDATA[MessageCallback]]></category>
		<category><![CDATA[MessageScope]]></category>
		<category><![CDATA[Saga]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[SendMessage]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=2509</guid>

					<description><![CDATA[<p>Envoyer un message Pour envoyer un message et donc invoquer un MessageCallback depuis un package Python vous devez utiliser la méthode “Constellation.SendMessage”. Par exemple : [crayon-6972d48e1c854418271352/] Ici par exemple on envoi un message au package “SMS” pour invoquer le MessageCallback</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/client-api/python-api/envoyer-des-messages-et-invoquer-des-messagecallbacks-en-python/">Envoyer des messages et invoquer des MessageCallbacks en Python</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h3>Envoyer un message</h3>
<p>Pour envoyer un message et donc <a href="/concepts/messaging-message-scope-messagecallback-saga/">invoquer un MessageCallback</a> depuis un package Python vous devez utiliser la méthode “<em>Constellation.SendMessage</em>”. Par exemple :</p>
<p></p><pre class="crayon-plain-tag">Constellation.SendMessage("SMS", "SendMessage", [ "+33676903634", "Bonjour Constellation" ])</pre><p></p>
<p>Ici par exemple on envoi un message au package “SMS” pour invoquer le MessageCallback “SendMessage” en passant en argument deux paramètres de type string.</p>
<p>Le MessageCallbacks Explorer de la Console Constellation permet de lister l’ensemble des MC déclarés par les packages de votre Constellation.</p>
<p>Par exemple, avec le package <a href="/package-library/nest/">Nest</a> déployé dans votre Constellation, on retrouvera un MessageCallback  “SetTargetTemperature” pour piloter la température de consigne d’un thermostat Nest.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-21.png"><img class="colorbox-2509"  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/2016/09/image_thumb-20.png" alt="image" width="350" height="99" border="0" /></a></p>
<p>Pour l’invoquer depuis notre code Python :</p>
<p></p><pre class="crayon-plain-tag">Constellation.SendMessage("Nest", "SetTargetTemperature", [ "thermostatId", 19 ], Constellation.MessageScope.package)</pre><p></p>
<p>On peut également passer en paramètre un objet complexe. Par exemple le MC “AreaArm” du package Paradox permet d’armer le système d’alarme en passant en paramètre un objet “ArmingRequestData” contenant le secteur à armer, le mode d’armement et le PIN.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-22.png"><img class="colorbox-2509"  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/2016/09/image_thumb-21.png" alt="image" width="350" height="121" border="0" /></a></p>
<p>Le code Python pour invoquer ce MC sera alors :</p>
<p></p><pre class="crayon-plain-tag">Constellation.SendMessage("Paradox", "AreaArm", { "Area":"All", "Mode":1, "PinCode":"0000" }, Constellation.MessageScope.package)</pre><p></p>
<p>Vous pouvez également passer plusieurs arguments à votre MC en combinant type simple et type complexe. Par exemple le MC “ShowNotification” du package <a href="/package-library/xbmc/">Xbmc</a> permettant d’afficher une notification sur une interface Kodi/XBMC prend deux paramètres : le nom d l’hôte XBMC (un type simple) et le détail de la notification à afficher (un type complexe) :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-23.png"><img class="colorbox-2509"  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/2016/09/image_thumb-22.png" alt="image" width="350" height="143" border="0" /></a></p>
<p></p><pre class="crayon-plain-tag">Constellation.SendMessage("Xbmc", "ShowNotification", [ xbmcName, { "Title":"Hello Constellation", "Message":"Hello I'm Python" } ], Constellation.MessageScope.package)</pre><p></p>
<p>Les exemples de message ci-dessus sont tous envoyés à un package mais vous pouvez également envoyer vos messages à <a href="/concepts/messaging-message-scope-messagecallback-saga/">différents scopes</a>.</p>
<p>Par exemple pour envoyer le message “Demo” sans aucun paramètre au groupe A, on écrira :</p>
<p></p><pre class="crayon-plain-tag">Constellation.SendMessage("A", "Demo", {}, Constellation.MessageScope.group)</pre><p></p>
<p>Les scopes disponibles sont :</p>
<ul>
<li>group</li>
<li>package</li>
<li>sentinel</li>
<li>others</li>
<li>all</li>
</ul>
<p>Notez par ailleurs que le paramètre “MessageScope” de la méthode “SendMessage” est optionnel. Si il n’est pas spécifié le scope par défaut est “package”.</p>
<h3>Envoyer des messages avec réponse : les Sagas</h3>
<p>Si le MC que vous invoquez retourne un message de réponse, vous devez envoyer votre message dans une saga. Pour cela vous pouvez utiliser la méthode “SendMessageWithSaga” dans laquelle vous devrez spécifier la fonction qui sera invoquée lors de la réception de la réponse.</p>
<p>Par exemple reprenons le MessageCallback “AreaArm” du package Paradox :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-24.png"><img class="colorbox-2509"  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/2016/09/image_thumb-23.png" alt="image" width="350" height="121" border="0" /></a></p>
<p align="left">Comme vous le constatez, ce MessageCallback retourne un “Boolean” pour indiquer si l’armement a bien été déclenché.</p>
<p align="left">On peut donc invoquer ce MC dans une saga et attacher un callback de réponse pour afficher dans le logs de notre package si l’armement a réussi :</p>
<p></p><pre class="crayon-plain-tag">Constellation.SendMessageWithSaga(lambda response:
   Constellation.WriteInfo("Arm result is %s" % response),
"Paradox", "AreaArm", { "Area":"All", "Mode":1, "PinCode":"0000" })</pre><p></p>
<p>Ici nous avons utilisé une fonction lambda pour simplifier la lecture mais vous pouvez également définir une fonction classique dans votre code.</p>
<p>Le paramètre “response” utilisé dans la fonction callback est l’objet de la réponse envoyé par le package qui a reçu votre message. Ici “response” est un “Boolean” car le MC “AreaArm” retourne un booléen mais il peut être de n’importe quel type (simple ou complexe).</p>
<p>Le MessageCallback Explorer de la Console Constellation vous donnera tous les détails.</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/client-api/python-api/envoyer-des-messages-et-invoquer-des-messagecallbacks-en-python/">Envoyer des messages et invoquer des MessageCallbacks en Python</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://developer.myconstellation.io/client-api/python-api/envoyer-des-messages-et-invoquer-des-messagecallbacks-en-python/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Messaging : Message, Scope, MessageCallback et Saga</title>
		<link>https://developer.myconstellation.io/concepts/messaging-message-scope-messagecallback-saga/</link>
					<comments>https://developer.myconstellation.io/concepts/messaging-message-scope-messagecallback-saga/#comments</comments>
		
		<dc:creator><![CDATA[Sebastien Warin]]></dc:creator>
		<pubDate>Wed, 16 Mar 2016 14:40:29 +0000</pubDate>
				<category><![CDATA[Concepts]]></category>
		<category><![CDATA[MessageCallback]]></category>
		<category><![CDATA[MessageScope]]></category>
		<category><![CDATA[Saga]]></category>
		<category><![CDATA[Messaging]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=1349</guid>

					<description><![CDATA[<p>Tous systèmes connectés dans Constellation (les packages réels ou virtuels et les consommateurs) peuvent tous envoyer ou recevoir des messages (sauf si des autorisations restreignent cela). Message &#38; Scope Les notions de base du Messaging de Constellation sont : Un message</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/concepts/messaging-message-scope-messagecallback-saga/">Messaging : Message, Scope, MessageCallback et Saga</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Tous systèmes connectés dans Constellation (les packages réels ou virtuels et les consommateurs) peuvent tous envoyer ou recevoir des messages (sauf si des autorisations restreignent cela).</p>
<h3>Message &amp; Scope</h3>
<p>Les notions de base du Messaging de Constellation sont :</p>
<p>Un message :</p>
<ul>
<li>porte obligatoirement une clé (le MessageKey), en quelque sorte l’équivalent du “Sujet” d’un mail.</li>
<li>peut contenir optionnellement un contenu, nommé “Data”</li>
<li>est envoyé à un scope.</li>
</ul>
<p>Un scope :</p>
<ul>
<li>défini les destinataires d’un message</li>
<li>peut être de différents types :
<ul>
<li>All : c’est à dire que tous les systèmes connectés dans Constellation recevront le message (y compris l’émetteur)</li>
<li>Other : tout le monde sauf l’émetteur</li>
<li>Package : cible un ou plusieurs packages</li>
<li>Sentinel : cible tous les packages hébergés sur les sentinelles visées par le scope</li>
<li>Group : cible les packages ou consommateurs appartenant aux groupes visés par le scope</li>
</ul>
</li>
</ul>
<p>Les scopes “Package”, “Sentinel” et “Group” peuvent déclarer une liste de packages, de sentinelles et de groupes.</p>
<ul>
<li>Lorsque l’on cible une sentinelle, on vise tous les packages qu’elle héberge.</li>
<li>Lorsque l’on cible un package, on vise toutes les instances de ce package sur les sentinelles de votre Constellation.</li>
</ul>
<p>Si vous voulez cibler un seul package en particulier, vous devez obligatoirement créer un scope de type Package et définir le nom du package <strong>préfixé</strong> du nom de la sentinelle avec la nomenclature “SENTINEL/Package”.</p>
<p>Chaque package ou consommateur peut s’inscrire à un groupe ou être inscrit d’office dans la configuration du serveur (lire <a href="/constellation-platform/constellation-server/fichier-de-configuration/">l’article sur les groupes</a>).</p>
<h3>MessageCallback</h3>
<p>Les messages dans Constellation servent essentiellement à invoquer des méthodes. On appelle cela des “MessageCallbacks” le fait de lier un message à une fonction de votre programme.</p>
<p>Il s’agit tout simplement déclarer une méthode de votre code comme « MessageCallback », c’est à dire que si le package reçoit un message dont la clé du message est le nom d’une méthode déclarée comme MessageCallback, alors cette méthode sera invoquée. Le contenu du message reçu (c’est à dire les “Datas”)  contiendra les paramètres de la méthode.</p>
<p>De la même façon, pour invoquer une méthode d’un autre package, il suffit d’envoyer un message dont la clé est la méthode à invoquer avec comme contenu de message les paramètres à passer à cette méthode.</p>
<h3>Les Sagas</h3>
<p>Chaque message envoyé dans Constellation est à sens unique. Il n’y a aucun retour.</p>
<p>Un message est envoyé à un scope,  il peut ne jamais être reçu (si « personne » n’est visée par le scope) ou à l’inverse être reçu par tout le monde.</p>
<p>Cependant il y a certain cas où il est indispensable d’obtenir une réponse à un message ! Comme en programmation, il n’y a pas que des procédures, il y a aussi des fonctions.</p>
<p>Pour cela, Constellation propose le concept de “Saga”. Une saga est un identifiant porté par un scope. Pour faire l’analogie, “<em>La guerre des étoiles</em>”, “<em>L&rsquo;Empire contre-attaque</em> » ou “<em>Le Retour du Jedi</em>” sont trois films distincts qui portent le même identifiant de Saga : “Star Wars”.</p>
<p>Il en va de même pour les messages Constellation. Pour “répondre”, il suffit d’envoyer un message “de réponse” à un scope qui vise l’émetteur du message original en prenant soin d’utiliser le même identifiant de saga.</p>
<p>Ainsi l’émetteur en recevant ce message, pourra savoir qu’il s’agit de la réponse à son message car il retrouvera le même identifiant de saga.</p>
<p>Bien entendu l’identifiant de Saga doit être unique et aléatoire pour chaque couple “Request / Response” .</p>
<p>De ce fait, lorsque l’on reçoit un message, si le scope porte un identifiant de Saga cela veut dire que l’émetteur a envoyé le message “dans une Saga”, il s’attend donc à recevoir une réponse. Le clé d’un message de réponse est toujours “__Response”.</p>
<h3>Auto-description des MessageCallbacks</h3>
<p>Chaque packages (virtuel ou non) doit ou devrait déclarer son “Package Descriptor”.</p>
<p>Il s’agit de la description du package qui contient entre autre les MessageCallbacks du package, c’est à dire les méthodes que le package expose dans la Constellation.</p>
<p>Le <a href="/constellation-platform/constellation-console/messagecallbacks-explorer/">MessageCallback Explorer</a> de la Console Constellation exploite les “Package Descriptors” connus pour créer la liste de l&rsquo;ensemble des MessageCallbacks exposés par les package d&rsquo;une Constellation avec le détail des paramètres en entrée et le type de retour. Il est également possible d&rsquo;invoquer ces MC avec une interface de test et de générer le code pour invoquer ces MC sur les différentes API de Constellation.</p>
<p><a href="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-59.png"><img loading="lazy" class="wp-image-4600 aligncenter colorbox-1349" title="MessageCallbacks Explorer" src="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-59-300x91.png" alt="MessageCallbacks Explorer" width="323" height="98" srcset="https://developer.myconstellation.io/wp-content/uploads/2017/05/image-59-300x91.png 300w, https://developer.myconstellation.io/wp-content/uploads/2017/05/image-59.png 605w" sizes="(max-width: 323px) 100vw, 323px" /></a></p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/concepts/messaging-message-scope-messagecallback-saga/">Messaging : Message, Scope, MessageCallback et Saga</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://developer.myconstellation.io/concepts/messaging-message-scope-messagecallback-saga/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>MessageCallbacks : exposez vos méthodes</title>
		<link>https://developer.myconstellation.io/client-api/net-package-api/messagecallbacks/</link>
					<comments>https://developer.myconstellation.io/client-api/net-package-api/messagecallbacks/#comments</comments>
		
		<dc:creator><![CDATA[Sebastien Warin]]></dc:creator>
		<pubDate>Wed, 16 Mar 2016 14:14:25 +0000</pubDate>
				<category><![CDATA[.NET API]]></category>
		<category><![CDATA[MessageCallback]]></category>
		<category><![CDATA[Saga]]></category>
		<category><![CDATA[Messaging]]></category>
		<category><![CDATA[MessageContent]]></category>
		<category><![CDATA[PackageDescriptor]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=1343</guid>

					<description><![CDATA[<p>Avant de tout, il est recommandé de lire cet article d’introduction aux concepts de Message, Scope, MessageCallback &#38; Saga dans Constellation pour bien comprendre le principe des MessageCallbacks. Exposer des méthodes Pour exposer une méthode .NET dans Constellation, il suffit</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/client-api/net-package-api/messagecallbacks/">MessageCallbacks : exposez vos méthodes</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Avant de tout, il est recommandé de lire <a href="/concepts/messaging-message-scope-messagecallback-saga/">cet article d’introduction aux concepts de Message, Scope, MessageCallback &amp; Saga</a> dans Constellation pour bien comprendre le principe des MessageCallbacks.</p>
<h3>Exposer des méthodes</h3>
<p>Pour exposer une méthode .NET dans Constellation, il suffit d&rsquo;ajouter l&rsquo;attribut “MessageCallback” sur une méthode :</p>
<p></p><pre class="crayon-plain-tag">[MessageCallback]
void MyMethod()
{
    PackageHost.WriteInfo("This is a MessageCallback !");
}</pre><p></p>
<p>Cela fonctionne que votre méthode soit privée ou public, d&rsquo;instance ou statique.</p>
<p>Une méthode marquée MessageCallback peut accepter zéro, un ou plusieurs paramètres :</p>
<p></p><pre class="crayon-plain-tag">[MessageCallback]       
void MyMethodWithMultipleParameters(string input, int number, bool boolean)
{
    PackageHost.WriteInfo("Input= {0} - Number: {1} - Boolean: {2}", input, number, boolean);
}</pre><p></p>
<p>De plus chaque paramètre peut être de type simple ou complexe :</p>
<p></p><pre class="crayon-plain-tag">[MessageCallback] 
void MyMethodWithComplexParameter(UserInfo user)
{
    PackageHost.WriteInfo("User: {0} &amp; Password = {1}", user.User, user.Password); 
}</pre><p></p>
<p>Par défaut seules les méthodes marquées [MessageCallback] sur votre classe ”<a href="/client-api/net-package-api/les-bases-des-packages-net/">IPackage</a>” sont enregistrées.</p>
<p>Si vous souhaitez également enregistrer les MessageCallbacks référencés de vos autres types, vous devez appeler la méthode “RegisterMessageCallbacks” en passant en paramètre l&rsquo;instance ou le type à enregistrer :</p>
<p></p><pre class="crayon-plain-tag">PackageHost.RegisterMessageCallbacks(source);</pre><p></p>
<h3>Testez vos MessageCallbacks depuis la Console Constellation</h3>
<p>Si vous <a href="/constellation-platform/constellation-sdk/publier-package-visual-studio/">publiez votre package</a> ou <a href="/getting-started/creez-votre-premier-package-constellation-en-csharp/">démarrer votre package depuis VS</a>  avec les trois méthodes ci-dessus, vous retrouverez ces trois MessageCallbacks dans <a href="/constellation-platform/constellation-console/messagecallbacks-explorer/">l’explorateur </a>:</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/03/image-116.png"><img class="colorbox-1343"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="MessageCallback Explorer" src="https://developer.myconstellation.io/wp-content/uploads/2016/03/image_thumb-93.png" alt="MessageCallback Explorer" width="424" height="191" border="0" /></a></p>
<p align="left">Tout y est décrit, y compris les types complexes :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/03/image-117.png"><img class="colorbox-1343"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Description des types" src="https://developer.myconstellation.io/wp-content/uploads/2016/03/image_thumb-94.png" alt="Description des types" width="424" height="165" border="0" /></a></p>
<p align="left">Vous pourrez alors directement tester vos MC depuis la Console :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/03/image-118.png"><img class="colorbox-1343"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="MessageCallback Explorer" src="https://developer.myconstellation.io/wp-content/uploads/2016/03/image_thumb-95.png" alt="MessageCallback Explorer" width="424" height="58" border="0" /></a></p>
<p align="left">Ce qui compte tenu du code donné en exemple ci-dessus affichera des messages dans les logs Constellation visible sur la <a href="/constellation-platform/constellation-console/console-log/">Console Log</a> :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/03/image-119.png"><img class="colorbox-1343"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Demo" src="https://developer.myconstellation.io/wp-content/uploads/2016/03/image_thumb-96.png" alt="Demo" width="424" height="25" border="0" /></a></p>
<h3 align="left">Personnaliser le nom du MessageCallback</h3>
<p align="left">Vous pouvez également changer le nom du MessageCallback sans forcement changer le nom de votre méthode :</p>
<p></p><pre class="crayon-plain-tag">[MessageCallback(Key="Logon")]
void MyMethodWithComplexParameter(UserInfo user)
{
    PackageHost.WriteInfo("User: {0} &amp; Password = {1}", user.User, user.Password);
}</pre><p></p>
<p align="left">Ici la méthode se nomme toujours “MyMethodWithComplexParameter” dans notre code C# mais est vue dans Constellation comme le MessageCallback nommé “Logon” :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/03/image-120.png"><img class="colorbox-1343"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="MessageCallback Explorer" src="https://developer.myconstellation.io/wp-content/uploads/2016/03/image_thumb-97.png" alt="MessageCallback Explorer" width="424" height="212" border="0" /></a></p>
<h3 align="left">MessageCallback caché</h3>
<p align="left">Vous pouvez aussi exposer des MessageCallbacks que vous ne souhaitez “rendre publique”. En d&rsquo;autre mots, vous ne souhaitez pas que votre MC soit référencé dans la description de votre package.</p>
<p align="left">Exemple : vous avez un package qui envoie des messages à un groupe pour prévenir de l’arrivée d’un événement (ex: le téléphone sonne). Vous souhaitez, dans le code de votre package, déclencher une méthode lorsque cet événement se produit. Autrement dit, vous créez une méthode marquée “MessageCallback“ qui porte le même nom que le MessageKey envoyé par l’autre package (le même nom de méthode ou via la propriété Key comme vu ci-dessus).</p>
<p align="left">Ainsi, comme votre package fait partie du groupe cible, lorsque le téléphone sonne, l’autre package envoie un message au groupe, vous recevez donc le message et comme vous avez un MessageCallback du même nom, votre méthode est invoquée !</p>
<p align="left">C’est parfait à l’exception que tout le monde “voit l’existence” de cette méthode et peuvent tous l’invoquer !</p>
<p align="left">Deux solutions :</p>
<ul>
<li>
<div align="left">Cacher le MessageCallback (= ne pas le déclarer dans la description du package)</div>
</li>
<li>
<div align="left">Vérifier l’émetteur</div>
</li>
</ul>
<p align="left">Pour cacher un MC, il suffit simple de définir la propriété “IsHidden” à vrai :</p>
<p></p><pre class="crayon-plain-tag">[MessageCallback(IsHidden = true)]
void HiddenMethod()
{
    PackageHost.WriteInfo("This is a MessageCallback !");
}</pre><p></p>
<p align="left">Ainsi la méthode, n&rsquo;apparaîtra nulle part, personne ne pourra savoir que votre package “écoute” des messages dont la clé est ici “HiddenMethod”.</p>
<h3 align="left">MessageContext</h3>
<p align="left">Vous pouvez, dans le code d&rsquo;un “MessageCallback”, accéder au contexte du message reçu via la propriété “<em>MessageContext.Current</em>”.</p>
<p align="left">Le contexte du message contient notamment le MessageSender (identifié de l’émetteur du message) et le MessageScope (scope dans lequel le message a été envoyé ).</p>
<p align="left">Par exemple on pourrait écrire :</p>
<p></p><pre class="crayon-plain-tag">[MessageCallback(IsHidden = true)]
void HiddenMethod()
{
    if(MessageContext.Current.Sender.FriendlyName == "SENTINEL-DEMO/MySafePackage")
    {
        PackageHost.WriteInfo("OK j’autorise le package MySafePackage de la sentinelle SENTINEL-DEMO");
    }
    else
    {
        PackageHost.WriteWarn("Je refuse que {0} puisse invoquer cette méthode !", MessageContext.Current.Sender.FriendlyName);
    }
}</pre><p></p>
<h3>Répondre à une saga</h3>
<p>Comme nous l’avons vu dans les concepts, il est possible de répondre à un message en renvoyant un message avec le même identifiant de saga. De ce fait, un MessageCallback peut renvoyer une réponse.</p>
<p>Dans la pratique, il suffit de regarder dans le contexte du message si c’est une saga (c’est à dire que le scope porte un identifiant de saga). Si c’est une saga, vous pouvez appeler la méthode d’extension “<em>SendResponse</em>” qui se chargera pour vous d’envoyer le contenu de votre message dans un scope portant le même identifiant de saga et à destination du package émetteur.</p>
<p>De plus, pour indiquer que le MessageCallback répond aux sagas, on indique quel est le type de l’objet de réponse dans l&rsquo;attribut [MessageCallback] avec la propriété <em>ResponseType</em>.</p>
<p>Par exemple :</p>
<p></p><pre class="crayon-plain-tag">[MessageCallback(Key="Logon", ResponseType=typeof(bool))]
void MyMethodWithComplexParameter(UserInfo user)
{
    PackageHost.WriteInfo("User: {0} &amp; Password = {1}", user.User, user.Password);

    if (MessageContext.Current.IsSaga)
    {
        MessageContext.Current.SendResponse(user.User == user.Password);
    }
}</pre><p></p>
<p>Avec Constellation 1.8, la syntaxe est encore plus simple. Vous pouvez simplement écrire votre MessageCallback avec une fonction .NET, c&rsquo;est à dire une méthode qui retourne (<em>return</em>) une valeur :</p>
<p></p><pre class="crayon-plain-tag">[MessageCallback(Key="Logon")]
bool MyMethodWithComplexParameter(UserInfo user)
{
    PackageHost.WriteInfo("User: {0} &amp; Password = {1}", user.User, user.Password);

    return user.User == user.Password;
}</pre><p></p>
<p>La propriété “ResponseType” du MessageCallback est automatiquement définie avec le type de retour de la méthode. C’est l’API .NET qui se chargera d’envoyer la réponse si le message est reçu est une saga. La réponse renvoyée étant l’objet retourné par votre méthode, dans l’exemple ci-dessus un booléen.</p>
<p>Ainsi en republiant le package avec le code ci-dessus, vous constaterez dans le <a href="/constellation-platform/constellation-console/messagecallbacks-explorer/">MessageCallbacks Explorer</a> que votre MessageCallback indique son type de réponse dans le cas d&rsquo;une saga :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/03/image-121.png"><img class="colorbox-1343"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="MessageCallback avec saga" src="https://developer.myconstellation.io/wp-content/uploads/2016/03/image_thumb-98.png" alt="MessageCallback avec saga" width="424" height="209" border="0" /></a></p>
<p align="left">Vous pourrez alors tester votre MessageCallback :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/03/image-122.png"><img class="colorbox-1343"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Envoyer un message dans une saga" src="https://developer.myconstellation.io/wp-content/uploads/2016/03/image_thumb-99.png" alt="Envoyer un message dans une saga" width="424" height="244" border="0" /></a></p>
<p align="left">Et visualisez le message de retour, ici un booléen :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/03/image-123.png"><img class="colorbox-1343"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Réponse d'une saga" src="https://developer.myconstellation.io/wp-content/uploads/2016/03/image_thumb-100.png" alt="Réponse d'une saga" width="424" height="438" border="0" /></a></p>
<h3>Décrire ses MessageCallbacks</h3>
<p>Pour finir il est vivement conseillé de décrire ses MessageCallbacks et les types utilisés en paramètre ou en réponse.</p>
<p>Vous avez deux possibilités :</p>
<ul>
<li>Utilisez la propriété “Description” sur l’attribut MessageCallback (mais limité aux MC et non aux types)</li>
<li>Utilisez les commentaires de documentation XML</li>
</ul>
<p>Pour gagner en productivité, je vous recommande l’extension Visual Studio <a href="http://submain.com/products/ghostdoc.aspx">GhostDoc de SubMain</a> pour générer automatiquement des commentaires de documentation XML dans votre code .NET.</p>
<p>Ainsi ajoutons des commentaires de documentation XML sur nos MessageCallbacks et sur la classe UserInfo utilisée dans nos exemples comme paramètre de notre MC :</p>
<p></p><pre class="crayon-plain-tag">/// &lt;summary&gt;
/// Methode d'identification d'un utilisateur.
/// &lt;/summary&gt;
/// &lt;param name="user"&gt;L'utilisateur à identifier.&lt;/param&gt;
/// &lt;returns&gt;&lt;c&gt;true&lt;/c&gt; si identifié&lt;/returns&gt;
[MessageCallback(Key="Logon")]
bool MyMethodWithComplexParameter(UserInfo user)
{
    PackageHost.WriteInfo("User: {0} &amp; Password = {1}", user.User, user.Password);

    return user.User == user.Password;
}

/// &lt;summary&gt;
/// Classe decrivrant un utilisateur
/// &lt;/summary&gt;
public class UserInfo
{
    /// &lt;summary&gt;
    /// Le nom d'utilisateur
    /// &lt;/summary&gt;
    public string User { get; set; }

    /// &lt;summary&gt;
    /// Le mot de passe de l'utilisateur
    /// &lt;/summary&gt;
    public string Password { get; set; }
}</pre><p></p>
<p>Si vous redéployez le package, vous observerez que l&rsquo;ensemble des MessageCallbacks et des paramètres sont décrits par vos commentaires XML :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/03/image-124.png"><img class="colorbox-1343"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="MessageCallback documenté" src="https://developer.myconstellation.io/wp-content/uploads/2016/03/image_thumb-101.png" alt="MessageCallback documenté" width="424" height="128" border="0" /></a></p>
<h3>S’abonner et recevoir les messages d’un groupe</h3>
<p>Comme <a href="/concepts/messaging-message-scope-messagecallback-saga/">vous le savez</a>, il existe plusieurs type de scope pour recevoir un message. Par défaut votre package recevra les messages adressés au scope “All” et “Other” (si il n’est pas l’émetteur du message) mais aussi et surtout ceux destinés au scope de sa sentinelle et/ou de son package.</p>
<p>Il y a un dernier type de scope fort utile : “les groupes”. Pour recevoir des messages destinés à un groupe, il faut d&rsquo;abord s’abonner au groupe.</p>
<p>Vous avez deux manières d’ajouter votre package dans un groupe :</p>
<ul>
<li>Depuis la configuration du serveur</li>
<li>Depuis le code de votre package</li>
</ul>
<p>La première méthode se réalise dans la configuration de votre package directement dans la configuration du serveur Constellation.</p>
<p>Il suffit d’ajouter un élément “group” en indiquant les noms des groupes à rejoindre.</p>
<p></p><pre class="crayon-plain-tag">&lt;sentinel name="PO-SWARIN" credential="StandardAccess"&gt;
    &lt;packages&gt;        
        &lt;package name="HWMonitor" enable="true"&gt;&lt;/package&gt;  
        &lt;package name="ConstellationPackageConsole1" enable="true"&gt;&lt;/package&gt; 
        &lt;package name="MonPremierPackage" enable="true"&gt;
            &lt;groups&gt;
                &lt;group name="MonGroupDemo" /&gt;
            &lt;/groups&gt;
            &lt;settings&gt;
                &lt;setting key="Interval" value="2000" /&gt;
            &lt;/settings&gt;
        &lt;/package&gt;  
    &lt;/packages&gt;                
 &lt;/sentinel&gt;</pre><p></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/03/image-149.png"><img class="colorbox-1343"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="Ajout de groupe dans la configuration" src="https://developer.myconstellation.io/wp-content/uploads/2016/03/image_thumb-126.png" alt="Ajout de groupe dans la configuration" width="424" height="261" border="0" /></a></p>
<p style="text-align: left;" align="center">Vous pouvez aussi utiliser<a href="/constellation-platform/constellation-console/gerer-packages-avec-la-console-constellation/#Editer_les_groupes_dun_package"> la Console Constellation pour éditer les groupes</a> de chaque package.</p>
<p align="left">Autre manière, directement dans votre code en utilisant la méthode “<em>PackageHost.SubscribeMessages</em>” (ou <em>PackageHost.UnsubscribeMessages</em>).</p>
<p align="left">Par exemple :</p>
<p></p><pre class="crayon-plain-tag">PackageHost.SubscribeMessages("MonGroupDemo");</pre><p></p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/client-api/net-package-api/messagecallbacks/">MessageCallbacks : exposez vos méthodes</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://developer.myconstellation.io/client-api/net-package-api/messagecallbacks/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Consommer Constellation avec l&#8217;API Javascript</title>
		<link>https://developer.myconstellation.io/client-api/javascript-api/consommer-constellation-api-javascript/</link>
					<comments>https://developer.myconstellation.io/client-api/javascript-api/consommer-constellation-api-javascript/#respond</comments>
		
		<dc:creator><![CDATA[Sebastien Warin]]></dc:creator>
		<pubDate>Thu, 18 Aug 2016 14:41:46 +0000</pubDate>
				<category><![CDATA[Javascript API]]></category>
		<category><![CDATA[StateObject]]></category>
		<category><![CDATA[Saga]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[SendMessage]]></category>
		<category><![CDATA[ReceiveMessage]]></category>
		<category><![CDATA[Consumer]]></category>
		<category><![CDATA[jQuery]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=2327</guid>

					<description><![CDATA[<p>Connecter une page HTML avec l’API Javascript Vous pouvez soit utiliser le gestionnaire de package Nuget depuis Visual Studio pour installer la dernière version du package “Constellation.Javascript” et ses dépendances : Ou bien utiliser (ou copier en local) les scripts</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/client-api/javascript-api/consommer-constellation-api-javascript/">Consommer Constellation avec l&rsquo;API Javascript</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h3>Connecter une page HTML avec l’API Javascript</h3>
<p>Vous pouvez soit utiliser le gestionnaire de package Nuget depuis Visual Studio pour installer la dernière version du package “Constellation.Javascript” et ses dépendances :</p>
<p align="center"><img class="colorbox-2327"  src="https://developer.myconstellation.io/wp-content/uploads/2016/07/image.png" alt="image" /></p>
<p>Ou bien utiliser (ou copier en local) les scripts des CDN en ajoutant dans votre code HTML les balises suivantes :</p>
<p></p><pre class="crayon-plain-tag">&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;</pre><p></p>
<p>Une fois les scripts ajoutés dans votre page vous devez initialiser le client Constellation en spécifiant l’URL de votre serveur Constellation, la clé d’accès et le “Friendly name” de votre page :</p>
<p></p><pre class="crayon-plain-tag">var constellation = $.signalR.createConstellationConsumer("http://localhost:8088", "123456789", "Test API JS");</pre><p></p>
<p>Vous pouvez <a href="/constellation-platform/constellation-console/gerer-credentials-avec-la-console-constellation/">créer une clé d’accès depuis la Console Constellation</a> ou en <a href="/constellation-platform/constellation-server/fichier-de-configuration/#Section_credentials">éditant le fichier de configuration du serveur</a>.</p>
<p>Enfin ajoutons un handler sur le changement d’état de la connexion pour afficher le message “Je suis connecté” dans la console de votre navigateur par exemple lorsque la connexion à Constellation est établie :</p>
<p></p><pre class="crayon-plain-tag">constellation.connection.stateChanged(function (change) {
    if (change.newState === $.signalR.connectionState.connected) {
        console.log("Je suis connecté");
    }
});</pre><p></p>
<p>Il ne reste plus qu’à lancer la connexion en invoquant la méthode Start :</p>
<p></p><pre class="crayon-plain-tag">constellation.connection.start();</pre><p></p>
<p>Et voilà, votre page est connectée à votre Constellation.</p>
<h3>Envoyer des messages et invoquer des MessageCallbacks</h3>
<h4>Envoyer des messages</h4>
<p>Pour envoyer des messages et donc invoquer des MessageCallbacks vous devez utiliser la méthode “<em>constellation.server.sendMessage</em>” en spécifiant :</p>
<ul>
<li>Le scope</li>
<li>La clé du message</li>
<li>Le contenu du message (= les paramètres du MessageCallback)</li>
</ul>
<p>Par exemple, avec le package <a href="/package-library/nest/">Nest </a>déployé dans votre Constellation, on retrouvera un MessageCallback  “SetTargetTemperature” pour piloter la température de consigne d’un thermostat Nest.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-21.png"><img class="colorbox-2327"  loading="lazy" title="image" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/image_thumb-20.png" alt="image" width="350" height="99" border="0" /></a></p>
<p align="left">N’hésitez pas à utiliser le <a href="/constellation-platform/constellation-console/messagecallbacks-explorer/">MessageCallback Explorer</a> pour découvrir l’ensemble des MessageCallbacks exposés par les packages de votre Constellation.</p>
<p>Pour invoquer le MessageCallback  “SetTargetTemperature” depuis votre page Web en passant en paramètre l&rsquo;ID du thermostat et la température de consigne :</p>
<p></p><pre class="crayon-plain-tag">constellation.server.sendMessage({ Scope: 'Package', Args: ['Nest'] }, 'SetTargetTemperature', 'thermostatId', 19);</pre><p></p>
<p>Vous pouvez également passer plusieurs arguments à votre MC combinant type simple et type complexe.</p>
<p>Par exemple le MC “ShowNotification” du package <a href="/package-library/xbmc/">Xbmc </a>permettant d’afficher une notification sur une interface Kodi/XBMC prend deux paramètres : le nom d l’hôte XBMC (un type string) et le détail de la notification à afficher (un type complexe) :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-23.png"><img class="colorbox-2327"  loading="lazy" title="image" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/image_thumb-22.png" alt="image" width="350" height="143" border="0" /></a></p>
<p></p><pre class="crayon-plain-tag">constellation.server.sendMessage({ Scope: 'Package', Args: ['Xbmc'] }, 'ShowNotification', xbmcName, { "Title":"Hello", "Message":"Hello from JS" });</pre><p></p>
<p>Bien entendu vous pouvez invoquer des MessageCallbacks de n’importe quel package, réel (programme Linux/Windows) ou virtuel (Arduino/ESP) ou même sur d’autres consommateurs (pages Web par exemple).</p>
<p>Ainsi vos pages Web peuvent, en envoyant des messages, invoquer des méthodes sur n&rsquo;importe quel système connecté dans votre Constellation.</p>
<p>Par exemple dans l’article sur les ESP/Arduinos, notre ESP8266 exposait un MC “Reboot” pour redémarrer la puce. Si l’on souhaite redémarrer notre Arduino/ESP depuis une page Web, il suffit d’envoyer un message sans paramètre au bon scope. Par exemple :</p>
<p></p><pre class="crayon-plain-tag">constellation.server.sendMessage({ Scope: 'Sentinel', Args: ['MyArduino'] }, 'Reboot');</pre><p></p>
<p>Ici le scope est “Sentinel” avec l’argument “MyArduino”, c’est à dire que le message “Reboot” sera envoyé à tous les packages de la sentinelle “MyArduino”.</p>
<p>Les <a href="/concepts/messaging-message-scope-messagecallback-saga/">scopes</a> peuvent être :</p>
<ul>
<li>Sentinel</li>
<li>Package</li>
<li>Group</li>
<li>Others</li>
<li>All</li>
</ul>
<p>La propriété “Args” de l’objet scope est un tableau contenant le nom des groupes, des sentinelles ou packages en fonction du type de scope sélectionné. Seuls les scopes “All” et “Others” n’ont pas besoin d’argument.</p>
<h4>Envoyer des messages avec réponse : les sagas</h4>
<p>Les <a href="https://developer.myconstellation.io/concepts/messaging-message-scope-messagecallback-saga/">Sagas</a> permettent de lier des messages et donc de créer des couples de “requêtes / réponses”.</p>
<p>Avec la libraire JavaScript, il est possible d’envoyer des messages dans une saga et d’enregistrer un callback pour traiter la réponse.</p>
<p>Par exemple, le package “<a href="/package-library/networktools/">NetworkTools</a>” expose un MC “Ping” permettant de réaliser un ping réseau. Le résultat du ping est retourné dans un message de réponse (un Int64 représentant le temps du réponse du ping) :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-25.png"><img class="colorbox-2327"  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/2016/09/image_thumb-24.png" alt="image" width="350" height="155" border="0" /></a></p>
<p align="left">De ce fait pour réaliser un ping vers « www.google.fr » depuis une page Web :</p>
<p></p><pre class="crayon-plain-tag">constellation.server.sendMessageWithSaga(function(response) {
        console.log("Ping %s ms", response.Data);
    }, { Scope: 'Package', Args: ['NetworkTools'] }, 'Ping', "www.google.fr");</pre><p></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-26.png"><img class="colorbox-2327"  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/2016/09/image_thumb-25.png" alt="image" width="350" height="160" border="0" /></a></p>
<p align="left"><a href="/client-api/arduino-esp-api/recevoir-des-messages-et-exposer-des-methodes-messagecallback-sur-arduino-esp/#Exposer_des_MessageCallbacks_avec_reponse_les_sagas">Souvenez-vous de notre package virtuel de notre ESP8266 / Arduino</a>, on exposait un MessageCallback “Addition” capable de réaliser une addition locale (sur le CPU de l’Arduino ou ESP) en prenant en paramètre deux entiers. Le résultat était retourné dans la saga.</p>
<p></p><pre class="crayon-plain-tag">constellation.server.sendMessageWithSaga(function(response) {
        console.log("Le resultat de 40+2 par l'Arduino est %s", response.Data);
    }, { Scope: 'Sentinel', Args: ['MyArduino'] }, 'Addition', 40, 2);</pre><p></p>
<p>Ainsi vos pages Web peuvent invoquer des méthodes et exploiter la réponse de tous les systèmes connectés sur Constellation exposant des MessageCallbacks.</p>
<h3>Recevoir des messages</h3>
<p>Une page Web connectée sur Constellation peut elle même recevoir des messages et donc exposer des MessageCallbacks que d’autres consommateurs (autres pages Web) ou packages (réels et virtuels) pourront invoquer.</p>
<p>Ceci dit un consommateur tel qu’une page Web n’a pas réellement d’existence. Autrement dit elle n’a pas d’identité et donc ne peut recevoir que des messages adressés à un groupe qu’elle devra joindre.</p>
<p>Pour joindre un groupe vous devez utiliser la méthode “subscribeMessages“ (et “unSubscribeMessages” pour en sortir). Vous pouvez joindre autant de groupe que vous souhaitez.</p>
<p>Par exemple, pour ajouter votre page au groupe “Demo” :</p>
<p></p><pre class="crayon-plain-tag">constellation.server.subscribeMessages("Demo");</pre><p></p>
<p>Vous pourrez ensuite recevoir les messages envoyés dans ce groupe en ajoutant un handler sur le “onReceiveMessage” :</p>
<p></p><pre class="crayon-plain-tag">constellation.client.onReceiveMessage(function (message) {
    console.log("Message recu !", message);
});</pre><p></p>
<p>Dans ce handler vous recevrez TOUS les messages (quelque soit la clé du message).</p>
<p>Vous avez aussi un moyen plus simple consistant à définir un handler pour une clé de message spécifiquement via la méthode “registerMessageCallback”.</p>
<p>Par exemple :</p>
<p></p><pre class="crayon-plain-tag">constellation.client.registerMessageCallback("ChangeTitle", function (msg) {
    document.title = msg.Data;
});
constellation.client.registerMessageCallback("HelloWorld", function (msg) {
    alert("Hello World");
});</pre><p></p>
<p>Ici on enregistre deux MessageCallbacks.</p>
<p>Si votre page reçoit un MessageCallback “HelloWorld”, une alerte sera ouverte, si elle reçoit un MessageCallback “ChangeTitle”, le titre de votre page sera modifié avec l’argument passé dans le MC.</p>
<p>Imaginez par exemple que vous ouvrez une page Web en plein écran sur différents devices dont vous n’avez pas de contrôle (par exemple des écrans Dashboard). Sur cette page vous affichez différentes données en temps réel, par exemple basées sur les StateObjects Constellation.</p>
<p>Vous modifiez votre page et vous souhaitez donc la rafraîchir sur tous les navigateurs qui ont ouvert votre page pour recharger la nouvelle version.</p>
<p>Pour ce faire, vous pouvez facilement exposer un MessageCallback “ReloadMe” qui recharge la page avec le code :</p>
<p></p><pre class="crayon-plain-tag">constellation.client.registerMessageCallback("ReloadMe", function (msg) {
    location.reload();
});</pre><p></p>
<p>Puis vous ajoutez votre page dans le groupe “ControlPage” :</p>
<p></p><pre class="crayon-plain-tag">constellation.server.subscribeMessages("ControlPage");</pre><p></p>
<p>Dans ce fait, vous pouvez maintenant créer une page “cachée” avec un bouton pour invoquer le MessageCallback “ReloadMe” sur le groupe “ControlPage” afin de recharger toutes les navigateurs qui ont ouvert votre page par la ligne :</p>
<p></p><pre class="crayon-plain-tag">constellation.server.sendMessage({ Scope:'Group', Args:['ControlPage'] }, "ReloadMe", {});</pre><p></p>
<p>Bien entendu, comme vos pages HTML peuvent enregistrer autant de MessageCallbacks qu’elles souhaitent et que ces MessageCallbacks sont invocables depuis n’importe quel système connecté à Constellation, d’autres pages Web, des objets à base d’Arduino, ESP ou autre, des programmes Python, .NET, etc… vous pouvez imaginer tout type d’usage.</p>
<h3>Consommer des StateObjects</h3>
<p>Pour consommer des StateObjects produits par des packages (virtuels ou réels) de votre Constellation, vous avez deux méthodes : l’évènement “onUpdateStateObject” ou les StateObjectLinks.</p>
<p>La première méthode consiste à enregistre un ou plusieurs handlers sur l’évènement “onUpdateStateObject” :</p>
<p></p><pre class="crayon-plain-tag">constellation.client.onUpdateStateObject(function (stateobject) {
    console.log(stateobject);
});</pre><p></p>
<p>Les handlers seront déclenchés à chaque mise à jour ou interrogation des StateObjects de votre page quelque soit le StateObject.</p>
<p>Pour interroger un ou plusieurs StateObjects à un instant T vous disposez de la méthode “requestStateObjects”.</p>
<p>Pour vous abonner aux mises à jour d’un ou plusieurs StateObjects, vous disposez de la méthode “subscribeStateObjects” (et “unSubscribeStateObjects” pour vous désabonner).</p>
<p>Enfin la méthode “requestSubscribeStateObjects” réalise un “requestStateObjects” et un “subscribeStateObjects” c’est à dire que la méthode demande la valeur actuelle du ou des StateObjects et s’abonne auprès du serveur Constellation pour être notifiée des mises à jour.</p>
<p>Toutes ces méthodes prennent en paramètre : le nom de la sentinelle, le nom du package, le nom du StateObject et le type du StateObject. Vous pouvez utiliser le wildcard “*” pour ne pas appliquer de filtre (<a href="/concepts/stateobjects/">plus d’information ici</a>).</p>
<p>Par exemple, pour récupérer tous les StateObjects du package “Demo” quelque soit la sentinelle et pour s’abonner aux mises à jour de ces StateObjects :</p>
<p></p><pre class="crayon-plain-tag">constellation.server.requestSubscribeStateObjects("*", "Demo", "*", "*");</pre><p></p>
<p>L’autre méthode consiste à enregistrer un (ou plusieurs) StateObjectLink. Cela permet de lier une fonction à un abonnement.</p>
<p>Par exemple :</p>
<p></p><pre class="crayon-plain-tag">constellation.client.registerStateObjectLink("*", "HWMonitor", "/intelcpu/0/load/0", "*", function (so) {
    // Code A
});

constellation.client.registerStateObjectLink("*", "Demo", "*", "*", function (so) {
    // Code B
});</pre><p></p>
<p>Ci-dessus le code A sera invoqué dès qu’un SO nommé « /intelcpu/0/load/0” et produit par le package “HWMonitor” est modifié alors que le code B sera déclenché dès qu’un StateObject du package “Demo” est modifié.</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/client-api/javascript-api/consommer-constellation-api-javascript/">Consommer Constellation avec l&rsquo;API Javascript</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://developer.myconstellation.io/client-api/javascript-api/consommer-constellation-api-javascript/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Consommer Constellation avec Angular JS</title>
		<link>https://developer.myconstellation.io/client-api/javascript-api/consommer-constellation-angular-js/</link>
					<comments>https://developer.myconstellation.io/client-api/javascript-api/consommer-constellation-angular-js/#comments</comments>
		
		<dc:creator><![CDATA[Sebastien Warin]]></dc:creator>
		<pubDate>Fri, 19 Aug 2016 08:27:12 +0000</pubDate>
				<category><![CDATA[Javascript API]]></category>
		<category><![CDATA[Saga]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[SendMessage]]></category>
		<category><![CDATA[ReceiveMessage]]></category>
		<category><![CDATA[AngularJS]]></category>
		<category><![CDATA[Consumer]]></category>
		<category><![CDATA[Subscribe]]></category>
		<category><![CDATA[StateObject]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=2331</guid>

					<description><![CDATA[<p>Préparer la page AngularJS Vous pouvez soit utiliser le gestionnaire de package Nuget depuis Visual Studio pour installer la dernière version du package “Constellation.Angular” et ses dépendances : Ou bien utiliser (ou copier en local) les scripts des CDN en</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/client-api/javascript-api/consommer-constellation-angular-js/">Consommer Constellation avec Angular JS</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h3>Préparer la page AngularJS</h3>
<p>Vous pouvez soit utiliser le gestionnaire de package Nuget depuis Visual Studio pour installer la dernière version du package “Constellation.Angular” et ses dépendances :</p>
<p align="center"><img class="colorbox-2331"  src="https://developer.myconstellation.io/wp-content/uploads/2016/07/image.png" alt="image" /></p>
<p>Ou bien utiliser (ou copier en local) les scripts des CDN en ajoutant dans votre code HTML les balises suivantes :</p>
<p></p><pre class="crayon-plain-tag">&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;</pre><p></p>
<p>Dans votre code Javascript, vous devez créer un module Angular pour votre page que nous appelleront “MyDemoApp” et dans lequel nous injecterons le module “ngConstellation” :</p>
<p></p><pre class="crayon-plain-tag">var myDemoApp = angular.module('MyDemoApp', ['ngConstellation']);</pre><p></p>
<p>Vous devez également ajouter l’attribut “ng-app” sur la balise &lt;html&gt; de votre page pour lier votre page HTML à votre module Angular :</p>
<p></p><pre class="crayon-plain-tag">&lt;html xmlns="http://www.w3.org/1999/xhtml" ng-app="MyDemoApp"&gt;</pre><p></p>
<p>Enfin vous devez créer un contrôleur AngularJS dans lequel nous injecterons la factory “constellationConsumer” que nous appellerons dans notre code “constellation” :</p>
<p></p><pre class="crayon-plain-tag">myDemoApp.controller('MyController', ['$scope',  'constellationConsumer', function ($scope, constellation) {

}]);</pre><p></p>
<p>Sans oublier de lier votre corps de page (&lt;body&gt;) à ce contrôleur :</p>
<p></p><pre class="crayon-plain-tag">&lt;body ng-controller="MyController"&gt;</pre><p></p>
<p>Et voilà votre squelette est prêt !</p>
<p>Pour plus d’information sur AngularJS, je vous recommande la lecture de ce guide : <a title="https://docs.angularjs.org/misc/started" href="https://docs.angularjs.org/misc/started">https://docs.angularjs.org/misc/started</a></p>
<p>Pour résumer notre squelette page est donc :</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;title&gt;Test API AngularJS&lt;/title&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) {

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

&lt;/head&gt;
&lt;body ng-controller="MyController"&gt;

&lt;/body&gt;
&lt;/html&gt;</pre><p></p>
<h3>Connecter une page HTML à Constellation avec AngularJS</h3>
<p>Dans notre contrôleur AngularJS, nous allons initialiser le client Consumer en spécifiant l’URL de votre serveur Constellation, la clé d’accès et le “Friendly name” de votre page :</p>
<p></p><pre class="crayon-plain-tag">constellation.initializeClient("http://localhost:8088", "123456789", "TestAPI");</pre><p></p>
<p>Vous pouvez <a href="/constellation-platform/constellation-console/gerer-credentials-avec-la-console-constellation/">créer une clé d’accès depuis la Console Constellation</a> ou en <a href="/constellation-platform/constellation-server/fichier-de-configuration/#Section_credentials">éditant le fichier de configuration du serveur</a>.</p>
<p>Enfin ajoutons un handler sur le changement d’état de la connexion pour afficher le message “Je suis connecté” dans la console de votre navigateur par exemple lorsque la connexion à Constellation est établie :</p>
<p></p><pre class="crayon-plain-tag">constellation.onConnectionStateChanged(function (change) {
    if (change.newState === $.signalR.connectionState.connected) {
        console.log("Je suis connecté !");
    }
});</pre><p></p>
<p>Il ne reste plus qu’à lancer la connexion en invoquant la méthode “connect” :</p>
<p></p><pre class="crayon-plain-tag">constellation.connect();</pre><p></p>
<p>Et voilà, votre page AngularJS est connectée à votre Constellation.</p>
<h3>Envoyer des messages et invoquer des MessageCallbacks</h3>
<h4>Envoyer des messages</h4>
<p>Pour envoyer des messages et donc invoquer des MessageCallbacks vous devez utiliser la méthode “<em>constellation.sendMessage</em>” en spécifiant :</p>
<ul>
<li>Le scope</li>
<li>La clé du message</li>
<li>Le contenu du message (= les paramètres du MessageCallback)</li>
</ul>
<p>Par exemple, avec le package Nest déployé dans votre Constellation, on retrouvera un MessageCallback  “SetTargetTemperature” pour piloter la température de consigne d’un thermostat Nest.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-21.png"><img class="colorbox-2331"  loading="lazy" title="image" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/image_thumb-20.png" alt="image" width="350" height="99" border="0" /></a></p>
<p align="left">N’hésitez pas à utiliser le <a href="/constellation-platform/constellation-console/messagecallbacks-explorer/">MessageCallback Explorer</a> pour découvrir l’ensemble des MessageCallbacks exposés par les packages de votre Constellation.</p>
<p>Pour invoquer le MessageCallback  “SetTargetTemperature” depuis votre page Web en passant en paramètre l’ID du thermostat et la température de consigne :</p>
<p></p><pre class="crayon-plain-tag">constellation.sendMessage({ Scope: 'Package', Args: ['Nest'] }, 'SetTargetTemperature', 'my_thermostat_id', 19);</pre><p></p>
<p>En AngularJS, pour lier l’invocation de ce code à un bouton, vous devez simplement ajouter l’attribut “ng-click” sur votre bouton.</p>
<p>Par exemple, dans votre code HTML :</p>
<p></p><pre class="crayon-plain-tag">&lt;body ng-controller="MyController"&gt;
    &lt;button ng-click="SetNestTemperature()"&gt;Set Nest to 19°C&lt;/button&gt;
&lt;/body&gt;</pre><p></p>
<p>Et dans votre contrôleur :</p>
<p></p><pre class="crayon-plain-tag">$scope.SetNestTemperature = function () {
   constellation.sendMessage({ Scope: 'Package', Args: ['Nest'] }, 'SetTargetTemperature', 'my_thermostat_id', 19);
};</pre><p></p>
<p>Autre solution, exposer le client Consumer dans le scope AngularJS :</p>
<p></p><pre class="crayon-plain-tag">$scope.constellation = constellation;</pre><p></p>
<p>Et donc s&rsquo;en servir directement dans le template HTML :</p>
<p></p><pre class="crayon-plain-tag">&lt;body ng-controller="MyController"&gt;
    &lt;button ng-click="constellation.sendMessage({ Scope: 'Package', Args: ['Nest'] }, 'SetTargetTemperature', 'my_thermostat_id', 19)"&gt;Set Nest to 19°C&lt;/button&gt;
&lt;/body&gt;</pre><p></p>
<p>Allons un peu plus loin en ajoutant un champ permettant à l’utilisateur de définir la température de consigne.</p>
<p>Dans le template HTML :</p>
<p></p><pre class="crayon-plain-tag">Temperature : &lt;input type="number" ng-model="targetTemperature" /&gt;
&lt;button ng-click="SetNestTemperature()"&gt;Set target temperature&lt;/button&gt;</pre><p></p>
<p>Le champ “input” est de type “number” et est lié à la variable de scope (le modèle) que nous appellerons “targetTemperature”.</p>
<p>De ce  fait dans notre fonction “SetNestTemperature” nous pouvons récupérer la valeur définie par l’utilisateur :</p>
<p></p><pre class="crayon-plain-tag">$scope.SetNestTemperature = function () {
   constellation.sendMessage({ Scope: 'Package', Args: ['Nest'] }, 'SetTargetTemperature', 'my_thermostat_id', $scope.targetTemperature);
};</pre><p></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-29.png"><img class="colorbox-2331"  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/2016/09/image_thumb-28.png" alt="image" width="350" height="60" border="0" /></a></p>
<p>Comme pour l’<a href="/client-api/javascript-api/consommer-constellation-api-javascript/">API Javascript</a>, vous pouvez également passer plusieurs arguments à votre MC combinant type simple et type complexe. Si il y a plusieurs paramètres vous devez les stocker dans un tableau.</p>
<p>Par exemple le MC “ShowNotification” du package <a href="/package-library/xbmc/">Xbmc</a> permettant d’afficher une notification sur une interface Kodi/XBMC prend deux paramètres : le nom d l’hôte XBMC (un type string) et le détail de la notification à afficher (un type complexe) :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-23.png"><img class="colorbox-2331"  loading="lazy" title="image" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/image_thumb-22.png" alt="image" width="350" height="143" border="0" /></a></p>
<p></p><pre class="crayon-plain-tag">constellation.sendMessage({ Scope: 'Package', Args: ['Xbmc'] }, 'ShowNotification', xbmcName, { "Title":"Hello", "Message":"Hello from JS" });</pre><p></p>
<p>Bien entendu vous pouvez invoquer des MessageCallbacks de n’importe quel package, réel (programme Linux/Windows) ou virtuel (Arduino/ESP, scripts, etc..) ou même sur d’autres consommateurs (pages Web par exemple).</p>
<p>Ainsi vos pages Web peuvent, en envoyant des messages, invoquer des méthodes sur n&rsquo;importe quel système connecté dans votre Constellation.</p>
<p>Par exemple dans l’article sur les ESP/Arduinos, notre ESP8266 exposait un MC “Reboot” pour redémarrer la puce. Si l’on souhaite redémarrer notre Arduino/ESP depuis une page Web, il suffirai d’envoyer un message sans paramètre au bon scope. Par exemple :</p>
<p></p><pre class="crayon-plain-tag">constellation.sendMessage({ Scope: 'Sentinel', Args: ['MyArduino'] }, 'Reboot');</pre><p></p>
<p>Ici le scope est “Sentinel” avec l’argument “MyArduino”, c’est à dire que le message “Reboot” sera envoyé à tous les packages de la sentinelle “MyArduino”.</p>
<p>Les <a href="/concepts/messaging-message-scope-messagecallback-saga/">scopes</a> peuvent être :</p>
<ul>
<li>Sentinel</li>
<li>Package</li>
<li>Group</li>
<li>Others</li>
<li>All</li>
</ul>
<p>La propriété “Args” de l’objet scope est un tableau contenant le nom des groupes, des sentinelles ou packages en fonction du type de scope sélectionné. Seuls les scopes “All” et “Others” n’ont pas besoin d’argument.</p>
<h4>Envoyer des messages avec réponse : les sagas</h4>
<p>Les <a href="https://developer.myconstellation.io/concepts/messaging-message-scope-messagecallback-saga/">Sagas</a> permettent de lier des messages et donc de créer des couples de “requêtes / réponses”.</p>
<p>Avec la libraire JavaScript, il est possible d’envoyer des messages dans une saga et d’enregistrer un callback pour traiter la réponse de ce message.</p>
<p>Par exemple, le package “NetworkTools” expose un MC “Ping” permettant de réaliser un ping réseau. Le résultat du ping est retourné dans un message de réponse (un Int64 représentant le temps du réponse du ping) :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image_thumb2.png"><img class="colorbox-2331"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image_thumb2" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/image_thumb2_thumb.png" alt="image_thumb2" width="244" height="110" border="0" /></a></p>
<p align="left">De ce fait pour réaliser un ping depuis une page Web, on pourrait proposer à l’utilisateur un champ pour saisir l’adresse à pinger et afficher le résultat dans un paragraphe.</p>
<p></p><pre class="crayon-plain-tag">&lt;body ng-controller="MyController"&gt;
   Host/IP : &lt;input ng-model="host" /&gt;
   &lt;button ng-click="Ping()"&gt;Ping&lt;/button&gt;
   &lt;p ng-show="pingResult"&gt;Result : {{pingResult}}ms&lt;/p&gt;
&lt;/body&gt;</pre><p></p>
<p>Vous remarquez que le paragraphe du n’est affiché (ng-show) que si la valeur de scope “pingResult” est définie, ce qui n’est pas le cas à l’ouverture de la page.</p>
<p>Déclarons enfin la méthode de scope “Ping” pour envoyer un message au package “NetworkTools” afin d’invoquer dans une saga sur le MC “Ping” avec en paramètre du message variable « $scope.host » qui est liée à la zone de texte (input) de votre vue HTML.</p>
<p>Comme il s’agit d’une saga, nous utilisons la méthode “sendMessageWithSaga” dans laquelle nous passons la fonction callback qui sera invoquée lors de la réponse. A la réception cette réponse, nous allons tous simplement stocker le résultat de la réponse (propriété Data) dans la variable de scope “pingResult”.</p>
<p>L’affectation de la réponse dans la variable de scope “pingResult” est réalisée dans un “$scope.$apply”, une fonction AngularJS qui permet d’indiquer au contrôleur AngularJS que des variables de scope ont été modifiées et donc qu’il faut rafraîchir la vue.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-30.png"><img class="colorbox-2331"  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/2016/09/image_thumb-29.png" alt="image" width="350" height="88" border="0" /></a></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-31.png"><img class="colorbox-2331"  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/2016/09/image_thumb-30.png" alt="image" width="350" height="90" border="0" /></a></p>
<p></p><pre class="crayon-plain-tag">scope.Ping = function () {
  constellation.sendMessageWithSaga(function(response) {
      $scope.$apply(function() {
        $scope.pingResult = response.Data;
      });
    }, { Scope: 'Package', Args: ['NetworkTools'] }, 'Ping', $scope.host);
};</pre><p></p>
<p>Ainsi vos pages Web peuvent invoquer des méthodes et exploiter la réponse de tous les systèmes connectés sur Constellation exposant des MessageCallbacks.</p>
<h3>Recevoir des messages</h3>
<p>Une page Web connectée sur Constellation peut elle même recevoir des messages et donc exposer des MessageCallbacks que d’autres consommateurs (autres pages Web) ou packages (réels et virtuels) pourront invoquer.</p>
<p>Ceci dit un consommateur tel qu’une page Web n’a pas réellement d’existence. Autrement dit elle n’a pas d’identité et donc ne peut recevoir que des messages adressés à un groupe qu’elle devra joindre.</p>
<p>Pour joindre un groupe vous devez utiliser la méthode “subscribeMessages“ (et “unSubscribeMessages” pour en sortir). Vous pouvez joindre autant de groupe que vous souhaitez.</p>
<p>Par exemple, pour ajouter votre page au groupe “Demo” :</p>
<p></p><pre class="crayon-plain-tag">constellation.subscribeMessages("Demo");</pre><p></p>
<p>Vous pourrez ensuite recevoir les messages envoyés dans ce groupe en ajoutant un handler sur le “onReceiveMessage” :</p>
<p></p><pre class="crayon-plain-tag">constellation.onReceiveMessage(function (message) {
    console.log("Message recu !", message);
});</pre><p></p>
<p>Dans ce handler vous recevrez TOUS les messages (quelque soit la clé du message).</p>
<p>Vous avez aussi un moyen plus simple consistant à définir un handler pour une clé de message spécifiquement via la méthode “registerMessageCallback”.</p>
<p>Par exemple :</p>
<p></p><pre class="crayon-plain-tag">constellation.registerMessageCallback("ChangeTitle", function (msg) {
    document.title = msg.Data;
});
constellation.registerMessageCallback("HelloWorld", function (msg) {
    alert("Hello World");
});</pre><p></p>
<p>Ici on enregistre deux MessageCallbacks.</p>
<p>Si votre page reçoit un MessageCallback “HelloWorld”, une alerte sera ouverte, si elle reçoit un MessageCallback “ChangeTitle”, le titre de votre page sera modifié avec l’argument passé dans le MC.</p>
<p>Bien entendu, comme vos pages HTML peuvent enregistrer autant de MessageCallbacks qu’elles souhaitent et que ces MessageCallbacks sont invocables depuis n’importe quel système connecté à Constellation, d’autres pages Web, des objets à base d’Arduino, ESP ou autre, des programmes Python, .NET, etc… vous pouvez imaginer tout type d’usage.</p>
<h3>Consommer des StateObjects</h3>
<p>Pour consommer des StateObjects produits par des packages (virtuels ou réels) de votre Constellation, vous avez deux méthodes : l’évènement “onUpdateStateObject” ou les StateObjectLinks.</p>
<p>La première méthode consiste à enregistre un ou plusieurs handlers sur l’évènement “onUpdateStateObject” :</p>
<p></p><pre class="crayon-plain-tag">constellation.onUpdateStateObject(function (stateobject) {
    console.log(stateobject);
});</pre><p></p>
<p>Les handlers seront déclenchés à chaque mise à jour ou interrogation des StateObjects de votre page quelque soit le StateObject.</p>
<p>Pour interroger un ou plusieurs StateObjects à un instant T vous disposez de la méthode “requestStateObjects”.</p>
<p>Pour vous abonner aux mises à jour d’un ou plusieurs StateObjects, vous disposez de la méthode “subscribeStateObjects” (et “unSubscribeStateObjects” pour vous désabonner).</p>
<p>Enfin la méthode “requestSubscribeStateObjects” réalise un “requestStateObjects” et un “subscribeStateObjects” c’est à dire que la méthode demande la valeur actuelle du ou des StateObjects et s’abonne auprès du serveur Constellation pour être notifiée des mises à jour.</p>
<p>Toutes ces méthodes prennent en paramètre : le nom de la sentinelle, le nom du package, le nom du StateObject et le type du StateObject. Vous pouvez utiliser le wildcard “*” pour ne pas appliquer de filtre (<a href="/concepts/stateobjects/">plus d’information ici</a>).</p>
<p>Par exemple, pour récupérer tous les StateObjects du package “Demo” quelque soit la sentinelle et pour s’abonner aux mises à jour de ces StateObjects :</p>
<p></p><pre class="crayon-plain-tag">constellation.requestSubscribeStateObjects("*", "Demo", "*", "*");</pre><p></p>
<p>L’autre méthode consiste à enregistrer un (ou plusieurs) StateObjectLink. Cela permet de lier une fonction à un abonnement.</p>
<p>Par exemple :</p>
<p></p><pre class="crayon-plain-tag">constellation.registerStateObjectLink("*", "HWMonitor", "/intelcpu/0/load/0", "*", function (so) {
    // Code A
});

constellation.registerStateObjectLink("*", "Demo", "*", "*", function (so) {
    // Code B
});</pre><p></p>
<p>Ci-dessus le code A sera invoqué dès qu’un SO nommé « /intelcpu/0/load/0” et produit par le package “HWMonitor” est modifié alors que le code B sera déclenché dès qu’un StateObject du package “Demo” est modifié.</p>
<p>Prenons un cas pratique, nous voulons afficher en temps réel la consommation de notre CPU. Comme expliqué ci-dessus, la consommation peut être connue avec le StateObject nommé « /intelcpu/0/load/0” et produit par le package “HWMonitor”.</p>
<p>Nous allons donc ajouter un StateObjectLink et affecter la variable de scope “cpu” à chaque mise à jour de ce SO. Comme pour la réception de message, nous devons utiliser la fonction Angular “$scope.$apply” pour informer le contrôleur Angular que nous avons changé une variable de scope :</p>
<p>Aussi vous devez enregistrer vos SOLink une fois connecté :</p>
<p></p><pre class="crayon-plain-tag">constellation.onConnectionStateChanged(function (change) {
  if (change.newState === $.signalR.connectionState.connected) {
    constellation.registerStateObjectLink("*", "HWMonitor", "/intelcpu/0/load/0", "*", function (so) {
      $scope.$apply(function() {
        $scope.cpu = so.Value.Value;
      });
    });
  }
});</pre><p></p>
<p>Et dans notre template :</p>
<p></p><pre class="crayon-plain-tag">&lt;body ng-controller="MyController"&gt;
    &lt;p&gt;CPU : {{cpu}}&lt;/p&gt;
&lt;/body&gt;</pre><p></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-33.png"><img class="colorbox-2331"  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/2016/09/image_thumb-32.png" alt="image" width="350" height="64" border="0" /></a></p>
<p>Plutôt que stocker dans notre variable de scope la propriété “Value” de la valeur de notre StateObject, nous pouvons aussi stocker le StateObject lui même :</p>
<p></p><pre class="crayon-plain-tag">$scope.cpu = so;</pre><p></p>
<p>De ce fait dans le template nous pouvons afficher différentes informations contenu dans notre StateObject  :</p>
<p></p><pre class="crayon-plain-tag">&lt;body ng-controller="MyController"&gt;
    &lt;p&gt;CPU on {{cpu.SentinelName }} at {{cpu.LastUpdate}} is &lt;strong&gt;{{cpu.Value.Value}} {{cpu.Value.Unit}}&lt;/strong&gt;&lt;/p&gt;
&lt;/body&gt;</pre><p></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-32.png"><img class="colorbox-2331"  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/2016/09/image_thumb-31.png" alt="image" width="350" height="50" border="0" /></a></p>
<p>Alors bien sûr le format de la date ou encore la précision de la valeur mesurée par le package HWMonitor ne sont très lisibles. Nous pouvons ajouter des <a href="https://docs.angularjs.org/api/ng/filter/filter">filtres AngularJS</a> directement dans notre template pour rendre notre page plus “user-friendly”.</p>
<p>Utilisons le filtre “date” pour formater la date et “number” pour limiter le nombre de chiffre après la virgule :</p>
<p></p><pre class="crayon-plain-tag">&lt;p&gt;CPU on {{cpu.SentinelName }} at {{cpu.LastUpdate | date : 'dd//MM/yyyy @ hh:mm:ss' }} is &lt;strong&gt;{{cpu.Value.Value | number:2}} {{cpu.Value.Unit}}&lt;/strong&gt;&lt;/p&gt;</pre><p></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-34.png"><img class="colorbox-2331"  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/2016/09/image_thumb-33.png" alt="image" width="350" height="69" border="0" /></a></p>
<p>C’est toute la magie d’AngularJS <img class="wlEmoticon wlEmoticon-winkingsmile colorbox-2331" style="border-style: none;" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/wlEmoticon-winkingsmile-1.png" alt="Clignement d'œil" /></p>
<p>Allons encore un peu plus loin !</p>
<p>Ici nous avons lié notre variable de scope “cpu” au StateObject nommé « /intelcpu/0/load/0” et produit par le package “HWMonitor”. Mais n’oubliez pas que <a href="/concepts/stateobjects/">l’unicité d’un StateObject</a> est obtenu avec le triplet : Sentinelle + Package + Nom.</p>
<p>Autrement dit il peut y avoir plusieurs SO qui correspondent à ce filtre dans le cas où vous avez déployé le package HWMonitor sur plusieurs sentinelles.</p>
<p>Dans ce cas, la valeur du SO est sans cesse écrasée et notre page devient illisible :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/cpus.gif"><img class="colorbox-2331"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="cpus" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/cpus_thumb-gap.jpg" data-gif="https://developer.myconstellation.io/wp-content/uploads/2016/09/cpus_thumb.gif" alt="cpus" width="350" height="58" border="0" /></a></p>
<p>Nous allons gérer ce cas en créant une variable de scope qui contiendra les différents StateObjects de nos CPUs.</p>
<p>Dans votre scope, commençons par déclarer une variable de scope nommée “cpus” en l’initialisant avec un objet vide :</p>
<p></p><pre class="crayon-plain-tag">$scope.cpus = {}</pre><p></p>
<p>Modifions notre StateObjectLink pour stocker le StateObject dans notre objet “cpus” sous la propriété du nom de la sentinelle de notre StateObject.</p>
<p></p><pre class="crayon-plain-tag">constellation.registerStateObjectLink("*", "HWMonitor", "/intelcpu/0/load/0", "*", function (so) {
  $scope.$apply(function() {
    $scope.cpus[so.SentinelName.replace("-", "")] = so;
  });
});</pre><p></p>
<p>C’est à dire que notre variable de scope “cpus” est un objet avec des propriétés du nom de la sentinelle et qui contient le StateObject de son CPU associé.</p>
<p>Attention le nom de la sentinelle est utilisée comme nom de propriété de notre objet JavaScript et vous n’êtes pas sans savoir que les “-“ (entre autre) ne sont pas autorisés en JS ce qui explique que nous les effaçons avec le “replace”.</p>
<p>Ainsi si je veux afficher dans mon template le CPU de ma machine nommée ”PC-SEB_UI” (= propriété “PCSEB_UI”), je devrais écrire :</p>
<p></p><pre class="crayon-plain-tag">&lt;p&gt;CPU on {{cpus.PCSEB_UI.SentinelName }} at {{cpus.PCSEB_UI.LastUpdate | date : 'dd//MM/yyyy @ hh:mm:ss' }} is &lt;strong&gt;{{cpus.PCSEB_UI.Value.Value | number:2}} {{cpus.PCSEB_UI.Value.Unit}}&lt;/strong&gt;&lt;/p&gt;</pre><p></p>
<p>Il ni a plus d’effet indésirable de voir les StateObjects chevaucher constamment.</p>
<p>Mais on peut aller encore plus loin car notre variable “cpus” contient tous les SO de la consommation de CPU produits par l’ensemble des packages HWMonitor de notre Constellation.</p>
<p>Il suffit d’itérer sur cette variable pour afficher le SO de chaque propriété de notre objet. Avec AngularJS vous pouvez utiliser la directive “<a href="https://docs.angularjs.org/api/ng/directive/ngRepeat">ng-repeat</a>” :</p>
<p></p><pre class="crayon-plain-tag">&lt;p ng-repeat="cpu in cpus"&gt;CPU on {{cpu.SentinelName }} at {{cpu.LastUpdate | date : 'dd//MM/yyyy @ hh:mm:ss' }} is &lt;strong&gt;{{cpu.Value.Value | number:2}} {{cpu.Value.Unit}}&lt;/strong&gt;&lt;/p&gt;</pre><p></p>
<p style="text-align: left;" align="center">Nous obtenons une page capable d&rsquo;afficher en temps réel la consommation de toutes nos machines Windows dans une simple page HTML :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/cpus2.gif"><img class="colorbox-2331"  loading="lazy" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="cpus2" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/cpus2_thumb-gap.jpg" data-gif="https://developer.myconstellation.io/wp-content/uploads/2016/09/cpus2_thumb.gif" alt="cpus2" width="350" height="256" border="0" /></a></p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/client-api/javascript-api/consommer-constellation-angular-js/">Consommer Constellation avec Angular JS</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://developer.myconstellation.io/client-api/javascript-api/consommer-constellation-angular-js/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Envoyer des messages et invoquer des MessageCallbacks depuis un Arduino/ESP</title>
		<link>https://developer.myconstellation.io/client-api/arduino-esp-api/envoyer-des-messages-et-invoquer-des-messagecallbacks-depuis-arduino-esp/</link>
					<comments>https://developer.myconstellation.io/client-api/arduino-esp-api/envoyer-des-messages-et-invoquer-des-messagecallbacks-depuis-arduino-esp/#respond</comments>
		
		<dc:creator><![CDATA[Sebastien Warin]]></dc:creator>
		<pubDate>Tue, 23 Aug 2016 13:20:13 +0000</pubDate>
				<category><![CDATA[Arduino / ESP API]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[ESP8266]]></category>
		<category><![CDATA[ESP]]></category>
		<category><![CDATA[Message]]></category>
		<category><![CDATA[MessageCallback]]></category>
		<category><![CDATA[Saga]]></category>
		<category><![CDATA[SendMessage]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=2461</guid>

					<description><![CDATA[<p>Envoyer des messages Pour envoyer des messages et invoquer des méthodes (MessageCallbacks) d’autres packages (ou consommateurs, pages Web, apps mobile, etc… ), vous pouvez utiliser la méthode “sendMessage” : [crayon-6972d48e1ea5b066227679/] C’est une fonction “variadic“ qui peut prendre plusieurs arguments qui</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/client-api/arduino-esp-api/envoyer-des-messages-et-invoquer-des-messagecallbacks-depuis-arduino-esp/">Envoyer des messages et invoquer des MessageCallbacks depuis un Arduino/ESP</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h3>Envoyer des messages</h3>
<p>Pour envoyer des <a href="/concepts/messaging-message-scope-messagecallback-saga/">messages et invoquer des méthodes (MessageCallbacks)</a> d’autres packages (ou consommateurs, pages Web, apps mobile, etc… ), vous pouvez utiliser la méthode “sendMessage” :</p>
<p></p><pre class="crayon-plain-tag">constellation.sendMessage(scope, args, messageKey, data);</pre><p></p>
<p>C’est une fonction “variadic“ qui peut prendre plusieurs arguments qui seront utilisés pour formater le contenu (data) du message :</p>
<p></p><pre class="crayon-plain-tag">constellation.sendMessage(scope, args, messageKey, data, ...);</pre><p></p>
<p>Par exemple pour envoyer un message “DemoMessage” avec en contenu un objet contenant deux propriétés (c’est à dire invoquer le MessageCallback “DemoMessage” en passant en paramètre un objet à deux propriétés) au package “MyCsharpPackage“ :</p>
<p></p><pre class="crayon-plain-tag">constellation.sendMessage(Package, "MyCsharpPackage", "DemoMessage", "{ A: '%s', B: %d  }",  myStringVal, myIntVal);</pre><p></p>
<p>Autre exemple : envoyer un message “SignalReceive” au groupe “IR” (dans lequel plusieurs packages ou consommateurs peuvent s’inscrire) avec en paramètre une valeur de type ”long” formatée en hexadécimal :</p>
<p></p><pre class="crayon-plain-tag">unsigned long value = results.value; // the IR signal decoded
constellation.sendMessage(Group, "IR", "SignalReceive", "%#x", value);</pre><p></p>
<h4>Le scope</h4>
<p>Le scope permet de définir les destinataires du message (<a href="/concepts/messaging-message-scope-messagecallback-saga/">plus d’information ici</a>).</p>
<p>Dans la libraire Arduino/SP, l’argument Scope est une énumération définie de la façon suivante :</p>
<p></p><pre class="crayon-plain-tag">enum ScopeType : uint8_t {
  None = 0,
  Group = 1,
  Package = 2,
  Sentinel = 3,
  Other = 4,
  All = 5
};</pre><p></p>
<p>L’argument “args” spécifie les arguments du scope, par exemple le ou les noms des packages, des sentinelles ou des groupes où envoyer le message. Pour cibler une instance d’un package vous spécifierez le nom de l’instance complet “SENTINEL/Package” (<a href="/concepts/messaging-message-scope-messagecallback-saga/">plus d’information ici</a>).</p>
<p>Si vous avez plusieurs “args” vous devez les séparer par des virgules. Par exemple pour envoyer un message “HelloWorld” au groupe A et au groupe B :</p>
<p></p><pre class="crayon-plain-tag">constellation.sendMessage(Group, "A,B", "HelloWorld", "{}");</pre><p></p>
<h4>Le contenu (Data) du message</h4>
<p>Dans la <a href="/concepts/messaging-message-scope-messagecallback-saga/">philosophie des MessageCallbacks</a>, le contenu du message (Data) permet de stocker les arguments d’une fonction (MessageCallback) à invoquer.</p>
<p>Si vous invoquez un MC sans paramètre, vous devez spécifier un objet vide “{}” :</p>
<p></p><pre class="crayon-plain-tag">constellation.sendMessage(Package, "DemoPackage", "HelloWorld", "{}");</pre><p></p>
<p>Si vous avez plusieurs paramètres à passer, vous formaterez vos arguments dans un tableau :</p>
<p></p><pre class="crayon-plain-tag">constellation.sendMessage(Package, "DemoPackage", "SayHello", "[ 'Sebastien', 'Warin' ]");</pre><p></p>
<p>Vous pouvez également envoyer en tant qu’argument un objet complexe, par exemple :</p>
<p></p><pre class="crayon-plain-tag">constellation.sendMessage(Package, "DemoPackage", "SayHello", "{ 'FirstName':'Sebastien', 'LastName':'Warin' }");</pre><p></p>
<p>Ou bien même un mixte, par exemple un MC prenant en paramètre un objet complexe et un entier :</p>
<p></p><pre class="crayon-plain-tag">constellation.sendMessage(Package, "DemoPackage", "SayHello", "[ { 'FirstName':'Sebastien', 'LastName':'Warin' }, 42 ]");</pre><p></p>
<p>Ici le contenu du message est formaté en JSON via une chaine de caractère mais vous pouvez également passer un JsonObject à cette méthode :</p>
<p></p><pre class="crayon-plain-tag">const int BUFFER_SIZE = JSON_OBJECT_SIZE(2);
StaticJsonBuffer&lt;BUFFER_SIZE&gt; jsonBuffer;
JsonObject&amp; data = jsonBuffer.createObject();
myStateObject["FirstName"] = "Sebastien";
myStateObject["LastName"] = "Warin";
constellation.sendMessage(Package, "DemoPackage", "SayHello", data);</pre><p></p>
<p>Notez aussi que la Console Constellation liste les MessageCallbacks déclarés par l’ensemble des packages de votre Constellation et vous génère le code pour chaque API.</p>
<p>Par exemple, si vous souhaitez invoquer le MessageCallback “PushNote” du package “PushBullet” qui vous permettra d’envoyer une notification sur un smartphone vous pouvez cliquez sur l’icone de génération de code :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/08/image-66.png"><img class="colorbox-2461"  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/2016/08/image_thumb-55.png" alt="image" width="350" height="147" border="0" /></a></p>
<p align="left">Sélectionnez ensuite le langage “Arduino” pour avoir le modèle correspondant :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/08/image-67.png"><img class="colorbox-2461"  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/2016/08/image_thumb-56.png" alt="image" width="350" height="220" border="0" /></a></p>
<p>Ainsi pour envoyer une notification sur mon smartphone depuis un Arduino/ESP :</p>
<p></p><pre class="crayon-plain-tag">constellation.sendMessage(Package, "PushBullet", "PushNote", "[ 'Demo from Arduino', 'Ceci est une demo', 'Device', '' ]");</pre><p></p>
<p>Bien entendu, n’importe quel package ou consommateur peut recevoir des messages. Vous pouvez donc invoquer des méthodes C#, Python, JS, etc.. depuis un Arduino/ESP.</p>
<h3>Envoyer des messages avec réponse : les Sagas</h3>
<p>Les <a href="/concepts/messaging-message-scope-messagecallback-saga/">Sagas</a> permettent de lier des messages et donc de créer des couples de “requêtes / réponses”.</p>
<p>Avec la libraire Arduino/ESP, il est possible d’envoyer des messages dans une saga afin d’enregistrer un callback de traitement de la réponse.</p>
<p>Par exemple, le package “NetworkTools” expose entre autre un MessageCallback “Ping” permettant de pinger une machine. Si le MC est invoqué dans une saga, le package répondra dans la saga un message contenant le temps de réponse du ping.</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-19.png"><img class="colorbox-2461"  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/2016/09/image_thumb-19.png" alt="image" width="350" height="106" border="0" /></a></p>
<p>De ce fait, si nous souhaitons invoquer cette méthode depuis notre Arduino et traiter la réponse, nous pouvons écrire :</p>
<p></p><pre class="crayon-plain-tag">const char* ip = "192.168.0.10";
constellation.sendMessageWithSaga([](JsonObject&amp; json) {
    constellation.writeInfo("Ping response in %s ms", json["Data"].as&lt;char *&gt;()); 
  }, Package, "NetworkTools", "Ping", "[ '%s' ]", ip);</pre><p></p>
<p>La signature de la méthode “<em>sendMessageWithSaga</em>” est la même que la méthode “<em>sendMessage</em>” présentée ci-dessus à la seule différence qu’elle prend comme 1er argument un callback vers une fonction traitant la réponse ici passée en tant que lambda.</p>
<p>Dans l’exemple ci-dessus, votre Arduino envoie donc un message “Ping” avec une adresse IP en paramètre au(x) package(s) “NetworkTools” en associant un n° de saga. Ce package exécutera le ping et vous retournera un message de réponse avec le résultat du ping. Cette réponse sera traitée par la fonction lambda qui dans l’exemple affichera dans les logs Constellation le résultat du ping.</p>
<p>Ainsi vos Arduino/ESP peuvent très facilement invoquer des méthodes (MessageCallback) avec ou sans retour des différents packages (virtuels ou non) ou consommateurs de votre Constellation; scripts Javascripts, Powershell, Bash, programmes .NET, Python, etc…</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/client-api/arduino-esp-api/envoyer-des-messages-et-invoquer-des-messagecallbacks-depuis-arduino-esp/">Envoyer des messages et invoquer des MessageCallbacks depuis un Arduino/ESP</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://developer.myconstellation.io/client-api/arduino-esp-api/envoyer-des-messages-et-invoquer-des-messagecallbacks-depuis-arduino-esp/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-23 02:53:18 by W3 Total Cache
-->