Make motorized Levolor blinds smarter?

no one yet. See If that seems doable for you I’d be happy to send you a ‘wevolor’ to test for me. I’ve only ever
tried it with the one remote I have.

Sure. Sounds totally doable. Shoot me an email at

Still looking for someone to test? I just got my blinds and am looking to automate.

Just in case anyone want to try the Powerview remote on the Levelor Blind, don’t . The remote won’t program with the blinds

Interesting. In the instruction, I don’t see where where you pair with the bluetooth remote. Does that mean the bluetooth remote command are always the same?

If I get my own esp32, would I be able to get the software for it?

The remote is a Bluetooth Low Energy ‘Peripheral’, and discovering the advertised service is easy (Get ‘nRF Connect’ App for your phone). The hard part is then figuring out what commands (reads and writes to the services and characteristics) do what. I figured it out for my remote. Is it the same for all remotes? Probably, but that’s what I need to test. (I only have one remote).


I’m going to prefaces this by saying I’m not a developer. I can tinker with things and pretty good with following instructions. So I check out some youtube video to see how to use nRF. I can read the remote but I don’t seem to be able to “scan or read” whats being sent to figure out what I need to write. Seems like the app has a lock on the remote so when I switch to the levelor app, it won’t let me send.

So when you said the hard part about figuring out the command, did you just guest the value? If you can provide me with one of the value, you used, I can see if it works on my setting to confirm if remotes are the same.

yeah, it’s tricky - took me ages to figure it out. Try this if you’re willing: Write BA0A (byte array) to the AB529101 (-5310-etc.) characteristic, and then read it. You should get back BA0A. That unlocks the remote to take commands. Writing F10101 (F1 followed by two bytes) to the AB529201 characteristic then sends the commands to the blinds. The second byte is the command - 01 is open and 02 is close. The third byte is the group number (the 6 numbered buttons on the remote) - 01 is group1, 02 is group2, 04 is group3, 08 is group 4, up to 20 (0x20 - this is hex) is group 6. So F10220 will close group 6. F1013F would send an open to all 6 groups.

Wrote BA0A to the AB529101. When I tried to read it back, I didn’t get anything. Looking at the log, I got an error 2 GATT READ NOT PERMIT. Looks like BA0A won’t work on my remote to unlock it

I did get my an andriod phone and tried to log the Bluetooth call from phone to the remote via HCI Snooping. Was able to get the log and view them in wireshark. Didn’t really know what to look for in there but I did see the communication between my phone and the remote.

Hi Scott - well that’s interesting. I wondered if the value written would be something based on the serial number but I coded an emulator for the remote and changed the serial number but the Levolor App still wrote BA0A when it first connected. With the wireshark output you should be able to see what the Levolor app wrote to the AB529101 characteristic.

Okay had to hit another youtube video on how to decode wireshark and bluetooth. If anyone wants to learn its, check out this video

Roger, I was able to find the unlock value. In my case it is BC9B. Rolling up the blinds work as you suggested in your original message with the other values.

Next step is to get this loaded onto a ESP32. I have not experience here either but i can probably youtube this too. Any suggestions on which on to get and the code for it to work with my alexa?

Thanks for your help so far.

That’s impressive. Nicely done. I need to figure out what makes yours BC9B and mine BA0A. There’s only so much data the Levolor App gets from the remote, so it’s got to be based on that.

The ESP32 which I’ve been using will cost you a whole 10 bucks:

Programming it is with the Arduino IDE which you can download. I’ll put my code on my server and give you a link.

Hey Scott - please can you send me as much as you can from nRF for your remote. What you see when it’s scanned - the ‘Scanner’ page. What the 2A24 thru 2A29 reads return etc. I’ll try to emulate your remove to see if the unlock number changes. The email to use is at the bottom of the Wevolor instructions I posted.

I do have Alexa Echo

Can you email me to discuss further?

emailed you. Let me know.

I was also able to get this to work using both a Raspberry Pi and Vera Plus Home Controller using bluetooth shell comands.

I wrote a bash script for the various combinations of commands for the Raspberry Pi and Vera (ash script for the Vera) so I could then execute the shell commands using scene controllers. Note the Vera uses a busybox unix shell so things are a bit different than when in the Raspberry Pi linux shell.

Also if you are going to use a Vera unit, you will need to reinstall the BlueZ bluetooth stack since recent firmware updates removed it as it was for some reason deemed useless. You can find instructions for installing BlueZ many places online.

I used an android phone to send the various commands to the Levolor remote control, downloaded the hci snoop log from my phone into my computer, and ran it through wireshark to see what the phone was sending. I then used gatttool to test some of the data until I was able to mimick the phone app using the Vera or Raspberry Pi and control the remote control via gatttool. To do this you should first disable the bluetooth HCI snoop log to clear the log. Enable HCI snoop log and go into the Levolor app and open and close your blinds a few times so the log records the data sent. Then transfer the hci snoop log to your computer and open it in wireshark.

On my Samsung Note 10 I had to first create a full bug report under developer options and then download the bug report by connecting a usb to my computer and using adb running “adb -d bugreport”. This will download a folder where the adb tools are stored and then the hci snoop log is located in in under \FS\data\log\bt\btsnoop_hci.log – adb and developer tools must be installed on your computer to pull the bug report and devleoper mode and usb debugging must be enabled your phone. There are many instructions for this online for how to run adb and pull the bug report. Some phones will store the snoop log directly on the phone and will be easier to find. I also found my older android phone easier for locating the hci snoop log.

Once you load the bluetooth hci snoop log into wireshark, organize the data by “Protocol”. Go through the ATT protocols and look for a Sent Write Request with a destination matching the MAC address of the Levolor controller and is writing to handle 0x0021. If you click this wireshark entry and look under Bluetooth Attribute Protocol, you will see the sent Value: xxxx and that hex code is your unlock value in hex.

You will need to find the MAC address of your Levolor remote as well. You can also find this through wireshark or by running the shell command: hcitool lescan
look for the mac address with (Levolor) listed next to it.

The app first sends an unlocking write command to the remote. From what I understand from the other replies about using an Amazon Echo is that this value may be unique to each paired phone/remote and so you may have to use an android phone and wireshark to detemine this.

To send the unlock command from the Vera/Pi shell using gatttool, run (without the square brackets around the MAC address and unlock code):

gatttool -b [MAC ADDRESS HERE] -t random -m 247 --char-write-req -a 0x0021 -n [unlock code in hex]

If it works you should see “Characteristic value was written successfully” The remote is then unlocked and you can send the next command to move the blinds which should be sent right away. You can use an bash/ash script to automate this process better.

To control the blinds, the app then sends a char-write-req to handle 0x0025 with various values depending on the operation. The shell command is:

gatttool -b [MAC ADDRESS HERE] -t random -m 247 --char-write-req -a 0x0025 -n [VALUE TO MOVE THE BLINDS]

The value sent to move the blinds can be defined as f1XXYY where XX = blind control function (up, down, open, close, stop) and YY = blind group to move or combination of blind groups to move.

For XX, the various commands are: up = 01, down = 02, close shades = 03, open shades = 04, favourite position (usually half way) = 05, stop = 06

For YY, it is easier to understand which blinds will be controlled if you look at the value as binary values first.

If you consider only the last 6 bits of an 8-bit byte value with the various blind groups representing the bits as 00654321, setting the value of the bit corresponding to the blind group to 1 will move that blind group, and setting the bit to 0 will not move that blind. You would then need to convert the binary to hex to send the value using gatttool. For example,

To move blind group 1 only the value would be: 00000001 (hex=01)
To move blind group 2 only the value would be: 00000010 (hex=02)
To move blind group 3 only the value would be: 00000100 (hex=03)
To move blind group 4 only the value would be: 00001000 (hex=08)
To move blind group 5 only the value would be: 00010000 (hex=10)
To move blind group 6 only the value would be: 00100000 (hex=20)

To move all blind groups the value would be: 00111111 (hex=3f)

The reason it is best to understand the binary values is it allows you to move any combination of blind groups you want. For example, if i wanted to move blind groups 1, 3, and 6, the binary value would be 00100101 (hex=25). If i wanted to move blind groups 1,2,3,4, the binary value would be 00001111 (hex=0f).

You can convert the binary to hex using an online tool, or it is quite easy to learn how to convert them yourself. You can also automate the conversion of multiple blind group arguments into a hex value for gatttool using a bash/ash script.

So if I wanted to move all the blind groups down, I would send the following commands one after another:

gatttool -b [MAC ADDRESS HERE] -t random -m 247 --char-write-req -a 0x0021 -n [unlock value]

gatttool -b [MAC ADDRESS HERE] -t random -m 247 --char-write-req -a 0x0025 -n f1 023f
( 02 for down, 3f for all blind groups (binary=00111111).

If you package this into a script that takes two arguments and inputs them into variables in those commands, you can automate the process with one simple command line script for any combination you want.

The simple ash script I developed for my Vera looks like this:

echo -n “sending command…”
echo “c” > berror.txt
while [ -s berror.txt ]
gatttool -b [mac adress for controller] -t random -m 247 --char-write-req -a 0x0021 -n [unlock value] 2> berror.txt > /dev/null
gatttool -b [mac adress for controller] -t random -m 247 --char-write-req -a 0x0025 -n f1$2$1 2>> berror.txt > /dev/null
echo -n “.”
rm berror.txt
echo “”
echo “Command sent succesfully to blinds”

If saved as you would run this script as: ./ [grouparg] [movementarg], for example ./ 3f 01 would move all blinds up.

Note this script is an ash script; if writing it for a raspberry pi it must start with #!bin/bash

The $2 and $1 in the second gatttool command take two command line arguments and input them into the script. So if this script was saved as you would run ./ 3f 01 and 3f would be put whre $1 is, and 01 where $2 is, and this would move all blinds up.

Further, the script first creates an berror.txt file with a single character in it “c” making its size >0. It will then repeat the loop until that error file is empty. The addition of 2> berror.txt writes any error messages from gatttool to berror.txt; if there is no error the berror.txt will be cleared and the loop will stop. The second gatttool command uses the append error 2>> so that it does not clear a first error reported by the unlock command. I found often errors occur which prevent the command from being sent which is a problem if you are asking a Google Home to open the blinds since it will only run once. The loop keeps re-attempting the command until it is sent so you can be sure it will work. Each time the loop runs it adds an extra “.” to “Sending command…” so you can see the attempts in progress. The > /dev/null dumps the normal stdout from gatttool to null so you dont have it being printed during the loops.

Th “rm berror.txt” deletes the temporary error file once the loop is done and before the script finishes, and then finally it echos confirmation that the loop finished and the command was sent successfully to the blinds.

Then using your Vera you can execute those commands using scenes etc. In Vera you have the scene run the command: os.execute(’~/root/ [argument1] [argument2]’) to control the blinds with a specific movement and combination of blind groups. You can set up a scene for any combination of blinds and movements you wish.

I stopped once I got my Vera working, which is controlled by a Google Home Mini, but I am sure there is also a way to run shell comands on a Raspberry Pi using various home controllers such as Alexa, etc., Someone with a bit more developer knowhow than I could probably write an better app or plugin for the various controllers as well.

I hope this helps you all out

One thing I found recently helps. Writing a null value (zero length) to the AB529101 characteristic also unlocks the remote. You can then read back the key value or simply unlock it each time you connect with the null write.

1 Like