aqhome-react: added code to determine sunset/sunrise times.
This commit is contained in:
@@ -43,6 +43,7 @@
|
|||||||
fini.h
|
fini.h
|
||||||
loop.h
|
loop.h
|
||||||
net_read.h
|
net_read.h
|
||||||
|
suntimes.h
|
||||||
</headers>
|
</headers>
|
||||||
|
|
||||||
<sources>
|
<sources>
|
||||||
@@ -52,6 +53,7 @@
|
|||||||
fini.c
|
fini.c
|
||||||
loop.c
|
loop.c
|
||||||
net_read.c
|
net_read.c
|
||||||
|
suntimes.c
|
||||||
main.c
|
main.c
|
||||||
</sources>
|
</sources>
|
||||||
|
|
||||||
@@ -63,6 +65,7 @@
|
|||||||
|
|
||||||
<libraries>
|
<libraries>
|
||||||
$(gwenhywfar_libs)
|
$(gwenhywfar_libs)
|
||||||
|
-lm
|
||||||
</libraries>
|
</libraries>
|
||||||
|
|
||||||
<subdirs>
|
<subdirs>
|
||||||
|
|||||||
203
apps/aqhome-react/suntimes.c
Normal file
203
apps/aqhome-react/suntimes.c
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* This file is part of the project AqHome.
|
||||||
|
* AqHome (c) by 2024 Martin Preuss, all rights reserved.
|
||||||
|
*
|
||||||
|
* The license for this file can be found in the file COPYING which you
|
||||||
|
* should have received along with this file.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "./suntimes.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------------
|
||||||
|
* forward declarations
|
||||||
|
* ------------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
static GWEN_TIME *_getSunTime(const GWEN_DATE *date, double lat, double lng, int calcSunrise);
|
||||||
|
static double _calcSunTime(const GWEN_DATE *date, double lat, double lng, int calcSunrise);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------------
|
||||||
|
* implementations
|
||||||
|
* ------------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
GWEN_TIME *AQHomeReact_GetSunriseTimeForDateAndLoc(const GWEN_DATE *date, double lat, double lng)
|
||||||
|
{
|
||||||
|
return _getSunTime(date, lat, lng, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GWEN_TIME *AQHomeReact_GetSunsetTimeForDateAndLoc(const GWEN_DATE *date, double lat, double lng)
|
||||||
|
{
|
||||||
|
return _getSunTime(date, lat, lng, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GWEN_TIME *_getSunTime(const GWEN_DATE *date, double lat, double lng, int calcSunrise)
|
||||||
|
{
|
||||||
|
double timeInFloat=fmod(24+_calcSunTime(date, lat, lng, calcSunrise), 24);
|
||||||
|
double hours;
|
||||||
|
double minutes = modf(timeInFloat, &hours)*60;
|
||||||
|
GWEN_TIME *ti=GWEN_Time_new(GWEN_Date_GetYear(date), GWEN_Date_GetMonth(date)-1, GWEN_Date_GetDay(date),
|
||||||
|
hours, minutes, 0, 1);
|
||||||
|
return ti;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
int _test(void) {
|
||||||
|
double lat = 52.619425; // Latitude of location.
|
||||||
|
double lng = 10.087891; // Longitude of location.
|
||||||
|
int y=2024;
|
||||||
|
int m=4;
|
||||||
|
int d;
|
||||||
|
|
||||||
|
for (d=19; d<=24; d++) {
|
||||||
|
GWEN_DATE *date;
|
||||||
|
GWEN_TIME *sunrise;
|
||||||
|
GWEN_TIME *sunset;
|
||||||
|
int sunsetHours, sunsetMinutes, sunsetSecs;
|
||||||
|
int sunriseHours, sunriseMinutes, sunriseSecs;
|
||||||
|
|
||||||
|
date=GWEN_Date_fromGregorian(y, m, d);
|
||||||
|
sunrise=AQHomeReact_GetSunriseTimeForDateAndLoc(date, lat, lng);
|
||||||
|
sunset=AQHomeReact_GetSunsetTimeForDateAndLoc(date, lat, lng);
|
||||||
|
|
||||||
|
GWEN_Time_GetBrokenDownTime(sunset, &sunsetHours, &sunsetMinutes, &sunsetSecs);
|
||||||
|
GWEN_Time_GetBrokenDownTime(sunrise, &sunriseHours, &sunriseMinutes, &sunriseSecs);
|
||||||
|
|
||||||
|
fprintf(stdout, "date=%04d-%02d-%02d: sunrise=%02d:%02d sunset=%02d:%02d\n",
|
||||||
|
GWEN_Date_GetYear(date), GWEN_Date_GetMonth(date), GWEN_Date_GetDay(date),
|
||||||
|
sunriseHours, sunriseMinutes,
|
||||||
|
sunsetHours, sunsetMinutes);
|
||||||
|
GWEN_Time_free(sunset);
|
||||||
|
GWEN_Time_free(sunrise);
|
||||||
|
GWEN_Date_free(date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate time of sunset or sunrise at a given position and date according to an algorithm presented
|
||||||
|
* on this site:
|
||||||
|
* http://edwilliams.org/sunrise_sunset_algorithm.htm
|
||||||
|
*
|
||||||
|
* Original notes follow.
|
||||||
|
*
|
||||||
|
* -----------------------------
|
||||||
|
* Source:
|
||||||
|
* Almanac for Computers, 1990
|
||||||
|
* published by Nautical Almanac Office
|
||||||
|
* United States Naval Observatory
|
||||||
|
* Washington, DC 20392
|
||||||
|
*
|
||||||
|
* Inputs:
|
||||||
|
* date : date for which to calculate sun time
|
||||||
|
* lat, lng: latitude and longitude of the location to calculate for (west and north are positive values)
|
||||||
|
* ZENITH : Sun's zenith for sunrise/sunset
|
||||||
|
* official = 90 degrees 50'
|
||||||
|
* civil = 96 degrees
|
||||||
|
* nautical = 102 degrees
|
||||||
|
* astronomical = 108 degrees
|
||||||
|
*
|
||||||
|
* NOTE: longitude is positive for East and negative for West
|
||||||
|
* NOTE: the algorithm assumes the use of a calculator with the
|
||||||
|
* trig functions in "degree" (rather than "radian") mode. Most
|
||||||
|
* programming languages assume radian arguments, requiring back
|
||||||
|
* and forth convertions. The factor is 180/pi. So, for instance,
|
||||||
|
* the equation RA = atan(0.91764 * tan(L)) would be coded as RA
|
||||||
|
* = (180/pi)*atan(0.91764 * tan((pi/180)*L)) to give a degree
|
||||||
|
* answer with a degree input for L.
|
||||||
|
*/
|
||||||
|
double _calcSunTime(const GWEN_DATE *date, double lat, double lng, int calcSunrise)
|
||||||
|
{
|
||||||
|
const double PI=3.1415926535897932384626433832795;
|
||||||
|
const double ZENITH=-.83; /* accounts for atmospheric refraction (assuming height of 0m above horizon) */
|
||||||
|
double PiBy180=PI/180.0;
|
||||||
|
double N;
|
||||||
|
double lngHour;
|
||||||
|
double t;
|
||||||
|
double M;
|
||||||
|
double L;
|
||||||
|
double RA;
|
||||||
|
double Lquadrant;
|
||||||
|
double RAquadrant;
|
||||||
|
double sinDec;
|
||||||
|
double cosDec;
|
||||||
|
double cosH;
|
||||||
|
double H;
|
||||||
|
double T;
|
||||||
|
double UT;
|
||||||
|
|
||||||
|
/* 1. first calculate the day of the year */
|
||||||
|
N=GWEN_Date_DaysInYear(date);
|
||||||
|
|
||||||
|
/* 2. convert the longitude to hour value and calculate an approximate time */
|
||||||
|
lngHour = lng/15.0;
|
||||||
|
if (calcSunrise)
|
||||||
|
t = N+((6-lngHour)/24);
|
||||||
|
else
|
||||||
|
t = N+((18-lngHour)/24);
|
||||||
|
|
||||||
|
/* 3. calculate the Sun's mean anomaly */
|
||||||
|
M = (0.9856*t)-3.289;
|
||||||
|
|
||||||
|
/* 4. calculate the Sun's true longitude */
|
||||||
|
L = fmod(M+(1.916*sin(PiBy180*M)) + (0.020 * sin(2*PiBy180*M)) + 282.634, 360.0);
|
||||||
|
|
||||||
|
/* 5a. calculate the Sun's right ascension */
|
||||||
|
RA = fmod(180/PI*atan(0.91764*tan(PiBy180*L)), 360.0);
|
||||||
|
|
||||||
|
/* 5b. right ascension value needs to be in the same quadrant as L */
|
||||||
|
Lquadrant = floor(L/90)*90;
|
||||||
|
RAquadrant = floor(RA/90)*90;
|
||||||
|
RA = RA + (Lquadrant-RAquadrant);
|
||||||
|
|
||||||
|
/* 5c. right ascension value needs to be converted into hours */
|
||||||
|
RA = RA / 15;
|
||||||
|
|
||||||
|
/* 6. calculate the Sun's declination */
|
||||||
|
sinDec = 0.39782*sin(PiBy180*L);
|
||||||
|
cosDec = cos(asin(sinDec));
|
||||||
|
|
||||||
|
/* 7a. calculate the Sun's local hour angle */
|
||||||
|
cosH = (sin(PiBy180*ZENITH)-(sinDec*sin(PiBy180*lat))) / (cosDec*cos(PiBy180*lat));
|
||||||
|
/* cosH >1 : sun never rises on this location and date
|
||||||
|
* cosH <-1: sun never sets on this location and date
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 7b. finish calculating H and convert into hours */
|
||||||
|
if (calcSunrise)
|
||||||
|
H = 360-(180/PI)*acos(cosH);
|
||||||
|
else
|
||||||
|
H = (180/PI)*acos(cosH);
|
||||||
|
H = H/15;
|
||||||
|
|
||||||
|
/* 8. calculate local mean time of rising/setting */
|
||||||
|
T = H+RA-(0.06571*t)-6.622;
|
||||||
|
|
||||||
|
/* 9. adjust back to UTC */
|
||||||
|
UT = fmod(T-lngHour, 24.0);
|
||||||
|
|
||||||
|
/* we don't do step 10. here which would be to convert UT into local time as we want UTC */
|
||||||
|
return UT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
49
apps/aqhome-react/suntimes.h
Normal file
49
apps/aqhome-react/suntimes.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* This file is part of the project AqHome.
|
||||||
|
* AqHome (c) by 2024 Martin Preuss, all rights reserved.
|
||||||
|
*
|
||||||
|
* The license for this file can be found in the file COPYING which you
|
||||||
|
* should have received along with this file.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef AQHOMEREACT_SUNTIMES_H
|
||||||
|
#define AQHOMEREACT_SUNTIMES_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "./aqhome_react.h"
|
||||||
|
|
||||||
|
#include <gwenhywfar/gwendate.h>
|
||||||
|
#include <gwenhywfar/gwentime.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the sunrise time on the provided day and location.
|
||||||
|
*
|
||||||
|
* You can get the location by just clicking on a position on your chosen map website (e.g. "G'maps").
|
||||||
|
*
|
||||||
|
* @return time of sunrise for the given date and location
|
||||||
|
* @param date date for which to calculate
|
||||||
|
* @param lat latitude of the location to calculate for (positive for east)
|
||||||
|
* @param lng longitude of the location to calculate for (positive for north)
|
||||||
|
*/
|
||||||
|
GWEN_TIME *AQHomeReact_GetSunriseTimeForDateAndLoc(const GWEN_DATE *date, double lat, double lng);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the sunset time on the provided day and location.
|
||||||
|
*
|
||||||
|
* You can get the location by just clicking on a position on your chosen map website (e.g. "G'maps").
|
||||||
|
*
|
||||||
|
* @return time of sunset for the given date and location
|
||||||
|
* @param date date for which to calculate
|
||||||
|
* @param lat latitude of the location to calculate for (positive for east)
|
||||||
|
* @param lng longitude of the location to calculate for (positive for north)
|
||||||
|
*/
|
||||||
|
GWEN_TIME *AQHomeReact_GetSunsetTimeForDateAndLoc(const GWEN_DATE *date, double lat, double lng);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user