Created
December 18, 2018 20:08
-
-
Save Bolukan/a0e1016219d8e6c588ae925b2b2b2888 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <Arduino.h> | |
| #include <Wire.h> | |
| #include <SPI.h> // BME280 library demand | |
| #if defined(ESP8266) | |
| #include <ESP8266WiFi.h> | |
| #elif defined(ESP32) | |
| #include <WiFi.h> | |
| #endif | |
| #include <WiFiClient.h> | |
| #include <PubSubClient.h> | |
| #include "secrets.h" | |
| #include <time.h> | |
| #include <rtcmem.h> | |
| #include <CRC32.h> | |
| #include <BME280I2C.h> | |
| /* | |
| * CONSTANTS | |
| */ | |
| // wifi | |
| #ifndef SECRETS_H | |
| #define SECRETS_H | |
| const char WIFI_SSID[] = "*** WIFI SSID ***"; | |
| const char WIFI_PASSWORD[] = "*** WIFI PASSWORD ***"; | |
| #endif | |
| // time | |
| const char TIME_NTPSERVER_1[] = "nl.pool.ntp.org"; | |
| const char TIME_NTPSERVER_2[] = "pool.ntp.org"; | |
| // other | |
| const uint32_t SECONDS_OFFSET = 60; | |
| const uint64_t SLEEPTIME = 60e6; | |
| const long SERIAL_BAUD = 115200; | |
| //const int SENSOR_INTERVAL_MILLIS = 60000; | |
| // http log | |
| const char* SERVER = "xxx.xxx.org"; | |
| const char* HTTPGET = "deviceid=%d&sensorid=%d&secondsoffset=%d&humidity=%d&pressure=%d&temperature=%d"; | |
| const char* MQTTPUB = "{'deviceid':%d,'sensorid':%d,'secondsoffset':%d,'humidity':%d,'pressure':%d,'temperature':%d}"; | |
| const char* MQTT_SERVER = "192.168.1.100"; | |
| const int MQTT_PORT = 1883; | |
| ADC_MODE(ADC_VCC); | |
| void callback(char* topic, byte* payload, unsigned int length) { | |
| // handle message arrived | |
| } | |
| /* | |
| * GLOBALS | |
| */ | |
| // BME280 | |
| BME280I2C::Settings settings( | |
| BME280::OSR_X1, | |
| BME280::OSR_X1, | |
| BME280::OSR_X1, | |
| BME280::Mode_Forced, | |
| BME280::StandbyTime_1000ms, | |
| BME280::Filter_Off, | |
| BME280::SpiEnable_False, | |
| BME280I2C::I2CAddr_0x76 // I2C address. I2C specific. | |
| ); | |
| BME280I2C bme(settings); | |
| typedef struct { | |
| uint32_t hum100; | |
| uint32_t pres100; | |
| int32_t temp100; | |
| } sensorData; | |
| sensorData sensordata; | |
| // rtcmem | |
| RTCMEM localmemory; | |
| /* | |
| * FUNCTIONS | |
| */ | |
| // wifi on, get time | |
| void connectToWiFi() { | |
| //Serial.printf("%u: ConnectToWiFi start\n", millis()); | |
| WiFi.forceSleepWake(); | |
| delay(1); | |
| WiFi.persistent(false); | |
| WiFi.mode(WIFI_STA); | |
| WiFi.begin(WIFI_SSID, WIFI_PASSWORD); | |
| configTime(0, 0, TIME_NTPSERVER_1, TIME_NTPSERVER_2); | |
| setenv("TZ", "CET-1CEST,M3.5.0,M10.5.0/3", 0); | |
| Serial.printf("%lu: ConnectToWiFi\n", millis()); | |
| } | |
| // save mem, wifi off, sleep | |
| void GoToSleep() { | |
| localmemory.saveMem(); | |
| WiFi.disconnect(true); | |
| delay(1); | |
| WiFi.mode(WIFI_OFF); | |
| WiFi.forceSleepBegin(); | |
| delay(5); | |
| Serial.printf("%lu: Going to sleep\n", millis()); | |
| Serial.flush(); | |
| // WAKE_RF_DISABLED to keep the WiFi radio disabled when we wake up | |
| ESP.deepSleep( SLEEPTIME, RF_DISABLED ); | |
| } | |
| char* dtostrfd(double number, unsigned char prec, char *s) | |
| { | |
| if ((isnan(number)) || (isinf(number))) { // Fix for JSON output (https://stackoverflow.com/questions/1423081/json-left-out-infinity-and-nan-json-status-in-ecmascript) | |
| strcpy(s, "null"); | |
| return s; | |
| } else { | |
| return dtostrf(number, 1, prec, s); | |
| } | |
| } | |
| // deviceID | |
| uint32_t deviceid() | |
| { | |
| #if defined(ESP8266) | |
| return ESP.getChipId(); | |
| #elif defined(ESP32) | |
| return ESP.getEfuseMac() & 0xffffff; | |
| #endif | |
| } | |
| // sensorID | |
| uint32_t sensorid() | |
| { | |
| uint8_t test[32]; | |
| CRC32 crc; | |
| return CRC32::calculate(bme.compensationParameters(test), 32); | |
| } | |
| void setup() { | |
| // Set WiFi Off | |
| WiFi.mode(WIFI_OFF); | |
| WiFi.forceSleepBegin(); | |
| delay(1); | |
| // Serial | |
| Serial.begin(SERIAL_BAUD); | |
| Serial.println(); | |
| // BME280 | |
| Serial.println(F("Starting BME280")); | |
| Wire.begin(); | |
| if (!bme.begin()) { | |
| Serial.println(F("Could not find BME280 sensor")); | |
| Serial.println(F("You have 60 seconds to connect the wires ...")); | |
| delay(60000); | |
| ESP.restart(); | |
| } | |
| if (bme.chipModel() != BME280::ChipModel_BME280) { | |
| Serial.println(F("Found BME280, but not full BME280 model")); | |
| Serial.println(F("You have 60 seconds to connect a full BME280 ...")); | |
| delay(60000); | |
| ESP.restart(); | |
| } | |
| // RTCMEM | |
| if (localmemory.loadMem()) { | |
| Serial.print("RTCMEM: OK Records: "); | |
| Serial.println(localmemory.recordCount()); | |
| } else { | |
| Serial.println("RTCMEM: Error"); | |
| localmemory.reset(sizeof(sensordata)); | |
| } | |
| } | |
| void loop() { | |
| // read BME280 | |
| float temp(NAN), hum(NAN), pres(NAN); | |
| BME280::TempUnit tempUnit(BME280::TempUnit_Celsius); | |
| BME280::PresUnit presUnit(BME280::PresUnit_hPa); | |
| bme.read(pres, temp, hum, tempUnit, presUnit); | |
| sensordata.hum100 = (uint32_t)(hum * 100); | |
| sensordata.pres100 = (uint32_t)(pres * 100); | |
| sensordata.temp100 = (int32_t)(temp * 100); | |
| // save in rtc memory | |
| localmemory.addRecord(&sensordata, sizeof(sensordata)); | |
| // Check for transfering memory | |
| if (localmemory.recordCount() > 5 || localmemory.isMemoryFull()) | |
| { | |
| // deviceID and sensorID | |
| uint32_t deviceID = deviceid(); | |
| uint32_t sensorID = sensorid(); | |
| char buffer[200]; | |
| char topic[100]; | |
| // WiFi and time | |
| WiFiClient client; | |
| connectToWiFi(); | |
| while (WiFi.status() != WL_CONNECTED) delay(1); | |
| while (time(nullptr) < 24 * 3600) delay(1); | |
| // mqtt | |
| PubSubClient mqtt(MQTT_SERVER, MQTT_PORT, callback, client); | |
| mqtt.setServer(MQTT_SERVER, MQTT_PORT); | |
| String clientId = "ESP"; | |
| clientId += String(deviceID, HEX); | |
| // Attempt to connect | |
| if (mqtt.connect(clientId.c_str())) { | |
| Serial.println("Connected"); | |
| } else { | |
| Serial.println("MQTT not connected"); | |
| } | |
| // VCC log | |
| char sVCC[33]; | |
| dtostrfd((double)ESP.getVcc()/1000, 3, sVCC); | |
| sprintf(topic, "sensor/%d/tele", deviceID); | |
| sprintf(buffer, "{\"deviceid\":%d,\"VCC\":\"%s\"}", deviceID, sVCC); | |
| mqtt.publish(topic, buffer); | |
| mqtt.loop(); | |
| uint16_t records = localmemory.recordCount(); | |
| uint16_t recordnr = 0; | |
| while (recordnr < records) | |
| { | |
| localmemory.getRecord(&sensordata, recordnr); | |
| sprintf(topic, "sensor/%d/bme280/%d", deviceID, sensorID); | |
| sprintf(buffer, "{\"deviceid\":%d,\"sensorid\":%d,\"o\":%d,\"h\":%d,\"p\":%d,\"t\":%d}", | |
| deviceID, sensorID, (records-recordnr-1) * SECONDS_OFFSET, sensordata.hum100, sensordata.pres100, sensordata.temp100); | |
| Serial.printf("%s %s\n", topic, buffer); | |
| mqtt.publish(topic, buffer); | |
| mqtt.loop(); | |
| delay(50); | |
| recordnr++; | |
| } | |
| delay(50); | |
| //mqtt.disconnect(); | |
| localmemory.reset(sizeof(sensordata)); | |
| } | |
| GoToSleep(); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment