An OBEX client class. (Note this is not available on Python for Series 60.)
For example, to connect to an OBEX server and send a file:
>>> import lightblue
>>> client = lightblue.obex.OBEXClient("aa:bb:cc:dd:ee:ff", 10)
>>> client.connect()
<OBEXResponse reason='OK' code=0x20 (0xa0) headers={}>
>>> client.put({"name": "photo.jpg"}, file("photo.jpg", "rb"))
<OBEXResponse reason='OK' code=0x20 (0xa0) headers={}>
>>> client.disconnect()
<OBEXResponse reason='OK' code=0x20 (0xa0) headers={}>
>>>
A client must call connect() to establish a connection before it can send
any other requests.
The connect(), disconnect(), put(), delete(), get() and setpath() methods
all accept the request headers as a dictionary of header-value mappings. The
request headers are used to provide the server with additional information
for the request. For example, this sends a Put request that includes Name,
Type and Length headers in the request headers, to provide details about
the transferred file:
>>> f = file("file.txt")
>>> client.put({"name": "file.txt", "type": "text/plain",
... "length": 5192}, f)
>>>
Here is a list of all the different string header keys that you can use in
the request headers, and the expected type of the value for each header:
- "name" -> a string
- "type" -> a string
- "length" -> an int
- "time" -> a datetime object from the datetime module
- "description" -> a string
- "target" -> a string or buffer
- "http" -> a string or buffer
- "who" -> a string or buffer
- "connection-id" -> an int
- "application-parameters" -> a string or buffer
- "authentication-challenge" -> a string or buffer
- "authentication-response" -> a string or buffer
- "creator-id" -> an int
- "wan-uuid" -> a string or buffer
- "object-class" -> a string or buffer
- "session-parameters" -> a string or buffer
- "session-sequence-number" -> an int less than 256
(The string header keys are not case-sensitive.)
Alternatively, you can use raw header ID values instead of the above
convenience strings. So, the previous example can be rewritten as:
>>> client.put({0x01: "file.txt", 0x42: "text/plain", 0xC3: 5192},
... fileobject)
>>>
This is also useful for inserting custom headers. For example, a PutImage
request for a Basic Imaging client requires the Img-Descriptor (0x71)
header:
>>> client.put({"type": "x-bt/img-img",
... "name": "photo.jpg",
... 0x71: '<image-descriptor version="1.0"><image encoding="JPEG" pixel="160*120" size="37600"/></image-descriptor>'},
... file('photo.jpg', 'rb'))
>>>
Notice that the connection-id header is not sent, because this is
automatically included by OBEXClient in the request headers if a
connection-id was received in a previous Connect response.
See the included src/examples/obex_ftp_client.py for an example of using
OBEXClient to implement a File Transfer client for browsing the files on a
remote device.
Methods
__init__(address, channel)
Creates an OBEX client.
Arguments:
- address: the address of the remote device
- channel: the RFCOMM channel of the remote OBEX service
connect(headers={})
Establishes the Bluetooth connection to the remote OBEX server and sends
a Connect request to open the OBEX session. Returns an OBEXResponse
instance containing the server response.
Raises lightblue.obex.OBEXError if the session is already connected, or if
an error occurs during the request.
If the server refuses the Connect request (i.e. if it sends a response code
other than OK/Success), the Bluetooth connection will be closed.
Arguments:
- headers={}: the headers to send for the Connect request
disconnect(headers={})
Sends a Disconnect request to end the OBEX session and closes the Bluetooth
connection to the remote OBEX server. Returns an OBEXResponse
instance containing the server response.
Raises lightblue.obex.OBEXError if connect() has not been called, or if an
error occurs during the request.
Note that you don't need to send any connection-id headers - this is
automatically included if the client received one in a Connect response.
Arguments:
- headers={}: the headers to send for the request
put(headers, fileobj)
Sends a Put request. Returns an OBEXResponse instance containing the
server response.
Raises lightblue.obex.OBEXError if connect() has not been called, or if an
error occurs during the request.
Note that you don't need to send any connection-id headers - this is
automatically included if the client received one in a Connect response.
Arguments:
- headers: the headers to send for the request
- fileobj: a file-like object containing the file data to be sent for
the request
For example, to send a file named 'photo.jpg', using the request headers
to notify the server of the file's name, MIME type and length:
>>> client = lightblue.obex.OBEXClient("aa:bb:cc:dd:ee:ff", 10)
>>> client.connect()
<OBEXResponse reason='OK' code=0x20 (0xa0) headers={}>
>>> client.put({"name": "photo.jpg", "type": "image/jpeg",
"length": 28566}, file("photo.jpg", "rb"))
<OBEXResponse reason='OK' code=0x20 (0xa0) headers={}>
>>>
delete(headers)
Sends a Put-Delete request in order to delete a file or folder on the remote
server. Returns an OBEXResponse instance containing the server response.
Raises lightblue.obex.OBEXError if connect() has not been called, or if an
error occurs during the request.
Note that you don't need to send any connection-id headers - this is
automatically included if the client received one in a Connect response.
Arguments:
- headers: the headers to send for the request - you should use the
'name' header to specify the file you want to delete
If the file on the server can't be deleted because it's a read-only file,
you might get an 'Unauthorized' response, like this:
>>> client = lightblue.obex.OBEXClient("aa:bb:cc:dd:ee:ff", 10)
>>> client.connect()
<OBEXResponse reason='OK' code=0x20 (0xa0) headers={}>
>>> client.delete({"name": "random_file.txt"})
<OBEXResponse reason='Unauthorized' code=0x41 (0xc1) headers={}>
>>>
get(headers, fileobj)
Sends a Get request. Returns an OBEXResponse instance containing the server
response.
Raises lightblue.obex.OBEXError if connect() has not been called, or if an
error occurs during the request.
Note that you don't need to send any connection-id headers - this is
automatically included if the client received one in a Connect response.
Arguments:
- headers: the headers to send for the request - you should use these
to specify the file you want to retrieve
- fileobj: a file-like object, to which the received data will be
written
An example:
>>> client.connect()
<OBEXResponse reason='OK' code=0x20 (0xa0) headers={}>
>>> f = file("received_file.txt", "w+")
>>> client.get({"name": "testfile.txt"}, f)
<OBEXResponse reason='OK' code=0x20 (0xa0) headers={'length':9}>
>>> f.seek(0)
>>> f.read()
'test file'
>>>
setpath(headers, cdtoparent=False, createdirs=False)
Sends a SetPath request in order to set the "current path" on the remote
server for file transfers. Returns an OBEXResponse instance containing the
server response.
Raises lightblue.obex.OBEXError if connect() has not been called, or if an
error occurs during the request.
Note that you don't need to send any connection-id headers - this is
automatically included if the client received one in a Connect response.
Arguments:
- headers: the headers to send for the request - you should use the
'name' header to specify the directory you want to change to
- cdtoparent=False: True if the remote server should move up one
directory before applying the specified directory (i.e. 'cd
../dirname')
- createdirs=False: True if the specified directory should be created
if it doesn't exist (if False, the server will return an error
response if the directory doesn't exist)
For example:
>>> client.setpath({"name": "images"})
<OBEXResponse reason='OK' code=0x20 (0xa0) headers={}>
>>>
>>> client.setpath({}, cdtoparent=True)
<OBEXResponse reason='OK' code=0x20 (0xa0) headers={}>
>>>
>>> client.setpath({"name": "My_Files"}, createdirs=True)
<OBEXResponse reason='OK' code=0x20 (0xa0) headers={}>
>>>
>>> client.setpath({"name": ""})
<OBEXResponse reason='OK' code=0x20 (0xa0) headers={}>
>>>