xPL.Arduino, réception des messages

Bonjour, j’ai ouvert un projet sur google code récement : xPL.Arduino. C’est une librairie permettant l’émission et le decodage de message xPL. Je vais vous expliquer rapidement dans cet article comment réceptionner et parser les messages xPL.

[adsGrandRectangleHTexte]

Les sources de la librairie sont accessibles sur google code et la version 0.2 est disponible dans la section download.

Je vais vous détailler les exemples concernant le shield ENC28J60 puisque c’est celui que j’utilise pour le moment et qu’il est légèrement plus compliqué à mettre en oeuvre.

Réception des messages xPL

Je vous rappelle que j’utilise la librairie ethercard pour la gestion du shield ethernet.

La partie déclaration. On définit ici le buffer de réception des trames ethernet (au moins égale à la taille max d’un message xPL) ainsi que les paramètres de la carte réseau. Adresse IP, MAC, Passerelle et l’adresse de broadcast du réseau.
Attention, la librairie ethercard n’émet des packets en broadcast que sur l’adresse 255.255.255.255, n’indiquez donc pas ici l’adresse de broadcast du réseau (192.168.0.255 dans mon cas). Et si vous utilisez xpl-perl, indiquez au xpl-hub d’écouter sur 0.0.0.0 avec –define broadcast=0.0.0.0 sinon vous ne recevrez rien :/

#include <xPL.h>
#include <EtherCard.h>

byte Ethernet::buffer[XPL_MESSAGE_BUFFER_MAX];
xPL xpl;

// Init du serveur HTTP
uint8_t mymac[6] = { 0x54,0x55,0x58,0x10,0x00,0x11 };
uint8_t myip[4] = { 192,168,0,133 };
uint8_t gwip[4] = { 192,168,0,240};

// Ethercard seems to only send broadcast on this addr
// if using xpl-perl, don't forget to add "--define broadcast=0.0.0.0" to the xpl-hub
uint8_t broadcast[4] = { 255,255,255,255};

On définit ensuite deux fonctions. Une qui se chargera de l’émission des messages sur le réseau. Cette fonction est à adapter en fonction du shield ethernet et de la libraire ethernet utilisée.

void SendUdPMessage(char *buffer)
{
    ether.sendUdp (buffer, strlen(buffer), xpl.udp_port, broadcast, xpl.udp_port);
}

La deuxième fonction sera appellée par la librairie xPL à chaque fois qu’elle aura parsé un message xPL avec succès. On y fait ce que l’on veut, c’est ici que l’on va faire réagir l’arduino en fonction du type de message reçu.
Dans l’exemple, on affiche le message dans la console et si le message est explicitement destiné à l’arduino (xpl.TargeIsMe), on vérifie de quel type est ce message. Si son schéma est de type lighting.basic on affiche un message sur la console.

void AfterParseAction(xPL_Message * message)
{
  if (xpl.TargetIsMe(message))
  {
    if (message->IsSchema_P(PSTR("lighting"), PSTR("basic")))
    {
      Serial.println(PSTR("is lighting.basic"));  
    }
  }

  // show message
  Serial.println(message->toString());
}

Vient ensuite le setup. On passe nos deux fonctions à la librairie xPL, puis on définit la source par laquelle l’arduino sera vu sur le réseau xPL, ici : xpl-arduino.test. Il reste ensuite à définir l’interval en minutes entre chaque message heartbeat. Ces messages permettent aux autres applications xPL du réseau de connaitre votre application et de savoir si elle est toujours active.

void setup()
{
  [...]

  xpl.SendExternal = &SendUdPMessage;  // pointer to the send callback
  xpl.AfterParseAction = &AfterParseAction;  // pointer to a post parsing action callback
  xpl.SetSource_P(PSTR("xpl"), PSTR("arduino"), PSTR("test")); // parameters for hearbeat message
}

Le corp du sketch. On commence par xpl.Process(). Cette méthode gère l’émission des messages heartbeat.
On récupère ensuite les packets entrant (ether.packetReceive()) et si c’est un message xPL on le parse avec xpl.ParseInputMessage.
Si vous avez suivis, une fois le parsing terminé, la librairie appelle notre fonction AfterParseAction pour traiter le message.

void loop()
{
   xpl.Process();  // heartbeat management

   word len = ether.packetReceive();
   if( len > 0 )
   {
     // Check if Xpl UDP packet
     if( isXpl( Ethernet::buffer ) )
     {
       char xPLMessageBuff[XPL_MESSAGE_BUFFER_MAX];
       ByteToChar(Ethernet::buffer, xPLMessageBuff, len);

       // parse du message
       xpl.ParseInputMessage(xPLMessageBuff);
     }
   }
}

Et voila, c’est tout pour la réception de messages. Je vous invite à lire l’article suivant sur l’émission de message xPL.

Partagez moi ...Tweet about this on TwitterShare on Facebook0Share on Google+0Digg thisEmail this to someone

Vous aimerez aussi...

18 réponses

  1. Goo dit :

    Bonjour,

    J’essai actuellement d’utiliser votre librairie, cependant lorsque je test le code d’exemple pour le shield ethernet classique, le premier message reçu est affiché entièrement mais le second ne contient pas de commande.

    De plus, tout ce qui utilise le progmem ne semble pas fonctionner :
    – Serial.println(PSTR( …
    – IsSchema_P(PSTR(« lighting »), PSTR(« basic »))

    Pourtant il détecte bien lorsqu’un message est pour lui.

    Faut il ajouter quelque chose pour la gestion du Progmem ? Merci de votre aide

    Goo

    • Olivier dit :

      Bonjour,

      N’ayant pas encore de shield officiel, je n’ai testé que sur enc28j60. Cependant tout le code de la librairie est commun, il n’y a que le code du sketch qui change donc ca devrait fonctionner de la meme façon.

      Deux choses à vérifier :
      sur quelle version de l’IDE arduino travaillez vous ? < à 1.0 ou >= à 1.0 ?
      et sur quel arduino ? Il me semble que pour l’instant, niveau memoire, le UNO est un peut juste pour le parser (à vérifier).

      • Goo dit :

        Tout d’abord, merci de votre réponse si rapide.

        Je suis sur un shield officiel, un arduino UNO et un IDE 1.0.1.
        Avec les 2 corrections précisée dans le post ci dessous, tout fonctionne parfaitement lors de la reception du premier message.

        En revanche, a partir du deuxième message, seules les commandes ne sont plus enregistrée.

        Edit : pendant que l’écriture de ce message j’ai fait un test dont le résultat est étrange :

        Envoie du premier message (contenant 3 commande) : pas de souci.
        Envoie d’un autre message (1 commande) : pas de souci.
        Envoie du message à 3 commande : probleme.
        Envoie du message à 1 commande : pas de souci

        • Olivier dit :

          Pour l’IDE, c’est celui que j’utilsie aussi.

          Pour les commands, la memoire est alouée dynamiquement (pas top sur de l’embarqué) mais on limite (arbitrairement) les messages à 10 commandes.
          Normalement c’est désaloué proprement une fois le message traité. Il faudrait peut etre vérifier de ce coté ?

          • Goo dit :

            En effet le problème semble être dû à un problème de taille mémoire.
            Après avoir réduit la taille des valeurs à 32 (au lieu de 128) tout semble fonctionner.

            Merci beaucoup

          • Olivier dit :

            Par contre tu risque de recevoir des messages xPL incomplets :/ (je n’en ai jamais vu d’une telle taille cela dit)
            128 est la taille définit dans la spec du protocol.

            Je cherche justement à réduire l’empreinte mémoire du parser donc si tu as des idées n’hésite pas 🙂

    • Zulu dit :

      Hi there,

      Warning: I’m not a programmer so I might say dumb things. 😉

      I’m playing with xPL and have a problem accessing the commands and values when there are multiple in the xPL message.
      The xPL message is like:

      xpl-stat
      {
      hop=1
      source=blah.host
      target=*
      }
      sensor.basic
      {
      device=testdevice
      type=input
      current=99
      }

      In my Arduino source I use:

      void AfterParseAction(xPL_Message * message)
      {
      Serial.println(message->command_count);
      ParseSensorUpdate(message->command->name);
      ParseSensorUpdate(message->command->value);
      }

      The message count is 3 as expected, but my ParseSensorUpdate function only sees « device » and « testdevice » for name and value of the xPL-command.

      How can I access the « current » and « 99 » part?
      I tried « ParseSensorUpdate(message->command[1].name) » and various combinations, but I doesn’t compile… 🙁

  2. Goo dit :

    Je rajoute une petite précision

    Dans IsSchema, ne faudrait il pas changer :

    if (memcmp(schema.class_id, _classId, 8) == 0)

    par

    if (memcmp(schema.class_id, _classId, strlen(schema.class_id)) == 0)

    ?

    • Olivier dit :

      Si si tu as raison, il y a une coquille ici que johan m’a remonté la semaine dernière. Je n’ai pas eu le temps de corriger et vérifier le reste du code.
      Si l’arduino chope des messages avec des shemas qui font justement 8 caractères cela pose problème.

      Merci pour l’info, j’essai de corriger rapidement.

  3. Laurent dit :

    Bonjour, j’ai retravaillé le code de la librairie parce que j’avais plusieurs problèmes de fuite de mémoire + le parser qui n’était pas totalement bullet-proof sur des messages mal formés. J’ai posté cela sur le site de google dans la partie issues:

    • Olivier dit :

      Salut,
      Merci Laurent pour ton travail. Suite aux commentaires de Goo et Johan j’avais commencé à regarder ces problèmes mais je ne suis pas aller aussi loin 🙂
      Veux tu un accès en tant que commiter sur le projet google code ?

  4. Johan dit :

    Hi,

    My French writing skills are not very good, so please excuse me for writing in English.

    I used the zip file from the bug report at http://code.google.com/p/xpl-arduino/issues/detail?id=1in order to get it working.
    It contains an error were an IP address was hardcoded in xPL.cpp.
    I assume this was for a test, because the correct line was just before it and was commented out.

    I stil have 2 issues, though.

    1: It seems « if (xpl.TargetIsMe(message)) » does not work.
    2: How can I have access to the command and the values of a received xPL message? Is this functionality available?

    The last part is quite imortant. 🙂

    Is this library still maintained?

    • Olivier dit :

      Hi,

      No problem 🙂

      The author of the bug report have change the heartbeat schema from hbeat.basic to hbeat.app in which you have some more informations (port, remote-ip). According to the specifications this is used by « PC based app ». For small devices, you can use hbeat.basic (the commented line above) and change XPL_HBEAT_ANSWER_TYPE_ID from « app » to « basic »

      >1: It seems « if (xpl.TargetIsMe(message)) » does not work.
      Can’t say, I need to make a test :/

      >2: How can I have access to the command and the values of a received xPL message? Is this functionality available?
      There is actually no functions to acces command tab but it’s a public properties of the xPL_Message class so you should be able to use it directly.
      Would you want some search functions ?

      > Is this library still maintained?
      Yes, I will release a new version (based on the version from the bug report) as soon as possible, just need to find some time to test it before :/
      I email you as soon a new version is available if you want.

  5. Quentin dit :

    Bonjour j’ai également le même problème que Goo après l’envoie de les messages via une première carte Arduino, je veux récuperer l’information avec cette deuxième carte arduino mais il ne m’affiche que le premier message entièrement

    xpl-trig
    {
    hop=1
    source=xpl-arduino.test
    target=*
    }
    sensor.basic
    {
    device=1
    type=temp
    current=27.63
    }

    xpl-trig
    {
    hop=1
    source=xpl-arduino.test
    target=*
    }
    sensor.basic
    {

    xpl-trig
    {
    hop=1
    source=xpl-arduino.test
    target=*
    }
    sensor.basic
    {

    Voici à peut près le résultat IDE 1.0.3 avec une carte Arduino UNO et un shield Ethernet Officiel

    Cordialement Quentin

  6. Quentin dit :

    Ah désolé pour le post j’ai utilisé la librairie de Laurent et ca marche maintenant 😉

  7. SnowPatrolXV dit :

    Bonjour Olivier,

    Je cherche à implémenter le protocol xPL sur ma carte Arduino et je suis tombé sur ton blog qui parlait d’une librairie que tu as developpé.

    Je suis donc très intéressé pour utiliser cette librairie mais j’ai quelques questions avant :

    1 – La librairie est-elle indépendante du connecteur réseau ? utilisation d’un module wifi ou zigbee par exemple ?

    2 – Laurent a corrigé des bugs dans la librairie mais au vu de la date de création du zip de la 0.2, la librairie ne comporte pas les fix de Laurent.

    Est-ce bien le cas ? si oui, serait-il possible d’avoir une nouvelle version avec ces fix ?

    merci d’avance

    • Olivier dit :

      Bonsoir,
      Le code est indépendant du hardware, charge à toi d’ajouter le code nécessaire à l’envoi du paquet dans le sketch. J’ai testé, et fournis un ex, sur les deux shields Ethernet connus (l’officiel et le ENC) donc ça devrait le faire pour d’autre type de matériel.

      Effectivement je n’ai pas maintenu la librairie (suite à la vente de ma maison). La version corrigée de Laurent est disponible ici si je ne me trompe pas: https://code.google.com/p/xpl-arduino/issues/detail?id=1
      Je viens tout juste de racheter une maison que je compte domotiser, il est donc probable que dans les mois à venir je rafraichisse tout ça 🙂

      ++

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *