Compare commits
10 Commits
875f47a9ae
...
01e0af6fcb
| Author | SHA1 | Date | |
|---|---|---|---|
| 01e0af6fcb | |||
| 27fb51e6e1 | |||
| d080fa9ecd | |||
| fac1d8c9eb | |||
| 440005d7a1 | |||
| 9a5b9bbd8d | |||
| 2a4e547a40 | |||
|
|
8fa4f865c1 | ||
|
|
c6e6e0c440 | ||
|
|
d8669c91d1 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
.svn/
|
||||
__pycache__
|
||||
venv
|
||||
*.pyc
|
||||
15
config.ini
Normal file
15
config.ini
Normal file
@@ -0,0 +1,15 @@
|
||||
[remote]
|
||||
host=localhost
|
||||
port=8883
|
||||
|
||||
[local]
|
||||
server=true
|
||||
|
||||
[server]
|
||||
port=8883
|
||||
|
||||
[general]
|
||||
implementation=local
|
||||
|
||||
[system]
|
||||
product=1
|
||||
@@ -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
39
contrib/usbenum.py
Normal 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)
|
||||
@@ -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
52
dx/manual.txt
Normal 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
|
||||
@@ -6,9 +6,7 @@ port: 8888
|
||||
|
||||
[system]
|
||||
# user to setuid to after daemon is started
|
||||
user: nobody
|
||||
# usb product id (do a lspci to check)
|
||||
usbproduct: 0001
|
||||
user: usernamehere
|
||||
|
||||
# logging
|
||||
# loglevel: info/debug
|
||||
250
dx/pybuddyDX.py
Normal file
250
dx/pybuddyDX.py
Normal 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
27
dynamic.py
Normal 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
207
ibuddy.py
Normal 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)
|
||||
13
implementation/__init__.py
Normal file
13
implementation/__init__.py
Normal 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
5
implementation/local.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from . import ibuddy
|
||||
|
||||
class local(ibuddy):
|
||||
def test(self):
|
||||
print('test local')
|
||||
5
implementation/remote.py
Normal file
5
implementation/remote.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from . import ibuddy
|
||||
|
||||
class remote(ibuddy):
|
||||
def test(self):
|
||||
print('test remote')
|
||||
204
my_pybuddy.py
204
my_pybuddy.py
@@ -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
272
pybuddylib.py
Normal 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
1
requirements.txt
Normal file
@@ -0,0 +1 @@
|
||||
pyusb
|
||||
241
server.py
Normal file
241
server.py
Normal 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
|
||||
@@ -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
35
test.py
Normal 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()
|
||||
Reference in New Issue
Block a user