février 23

Domotique avec Google Home, Teensy et Blynk

Mon projet domotique 2017. Le but étant de piloter les télécommandes infra-rouge (Freebox, ampli 5.1, switch HDMI…), les lampes de la maison (via des prises commandés en 433mhz) et un ruban LED multicolors via mon Google Home (et aussi IFTTT et Blynk).
Tout le montage rentre dans un bocal translucide de chez Ikea.

Le tout consomme 1.7 Watts au repos et 6.5 Watts avec une couleur allumé.

 

Pré-requis

Composants :

  • Régulateur 3.3volts LD1117v33
  • Teensy 3.2
  • ESP01 (WiFi)
  • XY-FST-433 (RX433)
  • SFH4346 (LED infra-rouge)
  • WS2812 (ruban LED)
  • Condensateur 1000 uF/25V
  • Transfo 5 Volts /2A
  • Éventuellement, un relais 220V/RX433

Le Principe

IFTTT reçoit les commandes du Google Home (trigger) et l’envoie une URL (WebHook) sur le serveur Blynk.
Celui-ci est connecté au Teensy via le ESP01 et déclenche des actions via le code Arduino.

On dit : Allume et un mot clé (tout, un, deux, Freebox…), le code Arduino contient des IF qui réagissent aux mot clés indiqués et envoie les codes infra-rouge ou 433mhz.

Le code Arduino

/*URL pour webhook IFTTT (passé en GET)  
 * https://ipduserveurblynk:9443/tokenblynk/update/v2?value={{TextField}}
 * avec le navigateur
 * https://ipduserveurblynk:9443/tokenblynk/update/v0?value=MotClé 
 * 
 * A base de Teensy 3.2
 * 2017 - Par Pit Wyman
 */
 
#define ESP8266_BAUD vitesse
#include <SoftwareSerial.h>
#define HWSERIAL Serial1 //pin RX1=0, TX1=1 du TeensyLC, Teensy 3.2

//RX433
#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();
int PinRX433 = 10; //pin Arduino/Teensy du module RX433

//Blynk
#define BLYNK_PRINT Serial //pour afficher les infos de connexion Wifi et Blynk  
#include <BlynkSimpleShieldEsp8266.h>

//ESP10
#include <ESP8266_Lib.h>
SoftwareSerial EspSerial(0, 1); // TX, RX de ESP10
ESP8266 wifi(&EspSerial);

//InfraRouge
/*
2 LED IR en série et Pas de résistance (avec certaines alims, ça envoie pas assez de jus)
Arduino Uno/Nano = pin 3
Teensy LC = 16
Tensy 3 à 3.6 = pin 5
*/
#include <IRremote.h>
//irrecv.blink13(true);// allume la LED interne du Teensy lors de l'envoie
IRsend irsend; //LED IR

//Ruban LED WS2812
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define WS2812Data 16 // Pin de la broche data du WS2812

// nombre de LED du WS2812
#define NbLED 55
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NbLED, WS2812Data, NEO_GRB + NEO_KHZ800);

int vitesse = 9600;
char auth[] = "***"; //token Blynk
char ssid[] = "****"; // Nom WiFi
char pass[] = "*****"; // Clé WiFi

#define VERSION "MaDomotique - Fin 2017"

void setup() {/*******************************************/
  Serial.begin(vitesse);//moniteur serie
  pixels.begin(); // NeoPixel library.
 //transmission RX433
  mySwitch.enableTransmit(PinRX433);
  // Optional set pulse length. default 320
  //mySwitch.setPulseLength(280); 
  // Optional set protocol (default is 1, will work for most outlets)
  //mySwitch.setProtocol(1); 
  // Optional set number of transmission repetitions. defaut 15
  //mySwitch.setRepeatTransmit(15);

  EspSerial.begin(ESP8266_BAUD);
  delay(50);
  Blynk.begin(auth, wifi, ssid, pass, "192.168.0.30"); //IP du serveur local Blynk
  
ws2812 (0,NbLED, 0,0,0);//éteint
ws2812 (0,NbLED, 255,255,255);//allume
delay(200);
ws2812 (0,NbLED, 0,0,0);//éteint
}

/******************** Allumer/éteindre lampes, Freebox ou Ampli 5.1 ***********************************/

BLYNK_WRITE(V0){// Allume ***
String ValeurV0 = param.asStr();
Serial.print("allume : ");
Serial.println(ValeurV0);

ws2812 (0,8, 255,0,0);//controle
ws2812 (0,8, 0,0,0);
   
Blynk.virtualWrite(0,ValeurV0);//envoie la valeur sur display de Blynk
 
      if (ValeurV0 == "tout" or ValeurV0 == "tous" or ValeurV0 == "tu"){
      mySwitch.send(16762196, 24); //lampe 1
      delay(100);
      mySwitch.send(16765268, 24); //lampe 2
      delay(100);
      mySwitch.send(16766036, 24); //lampe 3 
      delay(100);
      mySwitch.send(16766228, 24); //étoile papier
      delay(100);
      ws2812 (0,NbLED, 255,0,0); //WS2812 en rouge
      }

  if (ValeurV0 == "première" || ValeurV0 == "un" || ValeurV0 == "1" || ValeurV0 == "hein"){
  mySwitch.send(16762196, 24); //lampe 1
  }

      if (ValeurV0 == "deuxième" || ValeurV0 == "deux" || ValeurV0 == "2" || ValeurV0 == "de"){
      mySwitch.send(16765268, 24); //lampe 2
      }

  if (ValeurV0 == "troisième" || ValeurV0 == "trois" || ValeurV0 == "3"){
  mySwitch.send(16766036, 24); //lampe 3 
  }

  if (ValeurV0 == "veilleuse" or ValeurV0 == "étoile"){
  mySwitch.send(16766228, 24); //étoile papier
  }

  if (ValeurV0 == "cuisine") {
  mySwitch.send(1975778, 24); //cuisine
  }

      if (ValeurV0 == "Freebox" or ValeurV0 == "télé" or ValeurV0 == "tele"){

      irsend.sendNEC(0xA55A38C7, 32);// InfraRouge - Ampli 5.1 sur ON (allume la télé via prise intélligente)
          
      irsend.sendNEC(0xFF20DF, 32);// InfraRouge - switch HDMI sur Freebox
      delay(40);
      irsend.sendNEC(0xFFFFFF, 32);
      delay(100);
         
      CommandeFreebox("power");// allume la Freebox
      delay(2000);// attendre 2 sec
      CommandeFreebox ("ok");// valider (sur bouton télévision)
      }

if (ValeurV0 == "ampli" or ValeurV0 == "l'ampli"){// Ampli 5.1
      irsend.sendNEC(0xA55A38C7, 32);
}

if (ValeurV0 == "blanc"){// Ruban LED
      ws2812 (0,NbLED, 255,255,255);
}
if (ValeurV0 == "rouge"){// Ruban LED
      ws2812 (0,NbLED, 255,0,0);
} 
if (ValeurV0 == "vert"){// Ruban LED
      ws2812 (0,NbLED, 0,255,0);
} 
if (ValeurV0 == "bleu"){// Ruban LED
      ws2812 (0,NbLED, 0,0,255);
}
if (ValeurV0 == "jaune"){// Ruban LED
      ws2812 (0,NbLED, 255,255,0);
}
if (ValeurV0 == "orange"){// Ruban LED
      ws2812 (0,NbLED, 255,127,0);
}
if (ValeurV0 == "violet"){// Ruban LED
      ws2812 (0,NbLED, 127,0,255);
}

}//V0

BLYNK_WRITE(V1){// éteint ***
String ValeurV1 = param.asStr();
Serial.print("éteint : ");
Serial.println(ValeurV1);

ws2812 (0,8, 255,0,0);//controle
ws2812 (0,8, 0,0,0);
 
  if (ValeurV1 == "tout" or ValeurV1 == "tous" or ValeurV1 == "tu"){
  mySwitch.send(16762193, 24); //lampe 1
  delay(100);
  mySwitch.send(16765265, 24); //lampe 2
  delay(100);
  mySwitch.send(16766033, 24); //lampe 3 
  delay(100); 
  mySwitch.send(16766225, 24); //étoile papier
  delay(100);
  ws2812 (0,NbLED, 0,0,0); //WS2812
  }
  
      if (ValeurV1 == "première" || ValeurV1 == "un" || ValeurV1 == "1" || ValeurV1 == "hein"){
      mySwitch.send(16762193, 24); //lampe 1
      }

  if (ValeurV1 == "deuxième" || ValeurV1 == "deux" || ValeurV1 == "2" || ValeurV1 == "de"){
  mySwitch.send(16765265, 24); //lampe 2
  delay(100);
  }

      if (ValeurV1 == "troisième" || ValeurV1 == "trois" || ValeurV1 == "3"){
      mySwitch.send(16766033, 24); //lampe 3 
      delay(100);
      }

  if (ValeurV1 == "veilleuse" or ValeurV1 == "étoile"){
  mySwitch.send(16766225, 24); //étoile papier
  }

  if (ValeurV1 == "cuisine"){
  mySwitch.send(1975778, 24); //cuisine
  }
  
  if (ValeurV1 == "Freebox" or ValeurV1 == "télé"){
  CommandeFreebox ("power");// éteint la Freebox

  //la télé est éteinte via l'ampli HDMI
  //irsend.sendNEC(0x2FD48B7, 32);// InfraRouge - TV Toshiba sur OFF
  //delay(40);
  //irsend.sendNEC(0xFFFFFF, 32);
  delay(100);
  irsend.sendNEC(0xA55A38C7, 32);// InfraRouge - Ampli 5.1 sur OFF 
  }
  
      if (ValeurV1 == "ampli" or ValeurV1 == "l'ampli"){// Ampli 5.1
      irsend.sendNEC(0xA55A38C7, 32);
      }
      
if (ValeurV1 == "blanc" or ValeurV1 == "rouge" or ValeurV1 == "vert" or ValeurV1 == "bleu" or ValeurV1 == "jaune" or ValeurV1 == "orange" or ValeurV1 == "violet"){// Ruban LED
      ws2812 (0,NbLED, 0,0,0);
} 

}//V1

/****************************************** Switch HDMI  - InfraRouge *********************************/
BLYNK_WRITE(V2){// HDMI ***
String ValeurV2 = param.asStr();
Serial.print("HDMI  : ");
Serial.println(ValeurV2);

if (ValeurV2 == "Freebox"){
      irsend.sendNEC(0xFF20DF, 32);
      delay(40);
      irsend.sendNEC(0xFFFFFF, 32); 
  }//if

  if (ValeurV2 == "Netflix"){
      irsend.sendNEC(0xFF10EF, 32);
      delay(40);
      irsend.sendNEC(0xFFFFFF, 32);
  }//if

  if (ValeurV2 == "Kodi" or ValeurV2 == "mediacenter" or ValeurV2 == "libreelec"){
      irsend.sendNEC(0xFF50AF, 32);
      delay(40);
      irsend.sendNEC(0xFFFFFF, 32);  
  }//if

}//V2

/************************************* Ampli 5.1  - InfraRouge ************************************/
BLYNK_WRITE(V3){// monte/augmente l'ampli de ***
int ValeurV3 = param.asInt();
Serial.print("monte le volume de : ");
Serial.println(ValeurV3);

ws2812 (8,8+ValeurV3, 255,0,0);//controle
ws2812 (8,8+ValeurV3, 0,0,0);

  if (ValeurV3){
  
for (int i=0; i <= ValeurV3*2; i++){
Serial.println(ValeurV3);  
irsend.sendNEC(0xA55A50AF, 32);
delay(40);  
}//for
  }//if
  
}//V3

BLYNK_WRITE(V4){// baisse/diminue l'ampli de ***
int ValeurV4 = param.asInt();
Serial.print("baisse le volume de : ");
Serial.println(ValeurV4); 

ws2812 (8,8+ValeurV4, 255,0,0);//controle
ws2812 (8,8+ValeurV4, 0,0,0);

   if (ValeurV4){
  
for (int i=0; i <= ValeurV4*2; i++)
{
Serial.println(ValeurV4);  
irsend.sendNEC(0xA55AD02F, 32);
delay(40);
}//for
  }//if
  
}//V4

BLYNK_WRITE(V5){// coupe/remet l'ampli
int ValeurV5 = param.asInt();

if (ValeurV5 == 1){
Serial.println(ValeurV5);  
irsend.sendNEC(0xA55A48B7, 32);
  }//if
  
}//V5

/***************************************** Chaines Freebox - Webhook ************************/

BLYNK_WRITE(V6){// Freebox/regarder ***
String ValeurV6 = param.asStr();
Serial.print("regarder : ");
Serial.println(ValeurV6);

//définition des chaines
if (ValeurV6=="Mosaïque" or ValeurV6=="mosaïque" or ValeurV6=="panel") {CommandeFreebox("0");}
if (ValeurV6 == "TF 1") {CommandeFreebox("1");}
if (ValeurV6 == "France 2") {CommandeFreebox("2");}
if (ValeurV6== "France 3") {CommandeFreebox("3");}
if (ValeurV6 == "Canal +" or ValeurV6=="Canal") {CommandeFreebox("4");}
if (ValeurV6 == "France 5") {CommandeFreebox("5");}
if (ValeurV6 == "M 6") {CommandeFreebox("6");}
if (ValeurV6=="Arte") {CommandeFreebox("7");}
if (ValeurV6=="C 8") {CommandeFreebox("8");}
if (ValeurV6=="W 9") {CommandeFreebox("9");}
//a partir de 2 chiffres, ça ne marche plus ?!?


if (ValeurV6=="pause") {CommandeFreebox("play");}
if (ValeurV6=="direct") {
CommandeFreebox("green");
delay(2000);
CommandeFreebox("ok");
}

if (ValeurV6=="programme") {CommandeFreebox("epg");}
if (ValeurV6=="menu") {CommandeFreebox("green");}
if (ValeurV6=="maison") {CommandeFreebox("home");}
if (ValeurV6=="ok") {CommandeFreebox("ok");}
if (ValeurV6=="haut") {CommandeFreebox("up");}
if (ValeurV6=="bas") {CommandeFreebox("down");}
if (ValeurV6=="droite") {CommandeFreebox("right");}
if (ValeurV6=="gauche") {CommandeFreebox("left");}

if (ValeurV6=="dvd"){
CommandeFreebox("home");
delay(2000);
CommandeFreebox("right");
delay(1000);
CommandeFreebox("right");
delay(1000);
CommandeFreebox("right");
delay(1000);
CommandeFreebox("ok");
}

if (ValeurV6=="TV"){
CommandeFreebox("home");
delay(2500);
CommandeFreebox("ok");
}

/*************************************** Regarder Freebox Netflix ou Kodi ***************************************/

if (ValeurV6 == "Freebox" or ValeurV6 == "télé"){
      irsend.sendNEC(0xFF20DF, 32);// InfraRouge - switch HDMI sur Freebox
      delay(40);
      irsend.sendNEC(0xFFFFFF, 32);
      //la télé est allumé via l'ampli HDMI
      //delay(100);
      //irsend.sendNEC(0x2FD48B7, 32);// InfraRouge - TV Toshiba sur ON
      //delay(40);
      //irsend.sendNEC(0xFFFFFF, 32);
      delay(100);
      irsend.sendNEC(0xA55A38C7, 32);// InfraRouge - Ampli 5.1 sur ON     
  
      CommandeFreebox("power");// allume la Freebox
      delay(2000);// attendre 2 sec
      CommandeFreebox ("ok");// valider (sur bouton télévision)
      }

if (ValeurV6 == "Netflix"){
      //Ampli (qui allume la télé)
      irsend.sendNEC(0xFF10EF, 32);
      delay(40);
      irsend.sendNEC(0xFFFFFF, 32);  
delay(100);
      //HDMI sur Netflix
      irsend.sendNEC(0xFF10EF, 32);
      delay(40);
      irsend.sendNEC(0xFFFFFF, 32); 
}
if (ValeurV6 == "Kodi"){
      //Ampli (qui allume la télé)
      irsend.sendNEC(0xFF10EF, 32);
      delay(40);
      irsend.sendNEC(0xFFFFFF, 32);  
delay(100);
      //HDMI sur Kodi
      irsend.sendNEC(0xFF50AF, 32);
      delay(40);
      irsend.sendNEC(0xFFFFFF, 32);
}

}//V6

/********************************************* couper les lumières et la télé ***********************/

BLYNK_WRITE(V7){// on va se coucher
int ValeurV7 = param.asInt();

if (ValeurV7){
// lumières
mySwitch.send(16762193, 24); //lampe 1
  delay(100);
  mySwitch.send(16765265, 24); //lampe 2
  delay(100);
  mySwitch.send(16766033, 24); //lampe 3 
  delay(100); 
  mySwitch.send(16766225, 24); //étoile papier
  delay(100);
  ws2812 (0,NbLED, 0,0,0); //WS2812

CommandeFreebox ("power");// éteint la Freebox

irsend.sendNEC(0xA55A38C7, 32);// éteint l'ampli (qui éteint la télé)    
}
  
}//V7

/****************************** Ruban LED WS 2812 via l'appli Blynk *****************************/

BLYNK_WRITE(V8){ //zeRGBa de Blynk (http://docs.blynk.cc/#widgets-controllers-zergba)
  
  int r = param[0].asInt(); //rouge
  int v = param[1].asInt(); //vert
  int b = param[2].asInt(); //bleu

ws2812 (0,NbLED, r,v,b);//WS2812

}//V8


void CommandeFreebox(String MotCle){ /************************************* Fonction envoie des codes Freebox **************************************/
// WebHook Blynk avec : http://hd1.freebox.fr/pub/remote_control?code=86700567&key=/pin/
//&key=<touche>&long=true
//&key=<touche>&repeat=<n>

Blynk.virtualWrite(10, MotCle);
}

void ws2812 (int debut, int fin, int rouge, int vert, int bleu) /************** Fonction d'affichage des LED du ruban WS2812 *****************************/
{
    for(int i=debut;i<=fin;i++){
    // position de la LED (0=1er), couleurs RVB (de 0 à 255)
    pixels.setPixelColor(i, pixels.Color(rouge,vert,bleu)); 
    pixels.show(); // update couleurs
  }  
}//WS2812


void loop() { /**************************** LOOP *************************/
Blynk.run();      
}//loop


Ce code sera évidement adapté pour votre cas. Pour le miens, lorsque mon ampli 5.1 s’allume, il commande une multiprise « intelligente » qui allume la télé, le caisson basse et autre.
Le seul truc que je n’ai pas pu faire c’est changer les chaines de la Freebox qui ont 2 chiffres. Même en testant une URL dédié à ça, pas moyen.

L’électronique

Je suis partie d’un Teensy 3.2, un Arduino Uno n’est pas suffisant en terme de puissance.

Un ESP01 relié l’ensemble au WiFi, le module RX4333 envoie les codes en 433 mhz. 2 LED infra-rouge relié en série envoient les codes infra-rouge.
Le ruban LED (WS2812) est aussi relié au 5 volts.

L’ensemble est alimenté via un transfo 5 volts, un régulateur 3.3 volts alimente le ESP01. Un condensateur de 1000 uF/25V stabilise la tension (et pour protéger le ruban LED).

Le montage

Les composants électroniques sont fixés sur une plaque et reliés entrent eux par le dessous. Simple mais suffisant.
Le ruban LED s’enroule autour des montants.

J’ai fais une armature avec mon imprimante 3D. Tout est juste emboité, un trou est prévu à la base pour mettre un connecteur pour le transfo.
L’ensemble est coiffé par un bocal (à sucre je crois) de chez Ikea.

Fichier 3D

IFTTT et Blynk

J’utilise aussi le WebHook de IFTTT pour envoyer les mots clés qui seront reçu par Blynk et le WebHook de Blynk pour envoyer du code sur Teensy.

EX : Envoie le mot clé (TextField) sur l’IP du serveur Blynk/LeTokenBlynk, sur la VirtualPin V0

Dans le code Arduino :

BLYNK_WRITE(V0)
String ValeurV0 = param.asStr() (si c’est un mot)
String ValeurV0 = param.asInt() (si c’est un chiffre)

 

source 01 

Catégorie : Electronique | Commenter
janvier 6

Serveur Blynk local

Blynk est un service génial permettant de contrôler les entrées/sorties de beaucoup de matériels (Arduino, raspberryPi, Teensy…) via une appli smartphone ou du code arduino.
Blynk peut aussi utiliser les capteurs du smartphones pour son projet.
La création d’un compte octroi un cloud permettant la liaison via Internet mais du coup, une latence qui peut être gênante parfois.

Heureusement, on peut facilement installer son propre serveur Blynk, en Java, sur un raspberry Pi (une version 2 avec Raspbian Lite dans mon exemple).
L’avantage aussi est de s’affranchir de la limite « d’energy balance » du projet Blynk car sur son propre serveur, on peut monter cette valeur.

Installer Java

sudo apt-get update
sudo apt-get install oracle-java8-jdk

Faire : java -version pour afficher le numéro de version

Télécharger et installer Blynk

Allez chercher l’adresse sur le site : https://github.com/blynkkk/blynk-server/
(ex: wget « https://github.com/blynkkk/blynk-server/releases/download/v0.28.9/server-0.28.9-java8.jar »)

Démarrer Blynk
(modifier le numéro de java selon)
java -jar server-0.28.9-java8.jar -dataFolder /home/pi/Blynk

Un Ctrl+C ferme le serveur, pour redémarrer faire
java -jar server-0.28.9-java8.jar -dataFolder /home/pi/Blynk

Allez sur : https://ip_du_raspi:9443/admin

Utiliser au départ admin@blynk.cc et admin pour rentrer dans l’interface, ajouter ensuite un utilisateur avec login et password et supprimer ensuite le compte admin.

Mettre à jour le server

Tuer le processus, via son numéro PID

ps -aux | grep java
sudo kill ***

Télécharger et installer la nouvelle version

Penser à modifier le crontab

Source

 

Blynk au démarrage du Raspi

Editer le crontab
sudo crontab -e (sudo si le dossier Blynk est root:root, sinon crontab -e)
ajouter
@reboot java -jar /home/pi/server-0.28.9-java8.jar -dataFolder /home/pi/Blynk &

Pare-feux

Au besoin, ajouter des règles de redirection à sa box :

Blynk server has 3 ports open for different security levels.
8441 – SSL/TLS connection for hardware
8442 – plain TCP connection for hardware (no security)
9443 – Webhook SSL
8080 – Webhook

Modification des ports en début 2018
443 – mutual authentication (mutual SSL) connection for Mobile Apps

 

A partir de la, il suffit de créer un projet dans l’appli Blynk et de choisir « custom » pour le serveur, avec l’adresse IP de son Raspberry ou l’adresse IP externe de sa box, si l’on souhaite un accès via une connexion 4G.

L’appli envoie le token du projet par mail mais on peut le récupérer via la rubrique « users » du serveur Blynk.

Configuration

On peut aussi créer et personnaliser un fichier server.properties selon des besoins particuliers mais ce n’est pas indispensable.
En cas de réinstallation du serveur, il suffira de sauvegarder  ces fichiers.

sudo nano server.properties (dans le même dossier que le *.jar)
https://github.com/blynkkk/blynk-server/blob/master/server/core/src/main/resources/server.properties

remplacer
#server.host=test.blynk.cc
par
server.host=192.168.0.30

si une appli utilise le port 8080 (apache…) ou peut le changer
http.port=8181

en cas de blocage via webhook
webhooks.frequency.user.quota.limit=-1 to server properties.

Erreur de flow (trop de requètes)
If sending hundreds of requests is what you need for your product you may increase flood limit on local server and within Blynk library.
For local server you need to change user.message.quota.limit property within server.properties file :
#100 Req/sec rate limit per user.
user.message.quota.limit=100

sudo nano mail.properties
On peut recevoir le token via Gmail… créer un fichier mail.properties dans le même dossier que je ***.jar
sudo nano mail.properties
ATTENTION : ne fonctionne pas si la « validation en 2 étapes » est activé sur le compte Google
ajouter dedans
mail.smtp.auth=true
mail.smtp.starttls.enable=true
mail.smtp.host=smtp.gmail.com
mail.smtp.port=587
mail.smtp.username=YOUR_EMAIL_HERE
mail.smtp.password=YOUR_EMAIL_PASS_HERE

Webhook

Une des fonctions les plus puissante de Blynk est l’utilisation de webhook, des URL qui permettent de déclencher des actions sur Blynk.
Par exemple, via IFTTT : https://son_ip_publique:9443/le_token_du_projet/update/d10?value=1

enverra la valeur 1 sur la pin virtuel numéro 10 de Blynk.