- Saved searches
- Use saved searches to filter your results more quickly
- sraodev/bluetooth-service-rfcomm-python
- Name already in use
- Sign In Required
- Launching GitHub Desktop
- Launching GitHub Desktop
- Launching Xcode
- Launching Visual Studio Code
- Latest commit
- Git stats
- Files
- README.md
- About
- Write the Python Application
- BTLE_Manager.py
- Advertisement.py
- Characteristic.py
- Get in touch
- Python and Bluetooth – Part 1: Scanning For Devices And Services (Python)
- Installing
- Checking For Devices
- Checking For Services Running On Devices
- Links
Saved searches
Use saved searches to filter your results more quickly
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.
This application connects two devices over Bluetooth and allows one to send messages to the other using json. Raspberry Pi Bluetooth interfacing with Linux via RFCOMM BT network
sraodev/bluetooth-service-rfcomm-python
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Sign In Required
Please sign in to use Codespaces.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching Xcode
If nothing happens, download Xcode and try again.
Launching Visual Studio Code
Your codespace will open once ready.
There was a problem preparing your codespace, please try again.
Latest commit
Git stats
Files
Failed to load latest commit information.
README.md
Bluetooth Service (PyBluez) with RFCOMM sockets
This application connects two devices over Bluetooth and allows one to send messages to the other using json. The sending device runs bleClient.py, and the receiving device runs bleServer.py
How to setup a bluetooth server in a Raspberry Pi so an Linux can connect to it.
This python-script uses Bluez, Linux’s Bluetooth protocol stack, we’ll be using PyBluez, a Python API for accessing the bluetooth resources using the bluez protocol.
sudo apt-get install python-pip python-dev ipython sudo apt-get install bluetooth libbluetooth-dev sudo apt-get install bluez-utils blueman sudo apt-get install bluez python-bluez sudo pip install pybluez`
You’ve installed the Python 2 version of the bluez bindings. Either run the script using python2 or install the Python 3 bindings. Since they aren’t packaged, you would need to install them using pip:
sudo python3 -m pip install pybluez`
Make your device discoverable
sudo hciconfig hci0 piscan
Scanning for devices run the inquiry example:
Running the Bluetooth Server on RaspberryPi:
Running the Bluetooth Client on Linux box:
Traceback (most recent call last): File "/usr/share/doc/python-bluez/examples/simple/rfcomm-server.py", line 20, in profiles = [ SERIAL_PORT_PROFILE ], File "/usr/lib/python2.7/dist-packages/bluetooth/bluez.py", line 176, in advertise_service raise BluetoothError (str (e)) bluetooth.btcommon.BluetoothError: (2, 'No such file or directory')
Make sure you are using sudo when running the python script Make sure you have the serial profile loaded. How to enable the serial profile.
As it turns out, the culprit is bluetoothd, the Bluetooth daemon. Using SDP with bluetoothd requires deprecated features for some silly reason, so to fix this, the daemon must be started in compatibility mode with bluetoothd -C (or bluetooth —compat).
You need to run the Bluetooth daemon in ‘compatibility’ mode. Edit /lib/systemd/system/bluetooth.service and add ‘-C’ after ‘bluetoothd’. Reboot.
Find location of bluetooth.service by:
systemctl status bluetooth.service
Then edit bluetooth.service and look for ExecStart=/usr/libexec/bluetooth/bluetoothd Append —compat at the end of this line, save, and then run
If all goes well, you should be able to successfully run
sudo sdptool browse local
Finally, reset the adapter:
sudo hciconfig -a hci0 reset
Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are greatly appreciated. Please read the contribution guidelines first.
About
This application connects two devices over Bluetooth and allows one to send messages to the other using json. Raspberry Pi Bluetooth interfacing with Linux via RFCOMM BT network
Write the Python Application
Let’s write the code to get the bluetooth radio advertising our service, allowing centrals to connect, and notifying those centrals when the temperature value changes. The full code is available on Github, but we’ll look at some of the main components here.
We’ll run the application from the command line of the Raspberry Pi with this command:
docker run -it --rm \ --privileged \ --workdir /app \ --volume "$PWD":/app \ --volume /var/run/dbus/:/var/run/dbus/:z \ soodesune/python3-bluetooth BTLE_manager.py
BTLE_Manager.py
The first section of code is going to run our application in test-mode if it’s run as a stand alone application. We’ll have it broadcast some random values to centrals that are listening.
if __name__ == '__main__': bm = BluetoothManager() # Put out some random values for debugging / testing purposes # while True: bm.write_value( [choice([0x01, 0x02, 0x03, 0x04, 0xAB, 0xDE])] ) sleep(0.5)
Now let’s look at what BluetoothManager is doing.
class BluetoothManager: def __init__(self): bus = SystemMessageBus() Thread(target=EventLoop().run).start() bus.register_service("com.raspberrypi-bluetooth.Thermometer") proxy = bus.get_proxy("org.bluez", "/org/bluez/hci0") proxy.Set("org.bluez.Adapter1", "Powered", Variant("b", True)) print("Adapter powered: %s" % proxy.Get("org.bluez.Adapter1", "Powered")) # We don't need pairing for this application proxy.Set("org.bluez.Adapter1", "Pairable", Variant("b", False)) bus.publish_object( Advertisement.PATH, Advertisement().for_publication() ) proxy.RegisterAdvertisement(Advertisement.PATH, <>) self.characteristic = Characteristic().for_publication() bus.publish_object( Characteristic.PATH, self.characteristic ) bus.publish_object( Application.PATH, Application().for_publication() ) proxy.RegisterApplication(Application.PATH, <>) def write_value(self, value: List[Byte]) -> None: self.characteristic.WriteValue(value, <>)
- Getting a proxy to the Bluetooth device ( hci0 ) and configuring some of it’s settings.
- Publishing our application components on D-Bus so that BlueZ can communicate back with our application.
- Adding a write_value function, so that the MLX-90164 has a way of publishing it’s temperature readings.
Advertisement.py
class Advertisement(Publishable): PATH = "/com/raspberrypi-bluetooth/Thermometer/Advertisement/1" def for_publication(self): return AdvertisementInterface(self) @dbus_interface("org.bluez.LEAdvertisement1") class AdvertisementInterface(InterfaceTemplate): def Release(self) -> None: print("released") @property def Type(self) -> Str: return "peripheral" @property def ServiceUUIDS(self) -> List[Str]: return [Service.UUID] @property def Discoverable(self) -> Bool: return True @property def Includes(self) -> List[Str]: return ["tx-power"] @property def LocalName(self) -> Str: return "RasberryPi-Bluetooth.com Thermometer" # https://specificationrefs.bluetooth.com/assigned-values/Appearance%20Values.pdf @property def Appearance(self) -> UInt16: return 768 # Thermometer @property def MinInterval(self) -> UInt32: return 0 @property def MaxInterval(self) -> UInt32: return 0
There’s a pattern here that all of our application code is going to follow. We have a model class ( Advertisement ) that inherits from the Publishable class provided by Dasbus. The model class will have a method called for_publication that delegates to an interface class that inherits from InterfaceTemplate , which is also provided by the Dasbus library. The interface class is how D-Bus is going to see and interact with our application, while the model class is going to be where we do our internal logic.
Application.py and Service.py aren’t that interesting. You can look at them on Github.
Characteristic.py
class Characteristic(Publishable): PATH = "/com/raspberrypi-bluetooth/Thermometer/Characteristic/1" UUID = "4116f8d2-9f66-4f58-a53d-fc7440e7c14e" # hex chars only! # Will improve this later. Other problems to solve now. _SERVICE_PATH = "/com/raspberrypi-bluetooth/Thermometer/Service/1" def __init__(self): self._value = [None] super().__init__() def for_publication(self): return CharacteristicInterface(self) @property def value(self): return self._value @value.setter def value(self, value): self._value = value @dbus_interface("org.bluez.GattCharacteristic1") class CharacteristicInterfaceGatt(InterfaceTemplate): def ReadValue(self, options: Dict[Str, Variant]) -> List[Byte]: return self.implementation.value @emits_properties_changed def WriteValue(self, value: List[Byte], options: Dict[Str, Str]) -> None: self.implementation.value = value self.report_changed_property('Value') @property def UUID(self) -> Str: return Characteristic.UUID @property def Service(self) -> ObjPath: return Characteristic._SERVICE_PATH @property def Value(self) -> List[Byte]: return self.implementation.value class CharacteristicInterface(CharacteristicInterfaceGatt): _UUID = Variant("s", Characteristic.UUID) def get_properties(self): return < "org.bluez.GattCharacteristic1": < "Service": Variant("o", Characteristic._SERVICE_PATH), "UUID": self._UUID, "Flags": Variant.new_array(None, [Variant("s", "read"), Variant("s", "notify")]), "Descriptors": Variant.new_array(VariantType("t"), []), >>
In our model Characteristic.py you can see we’re keeping track of the temperature value from the MLX-90614. The interface class CharacteristicInterfaceGatt exposes an interface to D-Bus that allows reading and writing of the thermometer value. Finally, CharacteristicInterface publishes the Flags so that central devices know they can read or get notifications when this characteristic changes.
Get in touch
Can you improve the implementation or my write up? Are you better at D-Bus or BlueZ than I am? Please get it touch! I’d love to make this guide better.
Python and Bluetooth – Part 1: Scanning For Devices And Services (Python)
“Track and Trace” has got some attention in recent times here in the UK as the Covid-19 (Coronavirus) lockdown level looks to be relaxed. Part of the “Track and Trace” program is a mobile application that uses low energy bluetooth beaconing to see what other devices running the application have been close by. This has inspired me to look at Bluetooth connectivity in Python.
Note: I’ve written before, and I’ll probably write again, geektechstuff.com is not a political site. If you have come to this page/site to discuss political opinions around the NHS Track and Trace app, then please take them to a more appropriate site. Thank you. Also note, I am looking at Bluetooth and Python – I am not saying these functions are in the NHS app!
With this blog post I am going to take a look at using a Raspberry Pi (in this case a ZeroW) and some Python to get the Pi to detect active bluetooth devices.
Installing
I installed the required libraries for this project on my Raspberry Pi using the commands:
sudo apt install bluetooth libbluetooth-dev pip3 install pybluez
Checking For Devices
With the pybluez library installed and imported into Python, the Raspberry Pi can start to scan for active Bluetooth devices. This code can be tided up into a function, so that it can be expanded on later.
#!/usr/bin/python3 # geektechstuff bluetooth import bluetooth def scan(): print("Scanning for bluetooth devices:") devices = bluetooth.discover_devices(lookup_names = True, lookup_class = True) number_of_devices = len(devices) print(number_of_devices,"devices found") for addr, name, device_class in devices: print("\n") print("Device:") print("Device Name: %s" % (name)) print("Device MAC Address: %s" % (addr)) print("Device Class: %s" % (device_class)) print("\n") return
Checking For Services Running On Devices
A function to scan for Bluetooth services on found devices can also be created.
def scan_services(): print("Scanning for bluetooth devices: ") devices = bluetooth.discover_devices(lookup_names = True) number_of_devices = len(devices) print(number_of_devices, "devices found") for addr,name in devices: print("\n") print("Device Name: %s" % (name)) print("Device MAC Address: %s" % (addr)) print("Services Found:") services = bluetooth.find_service(address=addr) if len(services) print("zero services found on", addr) else: for serv in services: print(serv['name']) print("\n") return()
When run this function returns the device details and the name of the services it finds on those active devices.
Although I am only returning the service name (using serv[‘name’]) there are also options to return:
- host
- description
- provider
- protocol
- port
- service-classes
- profiles
- service-id
To use these, place them in the same format as serv[‘name’] e.g. serv[‘host’]
Links
The GitHub for pybluez (which contains examples of the library in action) can be found at:
The GitHub for NHSX Android Covid-19 app can be found at:
The GitHub for NHSX iOS Covid-19 app can be found at: