abfall/src/abfall.cpp

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();
}