-
-
Save ali1234/5e5758d9c591090291d6 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python | |
# BB-8 Python driver by Alistair Buxton <a.j.buxton@gmail.com> | |
from bluepy import btle | |
import time | |
class BB8(btle.DefaultDelegate): | |
def __init__(self, deviceAddress): | |
btle.DefaultDelegate.__init__(self) | |
# Address type must be "random" or it won't connect. | |
self.peripheral = btle.Peripheral(deviceAddress, btle.ADDR_TYPE_RANDOM) | |
self.peripheral.setDelegate(self) | |
self.seq = 0 | |
# Attribute UUIDs are identical to Ollie. | |
self.antidos = self.getSpheroCharacteristic('2bbd') | |
self.wakecpu = self.getSpheroCharacteristic('2bbf') | |
self.txpower = self.getSpheroCharacteristic('2bb2') | |
self.roll = self.getSpheroCharacteristic('2ba1') | |
self.notify = self.getSpheroCharacteristic('2ba6') | |
# This startup sequence is also identical to the one for Ollie. | |
# It even uses the same unlock code. | |
print 'Sending antidos' | |
self.antidos.write('011i3', withResponse=True) | |
print 'Sending txpower' | |
self.txpower.write('\x0007', withResponse=True) | |
print 'Sending wakecpu' | |
self.wakecpu.write('\x01', withResponse=True) | |
def getSpheroCharacteristic(self, fragment): | |
return self.peripheral.getCharacteristics(uuid='22bb746f'+fragment+'75542d6f726568705327')[0] | |
def dumpCharacteristics(self): | |
for s in self.peripheral.getServices(): | |
print s | |
for c in s.getCharacteristics(): | |
print c, hex(c.handle) | |
def cmd(self, did, cid, data=[], answer=True, resetTimeout=True): | |
# Commands are as specified in Sphero API 1.50 PDF. | |
# https://github.com/orbotix/DeveloperResources/ | |
seq = (self.seq&255) | |
self.seq += 1 | |
sop2 = 0xfc | |
sop2 |= 1 if answer else 0 | |
sop2 |= 2 if resetTimeout else 0 | |
dlen = len(data)+1 | |
chk = (sum(data)+did+cid+seq+dlen)&255 | |
chk ^= 255 | |
msg = [0xff, sop2, did, cid, seq, dlen] + data + [chk] | |
print 'cmd:', ' '.join([chr(c).encode('hex') for c in msg]) | |
# Note: withResponse is very important. Most commands won't work without it. | |
self.roll.write(''.join([chr(c) for c in msg]), withResponse=True) | |
def handleNotification(self, cHandle, data): | |
print 'Notification:', cHandle, data.encode('hex') | |
def waitForNotifications(self, time): | |
self.peripheral.waitForNotifications(time) | |
def disconnect(self): | |
self.peripheral.disconnect() | |
if __name__ == '__main__': | |
# Connect by address. Use "sudo hcitool lescan" to find address. | |
bb = BB8('EE:D7:9A:A7:79:77') | |
# Dump all GATT stuff. | |
#bb.dumpCharacteristics() | |
# Request some sensor stream. | |
bb.cmd(0x02, 0x11, [0, 80, 0, 1, 0x80, 0, 0, 0, 0]) | |
for i in range(255): | |
# Set RGB LED colour. | |
bb.cmd(0x02, 0x20, [254, i, 2, 0]) | |
# Wait for streamed data. | |
bb.waitForNotifications(1.0) | |
# Must manually disconnect or you won't be able to reconnect. | |
bb.disconnect() |
Somehow this does not work on my BB8. I have a bad feeling about this. I am able to sense BB's mac via hcitool. Using gentoo with Bluez5. I can even see the droid I was looking for with bluetoothctl. However when I run this snippet (with correct mac), it seems it connects, everything runs, I get loads of output (expected), but no errors or exceptions. BB doesn't even blink. No reaction. The force isn't strong enough. With phone app it runs just fine. Any ideas? (sorry for the puns :()
Yeah, I'm having a similar issue of the phone not reconnecting afterwards. Does anyone know of a definite way of disconnecting at the end of the program such that the phone can connect later?
Hi all, unfortunately I am having the same issue as others where the BB8 will not allow a phone connection after connecting with the python driver. Advice please as allowing it to 'sleep' didn't do the trick here.
Hello, did you try to press the small reset button on the base when bb8 is charging ? I did not yet test the python driver, but with this reset button i was able to pair/unpair different phones/tablets on my bb8. Hope this helps.
NickLeBoeuf - thanks! I had completely forgotten about that button which did the trick. Any idea what is causing the issue with switching back to other apps?
Hello Ali! Thanks for your code!!!
Does it work for ollie too?
good evening,
Congratulations on the code, I need to get information from the BB8 as the data of your sensors, IMU, accelerometer, gyroscope, can you do something like this?
Hello,
Thank you so much for the code!
I have an issue whenever I run the BB8test.py. Here is the output that comes up on my terminal. Any help would be greatly appreciated!
"File "BB8test.py", line 8, in <module>
bb8.connect()
File "/home/pi/Projects/SpheroBB8-python/BB8_driver.py", line 259, in connect
self.bt = BTInterface(self.deviceAddress)
File "/home/pi/Projects/SpheroBB8-python/BB8_driver.py", line 138, in __init__
self.peripheral = btle.Peripheral(deviceAddress, btle.ADDR_TYPE_RANDOM)
File "/usr/local/lib/python2.7/dist-packages/bluepy/btle.py", line 391, in __init__
self._connect(deviceAddr, addrType, iface)
File "/usr/local/lib/python2.7/dist-packages/bluepy/btle.py", line 439, in _connect
raise BTLEDisconnectError("Failed to connect to peripheral %s, addr type: %s" % (addr, addrType), rsp)
bluepy.btle.BTLEDisconnectError: Failed to connect to peripheral D7:74:05:73:09:55, addr type: random
What can happen is that if the program crashes it does not tear down the connection. Try waiting for BB-8 to go to sleep, that should fix it.