Guard peripheral disconnect handling with lock not to race with other
peripheral operations. After disconnect, set None to the peripheral
reference to ensure no use.
When scratch closes websocket connection, bluepy-scratch-link does not
close Bluetooth connection cleanly. This causes connection failure on
reconnect.
To close Bluetooth connection, catch ConnectionClosedError of websocket
and call close handler of the session.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
It was reported that bluepy-scratch-link fails to connect to BLE devices
with the PC has multiple Bluetooth adapters if the first adapter does not
support BLE. To support such a case, scan Bluetooth adapters up to 3.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
It was reported that the LEGO Boost brick connection needs 2 attempts.
The cause could be too short scan time. Extend the scan time from 1
second to 10 seconds.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
It was reported that Lego WeDo2 advertises its service class UUIDs with
adtype 0x6 "incomplete 128 bit service class UUIDs". Add this adtype as
well as some more adtypes 0x5, 0x4 and 0x2 defined in Bluetooth spec [1].
Also introduce _get_dev_uuid() helper function to simplify the code.
[1] https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile/
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
Now notification wait has 1 second timeout. This might be too long for
Lego Boost. Reduce it to 1 millisecond.
If BLE device does not send out any notification, bluepy-scratch-link
wait for 1 second and during this wait, write or read message from
Scratch is not sent to Boost. This is not an issue for micro:bit since
micro:bit sends out notifications frequently, the notification wait
completes before 1 second timeout.
It was reported that Lego Boost has a few seconds latency between Scratch
motor control command execution to Lego Boost motor move. To try out
smaller timeout, reduce the value.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
It turned out that bluepy Peripheral's getCharacteristics() and
getServiceByUUID() accesses shared resource with other bluepy APIs. Then
it needs guard with lock in same manner as other bluepy API calls. Guard
them with the lock of the session.
Introduce _get_characteristic() and _get_service() helper functions to
wrap the API calls with lock guard, and replace API calls with them.
Also remove unnecessary getCharacteristics() calls.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
To debug the dead lock status, print stack trace of all threads when
scratch_link.py stops by key interrupt.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
During trials to make Lego Boost work with bluepy-scratch-link, deadlock
race was observed between the lock for write to BLE device and
waitForNotifcations to BLE device. The cause of the dead lock is
coroutine call by BLE delegate handler to send out notifications to
Scratch through websocket conflict with websocket receive call by
websocket loop thread.
To avoid the conflict, only allow websocket loop thread to send out
through websocket. Have BLE thread to queue notifications so that it does
not need to touch websocket. On the other hand, introduce timeout when
websocket loop thread receives message from Scratch. This allow the
websocket loop thread to check the notifications queued. If any
notification is queued, the websocket loop thread sends it to Scratch.
Also fix notify() function argument signature, which was broken by commit
ba8eba4 ("BLESession: Introduce notification queue").
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
This reverts commit 2c7a10f848.
It turned out that string join with '\n' is not the proper way to pack
multiple JSON messages to Scratch Lego Boost extension.
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.
The value 'startNotification' is optional for the "read" request.
However, bluepy-scratch-link expects Scratch always set the value in the
requests. This may cause KeyError.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
In the GitHub issue "Scratux support #9", debug message log was required
for analysis. However, script edit by users was required to enable debug
print. This is not handy.
To avoid that the chore by users, add -d debug print option.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
In the GitHub issue "Scratux support #9", it was noticed that
bluepy-scratch-link is not so informative to tell what is happening.
Especially when BLE controllers or BLE devices are not available, no
information is printed.
Enrich log information so that users can tell what is happening easier.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
Now gencert.sh generates private key and certificate for the Secure WSS
server in a single file. This is not good to automate certification
addition to NSS databases. Generate them separately into two files and
initialize the Secure WSS server specifying them.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
LEGO Boost communicates with a Scratch extension through Scratch-link.
It was reported that bluepy-scratch-link fails to connect to LEGO Boost.
LEGO Boost advertises adtype 0x7 "Complete List of 128-bit Service Class
UUIDs". However, bluepy-scratch-link checks only adtype 0x3 "Complete
List of 16-bit Service Class UUIDs" which is valid for micro:bit.
To allow bluepy-scratch-link, check both adtypes 0x7 and 0x3. Introduce
constants to note those two adtype values.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
Implemented Scratch-link[1] feature as a small python script. Confirmed
it is working with Scratch 3.0[2] using a micro:bit as the BLE device to
link. This allows Linux PCs to connect Scratch and micro:bit.
Utilized bluez[3] and bluepy[4] to handle Bluetooth Low Energy connection.
Utilized Websocket module for Secure Web Socket server.
[1] https://github.com/LLK/scratch-link
[2] https://scratch.mit.edu/
[3] http://www.bluez.org/
[4] https://github.com/IanHarvey/bluepy
This is a minimal implementation to support micro:bit. Some of
Scratch-link features are not implemented. For example, Bluetooth (not
BLE) devices are not supported. BLE device support is confirmed only with
micro:bit.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>