13.12.2016, 19:45
(This post was last modified: 12.01.2017, 12:57 by Erwin van der Zwart.)
Hi Josep,
Make sure this function is inside common functions:
Then create a resident script with time 60 seconds and add this code:
If you want to combine it with a scheduler then make a 'and' logic, put the output of this script to input 1, output of the schedular to input 2 and the control object to the output of your 'and' logic.
BR,
Erwin
Make sure this function is inside common functions:
Code:
-- sunrise / sunset calculation
function rscalc(latitude, longitude, when)
local pi = math.pi
local doublepi = pi * 2
local rads = pi / 180.0
local TZ = function(when)
local ts = os.time(when)
local utcdate, localdate = os.date('!*t', ts), os.date('*t', ts)
localdate.isdst = false
local diff = os.time(localdate) - os.time(utcdate)
return math.floor(diff / 3600)
end
local range = function(x)
local a = x / doublepi
local b = doublepi * (a - math.floor(a))
return b < 0 and (doublepi + b) or b
end
when = when or os.date('*t')
local y2k = { year = 2000, month = 1, day = 1 }
local y2kdays = os.time(when) - os.time(y2k)
y2kdays = math.ceil(y2kdays / 86400)
local meanlongitude = range(280.461 * rads + 0.9856474 * rads * y2kdays)
local meananomaly = range(357.528 * rads + 0.9856003 * rads * y2kdays)
local lambda = range(meanlongitude + 1.915 * rads * math.sin(meananomaly) + rads / 50 * math.sin(2 * meananomaly))
local obliq = 23.439 * rads - y2kdays * rads / 2500000
local alpha = math.atan2(math.cos(obliq) * math.sin(lambda), math.cos(lambda))
local declination = math.asin(math.sin(obliq) * math.sin(lambda))
local LL = meanlongitude - alpha
if meanlongitude < pi then
LL = LL + doublepi
end
local dfo = pi / 216.45
if latitude < 0 then
dfo = -dfo
end
local fo = math.min(math.tan(declination + dfo) * math.tan(latitude * rads), 1)
local ha = 12 * math.asin(fo) / pi + 6
local timezone = TZ(when)
local equation = 12 + timezone + 24 * (1 - LL / doublepi) - longitude / 15
local sunrise, sunset = equation - ha, equation + ha
if sunrise > 24 then
sunrise = sunrise - 24
end
if sunset > 24 then
sunset = sunset - 24
end
return math.floor(sunrise * 60), math.ceil(sunset * 60)
end
Then create a resident script with time 60 seconds and add this code:
Code:
-- ***** Astronomic clock module Version 1.0 Created by Erwin van der Zwart ***** --
-- ********* Use this script as resident script and run every 60 seconds ******** --
-- ****** This script makes use of rscalc function inside common functions ****** --
-- ******************************** SET PARAMETERS ****************************** --
-- Set output address
adressoutput = '1/1/1' -- 1 bit output for control object
-- Set time shifting addresses
addressshifttimesunrice = '1/1/2' -- 1 or 2 byte signed integer to be able to adjust/offset calculated sunrise time (set min/max on object)
addressshifttimesundown = '1/1/3'-- 1 or 2 byte signed integer to be able to adjust/offset calculated down time (set min/max on object)
-- Set feedback adresses
addresssunrise = '1/1/4' -- 255 byte object for user feedback, shows calculated sunrise time
addresssundown = '1/1/5' -- 255 byte object for user feedback, shows calculated sundown time
addresssunriseshifted = '1/1/6' -- 255 byte object for user feedback, shows with offset calculated sunrise time
addressundownshifted = '1/1/7' -- 255 byte object for user feedback, shows with offset calculatedsundown time
-- Set location coordinates
latitude = 52.52198 --Zwolle Netherlands, Look at 'http://www.mapcoordinates.net/en' for other locations
longitude = 6.08213 --Zwolle Netherlands, Look at 'http://www.mapcoordinates.net/en' for other locations
-- ******************************** END PARAMETERS ****************************** --
-- ********************* DON'T CHANGE ANYTHING UNDER THIS LINE ****************** --
-- Function to calculate switching times based and output value
function astronomic(latitude,longitude,shiftedsunrise,shiftedsundown)
local now = os.date('*t')
local sunrise, sunset = rscalc(latitude, longitude, now) --Zwolle Netherlands, See http://www.mapcoordinates.net/en for other locations
sunriseorg = string.format('%d:%.2d', math.floor(sunrise / 60), sunrise % 60)
sunsetorg = string.format('%d:%.2d', math.floor(sunset / 60), sunset % 60)
sunrisenew = sunrise + shiftedsunrise
sunsetnew = sunset + shiftedsundown
sunrisetime = string.format('%d:%.2d', math.floor(sunrisenew / 60), sunrisenew % 60)
sunsettime = string.format('%d:%.2d', math.floor(sunsetnew / 60), sunsetnew % 60)
local minutes = now.hour * 60 + now.min
nowdark = minutes < sunrisenew or sunsetnew < minutes
local t = {sunricenormal = sunriseorg, sundownnormal = sunsetorg, sunriceshifted = sunrisetime, sundownshifted = sunsettime, output = nowdark}
return (t)
end
-- Get values for timeshifting
shiftedsunrise = grp.getvalue(addressshifttimesunrice) or 0 -- Make minutes negative to switch earlyer than normal calculated sunrice and positive to switch later than normal calculated sunrice
shiftedsundown = grp.getvalue(addressshifttimesundown) or 0 -- Make minutes negative to switch earlyer than normal calculated sundown and positive to switch later than normal calculated sundown
-- Call function to calculate astroinfo
astroinfo = astronomic(latitude,longitude,shiftedsunrise,shiftedsundown)
-- Set new sunrice time (unshifted)
currentvalue = grp.getvalue(addresssunrise)
if astroinfo.sunricenormal ~= currentvalue then
grp.update(addresssunrise, astroinfo.sunricenormal)
end
-- Set new sundown time (unshifted)
currentvalue = grp.getvalue(addresssundown)
if astroinfo.sundownnormal ~= currentvalue then
grp.update(addresssundown, astroinfo.sundownnormal)
end
-- Set new sunrice time (shifted)
currentvalue = grp.getvalue(addresssunriseshifted)
if astroinfo.sunriceshifted ~= currentvalue then
grp.update(addresssunriseshifted, astroinfo.sunriceshifted)
end
-- Set new sundown time (shifted)
currentvalue = grp.getvalue(addressundownshifted)
if astroinfo.sundownshifted ~= currentvalue then
grp.update(addressundownshifted, astroinfo.sundownshifted)
end
-- Set output value to output object
currentvalue = grp.getvalue(adressoutput)
if astroinfo.output == true then
if currentvalue == false then
grp.write(adressoutput, true)
end
else
if currentvalue == true then
grp.write(adressoutput, false)
end
end
If you want to combine it with a scheduler then make a 'and' logic, put the output of this script to input 1, output of the schedular to input 2 and the control object to the output of your 'and' logic.
BR,
Erwin