Created
May 29, 2022 15:59
-
-
Save inthuriel/f9104d18e6bd9f5bd003dfb9513e91d3 to your computer and use it in GitHub Desktop.
This file contains 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
// required liblaries | |
#include <LiquidCrystal_I2C.h> | |
#include <ESP8266WiFi.h> | |
#include <ESP8266WebServer.h> | |
#include <Adafruit_BME280.h> | |
#include <RTClib.h> | |
#include <uptime_formatter.h> | |
#include <NTPClient.h> | |
#include <WiFiUdp.h> | |
#include <Timezone.h> | |
// predefined constants | |
const char* SSID = ""; | |
const char* WIFI_PASSWORD = ""; | |
const float SEALEVELPRESSURE_HPA = 1013.25; | |
const unsigned int CLOCK_INTERVAL = 1000; | |
const unsigned int SENSOR_INTERVAL = 60000; | |
const unsigned int NTP_INTERVAL = 3600000; | |
const unsigned int REST_PORT = 80; | |
// predefined vars | |
unsigned int display_opt = 0; | |
unsigned long clock_time = 0; | |
unsigned long sensor_time = 0; | |
unsigned long ntp_time = 0; | |
String hostname = "weather-station-" + String(ESP.getChipId(), HEX); | |
TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120}; | |
TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60}; | |
float pressure; | |
float humidity; | |
float temperature; | |
// create timezone object based on predefined rules for Central Europe | |
Timezone central_europe_tz(CEST, CET); | |
// initialize LCD via I2C bus | |
LiquidCrystal_I2C lcd(0x27, 16, 2); | |
// initialize thermometer via I2C bus | |
Adafruit_BME280 bme; | |
// initialize RTC via I2C bus | |
RTC_DS3231 rtc; | |
// initialize web server | |
ESP8266WebServer http_server(REST_PORT); | |
// initialize UDP WiFi instance | |
WiFiUDP ntpUDP; | |
// initialize NTP client via UDP | |
NTPClient ntp_client(ntpUDP, "europe.pool.ntp.org"); | |
// functions headers | |
void api_sensor_readings(); | |
void api_device_status(); | |
void api_base_info(); | |
void api_not_found(); | |
void basic_clock(); | |
void extend_tmp(); | |
void rest_server_routing(); | |
int set_display_opt(int opt); | |
void short_tmp(); | |
void update_time(); | |
void setup() { | |
// initialize pin for button input | |
pinMode(13, INPUT); | |
// initialize LCD, set backlight and clear contents | |
lcd.init(); | |
lcd.backlight(); | |
lcd.clear(); | |
// initialize WiFi connection and set device hostname | |
WiFi.begin(SSID, WIFI_PASSWORD); | |
WiFi.hostname(hostname); | |
// initialize sensor readings | |
bme.begin(0x76); | |
// initialize RTC device | |
rtc.begin(); | |
// display user message about connecting to WiFi network | |
lcd.print("Connecting to "); | |
lcd.setCursor(0, 1); | |
lcd.print(SSID); | |
int i = 0; | |
while (WiFi.status() != WL_CONNECTED) { | |
delay(1000); | |
} | |
// as we are connected to WiFi establish HTTP server | |
// and run NTP client with time update | |
rest_server_routing(); | |
http_server.onNotFound(api_not_found); | |
http_server.begin(); | |
ntp_client.begin(); | |
update_time(); | |
// display user message about initialization completion | |
lcd.clear(); | |
lcd.setCursor(0, 0); | |
lcd.print("Initialized!"); | |
lcd.setCursor(0, 1); | |
lcd.print("IP: "); | |
lcd.print(WiFi.localIP()); | |
delay(1000); | |
// display default message for user | |
lcd.clear(); | |
basic_clock(); | |
short_tmp(); | |
} | |
void loop () { | |
// display clock if proper option was choosen | |
// refres every interval defined in CLOCK_INTERVAL miliseconds | |
if(millis() >= clock_time + CLOCK_INTERVAL){ | |
if (display_opt == 0) { | |
clock_time +=CLOCK_INTERVAL; | |
basic_clock(); | |
} | |
} | |
// display sensor data if proper option was choosen | |
// refres every interval defined in SENSOR_INTERVAL miliseconds | |
if(millis() >= sensor_time + SENSOR_INTERVAL){ | |
if (display_opt == 0) { | |
sensor_time +=SENSOR_INTERVAL; | |
short_tmp(); | |
} | |
} | |
// display extended sensor data if proper option was choosen | |
// refres every interval defined in SENSOR_INTERVAL miliseconds | |
if(millis() >= sensor_time + SENSOR_INTERVAL){ | |
if (display_opt == 1) { | |
sensor_time +=SENSOR_INTERVAL; | |
extend_tmp(); | |
} | |
} | |
// update RTC time settings | |
// refres every interval defined in NTP_INTERVAL miliseconds | |
if(millis() >= ntp_time + NTP_INTERVAL){ | |
ntp_time +=NTP_INTERVAL; | |
update_time(); | |
} | |
// check if touch sensor was touched to change display informations | |
if (digitalRead(13) == HIGH) { | |
int old_display_opt = display_opt; | |
display_opt = set_display_opt(display_opt); | |
if (old_display_opt - display_opt < 0) { | |
lcd.clear(); | |
basic_clock(); | |
short_tmp(); | |
} else { | |
lcd.clear(); | |
extend_tmp(); | |
} | |
} | |
// run HTTP server | |
http_server.handleClient(); | |
} | |
int set_display_opt(int opt) { | |
opt +=1; | |
if (opt > 1) { | |
opt = 0; | |
} | |
return opt; | |
} | |
void update_time() { | |
ntp_client.update(); | |
rtc.adjust(DateTime(central_europe_tz.toLocal(ntp_client.getEpochTime()))); | |
} | |
void basic_clock() { | |
char formatted_date[16]; | |
char sep; | |
DateTime now = rtc.now(); | |
if (now.second() % 2 != 0) { | |
sep = ':'; | |
} else { | |
sep = ' '; | |
} | |
sprintf(formatted_date, "%2d.%02d.%4d %2d%c%02d", now.day(),now.month(), now.year(), now.hour(), sep, now.minute()); | |
lcd.setCursor(0, 0); | |
lcd.print(formatted_date); | |
} | |
void extend_tmp() { | |
char formatted_temp[16]; | |
char formatted_hum[16]; | |
temperature = bme.readTemperature(); | |
pressure = bme.readPressure(); | |
humidity = bme.readHumidity(); | |
sprintf(formatted_temp, "%2.1f *C %4.0f hPa",temperature, round(pressure / 100.0F)); | |
sprintf(formatted_hum, "%4.2f proc.",temperature, humidity); | |
lcd.setCursor(0, 0); | |
lcd.print(formatted_temp); | |
lcd.setCursor(0, 1); | |
lcd.print(formatted_hum); | |
} | |
void short_tmp() { | |
char formatted_temp[16]; | |
temperature = bme.readTemperature(); | |
pressure = bme.readPressure(); | |
humidity = bme.readHumidity(); | |
sprintf(formatted_temp, "%2.1f *C %4.0f hPa",temperature, round(pressure / 100.0F)); | |
lcd.setCursor(0, 1); | |
lcd.print(formatted_temp); | |
} | |
void api_sensor_readings() { | |
char rest_response[128]; | |
DateTime now = rtc.now(); | |
int currenttimestamp = now.unixtime(); | |
sprintf(rest_response, "{\"environment\":{\"temperature\": %f, \"humidity\": %f, \"pressure\": %f}, \"timestamp\": %d}", temperature, humidity, pressure, currenttimestamp); | |
http_server.send(200, "text/json", rest_response); | |
} | |
void api_device_status() { | |
char rest_response[1024]; | |
DateTime now = rtc.now(); | |
int currenttimestamp = now.unixtime(); | |
String uptime = uptime_formatter::getUptime() + ""; | |
String wifi_status; | |
if (WiFi.status() == WL_CONNECTED) { | |
wifi_status = "connected"; | |
} else { | |
wifi_status = "disconnected"; | |
} | |
sprintf(rest_response, "{\"status\":{\"wlan-status\": \"%s\", \"ssid\": \"%s\", \"hostname\":\"%s\", \"ip\": \"%s\", \"uptime\": \"%s\"}, \"timestamp\": %d}", wifi_status.c_str(), SSID, hostname.c_str(), WiFi.localIP().toString().c_str(), uptime.c_str(), currenttimestamp); | |
http_server.send(200, "text/json", rest_response); | |
} | |
void api_base_info() { | |
char rest_response[1024]; | |
DateTime now = rtc.now(); | |
int currenttimestamp = now.unixtime(); | |
sprintf(rest_response, "{\"api\":{\"v1\": {\"endpoints\": [{\"name\": \"sensor readings\", \"path\": \"/api/v1/sensor\"}, {\"name\": \"device status\", \"path\": \"/api/v1/status\"}]}}, \"timestamp\": %d}", currenttimestamp); | |
http_server.send(200, "text/json", rest_response); | |
} | |
void api_not_found() { | |
char rest_response[1024]; | |
DateTime now = rtc.now(); | |
int currenttimestamp = now.unixtime(); | |
sprintf(rest_response, "{\"message\": \"Endpoint %s not found\", \"type\": \"error\", \"code\": 404, \"timestamp\": %d}", http_server.uri(), currenttimestamp); | |
http_server.send(404, "text/json", rest_response); | |
} | |
void rest_server_routing() { | |
http_server.on(("/"), HTTP_GET, api_base_info); | |
http_server.on(("/api/v1/sensor"), HTTP_GET, api_sensor_readings); | |
http_server.on(("/api/v1/status"), HTTP_GET, api_device_status); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment