diff --git a/.gitignore b/.gitignore index 29efabc..637a4cc 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,6 @@ dist build eggs parts -bin var sdist develop-eggs diff --git a/CHANGES.txt b/CHANGES.txt new file mode 100644 index 0000000..500b6a5 --- /dev/null +++ b/CHANGES.txt @@ -0,0 +1 @@ +v0.1.0, 2013-03-27 -- Initial release. \ No newline at end of file diff --git a/LICENSE b/LICENSE.txt similarity index 100% rename from LICENSE rename to LICENSE.txt diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..9203697 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,2 @@ +include *.txt +recursive-include docs *.txt \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 6fe9469..0000000 --- a/README.md +++ /dev/null @@ -1,84 +0,0 @@ -BlinkStick Python -================= - -BlinkStick Python interface to control devices connected to the computer. - -What is BlinkStick? Check it out here: - -http://www.blinkstick.com - -Requirements ------------- - -* Python -* PyUSB -* grapefruit - package for color manipulations -* pyusb - package to access USB devices -* psutil - only for example-cpu.py -* websocket-client - only for example-connect.py to connect to BlinkStick.com - -Installation ------------- - -Install all required packages with pip: - -```sh -[sudo] pip install grapefruit pyusb psutil websocket-client -``` - -If websocket-client fails to install, please make sure you run the following command: - -```sh -sudo apt-get install python-dev -``` - -Replace _python-dev_ with _python2.7-dev_ if you are installing on Raspberry Pi. - -Description ------------ - -Description of files: - -* blinkstick.py - main BlinkStick class definition -* example-info.py - displays information of each BlinkStick -* example-infoblock.py - read/write info block sample -* example-off.py - turn all blinksticks off -* example-random.py - set random color to all BlinkSticks -* example-cpu.py - displays CPU usage with a BlinkStick (transitions from green as 0% to red as 100%) -* example-connect.py - sample code to connect to BlinkStick.com and control it remotely - -Running examples: - -```sh -python example-info.py -``` - -Permission problems -------------------- - -If the script returns with an error - -```sh -Access denied (insufficient permissions) -``` - -You can either run the script with sudo, for example: - -```sh -sudo python example-info.py -``` - -Or you can add a udev rule to allow any user to access the device without root permissions with this single command: - -```sh -echo "SUBSYSTEM==\"usb\", ATTR{idVendor}==\"20a0\", ATTR{idProduct}==\"41e5\", MODE:=\"0666\"" | sudo tee /etc/udev/rules.d/85-blinkstick.rules -``` - -Reboot computer after you have added the command and all users will have permissions to access the device without the need of root permissions. - -Maintainers ------------- - -* Arvydas Juskevicius - http://twitter.com/arvydev -* Rob Berwick - http://twitter.com/robberwick - diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..55fcc0f --- /dev/null +++ b/README.rst @@ -0,0 +1,92 @@ +BlinkStick Python +================= + +BlinkStick Python interface to control devices connected to the +computer. + +What is BlinkStick? Check it out here: + +http://www.blinkstick.com + +Requirements +------------ + +- Python +- PyUSB +- grapefruit - package for color manipulations +- pyusb - package to access USB devices +- psutil - only for example-cpu.py +- websocket-client - only for example-connect.py to connect to + BlinkStick.com + +Installation +------------ + +Install all required packages with pip: + +:: + + [sudo] pip install grapefruit pyusb psutil websocket-client + +If websocket-client fails to install, please make sure you run the +following command: + +:: + + sudo apt-get install python-dev + +Replace *python-dev* with *python2.7-dev* if you are installing on +Raspberry Pi. + +Description +----------- + +Description of files: + +- blinkstick.py - main BlinkStick class definition +- example-info.py - displays information of each BlinkStick +- example-infoblock.py - read/write info block sample +- example-off.py - turn all blinksticks off +- example-random.py - set random color to all BlinkSticks +- example-cpu.py - displays CPU usage with a BlinkStick (transitions + from green as 0% to red as 100%) +- example-connect.py - sample code to connect to BlinkStick.com and + control it remotely + +Running examples: + +:: + + python example-info.py + +Permission problems +------------------- + +If the script returns with an error + +:: + + Access denied (insufficient permissions) + +You can either run the script with sudo, for example: + +:: + + sudo python example-info.py + +Or you can add a udev rule to allow any user to access the device +without root permissions with this single command: + +:: + + echo "SUBSYSTEM==\"usb\", ATTR{idVendor}==\"20a0\", ATTR{idProduct}==\"41e5\", MODE:=\"0666\"" | sudo tee /etc/udev/rules.d/85-blinkstick.rules + +Reboot computer after you have added the command and all users will have +permissions to access the device without the need of root permissions. + +Maintainers +----------- + +- Arvydas Juskevicius - http://twitter.com/arvydev +- Rob Berwick - http://twitter.com/robberwick + diff --git a/bin/blinkstick-connect.py b/bin/blinkstick-connect.py new file mode 100644 index 0000000..cd3cf47 --- /dev/null +++ b/bin/blinkstick-connect.py @@ -0,0 +1,111 @@ +import websocket +import json +import sys +from blinkstick import blinkstick + +print "Connect to BlinkStick.com and control BlinkStick remotely" +print "(c) Agile Innovative Ltd" +print "" + +if len(sys.argv) > 1: + access_code = sys.argv[1] +else: + print "Usage:" + print " [sudo] python example-connect.py \"AccessCode\"" + print "" + print "You can obtain the AccessCode parameter from the device information page on BlinkStick.com" + sys.exit() + +bstick = blinkstick.find_first() + +if bstick is None: + sys.exit("BlinkStick not found...") + + +def HTMLColorToRGB(colorstring): + """ convert #RRGGBB to an (R, G, B) tuple """ + colorstring = colorstring.strip() + if colorstring[0] == '#': colorstring = colorstring[1:] + if len(colorstring) != 6: + raise ValueError, "input #%s is not in #RRGGBB format" % colorstring + r, g, b = colorstring[:2], colorstring[2:4], colorstring[4:] + r, g, b = [int(n, 16) for n in (r, g, b)] + return (r, g, b) + + +def on_message(ws, message): + global client_id + global access_code + global bstick + + #Uncomment this for debugging purposes + #print message + + m = json.loads(message) + + if m[0]['channel'] == '/meta/connect': + ws.send(json.dumps( + {'channel': '/meta/connect', + 'clientId': client_id, + 'connectionType': 'websocket'})) + return + + elif m[0]['channel'] == '/meta/handshake': + client_id = m[0]['clientId'] + + print "Acquired clientId: " + client_id + + ws.send(json.dumps( + {'channel': '/meta/subscribe', + 'clientId': client_id, + 'subscription': '/devices/' + access_code})) + return + + elif m[0]['channel'] == '/devices/' + access_code: + if 'color' in m[0]["data"]: + print "Received color: " + m[0]["data"]["color"] + + (r, g, b) = HTMLColorToRGB(m[0]["data"]["color"]) + bstick.set_color(r, g, b) + elif 'status' in m[0]["data"] and m[0]["data"]['status'] == "off": + print "Turn off" + bstick.turn_off() + + elif m[0]['channel'] == '/meta/subscribe': + if m[0]['successful']: + print "Subscribed to device. Waiting for color message..." + else: + print "Subscription to the device failed. Please check the access_code value in the file." + + #Reconnect again and wait for further messages + ws.send(json.dumps( + {'channel': '/meta/connect', + 'clientId': client_id, + 'connectionType': 'websocket'})) + + +def on_error(ws, error): + print error + + +def on_close(ws): + print "### closed ###" + + +def on_open(ws): + ws.send(json.dumps( + {'channel': '/meta/handshake', + 'version': '1.0', + 'supportedConnectionTypes': ['long-polling', 'websocket']})) + + +if __name__ == "__main__": + # Set this to True for debugging purposes + websocket.enableTrace(False) + ws = websocket.WebSocketApp("ws://live.blinkstick.com:9292/faye", + on_message=on_message, + on_error=on_error, + on_close=on_close) + ws.on_open = on_open + + ws.run_forever() diff --git a/bin/blinkstick-cpu.py b/bin/blinkstick-cpu.py new file mode 100644 index 0000000..cd09aa3 --- /dev/null +++ b/bin/blinkstick-cpu.py @@ -0,0 +1,22 @@ +#!/usr/bin/python + +from blinkstick import blinkstick +import psutil + +print "Display CPU usage with BlinkStick" +print "(c) Agile Innovative Ltd" +print "" + +bstick = blinkstick.find_first() + +if bstick is None: + print "No BlinkSticks found..." +else: + print "Displaying CPU usage (Green = 0%, Amber = 50%, Red = 100%)" + print "Press Ctrl+C to exit" + + while True: + cpu = psutil.cpu_percent(interval=1) + intensity = int(255 * cpu / 100) + + bstick.set_color(intensity, 255 - intensity, 0) diff --git a/bin/blinkstick-find.py b/bin/blinkstick-find.py new file mode 100644 index 0000000..8b96707 --- /dev/null +++ b/bin/blinkstick-find.py @@ -0,0 +1,14 @@ +#!/usr/bin/python + +from blinkstick import blinkstick + +print "Find BlinkStick by serial number" +print "(c) Agile Innovative Ltd" +print "" + +bstick = blinkstick.find_by_serial("BS000001-1.0") + +if bstick is None: + print "Not found..." +else: + print "BlinkStick found. Current color: " + bstick.get_color_string() diff --git a/bin/blinkstick-info.py b/bin/blinkstick-info.py new file mode 100644 index 0000000..dc9a997 --- /dev/null +++ b/bin/blinkstick-info.py @@ -0,0 +1,16 @@ +#!/usr/bin/python + +from blinkstick import blinkstick + +print "Display BlinkStick info" +print "(c) Agile Innovative Ltd" +print "" + +for bstick in blinkstick.find_all(): + print "Found device:" + print " Manufacturer: " + bstick.get_manufacturer() + print " Description: " + bstick.get_description() + print " Serial: " + bstick.get_serial() + print " Current Color: " + bstick.get_color_string() + print " Info Block 1: " + bstick.get_info_block1() + print " Info Block 2: " + bstick.get_info_block2() diff --git a/bin/blinkstick-infoblock.py b/bin/blinkstick-infoblock.py new file mode 100644 index 0000000..d1cd952 --- /dev/null +++ b/bin/blinkstick-infoblock.py @@ -0,0 +1,15 @@ +#!/usr/bin/python + +from blinkstick import blinkstick + +print "Display BlinkStick Name (InfoBlock1)" +print "(c) Agile Innovative Ltd" +print "" + +bstick = blinkstick.find_first() +bstick.set_info_block1("Kitchen BlinkStick") +print bstick.get_info_block1() + +# set and get device info-block2 here +#bstick.set_info_block2("info-block-2data") +#print bstick.get_info_block2() diff --git a/bin/blinkstick-off.py b/bin/blinkstick-off.py new file mode 100644 index 0000000..0a2377c --- /dev/null +++ b/bin/blinkstick-off.py @@ -0,0 +1,11 @@ +#!/usr/bin/python + +from blinkstick import blinkstick + +print "Turn BlinkSticks off" +print "(c) Agile Innovative Ltd" +print "" + +for bstick in blinkstick.find_all(): + bstick.turn_off() + print bstick.get_serial() + " turned off" diff --git a/bin/blinkstick-random.py b/bin/blinkstick-random.py new file mode 100644 index 0000000..4968720 --- /dev/null +++ b/bin/blinkstick-random.py @@ -0,0 +1,11 @@ +#!/usr/bin/python + +from blinkstick import blinkstick + +print "Set random BlinkStick color" +print "(c) Agile Innovative Ltd" +print "" + +for bstick in blinkstick.find_all(): + bstick.set_random_color() + print bstick.get_serial() + " " + bstick.get_color_string() diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..6d7ce27 --- /dev/null +++ b/setup.py @@ -0,0 +1,24 @@ +from distutils.core import setup + +setup( + name='BlinkStick', + version='0.1.0', + author='Arvydas Juskevicius', + author_email='arvydas@arvydas.co.uk', + packages=['blinkstick'], + scripts=["bin/blinkstick-connect.py", + "bin/blinkstick-cpu.py", + "bin/blinkstick-find.py", + "bin/blinkstick-info.py", + "bin/blinkstick-infoblock.py", + "bin/blinkstick-off.py", + "bin/blinkstick-random.py"], + url='http://pypi.python.org/pypi/BlinkStick/', + license='LICENSE.txt', + description='Python package to control BlinkStick USB devices.', + long_description=open('README.rst').read(), + install_requires=[ + "grapefruit", + "pyusb" + ], + ) \ No newline at end of file