first try to get a skeleton

This commit is contained in:
coelner 2018-12-06 20:14:48 +01:00
parent 09c1bf5981
commit e9c9eb4282
9 changed files with 1912 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

133
esp8266-sensor.ino Normal file
View File

@ -0,0 +1,133 @@
/************************* settings *********************************/
#define SERIAL_DEBUG
//#define OLED_OUTPUT
//#define BATTERY_USE
//#define BME2_USE
//#define BME6_USE
//#define BH_USE
#define SHT_USE
//#define VEML_USE
//#define CCS_USE
const bool metric = true;
/************************* generic libs *********************************/
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266httpUpdate.h>
#include <Wire.h>
#include <MQTTClient.h>
#include <IPAddress.h>
/*
reset causes:
0:
1: normal boot
2: reset pin
3: software reset
4: watchdog reset
boot device:
0:
1: ram
3: flash
Label to GPIO NodeMCU
D0 = 16;
D1 = 5; SCL
D2 = 4; SDA
D3 = 0;
D4 = 2;
D5 = 14;
D6 = 12;
D7 = 13;
D8 = 15;
D9 = 3;
D10 = 1; builtinLED
Wemos D1 mini
builtinLED = 2
D0 = 16;
D1 = 5; SCL
D2 = 4; SDA
D3 = 0;
D4 = 2; builtinLED
D5 = 14;
D6 = 12;
D7 = 13; CCS INTERRUPT
D8 = 15;
RX = 3;
TX = 1;
*/
/************************* state machine *********************************/
//the charger board cuts at 2.5V
//state definitions
#define STATE_COLDSTART 0
#define STATE_SLEEP_WAKE 1
#define STATE_FIRMWARE 2
#define STATE_MEASUREMENT 4
#define SLEEP_TIME 60*1000000UL // sleep intervalls in us (1min)
#define SLEEP_TIME_MEASUREMENT 1*SLEEP_TIME // sleep 60s(1min) after measurement
#define SLEEP_TIME_WIFI_TIMEOUT 1*SLEEP_TIME // sleep a minute
#ifdef BATTERY_USE
#define SLEEP_TIME_LOW_BAT 60*SLEEP_TIME // sleep 3600s(60min) after measurement
#define BATT_WARNING_VOLTAGE 270 // Voltage for Low-Bat warning in mV --rember the drop-out of the voltage regulator -- Be aware not to measure the VCC!
#define BATT_MEASUREMENT_OFFSET 20 //Meh, somewhere and somehow is something not that well...
#endif
/************************* WiFi Client *********************************/
#define WLAN_SSID "IoT"
#define WLAN_PASS "TF0xJJHtMz5kJUdh3dqf"
const int WIFI_CONNECT_TIMEOUT = 10; // seconds - max time for wifi connect to router, if exceeded go to sleep
//ToDo Legacy IPv4
IPAddress ip(10, 0, 4, 7);
IPAddress gateway(10, 0, 4, 1);
IPAddress subnet(255, 255, 255, 240);
IPAddress dns(10, 0, 4, 1);
IPAddress mqttBroker(10, 0, 4, 1); //failsafe
/********************* Firmware update **************************************/
const int FW_VERSION = 10;
const char* fwUrlBase = "http://10.0.4.2/fota/";
/************************* MQTT Broker Setup *********************************/
const int MQTT_PORT = 1883;
const char MQTT_SERVER[] = "mqtt.koelner.dynvpn.de";
char MQTT_CLIENTID[10];
const char MQTT_USERNAME[] = "input";
const char MQTT_PASSWORD[] = "tFnlKJu9";
const char MQTT_WILL_TOPIC[] = "bathroom/sys/will";
const int MQTT_WILL_QOS = 0;
const int MQTT_WILL_RETAIN = 0;
const char MQTT_WILL_MESSAGE[] = "Finally died...";
/****************************** Feeds ***************************************/
//ToDo: generate feed from CLIENTID and determine the ClientID from the ChipID
#if defined(BME2_USE) || defined(BME6_USE)
const char TEMPERATURE_FEED[] = "bathroom/sensors/temperature";
const char PRESSURE_FEED[] = "bathroom/sensors/pressure";
const char HUMIDITY_FEED[] = "bathroom/sensors/humidity";
const char ABSHUMIDITY_FEED[] = "bathroom/sensors/abshumidity";
#endif
#if defined(SHT_USE)
const char TEMPERATURE_FEED[] = "bathroom/sensors/temperature";
const char HUMIDITY_FEED[] = "bathroom/sensors/humidity";
const char ABSHUMIDITY_FEED[] = "bathroom/sensors/abshumidity";
#endif
#ifdef BME6_USE
const char IAQ_FEED[] = "bathroom/sensors/iaq";
const char IAQPREC_FEED[] = "bathroom/sensors/iaqprec";
#endif
#ifdef VEML_USE
const char UVA_FEED[] = "bathroom/sensors/uva";
const char UVB_FEED[] = "bathroom/sensors/uvb";
const char UVINDEX_FEED[] = "bathroom/sensors/uvindex";
#endif
#ifdef BH_USE
const char LIGHT_FEED[] = "bathroom/sensors/light";
#endif
#ifdef CCS_USE
const char ECO2_FEED[] = "bathroom/sensors/eco2";
const char TVOC_FEED[] = "bathroom/sensors/tvoc";
#endif
#ifdef BATTERY_USE
const char BATTERY_FEED[] = "bathroom/sys/battery";
#endif

46
i2c_scan.ino Normal file
View File

@ -0,0 +1,46 @@
/*************************** I2C scan function **********************************/
#ifdef SERIAL_DEBUG
void I2Cscan()
{
// scan for i2c devices
byte error, address;
int nDevices;
Serial.println(F("Scanning..."));
nDevices = 0;
for (address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0)
{
Serial.print(F("I2C device found at address 0x"));
if (address < 16)
Serial.print(F("0"));
Serial.print(address, HEX);
Serial.println(F(" !"));
nDevices++;
}
else if (error == 4)
{
Serial.print(F("Unknown error at address 0x"));
if (address < 16)
Serial.print(F("0"));
Serial.println(address, HEX);
}
}
if (nDevices == 0)
Serial.println(F("No I2C devices found\n"));
else
Serial.println(F("done\n"));
}
#endif

654
main.ino Normal file
View File

@ -0,0 +1,654 @@
// The ESP8266 RTC memory is arranged into blocks of 4 bytes. The access methods read and write 4 bytes at a time,
// so the RTC data structure should be padded to a 4-byte multiple.
struct {
uint32_t crc32; // 4 bytes
uint8_t channel; // 1 byte, 5 in total
uint8_t bssid[6]; // 6 bytes, 11 in total
uint8_t txPow = 0; // 1 byte, 12 in total
IPAddress mqttServer=mqttBroker; //save the dns lookup
#ifdef CCS_USE
bool ccsInit = false;
#endif
} rtcData;
/************************* RTC Mem *********************************/
#define WiFi_RTC 0
/************************* SSD1306 SPI *********************************/
#ifdef OLED_OUTPUT
#include <SSD1306.h>
SSD1306 display(0x3c, D4, D3);
//#include "OLEDDisplayUi.h"
#include "DejaVu_Sans_Mono_18.h"
// Initialize the OLED display using SPI
// D5 -> CLK
// D7 -> MOSI (DOUT)
// D1 -> RES
// D2 -> DC
// D8 -> CS
SSD1306Spi display(D1, D2, D8);
OLEDDisplayUi ui( &display );
#endif
/************************* BMP280 I2C *********************************/
#ifdef BME2_USE
//https://github.com/finitespace/BME280#usage
#include <BME280I2C.h>
#include "EnvironmentCalculations.h"
BME280I2C bme;
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
BME280::PresUnit presUnit(BME280::PresUnit_hPa);
#endif
/************************* BMP680 I2C *********************************/
#ifdef BME6_USE //ToDo
/*
//https://github.com/finitespace/BME280#usage
#include <BME280I2C.h>
#include "EnvironmentCalculations.h"
BME280I2C bme6;
const bool metric = true;
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
BME280::PresUnit presUnit(BME280::PresUnit_hPa);
*/
#endif
/************************* SHTXX I2C *********************************/
#ifdef SHT_USE
#include <SHTSensor.h>
SHTSensor sht(SHTSensor::SHT3X_ALT);
#endif
/************************* VEML6075 I2C *********************************/
#ifdef VEML_USE
//https://github.com/schizobovine/VEML6075
#include <VEML6075.h>
VEML6075 uvMeter;
#endif
/************************* BH1750 I2C *********************************/
#ifdef BH_USE
//https://github.com/claws/BH1750
#include <BH1750.h>
BH1750 lightMeter;
#endif
/************************* CCS811 I2C *********************************/
#ifdef CCS_USE
//https://github.com/LucAce/CCS811
#include "CCS811.h"
// Error ID code
enum {
CCS811_ERROR_CODE_WRITE_REG_INVALID = B00000001,
CCS811_ERROR_CODE_READ_REG_INVALID = B00000010,
CCS811_ERROR_CODE_MEASMODE_INVALID = B00000100,
CCS811_ERROR_CODE_MAX_RESISTANCE = B00001000,
CCS811_ERROR_CODE_HEATER_FAULT = B00010000,
CCS811_ERROR_CODE_HEATER_SUPPLY = B00100000,
};
#ifdef SERIAL_DEBUG
//*****************************************************************************
// Function: errorDecode
// Environment decodes the single bits from the error return
//*****************************************************************************
void errorDecode(uint8_t error_code) {
if (bitRead(error_code, CCS811_ERROR_CODE_WRITE_REG_INVALID)) Serial.println(F("ERROR: Wrong write request received"));
if (bitRead(error_code, CCS811_ERROR_CODE_READ_REG_INVALID)) Serial.println(F("ERROR: Wrong read request received"));
if (bitRead(error_code, CCS811_ERROR_CODE_MEASMODE_INVALID)) Serial.println(F("ERROR: Wrong meausrement mode request received"));
if (bitRead(error_code, CCS811_ERROR_CODE_MAX_RESISTANCE)) Serial.println(F("ERROR: Maximum sensor resistance reached!"));
if (bitRead(error_code, CCS811_ERROR_CODE_HEATER_FAULT)) Serial.println(F("ERROR: Heater current out of range!"));
if (bitRead(error_code, CCS811_ERROR_CODE_HEATER_SUPPLY)) Serial.println(F("ERROR: Heater supply voltage out of bounce!"));
}
#endif
// CCS811 I2C Interface
CCS811 ccs;
#define CCSINTERRUPT D7 //GPIO13
#define CCSRESET D6 //GPIO12
#endif
void messageReceived(String &topic, String &payload) {
#ifdef SERIAL_DEBUG
Serial.println("incoming: " + topic + " - " + payload);
#endif
}
/************** generic settings **************************/
void sleep(int duration, RFMode type) {
#ifdef SERIAL_DEBUG
//flush UART (pg. 11 esp8266 low power solution)
Serial.flush();
delay(10);
#endif
ESP.deepSleep(duration, type);
yield();
delay(100);
}
uint32_t calculateCRC32( const uint8_t *data, size_t length ) {
uint32_t crc = 0xffffffff;
while ( length-- ) {
uint8_t c = *data++;
for ( uint32_t i = 0x80; i > 0; i >>= 1 ) {
bool bit = crc & 0x80000000;
if ( c & i ) {
bit = !bit;
}
crc <<= 1;
if ( bit ) {
crc ^= 0x04c11db7;
}
}
}
return crc;
}
uint32_t voltageDivCorrelation(uint32_t u3) {
#ifdef BATTERY_USE
const unsigned int offset = 8;
if (u3 < offset) {
return BATT_MEASUREMENT_OFFSET;
}
#endif
//translate the 10bit value to reference voltage
//uint32_t adc = map (u3-offset, 0, 1023, 0 , 110);
uint32_t r1 = 390;
uint32_t r2 = 220;
uint32_t r3 = 100;
uint32_t rges = r1 + r2 + r3;
uint32_t uges = u3 * rges / r3;
//TODO why?!
uges = uges / 10;
return uges;
}
uint32_t adc = 0;
#if defined(BME2_USE) || defined (BME6_USE)
float temperature(NAN);
float humidity(NAN);
float absHumidity(NAN);
float pressure(NAN);
float dew(NAN);
String temp_str;
String hum_str;
String absHum_str;
String pres_str;
char temp[7];
char hum[8];
char absHum[8];
char pres[7];
#endif
#ifdef BME6_USE
float iaqF(NAN);
float iaqprecF(NAN);
String iaq_str;
String iaqprec_str;
char iaq[5];
char iaqprec[5];
#endif
#if defined(SHT_USE) || defined(SI7021_USE)
float temperature(NAN);
float humidity(NAN);
float absHumidity(NAN);
float dew(NAN);
String temp_str;
String hum_str;
String absHum_str;
char temp[7];
char hum[8];
char absHum[8];
#endif
#ifdef BH_USE
float vislight(NAN);
String light_str;
char light[8];
#endif
#ifdef VEML_USE
float uvalight(NAN);
float uvblight(NAN);
float uvi(NAN);
String uva_str;
String uvb_str;
String uvindex_str;
char uva[8];
char uvb[8];
char uvindex[5];
#endif
#ifdef CCS_USE
float eco2(NAN);
String eco2_str;
char eco2C[8];
float tvoc(NAN);
String tvoc_str;
char tvocC[8];
#endif
#ifdef BATTERY_USE
float battery(NAN);
String batt_str;
char batt[7];
#endif
bool wifiCheck = false;
bool mqttCheck = false;
bool bme280Check = false;
bool bme680Check = false;
bool veml6075Check = false;
bool bh1750Check = false;
bool ccs811Check = false;
bool sht30Check = false;
WiFiClient mqttSocket;
MQTTClient mqttClient;
/*************************** Sketch Code ************************************/
void initSensors() {
//assign i2c pins to different pins. SPI is hardware defined. | Wire.begin(SDA,SCL) | CLK D3 | DATA D4 --> be aware that a lot libs do that internally
//Wire.begin(D4, D3); //nodemcu
Wire.begin(D2, D1); //wemos D1 mini
/*********************SSD1306 OLED init **************************************/
#ifdef OLED_OUTPUT
display.init();
display.flipScreenVertically();
//display.setFont(DejaVu_Sans_Mono_18);
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.displayOn();
#endif
/*********************BH1750 I2C init **************************************/
#ifdef BH_USE
#ifdef SERIAL_DEBUG
Serial.print("\tBH1750 init...\t");
#endif
#ifdef OLED_OUTPUT
// clear the display
display.clear();
display.drawStringMaxWidth(0, 0, 128, "BH1750 init" );
// write the buffer to the display
display.display();
#endif
if (!lightMeter.begin(BH1750::ONE_TIME_HIGH_RES_MODE))
{
#ifdef SERIAL_DEBUG
Serial.println("no BH1750 anwering");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 16, 128, "BH1750 FAILED" );
// write the buffer to the display
display.display();
#endif
}
else {
bh1750Check = true;
#ifdef SERIAL_DEBUG
Serial.println("BH1750 ready.");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 16, 128, "BH1750 ready" );
// write the buffer to the display
display.display();
#endif
}
#endif
/*********************VEML6075 I2C init **************************************/
#ifdef VEML_USE
#ifdef SERIAL_DEBUG
Serial.print(F("\tVEML6075 init...\t"));
#endif
#ifdef OLED_OUTPUT
// clear the display
display.clear();
display.drawStringMaxWidth(0, 0, 128, "VEML6075 init" );
// write the buffer to the display
display.display();
#endif
uvMeter.begin();
if (!uvMeter.getDevID())
{
delay(10);
#ifdef SERIAL_DEBUG
Serial.println(F("no VEML6075 detected!"));
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 16, 128, "VEML6075 FAILED" );
// write the buffer to the display
display.display();
#endif
}
else {
veml6075Check = true;
#ifdef SERIAL_DEBUG
Serial.println(F("VEML6075 ready."));
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 16, 128, "VEML6075 ready" );
// write the buffer to the display
display.display();
#endif
}
#endif
/*********************BME680 I2C init **************************************/
#ifdef BME6_USE
#ifdef SERIAL_DEBUG
Serial.print(F("\tBME680 init...\t"));
#endif
#ifdef OLED_OUTPUT
// clear the display
display.clear();
display.drawStringMaxWidth(0, 0, 128, "BME680 init" );
// write the buffer to the display
display.display();
#endif
if (!bme6.begin())
{
delay(10);
#ifdef SERIAL_DEBUG
Serial.println(F("no BME680 detected!"));
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 16, 128, "BME680 FAILED" );
// write the buffer to the display
display.display();
#endif
}
else {
bme680Check = true;
#ifdef SERIAL_DEBUG
Serial.println(F("BME680 ready."));
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 16, 128, "BME680 ready" );
// write the buffer to the display
display.display();
#endif
}
#endif
/*********************BME280 I2C init **************************************/
#ifdef BME2_USE
#ifdef SERIAL_DEBUG
Serial.print(F("\tBME280 init...\t"));
#endif
#ifdef OLED_OUTPUT
// clear the display
display.clear();
display.drawStringMaxWidth(0, 0, 128, "BME280 init" );
// write the buffer to the display
display.display();
#endif
if (!bme.begin())
{
#ifdef SERIAL_DEBUG
Serial.println(F("no BME280 detected!"));
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 16, 128, "BME280 FAILED" );
// write the buffer to the display
display.display();
#endif
}
else {
bme280Check = true;
#ifdef SERIAL_DEBUG
Serial.println(F("BME280 ready."));
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 16, 128, "BME280 ready" );
// write the buffer to the display
display.display();
#endif
}
#endif
/*********************SHT3X I2C init **************************************/
#ifdef SHT_USE
#ifdef SERIAL_DEBUG
Serial.print(F("\tSHT30 init...\t"));
#endif
#ifdef OLED_OUTPUT
// clear the display
display.clear();
display.drawStringMaxWidth(0, 0, 128, "SHT30 init" );
// write the buffer to the display
display.display();
#endif
if (!sht.init())
{
#ifdef SERIAL_DEBUG
Serial.println(F("no SHT30 detected!"));
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 16, 128, "SHT30 FAILED" );
// write the buffer to the display
display.display();
#endif
}
else {
sht30Check = true;
sht.setAccuracy(SHTSensor::SHT_ACCURACY_MEDIUM); // only supported by SHT3x
yield();
#ifdef SERIAL_DEBUG
Serial.println(F("SHT30 ready."));
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 16, 128, "SHT30 ready" );
// write the buffer to the display
display.display();
#endif
}
#endif
/*********************CCS811 I2C init **************************************/
#ifdef CCS_USE
// Extend I2C clock stretch timeout (See Notes)
//Wire.setClockStretchLimit(500);
Wire.setClockStretchLimit(200000);
pinMode(CCSINTERRUPT, INPUT);
//pinMode(CCSRESET, OUTPUT);
delay(10);
digitalWrite(CCSRESET, HIGH);
delay(10);
#ifdef SERIAL_DEBUG
Serial.print(F("\tCCS811 init...\t"));
#endif
#ifdef OLED_OUTPUT
// clear the display
display.clear();
display.drawStringMaxWidth(0, 0, 128, "CCS811 init" );
// write the buffer to the display
display.display();
#endif
if (!ccs.begin())
{
delay(10);
#ifdef SERIAL_DEBUG
Serial.println(F("no CCS811 detected!"));
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 16, 128, "CCS811 FAILED" );
// write the buffer to the display
display.display();
#endif
}
else {
ccs811Check = true;
if (!rtcData.ccsInit) {
Serial.println(F("CCS811 not initialised"));
rtcData.ccsInit = true;
}
//set CCS811 measurement mode
ccs.writeMeasModeRegister(CCS811_DRIVE_MODE_1SEC , 1 , 0);
//Serial.println(F("INFO: Set measurement refresh to 1s"));
//enable Interrupt
ccs.enableInterrupt();
//Serial.println(F("INFO: Enable interrupt"));
/*while (!digitalRead(CCSINTERRUPT))
{
delay(200);
Serial.print(".");
}
while (!ccs.isDATA_READY())
{
delay(100);
ccs.readStatusRegister();
Serial.print(".");
};
*/
// ToDo why and reasons
//float temp = ccs.calculateTemperature();
ccs.setTempOffset(temperature - 25.0);
#ifdef SERIAL_DEBUG
Serial.println(F("CCS811 ready."));
/*
// Print CCS811 sensor information
Serial.println(F("CCS811 Sensor Enabled:"));
Serial.print(F("Hardware ID: 0x"));
Serial.println(ccs.getHWID(), HEX);
Serial.print(F("Hardware Version: 0x"));
Serial.println(ccs.getHWVersion(), HEX);
Serial.print(F("Firmware Boot Version: 0x"));
Serial.println(ccs.getFWBootVersion(), HEX);
Serial.print(F("Firmware App Version: 0x"));
Serial.println(ccs.getFWAppVersion(), HEX);
Serial.println(); */
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 16, 128, "CCS811 ready" );
// write the buffer to the display
display.display();
#endif
}
#endif
/******************** i2c init END ****************/
}
void setup() {
// if serial is not initialized all following calls to serial end dead.
#ifdef SERIAL_DEBUG
Serial.flush();
Serial.begin(115200);
while (!Serial) {
delay(1);
} // Wait
Serial.print(F("\nReset reason : \t\t\t"));
Serial.println(ESP.getResetReason());
#endif
WiFi.forceSleepBegin(); // send wifi to sleep to reduce power consumption
yield();
delay(100);
#ifdef BATTERY_USE
//check battery status
//Battery Voltage Measurement
//pinMode(D6, OUTPUT);
//digitalWrite(D6, HIGH); //activate transistor
//yield();
//delay(10);
pinMode(A0, INPUT);
yield();
adc = analogRead(A0);
yield();
delay(10);
#ifdef SERIAL_DEBUG
Serial.print(F("ADC_measurement: \t\t\t"));
Serial.println (String(adc));
Serial.print(F("VoltageDividerCorrelation in V: \t"));
Serial.println(String(voltageDivCorrelation(adc) - BATT_MEASUREMENT_OFFSET));
#endif
yield();
delay(10);
// go to sleep if to low
if (voltageDivCorrelation(adc) - BATT_MEASUREMENT_OFFSET < BATT_WARNING_VOLTAGE) {
#ifdef SERIAL_DEBUG
Serial.println(F("Low Battery Voltage. Got to sleep"));
#endif
sleep(SLEEP_TIME_LOW_BAT, WAKE_RF_DISABLED);
}
#endif
//go further if not
//init wifi
wifiCheck = wifi_connect();
if (wifiCheck) {
//connect mqtt
if (!mqttClient.loop()) {
//connect mqtt
mqttCheck = mqtt_connect();
}
if (mqttCheck) {
#ifdef SERIAL_DEBUG
Serial.println(F("Sensor init routine"));
yield();
#endif
initSensors();
yield();
#ifdef SERIAL_DEBUG
Serial.println(F("--------measurement--------"));
yield();
#endif
measurement();
yield();
#ifdef SERIAL_DEBUG
Serial.println(F("---------------------------"));
yield();
#endif
mqtt_disconnect();
yield();
}
//firmware update check
/*if (firmware_available()
//{
// get firmware
}*/
//regular --check whether 5min leads to wifi timeout
wifi_disconnect();
yield();
if (mqttCheck) {
#ifdef SERIAL_DEBUG
Serial.println(F("regular sleep"));
Serial.println(F("***********************************************************"));
#endif
sleep(SLEEP_TIME_MEASUREMENT, WAKE_RF_DEFAULT);
}
else {
//ToDo Do more useful stuff
#ifdef SERIAL_DEBUG
Serial.println(F("mqtt failed - wifi timeout sleep"));
#endif
sleep(SLEEP_TIME_WIFI_TIMEOUT, WAKE_RF_DEFAULT);
}
}
//no wifi available
else {
#ifdef SERIAL_DEBUG
Serial.println(F("Wifi failed"));
#endif
sleep(SLEEP_TIME_WIFI_TIMEOUT, WAKE_RFCAL);
}
}
void loop() {
yield();
}

774
measurement.ino Normal file
View File

@ -0,0 +1,774 @@
/********************* Measurement **************************************/
void measurement() {
#ifdef BME2_USE
if (bme280Check) {
bme.read(pressure, temperature, humidity, tempUnit, presUnit);
yield();
delay(10);
bme.read(pressure, temperature, humidity, tempUnit, presUnit);
yield();
}
#endif
#ifdef SHT_USE
if (sht30Check) {
if (sht.readSample())
{
yield();
humidity = sht.getHumidity();
yield();
temperature = sht.getTemperature();
yield();
}
}
#endif
#ifdef SI7021_USE
if (si7021Check) {
// Measure Relative Humidity from the HTU21D or Si7021
humidity = THMeter.getRH();
yield();
delay(10);
// Measure Temperature from the HTU21D or Si7021
temperature = THMeter.getTemp();
yield();
//ToDo Heater https://www.silabs.com/community/sensors/forum.topic.html/when_si7021_is_neede-8a2a
if (humidity >= 80.0) {
THMeter.heaterOn();
delay(50);
//THMeter.heaterOff();
}
}
#endif
#ifdef BH_USE
if (bh1750Check) {
//vislight = float(lightMeter.readLightLevel(true, false));
vislight = lightMeter.readLightLevel(true);
yield();
if (vislight > 40000.0 ) {
if (lightMeter.setMTreg(32)) {
yield();
}
}
else {
if (vislight > 10.0 && vislight <= 40000.0 && lightMeter.setMTreg(69))
{
yield();
}
}
if (vislight < 10.0) {
if (lightMeter.setMTreg(254)) {
yield();
}
}
yield();
if (vislight < 0.0)
{
vislight = -1;
}
else {
vislight = lightMeter.readLightLevel(true);
yield();
}
}
#endif
#ifdef VEML_USE
if (veml6075Check) {
//uvMeter.triggerMeasurement();
delay(10);
uvMeter.poll();
yield();
uvalight = float(uvMeter.getUVA());
yield();
uvblight = float(uvMeter.getUVB());
yield();
uvi = uvMeter.getUVIndex();
yield();
uvMeter.sleep(true);
yield();
}
#endif
#ifdef CCS_USE
if (ccs811Check) {
yield();
uint8_t ccs_error = 0;
// set environmental data
ccs.setEnvData(temperature, humidity);
while (digitalRead(CCSINTERRUPT) == HIGH)
{
delay(100);
Serial.print(".");
}
// Read the sensor data, this updates multiple fields
// in the CCS811 library
ccs.readAlgResultDataRegister();
if (ccs.hasERROR()) {
ccs_error = ccs.getERROR_ID();
#ifdef SERIAL_DEBUG
Serial.println(F("ERROR: CCS811 Error Flag Set"));
Serial.print(F("INFO: CCS811 Error Register = "));
Serial.println(ccs_error);
errorDecode(ccs_error);
Serial.println();
#endif
ccs811Check = false;
}
if (ccs811Check) {
// Data is ready
eco2 = float(ccs.geteCO2());
tvoc = float(ccs.getTVOC());
}
#ifdef SERIAL_DEBUG
//Serial.println(F("ERROR: CCS811 Data Not Ready"));
#endif
}
#endif
/************************** ADC Measurement *********************************/
#ifdef BATTERY_USE
adc = analogRead(A0);
#ifdef SERIAL_DEBUG
Serial.println("ADC Read:\t" + String(adc) );
#endif
yield();
delay(10);
batt_str = String(float(voltageDivCorrelation(adc) - BATT_MEASUREMENT_OFFSET) / 100);
batt_str.toCharArray(batt, batt_str.length() + 1);
#ifdef SERIAL_DEBUG
Serial.print("Battery Read:\t" + batt_str + " V" + "\t\t\t");
#endif
#ifdef SERIAL_DEBUG
Serial.print("Publish Battery: \t\t");
#endif
if (! mqttClient.publish(BATTERY_FEED, batt, true, 1) || !mqttClient.loop()) {
#ifdef SERIAL_DEBUG
Serial.println("Failed!");
#endif
}
else {
#ifdef SERIAL_DEBUG
Serial.println("OK");
#endif
}
yield();
mqttClient.loop();
yield();
delay(10);
#endif
/********************* Temperature **************************************/
#ifdef BME2_USE
if (bme280Check) {
#ifdef SERIAL_DEBUG
Serial.print("Temperature:\t");
Serial.print(temperature);
Serial.print(" °" + String(metric ? 'C' : 'F') );
Serial.print("\t\t\t");
#endif
temp_str = String(temperature);
temp_str.toCharArray(temp, temp_str.length() + 1);
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 0, 128, " " + temp_str + "°" + String(metric ? 'C' : 'F'));
#endif
#ifdef SERIAL_DEBUG
Serial.print("Publish Temperature: \t");
#endif
if (! mqttClient.publish(TEMPERATURE_FEED, temp, true, 1) || !mqttClient.loop()) {
#ifdef SERIAL_DEBUG
Serial.println("Failed!");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 0, 128, "x");
#endif
} else {
#ifdef SERIAL_DEBUG
Serial.println("OK");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 0, 128, "o");
#endif
}
mqttClient.loop();
yield();
delay(10);
/********************* Pressure **************************************/
#ifdef SERIAL_DEBUG
Serial.print("Pressure:\t");
Serial.print(pressure);
Serial.print(" hPa");
Serial.print("\t\t");
#endif
pres_str = String(pressure);
pres_str.toCharArray(pres, pres_str.length() + 1);
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 16, 128, pres_str + " hPa");
#endif
#ifdef SERIAL_DEBUG
Serial.print("Publish Pressure: \t");
#endif
if (! mqttClient.publish(PRESSURE_FEED, pres, true, 1) || !mqttClient.loop()) {
#ifdef SERIAL_DEBUG
Serial.println("Failed!");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 16, 128, "x");
#endif
} else {
#ifdef SERIAL_DEBUG
Serial.println("OK");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 16, 128, "o");
#endif
}
mqttClient.loop();
yield();
delay(10);
/********************* Humidity **************************************/
#ifdef SERIAL_DEBUG
Serial.print("Humidity:\t");
Serial.print(humidity);
Serial.print(" %" );
Serial.print("\t\t\t");
#endif
hum_str = String(humidity);
hum_str.toCharArray(hum, hum_str.length() + 1);
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 32, 128, " " + String(hum) + " %");
#endif
#ifdef SERIAL_DEBUG
Serial.print("Publish Humidity: \t");
#endif
if (! mqttClient.publish(HUMIDITY_FEED, hum, true, 1) || !mqttClient.loop()) {
#ifdef SERIAL_DEBUG
Serial.println("Failed!");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 32, 128, "x");
#endif
}
else {
#ifdef SERIAL_DEBUG
Serial.println("OK");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 32, 128, "o");
#endif
}
mqttClient.loop();
yield();
delay(10);
}
#endif
/********************* Temperature **************************************/
#ifdef SHT_USE
if (sht30Check) {
#ifdef SERIAL_DEBUG
Serial.print("Temperature:\t");
Serial.print(temperature);
Serial.print(" °" + String(metric ? 'C' : 'F') );
Serial.print("\t\t\t");
#endif
temp_str = String(temperature);
temp_str.toCharArray(temp, temp_str.length() + 1);
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 0, 128, " " + temp_str + "°" + String(metric ? 'C' : 'F'));
#endif
#ifdef SERIAL_DEBUG
Serial.print("Publish Temperature: \t");
#endif
if (! mqttClient.publish(TEMPERATURE_FEED, temp, true, 1) || !mqttClient.loop()) {
#ifdef SERIAL_DEBUG
Serial.println("Failed!");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 0, 128, "x");
#endif
} else {
#ifdef SERIAL_DEBUG
Serial.println("OK");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 0, 128, "o");
#endif
}
mqttClient.loop();
yield();
delay(10);
/********************* Humidity **************************************/
#ifdef SERIAL_DEBUG
Serial.print("Humidity:\t");
Serial.print(humidity);
Serial.print(" %" );
Serial.print("\t\t\t");
#endif
hum_str = String(humidity);
hum_str.toCharArray(hum, hum_str.length() + 1);
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 32, 128, " " + String(hum) + " %");
#endif
#ifdef SERIAL_DEBUG
Serial.print("Publish Humidity: \t");
#endif
if (! mqttClient.publish(HUMIDITY_FEED, hum, true, 1) || !mqttClient.loop()) {
#ifdef SERIAL_DEBUG
Serial.println("Failed!");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 32, 128, "x");
#endif
}
else {
#ifdef SERIAL_DEBUG
Serial.println("OK");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 32, 128, "o");
#endif
}
mqttClient.loop();
yield();
delay(10);
}
#endif //SHT_USE
/********************* Temperature **************************************/
#ifdef SI7021_USE
if (si7021Check) {
#ifdef SERIAL_DEBUG
Serial.print("Temperature:\t");
Serial.print(temperature);
Serial.print(" °" + String(metric ? 'C' : 'F') );
Serial.print("\t\t\t");
#endif
temp_str = String(temperature);
temp_str.toCharArray(temp, temp_str.length() + 1);
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 0, 128, " " + temp_str + "°" + String(metric ? 'C' : 'F'));
#endif
#ifdef SERIAL_DEBUG
Serial.print("Publish Temperature: \t");
#endif
if (! mqttClient.publish(TEMPERATURE_FEED, temp, true, 1) || !mqttClient.loop()) {
#ifdef SERIAL_DEBUG
Serial.println("Failed!");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 0, 128, "x");
#endif
} else {
#ifdef SERIAL_DEBUG
Serial.println("OK");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 0, 128, "o");
#endif
}
mqttClient.loop();
yield();
delay(10);
/********************* Humidity **************************************/
#ifdef SERIAL_DEBUG
Serial.print("Humidity:\t");
Serial.print(humidity);
Serial.print(" %" );
Serial.print("\t\t\t");
#endif
hum_str = String(humidity);
hum_str.toCharArray(hum, hum_str.length() + 1);
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 32, 128, " " + String(hum) + " %");
#endif
#ifdef SERIAL_DEBUG
Serial.print("Publish Humidity: \t");
#endif
if (! mqttClient.publish(HUMIDITY_FEED, hum, true, 1) || !mqttClient.loop()) {
#ifdef SERIAL_DEBUG
Serial.println("Failed!");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 32, 128, "x");
#endif
}
else {
#ifdef SERIAL_DEBUG
Serial.println("OK");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 32, 128, "o");
#endif
}
mqttClient.loop();
yield();
delay(10);
}
#endif
/********************* UVA **************************************/
#ifdef VEML_USE
if (veml6075Check) {
#ifdef SERIAL_DEBUG
Serial.print("UVA:\t\t");
Serial.print(uvalight);
Serial.print(" Ctr per mW/cm²" );
Serial.print("\t");
#endif
uva_str = String(uvalight);
uva_str.toCharArray(uva, uva_str.length() + 1);
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 32, 128, " " + String(uva) + " ");
#endif
#ifdef SERIAL_DEBUG
Serial.print("Publish UVA: \t\t");
#endif
if (! mqttClient.publish(UVA_FEED, uva, true, 1) || !mqttClient.loop()) {
#ifdef SERIAL_DEBUG
Serial.println("Failed!");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 32, 128, "x");
#endif
}
else {
#ifdef SERIAL_DEBUG
Serial.println("OK");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 32, 128, "o");
#endif
}
mqttClient.loop();
yield();
delay(10);
/********************* UVB **************************************/
#ifdef SERIAL_DEBUG
Serial.print("UVB:\t\t");
Serial.print(uvblight);
Serial.print(" Ctr per mW/cm²" );
Serial.print("\t");
#endif
uvb_str = String(uvblight);
uvb_str.toCharArray(uvb, uvb_str.length() + 1);
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 32, 128, " " + String(uvb) + " ");
#endif
#ifdef SERIAL_DEBUG
Serial.print("Publish UVB: \t\t");
#endif
if (! mqttClient.publish(UVB_FEED, uvb, true, 1) || !mqttClient.loop()) {
#ifdef SERIAL_DEBUG
Serial.println("Failed!");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 32, 128, "x");
#endif
}
else {
#ifdef SERIAL_DEBUG
Serial.println("OK");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 32, 128, "o");
#endif
}
mqttClient.loop();
yield();
delay(10);
/********************* UVIndex **************************************/
#ifdef SERIAL_DEBUG
Serial.print("UVIndex:\t\t");
Serial.print(uvi);
Serial.print("\t\t\t");
#endif
uvindex_str = String(uvi);
uvindex_str.toCharArray(uvindex, uvindex_str.length() + 1);
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 32, 128, " " + String(uvindex) + " ");
#endif
#ifdef SERIAL_DEBUG
Serial.print("Publish UVIndex: \t\t");
#endif
if (! mqttClient.publish(UVINDEX_FEED, uvindex, true, 1) || !mqttClient.loop()) {
#ifdef SERIAL_DEBUG
Serial.println("Failed!");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 32, 128, "x");
#endif
} else {
#ifdef SERIAL_DEBUG
Serial.println("OK");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 32, 128, "o");
#endif
}
mqttClient.loop();
delay(10);
}
#endif
/********************* visible light **************************************/
#ifdef BH_USE
if (bh1750Check && vislight >= 0.0) {
#ifdef SERIAL_DEBUG
Serial.print("Light:\t\t");
Serial.print(vislight);
Serial.print(" lx" );
Serial.print("\t\t");
#endif
light_str = String(int(vislight));
light_str.toCharArray(light, light_str.length() + 1);
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 32, 128, " " + String(light) + " lx");
#endif
#ifdef SERIAL_DEBUG
Serial.print("\tPublish Light: \t\t");
#endif
if (!mqttClient.publish(LIGHT_FEED, light, true, 1) || !mqttClient.loop()) {
#ifdef SERIAL_DEBUG
Serial.println("Failed!");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 32, 128, "x");
#endif
} else {
#ifdef SERIAL_DEBUG
Serial.println("OK");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 32, 128, "o");
#endif
}
mqttClient.loop();
delay(10);
}
#endif
/********************* Absolute Humidity **************************************/
#ifdef SI7021_USE
if (si7021Check) {
absHumidity = EnvironmentCalculations::AbsoluteHumidity(temperature, humidity, EnvironmentCalculations::TempUnit_Celsius);
#ifdef SERIAL_DEBUG
Serial.print("abs Humidity:\t");
Serial.print(absHumidity);
Serial.print(" g/m^3");
Serial.print("\t\t");
#endif
absHum_str = String(absHumidity);
absHum_str.toCharArray(absHum, absHum_str.length() + 1);
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 0, 128, " " + absHum_str + "g/m^3" );
#endif
#ifdef SERIAL_DEBUG
Serial.print("Publish abs Humidity: \t");
#endif
if (! mqttClient.publish(ABSHUMIDITY_FEED, absHum, true, 1) || !mqttClient.loop()) {
#ifdef SERIAL_DEBUG
Serial.println("Failed!");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 0, 128, "x");
#endif
} else {
#ifdef SERIAL_DEBUG
Serial.println("OK");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 0, 128, "o");
#endif
}
mqttClient.loop();
yield();
delay(10);
}
#endif
/********************* Absolute Humidity **************************************/
#ifdef BME2_USE
if (bme280Check) {
absHumidity = EnvironmentCalculations::AbsoluteHumidity(temperature, humidity, EnvironmentCalculations::TempUnit_Celsius);
#ifdef SERIAL_DEBUG
Serial.print("abs Humidity:\t");
Serial.print(absHumidity);
Serial.print(" g/m^3");
Serial.print("\t\t");
#endif
absHum_str = String(absHumidity);
absHum_str.toCharArray(absHum, absHum_str.length() + 1);
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 0, 128, " " + absHum_str + "g/m^3" );
#endif
#ifdef SERIAL_DEBUG
Serial.print("Publish abs Humidity: \t");
#endif
if (! mqttClient.publish(ABSHUMIDITY_FEED, absHum, true, 1) || !mqttClient.loop()) {
#ifdef SERIAL_DEBUG
Serial.println("Failed!");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 0, 128, "x");
#endif
} else {
#ifdef SERIAL_DEBUG
Serial.println("OK");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 0, 128, "o");
#endif
}
mqttClient.loop();
yield();
delay(10);
}
#endif
/********************* eCO2 **************************************/
#ifdef CCS_USE
//fix sensors internal wait delay
if (ccs811Check && eco2 > 0.00) {
#ifdef SERIAL_DEBUG
Serial.print("eCO2:\t\t");
Serial.print(eco2);
Serial.print(" ppm");
Serial.print("\t\t");
#endif
eco2_str = String(eco2);
eco2_str.toCharArray(eco2C, eco2_str.length() + 1);
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 0, 128, " " + eco2_str + "ppm" );
#endif
#ifdef SERIAL_DEBUG
Serial.print("Publish eCO2: \t\t");
#endif
if (! mqttClient.publish(ECO2_FEED, eco2C, true, 1) || !mqttClient.loop()) {
#ifdef SERIAL_DEBUG
Serial.println("Failed!");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 0, 128, "x");
#endif
} else {
#ifdef SERIAL_DEBUG
Serial.println("OK");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 0, 128, "o");
#endif
}
mqttClient.loop();
yield();
delay(10);
}
#endif
/********************* TVOC **************************************/
#ifdef CCS_USE
//fix sensors internal wait delay
if (ccs811Check && eco2 > 0.00) {
#ifdef SERIAL_DEBUG
Serial.print("TVOC:\t\t");
Serial.print(tvoc);
Serial.print(" ppb");
Serial.print("\t\t");
#endif
tvoc_str = String(tvoc);
tvoc_str.toCharArray(tvocC, tvoc_str.length() + 1);
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 0, 128, " " + tvoc_str + "ppb" );
#endif
#ifdef SERIAL_DEBUG
Serial.print("Publish TVOC: \t\t");
#endif
if (! mqttClient.publish(TVOC_FEED, tvocC, true, 1) || !mqttClient.loop()) {
#ifdef SERIAL_DEBUG
Serial.println("Failed!");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 0, 128, "x");
#endif
} else {
#ifdef SERIAL_DEBUG
Serial.println("OK");
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(110, 0, 128, "o");
#endif
}
mqttClient.loop();
yield();
delay(10);
}
#endif
/************************************ END *******************************/
mqttClient.loop();
yield();
delay(10);
return;
}

80
mqtt.ino Executable file
View File

@ -0,0 +1,80 @@
/*********************MQTT connect **************************************/
bool mqtt_connect() {
const int8_t maxRetryMqtt = 5;
int8_t currRetryMqtt = 0;
char mqttBrokerBuf[16]; //ToDo Legacy IPv4
mqttBroker.toString().toCharArray( mqttBrokerBuf, mqttBroker.toString().length()+1 );
#ifdef SERIAL_DEBUG
//Serial.println("MQTT Status: " + String(mqttClient.state()));
#endif
if (mqttClient.connected()) {
mqttCheck = true;
return true;
}
#ifdef SERIAL_DEBUG
Serial.println("Connecting to MQTT Broker...\t"+ String(mqttBrokerBuf));
#endif
#ifdef OLED_OUTPUT
display.clear();
//display.drawStringMaxWidth(0, 0, 128, "MQTT: conn");
#endif
//set options, may be obsolete
//mqttClient.setOptions(2, true, 750);
mqttClient.begin(mqttBrokerBuf, MQTT_PORT, mqttSocket);
mqttClient.onMessage(messageReceived);
mqttClient.setWill(MQTT_WILL_TOPIC, MQTT_WILL_MESSAGE, MQTT_WILL_RETAIN, MQTT_WILL_QOS);
bool retVal = mqttClient.connect(MQTT_CLIENTID, MQTT_USERNAME, MQTT_PASSWORD);
delay(10);
while (currRetryMqtt <= maxRetryMqtt && !mqttClient.connect(MQTT_CLIENTID, MQTT_USERNAME, MQTT_PASSWORD))
{ // connect will return 0 for connected
currRetryMqtt++;
if (mqttClient.connected()) {
currRetryMqtt=0;
return true;
}
else {
#ifdef SERIAL_DEBUG
if (currRetryMqtt == 1) {
Serial.print("Retrying MQTT connection in 1 seconds \t.");
}
else {
Serial.print(".");
}
#endif
delay(1000);// wait 1 seconds
}
}
retVal = mqttClient.connected();
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 32, 128, "MQTT: Error " + String(retVal));
display.display();
#endif
#ifdef OLED_OUTPUT
display.clear();
#endif
return retVal;
}
bool mqtt_disconnect() {
bool retVal = mqttClient.disconnect();
delay(10);
mqttClient.loop();
delay(10);
#ifdef SERIAL_DEBUG
if ( retVal ) {
Serial.println("mqtt disconnected");
}
else {
Serial.println("mqtt NOT disconnected");
}
#endif
return retVal;
}

69
ota.ino Normal file
View File

@ -0,0 +1,69 @@
//String getMAC()
//{
// uint8_t mac[6]= {00, 00, 00, 00, 00, 00};
// char result[14];
//
// snprintf( result, sizeof( result ), "%02x%02x%02x%02x%02x%02x", mac[ 0 ], mac[ 1 ], mac[ 2 ], mac[ 3 ], mac[ 4 ], mac[ 5 ] );
//
// return String( result );
//}
//
//void checkForUpdates() {
// String mac = getMAC();
// String fwURL = String( fwUrlBase );
// fwURL.concat( mac );
// String fwVersionURL = fwURL;
// fwVersionURL.concat( ".version" );
//
// Serial.println( "Checking for firmware updates." );
// Serial.print( "MAC address: " );
// Serial.println( mac );
// Serial.print( "Firmware version URL: " );
// Serial.println( fwVersionURL );
//
// WiFiClient ota;
//
// HTTPClient httpClient;
// httpClient.begin( ota, fwVersionURL );
// int httpCode = httpClient.GET();
// if( httpCode == 200 ) {
// String newFWVersion = httpClient.getString();
//
// Serial.print( "Current firmware version: " );
// Serial.println( FW_VERSION );
// Serial.print( "Available firmware version: " );
// Serial.println( newFWVersion );
//
// int newVersion = newFWVersion.toInt();
//
// if( newVersion > FW_VERSION ) {
// Serial.println( "Preparing to update" );
//
// String fwImageURL = fwURL;
// fwImageURL.concat( ".bin" );
// t_httpUpdate_return ret = ESPhttpUpdate.update( fwImageURL );
//
// switch(ret) {
// case HTTP_UPDATE_FAILED:
// Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
// break;
//
// case HTTP_UPDATE_NO_UPDATES:
// Serial.println("HTTP_UPDATE_NO_UPDATES");
// break;
// case HTTP_UPDATE_OK:
// Serial.println("HTTP_UPDATE_OK");
// break;
// }
// }
// else {
// Serial.println( "Already on latest version" );
// }
// }
// else {
// Serial.print( "Firmware version check failed, got HTTP response code " );
// Serial.println( httpCode );
// }
// httpClient.end();
//}
//

BIN
wemos-d1-mini-shematics.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

156
wifi.ino Normal file
View File

@ -0,0 +1,156 @@
/*********************Wifi Client init **************************************/
bool resolveHosts(bool rtcValid) {
if (rtcValid && rtcData.mqttServer.isV4()) {
mqttBroker = rtcData.mqttServer;
}
else {
//DNS lookup
if(WiFi.hostByName(MQTT_SERVER, mqttBroker)) {
rtcData.mqttServer = mqttBroker;
}
else {
return false;
}
}
return true;
}
bool wifi_connect() {
bool rtcValid = false;
// Try to read WiFi settings from RTC memory
if( ESP.rtcUserMemoryRead( WiFi_RTC, (uint32_t*)&rtcData, sizeof( rtcData ) ) ) {
// Calculate the CRC of what we just read from RTC memory, but skip the first 4 bytes as that's the checksum itself.
uint32_t crc = calculateCRC32( ((uint8_t*)&rtcData) + 4, sizeof( rtcData ) - 4 );
if( crc == rtcData.crc32 ) {
rtcValid = true;
}
#ifdef SERIAL_DEBUG
Serial.println("\trtcData.channel: \t\t" + String(rtcData.channel));
Serial.println("\trtcData.txPow: \t\t" + String(rtcData.txPow));
//Serial.println("\trtcData.mqttServer:\t" + rtcData.mqttServer);
#endif
}
#ifdef OLED_OUTPUT
display.clear();
display.drawStringMaxWidth(0, 0, 128, "WiFi init" );
display.display();
display.drawStringMaxWidth(0, 16, 128, "WiFi: " + String(WLAN_SSID));
display.display();
#endif
#ifdef SERIAL_DEBUG
Serial.println();
Serial.print("Connecting to ");
Serial.println(WLAN_SSID);
#endif
WiFi.forceSleepWake();
delay(10);
WiFi.mode(WIFI_STA);
yield();
// Disable the WiFi persistence. The ESP8266 will not load and save WiFi settings in the flash memory.
// http://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/generic-class.html#persistent
WiFi.persistent (false);
WiFi.hostname("bathroom"); //ToDo Change to correct value
WiFi.config(ip, gateway, subnet, dns);
// Connect to WiFi access point.
if( rtcValid ) {
// The RTC data was good, make a quick connection
if (rtcData.txPow > 0 ) {
rtcData.txPow=rtcData.txPow-1;
WiFi.setOutputPower(rtcData.txPow);
yield();
}
WiFi.begin( WLAN_SSID, WLAN_PASS, rtcData.channel, rtcData.bssid, true );
#ifdef SERIAL_DEBUG
Serial.println("RTC WiFi used");
Serial.println("\tCurrent Powerlevel: \t" + String(rtcData.txPow*4) + "dB");
#endif
}
else {
//raise outputPower to max
WiFi.setOutputPower(10);
rtcData.txPow = 10;
// The RTC data was not valid, so make a regular connection
WiFi.begin( WLAN_SSID, WLAN_PASS );
yield();
delay(10);
}
#ifdef SERIAL_DEBUG
Serial.print("WiFi started");
//WiFi.printDiag(Serial);
#endif
int i = 0;
uint64_t sTime = millis();
while (WiFi.status() != WL_CONNECTED) {
delay(200);
i++;
yield();
#ifdef SERIAL_DEBUG
Serial.print(".");
#endif
if ((millis() - sTime) > WIFI_CONNECT_TIMEOUT * 1000) // wifi connection lasts too ling, retry
{
#ifdef SERIAL_DEBUG
Serial.println("WiFi connect timeout!");
#endif
//raise transmit power for next retry
rtcData.txPow=rtcData.txPow+1;
//make the crc invalid
ESP.rtcUserMemoryWrite (WiFi_RTC, (uint32_t*)&rtcData , sizeof( rtcData ) );
return false;
}
//every two second raise the TX power
if (i%4 == 0)
{
rtcData.txPow = rtcData.txPow+1;
WiFi.setOutputPower(rtcData.txPow);
yield();
#ifdef SERIAL_DEBUG
Serial.println("\tWiFi TX Power raised: \t" + String(rtcData.txPow) + "counter");
#endif
}
yield();
}
//ToDo stupid TX power correlation --needs improvement
long rssi = WiFi.RSSI();
//rtcData.txPow = int((72+rssi)/4)+rtcData.txPow;
if (rssi > -60 )
{
rtcData.txPow = 0;
}
#ifdef SERIAL_DEBUG
Serial.println("\n\r\tWiFi Connect Time: \t" + String(float((millis() - sTime)/1000)) + " s");
Serial.println("\tWiFi RSSI: \t\t" + String(rssi) + " dB");
Serial.println("\tWiFi next TX Power: \t" + String(rtcData.txPow) + " counter");
#endif
// Write current connection info back to RTC
resolveHosts( rtcValid );
rtcData.channel = WiFi.channel();
memcpy( rtcData.bssid, WiFi.BSSID(), 6 ); // Copy 6 bytes of BSSID (AP's MAC address)
rtcData.crc32 = calculateCRC32( ((uint8_t*)&rtcData) + 4, sizeof( rtcData ) - 4 );
ESP.rtcUserMemoryWrite (WiFi_RTC, (uint32_t*)&rtcData , sizeof( rtcData ) );
#ifdef SERIAL_DEBUG
Serial.println("\tIP address: \t\t" + WiFi.localIP().toString() );
#endif
#ifdef OLED_OUTPUT
display.drawStringMaxWidth(0, 32, 128, "IP: " + WiFi.localIP().toString());
display.display();
#endif
return true;
}
bool wifi_disconnect() {
//exit gracefully from WiFi AP - delete credentials
WiFi.disconnect(true);
yield();
#ifdef SERIAL_DEBUG
Serial.println("WiFi disconnected");
#endif
//shutdown WiFi modul
WiFi.mode(WIFI_OFF);
// set WiFi to sleep
WiFi.forceSleepBegin();
yield();
return true;
}