Announcement

Collapse
No announcement yet.

SetDeviceValueByRef vs CAPIControlHandler

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

    SetDeviceValueByRef vs CAPIControlHandler

    So, there are two ways to set device value - SetDeviceValueByRef and CAPIControlHandler. First I thought that SetDeviceValueByRef is just a convinience wrapper for CAPIControlHandler. But.

    SetDeviceValueByRef doen't seem to work with physical devices like Raspberry IO outputs. It looks like it changes the value in HS ui, but output doesn't change.
    So. I try CAPIControlHandler - it does work with Raspberry IO outputs - but is not reflected in HS ui.

    So WTH should I be using? I use both and it seems to work - but it's ridiculous.

    #2
    Here's what I'm doing now, but it looks unnecessary complicated.
    1. I made it configurable for each device so I can experiment - ctrlType is the swich
    2. If value is chaged from HS via SetIOMulti - I can't use CAPIControlHandler to confirm back to HS - I must use SetDeviceValueByRef , hence the additional forceSetDeviceValueByRef switch.

    Click image for larger version  Name:	Capture.PNG Views:	1 Size:	252.5 KB ID:	1280989

    Comment


      #3
      This code works for me, and sets both the device and the HS UI:

      Code:
      Public Function SetVirtual(ByVal sDevName As String, ByVal sLabel As String) As Integer
        Dim iRef As Integer = hs.GetDeviceRefByName(sDevName)
        Dim CS As ICAPIStatus = hs.CAPIGetStatus(iRef)
        For Each objCAPIControl As CAPIControl In hs.CAPIGetControl(iRef)
          If LCase(objCAPIControl.Label) = LCase(sLabel) Then
            hs.CAPIControlHandler(objCAPIControl)
            Return 0
          End If
        Next
        Return 1
      End Function

      Comment


        #4
        Originally posted by aa6vh View Post
        This code works for me, and sets both the device and the HS UI:
        ]
        It looks similar to what I'm doing, the problem is - you are setting virtual device, but as I said the real issue is with physical devices, like Raspberry IO output, and I saw similar discussions about setting thermostats as well.
        A couple notes:
        1. For performance I keep device ID and create CAPIControl dictionary at start, instead of 'for' looping at run time
        2. Since you use the device name anyway - why not just call SetDeviceStringByName?

        Comment


          #5
          Originally posted by alexbk66 View Post
          So, there are two ways to set device value - SetDeviceValueByRef and CAPIControlHandler. First I thought that SetDeviceValueByRef is just a convinience wrapper for CAPIControlHandler. But.

          SetDeviceValueByRef doen't seem to work with physical devices like Raspberry IO outputs. It looks like it changes the value in HS ui, but output doesn't change.
          So. I try CAPIControlHandler - it does work with Raspberry IO outputs - but is not reflected in HS ui.

          So WTH should I be using? I use both and it seems to work - but it's ridiculous.
          You should absolutely not being using both, and you are definitely confused (and its a confusing subject).

          To control a device you should always being the CapiControlHandler. If you are a plugin author that controls a device (say a bulb) you should respond to the SetIOMulti() and set your devices to their proper state AND call set value, however you should NOT respond to set value being set. This will cause horrible logic loops.

          You are doing a linking program so you are in a special case of hell ,) Since the devices are not yours you need to use CapiControlHandler but since you are forcing the change you don't want to retriever on the later value change. In your very special case you will need to keep track of the values you send to CapiControl handler for each device and ignore the corresponding value change when it arrives a bit later.

          Comment


            #6
            risquare

            Comment


              #7
              Thank you Bill I'm not really "confused" - I was using CapiControlHandler, but for RaspberryIO it wasn't showing in HS, but SetDeviceValueByRef was showing in HS, but wasn't changing outputs - that's the problem.

              Also, I'm not sure which one really should be used in SetIOMulti()? All examples and Help use SetDeviceValueByRef. And I did have problems with CapiControlHandler here.

              I reckon something is wrong with HS here - both functions should behave the same IMHO. Why do they have different effect?

              Comment


                #8
                Originally posted by MattL0 View Post
                what do you mean?

                Comment


                  #9
                  Originally posted by alexbk66 View Post
                  what do you mean?
                  I just quoted someone, because i want him to read that thread

                  Comment


                    #10
                    Originally posted by alexbk66 View Post
                    2. Since you use the device name anyway - why not just call SetDeviceStringByName?
                    What was said above. But since you asked about DeviceString, here is my understanding of where one would utilize the DeviceString:

                    A device will have pairs of numeric numbers and corresponding labels. For example, a standard binary switch might have 0 and off, and 100 and on. The "off" and "on" can be changed to whatever you want, but that label is associated with that value.

                    HS uses the value when setting a device, not the label. The label is for us humans. (BTW, a label text string can be associated with a range of values, such as on a dimmer). A label is locked to its corresponding value (or values).

                    On some devices, you might want to use something more than that label. For example on a thermostat, you might want to see a label that is more useful than the label associated with the value - label pair. For example, instead of just having "72 F" for a label, you might want a label that says "72 F (Heater is on)". You set that modified label using the DeviceString call. It sets the device's label to that string, but does not change the value (or state) of the device.

                    So you use CapiControl to change the value or state of a device. You use DeviceString if you want the text associated with that device to be something different. The UI will use the DeviceString if it is non-blank, otherwise it uses the label that is associated with the device's current value.

                    Hopefully I got that right. I am sure someone will correct me otherwise!

                    Comment


                      #11
                      Originally posted by aa6vh View Post
                      What was said above. But since you asked about DeviceString, here is my understanding of where one would utilize the DeviceString:
                      Sorry, my bad - I meant SetDeviceValueByName (not SetDeviceStringByName)

                      Comment


                        #12
                        Originally posted by alexbk66 View Post

                        Sorry, my bad - I meant SetDeviceValueByName (not SetDeviceStringByName)
                        The SetDeviceValue/SetDeviceValueByName was how they did it in the old days, before the CAPI stuff was implemented. It does not work properly now. Unfortunately, the documentation has not caught up yet.

                        Comment


                          #13
                          Originally posted by alexbk66 View Post
                          Thank you Bill I'm not really "confused" - I was using CapiControlHandler, but for RaspberryIO it wasn't showing in HS, but SetDeviceValueByRef was showing in HS, but wasn't changing outputs - that's the problem.

                          Also, I'm not sure which one really should be used in SetIOMulti()? All examples and Help use SetDeviceValueByRef. And I did have problems with CapiControlHandler here.

                          I reckon something is wrong with HS here - both functions should behave the same IMHO. Why do they have different effect?
                          Alex, you are confused (sorry, again its a normal part of learning this system). They do not do the same thing. In the example you mentioned (RaspberryPi) it sounds like a plugin bug you ran into that calling CapiControlHandler is not updating the device values. You should report that to the plugin author.

                          SetIOMulti is what is called to actually change a device, while SetDeviceValue is what is called to update the HS UI for the device. Lets take an example that will help:

                          DeviceX is a wifi light bulb. It has a plugin to control it from HS, and can also be controlled locally.
                          DeviceX supports ON and OFF.
                          The plugin exposes two controls set as both (so both status and control). One is the 'Off' and has the value 0 in HS, and On which has the value 9999

                          When a user clicks on the 'On' button on the device management page, or an event wants to turn the light On. It looks up the 'On' value and sends it via the capicontrolhandler. The plugin responsible for controlling that device type receives it in its SetIOMulti() and then is expected to PHYSICALLY CHANGE THE LIGHT TO ON (e.g. send the actual TCP or UDP data to the device to force a state change). If the change is successful (e.g. no errors sending the state change to DeviceX) then you should call SetDeviceByValue() to update the HomeSeer UI. The docs state this directly; "If setting the value in the hardware fails, do not call hs.SetDeviceValueByRef and log a warning or error message."

                          Now if the light is on and a user turns it off from a wall switch or say a non HS related app on their phone. In that case the plugin determines the light is off (maybe it polls for status like JowiHue does for the Hue bridge, or maybe it receives an updated message via TCP like the Tuya bulbs do, or maybe smoke signals are used ,) point is the plugin determine the device is off). In that case the device does NOT need to physically change anything on the bulb, it JUST needs to update the HomeSeer UI. So it calls SetDeviceValue with 0 so the UI reflects 'Off'.

                          Read this a few times, it will click, I promise...

                          Bill

                          Comment


                            #14
                            Originally posted by aa6vh View Post
                            The SetDeviceValue/SetDeviceValueByName was how they did it in the old days, before the CAPI stuff was implemented. It does not work properly now. Unfortunately, the documentation has not caught up yet.
                            I think it's opposite - in HS3 they removed this simple functionality (in HS2 function was called something like SendValue or similar). And introduced CAPI - and developers complained that lots of scripts were broken and opened a poll asking for this functionality in HS3. So HS added SetDeviceValueByName. But I could be wrong...

                            Comment


                              #15
                              Originally posted by bsobel View Post
                              Read this a few times, it will click, I promise...
                              Thanks again Bill.
                              So, if I understand correctly - in my plugin to control devices (both my and others) I always use CapiControlHandler.
                              And in SetIOMulti I use SetDeviceValueByRef.
                              And in case of RaspberryIO - I use both just because it's a problem in the plugin, and until the developer fixes the problem?

                              Comment

                              Working...
                              X