Communication grace à un ESP8266-01 entre une carte Arduino MEGA et un serveur MQTT
Schéma de principe :
Descriptif du fonctionnement :
La carte est reliée en wifi à un serveur MQTT qui enregistre une action ON/OFF sur l’interrupteur relié à la carte. Le même serveur MQTT renvoie à la carte des informations.
Pour la carte ARDUINO :
//////////////////////////////////////////////////////////////////////
// Envoi du statut d'une LED à un serveur web et à un serveur MQTT //
// via un ESP8266 connecté au port série 3 d'une carte Arduino MEGA //
//////////////////////////////////////////////////////////////////////
#define led 13 //-- Témoin LED
#define inPin1 22 //-- Switch
int val;
int i;
boolean dpAlarme = false;
////////////////////////////
void setup() {
Serial.begin(9600); //-- Pour console
Serial3.begin(115200); //-- Port ESP8266
pinMode(led, OUTPUT); //-- Led
pinMode(inPin1, INPUT); //-- Switch
digitalWrite(led, LOW); //-- LED OFF
Serial.println("Initialisation !");
}
///////////////////////////
void loop() {
//-- Lecture statut switch
val = digitalRead(inPin1);
//-- Action en fonction de l'état
if (val == HIGH)
{
if (!dpAlarme)
{
Serial.println("SWITCH ON");
Serial3.println("lon"); //-- Envoi à l'ESP la commande
digitalWrite(led, HIGH);
dpAlarme = true;
}
}
if (val == LOW)
{
if (dpAlarme)
{
Serial.println("SWITCH OFF");
Serial3.println("loff"); //-- Envoi de la commande
digitalWrite(led, LOW);
dpAlarme = false;
}
}
//-- Ecoute si on recoit une commande
TestRecep();
delay(50); //-- Tempo du switch
}
///////////////////////////
boolean TestRecep() {
String sRecu = "";
if (Serial3.available())
{
sRecu = Serial3.readStringUntil(13);
Serial.println("res=");
Serial.println(sRecu);
if (sRecu == "LON") {
Serial.println("LED -> On");
digitalWrite(led, HIGH);
delay(100);
return (true);
}
else if (sRecu == "LOFF")
{
Serial.println("LED -> Off");
digitalWrite(led, LOW);
delay(100);
return (true);
}
}
return (false);
}
Pour le module ESP :
////////////////////////////////////////////////////////////
// DOMOTICZ : prévoir un dispositif nommé AA_ACTIV_LIGHT
// ACCES DIRECT :
// adresseip de l'ESP/LIGHTON = activation de la LED
// adresseip de l'ESP/LIGHTOFF = désactivation de la LED
//---------------------------------------------------------
//////////////////////////////////
#include <WiFiUdp.h>
#include <WiFiClient.h>
#include <WiFiServer.h>
#include <SPI.h>
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <ESP8266AVRISP.h>
#include <PubSubClient.h>
#include <EEPROM.h>
//------------------
//-- DOMOTICZ idx
#define idxActivLight "89" //-- IDX à récupérer sous DomoticZ
//
String s_cmd;
//---------------
boolean bLightActiv = false; //-- LIGHT détection neutralisé=false
///////////////////////////////////////////////////
//--- WEB SETTINGS
WiFiServer serverHTTP(80);
WiFiClient clientHTTP;
char PHPSiteAddress[] = "xxxxxx";
unsigned int cpt = 0;
boolean takeRqte = false;
String requete = "", ResRequete = "";
//-- MQTT SETTINGS
WiFiClient CliWifiMQTT;
char msgToDomoticZ[120];
const char *topicin = "domoticz/in";
const char *topicout = "domoticz/out";
const char *msgContact = "{\"command\": \"switchlight\", \"idx\": ";
const char *msgContactOn = ", \"switchcmd\": \"On\", \"level\": 100}";
const char *msgContactOff = ", \"switchcmd\": \"Off\", \"level\": 100}";
//"{\"command\": \"switchlight\", \"idx\": 19, \"switchcmd\": \"On\", \"level\": 100}";
IPAddress serverMQTT(192, 168, 0, 20);
const char* ssid = "xxxx";
const char* password = "xxxxx";
////////////////////////////////////////////
//-- Récupération des instructions DOMOTICZ
void callback(const MQTT::Publish& pub) {
String sMsg;
sMsg = pub.payload_string();
//--
if (sMsg.indexOf("\"name\" : \"AA_ACTIV_LIGHT\"") > -1)
{ if (sMsg.indexOf("nvalue\" : 0") != -1)
{ Serial.println("LOFF");
SendServer("LIGHT","OFF");
bLightActiv = false;
return;
}
else
{
Serial.println("LON");
SendServer("LIGHT","ON");
bLightActiv = true;
return;
}
}
}
PubSubClient clientMQTT(CliWifiMQTT, serverMQTT);
//---------------
void setup() {
Serial.begin(115200);
delay(10);
//
clientMQTT.set_callback(callback);
//
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
Serial.println("WIFIOK");
Serial.println(WiFi.localIP());
//-- Start the HTTP server
serverHTTP.begin();
//--
clientMQTT.set_callback(callback);
if (clientMQTT.connect("arduinoClient")) {
//-- Subscribe
clientMQTT.subscribe(topicout);
}
}
void loop() {
//-- Lecture des infos sur le port série
if (Serial.available() > 0)
{
keyhandle();
}
//------------------
clientMQTT.loop();
//-----------------
////////////
ResRequete = "";
////
clientHTTP = serverHTTP.available();
if (clientHTTP) {
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (clientHTTP.connected()) {
if (clientHTTP.available()) {
char c = clientHTTP.read();
if (cpt == 4 && c == '/') {
takeRqte = true;
}
if (c == ' ') {
takeRqte = false;
}
if (takeRqte == true && cpt != 4)
{
requete = requete + c;
}
cpt++;
if (c == '\n' && currentLineIsBlank) {
ResRequete = ActionRequete(requete);
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
requete = "";
takeRqte = false;
cpt = 0;
if (ResRequete != "")
{
clientMQTT.publish(topicin, ResRequete);
}
}
delay(100);
}
Avec les fonctions suivantes :
String ActionRequete(String Requete)
{
//--
if (requete.indexOf("LIGHTON") > -1) {
bLightActiv = true;
strcpy(msgToDomoticZ, msgContact);
strcat(msgToDomoticZ, idxActivLight);
strcat(msgToDomoticZ, msgContactOn);
Serial.println("LON");
SendServer("LIGHT", "ON");
return (msgToDomoticZ);
}
if (requete.indexOf("LIGHTOFF") > -1) {
bLightActiv = false;
strcpy(msgToDomoticZ, msgContact);
strcat(msgToDomoticZ, idxActivLight);
strcat(msgToDomoticZ, msgContactOff);
Serial.println("LOFF");
SendServer("LIGHT", "OFF");
return (msgToDomoticZ);
}
return ("");
}
////////////////////////
//-- Send data to server
void SendServer(String contact, String statut) {
String sData = "contact=" + contact + "&statut=" + statut;
SendClient(sData);
clientHTTP.stop();
Serial.println(sData);
if (clientHTTP.connect(PHPSiteAddress, 80)) {
clientHTTP.println("GET /ar/updatetable.php?" + sData + " HTTP/1.1");
clientHTTP.println("Host: androraspberry.site40.net");
clientHTTP.print("Content-Type: text/html,application/xhtml+xml,application/xml\n");
clientHTTP.print("Accept-Encoding: gzip, deflate, sdch\n");
clientHTTP.print("Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4\n");
clientHTTP.print("Cookie: siteowner=1\n");
clientHTTP.print("Upgrade-Insecure-Requests: 1\n");
clientHTTP.print("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64)\n");
//client.print("\n");
clientHTTP.print("Content-Length: ");
clientHTTP.print(sData.length());
clientHTTP.print("\n\n");
}
else {
Serial.println("connection HTTP failed...");
}
}
//////////
void SendClient(String sInfo )
{
// send a standard http response header
clientHTTP.println("HTTP/1.1 200 OK");
clientHTTP.println("Content-Type: text/html");
clientHTTP.println("Connection: close"); // the connection will be closed after completion of the response
clientHTTP.println("<!DOCTYPE HTML>");
clientHTTP.println("<html>");
clientHTTP.println(sInfo);
clientHTTP.println("</html>");
}
Et
//----------------------------------------
// Acquisition de commande via la console ou le port série
//----------------------------------------
void keyhandle()
{ int i_key;
i_key = Serial.read(); // get incoming byte
if (i_key == 8 or i_key == 127)
{
int i_cl = s_cmd.length() - 1;
s_cmd = s_cmd.substring(0, i_cl);
Serial.write(8); Serial.write(32); Serial.write(8); i_key = 0;
}
if (i_key > 64 and i_key < 90) {
i_key += 32; // GROSS in klein-Buchstaben
}
if (i_key >= 32) {
s_cmd = s_cmd + char(i_key);
Serial.write(i_key);
}
if (i_key == 13) {
CLI_exec();
}
}
//----------------------------------------
// Traitement des commandes retourne OK ou ERROR
//----------------------------------------
int CLI_exec()
{
int i_ret = -1;
if (s_cmd == "lon")
{
bLightActiv = true;
strcpy(msgToDomoticZ, msgContact);
strcat(msgToDomoticZ, idxActivLight);
strcat(msgToDomoticZ, msgContactOn);
clientMQTT.publish(topicin, msgToDomoticZ);
SendServer("LIGHT", "ON");
i_ret = 0;
}
if (s_cmd == "loff")
{
bLightActiv = false;
strcpy(msgToDomoticZ, msgContact);
strcat(msgToDomoticZ, idxActivLight);
strcat(msgToDomoticZ, msgContactOff);
clientMQTT.publish(topicin, msgToDomoticZ);
SendServer("LIGHT", "OFF");
i_ret = 0;
}
if (i_ret == -1)
Serial.println("ERROR");
else
Serial.println("OK");
s_cmd = "";
}
Sketch Arduino et ESP8266 à télécharger ici