Source code for bt_manager.agent

from __future__ import unicode_literals

import dbus.service

from exceptions import BTRejectedException


[docs]class BTAgent(dbus.service.Object): """ Simple BT device pairing agent. A bluetooth pairing agent is responsible for admitting new devices onto the system and registering them for subsequent use. The procedure is abstracted away into a service object that implements a few procedures depending on the type of pairing scheme in use. Different pairing schemes are required since some devices do not have displays or keypads allowing them to enter passkeys or confirm passkeys. The SSP (Secure Simple Pairing) schemes that can be supported using this agent are: * `Just works`: No user interaction required. * `Numeric comparison`: A pass key is displayed which the receiving device must confirm with a binary yes/no response. * `Passkey entry`: A pass key must be entered manually which the receiving device must confirm by also entering the same pass key. The pairing scheme selected will be dependent on the `capability` of the agent which is defined when the agent is registered via the :py:meth:`.BTAdapter.register_agent` method. See also: :py:class:`.BTAdapter` """ NOTIFY_ON_RELEASE = 'Release' NOTIFY_ON_AUTHORIZE = 'Authorize' NOTIFY_ON_REQUEST_PIN_CODE = 'RequestPinCode' NOTIFY_ON_REQUEST_PASS_KEY = 'RequestPasskey' NOTIFY_ON_DISPLAY_PASS_KEY = 'DisplayPasskey' NOTIFY_ON_REQUEST_CONFIRMATION = 'RequestConfirmation' NOTIFY_ON_CONFIRM_MODE_CHANGE = 'ConfirmModeChange' NOTIFY_ON_CANCEL = 'Cancel' def __init__(self, path='/test/agent', auto_authorize_connections=True, default_pin_code='0000', default_pass_key=0, # Range: 0-999999 cb_notify_on_release=None, cb_notify_on_authorize=None, cb_notify_on_request_pin_code=None, cb_notify_on_request_pass_key=None, cb_notify_on_display_pass_key=None, cb_notify_on_request_confirmation=None, cb_notify_on_confirm_mode_change=None, cb_notify_on_cancel=None): self.auto_authorize_connections = auto_authorize_connections self.default_pin_code = default_pin_code self.default_pass_key = default_pass_key self.cb_notify_on_release = cb_notify_on_release self.cb_notify_on_authorize = cb_notify_on_authorize self.cb_notify_on_request_pin_code = cb_notify_on_request_pin_code self.cb_notify_on_request_pass_key = cb_notify_on_request_pass_key self.cb_notify_on_display_pass_key = cb_notify_on_display_pass_key self.cb_notify_on_request_confirmation = \ cb_notify_on_request_confirmation self.cb_notify_on_confirm_mode_change = \ cb_notify_on_confirm_mode_change self.cb_notify_on_cancel = cb_notify_on_cancel bus = dbus.SystemBus() super(BTAgent, self).__init__(bus, path) # Service object entry points defined below here @dbus.service.method("org.bluez.Agent", in_signature="", out_signature="") def Release(self): if (self.cb_notify_on_release): self.cb_notify_on_release(BTAgent.NOTIFY_ON_RELEASE) @dbus.service.method("org.bluez.Agent", in_signature="os", out_signature="") def Authorize(self, device, uuid): if (self.cb_notify_on_authorize): if (not self.cb_notify_on_authorize(BTAgent.NOTIFY_ON_AUTHORIZE, device, uuid)): raise BTRejectedException('Connection not authorized by user') elif (not self.auto_authorize_connections): raise BTRejectedException('Auto authorize is off') @dbus.service.method("org.bluez.Agent", in_signature="o", out_signature="s") def RequestPinCode(self, device): if (self.cb_notify_on_request_pin_code): pin_code = self.cb_notify_on_request_pin_code(BTAgent.NOTIFY_ON_REQUEST_PIN_CODE, # noqa device) if (pin_code is None): raise BTRejectedException('User did not provide PIN code') elif (self.default_pin_code is None): raise BTRejectedException('No default PIN code set') else: pin_code = self.default_pin_code return dbus.String(pin_code) @dbus.service.method("org.bluez.Agent", in_signature="o", out_signature="s") def RequestPasskey(self, device): if (self.cb_notify_on_request_pass_key): pass_key = self.cb_notify_on_request_pass_key(BTAgent.NOTIFY_ON_REQUEST_PASS_KEY, # noqa device) if (pass_key is None): raise BTRejectedException('User did not provide pass key') elif (self.default_pass_key is None): raise BTRejectedException('No default pass key set') else: pass_key = self.default_pass_key return dbus.UInt32(pass_key) @dbus.service.method("org.bluez.Agent", in_signature="ou", out_signature="") def DisplayPasskey(self, device, pass_key): if (self.cb_notify_on_display_pass_key): self.cb_notify_on_display_pass_key(BTAgent.NOTIFY_ON_DISPLAY_PASS_KEY, # noqa device, pass_key) @dbus.service.method("org.bluez.Agent", in_signature="ou", out_signature="") def RequestConfirmation(self, device, pass_key): if (self.cb_notify_on_request_confirmation): if (not self.cb_notify_on_request_confirmation(BTAgent.NOTIFY_ON_REQUEST_CONFIRMATION, # noqa device, pass_key)): raise \ BTRejectedException('User confirmation of pass key negative') # noqa @dbus.service.method("org.bluez.Agent", in_signature="s", out_signature="") def ConfirmModeChange(self, mode): if (self.cb_notify_on_confirm_mode_change): if (not self.cb_notify_on_confirm_mode_change(BTAgent.NOTIFY_ON_CONFIRM_MODE_CHANGE, # noqa mode)): raise \ BTRejectedException('User mode change confirmation negative') # noqa @dbus.service.method("org.bluez.Agent", in_signature="", out_signature="") def Cancel(self): if (self.cb_notify_on_cancel): self.cb_notify_on_cancel(BTAgent.NOTIFY_ON_CANCEL)