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 time
import queue
logLevel = logging.INFO
@@ -52,7 +53,7 @@ class Session():
self.websocket = websocket
self.loop = loop
self.lock = threading.RLock()
self.notification = None
self.notification_queue = queue.Queue()
async def recv_request(self):
"""
@@ -89,12 +90,17 @@ class Session():
logger.debug("default end_request")
return False
def notify(self, method, params):
def notify(self):
"""
Notify BT/BLE device events to scratch.
"""
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['params'] = params
notification = json.dumps(jsonn)
@@ -337,7 +343,8 @@ class BLESession(Session):
params = { 'rssi': d.rssi }
params['peripheralId'] = devices.index(d)
params['name'] = d.getValueText(0x9)
self.session.notify('didDiscoverPeripheral', params)
self.session.notification_queue.put(('didDiscoverPeripheral', params))
self.session.notify()
time.sleep(1)
elif self.session.status == self.session.CONNECTED:
logger.debug("in connected status:")
@@ -381,11 +388,12 @@ class BLESession(Session):
def handleNotification(self, 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():
return
params = self.handles[handle]
params['message'] = base64.standard_b64encode(data).decode('ascii')
self.session.notify('characteristicDidChange', params)
self.session.notify()
def __init__(self, websocket, loop):
super().__init__(websocket, loop)