Browse Source

move AlarmClock into own class

main
Hendrik Langer 7 years ago
parent
commit
4bcd62dce5
  1. 112
      src/AlarmClock.cpp
  2. 38
      src/AlarmClock.h
  3. 125
      src/main.cpp
  4. 4
      src/main.h
  5. 7
      src/screen.cpp
  6. 2
      src/screen.h

112
src/AlarmClock.cpp

@ -0,0 +1,112 @@
#include "AlarmClock.h"
AlarmClock::AlarmClock() {
}
bool AlarmClock::update(void) {
// time_t now;
// struct tm timeinfo;
time(&now); // update 'now' variable with current time
setenv("TZ", "CET-1CEST,M3.5.0/2,M10.5.0/3", 1);
tzset();
localtime_r(&now, &timeinfo);
}
bool AlarmClock::isTimeValid(void) {
update();
if (timeinfo.tm_year < (2016 - 1900)) {
return false; // time not set
}
return true;
}
bool AlarmClock::isNight(void) {
update();
return (timeinfo.tm_hour < 7 || timeinfo.tm_hour >= 22);
}
bool AlarmClock::isAlarmArmed(void) {
return alarmArmed;
}
double AlarmClock::getSecondsToAlarm(void) {
update();
return -difftime(now, mktime(&alarmTime));
}
bool AlarmClock::isPending(double window) {
double seconds = getSecondsToAlarm();
return (alarmArmed && seconds <= window);
}
void AlarmClock::setAlarmTime(struct tm time) {
alarmTime = time;
alarmArmed = true;
}
void AlarmClock::disableAlarm(void) {
alarmArmed = false;
}
struct tm AlarmClock::getAlarmTime() {
return alarmTime;
}
void AlarmClock::printTimeUnix(whichTime type) {
char strftime_buf[64];
getTime(strftime_buf, sizeof(strftime_buf), "%c", type);
Serial.println(strftime_buf);
}
void AlarmClock::getTime(char* ptr, size_t maxsize, const char* format, whichTime type) {
update();
switch (type) {
case TIME_CURRENT:
strftime(ptr, maxsize, format, &timeinfo);
break;
case TIME_ALARM:
strftime(ptr, maxsize, format, &alarmTime);
break;
default:
break;
}
}
/*
bool AlarmClock::getRTCTime(struct tm *timeinfo) {
time_t now;
time(&now); // update 'now' variable with current time
setenv("TZ", "CET-1CEST,M3.5.0/2,M10.5.0/3", 1);
tzset();
localtime_r(&now, timeinfo);
if (timeinfo->tm_year < (2016 - 1900)) {
// time not set
return false;
}
return true;
}
*/
bool AlarmClock::updateNTPTime(void) {
sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_setservername(0, "de.pool.ntp.org");
sntp_init();
// wait for time to be set
time_t now = 0;
struct tm timeinfo = { 0 };
int retry = 0;
const int retry_count = 10;
while(timeinfo.tm_year < (2016 - 1900) && ++retry < retry_count) {
ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
vTaskDelay(2000 / portTICK_PERIOD_MS);
time(&now);
localtime_r(&now, &timeinfo);
}
if (timeinfo.tm_year < (2016 - 1900)) return false;
else return true;
}

38
src/AlarmClock.h

@ -0,0 +1,38 @@
#ifndef _ALARMCLOCK_H
#define _ALARMCLOCK_H
#include <Arduino.h>
#include <time.h>
#include <sys/time.h>
#include "apps/sntp/sntp.h"
#include "driver/rtc_io.h"
enum whichTime { TIME_CURRENT, TIME_ALARM };
RTC_DATA_ATTR static struct tm alarmTime;
RTC_DATA_ATTR static bool alarmArmed;
class AlarmClock {
public:
AlarmClock();
bool isPending(double);
bool isAlarmArmed(void);
void setAlarmTime(struct tm time);
void disableAlarm(void);
struct tm getAlarmTime(void);
void getTime(char* ptr, size_t maxsize, const char* format = "%H:%M:%S", whichTime type = TIME_CURRENT);
bool isTimeValid(void);
bool isNight(void);
bool getRTCTime(struct tm *timeinfo);
bool updateNTPTime(void);
double getSecondsToAlarm(void);
void printTimeUnix(whichTime);
private:
bool update(void);
time_t now;
struct tm timeinfo;
};
#endif /* _ALARMCLOCK_H */

125
src/main.cpp

@ -23,10 +23,6 @@
#include <Wire.h> #include <Wire.h>
#endif #endif
#include <time.h>
#include <sys/time.h>
#include "apps/sntp/sntp.h"
#include <LoRa.h> #include <LoRa.h>
#include "driver/rtc_io.h" #include "driver/rtc_io.h"
@ -41,6 +37,7 @@
#include "rotary.h" #include "rotary.h"
#include "screen.h" #include "screen.h"
#include "led.h" #include "led.h"
#include "AlarmClock.h"
extern "C" { extern "C" {
int rom_phy_get_vdd33(); int rom_phy_get_vdd33();
@ -64,6 +61,7 @@ Rotary rotary;
Screen* screen; Screen* screen;
Led led; Led led;
WiFiUDP udp; WiFiUDP udp;
AlarmClock alarmclock;
menuType menuChange = eNone; menuType menuChange = eNone;
uint32_t lastButtonPress = 0; uint32_t lastButtonPress = 0;
@ -146,22 +144,8 @@ void setup() {
break; break;
} }
time_t now;
struct tm timeinfo;
time(&now);
setenv("TZ", "CET-1CEST,M3.5.0/2,M10.5.0/3", 1);
tzset();
localtime_r(&now, &timeinfo);
if (timeinfo.tm_year < (2016 - 1900)) {
// time not set
}
strftime(state.timeStr, sizeof(state.timeStr), "%H:%M", &timeinfo);
Serial.print(" Current time: "); alarmclock.printTimeUnix(TIME_CURRENT);
char strftime_buf[64];
strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
Serial.print("Current time: "); Serial.println(strftime_buf);
/* SPI.begin(SX1276_SCK, SX1276_MISO, SX1276_MOSI, SX1276_CS); /* SPI.begin(SX1276_SCK, SX1276_MISO, SX1276_MOSI, SX1276_CS);
LoRa.setPins(SX1276_CS, SX1276_RST, SX1276_IRQ);// set CS, reset, IRQ pin LoRa.setPins(SX1276_CS, SX1276_RST, SX1276_IRQ);// set CS, reset, IRQ pin
@ -178,16 +162,15 @@ void setup() {
for (int i=0; i<15 && iot.wifi.status() != WL_CONNECTED; i++) delay(500); for (int i=0; i<15 && iot.wifi.status() != WL_CONNECTED; i++) delay(500);
if (iot.wifi.status() == WL_CONNECTED) { if (iot.wifi.status() == WL_CONNECTED) {
transmitStatus(); transmitStatus();
obtain_time(); alarmclock.updateNTPTime();
} }
double seconds = difftime(now, mktime(&(state_persistant.alarmTime))); Serial.print(" Alarm time: "); alarmclock.printTimeUnix(TIME_ALARM);
double seconds = alarmclock.getSecondsToAlarm();
Serial.printf("alarm in %f seconds\n", seconds); Serial.printf("alarm in %f seconds\n", seconds);
strftime(strftime_buf, sizeof(strftime_buf), "%c", &(state_persistant.alarmTime));
Serial.print(" Alarm time: "); Serial.println(strftime_buf);
if (!state_persistant.alarmArmed || -seconds > secondsToSleep) suspend(); if (!alarmclock.isPending(secondsToSleep)) suspend();
else if (-seconds > 5*60) suspend(5*60); else if (!alarmclock.isPending(5*60)) suspend(5*60);
} }
u8g2.begin(); u8g2.begin();
@ -213,20 +196,19 @@ void setup() {
screen->draw(); screen->draw();
} }
WiFi.onEvent(WiFiGotIP, WiFiEvent_t::SYSTEM_EVENT_STA_GOT_IP);
IPAddress localIP = iot.wifi.getIP(); IPAddress localIP = iot.wifi.getIP();
char ipStr[16]; char ipStr[16];
localIP.toString().toCharArray(ipStr, 16); localIP.toString().toCharArray(ipStr, 16);
if (timeinfo.tm_year < (2016 - 1900)) { if (!alarmclock.isTimeValid()) {
ESP_LOGI(TAG, "Time is not set yet. Connecting to WiFi and getting time over NTP."); ESP_LOGI(TAG, "Time is not set yet. Connecting to WiFi and getting time over NTP.");
obtain_time(); alarmclock.updateNTPTime();
// update 'now' variable with current time
time(&now);
} }
localtime_r(&now, &timeinfo); alarmclock.getTime(state.timeStr, sizeof(state.timeStr), "%H:%M:%S", TIME_CURRENT);
strftime(state.timeStr, sizeof(state.timeStr), "%H:%M:%S", &timeinfo);
if (timeinfo.tm_hour < 7 || timeinfo.tm_hour >= 22) { if (alarmclock.isNight()) {
Serial.println("night mode"); Serial.println("night mode");
u8g2.setContrast(1); u8g2.setContrast(1);
u8x8_cad_StartTransfer(u8g2.getU8x8()); u8x8_cad_StartTransfer(u8g2.getU8x8());
@ -258,6 +240,13 @@ void setup() {
lastActive = millis(); lastActive = millis();
} }
void WiFiGotIP(WiFiEvent_t event, WiFiEventInfo_t info)
{
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(IPAddress(info.got_ip.ip_info.ip.addr));
}
//This function is called when the MQTT-Server is connected //This function is called when the MQTT-Server is connected
void onMqttConnect(bool sessionPresent) { void onMqttConnect(bool sessionPresent) {
@ -364,53 +353,10 @@ void suspend(uint32_t secondsToSleep) {
} }
void suspend() { void suspend() {
time_t now; if (!alarmclock.isPending(secondsToSleep)) suspend(secondsToSleep);
time(&now);
double seconds = difftime(now, mktime(&(state_persistant.alarmTime)));
if (-seconds > secondsToSleep || !state_persistant.alarmArmed) suspend(secondsToSleep);
else suspend(5*60); else suspend(5*60);
} }
void setAlarmTime(struct tm time) {
state_persistant.alarmTime = time;
state_persistant.alarmArmed = true;
char strftime_buf[64];
strftime(strftime_buf, sizeof(strftime_buf), "%c", &(state_persistant.alarmTime));
Serial.print("Setting Alarm time: "); Serial.println(strftime_buf);
}
struct tm getAlarmTime() {
return state_persistant.alarmTime;
}
bool isAlarmActive(){
/* time_t now;
time(&now);
double seconds = difftime(now, mktime(&(state_persistant.alarmTime)));
if (seconds > -24*60*60 && seconds <=0) return true;
else return false;*/
return state_persistant.alarmArmed;
}
void obtain_time(void) {
sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_setservername(0, "de.pool.ntp.org");
sntp_init();
// wait for time to be set
time_t now = 0;
struct tm timeinfo = { 0 };
int retry = 0;
const int retry_count = 10;
while(timeinfo.tm_year < (2016 - 1900) && ++retry < retry_count) {
ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
vTaskDelay(2000 / portTICK_PERIOD_MS);
time(&now);
localtime_r(&now, &timeinfo);
}
}
void rotation(int i, int direction, int buttonPressed) { void rotation(int i, int direction, int buttonPressed) {
if(millis() - lastButtonPress >= 300) { if(millis() - lastButtonPress >= 300) {
@ -428,19 +374,14 @@ void loop()
if(millis() - lastUpdate >= 1000) { if(millis() - lastUpdate >= 1000) {
lastUpdate = millis(); lastUpdate = millis();
time_t now; double seconds = alarmclock.getSecondsToAlarm();
struct tm timeinfo;
time(&now);
localtime_r(&now, &timeinfo);
double seconds = difftime(now, mktime(&(state_persistant.alarmTime)));
bool stayAwake = false; bool stayAwake = false;
if (state_persistant.alarmArmed && seconds >= -2*5*60) stayAwake = true; if (alarmclock.isPending(2*5*60)) stayAwake = true;
if (!mp3.playing && millis() - lastActive >= stayOnTime && !stayAwake) suspend(); if (!mp3.playing && millis() - lastActive >= stayOnTime && !stayAwake) suspend();
Serial.printf("alarm in %f seconds (%d)\n", seconds, state_persistant.alarmArmed); Serial.printf("alarm in %f seconds (%d)\n", seconds, alarmclock.isAlarmArmed());
if (seconds >= 0 && state_persistant.alarmArmed) { if (seconds <= 0 && alarmclock.isAlarmArmed()) { // alarm is currently running
if (mp3.aborted) alarmRunning = false; if (mp3.aborted) alarmRunning = false;
if (!mp3.playing && !alarmRunning) { if (!mp3.playing && !alarmRunning) {
led.wakeUpLight(0); led.wakeUpLight(0);
@ -458,21 +399,21 @@ void loop()
} }
led.changeAnimation(2, 0); led.changeAnimation(2, 0);
} }
if (lastButtonPress != 0 && millis() - lastButtonPress <= 10*1000) state_persistant.alarmArmed = false; // is this okay? if (lastButtonPress != 0 && millis() - lastButtonPress <= 10*1000) alarmclock.disableAlarm(); // is this okay?
if (seconds >= 360) state_persistant.alarmArmed = false; // auto disable after time if (seconds < -360) alarmclock.disableAlarm(); // auto disable after time
if (state_persistant.alarmArmed == false) mp3.stop(); if (alarmclock.isAlarmArmed() == false) mp3.stop();
lastActive = millis(); lastActive = millis();
} }
if (state_persistant.alarmArmed && seconds >= -5*60 && seconds <= 0) { if (alarmclock.isPending(5*60) && seconds >= 0) {
led.wakeUpLight(255*(seconds+300)/300); led.wakeUpLight(255*(-seconds+300)/300);
} }
int voltage = rom_phy_get_vdd33(); int voltage = rom_phy_get_vdd33();
Serial.printf("voltage: %d\n", voltage); Serial.printf("voltage: %d\n", voltage);
strftime(state.timeStr, sizeof(state.timeStr), "%H:%M:%S", &timeinfo); alarmclock.getTime(state.timeStr, sizeof(state.timeStr), "%H:%M:%S", TIME_CURRENT);
sprintf(state.string1, "%.1f°C %.1f%% %.0fhPa", bme280.readTemperature(), bme280.readHumidity(), bme280.readPressure()); sprintf(state.string1, "%.1f°C %.1f%% %.0fhPa", bme280.readTemperature(), bme280.readHumidity(), bme280.readPressure());
sprintf(state.string2, "%.1f %dmV %ddBm %ukB %s", temperatureRead(), voltage, WiFi.RSSI(), ESP.getFreeHeap()/1024, isAlarmActive()?"A":"_"); sprintf(state.string2, "%.1f %dmV %ddBm %ukB %s", temperatureRead(), voltage, WiFi.RSSI(), ESP.getFreeHeap()/1024, alarmclock.isAlarmArmed()?"A":"_");
Serial.print("Free Heap: "); Serial.print("Free Heap: ");
Serial.println(ESP.getFreeHeap()); Serial.println(ESP.getFreeHeap());

4
src/main.h

@ -13,12 +13,10 @@ struct tm getAlarmTime();
bool isAlarmActive(); bool isAlarmActive();
void loop(); void loop();
void rotation(int i, int direction, int buttonPressed); void rotation(int i, int direction, int buttonPressed);
void obtain_time(void); void WiFiGotIP(WiFiEvent_t event, WiFiEventInfo_t info);
struct __attribute__((packed)) WEBRADIO_STATE_PERSISTANT { struct __attribute__((packed)) WEBRADIO_STATE_PERSISTANT {
int boot_count = 0; int boot_count = 0;
struct tm alarmTime;
bool alarmArmed;
// uint8_t volume; // uint8_t volume;
}; };

7
src/screen.cpp

@ -336,12 +336,12 @@ void MainScreen::previous() {
} }
AlarmClockScreen::AlarmClockScreen() { AlarmClockScreen::AlarmClockScreen() {
if (getAlarmTime().tm_year < (2016 - 1900)) { if (alarmclock.getAlarmTime().tm_year < (2016 - 1900)) {
time_t now; time_t now;
time(&now); time(&now);
localtime_r(&now, &alarmTime); localtime_r(&now, &alarmTime);
} else { } else {
alarmTime = getAlarmTime(); alarmTime = alarmclock.getAlarmTime();
} }
} }
@ -393,7 +393,8 @@ uint8_t AlarmClockScreen::select() {
time(&now); time(&now);
alarmTime.tm_sec = 0; alarmTime.tm_sec = 0;
while(difftime(now, mktime(&alarmTime)) >= 0) alarmTime.tm_mday++; while(difftime(now, mktime(&alarmTime)) >= 0) alarmTime.tm_mday++;
setAlarmTime(alarmTime); alarmclock.setAlarmTime(alarmTime);
Serial.print("Setting Alarm time: "); alarmclock.printTimeUnix(TIME_ALARM);
menuChange = eMainScreen; menuChange = eMainScreen;
} }

2
src/screen.h

@ -22,6 +22,7 @@
#include "BME280.h" #include "BME280.h"
#include "image.h" #include "image.h"
#include "led.h" #include "led.h"
#include "AlarmClock.h"
enum menuType { eNone=0, eWelcomeScreen, eMainScreen, eMainMenu, eStationMenu, eAlarmClockScreen, eSuspendScreen, eLightScreen }; enum menuType { eNone=0, eWelcomeScreen, eMainScreen, eMainMenu, eStationMenu, eAlarmClockScreen, eSuspendScreen, eLightScreen };
@ -32,6 +33,7 @@ extern MP3 mp3;
extern menuType menuChange; extern menuType menuChange;
extern Basecamp iot; extern Basecamp iot;
extern Led led; extern Led led;
extern AlarmClock alarmclock;
class Screen { class Screen {

Loading…
Cancel
Save