Premise VRC0P and 2GIG CT30 Thermostat

Motorola Premise

doczaius

Member
I'm just getting started with Premise so forgive me if I'm missing something obvious.
 
I have a CT30 in my Z-Wave network.  The device supports reporting the set point, current temp, fan & mode as well as manual/scheduled however Temperature and Set Point are not working in Premise.
 
I did some manual poking around in the terminal and noticed that when queried the tstat reports back in a format that varies from what I've found in Zensys documentation.
 
>N4SE49,4
<E000
<X000
<N004:049,005,001,042,002,248
 
So I read this as, Node 4, Command Class, Command Report, Value is Temp, ??? (Expecting 009), ???, ???
 
The last bit changes as the thermostat temp does... at approximately 3.2 * Fahrenheit value...  So at 248, the thermostat itself read 76... at 233, 74.5 etc.  As far as I know this isn't °F, °C, K, °r,  or °R...
 
Any ideas?
 
Correction... Set Points do appear correctly after polling (and report as expected in console). So its just the Temperature Sensor that isn't working.
 
http://wiki.micasaverde.com/index.php/ZWave_Command_Classes
Your thermostat appears to be using one of the multilevel sensor classes (for the temperature reporting):

COMMAND_CLASS_SENSOR_MULTILEVEL
COMMAND_CLASS_SENSOR_MULTILEVEL_V2
 
My Trane thermostats both look like this:

<N033:049,005,001,009,072
<N032:049,005,001,009,069
 
For mine, the 49 is the class, 5 is for report, the 1 is for sensor type (1 is presumably for temperature?),the 9 is complicated so better fetch documents from the link below, followed by n values.  
 
I DID NOT post it and found it on google, but see the second link from the bottom here:
http://i7afp.googlecode.com/svn/trunk/Dokumentation/Unders%C3%B8gelsesrapport/Bilag/ZWave/
 
According to that "link" and the fact that I have never signed an NDA with Zensys and found the information freely on google:
I believe your answer lies in the byte after the 1, (the 042) and the data that follows.
 
42 in binary is 001    01     010.
 
<N004:049,005,001,042,002,248
 
From the link, the 001 indicates a precision of one (e.g. 72.1, 72.5 etc...), the 01 means *F, and the 010 means data size (two in your case).


 
I believe the value then is probably a normalized bit value (over the operating range of the sensor).  I believe this is using a two byte signed value where the 002 is the most significant byte and the 248 is the least significant byte. 
 
So we have:  0000 0010 (002) 1111 1000 (248)
If we use windows calculator in programming mode for binary, type in 0000001011111000, select word, then select decimal and we get 760.  Wait, what about about the 001 precision? That's 76.0 degrees Fahrenheit, Eureka!
 
Basically, you'll need to add code to due the binary conversion and process the value for the case when two sensor values are received (leave the existing case alone so other sensors will still work).  Let me know if you need help with that part by posting here.  I think the most significant byte is critical, so you cannot do the conversion like you are doing.  The next release may include a case for 2 bytes of sensor data, and will if I ever end up owning a multilevel sensor that does two bytes.  
 
Things are a little more complicated as the value is signed binary.  I left that part out as you are only dealing with positive values, but if the module is updated, we should make things generic for all multivalue sensor levels, even negative ones.  Also, feel free to post your modifications even if they do not handle the signed binary.  Again, I don't mind helping/doing, especially if a donation is involved ;)
 
Awesome. Thank you for the very detailed response.
 
I'm going to give it a try but.....donation like what... case of beer? or a multi-level sensor that does two bytes? :lol:
 
I think it's a good learning exercise if you are going to use the VRC0P and Premise a lot (I'm assuming you're a programmer?).  If you're not a programmer/engineer, I can give hints or do it...   Beer is accepted if you are in SC.  Paypal is always fine too.
 
How I would approach it is to use the hex and the cint function in vbscript (the binary was meant as a demonstration).  Don't forget to pad a leading zero when using the hex function though for a single character case (e.g. hex(3) = 3, but you'll want 03 for the lower byte).
 
I wouldn't call myself either -- although its what I studied, professionally I've been consumed by the Teradata world. So much besides the basics has gone out the window.  Do you recommend any particular IDE or just the builder itself?
 
Premise Builder and vbscript is all you need to build a complex module like the VRC0P.  Well, that and a lot or time!
 
I would do the following:
Study this link to learn how to explore an object.
http://cocoontech.com/forums/files/file/190-diagram-exploring-a-premise-object-and-its-class/
 
Be sure to enable expert mode in Builder:
http://cocoontech.com/forums/topic/21894-two-output-hdmi-switch-monoprice-4x2/?p=178136
 
Read the intro in the Premise Builder help file (the help files in Builder are very good and have coding examples).
 
Watch these videos:
http://www.mediapcforums.com/node/7
 
You can always open the xdo file as xml in notepad++, but Premise Builder is the only IDE for modifying a module.  There is an SDK for building "add-ins."
 
I was using notepad++ but that's alotta lines to go through!
 
So here is what I have thus far... probably a lot more efficient way to do the conversion... wasn't sure where the hex() should have come in.  So we have two functions one to convert the ints to binary strings and one to convert a binary string into decimal.  Borrowed from some VB sites, modified for vbscript. :
 
 
I placed this in the global vizia script:
 
Function IntToBin(IntegerNumber)
      
    IntNum = IntegerNumber
    Do
        'Use the Mod operator to get the current binary digit from the
        'Integer number
        BinTemp = IntNum Mod 2
        BinValue = CStr(BinTemp) + BinValue
          
        'Divide the current number by 2 and get the integer result
        IntNum = IntNum \ 2
    Loop Until IntNum = 0
    
    IntToBin = BinValue
          
End Function

Function BinToDec(strBin)
  dim lngResult
  dim intIndex

  lngResult = 0
  for intIndex = len(strBin) to 1 step -1
    strDigit = mid(strBin, intIndex, 1)
    select case strDigit
      case "0"
        ' do nothing
      case "1"
        lngResult = lngResult + (2 ^ (len(strBin)-intIndex))
      case else
        ' invalid binary digit, so the whole thing is invalid
        lngResult = 0
        intIndex = 0 ' stop the loop
    end select
  next

  BinToDec = lngResult
End Function

 
And the the follow modification to OnChangeNewData:
 
                    case 49: 'SENSOR_MULTILEVEL
                        if gViziaIsDebugOn(1) then debugout "OnChangeOnNewData(): <" & now & "> Process SENSOR_MULTILEVEL command from node=" & aParms(0) & ", , rxText=" & this.RxTextLine
                        if  iParms = 6 and aParms(2) = 5 and aParms(3) = 1 and aParms(4) = 9 then
                            this.Devices.SetTemperature aParms(0), aParms(5)
                        elseif iParms = 6 and aParms(2) = 5 and aParms(3) = 1 and aParms(4) = 42 then
                            BinStr = IntToBin(aParms(5)) & IntToBin(aParms(6))
                            this.Devices.SetTemperature aParms(0), BinToDec(BinStr) / 10   
                        else
                            this.Devices.ProcessCmd_SensorMultilevel parms, iParms
                        end if

 
I tested out a simplified version in VBSedit with a MsgBox to return the value and it did indeed return 76 -- only problem is the value doesn't seem to be making it to the field in premise?   :unsure:    
 
Happy to report back success as of this morning!  I set a breakpoint on the elseif and found it skipping over.  The temporary addition of a debugout led me to find that it was an issue with the test of iParms.
 
Not sure I completely understand why, but uBound w/in Premise was returning 7 instead of 6 as expected (subscripts start at 0 right?).  So a minor change from iParms = 6 to iParms = 7 and voilà! 
 
I went in and manually set my cooling set point (within premise!) to 75 (from 76 on schedule), and watched polling & spied on the com port while the house cooled. Sure enough a few seconds before I heard the A/C click off, premise reported back a change to 75! Hooray!!
 
I like how you used recursion in IntToBin; pretty neat!   IntToBin should probably be checking that a number was passed before proceeding and calculating a modulus (else an exemption could be thrown by the vbscript interpreter).  However, since the z-wave specification says the two sensor values must always be a number, technically this is optional...
 
Unfortunately, I am not a programmer and studied EE, so I had only one programming course in college.  As 99% of my programming experience is from vbscript alone (e.g. using Premise),  I would have used a function like this:

function gGetSignedInt(sFirstValue,sSecondValue)
dim sUpperByte,sLowerByte

' get values as hex
if isnumeric(sFirstValue) then sUpperByte = hex(sFirstValue)
if isnumeric(sSecondValue) then sLowerByte = hex(sSecondValue)
if len(sLowerByte) = 1 then sLowerByte = "0" & sLowerByte

' cint will automatically handle signed integers
gGetSignedInt = cint("&h" & sUpperByte & sLowerByte)
end function
As you discovered, vbscript doesn't support binary literals, so hex is always your best friend!
 
On second thought, now I remember why I used cint was to get the signed value.  If you just multiply the second number by 256 and add the two parameters, you will have to still handle the signed integer case.  I guess this would make John's suggestion about the same length as mine.
 
However, I like John's idea too.  Good discussion here on programming.
 
Back
Top