Premise Z-Wave Status using RZCOP/VRCOP help

Motorola Premise
Good news! PS works for single nodes! See the attached results. Note, I modified your code for OnChangeSceneID to run these tests to:

Code:
dim oMember, oDevice
dim sCmd: sCmd = "ON,UP"

if sysevent.newVal and this.SceneID > 0 then
	' Set light level for each member
	for each oMember in this.GetObjectsByType(Schema.Modules.Leviton.Classes.SceneMember.Path, false)
		set oDevice = oMember.Device
		if oDevice.IsOfExplicitType(Schema.Modules.Leviton.Classes.Dimmer.Path) then ' Dimmer
			this.Parent.Parent.SendCommand ">N" & oDevice.NodeID & "L" & this.ConvertBrightness(oMember.Brightness) & ",UP", true
		else ' Switch
			if oMember.PowerState = false then sCmd = "OF,UP"
			this.Parent.Parent.SendCommand ">N" & oDevice.NodeID & sCmd, true
		end if
		this.Parent.Parent.SendCommand ">N" & oDevice.NodeID & "PS" & this.SceneID & ",255", true
		this.Programmed = now	
	next
end if

set oMember = nothing
set oDevice = nothing

And to this the second time. Note I appended "UP" to the PS command for this trial. I think it is needed so that all controllers know which nodes have a scene stored:

Code:
dim oMember, oDevice
dim sCmd: sCmd = "ON,UP"

if sysevent.newVal and this.SceneID > 0 then
	' Set light level for each member
	for each oMember in this.GetObjectsByType(Schema.Modules.Leviton.Classes.SceneMember.Path, false)
		set oDevice = oMember.Device
		if oDevice.IsOfExplicitType(Schema.Modules.Leviton.Classes.Dimmer.Path) then ' Dimmer
			this.Parent.Parent.SendCommand ">N" & oDevice.NodeID & "L" & this.ConvertBrightness(oMember.Brightness) & ",UP", true
		else ' Switch
			if oMember.PowerState = false then sCmd = "OF,UP"
			this.Parent.Parent.SendCommand ">N" & oDevice.NodeID & sCmd, true
		end if
		this.Parent.Parent.SendCommand ">N" & oDevice.NodeID & "PS" & this.SceneID & ",255,UP", true
		this.Programmed = now	
	next
end if

set oMember = nothing
set oDevice = nothing
 

Attachments

Thanks for carrying out all of the tests. If I can summarize your results:

Play a scene
">S1,255" will activate Scene 1 but only the devices listed in the last association list will play the scene. So if the last command had an association list containing ">N2,10,25", then only those devices will play scene 1 (assuming they have been programmed with scene 1 instructions).
The best way to play a scene is to ensure it includes its own association list. For example: ">N2,10,25S1,255". This is how BETA9-5 currently plays a scene.

Add a device to a scene
Devices can be individually added to a scene. This is how BETA 9-5 currently handles scene programming. However, you indicated it is better if each transmission includes the "UP" comamnd. The next posted release will include this modification.

Let's allow the driver to run for at least a week and see if any other tweaks are needed. We'll accumulate all of the modifications into the next release.
 
What you said sounds correct. Anyways, here's the response from Leviton on fade rate:

The fade rate values will be entered in seconds for the scene commands with the VRC0P. All values between 0-127 will be measured in seconds after 127 there is a calculation in that takes place. This value can be adjusted up to three minutes for the VRC0P. The 255 default value will be the same as the default for the individual dimmers you are including into the scene.

Keith L. Culton

Technical Service Associate

T: 800-824-3005
F: 631-812-6762
[email protected]

Leviton Mfg. Co.
201 North Service Road
Melville, NY 11747
www.leviton.com

The maximum fade rate is three minutes which would be a value of 180.

Keith L. Culton

Technical Service Associate

T: 800-824-3005
F: 631-812-6762
[email protected]

Leviton Mfg. Co.
201 North Service Road
Melville, NY 11747
www.leviton.com
 
My thermostat arrived today: it is a model a Wayne Dalton WDTC-20. I can't wait to get home next week to install it. I'll post the thermostat test results on Wednesday.

Funny idea for the thermostat to keep my wife from changing settings on me ;):

Unless the up dimmer on an X10 remote has been held down for more than 3 seconds, at least 1 minute prior to changing the thermostats settings, any thermostat changes will be reset once the new settings have been received on the next polling cycle. I think she'll wise up to this pretty quickly though.

PS: I've had 60 second polling enabled for a few days now and the test results are attached. The results look very good. Thanks for building this wonderful driver 123!
 

Attachments

  • current_test_data.JPG
    current_test_data.JPG
    19.8 KB · Views: 11
Thermostat functionality seems to work great! Thanks 123. One thing to note though is the Wayne Dalton ~$65 is cheaply made and does not support fan status. If I watch the thermostats output in port spy there is nothing sent when I change the fan mode on/auto. Since I always use auto for the fan setting, I'll place a script at the home level to turn the fan off whenever the heater or air conditioner is not actually running, not a big deal.

Overall, I wouldn't recommend the Wayne Dalton WDCT-20 (unless you are on a budget like me) since it doesn't support fan status nor allow for manual user programs (ie set backs etc...). The thermostat itself does what the documentation says it will, but it does require a common wire while my previous thermostat did not. Luckily there were some spare wires ran already and I simply hooked one of them to the common terminal of the transformer and the other end to "C" on the thermostat.

Also, the plastic on the thermostat is cheap and it's hard to lock everything in place with it on the wall as the base will flex some after it's screwed into place. For $65 though, the thermostat is worth it. I think I'll do an RMA if I see one I like that supports fan status and is user programmable. My guess is there is no other z-wave thermostat in the $65 price range though.

Also, not a deal breaker, but the Wayne Dalton thermostat seems to slow the two way feedback down a few seconds for nodes placed near the thermostat. This seems better than the home settings light I returned that was slowing feedback down 30 seconds though! I'm not sure why non-leviton devices slow the feedback down. Of course, polling would still work fine.

I did change one place in the onchange script to get the thermostat to receive setpoints:
Code:
case 67: ' Thermostat Set Point
'modified the top line below as shown:
	'if  aParms(2) = 1 and _
	if  (aParms(2) = 1 or aParms(2) = 3) and _
	(aParms(3) = 1 or aParms(3) = 2) and _
	aParms(4) = 9 then this.Devices.SetThermostatSetpoint aParms(0), aParms(5), aParms(3)


Below is what the Wayne Dalton spits out following a poll command:
>N28SE49,4
>N28SE49,4
<E000
<X>N28SE64,2
000
>N28SE64,2
<E000
>N28SE66,2
>N28SE66,2
<N028:049,005,001,009,073
<X000
<E000
>N28SE67,2,1
<X000
>N28SE67,2,1

<E000
<N028:064,003,001
>N28SE67,2,2
>N28SE67,2,2
<X000
<E000
>N28SE68,2
<X000>N28SE68,2

<E000
>N28SE69,2
>N28SE69,2
<N028:064,003,001
<N028:066,003,001
<N028:067,003,002,009,071

<N028:067,003,002,009,071
<X000
<E000
<X000
 
Not sure why yet, but the desired temp disappears under the automation browser when I try to raise lower the blue and red arrows in automation browser, nothing happens unless the heater or ac is actually running at the time? Also, during this period desired temp says unavailable even though heating mode is selected?

EDIT: It appears the issues were in how Premise handles thermostats. The "desired temp" shown in the automation browser is the same as the "CurrentSetPoint" property found the thermostat class. This means code is needed to link "CurrentSetpoint" to the heating and cooling setpoints. I've took a stab at this, see the attached file. I modified: OnChangeOnNewData (from previous post), SetThermostatSetpoint, OnChangeHeatingSetPoint, OnChangeCoolingSetPoint, OnChangeTemperatureMode and OnChangeCurrentSetPoint (new script).

My thermostat doesn't have an auto heat/cool mode, so I'm not sure what code would be needed here. Somehow, CurrentSetPoint needs to know whether to use the heating or cooling set points, but if the mode is auto (versus hear or cool), this task is more complex...
 

Attachments

It took a fair bit of research to find the appropriate Z-Wave commands for handling thermostat functions. I'm glad to hear that the code is working correctly (more or less).

Before diving into AutomationBrowser, look at the driver's UI and watch how the Thermostat's HeatingSetPoint, CoolingSetPoint, and CurrentSetPoint properties work when you operate the physical thermostat. Confirm the driver's code is doing its job properly.

The AutomationBrowser's Thermostat user-interface is a complex animal. I recommend you become familiar with it in order to get a better handle on why it is acting up. Here is where you'll find the Thermostat's user-interface elements:
Modules > Plugins > Selectors > Thermostat > ThermostatPanel

The one you probably want to inspect is:
Modules > Plugins > Selectors > Thermostat > ThermostatPanel > CurrentSetPointValue

It has a related CompositeControl called CurrentSetPointState and it can be found here:
Modules > Plugins > ControlsLibrary > ThermostatControls > CurrentSetPointState

Dig one level deeper and you'll find its "OnRenderValue" method. This is the method that renders the user-interface. Have a look at the code and you'll find it prints "not available" if the temperature is not within the range of -20 F and 120 F. This could happen if the Temperature is converted incorrectly (i.e using the wrong Temperature scale). However, I'm certain the driver saves incoming readings in Fahrenheit (all Z-Wave examples indicate temperature data is returned in Fahrenheit).
 
Thanks 123, I'll look into this. See the EDIT on my last post.
I believe the fix was pretty simple, but I may not have fixed things the correct way (although the thermostat in automation browser seems to work now).

Ok, there appears to be one issue with my fix: if polling has been started, the new value for desired temp is replaced with the old value. Is there a way to pause polling? If not I believe a delay script could be used to fix the following issue:

Problem:
The WDCT-20 does not update temperature the second it receives a new set point value. It takes the termostat a few seconds after receiving the new temp to actually store and use the temp (I'm going to call Wayne Dalton for more info on this, it may be specific to Wayne Dalton). This means that after I change a value via the atuomation browser if the thermostat is polled a second later, my new set point value is lost.

Solution:
What is interesting is the up and down arrows for the thermostat under the automation browser do not behave like those found on brightness conrols. For each press a command is sent...!?! This led me to think about how unhappy the thermostat must feel when its internal buffer is filled with requests to change the temp every 100ms when I go from 1 to 5 degrees. A 3 second timer appears to fix the issue altogether. I'm still testing the code, but I'll post the new version later on tonight.
 
... code is needed to link "CurrentSetpoint" to the heating and cooling setpoints. ..
I thought I had included support for this but now realize I only added it in one function (OnChangeTemperatureMode). I took a quick look and the changes you made make sense. I would re-write SetThermostatSetpoint because it originally only handled two states (heating/cooling) and should handle 4 states (auto/heating/cooling/off). as it stands, the code has an initial if/then/else followed by the select/case you added. Everything should be handled in a select/case.

Regarding polling and the Wayne-Dalton thermostat's need for some time to digest its commands ... that's ugly. I'm not sure how a delay-timer can solve this problem.

  1. Adjust setpoint.
  2. Driver issues command to adjust setpoint.
  3. Thermostat receives command.
  4. Digesting the command ...
  5. Poll is sent.
  6. Digesting the command ...
  7. Thermostat receives poll.
  8. Digesting the command ...
  9. Replies to poll (replies with the old setpoint)
  10. Driver receives the (old) setpoint and effectively reverts the new setpoint back to the old setpoint!
  11. Thermostat finally digests the command.
  12. Driver issues command to adjust setpoint (uh-oh).

The simplest way to avoid this problem would be to have polling skip a cycle whenever the user changes the setpoint or any other thermostat property. This would ensure that polls occur well after the user makes a change.
 
Thanks 123! As a preliminary version, here's the code that I used to fix the problem described above. My solution is to modify the thermostat's on change scripts to set the oneway property to false, then re-enable using a 5 second timer. Also, once current set point has changed, a 3 second timer is used to send the new command is set to ensure the user is done using the up/down arrows in the automation browser. This works because addTimer will always reset any existing timer with the same name.

Another alternative would be to rewrite the automation browser code for the thermostat up/down buttons to behave like the press/hold dimmer buttons that only send one command.

Wayne Dalton time to adjust commands: I don't think this is necessary if a dozen commands aren't being sent to the thermostat to go from 68F to 80F. This new code should only send one command for this assuming the user doesn't stop for 3 seconds in between presses. The timers I've incorporated in effect allow for at least a 2 seoncd delay period (could be more depending on when next poll is) for the thermostat to rest (ie 5 seconds minus 3 seconds = 2 seconds).

Example:

OnChangeCoolingSetPoint

Code:
'
if this.ReceivingUpdate = false then
	if this.OneWay = true then
		this.OneWay = false
		system.addTimer 5, "this.OneWay = true", 1, this.Name & "_set_onway_" & this.ObjectID
	end if
	
	'this.Parent.Parent.SendCommand ">N" & this.NodeID & "SE67,1,2,9," & round(this.CoolingSetPoint.Fahrenheit) & ",UP", true ' High-priority
	system.addTimer 3, "this.Parent.Parent.SendCommand '>N' & this.NodeID & 'SE67,1,2,9,' & round(this.CoolingSetPoint.Fahrenheit) & ',UP', true", 1, this.Name & "_update_setpoint_" & this.ObjectID
	if this.TemperatureMode = "Cool" or this.TemperatureMode = "Auto" then
		this.CurrentSetPoint = this.CoolingSetPoint
	end if
end if
 

Attachments

This solution you've implemented is designed to address the situation where a poll occurs immediately after a user alters the setpoint. It disables the Thermostat's OneWay property so it is effectively excluded from the next polling cycle.

How will this solution address the equally possible situation where a poll occurs immediately before the user alters the setpoint?

The Job Queue will contain commands to query the thermostat. The end-user's setpoint alteration will be a high-priority command so it'll be executed before the low-priority thermostat polling commands. After the setpoint command is processed, the queued thermostat polling commands come next and are not suppressed by the code-changes you've made.

What I had in mind was twofold. Whenever the end-user changes a SetPoint:
1) Reset the Polling timer.
This ensures the next poll happens well after the setpoint command is issued.
2) Purge the Job Queue of all pending thermostat queries.
This ensures queued thermostat commands won't appear immediately after the setpoint command is transmitted.

This approach requires a minor modification to the driver's architecture. It needs a means of identifying a command's Type so SendCommand will know how to handle the command correctly.

The command types would be Lighting and Thermostat. If SendCommand is passed a High-Priority Thermostat command, it means the end-user has altered a thermostat setting. SendCommand would reset the Polling timer and purge all Low-Priority Thermostat commands (i.e. commands generated by Polling) from the Job Queue. Clean and simple.
 
What you're saying sounds entirely possible. I think I finally see your concern. Clearly you are very clever 123 :rolleyes:

If I understand you correctly, a poll would have to already be in queue and happen to fall x seconds after the user command has been sent since user commands have job queue priority. If we assume it would take the thermostat greater than x seconds to process the command, the poll would over write the user command with in SYS and SYS will have the incorrect value for the command. However, SYS would not try to send an incorrect command value to the thermostat due to the receive update flag (ie oDevice.receivingUpdate = true and if this.ReceivingUpdate = false). The incorrect value would be corrected on the next polling cycle since during this process the poll will not result in a command being sent out to the thermostat and the thermostat hopefully would have completed processing the user command after replying to the poll (ie the device should have an internal command buffer)?

I'm not seeing any issue with this one instance of polling taking place immediately after a command has been sent, but the original need for several timers is still there and such a solution is not as elegant as what you are proposing. I believe what you are proposing could be used to eliminate the receive update flags altogether, but I'm not sure how complicated this would be and I don't know much about programming except what I've learned from you.

Wouldn't this be possible with lighting (that relies on polling so non-vizia rf) too? I think I haven't noticed this for lighting because: 1. I haven't been home to test the lights much, 2. I don't rely on polling for the lights and 3. I don't use the dimming function very often. I do think my use of timers is a half baked solution compared to your idea ;) SendCommand could look at the oneway property for an object, and if it's set to true purge the job queue and reset the polling interval and not be limited to thermostats but do this for any object with oneway set to true?
 
I am now totally lost. I can no longer understand what, if anything, needs to be resolved.

...I'm not seeing any issue with this one instance of polling taking place immediately after a command has been sent, ..
This is contrary to what was stated in your previous post:
Problem:
The WDCT-20 does not update temperature the second it receives a new set point value. It takes the termostat a few seconds after receiving the new temp to actually store and use the temp ... This means that after I change a value via the atuomation browser if the thermostat is polled a second later, my new set point value is lost.
So you're saying it's no longer a problem? I no longer understand the purpose of the delay timers you've implemented. Is it to prevent successive SetPoint commands from overwhelming the thermostat ... or is that a separate issue?

Lost.

BTW
Delay Timers are evil. A problem that gets "fixed" by just waiting longer, can fail when the conditions change. What works with 2 red widgets, fails with 20 red widgets ... or 2 green widgets.

Wherever possible, it is more efficient and reliable to act on events ("Event-based programming") as opposed to waiting around for fixed time periods. For example, the driver could simply wait 2 seconds before sending the next command (or 3, 4, or 5 seconds) to prevent an RZC0P buffer overrun. However, the Job Queue eliminates fixed delays and makes the transmission process event-based and very time-efficient.
 
Problem:
The WDCT-20 does not update temperature the second it receives a new set point value.

I don't think this is what was actually causing the issue so disregard it.

What I now think was happening:
The real problem was the way the up/down buttons behave, sending a command for each degree and that polling would receive a previous value in the scenario where a user kept raising temp a degree at a time and commands were sent out for each increment. If we eliminate the issue with the incremental commands being sent, the polling issue could still occur if a user pauses 3 seconds and a poll is received during this period (the timer length to prevent incremental commands) between button presses. That was the purpose of the second 5 second poll: to eliminate a new poll being received during this three second pause, but as you have cleverly pointed out, it still could be in the job queue, so this 5 second timer in effect serves no purpose in the special case you brought up where a poll is immediately sent following a command, but assuming the user waits until the next polling cycle before pressing the up/down buttons in the Automation Browser, the next button press will send the correct value. If they repress the button after the invalid poll values are received, and invalid plus one degree value will be written to the thermostat.

Your idea is very clever and would fix all of these issues without the need for any timers because it would get rid of the polling issue and should avoid the situations described above.

I no longer understand the purpose of the delay timers you've implemented. Is it to prevent successive SetPoint commands from overwhelming the thermostat ... or is that a separate issue?

Yes, the three second timer serves this purpose. The five second timer is to prevent any new polls occurring while the user is changing the values. Again, this 5 second timer is for the special case of a user waiting 3 seconds in between each press (pretty unlikely, but possible). However, as you have pointed out, it doesn't check the job queue for previous polls still in the queue and should if a user is going to wait 4 seconds between presses or something like that.

BTW
Delay Timers are evil. A problem that gets "fixed" by just waiting longer, can fail when the conditions change. What works with 2 red widgets, fails with 20 red widgets ... or 2 green widgets.

This makes sense and is yet another reason why my fix may not always work... IE, if a user waits 4 seconds between button presses, the fix I have made may not work if poll jobs are still in queue from before. I would treat all one way objects the same and delete the job queue polls for all one way objects. I'm guessing this would require adding another reference property to the job class... and modifying send command to delete all jobs with low priority that reference a given object?
 
OK, thanks for the clarification; I think I'm on the same page as you now.

Here's what I've done in BETA 9.6.
  • Added an enumeration called JobCategories:
    0 - Other (identifies Scene, Group, and raw ViziaRf commands)
    1 - Switch
    2 - Dimmer
    3 - Thermostat
    4 - MotionDetector (for future use)
  • The following methods AddJob, RunJob, SendCommand now take three parameters: Data, Priority, and Category.
  • All calls to these methods have been updated so that they pass a Category parameter.
  • The ProcessCurrentJob method now displays (in DebugView) the current Job's category.
Everything else has been left untouched (i.e. delay timers, code for handling CurrentSetPoint, etc). The only difference you should notice is that the Job's category is displayed in DebugView. Please confirm BETA 9.6 works correctly and hasn't broken anything.

In previous versions of the driver, ProcessCurrentJob knew nothing about the command it was transmitting out the serial-port. In this version, ProcessCurrentJob knows if it is about to transmit a Switch, Dimmer, or Thermostat command. Now it has the potential to make decisions based on the command's category. Logic can be added to process one command category differently from another. For example, it can handle High-Priority (i.e. user-initiated) Thermostat commands differently from Low-Priority (i.e. polling-initiated) Thermostat commands.

But before we start adding more logic, let's confirm it still works correctly!

PS
I definitely agree with the need to prevent the driver from sending successive commands that change the setpoint. Each time the "Up" button is pressed, it'll generate a command to increase the thermostat's setpoint by one degree. Press 5 times and the driver sends 5 successive commands. It should buffer the requests and simply send the last one. The technique you've used, employing a 3 second resettable timer, serves to buffer these requests. I think there's no easier way to do this.

Changing Premise's Thermostat SetPoint buttons, so they behave like Dimmer buttons, is not a simple undertaking. Another challenge is that Ramp buttons use the "RampProperty" method which normally applies to 'Percentage' properties like Brightness and Volume. Each press of a Ramp button will increase the property's value by 10% (that's how RampProperty is documented). Temperature is an 'Integer', not 'Percentage' value (i.e. a real value from 0 to 1). Here's my take on wht happens when you call RampProperty on an Integer value like Temperature: Push the button once and 70 F is increased by 10% and you get 77 F. Not good!
 

Attachments

Back
Top