Kivy Создать кнопку вызывающую список подключенных по bluetooth устройств
У меня есть интерфейс приложения с использованием screenmanager. Screenmanager и все его составляющие прописаны в .kv файле:
BoxLayout:
orientation: 'vertical'
ScreenManager:
id: screen_manager
EegScreen:
id: eeg_screen
name:'EegScreen'
SettingsScreen:
id: settings_screen
name:'SettingsScreen'
ExchangeScreen:
id: exchange_screen
name:'ExchangeScreen'
ConnectionsScreen:
id: connections_screen
name:'ConnectionsScreen'
BoxLayout:
orientation: 'horizontal'
padding: '40dp'
spacing: '40dp'
Button:
text: 'Подключения'
font_size: 15
size_hint:0.15, 0.18
on_release: screen_manager.current = 'ConnectionsScreen'
Button:
text: 'Команды'
font_size: 15
size_hint:0.15, 0.18
on_release: screen_manager.current = 'ExchangeScreen'
Button:
text: 'ЭЭГ сигналы'
font_size: 15
size_hint:0.15, 0.18
on_release: screen_manager.current = 'EegScreen'
Button:
text: 'Настройки'
font_size: 15
size_hint:0.15, 0.18
on_release: screen_manager.current = 'SettingsScreen'
<EegScreen>:
FloatLayout:
Label:
text: 'EEG Signals'
pos_hint:{'center_x':0.5,'center_y':0.9}
<SettingsScreen>:
FloatLayout:
Label:
text: 'Количество каналов'
pos_hint:{'center_x':0.5,'center_y':0.9}
Button:
size_hint:0.2, 0.18
pos_hint:{'center_x':0.5,'y':0.2}
text: '4 канала'
Button:
size_hint:0.2, 0.18
pos_hint:{'center_x':0.5,'y':0.4}
text: '8 каналов'
<ExchangeScreen>:
FloatLayout:
Label:
text: 'Exchange'
pos_hint:{'center_x':0.5,'center_y':0.9}
<ConnectionsScreen>:
FloatLayout:
Label:
text: 'Connections'
pos_hint:{'center_x':0.5,'center_y':0.9}
Button:
size_hint:0.18, 0.18
pos_hint:{'center_x':0.5,'y':0.2}
text: 'поиск усилителя'
Файл main.py
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.dropdown import DropDown
from kivy.base import runTouchApp
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from bluetuz import GetData, SendData
class EegScreen(Screen):
pass
class ExchangeScreen(Screen):
pass
class ConnectionsScreen(Screen):
pass
class MyApp(App):
pass
if __name__ == '__main__':
MyApp().run()
Нужно чтобы при нажатии на кнопку 'поиск усилителя' на экране ConnectionsScreen появлялся список подключенных по bluetooth устройств. Приложение рассчитано в перспективе на android, но проверка работоспособности на windows. Знаю, что понадобится библиотека pybluez. Есть даже файл с методами блютуза (автор не я) для подобной задачи. Но как его привязать к кнопке идей нет. На всякий случай вот он:
import threading
from collections import deque
import bluetooth
import array
import datetime
from time import sleep
class DiscoverDevices(threading.Thread):
def __init__(self, parent):
super().__init__()
self.socket = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
self.device_list = []
self.parent = parent
self.running = True
def run(self):
self.parent.update_status("Поиск устройств...")
self.device_list = bluetooth.discover_devices(lookup_names=True)
for name, addr in self.device_list:
print("%s - %s" % (addr, name))
if self.running:
self.parent.list_refresh(self.device_list)
def stop(self):
self.running = False
class SendData(threading.Thread):
def __init__(self, addr):
super().__init__()
self.wear_mac_addr = addr
self.running = True
self.error = False
self.uuid = "00001101-0000-1000-8010-00805F9B34FB"
self.name = "SampleServer"
self.socket = None
self.command = "none"
def run(self):
try:
self.socket = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
self.socket.bind(("", bluetooth.PORT_ANY))
self.socket.listen(5)
print(self.uuid)
print(self.name)
bluetooth.advertise_service(self.socket, self.name, service_id=self.uuid,
service_classes=[self.uuid, bluetooth.SERIAL_PORT_CLASS],
profiles=[bluetooth.SERIAL_PORT_PROFILE])
print("open")
print("wait for client")
client, client_info = self.socket.accept()
print("got client")
# i = 0
while not self.error and self.running:
try:
if self.command != "none":
client.send(self.command)
self.command = "none"
sleep(1)
except:
self.error = True
except:
self.error = True
print('Подключиться к Bluetooth-устройству не удалось!')
return
def change_command(self, command):
self.command = command
def close_connection(self):
if self.socket is not None:
self.socket.close()
def stop(self):
self.running = False
self.close_connection()
class GetData(threading.Thread):
def __init__(self, channel_count, data_queue, port, addr, side):
super().__init__()
self.data_queue = data_queue
self.amp_mac_addr = addr
self.port = port
self.buffer_size = 100
self.running = True
self.channel_count = channel_count
self.len_package = self.channel_count * 2
self.buff = deque(maxlen=self.buffer_size)
self.package = []
self.chunk = ''
self.error = False
self.socket = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
self.do_save = True
if side == '0':
self.do_save = False
self.data_file_name = "data/sig_" + side + "_" + str(datetime.datetime.now()).replace(':', '.') + ".dat"
self.data = array.array('f')
def run(self):
try:
self.socket.connect((self.amp_mac_addr, self.port))
except:
self.error = True
print('Подключиться к Bluetooth-устройству не удалось!')
return
op = -1
omission_count = 0
while not self.error:
try:
self.chunk = self.socket.recv(1024)
i = 0
while i < len(self.chunk):
if (op == -1) and (self.chunk[i] & 128) == 128:
self.package = []
op = 0
omission_count = 3
elif op == 0:
omission_count -= 1
if omission_count == 0:
op = 1
elif op == 1:
self.package.append(self.chunk[i])
if len(self.package) == self.len_package:
package = []
for j in range(self.channel_count):
package.append(((self.package[2 * j + 1]
+ (self.package[2 * j] << 7)) - 2048) * 0.10417)
self.buff.append(package)
for k in range(0, self.channel_count):
self.data_queue[k].append(package[k])
op = -1
self.data.extend(package)
i = i + 1
except:
self.error = True
def close_connection(self):
self.socket.close()
if self.do_save:
self.save_data()
def save_data(self):
f = open(self.data_file_name, 'wb')
self.data.tofile(f)
f.close()
def stop(self):
self.running = False
self.close_connection()
Ещё немного подробностей: подключение осуществляется к усилителю сигнала ЭЭГ. Соответственно есть ещё выбор числа каналов 4 или 8. Цель подключения - получение записанных усилителем данных и отрисовка их в виде графика в реальном времени. На этот счёт есть идеи использовать FigureCanvasKivyAgg и matplotlib. Графики должны отображаться на экране EegScreen. При отсутствии сопряжения с усилителем просто пустые оси. Я только начала изучать kivy и в python не сильно давно, но так вышло, что есть острая необходимость решить такие задачи... Есть как образец версия на tkinter подобного приложения, но она не слишком ровная, нуждается в доработке и немного другого формата, но зато с горем пополам рабочая для windows. Могу отправить. Буду крайне благодарна любой помощи, будь то похожие примеры, объяснение как сделать хотя бы отображение списка устройств или полезные материалы: ссылки, курсы, книги.