8 Commits

Author SHA1 Message Date
Shin'ichiro Kawasaki
e34ec61f3b Tag version 0.2.1
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
2021-04-11 14:14:33 +09:00
Shin'ichiro Kawasaki
e552bd21bd bluepy_helper_cap.py: Check tools out of PATH
It was informed that the required tools setcap and getcap are not placed
in /usr/bin in some user environment. They can not be executed since
they are out of PATH. To allow the script to execute the commands out of
PATH, have the script find the tools. Keep the found paths of each
command in the dictionary 'tools', and refer it to execute the commands.

Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
2021-04-11 13:36:23 +09:00
Shin'ichiro Kawasaki
dc46869760 BLESession: Refine error message for capability check
The error message on bluepy-helper capability check failure was not
accurate. Refine it.

Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
2021-02-07 20:27:38 +09:00
Peter Butkovic
461377f7ea Fixed missing glib.h error 2021-02-07 20:25:42 +09:00
Shin'ichiro Kawasaki
923c036cec Tag version 0.2.0
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
2020-12-27 21:09:05 +09:00
Shin'ichiro Kawasaki
8a69c2c917 README.md: Add "Issue Reporting" and Releases" sections
Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
2020-12-27 20:57:09 +09:00
Shin'ichiro Kawasaki
1e7f81906e BLESession: Refactor cached characteristics handling
To improve readability a bit, introduce _get_characteristic_cached().
Added some failure handlings in the method for robustness.
Also rename _get_all_characteristics() to _cache_characteristics() for
simplification.

Signed-off-by: Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
2020-12-19 11:43:45 +09:00
sza2
73523120b9 Update scratch_link.py
Retrieve all characteristics value on connect and cache it to speed up characteristics write that was slow as the handle got by _get_characteristic() every time a write occurred.
2020-12-15 14:02:33 +01:00
4 changed files with 67 additions and 8 deletions

View File

@@ -73,7 +73,7 @@ Installation
```sh
Ubuntu
$ sudo apt install bluez libbluetooth-dev libnss3-tools libcap2-bin
$ sudo apt install bluez libbluetooth-dev libnss3-tools libcap2-bin libglib2.0-dev
Arch
$ sudo pacman -S bluez bluez-utils nss libcap
```
@@ -186,3 +186,24 @@ In Case You Fail to Connect
3. If scratch_link.py says "failed to connect to BT device: [Errno 13] Permission denied",
make sure to pair the bluetooth device to your PC before connecting to Scratch.
Issus Reporting
---------------
Please file issues to [GitHub issue tracker](https://github.com/kawasaki/pyscrlink/issues).
Releases
--------
Release 0.2.1
* Added libglib to required package list in README.md
* Improved setcap and getcap tool finding
Release 0.2.0
* Latency issue fix for BLE devices' write characteristics
Release 0.1.0
* Initial release

View File

@@ -22,10 +22,26 @@ logger.propagate = False
# Check dependent tools
DEPENDENT_TOOLS = {
"setcap": "libcap2-bin (Ubuntu) or libcap (Arch)",
"getcap": "libcap2-bin (Ubuntu) or libcap (Arch)",
}
tools = {}
for cmd in DEPENDENT_TOOLS:
if not shutil.which(cmd):
# find the tools in PATH
path = shutil.which(cmd)
if path:
tools[cmd] = path
logger.debug(f"{cmd} found: {path}")
continue
# find the tools out of PATH but in major directories
for d in ["/usr/bin", "/bin", "/usr/sbin", "/sbin"]:
path = d + '/' + cmd
if os.path.isfile(path) and os.access(path, os.X_OK):
tools[cmd] = path
logger.debug(f"{cmd} found: {path}")
break
if not cmd in tools:
print(f"'{cmd}' not found. Install package {DEPENDENT_TOOLS[cmd]}.")
sys.exit(1)
@@ -42,7 +58,7 @@ def helper_path():
def is_set():
path = helper_path()
p = subprocess.run(["getcap", path], stdout=subprocess.PIPE)
p = subprocess.run([tools["getcap"], path], stdout=subprocess.PIPE)
if p.returncode != 0:
logger.error(f"Failed to get capability of {path}")
return False
@@ -53,8 +69,8 @@ def setcap():
path = helper_path()
if is_set():
return True
p = subprocess.run(["sudo", "setcap", "cap_net_raw,cap_net_admin+eip",
path])
p = subprocess.run(["sudo", tools["setcap"],
"cap_net_raw,cap_net_admin+eip", path])
if p.returncode !=0:
logger.error(f"Failed to set capability to {path}")
return False

View File

@@ -423,6 +423,7 @@ class BLESession(Session):
self.deviceName = None
self.perip = None
self.delegate = None
self.characteristics_cache = []
def close(self):
self.status = self.DONE
@@ -490,6 +491,25 @@ class BLESession(Session):
charas = self.perip.getCharacteristics(uuid=chara_id)
return charas[0]
def _cache_characteristics(self):
if not self.perip:
return
with self.lock:
self.characteristics_cache = self.perip.getCharacteristics()
if not self.characteristics_cache:
logger.debug("Characteristics are not cached")
def _get_characteristic_cached(self, chara_id):
if not self.perip:
return None
if not self.characteristics_cache:
self._cache_characteristics()
if self.characteristics_cache:
for characteristic in self.characteristics_cache:
if characteristic.uuid == chara_id:
return characteristic
return _get_characteristic(chara_id)
def handle_request(self, method, params):
"""Handle requests from Scratch"""
if self.delegate:
@@ -508,7 +528,8 @@ class BLESession(Session):
if self.status == self.INITIAL and method == 'discover':
if not bluepy_helper_cap.is_set():
logger.error("Capability is not set to bluepy helper.")
logger.error("Run bluepy_setcap.py with root privilege.")
logger.error("Run bluepy_helper_cap(.py).")
logger.error("e.g. $ bluepy_helper_cap")
logger.error("e.g. $ sudo bluepy_helper_cap.py")
sys.exit(1)
found_ifaces = 0
@@ -558,6 +579,7 @@ class BLESession(Session):
self.status = self.CONNECTED
self.delegate = self.BLEDelegate(self)
self.perip.withDelegate(self.delegate)
self._cache_characteristics()
else:
err_msg = f"BLE connect failed: {self.deviceName}"
res["error"] = { "message": err_msg }
@@ -595,7 +617,7 @@ class BLESession(Session):
logger.debug("handle write request")
service_id = params['serviceId']
chara_id = params['characteristicId']
c = self._get_characteristic(chara_id)
c = self._get_characteristic_cached(chara_id)
if not c or c.uuid != UUID(chara_id):
logger.error(f"Failed to get characteristic {chara_id}")
self.status = self.DONE

View File

@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
setuptools.setup(
name="pyscrlink",
version="0.1.0",
version="0.2.1",
author="Shin'ichiro Kawasaki",
author_email='kawasaki@juno.dti.ne.jp',
description='Scratch-link for Linux with Python',