Skip to content

Commit fdb9ba4

Browse files
committed
Shows error message when bluetooth or Device turns of.
1 parent eae895b commit fdb9ba4

File tree

1 file changed

+43
-15
lines changed

1 file changed

+43
-15
lines changed

npg-ble.py

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from pylsl import StreamInfo, StreamOutlet
55
import sys
66
import argparse
7+
import os
78

89
# BLE parameters (must match your firmware)
910
DEVICE_NAME_PREFIX = "NPG"
@@ -22,6 +23,10 @@
2223
start_time = None
2324
total_missing_samples = 0
2425
outlet = None
26+
last_received_time = None
27+
DATA_TIMEOUT = 2.0
28+
monitor_task = None
29+
client = None
2530

2631
def parse_args():
2732
parser = argparse.ArgumentParser()
@@ -43,7 +48,8 @@ async def scan_devices():
4348
print(f"DEVICE:{dev.name}|{dev.address}")
4449

4550
def process_sample(sample_data: bytearray):
46-
global prev_unrolled_counter, samples_received, start_time, total_missing_samples, outlet
51+
global prev_unrolled_counter, samples_received, start_time, total_missing_samples, outlet, last_received_time
52+
last_received_time = time.time()
4753

4854
if len(sample_data) != SINGLE_SAMPLE_LEN:
4955
print("Unexpected sample length:", len(sample_data))
@@ -73,9 +79,9 @@ def process_sample(sample_data: bytearray):
7379

7480
# Process channels
7581
channels = [
76-
int.from_bytes(sample_data[1:3]), # Channel 0
77-
int.from_bytes(sample_data[3:5]), # Channel 1
78-
int.from_bytes(sample_data[5:7])]
82+
int.from_bytes(sample_data[1:3], byteorder='little'), # Channel 0
83+
int.from_bytes(sample_data[3:5], byteorder='little'), # Channel 1
84+
int.from_bytes(sample_data[5:7], byteorder='little')] # Channel 2
7985

8086
# Push to LSL
8187
if outlet:
@@ -91,29 +97,39 @@ def process_sample(sample_data: bytearray):
9197
def notification_handler(sender, data: bytearray):
9298
try:
9399
if len(data) == NEW_PACKET_LEN:
94-
# Process batched samples
95100
for i in range(0, NEW_PACKET_LEN, SINGLE_SAMPLE_LEN):
96101
process_sample(data[i:i+SINGLE_SAMPLE_LEN])
97102
elif len(data) == SINGLE_SAMPLE_LEN:
98-
# Process single sample
99103
process_sample(data)
100104
else:
101105
print(f"Unexpected packet length: {len(data)} bytes")
102106
except Exception as e:
103107
print(f"Error processing data: {e}")
104108

109+
async def monitor_connection():
110+
global last_received_time, client
111+
112+
while True:
113+
if last_received_time and (time.time() - last_received_time) > DATA_TIMEOUT:
114+
print("\nData Interrupted")
115+
os._exit(1)
116+
if client and not client.is_connected:
117+
print("\nData Interrupted (Bluetooth disconnected)")
118+
os._exit(1)
119+
120+
await asyncio.sleep(0.5)
121+
105122
async def connect_to_device(device_address):
106-
global outlet
123+
global outlet, last_received_time, monitor_task, client
107124

108125
print(f"Attempting to connect to {device_address}...", file=sys.stderr)
109126

110127
# Set up LSL stream (500Hz sampling rate)
111128
info = StreamInfo("NPG", "EXG", 3, 500, "int16", "npg1234")
112129
outlet = StreamOutlet(info)
113130

114-
client = None
131+
client = BleakClient(device_address)
115132
try:
116-
client = BleakClient(device_address)
117133
await client.connect()
118134

119135
if not client.is_connected:
@@ -122,6 +138,9 @@ async def connect_to_device(device_address):
122138

123139
print(f"Connected to {device_address}")
124140

141+
last_received_time = time.time()
142+
monitor_task = asyncio.create_task(monitor_connection())
143+
125144
# Send start command
126145
await client.write_gatt_char(CONTROL_CHAR_UUID, b"START", response=True)
127146
print("Sent START command")
@@ -140,16 +159,25 @@ async def connect_to_device(device_address):
140159
print(f"Connection error: {str(e)}", file=sys.stderr)
141160
return False
142161
finally:
162+
if monitor_task:
163+
monitor_task.cancel()
143164
if client and client.is_connected:
144165
await client.disconnect()
145166

146167
if __name__ == "__main__":
147168
args = parse_args()
148169

149-
if args.scan:
150-
asyncio.run(scan_devices())
151-
elif args.connect:
152-
asyncio.run(connect_to_device(args.connect))
153-
else:
154-
print("Please specify --scan or --connect", file=sys.stderr)
170+
try:
171+
if args.scan:
172+
asyncio.run(scan_devices())
173+
elif args.connect:
174+
asyncio.run(connect_to_device(args.connect))
175+
else:
176+
print("Please specify --scan or --connect", file=sys.stderr)
177+
sys.exit(1)
178+
except KeyboardInterrupt:
179+
print("\nScript terminated by user")
180+
sys.exit(0)
181+
except Exception as e:
182+
print(f"\nError: {str(e)}", file=sys.stderr)
155183
sys.exit(1)

0 commit comments

Comments
 (0)