diff options
Diffstat (limited to 'pybluez')
| -rw-r--r-- | pybluez/advanced/inquiry-with-rssi.py | 148 | ||||
| -rw-r--r-- | pybluez/advanced/l2-mtu.py | 60 | ||||
| -rw-r--r-- | pybluez/advanced/l2-unreliable-client.py | 76 | ||||
| -rw-r--r-- | pybluez/advanced/l2-unreliable-server.py | 34 | ||||
| -rw-r--r-- | pybluez/advanced/read-local-bdaddr.py | 35 | ||||
| -rw-r--r-- | pybluez/advanced/write-inquiry-scan.py | 90 | ||||
| -rw-r--r-- | pybluez/bluezchat/bluezchat.glade | 138 | ||||
| -rwxr-xr-x | pybluez/bluezchat/bluezchat.py | 191 | ||||
| -rw-r--r-- | pybluez/simple/asynchronous-inquiry.py | 65 | ||||
| -rw-r--r-- | pybluez/simple/inquiry.py | 17 | ||||
| -rw-r--r-- | pybluez/simple/l2capclient.py | 28 | ||||
| -rw-r--r-- | pybluez/simple/l2capserver.py | 32 | ||||
| -rw-r--r-- | pybluez/simple/rfcomm-client.py | 45 | ||||
| -rw-r--r-- | pybluez/simple/rfcomm-server.py | 41 | ||||
| -rw-r--r-- | pybluez/simple/sdp-browse.py | 35 |
15 files changed, 1035 insertions, 0 deletions
diff --git a/pybluez/advanced/inquiry-with-rssi.py b/pybluez/advanced/inquiry-with-rssi.py new file mode 100644 index 0000000..814f7ed --- /dev/null +++ b/pybluez/advanced/inquiry-with-rssi.py @@ -0,0 +1,148 @@ +# performs a simple device inquiry, followed by a remote name request of each +# discovered device + +import os +import sys +import struct +import bluetooth._bluetooth as bluez + +def printpacket(pkt): + for c in pkt: + sys.stdout.write("%02x " % struct.unpack("B",c)[0]) + print + + +def read_inquiry_mode(sock): + """returns the current mode, or -1 on failure""" + # save current filter + old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14) + + # Setup socket filter to receive only events related to the + # read_inquiry_mode command + flt = bluez.hci_filter_new() + opcode = bluez.cmd_opcode_pack(bluez.OGF_HOST_CTL, + bluez.OCF_READ_INQUIRY_MODE) + bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) + bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE); + bluez.hci_filter_set_opcode(flt, opcode) + sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt ) + + # first read the current inquiry mode. + bluez.hci_send_cmd(sock, bluez.OGF_HOST_CTL, + bluez.OCF_READ_INQUIRY_MODE ) + + pkt = sock.recv(255) + + status,mode = struct.unpack("xxxxxxBB", pkt) + if status != 0: mode = -1 + + # restore old filter + sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter ) + return mode + +def write_inquiry_mode(sock, mode): + """returns 0 on success, -1 on failure""" + # save current filter + old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14) + + # Setup socket filter to receive only events related to the + # write_inquiry_mode command + flt = bluez.hci_filter_new() + opcode = bluez.cmd_opcode_pack(bluez.OGF_HOST_CTL, + bluez.OCF_WRITE_INQUIRY_MODE) + bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) + bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE); + bluez.hci_filter_set_opcode(flt, opcode) + sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt ) + + # send the command! + bluez.hci_send_cmd(sock, bluez.OGF_HOST_CTL, + bluez.OCF_WRITE_INQUIRY_MODE, struct.pack("B", mode) ) + + pkt = sock.recv(255) + + status = struct.unpack("xxxxxxB", pkt)[0] + + # restore old filter + sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter ) + if status != 0: return -1 + return 0 + +def device_inquiry_with_with_rssi(sock): + # save current filter + old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14) + + # perform a device inquiry on bluetooth device #0 + # The inquiry should last 8 * 1.28 = 10.24 seconds + # before the inquiry is performed, bluez should flush its cache of + # previously discovered devices + flt = bluez.hci_filter_new() + bluez.hci_filter_all_events(flt) + bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) + sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt ) + + duration = 4 + max_responses = 255 + cmd_pkt = struct.pack("BBBBB", 0x33, 0x8b, 0x9e, duration, max_responses) + bluez.hci_send_cmd(sock, bluez.OGF_LINK_CTL, bluez.OCF_INQUIRY, cmd_pkt) + + results = [] + + done = False + while not done: + pkt = sock.recv(255) + ptype, event, plen = struct.unpack("BBB", pkt[:3]) + if event == bluez.EVT_INQUIRY_RESULT_WITH_RSSI: + pkt = pkt[3:] + nrsp = struct.unpack("B", pkt[0])[0] + for i in range(nrsp): + addr = bluez.ba2str( pkt[1+6*i:1+6*i+6] ) + rssi = struct.unpack("b", pkt[1+13*nrsp+i])[0] + results.append( ( addr, rssi ) ) + print "[%s] RSSI: [%d]" % (addr, rssi) + elif event == bluez.EVT_INQUIRY_COMPLETE: + done = True + elif event == bluez.EVT_CMD_STATUS: + status, ncmd, opcode = struct.unpack("BBH", pkt[3:7]) + if status != 0: + print "uh oh..." + printpacket(pkt[3:7]) + done = True + else: + print "unrecognized packet type 0x%02x" % ptype + + + # restore old filter + sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter ) + + return results + +dev_id = 0 +try: + sock = bluez.hci_open_dev(dev_id) +except: + print "error accessing bluetooth device..." + sys.exit(1) + +try: + mode = read_inquiry_mode(sock) +except Exception, e: + print "error reading inquiry mode. " + print "Are you sure this a bluetooth 1.2 device?" + print e + sys.exit(1) +print "current inquiry mode is %d" % mode + +if mode != 1: + print "writing inquiry mode..." + try: + result = write_inquiry_mode(sock, 1) + except Exception, e: + print "error writing inquiry mode. Are you sure you're root?" + print e + sys.exit(1) + if result != 0: + print "error while setting inquiry mode" + print "result: %d" % result + +device_inquiry_with_with_rssi(sock) diff --git a/pybluez/advanced/l2-mtu.py b/pybluez/advanced/l2-mtu.py new file mode 100644 index 0000000..1ffe04c --- /dev/null +++ b/pybluez/advanced/l2-mtu.py @@ -0,0 +1,60 @@ +import sys +import struct +import bluetooth + +def usage(): + print "usage: l2-mtu < server | client > [options]" + print "" + print "l2-mtu server to start in server mode" + print "l2-mtu client <addr> to start in client mode and connect to addr" + sys.exit(2) + +if len(sys.argv) < 2: usage() + +mode = sys.argv[1] +if mode not in [ "client", "server" ]: usage() + +if mode == "server": + server_sock=bluetooth.BluetoothSocket( bluetooth.L2CAP ) + server_sock.bind(("",0x1001)) + server_sock.listen(1) + while True: + print "waiting for incoming connection" + client_sock,address = server_sock.accept() + print "Accepted connection from %s" % str(address) + + bluetooth.set_l2cap_mtu( client_sock, 65535 ) + + print "waiting for data" + total = 0 + while True: + try: + data = client_sock.recv(65535) + except bluetooth.BluetoothError, e: + break + if len(data) == 0: break + print "received packet of size %d" % len(data) + + client_sock.close() + + print "connection closed" + + server_sock.close() +else: + sock=bluetooth.BluetoothSocket(bluetooth.L2CAP) + + bt_addr = sys.argv[2] + print "trying to connect to %s:1001" % bt_addr + port = 0x1001 + sock.connect((bt_addr, port)) + + print "connected. Adjusting link parameters." + bluetooth.set_l2cap_mtu( sock, 65535 ) + + totalsent = 0 + for i in range(1, 65535, 100): + pkt = "0" * i + sent = sock.send(pkt) + print "sent packet of size %d (tried %d)" % (sent, len(pkt)) + + sock.close() diff --git a/pybluez/advanced/l2-unreliable-client.py b/pybluez/advanced/l2-unreliable-client.py new file mode 100644 index 0000000..5b10a48 --- /dev/null +++ b/pybluez/advanced/l2-unreliable-client.py @@ -0,0 +1,76 @@ +import sys +import fcntl +import struct +import array +import bluetooth +import bluetooth._bluetooth as bt # low level bluetooth wrappers. + +def __get_acl_conn_handle(sock, addr): + hci_fd = sock.fileno() + reqstr = struct.pack( "6sB17s", bt.str2ba(addr), bt.ACL_LINK, "\0" * 17) + request = array.array( "c", reqstr ) + fcntl.ioctl( hci_fd, bt.HCIGETCONNINFO, request, 1 ) + handle = struct.unpack("8xH14x", request.tostring())[0] + return handle + +def write_flush_timeout( addr, timeout ): + hci_sock = bt.hci_open_dev() + # get the ACL connection handle to the remote device + handle = __get_acl_conn_handle(hci_sock, addr) + pkt = struct.pack("HH", handle, bt.htobs(timeout)) + response = bt.hci_send_req(hci_sock, bt.OGF_HOST_CTL, + 0x0028, bt.EVT_CMD_COMPLETE, 3, pkt) + status = struct.unpack("B", response[0])[0] + rhandle = struct.unpack("H", response[1:3])[0] + assert rhandle == handle + assert status == 0 + +def read_flush_timeout( addr ): + hci_sock = bt.hci_open_dev() + # get the ACL connection handle to the remote device + handle = __get_acl_conn_handle(hci_sock, addr) + pkt = struct.pack("H", handle) + response = bt.hci_send_req(hci_sock, bt.OGF_HOST_CTL, + 0x0027, bt.EVT_CMD_COMPLETE, 5, pkt) + status = struct.unpack("B", response[0])[0] + rhandle = struct.unpack("H", response[1:3])[0] + assert rhandle == handle + assert status == 0 + fto = struct.unpack("H", response[3:5])[0] + return fto + +# Create the client socket +sock=bluetooth.BluetoothSocket(bluetooth.L2CAP) + +if len(sys.argv) < 4: + print "usage: l2capclient.py <addr> <timeout> <num_packets>" + print " address - device that l2-unreliable-server is running on" + print " timeout - wait timeout * 0.625ms before dropping unACK'd packets" + print " num_packets - number of 627-byte packets to send on connect" + sys.exit(2) + +bt_addr=sys.argv[1] +timeout = int(sys.argv[2]) +num_packets = int(sys.argv[3]) + +print "trying to connect to %s:1001" % bt_addr +port = 0x1001 +sock.connect((bt_addr, port)) + +print "connected. Adjusting link parameters." +print "current flush timeout is %d ms" % read_flush_timeout( bt_addr ) +try: + write_flush_timeout( bt_addr, timeout ) +except bt.error, e: + print "error setting flush timeout. are you sure you're superuser?" + print e + sys.exit(1) +print "new flush timeout is %d ms" % read_flush_timeout( bt_addr ) + +totalsent = 0 +for i in range(num_packets): + pkt = "0" * 672 + totalsent += sock.send(pkt) +print "sent %d bytes total" % totalsent + +sock.close() diff --git a/pybluez/advanced/l2-unreliable-server.py b/pybluez/advanced/l2-unreliable-server.py new file mode 100644 index 0000000..d827775 --- /dev/null +++ b/pybluez/advanced/l2-unreliable-server.py @@ -0,0 +1,34 @@ +import sys +import bluetooth + +if len(sys.argv) < 2: + print "usage: l2-unreliable-server" + sys.exit(2) + +timeout = int(sys.argv[1]) +assert timeout >= 0 + +server_sock=bluetooth.BluetoothSocket( bluetooth.L2CAP ) +server_sock.bind(("",0x1001)) +server_sock.listen(1) +while True: + print "waiting for incoming connection" + client_sock,address = server_sock.accept() + print "Accepted connection from %s" % str(address) + + print "waiting for data" + total = 0 + while True: + try: + data = client_sock.recv(1024) + except bluetooth.BluetoothError, e: + break + if len(data) == 0: break + total += len(data) + print "total byte read: %d" % total + + client_sock.close() + + print "connection closed" + +server_sock.close() diff --git a/pybluez/advanced/read-local-bdaddr.py b/pybluez/advanced/read-local-bdaddr.py new file mode 100644 index 0000000..410a681 --- /dev/null +++ b/pybluez/advanced/read-local-bdaddr.py @@ -0,0 +1,35 @@ +import os +import sys +import struct +import bluetooth._bluetooth as _bt + +def read_local_bdaddr(hci_sock): + old_filter = hci_sock.getsockopt( _bt.SOL_HCI, _bt.HCI_FILTER, 14) + flt = _bt.hci_filter_new() + opcode = _bt.cmd_opcode_pack(_bt.OGF_INFO_PARAM, + _bt.OCF_READ_BD_ADDR) + _bt.hci_filter_set_ptype(flt, _bt.HCI_EVENT_PKT) + _bt.hci_filter_set_event(flt, _bt.EVT_CMD_COMPLETE); + _bt.hci_filter_set_opcode(flt, opcode) + hci_sock.setsockopt( _bt.SOL_HCI, _bt.HCI_FILTER, flt ) + + _bt.hci_send_cmd(hci_sock, _bt.OGF_INFO_PARAM, _bt.OCF_READ_BD_ADDR ) + + pkt = hci_sock.recv(255) + + status,raw_bdaddr = struct.unpack("xxxxxxB6s", pkt) + assert status == 0 + + t = [ "%X" % ord(b) for b in raw_bdaddr ] + t.reverse() + bdaddr = ":".join(t) + + # restore old filter + hci_sock.setsockopt( _bt.SOL_HCI, _bt.HCI_FILTER, old_filter ) + return bdaddr + +if __name__ == "__main__": + dev_id = 0 + hci_sock = _bt.hci_open_dev(dev_id) + bdaddr = read_local_bdaddr(hci_sock) + print bdaddr diff --git a/pybluez/advanced/write-inquiry-scan.py b/pybluez/advanced/write-inquiry-scan.py new file mode 100644 index 0000000..54793b7 --- /dev/null +++ b/pybluez/advanced/write-inquiry-scan.py @@ -0,0 +1,90 @@ +import os +import sys +import struct +import bluetooth._bluetooth as bluez + +def read_inquiry_scan_activity(sock): + """returns the current inquiry scan interval and window, + or -1 on failure""" + # save current filter + old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14) + + # Setup socket filter to receive only events related to the + # read_inquiry_mode command + flt = bluez.hci_filter_new() + opcode = bluez.cmd_opcode_pack(bluez.OGF_HOST_CTL, + bluez.OCF_READ_INQ_ACTIVITY) + bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) + bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE); + bluez.hci_filter_set_opcode(flt, opcode) + sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt ) + + # first read the current inquiry mode. + bluez.hci_send_cmd(sock, bluez.OGF_HOST_CTL, + bluez.OCF_READ_INQ_ACTIVITY ) + + pkt = sock.recv(255) + + status,interval,window = struct.unpack("!xxxxxxBHH", pkt) + interval = bluez.btohs(interval) + interval = (interval >> 8) | ( (interval & 0xFF) << 8 ) + window = (window >> 8) | ( (window & 0xFF) << 8 ) + if status != 0: mode = -1 + + # restore old filter + sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter ) + return interval, window + +def write_inquiry_scan_activity(sock, interval, window): + """returns 0 on success, -1 on failure""" + # save current filter + old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14) + + # Setup socket filter to receive only events related to the + # write_inquiry_mode command + flt = bluez.hci_filter_new() + opcode = bluez.cmd_opcode_pack(bluez.OGF_HOST_CTL, + bluez.OCF_WRITE_INQ_ACTIVITY) + bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) + bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE); + bluez.hci_filter_set_opcode(flt, opcode) + sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt ) + + # send the command! + bluez.hci_send_cmd(sock, bluez.OGF_HOST_CTL, + bluez.OCF_WRITE_INQ_ACTIVITY, struct.pack("HH", + interval, window) ) + + pkt = sock.recv(255) + + status = struct.unpack("xxxxxxB", pkt)[0] + + # restore old filter + sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter ) + if status != 0: return -1 + return 0 + +dev_id = 0 +try: + sock = bluez.hci_open_dev(dev_id) +except: + print "error accessing bluetooth device..." + sys.exit(1) + +try: + interval, window = read_inquiry_scan_activity(sock) +except Exception, e: + print "error reading inquiry scan activity. " + print e + sys.exit(1) +print "current inquiry scan interval: %d (0x%X) window: %d (0x%X)" % \ + (interval, interval, window, window) + +if len(sys.argv) == 3: + interval = int(sys.argv[1]) + window = int(sys.argv[2]) + print "target interval: %d window %d" % (interval, window) + write_inquiry_scan_activity(sock, interval, window) + interval, window = read_inquiry_scan_activity(sock) + print "current inquiry scan interval: %d (0x%X) window: %d (0x%X)" % \ + (interval, interval, window, window) diff --git a/pybluez/bluezchat/bluezchat.glade b/pybluez/bluezchat/bluezchat.glade new file mode 100644 index 0000000..b3f37eb --- /dev/null +++ b/pybluez/bluezchat/bluezchat.glade @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> +<!--*- mode: xml -*--> +<glade-interface> + <widget class="GtkWindow" id="bluezchat_window"> + <property name="visible">True</property> + <property name="title" translatable="yes">bluez chat</property> + <property name="default_width">240</property> + <property name="default_height">320</property> + <signal name="delete_event" handler="gtk_main_quit"/> + <signal name="destroy_event" handler="gtk_main_quit"/> + <child> + <widget class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow3"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <child> + <widget class="GtkTreeView" id="devices_tv"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">False</property> + <signal name="cursor_changed" handler="on_devices_tv_cursor_changed"/> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkVBox" id="vbox2"> + <property name="visible">True</property> + <child> + <widget class="GtkButton" id="quit_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Quit</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="on_quit_button_clicked"/> + </widget> + </child> + <child> + <widget class="GtkButton" id="scan_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">S_can</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="on_scan_button_clicked"/> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="chat_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Chat</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="on_chat_button_clicked"/> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow2"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <child> + <widget class="GtkTextView" id="main_text"> + <property name="visible">True</property> + <property name="can_focus">True</property> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox2"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="label" translatable="yes">text:</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="input_tb"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + </widget> + <packing> + <property name="padding">3</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="send_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Send</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="on_send_button_clicked"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + </widget> + </child> + </widget> +</glade-interface> diff --git a/pybluez/bluezchat/bluezchat.py b/pybluez/bluezchat/bluezchat.py new file mode 100755 index 0000000..5021eb3 --- /dev/null +++ b/pybluez/bluezchat/bluezchat.py @@ -0,0 +1,191 @@ +#!/usr/bin/python + +""" A simple graphical chat client to demonstrate the use of pybluez. + +Opens a l2cap socket and listens on PSM 0x1001 + +Provides the ability to scan for nearby bluetooth devices and establish chat +sessions with them. +""" + + +import os +import sys +import time + +import gtk +import gobject +import gtk.glade + +import bluetooth + +GLADEFILE="bluezchat.glade" + +# ***************** + +def alert(text, buttons=gtk.BUTTONS_NONE, type=gtk.MESSAGE_INFO): + md = gtk.MessageDialog(buttons=buttons, type=type) + md.label.set_text(text) + md.run() + md.destroy() + +class BluezChatGui: + def __init__(self): + self.main_window_xml = gtk.glade.XML(GLADEFILE, "bluezchat_window") + + # connect our signal handlers + dic = { "on_quit_button_clicked" : self.quit_button_clicked, + "on_send_button_clicked" : self.send_button_clicked, + "on_chat_button_clicked" : self.chat_button_clicked, + "on_scan_button_clicked" : self.scan_button_clicked, + "on_devices_tv_cursor_changed" : self.devices_tv_cursor_changed + } + + self.main_window_xml.signal_autoconnect(dic) + + # prepare the floor listbox + self.devices_tv = self.main_window_xml.get_widget("devices_tv") + self.discovered = gtk.ListStore(gobject.TYPE_STRING, + gobject.TYPE_STRING) + self.devices_tv.set_model(self.discovered) + renderer = gtk.CellRendererText() + column1=gtk.TreeViewColumn("addr", renderer, text=0) + column2=gtk.TreeViewColumn("name", renderer, text=1) + self.devices_tv.append_column(column1) + self.devices_tv.append_column(column2) + + self.quit_button = self.main_window_xml.get_widget("quit_button") + self.scan_button = self.main_window_xml.get_widget("scan_button") + self.chat_button = self.main_window_xml.get_widget("chat_button") + self.send_button = self.main_window_xml.get_widget("send_button") + self.main_text = self.main_window_xml.get_widget("main_text") + self.text_buffer = self.main_text.get_buffer() + + self.input_tb = self.main_window_xml.get_widget("input_tb") + + self.listed_devs = [] + + self.chat_button.set_sensitive(False) + + self.peers = {} + self.sources = {} + self.addresses = {} + + # the listening sockets + self.server_sock = None + +# --- gui signal handlers + + def quit_button_clicked(self, widget): + gtk.main_quit() + + def scan_button_clicked(self, widget): + self.quit_button.set_sensitive(False) + self.scan_button.set_sensitive(False) +# self.chat_button.set_sensitive(False) + + self.discovered.clear() + for addr, name in bluetooth.discover_devices (lookup_names = True): + self.discovered.append ((addr, name)) + + self.quit_button.set_sensitive(True) + self.scan_button.set_sensitive(True) +# self.chat_button.set_sensitive(True) + + def send_button_clicked(self, widget): + text = self.input_tb.get_text() + if len(text) == 0: return + + for addr, sock in self.peers.items(): + sock.send(text) + + self.input_tb.set_text("") + self.add_text("\nme - %s" % text) + + def chat_button_clicked(self, widget): + (model, iter) = self.devices_tv.get_selection().get_selected() + if iter is not None: + addr = model.get_value(iter, 0) + if addr not in self.peers: + self.add_text("\nconnecting to %s" % addr) + self.connect(addr) + else: + self.add_text("\nAlready connected to %s!" % addr) + + def devices_tv_cursor_changed(self, widget): + (model, iter) = self.devices_tv.get_selection().get_selected() + if iter is not None: + self.chat_button.set_sensitive(True) + else: + self.chat_button.set_sensitive(False) + +# --- network events + + def incoming_connection(self, source, condition): + sock, info = self.server_sock.accept() + address, psm = info + + self.add_text("\naccepted connection from %s" % str(address)) + + # add new connection to list of peers + self.peers[address] = sock + self.addresses[sock] = address + + source = gobject.io_add_watch (sock, gobject.IO_IN, self.data_ready) + self.sources[address] = source + return True + + def data_ready(self, sock, condition): + address = self.addresses[sock] + data = sock.recv(1024) + + if len(data) == 0: + self.add_text("\nlost connection with %s" % address) + gobject.source_remove(self.sources[address]) + del self.sources[address] + del self.peers[address] + del self.addresses[sock] + sock.close() + else: + self.add_text("\n%s - %s" % (address, str(data))) + return True + +# --- other stuff + + def cleanup(self): + self.hci_sock.close() + + def connect(self, addr): + sock = bluetooth.BluetoothSocket (bluetooth.L2CAP) + try: + sock.connect((addr, 0x1001)) + except bluez.error, e: + self.add_text("\n%s" % str(e)) + sock.close() + return + + self.peers[addr] = sock + source = gobject.io_add_watch (sock, gobject.IO_IN, self.data_ready) + self.sources[addr] = source + self.addresses[sock] = addr + + + def add_text(self, text): + self.text_buffer.insert(self.text_buffer.get_end_iter(), text) + + def start_server(self): + self.server_sock = bluetooth.BluetoothSocket (bluetooth.L2CAP) + self.server_sock.bind(("",0x1001)) + self.server_sock.listen(1) + + gobject.io_add_watch(self.server_sock, + gobject.IO_IN, self.incoming_connection) + + def run(self): + self.text_buffer.insert(self.text_buffer.get_end_iter(), "loading..") + self.start_server() + gtk.main() + +if __name__ == "__main__": + gui = BluezChatGui() + gui.run() diff --git a/pybluez/simple/asynchronous-inquiry.py b/pybluez/simple/asynchronous-inquiry.py new file mode 100644 index 0000000..abbd70c --- /dev/null +++ b/pybluez/simple/asynchronous-inquiry.py @@ -0,0 +1,65 @@ +# file: asynchronous-inquiry.py +# auth: Albert Huang <albert@csail.mit.edu> +# desc: demonstration of how to do asynchronous device discovery by subclassing +# the DeviceDiscoverer class +# $Id: asynchronous-inquiry.py 405 2006-05-06 00:39:50Z albert $ +# +# XXX Linux only (5/5/2006) + +import bluetooth +import select + +class MyDiscoverer(bluetooth.DeviceDiscoverer): + + def pre_inquiry(self): + self.done = False + + def device_discovered(self, address, device_class, name): + print "%s - %s" % (address, name) + + # get some information out of the device class and display it. + # voodoo magic specified at: + # + # https://www.bluetooth.org/foundry/assignnumb/document/baseband + major_classes = ( "Miscellaneous", + "Computer", + "Phone", + "LAN/Network Access point", + "Audio/Video", + "Peripheral", + "Imaging" ) + major_class = (device_class >> 8) & 0xf + if major_class < 7: + print " %s" % major_classes[major_class] + else: + print " Uncategorized" + + print " services:" + service_classes = ( (16, "positioning"), + (17, "networking"), + (18, "rendering"), + (19, "capturing"), + (20, "object transfer"), + (21, "audio"), + (22, "telephony"), + (23, "information")) + + for bitpos, classname in service_classes: + if device_class & (1 << (bitpos-1)): + print " %s" % classname + + def inquiry_complete(self): + self.done = True + +d = MyDiscoverer() +d.find_devices(lookup_names = True) + +readfiles = [ d, ] + +while True: + rfds = select.select( readfiles, [], [] )[0] + + if d in rfds: + d.process_event() + + if d.done: break diff --git a/pybluez/simple/inquiry.py b/pybluez/simple/inquiry.py new file mode 100644 index 0000000..8f77887 --- /dev/null +++ b/pybluez/simple/inquiry.py @@ -0,0 +1,17 @@ +# file: inquiry.py +# auth: Albert Huang <albert@csail.mit.edu> +# desc: performs a simple device inquiry followed by a remote name request of +# each discovered device +# $Id: inquiry.py 401 2006-05-05 19:07:48Z albert $ +# + +import bluetooth + +print "performing inquiry..." + +nearby_devices = bluetooth.discover_devices(lookup_names = True) + +print "found %d devices" % len(nearby_devices) + +for addr, name in nearby_devices: + print " %s - %s" % (addr, name) diff --git a/pybluez/simple/l2capclient.py b/pybluez/simple/l2capclient.py new file mode 100644 index 0000000..930e431 --- /dev/null +++ b/pybluez/simple/l2capclient.py @@ -0,0 +1,28 @@ +# file: l2capclient.py +# desc: Demo L2CAP client for bluetooth module. +# $Id: l2capclient.py 524 2007-08-15 04:04:52Z albert $ + +import sys +import bluetooth + +sock=bluetooth.BluetoothSocket(bluetooth.L2CAP) + +if len(sys.argv) < 2: + print "usage: l2capclient.py <addr>" + sys.exit(2) + +bt_addr=sys.argv[1] +port = 0x1001 + +print "trying to connect to %s on PSM 0x%X" % (bt_addr, port) + +sock.connect((bt_addr, port)) + +print "connected. type stuff" +while True: + data = raw_input() + if(len(data) == 0): break + sock.send(data) + +sock.close() + diff --git a/pybluez/simple/l2capserver.py b/pybluez/simple/l2capserver.py new file mode 100644 index 0000000..40ad7d6 --- /dev/null +++ b/pybluez/simple/l2capserver.py @@ -0,0 +1,32 @@ +# file: l2capclient.py +# desc: Demo L2CAP server for pybluez. +# $Id: l2capserver.py 524 2007-08-15 04:04:52Z albert $ + +import bluetooth + +server_sock=bluetooth.BluetoothSocket( bluetooth.L2CAP ) + +port = 0x1001 + +server_sock.bind(("",port)) +server_sock.listen(1) + +#uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ef" +#bluetooth.advertise_service( server_sock, "SampleServerL2CAP", +# service_id = uuid, +# service_classes = [ uuid ] +# ) + +client_sock,address = server_sock.accept() +print "Accepted connection from ",address + +data = client_sock.recv(1024) +print "Data received:", data + +while data: + client_sock.send('Echo =>' + data) + data = client_sock.recv(1024) + print "Data received:",data + +client_sock.close() +server_sock.close() diff --git a/pybluez/simple/rfcomm-client.py b/pybluez/simple/rfcomm-client.py new file mode 100644 index 0000000..4da12af --- /dev/null +++ b/pybluez/simple/rfcomm-client.py @@ -0,0 +1,45 @@ +# file: rfcomm-client.py +# auth: Albert Huang <albert@csail.mit.edu> +# desc: simple demonstration of a client application that uses RFCOMM sockets +# intended for use with rfcomm-server +# +# $Id: rfcomm-client.py 424 2006-08-24 03:35:54Z albert $ + +from bluetooth import * +import sys + +addr = None + +if len(sys.argv) < 2: + print "no device specified. Searching all nearby bluetooth devices for" + print "the SampleServer service" +else: + addr = sys.argv[1] + print "Searching for SampleServer on %s" % addr + +# search for the SampleServer service +uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee" +service_matches = find_service( uuid = uuid, address = addr ) + +if len(service_matches) == 0: + print "couldn't find the SampleServer service =(" + sys.exit(0) + +first_match = service_matches[0] +port = first_match["port"] +name = first_match["name"] +host = first_match["host"] + +print "connecting to \"%s\" on %s" % (name, host) + +# Create the client socket +sock=BluetoothSocket( RFCOMM ) +sock.connect((host, port)) + +print "connected. type stuff" +while True: + data = raw_input() + if len(data) == 0: break + sock.send(data) + +sock.close() diff --git a/pybluez/simple/rfcomm-server.py b/pybluez/simple/rfcomm-server.py new file mode 100644 index 0000000..1fb555f --- /dev/null +++ b/pybluez/simple/rfcomm-server.py @@ -0,0 +1,41 @@ +# file: rfcomm-server.py +# auth: Albert Huang <albert@csail.mit.edu> +# desc: simple demonstration of a server application that uses RFCOMM sockets +# +# $Id: rfcomm-server.py 518 2007-08-10 07:20:07Z albert $ + +from bluetooth import * + +server_sock=BluetoothSocket( RFCOMM ) +server_sock.bind(("",PORT_ANY)) +server_sock.listen(1) + +port = server_sock.getsockname()[1] + +uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee" + +advertise_service( server_sock, "SampleServer", + service_id = uuid, + service_classes = [ uuid, SERIAL_PORT_CLASS ], + profiles = [ SERIAL_PORT_PROFILE ], +# protocols = [ OBEX_UUID ] + ) + +print "Waiting for connection on RFCOMM channel %d" % port + +client_sock, client_info = server_sock.accept() +print "Accepted connection from ", client_info + +try: + while True: + data = client_sock.recv(1024) + if len(data) == 0: break + print "received [%s]" % data +except IOError: + pass + +print "disconnected" + +client_sock.close() +server_sock.close() +print "all done" diff --git a/pybluez/simple/sdp-browse.py b/pybluez/simple/sdp-browse.py new file mode 100644 index 0000000..9d24b7a --- /dev/null +++ b/pybluez/simple/sdp-browse.py @@ -0,0 +1,35 @@ +# file: sdp-browse.py +# auth: Albert Huang <albert@csail.mit.edu> +# desc: displays services being advertised on a specified bluetooth device +# $Id: sdp-browse.py 393 2006-02-24 20:30:15Z albert $ + +import sys +import bluetooth + +if len(sys.argv) < 2: + print "usage: sdp-browse <addr>" + print " addr can be a bluetooth address, \"localhost\", or \"all\"" + sys.exit(2) + +target = sys.argv[1] +if target == "all": target = None + +services = bluetooth.find_service(address=target) + +if len(services) > 0: + print "found %d services on %s" % (len(services), sys.argv[1]) + print +else: + print "no services found" + +for svc in services: + print "Service Name: %s" % svc["name"] + print " Host: %s" % svc["host"] + print " Description: %s" % svc["description"] + print " Provided By: %s" % svc["provider"] + print " Protocol: %s" % svc["protocol"] + print " channel/PSM: %s" % svc["port"] + print " svc classes: %s "% svc["service-classes"] + print " profiles: %s "% svc["profiles"] + print " service id: %s "% svc["service-id"] + print |
