﻿<?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 Message - Constellation</title>
	<atom:link href="https://developer.myconstellation.io/tag/message/feed/" rel="self" type="application/rss+xml" />
	<link>https://developer.myconstellation.io/tag/message/</link>
	<description>Votre plateforme d&#039;interconnexion</description>
	<lastBuildDate>Mon, 30 Apr 2018 12:40:00 +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 Message - Constellation</title>
	<link>https://developer.myconstellation.io/tag/message/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<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[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>
		<category><![CDATA[MessageCallback]]></category>
		<category><![CDATA[MessageContext]]></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-6972d3e973812066565085/] 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-6972d3e973ea5143964963/] 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>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-6972d3e97427a911732458/] 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>
		<item>
		<title>MessageCallback : exposer des méthodes et recevoir des messages sur un Arduino/ESP</title>
		<link>https://developer.myconstellation.io/client-api/arduino-esp-api/recevoir-des-messages-et-exposer-des-methodes-messagecallback-sur-arduino-esp/</link>
					<comments>https://developer.myconstellation.io/client-api/arduino-esp-api/recevoir-des-messages-et-exposer-des-methodes-messagecallback-sur-arduino-esp/#respond</comments>
		
		<dc:creator><![CDATA[Sebastien Warin]]></dc:creator>
		<pubDate>Tue, 23 Aug 2016 13:19:35 +0000</pubDate>
				<category><![CDATA[Arduino / ESP API]]></category>
		<category><![CDATA[Message]]></category>
		<category><![CDATA[MessageCallback]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[ESP8266]]></category>
		<category><![CDATA[ESP]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=2459</guid>

					<description><![CDATA[<p>Pour exposer des méthodes de votre Arduino/ESP dans la Constellation, vous pouvez enregistrer et par la même occasion déclarer auprès de Constellation des MessageCallbacks avec la méthode registerMessageCallback. Enregistrer un MessageCallback Par exemple enregistrons un MessageCallback “HelloWorld” via une expression</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/client-api/arduino-esp-api/recevoir-des-messages-et-exposer-des-methodes-messagecallback-sur-arduino-esp/">MessageCallback : exposer des méthodes et recevoir des messages sur un Arduino/ESP</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Pour exposer des méthodes de votre Arduino/ESP dans la Constellation, vous pouvez enregistrer et par la même occasion déclarer auprès de Constellation des MessageCallbacks avec la méthode <em>registerMessageCallback</em>.</p>
<h3>Enregistrer un MessageCallback</h3>
<p>Par exemple enregistrons un MessageCallback “HelloWorld” via une expression lambda C++ à l’initialisation de votre Arduino/ESP (c’est à dire dans la méthode <em>setup()</em>):</p>
<p></p><pre class="crayon-plain-tag">constellation.registerMessageCallback("HelloWorld",
  [](JsonObject&amp; json) {
    constellation.writeInfo("Hello Constellation !");
 });</pre><p></p>
<p>Enfin dans la boucle principal (loop), invoquez la méthode “constellation.loop” pour traiter et dispatcher les messages reçu par votre package virtuel :</p>
<p></p><pre class="crayon-plain-tag">constellation.loop();</pre><p></p>
<p>Dès lors que votre Arduino/ESP recevra un message dont la clé (<em>MessageKey</em>) est “HelloWorld”, votre méthode associée (représentée ci-dessus par une lambda) sera invoquée.</p>
<h4>Décrire son MessageCallback</h4>
<p>Le MessageCallback enregistré ci-dessus est dit “caché”, car il n’est pas référencé sur Constellation ! Vous pouvez bien sur envoyer un message “HelloWorld” à votre package pour invoquer votre fonction lambda mais cela suppose que vous connaissez par avance que votre package a enregistré le MessageCallback ci-dessus nommé “HelloWorld”.</p>
<p>Pour enregistrer<u> ET déclarer</u> un MessageCallback vous devez ajouter un “<em>MessageCallbackDescriptor</em>” dans les arguments de la méthode. Par exemple pour reprendre notre exemple “HelloWorld” :</p>
<p></p><pre class="crayon-plain-tag">constellation.registerMessageCallback("HelloWorld",
  MessageCallbackDescriptor().setDescription("Hello World !"),
  [](JsonObject&amp; json) {
    constellation.writeInfo("Hello Constellation !");
 });</pre><p></p>
<p>On a ici ajouté un “<em>MessageCallbackDescriptor</em>” en spécifiant la description de notre MC. Pour que la description du MC soit envoyée à Constellation, vous devez nécessairement publier le “Package Descriptor” à la fin de l’initialisation de votre Arduino/ESP par la ligne :</p>
<p></p><pre class="crayon-plain-tag">constellation.declarePackageDescriptor();</pre><p></p>
<p>Maintenant, depuis la Console Constellation, ouvrez le “MessageCallback Explorer” et vous retrouvez un MC nommé “HelloWorld” pour votre package :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-7.png"><img class="colorbox-2459"  loading="lazy" title="image" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/image_thumb-7.png" alt="image" width="350" height="96" border="0" /></a></p>
<p>Vous pouvez cliquer sur le bouton “Invoke” pour envoyer un message “HelloWorld” au package “MyVirtualPackage” et donc invoquer le code de la lambda.</p>
<p>On retrouvera donc dans la Console Log Constellation un “Hello Constellation” tel que programmé dans la lambda (via un <em>constellation.writeInfo</em>)  :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-8.png"><img class="colorbox-2459"  loading="lazy" title="image" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/image_thumb-8.png" alt="image" width="350" height="101" border="0" /></a></p>
<h4 align="left">Récupérer le contexte</h4>
<p align="left">Vous pouvez également récupérer le contexte de réception du message dans la fonction liée en ajoutant un argument « <em>MessageContext</em> » dans la signature du callback :</p>
<p></p><pre class="crayon-plain-tag">(*)(JsonObject&amp;, MessageContext);</pre><p></p>
<p>Le type “MessageContext” décrit 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;</pre><p></p>
<p>Avec :</p>
<p></p><pre class="crayon-plain-tag">enum SenderType : uint8_t {
   ConsumerHub = 0,
   ConsumerHttp = 1,
   ConstellationHub = 2,
   ConstellationHttp = 3
};

typedef struct {
    SenderType type;
    const char* friendlyName;
    const char* connectionId;
} MessageSender;</pre><p></p>
<p>Ainsi vous pouvez obtenir des informations sur le contexte de réception du message à savoir :</p>
<ul>
<li>Si le message est dans une saga, si oui obtenir l’identifiant de la saga</li>
<li>Connaitre le scope dans lequel a été envoyé le message</li>
<li>Connaitre l’émetteur du message (ID de connexion, friendly name, …)</li>
</ul>
<p align="left">Par exemple, pour afficher le nom de l’émetteur (son <em>FriendlyName</em>) nous pourrions écrire :</p>
<p></p><pre class="crayon-plain-tag">constellation.registerMessageCallback("HelloWorld",
  MessageCallbackDescriptor().setDescription("Hello World !"),
  [](JsonObject&amp; json, MessageContext ctx) {
    constellation.writeInfo("Hello %s from Constellation !", ctx.sender.friendlyName);
 });</pre><p></p>
<p align="left">En invoquant le MC depuis le “MessageCallback Explorer” en étant connecté sous l’utilisateur “seb”, nous obtiendrons dans les logs :</p>
<p></p><pre class="crayon-plain-tag">[MyVirtualSentinel/MyVirtualPackage] 17:28:41 : Hello Consumer/ControlCenter:seb from Constellation !</pre><p></p>
<h3>Décrire les paramètres de vos MessageCallbacks</h3>
<p>Dans la <a href="/concepts/messaging-message-scope-messagecallback-saga/">philosophie des MessageCallbacks</a> Constellation, un MessageCallback sert à invoquer des méthodes où la clé du message (MessageKey) est comme le nom d’une méthode.</p>
<p>Pour passer des paramètres à ces méthodes, on utilisera le contenu du message (Data).</p>
<h4>Paramètres de types simples</h4>
<p>Imaginez vouloir exposer une méthode “SayHello” qui prend en paramètre deux chaines de paramètres (= des types simples), le nom et prénom pour les afficher dans les logs.</p>
<p>On déclarera le MessageCallback suivant :</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].as&lt;char *&gt;(), json["Data"][1].as&lt;char *&gt;()); 
 });</pre><p></p>
<p>On a ajouté deux paramètres de type “String” dans le <em>MessageCallbackDescriptor</em> via la méthode “addParameter”. Dans le code de notre MessageCallback, nous exploitons les valeurs des paramètres via la propriété “Data” de notre message “json”.</p>
<p>Le 1er paramètre (<em>json[« Data »][0]</em>) étant ici le “FirstName” d’après la description et le 2ème (<em>json[« Data »][1]</em>) le “LastName”.</p>
<p><u>Attention</u> :</p>
<ul>
<li>lorsque plusieurs paramètres sont passés comme dans l’exemple ci-dessus, la propriété “Data” est un tableau contenant la valeur de chaque argument (ici [0] est “FirstName” et [1] le “LastName”)</li>
<li>Si un seul paramètre est passé dans votre MC, la propriété “Data” est la valeur de l’argument directement et non un tableau.</li>
</ul>
<p>Vous pouvez tester votre MC depuis le “MessageCallback Explorer” :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-9.png"><img class="colorbox-2459"  loading="lazy" title="image" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/image_thumb-9.png" alt="image" width="350" height="105" border="0" /></a></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-10.png"><img class="colorbox-2459"  loading="lazy" title="image" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/image_thumb-10.png" alt="image" width="350" height="15" border="0" /></a></p>
<p align="left">Bien entendu vous pouvez déclarer un ou plusieurs paramètres de type différent.</p>
<p align="left">Les types de base sont :</p>
<ul>
<li>
<div align="left">System.String</div>
</li>
<li>
<div align="left">System.Char</div>
</li>
<li>
<div align="left">System.Boolean</div>
</li>
<li>
<div align="left">System.Int16</div>
</li>
<li>
<div align="left">System.Int32</div>
</li>
<li>
<div align="left">System.Int64</div>
</li>
<li>
<div align="left">System.Double</div>
</li>
<li>
<div align="left">System.Decimal</div>
</li>
<li>
<div align="left">System.Float</div>
</li>
</ul>
<p>Pour simplifier l’enregistrement des paramètres de type de base, vous pouvez les déclarer en utilisant la forme générique.</p>
<p>Par exemple pour un paramètre de type “String” on écrira :</p>
<p></p><pre class="crayon-plain-tag">addParameter&lt;const char*&gt;("FirstName")</pre><p></p>
<p>Autre exemple pour ajouter des paramètres de type “Boolean” et “Int32” :</p>
<p></p><pre class="crayon-plain-tag">addParameter&lt;bool&gt;("IsEnable")
addParameter&lt;int&gt;("MyNumber")</pre><p></p>
<p>De ce fait notre MC “SayHello” pourrait s’écrire :</p>
<p></p><pre class="crayon-plain-tag">constellation.registerMessageCallback("SayHello",
  MessageCallbackDescriptor().setDescription("Say hello !").addParameter&lt;const char*&gt;("FirstName").addParameter&lt;const char*&gt;("LastName"),
  [](JsonObject&amp; json) {
    constellation.writeInfo("Hello %s %s", json["Data"][0].as&lt;char *&gt;(), json["Data"][1].as&lt;char *&gt;()); 
 });</pre><p></p>
<h4>Paramètre de types complexes</h4>
<p>Il est également possible de spécifier des objets complexes contenant des propriétés.</p>
<p>Reprenons l’exemple précédent “SayHello” sauf qu’au lieu de passer deux paramètres de type “simple”, passons qu’un seul paramètre : un objet contenant deux propriétés (LastName et FirstName).</p>
<p></p><pre class="crayon-plain-tag">constellation.registerMessageCallback("SayHello",
  MessageCallbackDescriptor().setDescription("Say hello with complex object!").addParameter("User", "SampleUserData"),
  [](JsonObject&amp; json) {
    constellation.writeInfo("Hello %s %s", json["Data"]["FirstName"].as&lt;char *&gt;(), json["Data"]["LastName"].as&lt;char *&gt;());
});</pre><p></p>
<p>Dans le MessageCallbackDescriptor de notre MessageCallback nous déclarons qu’un seul paramètre nommé “User” et de type “SampleUserData”.</p>
<p>Au niveau du code de notre MessageCallback, nous récupérons nos deux valeurs via le 1èr et unique paramètre (<em>json[« Data »]</em>) en accédant à la propriété “FirstName” et “LastName”.</p>
<p>Bien entendu pour que cela fonctionne il faut déclarer le type “SampleUserData” via la méthode “addMessageCallbackType” :</p>
<p></p><pre class="crayon-plain-tag">constellation.addMessageCallbackType("SampleUserData", TypeDescriptor().setDescription("This is a smaple user data").addProperty&lt;const char*&gt;("FirstName").addProperty&lt;const char*&gt;("LastName");</pre><p></p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-11.png"><img class="colorbox-2459"  loading="lazy" title="image" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/image_thumb-11.png" alt="image" width="350" height="117" border="0" /></a></p>
<p align="left">Il n’y a donc plus maintenant qu’un seul paramètre, un objet complexe contenant deux propriétés de type “string”. Vous pouvez d’ailleurs cliquez sur le type “SampleUserData” pour afficher sa description :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-12.png"><img class="colorbox-2459"  loading="lazy" title="image" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/image_thumb-12.png" alt="image" width="240" height="93" border="0" /></a></p>
<p align="left">Noter que vous pouvez enregistrer et déclarer des MessagesCallbacks mixant paramètre simple et paramètre complexe :</p>
<p></p><pre class="crayon-plain-tag">constellation.registerMessageCallback("MultipleParameters",
  MessageCallbackDescriptor().setDescription("Mixte de parametre simple &amp; complexe").addParameter("User", "SampleUserData").addParameter&lt;const char*&gt;("Password"),
  [](JsonObject&amp; json) {
    // json["Data"][0] is SampleUserData
    // json["Data"][1] is String
});</pre><p></p>
<h3>Exposer des MessageCallbacks avec réponse : les sagas</h3>
<p>Pour finir un MessageCallback peut retourner un message de réponse, c’est ce que l’on appelle <a href="/concepts/messaging-message-scope-messagecallback-saga/#Les_Sagas">les sagas</a>. C’est un peu comme une méthode en programmation, elle peut être “procédure” (sans retour, un void) ou “fonction” (retourne un type simple ou complexe).</p>
<p>Votre Arduino/ESP peut également enregistrer des MC retournant une réponse. Pour cela deux choses sont nécessaire :</p>
<ul>
<li>Appeler la méthode “sendReponse” dans votre callback pour envoyer la réponse</li>
<li>Appeler la méthode “setReturnType” sur le MessageCallbackDescriptor de votre MC pour déclarer le type de retour</li>
</ul>
<p>Par exemple exposons un MessageCallback “Addition” pour réaliser des additions sur un Arduino/ESP. Ce MessageCallback prend en paramètre deux entiers et retourne le résultat de type entier (Int32) également :</p>
<p></p><pre class="crayon-plain-tag">constellation.registerMessageCallback("Addition",
  MessageCallbackDescriptor().setDescription("Do addition on this tiny device").addParameter&lt;int&gt;("a").addParameter&lt;int&gt;("b").setReturnType&lt;int&gt;(),
  [](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>Pour retourner une réponse vous devez disposer du contexte de réception du message (le “MessageContext”). Vous noterez qu’ici, nous testons que le message appartient bien à une saga afin de renvoyer la réponse car il ne sert à rien d’envoyer une réponse sans saga, il ne sera jamais reçu par l’émetteur.</p>
<p>En déclarant le type de retour (ici un Int32), le <em>MessageCallback Explorer</em> reconnait ce MC comme une saga. Vous pouvez donc envoyer le message dans une saga (c’est à dire avec un identifiant de Saga) ou non grâce à la case à cocher :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-13.png"><img class="colorbox-2459"  loading="lazy" title="image" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/image_thumb-13.png" alt="image" width="350" height="70" border="0" /></a></p>
<p align="left">Si le message est envoyé dans une saga, notre code Arduino ci-dessus retournera une réponse, ici à la Console Constellation :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-14.png"><img class="colorbox-2459"  loading="lazy" title="image" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/image_thumb-14.png" alt="image" width="350" height="185" border="0" /></a></p>
<p align="left">La Console Constellation vous présentera ici toutes informations quant à la réponse et au message initial.  On retrouve ici la réponse de notre addition :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-15.png"><img class="colorbox-2459"  loading="lazy" title="image" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/image_thumb-15.png" alt="image" width="350" height="239" border="0" /></a></p>
<p align="left">Dans la Console Log, on retrouvera bien les logs produits par notre Arduino :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image52.png"><img class="colorbox-2459"  loading="lazy" title="image" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/image52_thumb.png" alt="image" width="450" height="19" border="0" /></a></p>
<p align="left">Vous pouvez également rejouer ce test mais cette fois ci en décochant la case “With Saga”, c’est à dire que nous invoquons le MC “Addition” sans n° de saga :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-17.png"><img class="colorbox-2459"  loading="lazy" title="image" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/image_thumb-17.png" alt="image" width="240" height="126" border="0" /></a></p>
<p align="left">Dans la Console Log, notre Arduino réalise bien l’addition mais ne retourne pas de message de réponse car il ne dispose pas de n° de saga pour répondre :</p>
<p align="center"><a href="https://developer.myconstellation.io/wp-content/uploads/2016/09/image-18.png"><img class="colorbox-2459"  loading="lazy" title="image" src="https://developer.myconstellation.io/wp-content/uploads/2016/09/image_thumb-18.png" alt="image" width="350" height="20" border="0" /></a></p>
<h3>Recevoir tous les messages dans une méthode</h3>
<p>Vous pouvez aussi “attraper” tous les messages que votre package virtuel reçoit en définissant un “callback”, c’est à dire une fonction prenant en paramètre le message sous forme d’un JsonObject et qui sera appelée à chaque message reçu.</p>
<p>Par exemple, écrivez la méthode suivante pour afficher le “MessageKey” de chaque message reçu (si nécessaire n’hésitez pas à lire ou relire <a href="/concepts/messaging-message-scope-messagecallback-saga/">les fondamentaux du Messaging Constellation</a>) :</p>
<p></p><pre class="crayon-plain-tag">void messageReceive(JsonObject&amp; json) {
  Serial.print("MSG RCV : ");
  Serial.println(json["Key"].as&lt;char *&gt;());
}</pre><p></p>
<p>Au “setup”, attachez cette méthode à la réception des messages (<em>setMessageReceiveCallback</em>) et abonnez-vous à la réception des messages (<em>subscribeToMessage</em>) :</p>
<p></p><pre class="crayon-plain-tag">constellation.setMessageReceiveCallback(messageReceive); 
constellation.subscribeToMessage();</pre><p></p>
<p>Avec les expression lambda en C++, vous auriez pu aussi écrire directement :</p>
<p></p><pre class="crayon-plain-tag">constellation.setMessageReceiveCallback([](JsonObject&amp; json) { 
  constellation.writeInfo("Message received ! Message key = %s", json["Key"].as&lt;char *&gt;());     
});
constellation.subscribeToMessage();</pre><p></p>
<p>Enfin dans la boucle principal (loop), invoquez la méthode “constellation.loop” pour traiter et dispatcher les messages reçu par votre package virtuel :</p>
<p></p><pre class="crayon-plain-tag">constellation.loop();</pre><p></p>
<p>Par exemple, imaginez un ESP8266 avec 2 MessageCallbacks : “Restart” sans paramètre qui redémarre l’ESP et “SendCode” avec un objet JSON en paramètre pour envoyer un signal infrarouge.</p>
<p>Le code pourrait être :</p>
<p></p><pre class="crayon-plain-tag">constellation.setMessageReceiveCallback([](JsonObject&amp; json) { 
  Serial.print("Message receive : ");
  const char * key = json["Key"].as&lt;char *&gt;();  
  if (stricmp (key, "SendCode") == 0) {

    const char * encoder = json["Data"]["Encoding"].as&lt;char *&gt;();  
    unsigned long code = strtoul(json["Data"]["Code"].as&lt;char *&gt;(), NULL, 0);

    // TODO : send the IR signal "code"

    else {
      constellation.writeInfo("Unable to send IR code : encoding '%s' not found !", encoder); 
    }    
    irrecv.enableIRIn();
  }
  else if (stricmp (key, "Restart") == 0) {
    ESP.restart();
  }
});  
constellation.subscribeToMessage();</pre><p></p>
<p>Avec cette façon de faire, votre “MessageReceiveCallback” est invoqué à chaque message reçu mais c’est à vous de “dispatcher” les messages en fonction de leur “MessageKey”.</p>
<p>De plus côté Constellation, il n’y a aucun “Message Callback” déclaré sur Constellation, c’est a vous de connaitre les “MessageKey” que votre package virtuel acceptent, ici “SendCode” et “Restart” !</p>
<h4>Obtenir contexte de réception</h4>
<p>Comme pour l&rsquo;enregistrement d&rsquo;un MessageCallback, vous pouvez ajouter un 2ème argument de type MessageContext pour récupérer le contexte de réception du message.</p>
<p>Par exemple nous pourrions écrire très simplement :</p>
<p></p><pre class="crayon-plain-tag">constellation.setMessageReceiveCallback([](JsonObject&amp; json, MessageContext ctx) { 
  constellation.writeInfo("Message receive from %s. Message key = %s", ctx.sender.friendlyName, json["Key"].as&lt;char *&gt;());  
});  
constellation.subscribeToMessage();</pre><p></p>
<h3>S&rsquo;abonner à un groupe Constellation</h3>
<p>Jusqu’a présent votre package virtuel recevra les messages :</p>
<ul>
<li>Du Scope “All” (c’est à dire tout le monde connecté à Constellation)</li>
<li>Du Scope “Others” si votre package n’est pas l’émetteur du message</li>
<li>Du Scope de votre sentinelle</li>
<li>Du Scope de votre package</li>
</ul>
<p>Si nécessaire n’hésitez pas à lire ou relire <a href="/concepts/messaging-message-scope-messagecallback-saga/">les fondamentaux du Messaging Constellation</a>.</p>
<p>Vous pouvez également vous abonner à des groupes pour recevoir les messages qui seraient envoyés dans ces groupes.</p>
<p>Pour cela il suffit d’invoquer la méthode “<em>subscribeToGroup</em>” en spécifiant le nom du groupe à joindre. Exemple :</p>
<p></p><pre class="crayon-plain-tag">constellation.subscribeToGroup("MonGroupe");</pre><p></p>
<p>Noter cependant que l’appartenance d’un package, virtuel ou non, à un groupe <a href="/constellation-platform/constellation-console/gerer-packages-avec-la-console-constellation/#Editer_les_groupes_dun_package">peut être défini au niveau de la configuration de la Constellation éditable simplement via la Console Constellation</a> afin de pouvoir faire évoluer ces appartenances à la volée sans devoir reprogrammer vos Arduino/ESP.</p>
<h3></h3>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/client-api/arduino-esp-api/recevoir-des-messages-et-exposer-des-methodes-messagecallback-sur-arduino-esp/">MessageCallback : exposer des méthodes et recevoir des messages sur 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/recevoir-des-messages-et-exposer-des-methodes-messagecallback-sur-arduino-esp/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>L&#8217;interface REST « Consumer »</title>
		<link>https://developer.myconstellation.io/client-api/rest-api/interface-rest-consumer/</link>
					<comments>https://developer.myconstellation.io/client-api/rest-api/interface-rest-consumer/#comments</comments>
		
		<dc:creator><![CDATA[Sebastien Warin]]></dc:creator>
		<pubDate>Fri, 12 Aug 2016 14:44:31 +0000</pubDate>
				<category><![CDATA[REST API]]></category>
		<category><![CDATA[MessageCallback]]></category>
		<category><![CDATA[Saga]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[group]]></category>
		<category><![CDATA[SendMessage]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[Constellation]]></category>
		<category><![CDATA[StateObject]]></category>
		<category><![CDATA[AccessKey]]></category>
		<category><![CDATA[Consumer]]></category>
		<category><![CDATA[Package]]></category>
		<category><![CDATA[Request]]></category>
		<category><![CDATA[Message]]></category>
		<category><![CDATA[Subscribe]]></category>
		<guid isPermaLink="false">https://developer.myconstellation.io/?p=2284</guid>

					<description><![CDATA[<p>L’interface REST “Consumer” permet à tout système, script, objet ou programme de “consommer” des éléments dans une Constellation sans devoir être déclaré comme un package. Un consommateur peut : Consommer des StateObjects (Request ou Subscribe) Envoyer ou recevoir des messages Généralités</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/client-api/rest-api/interface-rest-consumer/">L&rsquo;interface REST « Consumer »</a> appeared first on <a rel="nofollow" href="https://developer.myconstellation.io">Constellation</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>L’interface REST “Consumer” permet à tout système, script, objet ou programme de “consommer” des éléments dans une Constellation sans devoir être déclaré comme un package.</p>
<p>Un consommateur peut :</p>
<ul>
<li>Consommer des StateObjects (Request ou Subscribe)</li>
<li>Envoyer ou recevoir des messages</li>
</ul>
<h3>Généralités</h3>
<h4>Construction de l’URL</h4>
<p>L’URL est :  &lt;Root URI&gt;/rest/consumer/&lt;action&gt;?&lt;paramètres&gt;</p>
<p>Partons du principe que votre Constellation est exposée en HTTP sur le port 8088 (sans path). On retrouvera dans le <a href="https://developer.myconstellation.io/constellation-server/fichier-de-configuration/">fichier de configuration</a> la section suivante :</p>
<p></p><pre class="crayon-plain-tag">&lt;listenUris&gt;
  &lt;uri listenUri="http://+:8088/" /&gt;
&lt;/listenUris&gt;</pre><p></p>
<p>La “Root URI “ est donc “<strong>http://&lt;ip ou dns&gt;:8088/</strong>”.</p>
<p>Par exemple si nous sommes en local, nous pourrions écrire :</p>
<p></p><pre class="crayon-plain-tag">http://localhost:8088/rest/consumer/xxxxx</pre><p></p>
<h4>Authentification</h4>
<p>Comme pour toutes les requêtes vers Constellation vous devez impérativement spécifier dans <u>les headers HTTP</u> <strong>ou</strong> dans <u>les paramètres de l’URL</u> (querystring), les paramètres “SentinelName”, “PackageName” et “AccessKey” pour l’authentification.</p>
<p>Dans le cas de l’API “Consumer”, la “SentinelName” est “Consumer” et le “PackageName” est le nom de votre choix que l’on considère comme un “FriendlyName”. Typiquement le “FriendlyName” est par exemple le nom de l’application/page qui se connecte.</p>
<p>L’AccessKey doit bien sur être déclarée et activée sur le serveur.</p>
<p>Ainsi chaque appel sera sous la forme :</p>
<p></p><pre class="crayon-plain-tag">http://localhost:8088/rest/consumer/&lt;action&gt;?SentinelName=Consumer&amp;PackageName=&lt;Friendly name&gt;&amp;AccessKey=&lt;access key&gt;&amp;&lt;paramètres&gt;</pre><p></p>
<h4>Check Access</h4>
<p>Toutes les API REST de Constellation exposent une méthode en GET “CheckAccess” qui retourne un code HTTP 200 (OK). Cela permet de tester la connexion et l’authentification au serveur Constellation.</p>
<ul>
<li>Action : “CheckAccess” (GET)</li>
<li>Paramètres : aucun</li>
</ul>
<p>Exemple :</p>
<p></p><pre class="crayon-plain-tag">http://localhost:8088/rest/consumer/CheckAccess?SentinelName=Consumer&amp;PackageName=Demo&amp;AccessKey=MaCleDeTest123</pre><p></p>
<h3>Envoyer des messages</h3>
<ul>
<li>Action : “SendMessage” (GET ou POST)</li>
<li>En GET, voici les paramètres de l’URL :
<ul>
<li><u>scope</u> : le type de scope (All, Other, Group, Sentinel ou Package)</li>
<li><u>args</u> : les arguments du scope (par exemple le nom du groupe, de la sentinelle, du package ou de l’instance du package – plusieurs valeurs possibles séparées par des virgules)</li>
<li><u>key</u> : la clé du message (= la méthode à invoquer)</li>
<li><u>data</u> : le contenu du message (= les arguments de la méthode)</li>
<li><u>sagaId</u> (optionnel) : l’identification de la saga si le message est envoyé dans une saga</li>
</ul>
</li>
</ul>
<p>Vous pouvez également invoquer cette action en POST. Le corps de votre requête contiendra l’objet JSON suivant :</p>
<p></p><pre class="crayon-plain-tag">{
  "Scope" : { "Scope" : "&lt;type&gt;", Args: [ "&lt;arg1&gt;", "&lt;args2&gt;", .... ], "SagaId":"Identifiant de la Saga" },
  "Key" : "&lt;Key&gt;",
  "Data" : "&lt;Data&gt;"
}</pre><p></p>
<p>La propriété “SagaId” dans le JSON ci-dessus est optionnelle.</p>
<p>Par exemple pour envoyer un message au package Nest en invoquant la méthode (key) “SetTargetTemperature” avec en paramètre le nombre “21” :</p>
<p></p><pre class="crayon-plain-tag">http://localhost:8088/rest/consumer/SendMessage?SentinelName=Consumer&amp;PackageName=Demo&amp;AccessKey=MaCleDeTest123&amp;scope=Package&amp;args=Nest&amp;key=SetTargetTemperature&amp;data=21</pre><p></p>
<p>Par exemple pour invoquer ce MessageCallback depuis cURL :</p>
<p></p><pre class="crayon-plain-tag">curl "http://localhost:8088/rest/consumer/SendMessage?SentinelName=Consumer&amp;PackageName=Demo&amp;AccessKey=MaCleDeTest123&amp;scope=Package&amp;args=Nest&amp;key=SetTargetTemperature&amp;data=21"</pre><p></p>
<p>Ce même MessageCallback “SetTargetTemperature” du package Nest peut être invoqué dans une saga afin de recevoir un un accusé de réception :</p>
<p></p><pre class="crayon-plain-tag">http://localhost:8088/rest/consumer/SendMessage?SentinelName=Consumer&amp;PackageName=Demo&amp;AccessKey=MaCleDeTest123&amp;scope=Package&amp;args=Nest&amp;key=SetTargetTemperature&amp;data=21&amp;sagaId=123456789</pre><p></p>
<p>Il faudra ensuite “récupérer” les messages reçus (voir dessous) pour lire la réponse à votre saga que nous avons ici identifié par la clé “123456789”.</p>
<p>Autre exemple avec un MessageCallback avec plusieurs paramètres :</p>
<p></p><pre class="crayon-plain-tag">http://localhost:8088/rest/consumer/SendMessage?SentinelName=Consumer&amp;PackageName=Demo&amp;AccessKey=MaCleDeTest123&amp;scope=Package&amp;args=MyPackage&amp;key=MethodeAvec3Params&amp;data=[ 'param 1', 123, true ]</pre><p></p>
<p>Attention le contenu du paramètre « args » doit être encodé. De ce fait, avec cURL :</p>
<p></p><pre class="crayon-plain-tag">curl "http://localhost:8088/rest/consumer/SendMessage?SentinelName=Consumer&amp;PackageName=Demo&amp;AccessKey=MaCleDeTest123&amp;scope=Package&amp;args=MyPackage&amp;key=MethodeAvec3Params&amp;data=%5B+%27param+1%27%2C+123%2C+true+%5D"</pre><p></p>
<p>Pour invoquer ce même MC avec un « POST » depuis cURL :</p>
<p></p><pre class="crayon-plain-tag">curl -H "Content-Type: application/json" -X POST -i -d '{ "Scope" : { "Scope" : "Package", Args: [ "MyPackage"] }, "Key" : "MethodeAvec3Params", "Data" : [ "param 1", 123, true ] }' "http://localhost:8088/rest/consumer/SendMessage?SentinelName=Consumer&amp;PackageName=Demo&amp;AccessKey=MaCleDeTest123"</pre><p></p>
<h3>Recevoir des messages</h3>
<h4>Créer un abonnement de réception</h4>
<p>Tout d’abord pour recevoir des messages il faut s’abonner aux messages.</p>
<ul>
<li>Action : “SubscribeToMessage” (GET)</li>
<li>Paramètres :
<ul>
<li><u>subscriptionId</u> (optionnel) : identifiant de l’abonnement si déjà connu</li>
</ul>
</li>
</ul>
<p></p><pre class="crayon-plain-tag">http://localhost:8088/rest/consumer/SubscribeToMessage?SentinelName=Consumer&amp;PackageName=Demo&amp;AccessKey=MaCleDeTest123</pre><p></p>
<p>Vous obtiendrez en réponse l’ID de votre abonnement, le “Subscription Id”.</p>
<h4>Relever les messages</h4>
<ul>
<li>Action : “GetMessages” (GET)</li>
<li>Paramètres :
<ul>
<li><u>subscriptionId</u> : identifiant de l’abonnement</li>
<li><u>timeout</u> (optionnel – par défaut 60000) : temps maximal en milliseconde de la mise en attente de la requête (entre 1000ms et 120000ms)</li>
<li><u>limit</u> (optionnel – par défaut 0) : nombre maximum de message à retourner pour l’appel</li>
</ul>
<p><!--EndFragment--></li>
</ul>
<p>Il s’agit d’une requête en “long-polling” c’est à dire que la requête sera “bloquée” sur le serveur tant qu’il n’y a pas de message reçu évitant ainsi de “flooder” en continue le serveur pour savoir si de nouveaux messages sont disponibles ou non. Par défaut la requête est bloquée 60 secondes maximum mais vous pouvez personnaliser cette valeur avec le paramètre “timeout”. Si il y a des messages disponibles, le serveur vous renvoi un tableau JSON avec les messages reçus. Si il n’y a pas de réponse dans le délai spécifié par le paramètre “timeout” (60 secondes par défaut), le tableau retourné sera vide.</p>
<p>A chaque réponse vous devez donc relancer une requête “GetMessages” pour “écouter” les prochains messages qui vont sont destinés.</p>
<p>Il est également possible de limiter le nombre de message dans la réponse avec le paramètre “limit” ce qui peut être utile sur de petits “devices” ne disposant pas de beaucoup de mémoire RAM pour désérialiser de gros tableaux JSON.</p>
<p>Exemple simple :</p>
<p></p><pre class="crayon-plain-tag">http://localhost:8088/rest/consumer/GetMessages?SentinelName=Consumer&amp;PackageName=Demo&amp;AccessKey=MaCleDeTest123&amp;subscriptionId=xxxxx</pre><p></p>
<p>Autre exemple en limitant le nombre de message à 2 par appel et en bloquant la requête pendant 10 secondes au maximum :</p>
<p></p><pre class="crayon-plain-tag">http://localhost:8088/rest/consumer/GetMessages?SentinelName=Consumer&amp;PackageName=Demo&amp;AccessKey=MaCleDeTest123&amp;subscriptionId=xxxxx&amp;timeout=10000&amp;limit=2</pre><p></p>
<h4>S’abonner à un groupe</h4>
<p>Vous pouvez vous abonner à des groupes pour recevoir les messages envoyés dans ces groupes par l’action “SubscribeToMessageGroup” en précisant le nom du groupe et votre ID d’abonnement.</p>
<ul>
<li>Action : “SubscribeToMessageGroup” (GET)</li>
<li>Paramètres :
<ul>
<li><u>group</u> : le nom du groupe à joindre</li>
<li><u>subscriptionId</u> (optionnel) : identifiant de l’abonnement si déjà connu</li>
</ul>
</li>
</ul>
<p></p><pre class="crayon-plain-tag">http://localhost:8088/rest/consumer/SubscribeToMessageGroup?SentinelName=Consumer&amp;PackageName=Demo&amp;AccessKey=MaCleDeTest123&amp;subscriptionId=xxxxx&amp;group=A</pre><p></p>
<p>Comme l’action “SubscribeToMessage”, cette action vous retourne l’ID d’abonnement à utiliser pour l’action “GetMessages”.</p>
<h3>Consommation de StateObjects</h3>
<h4>Request</h4>
<p>Cette méthode permet de récupérer la valeur actuelle d’un ou de plusieurs StateObjects.</p>
<ul>
<li>Action : “RequestStateObjects” (GET)</li>
<li>Paramètres :
<ul>
<li><u>sentinel</u> (optionnel – par défaut “*”): nom de la sentinelle</li>
<li><u>package</u> (optionnel – par défaut “*”) : nom du package</li>
<li><u>name</u> (optionnel – par défaut “*”) : nom du StateObject</li>
<li><u>type</u> (optionnel – par défaut “*”) : type du StateObject</li>
</ul>
</li>
</ul>
<p>Par exemple pour récupérer tous les StateObject de votre Constellation :</p>
<p></p><pre class="crayon-plain-tag">http://localhost:8088/rest/consumer/RequestStateObjects?SentinelName=Consumer&amp;PackageName=Demo&amp;AccessKey=MaCleDeTest123</pre><p></p>
<p>Ou seulement ceux produits par le package “HWMonitor” (quelque soit la sentinelle) :</p>
<p></p><pre class="crayon-plain-tag">http://localhost:8088/rest/consumer/RequestStateObjects?SentinelName=Consumer&amp;PackageName=Demo&amp;AccessKey=MaCleDeTest123&amp;package=HWMonitor</pre><p></p>
<p>Ou encore tous les StateObjects nommés “/intelcpu/load/0” et produits le package “HWMonitor” (quelque soit la sentinelle) :</p>
<p></p><pre class="crayon-plain-tag">http://localhost:8088/rest/consumer/RequestStateObjects?SentinelName=Consumer&amp;PackageName=Demo&amp;AccessKey=MaCleDeTest123&amp;package=HWMonitor&amp;name=/intelcpu/load/0</pre><p></p>
<h4>Subscribe</h4>
<p>Vous pouvez également vous abonner aux mises à jour des StateObjects.</p>
<p>Le principe est le même qu’avec les messages : il faut récupérer un ID d’abonnement et invoquer une méthode en long-polling pour recevoir les mises à jour.</p>
<h5>S’abonner à des StateObjects</h5>
<ul>
<li>Action : “SubscribeToStateObjects” (GET)</li>
<li>Paramètres :
<ul>
<li><u>subscriptionId</u> (optionnel) : identifiant de l’abonnement si déjà connu</li>
<li><u>sentinel</u> (optionnel – par défaut “*”): nom de la sentinelle</li>
<li><u>package</u> (optionnel – par défaut “*”) : nom du package</li>
<li><u>name</u> (optionnel – par défaut “*”) : nom du StateObject</li>
<li><u>type</u> (optionnel – par défaut “*”) : type du StateObject</li>
</ul>
</li>
</ul>
<p>En retour vous obtiendrez l’ID d’abonnement (un GUID).</p>
<p>Par exemple pour s’abonner au SO “/intelcpu/load/0”, produit le package “HWMonitor” sur la sentinelle “MON-PC” :</p>
<p></p><pre class="crayon-plain-tag">http://localhost:8088/rest/consumer/SubscribeToStateObjects?SentinelName=Consumer&amp;PackageName=Demo&amp;AccessKey=MaCleDeTest123&amp;sentinel=MON-PC&amp;package=HWMonitor&amp;name=/intelcpu/load/0</pre><p></p>
<p><strong>ATTENTION</strong> : si vous souhaitez “ajouter” des SO à votre abonnement vous devez <u>impérativement</u> préciser votre ID d’abonnement récupéré lors du 1er appel autrement vous allez créer un nouvel abonnement.</p>
<p>Par exemple pour “ajouter” le SO correspondant à la consommation RAM :</p>
<p></p><pre class="crayon-plain-tag">http://localhost:8088/rest/consumer/SubscribeToStateObjects?SentinelName=Consumer&amp;PackageName=Demo&amp;AccessKey=MaCleDeTest123&amp;sentinel=MON-PC&amp;package=HWMonitor&amp;name=/ram/load&amp;subscriptionId=&lt;subId&gt;</pre><p></p>
<h5>Relever les StateObjects mis à jour</h5>
<p>Pour récupérer les SO de votre abonnement qui ont changés entre deux appels vous devez invoquer l’action “GetStateObjects” en spécifiant l’ID de votre abonnement :</p>
<ul>
<li>Action : “GetStateObjects” (GET)</li>
<li>Paramètres :
<ul>
<li><u>subscriptionId</u> : identifiant de l’abonnement</li>
<li><u>timeout</u> (optionnel – par défaut 60000) : temps maximal en milliseconde de la mise en attente de la requête (entre 1000ms et 120000ms)</li>
<li><u>limit</u> (optionnel – par défaut 0) : nombre maximum de message à retourner pour l’appel</li>
</ul>
</li>
<li><!--EndFragment--></li>
</ul>
<p>Comme pour les message, vous pouvez limiter le nombre de SO (limit) et le timeout de la requête (timeout).</p>
<p></p><pre class="crayon-plain-tag">http://localhost:8088/rest/consumer/GetStateObjects?SentinelName=Consumer&amp;PackageName=Demo&amp;AccessKey=MaCleDeTest123&amp;subscriptionId=&lt;subId&gt;</pre><p></p>
<p>Notez que si un StateObject pour lequel vous êtes abonné change plusieurs fois entre deux appels “GetStateObjects”, vous obtiendrez la dernière valeur et non l’historique de tous les changements.</p>
<p>The post <a rel="nofollow" href="https://developer.myconstellation.io/client-api/rest-api/interface-rest-consumer/">L&rsquo;interface REST « Consumer »</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/rest-api/interface-rest-consumer/feed/</wfw:commentRss>
			<slash:comments>2</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:50:33 by W3 Total Cache
-->