From d8669c91d1cbc365f3c76369a4046602f0ed195a Mon Sep 17 00:00:00 2001 From: ewall Date: Thu, 2 Sep 2010 12:47:36 -0400 Subject: [PATCH] reorg, rename, refactor --- .gitignore | 3 +- contrib/usbenum.py | 40 ++++++ my_pybuddy.py | 204 --------------------------- pybuddylib.py | 246 +++++++++++++++++++++++++++++++++ pybuddy.cfg => src/pybuddy.cfg | 0 5 files changed, 288 insertions(+), 205 deletions(-) create mode 100644 contrib/usbenum.py delete mode 100644 my_pybuddy.py create mode 100644 pybuddylib.py rename pybuddy.cfg => src/pybuddy.cfg (100%) diff --git a/.gitignore b/.gitignore index a9dcfce..f14629a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .svn/ -*.pyc \ No newline at end of file +*.pyc +contrib/usbenum.txt \ No newline at end of file diff --git a/contrib/usbenum.py b/contrib/usbenum.py new file mode 100644 index 0000000..d4403ed --- /dev/null +++ b/contrib/usbenum.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# +# usbenum.py: enumerate usb devices using pyusb module +# from http://wiki.erazor-zone.de/wiki:projects:python:pyusb:setup:examples:usbenum +# copyright 2005 Wander Lairson Costa + +import usb + +busses = usb.busses() + +for bus in busses: + devices = bus.devices + for dev in devices: + print "Device:", dev.filename + print " Device class:",dev.deviceClass + print " Device sub class:",dev.deviceSubClass + print " Device protocol:",dev.deviceProtocol + print " Max packet size:",dev.maxPacketSize + print " idVendor:",dev.idVendor + print " idProduct:",dev.idProduct + print " Device Version:",dev.deviceVersion + for config in dev.configurations: + print " Configuration:", config.value + print " Total length:", config.totalLength + print " selfPowered:", config.selfPowered + print " remoteWakeup:", config.remoteWakeup + print " maxPower:", config.maxPower + for intf in config.interfaces: + print " Interface:",intf[0].interfaceNumber + for alt in intf: + print " Alternate Setting:",alt.alternateSetting + print " Interface class:",alt.interfaceClass + print " Interface sub class:",alt.interfaceSubClass + print " Interface protocol:",alt.interfaceProtocol + for ep in alt.endpoints: + print " Endpoint:",hex(ep.address) + print " Type:",ep.type + print " Max packet size:",ep.maxPacketSize + print " Interval:",ep.interval + diff --git a/my_pybuddy.py b/my_pybuddy.py deleted file mode 100644 index 6e1a3a7..0000000 --- a/my_pybuddy.py +++ /dev/null @@ -1,204 +0,0 @@ -import usb -import time -import sys -from time import sleep - -## configuration -tsleep = 0.5 -usbvendor = 0x1130 -usbproduct = 0001 - -## iBUDDY class -class BuddyDevice: - SETUP = (0x22, 0x09, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00) - MESS = (0x55, 0x53, 0x42, 0x43, 0x00, 0x40, 0x02) - - LEFT = 0 - RIGHT = 1 - - UP = 0 - DOWN = 1 - - finalMess = 0xFF - battery = 0 - product = 0 - - def __init__(self, battery, buddy_product): - try: - self.dev=UsbDevice(usbvendor, buddy_product, battery) - self.dev.open() - self.dev.handle.reset() - self.resetMessage() - self.pumpMessage() - self.battery=battery - self.product=buddy_product - except NoBuddyException, e: - raise NoBuddyException() - -# commands are sent as disabled bits - def setReverseBitValue(self,num,value): - if (value==1): - temp = 0xFF - (1<> num - res = not(temp&1) - return res - - def setHeadColor(self, red, green, blue): - self.setReverseBitValue(4,red) - self.setReverseBitValue(5,green) - self.setReverseBitValue(6,blue) - - def setHeart(self, status): - self.setReverseBitValue(7,status) - - def pumpMessage(self): - self.send(self.finalMess) - - def resetMessage(self): - self.finalMess = 0xFF - - def flick(self, direction): - if (direction == self.RIGHT): - self.setReverseBitValue(1,1) - self.setReverseBitValue(0,0) - elif(direction == self.LEFT): - self.setReverseBitValue(1,0) - self.setReverseBitValue(0,1) - - def wing(self, direction): - if (direction == self.UP): - self.setReverseBitValue(3,1) - self.setReverseBitValue(2,0) - elif(direction == self.DOWN): - self.setReverseBitValue(3,0) - self.setReverseBitValue(2,1) - - def getColors (self): - return self.getReverseBitValue(4), self.getReverseBitValue(5), self.getReverseBitValue(6) - - def getHeart(self): - return self.getReverseBitValue(7) - - def getWing(self): - return self.getReverseBitValue(2) - - def getDirection(self): - return self.getReverseBitValue(1) - - def send(self, inp): - try: - self.dev.handle.controlMsg(0x21, 0x09, self.SETUP, 0x02, 0x01) - self.dev.handle.controlMsg(0x21, 0x09, self.MESS+(inp,), 0x02, 0x01) - except usb.USBError: - print "USB error!" - self.__init__(self.battery,buddy_product) - - #self.dev.handle.controlMsg(0x21, 0x09, self.SETUP, 0x02, 0x01) - #self.dev.handle.controlMsg(0x22, 0x09, self.SETUP, 0x02, 0x01) - #self.dev.handle.controlMsg(0x21, 0x09, self.MESS+(inp,), 0x02, 0x01) - -## USB class -class UsbDevice: - def __init__(self, vendor_id, product_id, skip): - busses = usb.busses() - self.handle = None - count = 0 - for bus in busses: - devices = bus.devices - for dev in devices: - - if dev.idVendor==vendor_id and dev.idProduct==product_id: - if count==skip: - print "iBuddy found! (vend: %s, prod: %s)" % (dev.idVendor, dev.idProduct) - self.dev = dev - - self.conf = self.dev.configurations[0] - self.intf = self.conf.interfaces[0][0] - self.endpoints = [] - for endpoint in self.intf.endpoints: - self.endpoints.append(endpoint) - print "(found endpoint)" - return - else: - count=count+1 - raise NoBuddyException() - - def open(self): - if self.handle: - self.handle = None - self.handle = self.dev.open() - # we need to detach HID interface - try: - self.handle.detachKernelDriver(0) - self.handle.detachKernelDriver(1) - except: - pass - - self.handle.setConfiguration(self.conf) - self.handle.claimInterface(self.intf) - self.handle.setAltInterface(self.intf) - -class NoBuddyException(Exception): pass - -####################################### -# MAIN program -####################################### - -# initialize device -print "Starting search..." -try: - buddy=BuddyDevice(0, int(usbproduct)) -except NoBuddyException, e: - print "No iBuddy device found!" - sys.exit(1) - -buddy.resetMessage() -buddy.pumpMessage() -sleep(0.5) -buddy.setHeadColor(1,0,0) -buddy.pumpMessage() -sleep(0.5) -buddy.setHeadColor(0,1,0) -buddy.pumpMessage() -sleep(0.5) -buddy.setHeadColor(0,0,1) -buddy.pumpMessage() -sleep(0.5) -buddy.flick(BuddyDevice.LEFT) -buddy.pumpMessage() -sleep(0.5) -buddy.flick(BuddyDevice.RIGHT) -buddy.pumpMessage() -sleep(0.5) -buddy.flick(BuddyDevice.LEFT) -buddy.pumpMessage() -sleep(0.5) -buddy.flick(BuddyDevice.RIGHT) -buddy.pumpMessage() -sleep(0.1) -buddy.wing(BuddyDevice.UP) -buddy.pumpMessage() -sleep(0.1) -buddy.wing(BuddyDevice.DOWN) -buddy.pumpMessage() -sleep(0.1) -buddy.wing(BuddyDevice.UP) -buddy.pumpMessage() -sleep(0.1) -buddy.wing(BuddyDevice.DOWN) -buddy.pumpMessage() -sleep(0.1) -buddy.wing(BuddyDevice.UP) -buddy.pumpMessage() -sleep(0.1) -buddy.wing(BuddyDevice.DOWN) -buddy.pumpMessage() -buddy.setHeadColor(0,0,0) -buddy.pumpMessage() diff --git a/pybuddylib.py b/pybuddylib.py new file mode 100644 index 0000000..5612929 --- /dev/null +++ b/pybuddylib.py @@ -0,0 +1,246 @@ +#!/usr/bin/env python +# +# pybuddylib.py: simple library to control iBuddy USB device +# by ewall , Sept 2010 +# +# borrows code from http://code.google.com/p/pybuddy +# by Jose.Carlos.Luna@gmail.com and luis.peralta@gmail.com +# who got most of the code from http://cuntography.com/blog/?p=17 +# which is based on http://scott.weston.id.au/software/pymissile/ + +import logging +from time import sleep +import usb + +### Global Configuration +DEBUG = True + +### Prepare Logging +log = logging.getLogger("pybuddy") +log.setLevel(logging.DEBUG) +console_handler = logging.StreamHandler() +if DEBUG: + console_handler.setLevel(logging.DEBUG) +else: + console_handler.setLevel(logging.ERROR) +log.addHandler(console_handler) + +### iBuddy Device Class +class iBuddyDevice: + USB_VENDOR = 0x1130 + USB_PRODUCT = int(0001) + BATTERY = 0 + SETUP = (0x22, 0x09, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00) + MESS = (0x55, 0x53, 0x42, 0x43, 0x00, 0x40, 0x02) + + WAITTIME = 0.1 + + LEFT = 0 + RIGHT = 1 + UP = 0 + DOWN = 1 + OFF = 0 + ON = 1 + + CLEAR = 0xFF + command = CLEAR + + # the following items deal with setup and control + + def __init__(self): + try: + self.dev=UsbDevice(self.USB_VENDOR, self.USB_PRODUCT, self.BATTERY) + self.dev.open() + self.dev.handle.reset() + self.resetCmd() + self.doCmd() + except NoBuddyException, e: + raise NoBuddyException() + + def __send(self, inp): + """ send your command to the device """ + try: + self.dev.handle.controlMsg(0x21, 0x09, self.SETUP, 0x02, 0x01) + self.dev.handle.controlMsg(0x21, 0x09, self.MESS+(inp,), 0x02, 0x01) + except usb.USBError: + if DEBUG: + raise + else: + self.__init__() + + def doCmd(self, seconds=WAITTIME): + """ send the command specified by the current command """ + self.__send(self.command) + sleep(seconds) + + # the following items operate on the command to be sent next + + def resetCmd(self): + """ reset command to default (must pump to take effect) """ + self.command = self.CLEAR + + def setReverseBitValue(self,num,value): + """ commands are sent as disabled bits """ + if (value==1): + temp = 0xFF - (1<> num + res = not(temp&1) + return res + + def setHeadColors(self, red, green, blue): + """ colors as (red, green, blue) can be on (1) or off (0) """ + self.setReverseBitValue(4,red) + self.setReverseBitValue(5,green) + self.setReverseBitValue(6,blue) + self.setReverseBitValue(2,1) + + def getHeadColors (self): + """ returns color status as tuple representing (red, green, blue) as on (1) or off (0) """ + return self.getReverseBitValue(4), self.getReverseBitValue(5), self.getReverseBitValue(6) + + def setHeart(self, status): + """ heart-light can be on (1) or off (0) """ + self.setReverseBitValue(7,status) + + def getHeart(self): + """ returns heart-light status of on (1) or off (0) """ + return self.getReverseBitValue(7) + + def setWing(self, direction): + """ move the wings iBuddyDevice.UP (0) or iBuddyDevice.DOWN (1) """ + if (direction == self.UP): + self.setReverseBitValue(3,1) + self.setReverseBitValue(2,0) + elif(direction == self.DOWN): + self.setReverseBitValue(3,0) + + def getWing(self): + """ returns wing status of iBuddyDevice.UP (0) or iBuddyDevice.DOWN (1) """ + return self.getReverseBitValue(2) + + def setSwivel(self, direction): + """ swivel the body iBuddyDevice.LEFT (0) or iBuddyDevice.RIGHT (1) """ + if (direction == self.RIGHT): + self.setReverseBitValue(1,1) + self.setReverseBitValue(0,0) + elif(direction == self.LEFT): + self.setReverseBitValue(1,0) + self.setReverseBitValue(0,1) + + def getSwivel(self): + """ returns current swivel direction as iBuddyDevice.LEFT (0) or iBuddyDevice.RIGHT (1) """ + return self.getReverseBitValue(1) + + # the following items are macros for specific behaviors + + def doReset(self, seconds=WAITTIME): + self.resetCmd() + self.doCmd(seconds) + + def doFlap(self, times=3, seconds=WAITTIME): + for i in range(times): + self.setWing(self.UP) + self.doCmd(seconds) + self.setWing(self.DOWN) + self.doCmd(seconds) + + def doWiggle(self, times=2, seconds=WAITTIME): + for i in range(times): + self.setSwivel(self.LEFT) + self.doCmd(seconds) + self.setSwivel(self.RIGHT) + self.doCmd(seconds) + + def doHeartbeat(self, times=3, seconds=WAITTIME): + for i in range(times): + self.setHeart(self.ON) + self.doCmd(seconds) + self.setHeart(self.OFF) + self.doCmd(seconds) + + # TODO: macros for specific colors + + +### General USB Device Class +class UsbDevice: + # TODO: improve on this device search + def __init__(self, vendor_id, product_id, skip): + busses = usb.busses() + self.handle = None + count = 0 + for bus in busses: + devices = bus.devices + for dev in devices: + + if dev.idVendor==vendor_id and dev.idProduct==product_id: + if count==skip: + log.info("iBuddy device found (vend: %s, prod: %s)." % (dev.idVendor, dev.idProduct)) + self.dev = dev + + self.conf = self.dev.configurations[0] + self.intf = self.conf.interfaces[0][0] + self.endpoints = [] + for endpoint in self.intf.endpoints: + self.endpoints.append(endpoint) + log.info("Endpoint found.") + return + else: + count=count+1 + raise NoBuddyException() + + def open(self): + # TODO: should the HID driver detachment be optional? + self.handle = self.dev.open() + + # we need to detach HID interface + try: + self.handle.detachKernelDriver(0) + self.handle.detachKernelDriver(1) + except: + pass + + self.handle.setConfiguration(self.conf) + self.handle.claimInterface(self.intf) + self.handle.setAltInterface(self.intf) + +## Custom Exceptions +class NoBuddyException(usb.USBError): + """ indicates errors communicating with iBuddy USB device """ + #def __init__(self, *args): + # Exception._ _init_ _(self, *args) + # self.wrapped_exc = sys.exc_info() + pass + + +### Main Program +if __name__ == '__main__': + + log.info("Starting search...") + try: + buddy = iBuddyDevice() + except NoBuddyException, e: + log.exception("No iBuddy device found!") + sys.exit(1) + + # sample commands and macros + buddy.setHeadColors(1,0,0) + buddy.doCmd(1) + buddy.setHeadColors(0,1,0) + buddy.doCmd(1) + buddy.setHeadColors(0,0,1) + buddy.doCmd(1) + buddy.doFlap() + sleep(1) + buddy.doWiggle() + sleep(1) + buddy.doHeartbeat() + sleep(1) + buddy.doReset() diff --git a/pybuddy.cfg b/src/pybuddy.cfg similarity index 100% rename from pybuddy.cfg rename to src/pybuddy.cfg