Compare commits

..

2 Commits

Author SHA1 Message Date
b123fc7a6a notify in progress 2018-05-29 12:07:43 +03:00
d462dcc147 test notify 2018-05-09 13:01:27 +03:00
6 changed files with 413 additions and 178 deletions

5
.vscode/arduino.json vendored Executable file → Normal file
View File

@ -1,6 +1,7 @@
{ {
"board": "esp8266:esp8266:generic", "board": "esp8266:esp8266:generic",
"configuration": "xtal=80,vt=flash,exception=disabled,ssl=all,ResetMethod=ck,CrystalFreq=26,FlashFreq=40,FlashMode=qio,eesz=4M1M,led=2,sdk=nonosdk221,ip=lm2f,dbg=Disabled,lvl=None____,wipe=none,baud=921600", "configuration": "CpuFrequency=160,FlashFreq=80,FlashMode=dio,UploadSpeed=115200,FlashSize=1M512,ResetMethod=ck,Debug=Disabled,DebugLevel=None____",
"port": "/dev/ttyUSB0",
"sketch": "frontend.ino", "sketch": "frontend.ino",
"port": "/dev/ttyUSB0" "output": "Output"
} }

5
.vscode/settings.json vendored Executable file → Normal file
View File

@ -1,6 +1,3 @@
{ {
"C_Cpp.intelliSenseEngineFallback": "Enabled", "C_Cpp.intelliSenseEngineFallback": "Enabled"
"files.associations": {
"*.inc": "cpp"
}
} }

0
LICENSE Executable file → Normal file
View File

0
front.svg Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

540
frontend.ino Executable file → Normal file
View File

@ -1,123 +1,369 @@
//TODO
//AT LEAST MAKE IT WORK (show ui and get data + ntp) - compiling - ... - WORKS!!11
//debug -> release
//remove useless serial debug - DONE
//show wifi info on oled - DONE
//reset on not connected - DONE
//check connectivity during work and do actions - DONE
//beep hourly - DONE
//github - oh yeahhh
//load config
//webconfig (?) - in progress
//mqtt update interval
//second screen
//reconfig wifi if not found (start webserver and AP)
//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
*/
//CONFIG
/*
beep time
on time
off time
mqtt update interval
*/
#include <ESP8266WiFi.h> #include <ESP8266WiFi.h>
#include <WiFiClient.h> #include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <NTPClient.h> #include <NTPClient.h>
#include <WiFiUdp.h> #include <WiFiUdp.h>
#include "SSD1306Brzo.h" #include "SSD1306Brzo.h"
#include <ArduinoJson.h>
#include <FS.h>
#include "wifi.h" #include "wifi.h"
#include <ESP8266HTTPClient.h> #include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
String inTemp,outTemp,pressure,humid; double inTemp,outTemp,pressure,humid;
const unsigned short int onTime=6, offTime=23, beepDelay=60, timeOffset=3; unsigned short int onTime = 5, offTime = 23, beepDelay = 60, lastNtp, lastBeep;
short int lastBeep; bool mqttAvail;
const String httpAddr="http://meteo-front:1880";
int alarms[10]={660,1260};
int alarmDuration(6);
int alarmStop(0);
WiFiUDP ntpUDP; WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP); NTPClient timeClient(ntpUDP);
SSD1306Brzo display(0x3C, 5, 4); SSD1306Brzo display(0x3C, 4, 5); //oled display w/ address 0x3C with SDA on GPIO4 and SCL on GPIO5 //address == offset
void demo();
WiFiClient client;
ESP8266WebServer server(80);
Adafruit_MQTT_Client mqtt(&client, "192.168.100.102", 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(){ void setup(){
Serial.begin(115200);
//==DISPLAY INIT== //==DISPLAY INIT==
display.init(); display.init();
display.flipScreenVertically(); display.flipScreenVertically();
display.setContrast(255); display.setContrast(255);
// display.invertDisplay();
display.clear();
display.fillRect(0,0,128,64);
display.display();
delay(3000);
if (!digitalRead(0)) //button
demo(120000);
Serial.begin(115200);
//==WIFI CONNECT== //==WIFI CONNECT==
WiFi.mode(WIFI_STA); WiFi.mode(WIFI_STA);
wifiConnect();
//==READ CONFIG==
if (!SPIFFS.begin())
SPIFFS.format();
if (!readConfig())
defConfig();
//==NTP INIT== //==NTP INIT==
timeClient.begin(); timeClient.begin();
timeClient.setTimeOffset(timeOffset*3600); timeClient.setTimeOffset(10800);
netTasks(); //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.on("/notify", notify);
server.begin();
} }
void loop(){ void loop(){
mainScreen(); if (WiFi.status() != WL_CONNECTED) { //check wifi status
if (((timeClient.getHours()*60 + timeClient.getMinutes()) % beepDelay == 0)&&(timeClient.getSeconds() < 1)&&(!nightMode())){ wifiConnect();
tone(15,1000); }
delay(100); server.handleClient();
noTone(15); MQTT_connect();//check connection and get packets for 0.5s
mqtt.processPackets(500);
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); tone(15,1000);
delay(100); delay(100);
noTone(15); noTone(15);
lastBeep = timeClient.getHours()*60; lastBeep = timeClient.getHours()*60;
netTasks();
// demo(12000);
} }
else { notifyCheck();
delay(500); updateNtp();//update time
} }
checkAlarm();
//====================IN PROGRESS===================
bool notifyCheck(){
File notifyFile = SPIFFS.open("/notify.json", "r");
if (!notifyFile) {
Serial.println("Failed to open notify file");
return false;
} }
void checkAlarm()
{ size_t size = notifyFile.size();
for (int i(0);i<10;i++) if (size > 1024) {
{ Serial.println("Config file size is too large");
if ((timeClient.getHours()*60+timeClient.getMinutes() >= alarms[i])&&(timeClient.getHours()*60+timeClient.getMinutes() - alarms[i] < alarmDuration)&&(alarms[i] != 0)) return false;
{ }
if (alarmStop != alarms[i])
{ // Allocate a buffer to store contents of the file.
std::unique_ptr<char[]> 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.
notifyFile.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;
}
return true;
notifyFile.close();
}
bool testNotifySave() {
StaticJsonBuffer<200> jsonBuffer;
JsonObject& json = jsonBuffer.createObject();
json["text"] = "testNotifySave";//string
json["time"] = "960";//in minutes
File notifyFile = SPIFFS.open("/notify.json", "w");
if (!notifyFile) {
Serial.println("Failed to open notify file for writing");
return false;
}
json.printTo(notifyFile);
notifyFile.close();
return true;
}
void notify() {
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 == "text"){
server.send(200, "text/plain", "notify");
notifyScreen(client_response);
}
}
} else {
server.send(200, "text/plain", "to notify, goto " + String(WiFi.localIP()) + "/edit?text=value");
}
}
void notifyScreen(String n_text) { //display func
while (true) {
display.clear();
if (!nightMode()) { //turn off screen at night
//Center
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(64, 22, n_text);
//progress bar
//top left
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawString(0, 0, timeClient.getFormattedTime());
//top right
// display.setFont(ArialMT_Plain_10);
// display.setTextAlignment(TEXT_ALIGN_RIGHT);
// display.drawString(128, 0, "p:"+String(pressure));
//bottom left
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawString(0, 53, "192.168.100.8");
//bottom right
// display.setFont(ArialMT_Plain_10);
// display.setTextAlignment(TEXT_ALIGN_RIGHT);
// display.drawString(128, 53, "h:"+String(humid)+"%");
//beep beep!
tone(15,750);
delay(100);
noTone(15);
tone(15,900);
delay(100);
noTone(15);
tone(15,1000); tone(15,1000);
delay(100); delay(100);
noTone(15); noTone(15);
delay(100);
tone(15,1000);
delay(100);
noTone(15);
delay(1000);
}
if (!digitalRead(0)) //button
alarmStop = alarms[i];
if (timeClient.getHours()*60+timeClient.getMinutes() - alarms[i] > alarmDuration)//stop current alarm
alarmStop = -1;
}
}
}
void netTasks() {
HTTPClient http;
WiFi.forceSleepWake();
if (WiFi.status() != WL_CONNECTED) {
wifiConnect(false);
}
http.begin(httpAddr+"/inTemp");
if (http.GET() < 0)
return;
inTemp="i:"+http.getString()+"C";
http.end();
http.begin(httpAddr+"/outTemp"); delay(3000);
if (http.GET() < 0)
return;
outTemp="o:"+http.getString()+"C";
http.end();
http.begin(httpAddr+"/humid");
if (http.GET() < 0)
return;
humid="h:"+http.getString()+"%";
http.end();
http.begin(httpAddr+"/pressure");
if (http.GET() < 0)
return;
pressure="p:"+http.getString()+"mBar";
http.end();
updateNtp();
WiFi.disconnect();
} }
display.display();
}
}
//====================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 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<char[]> 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;
configFile.close();
}
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);
configFile.close();
return true;
}
void mainScreen() { void mainScreen() {
display.clear(); display.clear();
if (!nightMode()) {
if (!nightMode()) { //turn off screen at night
int x = (timeClient.getHours()*60+timeClient.getMinutes())/11; int x = (timeClient.getHours()*60+timeClient.getMinutes())/11;
//Time //Time
display.setFont(ArialMT_Plain_24); display.setFont(ArialMT_Plain_24);
@ -125,99 +371,97 @@ void mainScreen() {
display.drawString(64, 22, timeClient.getFormattedTime()); display.drawString(64, 22, timeClient.getFormattedTime());
//progress bar //progress bar
display.drawLine(0,22,x,22); display.drawLine(0,22,x,22);
if (mqttAvail){ //do not show info if mqtt not available
//external temp //top left //external temp //top left
display.setFont(ArialMT_Plain_10); display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_LEFT); display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawString(0, 0, outTemp); display.drawString(0, 0, "o:"+String(outTemp));
//pressure //top right //pressure //top right
display.setFont(ArialMT_Plain_10); display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_RIGHT); display.setTextAlignment(TEXT_ALIGN_RIGHT);
display.drawString(128, 0, pressure); display.drawString(128, 0, "p:"+String(pressure));
//inside temp //bottom left //inside temp //bottom left
display.setFont(ArialMT_Plain_10); display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_LEFT); display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawString(0, 53, inTemp); display.drawString(0, 53, "i:"+String(inTemp));
//humid //bottom right //humid //bottom right
display.setFont(ArialMT_Plain_10); display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_RIGHT); display.setTextAlignment(TEXT_ALIGN_RIGHT);
display.drawString(128, 53, humid); display.drawString(128, 53, "h:"+String(humid)+"%");
} }
display.display(); else {
}
void displayStatus(){
bool run(true);
display.setFont(ArialMT_Plain_10); display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_LEFT); display.setTextAlignment(TEXT_ALIGN_LEFT);
int x(0),y(0); display.drawString(0, 53, "mqtt unavailable");
bool xd(false);//false - right, true - left }
}
while (run) display.display();
{ }
void displayStatus(int state){
display.clear(); display.clear();
if (WiFi.status() != WL_CONNECTED) { if (state == 0) {
display.fillRect(x,y,30,50); display.setFont(ArialMT_Plain_16);
if (x > 128-30) display.setTextAlignment(TEXT_ALIGN_CENTER);
xd = true; display.drawString(64, 22, "Connected!");
if (x < 0)
xd = false;
if (xd) {
x--;
} else {
x++;
}
display.drawString(1, 52, ssid);
} }
if (WiFi.status() == WL_CONNECTED) { if (state == 1) {
run = false; display.setFont(ArialMT_Plain_16);
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(64, 22, "Connecting...");
}
if (state == 2) {
display.setFont(ArialMT_Plain_16);
display.setTextAlignment(TEXT_ALIGN_CENTER);
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");
} }
display.display(); 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() { void updateNtp() {
while (!timeClient.update()) if (lastNtp != timeClient.getHours()) {
Serial.println(timeClient.getHours()); if (timeClient.update())
lastNtp = timeClient.getHours();
}
} }
bool nightMode() { bool nightMode() {
if ((timeClient.getHours() > offTime)||(timeClient.getHours() < onTime)) { if ((timeClient.getHours() > offTime)||(timeClient.getHours() < onTime)) { //turn off screen between loaded time
return true; return true;
} }
else else
return false; return false;
} }
void wifiConnect(bool boot) {
int beginMillis = millis();
WiFi.begin(ssid, password);
displayStatus();
}
void demo(int duration)
{
short xp(0),yp(0),xd(1),yd(1);
unsigned int startTime = millis();
bool run(true);
while (run) {
if ((xp > 128) || (xp < 0))
{
xd = xd * -1;
}
if ((yp > 64) || (yp < 0))
{
yd = yd * -1;
}
xp+=xd;
yp+=yd;
delay(10);
display.clear();
display.fillCircle(xp,yp,10);
display.display();
if (millis() - startTime > duration)
run = false;
}
}

View File

@ -1,7 +0,0 @@
#ifndef ssid_pass_h
#define ssid_pass_h
const char* ssid = "";
const char* password = "";
#endif