Compare commits

...

10 Commits

19 changed files with 1166 additions and 678 deletions

5
.gitignore vendored
View File

@@ -1,2 +1,3 @@
.svn/ __pycache__
*.pyc venv
*.pyc

15
config.ini Normal file
View File

@@ -0,0 +1,15 @@
[remote]
host=localhost
port=8883
[local]
server=true
[server]
port=8883
[general]
implementation=local
[system]
product=1

View File

@@ -1,20 +0,0 @@
#!/bin/bash
# ibuddy access log client
# contributed by pablo muñoz-chapuli
#
HOST=nowhere.com
APACHE_LOG=/var/log/apache2/access.log
tail -f $APACHE_LOG | awk '
/ 200 / {
system("echo MACRO_GREEN|nc -u -q 0 $HOST 8888")
}
/ 404 / {
system("echo MACRO_RED|nc -u -q 0 $HOST 8888")
}
/ 500 / {
system("echo MACRO_BEAT2|nc -u -q 0 $HOST 8888")
}'

39
contrib/usbenum.py Normal file
View File

@@ -0,0 +1,39 @@
#!/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)

View File

@@ -1,37 +0,0 @@
#!/usr/bin/perl
use strict;
my $account='lala@lalalala.com';
my $log_path=' /var/log/httpd/combined_log';
use IO::Socket;
my $sock = IO::Socket::INET->new(PeerPort => 8888,
PeerAddr => "127.0.0.1",
Proto => "udp",
LocalAddr => 'localhost'
)
or die "Can't bind : $@\n";
open(LOG,"ssh $account tail -f $log_path |");
while(<LOG>) {
chomp;
if(/HTTP\/\d.\d\"\s200/) {
print "OK:$_\n";
$sock->send("MACRO_GREEN");
} elsif (/HTTP\/\d.\d\"\s404/) {
print "NOTFOUND:$_\n";
$sock->send("MACRO_RED");
} elsif (/HTTP\/\d.\d\"\s403/) {
print "FORBIDDEN:$_\n";
$sock->send("MACRO_RED");
} elsif(/HTTP\/\d.\d\"\s500/) {
print "ERROR:$_\n";
$sock->send("MACRO_BEAT");
} else {
print "RECVD:$_\n";
}
}

52
dx/manual.txt Normal file
View File

@@ -0,0 +1,52 @@
pybuddyDX by Peter D'Hoye
http://code.google.com/p/pybuddy-dx/
Follow these steps to get pybuddyDX up and running:
1) Install dependencies: python v2.3 or higher, python-usb:
2) Edit the pybuddy.cfg if required (change at least the username)
=> To launch the daemon:
$ sudo ./pybuddyDX.py
2010-01-16 01:58:00,216 INFO Searching e-buddy...
2010-01-16 01:58:00,668 INFO DX e-buddy found!
2010-01-16 01:58:01,282 INFO Starting daemon...
=> To test:
$ echo 00 | nc -q0 -u localhost 8888
Where you can replace the 00 with any number between 00 and 25. 17 turns all effects off.
Effects 18 to 25 last until turned off again, the others stop themselves.
Here's a quick list of the commands, a more complete description will follow later
GLADNESS = 00
FEAR = 01
FIZZ = 02
PLEASANTSURPRISE = 03
GRIEF = 04
FURY = 05
QUELL = 06
REDHEAD = 07
GREENHEAD = 08
BLUEHEAD = 09
YELLOWHEAD = 10
BLAME = 11
BLUEGREENHEAD = 12
WHITEHEAD = 13
HEART = 14
WINGS = 15
BODY = 16
NOEFFECT = 17
ONLINE = 18
BUSY = 19
DAZE = 20
BACKSOON = 21
AWAY = 22
PHONE = 23
LUNCH = 24
OFFLINE = 25

View File

@@ -6,9 +6,7 @@ port: 8888
[system] [system]
# user to setuid to after daemon is started # user to setuid to after daemon is started
user: nobody user: usernamehere
# usb product id (do a lspci to check)
usbproduct: 0001
# logging # logging
# loglevel: info/debug # loglevel: info/debug

250
dx/pybuddyDX.py Normal file
View File

@@ -0,0 +1,250 @@
#!/usr/bin/python
#
# pybuddyDX
# python e-buddy (ibuddy alike sold on DX) daemon
# http://code.google.com/p/pybuddyDX
#
# protocol reverse engineered and implemented by
# peter.dhoye@gmail.com
#
# 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 usb
import time
import sys
import socket
import os
import pwd
import logging
from ConfigParser import RawConfigParser
################
#Commands
################
# GLADNESS = 00
# FEAR = 01
# FIZZ = 02
# PLEASANTSURPRISE =03
# GRIEF = 04
# FURY = 05
# QUELL = 06
# REDHEAD = 07
# GREENHEAD = 08
# BLUEHEAD = 09
# YELLOWHEAD = 10
# BLAME = 11
# BLUEGREENHEAD = 12
# WHITEHEAD = 13
# HEART = 14
# WINGS = 15
# BODY = 16
# NOEFFECT = 17
# ONLINE = 18
# BUSY = 19
# DAZE = 20
# BACKSOON = 21
# AWAY = 22
# PHONE = 23
# LUNCH = 24
# OFFLINE = 25
################
#Configuration
################
tsleep = 0.1
################
# IBUDDY class
################
class BuddyDevice:
SETUP = (0x21, 0x09, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00)
MESS = (0x43, 0x4D)
OFF1 = 0x31
OFF2 = 0x37
code1 = OFF1
code2 = OFF2
def __init__(self):
try:
self.dev=UsbDevice(0x0c45, 0x11)
self.dev.open()
self.dev.handle.reset()
self.resetMessage()
except NoBuddyException, e:
raise NoBuddyException()
def resetMessage(self):
self.code1 = self.OFF1
self.code1 = self.OFF1
self.send()
def send(self):
try:
self.dev.handle.controlMsg(0x21, 0x09, self.SETUP, 0x0200, 0x00)
self.dev.handle.controlMsg(0x21, 0x09, self.MESS+(self.code1,self.code2), 0x0200, 0x00)
except usb.USBError:
log.info("Error sending USB command")
raise NoBuddyException()
#####################
# USB class
######################
class UsbDevice:
def __init__(self, vendor_id, product_id):
busses = usb.busses()
self.handle = None
for bus in busses:
devices = bus.devices
for dev in devices:
if dev.idVendor==vendor_id and dev.idProduct==product_id:
log.info("DX e-buddy found!")
# log.info("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 = []
# log.info("interface = %x, class = %s, protocol = %s", self.intf.interfaceNumber, self.intf.interfaceClass, self.intf.interfaceProtocol)
for endpoint in self.intf.endpoints:
self.endpoints.append(endpoint)
# log.info("endpoint number = %x, type = %s", endpoint.address, endpoint.type)
return
raise NoBuddyException()
def open(self):
if self.handle:
self.handle = None
self.handle = self.dev.open()
# if self.handle:
# log.info("Handle OK")
#We need to detach HID interface
try:
self.handle.detachKernelDriver(0)
self.handle.detachKernelDriver(1)
except:
pass
try:
self.handle.setConfiguration(self.conf)
self.handle.claimInterface(0)
self.handle.setAltInterface(0)
except:
log.info("Configuration failed")
raise NoBuddyException()
# log.info("Device opened OK")
class NoBuddyException(Exception): pass
#########################################
# Decoding macros
##########################################
def decode_buddy (buddy,msg):
# log.info("Received message: %s",msg)
buddy.code1 = int(msg)/10 + 0x30
buddy.code2 = int(msg) - (int(msg)/10)*10 + 0x30
# log.info("Codes: %x %x",buddy.code1,buddy.code2)
#######################################
# MAIN program
#######################################
log = logging.getLogger('pybuddy')
#Default config
config = RawConfigParser(
{ 'port': 8888,
'address': '127.0.0.1',
'user': 'nobody',
'loglevel': 'info',
'logfile': 'console',
}
)
config._sections = {'network':{}, 'system':{}}
config_files = [ "~/.pybuddy.cfg",
"/etc/pybuddy/pybuddy.cfg",
"/usr/local/etc/pybuddy.cfg"
]
#Parse config
if len(sys.argv) > 1:
config_files.append(sys.argv[1])
config_read = config.read(config_files)
if config.get("system", "logfile") != "console":
logging.basicConfig(
filename=config.get("system", "logfile"),
format='%(asctime)s %(levelname)-8s %(message)s',
)
else:
logging.basicConfig(
stream=sys.stderr,
format='%(asctime)s %(levelname)-8s %(message)s',
)
if config.get("system", "loglevel") == "debug":
log.setLevel(logging.DEBUG)
elif config.get("system", "loglevel") == "info":
log.setLevel(logging.INFO)
if config_read:
log.info("Read config file: %s", config_read[0])
#Initialize device
log.info("Searching e-buddy...")
try:
buddy=BuddyDevice()
except NoBuddyException, e:
log.error("Not found or ERROR!")
sys.exit(1)
#Daemonize
log.info("Starting daemon...")
if os.fork()==0:
os.setsid()
else:
sys.exit(0)
#Create server socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((config.get("network", "address"), int(config.get("network", "port"))))
#Drop privileges
try:
uid = pwd.getpwnam(config.get("system", "user"))[2]
except KeyError:
log.error("Username %s not found, exiting...", config.get("system", "user"))
sys.exit(1)
os.setuid(uid)
#Main message loop
while 1:
try:
message, address = s.recvfrom(8192)
# log.debug("Got data from %s", address)
decode_buddy(buddy, message)
buddy.send()
except (KeyboardInterrupt, SystemExit):
raise

27
dynamic.py Normal file
View File

@@ -0,0 +1,27 @@
import sys
import importlib
import configparser
from implementation import *
from implementation import ibuddy
# Read chosen implementation from config
try:
config = configparser.ConfigParser()
config.read('config.ini')
implementation = config.get('general', 'implementation')
except:
sys.exit('[error] Failed to read config file!')
# Load implementation
implementations = [subclass.__name__ for subclass in ibuddy.__subclasses__()]
try:
if implementation in implementations:
ibuddy = getattr(globals()[implementation], implementation)()
else:
raise
except:
sys.exit('[error] Failed to load implementation!')
# Fun!
ibuddy.test()

207
ibuddy.py Normal file
View File

@@ -0,0 +1,207 @@
#!/usr/bin/python
import usb.core
import usb.util
from time import sleep
class DeviceNotFoundException(Exception):
pass
class ibuddy:
USB_VENDOR = 0x1130
USB_PRODUCT = 1
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
BLUE = (0, 0, 1)
GREEN = (0, 1, 0)
LTBLUE = (0, 1, 1)
PURPLE = (1, 0, 1)
RED = (1, 0, 0)
WHITE = (1, 1, 1)
YELLOW = (1, 1, 0)
CLEAR = 0xff
finalMess = CLEAR
command = CLEAR
def __init__(self, product=None):
dev = usb.core.find(idVendor = self.USB_VENDOR, idProduct = self.USB_PRODUCT)
if dev is None:
raise DeviceNotFoundException()
self.dev = dev
def __send(self, inp):
""" send your command to the device """
try:
self.dev.ctrl_transfer(0x21, 0x09, 0x02, 1, self.SETUP)
self.dev.ctrl_transfer(0x21, 0x09, 0x02, 1, self.MESS + (inp, ))
except usb.USBError as e:
print(e)
self.__init__()
def pumpMessage(self):
self.send(self.finalMess)
def resetMessage(self):
self.finalMess = self.CLEAR
def doCmd(self, seconds=WAITTIME):
""" send the command specified by the current command """
self.__send(self.command)
sleep(seconds)
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)
self.command = self.command & temp
elif value == 0:
temp = 1 << num
self.command = self.command | temp
def getReverseBitValue(self, num):
""" what was that bit set to again? """
temp = self.command
temp = temp >> num
res = not temp & 1
return res
def setHeart(self, status):
""" heart-light can be on (1) or off (0) """
self.setReverseBitValue(7, status)
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(0x02, 0)
elif direction == self.DOWN:
self.setReverseBitValue(3, 0)
self.setReverseBitValue(0x02, 1)
def getColors(self):
return (self.getReverseBitValue(4), self.getReverseBitValue(5),
self.getReverseBitValue(6))
def getHeart(self):
""" returns heart-light status of on (1) or off (0) """
return self.getReverseBitValue(7)
def getWing(self):
""" returns wing status of BuddyDevice.UP (0) or BuddyDevice.DOWN (1) """
return self.getReverseBitValue(0x02)
def getDirection(self):
return self.getReverseBitValue(1)
def send(self, inp):
try:
self.dev.ctrl_transfer(0x21, 0x09, 0x02, 1, self.SETUP)
self.dev.handle.controlMsg(0x21, 0x09, 0x02, 1, self.MESS + inp)
except usb.USBError:
self.__init__(self.battery, self.product)
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)
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 BuddyDevice.UP (0) or BuddyDevice.DOWN (1) """
if direction == self.UP:
self.setReverseBitValue(3, 1)
self.setReverseBitValue(0x02, 0)
elif direction == self.DOWN:
self.setReverseBitValue(3, 0)
self.setReverseBitValue(0x02, 1)
def getWing(self):
""" returns wing status of BuddyDevice.UP (0) or BuddyDevice.DOWN (1) """
return self.getReverseBitValue(0x02)
def setSwivel(self, direction):
""" swivel the body BuddyDevice.LEFT (0) or BuddyDevice.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 BuddyDevice.LEFT (0) or BuddyDevice.RIGHT (1) """
return self.getReverseBitValue(1)
def doReset(self, seconds=WAITTIME):
""" reset to default positions/off, run command immediately """
self.resetCmd()
self.doCmd(seconds)
def doFlap(self, times=3, seconds=0.2):
""" flap wings X times with Y seconds pause in between, run command immediately """
for i in range(times):
self.setWing(self.UP)
self.doCmd(seconds)
self.setWing(self.DOWN)
self.doCmd(seconds)
def doWiggle(self, times=3, seconds=0.2):
""" wiggle back and forth X times with Y seconds pauses, run command immediately """
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=0.3):
""" blink heart X times with Y seconds' pause in betwee, run command immediately """
for i in range(times):
self.setHeart(self.ON)
self.doCmd(seconds)
self.setHeart(self.Off)
self.doCmd(seconds)
def doColorRGB(self, r, g, b, seconds=WAITTIME):
""" set head color by red/green/blue values 0 or 1, run command immediately """
self.setHeadColors(r, g, b)
self.doCmd(seconds)
def doColorName(self, rgb, seconds=WAITTIME):
""" set head color with color name tuples, run command immediately """
self.setHeadColors(*rgb)
self.doCmd(seconds)

View File

@@ -0,0 +1,13 @@
import os
import glob
import abc
modules = glob.glob(os.path.dirname(__file__) + '/*.py')
__all__ = [os.path.basename(f)[:-3] for f in modules]
class ibuddy:
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def test(self):
return

5
implementation/local.py Normal file
View File

@@ -0,0 +1,5 @@
from . import ibuddy
class local(ibuddy):
def test(self):
print('test local')

5
implementation/remote.py Normal file
View File

@@ -0,0 +1,5 @@
from . import ibuddy
class remote(ibuddy):
def test(self):
print('test remote')

View File

@@ -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)
self.finalMess = self.finalMess & temp
elif (value==0):
temp = 1 << num
self.finalMess = self.finalMess | temp
def getReverseBitValue(self,num):
temp = self.finalMess
temp = temp >> 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()

272
pybuddylib.py Normal file
View File

@@ -0,0 +1,272 @@
#!/usr/bin/env python
#
# pybuddylib.py: simple library to control iBuddy USB device
# by ewall <e@ewall.org>, 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/
#
# TODO: - Why does libusb require sudo/root on Linux?
# - Why does libusb-win32 error on Windoze?
#
import logging
from time import sleep
from sys import exit
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)
### General USB Device 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:
log.info("USB 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("USB 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)
### iBuddy Device Class
class iBuddyDevice:
USB_VENDOR = 0x1130
USB_PRODUCT = int(0x0001)
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
BLUE = (0,0,1)
GREEN = (0,1,0)
LTBLUE = (0,1,1)
PURPLE = (1,0,1)
RED = (1,0,0)
WHITE = (1,1,1)
YELLOW = (1,1,0)
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:
self.__init__()
#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)
self.command = self.command & temp
elif (value==0):
temp = 1 << num
self.command = self.command | temp
def getReverseBitValue(self,num):
""" what was that bit set to again? """
temp = self.command
temp = temp >> 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)
self.setReverseBitValue(2,1)
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):
""" reset to default positions/off, run command immediately """
self.resetCmd()
self.doCmd(seconds)
def doFlap(self, times=3, seconds=0.2):
""" flap wings X times with Y seconds pause in between, run command immediately """
for i in range(times):
self.setWing(self.UP)
self.doCmd(seconds)
self.setWing(self.DOWN)
self.doCmd(seconds)
def doWiggle(self, times=3, seconds=0.2):
""" wiggle back and forth X times with Y seconds pauses, run command immediately """
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=0.3):
""" blink heart X times with Y seconds' pause in betwee, run command immediately """
for i in range(times):
self.setHeart(self.ON)
self.doCmd(seconds)
self.setHeart(self.OFF)
self.doCmd(seconds)
def doColorRGB(self, r, g, b, seconds=WAITTIME):
""" set head color by red/green/blue values 0 or 1, run command immediately """
self.setHeadColors(r, g, b)
self.doCmd(seconds)
def doColorName(self, rgb, seconds=WAITTIME):
""" set head color with color name tuples, run command immediately """
self.setHeadColors(*rgb)
self.doCmd(seconds)
## 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__':
# find iBuddy device
log.info("Starting search...")
try:
buddy = iBuddyDevice()
except NoBuddyException, e:
log.exception("No iBuddy device found!")
exit(1)
# demo command macros
buddy.doColorName(iBuddyDevice.PURPLE, 0.5)
buddy.doColorName(iBuddyDevice.BLUE, 0.5)
buddy.doColorName(iBuddyDevice.LTBLUE, 0.5)
buddy.doColorName(iBuddyDevice.YELLOW, 0.5)
buddy.doColorName(iBuddyDevice.GREEN, 0.5)
buddy.doColorName(iBuddyDevice.RED, 0.5)
buddy.doColorName(iBuddyDevice.WHITE, 0.5)
buddy.doFlap()
sleep(1)
buddy.doWiggle()
sleep(1)
buddy.doHeartbeat()
sleep(1)
buddy.doReset()

1
requirements.txt Normal file
View File

@@ -0,0 +1 @@
pyusb

241
server.py Normal file
View File

@@ -0,0 +1,241 @@
#!/usr/bin/python
import logging
import sys
import socket
import pwd
import os
import time
from ConfigParser import RawConfigParser
from plibbuddy import BuddyDevice
#########################################
# Decoding macros
##########################################
def macro_color (red, green, blue):
message = 'C:%d:%d:%d' % (red, green, blue)
message += "\nX\nS\nZ\nZ\n"
return message
def macro_heart ():
message = 'H:1'
message += "\nX\nS\nZ\nZ\n"
return message
def macro_move_flap():
message = "ML\nX\nS\nS\n"
message += "MR\nX\nS\nS\n"
message += "ML\nX\nS\nS\n"
return message + macro_flap()
def macro_flap (heart=0):
message = ''
for i in range(2):
message += "L\n"
message += "WU\n"
if heart:
message += "H:1\n"
message += "X\nS\nL\n"
message += "WD\nX\nS\n"
return message
def macro_heart2():
message = "H:1\nX\nS\n"
message += "Z\nS\n"
message += "H:1\nX\nS\n"
message += "Z\nS\n\nZ\nZ\n"
return message
def macro_demo(num = 1):
message = ''
for i in range(num):
message += "C:1:0:0\nH:0\nML\nWD\nX\nS\nS\n"
message += "C:0:1:0\nH:1\nMR\nWU\nX\nS\nS\n"
message += "C:0:0:1\nH:0\nML\nWD\nX\nS\nS\n"
message += "C:1:0:1\nH:1\nMR\nWU\nX\nS\nS\n"
message += "C:1:1:0\nH:0\nML\nWD\nX\nS\nS\n"
message += "C:0:1:1\nH:1\nMR\nWU\nX\nS\nS\n"
message += "C:1:1:1\nH:0\nML\nWD\nX\nS\nS\n"
message += "Z\nZ\n"
return message
def do_color(buddy, red, green, blue):
r, g, b = buddy.getColors()
try:
param1 = int(red)
param2 = int(green)
param3 = int(blue)
except:
param1 = -1
param2 = -1
param3 = -1
if (param1 == -1):
param1 = r
if (param2 == -1):
param2 = g
if (param3 == -1):
param3 = b
buddy.setHeadColors(param1, param2, param3)
buddy.doCmd(0.5)
def decode_buddy(buddy, msg):
orders = msg.split("\n")
for str in (orders):
cod = str.split(':')
param = 0
if cod[0] == 'RED' or cod[0] == 'R':
try: do_color(buddy, cod[1], -1, -1)
except: pass
elif cod[0] == 'GREEN' or cod[0] == 'G':
try: do_color(buddy,-1, cod[1], -1)
except: pass
elif cod[0] == 'BLUE' or cod[0] == 'B':
try: do_color(buddy, -1, -1, cod[1])
except: pass
elif cod[0] == 'YELLOW':
try: do_color(buddy, cod[1], cod[1], -1)
except: pass
continue
elif cod[0] == 'SAPHIRE':
try: do_color(buddy, -1, cod[1], cod[1])
except: pass
elif cod[0] == 'VIOLET':
try: do_color(buddy, cod[1], -1, cod[1])
except: pass
elif cod[0] == 'HEART' or cod[0] == 'H':
try:
param = int(cod[1])
except:
param = 0
buddy.setHeart(param)
elif cod[0] == 'C':
try: do_color(buddy, cod[1], cod[2], cod[3])
except: pass
elif cod[0] == 'MR':
buddy.flick(buddy.RIGHT)
continue
elif cod[0] == 'ML':
buddy.flick(buddy.LEFT)
elif cod[0] == 'SLEEP' or cod[0] == 'S':
time.sleep(0.1)
elif cod[0] == 'WU':
buddy.wing(buddy.UP)
elif cod[0] == 'WD':
buddy.wing(buddy.DOWN)
elif cod[0] == 'EXEC' or cod[0] == 'X':
buddy.pumpMessage()
elif cod[0] == 'CLEAR' or cod[0] == 'L':
buddy.resetMessage()
elif cod[0] == 'RESET' or cod[0] == 'Z':
buddy.resetMessage()
buddy.pumpMessage()
elif cod[0] == 'MACRO_FLAP':
decode_buddy(buddy, macro_move_flap())
elif cod[0] == 'MACRO_FLAP2':
decode_buddy(buddy, macro_flap())
elif cod[0] == 'MACRO_RED':
decode_buddy(buddy, macro_color(1, 0, 0))
elif cod[0] == 'MACRO_GREEN':
decode_buddy(buddy, macro_color(0, 1, 0))
elif cod[0] == 'MACRO_BLUE':
decode_buddy(buddy, macro_color(0,0,1))
elif cod[0] == 'MACRO_YELLOW':
decode_buddy(buddy, macro_color(1,1,0))
elif cod[0] == 'MACRO_VIOLET':
decode_buddy(buddy, macro_color(1,0,1))
elif cod[0] == 'MACRO_SAPHIRE':
decode_buddy(buddy, macro_color(0,1,1))
elif cod[0] == 'MACRO_LBLUE':
decode_buddy(buddy, macro_color(1,1,1))
elif cod[0] == 'MACRO_HEART':
decode_buddy(buddy, macro_heart())
elif cod[0] == 'MACRO_HEART2':
decode_buddy(buddy, macro_heart2())
elif cod[0] == 'DEMO':
decode_buddy(buddy, macro_demo())
#######################################
# MAIN program
#######################################
# Default config
config = RawConfigParser(
{ 'port': 8888,
'address': '0.0.0.0',
'deamon': False,
'user': 'nobody',
'loglevel': 'info',
'logfile': 'console',
'usbproduct': 0001,
}
)
config._sections = {'network':{}, 'system':{}}
config_files = [ 'pybuddy.cfg',
'~/.pybuddy.cfg',
'/etc/pybuddy/pybuddy.cfg',
'/usr/local/etc/pybuddy.cfg']
# Parse config
if len(sys.argv) > 1:
config_files.append(sys.argv[1])
config_read = config.read(config_files)
if config.get('system', 'logfile') != 'console':
logging.basicConfig(
filename = config.get('system', 'logfile'),
format = '%(asctime)s %(levelname)-8s %(message)s',
)
else:
logging.basicConfig(
stream = sys.stderr,
format = '%(asctime)s %(levelname)-8s %(message)s'
)
log = logging.getLogger('pybuddy')
if config.get('system', 'loglevel') == 'debug':
log.setLevel(logging.DEBUG)
elif config.get('system', 'loglevel') == 'info':
log.setLevel(logging.INFO)
if config_read:
log.info('Read config file: %s', config_read[0])
# Initialize device
log.info('Starting search...')
try:
buddy = BuddyDevice(0, int(config.get("system", "usbproduct")))
except NoBuddyException, e:
log.error('Not found!')
sys.exit(1)
if config.get('system', 'daemon') == True:
# Daemonize
log.info('Starting daemon...')
if os.fork() == 0:
os.setsid()
else:
sys.exit(0)
# Create server socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((config.get('network', 'address'), int(config.get('network', 'port'))))
# Drop privileges
try:
uid = pwd.getpwnam(config.get('system', 'user'))[2]
except KeyError:
log.error('Username %s not found, exiting...', config.get('system', 'user'))
sys.exit(1)
os.setuid(uid)
# Main message loop
while 1:
try:
message, address = s.recvfrom(8192)
log.debug('Got data from %s', address)
decode_buddy(buddy, message)
except (KeyboardInterrupt, SystemExit):
raise

View File

@@ -1,412 +0,0 @@
#!/usr/bin/python
#
# pybuddy
# python ibuddy daemon - http://code.google.com/p/pybuddy
#
# Jose.Carlos.Luna@gmail.com
# luis.peralta@gmail.com
#
# Most of the code comes from http://cuntography.com/blog/?p=17
# Which is based on http://scott.weston.id.au/software/pymissile/
import usb
import time
import sys
import socket
import os
import pwd
import logging
from ConfigParser import RawConfigParser
################
#Configuration
################
tsleep = 0.1
################
# 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(0x1130, 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)
self.finalMess = self.finalMess & temp
elif (value==0):
temp = 1 << num
self.finalMess = self.finalMess | temp
def getReverseBitValue(self,num):
temp = self.finalMess
temp = temp >> 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:
self.__init__(self.battery,self.product)
#####################
# 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:
log.info("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)
log.info("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
#########################################
# Decoding macros
##########################################
def macro_color (red,green,blue):
message = "C:%d:%d:%d" % (red,green,blue)
message += "\nX\nS\nZ\nZ\n"
return message
def macro_heart ():
message = "H:1"
message += "\nX\nS\nZ\nZ\n"
return message
def macro_move_flap():
message = "ML\nX\nS\nS\n"
message += "MR\nX\nS\nS\n"
message += "ML\nX\nS\nS\n"
return message + macro_flap()
def macro_flap (heart=0):
message = ""
for i in range(2):
message += "L\n"
message += "WU\n"
if heart:
message += "H:1\n"
message += "X\nS\nL\n"
message += "WD\nX\nS\n"
return message
def macro_heart2():
message = "H:1\nX\nS\n"
message += "Z\nS\n"
message += "H:1\nX\nS\n"
message += "Z\nS\n\nZ\nZ\n"
return message
def macro_demo(num=1):
message = ""
for i in range(num):
message += "C:1:0:0\nH:0\nML\nWD\nX\nS\nS\n"
message += "C:0:1:0\nH:1\nMR\nWU\nX\nS\nS\n"
message += "C:0:0:1\nH:0\nML\nWD\nX\nS\nS\n"
message += "C:1:0:1\nH:1\nMR\nWU\nX\nS\nS\n"
message += "C:1:1:0\nH:0\nML\nWD\nX\nS\nS\n"
message += "C:0:1:1\nH:1\nMR\nWU\nX\nS\nS\n"
message += "C:1:1:1\nH:0\nML\nWD\nX\nS\nS\n"
message += "Z\nZ\n"
return message
def do_color(buddy,red,green,blue):
r,g,b = buddy.getColors()
try:
param1=int(red)
param2=int(green)
param3=int(blue)
except:
param1=-1
param2=-1
param3=-1
if(param1==-1):
param1=r
if(param2==-1):
param2=g
if(param3==-1):
param3=b
buddy.setHeadColor(param1,param2,param3)
def decode_buddy (buddy,msg):
orders = msg.split("\n")
for str in (orders):
cod = str.split(":")
param=0
if cod[0] == 'RED' or cod[0]=='R':
try: do_color(buddy,cod[1],-1,-1)
except: pass
elif cod[0] == 'GREEN' or cod[0]=='G':
try: do_color(buddy,-1,cod[1],-1)
except: pass
elif cod[0] == 'BLUE' or cod[0]=='B':
try: do_color(buddy,-1,-1,cod[1])
except: pass
elif cod[0] == 'YELLOW':
try: do_color(buddy,cod[1],cod[1],-1)
except: pass
continue
elif cod[0] == 'SAPHIRE':
try: do_color(buddy,-1,cod[1],cod[1])
except: pass
elif cod[0] == 'VIOLET':
try: do_color(buddy,cod[1],-1,cod[1])
except: pass
elif cod[0] == 'HEART' or cod[0]=='H':
try:
param=int(cod[1])
except:
param=0
buddy.setHeart(param)
elif cod[0] == 'C':
try: do_color(buddy,cod[1],cod[2],cod[3])
except: pass
elif cod[0] == 'MR':
buddy.flick(buddy.RIGHT)
continue
elif cod[0] == 'ML':
buddy.flick(buddy.LEFT)
elif cod[0] == 'SLEEP' or cod[0]=='S':
time.sleep(0.1)
elif cod[0] == 'WU':
buddy.wing(buddy.UP)
elif cod[0]== 'WD':
buddy.wing(buddy.DOWN)
elif cod[0]== 'EXEC' or cod[0]=='X':
buddy.pumpMessage()
elif cod[0] == 'CLEAR' or cod[0]=='L':
buddy.resetMessage()
elif cod[0]== 'RESET' or cod[0]=='Z':
buddy.resetMessage()
buddy.pumpMessage()
elif cod[0] == 'MACRO_FLAP':
decode_buddy(buddy,macro_move_flap())
elif cod[0] == 'MACRO_FLAP2':
decode_buddy(buddy,macro_flap())
elif cod[0] == 'MACRO_RED':
decode_buddy(buddy,macro_color(1,0,0))
elif cod[0] == 'MACRO_GREEN':
decode_buddy(buddy,macro_color(0,1,0))
elif cod[0] == 'MACRO_BLUE':
decode_buddy(buddy,macro_color(0,0,1))
elif cod[0] == 'MACRO_YELLOW':
decode_buddy(buddy,macro_color(1,1,0))
elif cod[0] == 'MACRO_VIOLET':
decode_buddy(buddy,macro_color(1,0,1))
elif cod[0] == 'MACRO_SAPHIRE':
decode_buddy(buddy,macro_color(0,1,1))
elif cod[0] == 'MACRO_LBLUE':
decode_buddy(buddy,macro_color(1,1,1))
elif cod[0] == 'MACRO_HEART':
decode_buddy(buddy,macro_heart())
elif cod[0] == 'MACRO_HEART2':
decode_buddy(buddy,macro_heart2())
elif cod[0] == 'DEMO':
decode_buddy(buddy,macro_demo())
#######################################
# MAIN program
#######################################
log = logging.getLogger('pybuddy')
#Default config
config = RawConfigParser(
{ 'port': 8888,
'address': '127.0.0.1',
'user': 'nobody',
'loglevel': 'info',
'logfile': 'console',
'usbproduct': 0002,
}
)
config._sections = {'network':{}, 'system':{}}
config_files = [ "~/.pybuddy.cfg",
"/etc/pybuddy/pybuddy.cfg",
"/usr/local/etc/pybuddy.cfg"
]
#Parse config
if len(sys.argv) > 1:
config_files.append(sys.argv[1])
config_read = config.read(config_files)
if config.get("system", "logfile") != "console":
logging.basicConfig(
filename=config.get("system", "logfile"),
format='%(asctime)s %(levelname)-8s %(message)s',
)
else:
logging.basicConfig(
stream=sys.stderr,
format='%(asctime)s %(levelname)-8s %(message)s',
)
if config.get("system", "loglevel") == "debug":
log.setLevel(logging.DEBUG)
elif config.get("system", "loglevel") == "info":
log.setLevel(logging.INFO)
if config_read:
log.info("Read config file: %s", config_read[0])
#Initialize device
log.info("Starting search...")
try:
buddy=BuddyDevice(0, int(config.get("system", "usbproduct")))
except NoBuddyException, e:
log.error("Not found!")
sys.exit(1)
#Daemonize
log.info("Starting daemon...")
if os.fork()==0:
os.setsid()
else:
sys.exit(0)
#Create server socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((config.get("network", "address"), int(config.get("network", "port"))))
#Drop privileges
try:
uid = pwd.getpwnam(config.get("system", "user"))[2]
except KeyError:
log.error("Username %s not found, exiting...", config.get("system", "user"))
sys.exit(1)
os.setuid(uid)
#Main message loop
while 1:
try:
message, address = s.recvfrom(8192)
log.debug("Got data from %s", address)
decode_buddy(buddy, message)
except (KeyboardInterrupt, SystemExit):
raise

35
test.py Normal file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/python
import configparser
from time import sleep
from ibuddy import ibuddy, DeviceNotFoundException
if __name__ == '__main__':
try:
try:
config = configparser.ConfigParser()
config.read('config.ini')
product = int(config.get('system', 'product'))
except:
exit('[error] Failed to read config file!')
ibuddy = ibuddy(product)
except DeviceNotFoundException:
print('No iBuddy device found!')
exit(1)
for x in range(0, 10):
ibuddy.doColorName(ibuddy.PURPLE, 0.1)
ibuddy.doColorName(ibuddy.BLUE, 0.1)
ibuddy.doColorName(ibuddy.LTBLUE, 0.1)
ibuddy.doColorName(ibuddy.YELLOW, 0.1)
ibuddy.doColorName(ibuddy.GREEN, 0.1)
ibuddy.doColorName(ibuddy.RED, 0.1)
ibuddy.doColorName(ibuddy.WHITE, 0.1)
sleep(0.1)
ibuddy.doFlap() # does not work!
sleep(1)
ibuddy.doWiggle() # does not work!
sleep(1)
ibuddy.doHeartbeat()
sleep(1)
ibuddy.doReset()