Table of contents
Updated – January 20, 2023
Collecting weather data with SmartHome and visualizing it via AIO Creator on your cell phone or tablet is usually not a necessity, but it is a nice to have.
The online weather service weatherstack.com offers up to 250 queries per month – limited free of charge. If you really want up-to-date weather data, you should choose the standard package. 50,000 queries allow minute intervals.
The packages that are still available differ primarily in the number of requests and a weather forecast of 7 or 14 days.
The following data is included in all packages:
- Geographic longitude and latitude
- Location
- region
- country
- Time zone
- Local time and date
- UTC offset
- Current time of data collection
- Air temperature
- Weather description
- wind speed
- Wind direction numerical/geographical
- Air pressure
- Amount of rain
- Humidity
- Cloud density
- Chill temperature
- UV index
- view
Registration, regardless of the package, requires the usual details and payment details. An annual subscription, as opposed to monthly, is discounted at 20%.
After successfully completing this procedure, you will receive a so-called API code (Application Programming Interface), which you copy into the query URL. The response is an XML output containing the above data categories and values. The data is extracted using suitable scripts and stored in variables. These can then be used for visualization in the AIO Creator.
A detailed description of all parameters possible in the XML output, as well as the optional query options included in the higher-priced packages, including various code examples, here visible.
Program
The program is quite extensive due to the large amount of data. Therefore, the individual sections are listed sequentially here. All code snippets can ultimately be combined into a single program.
In addition to the data mentioned above, additional data is calculated in the program and made available for visualization:
- Solar elevation and azimuth
- Sun protection factor recommendation
Program header
The header only contains the URL, which must be supplemented by the API key, shown here with xxx, and the location (in plain text or, separated by a comma, as a longitude and latitude, marked with yyy:
var url = "http://api.weatherstack.com/current?access_key=xxx&query=yyy";
Conversion US to DE time format
Since there is no choice of display language in the free and standard tariff, so only the AM / PM time format is available, it is converted to 24-hour here.
Variable to be created:
W_LDU
of type string
Code:
! AM/PM conversion – save in W_LDU
var posValueStart;
var posValueEnd;
var posStart;
var posEnd; string stderr; string stdout;
system.Exec("wget -q -O - '"#url#"'", &stdout, &stderr);
WriteLine(stdout);
string weather_xml = stdout;
string word = 'observation_time":"';
integer word_length = word.Length();
integer word_position = weather_xml.Find(word);
string data = weather_xml.Substr((word_position + word_length), 5);
integer word_position = data.Find(word);
data = data.Substr(0, (word_position -2));
string word = 'observation_time":"';
integer word_length = word.Length();
integer word_position = weather_xml.Find(word);
string PM = weather_xml.Substr((word_position + word_length +6), 2);
integer word_position = PM.Find(word);
PM = PM.Substr(0, (word_position -2));
WriteLine("AM/PM");WriteLine(PM);
string word = 'observation_time":"';
integer word_length = word.Length();
integer word_position = weather_xml.Find(word);
string HH = weather_xml.Substr((word_position + word_length) + 1, 1);
integer word_position = HH.Find(word);
HH = HH.Substr(0, (word_position -2));
WriteLine("HH");WriteLine(HH);
string word = 'observation_time":"';
integer word_length = word.Length();
integer word_position = weather_xml.Find(word);
string MM = weather_xml.Substr((word_position + word_length) +3, 2);
integer word_position = MM.Find(word);
MM = MM.Substr(0, (word_position -2));
WriteLine("MM");WriteLine(MM);
if (PM == "PM")
{
integer Diff = 12;
WriteLine("Diff");WriteLine(Diff);
var HH_i = HH.ToInteger();
integer H = (HH_i + Diff);
WriteLine("HHi + Diff is = H)");WriteLine(H);
string HHMM = H #":";
WriteLine("H_+ : ");WriteLine(HHMM);
string HM = HHMM # MM;
WriteLine("HH_+12+MM");WriteLine(HM);
dom.GetObject("W_LDU").State(HM);
}
else
{
WriteLine("LDU_data");WriteLine(data);
dom.GetObject("W_LDU").State(data);
}
Country – Country code
The country code is also output in English and converted here into the international code. Additional countries can be added according to this pattern if necessary. The current country is automatically determined by Weatherstack when you select the city.
Variable to be created:
W_country_code
of type string
Code:
! Country_code
pos = 0;
posStart = 'country":"';
posEnd = '","region';
posValueStart = stdout.Find(posStart) + posStart.Length();
posValueEnd = stdout.Find(posEnd)-posValueStart;
string country_code = stdout.Substr(posValueStart, posValueEnd);
if (country_code == "Germany")
{
string country_code = "DE";
}
if (country_code == "Sweden")
{
string country_code = "SE";
}
WriteLine("country_code");WriteLine(country_code);
dom.GetObject("W_country_code").State(country_code);
region
The region, for example in Germany, is called “Lower Saxony” and is also determined automatically by Weatherstack.
Variable to be created:
W_region
of type string
Code:
! region
pos = 0;
posStart = 'region":"';
posEnd = '","lat';
posValueStart = stdout.Find(posStart) + posStart.Length();
posValueEnd = stdout.Find(posEnd)-posValueStart;
string region = stdout.Substr(posValueStart, posValueEnd);
WriteLine("region");WriteLine(region);
dom.GetObject("W_region").State(region);
City
When you enter the city, Weatherstack automatically determines the associated longitude and latitude, while the city is determined from the geodata entered.
Variable to be created:
W_city_name
of type string
Code:
! City_name
pos = 0;
posStart = 'name":"';
posEnd = '","country';
posValueStart = stdout.Find(posStart) + posStart.Length();
posValueEnd = stdout.Find(posEnd)-posValueStart;
string city_name = stdout.Substr(posValueStart, posValueEnd);
WriteLine("city_name");WriteLine(city_name);
dom.GetObject("W_city_name").State(city_name);
Latitude – geographical. Width
Variable to be created:
W_Lat
of type string
Code:
! Lat
pos = 0;
posStart = 'query":"Lat';
posEnd = 'and Lon';
posValueStart = stdout.Find(posStart) + posStart.Length();
posValueEnd = stdout.Find(posEnd)-posValueStart;
string Lat = stdout.Substr(posValueStart, posValueEnd);
WriteLine("Lat");WriteLine(Lat);
dom.GetObject("W_Lat").State(Lat);
Longitude – geogr. length
Variable to be created:
W_Lon
of type string
Code:
! Lon
pos = 0;
posStart = 'and Lon';
posEnd = '","language';
posValueStart = stdout.Find(posStart) + posStart.Length();
posValueEnd = stdout.Find(posEnd)-posValueStart;
string Lon = stdout.Substr(posValueStart, posValueEnd);
WriteLine("Lon");WriteLine(Lon);
dom.GetObject("W_Lon").State(Lon);
Visibility – visibility
Variable to be created:
W_vis
of type string
Code:
! Visibility
pos = 0;
posStart = 'visibility":';
posEnd = ',"is_day';
posValueStart = stdout.Find(posStart) + posStart.Length();
posValueEnd = stdout.Find(posEnd)-posValueStart;
string vis_data = stdout.Substr(posValueStart, posValueEnd);
WriteLine("vis_data");WriteLine(vis_data);
dom.GetObject("W_vis").State(vis_data);
Air pressure and trend
In addition to the air pressure provided, this script determines the air pressure tendency by saving a measured value as “current” and a previous one as “old”. Both are compared with each other, which results in the tendency.
Variable to be created:
W_air pressure_act
of type stringW_air pressure_old
of type stringW_Barometric pressure trend
of type string
Code:
! Pressure
var W_mb_old;
var W_mb_akt;
pos = 0;
posStart = 'pressure":';
posEnd = ',"precip';
posValueStart = stdout.Find(posStart) + posStart.Length();
posValueEnd = stdout.Find(posEnd)-posValueStart;
data = stdout.Substr(posValueStart, posValueEnd);WriteLine(data);
real W_mb_akt = data.ToInteger();WriteLine("W_mb_akt");WriteLine(W_mb_akt);
dom.GetObject("W_Luftdruck_akt").State(W_mb_akt);
W_mb_alt = dom.GetObject("W_Luftdruck_alt").Value();WriteLine(W_mb_alt);
if (W_mb_akt > W_mb_old)
{
dom.GetObject("W_Luftdruck_old").State(W_mb_akt);
dom.GetObject("W_Air pressure trend").State("S");
}
if (W_mb_akt < W_mb_old)
{
dom.GetObject("W_Luftdruck_old").State(W_mb_akt);
dom.GetObject("W_Air pressure trend").State("F");
}
if (W_mb_akt == W_mb_old)
{
dom.GetObject("W_Luftdruck_old").State(W_mb_akt);
dom.GetObject("W_Air pressure trend").State("N");
}
Chill temperature
The wind chill depends on the wind speed and the temperature. In water sports, the effect of evaporative cooling due to spray is also increased (but this is not taken into account here). Chill refers to the perceived temperature, which in a very cold environment can be up to one and a half times negative temperature compared to the actual temperature and can lead to rapid frostbite.
Variable to be created:
W_chill
of type string
Code:
! Chill
pos = 0;
posStart = 'feelslike":';
posEnd = ',"uv_index';
posValueStart = stdout.Find(posStart) + posStart.Length();
posValueEnd = stdout.Find(posEnd)-posValueStart;
string app_temp_data = stdout.Substr(posValueStart, posValueEnd);
WriteLine("app_temp_data");WriteLine(app_temp_data);
dom.GetObject("W_chill").State(app_temp_data);
UV and light protection recommendation
The UV exposure determined based on the UV index results in a recommendation for the use of light protection measures if necessary.
Variable to be created:
W_UV
of type stringW_LSF
of type string
Code:
! UV
pos = 0;
posStart = 'uv_index":';
posEnd = ',"visibility';
posValueStart = stdout.Find(posStart) + posStart.Length();
posValueEnd = stdout.Find(posEnd)-posValueStart;
var uv_data = stdout.Substr(posValueStart, posValueEnd);
dom.GetObject("W_UV").State(uv_data);
data = uv_data.Substr(0, (word_position -2));
real number = data.ToInteger();
WriteLine("UV number");WriteLine(number);
string LSF = "";
if (number <3) {LSF = "unnecessary" ;} elseif ((number >= "3") && (number <= "5")) {LSF = "recommended" ;} elseif ((number >= "6 ") && (number <= "7")) {LSF = "required" ;} elseif ((number >= "8") && (number <= "9")) {LSF = "required" ;} elseif ( number >= "10") {LSF = "MUST" ;}
dom.GetObject("W_LSF").State(LSF);WriteLine("LSF");WriteLine(LSF);
wind speed
Variable to be created:
W_WdSpd
of type number
Code:
! wind speed
pos = 0;
posStart = 'wind_speed":';
posEnd = ',"wind_degree';
posValueStart = stdout.Find(posStart) + posStart.Length();
posValueEnd = stdout.Find(posEnd)-posValueStart;
var wind_spd_daten = stdout.Substr(posValueStart, posValueEnd);
real x = wind_spd_data.ToFloat();
dom.GetObject("W_WdSpd").State(x);
Wind speed conversions
Since there are different preferred wind speed measurements in different regions, countries and applications, here is the conversion from m/s to km/h, knots and Beaufort.
Variable to be created:
W_Wind_kmh
of type numberW_Wind_knh
of type number- W_Wind_Bft of type number
Code:
real W_Wind_kmh = (wind_spd_daten.ToFloat() * 3.6);WriteLine("W_Wind_kmh");WriteLine(W_Wind_kmh);
dom.GetObject("W_Wind_kmh").State(W_Wind_kmh);
real W_Wind_knh = (W_Wind_kmh / 1.852);WriteLine("W_Wind_knh");WriteLine(W_Wind_knh);
dom.GetObject("W_Wind_knh").State(W_Wind_knh);
if (x < 0.30)
{
dom.GetObject(“W_Wind_Bft”).State(0);
}
if ((0.29 < x) && (x < 1.51))
{
dom.GetObject(“W_Wind_Bft”).State(1);
}
if ((1.59 < x) && ( x < 3.31))
{
dom.GetObject(“W_Wind_Bft”).State(2);
}
if ((3.39 < x) && ( x < 5.41))
{
dom.GetObject(“W_Wind_Bft”).State(3);
}
if ((5.49 < x) && ( x < 7.91))
{
dom.GetObject(“W_Wind_Bft”).State(4);
}
if ((7.99 < x) && (x < 10.71))
{
dom.GetObject(“W_Wind_Bft”).State(5);
}
if ((10.79 < x) && (x < 13.81))
{
dom.GetObject(“W_Wind_Bft”).State(6);
}
if ((12.89 < x) && (x < 17.11))
{
dom.GetObject(“W_Wind_Bft”).State(7);
}
if ((17.19 < x) && (x < 20.71))
{
dom.GetObject(“W_Wind_Bft”).State(8);
}
if ((20.79 < x) && (x < 24.41))
{
dom.GetObject(“W_Wind_Bft”).State(9);
}
if ((24.49 < x) && (x < 28.41))
{
dom.GetObject(“W_Wind_Bft”).State(10);
}
if ((28.49 < x) && (x < 32.61))
{
dom.GetObject(“W_Wind_Bft”).State(11);
}
if (x > 32.6)
{
dom.GetObject(“W_Wind_Bft”).State(12);
}
Wind speed – risk of frostbite
Anyone traveling in very cold zones will receive a warning with this script if there is a risk of frostbite due to wind speed and perceived outside temperature if appropriate protective clothing is not used.
The calculation assumes that with skin exposure of 30 minutes or less, the skin temperature can be expected to drop to -4.8 °C and that frostbite will occur in people at 5%.
Variable to be created:
- W_Wind_Danger type boolean
Code:
if (((app_temp_data == -27.2) && (8 > W_Wind_kmh <10.1)) || ((app_temp_data == -22.9) && (12 > W_Wind_kmh <15.1)) || ((app_temp_data == -24.2) && ( 18 > W_Wind_kmh <20.1)) || ((app_temp_data == -25.2) && (23 > W_Wind_kmh <25.1)) || ((app_temp_data == -26.0) && (28 > W_Wind_kmh <30.1)) || ((app_temp_data == -26.8) && (32 > W_Wind_kmh <35.1)) || ((app_temp_data == -27.4) && (37 > W_Wind_kmh <40.1)) || ((app_temp_data == -28.0) && (42 > W_Wind_kmh <45.1 )) || ((app_temp_data == -28.6) && (47 > W_Wind_kmh <50.1)) || ((app_temp_data == -22.2) && (53 > W_Wind_kmh <55.1)) || ((app_temp_data == -22.6) && (57 > W_Wind_kmh <60.1)))
{
dom.GetObject("W_Wind_Danger").State(true);
}
else
{
dom.GetObject("W_Wind_Danger").State(false);
}
Wind direction (geographic)
Variable to be created:
W_wind_dir
of type string
Code:
! Wind direction geographically
pos = 0;
posStart = 'wind_dir":"';
posEnd = '","pressure';
posValueStart = stdout.Find(posStart) + posStart.Length();
posValueEnd = stdout.Find(posEnd)-posValueStart;
string wind_dir_data = stdout.Substr(posValueStart, posValueEnd);
WriteLine("W_wind_dir");WriteLine(wind_dir_daten);
dom.GetObject("W_wind_dir").State(wind_dir_daten);
Wind direction (numerical)
Variable to be created:
W_Wind_rchtg
of type string
Code:
! Wind direction numerically
pos = 0;
posStart = 'wind_degree":';
posEnd = ',"wind_dir';
posValueStart = stdout.Find(posStart) + posStart.Length();
posValueEnd = stdout.Find(posEnd)-posValueStart;
string W_wind_rchtg = stdout.Substr(posValueStart, posValueEnd);
WriteLine("W_wind_rchtg");WriteLine(W_wind_rchtg);
dom.GetObject("W_wind_rchtg").State(W_wind_rchtg);
Cloud cover
The cloud cover is also written in English by Weatherstack, which is why the translation into German is made here.
Variable to be created:
W_description
of type string
Code:
! Cloud cover description
pos = 0;
posStart = 'weather_descriptions":["';
posEnd = '"],"wind_speed';
posValueStart = stdout.Find(posStart) + posStart.Length();
posValueEnd = stdout.Find(posEnd)-posValueStart;
string clouds_description = stdout.Substr(posValueStart, posValueEnd);
WriteLine("clouds_description_EN");WriteLine(clouds_description);
if (clouds_description == "Cloudy")
{
string clouds_description_DE = "Cloudy";
WriteLine("clouds_description_DE");WriteLine(clouds_description_DE);
dom.GetObject("W_description").State(clouds_description_DE);
}
if (clouds_description == "Light rain")
{
string clouds_description_DE = "Light rain";
WriteLine("clouds_description_DE");WriteLine(clouds_description_DE);
dom.GetObject("W_description").State(clouds_description_DE);
}
if (clouds_description == "Light rain shower")
{
string clouds_description_DE = "Light rain showers";
WriteLine("clouds_description_DE");WriteLine(clouds_description_DE);
dom.GetObject("W_description").State(clouds_description_DE);
}
if (clouds_description == "Light drizzle")
{
string clouds_description_DE = "Drizzle";
WriteLine("clouds_description_DE");WriteLine(clouds_description_DE);
dom.GetObject("W_description").State(clouds_description_DE);
}
if (clouds_description == "Mis")
{
string clouds_description_DE = "Haze";
WriteLine("clouds_description_DE");WriteLine(clouds_description_DE);
dom.GetObject("W_description").State(clouds_description_DE);
}
if (clouds_description == "Light snow showers")
{
string clouds_description_DE = "Light snow showers";
WriteLine("clouds_description_DE");WriteLine(clouds_description_DE);
dom.GetObject("W_description").State(clouds_description_DE);
}
if (clouds_description == "Sunny")
{
string clouds_description_DE = "Heiter";
WriteLine("clouds_description_DE");WriteLine(clouds_description_DE);
dom.GetObject("W_description").State(clouds_description_DE);
}
if (clouds_description == "Overcast")
{
string clouds_description_DE = "Overcast";
WriteLine("clouds_description");WriteLine(clouds_description_DE);
dom.GetObject("W_description").State(clouds_description_DE);
}
if (clouds_description == "Partly cloudy")
{
string clouds_description_DE = "Partly cloudy";
WriteLine("clouds_description_DE");WriteLine(clouds_description_DE);
dom.GetObject("W_description").State(clouds_description_DE);
}
if (clouds_description == "Clear")
{
string clouds_description_DE = "Clear";
WriteLine("clouds_description_DE");WriteLine(clouds_description_DE);
dom.GetObject("W_description").State(clouds_description_DE);
}
if (clouds_description == "Fog")
{
string clouds_description_DE = "Fog";
WriteLine("clouds_description_DE");WriteLine(clouds_description_DE);
dom.GetObject("W_description").State(clouds_description_DE);
}
if (clouds_description == "Patchy rain possible")
{
string clouds_description_DE = "Light rain possible";
WriteLine("clouds_description");WriteLine(clouds_description_DE);
dom.GetObject("W_description").State(clouds_description_DE);
}
if (clouds_description == "Moderate rain")
{
string clouds_description_DE = "Moderate precipitation";
WriteLine("clouds_description");WriteLine(clouds_description_DE);
dom.GetObject("W_description").State(clouds_description_DE);
}
Cloud cover
Variable to be created:
W_clouds
of type string
Code:
! Cloud cover
pos = 0;
posStart = 'cloudcover":';
posEnd = ',"feelslike';
posValueStart = stdout.Find(posStart) + posStart.Length();
posValueEnd = stdout.Find(posEnd)-posValueStart;
string clouds_data = stdout.Substr(posValueStart, posValueEnd);
WriteLine("clouds_data");WriteLine(clouds_data);
dom.GetObject("W_clouds").State(clouds_data);
Forecast rain
Variable to be created:
W_Precipitation
of type string
Code:
! Forecast rain
varx;
pos = 0;
posStart = 'precip":';
posEnd = ',"humidity';
posValueStart = stdout.Find(posStart) + posStart.Length();
posValueEnd = stdout.Find(posEnd)-posValueStart;
string precip = stdout.Substr(posValueStart, posValueEnd);
WriteLine("Precipitation");WriteLine(precip);
dom.GetObject("W_Precipitation").State(precip);
Elevation – Azimuth
The script was written by radio lighthouse written and the Homematic Forum taken from page 10 of the linked thread.
Two system variables must be created:
sun_elevation n
of type Numbersun_azimuth
of type Number
Why just 4 minutes? Because the Earth completes its 360° circle around the sun once in 24 hours. 360° / 24h = 15° per hour, corresponding to 60 minutes / 15° = 4 minutes.
The script should be used independently of the above scripts or the associated program, provided the update interval is different from 4 minutes.
Program:
Variables to be created:
sun_azimuth
of type numbersun_elevation
of type number
Code:
! Get latitudereal phi = system.Latitude();
phi = 0.017453292 * phi;
! Conversion to radians
! Calculate sin_phi and cos_phi with Taylor seriesreal temp = phi * phi;
real sin_phi =phi * ((temp * temp * 0.0083334) +1.0 - (temp * 0.1666667));
! sine approximation
real cos_phi = (temp *temp *0.0416667) + 1.0 - (temp * 0.5);
! cosine approximation
! Calculation of solar time, all times in minutesinteger time_min = system.Date("%M").ToInteger() + 60system.Date("%H").ToInteger(); integer start of day_min = system.SunriseTime("%M").ToInteger() + 60system.SunriseTime("%H").ToInteger();
integer end of day_min = system.SunsetTime("%M").ToInteger() + 60* system.SunsetTime("%H").ToInteger();
integer solar time = time_min + 720 - 0.5 *(start of day_min + end of day_min);
if (solar time > 1440) {solar time = solar time -1440;}
if (solar time < 1) {solar time = 1440 + solar time;} boolean afternoon =false; if (solartime > 720) {solartime =solartime - 720; afternoon = true; }
else {solar time =720 -solar time;}
! Calculation sin_tau and cos_taureal tau = 0.00436332313 * solar time; ! 15/60 * pi /180 * solar time [0 < tau < pi ] if (tau < 1.570796327) {temp = tau * tau; real sin_tau =tau * ((temp * temp * 0.0083334) +1.0 - (temp *0.1666667)); tau= 1.570796327 - tau; temp = tau * tau; real cos_tau =tau * ((temp * temp * 0.0083334) +1.0 - (temp * 0.1666667));} else {real tau1 =3.141592654 - tau; temp = tau1 * tau1; real sin_tau =tau1 * ((temp * temp * 0.0083334) +1.0 - (temp * 0.1666667)); tau = tau - 1.570796327; temp = tau * tau; real cos_tau = (tau) (-1.0) ((temp * temp * 0.0083334) +1.0 - (temp * 0.1666667));}
! Calculation deltainteger day number = system.Date("%j").ToInteger(); day number = day number +10; if (daynumber > 365) {daynumber = daynumber - 365;}
if (day number < 92) {real day = 0.0172142 *day number;temp = day * day; real delta = (-0.410152) *((temp *temp *0.041666) + 1.0 - (temp * 0.5));} if ((day number >91) && (day number < 184)) {day number = 183 - day number; real day = 0.0172142 *day number; temp = day * day; real delta = (0.410152) *((temp *temp *0.041666) + 1.0 - (temp * 0.5));} if ((day number >183) && (day number < 275)) {day number = day number - 183; real day = 0.0172142 *day number; temp = day * day; real delta = (0.410152) *((temp *temp *0.041666) + 1.0 - (temp * 0.5));} if ((day number >274) && (day number < 366)) {day number = 365 - day number; real day = 0.0172142 *day number; temp = day * day; real delta = (-0.410152) *((temp *temp *0.041666) + 1.0 - (temp * 0.5));}! calculation sin_delta, cos_delta
temp = delta * delta; real sin_delta =delta * ((temp * temp * 0.0083334) +1.0 - (temp * 0.1666667)); !sinus approximation real cos_delta = (temp *temp *0.0416667) + 1.0 - (temp * 0.5);
! cosine approximation
! Calculation of tan_delta with piecewise linearization of the tanboolean vsign = true; if (delta< 0.0) {vsign = false; delta = (-1.0) *delta;} real tan_delta = 1.0233 * delta; if (delta >=0.2618) {tan_delta = (1.1822*delta) - 0.0416;}
if (vsign == false) {tan_delta = (-1.0) * tan_delta;}
! Calculation sin_elevation and tan_azimuthreal sin_elevation = (sin_phi * sin_delta) +( cos_phi * cos_delta * cos_tau);
temp = sin_elevation * sin_elevation;
real sun_elevation = sin_elevation * (1.0 + (0.1666667 * temp) + (0.075 * temp * temp));
sun_elevation = 57.29577951 * sun_elevation;
real denominator = (sin_phi*cos_tau) - (cos_phi * tan_delta);
if (denominator < 0.0) {boolean plus180 = true;} real tan_azimuth = sin_tau / denominator;
! Calculation of sun_azimuth with piecewise linearization of the arctanboolean sign = true; if (tan_azimuth < 0.0) { sign = false; tan_azimuth = (-1.0)*tan_azimuth;} real sun_azimuth = 0.97723 * tan_azimuth; if ((tan_azimuth >=0.2679)&&(tan_azimuth < 0.5774)) {sun_azimuth = (0.84588* tan_azimuth) + 0.035189;} if ((tan_azimuth >= 0.5774)&&(tan_azimuth < 1.0)) {sun_azimuth = (0.6195* tan_azimuth) + 0.1659;} if ((tan_azimuth >= 1.0)&&(tan_azimuth < 1.3032)) {sun_azimuth = (0.43173* tan_azimuth) + 0.3537;} if ((tan_azimuth >= 1.3032)&&(tan_azimuth < 1.7321)) {sun_azimuth = ( 0.3052* tan_azimuth) + 0.51856;} if ((tan_azimuth >= 1.7321)&&(tan_azimuth < 2.4142)) {sun_azimuth = (0.1919* tan_azimuth) + 0.7148;} if ((tan_azimuth >= 2.4142)&&(tan_azimuth < 2.9459)) {sun_azimuth = (0.123* tan_azimuth) + 0.88115;} if ((tan_azimuth >= 2.9459)&&(tan_azimuth < 3.7321)) {sun_azimuth = (0.083312* tan_azimuth) + 0.9981;} if ((tan_azimuth >= 3.7321)&&(tan_azimuth < 5.0)) {sun_azimuth = (0.050792* tan_azimuth) + 1.1194;} if ((tan_azimuth >= 5.0)&&(tan_azimuth <7.0)) {sun_azimuth = (0.02775* tan_azimuth) + 1.23465;} if ((tan_azimuth >= 7.0 )&&(tan_azimuth <12.0)) {sun_azimuth = (0.01175117* tan_azimuth) + 1.346641;} if ((tan_azimuth >= 12.0)&&(tan_azimuth <20.0)) {sun_azimuth = (0.004147854* tan_azimuth) + 1.437881;} if (( tan_azimuth >= 20.0)&&(tan_azimuth <50.0)) {sun_azimuth = (0.0009987* tan_azimuth) + 1.5008639;} if (tan_azimuth >= 50.0) {sun_azimuth = (0.000099983* tan_azimuth) + 1.54579974;}
if (sun_azimuth > 1.5707963278) {sun_azimuth = 1.5707963278;}
if (sign == false) {sun_azimuth = (-1.0) * sun_azimuth;}
sun_azimuth = 57.29577951 * sun_azimuth;
if (plus180 == true) {sun_azimuth = sun_azimuth + 180.0;}
! Daily correction and save values to system variablesif (afternoon == false)
{sun_azimuth = 180.0 - sun_azimuth; solar time = 720 - solar time;}
else
{sun_azimuth = sun_azimuth + 180.0;solar time = 720 + solar time;}
sun_azimuth = 0.1 ((sun_azimuth10.0) .ToInteger());
sun_elevation = 0.1 ((sun_elevation10.0) .ToInteger());
dom.GetObject("sonne_elevation").State(sonne_elevation);
dom.GetObject("sun_azimuth").State(sun_azimuth);