Commit Graph

72 Commits

Author SHA1 Message Date
Shin'ichiro Kawasaki
7de173f324 gencert.py: Specify X.509 certificate version 3
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>
2020-10-23 18:06:55 +09:00
Shin'ichiro Kawasaki
ac819b926d bluepy_helper_cap.py, gencert.py: Remove capture_output
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>
2020-10-23 18:06:55 +09:00
Shin'ichiro Kawasaki
22dbd5e092 release.sh: Add upload command
To upload the release package to pypi.org, add upload command.

Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
2020-10-23 18:06:55 +09:00
Shin'ichiro Kawasaki
4ff47e2368 README.md: Describe repository rename to pyscrlink
Briefly described that bluepy-scratch-link was renamed to pyscrlink in
October 2020.

Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
2020-10-23 18:06:55 +09:00
Shin'ichiro Kawasaki
7be5a725fa setup.py: Add install_requires argument
To install dependent packages automatically, add install_requires
argument to setup() function.

Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
2020-10-23 18:06:55 +09:00
Shin'ichiro Kawasaki
bcd55cad00 README.md: Update description for pyscrlink
Rephrase explanation to match with the new project name "pyscrlink".

Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
2020-10-23 18:06:55 +09:00
Shin'ichiro Kawasaki
a53947fca3 pyscrlink/*.py, setup.py: Rename project to pyscrlink
Rename bluepy_scratch_link strings in python scripts to pyscrlink.

Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
2020-10-23 18:06:55 +09:00
Shin'ichiro Kawasaki
c4cf901878 pyscrlink directory: Rename bluepy_scratch_link directory to pyscrlink
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>
2020-10-11 15:12:46 +09:00
Shin'ichiro Kawasaki
7efd1ec827 scratch_link.py: Fix errors when it is run as package command
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>
2020-10-10 17:32:52 +09:00
Shin'ichiro Kawasaki
54c3a18e5e bluepy_helper_cap.py: Add sudo to setcap command
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>
2020-10-10 17:30:03 +09:00
Shin'ichiro Kawasaki
86ed7ebf91 release.sh: Add helper script for easier package release work
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
2020-10-10 17:13:45 +09:00
Shin'ichiro Kawasaki
559beb8802 setup.py: Initial implementation of setup.py for packaging
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
2020-10-10 17:13:45 +09:00
Shin'ichiro Kawasaki
abe63b54e5 bluepy_scratch_link: Add __main__.py
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>
2020-09-21 21:08:28 +09:00
Shin'ichiro Kawasaki
76bc9de261 blupey_scratch_link: Create blupey_scratch_link
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>
2020-09-21 20:59:00 +09:00
Shin'ichiro Kawasaki
74344c6dee README.md: Clarify that BLED112 USB dongle is not supported
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>
2020-09-20 21:15:06 +09:00
Shin'ichiro Kawasaki
e706263fea bluepy_helper_cap.py: Check bluepy-helper capability at scratch-link run
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>
2020-09-20 21:11:28 +09:00
Shin'ichiro Kawasaki
708a8a6f28 README.md: Remove description about gencert.sh
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>
2020-09-20 13:50:01 +09:00
Shin'ichiro Kawasaki
25afe8f6d0 .gitignore: Remove certificate files and add pycache
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>
2020-09-20 13:50:01 +09:00
Shin'ichiro Kawasaki
aaf1c5f01c gencert.py: Generate each users's certificate at scratch_link.py start
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>
2020-09-20 13:48:08 +09:00
Shin'ichiro Kawasaki
1cac5ebc68 scratch_link.py: Add time stamp to logging format
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>
2020-08-09 10:58:38 +09:00
Shin'ichiro Kawasaki
cc3d88eb51 Create CONTRIBUTING.md 2020-08-08 12:04:20 +09:00
ErrorJan
3a68a0109e BLESession.handle_request: Simplify Peripheral constructor call
Passing the device variable itself into Peripheral() will give the addr,
addrType and the iface to the Peripheral().
2020-08-08 11:29:28 +09:00
ErrorJan
e281543cb8 BLESession: Print device name in log
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.
2020-08-08 11:28:54 +09:00
ErrorJan
698447d18f BLESession,Session: Support Shortened Local Name and fix spelling
When the device do not have Complete Local Name, report Shortened Local
Name to the Scratch. Also, fix spelling mistakes.
2020-08-08 11:28:38 +09:00
Shin'ichiro Kawasaki
502670c3ac README.md: Avoid sudo for scratch_link.py
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>
2020-08-01 14:20:07 +09:00
Shin'ichiro Kawasaki
762141efbf setcap.sh: Add helper script to set bluepy-helper capability
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>
2020-08-01 14:20:07 +09:00
Shin'ichiro Kawasaki
d986e25173 BTSession.close: improve close handler
After bluetooth socket close, set None to the socket reference to ensure
no use.

This reverts commit 7fcaba55c4e700142310cefa00e63fd462bff6e2.
2020-08-01 14:20:07 +09:00
Shin'ichiro Kawasaki
fe86e485f4 BLESession.close: Improve close handler
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.
2020-08-01 14:20:07 +09:00
Shin'ichiro Kawasaki
dd194ae1c2 Session.close: Call close handler on websocket close
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>
2020-08-01 14:20:07 +09:00
Shin'ichiro Kawasaki
dfe97777fd BLESession: Support multiple Bluetooth adapters
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>
2020-08-01 14:20:07 +09:00
Shin'ichiro Kawasaki
c60a71ba4f BLESession: Extend scan time
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>
2020-08-01 14:20:07 +09:00
ErrorJan
a6972bb9a8 BLESession.matches: Support namePrefix in matching filters
Support "namePrefix" filter which is required for intelino Smart Train.
2020-08-01 14:09:35 +09:00
Shin'ichiro Kawasaki
20e65e9f03 BLESession: Support more adtypes
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>
2020-07-11 14:35:10 +09:00
Shin'ichiro Kawasaki
0af23d4280 BLEThread.run: Reduce notification wait time from 1s to 1ms
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>
2020-06-20 13:36:11 +09:00
Shin'ichiro Kawasaki
128786b06b BLESession: Guard getCharacteristics() and getServiceByUUID() with lock
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>
2020-06-20 13:36:04 +09:00
Shin'ichiro Kawasaki
751a96eec2 scratch_link.py: Print stack trace of all threads at KeyboardInterrupt
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>
2020-06-20 13:35:58 +09:00
Shin'ichiro Kawasaki
22d5b04d20 Session, BLESession: Avoid websocket send job from BLE thread
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>
2020-06-20 13:35:51 +09:00
Shin'ichiro Kawasaki
5dbb85713f BLESession: Add debug prints for Lego Boost
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
2020-06-20 13:33:34 +09:00
Shin'ichiro Kawasaki
e015d9c283 Revert "BLESession.notify: Send out notifications at once to avoid interruption"
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.
2020-06-20 13:31:31 +09:00
Shin'ichiro Kawasaki
3557a5d1d2 README.md: Add bluez-utils to required package list for Arch
To use btmgmt on Arch systems, need to install bluez-utils package.

Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
2020-05-31 13:22:45 +09:00
MDE
2c7a10f848 BLESession.notify: Send out notifications at once to avoid interruption 2020-05-17 09:35:34 +09:00
MDE
ba8eba4800 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.
2020-05-16 18:24:26 +09:00
MDE
199b54f094 BLESession: Simplify lock and unlock statements using 'with" statement 2020-05-16 17:48:35 +09:00
MDE
9038ef0ce3 BLESession.setNotifications: Refactor out start/stopNotifications 2020-05-16 17:44:13 +09:00
MDE
a217df401b BLESession.handle_request: Support stopNotifications request 2020-05-16 17:39:11 +09:00
MDE
1d29943233 BLESession.handle_request: Support startNotifications request 2020-05-16 17:39:11 +09:00
MDE
e42869c93b BLESession.startNotifications: Refactor out to a function 2020-05-16 17:23:11 +09:00
Shin'ichiro Kawasaki
6fdc8dcbb3 BLESession.handle_request: Fix startNotification KeyError
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>
2020-05-16 17:09:54 +09:00
Shin'ichiro Kawasaki
1ca2e910fb scratch_link.py: Add debug print option
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>
2020-05-01 12:55:03 +09:00
Shin'ichiro Kawasaki
8958594cf9 scratch_link.py: Enrich log information
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>
2020-05-01 12:54:07 +09:00