Cameteo/arduino/mqtt_esp8266_BME280/mqtt_esp8266_BME280.ino

307 lines
8.5 KiB
C++

#include <ESP8266WiFi.h>
#include <MQTTClient.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <RTClib.h>
#include <TimeLib.h>
#include <NtpClientLib.h>
/************************* WiFi Access Point *********************************/
#define WLAN_SSID "arowifi2"
#define WLAN_PASS "nAGjywhCQ4iUBcbmf0PBn_srrghpOur4-aIzcJ_8Uxm1b58dH1c4Vy-LEMLd"
/************************* MQTT broker Setup *********************************/
#define MQTT_SERVER "192.168.0.18"
#define MQTT_SERVERPORT 1883 // use 8883 for SSL
#define MQTT_USERNAME "arofarn"
#define MQTT_KEY "WaKaW9XMGUZ3rRJD"
#define MQTT_ID "huzzah0"
#define MQTT_PUB_INTERVAL 15000 // milliseconds
/************************* Time and NTP Setup *********************************/
#define NTP_SERVER "fr.pool.ntp.org"
#define TIMEZONE 0 // UTC+0
#define DAYLIGHT false
#define NTP_REFRESH_INTERVAL 3600
/************************* Atmospheric Pressure Mode *********************************/
#define MODE_STATION true
#define DEFAULT_ALTITUDE 140.0
#define DEFAULT_MSLP 1013.25 //Mean Atmospheric Pressure at Mean Sea-Level
// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient wifi_client;
MQTTClient mqtt_client;
//Create a class for the sensor
Adafruit_BME280 bme; // I2C
bool mode_station = MODE_STATION;
float altitude = DEFAULT_ALTITUDE;
float atm_press_sea_level = DEFAULT_MSLP;
bool led0_status = true ;
unsigned long previousPub = 0;
/*************************** Sketch Code ************************************/
// Bug workaround for Arduino 1.6.6, it seems to need a function declaration
// for some reason (only affects ESP8266, likely an arduino-builder bug).
void MQTT_connect();
void setup() {
bool wstatus=false;
Serial.begin(115200);
delay(10);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(2, OUTPUT);
digitalWrite(2, wstatus);
digitalWrite(LED_BUILTIN, led0_status);
// Connect to WiFi access point.
Serial.println(); Serial.println();
Serial.print("Connecting to ");
Serial.println(WLAN_SSID);
WiFi.begin(WLAN_SSID, WLAN_PASS);
while (WiFi.status() != WL_CONNECTED) {
wstatus = !wstatus;
delay(500);
Serial.print(".");
digitalWrite(2, wstatus);
}
Serial.println();
digitalWrite(2, LOW);
Serial.println("WiFi connected");
Serial.println("IP address: "); Serial.println(WiFi.localIP());
delay(500);
NTP.begin(NTP_SERVER, TIMEZONE, DAYLIGHT); //Local french NTP server, timezone, summertime= false
NTP.setInterval(NTP_REFRESH_INTERVAL);
NTP.onNTPSyncEvent([](NTPSyncEvent_t error) {
if (error) {
Serial.print("Time Sync error: ");
if (error == noResponse)
Serial.println("NTP server not reachable");
else if (error == invalidAddress)
Serial.println("Invalid NTP server address");
}
else {
Serial.print("Got NTP time: ");
Serial.println(NTP.getTimeDateString(NTP.getLastNTPSync()));
}
});
time_t nowNTP;
nowNTP = NTP.getTime();
Serial.println(nowNTP);
// default settings
bool status;
status = bme.begin();
if (!status) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
mqtt_client.begin(MQTT_SERVER, MQTT_SERVERPORT, wifi_client); //MQTT_SERVERPORT, MQTT_USERNAME, MQTT_KEY);
//client.onMessage(messageReceived);
MQTT_connect();
mqtt_client.onMessage(messageReceived);
previousPub = millis();
}
uint32_t x=0;
void loop() {
mqtt_client.loop();
if (!mqtt_client.connected()) {
MQTT_connect();
}
unsigned long currentMillis = millis();
if(currentMillis - previousPub > MQTT_PUB_INTERVAL) {
// save the last time you blinked the LED
previousPub = currentMillis;
float pressure_val = -99.9;
float temperature_val = -99.9;
float humidity_val = -99.9;
String date_str = "";
char date_val[20] = "00:00:00 00-00-0000";
char tosend[120];
pressure_val = bme.readPressure() / 100.0F;
temperature_val = bme.readTemperature();
humidity_val = bme.readHumidity();
date_str = NTP.getTimeDateString();
date_str.toCharArray(date_val,20);
// Now we can publish stuff!
Serial.print(F("Sending pressure value "));
Serial.print(pressure_val);
Serial.print("...");
val2json(pressure_val, date_str, "hPa", "AP").toCharArray(tosend, 120);
if (! mqtt_client.publish("huzzah0/AdaBME280_1/pressure", tosend, true, 2) ) {
Serial.println(F("Failed"));
} else {
Serial.println(F("OK!"));
}
if(mode_station) {
//Sea-level atmospheric pressure calculus
atm_press_sea_level = bme.seaLevelForAltitude(altitude, pressure_val);
} else {
altitude = bme.readAltitude(atm_press_sea_level);
}
Serial.print(F("Sending sea-level pressure value "));
Serial.print(atm_press_sea_level);
Serial.print("...");
val2json(atm_press_sea_level, date_str, "hPa", "MSLP").toCharArray(tosend, 120);
if (! mqtt_client.publish("huzzah0/AdaBME280_1/sea_level_pressure", tosend, true, 2) ) {
Serial.println(F("Failed"));
} else {
Serial.println(F("OK!"));
}
Serial.print(F("Sending altitude value "));
Serial.print(altitude);
Serial.print("...");
val2json(altitude, date_str, "m", "ALTI").toCharArray(tosend, 120);
if (! mqtt_client.publish("huzzah0/AdaBME280_1/altitude", tosend, true, 2) ) {
Serial.println(F("Failed"));
} else {
Serial.println(F("OK!"));
}
// Now we can publish stuff!
Serial.print(F("Sending humity value "));
Serial.print(humidity_val);
Serial.print("...");
val2json(humidity_val, date_str, "%", "RH").toCharArray(tosend, 120);
if (! mqtt_client.publish("huzzah0/AdaBME280_1/humidity", tosend, true, 2)) {
Serial.println(F("Failed"));
} else {
Serial.println(F("OK!"));
}
// Now we can publish stuff!
Serial.print(F("Sending temperature value "));
Serial.print(temperature_val);
Serial.print("...");
val2json(temperature_val, date_str, "degC", "AT").toCharArray(tosend, 120);
if (! mqtt_client.publish("huzzah0/AdaBME280_1/temperature", tosend, true, 2)) {
Serial.println(F("Failed"));
} else {
Serial.println(F("OK!"));
}
// __LAST__ thing to send : Date and Time
Serial.print(F("Sending date and time "));
Serial.print(date_val);
Serial.print("...");
if (! mqtt_client.publish("huzzah0/NTP/date", date_val, true, 2)) {
Serial.println(F("Failed"));
} else {
Serial.println(F("OK!"));
}
}
delay(10);
}
void MQTT_connect() {
Serial.print("checking wifi...");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.print("\nconnecting...");
while (!mqtt_client.connect(MQTT_ID, MQTT_USERNAME, MQTT_KEY)) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
mqtt_client.subscribe("huzzah0/led0", 1);
mqtt_client.subscribe("huzzah0/mode_station", 1);
if(mode_station) {
mqtt_client.unsubscribe("huzzah0/sea_level_pressure");
mqtt_client.subscribe("huzzah0/altitude", 2);
}
else {
mqtt_client.unsubscribe("huzzah0/altitude");
mqtt_client.subscribe("huzzah0/sea_level_pressure", 1);
}
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
if(topic == "huzzah0/led0") {
if(payload == "0") led0_status = HIGH;
if(payload == "1") led0_status = LOW;
digitalWrite(LED_BUILTIN, led0_status);
}
if(topic == "huzzah0/mode_station") {
if(payload == "0") {
mode_station = false;
mqtt_client.unsubscribe("huzzah0/altitude");
mqtt_client.subscribe("huzzah0/sea_level_pressure", 1);
}
if(payload == "1") {
mode_station = true;
mqtt_client.unsubscribe("huzzah0/sea_level_pressure");
mqtt_client.subscribe("huzzah0/altitude", 1);
}
}
if(topic == "huzzah0/altitude") {
String pl = payload;
altitude = pl.toFloat();
Serial.print("New altitude :");
Serial.println(altitude);
}
}
String int2str(int a) {
String ret = "";
if (a < 10) {
ret +="0";
}
if (a > 99)
a = 99;
ret += a;
return ret;
}
String val2json (float val, String date, String unit, String type) {
String json = "{\"date\": \"";
json += date;
json += "\", \"value\": \"";
json += val;
json += "\", \"unit\": \"";
json += unit;
json += "\", \"type\": \"";
json += type;
json += "\" }";
//Serial.println(json);
return json;
}