154 lines
4.1 KiB
C++
154 lines
4.1 KiB
C++
#include <cstdio>
|
|
#include <ctime>
|
|
|
|
#include <algorithm>
|
|
#include <chrono>
|
|
#include <iostream>
|
|
#include <string>
|
|
|
|
#include "hardware/pio.h"
|
|
#include "hardware/rtc.h"
|
|
#include "hardware/structs/scb.h"
|
|
|
|
#include "pico/cyw43_arch.h"
|
|
#include "pico/stdlib.h"
|
|
#include "pico/util/datetime.h"
|
|
|
|
#include "config.h"
|
|
#include "http_client.h"
|
|
#include "ntp_client.h"
|
|
#include "utils.h"
|
|
#include "ws2812.h"
|
|
|
|
using namespace std;
|
|
|
|
#define WS2812_PIN 18
|
|
|
|
int main() {
|
|
stdio_init_all();
|
|
rtc_init();
|
|
|
|
#ifdef DEBUG
|
|
printf("!!! DEBUG mode !!!\n");
|
|
#endif
|
|
printf("Firmware version: %s\n", PROJECT_VERSION);
|
|
|
|
WS2812 led(WS2812_PIN);
|
|
|
|
wifi_enable(); // Enable Wifi in order to set time and retrieve data
|
|
|
|
NtpClient::setDateTime();
|
|
HttpClient client;
|
|
std::string csv("");
|
|
for (int i = 1; i <= 10; i++) {
|
|
#ifdef DEBUG
|
|
printf("Attempt %d for retrieving data.\n", i);
|
|
#endif
|
|
csv = client.retrieveWasteDatesAsCsv();
|
|
if (csv.length() > 0) {
|
|
#ifdef DEBUG
|
|
printf("Data received!\n");
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (csv.length() == 0) {
|
|
#ifdef DEBUG
|
|
printf("Error getting data. Exiting!");
|
|
#endif
|
|
cyw43_arch_deinit();
|
|
return 1;
|
|
}
|
|
|
|
NtpClient::stop();
|
|
wifi_disable(); // We don't need Wifi anymore
|
|
|
|
auto dates = parseCsv(csv);
|
|
#ifdef DEBUG
|
|
printf("Number of Dates: %d\n", dates.size());
|
|
#endif
|
|
|
|
datetime_t dt;
|
|
|
|
// save values for later
|
|
uint scb_orig = scb_hw->scr;
|
|
uint clock0_orig = clocks_hw->sleep_en0;
|
|
uint clock1_orig = clocks_hw->sleep_en1;
|
|
|
|
while (true) {
|
|
auto timestamp = time_us_64() + 60'000'000ull;
|
|
|
|
rtc_get_datetime(&dt);
|
|
|
|
chrono::year_month_day tomorrowYMD(chrono::year{dt.year},
|
|
chrono::month{static_cast<unsigned>(dt.month)},
|
|
chrono::day{static_cast<unsigned>(dt.day + 1)});
|
|
auto it = std::find_if(dates.begin(), dates.end(), [&tomorrowYMD](const WasteDate &date) {
|
|
return date.date == tomorrowYMD;
|
|
});
|
|
|
|
int8_t hour = isDST(dt) ? dt.hour + 1 : dt.hour;
|
|
|
|
printf("%d-%02d-%02d %02d:%02d.%02d\n", dt.year, dt.month, dt.day, hour, dt.min, dt.sec);
|
|
|
|
// If there was a waste bin pickup found AND we are in the evening (>= 18:00) …
|
|
if (it != dates.end() && hour >= 18 && hour < 23) {
|
|
auto wasteDate = *it;
|
|
size_t count{0};
|
|
auto currentTime = time_us_64();
|
|
while (currentTime < timestamp) {
|
|
size_t index = count % wasteDate.wasteTypes.size();
|
|
|
|
switch (wasteDate.wasteTypes.at(index)) {
|
|
case Waste::GelberSack:
|
|
led.switchColor(Color::YELLOW);
|
|
break;
|
|
case Waste::Restmuell:
|
|
led.switchColor(Color::RED);
|
|
break;
|
|
case Waste::Papiertonne:
|
|
led.switchColor(Color::BLUE);
|
|
break;
|
|
case Waste::Problemstoffmobil:
|
|
led.switchColor(Color::CYAN);
|
|
break;
|
|
case Waste::Biotonne:
|
|
led.switchColor(Color::GREEN);
|
|
break;
|
|
}
|
|
|
|
auto timeLeft = timestamp - currentTime;
|
|
|
|
if (timeLeft > 3'000'000) {
|
|
sleep_us(3'000'000);
|
|
} else {
|
|
sleep_us(timeLeft);
|
|
}
|
|
|
|
currentTime = time_us_64();
|
|
count++;
|
|
}
|
|
|
|
} else {
|
|
// If we start already close to a full hour, dont't do a deep sleep yet
|
|
if (dt.min == 59 && dt.sec >= 57) {
|
|
sleep_ms((60 - dt.sec) * 1'000);
|
|
continue;
|
|
}
|
|
|
|
led.blinkReady();
|
|
|
|
datetime_t dtUntil = dt;
|
|
add_one_hour(dtUntil); // next hour
|
|
dtUntil.sec = 0;
|
|
dtUntil.min = 0;
|
|
|
|
perform_sleep(dtUntil);
|
|
recover_from_sleep(scb_orig, clock0_orig, clock1_orig);
|
|
}
|
|
}
|
|
|
|
cyw43_arch_deinit();
|
|
}
|