TDBU shades - revising shade driver for top bar

I've got Top Down Bottom Up Shades. They are paired to Hubitat through a Bond Bridge.

Neither Hubitat or Bond have a driver for TDBU, so I just paired the top and bottom bars as separate shades. This works great EXCEPT that is shows everything opposite for the top bar, and in my house, the shade position is changed almost entirely by moving the top bar. When I want to close it I have to select open and vice versa, and the dashboard icons are always wrong. After 2 years of this, I need to fix it.

To be clear, in my case, because the bottom bar never moves, when the top bar is down, the shade is open, when the top bar is up, the shade is closed

I'm using the Bond Motorized shade driver. The driver commands include a "Fix Shade" command that I can toggle beteen open & closed, as well as a "Start Position Change" command that has a dropdown from which I can select "open" & "closed". Doing either or both properly revises both the shade status and the dashboard icon to match the shade position, but it only holds for one or two position changes, then it reverts back to showing the opposite of what it is.

Next I attempted to revise the driver, but I have no idea what I'm doing, so I need some help from the smart people here.
Thus I've pasted the entire driver below (hope that is allowed). I tried switching the data after 'def open() from {parent.handleOpen(device)} to {parent.handleClosed(device)} and vice versa for def close(), but the only thing that changed with that is the command to send from the automation, The shade dashboard icons and the shade status in device is still backwards.

Is there a way to fix this either in the driver commands or by modifying the driver, and if so, please help me understand...

Original HE Driver:
/**

  • BOND Motorized Shade
  • Copyright 2019-2020 Dominick Meglio

*/

metadata {
definition (
name: "BOND Motorized Shade",
namespace: "bond",
author: "dmeglio@gmail.com",
importUrl: "https://raw.githubusercontent.com/dcmeglio/hubitat-bond/master/drivers/BOND_Motorized_Shade.groovy"
) {
capability "WindowShade"
capability "Switch"

    command "stop"
    command "fixShade", [[name:"Shade*", type: "ENUM", description: "Shade", constraints: ["open","close"] ] ]
	command "toggle"
	
}

}

def open() {
parent.handleOpen(device)
}

def close() {
parent.handleClose(device)
}

def on() {
open()
}

def off() {
close()
}

def toggle() {
if (device.currentValue("windowShade") == "open")
close()
else
open()
}

def stop() {
parent.handleStop(device)
}

def fixShade(shade) {
parent.fixShadeState(device, shade)
}

def setPosition(Number position) {
if (position == 0) {
log.info "position special value 0 is set, trigger CLose command"
close()
} else if (position == 50) {
log.info "position special value 50 is set, triggering Preset command"
parent.handlePreset(device)
} else if (position == 100) {
log.info "position special value 100 is set, triggering Open command"
open()
} else {
log.info "no-op for position value " + position + ", set position to 50 to trigger Preset command"
}
}

Bump. Can anyone help me figure out how to edit this driver to switch open and closed?

Hi Calinatl,

There are often misalignments between the different platforms - what shade position is open and what is closed...

You can experiment with changing the parent app, not the child device driver,
The app code is here :
https://raw.githubusercontent.com/dcmeglio/hubitat-bond/refs/heads/master/apps/BOND_Home_Integration.groovy

Look for 'handleOpen' and 'handleClosed' functions :

def handleOpen(device)
{
	def bondId = getBondIdFromDevice(device)
	logDebug "Handling Open event for ${bondId}"
	
    if (executeAction(bondId, "Open")) 
    {
        device.sendEvent(name: "windowShade", value: "open")
    }
}

def handleClose(device)
{
	def bondId = getBondIdFromDevice(device)
	logDebug "Handling Close event for ${bondId}"
	
    if (executeAction(bondId, "Close")) 
    {
        device.sendEvent(name: "windowShade", value: "closed")
    }
}

In these functions, reverse the executeAction second parameter, for example in the
def handleClose(device) method, change the line

if (executeAction(bondId, "Close"))

to

if (executeAction(bondId, "Open"))

Make a similar change also in the handleOpen() method. Do not change the child device driver code.

Will this work?

Thank you so much. I will definitely try this after the holiday

1 Like

@kkossev - so I've finally had an opportunity to dive into your suggestion. I'm not sure this is the direction I should go. What I'm specifically attempting to solve for is the TOP rail on a TopDownBottomUp shade. I have each of the two rails paired as it's own shade nice I don't think either Bond or HE have a TDBU driver.

If I change the code in the parent app, I'm thinking it will reverse things for ALL the shades. So it would "fix" the reporting for the top rail of the TDBU shades, but it would also reverse the bottom rail, which is currently correct...

I sort of think I need one version of the driver as it comes default, and another version of the driver reversed for the top bar.

Yep, this workaround in the parent app will reverse all shades :frowning:
Adding a 'reverse' option for the child device driver is not easy. I have done this in some of my drivers, but it requires a lot of testing.

Another approach could be to create a virtual shade device, then create RM5 rules to invert the commands and the attributes. However, bi-directional mirroring is also not easy - there is a risk of creating infinite loops that will freeze your hub... You need a dedicated dev. hub to experiment with.

Thanks.
I don't think I will try the virtual device; I don't have a dedicated dev. hub and can't risk creating an infinite loop...
If I had any idea of what I'm doing, I'd be fine to do testing, but ....

I tried to reverse the above pasted driver by reversing the def Open and Def close, which works for the commands, but not the dashboard tiles. Looking at it again, it occurs to me that maybe the dashboard tiles are working off of the on/off criteria, so I'm going to try reversing that also...I'll report back...

1 Like

Well I'm stumped.

As noted originally, I made the below revision to the driver, which allows the top rail to properly respond to open and close commands (because when top rail is down, shade is open, and when top rail is up, shade is closed)
def open() {
parent.handleOpen(device)
changed to
def close() {
parent.handleOpen(device)
AND
def close() {
parent.handleClose(device)
changed to
def open() {
parent.handleClose(device)

At this point, the automations work without needing to specify the opposite - ie if I set the automation to close, the top rail goes up, closing the shade, and if I set the automation to open, the top rail goes down, opening the shade. HOWEVER, the dashboard tiles show open when closed & vice versa.

To attempt to solve for the dashboard status, secondly, I made the below revision, which seems to have no effect at all, on the dashboard or on anything else:
def on() {
open()
changed to
def off() {
open()
AND
def off() {
close()
changed to
def on() {
close()

Third, still trying to resolve for dashboard status, I made the below revision, which again seem to have no effect at all, on the dashboard or on anything else.
if (position == 0) {
log.info "position special value 0 is set, trigger CLose command"
close()
changed to
if (position == 0) {
log.info "position special value 0 is set, trigger CLose command"
open()
AND
} else if (position == 100) {
log.info "position special value 100 is set, triggering Open command"
open()
changed to
} else if (position == 100) {
log.info "position special value 100 is set, triggering Open command"
close()

Obviously, I don't understand what I'm doing. Is anyone able to offer any guidance?