
Security News
Meet Socket at Black Hat and DEF CON 2025 in Las Vegas
Meet Socket at Black Hat & DEF CON 2025 for 1:1s, insider security talks at Allegiant Stadium, and a private dinner with top minds in software supply chain security.
An API for Switchbots that allows to control actions, settings and timers (also password protected)
A Python API for SwitchBots that allows to control actions, settings and timers.
The setup is tested on a RaspberryPi 3 with the Raspbian Buster OS in combination with Switchbots running firmware 4.4 and 4.5
Note that if you observe the following error: Can't init device hci0: Connection timed out (110)
while running either of the APIs. Update all packages see these steps.
The examples folder contains demonstrations how to scan for switchbots, press the switchbot, read and set settings (battery, firmware, hold time, etc.), read and set timers.
Use the scanner to find all switchbots in the area:
from switchbotpy import Scanner
scanner = Scanner()
mac_addresses = scanner.scan()
Use the mac address to create a bot instance providing methods to control the switchbots:
from switchbotpy import Bot
bot = Bot(id=bot_id, mac=mac, name=name)
bot.encrypted(password) # optional (only required in case the bot has a password)
bot.press() # press the switchbot
settings = bot.get_settings() # get a dict with the current bot settings
# all other options can be found in the example folder
For people interested in building an application controlling their switchbots, I provide a list with the results of my reverse engineering. I do not guarantee correctness nor completeness but with the BLE commands as described below I managed to control switchbots with firmware 4.4 and 4.5. The official switchbot app was used to set the password of the bots.
Request | Notification (Response) | |||||
---|---|---|---|---|---|---|
Name | Handle | Unencrypted | Encrypted | Required | Handle | Value |
press | 0x16 | 0x 57 01 | 0x 57 11 pw8 | 0x13 | stat2 | |
turn on | 0x 57 01 01 | 0x 57 11 pw8 01 | ||||
turn off | 0x 57 01 02 | 0x 57 11 pw8 02 |
pw8
: crc32 checksum of the password in 4 bytesstat2
: 1 = action complete, 3 = bot busy, 11 = bot unreachable, 7 = bot encrypted, 8 = bot unencrypted, 9 = wrong passwordThe bot settings are all retrieved by triggering one notification which consists of the concatenated settings.
Request | Notification (Response) | |||||
---|---|---|---|---|---|---|
Name | Handle | Unencrypted | Encrypted | Required | Handle | Value |
get settings | 0x16 | 0x 57 02 | 0x 57 12 pw8 | x | 0x13 | 0x stat2 bat2 fw2 64 00 00 00 00 nt2 ds1 inv1 sec2 |
battery | bat2 : 1st byte of value | |||||
firmware | fw2 : 2nd byte of value (div by 10) | |||||
number of timers | nt2 : 8th byte of value | |||||
dual state mode | ds1 : first 4 bits of 9th byte of value | |||||
inverse direction | inv1 : last 4 bits of 9th byte of value | |||||
hold seconds | sec2 : 10th byte of value |
pw8
: crc32 checksum of the password in 4 bytesstat2
: 1 = action complete, 3 = bot busy, 11 = bot unreachable, 7 = bot encrypted, 8 = bot unencrypted, 9 = wrong passwordRequest | Notification (Response) | |||||
---|---|---|---|---|---|---|
Name | Handle | Unencrypted | Encrypted | Required | Handle | Value |
hold time | 0x16 | 0x 57 0f 08 sec2 | 0x 57 1f pw8 08 sec2 | 0x13 | stat2 | |
mode | 0x 57 03 64 ds1 inv1 | 0x 57 13 64 pw8 ds1 inv1 |
pw8
: crc32 checksum of the password in 4 bytessec2
: seconds as one byte unsigned intds1
: if dual state mode: 1 else 0inv1
: if inverse mode: 1 else 0stat2
: 1 = action complete, 3 = bot busy, 11 = bot unreachable, 7 = bot encrypted, 8 = bot unencrypted, 9 = wrong passwordRequest | Notification (Response) | |||||
---|---|---|---|---|---|---|
Name | Handle | Unencrypted | Encrypted | Required | Handle | Value |
get timer | 0x16 | 0x 57 08 tid1 3 | 0x 57 18 pw8 tid1 3 | x | 0x13 | |
set timer | 0x 57 09 tid1 3 timer20 | 0x 57 19 pw8 tid1 3 timer20 | stat2 | |||
sync timer | 0x 57 09 01 t16 | 0x 57 19 pw8 01 t16 | stat2 |
pw8
: crc32 checksum of the password in 4 bytestid1
: timer id between 0 and 4timer20
: nt2
00 rep2
hh2
mm2
rep11
md1
rep21
act1
its2
ihh2
imm2
nt2
: number of timers as one byte (e.g. 0x03 if there are 3 timers set)rep2
: repeating pattern as one byte. Is 0x00 if timer is disabled. Is 0x80==b10000000 if there is no repetition. Otherwise, the last seven bits of the byte indicate the weekday on which the timer should be repeated (e.g. b01100000 means that the timer counts for Sunday and Saturday).hh2
: timer hour between 0 and 23mm2
: timer minute between 0 and 59rep11
: in case the timer is disabled (rep2
=0), the first 4 bits of the repeating byte are stored heremd1
: timer mode (standard=0, interval=1) as a byte,rep21
: in case the timer is disabled (rep2
=0), the last 4 bits of the repeating byte are stored hereact1
: timer action (press=0, turn_on=1, turn_off=2) as a byteits2
: interval timer sumihh2
: interval timer hourimm2
: interval timer minutesstat2
: 1 = action complete, 3 = bot busy, 11 = bot unreachable, 7 = bot encrypted, 8 = bot unencrypted, 9 = wrong passwordFAQs
An API for Switchbots that allows to control actions, settings and timers (also password protected)
We found that switchbotpy demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Meet Socket at Black Hat & DEF CON 2025 for 1:1s, insider security talks at Allegiant Stadium, and a private dinner with top minds in software supply chain security.
Security News
CAI is a new open source AI framework that automates penetration testing tasks like scanning and exploitation up to 3,600× faster than humans.
Security News
Deno 2.4 brings back bundling, improves dependency updates and telemetry, and makes the runtime more practical for real-world JavaScript projects.