517 lines
24 KiB
C++
517 lines
24 KiB
C++
#include "config.h"
|
|
#include <ESP8266WiFi.h>
|
|
#include <ESP8266HTTPClient.h>
|
|
#include <ArduinoJson.h>
|
|
#include <Wire.h>
|
|
#include <NTPClient.h>
|
|
#include <WiFiUdp.h>
|
|
#include <Adafruit_GFX.h>
|
|
#include <Adafruit_SSD1306.h>
|
|
#include <EEPROM.h>
|
|
#include "bitmaps.h"
|
|
#include "netman.h"
|
|
|
|
// Init display and wifi
|
|
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
|
|
netman netman(display);
|
|
WiFiClient client;
|
|
|
|
// Define NTP Client to get time
|
|
WiFiUDP ntpUDP;
|
|
NTPClient timeClient(ntpUDP, "pool.ntp.org", 3600, 43200000);
|
|
|
|
// Define these in config.h
|
|
const String Location = LOCATION;
|
|
const String API_Key = API_KEY;
|
|
int displayBrightness = 205;
|
|
|
|
void beep(int buzz) {
|
|
tone(PIN_BUZZER, buzz, 100);
|
|
delay(100);
|
|
noTone(PIN_BUZZER);
|
|
}
|
|
|
|
void initSystems() {
|
|
pinMode(PIN_BTN_L, INPUT);
|
|
pinMode(PIN_BTN_M, INPUT);
|
|
pinMode(PIN_BTN_R, INPUT);
|
|
pinMode(PIN_BUZZER, OUTPUT);
|
|
pinMode(LED_BUILTIN, OUTPUT);
|
|
digitalWrite(LED_BUILTIN, HIGH);
|
|
EEPROM.begin(512);
|
|
Wire.begin(); // Initialize I2C
|
|
Wire.setClock(400000L); // Set I2C to Fast Mode (400 kHz)
|
|
display.ssd1306_command(SSD1306_SETCONTRAST);
|
|
display.ssd1306_command(displayBrightness); // Value between 0 and 255
|
|
// Initialize the SSD1306 display
|
|
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Adjust I2C address if needed
|
|
for(;;); // Don't proceed, loop forever
|
|
}
|
|
|
|
// Rotate the display 180 degrees
|
|
display.setRotation(2);
|
|
|
|
// Clear the display buffer
|
|
display.clearDisplay();
|
|
display.setTextSize(1);
|
|
display.setTextColor(WHITE);
|
|
display.setCursor(0, 0);
|
|
display.display();
|
|
}
|
|
|
|
// Timers for dynamic updates
|
|
unsigned long lastWeatherUpdate = 0;
|
|
unsigned long lastDisplayOverride = 0;
|
|
const unsigned long weatherUpdateInterval = 2700000; // 45 minutes in milliseconds
|
|
const unsigned long displayOverrideTimeout = 120000; // 2 minutes in milliseconds
|
|
bool is_display_off = false;
|
|
bool display_override = false;
|
|
|
|
void commonButtonHandler() {
|
|
unsigned long currentMillis = millis();
|
|
static unsigned long leftPressStart = 0;
|
|
static unsigned long middlePressStart = 0;
|
|
static unsigned long rightPressStart = 0;
|
|
|
|
static bool leftBeeped = false;
|
|
static bool middleBeeped = false;
|
|
static bool rightBeeped = false;
|
|
|
|
bool leftPressed = (digitalRead(PIN_BTN_L) == HIGH);
|
|
bool middlePressed = (digitalRead(PIN_BTN_M) == HIGH);
|
|
bool rightPressed = (digitalRead(PIN_BTN_R) == HIGH);
|
|
|
|
// Short press detection
|
|
if (leftPressed) {
|
|
if ((currentMillis - leftPressStart > 50)) { // Debounce delay
|
|
if (!leftBeeped) {
|
|
beep(1000); // Play beep sound
|
|
leftBeeped = true; // Set beeped state
|
|
displayBrightness -= 50;
|
|
if (displayBrightness < 10 ) {
|
|
displayBrightness = 255;
|
|
}
|
|
// Send the command to set the contrast
|
|
display.ssd1306_command(SSD1306_SETCONTRAST);
|
|
display.ssd1306_command(displayBrightness); // Value between 0 and 255
|
|
// Handle left short press action here
|
|
}
|
|
}
|
|
} else {
|
|
leftPressStart = currentMillis; // Reset the timer if button is not pressed
|
|
leftBeeped = false; // Reset beeped state
|
|
}
|
|
|
|
if (middlePressed) {
|
|
if ((currentMillis - middlePressStart > 50)) { // Debounce delay
|
|
if (!middleBeeped) {
|
|
beep(1000); // Play beep sound
|
|
middleBeeped = true; // Set beeped state
|
|
lastWeatherUpdate = millis() + weatherUpdateInterval + 1;
|
|
// Handle middle short press action here
|
|
}
|
|
}
|
|
} else {
|
|
middlePressStart = currentMillis; // Reset the timer if button is not pressed
|
|
middleBeeped = false; // Reset beeped state
|
|
}
|
|
|
|
if (rightPressed) {
|
|
if ((currentMillis - rightPressStart > 50)) { // Debounce delay
|
|
if (!rightBeeped) {
|
|
beep(1000); // Play beep sound
|
|
rightBeeped = true; // Set beeped state
|
|
if (is_display_off) {
|
|
display.ssd1306_command(SSD1306_DISPLAYON); // Turn on display
|
|
is_display_off = false;
|
|
display_override = true;
|
|
beep(1300);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
rightPressStart = currentMillis; // Reset the timer if button is not pressed
|
|
rightBeeped = false; // Reset beeped state
|
|
}
|
|
|
|
// Long press detection
|
|
if (leftPressed && (currentMillis - leftPressStart > 2000)) {
|
|
if (!leftBeeped) {
|
|
beep(1000); // Play beep sound
|
|
leftBeeped = true; // Set beeped state
|
|
// Handle left long press action here
|
|
}
|
|
}
|
|
|
|
if (middlePressed && (currentMillis - middlePressStart > 2000)) {
|
|
if (!middleBeeped) {
|
|
beep(1000); // Play beep sound
|
|
middleBeeped = true; // Set beeped state
|
|
// Handle middle long press action here
|
|
}
|
|
}
|
|
|
|
if (rightPressed && (currentMillis - rightPressStart > 2000)) {
|
|
if (!is_display_off) {
|
|
beep(1300);
|
|
display.ssd1306_command(SSD1306_DISPLAYOFF); // Turn off display
|
|
is_display_off = true;
|
|
display_override = false;
|
|
beep(1000);
|
|
}
|
|
}
|
|
|
|
// Combination of Left and Middle long press
|
|
if (leftPressed && middlePressed &&
|
|
(currentMillis - leftPressStart > 2000) && (currentMillis - middlePressStart > 2000)) {
|
|
ESP.restart();
|
|
}
|
|
}
|
|
|
|
void powerSaveCheck() {
|
|
int currentHour = timeClient.getHours();
|
|
if ((currentHour >= 22 || currentHour < 8) && !is_display_off && !display_override) {
|
|
display.ssd1306_command(SSD1306_DISPLAYOFF); // Turn off display for power-saving
|
|
is_display_off = true;
|
|
}
|
|
}
|
|
|
|
float prevTemperature = 0.0;
|
|
int prevHumidity = 0;
|
|
float prevPressure = 0.0;
|
|
float prevWindSpeed = 0.0;
|
|
|
|
void saveWeatherData() {
|
|
|
|
// Store float values as bytes (4 bytes for each float)
|
|
EEPROM.put(0, prevTemperature);
|
|
EEPROM.put(4, prevHumidity);
|
|
EEPROM.put(8, prevPressure);
|
|
EEPROM.put(12, prevWindSpeed);
|
|
|
|
// Commit changes to EEPROM
|
|
EEPROM.commit(); // Write changes to flash
|
|
}
|
|
|
|
void loadWeatherData() {
|
|
// Read the data from EEPROM (addresses correspond to where they were saved)
|
|
|
|
EEPROM.get(0, prevTemperature);
|
|
EEPROM.get(4, prevHumidity);
|
|
EEPROM.get(8, prevPressure);
|
|
EEPROM.get(12, prevWindSpeed);
|
|
}
|
|
|
|
int icon = 0;
|
|
String weatherState;
|
|
float temperature;
|
|
int humidity;
|
|
float pressure;
|
|
float wind_speed;
|
|
int forecastIcons[3];
|
|
int currentYear, currentMonth, currentDay;
|
|
|
|
// Function to get a random message from an array
|
|
String getRandomMessage(const String messages[], int size) {
|
|
return messages[random(size)];
|
|
}
|
|
|
|
String generateTrendMessage(float current, float previous, const String& parameter) {
|
|
if (current > previous) {
|
|
return parameter + " rising ";
|
|
} else if (current < previous) {
|
|
return parameter + " falling ";
|
|
} else {
|
|
return parameter + " stable ";
|
|
}
|
|
}
|
|
|
|
bool fetchWeatherData() {
|
|
// Get current time
|
|
time_t epochTime = timeClient.getEpochTime();
|
|
struct tm *ptm = gmtime((time_t *)&epochTime);
|
|
currentDay = ptm->tm_mday;
|
|
currentMonth = ptm->tm_mon + 1;
|
|
currentYear = ptm->tm_year + 1900;
|
|
HTTPClient http;
|
|
|
|
// Request current weather
|
|
for (int attempt = 0; attempt < 3; attempt++) {
|
|
http.begin(client, "http://api.openweathermap.org/data/2.5/weather?q=" + Location + "&APPID=" + API_Key);
|
|
int httpCode = http.GET();
|
|
if (httpCode > 0) {
|
|
String payload = http.getString();
|
|
DynamicJsonDocument doc(1024);
|
|
|
|
if (!deserializeJson(doc, payload)) {
|
|
String mainWeather = doc["weather"][0]["main"].as<String>();
|
|
temperature = doc["main"]["temp"].as<float>() - 273.15;
|
|
humidity = doc["main"]["humidity"];
|
|
pressure = doc["main"]["pressure"].as<float>() / 1000;
|
|
wind_speed = doc["wind"]["speed"].as<float>();
|
|
if (mainWeather == "Clear") {
|
|
String clearMessages[] = {
|
|
"All systems nominal. Atmospheric clearance detected.",
|
|
"Clear skies confirmed. Solar energy levels stable for ship systems.",
|
|
"Sky conditions optimal for external scan. Proceed with visual sweep.",
|
|
"Visibility restored. All monitoring systems active and secure.",
|
|
"Open space ahead. Prepare for normal operations.",
|
|
"Solar reflection steady. Systems running at full capacity.",
|
|
"Clear. No interference detected. Navigation optimal.",
|
|
"Visible space clear. Proceed with standard operations.",
|
|
"Skies unclouded. No anomalies detected.",
|
|
"No obstructions in sight. Navigation systems operating normally.",
|
|
"Bright and clear skies. Optimal conditions for long-range communication.",
|
|
"Perfect visibility. All systems functioning within expected parameters.",
|
|
"Clear and stable. No impact on external activities.",
|
|
"The sky is free of disturbances. Proceed with confidence.",
|
|
"Atmospheric conditions steady. All sensors reporting normal."
|
|
};
|
|
weatherState = generateTrendMessage(temperature, prevTemperature, "Temperature") + generateTrendMessage(pressure, prevPressure, "Atmospheric pressure") + generateTrendMessage(humidity, prevHumidity, "Humidity") + generateTrendMessage(wind_speed, prevWindSpeed, "Wind speed") + getRandomMessage(clearMessages, 15);
|
|
} else if (mainWeather == "Clouds") {
|
|
String cloudMessages[] = {
|
|
"Cloud cover detected. Light interference on visual systems.",
|
|
"Overcast conditions observed.",
|
|
"Shadows overhead. Adjusting sensitivity on light filters.",
|
|
"Moderate cloud formation detected. System performance normal.",
|
|
"Atmospheric interference present. Monitoring light levels.",
|
|
"Cloud coverage rising. Operational impact minimal.",
|
|
"Low-visibility overhead. Preparing for reduced solar input.",
|
|
"Sensors report cloud patterns. Adjusting visibility protocols.",
|
|
"Clouds forming in surrounding space. Adjusting navigational parameters.",
|
|
"Light cloud cover detected. No operational impact expected.",
|
|
"Cloud formation increasing. Visual scan in progress.",
|
|
"Partly cloudy. Visibility reduced, but no immediate danger.",
|
|
"Overcast sky. Sensors adjusting for changing light levels.",
|
|
"Increasing cloud density. Proceeding with caution on exterior tasks.",
|
|
"Cumulus clouds observed. No operational impact anticipated."
|
|
};
|
|
weatherState = generateTrendMessage(temperature, prevTemperature, "Temperature") + generateTrendMessage(pressure, prevPressure, "Atmospheric pressure") + generateTrendMessage(humidity, prevHumidity, "Humidity") + generateTrendMessage(wind_speed, prevWindSpeed, "Wind speed") + getRandomMessage(cloudMessages, 15);
|
|
} else if (mainWeather == "Rain") {
|
|
String rainMessages[] = {
|
|
"Precipitation incoming. Shielding activated.",
|
|
"Rain detected. External moisture levels rising, activating water barriers.",
|
|
"Surface moisture increasing. Prepare for external wet conditions.",
|
|
"Rainstorm detected. External protection systems online.",
|
|
"Raindrops detected. Surface conditions becoming slick.",
|
|
"Incoming water influx. Prepare external surfaces for wet conditions.",
|
|
"Rain detected. Traction systems engaged for slippery terrain.",
|
|
"Wet conditions approaching. Hydration protocols for external units activated.",
|
|
"Raindrops increasing. Proceed with caution on exterior surfaces.",
|
|
"Heavy rain in the vicinity. External equipment may require adjustment.",
|
|
"Intense rain incoming. All systems on standby for moisture management.",
|
|
"Heavy precipitation. Surface traction adjustments being made.",
|
|
"Rainfall intensifying. Navigation systems recalibrating.",
|
|
"Storm-like rain detected. Prepare for potential delays in operations.",
|
|
"Rain approaching. All moisture-sensitive systems under review."
|
|
};
|
|
weatherState = generateTrendMessage(temperature, prevTemperature, "Temperature") + generateTrendMessage(pressure, prevPressure, "Atmospheric pressure") + generateTrendMessage(humidity, prevHumidity, "Humidity") + generateTrendMessage(wind_speed, prevWindSpeed, "Wind speed") + getRandomMessage(rainMessages, 15);
|
|
} else if (mainWeather == "Drizzle") {
|
|
String drizzleMessages[] = {
|
|
"Light drizzle detected. Surface moisture rising, minimal impact.",
|
|
"Low-intensity rain detected. External systems functioning normally.",
|
|
"Fine mist detected. Prepare for minor surface wetting.",
|
|
"Gentle drizzle. Light hydration of external units detected.",
|
|
"Atmospheric moisture levels rising slowly. Proceed with minor caution.",
|
|
"Minor drizzle detected. No immediate impact on operations.",
|
|
"Drizzle detected. Adjusting exterior temperature controls.",
|
|
"Light rain confirmed. Surface conditions remain stable.",
|
|
"Drizzle present. External activity unaffected.",
|
|
"Micro-droplets detected. Surface wetting minimal.",
|
|
"Drizzle increasing. Minimal disruption to operational efficiency.",
|
|
"Light mist falling. Preparing exterior equipment for light moisture.",
|
|
"Slight drizzle detected. Monitoring for potential buildup.",
|
|
"Traces of rain observed. Surface conditioning proceeding normally.",
|
|
"Faint drizzle. No significant effect on operational systems."
|
|
};
|
|
weatherState = generateTrendMessage(temperature, prevTemperature, "Temperature") + generateTrendMessage(pressure, prevPressure, "Atmospheric pressure") + generateTrendMessage(humidity, prevHumidity, "Humidity") + generateTrendMessage(wind_speed, prevWindSpeed, "Wind speed") + getRandomMessage(drizzleMessages, 15);
|
|
} else if (mainWeather == "Thunderstorm") {
|
|
String thunderstormMessages[] = {
|
|
"Warning: Severe storm approaching. High-voltage hazard detected.",
|
|
"Electrical storm detected in proximity. Shielding and surge protection engaged.",
|
|
"Thunderstorm alert: Prepare for sudden power fluctuations.",
|
|
"Storm in progress. Lightning detected. Surge protection active.",
|
|
"Electrical interference detected. Recalibrating external sensors.",
|
|
"Thunderstorm imminent. High-energy levels detected. Activating surge protocols.",
|
|
"Power surge imminent. Warning: high-voltage storm detected.",
|
|
"Electrical storm approaching. Brace for system disturbances.",
|
|
"Warning: Lightning detected. Secure sensitive systems immediately.",
|
|
"Severe atmospheric storm approaching. Power systems primed for protection.",
|
|
"Lightning detected. Power surge prevention systems activated.",
|
|
"Thunderstorm conditions intensifying. All external systems under review.",
|
|
"Severe electrical interference. Adjusting system tolerance for spikes.",
|
|
"Warning: Storm detected. Power fluctuations expected.",
|
|
"Thunderstorm alert. Lightning strike imminent. Systems on full defense."
|
|
};
|
|
weatherState = generateTrendMessage(temperature, prevTemperature, "Temperature") + generateTrendMessage(pressure, prevPressure, "Atmospheric pressure") + generateTrendMessage(humidity, prevHumidity, "Humidity") + generateTrendMessage(wind_speed, prevWindSpeed, "Wind speed") + getRandomMessage(thunderstormMessages, 15);
|
|
} else if (mainWeather == "Snow") {
|
|
String snowMessages[] = {
|
|
"Cryogenic conditions detected. Snowfall in progress.",
|
|
"Snow accumulation imminent. External traction systems engaged.",
|
|
"Freezing precipitation confirmed. Temperature control systems adjusting.",
|
|
"Snow falling. Low-traction surfaces detected. Proceed with caution.",
|
|
"Heavy snowfall recorded. Thermal systems operating at full capacity.",
|
|
"Snowstorm imminent. Prepare for reduced external mobility.",
|
|
"Temperature drop confirmed. Snow accumulation expected.",
|
|
"Snow detected. De-icing systems online.",
|
|
"Cryogenic particles in atmosphere. Surface stability compromised.",
|
|
"Snowfall detected. All external movement restricted.",
|
|
"Snow level increasing. Traction systems are in full effect.",
|
|
"Blizzard conditions approaching. Prepare for limited visibility.",
|
|
"Heavy snow confirmed. Adjusting exterior systems for extreme conditions.",
|
|
"Low-temperature alert. Ice accumulation expected.",
|
|
"Snowstorm detected. Proceed with extreme caution on external surfaces."
|
|
};
|
|
weatherState = generateTrendMessage(temperature, prevTemperature, "Temperature") + generateTrendMessage(pressure, prevPressure, "Atmospheric pressure") + generateTrendMessage(humidity, prevHumidity, "Humidity") + generateTrendMessage(wind_speed, prevWindSpeed, "Wind speed") + getRandomMessage(snowMessages, 15);
|
|
} else if (mainWeather == "Mist" || mainWeather == "Fog") {
|
|
String mistMessages[] = {
|
|
"Low-visibility conditions. Activate infrared scanning systems.",
|
|
"Fog detected. Navigation systems recalibrating for low-visibility operation.",
|
|
"Atmospheric opacity confirmed. Proceed with caution at reduced speed.",
|
|
"Dense mist detected. Visibility dropped to critical levels.",
|
|
"Fog levels increasing. Adjusting pathfinding parameters for accuracy.",
|
|
"Dense fog detected. Slowing navigation to safe speeds.",
|
|
"Increased fog density. Visual systems recalibrated.",
|
|
"Low visibility confirmed. Proceed with extreme caution.",
|
|
"Mist detected in sector. Visual enhancement systems engaged.",
|
|
"Fog detected. Reduced visibility affecting sensor accuracy.",
|
|
"Thick fog detected. External systems recalibrating for safety.",
|
|
"Reduced visibility confirmed. Navigating with extreme care.",
|
|
"Mist conditions detected. Heightened caution in exterior operations.",
|
|
"Fog rising in vicinity. Adjusting navigational parameters for safe course.",
|
|
"Low-visibility conditions. Monitoring environment closely."
|
|
};
|
|
weatherState = generateTrendMessage(temperature, prevTemperature, "Temperature") + generateTrendMessage(pressure, prevPressure, "Atmospheric pressure") + generateTrendMessage(humidity, prevHumidity, "Humidity") + generateTrendMessage(wind_speed, prevWindSpeed, "Wind speed") + getRandomMessage(mistMessages, 15);
|
|
} else {
|
|
weatherState = generateTrendMessage(temperature, prevTemperature, "Temperature") + generateTrendMessage(pressure, prevPressure, "Atmospheric pressure") + generateTrendMessage(humidity, prevHumidity, "Humidity") + generateTrendMessage(wind_speed, prevWindSpeed, "Wind speed") + "Unspecified weather anomaly detected. Monitoring closely.";
|
|
}
|
|
prevTemperature = temperature;
|
|
prevHumidity = humidity;
|
|
prevPressure = pressure;
|
|
prevWindSpeed = wind_speed;
|
|
saveWeatherData();
|
|
http.end();
|
|
break;
|
|
}
|
|
}
|
|
delay(1000); // Retry after 1 second
|
|
}
|
|
|
|
// Request forecast
|
|
for (int attempt = 0; attempt < 3; attempt++) {
|
|
http.begin(client, "http://api.openweathermap.org/data/2.5/forecast?q=" + Location + "&APPID=" + API_Key + "&cnt=3");
|
|
int httpCode = http.GET();
|
|
if (httpCode > 0) {
|
|
String payload = http.getString();
|
|
DynamicJsonDocument forecastDoc(1024);
|
|
|
|
if (!deserializeJson(forecastDoc, payload)) {
|
|
for (int day = 0; day <= 2; day++) {
|
|
int state = forecastDoc["list"][day]["weather"][0]["id"];
|
|
|
|
if (state >= 200 && state <= 232) forecastIcons[day] = 6; // Thunderstorm
|
|
else if (state >= 300 && state <= 321) forecastIcons[day] = 5; // Drizzle
|
|
else if (state >= 500 && state <= 531) forecastIcons[day] = 3; // Rain
|
|
else if (state >= 600 && state <= 622) forecastIcons[day] = 4; // Snow
|
|
else if (state >= 701 && state <= 781) forecastIcons[day] = 2; // Mist
|
|
else if (state == 800) forecastIcons[day] = 0; // Clear
|
|
else if (state >= 801 && state <= 804) forecastIcons[day] = 1; // Clouds
|
|
else forecastIcons[day] = 0;
|
|
}
|
|
http.end();
|
|
return true;
|
|
}
|
|
}
|
|
delay(1000); // Retry after 1 second
|
|
}
|
|
|
|
return false; // Return false if data fetch fails
|
|
}
|
|
|
|
int scrollPos = SCREEN_WIDTH; // Global variable to keep track of the scroll position
|
|
unsigned long lastScrollTime = 0; // To control the scroll speed
|
|
const int scrollDelay = 80; // Delay in milliseconds between scroll updates
|
|
|
|
void displayWeatherData() {
|
|
display.clearDisplay();
|
|
display.setTextSize(1);
|
|
display.setCursor(0, 0);
|
|
display.printf("%d-%d-%d\r\n", currentYear, currentMonth, currentDay);
|
|
display.setCursor(0, 9);
|
|
display.printf("%s", Location.c_str());
|
|
|
|
int stateWidth = strlen(weatherState.c_str()) * 12; // Approximate width of the status text in pixels
|
|
|
|
// Clear the area for the file name to avoid overlap
|
|
display.fillRect(0, 21, SCREEN_WIDTH, 11, BLACK);
|
|
|
|
// Scroll the text to the left
|
|
if (!is_display_off) {
|
|
if (millis() - lastScrollTime > scrollDelay) {
|
|
// Update scroll position
|
|
scrollPos -= 5; // Move left by 1 pixel each time
|
|
|
|
lastScrollTime = millis();
|
|
|
|
// If the text has completely scrolled off, reset scroll position to start from the right
|
|
if (scrollPos < -stateWidth) {
|
|
scrollPos = SCREEN_WIDTH;
|
|
}
|
|
}
|
|
}
|
|
// Draw the file name with current scroll position
|
|
display.setTextSize(2);
|
|
display.setCursor(scrollPos, 21);
|
|
display.print(weatherState);
|
|
// Clear the area for "Time left" display before printing
|
|
display.fillRect(0, 37, SCREEN_WIDTH, 27, BLACK); // Clear area for "Time left"
|
|
display.setCursor(0, 44);
|
|
display.setTextSize(1);
|
|
display.printf(" %5.2f C %d%%\r\n", temperature, humidity);
|
|
display.drawRect(43, 44, 3, 3, WHITE); // Degree symbol
|
|
|
|
display.setCursor(0, 55);
|
|
display.printf(" %.3fbar %.1fm/s \r\n", pressure, wind_speed);
|
|
display.drawLine(0, 18, 127, 18, 1);
|
|
display.drawLine(65, 18, 65, 0, 1);
|
|
display.drawLine(0, 40, 127, 40, 1);
|
|
|
|
display.drawBitmap(0, 42, temperature_icon, 10, 10, WHITE);
|
|
display.drawBitmap(74, 42, humidity_icon, 10, 10, WHITE);
|
|
display.drawBitmap(0, 54, pressure_icon, 10, 10, WHITE);
|
|
display.drawBitmap(74, 54, wind_icon, 10, 10, WHITE);
|
|
|
|
int pos = 69;
|
|
for (int i = 0; i < 3; i++) {
|
|
display.drawBitmap(pos, 0, bitmap_icons[forecastIcons[i]], 16, 16, WHITE);
|
|
pos += 20;
|
|
}
|
|
|
|
display.display();
|
|
}
|
|
|
|
void setup(void) {
|
|
initSystems();
|
|
netman.start();
|
|
timeClient.begin();
|
|
timeClient.update();
|
|
loadWeatherData();
|
|
fetchWeatherData();
|
|
}
|
|
|
|
void loop() {
|
|
timeClient.update();
|
|
commonButtonHandler();
|
|
displayWeatherData();
|
|
if (display_override && (millis() - lastDisplayOverride > displayOverrideTimeout)){
|
|
display_override = false;
|
|
lastDisplayOverride = millis();
|
|
}
|
|
if (!is_display_off && (millis() - lastWeatherUpdate > weatherUpdateInterval)) {
|
|
fetchWeatherData();
|
|
lastWeatherUpdate = millis();
|
|
scrollPos = SCREEN_WIDTH;
|
|
}
|
|
powerSaveCheck();
|
|
}
|