Announcement

Collapse
No announcement yet.

Help With Honeywell Z-Wave Thermostat Commands

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

  • Help With Honeywell Z-Wave Thermostat Commands

    Okay,

    So, I have done some searches and seen this come up multiple times, but I haven't been able to find a clear full answer...only many partial, sometimes nonsensical, answers.

    I have created a c# script to revert set points and thermostat modes to a set of adjustable "locked" virtual values. When the wife or kids change the thermostat it waits 30 seconds and reverts it to whatever I have the virtual devices locked to. Any time a value is changed or on the hour the script runs, compares set points to locked values, and runs functions based on != values.

    Getting the device values changed is no problem. Unfortunately, I cannot figure out how to get the script to send commands directly to the thermostat without using associated events. Changing the device value does not affect the actual thermostat. It does work with the associated events but is clunky, requires a ton of events, and uses 50 lines of code for what could be 2.

    I am aware that there are plug-ins available for variable controls and am not interested in using them. At this point it is principle and frustration more than necessity. It does work as it is but it sucks.

    I have read the documentation and can't determine if there is an answer in there. I'm sure there is, but I clearly don't understand it if so.

    I just need the line of code that will allow me to send the set point, mode command, or fan mode command to the thermostat with a device code of t1 based on a variable such as "int lockedHeatSetPoint" or "int /string lockedThermostatMode", etc... ...and I need the syntax for the method or statement spelled out for a plain idiot with little comprehension of scripting or coding to understand. Also, the only language I know is C#, though I'm sure I can make any necessary translations from VB. Any help is greatly appreciated. Thanks!!!

  • #2
    I just completed a new AC unit upgrade, and installed two Honeywell thermostats, one for each floor, adding a damper system to make a quite effective split a/c unit. The thermostats connect to a controller which controls the dampers and actual a/c unit.

    With HS3, the two thermostats stay synchronized. If I change one thermostat (mode, temperature, fan, etc.), the other thermostat gets immediately updated to match. Now the dampers take care of matching the temperatures between floors.

    I then added all the automation logic for home/away temperatures, time of day temperature set points. Lastly, I put sensors on all the windows. Using the day's weather forecast, if it starts to get warm in the house and it looks like it'll be an a/c day, the system will either announce it's turning on the a/c, or "it's time to turn on the a/c however there are still x windows open." Upon closing the last window the a/c turns on automatically. Sweet!

    Now to your question, here's the command that controls the thermostats directly.

    Code:
    Function SetDeviceByControlValue(ByVal intDevRef As Integer, ByVal ctlValue As Integer) As CAPIControlResponse
        ' Sets this device (refID) by Control Value [CAPI: ControlValue] - e.g. 0 = off, 1 = Heat, 2 = Cool... 
        SetDeviceByControlValue = CAPIControlResponse.Indeterminate
        For Each objCAPIControl As CAPIControl In hs.CAPIGetControl(intDevRef)
            If LCase(objCAPIControl.ControlValue) = ctlValue Then
                SetDeviceByControlValue = hs.CAPIControlHandler(objCAPIControl) ' SET
                Exit For
            End If
        Next
    End Function
    I've attached the full script, all events call this with a different {param} value. You can see the parameter names that are passed to the script from the events {param}, and follow the logic from there. Admittedly, some of the code could be optimized, I did this rather quickly but it has worked out very well.
    Attached Files
    Mike

    Comment


    • #3
      Much Thanks

      First of all. Thank you so much for taking the time to explain all of that for a moron such as myself.

      So, I started dissecting what I need out of the script and am still a little lost. Perhaps you can clarify a few things if you have the time.

      I'm unfamiliar with VB, but I'm guessing that what it calls Cases are similar to Methods which accept parms in C#.

      It looks like, for what I'm trying to replace in my own script, that I only need one of the commands in this thing "SetDeviceByControlValue()". I noticed two things about this. First of all, it is not prefixed with "hs.". I'm assuming that it is not requiring the prefix because of the statements or dependencies at the bottom of the script, but I have no idea how to implement those into a c# script. Do you have any clue or are these statements, as you quoted in your reply, even necessary within the script?...or how can I reference them from another script?

      The second, you are assigning the return of the SetDeviceByControlValue statement to "result" variable. Why? And is this step necessary?

      Please pardon the stupidity. I'm just learning this.

      Thanks again!

      Comment


      • #4
        Follow-Up

        Okay...upon a little further examination, I misunderstood something. The SetDeviceByControlValue that you sent is actually the method, yes? The rest are the parameters passed into that method to control the thermostat. So, the lines of code at the bottom are actually to create the "single command" that I was looking for. I just need to substitute parms to meet my needs. So, I only need to figure out how to add a method into a c# script and translate this thing into the correct syntax for c#. I think I'm on the right track. We all have to learn sometime I guess!

        Comment


        • #5
          The 'cases' is a branching mechanism.

          Code:
          Select Case {parameter}
            Case 1
               do this
            Case 2
                or do this
            Case 3
                or even this
          End Select
          The event passes the {parameter} to the script, then the script executes the code within the matching case. So if the event passed "1", then the 'do this' code executes, all other code within the Select Case ... End Select is ignored. Effective when you want a single script to perform different functions.

          The function at the end...
          Code:
          Function SetDeviceByControlValue(ByVal intDevRef As Integer, ByVal ctlValue As Integer) As CAPIControlResponse
              ' Sets this device (refID) by Control Value [CAPI: ControlValue] - e.g. 0 = off, 1 = Heat, 2 = Cool... 
              SetDeviceByControlValue = CAPIControlResponse.Indeterminate
              For Each objCAPIControl As CAPIControl In hs.CAPIGetControl(intDevRef)
                  If LCase(objCAPIControl.ControlValue) = ctlValue Then
                      SetDeviceByControlValue = hs.CAPIControlHandler(objCAPIControl) ' SET
                      Exit For
                  End If
              Next
          End Function
          ... is a function call, it can be called anything (in this case SetDeviceByControlValue). It's a code branch to jump to that function, execute the code within, and return some value (hence a function not a sub, which does not return a value). The function returns the status of the CAPIcontrol command. Normally when you call a function you expect to have a value returned, hence the 'results' value in the script. However, if you are not interested in knowing the results you can call the function without the results:

          Dim results = SetDeviceByControlValue(dnstairsFANset, upFAN)
          SetDeviceByControlValue(dnstairsFANset, upFAN)

          Both of these will execute equally well.

          Within the function you see the actual HS CAPI command to control the device:
          SetDeviceByControlValue = hs.CAPIControlHandler(objCAPIControl)
          'SetDeviceByControlValue' is the same name as the function, therefore this is the value the function returns to the main program (as results).

          Did I make it more or less confusing? I'm not a professional programmer so I may have not explained this well.
          Mike

          Comment


          • #6
            Originally posted by JosephQHughes View Post
            Okay...upon a little further examination, I misunderstood something. The SetDeviceByControlValue that you sent is actually the method, yes? The rest are the parameters passed into that method to control the thermostat. So, the lines of code at the bottom are actually to create the "single command" that I was looking for. I just need to substitute parms to meet my needs. So, I only need to figure out how to add a method into a c# script and translate this thing into the correct syntax for c#. I think I'm on the right track. We all have to learn sometime I guess!
            You snuck this in on me while I was explaining... lol! Yup, you only need the function code to perform a change to the thermostat.
            Mike

            Comment


            • #7
              Pretty Great Explanation

              I think your explanation was as clear as I could have possibly hoped for. The breakdown is all on my end, not yours. I've always had a bit of a breakdown passing arguments and parms to and from methods. To me that is pretty impressive for a "non-professional" programmer! Then again, I have little comprehension of anything I'm actually doing.

              So, maybe you can help with one more thing. I have translated this into C# to integrate it into all of my own scripts the best I know how but still show an error. I've been changing things for hours trying to figure it out. It is worth it to me because I'll literally be using this single function for nearly every script I use. Unfortunately, everything is already written in C#.

              Now, just as a basic test for the function, I have the following (pasted and attached as test.txt. It wouldn't let me upload a .cs file so I changed the extension). Any idea what is incorrect that is giving me an assembly error? I'm thinking it is somewhere in the function method header but can't seem to figure out the correct syntax. Here goes:


              public Object Main(Object[] parm)
              {

              //Test Call For the SetDeviceByControlValue Method
              int heatDevice =235;
              int heatSetPoint =51;
              SetDeviceByControlValue(heatDevice, heatSetPoint);
              //Test Call For the SetDeviceByControlValue Method
               
              return null;
              }
               
               
              public Object SetDeviceByControlValue(int intDevRef, int ctlValue) //(I don't know what to do with this) As CAPIControLResponse
              {
              SetDeviceByControlValue
              = CAPIControlResponse.Indeterminate;
              foreach (CAPIControl objCAPIControl in hs.CAPIGetControl(intDevRef))
              {
              if (objCAPIControl.ControlValue.ToLower() == ctlValue)
              {
              SetDeviceByControlValue
              = hs.CAPIControlHandler(objCAPIControl);
              break;
              }
              }
              return null;
              }
              P.S. How do you add those little scroll boxes into your forum posts?

              If it is easier, you can access the system directly to see how these things are set up. It can be accessed from http://zhome.josephqhughes.com/ (use default credentials).

              It's all backed up so feel free to do as you please.

              If it would be of any help to you there are also a lot of modified graphics at http://zwave.josephqhughes.com/ that I use for HSTouch. You're welcome to any of them you'd like.
              Attached Files

              Comment


              • #8
                Mix-Up

                Somehow our posts got placed chronologically backwards. I did respond to your last. It just, for some reason, is above your last post.

                Thanks again,

                Joe

                Comment


                • #9
                  Hi Joe,

                  I'm not C# knowledgeable, however see if this works:
                  Code:
                   
                   
                  public CAPIControlResponse SetDeviceByControlValue(int intDevRef, int ctlValue)
                  {
                   CAPIControlResponse functionReturnValue = default(CAPIControlResponse);
                   
                   functionReturnValue = CAPIControlResponse.Indeterminate;
                   foreach (CAPIControl objCAPIControl in hs.CAPIGetControl(intDevRef)) {
                    if (Strings.LCase(objCAPIControl.ControlValue) == ctlValue) {
                     functionReturnValue = hs.CAPIControlHandler(objCAPIControl);
                     // SET
                     break;
                    }
                   }
                   return functionReturnValue;
                  }
                  (to get the code in a scrollbox, select the code, then use the # symbol in the editor to wrap the selected text in code.)
                  Mike

                  Comment


                  • #10
                    It's awfully close

                    It still gives me an assembly reference failure, but it's really close. I will figure it out eventually. Someone around here has to know how to declare and call methods in c# for scripting. I just need to keep experimenting until I find the correct method header for HS functions. That seems to keep hanging me up. Every one I try to add into a script thinks its a main. Furthermore, I have some trouble with the objects in the method headers. Again, I can't thank you enough for your help. I'll try a new thread for c# method declarations for "functions".

                    Comment


                    • #11
                      Finally Got It

                      With your help and plenty of hours trying, I finally got the CAPI handling to work with c# and pass parms into the methods. If you ever wind up with a use for a c# template for control, using classes like TurnOn(device), TurnOff(device), etc...let me know and I'll shoot you a copy of everything I have. Thanks again for the help.

                      Comment


                      • #12
                        Originally posted by JosephQHughes View Post
                        With your help and plenty of hours trying, I finally got the CAPI handling to work with c# and pass parms into the methods. If you ever wind up with a use for a c# template for control, using classes like TurnOn(device), TurnOff(device), etc...let me know and I'll shoot you a copy of everything I have. Thanks again for the help.
                        OK thanks. Glad to see you got it working!
                        Mike

                        Comment


                        • #13
                          Hi guys. I am in the same boat as Joseph, a c/c++/c# programmer, so vbscript is new to me. I have Mike's Function working, but it controls both of my Honeywell thermostats. I just want it to control the one defined by the device ID I pass to the function. How can I "simplify" the function to perform that simple task?

                          Thanks!

                          Comment


                          • #14
                            Never mind..I got it. Thx.

                            Comment

                            Working...
                            X