lundi 1 juillet 2019

Une Télécommande Domotique Infrarouge


 Une Télécommande Domotique Infrarouge


Dans cet article je décris une solution de télécommande infrarouge permettant de piloter des dispositifs divers et variés :
  • allumage / extinction home-cinema
  • allumage / extinction éclairages
Afin de ne pas multiplier le nombre de télécommandes sur la table de salon, j'ai détourné quelques touches inutilisées de la télécommande de mon amplificateur (un ampli stéréo Rotel).
Une carte ARDUINO NANO équipée d'un récepteur TSOP4838 reçoit les codes de la télécommande.

Ce projet s'adresse à toute installation domotique équipée d'un serveur possédant une interface JSON, mais pas seulement. On peut également commander facilement des dispositifs WIFI à base d'ESP8266 ou ESP32.

1. La réception infra-rouge





Voici le petit sketch très simple du récepteur infrarouge :

#include <IRremote.h>

#define IR_PIN      9

IRrecv irrecv(IR_PIN);

void setup()
{
  Serial.begin(115200);  //starts serial communication
  irrecv.enableIRIn(); // Starts the receiver
}

long getIR(void)
{
  decode_results results;

  if (irrecv.decode(&results)){
    long int decCode = results.value;
    irrecv.resume();
    if (decCode != -1) {
      return decCode;
    }
  }
  return 0;
}

long lastCode;

void loop()
{
  //decodes the infrared input
  long   ir = getIR();
  if (ir != 0) {
      if (ir != lastCode) {
      Serial.println(ir, HEX);    }
    irrecv.resume();
  }
  lastCode = ir;
  delay(100);
}


Comme on le voit L'ARDUINO envoie les codes en hexadécimal sur sa ligne série (USB) au serveur, une RASPBERRY PI dans mon cas.

2. La RASPBERRY PI

Voici un schéma du système :


On voit plusieurs passerelles connectées en USB à la RASPBERRY PI :
  • une passerelle 2.4GHz MySensors
    • ARDUINO NANO
    • NRF24L01
  • une passerelle 433MHz RFLINK 
    • ARDUINO MEGA
    • Aurel RTX-MID-5V
  • le récepteur infrarouge
    • ARDUINO NANO
    • TSOP4838
La RASPBERRY PI est posée sur une étagère du home-cinema et la télécommande se trouve en permanence sur la table de salon.

Sur la RASPBERRY PI un petit script en PYTHON interprète les codes et exécute les actions correspondantes :

#!/usr/bin/python

import serial
import time, os

remote = serial.Serial('/dev/ttyUSB1', 115200, timeout=1)
lamp = 0
homeCinema = 0

while (1):
    line = remote.readline()
    if line <> '':
        command = line[:-2]
        print command


# ESP8266 MONOSTABLE RELAY

        if command in ('C148C837','F732'):
            os.system('curl -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET "http://192.168.1.11/?pin=1&action=PULSE&delay=100"')


# BLYSS PLUG

        elif command in ('F70D', 'C148708F'):
            cmd = 'bash -c /home/pi/lamp-on.sh'  if lamp == 0 else 'bash /home/pi/lamp-off.sh'
            print cmd
            os.system(cmd)
            lamp = not lamp


# ESP8266 PLUG

        elif command in ('F78D', 'DE103B86', 'C14858A7'):
            os.system('curl -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET "http://192.168.1.13/toggle"')


# HOME-CINEMA

        elif command in ('F7C2', 'F7B2', 'C148F00F', 'C148D02F'):
            cmd = 'bash -c /home/pi/home-cinema-on.sh'  if homeCinema == 0 else 'bash /home/pi/home-cinema-off.sh'
            print cmd
            os.system(cmd)
            homeCinema = not homeCinema


Que peut-on commander à partir d'un tel script ?
On peut tout faire en fait :
  • envoyer une commande sur la ligne série du RFLINK
  • envoyer une requête HTTP à un dispositif WIFI (ESP8266)
  • envoyer une requête JSON à un serveur DOMOTICZ ou autre
  • appeler un script

2.1. Les codes de la télécommande

Pour relever les codes de la télécommande, il suffit de lancer le script dans un terminal et de relever les codes des touches qui nous intéressent.

Note : le script a besoin de pyserial pour fonctionner. On installe pyserial comme ceci :

sudo apt-get install pyserial

Ensuite il faut remplacer les codes dans le script :

        elif command in ('F70D', 'C148708F'):

On voit ici que deux touches permettent d'effectuer la même action. Il est bien entendu possible d'en affecter une seule :

        elif command == 'F70D':

2.2. Le RFLINK

La passerelle RFLINK permet de piloter des prises du commerce (Blyss, Chacon, etc.).
Les commandes RFLINK peuvent être envoyées directement sur sa ligne série. Il faut connaître les protocoles employés.
Le plus simple est de disposer d'un serveur DOMOTICZ, JEEDOM ou autre et d'actionner la prise à l'aide de l'icône associée à la prise. Ensuite on va copier / coller la commande à partir des logs du serveur (sous DOMOTICZ cliquer sur "Réglages / Logs) :

2019-07-01 11:50:25.371 User: Admin initiated a switch command
2019-07-01 11:50:25.371 RFLink Sending: 10;Blyss;006776;e1;ON
2019-07-01 11:50:26.195 (RFLINK) Light/Switch (Lampe sur pied)

Dans le script PYTHON On voit la ligne suivante :

            cmd = 'bash -c /home/pi/lamp-on.sh'  if lamp == 0 else 'bash /home/pi/lamp-off.sh'
            os.system(cmd)

Comme on le devine les scripts lamp-on.sh et lamp-off.sh permettent d'allumer et d'éteindre une lampe branchée sur une prise Blyss. Il suffit d'envoyer les commandes sur la ligne série :

lamp-on.sh :

echo "10;Blyss;006776;e1;ON" > /dev/ttyACM0


lamp-off.sh :

echo "10;Blyss;006776;e1;OFF" > /dev/ttyACM0

C'est tout ce qu'il y a à faire.

2.3. Le WIFI

Pour envoyer une commande à un ESP8266 ou un ESP32 il suffit d'utiliser curl :

            os.system('curl -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET "http://192.168.1.11/?pin=1&action=PULSE&delay=100"')

Dans cet exemple le télérupteur a été développé par moi-même et l'URL "http://192.168.1.11/?pin=1&action=PULSE&delay=100" permet d'activer la sortie 1 à l'aide d'une impulsion de 100ms.

Mais on peut bien évidemment utiliser une autre URL pour commander toute prise WIFI du commerce, une SONOFF par exemple :

            os.system('curl -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET "http://192.168.1.10/control?cmd=GPIO,12,1"')
            os.system('curl -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET "http://192.168.1.10/control?cmd=GPIO,12,0"')

Voir ici l'intégration d'une prise SONOFF à DOMOTICZ : https://projetasgarddiy.fr/2018/06/14/interrupteur-sonoff-dans-domoticz/

Avec cette solution il serait même possible de se passer de la RASPBERRY PI, et envisager de commander ses prises directement à l'aide d'un client HTTP à base d'ESP8266, ESP32 ou même un ARDUINO + shield Ethernet.
Dans ce cas, on peut se passer de l'ARDUINO NANO et connecter le récepteur TSOP4838 directement sur l'ESP8266, l'ESP32 ou la MEGA.

2.4. Contrôle direct par le serveur

On peut à l'aide de ce moyen contrôler tous les dispositifs y compris les précédents, à partir du moment où ils sont connus du serveur.

Cette méthode sera la seule permettant un contrôle de dispositifs MYSENSORS à base de NRF24L01.

Dans le script PYTHON plus haut je l'utilise pour contrôler le HOME-CINEMA (une prise connectée à base d'ARDUINO MINI + NRF24L01) :

            cmd = 'bash -c /home/pi/home-cinema-on.sh'  if homeCinema == 0 else 'bash /home/pi/home-cinema-off.sh'
            os.system(cmd)

Que font les scripts home-cinema-on.sh et home-cinema-off.sh ?

home-cinema-on.sh :

python home-cinema.py On

home-cinema-off.sh :

python home-cinema.py Off

On se doute bien que si la tâche est confiée à un script PYTHON, c'est qu'elle est un peu plus complexe (on utilise JSON) :

Voici le contenu de home-cinema.py :

#!/usr/bin/python
# - *- coding: utf- 8 - *-
import sys
import json
import urllib2
import re
import time
import datetime
import httplib, urllib

def open_port():
    pass

def close_port():
    pass

class DomoticzDevice():

    def __init__(self, url):
        self.baseurl = url

    def __execute__(self, url):
        req = urllib2.Request(url)
        return urllib2.urlopen(req, timeout=5)

    def getDeviceId(self, name):
        """
        Get the Domoticz device id
        """
        url = u"%s/json.htm?type=devices&filter=all&used=true&order=Name&" % (self.baseurl)
        print url
        data = json.load(self.__execute__(url))
        for device in data['result']:
            if device['Name'] == name:
                return device['idx']
        return None

    def getDeviceData(self, name):
        """
        Get the Domoticz device data
        """
        url = u"%s/json.htm?type=devices&filter=all&used=true&order=Name&" % (self.baseurl)
        print url
        data = json.load(self.__execute__(url))
        for device in data['result']:
            if device['Name'] == name:
                return device['Data']
        return None

    def setDeviceInfo(self, xid, category, info):
        """
        Set the Domoticz device information.
        """
        url = "%s/json.htm?type=command&param=%s&idx=%s&switchcmd=%s&" % (self.baseurl, category, xid, info)
        print url
        data = json.load(self.__execute__(url))
        return data

url = "http://192.168.1.134:8080"
domo = DomoticzDevice(url)
switch = domo.getDeviceId(u'Home-cinema')
print switch
domo.setDeviceInfo(switch, "switchlight", sys.argv[1])

Explications des dernières lignes :

L'URL du serveur DOMOTICZ :
url = "http://192.168.1.134:8080"  
Instanciation de l'objet DomoticzDevice :
domo = DomoticzDevice(url)
Récupération de l'identifiant du dispositif portant le nom "Home-cinema" :
switch = domo.getDeviceId(u'Home-cinema')
Envoi de la commande à DOMOTICZ :
domo.setDeviceInfo(switch, "switchlight", sys.argv[1])

sys.argv[1] représente l'argument passé au script sur la ligne de commande :  "On" ou "Off" :
python home-cinema.py On
python home-cinema.py Off

Ce script construit en définitive une URL avec quelques arguments interprétés par le serveur.
Il est facile d'essayer de commander une prise en tapant cette URL dans son navigateur :

http://192.168.1.134:8080/json.htm?type=command&param=switchlight&idx=328&switchcmd=On
http://192.168.1.134:8080/json.htm?type=command&param=switchlight&idx=328&switchcmd=Off

Il est à noter que ces URLs sont les mêmes que celles que l'on peut utiliser pour définir une action au niveau du serveur pour un bouton-poussoir, un interrupteur ou un capteur de présence :

Voir cet article :
Paragraphe 5.3. Les actions

3. Conclusion

Voici une petite solution simple et économique à mettre en oeuvre pour commander ses prises à l'aide d'une simple télécommande infra-rouge.

Cordialement
Henri

2 commentaires:

  1. Bonjour Henry,

    Je reviens vers toi après une semaine de blocage.

    Mon projet actuel : serre extérieure avec mur béton (pour créer une inertie thermique) où j’ai intégré 3 résistances de chauffage électrique (identiques à celles d’un plancher chauffant).
    Objectif asservir le pilotage des résistances à la température de la serre.

    Ce qui fonctionne :
     Lecture des températures extérieures et dans la serre, sur des DHT 22 reliés à un ESP32 en liaison Wifi avec ma box
     Connexion et enregistrement sur DOMOTICZ (qui tourne sur Nas Synology).

    Ce qui coince : Je pensais que ça allait être une formalité de piloter les relais via DOMOTICZ, MAIS … après une semaine d’effort …, je n’arrive pas absolument pas à piloter ces relais d’alimentation des résistances … sachant qu’il me faudra ensuite créer un scénario pour mettre en œuvre cet asservissement.

    Ce que j’ai tenté :

    méthode 1 : Définir l’ESP32 comme Webserver avec IP fixe (inspiré de divers sites comme RandomNerdTutorials.com et https://projetsdiy.fr/piloter-gpio-esp8266-web-serveur-domoticz-partie2/ (avec tentative d’adaptation à ESP32). J’ai réalisé 3 codes qui tournent et les connections wifi semblent établies …mais …
    les requêtes DOMOTICZ échouent (syntaxe selon cet article) : voir ci-dessous message du Log domoticz.
    2021-03-06 13:57:01.771 (SERRE-Resist-1) Light/Switch (Serre-Resist-1)
    2021-03-06 13:57:01.742 Status: Schedule item started! Name: Serre-Resist-1, Type: On Time, DevID: 4,
    Time: 2021-03-06 13:57:01
    2021-03-06 13:57:05.071 Error: Error opening url: http://192.168.1.76/control?cmd=GPIO,2,0
    2021-03-06 13:58:01.419 (SERRE-Resist-1) Light/Switch (Serre-Resist-1)
    2021-03-06 13:58:01.384 Status: Schedule item started! Name: Serre-Resist-1, Type: On Time, DevID: 4,
    Time: 2021-03-06 13:58:01
    2021-03-06 13:58:04.683 Error: Error opening url: http://192.168.1.76/control?cmd=GPIO,2,1

    méthode 2 : Essai avec https://randomnerdtutorials.com/esp32-useful-wi-fi-functions-arduino

    Le code tourne …mais … les requêtes DOMOTICZ échouent également. Même retour !
    En conséquence :

    Aurais-tu en rayon quelque chose pour m’aider ?
    La syntaxe de ma requête DOMOTICZ est-elle correcte ?
    Je peux mettre mes codes ESP32 (Webserver et Wifi ) supour examen sur le forum Arduino.

    J’attends tes conseils avant la prochaine étape pour progresser.
    Merci d’avance. Bien cordialement.

    Etienne

    RépondreSupprimer
    Réponses
    1. Il est possible de faire tout cela avec un script qui envoie des requêtes JSON.
      https://bitbucket.org/henri_bachetti/mysensors-tft-temp-hum-sensor/src/master/domoticz/
      En particulier le script checkDevices.py surveille les capacités d'un certain nombre de batteries de capteurs, et également la température du freezer.
      Il actionne un buzzer en cas de problème. Le buzzer est vu comme un interrupteur (S_BINARY) par DOMOTICZ :
      https://riton-duino.blogspot.com/2019/05/un-afficheur-pour-domoticz-ou-jeedom.html

      Supprimer