Updating status LEDs on HomeSeer WD200+ Dimmers


#1

1) Give a description of the problem
I have HomeSeer WD200+ dimmers in nearly every room of the house. These dimmers have 7 RGB LEDs that show dimmer status but can also programmatically be set to show a status of something. In my case I show open/close/lock/unlocked status of the main entry points to my house. In Night more the LEDs blink and during the day they are solid. While the piston below works, it is very unreliable and slow to execute. Not all dimmers behave the same way… some are more reliable and some tend to miss some commands. The last one in the device list seems to be one that fails often (Patio Light). All the dimmers in the list are relatively close to eachother.

Setting the LEDs to 0 as their color before switching to “normal mode” if all LEDs are off was an attempt to address what appeared to be an old LED status from showing up when switching the dimmer LEDs to “status mode”.

The use of conditions Vs triggers was to address the fact that any of the 7 things I monitor may trigger a re-evaluation of all conditions so using triggers was causing LEDs to turn off when the condition was actually still true. Door changed to open Vs Door is open when back yard gate changed to open triggering a re-evaluation of door as well.

2) What is the expected behavior?
See above. Mostly, I am hoping for the LEDs to quickly follow the actual status of my access points.

3) What is happening/not happening?
The LEDs on the various dimmers are often inconsistent. They update very slowly and with much larger than expected delays between each other (I update one at a time but it seems to be quite slow). Even the first updated device is very slow. On the contrary, the array that holds the status updates very quickly.

4) Post a Green Snapshot of the piston![image|45x37]
(upload://xK8WwMCzoDkDrcB1Jf27yjtZ9bq.png)

In the snapshot below the ledStatusTarget has all LEDs turned on to a color except #4 for testing purposes (both test switches were on when I took the snapshot).

5) Attach any logs (From ST IDE and by turning logging level to Full)
(PASTE YOUR LOGS HERE BETWEEN THE MARKS THEN HIGHLIGHT ALL OF THE LOGS AND CLICK ON THE </> ICON TO FORMAT THEM)

10/5/2018, 12:43:10 PM +348ms
+0ms ╔Received event [Dog House].time/recovery = 1538761390346 with a delay of 1ms
+219ms ║RunTime Analysis CS &gt; 24ms &gt; PS &gt; 84ms &gt; PE &gt; 111ms &gt; CE
+222ms ║Runtime (59618 bytes) successfully initialized in 84ms (v0.3.108.20180906) (221ms)
+223ms ║╔Execution stage started
+225ms ║╚Execution stage complete. (1ms)
+226ms ╚Event processed successfully (227ms)
10/5/2018, 12:42:59 PM +93ms
+1ms ╔Received event [Dog House].time/recovery = 1538761379092 with a delay of 1ms
+162ms ║RunTime Analysis CS &gt; 12ms &gt; PS &gt; 44ms &gt; PE &gt; 106ms &gt; CE
+166ms ║Runtime (59618 bytes) successfully initialized in 44ms (v0.3.108.20180906) (164ms)
+167ms ║╔Execution stage started
+168ms ║╚Execution stage complete. (1ms)
+170ms ╚Event processed successfully (169ms)
10/5/2018, 12:41:48 PM +191ms
+1ms ╔Received event [Dog House].time/recovery = 1538761308190 with a delay of 0ms
+228ms ║RunTime Analysis CS &gt; 20ms &gt; PS &gt; 69ms &gt; PE &gt; 139ms &gt; CE
+233ms ║Runtime (59618 bytes) successfully initialized in 69ms (v0.3.108.20180906) (231ms)
+235ms ║╔Execution stage started
+237ms ║╚Execution stage complete. (2ms)
+239ms ╚Event processed successfully (239ms)
10/5/2018, 12:40:33 PM +253ms
+1ms ╔Received event [Dog House].time/recovery = 1538761233252 with a delay of 0ms
+7473ms ║RunTime Analysis CS &gt; 24ms &gt; PS &gt; 7263ms &gt; PE &gt; 187ms &gt; CE
+7475ms ║Piston waited at a semaphore for 7155ms
+7478ms ║Runtime (59692 bytes) successfully initialized in 7263ms (v0.3.108.20180906) (7476ms)
+7479ms ║╔Execution stage started
+7480ms ║╚Execution stage complete. (1ms)
+7482ms ╚Event processed successfully (7483ms)

I have a couple virtual switches that I use to test the piston without locking/unlocking the doors while away. In some cases I have to hit “Trace” to get the piston to do anything. Above is the minimal logs I got the last few times I tried this (logs set to full). What is causing this: “Piston waited at a semaphore for 7155ms”?


#2

This one looks like a doozy. Keep in mind, you have 15 triggers. (which is technically at least 30 events) This means that whenever ANY of them toggle in either direction, your entire piston will run from top to bottom. You are basically spamming your network, and I would expect that data would be lost occasionally.

For example, your piston will run top to bottom each time:

  • Location mode changes to anything
  • Front door is locked
  • Front door is unlocked
  • Front door opens
  • Front door closes
  • etc…

Also, you have used 100% conditions all throughout this piston. This forces webCoRE to re-send commands to all 7 devices three times each, whenever ANYTHING changes. (so whenever any of the 30 events change, you are sending out 21 commands) I would be surprised if this piston has not impacted your OTHER pistons as well… You have effectively created your own bottleneck.

I would delete the loops, and use triggers instead of conditions, so the commands are only sent when there is actual change.

For example:

IF {yardGate}'s contact CHANGES TO closed
Blah blah blah

This way, that section of code will ONLY run when the gate is first closed. Not when the front door is locked or any of the other 29 events


#3

I have noticed that something was running way more frequently than needed as the LEDs seemed to hiccup every so often. Considering that door unlock, door open, door closed, door lock tend to follow each other back to back, I was quite sure the piston could not keep up sending the commands. The issue is that when all my conditions were triggers, the LEDs that had to stay on given the condition had not changed, were coming and going. Looked like a disco… BUT that was before my additional FOR loop changes so it is best for me to go back and change the conditions to triggers as you suggested if that limits the spam.

Also, if the door is unlocked and that has already been reported, then I don’t need it to do it again when it opens… I was planning on having another list variable that keeps track of what I sent to the LEDs so that I can avoid sending the same command again. Issue is that I believe I would need to use a global variable to do so but I can’t create a global array (list).


#4

I think webCoRE can keep up… but I believe that most normal home networks cannot.


What I meant was something like this:

IF {yardGate}'s contact CHANGES TO *closed*
Then send appropriate color to the device
END IF

IF {yardGate}'s contact CHANGES TO *open*
Then send appropriate color to the device
END IF

No looping. No extra commands being sent to devices all around your house. Nice and clean.


Normally, I agree, but sending out one extraneous command is still MUCH better than sending out twentyone.


#5

I just re-read your initial post.

Are you making all 11 devices display the exact same colors all the time?
In other words, are the LEDs on each device mirroring all the others?


#6

The only LEDs that updated properly in the variable (see screenshot) are the ones where I forgot to change the conditions to triggers on the test buttons (LED 5,6,7). I need to split the on and off triggers so they are not both in the same IF. The previous iteration of this piston had an IF with a trigger and in the THEN it has the command sent to all “statusDevices” together. I was having issues there too so I figured that using loops to send commands to a single device at a time was preferable.

No, each LED is turned on as needed individually. The ledColor variables have the predefined colors I want used when a particular condition is met. 4 is Green so when the Back Yard Gate opens I want the 4th LED (coincidence) to turn Green (solid in the day, blinking in the night). 7, 6, and 5 are the main access doors and I use red (1) for all 3.

I must ensure that my ledStatusTarget variable always has the current LED map (1-7 = colors thus on; 0 = off). In previous iterations of this piston, one trigger would cause another LED to change when the condition had not changed. In other words opening the overhead garage door caused the front door led to go out when in reality it was still open. I figured it was due to using triggers (likely incorrectly) as changing it to conditions fixed the issue.


#7

I have errands I need to run at the moment,
but I just noticed on line 148, it refers to a variable that does not exist.

temp


#8

That was due to me renaming the ledStatus list to ledStatusTarget in preparation of two arrays, one to keep target and the other to keep track of what I already sent… but I got stuck when I did not find a way to create a global array…


#9

What I meant was, does the 4th LED represent Backyard Gate on all 10 devices?
(so when the gate changes, a command has to be sent to all 10 devices to update the 4th color?)


#10

Yes, the LED assignment is the same across all devices.

I saw in the logs what you were saying. I am trying to modify the code per your suggestions to bring that down to 1 update per LED change.


#11

Ouch, so even if the piston was broken down into the most basic form, a single door opened is still going to send out commands to all 10 devices.


Let me ask one more question…

If the LEDs are currently

  1. Red
  2. Yellow
  3. Green
  4. Blue
  5. Off
  6. Off
  7. Off

Are you able to send a one-line command that ONLY changes #4 to Purple?
Will doing that tamper with the other 6 colors?
Or do you have to send a command instructing all 7 colors each time you change one?


#12

You can update 1 LED at a time without affecting the others. Below is a snapshot of an older revision of this piston where I was doing that but it felt like a very messy way of doing it… I am trying to find a way to recursively send the commands to only update the LEDs that have changed. Ideally the special commands appear as infrequently as possible given they are annoying to work with (due to what I believe to be a webCore bug, they don’t show up as an option unless there is an actual device listed above instead of a variable listing the devices - sorry I don’t know the terms).

I have not tested this but this is what I am trying (I believe it incorporates your feedback):

Thank you for all your help!!!


#13

Got to a stopping point… it works but seems a bit slow and I am not sure whether any unnecessary commands are being sent over the zwave mesh network…


#14

I have skimmed the first half of of your latest piston, and it looks well structured. Making the conditions into triggers should reduce your network chatter about 90%.

The one thing to keep in mind though is:
Your Test Switch is still a condition, and peppered throughout your code. This means if you are using that during testing, the results will be almost identical to your original post. IE: Whenever Test Switch flips on or off, the piston runs the old way, looping and sending out hundreds of commands.

A more fitting test is to simply open a door and check the log & response time.
(but even this will not be accurate with the Test Switches causing extra spam)

IE: All seven ledStatusUpdatedIndex[x] will equal 1, no matter what triggered it.
This effectively forces each loop to run in it’s entirety, including all the extraneous commands.

Unfortunately, this is not one of the cases where testing can be easily done with a SimSwitch.
(unless you limit the SimSwitch to a single block)


If it were me, I would remove all references to all Test Switches, and test the “old fashioned” way by opening a door.

For future reference:
Test Switches work GREAT when creating a new piston, but they should be kept to one use per piston. If you want to reuse that Test Switch elsewhere, it should first be removed from the original block. (or you are bound to create conflicts)


#15

I REALLY REALLY appreciate all your help!!! I was using test switches even though I had to press “TEST” to force the piston to run as I could not actually lock/unlock the doors while programming. I did not realize they were causing all that extra spam (triggers/conditions still eludes me even though I read the sticky on it).

I think this last iteration incorporating your suggestions works as desired. I have not verified the amount of traffic but the LEDs respond quite fast and reliably:

One variable that introduces undesired delays is the amount of time that the locks take to report their status. If I lock/unlock the door physically it seems like the status changes immediately and reliably in the ST app. If I do so remotely it often gets stuck in between the lock/unlocked statuses just saying “unlocking” or “locking” even though the door lock has completed the operation. I don’t know whether this is a cloud issue, ST app issue, zwave mesh network issue… I guess looking at the logs might answer this in part.

I have a piston that plays door opening/closing/locking/unlocking alerts and I am quite sure my triggers/conditions are messed up there too so I will use what I learnt from you on this piston to rework that one as well. There I also have to deal with the door contact sometimes reporting open/closed faster than the lock change even though the latter happened prior. I know the piston can be improved as the LEDs now updated faster than the vocal alert so the delay is more likely caused by my piston rather than the lock reporting delays I was suspecting.


#16

Below is a new revision of my piston that I created in hopes of further optimizing the piston and resolve an outstanding issue. The backdoor is often closed and locked very quickly causing the system to miss something so the LED stays on. The lock is zwave and a bit slow and flaky. The door open/closed status actually comes from my alarm system. The alarm system is interfaced to ST using a variant of AlarmServer running on an Odroid C2. I believe that this is in art why the piston occasionally misses that the door is closed and locked. I don’t want to just rely on locked as the door could be open and locked… With less than a day of testing I can’t say it has solved the issue but things do seem to be faster (and if I am interpreting the Statistics section correctly, it does seem to have improved quite a bit since its first revisions).


#17

I am unable to test this, but I think it will resolve itself if you add a short wait between lines 78 & 79. Basically, the wait is to give the hub a chance to get the status update before checking the second IF statement.

LED_Alerts

(That Wait time can always be tweaked, but keep it short or the original IF will timeout)


If that fails, you could always split up the above block into 2 separate blocks. One for when door lock changes, and one for when door contact changes (worded slightly different)


#18

Just trying to make sure I understand everything in your code. Would you mind explaining a few things.

A few questions:

What is restriction switch? Judging my my reading of prior posts, are you setting a virtual switch that will stop/start the LED’s on your dimmer from reporting the status of your other items?

When specifying integer ledStatusTarget and ledStatusUpdateIndex, what is that doing?

What does integer loopIndex do?
What does integer allLedStatus do?

What does the const integer led color do? Why do some color dual the same number, like 1 and 2, and 5,6,7?


#19

restrictionSwitch is a virtual switch I use to turn a piston on or off. This way, I can easily turn off all pistons that announce the status of my doors. It is a programming alternative to pausing all pistons that provide “Door Alerts”. In summary, the piston only runs if the switch is on.

Please keep in mind that I may have done things in an absurd way… I fiddled with the code trying to make it work and reduce zwave traffic as much as possible as my network is constantly congested. In previous iterations I would update all LEDs every time there was a change and I kept missing updates etc. With my latest code it rarely misses the update… but it is still likely done is a terrible way.

Q: When specifying integer ledStatusTarget and ledStatusUpdateIndex, what is that doing?
A: When events happen I set the desired LED color by updating an array that will then be used to push all updates to the LEDs. Instead of hardcoding the number corresponding to the desired color, I use ledColor* variables that are defined in the define section. All that does is make it easy to change default color for each LED. The top 3 LEDs (led 5,6, and 7) are for my doors to the outside and they are always RED (1).

The ledStatusUpdateIndex is an array I use to indicate which LED needs updating. 1 means the change needs to be pushed to the devices and once done it gets reset to 0. The hope was that doing this I could avoid pushing the same status to LEDs unnecessarily. In other words, the only zwave commands issued should be for the LED(s) that changed. This was to reduce traffic.

Q: What does integer loopIndex do?
A: It is a variable I use to point to the correct array location. I also use it to count the proper number of iterations in the FOR loop.

Q: What does integer allLedStatus do?
A: I use it in a FOR loop to see if any LEDs are set to anything other than OFF. If they are all OFF then the variable will be set to 0 at the end of the FOR loop. If allLedStatus is 0 then I set all devices back to their normal mode where the LEDs are reporting the dimming.

Q: What does the const integer led color do? Why do some color dual the same number, like 1 and 2, and 5,6,7?
A: That is where I set the default color for that notification LED. My standard is red for doors to the outside, green for the backyard gate, purple for the garage door.

The resetSwitch is what I use to force the LEDs back to default if they ever get stuck to on. Instead of, for example, opening and closing the door to reset the door switch, I just turn on and then back off the virtual resetSwitch. I used to have this happen all the time but now it is rare.

I do not recall the changes I may have made since this version so I am pasting the one I am currently using in case I made corrections: