## Expected Behavior
Moving/setting the primary rail of a dual-rail shade shoul…d not change the binding's state for the secondary rail position.
## Current Behavior
When the primary rail of a dual-rail shade is moved (either using up/down commands or by sending a PercentType command), the secondary rail position becomes UNDEF within OpenHAB. As expected, the secondary rail itself does not move. However, the secondary rail state is lost. Eventually, the binding will tell the hub to do a "hard refresh" of each shade, and then the secondary rail state will be properly restored.
This bug seems to be due in part to a quirk of the Powerview Hub. When a shade position command is PUT to the hub, it seems to cache that exact position object, and returns it on future polling. So, if a command is sent with only the primary rail position set, the hub will return only the primary rail position with each poll until the hard refresh is performed.
I captured a TRACE level log showing this behavior. To make the logging a bit easier, I disabled the Thing for all but one of my shades, so only shade ID 58131 is getting updated. In addition, to speed up the state changes, I set the hard refresh interval to 5 minutes. I also set the polling interval to 2 minutes to reduce the number of log lines. The full log is attached ([powerview_secondary_undef_trace.txt](https://github.com/openhab/openhab-addons/files/7517630/powerview_secondary_undef_trace.txt)), but an annotated and truncated version is included below. Also, this log was captured using the JAR file that fixed issue #11543, but I confirmed that this bug existed in the 3.1.0 version of the add-on.
I started capturing the log the log after a hard refresh. I then issued a command to move the secondary rail (`LivingRoom_Shade5_Top`) to position 49. This worked as expected, and the JSON response included both rail positions.
```
21:38:27.755 [TRACE] [erview.internal.HDPowerViewWebTargets] - API command GET http://192.168.1.104/api/shades/58131
21:38:30.910 [TRACE] [erview.internal.HDPowerViewWebTargets] - JSON response = {"shade":{"id":58131,"type":9,"capabilities":7,"batteryKind":2,"smartPowerSupply":{"status":0,"id":0,"port":0},"batteryStatus":3,"batteryStrength":158,"roomId":1877,"firmware":{"revision":2,"subRevision":3,"build":3147,"index":3},"name":"TGl2aW5nIFJvb20gNQ==","groupId":27580,"signalStrength":4,"positions":{"posKind1":1,"position1":0,"posKind2":2,"position2":65535},"timedOut":false}}
21:38:47.931 [INFO ] [openhab.event.ItemCommandEvent ] - Item 'LivingRoom_Shade5_Top' received command 49
21:38:47.933 [INFO ] [openhab.event.ItemStatePredictedEvent] - Item 'LivingRoom_Shade5_Top' predicted to become 49
21:38:47.934 [TRACE] [erview.internal.HDPowerViewWebTargets] - API command GET http://192.168.1.104/api/shades/58131
21:38:47.940 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'LivingRoom_Shade5_Top' changed from 100 to 49
21:38:47.984 [TRACE] [erview.internal.HDPowerViewWebTargets] - JSON response = {"shade":{"id":58131,"type":9,"capabilities":7,"batteryKind":2,"smartPowerSupply":{"status":0,"id":0,"port":0},"batteryStatus":3,"batteryStrength":158,"roomId":1877,"firmware":{"revision":2,"subRevision":3,"build":3147,"index":3},"name":"TGl2aW5nIFJvb20gNQ==","groupId":27580,"signalStrength":4,"positions":{"posKind1":1,"position1":0,"posKind2":2,"position2":65535}}}
21:38:47.987 [TRACE] [erview.internal.HDPowerViewWebTargets] - API command PUT http://192.168.1.104/api/shades/58131
21:38:47.988 [TRACE] [erview.internal.HDPowerViewWebTargets] - JSON command = {"shade":{"id":58131,"positions":{"posKind1":1,"position1":0,"posKind2":2,"position2":32112}}}
21:38:49.625 [TRACE] [erview.internal.HDPowerViewWebTargets] - JSON response = {"shade":{"id":58131,"type":9,"capabilities":7,"batteryKind":2,"smartPowerSupply":{"status":0,"id":0,"port":0},"batteryStatus":3,"batteryStrength":158,"roomId":1877,"firmware":{"revision":2,"subRevision":3,"build":3147,"index":3},"name":"TGl2aW5nIFJvb20gNQ==","groupId":27580,"signalStrength":4,"positions":{"posKind1":1,"position1":0,"posKind2":2,"position2":32112}}}
```
I then issued a command to move the primary rail (`LivingRoom_Shade5_Bottom`) to position 80. This time, only a primary rail position was sent, and only a primary rail position was received in the JSON response:
```
21:39:02.785 [INFO ] [openhab.event.ItemCommandEvent ] - Item 'LivingRoom_Shade5_Bottom' received command 80
21:39:02.787 [INFO ] [openhab.event.ItemStatePredictedEvent] - Item 'LivingRoom_Shade5_Bottom' predicted to become 80
21:39:02.789 [TRACE] [erview.internal.HDPowerViewWebTargets] - API command PUT http://192.168.1.104/api/shades/58131
21:39:02.792 [TRACE] [erview.internal.HDPowerViewWebTargets] - JSON command = {"shade":{"id":58131,"positions":{"posKind1":1,"position1":13107}}}
21:39:02.797 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'LivingRoom_Shade5_Bottom' changed from 100 to 80
21:39:04.425 [TRACE] [erview.internal.HDPowerViewWebTargets] - JSON response = {"shade":{"id":58131,"type":9,"capabilities":7,"batteryKind":2,"smartPowerSupply":{"status":0,"id":0,"port":0},"batteryStatus":3,"batteryStrength":158,"roomId":1877,"firmware":{"revision":2,"subRevision":3,"build":3147,"index":3},"name":"TGl2aW5nIFJvb20gNQ==","groupId":27580,"signalStrength":4,"positions":{"posKind1":1,"position1":13107}}}
```
Then, the binding polled for state. For simplicity, I'm truncating the JSON response of all 11 shades to show only 2 shades: the shade with id 58131 that was just moved and another shade that was not recently moved for comparison. Shade 58131 is only returning the primary rail position that was just set, not both rails, and the update leads to the secondary rail (`LivingRoom_Shade5_Top`) being set to UNDEF. I've removed some lines for simplicity, but see attached for full log:
```
21:39:23.009 [DEBUG] [nternal.handler.HDPowerViewHubHandler] - Polling for state
21:39:23.010 [TRACE] [erview.internal.HDPowerViewWebTargets] - API command GET http://192.168.1.104/api/shades/
21:39:23.122 [TRACE] [erview.internal.HDPowerViewWebTargets] - JSON response = {"shadeIds":[44940,58131,10734,35688,49916,40481,13306,43539,48128,57893,57040],"shadeData":[{"id":44940,"type":8,"capabilities":7,"batteryKind":2,"smartPowerSupply":{"status":0,"id":0,"port":0},"batteryStatus":3,"batteryStrength":161,"roomId":23864,"firmware":{"revision":2,"subRevision":3,"build":3147,"index":3},"name":"TWFpbiBCZWRyb29tIDU=","groupId":24609,"signalStrength":4,"positions":{"posKind1":1,"position1":0,"posKind2":2,"position2":19911}},{"id":58131,"type":9,"capabilities":7,"batteryKind":2,"smartPowerSupply":{"status":0,"id":0,"port":0},"batteryStatus":3,"batteryStrength":158,"roomId":1877,"firmware":{"revision":2,"subRevision":3,"build":3147,"index":3},"name":"TGl2aW5nIFJvb20gNQ==","groupId":27580,"signalStrength":4,"positions":{"posKind1":1,"position1":13107}},<RESPONSE TRUNCATED>]}
21:39:23.136 [DEBUG] [nternal.handler.HDPowerViewHubHandler] - Received data for 11 shades
<SNIP>
21:39:23.152 [DEBUG] [nternal.handler.HDPowerViewHubHandler] - Updating shade '58131'
<SNIP>
21:39:23.173 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'LivingRoom_Shade5_Top' changed from 49 to UNDEF
```
Additional polling continues to return only the primary position for this shade. Eventually, a hard refresh is triggered, and the secondary rail position is once again returned on the next polling. Response and logs are truncated as above for simplicity:
```
21:43:27.762 [TRACE] [erview.internal.HDPowerViewWebTargets] - API command GET http://192.168.1.104/api/shades/58131
21:43:30.909 [TRACE] [erview.internal.HDPowerViewWebTargets] - JSON response = {"shade":{"id":58131,"type":9,"capabilities":7,"batteryKind":2,"smartPowerSupply":{"status":0,"id":0,"port":0},"batteryStatus":3,"batteryStrength":158,"roomId":1877,"firmware":{"revision":2,"subRevision":3,"build":3147,"index":3},"name":"TGl2aW5nIFJvb20gNQ==","groupId":27580,"signalStrength":4,"positions":{"posKind1":1,"position1":13155,"posKind2":2,"position2":32062},"timedOut":false}}
<SNIP>
21:45:23.774 [DEBUG] [nternal.handler.HDPowerViewHubHandler] - Polling for state
21:45:23.775 [TRACE] [erview.internal.HDPowerViewWebTargets] - API command GET http://192.168.1.104/api/shades/
21:45:23.838 [TRACE] [erview.internal.HDPowerViewWebTargets] - JSON response = {"shadeIds":[44940,58131,10734,35688,49916,40481,13306,43539,48128,57893,57040],"shadeData":[{"id":44940,"type":8,"capabilities":7,"batteryKind":2,"smartPowerSupply":{"status":0,"id":0,"port":0},"batteryStatus":3,"batteryStrength":161,"roomId":23864,"firmware":{"revision":2,"subRevision":3,"build":3147,"index":3},"name":"TWFpbiBCZWRyb29tIDU=","groupId":24609,"signalStrength":4,"positions":{"posKind1":1,"position1":0,"posKind2":2,"position2":19911}},{"id":58131,"type":9,"capabilities":7,"batteryKind":2,"smartPowerSupply":{"status":0,"id":0,"port":0},"batteryStatus":3,"batteryStrength":158,"roomId":1877,"firmware":{"revision":2,"subRevision":3,"build":3147,"index":3},"name":"TGl2aW5nIFJvb20gNQ==","groupId":27580,"signalStrength":4,"positions":{"posKind1":1,"position1":13155,"posKind2":2,"position2":32062}},<RESPONSE TRUNCATED>]}
21:45:23.845 [DEBUG] [nternal.handler.HDPowerViewHubHandler] - Received data for 11 shades
<SNIP>
21:45:23.848 [DEBUG] [nternal.handler.HDPowerViewHubHandler] - Updating shade '58131'
21:45:23.852 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'LivingRoom_Shade5_Top' changed from UNDEF to 49
```
## Possible Solution
I think there are a few approaches to fix this. One workaround would be to increase the hard refresh frequency, but hard refreshes are expensive/slow because they involve RF communications with all shades on the network. Another option would be to perform a hard refresh before polling whenever the binding knows a shade has recently been moved, but I'm not sure how easy that would be to implement. The approach that seems cleanest to me is to make setting the primary rail similar to setting the secondary rail in this shade handler code:
https://github.com/openhab/openhab-addons/blob/062f45440663b431d6213d2854c17027787c9269/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewShadeHandler.java#L204-L227
The binding could first get the current state of the shade regardless of which rail was being moved, then only update the position of the desired rail and send the move shade command with both positions set. This would ensure the hub keeps the state of both rails in its cache. In the case of single rail shades, I think the get operation would already have the secondary rail position recorded as null, so updating the primary rail position and resending should still work, but I don't have any single rail shades to test that on.
## Steps to Reproduce (for Bugs)
1. Set the primary rail position of a dual-rail shade
2. Wait for the next hub polling to take place
3. Check the secondary rail position, which will be UNDEF until the next hard refresh or secondary rail command
## Context
I have been setting up slider UIs for my dual-rail shades, so that I have vertical sliders for the top and bottom rails that visually show their physical position. When I use the slider to change the bottom (primary) rail, the slider for the top (secondary) rail will move to 0 (the location when the value is UNDEF), so the UI no longer reflects the physical position of my shades.
## Your Environment
* Version used: OpenHAB 3.1.0; HD PowerView Binding 3.1.0 (logs collected with version 3.2.0-SNAPSHOT from #11543)
[powerview_secondary_undef_trace.txt](https://github.com/openhab/openhab-addons/files/7517630/powerview_secondary_undef_trace.txt)