I am trying to turn my Raspberry Pi into a programable bluetooth keyboard by following this tutorial.
I think I have been able to programatically send bluetooth keystrokes, however I have an error stoping me from finding out.
The error I am getting is
Traceback (most recent call last): File "./PiTooth.py", line 191, in bt.send_input(state) File "./PiTooth.py", line 89, in send_input self.cinterrupt.send(hex_str) AttributeError: Bluetooth instance has no attribute 'cinterrupt'
And my code (PiTooth.py) is
#!/usr/bin/python2.7 # # PiTooth allows the Raspberry Pi to act as a Bluetooth keyboard, and relays # keypresses from a USB keyboard to a Bluetooth client. Written by Liam Fraser # for a Linux User & Developer tutorial. # import os # Used to call external commands import sys # Used to exit the script import bluetooth from bluetooth import * import dbus # Used to set up the SDP record import time # Used for pausing the process import evdev # Used to get input from the keyboard from evdev import * import keymap # Used to map evdev input to hid keycodes class Bluetooth: HOST = 0 # BT Mac address PORT = 1 # Bluetooth Port Number # Define the ports we'll use P_CTRL = 17 P_INTR = 19 def __init__(self): # Set the device class to a keyboard and set the name os.system("hciconfig hci0 class 0x002540") os.system("hciconfig hci0 name Raspberry\ Pi") # Make device discoverable os.system("hciconfig hci0 piscan") # Define our two server sockets for communication self.scontrol = BluetoothSocket(L2CAP) self.sinterrupt = BluetoothSocket(L2CAP) # Bind these sockets to a port self.scontrol.bind(("", Bluetooth.P_CTRL)) self.sinterrupt.bind(("", Bluetooth.P_INTR)) # Set up dbus for advertising the service record self.bus = dbus.SystemBus() try: self.manager = dbus.Interface(self.bus.get_object("org.bluez", "/"), "org.bluez.Manager") adapter_path = self.manager.DefaultAdapter() self.service = dbus.Interface(self.bus.get_object("org.bluez", adapter_path), "org.bluez.Service") except: sys.exit("Could not configure bluetooth. Is bluetoothd started?") # Read the service record from file try: fh = open(sys.path + "/sdp_record.xml", "r") except: sys.exit("Could not open the sdp record. Exiting...") self.service_record = fh.read() fh.close() def listen(self): # Advertise our service record self.service_handle = self.service.AddRecord(self.service_record) print "Service record added" # Start listening on the server sockets self.scontrol.listen(1) # Limit of 1 connection self.sinterrupt.listen(1) print "Waiting for a connection" self.ccontrol, self.cinfo = self.scontrol.accept() print "Got a connection on the control channel from " + self.cinfo[Bluetooth.HOST] self.cinterrupt, self.cinfo = self.sinterrupt.accept() print "Got a connection on the interrupt channel from " + self.cinfo[Bluetooth.HOST] def send_input(self, ir): # Convert the hex array to a string hex_str = "" for element in ir: if type(element) is list: # This is our bit array - convert it to a single byte represented # as a char bin_str = "" for bit in element: bin_str += str(bit) hex_str += chr(int(bin_str, 2)) else: # This is a hex value - we can convert it straight to a char hex_str += chr(element) # Send an input report self.cinterrupt.send(hex_str) class Keyboard(): def __init__(self): # The structure for an bt keyboard input report (size is 10 bytes) self.state = [ 0xA1, # This is an input report 0x01, # Usage report = Keyboard # Bit array for Modifier keys (D7 being the first element, D0 being last) [0, # Right GUI - (usually the Windows key) 0, # Right ALT 0, # Right Shift 0, # Right Control 0, # Left GUI - (again, usually the Windows key) 0, # Left ALT 0, # Left Shift 0], # Left Control 0x00, # Vendor reserved 0x00, # Rest is space for 6 keys 0x00, 0x00, 0x00, 0x00, 0x00 ] # Keep trying to get a keyboard have_dev = True while have_dev == False: try: # Try and get a keyboard - should always be event0 as we're only # plugging one thing in self.dev = InputDevice("/dev/input/event0") have_dev = True except OSError: print "Keyboard not found, waiting 3 seconds and retrying" time.sleep(3) print "Found a keyboard" def change_state(self, event): evdev_code = ecodes.KEY[event.code] modkey_element = keymap.modkey(evdev_code) if modkey_element > 0: # Need to set one of the modifier bits if self.state[modkey_element] == 0: self.state[modkey_element] = 1 else: self.state[modkey_element] = 0 else: # Get the hex keycode of the key hex_key = keymap.convert(ecodes.KEY[event.code]) # Loop through elements 4 to 9 of the input report structure for i in range (4, 10): if self.state[i] == hex_key and event.value == 0: # Code is 0 so we need to depress it self.state[i] = 0x00 elif self.state[i] == 0x00 and event.value == 1: # If the current space is empty and the key is being pressed self.state[i] = hex_key break def event_loop(self, bt): for event in self.dev.read_loop(): # Only bother if we a key and it's an up or down event if event.type == ecodes.EV_KEY and event.value < 2: self.change_state(event) bt.send_input(self.state) if __name__ == "__main__": # We can only run as root if not os.geteuid() == 0: sys.exit("Only root can run this script") print "1" bt = Bluetooth() print "2" #bt.listen() print "3" kb = Keyboard() print "4" raw_input(":") time.sleep(10) state = [ 0xA1, # This is an input report 0x01, # Usage report = Keyboard # Bit array for Modifier keys [0, # Right GUI - (usually the Windows key) 0, # Right ALT 0, # Right Shift 0, # Right Control 0, # Left GUI - (again, usually the Windows key) 0, # Left ALT 1, # Left Shift is pressed 0], # Left Control 0x00, # Vendor reserved 0x04, # The W key is pressed 0x00, 0x00, 0x00, 0x00, 0x00 ] bt.send_input(state)
How would I fix this issue?
The reason why I have modified the program to how it is can be found here.