Jump to content

Welcome to Smart Home Forum by FIBARO

Dear Guest,

 

as you can notice parts of Smart Home Forum by FIBARO is not available for you. You have to register in order to view all content and post in our community. Don't worry! Registration is a simple free process that requires minimal information for you to sign up. Become a part of of Smart Home Forum by FIBARO by creating an account.

 

As a member you can:

  •     Start new topics and reply to others
  •     Follow topics and users to get email updates
  •     Get your own profile page and make new friends
  •     Send personal messages
  •     ... and learn a lot about our system!

 

Regards,

Smart Home Forum by FIBARO Team


  • 0

calculate time when sun is 8 degrees below the horizon


Question

Posted

Hi

Can someone help to update a global variable with time that the sun will hit 8 degrees below the horizon?

Many thanks.

19 answers to this question

Recommended Posts

  • 0
Posted

Do you mean some code to update a variable or do you mean calculate sunset?

 

like this code for sunset

 

 

  • 0
Posted (edited)

Please login or register to see this link.

 

Maybe you need a little suncalc :) I love this site, someday i will also work out how

to use the API. But here, you can select your exact position. And find out on what time

the sun gives shadow or sunlight on that position.

 

Cant help you with the API. 

Edited by ppeterr
  • 0
Posted

Looks great. What could you do with it in Homeautomation?

  • 0
Posted (edited)
2 hours ago, SmartHomeEddy said:

Looks great. What could you do with it in Homeautomation?

 

Well, move my luxaflex indoor powerview sun shades to preset positions when the sun 

stands on a certain degree so it keeps the sun out of the television :)

 

 - and put the somfy outdoor sunshades on position to keep the sun outside in the summer.

 

Well, something like that. I wil have it working before next summer :P

 

Anyway, back to @Jay Ess What do you want to achieve

Edited by ppeterr
  • 0
Posted (edited)

A pity this API doesn’t gives back json 

 

 

 

Edited by SmartHomeEddy
  • 0
  • Inquirer
  • Posted (edited)
    21 hours ago, SmartHomeEddy said:

    Do you mean some code to update a variable or do you mean calculate sunset?

     

    like this code for sunset

     

     

    I am using this code in a vd to calculate the times, the problems i am having are two fold, one a minor issue is the sunset and sunrise times of the hc3 is different then the times this vd gives out by approx 1 minute, the second more important issue is the time which my vd gives as 8 degrees is out by approx 0.5 degree and am unsure how to fix this or to verify that the time is correct.

     

    CODE of VD:

     


    -- shortcuts for easier to read formulas
    PI = math.pi
    sin = math.sin
    cos = math.cos
    tan = math.tan
    asin = math.asin
    atan = math.atan2
    acos = math.acos
    rad = PI / 180
    -- sun calculations are based on

    Please login or register to see this link.

    formulas
    -- date/time constants and conversions
    dayMs = 1000 * 60 * 60 * 24
    J1970 = 2440588
    J2000 = 2451545
     
    function toJulian(date)
        return date / dayMs - 0.5 + J1970
    end
    function fromJulian(j)
        return (j + 0.5 - J1970) * dayMs
    end
    function toDays(date)
        return toJulian(date) - J2000
    end
    -- general calculations for position
    e = rad * 23.4397 -- obliquity of the Earth
    function rightAscension(l, b)
        return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l))
    end
    function declination(l, b)
        return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l))
    end
    function azimuth(H, phi, dec)
        return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi))
    end
    function altitude(H, phi, dec)
        return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H))
    end
    function siderealTime(d, lw)
        return rad * (280.16 + 360.9856235 * d) - lw
    end
    function astroRefraction(h)
        if (h < 0) then -- the following formula works for positive altitudes only.
            h = 0 -- if h = -0.08901179 a div/0 would occur.
        end
        -- formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998.
        -- 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad:
        return 0.0002967 / math.tan(h + 0.00312536 / (h + 0.08901179))
    end
    -- general sun calculations
    function solarMeanAnomaly(d)
        return rad * (357.5291 + 0.98560028 * d)
    end
    function eclipticLongitude(M)
        local C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)) -- equation of center
        local P = rad * 102.9372 -- perihelion of the Earth

     
        return M + C + P + PI
    end
    function sunCoords(d)
        M = solarMeanAnomaly(d)
        L = eclipticLongitude(M)
        return {
            dec = declination(L, 0),
            ra = rightAscension(L, 0)
        }
    end

    SunCalc = {}
    -- calculates sun position for a given date and latitude/longitude
    SunCalc.getPosition = function(date, lat, lng)
        lw = rad * -lng
        phi = rad * lat
        d = toDays(date)
        c = sunCoords(d)
        H = siderealTime(d, lw) - c.ra
        return {
            azimuth = azimuth(H, phi, c.dec),
            altitude = altitude(H, phi, c.dec)
        }
    end
    -- sun times configuration (angle, morning name, evening name)
    times = {
        {-0.833, "sunrise", "sunset"},
        {-0.3, "sunriseEnd", "sunsetStart"},
        {-3, "curtaindawn", "curtaindusk"},
        {-6, "dawn", "dusk"},
        {-12, "nauticalDawn", "nauticalDusk"},
        {-18, "nightEnd", "night"},
        {6, "goldenHourEnd", "goldenHour"},
        {-4, "blueHourDawnEnd", "blueHourDusk"},
        {-8, "blueHourDawn", "blueHourDuskEnd"}
    }
    -- adds a custom time to the times config
    SunCalc.addTime = function(angle, riseName, setName)
        table.insert(times, {angle, riseName, setName})
    end
    -- calculations for sun times
    J0 = 0.0009
    function julianCycle(d, lw)
        return math.round(d - J0 - lw / (2 * PI))
    end
    function approxTransit(Ht, lw, n)
        return J0 + (Ht + lw) / (2 * PI) + n
    end
    function solarTransitJ(ds, M, L)
        return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L)
    end
    function hourAngle(h, phi, d)
        return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d)))
    end
    -- returns set time for the given sun altitude
    function getSetJ(h, lw, phi, dec, n, M, L)
        w = hourAngle(h, phi, dec)
        a = approxTransit(w, lw, n)
        return solarTransitJ(a, M, L)
    end
    -- calculates sun times for a given date and latitude/longitude
    SunCalc.getTimes = function(date, lat, lng)
        lw = rad * -lng
        phi = rad * lat
        d = toDays(date)
        n = julianCycle(d, lw)
        ds = approxTransit(0, lw, n)
        M = solarMeanAnomaly(ds)
        L = eclipticLongitude(M)
        dec = declination(L, 0)
        Jnoon = solarTransitJ(ds, M, L)
        i, len, time, Jset, Jrise = nil
        result = {
            solarNoon = fromJulian(Jnoon),
            nadir = fromJulian(Jnoon - 0.5)
        }
        for i = 1, table.length(times) do
            time = times[i]
            Jset = getSetJ(time[1] * rad, lw, phi, dec, n, M, L)
            Jrise = Jnoon - (Jset - Jnoon)
            result[time[2]] = fromJulian(Jrise)
            result[time[3]] = fromJulian(Jset)
        end
        return result
    end
    -- moon calculations, based on

    Please login or register to see this link.

    formulas
    function moonCoords(d) -- geocentric ecliptic coordinates of the moon
        L = rad * (218.316 + 13.176396 * d) -- ecliptic longitude
        M = rad * (134.963 + 13.064993 * d) -- mean anomaly
        F = rad * (93.272 + 13.229350 * d) -- mean distance
        l = L + rad * 6.289 * sin(M) -- longitude
        b = rad * 5.128 * sin(F) -- latitude
        dt = 385001 - 20905 * cos(M) -- distance to the moon in km
        return {
            ra = rightAscension(l, b),
            dec = declination(l, b),
            dist = dt
        }
    end
    SunCalc.getMoonPosition = function(date, lat, lng)
        lw = rad * -lng
        phi = rad * lat
        d = toDays(date)
        c = moonCoords(d)
        H = siderealTime(d, lw) - c.ra
        h = altitude(H, phi, c.dec)
        -- formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998.
        pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H))
        h = h + astroRefraction(h) -- altitude correction for refraction
        return {
            azimuth = azimuth(H, phi, c.dec),
            altitude = h,
            distance = c.dist,
            parallacticAngle = pa
        }
    end
    -- calculations for illumination parameters of the moon,
    -- based on

    Please login or register to see this link.

    formulas and
    -- Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998.
    SunCalc.getMoonIllumination = function(date)
        d = toDays(date)
        s = sunCoords(d)
        m = moonCoords(d)
        sdist = 149598000 -- distance from Earth to Sun in km
        phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra))
        inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi))
        angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra))
        return {
            fraction = (1 + cos(inc)) / 2,
            phase = 0.5 + 0.5 * inc * (angle < 0 and -1 or 1) / math.pi,
            angle = angle
        }
    end
    function hoursLater(date, h)
        return date + h * dayMs / 24
    end
    -- calculations for moon rise/set times are based on

    Please login or register to see this link.

    article
    SunCalc.getMoonTimes = function(date, lat, lng)
        t = date
        hc = 0.133 * rad
        h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc
        h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx = nil
        -- go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set)
        for i = 1, 24, 2 do
            h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc
            h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc
            a = (h0 + h2) / 2 - h1
            b = (h2 - h0) / 2
            xe = -b / (2 * a)
            ye = (a * xe + b) * xe + h1
            d = b * b - 4 * a * h1
            roots = 0
            if d >= 0 then
                dx = math.sqrt(d) / (math.abs(a) * 2)
                x1 = xe - dx
                x2 = xe + dx
                if math.abs(x1) <= 1 then
                    roots = roots + 1
                end
                if math.abs(x2) <= 1 then
                    roots = roots + 1
                end
                if x1 < -1 then
                    x1 = x2
                end
            end
            if roots == 1 then
                if h0 < 0 then
                    rise = i + x1
                else
                    set = i + x1
                end
            elseif roots == 2 then
                rise = i + (ye < 0 and x2 or x1)
                set = i + (ye < 0 and x1 or x2)
            end
            if rise and set then
                break
            end
            h0 = h2
        end
        result = {}
        if rise then
            result.rise = hoursLater(t, rise)
        end
        if set then
            result.set = hoursLater(t, set)
        end
        if not rise and not set then
            result[ye > 0 and "alwaysUp" or "alwaysDown"] = true
        end
        return result
    end
    -- ---------- NOT PART OF THE ORIGINAL SCRIPT - HAD TO BE ADDED FOR THE SCRIPT TO WORK IN LUA ----------
    function math.round(num, numDecimalPlaces)
        local mult = 10 ^ (numDecimalPlaces or 0)
        return math.floor(num * mult + 0.5) / mult
    end
    function table.length(T)
        local count = 0
        for _ in pairs(T) do
            count = count + 1
        end
        return count
    end
    --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==
    function getKeysSortedByValue(tbl, sortFunction)
        local keys = {}
        for key in pairs(tbl) do
            table.insert(keys, key)
        end

     
        table.sort(
            keys,
            function(a, b)
                return sortFunction(tbl[a], tbl[b])
            end
        )

     
        return keys
    end

     
    function formatTime(tm)
        return os.date("%H:%M", math.floor(tm / 1000))
    end

     
    local events = {
        ["nauticalDawn"] = 1,
        ["blueHourDawn"] = 2,
        ["dawn"] = 3,
        ["blueHourDawnEnd"] = 4,
        ["sunrise"] = 5,
        ["sunriseEnd"] = 6,
        ["goldenHourEnd"] = 7,
        ["solarNoon"] = 8,
        ["goldenHour"] = 9,
        ["sunsetStart"] = 10,
        ["sunset"] = 11,
        ["blueHourDusk"] = 12,
        ["dusk"] = 13,
        ["blueHourDuskEnd"] = 14,
        ["nauticalDusk"] = 15,
        ["night"] = 16,
        ["nadir"] = 17,
        ["nightEnd"] = 18
    }

     
    function dump(o)
        if type(o) == "table" then
            local s = "{ "
            for k, v in pairs(o) do
                if type(k) ~= "number" then
                    k = '"' .. k .. '"'
                end
                s = s .. "[" .. k .. "] = " .. dump(v) .. ","
            end
            return s .. "} "
        else
            return tostring(o)
        end
    end

     
    local location = api.get("/panels/location")
    local lat = location[1].latitude
    local lon = location[1].longitude

     
    function QuickApp:sunCalc()
        local mDate = os.time() * 1000
        local sunTimes = SunCalc.getTimes(mDate, lat, lon)
        local sunrise, sunset, dawn, dusk, solarNoon, curtaindusk, blueHourDuskEnd =
            formatTime(sunTimes["sunrise"]),
            formatTime(sunTimes["sunset"]),
            formatTime(sunTimes["dawn"]),
            formatTime(sunTimes["dusk"]),
            formatTime(sunTimes["solarNoon"]),
            formatTime(sunTimes["curtaindusk"]),
            formatTime(sunTimes["blueHourDuskEnd"])
        local PlagHamincha = formatTime(sunTimes["sunset"] -(((sunTimes["sunset"] - sunTimes["sunrise"])/12)*1.25))
        -- print(sunrise, sunset, dawn, dusk);
     
        fibaro.setGlobalVariable("Sunrise", sunrise)
        fibaro.setGlobalVariable("Sunset", sunset)
        fibaro.setGlobalVariable("SunriseTwilight", dawn)
        fibaro.setGlobalVariable("SunsetTwilight", dusk)
        fibaro.setGlobalVariable("midDay", solarNoon)
        fibaro.setGlobalVariable("curtaindusk", curtaindusk)
        fibaro.setGlobalVariable("shabbosEndTime", blueHourDuskEnd)
        fibaro.setGlobalVariable("plagHamincha", PlagHamincha)
     
        self:updateView(
            "lblStatus",
            "text",
            "?" .. dawn .. "|" .. "?" .. sunrise .. "|" .. "?" .. sunset .. "|" .. "" .. dusk
        )
        local sortedKeys =
            getKeysSortedByValue(
            sunTimes,
            function(a, b)
                return a < b
            end
        )
        local dayPart = nil
        for _, key in ipairs(sortedKeys) do
            if sunTimes[key] <= mDate then
                dayPart = key
            end
        end
        dayPart = dayPart or "night"
        self:updateProperty("log", dayPart)
        dayPart = {dayPart = dayPart, dayPartIndex = events[dayPart]}
        fibaro.setGlobalVariable("DayPart", json.encode(dayPart))
    end
     
    function QuickApp:onInit()
        self:debug("onInit")
        self:updateProperty("deviceIcon", 1014)  
        self:sunCalc()
        setInterval(
            function()
                self:sunCalc()
            end,
            1000 * 60 * 1
        )
    end

    Edited by Jay Ess
    incorrect format
    • 0
    Posted (edited)

    That is a whole lot of calculations from @10der ?

     

    Did you compare the results from the HC2 and HC3 to for example the link @ppeterr posted: 

    Please login or register to see this link.

     

    Just to know which one is more accurate?

     

     

     

    Edited by SmartHomeEddy
    • Thanks 1
    • 0
  • Inquirer
  • Posted

    @SmartHomeEddy thank you for that, there was no comment in the vd and was not sure who had written it originally.

    Have compared it to with the link you have given me and this is what i get:

    Point of time -  VD time - Web Time(web time rounded up)

    Sunrise Twilight - 06.05 - 6.03.47 (6.04)

    Sunrise - 06.40 - 6.38.51 (6.39)

    Sunset - 19.32 - 19.29.47 (19.30)

    Sunset Twilight - 20.07 - 20.04.43 (20.05)

    8 degrees below - 20.21 - 20.19

     

    in the morning it is about 1 minute out and in the evening about 2 minutes out, i have found the -8 degrees to be out by up to 3 minutes and either the calculation are out a little or maybe some other issue is there?

    • 0
    Posted

    How did the HC3 do in this check?

     

    • 0
  • Inquirer
  • Posted

    according to hc3 get.value(1,"sunrseHour")

    sunrise 6.38 - 

    and sunset 19.30

     

    so hc3 is a minute early for sunrise from the web and is the same as the web for sunset,

    • 0
    Posted

    Let me also drop a dime in the pocket.

    The calculations done have a deviation and I dont know where to find it.

    In my opinion sunset and sunrise in HC3 with your deviation is not to much?

    I use sunset/sunrise from HC3 and I add a correction factor for each month and for % clouds. Its also not "watertight" but I can deal with it.

    If you do that you dont need to recalculate? Or what do I miss?

    Curious for your answer,

    //Sjakie

    • 0
  • Inquirer
  • Posted

    for sunset and sunrise you are correct the difference is one minute, however i need to get the time when the sun is 8 degrees below the horizan and i need it to be correct which is why i am using the suncalc vd, however it is the results are off by around 0.4/.5 degrees especially for the -8 degree time, i have found a vba spreadsheet which someone has made which is more exact but need o work through it to be able to understand either where the vd os going wrong or how to convert it to lua. It is a little bit over my head so was hoping for some help from the gurus on here lol.

    • 0
    Posted

    Hello,

     

    I have found one interesting API on this link:

    Please login or register to see this link.

     

    They provide all necessary data for sun and moon and have free plan with limit to 1000 calls per day which makes it possible to refresh data every 2-3 minutes.

    Is maybe this solution usable for you @Jay Ess?

     

    BTW I have tested it on HC2 and ti is working :-)

    • 0
  • Inquirer
  • Posted

    @Sankotronic thank you for that however the link you wont give me the 8 degrees below the horizan.

     

    have found some code in vba which i am trying to convert back to lua to see if i can get it to work as it should be.

     

    LOL with limited experience in coding am hoping i will get there LOL

     

    do you know if i have a number for example 7198.6714 how i can get the whole integer part without rounding, so would like to get 7198?

    • 0
  • Inquirer
  • Posted (edited)

    after looking at this code and other codes with similar functions, i think there is a tiny error in the calculation of the degrees of the sun in the original code as posted above, would any one be able to review the code and spot the mistake as the morning times are spot on it is the afternoon and evening times which are out in particular the 8 degree below which is out and is instead showing when the sun is at 8.44 degrees.

    i am using suncalc.org to check against.

    Edited by Jay Ess
    • 0
    Posted (edited)

    I like precision, but I'm very curious why this has to be so exact. What is your user case?


    Also - see my pm :)

    Edited by ppeterr
    • 0
  • Inquirer
  • Posted

    Thank you thought I had removed it lol but should now be gone. 
     

    For the Jewish calendar holidays and Saturday finishes when the sun is 8 degrees below. I have set my lights to automate for these times and am wanting to play a sound file at this time. 
     

     

    @ppeterr thank you for the heads up on the link. 

    • Like 1
    • 0
    Posted (edited)
    11 minutes ago, Jay Ess said:

    Thank you thought I had removed it lol but should now be gone. 
     

    For the Jewish calendar holidays and Saturday finishes when the sun is 8 degrees below. I have set my lights to automate for these times and am wanting to play a sound file at this time. 
     

     

    @ppeterr thank you for the heads up on the link. 

     

    You made me google it, learned something today :) 

     

    Anyway its above my head :)

     

    But i also found this:  

    Please login or register to see this link.

    Hebcal.com offers a REST API for fetching Jewish calendar data. The output format is in JSON.

    It can calculate tzeit hakochavim......uhhh little complex for me :)

     

    Take a look at it.

     

     

    Edited by ppeterr
    • 0
  • Inquirer
  • Posted

    i am already using it for getting dates LOL but the times given is different in different places so gets quite complicated hence why i am trying to fine tune the code i have.

    Join the conversation

    You can post now and register later. If you have an account, sign in now to post with your account.

    Guest
    Answer this question...

    ×   Pasted as rich text.   Paste as plain text instead

      Only 75 emoji are allowed.

    ×   Your link has been automatically embedded.   Display as a link instead

    ×   Your previous content has been restored.   Clear editor

    ×   You cannot paste images directly. Upload or insert images from URL.

    ×
    ×
    • Create New...