Help - Search - Members - Calendar
Full Version: Z-Wave Status using RZCOP/VRCOP help
CocoonTech.com > General > Marketplace > Premise Home Control
Pages: 1, 2, 3
manxam
Hey guys, I've recently started using Premise and have an VRCOP with a bunch of HA14C intermatic dimmers. These dimmers, unlike the super-expensive Vizia RF+ devices, do not update their status automatically and require polling.

Is anyone using the recently posted Zwave device driver for Premise with non Vizia RF/RF+? If so, has anyone figured out how to poll these devices for status?

Without being able to obtain the status of the dimmers, the automation software is relatively useless to me sad.gif

Unfortunately, I'm an html/php/perl/bash guy so I can't program C worth a damn. I have the source code to the dll if that helps.

For those without these devices but with the ability to help, every bound zwave device (node) is assigned an address (numerical 1 to 255).
The VRCOP/RZCOP serial device accepts ascii commands and requires a command such as ">?Nx" (x being the node number 1-255)
The response that is issued is also in ascii and would be "NxxxLzz" (xxx being the node 001-255 and zz being the level 0-99 (off to full bright))

One would then require the "brightness" element under home.room.whichlight.brightness to be updated accordingly.

Preferably this would be a bindable object as not all of the dimmers/switches require polling unless they're used in a schedule/scene/whatever.

Any help would be greatly appreciated...

Thanks!
123
As you've indicated, the driver does not employ polling and was not designed for use with the type of zwave switches you are using. Given this situation, the best solution is to modify the zwave driver. Its author, Damon Dean, has provided the source-code so it is possible to amend it. However, the challenge requires software development skills with C++, an understanding of the architecture of a native Premise driver, and familiarity with the RXCOP's ASCII protocol. Another option would be to study the driver's construction and develop a new one implemented as a Module.

I suspect you weren't planning to do any of the above and would prefer a simpler solution. I suggest you try the following experiment:
The zwave driver has a DiscoverDevices property. What happens when you enable it? I suspect that the first time it is clicked it will create child objects representing the Switches and Dimmers it discovers in your home. Now what happens if you click it a second time? Does it:
  1. Wipe out all existing child objects and then replace them with identical new ones.
  2. Retain the existing child objects and append identical new ones.
  3. Update the status of the existing child objects.

  • The first result is unusable for our purpose because it will destroy existing objects and lose their bindings.
  • The second result is equally bad because we don't want duplicated objects (I doubt it works this way!).
  • The third result is useful.

If #3 is what happens, then all we need is a simple Timer object that periodically triggers the DiscoverDevices property. I have no idea how much overhead a discovery operation represents nor how long it takes to run. I suspect it must iterate through all 255 addresses so the Timer shouldn't run faster than, I dunno, maybe once a minute ... or two?

Give it a try and let us know what happens.
manxam
Thanks for the response 123. As far as I know, this driver was intended for the original (due to the driver's age) RZCOP and Vizia RF line of products which did not automatically update their status ("set hail"). It wasn't until the release of the RF+ and VRCOP device that this feature was enabled so I find it a little curious that this driver doesn't support polling.

That being said, it was extremely nice of Damon to upload these drivers and their source code for us. Unfortunately I'm just not proficient enough in C++ to do much with them sad.gif

Regarding your suggestions, when using DiscoverDevices it adds all of the nodes by ID. When using DiscoverDevices it does not add duplicate nodes, BUT it does not poll the status of the devices. Apparently it only reads the list of nodes from the device as provided by the primary controller.

This just got me thinking.. let's just say that I had RF+ devices which do update their status. All they would be do is respond to each command or local dimming level with a "N002L99" automatically. This would still require some polling of Premise to read this data and update the appropriate dimmer levels. I see nowhere that this is being done.

I'm left to assume that this driver was originally intended for 1-way operation only which is kind of a bummer.

Darn sad.gif
123
"Darn" is right. I was hoping the discovery process included determining a device's status. Apparently not.

Not too many options left at this point. Unless someone rolls up their sleeves and modifies Damon's driver, the only other option is to create a new one as a Module. Module-based drivers for serially-controlled devices are easier to write than native drivers. However, it is a daunting task if you've never written one before. My first driver was for the ELK M1 and it was a long journey.

I think you've reached a point where Premise may not be the best solution for you. You need to consider switching to an HA product with comprehensive support for zwave devices.
manxam
Thanks again 123. The terrible part is that I really LIKE premise; how it's laid out and how it operates. I only went out and purchased the switches, primary controller, and serial controller once damon posted the ZWAVE drivers. I went with zwave due to the sheer amount of devices available (thermostats, lock sets, motion detectors, switches, dimmers, et cetera) and hoped I could get it working.

Now that I've purchased it all I suppose I'm stuck with it.

I was contemplating buy an ELK M1 for security purposes. I wonder if it will help me in any way...
123
QUOTE (manxam @ Oct 24 2009, 03:15 PM) *
...I was contemplating buy an ELK M1 for security purposes. I wonder if it will help me in any way...

I did a little research and although the ELK M1 supports zwave, it appears that it does not employ polling. From what I've gathered, most zwave switches do not automatically report their status when they are controlled locally. Periodic polling is the only way to keep track of a typical zwave switch's true state. Leviton implemented automated status reporting in its ViziaRF line and would not require polling to keep track of their true state.

IVB went through this exercise, with the ELK M1, and it is all documented in this post and this one.

When researching alternatives to Premise, you'll need to confirm that the product's zwave driver can perform polling so that it can properly support your brand of zwave switches. There is an excellent post on CQC's forum where IVB & Co. make their case that CQC's zwave driver should be enhanced with polling.
etc6849
Is there an easy way to expose an add-in's serial port and use it to send/receive data? Perhaps someone could make a class extension that adds the polling capability?

I too looked at the source code and C++ looks really different from any programming I have done before. I really wanted to add zwave thermostat control, but the source code is beyond my current programming skills at this point.

WRT zwave two way feedback: I too use the RZC0P and liked it a lot initially over the X10 stuff I was using before, but I have found I must use vizia rf+ exclusively else there are huge delays in receiving the feedback from a vizia rf+ switch. For example, I recently purchased a intermatic socket module for my garage light, only to find it severely delayed the two way feedback from neighboring leviton dimmers/switches (obviously I had no feedback from the intermatic module, but for $25 I didn't expect much). Once I excluded the intermatic switch, everything worked fine again! I would see a 10-30 second delay with the intermatic lamp switch included! Normally the two way feedback is received by the RZC0P in 1 second or so after the light is completely out. I verified this twice using port spy and did everything I could think of such as changing the rediscovery dB of the devices etc. I think I'm going to try one of those X10 lamp sockets in the garage, else I'll have to buy a $70 leviton RF+ switch.
manxam
Etc6849, with the Vizia RF switches that you're using, is premise updating the current dimmer level if someone changes the dim level locally (or via another piece of software)?

When sending a command via the VRCOP to a dimmer I should be able to request a return response (L50, UP) which SHOULD set the dimmer level to 50 and then get the switch to confirm that it truly IS at level 50. The weird thing is that I'm not getting these responses either.

I'm not sure if it's my gear or a configuration issue...

Hrmph!
etc6849
I use the following:
In wall Dimmers: VR106-1LX
In wall Switches: VR151LX
Plug in Lamp Module: Vizia RF and RF+ 300w lamp dimmers
RZC0P
Vizia RF+ handheld controller

Note that the switch needs 4 wires in total, including a common wire and a ground wire. The dimmer needs 3 wire in total including a ground wire.

When I manually change the brightness at the dimmer, it takes a total of ~2 seconds for the automation browser page to show the new brightness. Port spy shows the receipt of the command from the lamp dimmer.

When I use the handheld Vizia RF+ controller, the light gives the same response once action is completed and SYS updates automatically.

This appears to be pretty consistent until I include the z-wave intermattic light switch into the mesh network. For this reason, I've disconnecting the intermatic light switch permanently.

If you are having trouble with vizia rf devices:

If you are having trouble with vizia rf devices:
1. Exclude all intermatic devices.
2. Run network rediscovery from the handheld vizia rf+ controller.
3. Associate all the vizia rf+ and rf devices with the RZC0P from the handheld controller.
4. Set the device to hail the rs232 controller using the "set hail" command under the advanced menu of the handheld vizia rf+ controller.
5. Update the rs232 controller with the handheld vizia rf+ controller by standing within 3 feet of it.
manxam
So, I guess that answers my question: Premise does support 2-way with the Vizia RF line of products. Guess I'll have to go swap my 10 Homesettings with Vizia devices..

Anyone care to loan me a few hundred $$ ? smile.gif

Thanks for your help guys.


etc6849
As always, there are a few things you could do as an alternative:

1. Mimmick the X10 smart palm pad example found below to use X10 palm pads to turn the lights on/off, letting SYS keep track of the light's state. Also use X10 motion sensors to turn lights on/off. It goes without saying that you would not want to toggle the lamp switch manually if you let SYS keep track of the state.
http://www.cocoontech.com/forums/index.php?showtopic=14829

2. Use the setValueForce method to force a powerstate change. For example, if motion is detected and you have previously turned off the lights manually, the lights will not come on when motion is detected! However, if you use setValueForce a state change will be forced and the lights would come on even though SYS still thinks they are on, a command will be sent.

3. Write a custom module (aka driver) using Premise Builder. I'm going to attempt this in a few months, so I'll post one if I'm successful (I may not be as I'm somewhat new to Premise and home automation).
manxam
Thanks etc and 123 for both your help. Do either of you happen to have the sdk and visual c++ installed? I'm just curious how Premise is updating the dimmer level using the Vizia RF line of products if it doesn't read from the serial port. A quick perusal of the SPLEVINTON's various .h and .cpp files shows the commands being sent to the serial port, but I can't see anywhere that it's being read.

The Vizia RF devices automatically send back their status to the serial device using the same ascii commands (lets say: N004L50 for Node 4 Level 50) I can emulate this behaviour with a big hack by sharing my com port (virtual serial port emulator) and having a timer setup within premise requesting each nodes status every x amount of seconds.

I just can't figure out how the driver is reading this data and supplying it/updating Premise.

Again, I really appreciate both of your help in this.
macromark
QUOTE (123 @ Oct 24 2009, 12:44 PM) *
I think you've reached a point where Premise may not be the best solution for you. You need to consider switching to an HA product with comprehensive support for zwave devices.

Trying to tread lightly here... manxam, if you have a lot of the HA14's installed and you need instant status, we do handle this in our software. FYI.
123
QUOTE (manxam @ Oct 26 2009, 11:40 PM) *
... how Premise is updating the dimmer level ... I can't see anywhere that it's being read.

At the top of the VIZIARF.cpp file you'll find the following:
CODE
JumpTableEntry<MFP> arrJT[] =
{
    {"<F", CVIZIARF::UpdateZones},
    {"<E", CVIZIARF::HandleAck},
    {"<X", CVIZIARF::HandleResponse},
    {"<N", CVIZIARF::HandleUpdate},
    {NULL, NULL}
};
    
void CVIZIARF::ProcessLine(LPCSTR psz)
{
    if (m_spSite != NULL)
    {
        MFP fp = LookupJumpPartialMatch(psz, arrJT);
        if (fp != NULL)
            (this->*fp)(psz+2);
    }
}

  • Premise buffers the data that arrives via the serial port.
  • The driver object's "ProcessLine" method is called when something arrives in the buffer.
  • It calls on the "Jump Table" to decide what should happen next.

The "Jump Table" is like a C++ switch/case statement and defines which method to call based on the received data. For example, if the incoming data starts with "<F", the driver will execute its "UpdateZones" method.

The HSDK (Software Development Kit for creating native drivers) contains a manual that describes how to build a driver. I've posted a neatly formatted version of the HSDK's Quick Start Guide in Premise Downloads. Page 51 (Section 13. Adding A Jump Table To Handle Responses From The Device) describes how a driver receives data and uses a Jump Table.
etc6849
I too read the .cpp files and couldn't make too much sense of what is going on due to my lack of programming knowledge.

That being said, I have a simple driver I worked on last night that I'll share later this week. All you need to know is vbscript to follow it, but it does not deal with scenes or groups yet. It appears to be working, but I'm on travel so I can't test it in the real world. I'll post it after a few more tests/additions. I may add polling (not needed for my system), but polling would be very easy to add later too.
123
Nice job!

I look forward to seeing the next release.

EDIT
I removed my questions from this post ... just had to read a little more of your code to to be able to answer my own questions!
etc6849
Thanks 123. I decided to use builder and installed the module remotely, but discovered one small error; it is fixed now biggrin.gif Seems like it works pretty good. I also tested sendpollrequest and it worked fine for the vizia rf+ lights I have.

Same comments as before:
Try this alpha version and please report any issues as I'm not home this week to actually test it...

You'll have to manually add the dimmers and switches and the respective node ID's (must be an integer greater than or equal to 1 and less than 255). To do this import the module, then create a new VIZIA device under CustomDevices. Right click on VIZIA and click dimmer or switch. Be sure to fill in the address (node id).

For now the "discoverZones" button does nothing. I'll eventually post a new version that will create the children automatically for the user, and a version that supports thermostats (this is my hidden motive ) and perhaps scenes and groups. Fade time is also not implemented yet.

"SendPollRequest" should work for what manxam needs; just add a timer to toggle it true at the desired time interval.
etc6849
123, is there an advantage to using ManualAck in conjunction with toggling setAck when <E000 is received? Z-Wave seems so reliable that I don't need to do this so just used a 10 ms delay for now.
etc6849
I've improved polling to also include feedback of the form NxxxLxxx. I've finished the node discovery too. DiscoverNodes will add any newly discovered nodes, but also keep existing nodes that still exist (ie are still included in the mesh network).
123
QUOTE (etc6849 @ Oct 27 2009, 11:26 PM) *
...is there an advantage to using ManualAck in conjunction with toggling setAck when <E000 is received? ... just used a 10 ms delay for now.

I'll be honest and admit that I've never had to use the ManualAck/SetAck flags in any of the drivers I've built .. so I can't comment on how their usage will impact this driver. What I do know is that a 10 ms delay seems awfully short. The Windows operating system time-slices at around that amount so I wouldn't count on getting such a low time delay.

I'm not going to put too fine a point on it but the code in OnChangeOnNewData is getting awfully difficult to follow. Plus, there are several more Vizia packet types that you'll need to support including the "Node General" type (<N00:000,000,000,...) used for thermostats ... and it can contain a variable number of parameters.

I've written a parsing function that identifies received Vizia commands, validates their format, and extracts all parameters. It supports the following Vizia commands:
CODE
Error Status (<E)
Transmission Status (<X)
Found Node (<F)
Node Scene (<N S)
Node Light Level (<N L)
Node General (<N :)
Node Name (<N ")
Node Location Name (<N ')

gPacketParser returns an integer representing the packet type and a variable-length array containing all of the command's parameters. For example, for the Node Scene command the array would have four integer elements containing the following information:
(0) Node ID
(1) Scene Number
(2) Light Level
(3) Fade Rate

For the Node Light Level command, the array would have two integer elements:
(0) Node ID
(1) Light Level

For the Node Name command, the array would have two elements, one of type integer and the other string:
(0) Node ID
(1) Node Name

The attached zip archive contains a VBS file that allows you to test the function without using Premise. It doesn't read the serial-port but simply contains a few sample Vizia packets that you can test.

The zip archive also contains a bare-bones "zWave" driver that incorporates the new parser. It spits out whatever it receives to the Windows Debug Console.
etc6849
Thanks 123. RegEx looks really useful for something like this, too bad I've never heard of it!

Your code looks really nice. I think it's a good way to handle ascii feedback from any device, not just zwave... I'm going to have to study it a lot for learning purposes.

Just a few questions:
1. What's a good way to handle something like finding a node? Would you keep the FindDevice method that uses several object level hidden variables to store the node type asked about, instance, etc... or is there a better way?

If I make FindDevice a function instead of a method and place all of these variables (node type and instance) under it (where they probably belong), could I then access (from onchangenewdata) the last state of the variables after FindDevice has been called and completely executed using something like this: sysevent.method.FindDevice.DiscoveringInstance?
123
Regular Expressions are a very powerful means of handling strings. The syntax is difficult to master but it allows you to do some amazing things with very little code.

I reposted ViziaTester.zip (above) with a corrected version of the zWave class. The XDO should import cleanly.

1. I'll have a look at FindDevice and let you know.

2. The sysEvent object will definitely not support this: "sysevent.method.FindDevice.DiscoveringInstance" . If you need the last state of something, you have to save it somewhere.

ADDENDUM
I had a look at FindDevice and I recognize that you're emulating the Discovery process Damon created in his native driver. If you check his code you'll see that he is storing values in global properties of the ViziaRf class like "m_bInDiscoveryMode", "m_iCurrentAddress", "m_iDiscoveryType", etc. In a Module a class property is effectively a global variable. By making it hidden, as you've done, you avoid exposing it in the ViziaRf object's user-interface. It's all good.

I looked at AddDevice and, I may be wrong, but it doesn't look like the best way to handle additions. Correct me if I'm wrong but if a discovered object (Switch or Dimmer) does not already exist (i.e. as a child) then it will be created. However, if it does exist, it will be deleted and re-created. Won't deleting the existing object destroy any existing bindings? Imagine you have 25 Dimmer and Switch objects, all are bound to Home-level objects, and then you click "DiscoverNodes" . Poof! All of the objects and their bindings are deleted and you'll have to re-bind everything after Discovery is completed. Ouch! Perhaps if a discovered object has a matching child object then the child should be left alone?
etc6849
AddDevice shouldn't do that. The only time I thought it deletes children is if the new node type doesn't match the old. In other words, if I replace a dimmer with a switch, but kept the same node ID I need to make the dimmer a switch in premise. This is necessary since the vizia rf+ handheld controller can let you switch out devices, keeping the node id the same.

RemExcludedNodes removes nodes that are no longer included and does delete the associated objects.

I'm 99% sure I have this right, but please let me know if i don't wink.gif
123
And right you are! I stand corrected. It'll delete the child object only if it isn't the right class. Of course, the binding will still be lost. Here's another way to handle the situation: instead of deleting the child object, change its class.

If you've used X10 devices in Premise you will have encountered X10 objects whose underlying class can be changed from Dimmer, to Switch, to MotionSensor, to whatever. Have a look at this post regarding the Transformable flag.

Basically, all child objects would be based on a "zWaveDevice" class whose inheritance can be altered from Dimmer to Switch (the child would have to be deleted if it had to transform to a Thermostat!). It's a litle tricky to set up but the benefit is that AddDevice wouldn't delete a mis-matched child object but simply alter its class.

Food for thought.


etc6849
I'll have to study the transformable flag as this sounds neat. I've incorporated your version 1 code. I haven't looked at version 2, but I guess it just deleted the dimmer and switch containers?

Your code works great and is very clean, thanks! I have one question, what does the "d" mean below in the vizia rf 232 documentation?

2.1.7. Send Command (“SEnd”)
To provide control to the nodes which function a bit different than lighting control nodes the send
command can be used. This command sends over RF, all Z-wave command, the node will send the
message as before defined by any of the association commands:
N, AP, GR.
Example:
N5SE69,2 - Will request thermostat fan state from thermostat node 5.
2.1.8. NN and NL - Node name and location commands.
NN (NL) provides access to programming/recalling node name (node location name).
>NxxxNNdyyy…yyy
>NxxxNLdyyy… yyy

where xxx- node ID
yyy..yyy ASCII string up to 16 characters
To request previously programmed name use >?NN or >?NL
The name returns in format: <Nxxx”yyyyyyy
123
I found the answer in this PDF at the bottom of the third page. The "d" represents "Character Set" and the document recommends using "1" (Extended ASCII).

I recommend you have a look at the following post in zWaveWorld. It contains invaluable information about how things really work as opposed to what the documentation says. Apparently there is an undocumented response (<M000) after issuing a Group Set command (>GS). The gViziaParser function will simply return a zero ("Unknown Packet") if it encounters the "<M" command.

BTW, here's a source of information about the Z-Wave API.
etc6849
Thanks 123. I can't believe the Vizia documentation found on Leviton's site doesn't define "d" (see the vizia documentation in Damon's sourcecode or link below)!?! How could Leviton leave out such an important piece of information? I also tried to download the VRC0P documentation and it too left out these details.

http://www.leviton.com/OA_HTML/ibcGetAttac...amp;appName=IBE
etc6849
I was able to add naming and a built in timer for polling. I'm hoping someone with non vizia rf lights will try the polling feature and report back on the polling function.

However, if I use the automation browser to change a lights brightness property, the light doesn't update until I let go of the up or down button. Is there a way to fix this so that as you hold down the up/down buttons the light continually dims? It appears it is due to the way the onChange property works for brightness, but I thought I'd ask anyway.
123
QUOTE (etc6849 @ Oct 30 2009, 11:17 PM) *
...if I use the automation browser to change a lights brightness property, the light doesn't update until I let go of the up or down button. ..

That's by design. After you release the button, Premise transmits the desired brightness level to the lighting device. To have the brightness change while you are pressing the button, Premise would have to transmit a continuous stream of commands to the lighting device. This is not a practical proposition when it comes to PLC lighting technologies.

I've been working on the transformable classes (i.e. convert an existing Switch object into a Dimmer and vice-versa) and on Groups.

The inheritance hierarchy for lights looks like this:
Device (Base Class for all zWave devices)
Lighting (Base class for all zWave lights)
Switch (Inherits from Device, Lighting, and Premise's Power class)
Dimmer (Inherits from Switch and Premise's Dimmer class)

I've defined Device to be Transformable so it can be changed to whatever is needed ... from Switch to Dimmer and back to Switch (or even a Thermostat!). The transformation can be performed by the end-user, using Builder, or it can be done programmatically. The attached zWave2.xdo contains an example of transformation. Import it and it will also create a zWave object in Devices > CustomDevices and in its Devices container you'll find two properties:
  1. SwitchesToDimmers
  2. DimmersToSwitches

If you click the first one, it will convert all Switches in the Devices container into Dimmers. Now that's a completely useless feature that should never make into the final release but it demonstrates how easily transformation can be accomplished. Here's how it's done:
CODE
    for each oDevice in this.GetObjectsByType(Schema.Modules.zWave.Classes.Switch.Path, false)
        set oDevice.Class = Schema.Modules.zWave.Classes.Dimmer ' <-- This is the line that does the magic.
    next


Add a few Dimmers, Switches and Thermostats into the Devices container. You'll notice that the driver creates an "AllLights" group and automatically populates it with all of the Lighting Devices you created in the Devices container. The AllLights group cannot be deleted and its members cannot be renamed nor deleted.

If you right-click the Groups container, you can create a new Group. Name it what you wish then right-click it and add new GroupMembers. Within the GroupMember, click Device and select an existing Device. That's how you build your own groups of devices.

If you change the name of a Device (in the Devices container), its name in AllLights will update automatically. If you delete the Device, it will be automatically removed from AllLights. The auto-renaming and deletion also applies to any Groups you created manually.

Now here's the fun part, if you inspect a Group you'll find it contains PowerState and Brightness properties. If you enable PowerState, it will compose a command to turn on all lights in that Group. OK, that's not fully functional yet, but it does build a list of Device addresses (and prints them to the Debug Console).

A script can turn on all the lights using the following command:
CODE
Devices.CustomDevices.zWave.Groups.AllLights.Powerstate = true


I have a few more ideas about Groups (that may involve the ViziaRF's group commands) but its almost 2:00 AM and its time to call it a day! I think I can incorporate Groups into your driver after you've finished testing all of the core functionality (I don't have any Z-Wave equipment).

BTW, I reviewed CQC's Z-Wave driver and learned there's another possible response command: "<!000". That makes two more commands to add to gViziaParser (the other is "<M000"). I'll take care of that next week.
etc6849
Everything in Beta 5 works very well except polling. I finally made it home last night and tested everything and posted beta 5.

Some thoughts: Polling works better if you poll one device at a time. I would get X002 a lot if I polled everything at once. I ended up setting the timing at 100ms and this helped some. This seemed to get rid of the X002 error most of the time, but ~1/7 polls still receive an X002 from one random device. This really only happens on polling.

However, the thread link to suggests a very good idea: use command acknowledgement and send the next command only after receiving X000. This would entail breaking all commands down to handle each device one at a time and would use a global variable (or equivalent) called
nextNode. There would also need to be a way to track what the last method called was and recall it if necessary (I'm not sure how to do this). If X002 is received the method would be recalled and after 10 failed attempts in a role a comunications error set. Obviously, this would also require the use of manualAck that I couldn't figure out how to use manual ack.
etc6849
123, your code is very neat! I'm impressed with the object morphing and the group implementation. The morphing works great!

The way you are designing the zwave classes is very smart too. The module has mostly been designed generically and one could easily use it with a different controller or lighting technology.
123
QUOTE (etc6849 @ Oct 31 2009, 02:17 PM) *
... Polling works better if you poll one device at a time. ...setting the timing at 100ms ...but ~1/7 polls still receive an X002 from one random device. This really only happens on polling.

... use command acknowledgement and send the next command only after receiving X000. ...

etc6849,

I've been studying your driver and I have a few questions:

The documentation states that "<E000" and "<X000" are produced after a command is successively executed but that "<X000" may come before or after the response is received (tricky!). Transmitting another command before receiving an "<E000" response could result in overflowing the RZC0P's buffer. Transmitting another command before receiving "<X000" ... not sure what happens in this case ... the Z-Wave network may be busy processing the first command when the second one is issued and simply ignore it.

I believe one needs to wait for a "<E000" response (minimally) before transmitting additional commands. This ensure the interface received and processed the command. Waiting for an "<X000" would ensure the previous command has been sucessfully processed by the network and it is ready to process another command. Beta5's polling method (PollDevices) iterates through all Devices and uses a 100ms delay between transmissions. That means every 100ms a ">?N" is transmitted for each Device. I'm not certain but this might flood the network and that's why you're seeing a less-than-perfect success rate (1/7 failures). This is just a guess but transmitting commands in rapid succession in a larger Z-Wave network might exhibit an even higher failure rate.

To improve the success rate, I believe flow-control is needed in order to throttle the transmission of commands. In other words, before sending a second command, the driver needs to wait for a "<E000" confirmation ... maybe even an "<X000" as well. Naturally, while waiting for a response to the first command the driver may get a request to send another one. Clearly the driver cannot ignore the second request and must store it in a queue and then process it at the earliest opportunity. I'm currently experimenting with this idea .. the queue could simply be an array or a container that holds child "command" objects. In addition a watchdog timer is needed to ensure that the driver doesn't wait forever for the "<E000" confirmation.

In OnChangeOnNewData, there's this line:
CODE
    'set flag to prevent feedback loop
    this.Updating = true

So when new data is received, the Updating property is enabled. Then in SendCommand it has the following:
CODE
'if we aren't updating based on feedback, send the command
if this.Updating = false then

So when OnChangeOnNewData is processing incoming data, it prevents SendCommand from transmitting data. This sounds reasonable but I don't understand the comment's point about preventing a feedback loop. Can you shed some light on it?

I'm of the opinion that if an "<X002" is received (transmission of the requested command has failed) ... well, for now, tough luck. Perhaps a future version of the driver will retry transmitting the failed command.
etc6849
Thanks 123 for all your expertise and help! An in/out buffer array sounds like a great and clever idea. I too believe waiting for <E000 before sending another command will get rid of the X002 issue altogether.

Feedback Prevention Flag:
The only example I can think of is the flag will help stabalize a value for things like receiver volume (where repetitive values are sent, this is in contrast to brightness) if two way control is used. This was touched on in one of Damon's videos where he made an Onkyo receiver driver and that's where I stole it from.

It turns out that if someone were to turn the volume up under the automation browser, many volume values will be transmitted to the Onkyo receiver and the receiver will report the status for each level as the volume is increased. This would mean values have the potential to be unstable as the received values may be lower than those just transmitted due to timing characteristics and the onchangenewdata script may fight back and lower the volume some when you are actually trying to raise it!

I'm not sure one needs the flag to prevent feedback since brightness values are not continuously sent as you hold down the brightness up button in the automation browser (ie good catch 123 I don't think the feedback flag is needed wink.gif ). However, I still don't have a thermostat so it could be an issue with some thermostats. I'm also not yet sure how the thermostat buttons will behave under the automation browser.
123
I've built a "JobQueue" class in Premise that is effectively a First-In, First-Out (FIFO) buffer. If one wishes to implement flow-control in a driver (i.e. send a command and wait for acknowledgement before sending the next pending command) a JobQueue can store, and process, the outbound commands.

A JobQueue is a collection of Jobs where each Job hold a command string. JobQueue has just four methods:
  • AddJob -> Add a new job to the queue.
  • RunJob -> Add a new job to the queue and run it immediately.
  • ProcessCurrentJob -> Send the command string contained in the current job.
  • GetNextJob - > Set the next job in the queue as the current job and process it.

and two properties:
  • JobIndex -> An incremented number that is assigned to a Job's name.
  • CurrentJob -> Identifies the current job in the queue.

To use it is simplicity itself. You don't need to bother with any of JobQueue's methods or properties. Just create a method in your driver class called SendCommand that takes one parameter ("Data": the command string to transmit) and add the following code:
CODE
if this.Jobs.CurrentJob <> "" then
    this.Jobs.AddJob method.Data
else
    this.Jobs.RunJob method.Data
end if

Here's how JobQueue works:

SendCommand"MyCommandString"
If there are existing Jobs in the JobQueue, SendCommand uses AddJob to append a new Job to the queue.
If there are no existing Jobs, SendCommand uses RunJob.

AddJob
AddJob simply adds a new Job to the JobQueue. The Job contains the command to be transmitted (i.e. "MyCommandString"). The Job is given a unique name.

RunJob
In contrast, RunJob adds a new Job to the queue (via AddJob) and then immediately processes it using ProcessCurrentJob.

ProcessCurrentJob
ProcessCurrentJob gets the command string from the current job and transmits it. It then activates a Watchdog timer. If an acknowledgement is not received within a given time period, the Watchdog will simply delete the current job and move on to processing the next job in the queue. If the driver's OnChangeNewData method receives an acknowledgement promptly, it calls GetNextJob.

GetNextJob
GetNextJob deletes the Watchdog timer and the current job. If it finds another job in the queue, it sets it as the current job and calls ProcessNextJob. If there are no other jobs in the queue it sets JobIndex to zero and CurrentJob to null.

Here's how to test the JobQueue.

  1. Run DebugView so you can see the debugging messages.
  2. Delete Modules > zWave.
  3. Install the attached XDO.
  4. Make a new zWave object in Devices > CustomDevices
  5. You'll notice it contains a "JobQueue" object. In a release version, "JobQueue" would be hidden.
  6. In the zWave object, click the "transmit" property at least three times. This simulates the generation of three successive outbound commands.
  7. Expand the JobQueue you'll notice three Jobs: "Job0", "Job1", Job2", etc
  8. Click the "receive" property once. This simulates the acknowledgement of the transmitted command.
  9. "Job0" will disappear and now "Job1" is processed.
  10. Don't do anything for at least ten seconds.
  11. The Watchdog timer will expire after ten seconds (release version would use a shorter time period) and automatically purge "Job1" and move on to process "Job2".
  12. Click "receive" once.
  13. "Job2" is effectively acknowledged and will disappear from the JobQueue.
  14. The JobQueue is now empty.
  15. Click "transmit" and a new "Job0" is created.

This is about as clean a design as I can invent. Aside from the Watchdog timer there are no other timers, or timing loops, involved. The jobs are processed as fast as the acknowledgements are received and the Watchdog timer simply ensures that processing never stalls.
etc6849
Wow 123! This is really a nice implementation.

To test your implementation in the real world: I've added the job classes to the beta v5 driver. I set command time to 100ms command time and also added some test variables called JobCount and ErrorCount (counts X002 occurances) to the VIZIA driver. I also sent no other control signals over the zwave network during the test (ie I didn't use the handheld Vizia controller). The number of devices on my network is 4 (not including the rs232 controller and the handheld remote).

With the poll interval set to 10 seconds: 1 transmission error X002/ 1002 jobs processed (~250 polls to 4 devices).

With the poll interval set to 3 seconds: 1 transmission error X002/ 600 jobs processed (150 polls to 4 devices).

Obviously 3 second poll intervals is not what you would use in the real world. Perhaps 5 minute poll intervals is a good number which would mean there would be relatively rare occurance of transmission errors (if any). This new version appears to be very reliable and I think it works great! 1/1000 errors isn't bad I think for a lighting system!

What do you think about automatic reset?
I added a reset port script that will remove the current serial port from Network, then re-add it. The reset property is toggled every time there is no response from the rs232 controller (ie no Exxx or bad packet).
123
That's what I like to see! That's a substantial improvement over a 1 in 7 error rate!

I'll have a look at the reset code; it sounds like a good idea.

Eventually, we need to add support for the CommunicationFailure property. This property is found in all native drivers (I included it in the WeederTech driver) and indicates when the driver has lost communications with the physical device (i.e. the RZC0P). A standard thing to do when this happens is to have the driver log an Event.

Here's my idea for Groups. Each Group will have three properties:
  1. GroupNumber (Integer)
  2. ProgramGroupNumber (Boolean, Momentary)
  3. Programmed (DateTime)

So if you set the GroupNumber for "AllLights" to 125 and then click "ProgramGroupNumber", the driver will time-stamp "Programmed" and send a Group Store command ("N1,2,3,4GS125") to the RZC0P. This is something the end-user would (optionally) do for each group.

Now when you set a Group's PowerState to ON, the driver will check to see if the Group has an assigned GroupNumber (i.e. a non-zero value). If so, the driver will issue a Group Recall command ("GR125ON") to turn on lights in the group. On the other hand, if GroupNumber is zero, the driver iterates through all members of the group and sends individual commands (N1ON,UP"). Naturally, sending one GR command is more efficient than sending one N command per device.

The "Programmed" property is purely a convenience to remind the end-user when the GroupNumber was programmed.

QUESTION
Do you know if sending this command ">N1,2,3,4,5,6ON,UP" is as reliable as sending indvidual commands like ">N1ON,UP", "N2ON,UP", etc? Is it more, or less, time-efficient?

I'm trying to determine how a Group should be handled if the GroupNumber is not assigned. Should I send one long list (">N1,2,3,4,5,6ON,UP") or a bunch of individual commands (">N1ON,UP").
etc6849
I too think 1/1000 transmission failures is great. Especially considering my apartment is multiple levels and the signals may go through multiple walls/floors to reach the dimmer. I'm running a real world polling test this week with 2 minute polls combined with normal usage of the zwave network to test the driver. I'll report my results on Friday.

CommunicationFailure
Great idea 123! For the CommunicationFailure property, I would implement it by doing the following:
I already have a property of VIZIA called resetPortCount that I was going to delete later after testing, but why not keep it around? All one would do is add a timer that resets resetPortCount to 0 every half hour; then write an onchange script for resetPortCount that triggers a CommunicationFailure if there have been more than 5 port resets in the last half hour. I think this is a reasonable test as we would want to try resetting the port a few times before saying there is a true communications failure. I'm not sure about the code to log the event though... PS: Let me know if you need me to make this change or if you are already doing wink.gif

Group Question/Thoughts
I'll have to check on all this stuff as I haven't played with groups. However, I believe it is better to send commands to one device at a time now that we are properly testing for E000 before sending the next command. This is what the forum on zwaveworld seemed to say too. In fact, I believe I received X002 a few times last week when I tried to do something like ">N1,2,3,4,5,6ON,UP" all at once, but that was when I was using a 10ms command delay time (which is way too short).

I like being able to make a folder and not having to worry about programming/saving group names (but still having this option). This is a clever idea 123! Your implementation for group properties makes perfect sense to me. I'm going to study group commands tonight, but does >?GR return all groups and their nodes? Perhaps, it might be worth while then to write a script to automatically detect existing nodes? This is obviously an optional not required add on.

Future Improvements
These items sound like something to add in the future after there is a more finalized driver but...

Motion Sensor support?

Button Controller Support?
It appears that the rs232 controller can read button associations? Perhaps it's worth while to add a new type of device such as a generic four button controller where a user can add their own code to each button under a home keypad or define associated nodes for each button and hit program. I don't have one of these $100 + controllers to test though sad.gif I do have a handheld programmer and it may act like a four button controller. I can play with it tonight and see what all I can do with this type of functionality.
123
QUOTE (etc6849 @ Nov 3 2009, 02:33 PM) *
... I'm running a real world polling test this week with 2 minute polls combined with normal usage of the zwave network to test the driver. ...

I look forward to seeing your results. Polling is an important feature that will make this driver more useful for non-ViziaRF Z-Wave devices.

QUOTE
... triggers a CommunicationFailure if there have been more than 5 port resets in the last half hour .... I'm not sure about the code to log the event though...
In other drivers, I've created a "heartbeat function" that periodocally queries the hardware device and looks for a specific response. If the response is not received after three queries, the assumption is that the connection to the hardware has failed and "CommunicationFailure" is enabled. The trick is to find the right ViziaRF command to use.

Here's some OnChangeCommunicationFailure code from one of my drivers. "LogFailures" is a Boolean that lets the end-user choose if failures should be logged as Premise Events.
CODE
if sysevent.newVal and this.LogFailures then
    ' Create an entry in the Premise Event Log
    dim oEvent
    set oEvent = Events.CreateObject(Schema.System.Event.Path, "Communications Failure")
    with oEvent
        .Description = "No response from Premise TTS Driver Service: " & this.Name
        .Severity = 50
        .EventTime = Now
        .LinkObject = this
    end with
    set oEvent = nothing
end if


QUOTE
... I believe it is better to send commands to one device at a time ... I received X002 a few times ... when I tried ... ">N1,2,3,4,5,6ON,UP" all at once, but that was when I was using a 10ms command delay time (which is way too short).

Can you confirm if the current driver version (with command queueing and a 100ms delay) handles ">N1,2,3,4,5,6ON,UP" better than the previous one? Also, do lights turn on simultaneously with ">N1,2,3,4,5,6ON,UP" or do they turn on one-at-a-time like they would if called individually with ">N1ON,UP"?

QUOTE
... does >?GR return all groups and their nodes? ... it might be worth while then to write a script to automatically detect existing nodes?

I've been looking through the XML documentation for Johnny 9's .NET ViziaRFLibrary and it has a command that "Gets or sets a list of all Node IDs in the group." This suggests that there is a ViziaRF command that returns a list of nodes contained in a group. However, I don't know about a single command that gets a list of all groups and nodes.

If one is able to determine the nodes in a group (from the RZC0P), this information can be used to update the driver's Groups. I guess this "housekeeping function" would be executed by the driver on a periodic basis. Definitely something worth investigating for a future version.


BTW, I'm exploring what is need to enhance the JobQueue so that a Job can be re-issued in the event of failure. The Job would be purged only if it fails after being issued three times or by the Watchdog. This is in contrast to the current scenario where the Job is purged after the first failure (or by the Watchdog).
etc6849
I've revisited the topic below about the feedback prevention flag.

if we change brightness of the light from SYS with no feedback prevention:
>N002L60,UP
>N002L60,UP
<E000
<X000
<N002S000,060,000
>N002L60,UP
>N002L60,UP
<E000
<X000
<N002S000,060,000

with feedback prevention:
>N002L38,UP
>N002L38,UP
<E000
<X000
<N002S000,038,000

if we change brightness of the light manually with no feedback prevention:
<N002:130,001
<N002S000,049,000
>N002L49,UP
>N002L49,UP
<E000
<X000
<N002S000,049,000

with feedback prevention:
<N002:130,001
<N002S000,050,000

QUOTE (etc6849 @ Nov 1 2009, 09:39 PM) *
Thanks 123 for all your expertise and help! An in/out buffer array sounds like a great and clever idea. I too believe waiting for <E000 before sending another command will get rid of the X002 issue altogether.

Feedback Prevention Flag:
The only example I can think of is the flag will help stabalize a value for things like receiver volume (where repetitive values are sent, this is in contrast to brightness) if two way control is used. This was touched on in one of Damon's videos where he made an Onkyo receiver driver and that's where I stole it from.

It turns out that if someone were to turn the volume up under the automation browser, many volume values will be transmitted to the Onkyo receiver and the receiver will report the status for each level as the volume is increased. This would mean values have the potential to be unstable as the received values may be lower than those just transmitted due to timing characteristics and the onchangenewdata script may fight back and lower the volume some when you are actually trying to raise it!

I'm not sure one needs the flag to prevent feedback since brightness values are not continuously sent as you hold down the brightness up button in the automation browser (ie good catch 123 I don't think the feedback flag is needed wink.gif ). However, I still don't have a thermostat so it could be an issue with some thermostats. I'm also not yet sure how the thermostat buttons will behave under the automation browser.

etc6849
Nodes 2 and 14 appear to be actuating at the same exact time like you thought they would wink.gif However, the nodes don't send the update reply at the same time and there can be a small delay between updating 2 (<N002S000,099,000) and updateing 14 (<N014S000,255,000), but this isn't a big deal and is normal.

>N2,14,OFF,UP
>N2,14,OFF,UP
<E000
<X000
<N002S000,000,000
<N014S000,000,000
>N2,14,ON,UP
>N2,14,ON,UP
<E000
<X000
<N002S000,099,000
<N014S000,255,000

I also tried >N2,26,17,14ON,UP. I then hit the spacebar very fast to send it multiple times and received no errors.

>N2,26,17,14ON,UP
>N2,26,17,14ON,UP
<E000
<X000
<N002S000,099,000
>N2,26,17,14ON,UP
>N2,26,17,14ON,UP
<E000
<X000
>N2,26,17,14ON,UP
>N2,26,17,14ON,UP
<E000
<X000
>N2,26,17,14ON,UP
>N2,26,17,14ON,UP
<E000
<X000
>N2,26,17,14ON,UP
>N2,26,17,14ON,UP
<E000
<X000
<N014S000,255,000
<N017S000,080,000
<N026S000,099,000
<N002S000,099,000

PS: I've included the new code. It appears I forgot to divide by 100 in one spot sad.gif and I've added the flag I talked about in my previous post.
123
QUOTE (etc6849 @ Nov 3 2009, 07:36 PM) *
... with no feedback prevention:
>N002L60,UP
>N002L60,UP
<E000
<X000
<N002S000,060,000
>N002L60,UP
>N002L60,UP
<E000
<X000
<N002S000,060,000

with feedback prevention:
>N002L38,UP
>N002L38,UP
<E000
<X000
<N002S000,038,000

I think I understand what you mean now by 'feedback prevention'. I encountered this issue when developing the ELK M1 driver which supports Dimmers and Appliances. I resolved it using a very different technique that does not involve "blocking" the operation of OnChangeOnNewData.

Here's what a Dimmer's OnChangeBrightness looks like in the M1 driver:
CODE
if not (sysevent.srcElement.Name=this.Parent.Parent.Name and sysevent.srcProperty.Name="OnNewData") then
    iLevel = round(this.Brightness * 100)
    this.PowerState = cbool(iLevel)    
    
    ' Convert Premise range 1-100 to M1 range 2-99
    if iLevel = 100 then iLevel = 99
    if iLevel = 1 then iLevel = 2
    
    this.Parent.Parent.PLCDeviceControl this.OID, 9, iLevel, 0
end if

The first line is what does the trick. It ignores requests issued from a specific source. In this case, if the source is the M1_Panel driver object (this.Parent.Parent.Name translates to "M1_Panel") and the calling property is "OnNewData" then the request is ignored. For the ViziaRF driver, the first line would look like this:
CODE
if not (sysevent.srcElement.Name=this.Parent.Name and sysevent.srcProperty.Name="OnChangeOnNewData") then
....
end if

You can demonstrate this to yourself as follows:
  1. Disable the existing feedback prevention scheme.
  2. Add debugout statements to OnChangeBrightness and OnChangePowerState that show sysevent.srcElement.Name and sysevent.srcProperty.Name.
  3. Change brightness and powerstate (from SYS and from the physical devices) and watch Debugview to see the names of the sources.

You should see that the duplicated responses are generated by different sources.

QUESTION: why are there two successive commands being transmitted?
>N002L38,UP
>N002L38,UP
etc6849
SYS has always repeated RS232 commands on my system (for all serial drivers). Is it abnormal or is there a way to turn it off?

QUOTE (123 @ Nov 3 2009, 09:07 PM) *
QUESTION: why are there two successive commands being transmitted?
>N002L38,UP
>N002L38,UP
123
I'll have to check this on my system because I've never noticed duplicated transmissions. You're seeing this via Port Spy?

The attached file is a slightly modified version of your Beta 8 driver. It has a new SetLightLevel method that is called by OnChangeOnNewData for <N S and <N L commands. It does not change the existing feedback prevention scheme. It is simply a streamlined version of the code to set a Device's Brightness and Powerstate. Let me know if it works as I have no way of testing it (been looking for an RZC0P on eBay ...)
etc6849
Yes, the double command transmitions are seen under port spy. I'll test your new driver tonight and post the results.

FYI: you might also try a search for VRC0P on ebay too as I believe the protocols are identical. I bought my RZC0P on ebay for $54.99 as a buy it now; it was stated that it was old new stock. I did see that zwave products has it for $69.99, but I don't recall how much shipping is and haven't dealt with them before. http://www.zwaveproducts.com/ZWAVE-PC-CONT...-Interface.html
123
Click to view attachment
QUOTE (etc6849 @ Nov 4 2009, 12:28 PM) *
Yes, the double command transmitions are seen under port spy.

I set up a test-bed in order to observe the commands transmitted by the ViziaRF driver. The test-bed consists of a null-modem cable connecting two serial-ports (COM5 and COM6). Hyperterminal is connected to COM5 and the ViziaRF driver is on COM6.

Using Port Spy, I can see what's transmitted on COM6 and Hyperterminal let's me see what is received on COM5. I discovered that the ViziaRF Beta 7 driver sends only one instance of each command. If I enable a device's PowerState, the driver sends a single ">N001ON,UP" command.

Is it possible that what you believe are two instances is due to the way Port Spy displays data? Have a look at the attached image; there are two identical lines of displayed data but only one instance of the command is actually sent. Port Spy uses colours to convey the meaning of the data. The first line (Brown) represents the data waiting to be sent. The second line (Green) represents the the data that was sent.

------------------------------------------------------------------------

While testing the driver, I encountered something odd. I bound a light to the driver (a Dimmer), enabled its PowerState and waited. I don't have an RZC0P so there's nothing to respond to the transmitted command. Ten seconds later, the Watchdog timer expired, and purged the job. Everything worked correctly but then imagine my surprise as I watched, in Builder's Connections window, an animation of the COM5 object disappearing and then reappearing! ???

I discovered the following line in ProcessCurrentJob:
system.addTimer 10, "this.GetNextJob" & vbCrLf & "this.Parent.Reset = True", 1, "Job_Watchdog"

Why is the serial port being reset each time the Watchdog runs to completion? The Watchdog runs when the transmitted command fails to receive a reply (within X seconds). The failure could be due to causes that are unrelated to a faulty serial-connection. Perhaps the port can be reset only if the driver experiences 5 consecutive response-failures (i.e. not 5 cumulative but 5 in a row). Frankly, if you encounter 5 consecutive response-failures you might as well set the CommunicationFailure property and halt all processing.
etc6849
Resetting the port after a failed command is overkill. I wrote the code before reading your earlier response on what the proper way to implement a port reset is... For the timer I would delete the code I've added, but append any timers with this.ObjectID incase a user potentially has two RZC0P's.

The code looks good, I'm just getting one error: a missing dim for bIsDimmer: bIsDimmer = false under setLightLevel

EDIT: I just read what a colon operator can do. I had no idea you could have two lines of code on the same line. That's the only error and you didn't even run the code?!? I wish I could do that!

PS: Is there an advantage to using dim? I thought it wasn't required for vbscript. Also you seemed to have solved the mystery on why transmitted commands show up twice in portspy! Many thanks.
123
QUOTE (etc6849 @ Nov 4 2009, 05:49 PM) *
... I just read what a colon operator can do. I had no idea you could have two lines of code on the same line. ...

I've found it useful when defining a Timer's payload (i.e its "ScriptToRun" parameter). In this example, the colon allows me to define two statements in the Timer's payload, there's an "on error resume next" followed by a "this.OnWatchDogTimer".
system.addTimer this.WatchdogInterval, "on error resume next: this.OnWatchdogTimer", 1, this.GetWatchdogTimerName

BTW, this example resolves the following issue:
  • You create some sort of custom Home object that has an associated timer that runs "this.DoSomething".
  • Then you delete the Home object.
  • The timer expires and attempts to execute "this.DoSomething".
  • Unfortunately "this" was the Home object and no longer exists!
  • The Timer fails to execute "this.DoSomething" and the VBScript interpreter halts at the offending code.
  • By adding "On Error Resume Next" as the first line, the VBScript interpreter skips over "this.DoSomething" (i.e. ignores the error) and continues without interruption.

------------------------------------------------------------------------

I've revised the JobQueue class and now it can retry a failed Job. Basically each Job has a "Reps" property indicating how many times it ran (i.e. Repetitions). The JobQueue class has a "MaxReps" property which indicates the maximum number of times a Job can be repeated. MaxReps's default value is 3 so each Job can be run three times before it is discarded and the next Job in the queue is executed.

I believe if the driver fails to successfully transmit 2 consecutive Jobs (that's 2 Jobs x 3 repetitions per Job = 6 consecutive failed commands) that it'd be safe to conclude there's a communications problem and the driver should set the CommunicationFailure flag. If the next Job completes successfully, it will clear the CommunicationFailure flag. Does that sound reasonable?

If you've modified version 8-1, please post the revised version so I can proceed to add the improved JobQueue class.
etc6849
123, the only thing I've added is the missing "dim" and I removed the reset port code from the job timeout. Other than that I have not changed anything and have no new version to offer. Your code works good.

Using the ":" operator to resume if a timer errors is clever. I've had timers give me an error in the past and halt execution. This is a great idea!

I double checked all possible cases through port spy I could think of: manual dimming/switching, automation browser dimming/switching etc... Naming, discovery etc also all work perfectly and I set the device for 1 minute polls to see what the error count would be after a day or two. The previous test with 2 minute polling showed ~1/6000 errors!

This driver is turning out to be a very useful framework for anyone wanting to make their own rs232 lighting driver biggrin.gif
123
I've been thinking about a way to optimize polling.

ViziaRF devices do not need to be polled because, when operated manually, they can broadcast their new state. The Polling function can safely skip them. All that's needed is a way of knowing which Devices don't need polling.

If the Device class had a property called "RequiresPolling", the end-user can set this property for each non-ViziaRF Device. When the Polling function builds its list of Devices to poll, it would filter it using 'RequiresPolling = true'. The Polling function wouldn't waste its time querying a Device that can automatically report its state.

---------------------------------------------------------------------------------

I think there's a line of code in OnChangeOnNewState that should be removed. It's the first call to GetNextJob.

CODE
            case 1:    ' Error Status (<E)
                sMsg = "Error Status: " &  aParms(0)
                this.Jobs.GetNextJob
                if aParms(0) = 10 then
                    this.Jobs.GetNextJob
                    if this.DiscoveringType = 16 then
                        this.DiscoveringType = 17
                        this.DiscoveringInstance = 1
                        this.FindDevice
                        ...

When OnChangeOnNewState receives an Error State "<E" response, the first thing it does is GetNextJob. Then it checks if the Error State = 10. Then it does a GetNextJob again. That doesn't sound right ... two GetNextJobs are being called one after the other.

I'm going to add code that looks like this:
CODE
            case 1:    ' Error Status (<E)
                sMsg = "Error Status: " &  aParms(0)

                select case aParms(0)
                    case 0: ' Good response
                        this.Jobs.GetNextJob

                    case 1,2,3,4,5,6,7,8,9: ' Bad response
                        this.Jobs.RetryJob

                    case 10: ' Discovery
                        this.Jobs.GetNextJob
                        if this.DiscoveringType = 16 then
                            this.DiscoveringType = 17
                            this.DiscoveringInstance = 1
                            this.FindDevice
                            ...
                end select


What do you think?
etc6849
These sound like great ideas to me!

So, when I came home today after running the polls for one minute for ~24 hours, my serial port does not seem to work unless I click reset or do a manually delete/re-add. Port spy also shows no data being rx or tx. Your new driver did make it to 1 errors/5954 commands!

This is exactly the same issue I had sending the betabright updates every minute if you remember; after 5-6 hours the betabrite would stop receiving data. For the betabrite I ended up making a reset timer that triggers every 2 hours (pretty basic).

Is there some new security feature to vista and windows 7 that could be causing this? This issue makes me want to add the reset port timer back wink.gif Personally, I think after x number of job retry's the driver should try to reset the serial port at least once, then retry the job again. Periodically polling for a predefined resonse would also work too.

Having three devices now that have this issue, I'm really curious if anyone running vista uses a custom serial driver that polls every minute and doesn't stop working (obviously the driver must not do the automatic port reset for the test)?

This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2010 Invision Power Services, Inc.