#include #include // #include #include #include #include #include "SSD1306Brzo.h" #include // #include #include "wifi.h" #include "Adafruit_MQTT.h" #include "Adafruit_MQTT_Client.h" double inTemp,outTemp,pressure,humid; unsigned short int onTime = 5, offTime = 23, beepDelay = 60, lastBeep, lastWifi; bool mqttAvail; WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP); SSD1306Brzo display(0x3C, 5, 4); //oled display w/ address 0x3C with SDA on GPIO4 and SCL on GPIO5 //address == offset WiFiClient client; // ESP8266WebServer server(80); Adafruit_MQTT_Client mqtt(&client, "192.168.100.100", 1883); Adafruit_MQTT_Subscribe pressureFeed = Adafruit_MQTT_Subscribe(&mqtt, "pressure"); Adafruit_MQTT_Subscribe inFeed = Adafruit_MQTT_Subscribe(&mqtt, "bmpTemp"); Adafruit_MQTT_Subscribe outFeed = Adafruit_MQTT_Subscribe(&mqtt, "externalTemp"); Adafruit_MQTT_Subscribe humidFeed = Adafruit_MQTT_Subscribe(&mqtt, "humid"); void wifiConnect() { int beginMillis = millis(); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED && millis() - beginMillis < 30000) { delay(250); displayStatus(1); Serial.print("."); } if (WiFi.status() != WL_CONNECTED) { displayStatus(2); delay(10000); ESP.reset(); } else { MDNS.begin("esp8266-frontend"); Serial.print("Connected to " + String(ssid) + "; IP address: "); Serial.println(WiFi.localIP()); displayStatus(0); } } void setup(){ Serial.begin(115200); //==DISPLAY INIT== display.init(); display.flipScreenVertically(); display.setContrast(255); //==WIFI CONNECT== WiFi.mode(WIFI_STA); wifiConnect(); //==READ CONFIG== // if (!SPIFFS.begin()) // SPIFFS.format(); // if (!readConfig()) // defConfig(); //==NTP INIT== timeClient.begin(); timeClient.setTimeOffset(10800); //MQTT pressureFeed.setCallback(pressureCall); inFeed.setCallback(inCall); outFeed.setCallback(outCall); humidFeed.setCallback(humidCall); mqtt.subscribe(&pressureFeed); mqtt.subscribe(&outFeed); mqtt.subscribe(&inFeed); mqtt.subscribe(&humidFeed); // server.on("/edit", editConfig); // server.begin(); updateNtp(); } void loop(){ if (WiFi.status() != WL_CONNECTED) { //check wifi status wifiConnect(); } // server.handleClient(); if (timeClient.getHours()*60+timeClient.getMinutes() - lastWifi >= 60){ // due to powersaving lastWifi = timeClient.getHours()*60+timeClient.getMinutes(); MQTT_connect();//check connection and get packets for 0.5s mqtt.processPackets(750); updateNtp();//update time } else delay(900); mainScreen();//it could be cool and smooth if we could update screen independently, in some kind of separate thread or smthn similar if ((timeClient.getHours()*60 + timeClient.getMinutes() - lastBeep >= beepDelay)&&(!nightMode())){ //beep every $lastBeep tone(15,1000); delay(100); noTone(15); lastBeep = timeClient.getHours()*60; } } //second screen //GRAPH /* get json from server ~12 values hourly values + hourly display if pressure lowers then weather gonna be bad if pressure uppers then weather gonna be good */ //====================IN PROGRESS=================== // void editConfig(){ // if (server.args() > 0 ) { // for ( uint8_t i = 0; i < server.args(); i++ ){ // String Argument_Name = server.argName(i); // String client_response = server.arg(i); // if (Argument_Name == "beepDelay"){ // beepDelay = client_response.toInt(); // } // if (Argument_Name == "onTime"){ // onTime = client_response.toInt(); // } // if (Argument_Name == "offTime"){ // offTime = client_response.toInt(); // } // updateConfig(); // server.send(200, "text/plain", "updatedConfig"); // } // } else { // server.send(200, "text/plain", "to update config, goto " + String(WiFi.localIP()) + "/edit?parameter=value"); // } // } // bool updateConfig() { // StaticJsonBuffer<200> jsonBuffer; // JsonObject& json = jsonBuffer.createObject(); // json["onTime"] = onTime; // json["offTime"] = offTime; // json["beepDelay"] = beepDelay; // File configFile = SPIFFS.open("/config.json", "w"); // if (!configFile) { // Serial.println("Failed to open config file for writing"); // return false; // } // json.printTo(configFile); // return true; // } // bool readConfig() { // File configFile = SPIFFS.open("/config.json", "r"); // if (!configFile) { // Serial.println("Failed to open config file"); // return false; // } // size_t size = configFile.size(); // if (size > 1024) { // Serial.println("Config file size is too large"); // return false; // } // // Allocate a buffer to store contents of the file. // std::unique_ptr buf(new char[size]); // // We don't use String here because ArduinoJson library requires the input buffer to be mutable. If you don't use ArduinoJson, you may as well use configFile.readString instead. // configFile.readBytes(buf.get(), size); // StaticJsonBuffer<200> jsonBuffer; // JsonObject& json = jsonBuffer.parseObject(buf.get()); // if (!json.success()) { // Serial.println("Failed to parse config file"); // return false; // } // offTime = int(json["offTime"]); // onTime = int(json["onTime"]); // beepDelay = int(json["beepDelay"]); // return true; // } // bool defConfig() { // StaticJsonBuffer<200> jsonBuffer; // JsonObject& json = jsonBuffer.createObject(); // json["onTime"] = "6"; // json["offTime"] = "23"; // json["beepDelay"] = "60"; // File configFile = SPIFFS.open("/config.json", "w"); // if (!configFile) { // Serial.println("Failed to open config file for writing"); // return false; // } // json.printTo(configFile); // return true; // } //====================paused=================== // void secondDisplay() { // display.clear(); // display.setFont(ArialMT_Plain_16); // display.setTextAlignment(TEXT_ALIGN_CENTER); // display.drawString(0, 30, timeClient.getFormattedTime()); // display.drawRect(0,18,128,53); //frame // /* // 128/12=10px // 128x32 resolution // 32-19=13px for graph // */ // int x = 0; // for (int i=0;i<12;++i){ // display.drawLine(x+i*10, y[x], x+i*10+10, y[x]); // } // } //===================WELL DONE======================= void mainScreen() { display.clear(); if (!nightMode()) { //turn off screen at night int x = (timeClient.getHours()*60+timeClient.getMinutes())/11; //Time display.setFont(ArialMT_Plain_24); display.setTextAlignment(TEXT_ALIGN_CENTER); display.drawString(64, 22, timeClient.getFormattedTime()); //progress bar display.drawLine(0,22,x,22); if (mqttAvail){ //do not show info if mqtt not available //external temp //top left display.setFont(ArialMT_Plain_10); display.setTextAlignment(TEXT_ALIGN_LEFT); display.drawString(0, 0, "o:"+String(outTemp)); //pressure //top right display.setFont(ArialMT_Plain_10); display.setTextAlignment(TEXT_ALIGN_RIGHT); display.drawString(128, 0, "p:"+String(pressure)); //inside temp //bottom left display.setFont(ArialMT_Plain_10); display.setTextAlignment(TEXT_ALIGN_LEFT); display.drawString(0, 53, "i:"+String(inTemp)); //humid //bottom right display.setFont(ArialMT_Plain_10); display.setTextAlignment(TEXT_ALIGN_RIGHT); display.drawString(128, 53, "h:"+String(humid)+"%"); } else { display.setFont(ArialMT_Plain_10); display.setTextAlignment(TEXT_ALIGN_LEFT); display.drawString(0, 53, "mqtt unavailable"); } } display.display(); } void displayStatus(int state){ display.clear(); display.setFont(ArialMT_Plain_16); display.setTextAlignment(TEXT_ALIGN_CENTER); switch (state) { case 0: display.drawString(64, 22, "Connected!"); break; case 1: display.drawString(64, 22, "Connecting..."); break; case 2: display.drawString(64, 22, "Not connected!"); display.setFont(ArialMT_Plain_10); display.setTextAlignment(TEXT_ALIGN_LEFT); display.drawString(0, 53, "we will die in 10s! :0"); break; } display.display(); } void MQTT_connect() { if (mqtt.connected()) { return; } int8_t ret; uint8_t retries = 3; while ((ret = mqtt.connect()) != 0) { displayStatus(3); mqtt.disconnect(); delay(5000); retries--; if (retries == 0) { mqttAvail = false; } } if (mqtt.connected()) mqttAvail = true; } void pressureCall(double x) { pressure = x; } void inCall(double x) { inTemp = x; } void outCall(double x) { outTemp = x; } void humidCall(double x){ humid = x; } void updateNtp() { // if (lastNtp != timeClient.getHours()) { // if (timeClient.update()) while (!timeClient.update()) { delay(100); } // lastNtp = timeClient.getHours(); // } } bool nightMode() { if ((timeClient.getHours() > offTime)||(timeClient.getHours() < onTime)) { //turn off screen between loaded time return true; } else return false; }