/*
Projet de sonde luminosité, température et humidité.
Ajout de commande des volets roulants pour une gestion de la température du logement.
Basé sur l'exemple Basic ESP8266 MQTT
Il cherche une connexion sur un serveur MQTT puis :
- Il affiche les luminosités/humidités, lunière, pression baro intener (et externe).
- Il envoie tout cela en MQTT
- La température interne, (externe)
- L'humidité interne, (externe)
- La lumiére
- La pression barométrique et les autres parmêtres du BMP180
En fonction des paramètres lumiére, température,
il pourra monter ou descendre le volets roulants.
Affichage normal : (heure option) Tempéarute, Humidité
Si BP = 1s -> (peut étre 1 pression)
Affiche Temp int/ext, Lum int/ext, hum int/ext
Si BP = 3S ->
Affiche pression, (prévisions météos options)
Si BP = 10s -> désactivation volets
FUTUR :
On pourra définir les paramètres via une instruction MQTT
Fonction accessoire :
It will reconnect to the server if the connection is lost using a blocking
reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to
achieve the same result without blocking the main loop.
Exemples :
MQTT:
https://github.com/aderusha/IoTWM-ESP8266/blob/master/04_MQTT/MQTTdemo/MQTTdemo.ino
Witty:
https://blog.the-jedi.co.uk/2016/01/02/wifi-witty-esp12f-board/
Module tricapteur:
http://arduinolearning.com/code/htu21d-bmp180-bh1750fvi-sensor-example.php
*/
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
// Include the correct display library
// For a connection via I2C using Wire include
#include <Wire.h> // Only needed for Arduino 1.6.5 and earlier
#include "SSD1306.h" // alias for `#include "SSD1306Wire.h"`
// Include custom images
#include "WeatherStationImages.h"
#include "WeatherStationFonts.h"
// DHT 11 sensor
#define DHTPIN 2
#define DHTTYPE DHT11
// Utilisation d’une photo-résistance
// Et ports pour cmd volet
const int port = A0; // LDR
#define haut 12
#define arret 13
#define bas 15
#define lbp 14
// Update these with values suitable for your network.
// Buffer pour convertir en chaine de l'adresse IP de l'appareil
char buffer[20];
const char* ssid1 = "FREEBOX_xxx_EXT";
const char* ssid2 = "FREEBOX_xxx_P2";
const char* password = "xxxx";
const char* mqtt_server = "192.168.0.x";
// Création objet
WiFiClient espClient;
PubSubClient client(espClient);
// DHT sensor
DHT dht(DHTPIN, DHTTYPE, 15);
// Variables
int valeur = 0;
float vin = 0;
char msg[50];
int value = 0;
unsigned long readTime;
//Buffer qui permet de décoder les messages MQTT reçus
char message_buff[100];
long lastMsg = 0; //Horodatage du dernier message publié sur MQTT
long lastRecu = 0;
bool debug = false; //Affiche sur la console si True
bool mess = false; // true si message reçu
String sujet = "";
String mesg = "";
// Initialize the OLED display using Wire library
SSD1306 display(0x3c, 4, 5);
//========================================
void setup_wifi() {
int cpt = 0;
boolean ssid = true;
delay(10);
int ss = 1;
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_10);
display.drawString(0, 0, "Connexion au WiFi");
// We start by connecting to a WiFi network
while (WiFi.status() != WL_CONNECTED) {
if (ssid) {
WiFi.begin(ssid1, password);
}
else {
ss = 2;
WiFi.begin(ssid2, password);
}
if (debug) {
Serial.println();
Serial.print("Connecting to ");
if (ss == 1) {
Serial.println(ssid1);
} else {
Serial.println(ssid2);
}
}
int counter = 0;
while ((WiFi.status() != WL_CONNECTED) && (cpt <= 20)) {
delay(500);
Serial.print(".");
display.clear();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawString(24, 0, "Connecting to WiFi");
display.drawXbm(46, 30, 8, 8, counter % 3 == 0 ? activeSymbole : inactiveSymbole);
display.drawXbm(60, 30, 8, 8, counter % 3 == 1 ? activeSymbole : inactiveSymbole);
display.drawXbm(74, 30, 8, 8, counter % 3 == 2 ? activeSymbole : inactiveSymbole);
display.display();
counter++;
cpt=cpt+1;
// Serial.print(".");
}
if (cpt >= 20) {
if (ssid) {
ssid=false;
} else {
ssid=true;
}
}
}
// Connexion au serveur MQTT
display.clear();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_10);
display.drawString(32, 0, "WiFi connecté");
display.drawString(32, 20, "IP address");
// On récupère et on prépare le buffer contenant l'adresse IP attibué à l'ESP-01
IPAddress ip = WiFi.localIP();
String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
ipStr.toCharArray(buffer, 20);
display.drawString(30, 30, String(ipStr));
display.display();
delay(2000);
display.clear();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_10);
display.drawString(25, 0, "Connecting to MQTT");
display.drawString(32, 20, mqtt_server);
display.display();
delay(2000);
if ( debug ) {
Serial.println("");
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
Serial.print("Connecting to ");
Serial.println(mqtt_server);
}
/* Serial.print(" as ");
Serial.println(clientName);
*/
}
//========================================
// Déclenche les actions à la réception d'un message
// D'après http://m2mio.tumblr.com/post/30048662088/a-simple-example-arduino-mqtt-m2mio
void callback(char* topic, byte* payload, unsigned int length) {
// pinMode(lbp,OUTPUT);
int i = 0;
if ( debug ) {
Serial.println("Message recu => topic: " + String(topic));
Serial.print(" | longueur: " + String(length,DEC));
}
sujet = String(topic);
// create character buffer with ending null terminator (string)
for(i=0; i<length; i++) {
message_buff[i] = payload[i];
}
message_buff[i] = '\0';
String msgString = String(message_buff);
mesg = msgString;
if ( debug ) {
Serial.println("Payload: " + msgString);
}
mess = true;
}
/*
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
// Switch on the LED if an 1 was received as first character
if ((char)payload[0] == '1') {
digitalWrite(BUILTIN_LED, LOW); // Turn the LED on (Note that LOW is the voltage level
// but actually the LED is on; this is because
// it is acive low on the ESP-01)
} else {
digitalWrite(BUILTIN_LED, HIGH); // Turn the LED off by making the voltage HIGH
}
}
*/
//========================================
void reconnect() {
// Loop until we're reconnected
int counter = 0;
int compt = 0;
boolean noconnect = true;
// tant qu'il ne trouve pas un serveur affiche rond
while ((!client.connected()) && (noconnect == true)) {
display.clear();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_10);
display.drawString(0, 0, "Attempting MQTT connection");
display.drawXbm(46, 30, 8, 8, counter % 3 == 0 ? activeSymbole : inactiveSymbole);
delay(500);
display.drawXbm(60, 30, 8, 8, counter % 3 == 1 ? activeSymbole : inactiveSymbole);
delay(500);
display.drawXbm(74, 30, 8, 8, counter % 3 == 2 ? activeSymbole : inactiveSymbole);
display.display();
counter++;
delay(500);
if (debug ) {
Serial.print("Attempting MQTT connection...");
}
// Attempt to connect
if (client.connect("ESP8266Client")) {
display.clear();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_16);
display.drawString(23, 20, "Connecté sur");
display.drawString(18, 38, "Serveur MQTT !");
display.display();
if (debug ) {
Serial.println("connected");
}
// Once connected, publish an announcement...
client.publish("cuisine", "hello world");
// ... and resubscribe
client.subscribe("#");
noconnect=true;
} else {
display.clear();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_10);
display.drawString(2, 0, "On réessaye dans 3 sec");
display.setFont(ArialMT_Plain_16);
display.drawString(5, 20, "Erreur !");
display.drawString(0, 38, "Non Connecté !");
display.display();
if ( debug ) {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
}
// Wait 5 seconds before retrying
if (compt <= 3) {
delay(3000);
counter=0;
compt++;
} else {
noconnect=false;
}
}
}
delay(1500);
}
//========================================
void sensorRead() {
readTime = millis();
// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h = dht.readHumidity();
// Read temperature as Celsius (the default)
float t = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
// float f = dht.readTemperature(true);
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t)) { // || isnan(f)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
display.clear();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_10);
display.drawString(8, 0, "Temp + Humidité interne");
display.setFont(ArialMT_Plain_16);
display.drawString(6, 20, "Température=" + String(t)+" °C");
display.drawString(10, 38, "Humidité=" + String(h)+" %");
display.display();
// delay(500);
char buffer[20];
strcpy(msg, "Température ");
dtostrf(t,3, 2, buffer);
// On concatene les 2 tab de char
strcat(msg, buffer);
client.publish("cuisine",msg);
//Serial.println(buffer);
strcpy(msg, "Humiditée ");
dtostrf(h,3, 2, buffer);
strcat(msg, buffer);
client.publish("cuisine",msg);
//client.publish("cuisine",sprintf(buf, "%f", h));
/*Serial.print("Humidity: ");
Serial.print(h);
Serial.print(" %\t");
Serial.print("Temperature: ");
Serial.print(t);
Serial.print(" *C ");
/*Serial.print(f);
Serial.print(" *F\t");
Serial.print("Heat index: ");
Serial.print(hic);
Serial.print(" *C ");
Serial.print(hif);
Serial.println(" *F"); */
}
//========================================
void setup() {
pinMode(haut, OUTPUT); // Initialize le mvmt haut
pinMode(arret, OUTPUT); // Initialize le mvmt arret
pinMode(bas, OUTPUT); // Initialize le mvmt bas
pinMode(lbp, INPUT); // Initialize le BP
Serial.begin(115200);
// Initialising the UI will init the display too.
display.init();
display.clear();
//delay(500);
display.flipScreenVertically();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_16);
display.drawString(30, 31, "Bonjour");
// delay(1000);
display.setFont(ArialMT_Plain_10);
display.drawString(32, 0, "Hello world");
display.display();
delay(1500);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
dht.begin(); // initialize temperature sensor
client.subscribe("mod_cuisine");
}
//========================================
void loop() {
// test de connection, sinon reconnecte
//int counter = 0;
if (!client.connected()) {
reconnect();
}
client.loop();
//Serial.println("Lecture du capteur");
// affiche message reçu en MQTT
if ( mess ) {
pinMode(lbp,OUTPUT);
display.clear();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_10);
display.drawString(25, 0, "Message de MQTT");
display.drawString(32, 20, sujet);
display.drawString(32, 30, mesg);
display.display();
delay(1500);
if ( sujet == "mod_cuisine" ) {
if ( mesg == "ON" ) {
digitalWrite(lbp,HIGH);
} else {
digitalWrite(lbp,LOW);
}
}
pinMode(lbp,INPUT);
mess = false;
}
// renvoie le niveau de la ldr tous les 10 sec
long now = millis();
if (now - lastMsg > 5000) {
lastMsg = now;
++value;
snprintf (msg, 50, "hello world #%ld", value);
//Serial.print("Publish message: ");
//Serial.println(msg);
client.publish("cuisine", msg);
// Lit l’entrée analogique A0
valeur = analogRead(port);
//Serial.print("valeur = ");
//Serial.println(valeur);
// convertit l’entrée en volt
vin = (valeur * 3.3) / 1024.0;
//Serial.print("volt = ");
//Serial.println(vin);
display.clear();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_10);
display.drawString(14, 0, "Luminosité interne");
display.setFont(ArialMT_Plain_16);
display.drawString(25, 20, "Niv=" + String(valeur));
display.drawString(18, 38, "Volts=" + String(vin));
display.display();
delay(1500);
snprintf (msg, 50, "Luminosité %ld", valeur);
client.publish("cuisine", msg);
while (now - lastMsg > 10000) {
Serial.print("compteur: "+ (now-lastMsg));
}
//Serial.println("Lecture du capteur");
sensorRead();
delay(1500);
}
}
/*
void DHT11() {
// Grab the current state of the sensor
int humidity_data = (int)dht.readHumidity();
int temperature_data = (int)dht.readTemperature();
// Publish data
if (! temperature.publish(temperature_data))
Serial.println(F("Failed to publish temperature"));
else
Serial.println(F("Temperature published!"));
if (! humidity.publish(humidity_data))
Serial.println(F("Failed to publish humidity"));
else
Serial.println(F("Humidity published!"));
// Setup feeds for temperature & humidity
const char TEMPERATURE_FEED[] PROGMEM = AIO_USERNAME "/feeds/temperature";
Adafruit_MQTT_Publish temperature = Adafruit_MQTT_Publish(&mqtt, TEMPERATURE_FEED);
const char HUMIDITY_FEED[] PROGMEM = AIO_USERNAME "/feeds/humidity";
Adafruit_MQTT_Publish humidity = Adafruit_MQTT_Publish(&mqtt, HUMIDITY_FEED);
}
*/