1

I'm trying to emulate bluetooth keyboard on raspberry pi 3. I'm trying to connect my RPI3 with my lapbtop first via btk_server.py code which I got from github. I downloaded the code from github and followed the instruction from following link:

http://yetanotherpointlesstechblog.blogspot.com/2016/04/emulating-bluetooth-keyboard-with.html?m=1

everything seems fine until I run btk_server.py code after changing MY_ADDRESS to my RPI3's BD Address.

Here's the btk_server.py code:

from __future__ import absolute_import, print_function

from optparse import OptionParser, make_option

import os

import sys

import uuid

import dbus

import dbus.service

import dbus.mainloop.glib

import time

import bluetooth

from bluetooth import *





import gtk

from dbus.mainloop.glib import DBusGMainLoop





#

#define a bluez 5 profile object for our keyboard

#

class BTKbBluezProfile(dbus.service.Object):

    fd = -1



    @dbus.service.method("org.bluez.Profile1",

                                    in_signature="", out_signature="")

    def Release(self):

            print("Release")

            mainloop.quit()



    @dbus.service.method("org.bluez.Profile1",

                                    in_signature="", out_signature="")

    def Cancel(self):

            print("Cancel")



    @dbus.service.method("org.bluez.Profile1", in_signature="oha{sv}", out_signature="")

    def NewConnection(self, path, fd, properties):

            self.fd = fd.take()

            print("NewConnection(%s, %d)" % (path, self.fd))

            for key in properties.keys():

                    if key == "Version" or key == "Features":

                            print("  %s = 0x%04x" % (key, properties[key]))

                    else:

                            print("  %s = %s" % (key, properties[key]))







    @dbus.service.method("org.bluez.Profile1", in_signature="o", out_signature="")

    def RequestDisconnection(self, path):

            print("RequestDisconnection(%s)" % (path))



            if (self.fd > 0):

                    os.close(self.fd)

                    self.fd = -1



    def __init__(self, bus, path):

            dbus.service.Object.__init__(self, bus, path)





#

#create a bluetooth device to emulate a HID keyboard, 

# advertize a SDP record using our bluez profile class

#

class BTKbDevice():

    #change these constants 

    MY_ADDRESS="B8:27:EB:12:5B:04"

    MY_DEV_NAME="DeskPi_BTKb"



    #define some constants

    P_CTRL =17  #Service port - must match port configured in SDP record

    P_INTR =19  #Service port - must match port configured in SDP record#Interrrupt port  

    PROFILE_DBUS_PATH="/bluez/yaptb/btkb_profile" #dbus path of  the bluez profile we will create

    SDP_RECORD_PATH = sys.path[0] + "/sdp_record.xml" #file path of the sdp record to laod

    UUID="00001124-0000-1000-8000-00805f9b34fb"





    def __init__(self):



        print("Setting up BT device")



        self.init_bt_device()

        self.init_bluez_profile()





    #configure the bluetooth hardware device

    def init_bt_device(self):





        print("Configuring for name "+BTKbDevice.MY_DEV_NAME)



        #set the device class to a keybord and set the name

        os.system("hciconfig hcio class 0x002540")

        os.system("hciconfig hcio name " + BTKbDevice.MY_DEV_NAME)



        #make the device discoverable

        os.system("hciconfig hcio piscan")





    #set up a bluez profile to advertise device capabilities from a loaded service record

    def init_bluez_profile(self):



        print("Configuring Bluez Profile")



        #setup profile options

        service_record=self.read_sdp_service_record()



        opts = {

            "ServiceRecord":service_record,

            "Role":"server",

            "RequireAuthentication":False,

            "RequireAuthorization":False

        }



        #retrieve a proxy for the bluez profile interface

        bus = dbus.SystemBus()

        manager = dbus.Interface(bus.get_object("org.bluez","/org/bluez"), "org.bluez.ProfileManager1")



        profile = BTKbBluezProfile(bus, BTKbDevice.PROFILE_DBUS_PATH)



        manager.RegisterProfile(BTKbDevice.PROFILE_DBUS_PATH, BTKbDevice.UUID,opts)



        print("Profile registered ")





    #read and return an sdp record from a file

    def read_sdp_service_record(self):



        print("Reading service record")



        try:

            fh = open(BTKbDevice.SDP_RECORD_PATH, "r")

        except:

            sys.exit("Could not open the sdp record. Exiting...")



        return fh.read()   







    #listen for incoming client connections

    #ideally this would be handled by the Bluez 5 profile 

    #but that didn't seem to work

    def listen(self):



        print("Waiting for connections")

        self.scontrol=BluetoothSocket(bluetooth.L2CAP)

        self.sinterrupt=BluetoothSocket(bluetooth.L2CAP)



        #bind these sockets to a port - port zero to select next available      

        self.scontrol.bind((self.MY_ADDRESS,self.P_CTRL))

        self.sinterrupt.bind((self.MY_ADDRESS,self.P_INTR ))



        #Start listening on the server sockets 

        self.scontrol.listen(1) # Limit of 1 connection

        self.sinterrupt.listen(1)



        self.ccontrol,cinfo = self.scontrol.accept()

        print ("Got a connection on the control channel from " + cinfo[0])



        self.cinterrupt, cinfo = self.sinterrupt.accept()

        print ("Got a connection on the interrupt channel from " + cinfo[0])





    #send a string to the bluetooth host machine

    def send_string(self,message):



     #    print("Sending "+message)

         self.cinterrupt.send(message)







#define a dbus service that emulates a bluetooth keyboard

#this will enable different clients to connect to and use 

#the service

class  BTKbService(dbus.service.Object):



    def __init__(self):



        print("Setting up service")



        #set up as a dbus service

        bus_name=dbus.service.BusName("org.yaptb.btkbservice",bus=dbus.SystemBus())

        dbus.service.Object.__init__(self,bus_name,"/org/yaptb/btkbservice")



        #create and setup our device

        self.device= BTKbDevice();



        #start listening for connections

        self.device.listen();





    @dbus.service.method('org.yaptb.btkbservice', in_signature='yay')

    def send_keys(self,modifier_byte,keys):



        cmd_str=""

        cmd_str+=chr(0xA1)

        cmd_str+=chr(0x01)

        cmd_str+=chr(modifier_byte)

        cmd_str+=chr(0x00)



        count=0

        for key_code in keys:

            if(count<6):

                cmd_str+=chr(key_code)

            count+=1



        self.device.send_string(cmd_str);       





#main routine

if __name__ == "__main__":

    # we an only run as root

    if not os.geteuid() == 0:

       sys.exit("Only root can run this script")



    DBusGMainLoop(set_as_default=True)

    myservice = BTKbService();

    gtk.main()

Following error is this

pi@jeanberry:~/BlogCode/btkeyboard/server $ sudo python btk_server.py

Setting up service

Setting up BT device

Configuring for name DeskPi_BTKb

Configuring Bluez Profile

Reading service record

Profile registered 

Waiting for connections

Traceback (most recent call last):

  File "btk_server.py", line 227, in <module>

    myservice = BTKbService();

  File "btk_server.py", line 199, in __init__

    self.device.listen();

  File "btk_server.py", line 160, in listen

    self.scontrol.bind((self.MY_ADDRESS,self.P_CTRL))

  File "build/bdist.linux-armv7l/egg/bluetooth/bluez.py", line 205, in bind

_bluetooth.error: (98, '\xec\xa3\xbc\xec\x86\x8c\xea\xb0\x80 \xec\x9d\xb4\xeb\xaf\xb8 \xec\x82\xac\xec\x9a\xa9 \xec\xa4\x91\xec\x9e\x85\xeb\x8b\x88\xeb\x8b\xa4')

I have no idea why this happens. I tried turning background bluetooth off but that doesn't seem to solve the problem.

I also found this link: https://github.com/mlabviet/BL_keyboard_RPI

both btk_server code seems pretty much same and I also have same problem when running btk_server.py. If I put empty string or any random BD address, I don't get error message but it stays in ' Waiting for connections'.

I don't think the code has any problem because once I didn't get error message( in BL_keyboard_RPI) when I boot my raspberry pi and after running ./boot.sh and running btk_server.py with my rpi3 bd address. Instead, it stayed on waiting for connection and got connected not with my laptop but with my bluetooth keyboard I use(which wasn't my intention). After that, I closed the terminal and tried again but failed. I also rebooted raspberry pi multiple times but still failed.

Can someone tell me what is the reason behind this error?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.