Skip to content

Commit

Permalink
All working!
Browse files Browse the repository at this point in the history
  • Loading branch information
MartwyJez committed Nov 21, 2020
1 parent bb1ddf2 commit 53406d3
Show file tree
Hide file tree
Showing 8 changed files with 443 additions and 134 deletions.
98 changes: 69 additions & 29 deletions chandelier/bt_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,23 @@

from time import sleep
import sys
import re
import pexpect
from retry import retry
from .utilities import errprint, stdprint

def reset_config():
try:
hci_name = re.search('hc..', pexpect.spawn('hcitool dev').read().decode("utf-8")).group(0)
hci = pexpect.spawn("sudo hciconfig "+ hci_name +" reset")
if hci.expect(pexpect.EOF) == 0:
return True
else:
return False
except pexpect.ExceptionPexpect as exception:
errprint(exception)
return False

class BluetoothDevice:
""" Class for generic bluetooth. Can be connected, checked if connected and is disconnecting
when object remove."""
Expand All @@ -17,7 +30,7 @@ class BluetoothError(Exception):
class DeviceNotFound(Exception):
"""Raised when given device can't be found"""

def check_if_connected(self):
def is_connected(self):
try:
hci = pexpect.spawn("hcitool con")
if hci.expect([self.addr, pexpect.EOF]) == 0:
Expand All @@ -29,33 +42,45 @@ def check_if_connected(self):
return False

def __end_connection__(self):
self.__interface__.sendline("\ndisconnect")
self.__interface__.expect("diconnected", timeout=5)
if not hasattr(self, '__interface__'):
self.__interface__ = self.__open_interface__()
self.__prepare_bluetooth__(self.__agent__)
print("Disconnecting!")
self.__interface__.sendline("\ndisconnect " + self.addr)
self.__interface__.expect("Successful disconnected", timeout=5)
self.__interface__.sendline("\nremove " + self.addr)
self.__interface__.expect("Device has been removed", timeout=5)
self.__interface__.close(force=True)
sleep(5)

@retry(pexpect.exceptions.TIMEOUT, tries=20)
def __check_if_device_is_visible__(self):
@retry(pexpect.exceptions.TIMEOUT, tries=3, delay=1)
def __is_device_visible__(self):
try:
self.__interface__.sendline("\ndevices")
self.__interface__.expect(self.addr)
self.__interface__.expect(self.addr, timeout=5)
except self.DeviceNotFound as exception:
raise exception

@retry(pexpect.exceptions.TIMEOUT, tries=120)
@retry(pexpect.exceptions.TIMEOUT, tries=3, delay=2)
def __connect_to_device__(self):
if not self.check_if_connected:
self.__end_connection__()
sleep(3)
self.__interface__.sendline("\nconnect "+self.addr)
self.__interface__.expect("Connection successful", timeout=5)
sleep(2)
if not self.is_connected():
raise pexpect.exceptions.TIMEOUT

def __trust__(self):
self.__interface__.sendline("\ntrust " + self.addr)
self.__interface__.expect("trust succeeded", timeout=5)

def __pair__(self):
try:
self.__interface__.sendline("\npaired-devices")
try:
self.__interface__.expect(self.addr)
self.__interface__.expect(self.addr, timeout=5)
except pexpect.exceptions.TIMEOUT:
self.__interface__.sendline("\npair " + self.addr)
self.__interface__.expect("Pairing successful")
self.__interface__.expect("Pairing successful", timeout=5)
except:
raise self.BluetoothError

Expand All @@ -66,6 +91,7 @@ def __open_interface__(self):
# enable debuging to stdout
if self.__debug_on__:
bluetoothctl.logfile = sys.stdout.buffer
sleep(3)
return bluetoothctl
except Exception as exception:
errprint(exception)
Expand All @@ -77,26 +103,30 @@ def __prepare_bluetooth__(self, __agent__):
self.__interface__.sendline("\nagent off")
self.__interface__.sendline("\nagent " + __agent__)
self.__interface__.sendline("\ndefault-agent")
self.__interface__.expect("successful")
self.__interface__.expect("successful", timeout=5)
self.__interface__.sendline("\npower on")
self.__interface__.expect("succeeded")
self.__interface__.expect("succeeded", timeout=5)
self.__interface__.sendline("\npairable on")
self.__interface__.expect("succeeded")
self.__interface__.expect("succeeded", timeout=5)
self.__interface__.sendline("\nscan on")
self.__interface__.expect("started")
self.__interface__.expect("started", timeout=5)
except Exception as exception:
errprint(exception)
errprint("Raspberry have problem with prepare bluetooth.")
raise self.BluetoothError

def __connect__(self):
try:
self.__check_if_device_is_visible__()
self.__is_device_visible__()
stdprint("Device " + self.addr + " is visible")
sleep(1)
self.__trust__()
self.__pair__()
sleep(1)
stdprint("Device " + self.addr + " is paired")
self.__connect_to_device__()
stdprint("Connection to " + self.addr + " are estabilished")
sleep(1)
stdprint("Connection to " + self.addr + " is estabilished")
except self.DeviceNotFound as exception:
errprint(exception)
errprint("Rasberry couldn't find device or connect.")
Expand All @@ -106,28 +136,38 @@ def __connect__(self):
errprint("Rasberry couldn't pair to the device.")
raise exception

def __init__(self, addr, debug=False, agent="NoInputNoOutput"):
def __init__(self, addr, disconnect=True, debug=False, agent="NoInputNoOutput"):
try:
self.disconnect_on_failure = disconnect
self.addr = addr
self.__debug_on__ = debug
self.__agent__ = agent
if self.check_if_connected():
if self.is_connected():
stdprint("Device already connected.")
return None
self.__interface__ = self.__open_interface__()
self.__prepare_bluetooth__(self.__agent__)
self.__connect__()
self.__interface__.kill(15)
self.__interface__.close(force=True)
print("Interface is killed")
except Exception as exception:
global shit_happens
print(exception)
self.__interface__ = self.__open_interface__()
#self.__end_connection__()
if self.disconnect_on_failure:
reset_config()
self.__interface__ = self.__open_interface__()
self.__end_connection__()
self.__interface__.close(force=True)
shit_happens = True
print("Interface is killed")
raise exception

#def __del__(self):
# self.__interface__ = self.__open_interface__()
# try:
# #self.__end_connection__()
# except:
# pass
# stdprint("Device " + self.addr + " is disconnected!")
# if self.__debug_on__:
# print("disconnect")
# self.__interface__ = self.__open_interface__()
# try:
# self.__end_connection__()
# except:
# pass
# stdprint("Device " + self.addr + " is disconnected!")
44 changes: 27 additions & 17 deletions chandelier/bt_devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,44 @@

class BluetoothSpeaker(bt_device.BluetoothDevice):

@retry(Exception, tries=5, delay=3)
@retry(Exception, tries=3, delay=1)
def __get_pulse_audio_sink__(self):
with pulsectl.Pulse('list-sinks') as pulse:
for sink in pulse.sink_list():
if sink.proplist.get('device.string') == self.addr:
return sink.index, sink.name

def __init__(self, addr, debug=False, agent="NoInputNoOutput"):
super().__init__(addr, debug, agent)
def __init__(self, addr, disconnect=False, debug=False, agent="NoInputNoOutput"):
super().__init__(addr, disconnect=False, debug=debug, agent=agent)
sleep(3)
try:
self.pa_index, self.paname = self.__get_pulse_audio_sink__()
except TypeError:
global shit_happens
shit_happens = True
utilities.errprint("Device " + self.addr + " is not recongized as bluetooth speaker.")
raise self.BluetoothError



class BluetoothRemote(bt_device.BluetoothDevice):
__loop = ""
remote_inputs = []
output = ""
@retry(Exception, tries=5, delay=3)

@retry(Exception, tries=3, delay=1)
def __remote_devices__(self, addr):
remote_address = addr
devices = [evdev.InputDevice(path) for path in evdev.list_devices()]
for device in devices:
if device.phys not in remote_address:
if device.phys == '':
devices.remove(device)
if len(devices) < 2:
raise Exception
return devices

def stop_waiting_on_output(self):
self.__loop.stop()

def wait_and_get_output(self):
@asyncio.coroutine
async def print_events(device):
Expand All @@ -46,27 +54,29 @@ async def print_events(device):
asyncio.get_running_loop().stop()
return cat_event

loop = asyncio.new_event_loop()
self.__loop = asyncio.new_event_loop()

tasks = []
for device in self.remote_inputs:
tasks.append(loop.create_task(print_events(device)))
tasks.append(self.__loop.create_task(print_events(device)))

loop.run_forever()
self.__loop.run_forever()

for task in tasks:
if task.done():
return task.result()

#devs_tasks = []
#for device in inputs:
# task = asyncio.ensure_future(print_events(device))
# devs_tasks.append(task)
try:
if task.done():
return task.result()
except:
return None

def __init__(self, addr, debug=False, agent="NoInputNoOutput"):
try:
super().__init__(addr, debug, agent)
super().__init__(addr, disconnect=False, debug=debug, agent=agent)
self.remote_inputs = self.__remote_devices__(addr)
except Exception as exception:
global shit_happens
shit_happens = True
bt_device.reset_config()
utilities.errprint(exception)
self.__end_connection__()
raise exception
Loading

0 comments on commit 53406d3

Please sign in to comment.