Skip to content

Commit

Permalink
record.py: if disconnected, attempt to reconnect forever
Browse files Browse the repository at this point in the history
  • Loading branch information
zero committed Apr 19, 2024
1 parent 6d837e6 commit ee5461e
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 15 deletions.
33 changes: 28 additions & 5 deletions muselsl/backends.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import asyncio
import atexit
import sys
import time
try:
import bleak
except ModuleNotFoundError as error:
bleak = error

RETRY_SLEEP = 1

def _wait(coroutine):
loop = asyncio.get_event_loop()
return loop.run_until_complete(coroutine)
Expand All @@ -32,18 +35,38 @@ def scan(self, timeout=10):
raise bleak
devices = _wait(bleak.BleakScanner.discover(timeout))
return [{'name':device.name, 'address':device.address} for device in devices]
def connect(self, address):
def connect(self, address, retries):
result = BleakDevice(self, address)
result.connect()
if not result.connect(retries):
return None
return result

class BleakDevice:
def __init__(self, adapter, address):
self._adapter = adapter
self._client = bleak.BleakClient(address)
def connect(self):
_wait(self._client.connect())
self._address = address
self._client = None
# Use retries=-1 to continue attempting to reconnect forever
def connect(self, retries):
attempts = 1
while True:
self._client = bleak.BleakClient(self._address)
if attempts > 1:
print(f'Connection attempt {attempts}')
try:
_wait(self._client.connect())
except (
bleak.exc.BleakDeviceNotFoundError, bleak.exc.BleakError
) as err:
print(f'Failed to connect: {err}', file=sys.stderr)
if attempts == 1 + retries:
return False
sleep(RETRY_SLEEP)
attempts += 1
else:
break
self._adapter.connected.add(self)
return True
def disconnect(self):
_wait(self._client.disconnect())
self._adapter.connected.remove(self)
Expand Down
8 changes: 6 additions & 2 deletions muselsl/muse.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def __init__(self,
self.preset = preset
self.disable_light = disable_light

def connect(self, interface=None):
def connect(self, interface=None, retries=0):
"""Connect to the device"""
try:
if self.backend == 'bluemuse':
Expand All @@ -81,7 +81,11 @@ def connect(self, interface=None):
serial_port=self.interface)

self.adapter.start()
self.device = self.adapter.connect(self.address)
if ((device := self.adapter.connect(self.address, retries))
is None):
return False
self.device = device

if(self.preset != None):
self.select_preset(self.preset)

Expand Down
38 changes: 30 additions & 8 deletions muselsl/record.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import bleak
import numpy as np
import pandas as pd
import os
import sys
from typing import Union, List, Optional
from pathlib import Path
from pylsl import StreamInlet, resolve_byprop
Expand All @@ -13,7 +15,6 @@

# Records a fixed duration of EEG data from an LSL stream into a CSV file


def record(
duration: int,
filename=None,
Expand Down Expand Up @@ -212,7 +213,9 @@ def save_eeg(new_samples, new_timestamps):
timestamps.append(new_timestamps)

muse = Muse(address, save_eeg, backend=backend)
muse.connect()
if not muse.connect():
print(f'Failed to connect to Muse: {address}', file=sys.stderr)
return
muse.start()

t_init = time()
Expand All @@ -221,13 +224,32 @@ def save_eeg(new_samples, new_timestamps):
last_update = t_init
while (time() - t_init) < duration:
try:
backends.sleep(1)

# Send a keep alive every minute
if time() - last_update > 60:
last_update = time()
muse.keep_alive()
try:
backends.sleep(1)

# Send a keep alive every 10 secs
if time() - last_update > 10:
last_update = time()
muse.keep_alive()
except bleak.exc.BleakError:
print('Disconnected. Attempting to reconnect...')
# Do not giveup since we make a best effort to continue
# data collection. Assume device is out of range or another
# temp error.
while True:
muse.connect(retries=-1)
try:
muse.resume()
except bleak.exc.BleakDBusError:
# Something is wrong with this connection
print('DBus error occurred. Reconnecting.')
muse.disconnect()
continue
else:
break
print('Connected. Continuing with data collection...')
except KeyboardInterrupt:
print('Interrupt received. Exiting data collection.')
break

muse.stop()
Expand Down

0 comments on commit ee5461e

Please sign in to comment.