Announcement

Collapse
No announcement yet.

Script to calculate sunrise and sunset and place the values in virtual devices

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Script to calculate sunrise and sunset and place the values in virtual devices

    I wanted to have sunrise and sunset times available in a virtual device. I have two things left to do on the script. One is to add in elevation correction and the other is to pull in the UTC to current time zone offset so it utilizes local time. Right now it is hardcoded for MST (Mountain Standard Time). Hope Other find this Useful.

    Here is the File:

    [ATTACH]n1442275[/ATTACH]
    ' Program to Calculate Sunrise and sunset
    ' I took the Equations from https://edwilliams.org/sunrise_sunset_algorithm.htm
    ' JLG 12/19/2020
    '
    ' ---------------------------------------------------------------
    'Libraries
    ' ---------------------------------------------------------------

    IMPORTS System.IO
    IMPORTS System.Net
    IMPORTS System.Core
    IMPORTS System.Globalization

    Sub Main(ByVal parms As Object) 'passing arguments on stack as an object

    ' ---------------------------------------------------------------
    'Declare Variables
    ' ---------------------------------------------------------------

    Dim parm, sParm() As String
    Dim MyName As String
    Dim MyDayOfYear As Integer
    Dim MyToday As DateTime = Now
    Dim Debug, RiseOrSet, Sunrise, Sunset As Boolean
    Dim Zenith, TLong, T, M, L, RA, LQuad, RAQuad, sinDec, cosDec, MycosH, H, LTime, MyTime, UCT As Double
    Dim Longitude, Latitude, Elevation, MyRad As Double
    ' ---------------------------------------------------------------
    ' Write to the log so we know it is executing and display in standard and colored text
    ' WHITE = "#FFFFFF"
    ' RED = "#FF0000"
    ' BLACK = "#000000"
    ' NAVY = "#000080"
    ' LIGHT BLUE = "#D9F2FF"
    ' LIGHT GRAY = "#E1E1E1"
    ' PINK = "#FFB6C1"
    ' ORANGE = "#D58000"
    ' GREEN = "#008000"
    ' ---------------------------------------------------------------
    MyName = "SunRiseSet"
    Debug = True

    If (Debug) Then
    hs.WritelogEX(MyName, "Start Executing SunRiseandSet.vb", "#000000")
    End If

    ' ---------------------------------------------------------------
    ' Process the parameter(s)
    ' ---------------------------------------------------------------

    If parms.GetType().ToString = "System.String" Then 'Called from an Event
    parm = parms.ToString()
    Else ' Called from HSTouch
    parm = parms(0).ToString() & "|" & parms(1).ToString() & "|" & parms(2).ToString() & "|" & parms(3).ToString()
    End If 'Now use parm as your input variable...

    sParm = Split(parm, "|", -1, 1) 'split into individual parameters. Use | as the separator

    Longitude = CDbl(SParm(0))
    Latitude = CDbl(SParm(1))
    Elevation = CDbl(SParm(2))
    RiseOrSet = CInt(SParm(3)) '0 for Rise, 1 for Set

    ' ------------------------------------------------------------------------------------------------------
    ' Programming starts here
    ' ------------------------------------------------------------------------------------------------------
    Zenith = 90 + 50/60 '- Official Zenith for Sunrise/Sunset
    MyRad = 180 / Math.Pi '3.1415926535

    ' ---------------------------------------------------------------
    ' Get the Day of the year - Step 1
    ' ---------------------------------------------------------------
    MyDayOfYear = MyToday.DayOfYear

    If (Debug) Then
    hs.WriteLog(MyName, "Day of The Year = " & CStr(MyDayOfYear))
    End If

    ' ---------------------------------------------------------------
    ' Convert Long to Hour and Calculate an Approx Time - Step 2
    ' ---------------------------------------------------------------
    TLong = Longitude / 15

    If (RiseOrSet) Then
    T = MyDayOfYear + ((18 - TLong)/24)
    Else
    T = MyDayOfYear + (( 6 - TLong)/24)
    End If

    If (Debug) Then
    hs.WriteLog(MyName, "T = " & CStr(T))
    End If

    ' ---------------------------------------------------------------
    ' Solar Mean Anomaly - Step 3
    ' ---------------------------------------------------------------

    M = 0.9856 * T - 3.289

    If (Debug) Then
    hs.WriteLog(MyName, "M = " & CStr(M))
    End If

    ' ---------------------------------------------------------------
    ' Sun's True Longitude - Step 4
    ' ---------------------------------------------------------------

    L = (M + (1.916*Math.sin(M/MyRad) + 0.020*Math.Sin(2*M/MyRad)) + 282.634) Mod 360

    If (Debug) Then
    hs.WriteLog(MyName, "L = " & CStr(L))
    End If

    ' ---------------------------------------------------------------
    ' Calculate the Sun's Right Ascension - Step 5a
    ' ---------------------------------------------------------------

    RA = (MyRad * Math.ATan(0.91764 * Math.Tan(L/MyRad))) Mod 360

    If (RA < 0) Then
    RA = RA + 360
    End If

    If (Debug) Then
    hs.WriteLog(MyName, "RA = " & CStr(RA))
    End If

    ' ---------------------------------------------------------------
    ' Make the same Quadrant as L and convert into hours 5b&c
    ' ---------------------------------------------------------------

    LQuad = Math.Floor(L/90) * 90
    RAQuad = Math.Floor(RA/90) * 90
    RA = (RA + LQuad - RAQuad)/15

    If (Debug) Then
    hs.WriteLog(MyName, "LQuad = " & CStr(LQuad) & " RAQuad = " & CStr(RAQuad) & " RA = " & CStr(RA))
    End If

    ' ---------------------------------------------------------------
    ' Calculate the Sun's Declination - Step 6
    ' ---------------------------------------------------------------

    sinDec = 0.39782 * Math.Sin(L/MyRad)
    cosDec = Math.Cos(Math.Asin(sinDec))

    ' ---------------------------------------------------------------
    ' Calculate the Sun's Local Hour Angle - Step 7a
    ' ---------------------------------------------------------------
    MycosH = (Math.Cos(Zenith/MyRad) - (sinDec * Math.Sin(Latitude/MyRad))) / (cosDec * Math.Cos(Latitude/MyRad))

    If (Debug) Then
    hs.WriteLog(MyName, "cosH = " & CStr(MycosH))
    End If

    Sunrise = True
    Sunset = True

    If (MycosH > 1) Then ' No Sunrise
    Sunrise = False
    MycosH = 0.9999
    End If

    If (MyCosH < -1) Then 'No Sunset
    Sunset = False
    MycosH = -0.9999
    End If

    ' ---------------------------------------------------------------
    ' Calculate the Sun's Local Hour Angle - Step 7b
    ' ---------------------------------------------------------------

    If(RiseOrSet) Then
    H = MyRad*Math.ACos(MyCosH)
    Else
    H = 360 - MyRad*Math.ACos(MycosH)
    End If

    H = H/15

    If (Debug) Then
    hs.WriteLog(MyName, "H = " & CStr(H))
    End If

    ' ---------------------------------------------------------------
    ' Calculate Local Mean time - Step 8
    ' ---------------------------------------------------------------

    LTime = H + RA - 0.06571*T - 6.622

    If (Debug) Then
    hs.WriteLog(MyName, "LTime = " & CStr(LTime))
    End If

    ' ---------------------------------------------------------------
    ' Return to UTC Time - Step 9
    ' ---------------------------------------------------------------

    UCT = LTime - TLong

    If (UCT > 24) Then
    UCT = UCT - 24
    End If

    If (UCT < 0) Then
    UCT = UCT + 24
    End If

    If (Debug) Then
    hs.WriteLog(MyName, "UCT = " & CStr(UCT))
    End If

    ' ---------------------------------------------------------------
    ' Take it back to Defined Local Time - Step 10
    ' ---------------------------------------------------------------

    MyTime = UCT - 7 <-- Hardcoded for MST

    If (Debug) Then
    hs.WriteLog(MyName, "MyTime = " & CStr(MyTime))
    End If


    If (RiseOrSet) Then
    If (Sunset) Then
    hs.SetDeviceValuebyName("MySunset", MyTime)
    Else
    hs.SetDeviceValuebyName("MySunset", 24)
    End If
    Else
    If (Sunrise) Then
    hs.SetDeviceValuebyName("MySunrise", MyTime)
    Else
    hs.SetDeviceValuebyName("MySunrise", 0)
    End if
    End If

    End Sub
    [ATTACH]n1442275[/ATTACH]

    Click image for larger version

Name:	Screenshot from 2020-12-21 21-43-50.png
Views:	575
Size:	99.5 KB
ID:	1442276

    Here is my virtual devices to hold:

    Click image for larger version

Name:	Screenshot from 2020-12-21 21-48-42.png
Views:	314
Size:	31.9 KB
ID:	1442277

    #2
    FYI, you do know Homeseer has the commands hs.Sunrise, hs.Sunset & hs.Solarnoon (calculated from the Lat/Long entered in the settings) to provide this info?
    Jon

    Comment


      #3
      Yes I did but I wanted to be able to calculate with more precision and for multiple places. Something that I can't do with the settings based data.

      Comment


        #4
        I have added code to remove hardcoded timezone offset. If you happen to be in a 1/2hr timezone compared to UTC then you will have to change the offset to minutes and divide by 60.

        Code:
        ' Program to Calculate Sunrise and sunset
        ' I took the Equations from https://edwilliams.org/sunrise_sunset_algorithm.htm
        ' JLG 12/19/2020
        '
        ' ---------------------------------------------------------------
        'Libraries
        ' ---------------------------------------------------------------
        
        IMPORTS System.IO
        IMPORTS System.Net
        IMPORTS System.Core
        IMPORTS System.Globalization
        
        Sub Main(ByVal parms As Object) 'passing arguments on stack as an object
        
        ' ---------------------------------------------------------------
        'Declare Variables
        ' ---------------------------------------------------------------
        
        Dim parm, sParm() As String
        Dim MyName As String
        Dim MyDayOfYear, MyOffset As Integer
        Dim MyToday As DateTime = Now
        Dim MyUCTTime As DateTime = DateTime.UtcNow
        Dim Debug, RiseOrSet, Sunrise, Sunset As Boolean
        Dim Zenith, TLong, T, M, L, RA, LQuad, RAQuad, sinDec, cosDec, MycosH, H, LTime, MyTime, UCT As Double
        Dim Longitude, Latitude, Elevation, MyRad As Double
        ' ---------------------------------------------------------------
        ' Write to the log so we know it is executing and display in standard and colored text
        ' WHITE = "#FFFFFF"
        ' RED = "#FF0000"
        ' BLACK = "#000000"
        ' NAVY = "#000080"
        ' LIGHT BLUE = "#D9F2FF"
        ' LIGHT GRAY = "#E1E1E1"
        ' PINK = "#FFB6C1"
        ' ORANGE = "#D58000"
        ' GREEN = "#008000"
        ' ---------------------------------------------------------------
        MyName = "SunRiseSet"
        Debug = False
        
        MyOffset = DateDiff("h", MyToday, MyUCTTime)
        'hs.Writelog(MyName, "Offset Hours = " & CStr(MyOffset))
        
        If (Debug) Then
        hs.WritelogEX(MyName, "Start Executing SunRiseandSet.vb", "#000000")
        End If
        
        ' ---------------------------------------------------------------
        ' Process the parameter(s)
        ' ---------------------------------------------------------------
        
        If parms.GetType().ToString = "System.String" Then 'Called from an Event
        parm = parms.ToString()
        Else ' Called from HSTouch
        parm = parms(0).ToString() & "|" & parms(1).ToString() & "|" & parms(2).ToString() & "|" & parms(3).ToString()
        End If 'Now use parm as your input variable...
        
        sParm = Split(parm, "|", -1, 1) 'split into individual parameters. Use | as the separator
        
        Longitude = CDbl(SParm(0))
        Latitude = CDbl(SParm(1))
        Elevation = CDbl(SParm(2))
        RiseOrSet = CInt(SParm(3)) '0 for Rise, 1 for Set
        
        ' ------------------------------------------------------------------------------------------------------
        ' Programming starts here
        ' ------------------------------------------------------------------------------------------------------
        Zenith = 90 + 50/60 '- Official Zenith for Sunrise/Sunset
        MyRad = 180 / Math.Pi '3.1415926535
        
        ' ---------------------------------------------------------------
        ' Get the Day of the year - Step 1
        ' ---------------------------------------------------------------
        MyDayOfYear = MyToday.DayOfYear
        
        If (Debug) Then
        hs.WriteLog(MyName, "Day of The Year = " & CStr(MyDayOfYear))
        End If
        
        ' ---------------------------------------------------------------
        ' Convert Long to Hour and Calculate an Approx Time - Step 2
        ' ---------------------------------------------------------------
        TLong = Longitude / 15
        
        If (RiseOrSet) Then
        T = MyDayOfYear + ((18 - TLong)/24)
        Else
        T = MyDayOfYear + (( 6 - TLong)/24)
        End If
        
        If (Debug) Then
        hs.WriteLog(MyName, "T = " & CStr(T))
        End If
        
        ' ---------------------------------------------------------------
        ' Solar Mean Anomaly - Step 3
        ' ---------------------------------------------------------------
        
        M = 0.9856 * T - 3.289
        
        If (Debug) Then
        hs.WriteLog(MyName, "M = " & CStr(M))
        End If
        
        ' ---------------------------------------------------------------
        ' Sun's True Longitude - Step 4
        ' ---------------------------------------------------------------
        
        L = (M + (1.916*Math.sin(M/MyRad) + 0.020*Math.Sin(2*M/MyRad)) + 282.634) Mod 360
        
        If (Debug) Then
        hs.WriteLog(MyName, "L = " & CStr(L))
        End If
        
        ' ---------------------------------------------------------------
        ' Calculate the Sun's Right Ascension - Step 5a
        ' ---------------------------------------------------------------
        
        RA = (MyRad * Math.ATan(0.91764 * Math.Tan(L/MyRad))) Mod 360
        
        If (RA < 0) Then
        RA = RA + 360
        End If
        
        If (Debug) Then
        hs.WriteLog(MyName, "RA = " & CStr(RA))
        End If
        
        ' ---------------------------------------------------------------
        ' Make the same Quadrant as L and convert into hours 5b&c
        ' ---------------------------------------------------------------
        
        LQuad = Math.Floor(L/90) * 90
        RAQuad = Math.Floor(RA/90) * 90
        RA = (RA + LQuad - RAQuad)/15
        
        If (Debug) Then
        hs.WriteLog(MyName, "LQuad = " & CStr(LQuad) & " RAQuad = " & CStr(RAQuad) & " RA = " & CStr(RA))
        End If
        
        ' ---------------------------------------------------------------
        ' Calculate the Sun's Declination - Step 6
        ' ---------------------------------------------------------------
        
        sinDec = 0.39782 * Math.Sin(L/MyRad)
        cosDec = Math.Cos(Math.Asin(sinDec))
        
        ' ---------------------------------------------------------------
        ' Calculate the Sun's Local Hour Angle - Step 7a
        ' ---------------------------------------------------------------
        MycosH = (Math.Cos(Zenith/MyRad) - (sinDec * Math.Sin(Latitude/MyRad))) / (cosDec * Math.Cos(Latitude/MyRad))
        
        If (Debug) Then
        hs.WriteLog(MyName, "cosH = " & CStr(MycosH))
        End If
        
        Sunrise = True
        Sunset = True
        
        If (MycosH > 1) Then ' No Sunrise
        Sunrise = False
        MycosH = 0.9999
        End If
        
        If (MyCosH < -1) Then 'No Sunset
        Sunset = False
        MycosH = -0.9999
        End If
        
        ' ---------------------------------------------------------------
        ' Calculate the Sun's Local Hour Angle - Step 7b
        ' ---------------------------------------------------------------
        
        If(RiseOrSet) Then
        H = MyRad*Math.ACos(MyCosH)
        Else
        H = 360 - MyRad*Math.ACos(MycosH)
        End If
        
        H = H/15
        
        If (Debug) Then
        hs.WriteLog(MyName, "H = " & CStr(H))
        End If
        
        ' ---------------------------------------------------------------
        ' Calculate Local Mean time - Step 8
        ' ---------------------------------------------------------------
        
        LTime = H + RA - 0.06571*T - 6.622
        
        If (Debug) Then
        hs.WriteLog(MyName, "LTime = " & CStr(LTime))
        End If
        
        ' ---------------------------------------------------------------
        ' Return to UTC Time - Step 9
        ' ---------------------------------------------------------------
        
        UCT = LTime - TLong
        
        If (UCT > 24) Then
        UCT = UCT - 24
        End If
        
        If (UCT < 0) Then
        UCT = UCT + 24
        End If
        
        If (Debug) Then
        hs.WriteLog(MyName, "UCT = " & CStr(UCT))
        End If
        
        ' ---------------------------------------------------------------
        ' Take it back to Defined Local Time - Step 10
        ' ---------------------------------------------------------------
        
        MyTime = UCT - MyOffset
        
        If (Debug) Then
        hs.WriteLog(MyName, "MyTime = " & CStr(MyTime))
        End If
        
        
        If (RiseOrSet) Then
        If (Sunset) Then
        hs.SetDeviceValuebyName("MySunset", MyTime)
        Else
        hs.SetDeviceValuebyName("MySunset", 24)
        End If
        Else
        If (Sunrise) Then
        hs.SetDeviceValuebyName("MySunrise", MyTime)
        Else
        hs.SetDeviceValuebyName("MySunrise", 0)
        End if
        End If
        
        End Sub

        The file to download

        SunRiseandSetV2.vb.txt

        Here is the spreadsheet that I used as part of my verification. It is a libreOffice calc spreadsheet.

        SunRiseSet.ods.txt

        Comment


          #5
          Originally posted by jon00 View Post
          FYI, you do know Homeseer has the commands hs.Sunrise, hs.Sunset & hs.Solarnoon (calculated from the Lat/Long entered in the settings) to provide this info?
          I'm a novice scripter. Can someone point me to how I might get hs.Sunrise etc into a virtual device?

          Comment


            #6
            Function Main(parm as object)
            dim result as object
            result=hs.SetDeviceString(290, hs.Sunrise, True)
            'hs.WriteLog("SunRise", "Sunrise is " & hs.Sunrise)
            return(result)
            End Function


            My VD to hold sunrise value is 290. I run this from am event every day at 02:00 am. Uncomment the ’ to log results when script runs.

            I have a similar one for sunset.

            Sent from my iPad using Tapatalk

            Comment


              #7
              I just created an event with the following

              IF The time is at 12:29:00 AM

              Then Execute the command: &hs.setdevicestring(487, "Sunrise Today " & hs.sunrise, True)
              and only allow one instance of the script to run at a time.

              Comment

              Working...
              X