Skip to content

Instantly share code, notes, and snippets.

@cava
Created February 17, 2018 17:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cava/5628289fa2bd804aa5db8185729d9741 to your computer and use it in GitHub Desktop.
Save cava/5628289fa2bd804aa5db8185729d9741 to your computer and use it in GitHub Desktop.
# 'Lunvon Smart LED Bulb' bluetooth reverse engineering
import bluetooth
from string import hexdigits
from time import sleep
LAMP_ADDR = "f4:4e:fd:00:00:00"
LAMP_UUID = "00001101-0000-1000-8000-00805f9b34fb"
LAMP_LOGIN = "3031323334353637" # '01234567'
CMD_BASE = "01fe000053831000"
CMD_TURNON = "0000000050ff0000"
CMD_TURNOFF = "0000000050000000"
# RGB: BASE + "GGBBRR0050000000" where GG is green hex, etc.
# Bluetooth connection socket
btsock = None
def bt_send(data, debug=False):
cleanPayload = data.replace(":", "")
if debug:
print("> ", cleanPayload)
try:
btsock.send(bluetooth.binascii.unhexlify(cleanPayload))
except bluetooth.btcommon.BluetoothError as e:
print("! lamp disconnected")
lamp_connect()
def bt_read(n, debug=False):
d = bluetooth.binascii.hexlify(btsock.recv(n))
if debug:
print("< ", str(d))
return d
def lamp_turnon():
bt_send(CMD_BASE + CMD_TURNON)
def lamp_turnoff():
bt_send(CMD_BASE + CMD_TURNOFF)
def lamp_setrgb(rgb):
assert len(rgb) == 6
assert all(c in hexdigits for c in rgb)
hexR, hexG, hexB = rgb[0:2], rgb[2:4], rgb[4:6]
gbr = hexG + hexB + hexR + "0050000000"
bt_send(CMD_BASE + gbr)
def hsv2rgb(h,s,v):
assert 0 <= h < 360
assert 0 <= s <= 1
assert 0 <= v <= 1
c = s*v
x = c * (1 - abs((h/60) % 2 - 1))
m = v - c
r = g = b = 0
if 0 <= h < 60:
r, g = c, x
elif 60 <= h < 120:
r, g = x, c
elif 120 <= h < 180:
g, b = c, x
elif 180 <= h < 240:
g, b = x, c
elif 240 <= h < 300:
r, b = x, c
else:
r, b = c, x
return [ (r+m)*255, (g+m)*255, (b+m)*255 ]
def lamp_sethsv(h,s,v):
r, g, b = hsv2rgb(h,s,v)
rgbStr = "%.2X" % r + "%.2X" % g + "%.2X" % b
lamp_setrgb(rgbStr)
def lamp_connect(rgbTest=False):
global btsock
services = []
print("? searching for compatible devices ...")
# wait for the lamp to be avaible
while True:
services = bluetooth.find_service(
uuid=LAMP_UUID, address=LAMP_ADDR)
if len(services) > 0: break
print("? device not found, retrying in 5 seconds ...")
sleep(2)
lamp = services[0]
print("> lamp found [{}], connecting ...".format(LAMP_ADDR))
btsock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
btsock.connect((lamp['host'], lamp['port']))
# Login
print("> lamp 'login' ...")
bt_send(LAMP_LOGIN)
sleep(0.5)
if rgbTest:
print("> RGB test")
lamp_setrgb("220000")
sleep(0.4)
lamp_setrgb("002200")
sleep(0.4)
lamp_setrgb("000022")
sleep(0.4)
def lamp_color_loop():
print("> color loop ...")
while True:
for i in range(1, 360):
lamp_sethsv(i, 1, 1)
sleep(0.25)
if __name__ == "__main__":
lamp_connect(rgbTest=True)
lamp_color_loop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment