By default, pyOpenSSL generates X.509 certification version 1. However,
Chrome does not work with X.509 with version 1 and fails with
ERR_SSL_SERVER_CERT_BAD_FORMAT error. Set version 3 to generate X.509
certificate.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
The argument capture_output which was introduced in python 3.7 is used in
bluepy_helper_cap.py and gencert.py. This cause failure with python 3.6
environment. Avoid the failure by removing the argument.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
As the first step to rename the project to pyscrlink, rename the module
directory from bluepy_scratch_link to pyscrlink.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
When scratch_link.py is executed as the command specified by setuptools'
entry_point, following errors happen. Fix them.
- Package name can not be resolved to import modules.
- The global variable sessionTypes can not be refereed from the main
function.
- Command line options are not parsed in main function.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
When a python package is installed by user, the commands in the package
can not run with sudo. To run setcap in bluepy_helper_cap.py with sudo
privilege, specify sudo command within the python script.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
Add __main__.py to the bluepy-scratch-link package to invoke its feature
using the package name.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
To create PyPI package for bluepy-scratch-link, create a package
directory to hold the python scripts. Also add __init__.py to mark the
directory as a package.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
BLED112 is not supported at this moment. Comment it in README.md until
path for support gets clarified.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
To run bluepy-scratch-link as a normal user bluepy-helper must have
cap_net_admin and cap_net_raw capabilities to connect to BLE devices
using bluepy. When it lacks these capabilities, bluepy-scratch-link
fails to discover BLE devices without message about the failure reason.
To inform users the reason of BLE device detection failure, check
capabilities of bluepy-helper when discovery of BLE device is requested.
If the capabilities are not set, print error messages and request users
to run script to set the capabilities. Implement this features in
bluepy_helper_cap.py.
In addition, re-implement bash script setcap.sh feature as python and
added to bluepy_helper_cap.py to simplify the code set.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
Now scratch_link.py generates certificate at server start. Remove
description about gencert.sh which is no longer needed.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
WSS server certificate files are no longer generated in the directory
git controls. Remove it from .gitignore.
Add __pycache__ directory to .gitignore not to make "git status" list it.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
The script gencert.sh prepares the certificate for the WSS server.
The certificate is stored in the bluepy-scratch-link directory path, and
shared by users on the machine. This certificate sharing among users is
not handy in case one user prepares bluepy-scratch-link and another user
use it, since the latter user may not know where the certificate is.
Address this issue by generating the certificate for each user.
Re-implement gencert.sh as a python module gencert.py, and integrate it
in scratch_link.py. With this, when a user starts scratch_link.py,
the certificate unique for the user is generated and stored under user
home directory at the path "~/.local/share/blupy-scrach-link".
The newly added python module gencert.py depends on pyOpenSSL to generate
the certificates. Add this dependency to requirements.txt.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
To know how long each operation in scratch_link.py takes, add time stamps
to each log entry.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
In logger.* the device was printed out as "<bluepy.btle.Peripheral object
at 0x************>" which is not very useful to the user. Print the
deviceName variable instead.
Also add missing "f" for f-Strings.
The README instruction notes to run scratch_link.py with sudo. This is
not good for normal users especially for children. To allow normal users
to run scratch_link.py, revise the instruction.
Add a step to run setcap.sh at set up. Remove the step of btmgmt commands
with sudo which are not required when bluetooth.service is running.
Also add some more troubleshooting guides users might be caught at
scratch_link.py without sudo.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
To avoid sudo for scratch_link.py, it is required to set capability to
bluepy-helper executable so that normal users can connect to BLE devices
through bluepy. To simplify the command line to do this, add the helper
script setcap.sh.
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
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>