Mar.24

S-Energy : la solution de monitoring des ressources énergétiques de la maison – Geek Is In Da House 2015 – quand la maison vous fera sortir de votre douche, de gré ou de force !

Microsoft TechDays 2015Suite à la mythique “Geek Is In Da House” des Microsoft Techdays 2015 que j’ai pu animer aux côtés de David Catuhe, Stanislas Quastana et Laurent Ellerbach , retour en détail sur mon projet “S-Energy” !

(Passage dédié à S-Energy à 31’30).

L’idée du projet fait suite à un problème de chaudière qui est intervenu en Septembre 2014. En effet lors de l’entretien annuel nous avons constaté que la vanne de sécurité du ballon d’eau chaude était défaillante laissant ainsi partir dans les canalisations des litres et des litres d’eau en continue !

Après investigation, ce problème est apparu environ 4 mois plus tôt, soit une perte sèche de plus de 450m3, l’équivalent de 3750 litres par jour (environ 25 bains tous les jours !).

Vanne de sécurité défaillante sur la chaudière

Alors forcément côté portefeuille c’est dur et côté orgueil, pour un “geek” avec une maison ultra connectée, ne pas détecter une perte de près de 4.000L/jour pendant plus de 4 mois, c’est tout simplement honteux Sourire

Logo S-Energy

Dès lors, je me mis en tête de concevoir “S-Energy”, une solution de monitoring intelligente des ressources énergétiques de la maison : eau, gaz et électricité.

Intelligente car une simple solution de monitoring qui ne produit que des graphiques de la consommation n’a pour moi que peu d’intérêt ! C’est bien sûr indispensable d’avoir un historique très précis sur sa consommation mais ça ne suffit pas !

L’intelligence réside dans le fait que la maison “prend conscience” de cette consommation en temps réel et dans la durée et est capable d’agir en fonction ! Vous avertir en cas de consommation anormale, vous incitez à consommer moins, etc…

Dans cet article vous découvrirez comment j’ai pu monitorer mes anciens compteurs qui n’ont pourtant pas d’interface pour permettre de faire des “auto-relevés” (impulsions, télé info, etc..) mais aussi comment je me sers des données produites grâce à la plateforme d’interconnexion des objets connectés “Constellation” pour créer de l’intelligence autour des ressources énergiques de la maison.


Mes compteurs et les solutions du marché

Quand on regarde mes compteurs, il s’agit là de vieux compteurs datant des années 90.

Mes compteurs : eau, electricité, gaz

Hélas pas de télé-info ou d’impulsion pouvant être facilement captée à l’image du compteur d’eau “Sensus Résidia Jet” qui couplé au module Z-Wave SECURE par exemple, permet de remonter très facilement votre consommation d’eau à une box domotique.

Module Z-Wave pour compteur d'eau

Il existe bien des solutions sur le marché comme OpenEnergyMonitor ou encore la solution “made in france” d’EWattch mais ces dernières sont basées sur des compteurs à impulsion et télé-info pour la partie électrique, bref tout ce que je n’ai pas !

Open Energy Monitor E-wattch

Ces deux solutions utilisent aussi des pinces ampérométrique pour l’électricité : il s’agit de pinces qu’on fixe autour d’un câble de phase et qui en déduisent l’intensité du courant électrique (donc la puissance en connaissant la tension) par le champ magnétique généré.

C’est une technique que j’utilise depuis des années. Il y a plus de trois ans, à l’aide de modules Gadgeteer et du .NET MicroFramework, j’avais réalisé un système d’estimation de ma consommation d’électricité basée sur une pince ampérométrique. La mainboard affichait la consommation instantanée sur un écran touch et envoyait, via un module Wifi, l’information dans le cloud Windows Azure.  En quelque sorte, l’ancêtre de S-Energy :

EnergyMeter à base de GadgeteerEnergyMeter à base de Gadgeteer

EnergyMeter à base de Gadgeteer

Plus tard j’ai remplacé ce système par le module Z-Wave HEM de chez Aeon Labs comme présenté dans mon article “Piloter sa maison : c’est facile !”.

HEM

Mais le problème des pinces ampérométrique est qu’ils ne donnent qu’une estimation car il y a un taux d’erreur non-négligeable due à la technique de mesure et de calcul. Parfait pour donner une estimation de la consommation instantanée, mais il y une dérive importante dans le temps quant à la consommation cumulée.

Alors dernier recours : changer les compteurs par des modèles plus récents ?… Bien trop cher (plusieurs centaines d’euros par compteur) !

Pour résumer : les solutions existantes ne peuvent pas monitorer mes vieux compteurs et je refuse de dépenser de grosses sommes pour les changer ! En clair je dois trouver des solutions (qui plus est, fiables et précises) compatibles avec mes compteurs actuels !

 

Monitoring du compteur électrique avec un opto-interrupteur

Il y a un moyen très fiable de calculer la consommation électrique : le disque métallique qui tourne ! En effet, il s’agit d’un disque métallique avec une petite bande noir ! Chaque tour équivaut à 4 Watts/heures consommés.

Il suffit donc de compter le nombre de tour pour connaitre très précisément combien j’ai consommé d’électricité et chronométrer la vitesse de révolution pour estimer ma consommation instantanée ! C’est d’autant plus facile que le disque est métallique, donc réfléchit bien la lumière !

Pour cela j’utilise un opto-interrupteur ! Il s’agit d’un interrupteur optique : d’un côté il y a un émetteur et de l’autre un récepteur.

 Opto-interrupteur

Installé face au disque du compteur, l’opto-interrupteur va émettre un faisceau infrarouge qui sera réfléchit par le disque métallique et capté par la partie récepteur. Dès lors que la bande noir passera devant on ne captera plus cette lumière infrarouge : un nouveau tour vient d’être détecté !

Préparation de l'opto-interrupteurPréparation de l'opto-interrupteur

Préparation de l'opto-interrupteur

Pour driver çà, j’utilise un Arduino Pro Mini à 16Mhez et fonctionnant sur 5V (environ 2€ sur eBay !!) :

Préparation de l'Arduino Pro MiniPréparation de l'Arduino Pro Mini

Pour le circuit, j’ai utilisé une simple plaque époxy découpé à la bonne taille :

Préparation de la plaque epoxyPréparation de la plaque epoxy

Et pour pouvoir facilement remplacer l’Arduino ou le module de RF, j’utile des barrettes male/femelle :

Réalisation du circuitRéalisation du circuit

Réalisation du circuitRéalisation du circuit

L’idée du circuit est de pouvoir commander l’émetteur IR via la sortie digital n° 2 (D2) de mon Arduino. Pour la lecture de la valeur du capteur, on utilisera l’entrée analogique n°2 (A2).

Une LED rouge s’allumera à chaque tour détecté pour avoir un feedback visuel du bon fonctionnement de notre circuit. On connecte cette LED sur la sortie digitale n°9 (D9).

Enfin, à chaque tour l’idée est d’envoyer l’information à une base que nous verrons dans la suite de cet article. Pour la communication, nous utiliserons les radiofréquences sur la bande des 2,4Ghz. Pour cela j’utilise un module nRF24L01+ connecté sur le bus SPI de l’Arduino.

Comme ce module doit être alimenté en 3,3V et que notre Arduino est en 5V, j’ai ajouté un régulateur de tension LM1117T 3,3V avec quelques condensateurs 10uF.

Le schéma final :

Schéma sous Fritzing

Schéma des composants

Pour la suite, il ne reste plus qu’à installer le circuit dans un petit boitier et connecter la puce nRF24L01+ ainsi que l’Arduino Pro Mini :

Installation du circuit dans un boiter ABSInstallation de l'Arduino Pro Mini & module nRF24L01+

Pour la programmation, j’utilise une interface FTDI USB pour “téléverser” le code de l’Arduino:

Programmation de l'ArduinoProgrammation de l'Arduino

Le code est relativement simple. Je commence par déclarer les librairies que je vais utiliser, principalement le SPI et la librairie RF24 pour émettre nos informations en RF.

#include <spi.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"

Ensuite je déclare les constantes pour la detection de la bande noir sur notre disque ainsi que la configuration des IO et de la puce nRF24 :

// Const
const int edgeThreshold = 25; 		// seuil max. dans la bande noir
const int normalThreshold = 150;	// seuil min. sur la bande argentée
const int interval =  20;		// interval entre deux mesures
 
// HW Configuration			
const int emitterPin = 2;		// sortie digitale
const int analogSendorPin = 2;		// entrée analogique
const int ledPin =  9;			// sortie digitale
const uint64_t pipe = 0xF0F0F0F0E1LL;
 
// Set up nRF24L01 radio on SPI + pin for CE, CSN
RF24 radio(8, 7);

Pour finir, je déclare deux variables : une pour le n° du tour detecté et l’autre pour savoir si je suis dans la bande noir ou non :

// Variables
unsigned long c=0; // c = nombre de revolutions
unsigned int t=0; // t = 0 : je suis sur la bande noir, t = 1 ; je suis sur la bande argentée

Au démarrage du programme je configure mes IO et la radio :

void setup() {
  // Starting serial console
  Serial.begin(57600);
  printf_begin();  
  // Configure outputs
  pinMode(emitterPin, OUTPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(emitterPin, HIGH);
  digitalWrite(ledPin, LOW);  
  // Configure RF radio
  radio.begin();
  radio.setAutoAck(1);                    // Ensure autoACK is enabled
  radio.setRetries(15,15);
  radio.openWritingPipe(pipe);
  radio.printDetails();  
  // Started
  Serial.println("Started !");
}

Dans la boucle principale, je mesure l’intensité du signal reçu. Si cette mesure est deux fois de suite (pour éviter les faux positifs) inférieure au seuil “edgeThreshold” alors que j’étais précédement sur la bande argenté (t = 1), alors on vient de détecter un nouveau tour !

Dans ce cas j’incrémente la variable du nombre de tour (c) et je place “t” à 0 pour indiquer que je suis maintenant sur la bande noire.

J’allume ensuite la LED rouge et je prépare un tableau de long qui contiendra le n° du tour (variable c) ainsi que le timestamp (fonction “millis()” qui nous retourne le nombre de millisecondes depuis le démarrage du programme). Cette information nous permettra de calculer le temps de révolution et donc d’en déduire la consommation instantanée.

Après avoir envoyé ce tableau dans le pipe de notre module RF, j’éteins la LED rouge.

Autrement si la mesure de l’intensité du faisceau infrarouge est (deux fois de suite) supérieure au seuil “normalThreshold” c’est que je suis dans la bande argentée, je positionne alors notre variable “t” à 1, prêt pour détecter un nouveau tour !

void loop() {
  if (analogRead(analogSendorPin) < edgeThreshold) {
    delay(interval);
    int sensorValue = analogRead(analogSendorPin);
    if (sensorValue < edgeThreshold) {
      if (t==1) {
        // Increment counter
        t=0; c++;
        // LED Power On
        digitalWrite(ledPin, HIGH);
        // Prepare data to send
        unsigned long datas[2];
        datas[0] = c;
        datas[1] = millis();
        // Send datas
        radio.write(datas, sizeof(datas));
        // LED Power Off
        digitalWrite(ledPin, LOW);
      }
    }
  }
  if (analogRead(analogSendorPin) > normalThreshold) {
    delay(interval);
    if (analogRead(analogSendorPin) > normalThreshold) {
      t=1;
    }
  } 
}

Il ne me reste plus qu’à installer notre système devant le compteur électrique :

Boitier fini !Signal infrarouge

Installation du dispositif sur le compteur electrique

Je vous conseille d’utiliser un appareil photo ou une caméra pour “voir” le rayon IR afin de positionner précisément votre opto-interrupteur. La LED rouge vous permettra de savoir si la détection des tours est correcte.

Il ne restera plus qu’à réceptionner les données reçues par RF, ce que nous verrons dans la suite de cet article.

Monitoring du compteur d’eau avec une simple caméra

Comme vous le savez impossible d’équiper une quelconque solution de monitoring pour mon compteur d’eau sans le remplacer !

Photo du compteur prise par le Raspberry

Pour éviter d’en arriver là, j’ai opté pour une bonne veille technique : lire le compteur d’eau !!!

Côté hardware, il faudra “juste” faire une photo du compteur que j’analyserai ensuite par un programme de reconnaissance des caractères (OCR).

Comme la solution sera basée sur un Raspberry Pi, j’ai sélectionné la RaspiCam ! Il faudra cependant régler l’objectif pour pouvoir prendre des photos nettes à moins de 30 cm. Bon courage car l’objectif est collé, vraiment pas évident Sourire

RaspiCam calibrée

Comme le compteur est dans un environnement obscur, il faudra ajouter des LEDs pour pouvoir éclairer le compteur lors des photos.

Monitoring du compteur de gaz avec un compteur d’impulsion magnétique

Le compteur de gaz est la partie la plus facile du projet. En effet je suis équipé d’un compteur Itron Gallon G4 sur lequel il est possible d’installer un compteur d’impulsion :

Compteur d'impulsion pour Itron Gallus G4

J’ai tout simplement tiré un câble RJ45 (double blindage) derrière les grilles des radiateurs jusqu’au module de compteur d’impulsion qui sera installé sur le compteur.

Installation du module sur mon compteur de gaz

Réalisation de la base S-Energy avec un Raspberry Pi

Le Raspberry Pi va permettre de faire l’acquisition des trois compteurs :

  • Gaz : en captant les impulsions du compteur de gaz Itron Gallus
  • Electricité : réceptionnant les données émises en RF
  • Eau : en analysant par OCR des photos du compteur d’eau

Pour clarifier les choses, le compteur d’eau et de gaz sont relativement proche (dans le salon) à l’inverse du compteur d’électricité qui se trouve dans l’entrée, c’est pourquoi j’ai choisi une communication sans fil entre la base « Raspberry » et l’Arduino pour le compteur électrique afin d’éviter de devoir passer un câble.

Architecture physique d'S-Energy

Le Raspberry sera connecté dans mon système Constellation, une plateforme d’interconnexion des objets connectés qui me permettra beaucoup de chose comme nous le verrons par la suite.

Pour la réalisation technique, j’ai utilisé un boitier étanche transparent dans lequel j’ai fait passer un câble RJ45 par un presse-étoupe :

Boitier étancheArrivée d'un cable RJ45 par un presse-etoupe

Le câble RJ45 me permettra :

  • De connecter le Raspberry au réseau (donc à la Constellation) en utilisant seulement 2 paires (100 MBits sur un RPi, donc pas besoin de plus)
  • De l’alimenter (utilisation d’une paire pour faire arriver du 5V, attention tout de même à la section de votre câble)
  • D’y connecter le module d’impulsion pour le gaz (via une paire)

Sur la paroi j’ai installé quelques LED et la camera pour photographier le compteur d’eau dans le noir :

Camera & LEDs

J’ai ensuite réalisé un petit circuit pour le pilotage des LEDs via le RPi et pour pouvoir accueillir un module nRF24L01+ pour la réception des infos du compteur électrique.

PCB pour l'installation du module RF et pilotage des LEDs

Le tout assemblé dans le boitier :

Schéma global

Il ne reste plus qu’à l’installer juste au-dessus du compteur d’eau :

Installation

S-Energy : test LEDInstallation OK

Pour l’expérience WAF, on remet les grilles des radiateurs et les meubles en place, pour une technologie invisible :

WAF Certified !

Il ne reste plus qu’à programmer et exploiter tout cela maintenant Sourire

Programmation et intégration dans la Constellation

Chez moi j’ai beaucoup de machines qui tournent. Des serveurs physiques, des machines virtuelles, des NUC, les laptops, des Raspberry, etc… Que ce soit sous Linux ou Windows !

Sur chacune de ces machines, il y a une armée de programme qui fonctionne 24/7 ! Une passerelle vers la Vera, une pour l’alarme Paradox, les lampes Hue, la NetAtmo, mais aussi des programmes comme Slight, S-Sound mon système audio multiroom, des programmes de surveillance du hardware, The Mirror, etc.. etc…

Il n’est pas envisageable d’écrire autant de programme/service en repartant “from scratch” et à déployer sur autant de machine !!! A chaque mise à jour, il faudrait se connecter sur la machine en RDP ou SSH pour linux, arrêter les services, déployer les MAJ, relancer les services, etc.. Quelle perte de temps !

Pour simplifier tout cela, j’ai conçu depuis plus d’un an, une technologie nommée Constellation que vous avez pu découvrir dans mon article : l’alarme du geek connectée au poignet et dans les nuages

Constellation

Cette technologie sera ouverte très prochainement en open-source et vous permet de connecter vos applications, vos devices et objets sur une technologie simple et efficace !

Pour en revenir à S-Energy, la seule chose que je dois faire sur mon Raspberry est de connecter la bête à Constellation. Pour cela il suffit d’installer une “Sentinel” Constellation : copier des binaires, renseigner l’adresse du serveur Constellation et la clé d’accès, et hop mon Raspberry est enregistré dans ma constellation :

Sentinelles Constellation

Maintenant je peux commencer le développement d’un “Package” Constellation.

La plateforme Constellation est livrée avec un SDK basé sur l’IDE de Microsoft Visual Studio 2013 disponible gratuitement avec l’édition “Community”.

Pour développer sur une plateforme Raspberry, le plus simple est de concevoir son package en Python :

Creation du package Constellation Python

Grace l’IDE Visual Studio et au SDK Constellation, il devient très confortable de développer en Python depuis Visual Studio avec tout l’IntelliSense dont on a besoin :

Developpement dans Visual Studio

Réception des données du compteur électrique

Par manque de temps, je n’ai pas réussi à piloter le module nRF24 depuis un script Python, alors pour faire plus simple j’ai écrit un programme en C++ qui réceptionne les informations (numéro du tour et le timestamp) et l’affichage sur la sortie standard :

#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <RF24/RF24.h>
 
using namespace std;
 
// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 8Mhz
RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_26, BCM2835_SPI_SPEED_8MHZ);
 
// Radio pipe address
const uint64_t pipe_address = 0xF0F0F0F0E1LL;
 
int main(int argc, char** argv)
{	
	// Make line buffered stdout
	setvbuf( stdout, (char *) NULL, _IOLBF, 0 ); 
	// Starting server
	printf("S-Energy - Elec Server is starting ...\n");
	// Configure RF radio
	radio.begin();
	// optionally, increase the delay between retries & # of retries
	radio.setRetries( 15,15 );
	// Dump the configuration of the rf unit for debugging
	radio.printDetails();
	// Listening
	radio.openReadingPipe( 1, pipe_address );
	radio.startListening();	
	printf("Listening ...\n");
 
	while (1)
	{
		if ( radio.available() )
		{
			// Receive datas
			unsigned long revolution_count[2];
			radio.read( &revolution_count, sizeof(revolution_count) );			
			// Display datas
			printf( "Got revolution counter ! C = %lu @ %lu\n", revolution_count[0], revolution_count[1] );
		}
		//Delay to minimize RPi CPU time
		delay( 925 );
	}
	return 0;
}

Côté Python, je n’ai plus qu’à lancer ce programme et lire la sortie standard. Une petite regex pour extraire les informations et le tour est joué !

Pour lancer le process (en prenant soin de conserver son PID pour pouvoir tuer le processus en cas d’arrêt de notre package Constellation) :

def startElecServerProcess():
    global elecServerPID
    # Make the ElecServer's file as executable
    st = os.stat(ELECSERVER_EXECUTABLE_FILENAME)
    os.chmod(ELECSERVER_EXECUTABLE_FILENAME, st.st_mode | stat.S_IEXEC)
    # Start process
    process = subprocess.Popen("./" + ELECSERVER_EXECUTABLE_FILENAME, stdout=subprocess.PIPE)
    # Save his PID
    elecServerPID = process.pid
    # On exit, kill process
    Constellation.OnExitCallback = killChildProcess
    atexit.register(killChildProcess)
    return process

Au démarrage du package dans la Constellation, on lance le process et on parse chaque ligne sur la sortie standard :

def Start():
    Constellation.WriteInfo("Starting Electricy RF Receiver")    
    if Constellation.GetSetting("ShowDebug") is not None:
        SHOW_DEBUG =  str(Constellation.GetSetting("ShowDebug")).lower() == "true"
    # Start ElecServer process
    process = startElecServerProcess()
    while Constellation.IsRunning:
        # Reading elec server output
        for line in iter(process.stdout.readline, ''):
            readElecServerOutputLine(line)
 
Constellation.Start(Start)

Pour chaque ligne de notre programme C++, si la ligne match avec la regex, on récupère le n° du tour et le timestamp qu’on a plus qu’à envoyer dans la Constellation :

def readElecServerOutputLine(line):
    global e_lasttime 
    global e_lastcounter
    global e_cumul	
    isFirstRev = e_lasttime == 0
    # Parse line
    matchObj = re.match('Got revolution counter ! C = (\d*) @ (\d*)', line)
    if matchObj:
        # Reading value
        counter = int(matchObj.group(1))
        ts = int(matchObj.group(2))
        # Compare
        timediff = ts - e_lasttime
        counterNb = counter - e_lastcounter
        timePerRevolution = timediff / counterNb
        wattPerHour = (MS_PER_HOUR / timePerRevolution) * WATT_PER_REVOLUTION
        # History
        e_lasttime = ts
        e_lastcounter = counter
        e_cumul = counter * WATT_PER_REVOLUTION
        # Print
        if isFirstRev:
            Constellation.WriteInfo("[ELEC] First revolution detected #%s (%s - Cumul %s W)" % (counter, ts, e_cumul))
        else:            
            Constellation.PushStateObject("Electricity", { "Counter": counter, "Timestamp" : ts, "RevolutionTime" : timePerRevolution, "WattPerHour" : wattPerHour, "Cumul" : e_cumul }, "SEnergy.Electricity")
            if SHOW_DEBUG:
                Constellation.WriteInfo("[ELEC] New revolution #%s (%s) Time/rev: %s ms => %s Wh (Cumul %s W)" % (counter, ts, timePerRevolution, wattPerHour, e_cumul))
    else:
        Constellation.WriteInfo("INFO: %s" % line)

Vous remarquerez quelques fonctionnalités propres à la Constellation :

  • WriteInfo : permettant d’écrire des logs sur la Constellation
  • PushStateObject : permettant d’envoyer dans la Constellation des objets d’état. Ici notre script envoi un StateObject nommé “Electricity” qui contient les propriétés “Counter”, “Timestamp”, “RevolutionTime”, “WattPerHour” et “Cumul” représentant l’état du compteur electrique

Nous verrons plus loin comment nous pourrons exploiter les StateObjects produits par les packages Constellation pour réaliser des systèmes d’alerting, des dashboards temps réel ou encore des systèmes de reporting.

 

Capter les impulsions du compteur de gaz

Notre script pour le gaz est encore olus simple, on définit une GPIO d’entrée où est connectée le compteur d’impulsion en “Pull-Up” et on attend que l’entrée soit “risée” :

def Start():
    Constellation.WriteInfo("Starting GAS Sensor")
    Constellation.OnExitCallback = OnExit
    loadConfiguration()
    # Configure Gaz Sensor
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(GAZ_SENSOR_GPIO, GPIO.IN, pull_up_down = GPIO.PUD_UP)
    # Start sensor
    # GPIO.add_event_detect(GAZ_SENSOR_GPIO, GPIO.RISING, callback=risingGazSensor, bouncetime=300)
    while Constellation.IsRunning:
        # Wait rising sensor
        GPIO.wait_for_edge(GAZ_SENSOR_GPIO, GPIO.FALLING)
        GPIO.wait_for_edge(GAZ_SENSOR_GPIO, GPIO.RISING)
        # Rising sensor
        risingGazSensor()
 
Constellation.Start(Start)

A chaque impulsion captée, on push un StateObject dans la Constellation où on indique le n° de l’impulsion (variable incrémentée à chaque révolution) ou encore le temps de révolution :

def risingGazSensor():
    global g_counter
    global g_lasttime
    global g_lastdiff    
    if g_counter == 0:
        Constellation.WriteInfo("[GAS] First revolution detected")
    ts = int(round(time.time() * 1000))
    # Compare
    timediff = ts - g_lasttime
    g_counter += 1
    g_lasttime = ts
    # Push SO
    Constellation.PushStateObject("Gas", { "Counter": g_counter, "Timestamp" : ts, "RevolutionTime" : (timediff if g_counter > 1 else 0),  "Cumul" : g_counter * 10 }, "SEnergy.Gas")

 

Lecture du compteur d’eau

C’est la véritable difficulté du projet : lire la valeur du compteur d’eau à partir d’une photo !

Le démarrage du script est relativement simple : on charge les valeurs de configuration depuis la Constellation et on enregistre des MessageCallabcks.

Les MessageCallbacks permettent d’exposer des méthodes dans la Constellation pour que d’autre package ou application puissent les invoquer : c’est un système de Messaging intégré qui permet faire parler tout le monde (un script Python, Powershell, un programme C#, un Arduino, une page Web Javascript, etc..) ! Ici par exemple, on peut à partir d’une page Web par exemple, envoyer un message au Package “Senergy” de type “SendWaterMeterByMail” pour déclencher l’envoi de la photo du compteur par mail (utile pour un contrôle manuel).

Le plus important c’est qu’une fois démarré, on appelle la méthode “readWaterMeter” toutes les 30 secondes :

def Start():
    Constellation.WriteInfo("Starting OCR Water Reader")
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(LED_GPIO, GPIO.OUT)
    loadConfiguration()
    # Register MessageCallbacks
    Constellation.RegisterMessageCallback("CalibrateNumbersShape", calibrateNumbersShape, True, "Recalibrate the numbers shape")
    Constellation.RegisterMessageCallback("SendWaterMeterByMail", sendReportByMail, True, "Send the WaterMeter report by mail")
    Constellation.DeclarePackageDescriptor()
    Constellation.OnExitCallback = OnExit
    # Start
    while Constellation.IsRunning:
        readWaterMeter(IMAGE_FILENAME)
        time.sleep(INTERVAL) 
 
Constellation.Start(Start)

La première étape lors de la lecture du compteur c’est de prendre la photo du compteur !

Pour cela on allume les LEDs, on prend une photo en BGR et on éteint la lumière :

def takePicture():       
    GPIO.output(LED_GPIO, True)
    with picamera.PiCamera() as camera:
        with picamera.array.PiRGBArray(camera) as stream:
            camera.resolution = CAMERA_RESOLUTION
            camera.capture(stream, format="bgr")
            image = stream.array
    GPIO.output(LED_GPIO, False)
    return image

On obtient cela :

Image brute

La deuxième étape est de “trouver” l’emplacement des chiffres !

Nous allons utiliser des algorithmes de  “template matching” inclut dans OpenCV pour trouver les coordonnées de ces deux images :

Bord droit  Bord gauche

Si vous regardez attentivement il s’agit des bords gauche et droit :

findNumberShape

Comme nous travaillons sur une image haute résolution le traitement est assez long (environ 20 secondes sur un RPi V1). Nous conservons donc ces coordonnées dans la variable “numbersShapes” car d’une photo à l’autre les coordonnées ne sont pas censées bouger !

Reste ensuite à faire du cropping pour découper la partie de l’image qui nous intéresse, puis faire une rotation :

# Convert BGR to gray
    image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    # Find numbers shape
    if not numbersShape:
        numbersShape = findNumbersShape(image_gray)
    # Cropping
    (startingPoint, endingPoint, left, right) = numbersShape
    numbers = image_gray[startingPoint[1] + left[0] - 20 : endingPoint[1], startingPoint[0] : endingPoint[0] + left[1] + 20]
    # Rotation
    transposeImage = cv2.transpose(numbers)
    rotated = cv2.flip(transposeImage, 0)
    sizePerNumber = rotated.shape[1] / 8

Préparation de l'image pour OCR

Pour la suite, nous allons découper notre image en 8 parties égales, une pour chaque chiffre à “lire” :

# Searching numbers
for i in range(0, 8): 
    # Cropping number area
    number = rotated[0:rotated.shape[0], (sizePerNumber * i) - (10 if i > 1 else 0) :(sizePerNumber * i) + sizePerNumber - 10]

Encore une fois nous allons faire du “template matching” avec comme référence les images ci-dessous :

Templates des chiffres à trouver

Pour chacun des huit nombres du compteur nous allons tenter de trouver à quel chiffres possibles (0 à 9) il correspond, sachant que les 4 premiers chiffres sont blancs sur fond noir et les 4 dernières sont rouges sur fond blanc.

Si la correspondance dépasse 90% on considère qu’on tient le bon chiffre, sinon on tentera d’autre type de matching : par le haut et par le bas ! En fait on “crop” le template dans sa partie supérieure ou inférieure car le compteur tourne : on peut voir la fin d’un “2” et le début d’un “3”.

# For each type (0: full, 1: top & 2: bottom) 
for t in range(0, 3):
    # For each potential number from 0 to 9 (include)
    for j in range(0, 10):
        for file in os.listdir("OCR_Data/"):
            if file.startswith(str(j) + str('r' if i > 3 else 'b')):
                # Open template
                digit =  cv2.imread("OCR_Data/" + file, 0)
                if digit is not None:
                    if t == 0:
                        template = digit
                    elif t == 1:
                        digitW, digitH = digit.shape[::-1]
                        template = digit[0:digitH/1.5, 0:digitW]
                    elif t == 2:
                        digitW, digitH = digit.shape[::-1]
                        template = digit[digitH/2.5:digitH, 0:digitW]
                    # Finding template
                    x, y, score = findTemplate(number, template)
                    # Save the best score
                    if score > bestScore:
                        bestScore = score
                        bestNumber = j
                        bestType = t
                    # If it's top or bottom matching, keep potential number                    
                    if t > 0 and score > 0.8:
                        (scoringOnTop[i] if t == 1 else scoringOnBottom[i]).append((j, score))
    # Break search type if match more than 90%
    if bestScore >= 0.9:
        break

Si un chiffre n’est pas reconnu, j’inscris un “?” dans le résultat :

Test de l'algo d'OCR

Comme vous le voyez, l’algorithme arrive bien a découvrir des chiffres même en partie caché (comme ci-dessus où les nombre 7 et 9 sont partiels).

Je “push” un premier StateObject nommé “Water.ProcessInfo” qui contient mon objet “OrcResult” (un tableau qui pour chaque chiffre indique le type de matching et son score) mais aussi le temps de capture, le temps de traitement pour l’OCR, etc… En clair un StateObject de “debug” !

J’ai ensuite quelques tests pour valider le résultat de l’OCR :

  • un résultat ne peut avoir qu’un seul chiffre inconnu “?” et seulement le dernier (les décilitres)
  • un résultat ne peut pas être inferieure à la valeur précédente (c’est comme le temps, ca s’écoule que dans un sens Sourire)
  • la différente entre deux résultats ne peut pas être supérieure au débit maximum admissible par mon compteur d’eau (5m3/h max soit 0,00138 L / milliseconde).

En cas d’erreur, je m’envoi un mail avec la photo du compteur en pièce jointe pour analyse.

Si la valeur du compteur est cohérente, je pousse deux StateObjects dans la Constellation :

  • Water.Counter : qui indique la valeur actuelle du compteur (poussé si et seulement si la valeur est différente du compteur précèdent)
  • Water.Flow : contient des informations sur le débit d’eau courant : il s’agit du différentiel de temps et de litre entre les deux valeurs
 # Push detail
 Constellation.PushStateObject("Water.ProcessInfo", { "OcrResult": result, "Timestamp" : ts, "StringResult" : strResult, "CaptureTime": captureTime, "ProcessingTime": processingTime - captureTime }, "SEnergy.WaterProcessInfo")
 # Check result
 errorMessage = ""
 if not checkResult(result):
     errorMessage = "Error: unable to read the water meter. The result was : %s" % strResult
 if not errorMessage and w_lastcounter > 0 and w_lastcounter > intResult :
     if strResult.endswith("?") and strResult[:-1] == str(w_lastcounter)[:-1]:
         strResult = str(w_lastcounter)
         intResult = w_lastcounter
         literDelta = 0
         literPerHour = 0
     else:
         errorMessage = "Error while reading water meter. The result was : %s but its less than the previous counter: %s" %  (strResult, str(w_lastcounter))
 if not errorMessage and (w_lastcounter > 0 and literDelta > timediff * QN):            
     errorMessage = "Error while reading water meter. The result was : %s but the difference between the last counter (%s) is too high. LiterDelta:%s in %s ms" %  (strResult, str(w_lastcounter), str(literDelta), str(timediff))
 if errorMessage:
     Constellation.WriteError(errorMessage)
     sendErrorByMail(errorMessage, strResult)
     return None
 # Push result only if new value
 w_lasttime = ts
 if w_lastcounter != intResult:
     Constellation.PushStateObject("Water.Counter", {  "StringResult" : strResult, "Counter" : intResult, "Timestamp" : ts }, "SEnergy.WaterResult")
     w_lastcounter = intResult
 Constellation.PushStateObject("Water.Flow", { "Timestamp" : ts, "TimeDelta" : timediff, "LiterDelta" : literDelta, "LiterPerHour" : literPerHour  }, "SEnergy.WaterProcessInfo")

 

Déploiement du package dans la Constellation

Et voilà, notre package Constellation “S-Energy” est prêt ! Réception des infos par RF, lecture du compteur d’eau par OCR, détection des impulsions du compteur de gaz ! Toutes ses informations sont poussées dans des StateObjects Constellation !

Pour le déploiement il suffit depuis Visual Studio de publier le package dans la Constellation :

Packaging Constellation

Sur la WebConsole de ma Constellation, j’assigne le package “SEnergy” à la sentinelle installée sur le Raspberry du même nom. Le package démarre !

Démarrage du package

A coup d’œil dans la Console Web pour voir que tout démarre correctement :

Démarrage du package

Cette Console Web vous permettra de suivre en temps réel tous les “WriteLog” produits par tous vos packages de toutes vos sentinelles de votre Constellation.

Maintenant que tous mes compteurs sont publiés dans la Constellation, il ne reste plus qu’à exploiter les données !

Dashboard temps-réel

Première mission : afficher en temps-réel la valeur de mes compteurs ! Pour cela je vais utiliser l’API Javascript de la Constellation pour m’abonner aux modifications des StateObjects de SEnergy.

L’API Javascript Constellation est également disponible dans un package Nuget, il suffit donc d’installer le package pour récupérer les fichiers JS :

Installation de l'API Javascript Constellation

Ensuite dans notre page HTML ajoutons les références qui vont bien :

<script type="text/javascript" src="Scripts/jquery-2.1.3.min.js"></script>
<script type="text/javascript" src="Scripts/jquery.signalR-2.2.0.min.js"></script>
<script type="text/javascript" src="Scripts/Constellation.js"></script>

Puis je me connecte à mon serveur Constellation avec une clé d’accès afin de demander la valeur de tous les StateObjects du package SEnergy et m’abonner aux changements de ces StateObjects.

Dans l’exemple ci-dessous, j’affiche dans la console de mon navigateur le débit courant de l’eau (LiterPerHour du StateObject “Water.Flow”).

    var constellation = $.signalR.createConstellationClient("http://myConstellationServer:8888/constellation", "AccessKeyWithControlHubAccess", "SEnergy");
 
    constellation.client.onUpdateStateObject(function (message) {
        if (message.Name == "Water.Flow") {
            console.log("Debit courant = " + message.Value.LiterPerHour);
        }
    });
 
    constellation.connection.stateChanged(function (change) {
        if (change.newState === $.signalR.connectionState.connected) {
            constellation.server.requestStateObjects("*", "SEnergy", "*", "*");
            constellation.server.subscribeStateObjects("*", "SEnergy", "*", "*");
        }
    });
    constellation.connection.start();

Pour faire quelque chose de plus poussé, on peut utiliser le framework AngularJS. Pour cela, à chaque modification d’un StateObject je “broadcaste” le message de la Constellation dans le scope Angular :

    constellation.client.onUpdateStateObject(function (message) {
        $rootScope.$broadcast('updateStateObject', message);
 
    });

Puis dans mon scope, j’affecte tout simplement les propriétés de mes StateObjects à des variables de scope avec les différentes informations qui m’intéresse d’afficher :

$scope.$on('updateStateObject', function (event, message) {
    $scope.$apply(function () {
		if(message.Name == "Electricity"){												
			$scope.WattPerHour = message.Value.WattPerHour;
			$scope.ElectricityCumul = message.Value.Cumul;
			$scope.ElectricityRevolutionTime = message.Value.RevolutionTime;
			$scope.ElectricityCounter = message.Value.Counter;						
		}
		if(message.Name == "Gas"){					
			$scope.m3PerHour = message.Value.RevolutionTime > 0 ? Math.round(((60 * 60 * 1000) / message.Value.RevolutionTime) * 10) / 1000 : 0;
			$scope.GasCumul = message.Value.Cumul;
			$scope.GasRevolutionTime = message.Value.RevolutionTime;
			$scope.GasCounter = message.Value.Counter;			
			$scope.GasLastUpdate = message.LastUpdate;
		}	
		if(message.Name == "Water.Counter"){				
 
			$scope.WaterCumul = message.Value.Counter;
		}
		if(message.Name == "Water.Flow") {
			$scope.LiterPerHour = Math.round(message.Value.LiterPerHour * 100) / 100;
			$scope.LiterDelta = message.Value.LiterDelta;
		}
    });

Ne reste plus qu’à faire un bon template HTML. J’utilise une directive angular pour afficher des gauges JustGage :

<table>
  <tr>
    <td><just-gage id="gage1" value="baieReseauWatts" min=0 max=250 title="Baie Réseau"></just-gage></td>
    <td><just-gage id="gage2" value="hcWatts" min=0 max=500 title="Home Cinema"></just-gage></td>
    <td><just-gage id="gage6" value="light" min=0 max=20000 title="Light"></just-gage></td>
  </tr>
  <tr>
    <td><just-gage id="gage3" value="WattPerHour" min=0 max=6000 title="Electricity (W/h)"></just-gage></td>
    <td><just-gage id="gage4" value="m3PerHour" min=0 max=6 title="Gas (m3/h)"></just-gage></td>
    <td><just-gage id="gage5" value="LiterPerHour" min=0 max=2000 title="Water (L/h)"></just-gage></td>
  </tr>
</table>

J’utilise aussi dans mon template HTML le plugin jQuery Counter pour afficher les variables “Cumul”, la valeur des compteurs.

Et avec ces quelques lignes d’HTML, un peu de JS, le framework AngularJS et surtout l’API Constellation, j’obtiens très rapidement une interface HTML5 temps réel et responsive qui affiche ma consommation instantanée et cumulée de mes compteurs d’eau, de gaz et d’électricité :

Interface Web S-Energy

Vous remarquerez d’ailleurs que j’affiche également les informations de consommation de ma baie réseau et du home cinéma qui sont en fait issues du package Vera (interface Z-Wave dans la Constellation) qui push des StateObjects pour mes prises Z-Wave AN158 d’Everspring ! L’une des forces de la Constellation : tout est fédéré et interconnecté !

Reporting avec Windows Azure et Excel

Une fois notre interface Web temps réel réalisé, il me faut du reporting de mes consommations énergétiques.

Le principe est exactement le même que celui mis en place pour le reporting de mon système d’alarme que vous avez découvert dans mon article :  l’alarme du geek connectée au poignet et dans les nuages.

On utilisera le même package Constellation, le “Could Conector” :

Package CloudConnector

Ce package s’abonne aux mises à jour des StateObjects et dès que la valeur change, il l’enregistre dans une table Windows Azure Table :

image

Données historique dans Azure Table

La suite vous la connaissez déjà : je charge les données de ma table Azure dans Excel avec PowerQuery !

Chargement des données avec PowerQuery

Une fois mes données prétraitées, j’utilise un “data model” PowerPivot dans lequel je calcule le différentiel entre chaque ligne pour connaitre la consommation en utilisant des formules DAX.

J’ajoute également des colonnes pour calculer le cout de chaque énergie :

Traitement des données avec PowerPivot

Maintenant je peux créer des “Pivot Tables” dans ma feuille Excel et sélectionner le reporting que je souhaite :

Creation d'un pivot dans Excel

Et bien sûr générer un tas de graphique Sourire

Reporting sous ExcelReporting sous Excel

Reporting sous ExcelReporting sous Excel

La puissance d’Excel et de Power Pivot me permet de faire des analyses très poussées.

Détection des fuites

Un dashboard temps réel ou une solution de reporting c’est bien mais ce qui est mieux c’est quand le système est proactif et est capable de détecter des situations nécessitant votre attention ! En gros un système d’alerting !

Package MyBrain : le cerveau de la maison

Déjà présenté dans mon article sur mon système d’alarme, le package MyBrain est un package Constellation écrit en C# qui contient toute l’intelligence de la maison.

Grace à l’API .NET Constellation il suffit de poser l’attribut “StateObjectLink” sur une propriété .NET pour la binder à un StateObject de la Constellation en temps réel.

Dans MyBrain, j’ai donc écrit une classe avec 4 propriétés bindées aux StateObjects de SEnergy pour l’electricité, le gaz et l’eau (compteur et débit) :

 public class SEnergy 
 {
     [StateObjectLink("SEnergy", "Gas")]
     public StateObjectNotifier Gas { get; set; }
 
     [StateObjectLink("SEnergy", "Electricity")]
     public StateObjectNotifier Electricity { get; set; }
 
     [StateObjectLink("SEnergy", "Water.Counter")]
     public StateObjectNotifier Water { get; set; }
 
     [StateObjectLink("SEnergy", "Water.Flow")]
     public StateObjectNotifier WaterFlow { get; set; }

Pour détecter une fuite d’eau je surveille mon compteur d’eau pendant nos absences.

Il suffit donc d’enregistrer le compteur d’eau lorsque j’active l’alarme puis de surveiller si le compteur change ou pas ! Si oui, j’envoie une notification sur mon GSM.

Comme l’alarme est également connectée dans la Constellation et que son StateObject est bindée dans ma classe (avec la encore un StateObjectLink), il n’y a plus qu’à s’abonner au changement d’état. Pour envoyer un push j’utilise le service “PushBullet” qui est lui aussi un package dans ma Constellation !

Le système de détection est donc implémenté en 2 lignes de C# :

 int waterCounterWhenArmed = 0;
 this.AreaStatus.ValueChanged += (s, e) =>
 {
     if (e.NewState.DynamicValue.IsFullArmed)
     {
         waterCounterWhenArmed = (int)this.Water.DynamicValue.Counter;
     }
 };
 this.Water.ValueChanged += (s, e) =>
 {
     // Compteur différent de plus d'un litre (10 décilitres) avec l'alarme full-armed = pas normal !!
     if (this.AreaStatus.DynamicValue.IsFullArmed &&
         waterCounterWhenArmed < (int)e.NewState.DynamicValue.Counter &&
         ((int)e.NewState.DynamicValue.Counter - waterCounterWhenArmed > 10))
     {
         this.SendMessage("PushBullet").SendPush(new { Title = "Water", Message = "Consommation d'eau alors que la maison est sous alarme complète ! Fuite ?" });
     }
 };

Rien ne m’échappe à présent (même pas une machine à laver lancée pendant notre absence Clignement d'œil)

Push en cas de fuite !

Relevé par SMS

Parce qu’une fois dans la Constellation c’est tellement simple de tout interconnecter qu’on est tenté d’ajouter un tas de lien plus ou moins gadget Sourire

Sur un autre Raspberry j’ai branché un modem GSM avec une carte SIM. Dessus je fais tourner un package Constellation nommé “GSM” qui est ni plus ni moins qu’un package Python qui exploite la librairie “Gammu” pour exposer le GSM dans la Constellation :

Package GSM

Package GSM

Ainsi dès qu’un SMS est reçu, le package transfert le SMS dans la Constellation et inversement, n’importe qui connecté dans ma Constellation peut envoyer un SMS via ce package !

En .NET il suffit de marquer une méthode avec l’attribut “MessageCallback” pour l’exposer dans la Constellation. Lorsque le package GSM reçoit un SMS, il envoi le contenu du SMS dans la Constellation dans un message “IncomingSMS”.

Comme le Package “MyBrain” a enregistré un MessageCallback “IncomingSMS”, il reçoit donc les SMS ! Si le contenu du SMS est “energie” il répond un message au package GSM pour envoyer un SMS au même numéro en indiquant la valeur des différents compteurs.

Merci Constellation !

[MessageCallback(Key = "IncomingSMS")]
private void ReceiveIncomingSMS(string number, string text)
{
    if (text.ToLower() == "energie" || text.ToLower() == "energy")
    {
        this.SendMessage("GSM").SendSMS(new 
        {
            Number = number,
            Text = string.Format("Gaz: {0}dm3 - Electricity: {1}W - Water: {2}L",
            (int)this.Gas.DynamicValue.Cumul, (int)this.Electricity.DynamicValue.Cumul, ((double)this.Water.DynamicValue.Counter / 10))
        });
    }
}

Interface GSM

Dans la vrai vie, j’ai des méthodes me simplifiant le code avec un contrôle de l’émetteur pour ne pas répondre au SMS de n’importe qui Sourire 

Vers une douche plus économique : quand votre salle bain vous parles !

Je pense que vous commencez à bien comprendre tout ce qu’apporte la Constellation !

Encore un autre package qui tourne dans la Constellation : S-Sound, un système de diffusion audio multi-room !

Logo SSound

Un article très complet sur SSound paraitra prochainement, mais ce qu’il faut retenir pour l’heure c’est que ce package tourne dans plusieurs pièces de la maison, dans le salon, la cuisine, la chambre ou encore la salle de bain.

Package SSound dans la salle de bain

Il me permet de diffuser tout type de média : fichier audio, streaming MP3 (web radio & co), entrée audio (line ou chromecast), etc… Mais aussi de la synthèse vocale (TTS).

Comme c’est un package Constellation, tout peut être contrôlé depuis une application Web et surtout chaque package de la Constellation peut envoyer des messages aux différents S-Sound de la maison !

Dans mon article sur mon système d’alarme, je vous avais déjà montré comment la maison vous dit bonjour dès qu’on rentre, en utilisant SSound comme interface vocale.

Ici notre package “MyBrain” va utiliser le package SSound de la salle de bain pour parler en fonction de notre consommation d’eau !

Le code est très simple :

double cumul = 0; var lastValue = DateTime.MinValue; int avertissement = 0; double cumulSpoke = 0;
this.WaterFlow.ValueChanged += (s, e) =>
{
    // 2 valeurs à 0 + cumul > à 30 litres, douche finie !
    if ((int)e.NewState.DynamicValue.LiterDelta == 0 && cumul >= 30 && cumulSpoke != cumul)
    {
        cumulSpoke = cumul;
        this.SendMessage("SSound-SalleDeBain").Speech("Vous avez consommé " + cumulSpoke.ToString() + " litres");
    }
 
    // Surveillance de la douche
    if ((int)e.NewState.DynamicValue.LiterDelta > 0)
    {
        if (DateTime.Now.Subtract(lastValue).TotalMinutes >= 3)
        {
            cumul = 0;
            avertissement = 0;
        }
        lastValue = DateTime.Now;
        cumul += (double)e.NewState.DynamicValue.LiterDelta;
    }
};

A chaque modification du StateObject du débit de l’eau (Water.Flow) pushé par le Raspberry S-Energy, on incrémente la variable “cumul” pour avoir le nombre litre cumulé consommé (cette variable est remise à 0 au bout de 3 minutes sans consommation).

Si on a consommé plus de 30 litres sans interruption (= cas d’une douche ou bain) et que le delta entre deux mesures (= deux photos) est de 0 on considère qu’on a fini sa douche ! On envoi alors un message au S-Sound de la Salle de Bain pour indiquer combien de litres on vient de consommer !

En sortant de votre douche, vous entendez un Vous avez consommé 45 litres!

On prend conscience de notre consommation et on essaye maintenant de trouver des stratégies pour changer nos habitudes afin de consommer moins !

LA procédure de sortie de douche (pour ceux qui abusent !!)

Avoir son “score” à la fin d’une douche c’est bien, mais le suivre en direct c’est mieux ! Car il y a des jours où on ne fait pas forcement attention au temps que l’on passe sous la douche.

De ce fait, la salle de bain vous parle tout au long de votre douche pour vous indiquer les “seuils” que vous dépassez !

A la maison, on a défini un 1er seuil à 60 litres, puis à 80, 90 et enfin à 100 litres :

if (avertissement == 0 && cumul >= 60)
{
    avertissement++;
    this.SendMessage("SSound-SalleDeBain").Speech("Vous dépassez les 60 litres");
}
if (avertissement == 1 && cumul >= 80)
{
    avertissement++;
    this.SendMessage("SSound-SalleDeBain").Speech("Attention, vous dépassez 80 litres");
}
else if (avertissement == 2 && cumul >= 90)
{
    avertissement++;
    this.SendMessage("SSound-SalleDeBain").Speech("Ceci est le dernier avertissement, 90 litres d’eau consommés");
}
else if (avertissement == 3 && cumul >= 100)
{
    avertissement++;
    this.SendMessage("SSound-SalleDeBain").Speech("Déclenchement du plan de sortie de l’eau, veuillez couper l’eau pour annuler !");
    // Suite du code ci-dessous ... !
}

En général lorsque l’on prend sa douche et qu’on entend notre salle de bain nous informer que l’on dépasse les 60 litres on termine très rapidement !

Mais il y a le cas où l’utilisateur ne souhaite pas sortir Sourire Alors la maison engage “son plan de sortie de douche”.

Le code tient en deux lignes :

 // Faire dans 5 sec (le temps d’entendre le message vocale de démarrage du plan de sortie de douche)...
this.DoAsync(() =>
    {
        // Eteindre lumière SdB
        this.SendMessage("Vera").SetSwitchState(new { DeviceID = (int)this.EclairagesSalleDeBain.DynamicValue.Id, State = false });
        // Démarrer playlist dans la SdB
        this.SendMessage("SSound-SalleDeBain").PlayPlaylist(PackageHost.GetSettingValue<string>("MusicNetworkShare") + "HorribleMusic.m3u");
 
    }, delayBeforeAction: 5000);
 
 
// Faire lorsque LiterDelta = 0
this.DoAsync(() =>
{
    // Rallumer lumière SdB si pas de lumière du jour
    if (!this.SunInfo.IsDayLight)
    {
        this.SendMessage("Vera").SetSwitchState(new { DeviceID = (int)this.EclairagesSalleDeBain.DynamicValue.Id, State = true });
    }
    // Couper SSound dans la SdB
    this.SendMessage("SSound-SalleDeBain").Stop();
 
}, waitUntil: () => (int)this.WaterFlow.DynamicValue.LiterDelta == 0);

Comme tout est connecté dans la Constellation, y compris ma Vera Lite (passerelle domotique Z-Wave pour le contrôle des luminaires, volets, etc…), le plan de sortie de douche c’est :

  1. Ferme la lumière dans la salle de bain (en envoyant un message à la Vera)
  2. Démarre une musique “horrible” via S-Sound
  3. Si le nombre de litre consommé revient à 0 (arrêt de la douche), on rallume la lumière et surtout on éteint la musique Sourire

Pour la démo, avancez à 9’15 :

(ps: merci à Framboise314 pour cette vidéo raccourcie)

Je vous assure que se retrouver dans le noir complet sous la douche avec une telle musique, nous ne tenez pas plus de 10 secondes Sourire

Conclusion

S-Energy fonctionne maintenant depuis plusieurs mois en continue. Les techniques d’acquisition des différents compteurs m’ont permis de répondre à ma 1ère contrainte qui était de pouvoir les lire sans changer de compteurs et avec très grande précision.

L’intégration dans la Constellation permet d’envisager des interactions avec d’autres devices/programmes de la maison très facilement et de réaliser des interfaces de contrôle & dashboard de visualisation temps réel en quelques lignes de code.

Aujourd’hui je peux donc surveiller tout çà en temps réel depuis n’importe quel device, faire des rapports de consommation très précis mais surtout, au quotidien, nous sommes constamment sensibilisé quand nous consommons trop d’eau dans la salle de bain ! Après quelques mois d’utilisation, nous avons réellement changé nos habitudes pour consommer moins (comme réduire le débit d’eau par exemple). Un gain mesuré de 20 à 50% d’eau pour chaque douche !

Une fuite comme nous avons connu au mois de Septembre ne pourrait plus se produire; je serai automatiquement harcelé de notifications sur mon téléphone et dans la journée nous aurons déjà appelé un plombier en urgence et éviter ainsi plusieurs centaines de m3 gaspillés.

Pour finir, côté cout, le plus cher reste le Raspberry Pi  (30€) et la camera (25 €). Pour le reste, le module de compteur d’impulsion pour le gaz (15€ sur eBay), un Arduino Pro Mini (version chinoise à 2,5€), deux modules nRF24 (5€ les deux), l’opto-interrupteur (4€),  boitier étanche (18€), alimentation 5V (10 €) et moins de 3 euros pour les différents composants électronique. Bref un peu plus de 100€ au total pour une solution de monitoring temps réel pour l’eau, l’électricité et le gaz.

Logo S-Energy

Note : la plateforme Constellation sera très prochainement ouverte en open-source. Pour les early adopters qui souhaitent tester cette technologie en beta, n’hésitez pas à me contacter Sourire

Domotique,TechDays 2015,Constellation
Share this Story:
  • facebook
  • twitter
  • gplus

Comments(56)

  1. Plessis Marc
    518 days ago

    Tout d’abord félicitations !!!! Quel travail de fou il vous a surement fallu produire pour écrire une plateforme d’agrégation et d’interconnexion de tous ces modules, et le tout en produisant le tooling Visual Studio qui va avec, bravo !!! Vivement la disponibilité de cette plateforme, je suis tout à la fois curieux et impatient de voir l’architecture qu’il y derrière et pouvoir « jouer » avec ce cerveau de maison.

  2. hydro
    518 days ago

    Vraiment impressionnant, j’aime l’idée d’un « cerveau » qui contrôle chaque module.

    Ton system multi room audio permet de synchroniser plusieurs zones ?

  3. thierry perrier
    518 days ago

    Un grand bravo pour tout ce travail . Impressionnant. quel boulot extraordinaire

  4. PIERRE
    518 days ago

    Chapeau l’artiste…

  5. Christian Hougardy
    518 days ago

    Seb, suis pas sur d’avoir tout compris (ça t’aurait étonné aussi 🙂 ) mais c’est génial comme truc. Toujours aussi génial tu es !!! Take care.

  6. François
    518 days ago

    Bonjour,

    bravo pour l’article, comme d’habitude c’est super intéressant ! Une petite question, pour le compteur d’impulsion, tu ne précises pas comment tu l’as connecté à ton système pour en déduire la consommation de gaz ?

    Il me tarde de voir Constellation !

  7. Sebastien
    518 days ago

    Merci pour vos commentaires !

    @hydro : oui et non 🙂 Chaque S-Sound est indépendant des uns des autres bien qu’on puisse lancer un seul ordre pour toutes les instances (by Constellation). Typiquement on peut lancer le même son dans toutes les pièces mais il peut y avoir un léger décalage (un peu moins d’une seconde).
    Après chez moi, les enceintes de la cuisine & SdB sont connectées sur le même serveur sur lequel deux instances SSound tournent. Et là tu as la synchronisation entre les deux !
    Donc pour résumer, si tes SSound des différentes pièces sont reliées sur le même serveur physique c’est parfaitement synchro, sinon si chaque pièce à son propre système tu peux tout contrôler depuis Constellation mais avec un léger décalage !

    @ Francois : le module compteur d’impulsion est connecté en « pull-up »sur le RPi ! Sur le module tu as un bornier pour 2 fils afin de faire l’impulsion (en gros c’est un interrupteur qui se ferme lors d’une impulsion). Les deux fils arrivent au RPi à travers un câble RJ45 blindé (pour éviter les perturbations). L’un des fils est connecté à la masse (GND) du RPi et l’autre sur une GPIO en entrée (chez moi j’ai pris la GPIO18). Pour filtrer le signal de potentielles perturbations extérieures tu peux rajouter un condensateur 1uF entre ta GPIO et la masse au niveau du RPi.

    Bien à vous

  8. François
    518 days ago

    Merci pour la précision Sébastien ! malheureusement sur mon RPI la GPIO est utilisé par le RaZBerry, il va falloir que je trouve une autre solution !

  9. Sebastien
    518 days ago

    SI j’en crois les specs, le RaZBerry prend les 5 premières pin (des deux côtés). Tu as donc toute la partie inférieure disponible. Tu peux donc utiliser n’importe quel IO pour connecter un entrée en pullup : http://raspi.tv/wp-content/uploads/2014/07/Raspberry-Pi-GPIO-pinouts.png

  10. François
    518 days ago

    Pas con, je m’en souvenais plus vu qu’il est fermé dans un boitier. Une doc sur comment traiter les données reçues sur GPIO par la suite ? Je n’ai jamais fait ça !

  11. Trackback: Resource monitoring solution | Hackaday

  12. Trackback: Resource monitoring solution - zeax blog (ze-ax.com)

  13. Trackback: Resource monitoring solution | Hack The Planet

  14. carfnann
    509 days ago

    bravo!
    j’étais mort de rire pour l’opération sortie de douche mais ca me donne une bonne idée!

  15. Dodutils
    507 days ago

    « Chaque tour équivaut à 4 Watts/heures consommés. » attention cela dépend des compteurs, mais la valeur est indiquée dessus le mien par exemple fait 1.6Wh/tr

  16. Dodutils
    507 days ago

    Dommage que se soit sur le chauffe eau car le Décret n° 2012-1078 du 24 septembre 2012 relatif à la facturation en cas de fuites sur les canalisations d’eau potable après compteur qui protège en partie des grosses factures ne fonctionne pas si l’augmentation de volume d’eau consommée est due à des fuites sur les appareils ménagers et les équipements sanitaires ou de chauffage.

  17. Sebastien
    507 days ago

    Bonjour Dodutils,
    Oui tu as raison de le préciser, cela dépend bien sûr du calibrage différent sur chaque compteur.
    Cette indication est gravée sur le compteur. Dans mon cas, C = 4Wh/tour.
    Cette constante est configurée au niveau du script Python qui push le StateObject de l’électricité dans la Constellation. Car au niveau de l’Arduino il n’y a pas besoin de cette information (l’Arduino sur le compteur n’a que pour seule mission que de compter le nombre de révolution et le temps mis !).
    Bien sûr nous avons engagé une médiation avec la compagnie de eaux mais comme tu le dis les « accessoires » (comprenez chauffe eau / chaudière, etc…) ne sont pas couverts ! Dans mon cas il s’agit d’un accessoire d’un accessoire (la vanne de sécurité d’une chaudière). Bref c’est pas gagné !

  18. Dodutils
    506 days ago

    Par curiosité ils veulent te facturer combien ?

    Quid du taux d’erreur de ce type de lecture optique quand la roue tourne vite ? il lui arrive de rater des tours ?

    J’ai aussi une citerne de gaz pour le chauffage et eau chaude sanitaire, mais c’est un manomètre et il est difficile de faire une lecture précise et automatisée via une prise de photo, déjà qu’à l’oeil nu c’est pas simple 😉

    Il existe des compteur à chiffres ou numérique mais ça doit coûter cher.

    Voici un bel exemple de révision de chaudière ratée par le gars de l’entretien heureusement que je regarde mes courbes régulièrement !

    http://i.imgur.com/vlBFPUr.png

    Le technicien avait commis une erreur en réglant la puissance chaudière à seulement 50%, par grand froid la chaudière aurait tourné non-stop… bonjour la conso !

    p.s : dommage qu’on ne puisse pas s’abonner aux commentaires du billet ça oblige à venir relire régulièrement voir ce qui s’y passe.

  19. Dodutils
    506 days ago

    Par contre plutôt que d’utiliser une RaspiCam et d’y adjoindre des LED et faire un montage (ce qui au final coûte du temps et de l’argent) j’utilise une simple caméra Hercules USB à 20€ avec des LED autour qui a un objectif réglable ce qui permet d’avoir une image nette de très prêt ou de plus loin.

    Je m’en suis d’ailleurs servi pour suivre la vie d’un nid de guêpes 😉

    http://i.imgur.com/9kIbV8j.jpg.

  20. Sebastien
    506 days ago

    Oui il y a toujours plein de moyen de faire les choses 😉
    La RaspiCam ne coûte que 25€ et dans mon cas elle m’a été offerte par Farnell l’an passé ce qui explique ce choix !
    Mais en effet une simple webcam USB aurait pu aussi faire l’affaire ! Je ne connaissais pas ce modèle avec LED intégré, c’est tjs bon à savoir 😉
    Pour le petit circuit j’en avais dans tous les cas besoin pour le module nRF ! Ca n’a pas été très long d’adjoindre un transistor + résistance pour piloter des leds 🙂
    Autrement pour le compteur d’elec, même quand le disque tourne très vite il n’y a aucun tour « loupé » ! Au max j’ai enregistré une conso d’un peu plus de 6000W soit une rotation en moins de 2,4 secondes, aucun problème de détection !
    Pour vérifier çà, après plusieurs mois d’utilisation d’S-Energy, j’ai comparé le compteur EDF avec celui d’S-Energy… Bon la précision n’est qu’au kW sur le compteur EDF mais l’information était la même ! Donc visiblement on ne loupe « aucun » tour ou très peu car il n’y a aucune décalage (en 6 mois de monitoring).

  21. MARC
    505 days ago

    Bonjour,
    Je suis intéressé pour testé en version bêta la plateforme Constellation. Merci de m’informer comment faire.

    marc, @Belgique

  22. Olivier
    502 days ago

    Hello,
    Impressionnant Oo
    Le coup de la caméra et de la lecture optique correspond tout à fait à l’adage : « Parce que si on ne se compliquait pas un peu la vie, ce serait beaucoup moins drôle ! » 😀

    Pour la suivi conso EDF y a ça : http://www.magdiblog.fr/gpio/teleinfo-edf-suivi-conso-de-votre-compteur-electrique/ ! Parce que si on ne se compliquait pas un peu la vie, ce serait beaucoup moins drôle !

    Bonne continuation 🙂

  23. Sebastien
    502 days ago

    Salut Olivier,
    Merci pour ton commentaire mais je crois que tu as loupé une partie 😉
    Comme je l’explique dans le 1er paragraphe de cet article mes compteurs sont trop vieux et n’ont aucune interface pour faire des auto-relevés !
    Pas d’impulsion ni de téléinfo sur mon compteur EDF, ce qui explique la mise en place d’un opto-interrupteur pour capter les tours du compteur EDF via un Arduino ! La solution que tu proposes utilise la téléinformation EDF que je n’ai pas, donc pas envisageable pour moi 🙂
    Idem pour le compteur d’eau, je ne suis pas (complètement) fou, même si c’est amusant de faire de l’OCR, je m’en serais bien passé 😉 Mais je n’ai pas eu le choix : pas d’impulsion ou autre « indice » sur mon compteur me permettant de capturer l’eau consommée !
    De ce fait, la seule solution fut de « lire » (littéralement) le compteur, donc de faire de l’OCR !
    Ainsi ce n’est donc pas pour se compliquer la vie mais plutôt parce qu’à m’a connaissance je n’avais pas d’autre solution (autre que remplacer mes compteurs eau & EDF, ce qui est très coûteux !).
    Cependant, si il n’y avait pas eu autant de contrainte ça aurait été moins drôle 🙂
    Bien à toi,

  24. Doudy
    502 days ago

    Impressionnant…
    Chez moi (en Belgique) mon compteur électrique tourne dans les deux sens.
    Lorsque je produit avec mes panneaux photovoltaïques plus que je ne consomme le disque tourne dans l’autre sens (donc il décompte).
    Une idée pour la lecture avec l’ opto-interrupteur?
    Merci

  25. Yves Accard
    495 days ago

    Bonjour
    Bravo pour cette réalisation et surtout pour les idées originales permettant de « lire » un compteur sans intervention sur la partie hydraulique.
    De mon coté, j’ai un projet « open source » (hard et soft) dans le domaine GTC/domotique dont une partie ressemble beaucoup à ce que tu a fais.
    Une des différences est qu’il s’agira de faire des produits « professionnels » c’est à dire avec un boîtier, un notice, une garantie, un service après vente et le plus possible « plug and play

    Lien vers une version plus détaillée de ce texte :
    http://speranto.accard.fr/texte-linux.php
    Lien vers le site speranto.fr :
    http://speranto.fr
    Tout le monde est bienvenu pour participer à Speranto.
    Yves Accard

  26. Olivier
    494 days ago

    Salut Sebastien,

    Tout à fait, j’ai bien compris la nécessité d’utiliser un opto-interrupteur, c’était une boutade 🙂 Et comme tu le dis « si il n’y avait pas eu autant de contrainte ça aurait été moins drôle » 🙂

    Excellent boulot en tout cas 🙂

    Bonne continuation

  27. FredThx
    485 days ago

    Merci beaucoup pour les explications précises. Pour ma part, je m’en suis inspiré pour réaliser la lecture de mon compteur électrique (à roue comme le tien). J’ai directement mis le Rpi sur le coup et ça fonctionne très bien. Par contre je me pose la question pour différencier les heures creuses et heures pleines. La solution de lire l’heure ne me plait pas trop (changement d’heure, de tarification …). As tu une solution pour lire directement le relais EDF?

  28. Trackback: MakerFaire Paris 2015 : retrouvez-moi en conférence le 2 & 3 Mai 2015 - Sebastien.warin.fr

  29. Dodutils
    478 days ago

    Tu connais le module ESP8266 ? c’est une petite merveille programmable en LUA (mais l’IDE Arduino sait aussi travailler avec lu) intégrant des GPIO et le WiFi, le tout dans un module de 2.5 x 1.4cm pour moins de 4€ !

    Je pense que je vais tenter le coup avec ça pour le compteur EDF.

  30. Sebastien
    477 days ago

    Excellent merci Dodutils !
    Je cherchais justement depuis plusieurs semaines un module Wifi pour Arduino assez petit !
    Je viens d’en commander 5 sur eBay !

  31. Dodutils
    477 days ago

    Parfait 🙂 question pourquoi un LM1137 et pas un LM317 pour reguler le 5v en 3.3v ? pour info l’ESP8266 peut demander des pics à 300mA.

  32. Sebastien
    477 days ago

    Hello, petite correction de ma part sur l’article ! Ça m’a fait tilte en lisant ton commentaire, je n’utilise pas des LM1137 (qui n’existe pas ;)) mais des LM1117 ! LM1117T pour être précis !
    Le LM317 a une tension de sortie ajustable entre 1,25V et 37V mais il faut piloter ce réglage via la patte d’ajustement via des diodes zener !
    A l’inverse du LM1117T lui à une tension de sortie fixe en 3.3V à partir d’une entrée 5V.
    Il était donc plus simple d’utiliser directement un LM1117 étant donné que mon Arduino est alimenté en 5V et que j’ai juste besoin d’un 3.3V régulé pour la puce nRF24.
    Sur la charge, le LM1117 délivre jusqu’à 800mA bien au delà des 115mA max du nRF24L01+ !
    Si le l’ESP8266 demande jusqu’à 300mA le LM1117T fera donc parfaitement l’affaire 🙂

  33. Dodutils
    477 days ago

    OK ça explique pourquoi je ne trouvais aucune info sur ce régulateur du coup je ne savais pas trop ce qu’il faisait 😉

  34. Sebastien
    463 days ago

    Hello Dodutils,
    J’ai reçu et commencé à jouer avec les ESP8266 ! Absolument super comme puce, plein de nouveau projets en tête que je ne manquerai pas de présenter ici !
    De ce fait, on pourrait en effet revoir le module de comptage d’elec sans Arduino ni RPi comme passerelle !
    Car l’ESP peut être une passerelle Wifi pour Arduino ou directement programmée (Lua, C ou Arduino) !
    Ceci dit, l’ESP-01 n’offre que 2 GPIO ce qui est assez limité ! Il existe plus d’une 10aine de modèles, voir : http://l0l.org.uk/2014/12/esp8266-modules-hardware-guide-gotta-catch-em-all/
    Aussi, pour refaire une version de mon compteur d’elec, il faut prendre l’ESP-07 ou 12 qui disposent tout deux d’un ADC pour les signaux analogiques (je rappelle que l’opto-interrupteur utilisé pour compteur les tours est analogique).
    Bref que du bonheur et encore merci de l’info 🙂

  35. Hervé
    444 days ago

    Bonjour, bravo pour ce projet très intéressant. J’ai expérimenté à mon tour la lecture du disque de mon compteur EDF, mais l’opto interrupteur ne détecte pas les alternances de la bande noire. J’ai rigoureusement les mêmes composants que les votres. Des conseils pour la mise au point ? Merci. Hervé

  36. Sebastien
    443 days ago

    Bonjour Hervé,
    Il faudrait voir en premier lieu si la lecture de l’opto -interrupteur fonctionne bien, typiquement si ton analogRead() renvoi bien une mesure « correcte » !
    Testes ensuite de passer devant un objet métallique ou un miroir pour voir si ton algo fonctionne bien !
    Si tout est fonctionnel à ce stade, il faudra chercher du côté de l’installation sur ton compteur, il faut aligner très précisément le rayon IR devant le disque qui ne fait qu’un millimètre d’épaisseur ! La tache la plus compliquée du projet 😉
    Bon courage

  37. Schoubi
    442 days ago

    Bonjour,

    Superbe article qui m’a motivé à fond pour domotiser ma maison …

    Je suis dans le même cas qu’hervé, je n’arrive pas à reproduire la technique de lecture du compteur par opto-interrupteur.
    Quelle est la référence précis de votre opto-interrupteur ? Le mien est de récupération et j’ai l’impression que le faisceau infrarouge est trop ‘fin’ et pas assez puissant pour que j’arrive à l’aligner sur le disque et/ou que le faisceau retourne sur le récepteur…

    Merci d’avance,

  38. Sebastien
    442 days ago

    Il s’agit d’un H21B1 offrant de meilleur résultat qu’un classique CNY70 : « The H21B1, H21B2 and H21B3 consist of a gallium arsenide infrared emitting diode coupled with a silicon photodarlington in a plastic housing. The packaging system is designed to optimize the mechanical resolution, coupling efficiency, ambient light rejection, cost and reliability. The gap in the housing provides a means of interrupting the signal with an opaque material, switching the output from an “ON” to an “OFF” state. » : http://pdf.datasheetcatalog.com/datasheet/fairchild/H21B1.pdf

  39. Trackback: S-Panel : une interface domotique et IoT multi-plateforme avec Cordova, AngularJS et Constellation–ou comment créer son dashboard domotique mural - Sebastien.warin.fr

  40. emmanuel
    398 days ago

    Bonjour Sébastien,

    mon compteur de gaz est comme ton compteur d’eau… y-a-t-il un moyen d’extraire ton code de reconnaissance de caractère pour le faire fonctionner sans constellation ?

    En te remerciant par avance,

    Emmanuel (epierre)

  41. doudy
    393 days ago

    Bonjour Sébastien,
    Je suis comme emmanuel intéressé par ton code sans constellation.
    Merci.
    Doudy

  42. Witty
    380 days ago

    A] J’ai l’impression que l’image montrant les soudures est une photo avant la fin des soudures, ( http://sebastien.warin.fr/wp-content/uploads/2015/02/P1160070.jpg )
    en effet, il semble manquer plusieurs points de soudures!
    Serait-ce possible d’ajouter un dessin des soudures a faire de l’autre coté de la plaque ?

    B] On ne voit pas non plus a quoi correspond les pins qui doivent etre reliés au FTDI USB !

    C] Est il prévu une mise a jour utilisant le ESP8266 ???

    Cordialement.

  43. Sebastien
    378 days ago

    Hello,
    @emmanuel & doudy : le code peut fonctionner sans Constellation si vous remplacez les WriteInfo par des simples « print » et les PushStateObject par ce que vous voulez faire du resultat 🙂
    @Witty : A) pas de soudure sur la face « avant », tout est sur l’image, ni plus ni moins 🙂 Il y a un schéma sur l’article pour résume tout çà ! B) le FTDI te sert à programmer ton Arduino (Vcc, Gnd, Rx et Tx), ca dépends de ton modèle d’arduino ! C) je posterai des articles sur les ESP8266 et nottament la connexion avec COnstellaiton, mais je ne vais pas « porter » S-Energy sur ESP : 1- je n’en ai pas d’intérêt puisque cette solution marche terriblement bien depuis des moins, 2 – les ESP ne sont vraiment pas fiable sur le long terme ! Cependant pour le faire il faudrait un ESP8266 07 ou 12 avec un port ADC pour pouvoir exploiter le signal analogique de l’opto-interrupteur ! C’est pas très compliqué à faire en Lua via NodeMCU… J’ai un article à poster dans ce sens avec un capteur de luminosité prochainement 🙂

  44. doudy
    363 days ago

    Merci pour les infos

  45. Dodutils
    336 days ago

    Tu as essayé de remplacer ta puce GSM par un module compatible SigFox genre TD1208 ?

  46. Dodutils
    336 days ago

    C’est quoi le problème de fiabilité des ESP ? ils plantent ? ils tombent en panne ?

  47. Sebastien
    336 days ago

    Hello,
    Non pas testé SigFox… J’ai un package Constellation qui tourne sur un RPi et exploite l’API Gammu via une carte USB/3G qui me sert de passerelle SMS. De la même manière un package Luync pour la passerelle vers le réseau RTC/Voix.
    Mon prochain article sera consacré aux ESP qu’on découvrira en long et en large… NodeMCU n’est pas stable dès qu’on fait quelque chose d’un peu plus complexe que l’acquisition d’un capteur pour générer une requête HTTP !
    Par contre en développement en C++ sur le SDK natif ou en Arduino ca marche du tonnerre ! Le SDK Constellation est compatible avec, et de ce fait on peut faire des trucs de folie car dès lors, la petite puce ESP à accès à tout ce qui se trouve dans la Constellation comme contrôler un Nest, l’alarme, les XBMC, la domotique Z-Wave, etc.. Et bien sûr, vice-versa, exploiter les données produites des ESP dans vos pages Web, programme Windows & Linux, le tout en 2 lignes de code 🙂

  48. Sebastien
    336 days ago

    Et en parlant d’ESP8266, je viens juste de finir de porter ce soir/cette nuit, la lib Arduino-IRRemote sur l’ESP8266 en prenant notamment en charge la partie réception & décodage des signaux IR ce qui n’était pas une mince affaire sans l’ISR des Arduinos. Je publie çà sur mon Github cette semaine et j’en reparlerai dans mon article à paraître prochainement et notamment ce qui ça ouvre comme possibilité une fois dans la Constellation 🙂

  49. Dodutils
    336 days ago

    Attention à NodeMCU c’est pas le firmware d’origine des ESP en plus il est en retard par rapport au firmware actuel

  50. Trackback: Créez votre “Home Analytics” : l’analyse et le reporting de votre domotique, informatique et objets connectés avec ElasticSearch, Graylog, Kibana et la plateforme Constellation - Sebastien.warin.fr

  51. Dodutils
    312 days ago

    Bon j’ai testé le montage (sans le nRF24 pour l’instant), face à face l’opto clignote bien la LED mais côte-à-côte ça fait rien, jai même tenté de mettre un mirroir devant, pareil, j’ai essayé avec une lampe devant le récepteur, là ça marche, alors j’ai pensé que peut-être je ne donnais pas assez de jus à l’émetteur IR, du coup j’ai baissé à 47 ohms, puis 39, puis 22 toujours rien même avec un miroir en va-et-vient en face pour obtenir une meilleur réflexion, puis je suis descendu à 10 ohms et pour le coup je crois que j’ai grillé la bestiole elle n’émet plus de lumière, pas grave j’avais prévu le coup j’en ai un second.

  52. Trackback: FERG : Mon vieux compteur EDF connecté en mode framboise - Oui Are Makers

  53. Dodutils
    286 days ago

    APrès quelques jours de fonctionnement avec une LED IR TCRT5000 ça fonctionne pas mal, il fallait sûrement un truc plus puissant pour ma roulette par contre les valeurs hautes et basses ont un peu évolué dans la temps (ou alors le module IR a légèrement bougé du coup le reflet est un poil différent) ça ne comptait plus rien il a fallu modifier les valeurs du palier haut/bas je vais voir à modifier le code pour essayer de faire en sorte qu’il s’auto calibre.

  54. Bientzou
    154 days ago

    Bonjour,
    Ce travail est vraiment top!!
    Je me demandais si tu pouvais fournir le code complet pour tester chez moi.
    Merci

  55. Marc
    119 days ago

    bonjour ,
    Pour commencer je ne suis ni électronicien ni informaticien ou développeur , j’ai péniblement instaler motion et la pi cam sur mon rspberry autant dire que je maitrise pas énormément . je voudrais piloter mon chauffage avec le raspberry ..un ami ma parler des sonde 18b20 facile a utiliser avec le raspberry mais je ne trouve rien pour programmer la mise en route ou l’extinction du chauffage en fonction de seuil préétablis ni du module de puissance …l’un de vous peux il m’aider ?

  56. Thibaut
    95 days ago

    Bonjour et bravo,
    je travaille dans une collectivité et tous les systèmes de télérelève existant coûte une fortune. Soucieux d’économiser l’argent public, je me suis dit qu’il y a surement un moyen plus économe de récupérer lesindex des compteurs. En cherchant si quelqu’un avait déja utilisé une caméra et un logiciel de reconnaissance de texte je suis tombé sur votre blog. MERCI!
    Pensez-vous qu’il soit possible de reproduire vos différents moyens de lecture de compteur? Quelles compétences faut-il? Je travaille sur Bordeaux, avec un peu de chance vous n’êtes pas loin et nous pourrions nous rencontrer….
    En tous cas encore bravo!

Leave a comment

Comment