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. Могу отправить. Буду крайне благодарна любой помощи, будь то похожие примеры, объяснение как сделать хотя бы отображение списка устройств или полезные материалы: ссылки, курсы, книги.


Ответы (0 шт):