#include "astronomy.h" #include #include #include #include #include #include "location.h" #include "sunriset.h" #include "util.h" struct solar_time_cache { time_t prev; time_t next; }; static struct solar_time_cache cache[NUM_SOLAR_TIMES] = {}; // Day is a time_t on the day to test time_t get_solar_time_nocache(uint8_t type, time_t day) { const struct { float angle; bool morning; bool upper_lim; } times[] = { [NIGHT_END] = {-18.0, true, false}, [DAY_START] = {0.0, true, true}, [DAY_END] = {0.0, false, true}, [SUNRISE_END] = {4.0, true, false}, [SUNSET_START] = {4.0, false, false}, [NIGHT_START] = {-18.0, false, false}, }; const struct location_data *loc = get_location_data(); struct tm *t = localtime(&day); // Compute the time zone with DST included double hour_offset = loc->time_zone; if(is_on_dst(loc, t)) { hour_offset += 1.0; } // Adjust the local time to UTC time_t utc_day = day - hour_offset * ONE_HOUR; t = localtime(&utc_day); double rise = 0.0, set = 0.0; __sunriset__(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, loc->longitude, loc->latitude, times[type].angle, times[type].upper_lim, &rise, &set); double frac_hours; if(times[type].morning) { frac_hours = rise; } else { frac_hours = set; } frac_hours += hour_offset; // Convert midnight UTC to a time_t struct tm base_time = *t; base_time.tm_hour = 0; base_time.tm_min = 0; base_time.tm_sec = 0; time_t result = mktime(&base_time); result += frac_hours * ONE_HOUR; return result; } void update_cache(uint8_t type, time_t current) { // this is kinda lazy but whatever time_t prev = 0; time_t next = -1; for(time_t t = current - ONE_DAY; t <= current + ONE_DAY; t += ONE_DAY) { time_t todays = get_solar_time_nocache(type, t); if(todays > prev && todays <= current) prev = todays; if(todays < next && todays >= current) next = todays; } assert(prev != 0); assert(next != (time_t)-1); cache[type].prev = prev; cache[type].next = next; dbg_printf("cache %u updated, %lu %lu\n", type, cache[type].prev, cache[type].next); } time_t last_solar_time(uint8_t type, time_t current) { if(current < cache[type].next) { return cache[type].prev; } else { update_cache(type, current); return cache[type].prev; } } uint16_t get_sky_color(time_t time) { if(last_solar_time(NIGHT_END, time) < last_solar_time(NIGHT_START, time)) return gfx_RGBTo1555(0, 0, 0); if(last_solar_time(DAY_START, time) < last_solar_time(NIGHT_END, time)) return gfx_RGBTo1555(70, 70, 60); if(last_solar_time(SUNRISE_END, time) < last_solar_time(DAY_START, time)) return gfx_RGBTo1555(210, 140, 10); if(last_solar_time(SUNSET_START, time) < last_solar_time(SUNRISE_END, time)) return gfx_RGBTo1555(64, 110, 160); if(last_solar_time(DAY_END, time) < last_solar_time(SUNSET_START, time)) return gfx_RGBTo1555(210, 140, 10); if(last_solar_time(NIGHT_START, time) < last_solar_time(DAY_END, time)) return gfx_RGBTo1555(70, 70, 60); return gfx_RGBTo1555(255, 0, 255); // hot pink error sky }