Let's see. I am using telnet to connect to an AVR receiver. The receiver supports commands for volume up and volume down; but does not support setting the volume. So, instead, I run a loop and single step volume up/down until the values match.
In my code; on the response of the telnet call; I update an attribute.
// If response is volume related
if( resp.matches( 'VOL(.*)' ) ) {
// Remove VOL, check if even, divide by two
vol = resp.replaceAll("VOL", "").toInteger()
if( vol % 2 != 0 ) vol = vol - 1
sendEvent( name: "Volume", value: vol / 2 ) //********
}
Next (in the same response function), if a condition matches, I go to run a different function (recursively until the numbers match):
// If we are increasing or decreasing, call function
if( iterate == "increase" || iterate == "decrease" ) setVol( desired )
Lastly, in the setVol() function, I grab that attribute again:
// Get current Volume
curVol = device.currentValue( "Volume" ).toInteger() //********
The issue is that sometimes the sendEvent() function completes before the currentValue() function is called; and sometimes it does not.
Is there a way to tie into the sendEvent() function? Maybe a complete() or then() method?
That's what I would typically do, but I have also experimented with adding singleThreaded: true to the driver declaration. It's supposed to ensure coherency on State (and, I would assume, other things like attributes).
But I think this is a pretty aggressive use of the attribute history, so the short delay may be a good failsafe in addition to the singleThreaded setting. At the least, it would likely reduce the number of retries required to see the change propagate through.
I tried this method, first. And while it did work; it just seemed "hackish" compared to something that could trigger after sendEvent completes. Awesome suggestion, though.
This is news to me. I'll have to at least research how that feature works.
In the end, my solution was simple. I just passed an extra parameter to setVol() with the modified volume value. I didn't think about this at first, because setVol() is a command, and I didn't know about passing additional parameters when a command is declared. This worked great, and I now have smooth scrolling and stops on a dime.
Again, thank you! I still have much to learn with this "groovy" language.