| #!/usr/bin/python | |
| from __future__ import absolute_import, print_function, unicode_literals | |
| from optparse import OptionParser | |
| import os.path | |
| 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' | |
| FILE_TRASNFER_INTERFACE='org.bluez.obex.FileTransfer1' | |
| TRANSFER_INTERFACE='org.bluez.obex.Transfer1' | |
| def parse_options(): | |
| parser.add_option("-d", "--device", dest="device", | |
| help="Device to connect", metavar="DEVICE") | |
| parser.add_option("-c", "--chdir", dest="new_dir", | |
| help="Change current directory to DIR", metavar="DIR") | |
| parser.add_option("-l", "--list", action="store_true", dest="list_dir", | |
| help="List the current directory") | |
| parser.add_option("-g", "--get", dest="get_file", | |
| help="Get FILE", metavar="FILE") | |
| parser.add_option("-p", "--put", dest="put_file", | |
| help="Put FILE", metavar="FILE") | |
| parser.add_option("-y", "--copy", dest="copy_file", | |
| help="Copy FILE", metavar="FILE") | |
| parser.add_option("-m", "--move", dest="move_file", | |
| help="Move FILE", metavar="FILE") | |
| parser.add_option("-n", "--destname", dest="dest_file", | |
| help="Destination FILE", metavar="FILE") | |
| parser.add_option("-r", "--remove", dest="remove_file", | |
| help="Remove FILE", metavar="FILE") | |
| parser.add_option("-v", "--verbose", action="store_true", | |
| dest="verbose") | |
| return parser.parse_args() | |
| class FtpClient: | |
| def __init__(self, session_path, verbose=False): | |
| self.transferred = 0 | |
| self.transfer_path = None | |
| self.transfer_size = 0 | |
| self.verbose = verbose | |
| bus = dbus.SessionBus() | |
| obj = bus.get_object(BUS_NAME, session_path) | |
| self.session = dbus.Interface(obj, SESSION_INTERFACE) | |
| self.ftp = dbus.Interface(obj, FILE_TRASNFER_INTERFACE) | |
| bus.add_signal_receiver(self.properties_changed, | |
| dbus_interface="org.freedesktop.DBus.Properties", | |
| signal_name="PropertiesChanged", | |
| path_keyword="path") | |
| def create_transfer_reply(self, path, properties): | |
| self.transfer_path = path | |
| self.transfer_size = properties["Size"] | |
| if self.verbose: | |
| print("Transfer created: %s" % path) | |
| def generic_reply(self): | |
| if self.verbose: | |
| print("Operation succeeded") | |
| def error(self, err): | |
| print(err) | |
| mainloop.quit() | |
| def properties_changed(self, interface, properties, invalidated, path): | |
| if path != self.transfer_path: | |
| return | |
| if "Status" in properties and \ | |
| (properties['Status'] == 'complete' or \ | |
| properties['Status'] == 'error'): | |
| if self.verbose: | |
| print("Transfer %s" % properties['Status']) | |
| mainloop.quit() | |
| return | |
| if "Transferred" not in properties: | |
| return | |
| value = properties["Transferred"] | |
| speed = (value - self.transferred) / 1000 | |
| print("Transfer progress %d/%d at %d kBps" % (value, | |
| self.transfer_size, | |
| speed)) | |
| self.transferred = value | |
| def change_folder(self, new_dir): | |
| for node in new_dir.split("/"): | |
| self.ftp.ChangeFolder(node) | |
| def list_folder(self): | |
| for i in self.ftp.ListFolder(): | |
| if i["Type"] == "folder": | |
| print("%s/" % (i["Name"])) | |
| else: | |
| print("%s" % (i["Name"])) | |
| def put_file(self, filename): | |
| self.ftp.PutFile(os.path.abspath(filename), | |
| os.path.basename(filename), | |
| reply_handler=self.create_transfer_reply, | |
| error_handler=self.error) | |
| def get_file(self, filename): | |
| self.ftp.GetFile(os.path.abspath(filename), | |
| os.path.basename(filename), | |
| reply_handler=self.create_transfer_reply, | |
| error_handler=self.error) | |
| def remove_file(self, filename): | |
| self.ftp.Delete(filename, | |
| reply_handler=self.generic_reply, | |
| error_handler=self.error) | |
| def move_file(self, filename, destname): | |
| self.ftp.MoveFile(filename, destname, | |
| reply_handler=self.generic_reply, | |
| error_handler=self.error) | |
| def copy_file(self, filename, destname): | |
| self.ftp.CopyFile(filename, destname, | |
| reply_handler=self.generic_reply, | |
| error_handler=self.error) | |
| if __name__ == '__main__': | |
| dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) | |
| parser = OptionParser() | |
| (options, args) = parse_options() | |
| if not options.device: | |
| parser.print_help() | |
| sys.exit(0) | |
| bus = dbus.SessionBus() | |
| mainloop = GObject.MainLoop() | |
| client = dbus.Interface(bus.get_object(BUS_NAME, PATH,), | |
| CLIENT_INTERFACE) | |
| print("Creating Session") | |
| path = client.CreateSession(options.device, { "Target": "ftp" }) | |
| ftp_client = FtpClient(path, options.verbose) | |
| if options.new_dir: | |
| ftp_client.change_folder(options.new_dir) | |
| if options.list_dir: | |
| ftp_client.list_folder() | |
| if options.get_file: | |
| ftp_client.get_file(options.get_file) | |
| if options.put_file: | |
| ftp_client.put_file(options.put_file) | |
| if options.move_file: | |
| ftp_client.move_file(options.move_file, options.dest_file) | |
| if options.copy_file: | |
| ftp_client.copy_file(options.copy_file, options.dest_file) | |
| if options.remove_file: | |
| ftp_client.remove_file(options.remove_file) | |
| mainloop.run() |