kallistoapi 2.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kallistoapi-2.0.1/LICENSE +17 -0
- kallistoapi-2.0.1/PKG-INFO +140 -0
- kallistoapi-2.0.1/README.md +104 -0
- kallistoapi-2.0.1/kallistoapi/__init__.py +1 -0
- kallistoapi-2.0.1/kallistoapi/bluetooth_gatt.py +199 -0
- kallistoapi-2.0.1/kallistoapi/config_pb2.py +79 -0
- kallistoapi-2.0.1/kallistoapi/kallisto_battery_service.py +168 -0
- kallistoapi-2.0.1/kallistoapi/kallisto_helper.py +57 -0
- kallistoapi-2.0.1/kallistoapi/kallisto_manager.py +673 -0
- kallistoapi-2.0.1/kallistoapi/kallisto_sensry_serive_microstrain.py +184 -0
- kallistoapi-2.0.1/kallistoapi/kallisto_time.py +82 -0
- kallistoapi-2.0.1/kallistoapi/mcumgr.py +204 -0
- kallistoapi-2.0.1/kallistoapi/modules/__init__.py +0 -0
- kallistoapi-2.0.1/kallistoapi/modules/base.py +104 -0
- kallistoapi-2.0.1/kallistoapi/modules/device_info.py +43 -0
- kallistoapi-2.0.1/kallistoapi/modules/list.py +57 -0
- kallistoapi-2.0.1/kallistoapi/modules/sensor.py +383 -0
- kallistoapi-2.0.1/kallistoapi/modules/sensor_accelerometer.py +98 -0
- kallistoapi-2.0.1/kallistoapi/modules/sensor_barometer.py +71 -0
- kallistoapi-2.0.1/kallistoapi/modules/sensor_bvoc.py +71 -0
- kallistoapi-2.0.1/kallistoapi/modules/sensor_eco2.py +71 -0
- kallistoapi-2.0.1/kallistoapi/modules/sensor_env_vector.py +68 -0
- kallistoapi-2.0.1/kallistoapi/modules/sensor_fuel_gauge.py +40 -0
- kallistoapi-2.0.1/kallistoapi/modules/sensor_gyrometer.py +99 -0
- kallistoapi-2.0.1/kallistoapi/modules/sensor_humidity.py +71 -0
- kallistoapi-2.0.1/kallistoapi/modules/sensor_iaq.py +71 -0
- kallistoapi-2.0.1/kallistoapi/modules/sensor_light.py +71 -0
- kallistoapi-2.0.1/kallistoapi/modules/sensor_magnetometer.py +70 -0
- kallistoapi-2.0.1/kallistoapi/modules/sensor_pressure.py +71 -0
- kallistoapi-2.0.1/kallistoapi/modules/sensor_pt100.py +71 -0
- kallistoapi-2.0.1/kallistoapi/modules/sensor_temperature.py +71 -0
- kallistoapi-2.0.1/kallistoapi/modules/sensor_tvoc.py +71 -0
- kallistoapi-2.0.1/kallistoapi/modules/sensor_tx_power.py +86 -0
- kallistoapi-2.0.1/kallistoapi/modules/sensor_vibration.py +117 -0
- kallistoapi-2.0.1/kallistoapi.egg-info/PKG-INFO +140 -0
- kallistoapi-2.0.1/kallistoapi.egg-info/SOURCES.txt +39 -0
- kallistoapi-2.0.1/kallistoapi.egg-info/dependency_links.txt +1 -0
- kallistoapi-2.0.1/kallistoapi.egg-info/requires.txt +10 -0
- kallistoapi-2.0.1/kallistoapi.egg-info/top_level.txt +2 -0
- kallistoapi-2.0.1/pyproject.toml +28 -0
- kallistoapi-2.0.1/setup.cfg +4 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2026 sensry.io
|
|
5
|
+
|
|
6
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
you may not use this file except in compliance with the License.
|
|
8
|
+
You may obtain a copy of the License at
|
|
9
|
+
|
|
10
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
|
|
12
|
+
Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
See the License for the specific language governing permissions and
|
|
16
|
+
limitations under the License.
|
|
17
|
+
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kallistoapi
|
|
3
|
+
Version: 2.0.1
|
|
4
|
+
Summary: Sensry Kallisto API package
|
|
5
|
+
Author-email: Dzmitry Yemelyanau <d.yemelyanau@sensry.de>
|
|
6
|
+
License: Apache License
|
|
7
|
+
Version 2.0, January 2004
|
|
8
|
+
|
|
9
|
+
Copyright (c) 2026 sensry.io
|
|
10
|
+
|
|
11
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
12
|
+
you may not use this file except in compliance with the License.
|
|
13
|
+
You may obtain a copy of the License at
|
|
14
|
+
|
|
15
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
16
|
+
|
|
17
|
+
Unless required by applicable law or agreed to in writing, software
|
|
18
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
20
|
+
See the License for the specific language governing permissions and
|
|
21
|
+
limitations under the License.
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
Project-URL: Homepage, https://gitlab.sensry.net/public_external/kallisto/kallisto-api-pypi
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: bleak==0.22.3
|
|
28
|
+
Requires-Dist: dateutils==0.6.12
|
|
29
|
+
Requires-Dist: psutil==6.1.0
|
|
30
|
+
Requires-Dist: pywin32==310; sys_platform == "win32"
|
|
31
|
+
Requires-Dist: scipy==1.15.2
|
|
32
|
+
Requires-Dist: numpy==2.4.2
|
|
33
|
+
Requires-Dist: crcmod==1.7
|
|
34
|
+
Requires-Dist: protobuf==6.31.1
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
|
|
37
|
+
# KallistoAPI Python Library
|
|
38
|
+
|
|
39
|
+
**KallistoAPI** is a Python library for interacting with Kallisto sensor nodes over BLE (Bluetooth Low Energy). It provides easy access to device information, time synchronization, and readings from a wide range of environmental and motion sensors.
|
|
40
|
+
|
|
41
|
+
This library is designed for developers and researchers who want to integrate Kallisto sensor data into Python applications with minimal setup.
|
|
42
|
+
|
|
43
|
+
## Features
|
|
44
|
+
|
|
45
|
+
- Connect to Kallisto sensor nodes via BLE
|
|
46
|
+
- Read and update device time
|
|
47
|
+
- Access a variety of sensor modules including temperature, humidity, accelerometer, gyrometer, light, pressure, gas sensors, and more
|
|
48
|
+
|
|
49
|
+
## Installation
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install kallistoapi
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Quick Start
|
|
56
|
+
|
|
57
|
+
Here’s a simple example showing how to connect to a Kallisto device, and get the accelerometer values:
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from time import sleep
|
|
61
|
+
from kallistoapi.kallisto_manager import KallistoManager
|
|
62
|
+
|
|
63
|
+
import argparse
|
|
64
|
+
|
|
65
|
+
parser = argparse.ArgumentParser(description="Connect to a BLE device using KallistoSensorsManager")
|
|
66
|
+
parser.add_argument(
|
|
67
|
+
"-m", "--mac",
|
|
68
|
+
help=f"BLE MAC address"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
args = parser.parse_args()
|
|
72
|
+
mac_address = args.mac
|
|
73
|
+
|
|
74
|
+
kallisto = KallistoManager()
|
|
75
|
+
|
|
76
|
+
if not kallisto.connect(mac_address):
|
|
77
|
+
print("Failed to connect to Kallisto")
|
|
78
|
+
exit(1)
|
|
79
|
+
|
|
80
|
+
modules = kallisto.discover_modules()
|
|
81
|
+
print("available modules")
|
|
82
|
+
for module in modules:
|
|
83
|
+
print(f" - {module}")
|
|
84
|
+
|
|
85
|
+
accelerometer0 = kallisto.get_module("accelerometer", 0)
|
|
86
|
+
|
|
87
|
+
parameters = accelerometer0.parameters()
|
|
88
|
+
print(f"available parameters for {accelerometer0}")
|
|
89
|
+
for parameter, desc in parameters.items():
|
|
90
|
+
print(f" - {parameter}: {desc}")
|
|
91
|
+
|
|
92
|
+
accelerometer0.configure("enable", True)
|
|
93
|
+
accelerometer0.configure("sample_rate", "200Hz")
|
|
94
|
+
accelerometer0.configure("sensitivity", "8g")
|
|
95
|
+
accelerometer0.apply_config()
|
|
96
|
+
|
|
97
|
+
def handle_accel(sender, data_array):
|
|
98
|
+
value_list = accelerometer0.decode(data_array)
|
|
99
|
+
print("handle_accel value_list {}".format(value_list))
|
|
100
|
+
|
|
101
|
+
accelerometer0.start_notify(handle_accel)
|
|
102
|
+
|
|
103
|
+
sleep(20)
|
|
104
|
+
|
|
105
|
+
accelerometer0.stop_notify()
|
|
106
|
+
|
|
107
|
+
kallisto.disconnect()
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Available Sensor Modules
|
|
112
|
+
|
|
113
|
+
Kallisto currently supports the following sensor modules:
|
|
114
|
+
|
|
115
|
+
### Motion & Orientation (IMU)
|
|
116
|
+
- `vibration`
|
|
117
|
+
- `magnetometer`
|
|
118
|
+
- `accelerometer`
|
|
119
|
+
- `gyrometer`
|
|
120
|
+
|
|
121
|
+
### Environmental / Air Quality
|
|
122
|
+
- `temperature`
|
|
123
|
+
- `light`
|
|
124
|
+
- `pressure`
|
|
125
|
+
- `humidity`
|
|
126
|
+
- `eco2`
|
|
127
|
+
- `bvoc`
|
|
128
|
+
- `iaq`
|
|
129
|
+
|
|
130
|
+
### ADC Sensors
|
|
131
|
+
- `pt100`
|
|
132
|
+
|
|
133
|
+
### Device & Power
|
|
134
|
+
- `fuel_gauge`
|
|
135
|
+
- `tx_power`
|
|
136
|
+
- `device_info`
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# KallistoAPI Python Library
|
|
2
|
+
|
|
3
|
+
**KallistoAPI** is a Python library for interacting with Kallisto sensor nodes over BLE (Bluetooth Low Energy). It provides easy access to device information, time synchronization, and readings from a wide range of environmental and motion sensors.
|
|
4
|
+
|
|
5
|
+
This library is designed for developers and researchers who want to integrate Kallisto sensor data into Python applications with minimal setup.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- Connect to Kallisto sensor nodes via BLE
|
|
10
|
+
- Read and update device time
|
|
11
|
+
- Access a variety of sensor modules including temperature, humidity, accelerometer, gyrometer, light, pressure, gas sensors, and more
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install kallistoapi
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
Here’s a simple example showing how to connect to a Kallisto device, and get the accelerometer values:
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
from time import sleep
|
|
25
|
+
from kallistoapi.kallisto_manager import KallistoManager
|
|
26
|
+
|
|
27
|
+
import argparse
|
|
28
|
+
|
|
29
|
+
parser = argparse.ArgumentParser(description="Connect to a BLE device using KallistoSensorsManager")
|
|
30
|
+
parser.add_argument(
|
|
31
|
+
"-m", "--mac",
|
|
32
|
+
help=f"BLE MAC address"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
args = parser.parse_args()
|
|
36
|
+
mac_address = args.mac
|
|
37
|
+
|
|
38
|
+
kallisto = KallistoManager()
|
|
39
|
+
|
|
40
|
+
if not kallisto.connect(mac_address):
|
|
41
|
+
print("Failed to connect to Kallisto")
|
|
42
|
+
exit(1)
|
|
43
|
+
|
|
44
|
+
modules = kallisto.discover_modules()
|
|
45
|
+
print("available modules")
|
|
46
|
+
for module in modules:
|
|
47
|
+
print(f" - {module}")
|
|
48
|
+
|
|
49
|
+
accelerometer0 = kallisto.get_module("accelerometer", 0)
|
|
50
|
+
|
|
51
|
+
parameters = accelerometer0.parameters()
|
|
52
|
+
print(f"available parameters for {accelerometer0}")
|
|
53
|
+
for parameter, desc in parameters.items():
|
|
54
|
+
print(f" - {parameter}: {desc}")
|
|
55
|
+
|
|
56
|
+
accelerometer0.configure("enable", True)
|
|
57
|
+
accelerometer0.configure("sample_rate", "200Hz")
|
|
58
|
+
accelerometer0.configure("sensitivity", "8g")
|
|
59
|
+
accelerometer0.apply_config()
|
|
60
|
+
|
|
61
|
+
def handle_accel(sender, data_array):
|
|
62
|
+
value_list = accelerometer0.decode(data_array)
|
|
63
|
+
print("handle_accel value_list {}".format(value_list))
|
|
64
|
+
|
|
65
|
+
accelerometer0.start_notify(handle_accel)
|
|
66
|
+
|
|
67
|
+
sleep(20)
|
|
68
|
+
|
|
69
|
+
accelerometer0.stop_notify()
|
|
70
|
+
|
|
71
|
+
kallisto.disconnect()
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Available Sensor Modules
|
|
76
|
+
|
|
77
|
+
Kallisto currently supports the following sensor modules:
|
|
78
|
+
|
|
79
|
+
### Motion & Orientation (IMU)
|
|
80
|
+
- `vibration`
|
|
81
|
+
- `magnetometer`
|
|
82
|
+
- `accelerometer`
|
|
83
|
+
- `gyrometer`
|
|
84
|
+
|
|
85
|
+
### Environmental / Air Quality
|
|
86
|
+
- `temperature`
|
|
87
|
+
- `light`
|
|
88
|
+
- `pressure`
|
|
89
|
+
- `humidity`
|
|
90
|
+
- `eco2`
|
|
91
|
+
- `bvoc`
|
|
92
|
+
- `iaq`
|
|
93
|
+
|
|
94
|
+
### ADC Sensors
|
|
95
|
+
- `pt100`
|
|
96
|
+
|
|
97
|
+
### Device & Power
|
|
98
|
+
- `fuel_gauge`
|
|
99
|
+
- `tx_power`
|
|
100
|
+
- `device_info`
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#kallistointegrationtest/support$ protoc --python_out=. kallistoapi/config.proto
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
|
|
3
|
+
from bleak import BleakClient, BleakScanner
|
|
4
|
+
import asyncio
|
|
5
|
+
# from pydbus import SystemBus
|
|
6
|
+
|
|
7
|
+
class BluetoothGatt:
|
|
8
|
+
def __init__(self):
|
|
9
|
+
self._client = None
|
|
10
|
+
self._mac = "none"
|
|
11
|
+
|
|
12
|
+
# bleak runs in async, we need to have a way to run the loop in parallel to pythons
|
|
13
|
+
# sync calls. so we let the loop run in a thread
|
|
14
|
+
self._bleak_loop_thread = None
|
|
15
|
+
self._bleak_client_loop = None
|
|
16
|
+
self._bleak_loop_thread_started = threading.Event()
|
|
17
|
+
self._start_bleak_loop_thread()
|
|
18
|
+
|
|
19
|
+
self.context = None
|
|
20
|
+
self.notify_dict = {}
|
|
21
|
+
self.service_handlers = {}
|
|
22
|
+
|
|
23
|
+
self.disconnect_handler = None
|
|
24
|
+
|
|
25
|
+
def connect(self, mac_address: str, disconnect_callback=None):
|
|
26
|
+
# if self.is_device_connected(mac_address):
|
|
27
|
+
# print(f"Device {mac_address} is already connected")
|
|
28
|
+
# return False
|
|
29
|
+
|
|
30
|
+
if self.is_connected():
|
|
31
|
+
if mac_address == self._mac:
|
|
32
|
+
return True
|
|
33
|
+
print(f"disconnecting from {self._mac}")
|
|
34
|
+
self.disconnect()
|
|
35
|
+
|
|
36
|
+
self._mac = mac_address
|
|
37
|
+
|
|
38
|
+
self.disconnect_handler = disconnect_callback
|
|
39
|
+
if not self._await_bleak_loop(self._connect(self._mac), 60):
|
|
40
|
+
self.disconnect_handler = None
|
|
41
|
+
print("connection timed out")
|
|
42
|
+
return False
|
|
43
|
+
self._discover_services()
|
|
44
|
+
return True
|
|
45
|
+
|
|
46
|
+
def disconnect(self):
|
|
47
|
+
return self._await_bleak_loop(self._disconnect())
|
|
48
|
+
|
|
49
|
+
# def is_device_connected(self, mac_address):
|
|
50
|
+
# dbus_path = "/org/bluez/hci0/dev_" + mac_address.replace(":", "_")
|
|
51
|
+
# bus = SystemBus()
|
|
52
|
+
# mngr = bus.get("org.bluez", "/")
|
|
53
|
+
# objects = mngr.GetManagedObjects()
|
|
54
|
+
# device = objects.get(dbus_path, {}).get("org.bluez.Device1")
|
|
55
|
+
# return device.get("Connected", False) if device else False
|
|
56
|
+
#
|
|
57
|
+
def scan_for_devices(self):
|
|
58
|
+
return self._await_bleak_loop(self._scan_for_devices())
|
|
59
|
+
|
|
60
|
+
def detect_services(self):
|
|
61
|
+
return self._await_bleak_loop(self._detect_services())
|
|
62
|
+
|
|
63
|
+
def read_gatt_characteristics(self, characteristic_uuid):
|
|
64
|
+
return self._await_bleak_loop(self._read_gatt_characteristics(characteristic_uuid))
|
|
65
|
+
|
|
66
|
+
def get_service(self, characteristic_uuid):
|
|
67
|
+
return self._client.services.get_service(characteristic_uuid)
|
|
68
|
+
|
|
69
|
+
def start_gatt_notify(self, characteristic_uuid, notify_cb):
|
|
70
|
+
return self._await_bleak_loop(self._start_gatt_notify(characteristic_uuid, notify_cb))
|
|
71
|
+
|
|
72
|
+
def stop_gatt_notify(self, characteristic_uuid):
|
|
73
|
+
return self._await_bleak_loop(self._stop_gatt_notify(characteristic_uuid))
|
|
74
|
+
|
|
75
|
+
def write_gatt_characteristics(self, characteristic_uuid, data):
|
|
76
|
+
return self._await_bleak_loop(self._write_gatt_characteristics(characteristic_uuid, data))
|
|
77
|
+
|
|
78
|
+
def get_mac_address(self):
|
|
79
|
+
return self._mac
|
|
80
|
+
|
|
81
|
+
def is_connected(self):
|
|
82
|
+
if self._client is None:
|
|
83
|
+
return False
|
|
84
|
+
return self._client.is_connected
|
|
85
|
+
|
|
86
|
+
def get_uuid_from_handle(self, handle):
|
|
87
|
+
if handle in self.service_handlers:
|
|
88
|
+
return self.service_handlers[handle]
|
|
89
|
+
else:
|
|
90
|
+
return None
|
|
91
|
+
|
|
92
|
+
###############################
|
|
93
|
+
# internal functions
|
|
94
|
+
def _discover_services(self):
|
|
95
|
+
for service in self._client.services:
|
|
96
|
+
for characteristic in service.characteristics:
|
|
97
|
+
self.service_handlers[characteristic.handle] = characteristic.uuid
|
|
98
|
+
|
|
99
|
+
###############################
|
|
100
|
+
# async functions
|
|
101
|
+
|
|
102
|
+
def _start_bleak_loop_thread(self):
|
|
103
|
+
self._bleak_thread = threading.Thread(target=self._run_bleak_loop_thread)
|
|
104
|
+
self._bleak_thread.daemon = True
|
|
105
|
+
self._bleak_thread.start()
|
|
106
|
+
# finally wait for the thread to have properly started
|
|
107
|
+
self._bleak_loop_thread_started.wait()
|
|
108
|
+
|
|
109
|
+
def _run_bleak_loop_thread(self):
|
|
110
|
+
self._bleak_client_loop = asyncio.new_event_loop()
|
|
111
|
+
self._bleak_loop_thread_started.set()
|
|
112
|
+
self._bleak_client_loop.run_forever()
|
|
113
|
+
|
|
114
|
+
def _await_bleak_loop(self, coro, timeout=10):
|
|
115
|
+
future = asyncio.run_coroutine_threadsafe(coro, self._bleak_client_loop)
|
|
116
|
+
try:
|
|
117
|
+
return future.result(timeout)
|
|
118
|
+
except asyncio.TimeoutError:
|
|
119
|
+
print("Timeout waiting for bluetooth operation")
|
|
120
|
+
return False
|
|
121
|
+
|
|
122
|
+
async def _connect(self, mac_address):
|
|
123
|
+
self._client = BleakClient(mac_address, disconnected_callback=self._disconnect_handler)
|
|
124
|
+
if self._client is None:
|
|
125
|
+
print(f"Failed to create client for {mac_address}")
|
|
126
|
+
return False
|
|
127
|
+
try:
|
|
128
|
+
await self._client.connect()
|
|
129
|
+
except Exception as e:
|
|
130
|
+
print(f"Failed to connect to {mac_address}: {e}")
|
|
131
|
+
return False
|
|
132
|
+
if self._client.is_connected:
|
|
133
|
+
print(f"Connected to {mac_address}")
|
|
134
|
+
self._mac = mac_address
|
|
135
|
+
return True
|
|
136
|
+
else:
|
|
137
|
+
self._mac = "none"
|
|
138
|
+
print(f"Failed to connect to {mac_address}")
|
|
139
|
+
return False
|
|
140
|
+
|
|
141
|
+
async def _disconnect(self):
|
|
142
|
+
if self._client:
|
|
143
|
+
await self._client.disconnect()
|
|
144
|
+
print(f"Disconnected successfully")
|
|
145
|
+
else:
|
|
146
|
+
print("No device to disconnect")
|
|
147
|
+
|
|
148
|
+
def _disconnect_handler(self, client):
|
|
149
|
+
print(f"Device disconnected: {self._mac}")
|
|
150
|
+
if self.disconnect_handler is not None:
|
|
151
|
+
self.disconnect_handler()
|
|
152
|
+
return
|
|
153
|
+
|
|
154
|
+
@staticmethod
|
|
155
|
+
async def _scan_for_devices():
|
|
156
|
+
devices = await BleakScanner.discover(timeout=3.0)
|
|
157
|
+
# for device in devices:
|
|
158
|
+
# print(f"Device found: {device.name} ({device.address})")
|
|
159
|
+
return devices
|
|
160
|
+
|
|
161
|
+
async def _detect_services(self):
|
|
162
|
+
if not self.is_connected():
|
|
163
|
+
print("Not connected")
|
|
164
|
+
return {}
|
|
165
|
+
|
|
166
|
+
# This implicitly fetches services
|
|
167
|
+
services = self._client.services
|
|
168
|
+
|
|
169
|
+
s = {}
|
|
170
|
+
for service in services:
|
|
171
|
+
s[service.uuid] = {}
|
|
172
|
+
for char in service.characteristics:
|
|
173
|
+
s[service.uuid][char.uuid] = {
|
|
174
|
+
"uuid": char.uuid,
|
|
175
|
+
"description": char.description,
|
|
176
|
+
"properties": char.properties,
|
|
177
|
+
}
|
|
178
|
+
return s
|
|
179
|
+
|
|
180
|
+
# characteristics
|
|
181
|
+
async def _read_gatt_characteristics(self, characteristic_uuid):
|
|
182
|
+
return await self._client.read_gatt_char(characteristic_uuid)
|
|
183
|
+
|
|
184
|
+
async def _write_gatt_characteristics(self, characteristic_uuid, data):
|
|
185
|
+
return await self._client.write_gatt_char(characteristic_uuid, data)
|
|
186
|
+
|
|
187
|
+
async def _get_mtu(self):
|
|
188
|
+
return await self._client._acquire_mtu()
|
|
189
|
+
|
|
190
|
+
# notification
|
|
191
|
+
def _notify_callback(self, sender, data):
|
|
192
|
+
print(f"{sender}: {data}")
|
|
193
|
+
self.context.notify_dict.update({"uuid": data})
|
|
194
|
+
|
|
195
|
+
async def _start_gatt_notify(self, characteristic_uuid, notify_cb):
|
|
196
|
+
return await self._client.start_notify(characteristic_uuid, notify_cb)
|
|
197
|
+
|
|
198
|
+
async def _stop_gatt_notify(self, characteristic_uuid):
|
|
199
|
+
return await self._client.stop_notify(characteristic_uuid)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# source: kallistoapi/config.proto
|
|
4
|
+
"""Generated protocol buffer code."""
|
|
5
|
+
from google.protobuf.internal import builder as _builder
|
|
6
|
+
from google.protobuf import descriptor as _descriptor
|
|
7
|
+
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
8
|
+
from google.protobuf import symbol_database as _symbol_database
|
|
9
|
+
# @@protoc_insertion_point(imports)
|
|
10
|
+
|
|
11
|
+
_sym_db = _symbol_database.Default()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18kallistoapi/config.proto\x12\rsensry.api.v1\"m\n GlobalConfigEnabledFeaturesClass\"I\n\x04Type\x12\x0f\n\x0b\x62\x65\x61\x63on_mode\x10\x00\x12\x13\n\x0fradio_time_sync\x10\x01\x12\x1b\n\x17vibration_approximation\x10\x02\"G\n\x0bUIModeClass\"8\n\x04Type\x12\x08\n\x04none\x10\x00\x12\x0c\n\x08periodic\x10\x01\x12\x0b\n\x07sw_sync\x10\x02\x12\x0b\n\x07hw_sync\x10\x03\"K\n\x19TransformationMethodClass\".\n\x04Type\x12\x08\n\x04mean\x10\x00\x12\n\n\x06median\x10\x01\x12\x07\n\x03max\x10\x02\x12\x07\n\x03min\x10\x03\"g\n\rTimesyncClass\"!\n\rTimestampType\x12\x07\n\x03tai\x10\x00\x12\x07\n\x03utc\x10\x01\"3\n\x11InterpolationMode\x12\x08\n\x04none\x10\x00\x12\t\n\x05liner\x10\x01\x12\t\n\x05\x63ubic\x10\x02\"g\n\x0e\x45xtensionClass\"U\n\tBoardType\x12\x08\n\x04none\x10\x00\x12\n\n\x06hf_gas\x10\x01\x12\x0f\n\x0bmicrostrain\x10\x02\x12\x0f\n\x0btemperature\x10\x03\x12\x10\n\x0cthermocouple\x10\x04\"\x9a\x03\n\x06\x43onfig\x12\x31\n\tmeta_info\x18\xff\x01 \x01(\x0b\x32\x1d.sensry.api.v1.ConfigMetaInfo\x12\x38\n\x13global_config_label\x18\x02 \x01(\x0b\x32\x1b.sensry.api.v1.GlobalConfig\x12\x32\n\rsensor_config\x18\x03 \x01(\x0b\x32\x1b.sensry.api.v1.SensorConfig\x12\x42\n\x15transformation_config\x18\x04 \x01(\x0b\x32#.sensry.api.v1.TransformationConfig\x12\x38\n\x10\x65xtension_config\x18\x05 \x01(\x0b\x32\x1e.sensry.api.v1.ExtensionConfig\x12\x36\n\x0ftimesync_config\x18\x06 \x01(\x0b\x32\x1d.sensry.api.v1.TimesyncConfig\x12\x39\n\x11ui_manager_config\x18\x07 \x01(\x0b\x32\x1e.sensry.api.v1.UIManagerConfig\"=\n\x0e\x43onfigMetaInfo\x12\x16\n\x0e\x63onfig_version\x18\x01 \x02(\r\x12\x13\n\nconfig_crc\x18\xff\x01 \x02(\r\"@\n\x0fUIManagerConfig\x12-\n\x04mode\x18\x01 \x02(\x0e\x32\x1f.sensry.api.v1.UIModeClass.Type\"\x86\x01\n\x0cGlobalConfig\x12\x13\n\x0b\x64\x65vice_name\x18\x01 \x01(\t\x12\x11\n\tlog_level\x18\x02 \x01(\x05\x12N\n\x10\x65nabled_features\x18\x03 \x03(\x0e\x32\x34.sensry.api.v1.GlobalConfigEnabledFeaturesClass.Type\"\xbd\x01\n\x0eTimesyncConfig\x12\x1b\n\x13prolongation_offset\x18\x01 \x02(\x05\x12\x42\n\x0etimestamp_type\x18\x02 \x02(\x0e\x32*.sensry.api.v1.TimesyncClass.TimestampType\x12J\n\x12interpolation_mode\x18\x03 \x02(\x0e\x32..sensry.api.v1.TimesyncClass.InterpolationMode\"\xcc\x02\n\x0cSensorConfig\x12/\n\x08\x64\x65\x66\x61ults\x18\x01 \x01(\x0b\x32\x1d.sensry.api.v1.SensorDefaults\x12\x31\n\tvibration\x18\x02 \x01(\x0b\x32\x1e.sensry.api.v1.VibrationConfig\x12\x35\n\x0btemperature\x18\x03 \x01(\x0b\x32 .sensry.api.v1.TemperatureConfig\x12\x36\n\x0bmicrostrain\x18\x04 \x01(\x0b\x32!.sensry.api.v1.ADCExtentionConfig\x12\x30\n\x05pt100\x18\x05 \x01(\x0b\x32!.sensry.api.v1.ADCExtentionConfig\x12\x37\n\x0cthermocouple\x18\x06 \x01(\x0b\x32!.sensry.api.v1.ADCExtentionConfig\"5\n\x0eSensorDefaults\x12\x15\n\rsampling_rate\x18\x01 \x02(\x05\x12\x0c\n\x04unit\x18\x02 \x02(\t\"$\n\x0fVibrationConfig\x12\x11\n\tthreshold\x18\x01 \x02(\x02\"R\n\x11TemperatureConfig\x12\x15\n\rsampling_rate\x18\x01 \x01(\x05\x12\x0c\n\x04unit\x18\x02 \x01(\t\x12\x18\n\x10\x63\x61libration_mode\x18\x03 \x01(\r\"{\n\x14TransformationConfig\x12\r\n\x05scale\x18\x01 \x02(\x02\x12\x0e\n\x06offset\x18\x02 \x01(\x02\x12\x0f\n\x07\x66ilters\x18\x03 \x03(\t\x12\x33\n\x06\x63ustom\x18\x04 \x01(\x0b\x32#.sensry.api.v1.TransformationCustom\"j\n\x14TransformationCustom\x12\x13\n\x0bwindow_size\x18\x01 \x02(\x05\x12=\n\x06method\x18\x02 \x02(\x0e\x32-.sensry.api.v1.TransformationMethodClass.Type\"X\n\x0f\x45xtensionConfig\x12\x45\n\x14\x65xtension_board_type\x18\x01 \x02(\x0e\x32\'.sensry.api.v1.ExtensionClass.BoardType\"\xf3\x01\n\x0f\x41\x64\x63\x44riverConfig\x12\x1a\n\x12samples_per_second\x18\x01 \x01(\r\x12\r\n\x05v_ref\x18\x02 \x01(\r\x12\x18\n\x10\x63ontiniouse_mode\x18\x03 \x01(\r\x12\x10\n\x08\x61\x64\x63_gain\x18\x04 \x01(\r\x12\x10\n\x08meas_cur\x18\x05 \x01(\r\x12\x17\n\x0fmeas_cur_output\x18\x06 \x01(\r\x12\x14\n\x0c\x64ifferential\x18\x07 \x01(\r\x12\x10\n\x08idac1_ch\x18\x08 \x01(\r\x12\x10\n\x08idac2_ch\x18\t \x01(\r\x12\x11\n\tinput_pos\x18\n \x01(\r\x12\x11\n\tinput_neg\x18\x0b \x01(\r\"H\n\x11\x41\x44\x43SensorWireMode\"3\n\x04Type\x12\x0c\n\x08two_wire\x10\x00\x12\x0e\n\nthree_wire\x10\x01\x12\r\n\tfour_wire\x10\x02\"\x9a\x02\n\x13\x41\x44\x43SensorItemConfig\x12\x15\n\rover_sampling\x18\x02 \x01(\r\x12 \n\x18oversampling_interval_us\x18\x03 \x01(\r\x12\x12\n\nresolution\x18\x04 \x01(\r\x12\r\n\x05r_ref\x18\x05 \x01(\x02\x12\x0e\n\x06offset\x18\x06 \x01(\x02\x12\x18\n\x10\x61\x64\x63_quantization\x18\x07 \x01(\x02\x12\x0f\n\x07lp_coof\x18\x08 \x01(\x02\x12\x38\n\twire_mode\x18\t \x01(\x0e\x32%.sensry.api.v1.ADCSensorWireMode.Type\x12\x32\n\nadc_config\x18\n \x03(\x0b\x32\x1e.sensry.api.v1.AdcDriverConfig\"s\n\x12\x41\x44\x43\x45xtentionConfig\x12\x16\n\x0e\x65nable_sensors\x18\x01 \x01(\r\x12\x11\n\tperiod_us\x18\x02 \x01(\r\x12\x32\n\x06\x63onfig\x18\x03 \x03(\x0b\x32\".sensry.api.v1.ADCSensorItemConfig')
|
|
17
|
+
|
|
18
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
|
|
19
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'kallistoapi.config_pb2', globals())
|
|
20
|
+
if _descriptor._USE_C_DESCRIPTORS == False:
|
|
21
|
+
|
|
22
|
+
DESCRIPTOR._options = None
|
|
23
|
+
_GLOBALCONFIGENABLEDFEATURESCLASS._serialized_start=43
|
|
24
|
+
_GLOBALCONFIGENABLEDFEATURESCLASS._serialized_end=152
|
|
25
|
+
_GLOBALCONFIGENABLEDFEATURESCLASS_TYPE._serialized_start=79
|
|
26
|
+
_GLOBALCONFIGENABLEDFEATURESCLASS_TYPE._serialized_end=152
|
|
27
|
+
_UIMODECLASS._serialized_start=154
|
|
28
|
+
_UIMODECLASS._serialized_end=225
|
|
29
|
+
_UIMODECLASS_TYPE._serialized_start=169
|
|
30
|
+
_UIMODECLASS_TYPE._serialized_end=225
|
|
31
|
+
_TRANSFORMATIONMETHODCLASS._serialized_start=227
|
|
32
|
+
_TRANSFORMATIONMETHODCLASS._serialized_end=302
|
|
33
|
+
_TRANSFORMATIONMETHODCLASS_TYPE._serialized_start=256
|
|
34
|
+
_TRANSFORMATIONMETHODCLASS_TYPE._serialized_end=302
|
|
35
|
+
_TIMESYNCCLASS._serialized_start=304
|
|
36
|
+
_TIMESYNCCLASS._serialized_end=407
|
|
37
|
+
_TIMESYNCCLASS_TIMESTAMPTYPE._serialized_start=321
|
|
38
|
+
_TIMESYNCCLASS_TIMESTAMPTYPE._serialized_end=354
|
|
39
|
+
_TIMESYNCCLASS_INTERPOLATIONMODE._serialized_start=356
|
|
40
|
+
_TIMESYNCCLASS_INTERPOLATIONMODE._serialized_end=407
|
|
41
|
+
_EXTENSIONCLASS._serialized_start=409
|
|
42
|
+
_EXTENSIONCLASS._serialized_end=512
|
|
43
|
+
_EXTENSIONCLASS_BOARDTYPE._serialized_start=427
|
|
44
|
+
_EXTENSIONCLASS_BOARDTYPE._serialized_end=512
|
|
45
|
+
_CONFIG._serialized_start=515
|
|
46
|
+
_CONFIG._serialized_end=925
|
|
47
|
+
_CONFIGMETAINFO._serialized_start=927
|
|
48
|
+
_CONFIGMETAINFO._serialized_end=988
|
|
49
|
+
_UIMANAGERCONFIG._serialized_start=990
|
|
50
|
+
_UIMANAGERCONFIG._serialized_end=1054
|
|
51
|
+
_GLOBALCONFIG._serialized_start=1057
|
|
52
|
+
_GLOBALCONFIG._serialized_end=1191
|
|
53
|
+
_TIMESYNCCONFIG._serialized_start=1194
|
|
54
|
+
_TIMESYNCCONFIG._serialized_end=1383
|
|
55
|
+
_SENSORCONFIG._serialized_start=1386
|
|
56
|
+
_SENSORCONFIG._serialized_end=1718
|
|
57
|
+
_SENSORDEFAULTS._serialized_start=1720
|
|
58
|
+
_SENSORDEFAULTS._serialized_end=1773
|
|
59
|
+
_VIBRATIONCONFIG._serialized_start=1775
|
|
60
|
+
_VIBRATIONCONFIG._serialized_end=1811
|
|
61
|
+
_TEMPERATURECONFIG._serialized_start=1813
|
|
62
|
+
_TEMPERATURECONFIG._serialized_end=1895
|
|
63
|
+
_TRANSFORMATIONCONFIG._serialized_start=1897
|
|
64
|
+
_TRANSFORMATIONCONFIG._serialized_end=2020
|
|
65
|
+
_TRANSFORMATIONCUSTOM._serialized_start=2022
|
|
66
|
+
_TRANSFORMATIONCUSTOM._serialized_end=2128
|
|
67
|
+
_EXTENSIONCONFIG._serialized_start=2130
|
|
68
|
+
_EXTENSIONCONFIG._serialized_end=2218
|
|
69
|
+
_ADCDRIVERCONFIG._serialized_start=2221
|
|
70
|
+
_ADCDRIVERCONFIG._serialized_end=2464
|
|
71
|
+
_ADCSENSORWIREMODE._serialized_start=2466
|
|
72
|
+
_ADCSENSORWIREMODE._serialized_end=2538
|
|
73
|
+
_ADCSENSORWIREMODE_TYPE._serialized_start=2487
|
|
74
|
+
_ADCSENSORWIREMODE_TYPE._serialized_end=2538
|
|
75
|
+
_ADCSENSORITEMCONFIG._serialized_start=2541
|
|
76
|
+
_ADCSENSORITEMCONFIG._serialized_end=2823
|
|
77
|
+
_ADCEXTENTIONCONFIG._serialized_start=2825
|
|
78
|
+
_ADCEXTENTIONCONFIG._serialized_end=2940
|
|
79
|
+
# @@protoc_insertion_point(module_scope)
|