20static const char *
const TAG =
"sun";
45 d += moment.
hour / 24.0;
46 d += moment.
minute / (24.0 * 60);
47 d += moment.
second / (24.0 * 60 * 60);
53 int b = 2 - a + a / 4;
54 return ((
int) (365.25 * (
y + 4716))) + ((int) (30.6001 * (
m + 1))) + d + b - 1524.5;
58 int t = moment.
year - 2000;
59 return 62.92 + t * (0.32217 + t * 0.005589);
74 return jd() +
delta_t(dt) / (60 * 60 * 24);
82 SunAtTime(
num_t jde) : jde(jde), t((jde - 2451545) / 36525.0) {}
84 num_t mean_obliquity()
const {
94 num_t omega = 125.05 - 1934.136 * t;
98 num_t true_obliquity()
const {
100 num_t delta_epsilon = 0.00256 * cos(radians(omega()));
101 num_t epsilon = mean_obliquity() + delta_epsilon;
105 num_t mean_longitude()
const {
107 num_t l0 = 280.46646 + 36000.76983 * t + 0.0003032 *
sq(t);
108 return wmod(l0, 360);
111 num_t eccentricity()
const {
113 num_t e = 0.016708634 - 0.000042037 * t - 0.0000001267 *
sq(t);
117 num_t mean_anomaly()
const {
119 num_t m = 357.52911 + 35999.05029 * t - 0.0001537 *
sq(t);
123 num_t equation_of_center()
const {
126 num_t c = ((1.914602 - 0.004817 * t - 0.000014 *
sq(t)) * sin(m_rad) + (0.019993 - 0.000101 * t) * sin(2 * m_rad) +
127 0.000289 * sin(3 * m_rad));
131 num_t true_longitude()
const {
133 num_t x = mean_longitude() + equation_of_center();
137 num_t true_anomaly()
const {
139 num_t x = mean_anomaly() + equation_of_center();
143 num_t apparent_longitude()
const {
145 num_t x = true_longitude() - 0.00569 - 0.00478 * sin(
radians(omega()));
153 num_t right_ascension_rad = atan2(cos(epsilon_rad) * sin(app_lon_rad), cos(app_lon_rad));
154 num_t declination_rad = asin(sin(epsilon_rad) * sin(app_lon_rad));
158 num_t equation_of_time()
const {
162 num_t l2 = 2 * mean_longitude();
164 num_t e = eccentricity();
167 num_t sin_m = sin(m_rad);
168 num_t eot = (
y * sin(l2_rad) - 2 * e * sin_m + 4 * e *
y * sin_m * cos(l2_rad) - 1 / 2.0 *
sq(
y) * sin(2 * l2_rad) -
169 5 / 4.0 *
sq(e) * sin(2 * m_rad));
175 auto eq = equatorial_coordinate();
189 "right_ascension: %f\n"
191 jde, t, mean_longitude(), mean_anomaly(), eccentricity(), equation_of_center(), true_longitude(), omega(),
192 apparent_longitude(), mean_obliquity(), true_obliquity(), true_anomaly(), eq.right_ascension,
197struct SunAtLocation {
200 num_t greenwich_sidereal_time(
Moment moment)
const {
208 num_t t = (jd0 - 2451545) / 36525;
210 num_t gmst = (+280.46061837 + 360.98564736629 * (jd - 2451545) + 0.000387933 *
sq(t) - (1 / 38710000.0) *
cb(t));
211 return wmod(gmst, 360);
215 auto eq = SunAtTime(moment.
jde()).equatorial_coordinate();
216 num_t gmst = greenwich_sidereal_time(moment);
218 num_t nutation_corr = 0;
220 num_t ra = eq.right_ascension;
222 alpha =
wmod(alpha, 360);
227 num_t sin_elevation = (+sin_lat * sin(eq.declination_rad()) + cos_lat * cos(eq.declination_rad()) * cos(alpha_rad));
228 num_t elevation_rad = asin(sin_elevation);
229 num_t azimuth_rad = atan2(sin(alpha_rad), cos(alpha_rad) * sin_lat - tan(eq.declination_rad()) * cos_lat);
239 auto m = local_event_(date, 12);
241 num_t new_h = 0, old_h;
244 auto x = local_hour_angle_(jde + old_h / 86400, rise, zenith);
248 }
while (std::abs(new_h - old_h) >= 15);
249 time_t new_timestamp =
m.timestamp + (time_t) new_h;
250 return ESPTime::from_epoch_local(new_timestamp);
255 auto pos = SunAtTime(jde).equatorial_coordinate();
256 num_t dec_rad =
pos.declination_rad();
258 num_t num = cos(
radians(zenith)) - (sin(dec_rad) * sin(lat_rad));
259 num_t denom = cos(dec_rad) * cos(lat_rad);
260 num_t cos_h = num / denom;
261 if (cos_h > 1 || cos_h < -1)
274 num_t eot = SunAtTime(jd).equation_of_time() * 240;
275 time_t new_timestamp = (time_t) (date.
timestamp + added_d * 86400 - eot);
276 return ESPTime::from_epoch_utc(new_timestamp);
281 SunAtLocation sun{location_};
283 if (!
m.dt.is_valid())
291 return sun.true_coordinate(
m);
294 SunAtLocation sun{location_};
299 today.
hour = today.minute = today.second = 0;
300 today.recalc_timestamp_utc();
302 auto it = sun.event(rising, today, zenith);
303 if (it.has_value() && it->timestamp < date.
timestamp) {
306 time_t new_timestamp = today.timestamp + 24 * 60 * 60;
308 it = sun.event(rising, today, zenith);
optional< ESPTime > calc_event_(bool rising, double zenith)
internal::HorizontalCoordinate calc_coords_()
optional< ESPTime > sunset(double elevation)
optional< ESPTime > sunrise(double elevation)
num_t delta_t(ESPTime moment)
num_t wmod(num_t x, num_t y)
num_t arcdeg(num_t deg, num_t minutes, num_t seconds)
num_t julian_day(ESPTime moment)
Providing packet encoding functions for exchanging data with a remote host.
A more user-friendly version of struct tm from time.h.
uint8_t minute
minutes after the hour [0-59]
uint8_t second
seconds after the minute [0-60]
uint8_t hour
hours since midnight [0-23]
time_t timestamp
unix epoch time (seconds since UTC Midnight January 1, 1970)
bool is_valid() const
Check if this ESPTime is valid (all fields in range and year is greater than 2018)
static ESPTime from_epoch_utc(time_t epoch)
Convert an UTC epoch timestamp to a UTC time ESPTime instance.
uint8_t day_of_month
day of the month [1-31]
uint8_t month
month; january=1 [1-12]
num_t declination_rad() const
num_t right_ascension_rad() const
num_t latitude_rad() const
num_t longitude_rad() const
num_t elevation_rad() const
num_t azimuth_rad() const