Announcement

Collapse
No announcement yet.

CAPI for scripts

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

    CAPI for scripts

    As promised, here are some simple scripting examples of how to manage devices with CAPI.

    First a disclaimer. I am no expert on any of this, I've just spent some time poking around and trying out some of the new HS3 scripting functions. HS3 is still a work in progress, and there is some discussion between plug-in developers and HST on developing some standards, and possibly additional scripting functions to make this all easier to work with.

    CAPI is an interface for controlling devices. As far as I can tell, it is not intended to be an interface for determining device status (although that is what some of the examples below do).

    So be warned that you need to do some homework, and nothing is guaranteed.

    Any device in HS3 can have any number of CAPIControl objects associated with it. The full definition of the CAPIControl object can be found in the HS3 scripting documentation (but that does not tell the whole story). Basically it is an array of objects, with labels, such as "On" or "Off" and associated device values. The value of those labels, and associated values, are defined by the plug-in or script that creates the devices.

    Here are some basic examples:

    For a Z-Wave device, there are at least two objects. A label of "On", value 255 and label of "Off", value 0. For dimmable devices, there are entries from "Dim 1%" to "Dim 99%", but only every other value, so Dim 1%, 3%, 5%, 7%, 9%... 99%, with associated values of 1, 3, 5, 7, 9 through 99.
    So you can't directly dim to 50%, it will not do anything, as that is not defined.

    X-10 devices are similar, but "On" is 101 and "Off" is -1.

    For a device added from the Device Manager, "On" is 100 and "Off" is 0.

    Note that setting a device to the CAPIControl object value does not do anything. For the owning plug-in to actually turn a device on, off, or set some other status, the hs.CAPIControlHandler function call must be used.

    But that does not mean that you can't define your own devices that only hold "status" based on their on/off/dim values.

    This script will write some information about a device, including any CAPI objects to the log. To get a better feel for the CAPI objects, I'd suggest running this on various devices in your own system. It is set up to take a string device ref so that it can be easily run from an event.
    Code:
    Imports HomeSeerAPI
    
    Sub Main(ByVal strDevRef As String)
    	Dim objDev As Object
    	Dim intDevRef as Integer
    	Dim intCount As Integer
    
    	intDevRef = CInt(strDevRef)	
    	objDev = hs.GetDevicebyRef(intDevRef)
    	If objDev Is Nothing Then
    		hs.WriteLog("DevInfo","Invalid device ref: " & strDevRef)
    	Else
    		hs.WriteLog("DevInfo", "Ref=" & strDevRef & "; Name=" & objDev.Name(hs) & "; Location=" & objDev.Location(hs) & "; Location2=" & objDev.Location2(hs) & "; Address=" & objDev.Address(hs))
    
    		intCount = 0
    		For Each objCAPIControl As CAPIControl In hs.CAPIGetControl(intDevRef)
    			hs.WriteLog("DevInfo", ".CCIndex=" & CStr(objCAPIControl.CCIndex) & "; Label=" & objCAPIControl.Label) & "; ControlType=" & CStr(objCAPIControl.ControlType) & "; ControlValue=" & CStr(objCAPIControl.ControlValue) & "; ControlString=" & objCAPIControl.ControlString)
    			intCount = intCount + 1
    		Next
    		If intCount = 0 Then hs.WriteLog("DevInfo", "No CAPIControl objects defined for this device")
    	End If
    End Sub
    Here are the IsOn and IsOff replacements. This assumes that the device has an "On" or "Off" object defined (the check is not case sensitive). For ByName variations, use hs.GetDeviceRefByName. For example: IsOnCAPI(hs.GetDeviceRefByName("Room1 Device1")). Also note that a device is not "On" if it is dimmed. It might make more sense to use Not IsOffCAPI rather than IsOnCAPI, if the device is dimmable.
    Code:
    Function IsOnCAPI(ByVal intDevRef As Integer) As Boolean
    	Dim intValue = hs.DeviceValueEx(intDevRef)
    
    	IsOnCAPI = False
    	For Each objCAPIControl As CAPIControl In hs.CAPIGetControl(intDevRef)
    		If intValue = objCAPIControl.ControlValue Then
    			If LCase(objCAPIControl.Label) = "on" Then
    				IsOnCAPI = True
    			End If
    			Exit For
    		End If
    	Next
    End Function
    
    Function IsOffCAPI(ByVal intDevRef As Integer) As Boolean
    	Dim intValue = hs.DeviceValueEx(intDevRef)
    
    	IsOffCAPI = False
    	For Each objCAPIControl As CAPIControl In hs.CAPIGetControl(intDevRef)
    		If intValue = objCAPIControl.ControlValue Then
    			If LCase(objCAPIControl.Label) = "off" Then
    				IsOffCAPI = True
    			End If
    			Exit For
    		End If
    	Next
    End Function
    Here is a more generic IsCAPI function that requires the full text of the CAPI label. IsCAPI(devref, "On") or IsCAPI(devref, "Dim 13%") for example.
    Code:
    Function IsCAPI(ByVal intDevRef As Integer, ByVal strDevCmd As String) As Boolean
    	Dim intValue = hs.DeviceValueEx(intDevRef)
    
    	IsCAPI = False
    	For Each objCAPIControl As CAPIControl In hs.CAPIGetControl(intDevRef)
    		If intValue = objCAPIControl.ControlValue Then
    			If LCase(objCAPIControl.Label) = LCase(strDevCmd) Then
    				IsCAPI = True
    			End If
    			Exit For
    		End If
    	Next
    End Function
    This is the function that most closely replaces ExecX10 and requires the full text of the CAPI label. Samples: CallCAPI(devref, "On"), CallCAPI(devref, "dim 51%")
    Code:
    Function CallCAPI(ByVal intDevRef As Integer, ByVal strDevCmd As String) As CAPIControlResponse
    	CallCAPI = CAPIControlResponse.Indeterminate
    	For Each objCAPIControl As CAPIControl In hs.CAPIGetControl(intDevRef)
    		If LCase(objCAPIControl.Label) = LCase(strDevCmd) Then
    			CallCAPI = hs.CAPIControlHandler(objCAPIControl)
    			Exit For
    		End If
    	Next
    End Function
    This function will try to approximate a dim level. So if CAPI only defines dim levels of 5%, 10%, etc. you can call this function with a value of 8 and it will find the closest dim level that is defined (it should choose 10). The third parameter limits the search to within +- of that value, a value of 0 will only work on an exact match. This has only been tested with Z-Wave and X-10 devices with the current plug-ins.
    Code:
    Function DimCAPI(ByVal intDevRef As Integer, ByVal intDimValue As Integer, ByVal intOffSetMax As Integer) As CAPIControlResponse
    	Dim blnMatch As Boolean
    	Dim intOffset As Integer
    	Dim intStartPos As Integer
    	Dim strDimVal As String
    	Dim intDimVal As Integer
    
    	DimCAPI = CAPIControlResponse.Indeterminate
    	blnMatch = False
    	intOffSet = 0
    	While True
    		For Each objCAPIControl As CAPIControl In hs.CAPIGetControl(intDevRef)
    			If Len(objCAPIControl.Label) > 5 Then
    				If LCase(Left(objCAPIControl.Label, 4)) = "dim " Then
    					intStartPos = InStr(4, objCAPIControl.Label, "%")
    					If intStartPos > 5 Then
    						strDimVal = Mid(objCAPIControl.Label, 5, intStartPos - 5)
    						If IsNumeric(strDimVal) Then
    							intDimVal = CInt(strDimVal)
    							If ((intDimVal - intOffSet) = intDimValue) Or ((intDimVal + intOffSet) = intDimValue) Then
    								DimCAPI = hs.CAPIControlHandler(objCAPIControl)
    								blnMatch = True
    								'hs.WriteLog("DimCAPI", "Dim match found. Requested=" & CStr(intDimValue) & ". Matched=" & strDimVal)
    								Exit For
    							End If
    						End If
    					End If
    				End If
    			End If
    		Next
    		If blnMatch Then Exit While
    		intOffSet = intOffSet + 1
    		If intOffSet > intOffSetMax Then Exit While
    	End While
    End Function

    #2
    Most excellent and very appreciated.. Good background info as well.
    We're dangerous now

    For control, I'm cheating and just setting the control variables directly and then use the SingleControl option. The no case option is nice.
    objCAPIControl = hs.CAPIGetSingleControl(8959,true,"on",false,true)
    hs.CAPIControlHandler(objCAPIControl)

    Won't always work for Dim, so your Dim search function is a good way around that..

    Thanks,
    Z
    Last edited by vasrc; July 11, 2013, 09:38 AM.

    Comment


      #3
      The strDevRef needs to be numeric which is the reference ID of the device you are trying to examine.
      Jon

      Comment


        #4
        Originally posted by skarragallagher
        unfortunately events still don't work for what I want to do

        I just want a simple way to get the status of a device, And set a device on/off/dim(level). Why take something so simple and complicate it.

        Can someone please post some CAPI examples of ways to do this. I have read the documentation (which is seriously lacking) and the searched the forum. Still just as confused.
        This might just get you started, this is a vb.net scripting using the functions at the top of the thread. It turns a device on, off and then dims it from 0-100%.

        Code:
        Imports System.Threading
        
        Sub Main(ByVal strDevRef As String)
        
            Dim dvRef As Long = 3
        
            CallCAPI(dvRef, "On")
            Thread.Sleep(5000)
            CallCAPI(dvRef, "Off")
            thread.sleep(5000)
        
            For i As Integer = 0 To 100
                CallCAPI(dvRef, "Brightness " & i & "%")
                thread.sleep(500)
            Next
        
        End Sub
        
        Function CallCAPI(ByVal intDevRef As Integer, ByVal strDevCmd As String) As CAPIControlResponse
            hs.writelog("CallCAPI", "Device Reference: " & intDevRef & " strDevCmd: " & strDevCmd)
            CallCAPI = CAPIControlResponse.Indeterminate
            For Each objCAPIControl As CAPIControl In hs.CAPIGetControl(intDevRef)
                If LCase(objCAPIControl.Label) = LCase(strDevCmd) Then
                    CallCAPI = hs.CAPIControlHandler(objCAPIControl)
                    Exit For
                End If
            Next
        End Function

        Comment


          #5
          Ok. So I could use this if my dvref was 1234?

          Code:
          CallCAPI(1234, "On")
          CallCAPI(1234, "Off")
          CallCAPI(1234, "Brightness 51%")
          That is simple enough

          How about getting the status string?

          Comment


            #6
            You do need to double check how your device appears in the HS3 web page, I don't have a great understanding of this but basically if your device shows as "Dim x%" then this is what you send to the CAPI Control Handler, the X10 plugin shows "Brightness x%" for example but you need to check each individual device. For a status in the past I have used something like this I think;

            hs.DeviceVSP_GetStatus(1234, hs.devicevalue(1234),ePairStatusControl.Status)

            Comment


              #7
              Originally posted by bdickhaus View Post
              As promised, here are some simple scripting examples of how to manage devices with CAPI.

              This script will write some information about a device, including any CAPI objects to the log. To get a better feel for the CAPI objects, I'd suggest running this on various devices in your own system. It is set up to take a string device ref so that it can be easily run from an event.
              Code:
              Imports HomeSeerAPI
              
              Sub Main(ByVal strDevRef As String)
                  Dim objDev As Object
                  Dim intDevRef as Integer
                 .......
              Many thanks for this extremely useful script to start to better understand CAPI.
              Please note that there is a slight error in the script, here below is the corrected version.

              cheers !

              ' This script will show the CAPI possibilities of a Device
              ' it should be run from an event by adding the device reference ID in the parameter of the script
              ' it will output the CAPI possibilities into the HS log

              sub Main(ByVal strDevRef As String)

              Dim objDev As Object
              Dim intDevRef as Integer
              Dim intCount As Integer

              hs.WriteLog("DevInfo", "Device : " & strDevRef)

              intDevRef = CInt(strDevRef)
              objDev = hs.GetDevicebyRef(intDevRef)
              If objDev Is Nothing Then
              hs.WriteLog("DevInfo", "Invalid device ref: " & strDevRef)
              Else
              hs.WriteLog("DevInfo", "Ref=" & strDevRef & "; Name=" & objDev.Name(hs) & "; Location=" & objDev.Location(hs) & "; Location2=" & objDev.Location2(hs) & "; Address=" & objDev.Address(hs) )

              intCount = 0
              For Each objCAPIControl As CAPIControl In hs.CAPIGetControl(intDevRef)
              hs.WriteLog("DevInfo", ".CCIndex=" & CStr(objCAPIControl.CCIndex) & "; Label=" & CStr(objCAPIControl.Label) & "; ControlType=" & CStr(objCAPIControl.ControlType) & "; ControlValue=" & CStr(objCAPIControl.ControlValue) & "; ControlString=" & objCAPIControl.ControlString)
              intCount = intCount + 1
              Next
              If intCount = 0 Then
              hs.WriteLog("DevInfo", "No CAPIControl objects defined for this device")
              end if
              End If

              end sub

              Comment


                #8
                Problem with Dimming with CAPI

                I have been doing scripting a bit and now I came across a problem where I need to use CAPI command, I have been able to get my light On and Off but the DIMMING does not work

                here is my script

                Sub Main(ByVal Parms As Object)

                Dim ParmArray() As String
                ParmArray = Parms.ToString.Split("|")

                if hs.IsOff(ParmArray(0)) = True then
                hs.CAPIControlHandler(hs.CAPIGetSingleControl(ParmArray(0),T rue,"13%",False,False))
                end if

                End Sub



                the followings work without any issue:
                hs.CAPIControlHandler(hs.CAPIGetSingleControl(ParmArray(0),T rue,"On",False,False))

                hs.CAPIControlHandler(hs.CAPIGetSingleControl(ParmArray(0),T rue,"Off",False,False))


                Reading Through posts, I saw tht the value passed in the CAPI need to reflect the device specific value for Dim so I lloked in the device advanced page and here is what it shows if I set my dimmer to 41%: (see attached image)

                so I tried many variant of the CAPI:
                hs.CAPIControlHandler(hs.CAPIGetSingleControl(ParmArray(0),T rue,"Dim 13%",False,False))
                hs.CAPIControlHandler(hs.CAPIGetSingleControl(ParmArray(0),T rue,"13%",False,False))
                hs.CAPIControlHandler(hs.CAPIGetSingleControl(ParmArray(0),T rue,"13",False,False))
                hs.CAPIControlHandler(hs.CAPIGetSingleControl(ParmArray(0),T rue,"Dim 13% (13)",False,False))


                I am at a stuck if anyone have an idea ?
                Attached Files

                Comment


                  #9
                  Parmarray{0} is a string, I think capital expects a LONG
                  tenholde

                  Comment


                    #10
                    Originally posted by tenholde View Post
                    Parmarray{0} is a string, I think capital expects a LONG
                    you might be roight but parmarray() is only used to pass the devref and it works for the On and Off state...

                    Comment


                      #11
                      Using tenScriptAid, here is code for dimming devref 845 to 15.
                      Code:
                      Dim cc as HomeSeerAPI.CAPI.CAPIControl = hs.CAPIGetSingleControl(845, True, "Dim (value)%", False, False)
                      cc.ControlValue = 15
                      Dim cr as HomeSeerAPI.CAPI.CAPIControlResponse = hs.CAPIControlHandler(cc)
                      tenholde
                      tenholde

                      Comment


                        #12
                        CapiControl for Timers?

                        Hello!
                        I would like to create an event for a timer by scripting it.

                        AddDeviceActionToEvent can be used for Devices, but I cannot seem to get any CapiControls for Timers.

                        AddActionRunScript is undocumented but functionning.

                        Is there such function as AddTimerActionToEvent ?

                        (Actually, I would more importantly like to create a Timer by script, but have not found how to?)
                        Thx, Bob

                        Comment


                          #13
                          Originally posted by tenholde View Post
                          Using tenScriptAid, here is code for dimming devref 845 to 15.
                          Code:
                          Dim cc as HomeSeerAPI.CAPI.CAPIControl = hs.CAPIGetSingleControl(845, True, "Dim (value)%", False, False)
                          cc.ControlValue = 15
                          Dim cr as HomeSeerAPI.CAPI.CAPIControlResponse = hs.CAPIControlHandler(cc)
                          tenholde

                          I was able to use the above 3-line solution to dim HS devices created by DonMor's Lutron RadioRA 2 plugin that control Lutron RadioRA 2 dimmers. i would like a 1-line solution.

                          the below have not worked to dim device 308 to 50%
                          a. hs.CAPIControlHandler(hs.CAPIGetSingleControl(308,True,"Dim (50)%",False,False))
                          b. hs.CAPIControlHandler(hs.CAPIGetSingleControl(308,True,"Dim( 50)%",False,False))
                          c. hs.CAPIControlHandler(hs.CAPIGetSingleControl(308,True,"Dim 50%",False,False))
                          d. hs.CAPIControlHandler(hs.CAPIGetSingleControl(308,True,"Dim 50",False,False))
                          f. hs.CAPIControlHandler(hs.CAPIGetSingleControl(308,True,"50%" ,False,False))
                          g. hs.CAPIControlHandler(hs.CAPIGetSingleControl(308,True,"(50) %",False,False))
                          h. hs.CAPIControlHandler(hs.CAPIGetSingleControl(308,True,"50", False,False))

                          as others previously mentioned, using "On" and "Off" for the 3rd parameter does work.

                          thanks for any help

                          Comment


                            #14
                            Originally posted by Heychristian View Post


                            I was able to use the above 3-line solution to dim HS devices created by DonMor's Lutron RadioRA 2 plugin that control Lutron RadioRA 2 dimmers. i would like a 1-line solution.

                            the below have not worked to dim device 308 to 50%
                            a. hs.CAPIControlHandler(hs.CAPIGetSingleControl(308,True,"Dim (50)%",False,False))
                            b. hs.CAPIControlHandler(hs.CAPIGetSingleControl(308,True,"Dim( 50)%",False,False))
                            c. hs.CAPIControlHandler(hs.CAPIGetSingleControl(308,True,"Dim 50%",False,False))
                            d. hs.CAPIControlHandler(hs.CAPIGetSingleControl(308,True,"Dim 50",False,False))
                            f. hs.CAPIControlHandler(hs.CAPIGetSingleControl(308,True,"50%" ,False,False))
                            g. hs.CAPIControlHandler(hs.CAPIGetSingleControl(308,True,"(50) %",False,False))
                            h. hs.CAPIControlHandler(hs.CAPIGetSingleControl(308,True,"50", False,False))

                            as others previously mentioned, using "On" and "Off" for the 3rd parameter does work.

                            thanks for any help
                            Do not know how to accomplish this in a single statement
                            tenholde

                            Comment


                              #15
                              You could make a subroutine with the three lines and call it with arguments. Then it would be one line for each call. This is more or less what I did.

                              Comment

                              Working...
                              X