FEATURE: Adding asynchronous scan for Bluetooth Peers.
git-svn-id: http://www.neo1973-germany.de/svn@46 46df4e5c-bc4e-4628-a0fc-830ba316316d
This commit is contained in:
parent
1f6aebe1a6
commit
c539f22371
1 changed files with 156 additions and 47 deletions
|
@ -23,13 +23,66 @@ import sys
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import gtk
|
import gtk
|
||||||
|
import gobject
|
||||||
import SysFSAccess
|
import SysFSAccess
|
||||||
from GlobalConfiguration import *
|
from GlobalConfiguration import *
|
||||||
from SysFSAccess import *
|
from SysFSAccess import *
|
||||||
from ProcessInterface import *
|
from ProcessInterface import *
|
||||||
#from settingsgui.GlobalConfiguration import *
|
|
||||||
#from settingsgui.SysFSAccess import *
|
class BluetoothScanner(threading.Thread):
|
||||||
#from settingsgui.ProcessInterface import *
|
def __init__(self, update_callback):
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
self.keep_running = True
|
||||||
|
self.scan_active = False
|
||||||
|
self.update_callback = update_callback
|
||||||
|
self.start()
|
||||||
|
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
while (self.keep_running):
|
||||||
|
print "RUN"
|
||||||
|
if self.scan_active:
|
||||||
|
print "SCAN"
|
||||||
|
self.update_callback(self.update_list())
|
||||||
|
time.sleep(3) # scan every 3 seconds, when running
|
||||||
|
else:
|
||||||
|
print "WAIT"
|
||||||
|
time.sleep(1) # check again if we are active in a second
|
||||||
|
|
||||||
|
|
||||||
|
def set_active(self, active):
|
||||||
|
self.scan_active = active
|
||||||
|
|
||||||
|
|
||||||
|
def update_list(self):
|
||||||
|
## exec hcitool scan
|
||||||
|
hcitool = ProcessInterface("%s scan hci0" % HCITOOL_CMD)
|
||||||
|
while not hcitool.process_finished():
|
||||||
|
time.sleep(0.1) ## wait for command to compute
|
||||||
|
hcitool_output = hcitool.read_from_process()
|
||||||
|
|
||||||
|
## exec pand list
|
||||||
|
pand = ProcessInterface("pand -l")
|
||||||
|
while not pand.process_finished():
|
||||||
|
time.sleep(0.1) ## wait for command to compute
|
||||||
|
pand_output = pand.read_from_process()
|
||||||
|
|
||||||
|
## filter output for visible peers
|
||||||
|
visible_peers = []
|
||||||
|
for line in hcitool_output.split("\n"):
|
||||||
|
if line.find(":") >= 1:
|
||||||
|
visible_peers.append((line.strip().split("\t")[1],\
|
||||||
|
line.strip().split("\t")[0]))
|
||||||
|
## filter output for connected peers
|
||||||
|
connected_peers = []
|
||||||
|
for line in pand_output.split("\n"):
|
||||||
|
if len(line.split(" ")) > 1:
|
||||||
|
connected_peers.append(line.split(" ")[1])
|
||||||
|
|
||||||
|
return (visible_peers, connected_peers)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class BluetoothPanel(gtk.VBox):
|
class BluetoothPanel(gtk.VBox):
|
||||||
"""
|
"""
|
||||||
|
@ -38,9 +91,34 @@ class BluetoothPanel(gtk.VBox):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
gtk.VBox.__init__(self, False, 0)
|
gtk.VBox.__init__(self, False, 0)
|
||||||
self.address = ""
|
self.address = ""
|
||||||
self.scan_for_bt_peers = True
|
|
||||||
self.create_notebook_page()
|
|
||||||
|
|
||||||
|
self.create_notebook_page()
|
||||||
|
|
||||||
|
# asyncronous stuff
|
||||||
|
self.update_ui_condition = threading.Condition()
|
||||||
|
self.scan_for_bt_peers = True # to be handled in critical section!
|
||||||
|
self.async_updated = False # to be handled in critical section!
|
||||||
|
|
||||||
|
# creating backgroundscanner - not active by default
|
||||||
|
self.bluetooth_scanner = BluetoothScanner(self.update_from_scanner)
|
||||||
|
|
||||||
|
# start our update timer
|
||||||
|
gobject.timeout_add(500, self.update_ui) # every 1/2 second
|
||||||
|
|
||||||
|
# settings powerstate as last operation to ensure existence of all
|
||||||
|
# widgets
|
||||||
|
if self.get_power_state():
|
||||||
|
self.power_state_cbtn.set_active(True)
|
||||||
|
self.visible_state_cbtn.set_active(True)
|
||||||
|
self.update_btn.set_active(True)
|
||||||
|
self.list_store1.append(("Scanning for ", "Peers", False))
|
||||||
|
self.update_infos()
|
||||||
|
else:
|
||||||
|
self.power_state_cbtn.set_active(False)
|
||||||
|
self.visible_state_cbtn.set_active(False)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def create_notebook_page(self):
|
def create_notebook_page(self):
|
||||||
self.set_border_width(0)
|
self.set_border_width(0)
|
||||||
|
|
||||||
|
@ -98,16 +176,10 @@ class BluetoothPanel(gtk.VBox):
|
||||||
["text", "text", "toggle"])
|
["text", "text", "toggle"])
|
||||||
scan_frame_box.pack_start(scroll_win, True, True, 0)
|
scan_frame_box.pack_start(scroll_win, True, True, 0)
|
||||||
|
|
||||||
# self.add_scan_list_entry
|
|
||||||
self.list_store1.append(("Scanning for Peers", "", False))
|
|
||||||
self.update_infos()
|
|
||||||
self.update_list(None)
|
|
||||||
|
|
||||||
|
|
||||||
scan_btn_box = gtk.HBox()
|
scan_btn_box = gtk.HBox()
|
||||||
update_btn = gtk.Button("Update\nList")
|
self.update_btn = gtk.ToggleButton("Scan for\nPeers")
|
||||||
update_btn.connect('clicked', self.update_list)
|
self.update_btn.connect('toggled', self.scan_for_peers_toggled)
|
||||||
scan_btn_box.add(update_btn)
|
scan_btn_box.add(self.update_btn)
|
||||||
connect_btn = gtk.Button("Connect\n(PAN)")
|
connect_btn = gtk.Button("Connect\n(PAN)")
|
||||||
connect_btn.connect('clicked', self.connect_to_peer)
|
connect_btn.connect('clicked', self.connect_to_peer)
|
||||||
scan_btn_box.add(connect_btn)
|
scan_btn_box.add(connect_btn)
|
||||||
|
@ -116,16 +188,6 @@ class BluetoothPanel(gtk.VBox):
|
||||||
|
|
||||||
self.pack_start(scan_frame, True, True, 0)
|
self.pack_start(scan_frame, True, True, 0)
|
||||||
|
|
||||||
# settings powerstate as last operation to ensure existence of all
|
|
||||||
# widgets
|
|
||||||
if self.get_power_state():
|
|
||||||
self.power_state_cbtn.set_active(True)
|
|
||||||
self.visible_state_cbtn.set_active(True)
|
|
||||||
self.toggle_power(None)
|
|
||||||
else:
|
|
||||||
self.power_state_cbtn.set_active(False)
|
|
||||||
self.visible_state_cbtn.set_active(False)
|
|
||||||
|
|
||||||
## finish notebook page creation
|
## finish notebook page creation
|
||||||
self.show_all()
|
self.show_all()
|
||||||
|
|
||||||
|
@ -165,24 +227,77 @@ class BluetoothPanel(gtk.VBox):
|
||||||
scroll_win.add(tree_view)
|
scroll_win.add(tree_view)
|
||||||
return (scroll_win, tree_view, list_store)
|
return (scroll_win, tree_view, list_store)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
######### update GUI from asynchronous changes (from threads) ##################
|
||||||
|
################################################################################
|
||||||
|
def update_ui(self):
|
||||||
|
self.update_ui_condition.acquire() # <- critical section
|
||||||
|
if not self.async_updated: # to be handled in critical section!
|
||||||
|
self.update_ui_condition.release() # -> critical section
|
||||||
|
return True # Do nothing, keep going
|
||||||
|
|
||||||
|
self.list_store1.clear()
|
||||||
|
# access the peer_list (which is written to by the scan thread)
|
||||||
|
for entry in self.peer_list:
|
||||||
|
self.list_store1.append(entry)
|
||||||
|
|
||||||
|
if len(self.peer_list) <= 0:
|
||||||
|
self.list_store1.append(("Scanning for ", "Peers...", False))
|
||||||
|
|
||||||
|
self.update_ui_condition.release() # -> critical section
|
||||||
|
return True # keep going for ever
|
||||||
|
|
||||||
|
## gets calles from thread context - has no access to GUI!
|
||||||
|
def update_from_scanner(self, data):
|
||||||
|
(visible_peers, connected_peers) = data
|
||||||
|
|
||||||
|
print "enter critical section"
|
||||||
|
self.update_ui_condition.acquire() # <- critical section
|
||||||
|
self.peer_list = [] # to be handled in critical section!
|
||||||
|
|
||||||
|
print "entry loop"
|
||||||
|
for entry in visible_peers:
|
||||||
|
## see if entry can be found in conneced list
|
||||||
|
found = False
|
||||||
|
for conneted in connected_peers:
|
||||||
|
print "."
|
||||||
|
if entry[1] == connected:
|
||||||
|
found = True
|
||||||
|
## add to list als (Name, Address, Found)
|
||||||
|
self.peer_list.append((entry[0], entry[1], found))
|
||||||
|
print "added entry"
|
||||||
|
|
||||||
|
print "entry loop left"
|
||||||
|
|
||||||
|
self.async_updated = True # to be handled in critical section!
|
||||||
|
self.update_ui_condition.release() # -> critical section
|
||||||
|
print "leaving critical section"
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
####################### Callbacks from GUI #####################################
|
####################### Callbacks from GUI #####################################
|
||||||
################################################################################
|
################################################################################
|
||||||
|
def scan_for_peers_toggled(self, event):
|
||||||
|
'''
|
||||||
|
activate/deactivate background scanner
|
||||||
|
'''
|
||||||
|
self.bluetooth_scanner.set_active(self.update_btn.get_active())
|
||||||
|
|
||||||
|
|
||||||
def toggle_power(self, event):
|
def toggle_power(self, event):
|
||||||
print "Toggleing Power state!"
|
print "Toggleing Power state!"
|
||||||
if not self.get_power_state():
|
if not self.get_power_state():
|
||||||
set_sysfs_value(SYSFS_ENTRY_BLUETOOTH_POWER, 1)
|
set_sysfs_value(SYSFS_ENTRY_BLUETOOTH_POWER, 1)
|
||||||
self.list_store1.append(("Scanning for Peers", "", False))
|
self.list_store1.clear()
|
||||||
|
self.list_store1.append(("Scanning for ", "Peers...", False))
|
||||||
|
self.update_btn.set_active(True)
|
||||||
else:
|
else:
|
||||||
set_sysfs_value(SYSFS_ENTRY_BLUETOOTH_POWER, 0)
|
set_sysfs_value(SYSFS_ENTRY_BLUETOOTH_POWER, 0)
|
||||||
|
|
||||||
if self.power_state_cbtn.get_active() != self.get_power_state():
|
self.power_state_cbtn.set_active(self.get_power_state())
|
||||||
self.power_state_cbtn.get_active()
|
|
||||||
|
|
||||||
## have to wait for async init :-( - TODO - make updates async.
|
## have to wait for async init :-( - TODO - make updates async.
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
self.update_infos()
|
self.update_infos()
|
||||||
self.update_list(None)
|
|
||||||
|
|
||||||
## for now we are alyways visible when power is on
|
## for now we are alyways visible when power is on
|
||||||
self.visible_state_cbtn.set_active(self.get_power_state())
|
self.visible_state_cbtn.set_active(self.get_power_state())
|
||||||
|
@ -198,13 +313,21 @@ class BluetoothPanel(gtk.VBox):
|
||||||
self.pand_state_cbtn.set_active(1)
|
self.pand_state_cbtn.set_active(1)
|
||||||
self.pand_state_cbtn.set_inconsistent(0)
|
self.pand_state_cbtn.set_inconsistent(0)
|
||||||
|
|
||||||
|
|
||||||
def get_power_state(self):
|
def get_power_state(self):
|
||||||
state = get_sysfs_value(SYSFS_ENTRY_BLUETOOTH_POWER)[0]
|
power_value = get_sysfs_value(SYSFS_ENTRY_BLUETOOTH_POWER)
|
||||||
print "Powerstate is [%s]" %state
|
|
||||||
if state.isdigit():
|
## value will be empty if sysfs entry does not exist
|
||||||
return int(state)
|
if len(power_value) > 0:
|
||||||
|
state = power_value[0]
|
||||||
else:
|
else:
|
||||||
return 0
|
state = "0"
|
||||||
|
|
||||||
|
if state.isdigit():
|
||||||
|
if int(state) > 0:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def connect_to_peer(self, event):
|
def connect_to_peer(self, event):
|
||||||
|
|
||||||
|
@ -232,20 +355,6 @@ class BluetoothPanel(gtk.VBox):
|
||||||
self.update_infos()
|
self.update_infos()
|
||||||
|
|
||||||
|
|
||||||
def update_list(self, event):
|
|
||||||
self.hcitool = ProcessInterface("%s scan" % HCITOOL_CMD)
|
|
||||||
self.list_store1.clear()
|
|
||||||
self.hcitool.register_event_handler(":", self.add_scan_list_entry)
|
|
||||||
|
|
||||||
pand_list_tool = ProcessInterface("pand -l")
|
|
||||||
time.sleep(1) ## wait for command to compute
|
|
||||||
output = pand_list_tool.read_from_process()
|
|
||||||
|
|
||||||
self.connected_peers = []
|
|
||||||
for line in output.split("\n"):
|
|
||||||
if len(line.split(" ")) > 1:
|
|
||||||
self.connected_peers.append(line.split(" ")[1])
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
#################### subprocess callbacks (outputs) ############################
|
#################### subprocess callbacks (outputs) ############################
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
Loading…
Reference in a new issue