|
#!/usr/bin/python |
|
|
|
from __future__ import absolute_import, print_function, unicode_literals |
|
|
|
import os |
|
import sys |
|
import dbus |
|
import dbus.service |
|
import dbus.mainloop.glib |
|
try: |
|
from gi.repository import GObject |
|
except ImportError: |
|
import gobject as GObject |
|
|
|
BUS_NAME='org.bluez.obex' |
|
PATH = '/org/bluez/obex' |
|
CLIENT_INTERFACE = 'org.bluez.obex.Client1' |
|
SESSION_INTERFACE = 'org.bluez.obex.Session1' |
|
PHONEBOOK_ACCESS_INTERFACE = 'org.bluez.obex.PhonebookAccess1' |
|
TRANSFER_INTERFACE = 'org.bluez.obex.Transfer1' |
|
|
|
class Transfer: |
|
def __init__(self, callback_func): |
|
self.callback_func = callback_func |
|
self.path = None |
|
self.filename = None |
|
|
|
class PbapClient: |
|
def __init__(self, session_path): |
|
self.transfers = 0 |
|
self.props = dict() |
|
self.flush_func = None |
|
bus = dbus.SessionBus() |
|
obj = bus.get_object(BUS_NAME, session_path) |
|
self.session = dbus.Interface(obj, SESSION_INTERFACE) |
|
self.pbap = dbus.Interface(obj, PHONEBOOK_ACCESS_INTERFACE) |
|
bus.add_signal_receiver(self.properties_changed, |
|
dbus_interface="org.freedesktop.DBus.Properties", |
|
signal_name="PropertiesChanged", |
|
path_keyword="path") |
|
|
|
def register(self, path, properties, transfer): |
|
transfer.path = path |
|
transfer.filename = properties["Filename"] |
|
self.props[path] = transfer |
|
print("Transfer created: %s (file %s)" % (path, |
|
transfer.filename)) |
|
|
|
def error(self, err): |
|
print(err) |
|
mainloop.quit() |
|
|
|
def transfer_complete(self, path): |
|
req = self.props.get(path) |
|
if req == None: |
|
return |
|
self.transfers -= 1 |
|
print("Transfer %s complete" % path) |
|
try: |
|
f = open(req.filename, "r") |
|
os.remove(req.filename) |
|
lines = f.readlines() |
|
del self.props[path] |
|
req.callback_func(lines) |
|
except: |
|
pass |
|
|
|
if (len(self.props) == 0) and (self.transfers == 0): |
|
if self.flush_func != None: |
|
f = self.flush_func |
|
self.flush_func = None |
|
f() |
|
|
|
def transfer_error(self, path): |
|
print("Transfer %s error" % path) |
|
mainloop.quit() |
|
|
|
def properties_changed(self, interface, properties, invalidated, path): |
|
req = self.props.get(path) |
|
if req == None: |
|
return |
|
|
|
if properties['Status'] == 'complete': |
|
self.transfer_complete(path) |
|
return |
|
|
|
if properties['Status'] == 'error': |
|
self.transfer_error(path) |
|
return |
|
|
|
def pull(self, vcard, params, func): |
|
req = Transfer(func) |
|
self.pbap.Pull(vcard, "", params, |
|
reply_handler=lambda o, p: self.register(o, p, req), |
|
error_handler=self.error) |
|
self.transfers += 1 |
|
|
|
def pull_all(self, params, func): |
|
req = Transfer(func) |
|
self.pbap.PullAll("", params, |
|
reply_handler=lambda o, p: self.register(o, p, req), |
|
error_handler=self.error) |
|
self.transfers += 1 |
|
|
|
def flush_transfers(self, func): |
|
if (len(self.props) == 0) and (self.transfers == 0): |
|
return |
|
self.flush_func = func |
|
|
|
def interface(self): |
|
return self.pbap |
|
|
|
if __name__ == '__main__': |
|
|
|
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) |
|
|
|
bus = dbus.SessionBus() |
|
mainloop = GObject.MainLoop() |
|
|
|
client = dbus.Interface(bus.get_object(BUS_NAME, PATH), |
|
CLIENT_INTERFACE) |
|
|
|
if (len(sys.argv) < 2): |
|
print("Usage: %s <device>" % (sys.argv[0])) |
|
sys.exit(1) |
|
|
|
print("Creating Session") |
|
session_path = client.CreateSession(sys.argv[1], { "Target": "PBAP" }) |
|
|
|
pbap_client = PbapClient(session_path) |
|
|
|
def process_result(lines, header): |
|
if header != None: |
|
print(header) |
|
for line in lines: |
|
print(line), |
|
print |
|
|
|
def test_paths(paths): |
|
if len(paths) == 0: |
|
print |
|
print("FINISHED") |
|
mainloop.quit() |
|
return |
|
|
|
path = paths[0] |
|
|
|
print("\n--- Select Phonebook %s ---\n" % (path)) |
|
pbap_client.interface().Select("int", path) |
|
|
|
print("\n--- GetSize ---\n") |
|
ret = pbap_client.interface().GetSize() |
|
print("Size = %d\n" % (ret)) |
|
|
|
print("\n--- List vCard ---\n") |
|
try: |
|
ret = pbap_client.interface().List(dbus.Dictionary()) |
|
except: |
|
ret = [] |
|
|
|
params = dbus.Dictionary({ "Format" : "vcard30", |
|
"Fields" : ["PHOTO"] }) |
|
for item in ret: |
|
print("%s : %s" % (item[0], item[1])) |
|
pbap_client.pull(item[0], params, |
|
lambda x: process_result(x, None)) |
|
|
|
pbap_client.pull_all(params, lambda x: process_result(x, |
|
"\n--- PullAll ---\n")) |
|
|
|
pbap_client.flush_transfers(lambda: test_paths(paths[1:])) |
|
|
|
test_paths(["PB", "ICH", "OCH", "MCH", "CCH", "SPD", "FAV"]) |
|
|
|
mainloop.run() |