Skip to content

Commit

Permalink
Update README.md and Add yeelight control program
Browse files Browse the repository at this point in the history
  • Loading branch information
swkim01 committed Jan 26, 2016
1 parent 5df2501 commit c802802
Show file tree
Hide file tree
Showing 2 changed files with 233 additions and 0 deletions.
75 changes: 75 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,77 @@
# ble
Bluetooth LE related programs

- bledevice.py : basic class module for BLE devices
- blecomm.py : test program for communicating with an HM-10 BLE module
- blebulb.py : control program for Zengge BLE bulb
- yeelight.py : control program for Yeelight bedside lamp
- beacon : iBeacon and Google Eddystone related programs

To use these programs, you have to install bluez and python pexpect module.

The [bluez](http://www.elinux.org/RPi_Bluetooth_LE) (Bluetooth stack for linux) package can be installed by executing the following command:
````
sudo apt-get install bluetooth blueman bluez python-gobject python-gobject-2
````

The [pexpect](http://pexpect.readthedocs.org/en/stable/) module can be installed as follows:
````
sudo pip install pexpect
````

# BLE bulb Protocols
##[Zengge Bluetooth LED](http://www.enledcontroller.com/picture/show/164.aspx)
<a id="Zengge BLE Protocol"></a>
<table>
<tr>
<th scope="col">기능</th><th scope="col">명령</th><th scope="col">특성 (핸들)</th><th scope="col">데이터</th>
</tr>
<tr>
<td>전원</td><td>쓰기</td><td>0xffe9 (0x43)</td>
<td>STX(cc) : 0x24 : ETX(33)</br>예) 켜기 : 0xcc2333, 끄기: 0xcc2433</td>
</tr>
<tr>
<td>RGB 등</td><td>쓰기</td><td>0xffe9 (0x43)</td>
<td>STX(56) : R : G : B : 00 : f0 : ETX(aa)</br>예) 빨강 : 0x56ff000000f0aa</br>노랑 : 0x56ffff0000f0aa, 파랑: 0x560000ff00f0aa</td>
</tr>
<tr>
<td>Warm 등</td><td>쓰기</td><td>0xffe9 (0x43)</td>
<td>STX(56) : 00 00 00 : 밝기 : 0f : ETX(aa)</br>예) 0x56000000ff0faa</td>
</tr>
<tr>
<td>모드</td><td>쓰기</td><td>0xffe9 (0x43)</td>
<td>STX(bb) : 모드(25-38) : 속도(01-FF) : ETX(44)</br>예) 7가지 색으로 변화(모드=0x25) : 0xbb250344</td>
</tr>
<tr>
<td>상태 획득</td><td>쓰기 및 읽기</td><td>0xffe9 (0x43)</br>0xffe4 (0x50)</td>
<td>STX(ef) : 01 : ETX(77) = 0xef0177</br>반환: STX(66) 15 전원 모드 20 속도 R G B 밝기 06 ETX(99)</br>66 15 23 41 20 00 ff ff ff 00 06 99</br>66 15 23 25 20 05 ff ff ff 00 06 99 모드 (0x25)</br>66 15 23 41 20 00 00 00 00 ff 06 99 Warm </td>
</tr>
</table>

##[Yeelight Bedside Lamp](http://item.mi.com/1152300006.html)
<a id="Yeelight BLE Protocol"></a>
<table>
<tr>
<th scope="col">기능</th><th scope="col">명령</th><th scope="col">특성 (핸들)</th><th scope="col">데이터</th>
</tr>
<tr>
<td>인증</td><td>쓰기 및 읽기</td><td>0xaa7d3f34 (0x12)</td>
<td>STX(43) : CMD(0x67) : ON(0x02) : ETX(00)\*15 - 총 18B</br>반환: STX(43) : CMD(0x63) : ON(0x02) : ETX(00)</td>
</tr>
<tr>
<td>전원</td><td>쓰기</td><td>0xaa7d3f34 (0x12)</td>
<td>STX(43) : CMD(0x40) : ON(0x01)|OFF(0x02) : ETX(00)\*15 - 총 18B</br>예) 켜기 : 0x434001000000000000000000000000000000</br>끄기: 0x434002000000000000000000000000000000</td>
</tr>
<tr>
<td>RGB 등</td><td>쓰기</td><td>0xaa7d3f34 (0x12)</td>
<td>STX(43) : CMD(0x41) : R : G : B : 00 : 65 : ETX(00)\*11</br>예) 빨강 : 0x4341ff000000650000000000000000000000</td>
</tr>
<tr>
<td>Warm 등</td><td>쓰기</td><td>0xaa7d3f34 (0x12)</td>
<td>STX(43) : CMD(0x43) ; 색(2B, 1700~6500) : 65 : ETX(00)\*13</br>예) 0x43430400650000000000000000000000</td>
</tr>
<tr>
<td>밝기</td><td>쓰기</td><td>0xaa7d3f34 (0x12)</td>
<td>STX(43) : CMD(0x42) : 밝기 : ETX(00)*15</br>밝기 범위는 1 ~ 100</br>예) 0x434263000000000000000000000000000000</td>
</tr>
</table>
158 changes: 158 additions & 0 deletions yeelight.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
from Tkinter import *
from tkColorChooser import askcolor
import colorsys
import math, sys, time
from bledevice import scanble, BLEDevice

bulb = None
WRITE_CHAR_UUID = "aa7d3f34" #-2d4f-41e0-807f-52fbf8cf7443"

COMMAND_STX = "43"
COMMAND_ETX = "00"

AUTH_CMD = "67"
AUTH_ON = "02"

POWER_CMD = "40"
POWER_ON = "01"
POWER_OFF = "02"

COLOR_CMD = "41"
RGB_MODE = "65"

BRIGHT_CMD = "42"

COLORTEMP_CMD = "43"
TEMP_MODE = "65"

COLORFLOW_CMD = "4a"

class ConnectPanel(Frame):
def __init__(self, app):
Frame.__init__(self, app)
self.scanb = Button(self, text="Scan", command=self.scan)
self.bl = StringVar()
self.bles = OptionMenu(self, self.bl, ())
self.connb = Button(self, text="Connect", command=self.connect)

self.scanb.pack(side=LEFT)
self.bles.pack(side=LEFT)
self.connb.pack(side=RIGHT)

def scan(self):
bllist = scanble(timeout=2)
print bllist
if len(bllist) != 0:
self.bl.set(bllist[0]['addr'])
menu = self.bles['menu']
menu.delete(0, 'end')
for bl in bllist:
menu.add_command(label=bl, command=lambda v=bl: self.bl.set(v['addr']))

def connect(self):
global bulb
bulb = BLEDevice(self.bl.get())
time.sleep(0.1)
bulb.writereq(bulb.getvaluehandle(WRITE_CHAR_UUID), COMMAND_STX+AUTH_CMD+AUTH_ON+COMMAND_ETX*15)

class PowerPanel(Frame):
def __init__(self, app):
Frame.__init__(self, app)
self.powerl = Label(self, text="Power")
self.onb = Button(self, text="On", command=self.poweron)
self.offb = Button(self, text="Off", command=self.poweroff)

self.powerl.pack(side=LEFT)
self.offb.pack(side=RIGHT)
self.onb.pack(side=RIGHT)

def poweron(self):
global bulb
bulb.writecmd(bulb.getvaluehandle(WRITE_CHAR_UUID), COMMAND_STX+POWER_CMD+POWER_ON+COMMAND_ETX*15)

def poweroff(self):
global bulb
bulb.writecmd(bulb.getvaluehandle(WRITE_CHAR_UUID), COMMAND_STX+POWER_CMD+POWER_OFF+COMMAND_ETX*15)

class RgbPanel(Frame):
def __init__(self, app):
Frame.__init__(self, app)
self.rgbl = Label(self, text="RGB")
self.color = ((255, 255, 255), '#ffffff')
self.selectb = Button(self, text="Select", command=self.getcolor)
self.coll = Label(self, text=" ", bg="#FFFFFF")
self.setb = Button(self, text="Set", command=self.setrgb)

self.rgbl.pack(side=LEFT)
self.setb.pack(side=RIGHT)
self.coll.pack(side=RIGHT)
self.selectb.pack(side=RIGHT)

def getcolor(self):
self.color = askcolor()
print "color is ", self.color
self.coll.configure(bg=self.color[1])

def setrgb(self):
global bulb
bulb.writecmd(bulb.getvaluehandle(WRITE_CHAR_UUID), COMMAND_STX+COLOR_CMD+self.color[1][1:]+"00"+RGB_MODE+COMMAND_ETX*11)

class BrightnessPanel(Frame):
def __init__(self, app):
Frame.__init__(self, app)
self.brightl = Label(self, text="Brightness")
self.value = DoubleVar()
self.value.set(1.0)
self.scale = Scale(self, variable=self.value, from_=0.0, to=1.0, resolution=0.01, orient=HORIZONTAL)
self.setb = Button(self, text="Set", command=self.setvalue)

self.brightl.pack(side=LEFT)
self.setb.pack(side=RIGHT)
self.scale.pack(side=RIGHT)

def setvalue(self):
global bulb
bulb.writecmd(bulb.getvaluehandle(WRITE_CHAR_UUID), COMMAND_STX+BRIGHT_CMD+("%02x"%(self.value.get()*100))+COMMAND_ETX*15)

class WarmPanel(Frame):
def __init__(self, app):
Frame.__init__(self, app)
self.warml = Label(self, text="Warm")
self.color = DoubleVar()
self.color.set(1.0)
self.scale = Scale(self, variable=self.color, from_=0.0, to=1.0, resolution=0.01, command=self.changecolor, orient=HORIZONTAL)
self.setb = Button(self, text="Set", command=self.setwarm)

self.warml.pack(side=LEFT)
self.setb.pack(side=RIGHT)
self.scale.pack(side=RIGHT)

def changecolor(self, v):
value = self.color.get()*255
color = "#FFFF%02x" % (value)
self.scale.configure(bg=color)

def setwarm(self):
global bulb
bulb.writecmd(bulb.getvaluehandle(WRITE_CHAR_UUID), COMMAND_STX+COLORTEMP_CMD+("%04x"%(1700+self.color.get()*4800))+TEMP_MODE+COMMAND_ETX*13)

if __name__ == "__main__":
tk = Tk()
tk.title("Yeelight Bedside Lamp")

connectp = ConnectPanel(tk)
connectp.pack()
powerp = PowerPanel(tk)
powerp.pack(fill="both")
rgbp = RgbPanel(tk)
rgbp.pack(fill="both")
brightp = BrightnessPanel(tk)
brightp.pack(fill="both")
warmp = WarmPanel(tk)
warmp.pack(fill="both")

def shutdown():
tk.destroy()

tk.protocol("WM_DELETE_WINDOW", shutdown)
tk.mainloop()

0 comments on commit c802802

Please sign in to comment.