Table des matières
1 Introduction
2 Concepts SimpleBee
2.1 Intégration dans le framework Open the Box
3 Pratique
3.1 Etape 1 – Intégrer un équipement SimpleBee à un application Open the Box
3.1.1 Installer le base driver SimpleBee
3.1.2 Intégrer la librairie SimpleBee au projet de l’application Open the Box
3.1.3 Mettre à jour le fichier Declarative Services component-devices.xml
3.1.4 Mettre à jour la classe d’implémentation du composant Declarative Services
3.1.5 Utilisation de l’instance SimpleBee pour récupérer la valeur métier
3.1.6 Exercice
3.2 Etape 2 – Configurer la donnée métier
3.2.1 Exercice
3.3 Etape 3 – Recevoir des notifications de changement de donnée métier
3.3.1 Exercice
4 Annexes
4.1 Programmation du dongle
4.2 Décodage des données métier
4.2.1 Thermomètre
4.2.2 Capteur de luminosité
4.2.3 Sandtimer
4.3 Exemple d’application
1. Introduction
SimpleBee est un protocole d’échange au-dessus de la technologie radio 802.15.4 implémenté dans les modules XBee de la société Digi International. Le Laboratoire Informatique de Grenoble (LIG) et Orange ont spécifié une couche applicative extensible afin de faciliter le prototypage d’équipements communicants.
Le base driver SimpleBee permet l’accès aux équipements SimpleBee. Ce base driver est disponible en open source sur le site github Orange. Pour le développement des équipements, un tutoriel et le code source sont aussi disponibles sur le site github Orange.
Le présent document montre comment intégrer des équipements SimpleBee dans une application Open the Box.
Ce tutoriel est décomposé en deux parties. La première partie présente sommairement la technologie SimpleBee ainsi que ces concepts, la seconde montre comment interagir avec un équipement SimpleBee depuis une application Open the Box.
2. Concepts SimpleBee
2.1. Intégration dans le framework Open the Box
Un base driver a été développé en collaboration avec les équipes du LIG et d’Orange. Ce base driver enregistre des services de type com.orange.simplebee.SimpleBeeDevice pour chaque équipement SimpleBee disponible sur le réseau. Ces services SimpleBeeDevice sont dés-enregistrés lorsque l’équipement SimpleBee n’est plus disponible.
Chaque équipement SimpleBee propose une donnée “métier” qui peut être lue et, selon le type d’équipement, configurée. Les instances SimpleBeeDevice permettent de lire et d’écrire cette donnée métier. Il est aussi possible, pour les applications Open the Box, de recevoir des notifications de la part des équipements SimpleBee.
3. Pratique
La présente section met en œuvre les concepts décrits précédemment. Afin de s’exercer, on pourra partir de l’application vide hackathon.template.app et la compléter. Des idées d’exercices seront proposées dans les sous-sections suivantes.
La première partie montre comment une application Open the Box peut utiliser un équipement SimpleBee afin de récupérer sa donnée métier. La seconde partie décrit comment configurer la donnée métier d’un équipement SimpleBee. La dernière enfin précise comment recevoir des notifications de changement de valeur métier d’un équipement SimpleBee.
3.1. Étape 1 – Intégrer un équipement SimpleBee à une application Open the Box
Pour interagir avec un équipement SimpleBee, les opérations suivantes doivent être réalisées.
- Installer le base driver.
- Intégrer la librairie SimpleBee au projet de l’application.
- Mettre à jour le fichier Declarative Services component-devices.xml pour créer une dépendance vers des services de type com.orange.simplebee.SimpleBeeDevice.
- Mettre à jour la classe d’implémentation du composant défini dans le fichier Declarative Services afin de récupérer les instances de type SimpleBeeDevice.
- Enfin, lire la valeur métier de l’équipement.
3.1.1. Installer le base driver SimpleBee
Le base driver SimpleBee est installé nativement sur le framework Open the Box. Il est nécessaire de brancher le dongle SimpleBee avant de lancer le framework.
Le fichier load/simplebee.xml permet de paramétrer le base driver SimpleBee et notamment le descripteur de fichier Linux :
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE cm_data PUBLIC '-//Gatespace//DTD cm_data 0.1//EN' 'cm_data.dtd'> <cm_data version="0.1"> <!-- EDITING THIS FILE IS NOT GUARANTEED TO WORK --> <configuration pid="simplebee.driver.manager" mode="new"> <property name="simplebee.driver.port"> <value type="String">/dev/ttyUSB0</value> </property> <property name="service.pid"> <value type="String">simplebee.driver.manager</value> </property> <property name="simplebee.driver.baud.rate"> <value type="Integer">115200</value> </property> </configuration> </cm_data>
Il convient de mettre dans la propriété simplebee.driver.port la valeur du descripteur de fichier Linux associé au dongle SimpleBee.
Note importante : dans le cas où l’on veut utiliser le protocole SimpleBee en simultané avec le protocole ZigBee, il convient de brancher les deux dongles SimpleBee et ZigBee avant de démarrer le framework.
3.1.2. Intégrer la librairie SimpleBee au projet de l’application Open the Box
Pour ajouter la librairie SimpleBee, il convient d’éditer le fichier pom.xml de l’application et de rajouter la portion suivante dans la section dependencies :
<dependency> <groupId>com.orange.dhsa.homeapi</groupId> <artifactId>simplebee.basedriver</artifactId> <version>1.0.3-SNAPSHOT</version> </dependency>
On exécute ensuite la commande :
mvn eclipse:eclipse
afin de mettre à jour les dépendances dans le projet Eclipse de l’application.
3.1.3. Mettre à jour le fichier Declarative Services component-devices.xml
Le fichier component-devices.xml décrit les services OSGi (et donc les équipements SimpleBee) nécessaires à l’exécution de l’application. Ce fichier est primordial car le framework Open the Box l’utilise afin de donner les permissions aux équipements.
Afin d’interagir avec les équipements SimpleBee, l’application doit définir une dépendance vers des services de type com.orange.simplebee.SimpleBeeDevice. Il faut ainsi modifier la déclaration du component
et créer une nouvelle balise reference
:
<reference interface="com.orange.simplebee.SimpleBeeDevice" cardinality="0..n" policy="dynamic" target="(DEVICE_TYPE=BINARY_LIGHT)" bind="bindSimpleBeeDevice" unbind="unbindSimpleBeeDevice"/>
On pourra, en fonction des besoins de l’application, faire varier / ajouter les paramètres :
- cardinality : définit le nombre d’instances de services devant être utilisés (0..1, 1..1, 0..n, 1..n) ;
- target : filtre pour préciser les équipements à sélectionner.
Le paramètre target permet de filtrer les instances de services SimpleBeeDevice. On pourra utiliser la propriété DEVICE_TYPE (exemple: (DEVICE_TYPE=BINARY_LIGHT)
):
- Bouton poussoir :
DEVICE_TYPE=PUSH_BUTTON
- Led :
DEVICE_TYPE=BINARY_LIGHT
- Détecteur de mouvement :
DEVICE_TYPE=MOTION_SENSOR
- Power switch :
DEVICE_TYPE=POWER_SWITCH
- Détecteur de luminosité :
DEVICE_TYPE=LIGHT_SENSOR
- Thermomètre :
DEVICE_TYPE=TEMPERATURE_SENSOR
- Sablier électronique :
DEVICE_TYPE=SANDTIMER
3.1.4. Mettre à jour la classe d’implémentation du composant Declarative Services
Il convient d’implémenter, dans la classe du composant (balise implementation), les méthodes bindSimpleBeeDevice(com.orange.simplebee.SimpleBeeDevice)
et unbindSimpleBeeDevice(com.orange.simplebee.SimpleBeeDevice)
qui ont été définies dans la balise reference
(cf sous-section précédente). La méthode bindSimpleBeeDevice(com.orange.simplebee.SimpleBeeDevice)
est appelée lorsque un équipement SimpleBee devient disponible. À l’inverse, la méthode unbindSimpleBeeDevice(com.orange.simplebee.SimpleBeeDevice)
est appelée lorsque qu’il devient indisponible.
Un exemple d’implémentation pour la méthode bindSimpleBeeDevice(SimpleBeeDevice)
:
Dans l’idéal, on stockera dans une variable membre de la classe l’instance SimpleBeeDevice fourni par la méthode bindSimpleBeeDevice(SimpleBeeDevice)
.
Un exemple d’implémentation pour la méthode unbindSimpleBeeDevice(SimpleBeeDevice)
:
3.1.5. Utilisation de l’instance SimpleBeeDevice pour récupérer la valeur métier
Chaque équipement SimpleBee possède une donnée métier qu’il est possible de lire depuis l’équipement. La récupération de cette donnée se fait simplement en invoquant la méthode SimpleBeeDevice.getData()
. La valeur renvoyée est un String dont le format dépend de l’équipement :
Équipement | Valeurs possibles |
---|---|
Bouton poussoir | “0”: bouton relâché “1”: bouton appuyé |
Led | “0”: lampe éteinte “1”: lampe allumée |
Détecteur de mouvement | “0”: pas de présence détectée “1”: présence détectée |
Détecteur de luminosité | chaîne de 4 caractères. Voir la méthodologie de décodage en annexe |
Thermomètre | chaîne de 4 caractères. Voir la méthodologie de décodage en annexe |
Sandtimer | chaîne de 3 caractères. Voir la méthodologie de décodage en annexe |
À titre d’information, il existe également les méthodes SimpleBeeDevice.getSerial()
, qui renvoie le numéro de série de l’équipement SimpleBee, et SimpleBeeDevice.getModuleAddress()
qui donne son adresse réseau.
3.1.6. Exercice
À partir de l’application hackathon.template.app, utiliser un ou plusieurs équipements SimpleBee. On pourra par exemple récupérer la donnée métier de l’équipement et l’afficher dans la page Web de l’application.
3.2. Étape 2 – Configurer la donnée métier d’un équipement
Certains équipements SimpleBee acceptent que les applications Open the Box puissent configurer leur valeur métier.
C’est le cas des équipements suivants:
Équipement | Valeurs acceptées |
---|---|
Led | “0” : éteint “1”: allumé |
Sandtimer | Nombre : “0” à “6” permettant d’allumer les leds |
La donnée métier est simplement configurée via la méthode SimpleBeeDevice.setData(String)
.
3.2.1. Exercice
Avec le sandtimer, allumer les leds et les éteindre pour créer un compte à rebours électronique.
3.3. Étape 3 -Recevoir des notifications de changement de donnée métier
Chaque équipement SimpleBee émet nativement des événements à chaque fois que sa donnée métier évolue. Il en est de même pour son niveau de batterie.
Une application peut être notifiée de tels événements en enregistrant un service OSGi de type com.orange.simplebee.SimpleBeeListener.
On peut modifier la déclaration du composant Declarative Services (component-devices.xml) en ajoutant la balise service
qui indique que le composant sera enregistré en tant que service OSGi :
Ensuite, on peut optionnellement définir un filtre permettant de spécifier de quel équipement SimpleBee on veut recevoir des notifications. Pour ce faire, on ajoute la propriété DEVICE_SERIAL au niveau de la racine du component
qui permet de spécifier le numéro de série de l’équipement dans la définition du composant Declarative Services :
Enfin, il faut que la classe d’implémentation du composant implémente l’interface com.orange.simplebee.SimpleBeeListener.
Cette interface contient la méthode updateData(SimpleBeeDevice simpleBeeDevice, String oldData, String newData)
:
- simpleBeeDevice spécifie l’équipement SimpleBee ayant envoyé la notification ;
- oldData est la précédente valeur connue (String) ;
- newData est la nouvelle valeur de la donnée métier.
À chaque changement de la valeur de la donnée métier d’un équipement SimpleBee, le base driver SimpleBee appellera la méthode SimpleBeeListener.updateData()
de tous les SimpleBeeListener éligibles.
L’interface SimpleBeeListener contient aussi la méthode updateBatteryLevel(SimpleBeeDevice simpleBeeDevice, float oldBatteryLevel, float newBatteryLevel)
:
- simpleBeeDevice spécifie l’équipement ayant envoyé la notification ;
- oldBatteryLevel est le précédent niveau de batterie ;
- newBatteryLevel est le nouveau niveau de batterie.
À chaque changement du niveau de batterie d’un équipement SimpleBee, le base driver SimpleBee appellera la méthode SimpleBeeListener.updateBatteryLevel(..)
de tous les SimpleBeeListener éligibles.
3.3.1. Exercice
Enregistrer un SimpleBeeListener afin de recevoir des notifications de données métier ou de niveau de batterie.
4. Annexes
4.1. Programmation du dongle
Les propriétés USB du dongle doivent avoir été modifiées par un programme du style FT_Prog. Les propriétés attendues sont :
- ModelName : “SimpleBeeDongle”
- VendorName : “Orange”
4.2. Décodage des données métier
4.2.1. Thermomètre
La valeur obtenue est une chaîne de 4 caractères. Par exemple: “1/>0”.
Il faut convertir chaque caractère en byte (new Byte(s)) :
Caractère | Valeur en byte (hexadécimal) |
---|---|
1 | 0x31 |
/ | 0x3A |
> | 0x3E |
0 | 0x00 |
Le dernier caractère est non significatif et est toujours égal à 0.
Ensuite, pour les 3 premières valeurs, on garde seulement les 4 bits de poids faible :
Valeur | 4 bits de poids faible |
---|---|
0x31 | 1 |
0x3A | A |
0x3E | E |
Ce qui nous donne le résultat 0x1AE que l’on multiplie par 0.0625:
0x1AE = 430 (base 10) * 0.0625 = 26.875 °c
Ci-dessous un extrait de code qui décode la température. La méthode decodeTemperature(String newData) renvoie la valeur de la température sous forme de float. Le paramètre newData est la valeur de donnée métier lue ou reçue par notification d’un équipement SimpleBee de type thermomètre :
4.2.2. Capteur de luminosité
La valeur obtenue est une chaîne de 4 caractères par exemple “>9<:”.
Il faut passer en byte chaque caractère suivant la table ASCII :
Caractère | Valeur en byte (hexadécimal) |
---|---|
> | 0x3E |
9 | 0x39 |
< | 0x3C |
: | 0x3A |
À partir de ces valeurs en bytes, on reconstitue deux nouvelles valeurs à partir respectivement des deux premiers octets et des deux derniers :
0x3E 0x39 —> 0xE9
0x3C 0x3A —> 0xCA
La première valeur reconstituée (i.e. v0 = 0xE9) va permettre de calculer c0, la seconde (i.e. v1 = oxCA) donnera c1.
Pour chacune de ces deux valeurs reconstituées, on calcule respectivement i0 et i1 en suivant la formule suivante :
ix = (vx & 0x70) >> 4
Pour notre exemple, i0 = 6 et i1 = 4.
Ensuite, en fonction de la valeur de i, on se sert de la table de correspondance suivante afin d’obtenir les valeurs chord et step :
Valeur de i | chord | step |
---|---|---|
0 | 0 | 1 |
1 | 16 | 2 |
2 | 49 | 4 |
3 | 115 | 8 |
4 | 247 | 16 |
5 | 511 | 32 |
6 | 1039 | 64 |
7 | 2095 | 128 |
En suivant cette table de correspondance, on obtient les valeurs chord0=1039, step0=64, chord1=247 et step1=16.
Il convient ensuite de calculer la valeur step_number pour les première et deuxième valeurs reconstituées avec la formule :
step_numberx = vx & 0x0F
On obtient step_number0=9 et step_number1=A.
Enfin, on calcule c0 et c1 avec la formule :
cx = chordx + (stepx * step_numberx)
si la valeur reconstituée est supérieure ou égale à 128 (base 10) sinon -1.
On obtient c0=1615 et c1=407.
Et finalement, la valeur de la luminosité en lux est donnée par la formule :
luminosité = c0 * 0.46 * e(-3.13 * c0 / c1)
Pour notre exemple, luminosité = 337.56 lux.
Ci-dessous un extrait de la méthode decodeLux(newData)
qui permet le décodage de la valeur de la luminosité à partir du paramètre newData qui est la valeur lue ou reçue par notification :
4.2.3. Sandtimer
La donnée métier du Sandtimer est une string de 3 caractères représentant l’accélération sur l’axe X, Y et Z subit par l’objet.
Les valeurs possibles pour chacun des trois axes sont 0 et 8. Ces deux valeurs sont cycliques (i.e 0 devient 8 puis 0).
Dès qu’un mouvement est détecté sur l’un des axes, une notification est émise.
4.3. Exemple d’application
Une application exemple utilisant l’ensemble des équipements SimpleBee disponibles est téléchargeable ici : m2m.simplebee.application