ruuvitag-sensor 2.2.0__py3-none-any.whl → 2.3.1__py3-none-any.whl
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.
Potentially problematic release.
This version of ruuvitag-sensor might be problematic. Click here for more details.
- ruuvitag_sensor/adapters/__init__.py +40 -10
- ruuvitag_sensor/adapters/bleak_ble.py +17 -5
- ruuvitag_sensor/adapters/bleson.py +4 -0
- ruuvitag_sensor/adapters/utils.py +2 -0
- ruuvitag_sensor/data_formats.py +1 -1
- ruuvitag_sensor/ruuvi.py +20 -6
- {ruuvitag_sensor-2.2.0.dist-info → ruuvitag_sensor-2.3.1.dist-info}/METADATA +96 -70
- {ruuvitag_sensor-2.2.0.dist-info → ruuvitag_sensor-2.3.1.dist-info}/RECORD +11 -10
- {ruuvitag_sensor-2.2.0.dist-info → ruuvitag_sensor-2.3.1.dist-info}/WHEEL +1 -1
- {ruuvitag_sensor-2.2.0.dist-info → ruuvitag_sensor-2.3.1.dist-info}/LICENSE +0 -0
- {ruuvitag_sensor-2.2.0.dist-info → ruuvitag_sensor-2.3.1.dist-info}/top_level.txt +0 -0
|
@@ -5,29 +5,49 @@ from typing import AsyncGenerator, Generator, List
|
|
|
5
5
|
|
|
6
6
|
from ruuvitag_sensor.ruuvi_types import MacAndRawData, RawData
|
|
7
7
|
|
|
8
|
-
# pylint: disable=import-outside-toplevel, cyclic-import
|
|
8
|
+
# pylint: disable=import-outside-toplevel, cyclic-import, too-many-return-statements
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def get_ble_adapter():
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
forced_ble_adapter = os.environ.get("RUUVI_BLE_ADAPTER", "").lower()
|
|
13
|
+
use_ruuvi_nix_from_file = "RUUVI_NIX_FROMFILE" in os.environ
|
|
14
|
+
is_ci_env = "CI" in os.environ
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
if forced_ble_adapter:
|
|
17
|
+
if "bleak" in forced_ble_adapter:
|
|
18
|
+
from ruuvitag_sensor.adapters.bleak_ble import BleCommunicationBleak
|
|
19
|
+
|
|
20
|
+
return BleCommunicationBleak()
|
|
21
|
+
if "bleson" in forced_ble_adapter:
|
|
22
|
+
from ruuvitag_sensor.adapters.bleson import BleCommunicationBleson
|
|
23
|
+
|
|
24
|
+
return BleCommunicationBleson()
|
|
25
|
+
if "bluez" in forced_ble_adapter:
|
|
26
|
+
from ruuvitag_sensor.adapters.nix_hci import BleCommunicationNix
|
|
18
27
|
|
|
19
|
-
|
|
20
|
-
|
|
28
|
+
return BleCommunicationNix()
|
|
29
|
+
|
|
30
|
+
raise RuntimeError(f"Unknown BLE adapter: {forced_ble_adapter}")
|
|
31
|
+
|
|
32
|
+
if use_ruuvi_nix_from_file:
|
|
21
33
|
# Emulate BleCommunicationNix by reading hcidump data from a file
|
|
22
34
|
from ruuvitag_sensor.adapters.nix_hci_file import BleCommunicationNixFile
|
|
23
35
|
|
|
24
36
|
return BleCommunicationNixFile()
|
|
25
|
-
|
|
26
|
-
|
|
37
|
+
|
|
38
|
+
if is_ci_env:
|
|
39
|
+
# Use BleCommunicationDummy for CI as it can't use BlueZ
|
|
27
40
|
from ruuvitag_sensor.adapters.dummy import BleCommunicationDummy
|
|
28
41
|
|
|
29
42
|
return BleCommunicationDummy()
|
|
30
43
|
|
|
44
|
+
# Use default adapter for platform
|
|
45
|
+
if sys.platform.startswith("win") or sys.platform.startswith("darwin"):
|
|
46
|
+
from ruuvitag_sensor.adapters.bleak_ble import BleCommunicationBleak
|
|
47
|
+
|
|
48
|
+
return BleCommunicationBleak()
|
|
49
|
+
|
|
50
|
+
# BlueZ is default for Linux
|
|
31
51
|
from ruuvitag_sensor.adapters.nix_hci import BleCommunicationNix
|
|
32
52
|
|
|
33
53
|
return BleCommunicationNix()
|
|
@@ -41,6 +61,16 @@ def is_async_from_env():
|
|
|
41
61
|
return "bleak" in os.environ.get("RUUVI_BLE_ADAPTER", "").lower()
|
|
42
62
|
|
|
43
63
|
|
|
64
|
+
def throw_if_not_sync_adapter(ble: object):
|
|
65
|
+
if is_async_adapter(ble):
|
|
66
|
+
raise RuntimeError("Sync BLE adapter required")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def throw_if_not_async_adapter(ble: object):
|
|
70
|
+
if not is_async_adapter(ble):
|
|
71
|
+
raise RuntimeError("Async BLE adapter required")
|
|
72
|
+
|
|
73
|
+
|
|
44
74
|
class BleCommunication:
|
|
45
75
|
"""Bluetooth LE communication"""
|
|
46
76
|
|
|
@@ -6,15 +6,16 @@ import sys
|
|
|
6
6
|
from typing import AsyncGenerator, List, Tuple
|
|
7
7
|
|
|
8
8
|
from bleak import BleakScanner
|
|
9
|
-
from bleak.backends.scanner import AdvertisementData, BLEDevice
|
|
9
|
+
from bleak.backends.scanner import AdvertisementData, AdvertisementDataCallback, BLEDevice
|
|
10
10
|
|
|
11
11
|
from ruuvitag_sensor.adapters import BleCommunicationAsync
|
|
12
|
+
from ruuvitag_sensor.adapters.utils import rssi_to_hex
|
|
12
13
|
from ruuvitag_sensor.ruuvi_types import MacAndRawData, RawData
|
|
13
14
|
|
|
14
15
|
MAC_REGEX = "[0-9a-f]{2}([:])[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$"
|
|
15
16
|
|
|
16
17
|
|
|
17
|
-
def _get_scanner(detection_callback):
|
|
18
|
+
def _get_scanner(detection_callback: AdvertisementDataCallback, bt_device: str = ""):
|
|
18
19
|
# NOTE: On Linux - bleak.exc.BleakError: passive scanning mode requires bluez or_patterns
|
|
19
20
|
# NOTE: On macOS - bleak.exc.BleakError: macOS does not support passive scanning
|
|
20
21
|
scanning_mode = "passive" if sys.platform.startswith("win") else "active"
|
|
@@ -25,7 +26,12 @@ def _get_scanner(detection_callback):
|
|
|
25
26
|
|
|
26
27
|
return DevBleakScanner(detection_callback, scanning_mode)
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
if bt_device:
|
|
30
|
+
return BleakScanner(
|
|
31
|
+
detection_callback=detection_callback, scanning_mode=scanning_mode, adapter=bt_device
|
|
32
|
+
) # type: ignore[arg-type]
|
|
33
|
+
|
|
34
|
+
return BleakScanner(detection_callback=detection_callback, scanning_mode=scanning_mode) # type: ignore[arg-type]
|
|
29
35
|
|
|
30
36
|
|
|
31
37
|
# TODO: Python 3.7 - TypeError: 'type' object is not subscriptable
|
|
@@ -71,15 +77,19 @@ class BleCommunicationBleak(BleCommunicationAsync):
|
|
|
71
77
|
if 1177 not in advertisement_data.manufacturer_data:
|
|
72
78
|
return
|
|
73
79
|
|
|
80
|
+
log.debug("Received data: %s", advertisement_data)
|
|
81
|
+
|
|
74
82
|
data = BleCommunicationBleak._parse_data(advertisement_data.manufacturer_data[1177])
|
|
75
83
|
|
|
76
84
|
# Add RSSI to encoded data as hex. All adapters use a common decoder.
|
|
77
|
-
data +=
|
|
85
|
+
data += rssi_to_hex(advertisement_data.rssi)
|
|
78
86
|
await queue.put((mac, data))
|
|
79
87
|
|
|
80
|
-
scanner = _get_scanner(detection_callback)
|
|
88
|
+
scanner = _get_scanner(detection_callback, bt_device)
|
|
81
89
|
await scanner.start()
|
|
82
90
|
|
|
91
|
+
log.debug("Bleak scanner started")
|
|
92
|
+
|
|
83
93
|
try:
|
|
84
94
|
while True:
|
|
85
95
|
next_item: Tuple[str, str] = await queue.get()
|
|
@@ -93,6 +103,8 @@ class BleCommunicationBleak(BleCommunicationAsync):
|
|
|
93
103
|
|
|
94
104
|
await scanner.stop()
|
|
95
105
|
|
|
106
|
+
log.debug("Bleak scanner stopped")
|
|
107
|
+
|
|
96
108
|
@staticmethod
|
|
97
109
|
async def get_first_data(mac: str, bt_device: str = "") -> RawData:
|
|
98
110
|
"""
|
|
@@ -8,6 +8,7 @@ from typing import Generator, List
|
|
|
8
8
|
from bleson import Observer, get_provider
|
|
9
9
|
|
|
10
10
|
from ruuvitag_sensor.adapters import BleCommunication
|
|
11
|
+
from ruuvitag_sensor.adapters.utils import rssi_to_hex
|
|
11
12
|
from ruuvitag_sensor.ruuvi_types import MacAndRawData, RawData
|
|
12
13
|
|
|
13
14
|
log = logging.getLogger(__name__)
|
|
@@ -56,6 +57,9 @@ class BleCommunicationBleson(BleCommunication):
|
|
|
56
57
|
data = f"FF{data.hex()}"
|
|
57
58
|
data = f"{(len(data) >> 1):02x}{data}"
|
|
58
59
|
data = f"{(len(data) >> 1):02x}{data}"
|
|
60
|
+
|
|
61
|
+
# Add RSSI to encoded data as hex. All adapters use a common decoder.
|
|
62
|
+
data += rssi_to_hex(advertisement.rssi)
|
|
59
63
|
queue.put((mac, data.upper()))
|
|
60
64
|
except GeneratorExit:
|
|
61
65
|
break
|
ruuvitag_sensor/data_formats.py
CHANGED
|
@@ -78,7 +78,7 @@ class DataFormats:
|
|
|
78
78
|
break
|
|
79
79
|
except ShortDataError as ex:
|
|
80
80
|
# Data might be from RuuviTag, but received data was invalid
|
|
81
|
-
# e.g. it's
|
|
81
|
+
# e.g. it's possible that Bluetooth stack received only partial data
|
|
82
82
|
# Set the format to None, and data to '', this allows the
|
|
83
83
|
# caller to determine that we did indeed see a Ruuvitag.
|
|
84
84
|
log.debug("Error parsing advertisement data: %s", ex)
|
ruuvitag_sensor/ruuvi.py
CHANGED
|
@@ -5,7 +5,7 @@ from multiprocessing.managers import ListProxy
|
|
|
5
5
|
from typing import AsyncGenerator, Callable, Dict, Generator, List, Optional
|
|
6
6
|
from warnings import warn
|
|
7
7
|
|
|
8
|
-
from ruuvitag_sensor.adapters import get_ble_adapter,
|
|
8
|
+
from ruuvitag_sensor.adapters import get_ble_adapter, throw_if_not_async_adapter, throw_if_not_sync_adapter
|
|
9
9
|
from ruuvitag_sensor.data_formats import DataFormats
|
|
10
10
|
from ruuvitag_sensor.decoder import get_decoder, parse_mac
|
|
11
11
|
from ruuvitag_sensor.ruuvi_types import DataFormatAndRawSensorData, Mac, MacAndRawData, MacAndSensorData, SensorData
|
|
@@ -42,6 +42,7 @@ class RuuviTagSensor:
|
|
|
42
42
|
Returns:
|
|
43
43
|
tuple (int, string): Data Format type and raw Sensor data
|
|
44
44
|
"""
|
|
45
|
+
throw_if_not_sync_adapter(ble)
|
|
45
46
|
|
|
46
47
|
raw = ble.get_first_data(mac, bt_device)
|
|
47
48
|
return DataFormats.convert_data(raw)
|
|
@@ -60,6 +61,8 @@ class RuuviTagSensor:
|
|
|
60
61
|
Returns:
|
|
61
62
|
tuple (int, string): Data Format type and raw Sensor data
|
|
62
63
|
"""
|
|
64
|
+
throw_if_not_async_adapter(ble)
|
|
65
|
+
|
|
63
66
|
raw = await ble.get_first_data(mac, bt_device)
|
|
64
67
|
return DataFormats.convert_data(raw)
|
|
65
68
|
|
|
@@ -74,6 +77,7 @@ class RuuviTagSensor:
|
|
|
74
77
|
Returns:
|
|
75
78
|
dict: MAC and state of found sensors
|
|
76
79
|
"""
|
|
80
|
+
throw_if_not_sync_adapter(ble)
|
|
77
81
|
|
|
78
82
|
log.info("Finding RuuviTags. Stop with Ctrl+C.")
|
|
79
83
|
|
|
@@ -99,9 +103,7 @@ class RuuviTagSensor:
|
|
|
99
103
|
Returns:
|
|
100
104
|
dict: MAC and state of found sensors
|
|
101
105
|
"""
|
|
102
|
-
|
|
103
|
-
if not is_async_adapter(ble):
|
|
104
|
-
raise Exception("Only Bleak BLE communication is supported")
|
|
106
|
+
throw_if_not_async_adapter(ble)
|
|
105
107
|
|
|
106
108
|
log.info("Finding RuuviTags. Stop with Ctrl+C.")
|
|
107
109
|
|
|
@@ -135,6 +137,7 @@ class RuuviTagSensor:
|
|
|
135
137
|
Returns:
|
|
136
138
|
dict: MAC and state of found sensors
|
|
137
139
|
"""
|
|
140
|
+
throw_if_not_sync_adapter(ble)
|
|
138
141
|
|
|
139
142
|
log.info("Get latest data for sensors. Stop with Ctrl+C.")
|
|
140
143
|
log.info("Stops automatically in %ss", search_duratio_sec)
|
|
@@ -162,6 +165,7 @@ class RuuviTagSensor:
|
|
|
162
165
|
Returns:
|
|
163
166
|
dict: MAC and state of found sensors
|
|
164
167
|
"""
|
|
168
|
+
throw_if_not_async_adapter(ble)
|
|
165
169
|
|
|
166
170
|
log.info("Get latest data for sensors. Stop with Ctrl+C.")
|
|
167
171
|
log.info("Stops automatically in %ss", search_duratio_sec)
|
|
@@ -180,8 +184,16 @@ class RuuviTagSensor:
|
|
|
180
184
|
|
|
181
185
|
@staticmethod
|
|
182
186
|
async def get_data_async(macs: List[str] = [], bt_device: str = "") -> AsyncGenerator[MacAndSensorData, None]:
|
|
183
|
-
|
|
184
|
-
|
|
187
|
+
"""
|
|
188
|
+
Get data for all ruuvitag sensors or sensors in the MAC's list.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
macs (list): MAC addresses
|
|
192
|
+
bt_device (string): Bluetooth device id
|
|
193
|
+
Returns:
|
|
194
|
+
AsyncGenerator: MAC and State of RuuviTag sensor data (tuple)
|
|
195
|
+
"""
|
|
196
|
+
throw_if_not_async_adapter(ble)
|
|
185
197
|
|
|
186
198
|
mac_blacklist = Manager().list()
|
|
187
199
|
data_iter = ble.get_data(mac_blacklist, bt_device)
|
|
@@ -213,6 +225,7 @@ class RuuviTagSensor:
|
|
|
213
225
|
run_flag (object): RunFlag object. Function executes while run_flag.running
|
|
214
226
|
bt_device (string): Bluetooth device id
|
|
215
227
|
"""
|
|
228
|
+
throw_if_not_sync_adapter(ble)
|
|
216
229
|
|
|
217
230
|
log.info("Get latest data for sensors. Stop with Ctrl+C.")
|
|
218
231
|
log.info("MACs: %s", macs)
|
|
@@ -233,6 +246,7 @@ class RuuviTagSensor:
|
|
|
233
246
|
Use get_data-method instead.
|
|
234
247
|
"""
|
|
235
248
|
warn("This method will be removed in a future version, use get_data() instead", FutureWarning)
|
|
249
|
+
throw_if_not_sync_adapter(ble)
|
|
236
250
|
return RuuviTagSensor.get_data(callback, macs, run_flag, bt_device)
|
|
237
251
|
|
|
238
252
|
@staticmethod
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
|
-
Name:
|
|
3
|
-
Version: 2.
|
|
2
|
+
Name: ruuvitag_sensor
|
|
3
|
+
Version: 2.3.1
|
|
4
4
|
Summary: Find RuuviTag sensors and get decoded data from selected sensors
|
|
5
5
|
Author-email: Tomi Tuhkanen <tomi.tuhkanen@iki.fi>
|
|
6
6
|
License: MIT License
|
|
@@ -36,6 +36,7 @@ Classifier: Programming Language :: Python :: 3.8
|
|
|
36
36
|
Classifier: Programming Language :: Python :: 3.9
|
|
37
37
|
Classifier: Programming Language :: Python :: 3.10
|
|
38
38
|
Classifier: Programming Language :: Python :: 3.11
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
39
40
|
Classifier: License :: OSI Approved :: MIT License
|
|
40
41
|
Classifier: Operating System :: OS Independent
|
|
41
42
|
Classifier: Intended Audience :: Developers
|
|
@@ -47,6 +48,7 @@ Description-Content-Type: text/markdown
|
|
|
47
48
|
License-File: LICENSE
|
|
48
49
|
Requires-Dist: reactivex
|
|
49
50
|
Requires-Dist: ptyprocess ; platform_system == "Linux"
|
|
51
|
+
Requires-Dist: bleak ; platform_system == "Windows" or platform_system == "Darwin"
|
|
50
52
|
Requires-Dist: mypy-extensions ; python_version < "3.8"
|
|
51
53
|
Requires-Dist: importlib-metadata <4.3,>=1.1.0 ; python_version < "3.8"
|
|
52
54
|
Provides-Extra: dev
|
|
@@ -56,7 +58,7 @@ Requires-Dist: flake8-pyproject ; extra == 'dev'
|
|
|
56
58
|
Requires-Dist: pylint ; extra == 'dev'
|
|
57
59
|
Requires-Dist: mypy ; extra == 'dev'
|
|
58
60
|
Requires-Dist: isort ; extra == 'dev'
|
|
59
|
-
Requires-Dist: black ; extra == 'dev'
|
|
61
|
+
Requires-Dist: black ==23.3.0 ; extra == 'dev'
|
|
60
62
|
|
|
61
63
|
RuuviTag Sensor Python Package
|
|
62
64
|
---------------------------------
|
|
@@ -65,7 +67,7 @@ RuuviTag Sensor Python Package
|
|
|
65
67
|
[](https://pypi.python.org/pypi/ruuvitag-sensor/)
|
|
66
68
|
[](https://pypi.python.org/pypi/ruuvitag_-sensor)
|
|
67
69
|
[](https://pypistats.org/packages/ruuvitag-sensor)
|
|
68
|
-
[](https://pypi.python.org/pypi/ruuvitag-sensor/)
|
|
69
71
|
|
|
70
72
|
`ruuvitag-sensor` is a Python package for communicating with [RuuviTag BLE Sensor](https://ruuvi.com/) and for decoding measurement data from broadcasted BLE data.
|
|
71
73
|
|
|
@@ -73,18 +75,25 @@ RuuviTag Sensor Python Package
|
|
|
73
75
|
|
|
74
76
|
## Requirements
|
|
75
77
|
|
|
76
|
-
* RuuviTag
|
|
77
|
-
* Setup [guide](https://
|
|
78
|
-
* Supports [Data Format 2, 3, 4 and 5](https://
|
|
78
|
+
* RuuviTag sensor
|
|
79
|
+
* Setup [guide](https://ruuvi.com/quick-start/)
|
|
80
|
+
* Supports [Data Format 2, 3, 4 and 5](https://docs.ruuvi.com/)
|
|
79
81
|
* __NOTE:__ Data Formats 2, 3 and 4 are _deprecated_ and should not be used
|
|
82
|
+
* [Bleak](https://github.com/hbldh/bleak) communication module (Windows, macOS and Linux)
|
|
83
|
+
* Default adapter for Windows and macOS
|
|
84
|
+
* Bleak supports
|
|
85
|
+
* [Async-methods](#usage)
|
|
86
|
+
* [Observable streams](#usage)
|
|
87
|
+
* [Install guide](#Bleak)
|
|
80
88
|
* Bluez (Linux-only)
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
|
|
84
|
-
*
|
|
85
|
-
|
|
86
|
-
*
|
|
87
|
-
*
|
|
89
|
+
* Default adapter for Linux
|
|
90
|
+
* Bluez supports
|
|
91
|
+
* [Sync-methods](#usage)
|
|
92
|
+
* [Observable streams](#usage)
|
|
93
|
+
* [Install guide](#BlueZ)
|
|
94
|
+
* __NOTE:__ The BlueZ-adapter implementation uses deprecated BlueZ tools that are no longer supported.
|
|
95
|
+
* Even though BlueZ is still the default adapter, it is recommended to use the Bleak-communication adapter with Linux. Bleak will be the default adapter for Linux in the next major release.
|
|
96
|
+
* Bleson-adapter supports sync-methods, but please be aware that it is not fully supported due to the alpha release status of the Bleson communication module. See [Bleson](#Bleson) for more information.
|
|
88
97
|
* Python 3.7+
|
|
89
98
|
* For Python 2.x or <3.7 support, check [installation instructions](#python-2x-and-36-and-below) for an older version
|
|
90
99
|
|
|
@@ -113,8 +122,8 @@ Full installation guide for [Raspberry PI & Raspbian](https://github.com/ttu/ruu
|
|
|
113
122
|
|
|
114
123
|
The package provides 3 ways to fetch data from sensors:
|
|
115
124
|
|
|
116
|
-
1.
|
|
117
|
-
2.
|
|
125
|
+
1. Asynchronously with async/await
|
|
126
|
+
2. Synchronously with callback
|
|
118
127
|
3. Observable streams with ReactiveX
|
|
119
128
|
|
|
120
129
|
RuuviTag sensors can be identified using MAC addresses. Methods return a tuple with MAC and sensor data payload.
|
|
@@ -123,56 +132,11 @@ RuuviTag sensors can be identified using MAC addresses. Methods return a tuple w
|
|
|
123
132
|
('D2:A3:6E:C8:E0:25', {'data_format': 5, 'humidity': 47.62, 'temperature': 23.58, 'pressure': 1023.68, 'acceleration': 993.2331045630729, 'acceleration_x': -48, 'acceleration_y': -12, 'acceleration_z': 992, 'tx_power': 4, 'battery': 2197, 'movement_counter': 0, 'measurement_sequence_number': 88, 'mac': 'd2a36ec8e025', 'rssi': -80})
|
|
124
133
|
```
|
|
125
134
|
|
|
126
|
-
### 1. Get sensor data
|
|
135
|
+
### 1. Get sensor data asynchronously with async/await
|
|
127
136
|
|
|
128
|
-
|
|
137
|
+
__NOTE:__ Asynchronous functionality works only with `Bleak`-adapter.
|
|
129
138
|
|
|
130
|
-
|
|
131
|
-
from ruuvitag_sensor.ruuvi import RuuviTagSensor
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
def handle_data(found_data):
|
|
135
|
-
print(f"MAC {found_data[0]}")
|
|
136
|
-
print(f"Data {found_data[1]}")
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
if __name__ == "__main__":
|
|
140
|
-
RuuviTagSensor.get_data(handle_data)
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
The line `if __name__ == "__main__":` is required on Windows and macOS due to the way the `multiprocessing` library works. It is not required on Linux, but it is recommended. It is omitted from the rest of the examples below.
|
|
144
|
-
|
|
145
|
-
The optional list of MACs and run flag can be passed to the `get_data` function. The callback is called only for MACs in the list and setting the run flag to false will stop execution. If the run flag is not passed, the function will execute forever.
|
|
146
|
-
|
|
147
|
-
```python
|
|
148
|
-
from ruuvitag_sensor.ruuvi import RuuviTagSensor, RunFlag
|
|
149
|
-
|
|
150
|
-
counter = 10
|
|
151
|
-
# RunFlag for stopping execution at desired time
|
|
152
|
-
run_flag = RunFlag()
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
def handle_data(found_data):
|
|
156
|
-
print(f"MAC: {found_data[0]}")
|
|
157
|
-
print(f"Data: {found_data[1]}")
|
|
158
|
-
|
|
159
|
-
global counter
|
|
160
|
-
counter = counter - 1
|
|
161
|
-
if counter < 0:
|
|
162
|
-
run_flag.running = False
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
# List of MACs of sensors which will execute callback function
|
|
166
|
-
macs = ["AA:2C:6A:1E:59:3D", "CC:2C:6A:1E:59:3D"]
|
|
167
|
-
|
|
168
|
-
RuuviTagSensor.get_data(handle_data, macs, run_flag)
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
### 2. Get sensor data asynchronously
|
|
172
|
-
|
|
173
|
-
__NOTE:__ Asynchronous functionality is currently in beta state and works only with `Bleak`-adapter.
|
|
174
|
-
|
|
175
|
-
`get_data_async` returns the data whenever a RuuviTag sensor broadcasts data. `get_data_async` will exceute until iterator is exited. This method is the preferred way to use the library with async-adapter.
|
|
139
|
+
`get_data_async` returns the data whenever a RuuviTag sensor broadcasts data. `get_data_async` will execute until iterator is exited. This method is the preferred way to use the library with _Bleak_.
|
|
176
140
|
|
|
177
141
|
```py
|
|
178
142
|
import asyncio
|
|
@@ -213,6 +177,53 @@ if __name__ == "__main__":
|
|
|
213
177
|
asyncio.get_event_loop().run_until_complete(main())
|
|
214
178
|
```
|
|
215
179
|
|
|
180
|
+
The line `if __name__ == "__main__":` is required on Windows and macOS due to the way the `multiprocessing` library works. It is not required on Linux, but it is recommended. It is omitted from the rest of the examples below.
|
|
181
|
+
|
|
182
|
+
### 2. Get sensor data synchronously with callback
|
|
183
|
+
|
|
184
|
+
__NOTE:__ Asynchronous functionality works only with `BlueZ`-adapter.
|
|
185
|
+
|
|
186
|
+
`get_data` calls the callback whenever a RuuviTag sensor broadcasts data. This method is the preferred way to use the library with _BlueZ_.
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
from ruuvitag_sensor.ruuvi import RuuviTagSensor
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def handle_data(found_data):
|
|
193
|
+
print(f"MAC {found_data[0]}")
|
|
194
|
+
print(f"Data {found_data[1]}")
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
if __name__ == "__main__":
|
|
198
|
+
RuuviTagSensor.get_data(handle_data)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The optional list of MACs and run flag can be passed to the `get_data` function. The callback is called only for MACs in the list and setting the run flag to false will stop execution. If the run flag is not passed, the function will execute forever.
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
from ruuvitag_sensor.ruuvi import RuuviTagSensor, RunFlag
|
|
205
|
+
|
|
206
|
+
counter = 10
|
|
207
|
+
# RunFlag for stopping execution at desired time
|
|
208
|
+
run_flag = RunFlag()
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def handle_data(found_data):
|
|
212
|
+
print(f"MAC: {found_data[0]}")
|
|
213
|
+
print(f"Data: {found_data[1]}")
|
|
214
|
+
|
|
215
|
+
global counter
|
|
216
|
+
counter = counter - 1
|
|
217
|
+
if counter < 0:
|
|
218
|
+
run_flag.running = False
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
# List of MACs of sensors which will execute callback function
|
|
222
|
+
macs = ["AA:2C:6A:1E:59:3D", "CC:2C:6A:1E:59:3D"]
|
|
223
|
+
|
|
224
|
+
RuuviTagSensor.get_data(handle_data, macs, run_flag)
|
|
225
|
+
```
|
|
226
|
+
|
|
216
227
|
### 3. Get sensor data with observable streams (ReactiveX / RxPY)
|
|
217
228
|
|
|
218
229
|
`RuuviTagReactive` is a reactive wrapper and background process for RuuviTagSensor `get_data`. An optional MAC address list can be passed on the initializer and execution can be stopped with the stop function.
|
|
@@ -240,7 +251,7 @@ ruuvi_rx.get_subject().pipe(
|
|
|
240
251
|
ops.distinct_until_changed()
|
|
241
252
|
).subscribe(lambda x: print(f"Temperature changed: {x}"))
|
|
242
253
|
|
|
243
|
-
# Close all connections and stop
|
|
254
|
+
# Close all connections and stop Bluetooth communication
|
|
244
255
|
ruuvi_rx.stop()
|
|
245
256
|
```
|
|
246
257
|
|
|
@@ -306,7 +317,7 @@ RuuviTagSensor.find_ruuvitags()
|
|
|
306
317
|
|
|
307
318
|
### Using different Bluetooth device
|
|
308
319
|
|
|
309
|
-
If you have multiple Bluetooth devices installed, a device to be used might not be the default (Linux: hci0). The device can be passed with a `bt_device`-parameter.
|
|
320
|
+
If you have multiple Bluetooth devices installed, a device to be used might not be the default (Linux: `hci0`). The device can be passed with a `bt_device`-parameter.
|
|
310
321
|
|
|
311
322
|
```python
|
|
312
323
|
from ruuvitag_sensor.ruuvi import RuuviTagSensor
|
|
@@ -476,6 +487,18 @@ $ sudo apt-get install bluez bluez-hcidump
|
|
|
476
487
|
|
|
477
488
|
`ruuvitag-sensor` package uses internally _hciconfig_, _hcitool_ and _hcidump_. These tools are deprecated. In case tools are missing, an older version of BlueZ is required ([Issue](https://github.com/ttu/ruuvitag-sensor/issues/31))
|
|
478
489
|
|
|
490
|
+
If you wish to test the library on Windows or macOS, enable it with `RUUVI_BLE_ADAPTER` environment variable.
|
|
491
|
+
|
|
492
|
+
```sh
|
|
493
|
+
$ export RUUVI_BLE_ADAPTER="bluez"
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
And install ptyprocess.
|
|
497
|
+
|
|
498
|
+
```sh
|
|
499
|
+
python -m pip install ptyprocess
|
|
500
|
+
```
|
|
501
|
+
|
|
479
502
|
#### BlueZ limitations
|
|
480
503
|
|
|
481
504
|
`ruuvitag-sensor` package uses BlueZ to listen to broadcasted BL information (uses _hciconf_, _hcitool_, _hcidump_). Implementation does not handle well all unexpected errors or changes, e.g. when the adapter is busy, rebooted or powered down.
|
|
@@ -484,7 +507,9 @@ In case of errors, the application tries to exit immediately, so it can be autom
|
|
|
484
507
|
|
|
485
508
|
### Bleak
|
|
486
509
|
|
|
487
|
-
Bleak is
|
|
510
|
+
On Windows and macOS Bleak is installed and used automatically with `ruuvitag-sensor` package.
|
|
511
|
+
|
|
512
|
+
On Linux install it manually from PyPI and enable it with `RUUVI_BLE_ADAPTER` environment variable.
|
|
488
513
|
|
|
489
514
|
```sh
|
|
490
515
|
$ python -m pip install bleak
|
|
@@ -495,7 +520,8 @@ Add environment variable RUUVI_BLE_ADAPTER with value Bleak. E.g.
|
|
|
495
520
|
```sh
|
|
496
521
|
$ export RUUVI_BLE_ADAPTER="bleak"
|
|
497
522
|
```
|
|
498
|
-
|
|
523
|
+
|
|
524
|
+
Or use `os.environ`. __NOTE:__ this must be set before importing `ruuvitag_sensor`.
|
|
499
525
|
|
|
500
526
|
```py
|
|
501
527
|
import os
|
|
@@ -529,12 +555,12 @@ Bleak-adapter has a development-time generator for dummy data, which can be usef
|
|
|
529
555
|
|
|
530
556
|
Current state and known bugs in [issue #78](https://github.com/ttu/ruuvitag-sensor/issues/78).
|
|
531
557
|
|
|
532
|
-
Bleson works with Linux, macOS and partially with Windows.
|
|
558
|
+
[Bleson](https://github.com/TheCellule/python-bleson) works with Linux, macOS and partially with Windows.
|
|
533
559
|
|
|
534
560
|
Bleson is not installed automatically with `ruuvitag-sensor` package. Install it manually from GitHub.
|
|
535
561
|
|
|
536
562
|
```sh
|
|
537
|
-
$ pip install git+https://github.com/TheCellule/python-bleson
|
|
563
|
+
$ python -m pip install git+https://github.com/TheCellule/python-bleson
|
|
538
564
|
```
|
|
539
565
|
|
|
540
566
|
Add environment variable `RUUVI_BLE_ADAPTER` with value `bleson`. E.g.
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
ruuvitag_sensor/__init__.py,sha256=gg9b1cHow3Cya18ztEYQ-CMkmH8VAg4zsodmFQM7zJo,274
|
|
2
2
|
ruuvitag_sensor/__main__.py,sha256=h47tQCmq6VrToCFZnACLKwTL_VRFrZemy8RSQB3XtzE,3133
|
|
3
|
-
ruuvitag_sensor/data_formats.py,sha256=
|
|
3
|
+
ruuvitag_sensor/data_formats.py,sha256=goYT2qmm96fXCLouM5PgHJiegV7qrQlkE9Lww_gEU4Y,6427
|
|
4
4
|
ruuvitag_sensor/decoder.py,sha256=sl8mwV2X4GMoXpHTkxSZ81CCXqA114fjXQATFXkF2xI,9831
|
|
5
5
|
ruuvitag_sensor/log.py,sha256=Z9dNC3R9AOEMJBw7pfqxzU0Bv9cNRrNnVDJuUnSQCXc,658
|
|
6
|
-
ruuvitag_sensor/ruuvi.py,sha256=
|
|
6
|
+
ruuvitag_sensor/ruuvi.py,sha256=_1l91A9t6lGONmszdGHSlDjOj9bcCdR1nfjeklmLBos,11394
|
|
7
7
|
ruuvitag_sensor/ruuvi_rx.py,sha256=9ExDd4TJzR-AVivv6Vl8aZfV6nR2vYUTUegx6fRDkfA,3494
|
|
8
8
|
ruuvitag_sensor/ruuvi_types.py,sha256=PdegKFuXTTRg90v11vMa2eV0n5pJ4nrel3y4KeWZCxg,1203
|
|
9
9
|
ruuvitag_sensor/ruuvitag.py,sha256=2mPF6hCcDCOgSu7XBSgSLnelwncHgTMvoVGxu7kjKBw,2123
|
|
10
|
-
ruuvitag_sensor/adapters/__init__.py,sha256=
|
|
11
|
-
ruuvitag_sensor/adapters/bleak_ble.py,sha256=
|
|
12
|
-
ruuvitag_sensor/adapters/bleson.py,sha256=
|
|
10
|
+
ruuvitag_sensor/adapters/__init__.py,sha256=OYZXwb1fhXoiV16HgeB2AQuEC_A9CJM33Tgz-02Y0sA,3532
|
|
11
|
+
ruuvitag_sensor/adapters/bleak_ble.py,sha256=UFDL72KKGBgJus5Ln6026s4sKAvekso8T-m3r8bIFf8,4622
|
|
12
|
+
ruuvitag_sensor/adapters/bleson.py,sha256=UPqzTDPd_utAuznhSOHEi2yOQrN5TAZ5SCOXwZrV8qs,5000
|
|
13
13
|
ruuvitag_sensor/adapters/dummy.py,sha256=OfmZCm_wBiXo3Ig0QoUJHRuZTMZ_0twXs486xi-eTQU,1606
|
|
14
14
|
ruuvitag_sensor/adapters/nix_hci.py,sha256=LQHqDN613U5GMwkotU-RGUtg0Hm7jB6nJ0Uq03Li3pQ,6196
|
|
15
15
|
ruuvitag_sensor/adapters/nix_hci_file.py,sha256=SyTEJmQEUpNZchpriPT5l8Sftr3r76BXp1wCyt5bOdo,743
|
|
16
|
+
ruuvitag_sensor/adapters/utils.py,sha256=CC_n-DTT4MEwgJ-CVee3sfcY5a2lAz0dZB7kQHsn_tg,82
|
|
16
17
|
ruuvitag_sensor/adapters/development/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
18
|
ruuvitag_sensor/adapters/development/dev_bleak_scanner.py,sha256=lWyvTvYLDEXHfXv224DS3u5XtxGwHx19FhQNuDo0gAg,1569
|
|
18
|
-
ruuvitag_sensor-2.
|
|
19
|
-
ruuvitag_sensor-2.
|
|
20
|
-
ruuvitag_sensor-2.
|
|
21
|
-
ruuvitag_sensor-2.
|
|
22
|
-
ruuvitag_sensor-2.
|
|
19
|
+
ruuvitag_sensor-2.3.1.dist-info/LICENSE,sha256=ROQ2frpjKCU0cO9ManPSnB5_dr6gV8WHBbYvO55Jlzk,1070
|
|
20
|
+
ruuvitag_sensor-2.3.1.dist-info/METADATA,sha256=yEERpb1C4wLCUpzDk9iUr2pe3rmgZFg8CYvoBxUtL0Q,23723
|
|
21
|
+
ruuvitag_sensor-2.3.1.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
22
|
+
ruuvitag_sensor-2.3.1.dist-info/top_level.txt,sha256=CurIe7zHRdVeHrxlMqISZgWSy85umT8s7F_QxYE1QDY,16
|
|
23
|
+
ruuvitag_sensor-2.3.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|