WindowShade Level vs Position

Sorry but I'm new. What's the difference between Level and Position.

In the doc's, setPosition method and the position attribute are used to open.close, x% open, etc.

But in my devices (Qubino roller shutter) I just see the level property. When using the HA & homebridge makerapi apps I get no position/level feedback.

It's all confusing!!!

Position is technically an attribute of the Windows Shade capability, whereas level is an attribute of the Switch Level capability. The latter is mostly intended for dimmers, but any device with some sort of 0-100 (or 99) range can use it. I think most shades/blinds drivers still use it because it makes them more widely compatible with apps, far many more of which are written to accommodate dimmers/level than shades/position in particular. Some drivers implement only the position attribute (and Set Position command) from the Window Shade capability, which is probably all you'd need in an ideal world, but again, having the rest tends to make the device more widely usable.

In all drivers I've seen, these attributes (position and level) and commands (open/close and on/off, setPosition and setLevel) are synonymous. For Homebridge, you can hide capabilities or attributes you don't want exposed. Adding one would be more difficult unless you have the driver code to modify or wanted to use a virtual device and "mirror" them.

That makes sense and I'm guessing most people only use curtains/blinds will only use in a open/closed mode but if you want to use position/level control then the apps using the makerapi then the position attribute is either null, undefined.

This fix for the home assistant integration is:

def current_cover_position(self) -> Optional[int]:
"""Return current position of cover."""
position = self.get_int_attr(ATTR_POSITION)
if position is None:
return self.get_int_attr("level")
return position

When I was creating the WindowShade driver for HubConnect.. which is a very special case driver, I encountered the 'definition confusion' too. My solution was, as @bertabcd1234 suggests, to make them synonymous:

      sets the shade to a partial position, special case for null (Homebridge)
def setPosition(pos) 
	if (pos != null)
	   parent.sendDeviceEvent(device.deviceNetworkId, "setPosition", [pos])
	   parent.sendDeviceEvent(device.deviceNetworkId, "close")
// Dashboard uses setLevel as if shades are 'dimmers'
def setLevel(pos) { setPosition(pos) }

This last line simply takes Level values and uses them as Position values. I also imagine that it's done like this for most Shade drivers.

1 Like

So I need to develop my own driver to be to fit a square peg in a round hole?

Thanks for the code snipet, great reference!!!!

I would be surprised if you did need to create your own... I think it's a common 'fixup' as far as I know. Fans suffer from the same general issue.. two 'definitions' for setting a fan speed. Level is one... :slight_smile: Fans support a fixed set of speeds.. so if you set a level of 40 (%) what speed is that exactly?? Medium? Medium-low?

1 Like

I'm quite deep in the Home Assistant rabbit hole and been there for a while an only past the entrance in the Hubitat rabbit hole. So far no cave ins which make me want to go deeper :stuck_out_tongue:

I'm done with HA, too many issues so more digging required with hubitat!!!


I am trying to troubleshoot some behavior in my shades and was wondering how
to re-write the last line of code. If

is taking the Level Value and uses them as Position value do I reverse the order so that it is taking Position value and uses it as Level Value like so:

Thanks for your help.

Edit: I just tried it and it solved my issue.