Closed openhab-bot closed 10 years ago
this lib looks promising http://www.jstott.me.uk/jsuntimes/
I use these fields in Misterhouse, would welcome them in Openhab: $Time_Sunset_Twilight, $Time_Sunrise_Twilight, $Dark: true between $Time_Sunset_Twilight and $Time_Sunrise_Twilight, false otherwise. These are more relevant than fixed offsets before sunrise and after sunset.
This can be achieved by using the following (thanks RaK for providing the base script)
################################################# import org.openhab.core.library.types.* import java.lang.Math
// constants var Number K = 0.017453
// coordinates (see Google-Maps) var Number latitude = xx.xxxxxx var Number longitude = xx.xxxxxx
rule "Calculate Sunheight and Azimut" when Time cron "0 0/5 * * * ?" then var Number tageszahl var Number deklination var Number zeitgleichung var Number stundenwinkel var Number x var Number y var Number sonnenhoehe var Number azimut
var month = now.getMonthOfYear
var day = now.getDayOfMonth
var hour = now.getHourOfDay
var minute = now.getMinuteOfHour
// Source: http://www.jgiesen.de/SME/tk/index.htm
tageszahl = (month - 1) * 30 + day + hour / 24
deklination = -23.45 * Math::cos((K * 360 * (tageszahl + 10) / 365).doubleValue)
zeitgleichung = 60.0 * (-0.171 * Math::sin((0.0337*tageszahl+0.465).doubleValue) - 0.1299 * Math::sin((0.01787*tageszahl-0.168).doubleValue))
stundenwinkel = 15.0 * (hour.doubleValue + (minute.doubleValue/60.0) - (15.0-longitude)/15.0 - 12.0 + zeitgleichung/60.0)
x = Math::sin((K * latitude).doubleValue()) * Math::sin((K * deklination).doubleValue()) + Math::cos((K * latitude).doubleValue()) * Math::cos((K * deklination).doubleValue()) * Math::cos((K * stundenwinkel).doubleValue())
y = - (Math::sin((K*latitude).doubleValue) * x - Math::sin((K*deklination).doubleValue)) / (Math::cos((K*latitude).doubleValue) * Math::sin(Math::acos(x.doubleValue)))
sonnenhoehe = Math::asin(x.doubleValue) / K
var break = hour.doubleValue + (minute.doubleValue/60.0) <= 12.0 + (15.0-longitude)/15.0 - zeitgleichung/60.0
if (break) {
azimut = Math::acos(y.doubleValue) / K
} else {
azimut = 360.0 - Math::acos(y.doubleValue) / K
}
logDebug("Sun.rules", "Calculated new SunHeight angle '" + sonnenhoehe + "°'")
logDebug("Sun.rules", "Calculated new Azimut angle '" + azimut + "°'")
// post new values to the bus
Sun_Height.postUpdate(sonnenhoehe)
Sun_Azimut.postUpdate(azimut)
end
#################################################
furthermore you need two new items of type 'Number'
In order to react properly please add other rules with an Item-Changed-Trigger in Sun_Height or Sun_Azimut which in turn can do all the time tweaks using joda-time
Does that suite your needs?
may be this will also help:
import org.openhab.core.library.types. import org.openhab.model.script.actions.
import java.lang.Math import java.util.Date import java.util.Calendar import org.joda.time.DateTime
// Change this reflecting your destination var Number lat = x.xxxx var Number lng = y.yyyy
var Calendar sunrise = Calendar::getInstance() var Calendar sunset = Calendar::getInstance()
rule "Sun" when Time cron "0 0/30 * * * ?" then // http://www.suncalc.net var J1970 = 2440588 var J2000 = 2451545 var deg2rad = Math::PI / 180 var M0 = 357.5291 * deg2rad var M1 = 0.98560028 * deg2rad var J0 = 0.0009 var J1 = 0.0053 var J2 = -0.0069 var C1 = 1.9148 * deg2rad var C2 = 0.0200 * deg2rad var C3 = 0.0003 * deg2rad var P = 102.9372 * deg2rad var e = 23.45 * deg2rad var th0 = 280.1600 * deg2rad var th1 = 360.9856235 * deg2rad var h0 = -0.83 * deg2rad //sunset angle var d0 = 0.53 * deg2rad //sun diameter var h1 = -6 * deg2rad //nautical twilight angle var h2 = -12 * deg2rad //astronomical twilight angle var h3 = -18 * deg2rad //darkness angle var msInDay = 1000 * 60 * 60 * 24 var lw = -lng * deg2rad var phi = lat * deg2rad
var datum = new Date()
var J = datum.getTime() / msInDay - 0.5 + J1970
var n = Math::round( (J - J2000 - J0 - lw/(2 * Math::PI)).doubleValue)
var Js = (J2000 + J0 + (0 + lw)/(2 * Math::PI) + n)
var M = ( M0 + M1 * (Js - J2000))
var C = C1 * Math::sin(M.doubleValue) + C2 * Math::sin((2 * M).doubleValue) + C3 * Math::sin((3 * M).doubleValue)
var Lsun = M + P + C + Math::PI
var Jtransit = Js + (J1 * Math::sin(M.doubleValue)) + (J2 * Math::sin((2 * Lsun).doubleValue))
var d = Math::asin((Math::sin(Lsun.doubleValue) * Math::sin(e.doubleValue)).doubleValue)
var w0 = Math::acos(((Math::sin(h0.doubleValue) - Math::sin(phi.doubleValue) * Math::sin(d.doubleValue)) / (Math::cos(phi.doubleValue) * Math::cos(d.doubleValue))).doubleValue)
var w1 = Math::acos(((Math::sin((h0+d0).doubleValue) - Math::sin(phi.doubleValue) * Math::sin(d.doubleValue)) / (Math::cos(phi.doubleValue) * Math::cos(d.doubleValue))).doubleValue)
var Jset = J2000 + J0 + (w0 + lw)/(2 * Math::PI) + n + (J1 * Math::sin(M.doubleValue)) + (J2 * Math::sin((2 * Lsun).doubleValue))
var Jsetstart = J2000 + J0 + (w1 + lw)/(2 * Math::PI) + n + (J1 * Math::sin(M.doubleValue)) + (J2 * Math::sin((2 * Lsun).doubleValue))
var Jrise = Jtransit - (Jset - Jtransit)
var Jriseend = Jtransit - (Jsetstart - Jtransit)
var sunrise_ms_start = ( (Jrise + 0.5 - J1970) * msInDay).longValue
var sunrise_ms_end = ( (Jriseend + 0.5 - J1970) * msInDay).longValue
var sunset_ms_start = ((Jsetstart + 0.5 - J1970) * msInDay).longValue
var sunset_ms_end = ((Jset + 0.5 - J1970) * msInDay).longValue
// Items:
// DateTime SunRise "Sonnenaufgang [%1$tA, %1$td.%1$tm.%1$tY %1$tT]" <calendar>
// DateTime SunSet "Sonnenuntergang [%1$tA, %1$td.%1$tm.%1$tY %1$tT]" <calendar>
var Calendar sunrise_start = Calendar::getInstance()
sunrise_start.setTimeInMillis( sunrise_ms_start )
SunRise.postUpdate( new DateTimeType(sunrise_start))
var Calendar sunset_start = Calendar::getInstance()
sunset_start.setTimeInMillis( sunset_ms_start )
SunSet.postUpdate( new DateTimeType(sunset_start))
end
Can someon confirm that comment #4 give valid results? I tried it for my self (northern germany) and got
SunRise 3:44 seems to be wrong SunSet 15:16 seens to be UTC, so this is correct
while Google gives me
SunRise 8:34 local SunSet 16:17 local
This code works for me : import org.openhab.core.library.types.* import java.lang.Math
// Constants var Number K = 0.017453
// Change this reflecting your destination var Number latitude = 50.892 var Number longitude = 4.733
rule "Set Sun and Dawn States" when Time cron "0 0/5 * * * ?" then var Number tageszahl var Number deklination var Number zeitgleichung var Number stundenwinkel var Number x var Number y var Number sonnenhoehe var Number azimut
var month = now.getMonthOfYear
var day = now.getDayOfMonth
var hour = now.getHourOfDay
var minute = now.getMinuteOfHour
// Source: http://www.jgiesen.de/SME/tk/index.htm
tageszahl = (month - 1) * 30 + day + hour / 24
deklination = -23.45 * Math::cos((K * 360 * (tageszahl + 10) / 365).doubleValue)
zeitgleichung = 60.0 * (-0.171 * Math::sin((0.0337*tageszahl+0.465).doubleValue) - 0.1299 * Math::sin((0.01787*tageszahl-0.168).doubleValue))
stundenwinkel = 15.0 * (hour.doubleValue + (minute.doubleValue/60.0) - (15.0-longitude)/15.0 - 12.0 + zeitgleichung/60.0)
x = Math::sin((K * latitude).doubleValue()) * Math::sin((K * deklination).doubleValue()) + Math::cos((K * latitude).doubleValue()) * Math::cos((K * deklination).doubleValue()) * Math::cos((K * st
undenwinkel).doubleValue()) y = - (Math::sin((K_latitude).doubleValue) * x - Math::sin((K_deklination).doubleValue)) / (Math::cos((Klatitude).doubleValue) \ Math::sin(Math::acos(x.doubleValue))) sonnenhoehe = Math::asin(x.doubleValue) / K
var break = hour.doubleValue + (minute.doubleValue/60.0) <= 12.0 + (15.0-longitude)/15.0 - zeitgleichung/60.0
if (break) {
azimut = Math::acos(y.doubleValue) / K
} else {
azimut = 360.0 - Math::acos(y.doubleValue) / K
}
logDebug("Sun.rules", "month: " + month)
logDebug("Sun.rules", "day: " + day)
logDebug("Sun.rules", "hour: " + hour)
logDebug("Sun.rules", "minute: " + minute)
logDebug("Sun.rules", "tageszahl: " + tageszahl)
logDebug("Sun.rules", "deklination: " + deklination)
logDebug("Sun.rules", "zeitgleichung: " + zeitgleichung)
logDebug("Sun.rules", "stundenwinkel: " + stundenwinkel)
logDebug("Sun.rules", "x: " + x)
logDebug("Sun.rules", "y: " + y)
logDebug("Sun.rules", "sonnenhoehe: " + sonnenhoehe)
logDebug("Sun.rules", "azimut: " + azimut)
logDebug("Sun.rules", "Calculated new SunHeight angle '" + sonnenhoehe + "°'")
logDebug("Sun.rules", "Calculated new Azimut angle '" + sonnenhoehe + "°'")
// Send all calculations to the event bus
Sun_Height.postUpdate(sonnenhoehe)
Sun_Azimut.postUpdate(azimut)
Daytime.postUpdate( if (sonnenhoehe > 0) OPEN else CLOSED )
if (hour > 3 && hour < 10){
Sun_Dawn_Civil.postUpdate( if (sonnenhoehe > -6 && sonnenhoehe < 0 ) OPEN else CLOSED )
Sun_Dawn_Nautical.postUpdate( if (sonnenhoehe > -12 && sonnenhoehe < -6 ) OPEN else CLOSED )
Sun_Dawn_Astronomical.postUpdate( if (sonnenhoehe > -18 && sonnenhoehe < -12) OPEN else CLOSED )
} if (hour > 15 && hour < 21) {
Sun_Dusk_Civil.postUpdate( if (sonnenhoehe > -6 && sonnenhoehe < 0 ) OPEN else CLOSED )
Sun_Dusk_Nautical.postUpdate( if (sonnenhoehe > -12 && sonnenhoehe < -6 ) OPEN else CLOSED )
Sun_Dusk_Astronomical.postUpdate( if (sonnenhoehe > -18 && sonnenhoehe < -12) OPEN else CLOSED )
}
end
in items
Contact Sun_Dawn_Civil "Zon dawn civil [MAP(sunstates.map):%S]"
Maybe this helps. Regards, Nico
Shame on me ... i mixed up the variables "lng" and "lat". :(
Apr 2, 2013 Delete comment #8 kristian.backstrom It seems to me, that #4 gives good results for sunrise / sunset.
It also seems to me that #6 gives me negative sun height values quite too early in the evenings. My coordinates are roughly 25,66E and 60,39N (if you like to test).
Have anyone written a rule for calculating the solar beam hitting angle against flat solar collectors for a given time? The additional parameters would naturally be panel tilt angle and panel rotation angle.
I would like to forecast their power, by also using weather forecasts for estimating the cloud cover.
Regards, Kristian
Apr 3, 2013 Delete comment Project Member #9 teichsta good question ...
I would propose to ask the question on the google group since there are more observers than on this issue.
Regards,
Thomas E.-E.
Jun 28, 2013 Delete comment #11 Erland.Lestander For sake of completness, two booleans should be made available as well: MidnightSun and MidWinterDarkness, or something similiar in name. Those should indicate when we are outside of the valid region for the equation, i.e. when the sun doesn't set resp. rise. Then the equation work for everybody (on this planet).
Jul 17, 2013 Delete comment #12 evazzoler Why not integrate this into the official code with the next release?
Jul 18, 2013 Delete comment Project Member #13 teichsta we could add the calculation rule to the demo package, yes
Jul 24, 2013 Delete comment #14 enrico.vazzoler@archeometra.it No, I meant in the code giving the possibility to use a short syntax in a rule:
"Time is sunset" or "Time is sunrise.plusHours(2)"
Pay attention on this: there is no home automation where no astronomical timer is provided...
Jul 24, 2013 Delete comment Project Member #15 belovictor I would agree with that, those functions should be nicely available.
Jul 25, 2013 Delete comment Project Member #16 kai.openhab sounds like a good idea, yes.
Sep 15, 2013 Delete comment #17 mg@subscribe.audumla.net This is something that I needed for my own Apache Karaf project. I'm in the process of converting it from Apache Karaf to OpenHab but will have difficulty converting the sunrise/sunset functionality as OpenHab is quite restricted regarding extension of the trigger mechanism. This component really should allow an extensible mechanism of allowing custom triggers to be written and deployed as bundles. In the meantime I will try to package up my Quartz Astrological Scheduler and make it available. As OpenHab uses Quartz it would fit straight in if the createTimer method was changed to switch schedulers instead of statically using the cron scheduler.
Sep 16, 2013 Delete comment Project Member #18 kai.openhab For the Eclipse SmartHome project, I plan to further modularize the rule engine - triggers as addons definitely sound like a good idea.
meanwhile the Astro-Binding (see https://github.com/openhab/openhab/wiki/Astro-binding) has been implemented which should solve the problem
Original issue: http://code.google.com/p/openhab/issues/detail?id=71