Raspberry Pi et domotique

raspberry-ban
Afin d’appareiller nos maisons respectives, nous cherchions une solution domotique abordable.
Après avoir fait le tour du net et des magasins de bricolage, nous nous sommes fixés sur les équipements avec une fréquence de 433Mhz. Ces équipements sont économiques, les protocoles utilisés sont statiques et il est très simple de trouver de quoi communiquer avec.

Le projet

Nous avons profité d’un projet lancé par l’ENSICAEN en partenariat avec Radiospare. Nous souhaitons d’ailleurs les remercier tous les deux pour nous avoir accompagner tant financièrement que techniquement durant ce projet.

La base du projet est la réalisation d’un projet domotique avec Raspberry Pi.

Nous avons choisi de réaliser un petit module à greffer sur les ports du Raspberry Pi afin de pouvoir éteindre et allumer des équipements en RF433 (volets roulants, prises, lumières, etc…).
Une fois ce module réalisé, nous avons développé une interface web afin de pouvoir utiliser et scénariser les équipements.

L’architecture

Nous avons développé notre module à l’aide d’un composant permettant de moduler et démoduler les signaux RF433, le RTX MID 3V.

Afin de capturer les signaux, nous avions besoin d’un système temps réel. La première solution consiste à installer un OS temps réel sur le Raspberry Pi. La seconde consiste à utiliser un micro-contrôleur. Nous sommes partis sur la seconde solution et avons développé sur un PIC18F24k50. Il présente l’avantage d’être petit, économique et de disposer de suffisamment de RAM.

architexture_hard

Les signaux

Les signaux qui permettent de commander les équipements sont statiques. Ceci implique que pour chaque commande allumer et éteindre, le signal émit est identique. La figure ci dessous représente un signal quelconque.

signal

L’objectif de notre module est donc de faire un enregistreur de signal capable de le réémettre. Nous avons remarqué que le signal de commande était réémis plusieurs fois de suite par les émetteurs du commerce. Ceci est dû au fait que le protocole est à sens unique. Il n’y a donc pas de validation (ACK) une fois le signal reçu. Ces espaces vides sont cependant présents sur plusieurs protocoles RF433 que nous avons observé à l’oscilloscope (équipements des marques DIO et Carrefour).

Afin d’acquérir correctement le signal émis à l’intention de ces équipements, nous utilisons l’algorithme suivant :

  1. Lire état (haut/bas)
  2. Si état haut continuer, sinon revenir à 1
  3. Enregistrer le plus longtemps possible
  4. Chercher la plus longue série d’états bas consécutifs
  5. Chercher la plus proche série d’états bas consécutifs de longueur équivalente
  6. Le signal se trouve entre les deux séries d’états bas

Il suffit ensuite d’émettre plusieurs fois ce signal pour allumer ou éteindre un équipement. Cet algorithme a été implémenté en C. L’enregistrement fonctionne sur le module et la recherche du signal (étape 4 à 6) tourne sur le Raspberry Pi.

Le module

Le module se connecte sur les PIN du Raspberry Pi. La communication entre le Raspberry Pi et le PIC18F24k50 est assuré au travers du port série. Pour cela, il a été nécessaire d’utiliser une astuce pour retirer la console du port série d’un Raspberry Pi.
Le module tient dans un boîtier de Raspberry Pi avec une antenne de 8.175 cm de long.
IMG_20141122_172059

Les prochains travaux consisterons à améliorer l’antenne afin d’optimiser la porté en réception afin de permettre l’ajout de nouveaux modules.

Interface Web

Afin de mettre en place l’interface web, nous avons installé un serveur Nginx. La base php et les interfaces ont été développés par Antoine Choquet.

home

equipements

Quand est ce que ça sort

Nous réalisons encore quelques tests avec l’antenne, ce qui peut entraîner quelques changements sur le PCB. En parallèle, nous testons encore un peu le scripts d’installation. Tout ça devrait être prêt dans le courant de décembre, avant noël. Comme toujours, les sources et les schematics seront libres.

Open data, les calendriers

android

Dans cet article nous verrons comment récupérer les données d’un google agenda afin de le rendre exploitable par une application android ou java. Je l’utilise moi même pour le système d’intelligence artificiel qui contrôle ma maison. Je peux ainsi prévoir mes prochains rendez vous et connaitre mes rendez vous de la journée lorsque je me lève. Afin de réaliser le parsing des données, j’utilise la librairie iCal4j qui est assez bien documenté et pour lequel le net regorge d’exemple.

Le format iCalendar

Le format est iCal est un format qui permet de représenter les agendas. Il s’agit d’un format normalisé. La page Wikipedia à ce sujet est assez bien réalisée et je vous laisse le soin de la visualiser.

Google propose d’exporter vos agendas dans ce format. Vous ne devriez pas rencontrez de difficulté si vous suivez les instructions des services de google à cette adresse. Attention à bien lire jusqu’au bout et à partager votre agenda (le rendre public) pour pouvoir accèder aux données.

Vous devez maintenant avoir un lien iCal qui ressemble à celui ci : « https://www.google.com/calendar/ical/mon.compte%40gmail.com/public/basic.ics »

Quelques exemples

Si vous avez pris le temps de lire la page Wikipedia, vous connaissez maintenant les différents composants que l’ont peux récupérer. Si vous ne l’avez pas encore fait je vous invite à le faire, c’est très rapide et ceci vous permettra de comprendre comment fonctionne le standard.

J’aimerai récupérer mon prochain rendez vous afin de l’afficher par exemple. Si celui ci a lieu dans plus de 7 jours, alors je n’en prends pas compte et indique à l’utilisateur qu’il n’a pas de rendez vous prévu dans les 7 prochains jours.

Pour cela il est nécessaire de :

  1. Récupérer un flux vers l’url de mon google agenda au format iCal
  2. Parser ce flux de données
  3. Filtrer les données pour récupérer les VEVENTs qui ont lieu dans les 7 prochains jours
  4. Afficher le premier VEVENT ou bien un message si il n’y a pas de rendez vous dans les 7 prochains jours

ce qui donne le code correspondant :

//1 Récupérer le flux de icalendar à partir de mon google agenda
URL googleCalendar = new URL("https://www.google.com/calendar/ical/mon.compte%40gmail.com/public/basic.ics");
BufferedReader in = new BufferedReader(new InputStreamReader(googleCalendar.openStream()));
 
//2 Parser le flux de données
CalendarBuilder builder = new CalendarBuilder();
Calendar calendar = builder.build(in);
 
//3 Filtrer les données pour récupérer les VEVENTs qui ont lieu dans les 7 prochains jours
Period period = new Period(new DateTime(today.getTime()), new Dur(7, 0, 0, 0));
Filter filter = new Filter(new PeriodRule(period));
Collection<?> eventsToday = filter.filter(calendar.getComponents(Component.VEVENT));
 
//4 Afficher le premier VEVENT ou bien un message si il n'y a pas de rendez vous dans les 7 prochains jours
Iterator<?> i = eventsToday.iterator();
if (!i.hasNext()) {
   System.out.println("Pas de rendez vous dans les 7 prochains jours");
} else {
   Component component = (Component) i.next();
 
   DateTime dateStart = new DateTime(component.getProperty("DTSTART").getValue());
   //DateTime dateEnd = new DateTime(component.getProperty("DTEND").getValue());
   String description = component.getProperty("DESCRIPTION").getValue();
   String location = component.getProperty("LOCATION").getValue();
   String name = component.getProperty("SUMMARY").getValue();
DateFormat formater = new SimpleDateFormat("dd MMMM yyyy 'à' hh 'heure et' mm 'minutes'",new Locale("FR", "fr"));
 
sentence = "Vous avez rendez-vous " + name + " le " + formater.format(dateStart) + ".";
if(null != location && !location.isEmpty()) {
   sentence = sentence + " Il se tiendra à " + location + ".";
}
 
if(null != description && !description.isEmpty()) {
   sentence = sentence + " La description asocié est " + description + ".";
}
 
System.out.println(sentence);

Afin d’obtenir d’avantage d’exemples, je vous invite à parcourir la page du wiki de iCal4j : http://wiki.modularity.net.au/ical4j/index.php?title=Examples
Vous y trouverez des exemples pour ajouter / récupérer des VEVENT, VCARD, générer un iCal etc…