BLESession: Introduce notification queue

During bluepy-scratch-link handles requests from Scratch, it throws away
notifications from BLE devices. This loses those notifications.

Not to lose the notifications, introduce a queue to keep notifications
from BLE devices. Once request handling completes, flush the
notifications kept in the queue.
This commit is contained in:
MDE
2020-02-08 22:16:53 +01:00
committed by Shin'ichiro Kawasaki
parent 199b54f094
commit ba8eba4800

View File

@@ -22,6 +22,7 @@ from bluepy.btle import BTLEDisconnectError, BTLEManagementError
import threading import threading
import time import time
import queue
logLevel = logging.INFO logLevel = logging.INFO
@@ -52,7 +53,7 @@ class Session():
self.websocket = websocket self.websocket = websocket
self.loop = loop self.loop = loop
self.lock = threading.RLock() self.lock = threading.RLock()
self.notification = None self.notification_queue = queue.Queue()
async def recv_request(self): async def recv_request(self):
""" """
@@ -89,12 +90,17 @@ class Session():
logger.debug("default end_request") logger.debug("default end_request")
return False return False
def notify(self, method, params): def notify(self):
""" """
Notify BT/BLE device events to scratch. Notify BT/BLE device events to scratch.
""" """
logger.debug("start to notify") logger.debug("start to notify")
# flush notification queue
while not self.notification_queue.empty():
method, params = self.notification_queue.get()
self._send_notification(method, params)
def _send_notification(self, method, params):
jsonn = { 'jsonrpc': "2.0", 'method': method } jsonn = { 'jsonrpc': "2.0", 'method': method }
jsonn['params'] = params jsonn['params'] = params
notification = json.dumps(jsonn) notification = json.dumps(jsonn)
@@ -337,7 +343,8 @@ class BLESession(Session):
params = { 'rssi': d.rssi } params = { 'rssi': d.rssi }
params['peripheralId'] = devices.index(d) params['peripheralId'] = devices.index(d)
params['name'] = d.getValueText(0x9) params['name'] = d.getValueText(0x9)
self.session.notify('didDiscoverPeripheral', params) self.session.notification_queue.put(('didDiscoverPeripheral', params))
self.session.notify()
time.sleep(1) time.sleep(1)
elif self.session.status == self.session.CONNECTED: elif self.session.status == self.session.CONNECTED:
logger.debug("in connected status:") logger.debug("in connected status:")
@@ -381,11 +388,12 @@ class BLESession(Session):
def handleNotification(self, handle, data): def handleNotification(self, handle, data):
logger.debug(f"BLE notification: {handle} {data}") logger.debug(f"BLE notification: {handle} {data}")
params = self.handles[handle].copy()
params['message'] = base64.standard_b64encode(data).decode('ascii')
self.session.notification_queue.put(('characteristicDidChange', params))
if not self.restart_notification_event.is_set(): if not self.restart_notification_event.is_set():
return return
params = self.handles[handle] self.session.notify()
params['message'] = base64.standard_b64encode(data).decode('ascii')
self.session.notify('characteristicDidChange', params)
def __init__(self, websocket, loop): def __init__(self, websocket, loop):
super().__init__(websocket, loop) super().__init__(websocket, loop)