added internet time which is shown in the main first screen
This commit is contained in:
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef INTERNET_TIME_H
|
||||||
|
#define INTERNET_TIME_H
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
struct InternetTimeInfo
|
||||||
|
{
|
||||||
|
bool valid;
|
||||||
|
uint16_t year;
|
||||||
|
uint8_t month;
|
||||||
|
uint8_t day;
|
||||||
|
uint8_t hour;
|
||||||
|
uint8_t minute;
|
||||||
|
};
|
||||||
|
|
||||||
|
class InternetTime
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InternetTime();
|
||||||
|
void update(unsigned long now, bool wifiConnected);
|
||||||
|
InternetTimeInfo info() const;
|
||||||
|
bool consumeDirty();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void fetch(unsigned long now);
|
||||||
|
void updateCurrentTime(unsigned long now);
|
||||||
|
InternetTimeInfo infoFromEpoch(unsigned long epoch) const;
|
||||||
|
|
||||||
|
unsigned long lastEpoch_;
|
||||||
|
unsigned long lastSyncMillis_;
|
||||||
|
unsigned long nextAttempt_;
|
||||||
|
InternetTimeInfo current_;
|
||||||
|
bool dirty_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
+3
-1
@@ -4,9 +4,11 @@
|
|||||||
#include <U8g2lib.h>
|
#include <U8g2lib.h>
|
||||||
|
|
||||||
#include "am2302_sensor.h"
|
#include "am2302_sensor.h"
|
||||||
|
#include "internet_time.h"
|
||||||
#include "wifi_connection.h"
|
#include "wifi_connection.h"
|
||||||
|
|
||||||
void drawScreen1(U8G2 &u8g2);
|
void setInternetTimeInfo(InternetTimeInfo timeInfo);
|
||||||
|
void drawTimeScreen(U8G2 &u8g2);
|
||||||
void drawHelloWorldScreen(U8G2 &u8g2);
|
void drawHelloWorldScreen(U8G2 &u8g2);
|
||||||
void drawInternetConnectionScreen(U8G2 &u8g2, WifiConnectionInfo wifiInfo);
|
void drawInternetConnectionScreen(U8G2 &u8g2, WifiConnectionInfo wifiInfo);
|
||||||
void setEnvironmentReading(Am2302Reading reading);
|
void setEnvironmentReading(Am2302Reading reading);
|
||||||
|
|||||||
@@ -4,4 +4,7 @@
|
|||||||
const char WIFI_SSID[] = "your-wifi-name";
|
const char WIFI_SSID[] = "your-wifi-name";
|
||||||
const char WIFI_PASSWORD[] = "your-wifi-password";
|
const char WIFI_PASSWORD[] = "your-wifi-password";
|
||||||
|
|
||||||
|
// Offset from UTC in seconds. Examples: Finland winter 7200, Finland summer 10800.
|
||||||
|
#define TIME_UTC_OFFSET_SECONDS 0
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,142 @@
|
|||||||
|
#include "internet_time.h"
|
||||||
|
|
||||||
|
#include <WiFi101.h>
|
||||||
|
|
||||||
|
#include "wifi_credentials.h"
|
||||||
|
|
||||||
|
#ifndef TIME_UTC_OFFSET_SECONDS
|
||||||
|
#define TIME_UTC_OFFSET_SECONDS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
const unsigned long retryInterval = 15000;
|
||||||
|
const unsigned long refreshInterval = 3600000;
|
||||||
|
const unsigned long secondsPerDay = 86400;
|
||||||
|
|
||||||
|
bool isLeapYear(uint16_t year)
|
||||||
|
{
|
||||||
|
return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t daysInMonth(uint16_t year, uint8_t month)
|
||||||
|
{
|
||||||
|
const uint8_t days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||||
|
if (month == 2 && isLeapYear(year)) {
|
||||||
|
return 29;
|
||||||
|
}
|
||||||
|
return days[month - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long applyTimeOffset(unsigned long epoch)
|
||||||
|
{
|
||||||
|
if (TIME_UTC_OFFSET_SECONDS >= 0) {
|
||||||
|
return epoch + TIME_UTC_OFFSET_SECONDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned long offset = static_cast<unsigned long>(-TIME_UTC_OFFSET_SECONDS);
|
||||||
|
return epoch > offset ? epoch - offset : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InternetTime::InternetTime()
|
||||||
|
: lastEpoch_(0),
|
||||||
|
lastSyncMillis_(0),
|
||||||
|
nextAttempt_(0),
|
||||||
|
current_({false, 0, 0, 0, 0, 0}),
|
||||||
|
dirty_(true) {}
|
||||||
|
|
||||||
|
void InternetTime::update(unsigned long now, bool wifiConnected)
|
||||||
|
{
|
||||||
|
if (current_.valid) {
|
||||||
|
updateCurrentTime(now);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wifiConnected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (now >= nextAttempt_) {
|
||||||
|
fetch(now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InternetTimeInfo InternetTime::info() const
|
||||||
|
{
|
||||||
|
return current_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InternetTime::consumeDirty()
|
||||||
|
{
|
||||||
|
const bool d = dirty_;
|
||||||
|
dirty_ = false;
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InternetTime::fetch(unsigned long now)
|
||||||
|
{
|
||||||
|
const unsigned long epoch = WiFi.getTime();
|
||||||
|
nextAttempt_ = now + retryInterval;
|
||||||
|
|
||||||
|
if (epoch == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastEpoch_ = epoch;
|
||||||
|
lastSyncMillis_ = now;
|
||||||
|
nextAttempt_ = now + refreshInterval;
|
||||||
|
updateCurrentTime(now);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InternetTime::updateCurrentTime(unsigned long now)
|
||||||
|
{
|
||||||
|
const unsigned long elapsedSeconds = (now - lastSyncMillis_) / 1000;
|
||||||
|
const InternetTimeInfo updated = infoFromEpoch(lastEpoch_ + elapsedSeconds);
|
||||||
|
|
||||||
|
if (!current_.valid ||
|
||||||
|
current_.year != updated.year ||
|
||||||
|
current_.month != updated.month ||
|
||||||
|
current_.day != updated.day ||
|
||||||
|
current_.hour != updated.hour ||
|
||||||
|
current_.minute != updated.minute) {
|
||||||
|
current_ = updated;
|
||||||
|
dirty_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InternetTimeInfo InternetTime::infoFromEpoch(unsigned long epoch) const
|
||||||
|
{
|
||||||
|
unsigned long adjustedEpoch = applyTimeOffset(epoch);
|
||||||
|
unsigned long days = adjustedEpoch / secondsPerDay;
|
||||||
|
unsigned long secondsToday = adjustedEpoch % secondsPerDay;
|
||||||
|
|
||||||
|
uint16_t year = 1970;
|
||||||
|
while (true) {
|
||||||
|
const uint16_t yearDays = isLeapYear(year) ? 366 : 365;
|
||||||
|
if (days < yearDays) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
days -= yearDays;
|
||||||
|
year++;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t month = 1;
|
||||||
|
while (true) {
|
||||||
|
const uint8_t monthDays = daysInMonth(year, month);
|
||||||
|
if (days < monthDays) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
days -= monthDays;
|
||||||
|
month++;
|
||||||
|
}
|
||||||
|
|
||||||
|
InternetTimeInfo info = {
|
||||||
|
true,
|
||||||
|
year,
|
||||||
|
month,
|
||||||
|
static_cast<uint8_t>(days + 1),
|
||||||
|
static_cast<uint8_t>(secondsToday / 3600),
|
||||||
|
static_cast<uint8_t>((secondsToday % 3600) / 60)
|
||||||
|
};
|
||||||
|
return info;
|
||||||
|
}
|
||||||
+11
-1
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "am2302_sensor.h"
|
#include "am2302_sensor.h"
|
||||||
#include "carousel.h"
|
#include "carousel.h"
|
||||||
|
#include "internet_time.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "screens.h"
|
#include "screens.h"
|
||||||
#include "wifi_connection.h"
|
#include "wifi_connection.h"
|
||||||
@@ -16,6 +17,7 @@ uint8_t buttonNext = A4;
|
|||||||
uint8_t buttonSelect = A5;
|
uint8_t buttonSelect = A5;
|
||||||
Am2302Sensor am2302(A3);
|
Am2302Sensor am2302(A3);
|
||||||
WifiConnection wifiConnection;
|
WifiConnection wifiConnection;
|
||||||
|
InternetTime internetTime;
|
||||||
|
|
||||||
enum class AppMode
|
enum class AppMode
|
||||||
{
|
{
|
||||||
@@ -26,7 +28,7 @@ enum class AppMode
|
|||||||
};
|
};
|
||||||
|
|
||||||
Screen screens[] = {
|
Screen screens[] = {
|
||||||
{ drawScreen1 },
|
{ drawTimeScreen },
|
||||||
{ drawEnvironmentScreen },
|
{ drawEnvironmentScreen },
|
||||||
{ drawWeatherIconScreen }
|
{ drawWeatherIconScreen }
|
||||||
};
|
};
|
||||||
@@ -142,6 +144,14 @@ void drawActiveView()
|
|||||||
void loop(){
|
void loop(){
|
||||||
const unsigned long now = millis();
|
const unsigned long now = millis();
|
||||||
wifiConnection.update(now);
|
wifiConnection.update(now);
|
||||||
|
internetTime.update(now, wifiConnection.info().connected);
|
||||||
|
|
||||||
|
if (internetTime.consumeDirty()) {
|
||||||
|
setInternetTimeInfo(internetTime.info());
|
||||||
|
if (appMode == AppMode::Carousel) {
|
||||||
|
carousel.requestRedraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (appMode == AppMode::Carousel) {
|
if (appMode == AppMode::Carousel) {
|
||||||
carousel.update(now);
|
carousel.update(now);
|
||||||
|
|||||||
+35
-3
@@ -3,6 +3,15 @@
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
Am2302Reading environmentReading = {0.0F, 0.0F, false};
|
Am2302Reading environmentReading = {0.0F, 0.0F, false};
|
||||||
|
InternetTimeInfo internetTimeInfo = {false, 0, 0, 0, 0, 0};
|
||||||
|
|
||||||
|
void printTwoDigits(U8G2 &u8g2, uint8_t value)
|
||||||
|
{
|
||||||
|
if (value < 10) {
|
||||||
|
u8g2.print("0");
|
||||||
|
}
|
||||||
|
u8g2.print(value);
|
||||||
|
}
|
||||||
|
|
||||||
void drawSun(U8G2 &u8g2, uint8_t x, uint8_t y)
|
void drawSun(U8G2 &u8g2, uint8_t x, uint8_t y)
|
||||||
{
|
{
|
||||||
@@ -27,10 +36,33 @@ void drawCloud(U8G2 &u8g2, uint8_t x, uint8_t y)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawScreen1(U8G2 &u8g2)
|
void setInternetTimeInfo(InternetTimeInfo timeInfo)
|
||||||
{
|
{
|
||||||
u8g2.setFont(u8g2_font_ncenB14_tr);
|
internetTimeInfo = timeInfo;
|
||||||
u8g2.drawStr(0, 20, "Screen 1");
|
}
|
||||||
|
|
||||||
|
void drawTimeScreen(U8G2 &u8g2)
|
||||||
|
{
|
||||||
|
if (!internetTimeInfo.valid) {
|
||||||
|
u8g2.setFont(u8g2_font_6x12_tr);
|
||||||
|
u8g2.drawStr(0, 24, "Time has not");
|
||||||
|
u8g2.drawStr(0, 40, "been updated");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8g2.setFont(u8g2_font_6x12_tr);
|
||||||
|
u8g2.setCursor(0, 14);
|
||||||
|
printTwoDigits(u8g2, internetTimeInfo.day);
|
||||||
|
u8g2.print(".");
|
||||||
|
printTwoDigits(u8g2, internetTimeInfo.month);
|
||||||
|
u8g2.print(".");
|
||||||
|
u8g2.print(internetTimeInfo.year);
|
||||||
|
|
||||||
|
u8g2.setFont(u8g2_font_ncenB24_tr);
|
||||||
|
u8g2.setCursor(0, 54);
|
||||||
|
printTwoDigits(u8g2, internetTimeInfo.hour);
|
||||||
|
u8g2.print(":");
|
||||||
|
printTwoDigits(u8g2, internetTimeInfo.minute);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawHelloWorldScreen(U8G2 &u8g2)
|
void drawHelloWorldScreen(U8G2 &u8g2)
|
||||||
|
|||||||
Reference in New Issue
Block a user