Announcement

Collapse
No announcement yet.

Twinkly.vb - Christmas tree lights with predefined and custom animations

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

    Twinkly.vb - Christmas tree lights with predefined and custom animations



    It's the same every year: "Why do we have to use these white lights? They are so... static." We've all been there.

    Well, here's Twinkly. And here's the script where you can control some of it's functions.

    Save the script as "Twinkly.vb", change the IP-address, and run the "Setup" sub.

    Code:
    'Moskus 2019
        Const IP As String = "192.168.0.166"
        Dim debug As Boolean = False
    
        Public Sub Main(ByVal something As Object)
        End Sub
    
        Public Sub ButtonPress(ByVal input As Object)
            Dim deviceRef As Integer = input(0)
            Dim cmd As String = input(1)
            If DoCmd(cmd) Then hs.SetDeviceString(deviceRef, cmd, True)
        End Sub
    
        Public Function DoCmd(ByVal command As String) As Boolean
            'SetMode("rt")
            'SetMode("demo")
            'SetMode("movie")
            'SetMode("effect")
            'SetMode("off")
    
            If debug Then hs.WriteLog("Twinkly", "Starting DoCmd()")
            Dim code As String = GetRandomCode()
            If debug Then hs.WriteLog("Twinkly", "Code: " & code)
    
            Dim auth As TwinklyAuthentication = Login(code, forceNew:=True)
            If debug Then hs.WriteLog("Twinkly", "Authentication_token: " & auth.authentication_token)
    
            Dim success As Boolean = Verify()
            If debug Then hs.WriteLog("Twinkly", "Verified: " & success)
    
            SetMode(command)
            Return True
        End Function
    
        Public Sub Setup(ByVal not_used As String)
            Dim new_ref As Integer = hs.NewDeviceRef("Twinkly")
            Dim dv As Scheduler.Classes.DeviceClass = hs.GetDeviceByRef(new_ref)
            dv.Location(hs) = "Twinkly"
            dv.Location2(hs) = "Twinkly"
            dv.Can_Dim(hs) = False
            dv.DeviceType_Set(hs) = New HomeSeerAPI.DeviceTypeInfo
            dv.Status_Support(hs) = True
            dv.Can_Dim(hs) = False
            dv.MISC_Set(hs, HomeSeerAPI.Enums.dvMISC.SHOW_VALUES) 'This is &H100
            dv.MISC_Clear(hs, HomeSeerAPI.Enums.dvMISC.STATUS_ONLY) 'This is &H10
            hs.SaveEventsDevices()
    
            AddDeviceButtons(new_ref)
            hs.WriteLog("Twinkly", "Initiation done!")
        End Sub
    
    
        Public Sub AddDeviceButtons(ByVal device_ref As String)
            Dim devID As Integer = CInt(device_ref)
            hs.DeviceScriptButton_DeleteAll(devID)
            hs.DeviceProperty_dvMISC(device_ref, HomeSeerAPI.Enums.eDeviceProperty.MISC_Set, HomeSeerAPI.Enums.dvMISC.SHOW_VALUES)
    
            Try
                hs.WriteLog("Twinkly", "Added button 1: " & hs.DeviceScriptButton_AddButton(devID, "Movie", 1, "Twinkly.vb", "ButtonPress", "Movie", 1, 1, 1))
                hs.WriteLog("Twinkly", "Added button 2: " & hs.DeviceScriptButton_AddButton(devID, "Effect", 2, "Twinkly.vb", "ButtonPress", "Effect", 1, 2, 1))
                hs.WriteLog("Twinkly", "Added button 3: " & hs.DeviceScriptButton_AddButton(devID, "Demo", 3, "Twinkly.vb", "ButtonPress", "Demo", 1, 3, 1))
                hs.WriteLog("Twinkly", "Added button 4: " & hs.DeviceScriptButton_AddButton(devID, "RT", 4, "Twinkly.vb", "ButtonPress", "RT", 2, 1, 1))
                hs.WriteLog("Twinkly", "Added button 5: " & hs.DeviceScriptButton_AddButton(devID, "Off", 0, "Twinkly.vb", "ButtonPress", "Off", 2, 2, 1))
            Catch ex As Exception
                hs.WriteLog("Twinkly", "Error adding buttons: " & ex.Message)
            End Try
        End Sub
    
        Public Sub SetMovieConfig(ByVal frameDelay As Integer, ByVal numberOfLEDs As Integer, ByVal framesNumber As Integer, ByVal loopType As Integer)
            Dim data As New System.Collections.Generic.Dictionary(Of String, Integer)
            data.Add("frame_delay", frameDelay)
            data.Add("leds_number", numberOfLEDs)
            data.Add("frames_number", framesNumber)
    
            Dim output As String = RunAPI("led/movie/config", Newtonsoft.Json.JsonConvert.SerializeObject(data))
            If debug Then hs.WriteLog("Twinkly", "SetMovieConfig: " & output)
        End Sub
    
        Public Sub GetMovieConfig()
            ' {"frame_delay":66,"leds_number":175,"loop_type":0,"frames_number":212,"sync":{"mode":"none","slave_id":"","master_id":""},"code":1000}
            Dim output As String = RunAPI("led/movie/config")
            If debug Then hs.WriteLog("Twinkly", "GetMovieConfig: " & output)
        End Sub
    
        Public Sub GetMovieFull()
            If debug Then hs.WriteLog("Twinkly", "GetMovieFull: ")
            Dim output As Byte() = RunAPIraw("led/movie/all")
            If debug Then hs.WriteLog("Twinkly", ConvertByteArrayToString(output) & " ... done!")
        End Sub
    
        Public Sub SetMovieFull(ByVal octetString As String)
            Dim movie() As Byte = ConvertStringToByteArray(octetString)
            If debug Then hs.WriteLog("Twinkly", "SetMovieFull: ")
            Dim ret = RunAPIraw("led/movie/full", movie)
            If debug Then hs.WriteLog("Twinkly", System.Text.Encoding.ASCII.GetString(ret) & " ... done!")
        End Sub
    
        ''' <summary>
        ''' Sets the display
        ''' </summary>
        ''' <param name="mode">rt, movie, demo, restart, effect, off</param>
        Public Sub SetMode(ByVal mode As String)
            If debug Then hs.WriteLog("Twinkly", "Setting mode to '" & mode & "'")
    
            Dim data As New System.Collections.Generic.Dictionary(Of String, String)
            data.Add("mode", mode.ToLower())
    
            Dim output As String = RunAPI("led/mode", Newtonsoft.Json.JsonConvert.SerializeObject(data))
            Dim success As Boolean = output.Contains("1000")
            If debug Then hs.WriteLog("Twinkly", "Mode set: " & IIf(success, " was a success!", " failed. :("))
            If Not success And debug Then hs.WriteLog("Twinkly", "Output: " & output)
        End Sub
    
        Public Function GetAuthentication() As TwinklyAuthentication
            Dim auth As TwinklyAuthentication = New TwinklyAuthentication
            Dim authString As String = hs.GetINISetting("Twinkly", "Authentication", "", "Twinkly.ini")
            Try
                If authString <> "" Then
                    auth = Newtonsoft.Json.JsonConvert.DeserializeObject(Of TwinklyAuthentication)(authString)
                End If
            Catch ex As Exception
            End Try
    
            Return auth
        End Function
    
        Public Function Verify() As Boolean
            Dim auth As TwinklyAuthentication = GetAuthentication()
            Dim data As New System.Collections.Generic.Dictionary(Of String, String)
            data.Add("challenge-response", auth.challengeresponse)
    
            Dim output As String = RunAPI("verify", Newtonsoft.Json.JsonConvert.SerializeObject(data))
            Return output.Contains("1000")
        End Function
    
        Public Function Login(ByVal challenge As String, Optional ByVal forceNew As Boolean = False) As TwinklyAuthentication
            Dim auth As TwinklyAuthentication = Nothing
            Dim authString As String = ""
    
            authString = hs.GetINISetting("Twinkly", "Authentication", "", "Twinkly.ini")
            Try
                If authString <> "" Then auth = Newtonsoft.Json.JsonConvert.DeserializeObject(Of TwinklyAuthentication)(authString)
            Catch ex As Exception
            End Try
    
            If auth Is Nothing OrElse forceNew Then
                Dim data As New System.Collections.Generic.Dictionary(Of String, String)
                data.Add("challenge", challenge)
    
                Dim output As String = RunAPI("login", Newtonsoft.Json.JsonConvert.SerializeObject(data))
    
    
                hs.SaveINISetting("Twinkly", "Authentication", output, "Twinkly.ini")
                auth = Newtonsoft.Json.JsonConvert.DeserializeObject(Of TwinklyAuthentication)(output)
            End If
    
            Return auth
        End Function
    
        Private Function RunAPI(ByVal urlFunction As String, Optional ByVal query As String = "") As String
            Dim source As String = ""
            Dim url As String = "http://" & IP & "/xled/v1/" & urlFunction
            Dim auth As TwinklyAuthentication = GetAuthentication()
    
            Using client As New System.Net.WebClient
                client.Headers.Add("Content-Type", "application/json")
                If auth.authentication_token <> "" Then
                    client.Headers.Add("X-Auth-Token", auth.authentication_token)
                End If
    
                If query <> "" Then
                    source = client.UploadString(url, "POST", query)
                Else
                    source = client.DownloadString(url)
                End If
            End Using
    
            Return source
        End Function
    
        Private Function RunAPIraw(ByVal urlFunction As String, Optional ByVal bytes() As Byte = Nothing) As Byte()
            Dim auth As TwinklyAuthentication = GetAuthentication()
            Dim source As Byte() = {}
    
            Dim url As String = "http://" & IP & "/xled/v1/" & urlFunction
            Using client As New System.Net.WebClient
                Net.ServicePointManager.DefaultConnectionLimit = 9999
                client.Headers.Add("Content-Type", "application/octet-stream")
                If auth.authentication_token <> "" Then
                    client.Headers.Add("X-Auth-Token", auth.authentication_token)
                End If
    
                If bytes IsNot Nothing Then
                    source = client.UploadData(New Uri(url), bytes)
                Else
                    source = client.DownloadData(url)
                End If
            End Using
    
            Return source
        End Function
    
        Public Function GetRandomCode(Optional ByVal forceNew As Boolean = False) As String
            Dim code As String = hs.GetINISetting("Twinkly", "Code", "", "Twinkly.ini")
    
            If code = "" OrElse forceNew Then
                code = GetRandomString(32)
                hs.SaveINISetting("Twinkly", "Code", code, "Twinkly.ini")
            End If
    
            Return code
        End Function
    
        Private Function GetRandomString(ByVal length As Integer)
            Dim s As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
            Dim r As New Random
            Dim sb As New Text.StringBuilder
            For i As Integer = 0 To length - 1
                Dim idx As Integer = r.Next(0, 35)
                sb.Append(s.Substring(idx, 1))
            Next
            Return sb.ToString()
        End Function
    
        Public Function ConvertStringToByteArray(ByVal input As String) As Byte()
            Dim lst As New System.Collections.Generic.List(Of Byte)
            For i As Integer = 0 To input.Length - 1 Step 2
                Dim temp As String = input.Substring(i, 2)
                Dim val As Integer = Convert.ToInt32(temp, 16)
                lst.Add(Convert.ToByte(val))
            Next
    
            Return lst.ToArray()
        End Function
    
        Public Function ConvertByteArrayToString(ByVal bytes() As Byte) As String
            Dim ret As String = ""
            For Each b As Byte In bytes
                ret &= Convert.ToChar(b).ToString()
            Next
            Return ret
        End Function
    
        Public Class TwinklyAuthentication
            Private _authentication_token As String
            Public Property authentication_token() As String
                Get
                    Return _authentication_token
                End Get
                Set(ByVal value As String)
                    _authentication_token = value
                End Set
            End Property
    
            Private _authentication_token_expires_in As Integer
            Public Property authentication_token_expires_in() As Integer
                Get
                    Return _authentication_token_expires_in
                End Get
                Set(ByVal value As Integer)
                    _authentication_token_expires_in = value
                End Set
            End Property
    
            Private _challengeresponse As String
            Public Property challengeresponse() As String
                Get
                    Return _challengeresponse
                End Get
                Set(ByVal value As String)
                    _challengeresponse = value
                End Set
            End Property
    
            Private _code As Integer
            Public Property code() As Integer
                Get
                    Return _code
                End Get
                Set(ByVal value As Integer)
                    _code = value
                End Set
            End Property
    
        End Class
    HSPro 3.0.0.458, Z-NET with Z-wave plugin 3.0.1.190, RFXCOM + 2x RFXtrx433E, HSTouch, Squeezebox plugin, iTach IP/WF2IR & GC-100-6 with UltraGCIR, BLDenon, NetcamStudio, Jon00s Webpage builder, Harmony Hub plugin, SCSIP (with FreePBX), Arduino plugin, IFTTT, Pushalot plugin, Device History plugin.
    Running on Windows 10 (64) virtualized
    on ESXi (Fujitsu Primergy TX150 S8).
    WinSeer (for Win10) - TextSeer - FitbitSeer - HSPI_MoskusSample

    Are you Norwegian (or Scandinavian) and getting started with HomeSeer? Read the "HomeSeer School"!

    #2
    Hi Moskus, it looks good, but what lighting hardware will it work with ? I can't see it working with my static lights

    Comment


      #3
      Originally posted by Traction Tim View Post
      Hi Moskus, it looks good, but what lighting hardware will it work with ? I can't see it working with my static lights
      --> https://twinkly.com/
      HSPro 3.0.0.458, Z-NET with Z-wave plugin 3.0.1.190, RFXCOM + 2x RFXtrx433E, HSTouch, Squeezebox plugin, iTach IP/WF2IR & GC-100-6 with UltraGCIR, BLDenon, NetcamStudio, Jon00s Webpage builder, Harmony Hub plugin, SCSIP (with FreePBX), Arduino plugin, IFTTT, Pushalot plugin, Device History plugin.
      Running on Windows 10 (64) virtualized
      on ESXi (Fujitsu Primergy TX150 S8).
      WinSeer (for Win10) - TextSeer - FitbitSeer - HSPI_MoskusSample

      Are you Norwegian (or Scandinavian) and getting started with HomeSeer? Read the "HomeSeer School"!

      Comment


        #4
        I need a pre lit Twinkly tree With the proliferation of prelits this company should jump on that wagon.
        -Rupp
        sigpic

        Comment


          #5
          That is awesome! How would I plug this into HS3? I just bought these lights.

          Comment


            #6
            Originally posted by bmsmithvb View Post
            That is awesome! How would I plug this into HS3? I just bought these lights.
            The script is shown above. Copy that into a file called "Twinkly.vb". Make an Event that runs this script, and tell this action to run the sub or function "Setup". You will get a new device that can be used to control the lights.
            HSPro 3.0.0.458, Z-NET with Z-wave plugin 3.0.1.190, RFXCOM + 2x RFXtrx433E, HSTouch, Squeezebox plugin, iTach IP/WF2IR & GC-100-6 with UltraGCIR, BLDenon, NetcamStudio, Jon00s Webpage builder, Harmony Hub plugin, SCSIP (with FreePBX), Arduino plugin, IFTTT, Pushalot plugin, Device History plugin.
            Running on Windows 10 (64) virtualized
            on ESXi (Fujitsu Primergy TX150 S8).
            WinSeer (for Win10) - TextSeer - FitbitSeer - HSPI_MoskusSample

            Are you Norwegian (or Scandinavian) and getting started with HomeSeer? Read the "HomeSeer School"!

            Comment


              #7
              Hello Moskus,

              What I am doing wrong.
              I have twinkly hardware (2x icicle gen2)
              changed the ip adress
              i made the script => Running script in background: C:/Program Files (x86)/HomeSeer HS3/scripts/Twinkly.vb("Setup")
              get errors below
              - Compiling script C:\Program Files (x86)\HomeSeer HS3\scripts\Twinkly.vb: Namespace or type specified in the Imports 'System.Core' doesn't contain any public member or cannot be found. Make sure the namespace or the type is defined and contains at least one public member. Make sure the imported element name doesn't use any aliases.
              - Compiling script C:\Program Files (x86)\HomeSeer HS3\scripts\Twinkly.vb: 'Newtonsoft' is not declared. It may be inaccessible due to its protection level.

              Comment


                #8
                Ah sorry. You need a reference to the Newtonsoft.JSON.dll in your script settings.
                HSPro 3.0.0.458, Z-NET with Z-wave plugin 3.0.1.190, RFXCOM + 2x RFXtrx433E, HSTouch, Squeezebox plugin, iTach IP/WF2IR & GC-100-6 with UltraGCIR, BLDenon, NetcamStudio, Jon00s Webpage builder, Harmony Hub plugin, SCSIP (with FreePBX), Arduino plugin, IFTTT, Pushalot plugin, Device History plugin.
                Running on Windows 10 (64) virtualized
                on ESXi (Fujitsu Primergy TX150 S8).
                WinSeer (for Win10) - TextSeer - FitbitSeer - HSPI_MoskusSample

                Are you Norwegian (or Scandinavian) and getting started with HomeSeer? Read the "HomeSeer School"!

                Comment


                  #9
                  THX but where and how should I add that?

                  Comment


                    #10
                    In your settings.ini, Scriptingreference should look something like this:
                    ScriptingReferences=Newtonsoft.Json;Newtonsoft.Json.dll
                    HSPro 3.0.0.458, Z-NET with Z-wave plugin 3.0.1.190, RFXCOM + 2x RFXtrx433E, HSTouch, Squeezebox plugin, iTach IP/WF2IR & GC-100-6 with UltraGCIR, BLDenon, NetcamStudio, Jon00s Webpage builder, Harmony Hub plugin, SCSIP (with FreePBX), Arduino plugin, IFTTT, Pushalot plugin, Device History plugin.
                    Running on Windows 10 (64) virtualized
                    on ESXi (Fujitsu Primergy TX150 S8).
                    WinSeer (for Win10) - TextSeer - FitbitSeer - HSPI_MoskusSample

                    Are you Norwegian (or Scandinavian) and getting started with HomeSeer? Read the "HomeSeer School"!

                    Comment

                    Working...
                    X