Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions bluezero/GATT.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def resolve_gatt(self):
self.srv_uuid)

@property
def UUID(self):
def UUID(self): # pylint: disable=invalid-name
"""
Return the value of the Service UUID for this path.

Expand Down Expand Up @@ -118,7 +118,7 @@ def resolve_gatt(self):
return False

@property
def UUID(self):
def UUID(self): # pylint: disable=invalid-name
"""
Return the value of the Characteristic UUID for this path.

Expand Down Expand Up @@ -152,7 +152,7 @@ def value(self):

@value.setter
def value(self, new_value):
if type(new_value) is not list:
if not isinstance(new_value, list):
new_value = [new_value]
self.write_value(new_value)

Expand Down Expand Up @@ -262,7 +262,7 @@ def props_changed_cb(self, iface, changed_props, invalidated_props):
if iface != constants.GATT_CHRC_IFACE:
return

if not len(changed_props):
if not changed_props:
return

value = changed_props.get('Value', None)
Expand Down Expand Up @@ -322,7 +322,7 @@ def resolve_gatt(self):
self.dscr_uuid)

@property
def UUID(self):
def UUID(self): # pylint: disable=invalid-name
"""
Return the value of the Descriptor UUID for this path.

Expand Down Expand Up @@ -419,7 +419,7 @@ def release(self):
self.profile_methods.Release()

@property
def UUIDs(self):
def UUIDs(self): # pylint: disable=invalid-name
"""
128-bit GATT service UUIDs to auto connect.

Expand Down
3 changes: 2 additions & 1 deletion bluezero/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@


class AdapterError(Exception):
"""Custom exception for missing Bluetooth adapter"""
pass


Expand All @@ -26,7 +27,7 @@ def list_adapters():
return [dongle.address for dongle in Adapter.available()]


class Adapter(object):
class Adapter:
"""Bluetooth Adapter Class.

This class instantiates an object that interacts with the physical
Expand Down
22 changes: 13 additions & 9 deletions bluezero/advertisement.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,11 @@ def __init__(self, advert_id, ad_type):
}

def start(self):
"""Start GLib event loop"""
self.mainloop.run()

def stop(self):
"""Stop GLib event loop"""
self.mainloop.quit()

def get_path(self):
Expand All @@ -98,7 +100,7 @@ def get_path(self):
@dbus.service.method(constants.LE_ADVERTISEMENT_IFACE,
in_signature='',
out_signature='')
def Release(self):
def Release(self): # pylint: disable=invalid-name
"""
This method gets called when the service daemon
removes the Advertisement. A client can use it to do
Expand All @@ -110,13 +112,13 @@ def Release(self):
pass

@property
def service_UUIDs(self):
def service_UUIDs(self): # pylint: disable=invalid-name
"""List of UUIDs that represent available services."""
return self.Get(constants.LE_ADVERTISEMENT_IFACE,
'ServiceUUIDs')

@service_UUIDs.setter
def service_UUIDs(self, UUID):
def service_UUIDs(self, UUID): # pylint: disable=invalid-name
self.Set(constants.LE_ADVERTISEMENT_IFACE,
'ServiceUUIDs',
UUID)
Expand All @@ -125,7 +127,7 @@ def manufacturer_data(self):
"""Manufacturer Data to be broadcast (Currently not supported)"""
pass

def solicit_UUIDs(self):
def solicit_UUIDs(self): # pylint: disable=invalid-name
"""Manufacturer Data to be broadcast (Currently not supported)"""
pass

Expand All @@ -137,10 +139,10 @@ def service_data(self):

@service_data.setter
def service_data(self, data):
for UUID in data:
for uuid in data:
self.Set(constants.LE_ADVERTISEMENT_IFACE,
'ServiceData',
{UUID: dbus.Array(data[UUID], signature='y')})
{uuid: dbus.Array(data[uuid], signature='y')})

@property
def include_tx_power(self):
Expand Down Expand Up @@ -174,7 +176,7 @@ def appearance(self, appearance):
@dbus.service.method(constants.DBUS_PROP_IFACE,
in_signature='s',
out_signature='a{sv}')
def GetAll(self, interface_name):
def GetAll(self, interface_name): # pylint: disable=invalid-name
"""Return the advertisement properties.

This method is registered with the D-Bus at
Expand Down Expand Up @@ -219,7 +221,8 @@ def GetAll(self, interface_name):

@dbus.service.method(dbus.PROPERTIES_IFACE,
in_signature='ss', out_signature='v')
def Get(self, interface_name, property_name):
def Get(self, interface_name, # pylint: disable=invalid-name
property_name):
"""DBus API for getting a property value"""

if interface_name != constants.LE_ADVERTISEMENT_IFACE:
Expand All @@ -234,7 +237,8 @@ def Get(self, interface_name, property_name):

@dbus.service.method(dbus.PROPERTIES_IFACE,
in_signature='ssv', out_signature='')
def Set(self, interface_name, property_name, value, *args, **kwargs):
def Set(self, interface_name, property_name, value,
*args, **kwargs): # pylint: disable=invalid-name
"""Standard D-Bus API for setting a property value"""

try:
Expand Down
9 changes: 9 additions & 0 deletions bluezero/async_tools.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
"""
Collection of functions to work with the GLib Event Loop
"""
# Main eventloop import
import dbus
import dbus.mainloop.glib
Expand All @@ -9,20 +12,23 @@


def add_timer_ms(time, callback, data=None):
"""Call given callback every x milliseconds"""
if data:
GLib.timeout_add(time, callback, data)
else:
GLib.timeout_add(time, callback)


def add_timer_seconds(time, callback, data=None):
"""Call given callback every x seconds"""
if data:
GLib.timeout_add_seconds(time, callback, data)
else:
GLib.timeout_add_seconds(time, callback)


class EventLoop:
"""Facade class to help with using GLib event loop"""
# def generic_error_cb(self, error):
# """Generic Error Callback function."""
# logger.error('D-Bus call failed: ' + str(error))
Expand All @@ -36,10 +42,13 @@ def __init__(self):
self.mainloop = GLib.MainLoop()

def run(self):
"""Run event loop"""
self.mainloop.run()

def quit(self):
"""Stop event loop"""
self.mainloop.quit()

def is_running(self):
"""Check if event loop is running"""
self.mainloop.is_running()
2 changes: 1 addition & 1 deletion bluezero/broadcaster.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def include_tx_power(self, show_power=None):
:return:
"""
if show_power is None:
self.broadcaster.include_tx_power
return self.broadcaster.include_tx_power
else:
self.broadcaster.include_tx_power = show_power

Expand Down
7 changes: 5 additions & 2 deletions bluezero/central.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def __init__(self, device_addr, adapter_addr=None):
@staticmethod
def available(adapter_address=None):
"""Generator for getting a list of devices"""
return device.Device.available()
return device.Device.available(adapter_address)

def add_characteristic(self, srv_uuid, chrc_uuid):
"""
Expand All @@ -56,14 +56,15 @@ def load_gatt(self):
available = chrc.resolve_gatt()
if available:
logger.info('Service: %s and characteristic: %s added',
(chrc.srv_uuid, chrc.chrc_uuid))
chrc.srv_uuid, chrc.chrc_uuid)
else:
logger.warning('Service: %s and characteristic: %s not '
'available on device: %s', chrc.srv_uuid,
chrc.chrc_uuid, chrc.device_addr)

@property
def services_available(self):
"""Get a list of Service UUIDs available on this device"""
return self.rmt_device.services_available

@property
Expand Down Expand Up @@ -97,7 +98,9 @@ def disconnect(self):
self.rmt_device.disconnect()

def run(self):
"""Start event loop"""
self.dongle.run()

def quit(self):
"""Stop event loop"""
self.dongle.quit()
27 changes: 23 additions & 4 deletions bluezero/dbus_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
def bluez_version():
"""
get the version of the BlueZ daemon being used on the system

:return: String of BlueZ version
"""
p = subprocess.Popen(['bluetoothctl', '-v'], stdout=subprocess.PIPE)
ver = p.communicate()
return str(ver[0].decode().rstrip())
cmd = ['bluetoothctl', '-v']
cmd_output = subprocess.run(cmd, capture_output=True, check=True)
version = cmd_output.stdout.decode('utf-8').split()
return version[1]


def bluez_experimental_mode():
Expand Down Expand Up @@ -92,13 +94,22 @@ def get_managed_objects():


def get_mac_addr_from_dbus_path(path):
"""
[Deprecated] Function to get the address of a remote device from
a given D-Bus path. Path must include device part
(e.g. dev_XX_XX_XX_XX_XX_XX)
"""
logger.warning('get_mac_addr_from_dbus_path has been deprecated and has'
'been replaced with get_device_address_from_dbus_path')
return get_device_address_from_dbus_path(path)


def get_device_address_from_dbus_path(path):
"""Return the mac address from a dev_XX_XX_XX_XX_XX_XX dbus path"""
"""
[Deprecated] Function to get the address of a remote device from
a given D-Bus path. Path must include device part
(e.g. dev_XX_XX_XX_XX_XX_XX)
"""
for path_elem in path.split('/'):
if path_elem.startswith('dev_'):
return path_elem.replace("dev_", '').replace("_", ":")
Expand Down Expand Up @@ -323,6 +334,12 @@ def get_props(adapter=None,


def get_services(path_obj):
"""
Return a list of GATT Service UUIDs for a given Bluetooth device D-Bus path

:param path_obj: D-Bus path for remote Bluetooth device
:return: List of GATT Service UUIDs
"""
found_services = []
valid_structure = re.match(r'/org/bluez/hci\d+/dev(_([0-9A-Fa-f]){2}){6}',
path_obj)
Expand Down Expand Up @@ -378,8 +395,10 @@ def get(dbus_prop_obj, dbus_iface, prop_name, default=None):


def str_to_dbusarray(word):
"""Helper function to represent Python string as D-Dbus Byte array"""
return dbus.Array([dbus.Byte(ord(letter)) for letter in word], 'y')


def bytes_to_dbusarray(bytesarray):
"""Helper function to represent Python bytearray as D-Bus Byte array"""
return dbus.Array([dbus.Byte(elem) for elem in bytesarray], 'y')
4 changes: 2 additions & 2 deletions bluezero/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
logger = tools.create_module_logger(__name__)


class Device(object):
class Device:
"""Remote Bluetooth Device Class.

This class instantiates an object that interacts with a remote
Expand Down Expand Up @@ -207,7 +207,7 @@ def modalias(self):
constants.DEVICE_INTERFACE, 'Modalias')

@property
def RSSI(self):
def RSSI(self): # pylint: disable=invalid-name
"""
Received Signal Strength Indicator of the remote device.

Expand Down
Loading